From bfe98c20e5e799207e8a69f5b2f172e119e5997a Mon Sep 17 00:00:00 2001 From: Egor Yusov Date: Sat, 20 Oct 2018 15:54:43 -0700 Subject: Removed existing glslang folder --- External/glslang/.appveyor.yml | 90 - External/glslang/.clang-format | 12 - External/glslang/.gitattributes | 17 - External/glslang/.gitignore | 10 - External/glslang/.travis.yml | 123 - External/glslang/CMakeLists.txt | 122 - External/glslang/ChooseMSVCCRT.cmake | 105 - External/glslang/External/CMakeLists.txt | 43 - External/glslang/OGLCompilersDLL/CMakeLists.txt | 14 - External/glslang/OGLCompilersDLL/InitializeDll.cpp | 165 - External/glslang/OGLCompilersDLL/InitializeDll.h | 49 - External/glslang/README-spirv-remap.txt | 137 - External/glslang/README.md | 332 - External/glslang/SPIRV/CMakeLists.txt | 76 - External/glslang/SPIRV/GLSL.ext.AMD.h | 108 - External/glslang/SPIRV/GLSL.ext.EXT.h | 37 - External/glslang/SPIRV/GLSL.ext.KHR.h | 42 - External/glslang/SPIRV/GLSL.ext.NV.h | 57 - External/glslang/SPIRV/GLSL.std.450.h | 131 - External/glslang/SPIRV/GlslangToSpv.cpp | 7019 ------------- External/glslang/SPIRV/GlslangToSpv.h | 67 - External/glslang/SPIRV/InReadableOrder.cpp | 113 - External/glslang/SPIRV/Logger.cpp | 68 - External/glslang/SPIRV/Logger.h | 74 - External/glslang/SPIRV/SPVRemapper.cpp | 1479 --- External/glslang/SPIRV/SPVRemapper.h | 304 - External/glslang/SPIRV/SpvBuilder.cpp | 2775 ----- External/glslang/SPIRV/SpvBuilder.h | 648 -- External/glslang/SPIRV/bitutils.h | 81 - External/glslang/SPIRV/disassemble.cpp | 698 -- External/glslang/SPIRV/disassemble.h | 52 - External/glslang/SPIRV/doc.cpp | 2568 ----- External/glslang/SPIRV/doc.h | 258 - External/glslang/SPIRV/hex_float.h | 1078 -- External/glslang/SPIRV/spirv.hpp | 1099 -- External/glslang/SPIRV/spvIR.h | 407 - External/glslang/StandAlone/CMakeLists.txt | 47 - External/glslang/StandAlone/DirStackFileIncluder.h | 141 - External/glslang/StandAlone/ResourceLimits.cpp | 458 - External/glslang/StandAlone/ResourceLimits.h | 57 - External/glslang/StandAlone/StandAlone.cpp | 1489 --- External/glslang/StandAlone/Worklist.h | 95 - External/glslang/StandAlone/spirv-remap.cpp | 343 - External/glslang/glslang/CMakeLists.txt | 114 - .../glslang/glslang/GenericCodeGen/CodeGen.cpp | 76 - External/glslang/glslang/GenericCodeGen/Link.cpp | 91 - External/glslang/glslang/Include/BaseTypes.h | 464 - External/glslang/glslang/Include/Common.h | 278 - External/glslang/glslang/Include/ConstantUnion.h | 938 -- External/glslang/glslang/Include/InfoSink.h | 144 - .../glslang/glslang/Include/InitializeGlobals.h | 44 - External/glslang/glslang/Include/PoolAlloc.h | 317 - External/glslang/glslang/Include/ResourceLimits.h | 140 - External/glslang/glslang/Include/ShHandle.h | 176 - External/glslang/glslang/Include/Types.h | 1947 ---- External/glslang/glslang/Include/arrays.h | 339 - External/glslang/glslang/Include/intermediate.h | 1677 ---- External/glslang/glslang/Include/revision.h | 3 - External/glslang/glslang/Include/revision.template | 13 - .../glslang/MachineIndependent/Constant.cpp | 1118 --- .../glslang/MachineIndependent/InfoSink.cpp | 113 - .../glslang/MachineIndependent/Initialize.cpp | 8639 ---------------- .../glslang/MachineIndependent/Initialize.h | 110 - .../glslang/MachineIndependent/IntermTraverse.cpp | 302 - .../glslang/MachineIndependent/Intermediate.cpp | 3815 ------- .../glslang/MachineIndependent/LiveTraverser.h | 138 - .../MachineIndependent/ParseContextBase.cpp | 613 -- .../glslang/MachineIndependent/ParseHelper.cpp | 6736 ------------- .../glslang/MachineIndependent/ParseHelper.h | 503 - .../glslang/MachineIndependent/PoolAlloc.cpp | 315 - .../glslang/MachineIndependent/RemoveTree.cpp | 118 - .../glslang/MachineIndependent/RemoveTree.h | 41 - .../glslang/glslang/MachineIndependent/Scan.cpp | 1694 ---- External/glslang/glslang/MachineIndependent/Scan.h | 274 - .../glslang/MachineIndependent/ScanContext.h | 88 - .../glslang/MachineIndependent/ShaderLang.cpp | 1949 ---- .../glslang/MachineIndependent/SymbolTable.cpp | 385 - .../glslang/MachineIndependent/SymbolTable.h | 825 -- .../glslang/MachineIndependent/Versions.cpp | 964 -- .../glslang/glslang/MachineIndependent/Versions.h | 278 - .../glslang/MachineIndependent/attribute.cpp | 257 - .../glslang/glslang/MachineIndependent/attribute.h | 102 - .../glslang/glslang/MachineIndependent/gl_types.h | 214 - .../glslang/glslang/MachineIndependent/glslang.y | 3614 ------- .../glslang/MachineIndependent/glslang_tab.cpp | 10051 ------------------- .../glslang/MachineIndependent/glslang_tab.cpp.h | 489 - .../glslang/MachineIndependent/intermOut.cpp | 1424 --- .../glslang/MachineIndependent/iomapper.cpp | 789 -- .../glslang/glslang/MachineIndependent/iomapper.h | 63 - .../glslang/glslang/MachineIndependent/limits.cpp | 198 - .../glslang/MachineIndependent/linkValidate.cpp | 1286 --- .../glslang/MachineIndependent/localintermediate.h | 752 -- .../glslang/MachineIndependent/parseConst.cpp | 204 - .../glslang/MachineIndependent/parseVersions.h | 147 - .../glslang/MachineIndependent/preprocessor/Pp.cpp | 1270 --- .../MachineIndependent/preprocessor/PpAtom.cpp | 181 - .../MachineIndependent/preprocessor/PpContext.cpp | 115 - .../MachineIndependent/preprocessor/PpContext.h | 622 -- .../MachineIndependent/preprocessor/PpScanner.cpp | 1100 -- .../MachineIndependent/preprocessor/PpTokens.cpp | 359 - .../MachineIndependent/preprocessor/PpTokens.h | 179 - .../MachineIndependent/propagateNoContraction.cpp | 866 -- .../MachineIndependent/propagateNoContraction.h | 55 - .../glslang/MachineIndependent/reflection.cpp | 843 -- .../glslang/MachineIndependent/reflection.h | 177 - .../glslang/OSDependent/Unix/CMakeLists.txt | 8 - .../glslang/glslang/OSDependent/Unix/ossource.cpp | 204 - .../glslang/OSDependent/Windows/CMakeLists.txt | 20 - .../glslang/glslang/OSDependent/Windows/main.cpp | 74 - .../glslang/OSDependent/Windows/ossource.cpp | 147 - External/glslang/glslang/OSDependent/osinclude.h | 63 - External/glslang/glslang/Public/ShaderLang.h | 714 -- External/glslang/glslang/updateGrammar | 3 - External/glslang/gtests/AST.FromFile.cpp | 249 - .../glslang/gtests/BuiltInResource.FromFile.cpp | 57 - External/glslang/gtests/CMakeLists.txt | 59 - External/glslang/gtests/Config.FromFile.cpp | 107 - External/glslang/gtests/HexFloat.cpp | 1231 --- External/glslang/gtests/Hlsl.FromFile.cpp | 433 - External/glslang/gtests/Initializer.h | 55 - External/glslang/gtests/Link.FromFile.Vk.cpp | 114 - External/glslang/gtests/Link.FromFile.cpp | 108 - External/glslang/gtests/Pp.FromFile.cpp | 75 - External/glslang/gtests/README.md | 26 - External/glslang/gtests/Remap.FromFile.cpp | 118 - External/glslang/gtests/Settings.cpp | 51 - External/glslang/gtests/Settings.h | 58 - External/glslang/gtests/Spv.FromFile.cpp | 505 - External/glslang/gtests/TestFixture.cpp | 164 - External/glslang/gtests/TestFixture.h | 646 -- External/glslang/gtests/main.cpp | 79 - External/glslang/hlsl/CMakeLists.txt | 35 - External/glslang/hlsl/hlslAttributes.cpp | 106 - External/glslang/hlsl/hlslAttributes.h | 59 - External/glslang/hlsl/hlslGrammar.cpp | 4120 -------- External/glslang/hlsl/hlslGrammar.h | 140 - External/glslang/hlsl/hlslOpMap.cpp | 173 - External/glslang/hlsl/hlslOpMap.h | 69 - External/glslang/hlsl/hlslParseHelper.cpp | 9943 ------------------ External/glslang/hlsl/hlslParseHelper.h | 496 - External/glslang/hlsl/hlslParseables.cpp | 1324 --- External/glslang/hlsl/hlslParseables.h | 64 - External/glslang/hlsl/hlslScanContext.cpp | 903 -- External/glslang/hlsl/hlslScanContext.h | 109 - External/glslang/hlsl/hlslTokenStream.cpp | 150 - External/glslang/hlsl/hlslTokenStream.h | 96 - External/glslang/hlsl/hlslTokens.h | 374 - External/glslang/make-revision | 6 - External/glslang/update_glslang_sources.py | 155 - 149 files changed, 107914 deletions(-) delete mode 100644 External/glslang/.appveyor.yml delete mode 100644 External/glslang/.clang-format delete mode 100644 External/glslang/.gitattributes delete mode 100644 External/glslang/.gitignore delete mode 100644 External/glslang/.travis.yml delete mode 100644 External/glslang/CMakeLists.txt delete mode 100644 External/glslang/ChooseMSVCCRT.cmake delete mode 100644 External/glslang/External/CMakeLists.txt delete mode 100644 External/glslang/OGLCompilersDLL/CMakeLists.txt delete mode 100644 External/glslang/OGLCompilersDLL/InitializeDll.cpp delete mode 100644 External/glslang/OGLCompilersDLL/InitializeDll.h delete mode 100644 External/glslang/README-spirv-remap.txt delete mode 100644 External/glslang/README.md delete mode 100644 External/glslang/SPIRV/CMakeLists.txt delete mode 100644 External/glslang/SPIRV/GLSL.ext.AMD.h delete mode 100644 External/glslang/SPIRV/GLSL.ext.EXT.h delete mode 100644 External/glslang/SPIRV/GLSL.ext.KHR.h delete mode 100644 External/glslang/SPIRV/GLSL.ext.NV.h delete mode 100644 External/glslang/SPIRV/GLSL.std.450.h delete mode 100644 External/glslang/SPIRV/GlslangToSpv.cpp delete mode 100644 External/glslang/SPIRV/GlslangToSpv.h delete mode 100644 External/glslang/SPIRV/InReadableOrder.cpp delete mode 100644 External/glslang/SPIRV/Logger.cpp delete mode 100644 External/glslang/SPIRV/Logger.h delete mode 100644 External/glslang/SPIRV/SPVRemapper.cpp delete mode 100644 External/glslang/SPIRV/SPVRemapper.h delete mode 100644 External/glslang/SPIRV/SpvBuilder.cpp delete mode 100644 External/glslang/SPIRV/SpvBuilder.h delete mode 100644 External/glslang/SPIRV/bitutils.h delete mode 100644 External/glslang/SPIRV/disassemble.cpp delete mode 100644 External/glslang/SPIRV/disassemble.h delete mode 100644 External/glslang/SPIRV/doc.cpp delete mode 100644 External/glslang/SPIRV/doc.h delete mode 100644 External/glslang/SPIRV/hex_float.h delete mode 100644 External/glslang/SPIRV/spirv.hpp delete mode 100644 External/glslang/SPIRV/spvIR.h delete mode 100644 External/glslang/StandAlone/CMakeLists.txt delete mode 100644 External/glslang/StandAlone/DirStackFileIncluder.h delete mode 100644 External/glslang/StandAlone/ResourceLimits.cpp delete mode 100644 External/glslang/StandAlone/ResourceLimits.h delete mode 100644 External/glslang/StandAlone/StandAlone.cpp delete mode 100644 External/glslang/StandAlone/Worklist.h delete mode 100644 External/glslang/StandAlone/spirv-remap.cpp delete mode 100644 External/glslang/glslang/CMakeLists.txt delete mode 100644 External/glslang/glslang/GenericCodeGen/CodeGen.cpp delete mode 100644 External/glslang/glslang/GenericCodeGen/Link.cpp delete mode 100644 External/glslang/glslang/Include/BaseTypes.h delete mode 100644 External/glslang/glslang/Include/Common.h delete mode 100644 External/glslang/glslang/Include/ConstantUnion.h delete mode 100644 External/glslang/glslang/Include/InfoSink.h delete mode 100644 External/glslang/glslang/Include/InitializeGlobals.h delete mode 100644 External/glslang/glslang/Include/PoolAlloc.h delete mode 100644 External/glslang/glslang/Include/ResourceLimits.h delete mode 100644 External/glslang/glslang/Include/ShHandle.h delete mode 100644 External/glslang/glslang/Include/Types.h delete mode 100644 External/glslang/glslang/Include/arrays.h delete mode 100644 External/glslang/glslang/Include/intermediate.h delete mode 100644 External/glslang/glslang/Include/revision.h delete mode 100644 External/glslang/glslang/Include/revision.template delete mode 100644 External/glslang/glslang/MachineIndependent/Constant.cpp delete mode 100644 External/glslang/glslang/MachineIndependent/InfoSink.cpp delete mode 100644 External/glslang/glslang/MachineIndependent/Initialize.cpp delete mode 100644 External/glslang/glslang/MachineIndependent/Initialize.h delete mode 100644 External/glslang/glslang/MachineIndependent/IntermTraverse.cpp delete mode 100644 External/glslang/glslang/MachineIndependent/Intermediate.cpp delete mode 100644 External/glslang/glslang/MachineIndependent/LiveTraverser.h delete mode 100644 External/glslang/glslang/MachineIndependent/ParseContextBase.cpp delete mode 100644 External/glslang/glslang/MachineIndependent/ParseHelper.cpp delete mode 100644 External/glslang/glslang/MachineIndependent/ParseHelper.h delete mode 100644 External/glslang/glslang/MachineIndependent/PoolAlloc.cpp delete mode 100644 External/glslang/glslang/MachineIndependent/RemoveTree.cpp delete mode 100644 External/glslang/glslang/MachineIndependent/RemoveTree.h delete mode 100644 External/glslang/glslang/MachineIndependent/Scan.cpp delete mode 100644 External/glslang/glslang/MachineIndependent/Scan.h delete mode 100644 External/glslang/glslang/MachineIndependent/ScanContext.h delete mode 100644 External/glslang/glslang/MachineIndependent/ShaderLang.cpp delete mode 100644 External/glslang/glslang/MachineIndependent/SymbolTable.cpp delete mode 100644 External/glslang/glslang/MachineIndependent/SymbolTable.h delete mode 100644 External/glslang/glslang/MachineIndependent/Versions.cpp delete mode 100644 External/glslang/glslang/MachineIndependent/Versions.h delete mode 100644 External/glslang/glslang/MachineIndependent/attribute.cpp delete mode 100644 External/glslang/glslang/MachineIndependent/attribute.h delete mode 100644 External/glslang/glslang/MachineIndependent/gl_types.h delete mode 100644 External/glslang/glslang/MachineIndependent/glslang.y delete mode 100644 External/glslang/glslang/MachineIndependent/glslang_tab.cpp delete mode 100644 External/glslang/glslang/MachineIndependent/glslang_tab.cpp.h delete mode 100644 External/glslang/glslang/MachineIndependent/intermOut.cpp delete mode 100644 External/glslang/glslang/MachineIndependent/iomapper.cpp delete mode 100644 External/glslang/glslang/MachineIndependent/iomapper.h delete mode 100644 External/glslang/glslang/MachineIndependent/limits.cpp delete mode 100644 External/glslang/glslang/MachineIndependent/linkValidate.cpp delete mode 100644 External/glslang/glslang/MachineIndependent/localintermediate.h delete mode 100644 External/glslang/glslang/MachineIndependent/parseConst.cpp delete mode 100644 External/glslang/glslang/MachineIndependent/parseVersions.h delete mode 100644 External/glslang/glslang/MachineIndependent/preprocessor/Pp.cpp delete mode 100644 External/glslang/glslang/MachineIndependent/preprocessor/PpAtom.cpp delete mode 100644 External/glslang/glslang/MachineIndependent/preprocessor/PpContext.cpp delete mode 100644 External/glslang/glslang/MachineIndependent/preprocessor/PpContext.h delete mode 100644 External/glslang/glslang/MachineIndependent/preprocessor/PpScanner.cpp delete mode 100644 External/glslang/glslang/MachineIndependent/preprocessor/PpTokens.cpp delete mode 100644 External/glslang/glslang/MachineIndependent/preprocessor/PpTokens.h delete mode 100644 External/glslang/glslang/MachineIndependent/propagateNoContraction.cpp delete mode 100644 External/glslang/glslang/MachineIndependent/propagateNoContraction.h delete mode 100644 External/glslang/glslang/MachineIndependent/reflection.cpp delete mode 100644 External/glslang/glslang/MachineIndependent/reflection.h delete mode 100644 External/glslang/glslang/OSDependent/Unix/CMakeLists.txt delete mode 100644 External/glslang/glslang/OSDependent/Unix/ossource.cpp delete mode 100644 External/glslang/glslang/OSDependent/Windows/CMakeLists.txt delete mode 100644 External/glslang/glslang/OSDependent/Windows/main.cpp delete mode 100644 External/glslang/glslang/OSDependent/Windows/ossource.cpp delete mode 100644 External/glslang/glslang/OSDependent/osinclude.h delete mode 100644 External/glslang/glslang/Public/ShaderLang.h delete mode 100644 External/glslang/glslang/updateGrammar delete mode 100644 External/glslang/gtests/AST.FromFile.cpp delete mode 100644 External/glslang/gtests/BuiltInResource.FromFile.cpp delete mode 100644 External/glslang/gtests/CMakeLists.txt delete mode 100644 External/glslang/gtests/Config.FromFile.cpp delete mode 100644 External/glslang/gtests/HexFloat.cpp delete mode 100644 External/glslang/gtests/Hlsl.FromFile.cpp delete mode 100644 External/glslang/gtests/Initializer.h delete mode 100644 External/glslang/gtests/Link.FromFile.Vk.cpp delete mode 100644 External/glslang/gtests/Link.FromFile.cpp delete mode 100644 External/glslang/gtests/Pp.FromFile.cpp delete mode 100644 External/glslang/gtests/README.md delete mode 100644 External/glslang/gtests/Remap.FromFile.cpp delete mode 100644 External/glslang/gtests/Settings.cpp delete mode 100644 External/glslang/gtests/Settings.h delete mode 100644 External/glslang/gtests/Spv.FromFile.cpp delete mode 100644 External/glslang/gtests/TestFixture.cpp delete mode 100644 External/glslang/gtests/TestFixture.h delete mode 100644 External/glslang/gtests/main.cpp delete mode 100644 External/glslang/hlsl/CMakeLists.txt delete mode 100644 External/glslang/hlsl/hlslAttributes.cpp delete mode 100644 External/glslang/hlsl/hlslAttributes.h delete mode 100644 External/glslang/hlsl/hlslGrammar.cpp delete mode 100644 External/glslang/hlsl/hlslGrammar.h delete mode 100644 External/glslang/hlsl/hlslOpMap.cpp delete mode 100644 External/glslang/hlsl/hlslOpMap.h delete mode 100644 External/glslang/hlsl/hlslParseHelper.cpp delete mode 100644 External/glslang/hlsl/hlslParseHelper.h delete mode 100644 External/glslang/hlsl/hlslParseables.cpp delete mode 100644 External/glslang/hlsl/hlslParseables.h delete mode 100644 External/glslang/hlsl/hlslScanContext.cpp delete mode 100644 External/glslang/hlsl/hlslScanContext.h delete mode 100644 External/glslang/hlsl/hlslTokenStream.cpp delete mode 100644 External/glslang/hlsl/hlslTokenStream.h delete mode 100644 External/glslang/hlsl/hlslTokens.h delete mode 100644 External/glslang/make-revision delete mode 100644 External/glslang/update_glslang_sources.py diff --git a/External/glslang/.appveyor.yml b/External/glslang/.appveyor.yml deleted file mode 100644 index 07e269be..00000000 --- a/External/glslang/.appveyor.yml +++ /dev/null @@ -1,90 +0,0 @@ -# Windows Build Configuration for AppVeyor -# http://www.appveyor.com/docs/appveyor-yml - -# build version format -version: "{build}" - -os: Visual Studio 2013 - -platform: - - x64 - -configuration: - - Debug - - Release - -branches: - only: - - master - -# Travis advances the master-tot tag to current top of the tree after -# each push into the master branch, because it relies on that tag to -# upload build artifacts to the master-tot release. This will cause -# double testing for each push on Appveyor: one for the push, one for -# the tag advance. Disable testing tags. -skip_tags: true - -clone_depth: 5 - -matrix: - fast_finish: true # Show final status immediately if a test fails. - -# scripts that run after cloning repository -install: - - git clone https://github.com/google/googletest.git External/googletest - - C:/Python27/python.exe update_glslang_sources.py - -build: - parallel: true # enable MSBuild parallel builds - verbosity: minimal - -build_script: - - mkdir build && cd build - - cmake .. -DCMAKE_INSTALL_PREFIX=install - - cmake --build . --config %CONFIGURATION% --target install - -test_script: - - ctest -C %CONFIGURATION% --output-on-failure - - cd ../Test && bash runtests - - cd ../build - -after_test: - # For debug build, the generated dll has a postfix "d" in its name. - - ps: >- - If ($env:configuration -Match "Debug") { - $env:SUFFIX="d" - } Else { - $env:SUFFIX="" - } - - cd install - # Zip all glslang artifacts for uploading and deploying - - 7z a glslang-master-windows-"%PLATFORM%"-"%CONFIGURATION%".zip - bin\glslangValidator.exe - include\glslang\* - include\SPIRV\* - lib\glslang%SUFFIX%.lib - lib\HLSL%SUFFIX%.lib - lib\OGLCompiler%SUFFIX%.lib - lib\OSDependent%SUFFIX%.lib - lib\SPIRV%SUFFIX%.lib - lib\SPVRemapper%SUFFIX%.lib - lib\SPIRV-Tools%SUFFIX%.lib - lib\SPIRV-Tools-opt%SUFFIX%.lib - -artifacts: - - path: build\install\*.zip - name: artifacts-zip - -deploy: - - provider: GitHub - auth_token: - secure: YglcSYdl0TylEa59H4K6lylBEDr586NAt2EMgZquSo+iuPrwgZQuJLPCoihSm9y6 - release: master-tot - description: "Continuous build of the latest master branch by Appveyor and Travis CI" - artifact: artifacts-zip - draft: false - prerelease: false - force_update: true - on: - branch: master - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013 diff --git a/External/glslang/.clang-format b/External/glslang/.clang-format deleted file mode 100644 index daf87985..00000000 --- a/External/glslang/.clang-format +++ /dev/null @@ -1,12 +0,0 @@ -Language: Cpp -IndentWidth: 4 -BreakBeforeBraces: Custom -BraceWrapping: { AfterFunction: true, AfterControlStatement: true } -IndentCaseLabels: false -ReflowComments: false -ColumnLimit: 120 -AccessModifierOffset: -4 -AlignTrailingComments: true -AllowShortBlocksOnASingleLine: false -AllowShortIfStatementsOnASingleLine: false -AllowShortLoopsOnASingleLine: false diff --git a/External/glslang/.gitattributes b/External/glslang/.gitattributes deleted file mode 100644 index cade3908..00000000 --- a/External/glslang/.gitattributes +++ /dev/null @@ -1,17 +0,0 @@ -# test files have a mix of lf/crlf, and that's a good thing, for testing, don't mess with it -# bash scripts need lines ending with lf, and that's correct for Windows too, e.g., under Cygwin -# (scripts often don't have a suffix) -* -text -*.sh text eof=lf - -# txt files should be native and normalized -*.txt text - -# source code can be native and normalized, but simpler if lf everywhere; will try that way -*.h text eof=lf -*.c text eof=lf -*.cpp text eof=lf -*.y text eof=lf -*.out text eof=lf -*.conf text eof=lf -*.err text eof=lf diff --git a/External/glslang/.gitignore b/External/glslang/.gitignore deleted file mode 100644 index a1fe3944..00000000 --- a/External/glslang/.gitignore +++ /dev/null @@ -1,10 +0,0 @@ -*.o -*.a -*.so -*.exe -tags -TAGS -build/ -Test/localResults/ -External/googletest -External/spirv-tools diff --git a/External/glslang/.travis.yml b/External/glslang/.travis.yml deleted file mode 100644 index 4fe4b5e5..00000000 --- a/External/glslang/.travis.yml +++ /dev/null @@ -1,123 +0,0 @@ -# Linux and Mac Build Configuration for Travis - -language: cpp - -os: - - linux - - osx - -# Use Ubuntu 14.04 LTS (Trusty) as the Linux testing environment. -sudo: false -dist: trusty - -env: - global: - - secure: aGFrgzyKp+84hKrGkxVWg8cHV61uqrKEHT38gfSQK6+WS4GfLOyH83p7WnsEBb7AMhzU7LMNFdvOFr6+NaMpVnqRvc40CEG1Q+lNg9Pq9mhIZLowvDrfqTL9kQ+8Nbw5Q6/dg6CTvY7fvRfpfCEmKIUZBRkoKUuHeuM1uy3IupFcdNuL5bSYn3Beo+apSJginh9DI4BLDXFUgBzTRSLLyCX5g3cpaeGGOCr8quJlYx75W6HRck5g9SZuLtUoH9GFEV3l+ZEWB8noErW+J56L03bwNwFuuAh321evw++oQk5KFa8rlDvar3SJ3b1RHB8u/eq5DBYMyaK/fS8+Q7QbGr8diF/wDe68bKO7U9IhpNfExXmczCpExjHomW5TQv4rYdGhygPMfW97aIsPRYyNKcl4fkmb7NDrM8w0Jscdq2g5c2Kz0ItyZoBri/NXLwFQQjaVCs7Pf97TjuMA7mK0GJmDTRzi6SrDYlWMt5BQL3y0CCojyfLIRcTh0CQjQI29s97bLfQrYAxt9GNNFR+HTXRLLrkaAlJkPGEPwUywlSfEThnvHLesNxYqemolAYpQT4ithoL4GehGIHmaxsW295aKVhuRf8K9eBODNqrfblvM42UHhjntT+92ZnQ/Gkq80GqaMxnxi4PO5FyPIxt0r981b54YBkWi8YA4P7w5pNI= - matrix: - - GLSLANG_BUILD_TYPE=Release - - GLSLANG_BUILD_TYPE=Debug - -compiler: - - clang - - gcc - -matrix: - fast_finish: true # Show final status immediately if a test fails. - exclude: - # Skip GCC builds on Mac OS X. - - os: osx - compiler: gcc - include: - # Additional build using Android NDK. - - env: BUILD_NDK=ON - -cache: - apt: true - -branches: - only: - - master - -addons: - apt: - packages: - - clang-3.6 - -install: - # Make sure that clang-3.6 is selected on Linux. - - if [[ "$TRAVIS_OS_NAME" == "linux" && "$CC" == "clang" ]]; then - export CC=clang-3.6 CXX=clang++-3.6; - fi - # Download Android NDK and Android CMake toolchain file. - - if [[ "$BUILD_NDK" == "ON" ]]; then - git clone --depth=1 https://github.com/urho3d/android-ndk.git $HOME/android-ndk; - export ANDROID_NDK=$HOME/android-ndk; - git clone --depth=1 https://github.com/taka-no-me/android-cmake.git $HOME/android-cmake; - export TOOLCHAIN_PATH=$HOME/android-cmake/android.toolchain.cmake; - fi - -before_script: - - git clone --depth=1 https://github.com/google/googletest.git External/googletest - - ./update_glslang_sources.py - -script: - - mkdir build && cd build - # For Android, do release building using NDK without testing. - # For Linux and macOS, do debug/release building with testing. - - if [[ "$BUILD_NDK" == "ON" ]]; then - cmake -DCMAKE_TOOLCHAIN_FILE=${TOOLCHAIN_PATH} - -DANDROID_NATIVE_API_LEVEL=android-12 - -DCMAKE_BUILD_TYPE=Release - -DANDROID_ABI="armeabi-v7a with NEON" - -DBUILD_TESTING=OFF ..; - make -j4; - else - cmake -DCMAKE_BUILD_TYPE=${GLSLANG_BUILD_TYPE} - -DCMAKE_INSTALL_PREFIX=`pwd`/install ..; - make -j4 install; - ctest --output-on-failure && - cd ../Test && ./runtests; - fi - -after_success: - # For debug build, the generated dll has a postfix "d" in its name. - - if [[ "${GLSLANG_BUILD_TYPE}" == "Debug" ]]; then - export SUFFIX="d"; - else - export SUFFIX=""; - fi - # Create tarball for deployment - - if [[ ${CC} == clang* && "${BUILD_NDK}" != "ON" ]]; then - cd ../build/install; - export TARBALL=glslang-master-${TRAVIS_OS_NAME}-${GLSLANG_BUILD_TYPE}.zip; - zip ${TARBALL} - bin/glslangValidator - include/glslang/* - include/SPIRV/* - lib/libglslang${SUFFIX}.a - lib/libHLSL${SUFFIX}.a - lib/libOGLCompiler${SUFFIX}.a - lib/libOSDependent${SUFFIX}.a - lib/libSPIRV${SUFFIX}.a - lib/libSPVRemapper${SUFFIX}.a - lib/libSPIRV-Tools${SUFFIX}.a - lib/libSPIRV-Tools-opt${SUFFIX}.a; - fi - -before_deploy: - # Tag the current top of the tree as "master-tot". - # Travis CI replies on the tag name to properly push to GitHub Releases. - - git config --global user.name "Travis CI" - - git config --global user.email "builds@travis-ci.org" - - git tag -f master-tot - - git push -q -f https://${glslangtoken}@github.com/KhronosGroup/glslang --tags - -deploy: - provider: releases - api_key: ${glslangtoken} - on: - branch: master - condition: ${CC} == clang* && ${BUILD_NDK} != ON - file: ${TARBALL} - skip_cleanup: true - overwrite: true diff --git a/External/glslang/CMakeLists.txt b/External/glslang/CMakeLists.txt deleted file mode 100644 index 07ce2c99..00000000 --- a/External/glslang/CMakeLists.txt +++ /dev/null @@ -1,122 +0,0 @@ -# increase to 3.1 once all major distributions -# include a version of CMake >= 3.1 -cmake_minimum_required(VERSION 2.8.12) -if (POLICY CMP0048) - cmake_policy(SET CMP0048 NEW) -endif() -set_property(GLOBAL PROPERTY USE_FOLDERS ON) - -# Adhere to GNU filesystem layout conventions -include(GNUInstallDirs) - -option(BUILD_SHARED_LIBS "Build Shared Libraries" OFF) - -set(LIB_TYPE STATIC) - -if(BUILD_SHARED_LIBS) - set(LIB_TYPE SHARED) -endif() - -option(SKIP_GLSLANG_INSTALL "Skip installation" ${SKIP_GLSLANG_INSTALL}) -if(NOT ${SKIP_GLSLANG_INSTALL}) - set(ENABLE_GLSLANG_INSTALL ON) -endif() - -option(ENABLE_AMD_EXTENSIONS "Enables support of AMD-specific extensions" ON) -option(ENABLE_GLSLANG_BINARIES "Builds glslangValidator and spirv-remap" ON) - -option(ENABLE_NV_EXTENSIONS "Enables support of Nvidia-specific extensions" ON) - -option(ENABLE_HLSL "Enables HLSL input support" ON) - -option(ENABLE_OPT "Enables spirv-opt capability if present" ON) - -if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT AND WIN32) - set(CMAKE_INSTALL_PREFIX "install" CACHE STRING "..." FORCE) -endif() - -project(glslang) -# make testing optional -#include(CTest) - -if(ENABLE_AMD_EXTENSIONS) - add_definitions(-DAMD_EXTENSIONS) -endif(ENABLE_AMD_EXTENSIONS) - -if(ENABLE_NV_EXTENSIONS) - add_definitions(-DNV_EXTENSIONS) -endif(ENABLE_NV_EXTENSIONS) - -if(ENABLE_HLSL) - add_definitions(-DENABLE_HLSL) -endif(ENABLE_HLSL) - -if(WIN32) - set(CMAKE_DEBUG_POSTFIX "d") - if(MSVC) - include(ChooseMSVCCRT.cmake) - endif(MSVC) - add_definitions(-DGLSLANG_OSINCLUDE_WIN32) -elseif(UNIX) - add_definitions(-DGLSLANG_OSINCLUDE_UNIX) -else(WIN32) - message("unknown platform") -endif(WIN32) - -if(${CMAKE_CXX_COMPILER_ID} MATCHES "GNU") - add_compile_options(-Wall -Wmaybe-uninitialized -Wuninitialized -Wunused -Wunused-local-typedefs - -Wunused-parameter -Wunused-value -Wunused-variable -Wunused-but-set-parameter -Wunused-but-set-variable -fno-exceptions) - add_compile_options(-Wno-reorder) # disable this from -Wall, since it happens all over. -elseif(${CMAKE_CXX_COMPILER_ID} MATCHES "Clang") - add_compile_options(-Wall -Wuninitialized -Wunused -Wunused-local-typedefs - -Wunused-parameter -Wunused-value -Wunused-variable) - add_compile_options(-Wno-reorder) # disable this from -Wall, since it happens all over. -endif() - -# Request C++11 -if(${CMAKE_VERSION} VERSION_LESS 3.1) - # CMake versions before 3.1 do not understand CMAKE_CXX_STANDARD - # remove this block once CMake >=3.1 has fixated in the ecosystem - add_compile_options(-std=c++11) -else() - set(CMAKE_CXX_STANDARD 11) - set(CMAKE_CXX_STANDARD_REQUIRED ON) - set(CMAKE_CXX_EXTENSIONS OFF) -endif() - -function(glslang_set_link_args TARGET) - # For MinGW compiles, statically link against the GCC and C++ runtimes. - # This avoids the need to ship those runtimes as DLLs. - if(WIN32 AND ${CMAKE_CXX_COMPILER_ID} MATCHES "GNU") - set_target_properties(${TARGET} PROPERTIES - LINK_FLAGS "-static -static-libgcc -static-libstdc++") - endif() -endfunction(glslang_set_link_args) - -# We depend on these for later projects, so they should come first. -add_subdirectory(External) - -if(NOT TARGET SPIRV-Tools-opt) - set(ENABLE_OPT OFF) -endif() - -if(ENABLE_OPT) - message(STATUS "optimizer enabled") - add_definitions(-DENABLE_OPT=1) -else() - if(ENABLE_HLSL) - message(STATUS "spirv-tools not linked - illegal SPIRV may be generated for HLSL") - endif() - add_definitions(-DENABLE_OPT=0) -endif() - -add_subdirectory(glslang) -add_subdirectory(OGLCompilersDLL) -if(ENABLE_GLSLANG_BINARIES) - add_subdirectory(StandAlone) -endif() -add_subdirectory(SPIRV) -if(ENABLE_HLSL) - add_subdirectory(hlsl) -endif(ENABLE_HLSL) -#add_subdirectory(gtests) diff --git a/External/glslang/ChooseMSVCCRT.cmake b/External/glslang/ChooseMSVCCRT.cmake deleted file mode 100644 index 20978817..00000000 --- a/External/glslang/ChooseMSVCCRT.cmake +++ /dev/null @@ -1,105 +0,0 @@ -# The macro choose_msvc_crt() takes a list of possible -# C runtimes to choose from, in the form of compiler flags, -# to present to the user. (MTd for /MTd, etc) -# -# The macro is invoked at the end of the file. -# -# CMake already sets CRT flags in the CMAKE_CXX_FLAGS_* and -# CMAKE_C_FLAGS_* variables by default. To let the user -# override that for each build type: -# 1. Detect which CRT is already selected, and reflect this in -# LLVM_USE_CRT_* so the user can have a better idea of what -# changes they're making. -# 2. Replace the flags in both variables with the new flag via a regex. -# 3. set() the variables back into the cache so the changes -# are user-visible. - -### Helper macros: ### -macro(make_crt_regex regex crts) - set(${regex} "") - foreach(crt ${${crts}}) - # Trying to match the beginning or end of the string with stuff - # like [ ^]+ didn't work, so use a bunch of parentheses instead. - set(${regex} "${${regex}}|(^| +)/${crt}($| +)") - endforeach(crt) - string(REGEX REPLACE "^\\|" "" ${regex} "${${regex}}") -endmacro(make_crt_regex) - -macro(get_current_crt crt_current regex flagsvar) - # Find the selected-by-CMake CRT for each build type, if any. - # Strip off the leading slash and any whitespace. - string(REGEX MATCH "${${regex}}" ${crt_current} "${${flagsvar}}") - string(REPLACE "/" " " ${crt_current} "${${crt_current}}") - string(STRIP "${${crt_current}}" ${crt_current}) -endmacro(get_current_crt) - -# Replaces or adds a flag to a variable. -# Expects 'flag' to be padded with spaces. -macro(set_flag_in_var flagsvar regex flag) - string(REGEX MATCH "${${regex}}" current_flag "${${flagsvar}}") - if("${current_flag}" STREQUAL "") - set(${flagsvar} "${${flagsvar}}${${flag}}") - else() - string(REGEX REPLACE "${${regex}}" "${${flag}}" ${flagsvar} "${${flagsvar}}") - endif() - string(STRIP "${${flagsvar}}" ${flagsvar}) - # Make sure this change gets reflected in the cache/gui. - # CMake requires the docstring parameter whenever set() touches the cache, - # so get the existing docstring and re-use that. - get_property(flagsvar_docs CACHE ${flagsvar} PROPERTY HELPSTRING) - set(${flagsvar} "${${flagsvar}}" CACHE STRING "${flagsvar_docs}" FORCE) -endmacro(set_flag_in_var) - - -macro(choose_msvc_crt MSVC_CRT) - if(LLVM_USE_CRT) - message(FATAL_ERROR - "LLVM_USE_CRT is deprecated. Use the CMAKE_BUILD_TYPE-specific -variables (LLVM_USE_CRT_DEBUG, etc) instead.") - endif() - - make_crt_regex(MSVC_CRT_REGEX ${MSVC_CRT}) - - foreach(build_type ${CMAKE_CONFIGURATION_TYPES} ${CMAKE_BUILD_TYPE}) - string(TOUPPER "${build_type}" build) - if (NOT LLVM_USE_CRT_${build}) - get_current_crt(LLVM_USE_CRT_${build} - MSVC_CRT_REGEX - CMAKE_CXX_FLAGS_${build}) - set(LLVM_USE_CRT_${build} - "${LLVM_USE_CRT_${build}}" - CACHE STRING "Specify VC++ CRT to use for ${build_type} configurations." - FORCE) - set_property(CACHE LLVM_USE_CRT_${build} - PROPERTY STRINGS ;${${MSVC_CRT}}) - endif(NOT LLVM_USE_CRT_${build}) - endforeach(build_type) - - foreach(build_type ${CMAKE_CONFIGURATION_TYPES} ${CMAKE_BUILD_TYPE}) - string(TOUPPER "${build_type}" build) - if ("${LLVM_USE_CRT_${build}}" STREQUAL "") - set(flag_string " ") - else() - set(flag_string " /${LLVM_USE_CRT_${build}} ") - list(FIND ${MSVC_CRT} ${LLVM_USE_CRT_${build}} idx) - if (idx LESS 0) - message(FATAL_ERROR - "Invalid value for LLVM_USE_CRT_${build}: ${LLVM_USE_CRT_${build}}. Valid options are one of: ${${MSVC_CRT}}") - endif (idx LESS 0) - message(STATUS "Using ${build_type} VC++ CRT: ${LLVM_USE_CRT_${build}}") - endif() - foreach(lang C CXX) - set_flag_in_var(CMAKE_${lang}_FLAGS_${build} MSVC_CRT_REGEX flag_string) - endforeach(lang) - endforeach(build_type) -endmacro(choose_msvc_crt MSVC_CRT) - - -# List of valid CRTs for MSVC -set(MSVC_CRT - MD - MDd - MT - MTd) - -choose_msvc_crt(MSVC_CRT) diff --git a/External/glslang/External/CMakeLists.txt b/External/glslang/External/CMakeLists.txt deleted file mode 100644 index 4d969013..00000000 --- a/External/glslang/External/CMakeLists.txt +++ /dev/null @@ -1,43 +0,0 @@ -# Suppress all warnings from external projects. -set_property(DIRECTORY APPEND PROPERTY COMPILE_OPTIONS -w) - -if(BUILD_TESTING) - if(TARGET gmock) - message(STATUS "Google Mock already configured - use it") - elseif(IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/googletest) - # We need to make sure Google Test does not mess up with the - # global CRT settings on Windows. - if(WIN32) - set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) - endif(WIN32) - add_subdirectory(googletest) - set(GTEST_TARGETS - gtest - gtest_main - gmock - gmock_main) - foreach(target ${GTEST_TARGETS}) - set_property(TARGET ${target} PROPERTY FOLDER gtest) - endforeach() - mark_as_advanced(gmock_build_tests - BUILD_GMOCK - BUILD_GTEST - BUILD_SHARED_LIBS - gtest_build_samples - gtest_build_tests - gtest_disable_pthreads - gtest_force_shared_crt - gtest_hide_internal_symbols) - else() - message(STATUS - "Google Mock was not found - tests based on that will not build") - endif() -endif() - -if(ENABLE_OPT AND NOT TARGET SPIRV-Tools-opt) - if(IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/spirv-tools) - set(SPIRV_SKIP_TESTS ON CACHE BOOL "Skip building SPIRV-Tools tests") - add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/spirv-tools spirv-tools) - endif() -endif() - diff --git a/External/glslang/OGLCompilersDLL/CMakeLists.txt b/External/glslang/OGLCompilersDLL/CMakeLists.txt deleted file mode 100644 index 5bb3f0ee..00000000 --- a/External/glslang/OGLCompilersDLL/CMakeLists.txt +++ /dev/null @@ -1,14 +0,0 @@ -set(SOURCES InitializeDll.cpp InitializeDll.h) - -add_library(OGLCompiler STATIC ${SOURCES}) -set_property(TARGET OGLCompiler PROPERTY FOLDER glslang) -set_property(TARGET OGLCompiler PROPERTY POSITION_INDEPENDENT_CODE ON) - -if(WIN32) - source_group("Source" FILES ${SOURCES}) -endif(WIN32) - -if(ENABLE_GLSLANG_INSTALL) - install(TARGETS OGLCompiler - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) -endif(ENABLE_GLSLANG_INSTALL) diff --git a/External/glslang/OGLCompilersDLL/InitializeDll.cpp b/External/glslang/OGLCompilersDLL/InitializeDll.cpp deleted file mode 100644 index abea9108..00000000 --- a/External/glslang/OGLCompilersDLL/InitializeDll.cpp +++ /dev/null @@ -1,165 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -#define SH_EXPORTING - -#include - -#include "InitializeDll.h" -#include "../glslang/Include/InitializeGlobals.h" -#include "../glslang/Public/ShaderLang.h" -#include "../glslang/Include/PoolAlloc.h" - -namespace glslang { - -OS_TLSIndex ThreadInitializeIndex = OS_INVALID_TLS_INDEX; - -// Per-process initialization. -// Needs to be called at least once before parsing, etc. is done. -// Will also do thread initialization for the calling thread; other -// threads will need to do that explicitly. -bool InitProcess() -{ - glslang::GetGlobalLock(); - - if (ThreadInitializeIndex != OS_INVALID_TLS_INDEX) { - // - // Function is re-entrant. - // - - glslang::ReleaseGlobalLock(); - return true; - } - - ThreadInitializeIndex = OS_AllocTLSIndex(); - - if (ThreadInitializeIndex == OS_INVALID_TLS_INDEX) { - assert(0 && "InitProcess(): Failed to allocate TLS area for init flag"); - - glslang::ReleaseGlobalLock(); - return false; - } - - if (! InitializePoolIndex()) { - assert(0 && "InitProcess(): Failed to initialize global pool"); - - glslang::ReleaseGlobalLock(); - return false; - } - - if (! InitThread()) { - assert(0 && "InitProcess(): Failed to initialize thread"); - - glslang::ReleaseGlobalLock(); - return false; - } - - glslang::ReleaseGlobalLock(); - return true; -} - -// Per-thread scoped initialization. -// Must be called at least once by each new thread sharing the -// symbol tables, etc., needed to parse. -bool InitThread() -{ - // - // This function is re-entrant - // - if (ThreadInitializeIndex == OS_INVALID_TLS_INDEX) { - assert(0 && "InitThread(): Process hasn't been initalised."); - return false; - } - - if (OS_GetTLSValue(ThreadInitializeIndex) != 0) - return true; - - if (! OS_SetTLSValue(ThreadInitializeIndex, (void *)1)) { - assert(0 && "InitThread(): Unable to set init flag."); - return false; - } - - glslang::SetThreadPoolAllocator(nullptr); - - return true; -} - -// Not necessary to call this: InitThread() is reentrant, and the need -// to do per thread tear down has been removed. -// -// This is kept, with memory management removed, to satisfy any exiting -// calls to it that rely on it. -bool DetachThread() -{ - bool success = true; - - if (ThreadInitializeIndex == OS_INVALID_TLS_INDEX) - return true; - - // - // Function is re-entrant and this thread may not have been initialized. - // - if (OS_GetTLSValue(ThreadInitializeIndex) != 0) { - if (!OS_SetTLSValue(ThreadInitializeIndex, (void *)0)) { - assert(0 && "DetachThread(): Unable to clear init flag."); - success = false; - } - } - - return success; -} - -// Not necessary to call this: InitProcess() is reentrant. -// -// This is kept, with memory management removed, to satisfy any exiting -// calls to it that rely on it. -// -// Users of glslang should call shFinalize() or glslang::FinalizeProcess() for -// process-scoped memory tear down. -bool DetachProcess() -{ - bool success = true; - - if (ThreadInitializeIndex == OS_INVALID_TLS_INDEX) - return true; - - success = DetachThread(); - - OS_FreeTLSIndex(ThreadInitializeIndex); - ThreadInitializeIndex = OS_INVALID_TLS_INDEX; - - return success; -} - -} // end namespace glslang diff --git a/External/glslang/OGLCompilersDLL/InitializeDll.h b/External/glslang/OGLCompilersDLL/InitializeDll.h deleted file mode 100644 index 661cee4d..00000000 --- a/External/glslang/OGLCompilersDLL/InitializeDll.h +++ /dev/null @@ -1,49 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// -#ifndef __INITIALIZEDLL_H -#define __INITIALIZEDLL_H - -#include "../glslang/OSDependent/osinclude.h" - -namespace glslang { - -bool InitProcess(); -bool InitThread(); -bool DetachThread(); // not called from standalone, perhaps other tools rely on parts of it -bool DetachProcess(); // not called from standalone, perhaps other tools rely on parts of it - -} // end namespace glslang - -#endif // __INITIALIZEDLL_H - diff --git a/External/glslang/README-spirv-remap.txt b/External/glslang/README-spirv-remap.txt deleted file mode 100644 index 3e5288aa..00000000 --- a/External/glslang/README-spirv-remap.txt +++ /dev/null @@ -1,137 +0,0 @@ - -VERSION --------------------------------------------------------------------------------- -spirv-remap 0.97 - -INTRO: --------------------------------------------------------------------------------- -spirv-remap is a utility to improve compression of SPIR-V binary files via -entropy reduction, plus optional stripping of debug information and -load/store optimization. It transforms SPIR-V to SPIR-V, remapping IDs. The -resulting modules have an increased ID range (IDs are not as tightly packed -around zero), but will compress better when multiple modules are compressed -together, since compressor's dictionary can find better cross module -commonality. - -Remapping is accomplished via canonicalization. Thus, modules can be -compressed one at a time with no loss of quality relative to operating on -many modules at once. The command line tool operates on multiple modules -only in the trivial repetition sense, for ease of use. The remapper API -only accepts a single module at a time. - -There are two modes of use: command line, and a C++11 API. Both are -described below. - -spirv-remap is currently in an alpha state. Although there are no known -remapping defects, it has only been exercised on one real world game shader -workload. - - -FEEDBACK --------------------------------------------------------------------------------- -Report defects, enhancements requests, code improvements, etc to: - spvremapper@lunarg.com - - -COMMAND LINE USAGE: --------------------------------------------------------------------------------- -Examples are given with a verbosity of one (-v), but more verbosity can be -had via -vv, -vvv, etc, or an integer parameter to --verbose, such as -"--verbose 4". With no verbosity, the command is silent and returns 0 on -success, and a positive integer error on failure. - -Pre-built binaries for several OSs are available. Examples presented are -for Linux. Command line arguments can be provided in any order. - -1. Basic ID remapping - -Perform ID remapping on all shaders in "*.spv", writing new files with -the same basenames to /tmp/out_dir. - - spirv-remap -v --map all --input *.spv --output /tmp/out_dir - -2. Perform all possible size reductions - - spirv-remap-linux-64 -v --do-everything --input *.spv --output /tmp/out_dir - -Note that --do-everything is a synonym for: - - --map all --dce all --opt all --strip all - -API USAGE: --------------------------------------------------------------------------------- - -The public interface to the remapper is defined in SPIRV/SPVRemapper.h as follows: - -namespace spv { - -class spirvbin_t -{ -public: - enum Options { ... }; - spirvbin_t(int verbose = 0); // construct - - // remap 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 c/c++ fn, lambda fn, or functor) - static void registerErrorHandler(errorfn_t handler) { errorHandler = handler; } - static void registerLogHandler(logfn_t handler) { logHandler = handler; } -}; - -} // namespace spv - -The class definition is in SPVRemapper.cpp. - -remap() accepts an std::vector of SPIR-V words, modifies them per the -request given in 'opts', and leaves the 'spv' container with the result. -It is safe to instantiate one spirvbin_t per thread and process a different -SPIR-V in each. - -The "opts" parameter to remap() accepts a bit mask of desired remapping -options. See REMAPPING AND OPTIMIZATION OPTIONS. - -On error, the function supplied to registerErrorHandler() will be invoked. -This can be a standard C/C++ function, a lambda function, or a functor. -The default handler simply calls exit(5); The error handler is a static -member, so need only be set up once, not once per spirvbin_t instance. - -Log messages are supplied to registerLogHandler(). By default, log -messages are eaten silently. The log handler is also a static member. - -BUILD DEPENDENCIES: --------------------------------------------------------------------------------- - 1. C++11 compatible compiler - 2. cmake - 3. glslang - - -BUILDING --------------------------------------------------------------------------------- -The standalone remapper is built along side glslangValidator through its -normal build process. - - -REMAPPING AND OPTIMIZATION OPTIONS --------------------------------------------------------------------------------- -API: - These are bits defined under spv::spirvbin_t::, and can be - bitwise or-ed together as desired. - - MAP_TYPES = canonicalize type IDs - MAP_NAMES = canonicalize named data - MAP_FUNCS = canonicalize function bodies - DCE_FUNCS = remove dead functions - DCE_VARS = remove dead variables - DCE_TYPES = remove dead types - OPT_LOADSTORE = optimize unneeded load/stores - 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) - diff --git a/External/glslang/README.md b/External/glslang/README.md deleted file mode 100644 index 402b4d60..00000000 --- a/External/glslang/README.md +++ /dev/null @@ -1,332 +0,0 @@ -Also see the Khronos landing page for glslang as a reference front end: - -https://www.khronos.org/opengles/sdk/tools/Reference-Compiler/ - -The above page includes where to get binaries, and is kept up to date -regarding the feature level of glslang. - -glslang -======= - -[![Build Status](https://travis-ci.org/KhronosGroup/glslang.svg?branch=master)](https://travis-ci.org/KhronosGroup/glslang) -[![Build status](https://ci.appveyor.com/api/projects/status/q6fi9cb0qnhkla68/branch/master?svg=true)](https://ci.appveyor.com/project/Khronoswebmaster/glslang/branch/master) - -An OpenGL and OpenGL ES shader front end and validator. - -There are several components: - -1. A GLSL/ESSL front-end for reference validation and translation of GLSL/ESSL into an AST. - -2. An HLSL front-end for translation of a broad generic HLL into the AST. See [issue 362](https://github.com/KhronosGroup/glslang/issues/362) and [issue 701](https://github.com/KhronosGroup/glslang/issues/701) for current status. - -3. A SPIR-V back end for translating the AST to SPIR-V. - -4. A standalone wrapper, `glslangValidator`, that can be used as a command-line tool for the above. - -How to add a feature protected by a version/extension/stage/profile: See the -comment in `glslang/MachineIndependent/Versions.cpp`. - -Tasks waiting to be done are documented as GitHub issues. - -Execution of Standalone Wrapper -------------------------------- - -To use the standalone binary form, execute `glslangValidator`, and it will print -a usage statement. Basic operation is to give it a file containing a shader, -and it will print out warnings/errors and optionally an AST. - -The applied stage-specific rules are based on the file extension: -* `.vert` for a vertex shader -* `.tesc` for a tessellation control shader -* `.tese` for a tessellation evaluation shader -* `.geom` for a geometry shader -* `.frag` for a fragment shader -* `.comp` for a compute shader - -There is also a non-shader extension -* `.conf` for a configuration file of limits, see usage statement for example - -Building --------- - -Instead of building manually, you can also download the binaries for your -platform directly from the [master-tot release][master-tot-release] on GitHub. -Those binaries are automatically uploaded by the buildbots after successful -testing and they always reflect the current top of the tree of the master -branch. - -### Dependencies - -* A C++11 compiler. - (For MSVS: 2015 is recommended, 2013 is fully supported/tested, and 2010 support is attempted, but not tested.) -* [CMake][cmake]: for generating compilation targets. -* make: _Linux_, ninja is an alternative, if configured. -* [Python 2.7][python]: for executing SPIRV-Tools scripts. (Optional if not using SPIRV-Tools.) -* [bison][bison]: _optional_, but needed when changing the grammar (glslang.y). -* [googletest][googletest]: _optional_, but should use if making any changes to glslang. - -### Build steps - -The following steps assume a Bash shell. On Windows, that could be the Git Bash -shell or some other shell of your choosing. - -#### 1) Check-Out this project - -```bash -cd -git clone https://github.com/KhronosGroup/glslang.git -``` - -#### 2) Check-Out External Projects - -```bash -cd -git clone https://github.com/google/googletest.git External/googletest -``` - -If you wish to assure that SPIR-V generated from HLSL is legal for Vulkan, -or wish to invoke -Os to reduce SPIR-V size from HLSL or GLSL, install -spirv-tools with this: - -```bash -./update_glslang_sources.py -``` - -#### 3) Configure - -Assume the source directory is `$SOURCE_DIR` and the build directory is -`$BUILD_DIR`. First ensure the build directory exists, then navigate to it: - -```bash -mkdir -p $BUILD_DIR -cd $BUILD_DIR -``` - -For building on Linux: - -```bash -cmake -DCMAKE_BUILD_TYPE={Debug|Release|RelWithDebInfo} \ - -DCMAKE_INSTALL_PREFIX="$(pwd)/install" $SOURCE_DIR -``` - -For building on Windows: - -```bash -cmake $SOURCE_DIR -DCMAKE_INSTALL_PREFIX="$(pwd)/install" -# The CMAKE_INSTALL_PREFIX part is for testing (explained later). -``` - -The CMake GUI also works for Windows (version 3.4.1 tested). - -#### 4) Build and Install - -```bash -# for Linux: -make -j4 install - -# for Windows: -cmake --build . --config {Release|Debug|MinSizeRel|RelWithDebInfo} \ - --target install -``` - -If using MSVC, after running CMake to configure, use the -Configuration Manager to check the `INSTALL` project. - -### If you need to change the GLSL grammar - -The grammar in `glslang/MachineIndependent/glslang.y` has to be recompiled with -bison if it changes, the output files are committed to the repo to avoid every -developer needing to have bison configured to compile the project when grammar -changes are quite infrequent. For windows you can get binaries from -[GnuWin32][bison-gnu-win32]. - -The command to rebuild is: - -```bash -bison --defines=MachineIndependent/glslang_tab.cpp.h - -t MachineIndependent/glslang.y - -o MachineIndependent/glslang_tab.cpp -``` - -The above command is also available in the bash script at -`glslang/updateGrammar`. - -Testing -------- - -Right now, there are two test harnesses existing in glslang: one is [Google -Test](gtests/), one is the [`runtests` script](Test/runtests). The former -runs unit tests and single-shader single-threaded integration tests, while -the latter runs multiple-shader linking tests and multi-threaded tests. - -### Running tests - -The [`runtests` script](Test/runtests) requires compiled binaries to be -installed into `$BUILD_DIR/install`. Please make sure you have supplied the -correct configuration to CMake (using `-DCMAKE_INSTALL_PREFIX`) when building; -otherwise, you may want to modify the path in the `runtests` script. - -Running Google Test-backed tests: - -```bash -cd $BUILD_DIR - -# for Linux: -ctest - -# for Windows: -ctest -C {Debug|Release|RelWithDebInfo|MinSizeRel} - -# or, run the test binary directly -# (which gives more fine-grained control like filtering): -/glslangtests -``` - -Running `runtests` script-backed tests: - -```bash -cd $SOURCE_DIR/Test && ./runtests -``` - -### Contributing tests - -Test results should always be included with a pull request that modifies -functionality. - -If you are writing unit tests, please use the Google Test framework and -place the tests under the `gtests/` directory. - -Integration tests are placed in the `Test/` directory. It contains test input -and a subdirectory `baseResults/` that contains the expected results of the -tests. Both the tests and `baseResults/` are under source-code control. - -Google Test runs those integration tests by reading the test input, compiling -them, and then compare against the expected results in `baseResults/`. The -integration tests to run via Google Test is registered in various -`gtests/*.FromFile.cpp` source files. `glslangtests` provides a command-line -option `--update-mode`, which, if supplied, will overwrite the golden files -under the `baseResults/` directory with real output from that invocation. -For more information, please check `gtests/` directory's -[README](gtests/README.md). - -For the `runtests` script, it will generate current results in the -`localResults/` directory and `diff` them against the `baseResults/`. -When you want to update the tracked test results, they need to be -copied from `localResults/` to `baseResults/`. This can be done by -the `bump` shell script. - -You can add your own private list of tests, not tracked publicly, by using -`localtestlist` to list non-tracked tests. This is automatically read -by `runtests` and included in the `diff` and `bump` process. - -Programmatic Interfaces ------------------------ - -Another piece of software can programmatically translate shaders to an AST -using one of two different interfaces: -* A new C++ class-oriented interface, or -* The original C functional interface - -The `main()` in `StandAlone/StandAlone.cpp` shows examples using both styles. - -### C++ Class Interface (new, preferred) - -This interface is in roughly the last 1/3 of `ShaderLang.h`. It is in the -glslang namespace and contains the following. - -```cxx -const char* GetEsslVersionString(); -const char* GetGlslVersionString(); -bool InitializeProcess(); -void FinalizeProcess(); - -class TShader - setStrings(...); - setEnvInput(EShSourceHlsl or EShSourceGlsl, stage, EShClientVulkan or EShClientOpenGL, 100); - setEnvClient(EShClientVulkan or EShClientOpenGL, EShTargetVulkan_1_0 or EShTargetVulkan_1_1 or EShTargetOpenGL_450); - setEnvTarget(EShTargetSpv, EShTargetSpv_1_0 or EShTargetSpv_1_3); - bool parse(...); - const char* getInfoLog(); - -class TProgram - void addShader(...); - bool link(...); - const char* getInfoLog(); - Reflection queries -``` - -See `ShaderLang.h` and the usage of it in `StandAlone/StandAlone.cpp` for more -details. - -### C Functional Interface (orignal) - -This interface is in roughly the first 2/3 of `ShaderLang.h`, and referred to -as the `Sh*()` interface, as all the entry points start `Sh`. - -The `Sh*()` interface takes a "compiler" call-back object, which it calls after -building call back that is passed the AST and can then execute a backend on it. - -The following is a simplified resulting run-time call stack: - -```c -ShCompile(shader, compiler) -> compiler(AST) -> -``` - -In practice, `ShCompile()` takes shader strings, default version, and -warning/error and other options for controlling compilation. - -Basic Internal Operation ------------------------- - -* Initial lexical analysis is done by the preprocessor in - `MachineIndependent/Preprocessor`, and then refined by a GLSL scanner - in `MachineIndependent/Scan.cpp`. There is currently no use of flex. - -* Code is parsed using bison on `MachineIndependent/glslang.y` with the - aid of a symbol table and an AST. The symbol table is not passed on to - the back-end; the intermediate representation stands on its own. - The tree is built by the grammar productions, many of which are - offloaded into `ParseHelper.cpp`, and by `Intermediate.cpp`. - -* The intermediate representation is very high-level, and represented - as an in-memory tree. This serves to lose no information from the - original program, and to have efficient transfer of the result from - parsing to the back-end. In the AST, constants are propogated and - folded, and a very small amount of dead code is eliminated. - - To aid linking and reflection, the last top-level branch in the AST - lists all global symbols. - -* The primary algorithm of the back-end compiler is to traverse the - tree (high-level intermediate representation), and create an internal - object code representation. There is an example of how to do this - in `MachineIndependent/intermOut.cpp`. - -* Reduction of the tree to a linear byte-code style low-level intermediate - representation is likely a good way to generate fully optimized code. - -* There is currently some dead old-style linker-type code still lying around. - -* Memory pool: parsing uses types derived from C++ `std` types, using a - custom allocator that puts them in a memory pool. This makes allocation - of individual container/contents just few cycles and deallocation free. - This pool is popped after the AST is made and processed. - - The use is simple: if you are going to call `new`, there are three cases: - - - the object comes from the pool (its base class has the macro - `POOL_ALLOCATOR_NEW_DELETE` in it) and you do not have to call `delete` - - - it is a `TString`, in which case call `NewPoolTString()`, which gets - it from the pool, and there is no corresponding `delete` - - - the object does not come from the pool, and you have to do normal - C++ memory management of what you `new` - - -[cmake]: https://cmake.org/ -[python]: https://www.python.org/ -[bison]: https://www.gnu.org/software/bison/ -[googletest]: https://github.com/google/googletest -[bison-gnu-win32]: http://gnuwin32.sourceforge.net/packages/bison.htm -[master-tot-release]: https://github.com/KhronosGroup/glslang/releases/tag/master-tot diff --git a/External/glslang/SPIRV/CMakeLists.txt b/External/glslang/SPIRV/CMakeLists.txt deleted file mode 100644 index 1e32e275..00000000 --- a/External/glslang/SPIRV/CMakeLists.txt +++ /dev/null @@ -1,76 +0,0 @@ -set(SOURCES - GlslangToSpv.cpp - InReadableOrder.cpp - Logger.cpp - SpvBuilder.cpp - doc.cpp - disassemble.cpp) - -set(SPVREMAP_SOURCES - SPVRemapper.cpp - doc.cpp) - -set(HEADERS - bitutils.h - spirv.hpp - GLSL.std.450.h - GLSL.ext.EXT.h - GLSL.ext.KHR.h - GlslangToSpv.h - hex_float.h - Logger.h - SpvBuilder.h - spvIR.h - doc.h - disassemble.h) - -set(SPVREMAP_HEADERS - SPVRemapper.h - doc.h) - -if(ENABLE_AMD_EXTENSIONS) - list(APPEND - HEADERS - GLSL.ext.AMD.h) -endif(ENABLE_AMD_EXTENSIONS) - -if(ENABLE_NV_EXTENSIONS) - list(APPEND - HEADERS - GLSL.ext.NV.h) -endif(ENABLE_NV_EXTENSIONS) - -add_library(SPIRV ${LIB_TYPE} ${SOURCES} ${HEADERS}) -set_property(TARGET SPIRV PROPERTY FOLDER glslang) -set_property(TARGET SPIRV PROPERTY POSITION_INDEPENDENT_CODE ON) - -add_library(SPVRemapper ${LIB_TYPE} ${SPVREMAP_SOURCES} ${SPVREMAP_HEADERS}) -set_property(TARGET SPVRemapper PROPERTY FOLDER glslang) -set_property(TARGET SPVRemapper PROPERTY POSITION_INDEPENDENT_CODE ON) - -if(WIN32 AND BUILD_SHARED_LIBS) - set_target_properties(SPIRV PROPERTIES PREFIX "") - set_target_properties(SPVRemapper PROPERTIES PREFIX "") -endif() - -if(ENABLE_OPT) - target_include_directories(SPIRV - PRIVATE ${spirv-tools_SOURCE_DIR}/include - PRIVATE ${spirv-tools_SOURCE_DIR}/source - ) - target_link_libraries(SPIRV glslang SPIRV-Tools-opt) -else() - target_link_libraries(SPIRV glslang) -endif(ENABLE_OPT) - -if(WIN32) - source_group("Source" FILES ${SOURCES} ${HEADERS}) - source_group("Source" FILES ${SPVREMAP_SOURCES} ${SPVREMAP_HEADERS}) -endif(WIN32) - -if(ENABLE_GLSLANG_INSTALL) - install(TARGETS SPIRV SPVRemapper - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) - - install(FILES ${HEADERS} ${SPVREMAP_HEADERS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/SPIRV/) -endif(ENABLE_GLSLANG_INSTALL) diff --git a/External/glslang/SPIRV/GLSL.ext.AMD.h b/External/glslang/SPIRV/GLSL.ext.AMD.h deleted file mode 100644 index 009d2f1c..00000000 --- a/External/glslang/SPIRV/GLSL.ext.AMD.h +++ /dev/null @@ -1,108 +0,0 @@ -/* -** Copyright (c) 2014-2016 The Khronos Group Inc. -** -** Permission is hereby granted, free of charge, to any person obtaining a copy -** of this software and/or associated documentation files (the "Materials"), -** to deal in the Materials without restriction, including without limitation -** the rights to use, copy, modify, merge, publish, distribute, sublicense, -** and/or sell copies of the Materials, and to permit persons to whom the -** Materials are furnished to do so, subject to the following conditions: -** -** The above copyright notice and this permission notice shall be included in -** all copies or substantial portions of the Materials. -** -** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS -** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND -** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ -** -** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS -** IN THE MATERIALS. -*/ - -#ifndef GLSLextAMD_H -#define GLSLextAMD_H - -static const int GLSLextAMDVersion = 100; -static const int GLSLextAMDRevision = 7; - -// SPV_AMD_shader_ballot -static const char* const E_SPV_AMD_shader_ballot = "SPV_AMD_shader_ballot"; - -enum ShaderBallotAMD { - ShaderBallotBadAMD = 0, // Don't use - - SwizzleInvocationsAMD = 1, - SwizzleInvocationsMaskedAMD = 2, - WriteInvocationAMD = 3, - MbcntAMD = 4, - - ShaderBallotCountAMD -}; - -// SPV_AMD_shader_trinary_minmax -static const char* const E_SPV_AMD_shader_trinary_minmax = "SPV_AMD_shader_trinary_minmax"; - -enum ShaderTrinaryMinMaxAMD { - ShaderTrinaryMinMaxBadAMD = 0, // Don't use - - FMin3AMD = 1, - UMin3AMD = 2, - SMin3AMD = 3, - FMax3AMD = 4, - UMax3AMD = 5, - SMax3AMD = 6, - FMid3AMD = 7, - UMid3AMD = 8, - SMid3AMD = 9, - - ShaderTrinaryMinMaxCountAMD -}; - -// SPV_AMD_shader_explicit_vertex_parameter -static const char* const E_SPV_AMD_shader_explicit_vertex_parameter = "SPV_AMD_shader_explicit_vertex_parameter"; - -enum ShaderExplicitVertexParameterAMD { - ShaderExplicitVertexParameterBadAMD = 0, // Don't use - - InterpolateAtVertexAMD = 1, - - ShaderExplicitVertexParameterCountAMD -}; - -// SPV_AMD_gcn_shader -static const char* const E_SPV_AMD_gcn_shader = "SPV_AMD_gcn_shader"; - -enum GcnShaderAMD { - GcnShaderBadAMD = 0, // Don't use - - CubeFaceIndexAMD = 1, - CubeFaceCoordAMD = 2, - TimeAMD = 3, - - GcnShaderCountAMD -}; - -// SPV_AMD_gpu_shader_half_float -static const char* const E_SPV_AMD_gpu_shader_half_float = "SPV_AMD_gpu_shader_half_float"; - -// SPV_AMD_texture_gather_bias_lod -static const char* const E_SPV_AMD_texture_gather_bias_lod = "SPV_AMD_texture_gather_bias_lod"; - -// SPV_AMD_gpu_shader_int16 -static const char* const E_SPV_AMD_gpu_shader_int16 = "SPV_AMD_gpu_shader_int16"; - -// SPV_AMD_shader_image_load_store_lod -static const char* const E_SPV_AMD_shader_image_load_store_lod = "SPV_AMD_shader_image_load_store_lod"; - -// SPV_AMD_shader_fragment_mask -static const char* const E_SPV_AMD_shader_fragment_mask = "SPV_AMD_shader_fragment_mask"; - -// SPV_AMD_gpu_shader_half_float_fetch -static const char* const E_SPV_AMD_gpu_shader_half_float_fetch = "SPV_AMD_gpu_shader_half_float_fetch"; - -#endif // #ifndef GLSLextAMD_H diff --git a/External/glslang/SPIRV/GLSL.ext.EXT.h b/External/glslang/SPIRV/GLSL.ext.EXT.h deleted file mode 100644 index c4a24308..00000000 --- a/External/glslang/SPIRV/GLSL.ext.EXT.h +++ /dev/null @@ -1,37 +0,0 @@ -/* -** Copyright (c) 2014-2016 The Khronos Group Inc. -** -** Permission is hereby granted, free of charge, to any person obtaining a copy -** of this software and/or associated documentation files (the "Materials"), -** to deal in the Materials without restriction, including without limitation -** the rights to use, copy, modify, merge, publish, distribute, sublicense, -** and/or sell copies of the Materials, and to permit persons to whom the -** Materials are furnished to do so, subject to the following conditions: -** -** The above copyright notice and this permission notice shall be included in -** all copies or substantial portions of the Materials. -** -** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS -** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND -** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ -** -** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS -** IN THE MATERIALS. -*/ - -#ifndef GLSLextEXT_H -#define GLSLextEXT_H - -static const int GLSLextEXTVersion = 100; -static const int GLSLextEXTRevision = 1; - -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"; - -#endif // #ifndef GLSLextEXT_H diff --git a/External/glslang/SPIRV/GLSL.ext.KHR.h b/External/glslang/SPIRV/GLSL.ext.KHR.h deleted file mode 100644 index d8ea9b67..00000000 --- a/External/glslang/SPIRV/GLSL.ext.KHR.h +++ /dev/null @@ -1,42 +0,0 @@ -/* -** Copyright (c) 2014-2016 The Khronos Group Inc. -** -** Permission is hereby granted, free of charge, to any person obtaining a copy -** of this software and/or associated documentation files (the "Materials"), -** to deal in the Materials without restriction, including without limitation -** the rights to use, copy, modify, merge, publish, distribute, sublicense, -** and/or sell copies of the Materials, and to permit persons to whom the -** Materials are furnished to do so, subject to the following conditions: -** -** The above copyright notice and this permission notice shall be included in -** all copies or substantial portions of the Materials. -** -** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS -** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND -** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ -** -** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS -** IN THE MATERIALS. -*/ - -#ifndef GLSLextKHR_H -#define GLSLextKHR_H - -static const int GLSLextKHRVersion = 100; -static const int GLSLextKHRRevision = 2; - -static const char* const E_SPV_KHR_shader_ballot = "SPV_KHR_shader_ballot"; -static const char* const E_SPV_KHR_subgroup_vote = "SPV_KHR_subgroup_vote"; -static const char* const E_SPV_KHR_device_group = "SPV_KHR_device_group"; -static const char* const E_SPV_KHR_multiview = "SPV_KHR_multiview"; -static const char* const E_SPV_KHR_shader_draw_parameters = "SPV_KHR_shader_draw_parameters"; -static const char* const E_SPV_KHR_16bit_storage = "SPV_KHR_16bit_storage"; -static const char* const E_SPV_KHR_storage_buffer_storage_class = "SPV_KHR_storage_buffer_storage_class"; -static const char* const E_SPV_KHR_post_depth_coverage = "SPV_KHR_post_depth_coverage"; - -#endif // #ifndef GLSLextKHR_H diff --git a/External/glslang/SPIRV/GLSL.ext.NV.h b/External/glslang/SPIRV/GLSL.ext.NV.h deleted file mode 100644 index 148d4b45..00000000 --- a/External/glslang/SPIRV/GLSL.ext.NV.h +++ /dev/null @@ -1,57 +0,0 @@ -/* -** Copyright (c) 2014-2017 The Khronos Group Inc. -** -** Permission is hereby granted, free of charge, to any person obtaining a copy -** of this software and/or associated documentation files (the "Materials"), -** to deal in the Materials without restriction, including without limitation -** the rights to use, copy, modify, merge, publish, distribute, sublicense, -** and/or sell copies of the Materials, and to permit persons to whom the -** Materials are furnished to do so, subject to the following conditions: -** -** The above copyright notice and this permission notice shall be included in -** all copies or substantial portions of the Materials. -** -** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS -** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND -** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ -** -** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS -** IN THE MATERIALS. -*/ - -#ifndef GLSLextNV_H -#define GLSLextNV_H - -enum BuiltIn; -enum Decoration; -enum Op; -enum Capability; - -static const int GLSLextNVVersion = 100; -static const int GLSLextNVRevision = 5; - -//SPV_NV_sample_mask_override_coverage -const char* const E_SPV_NV_sample_mask_override_coverage = "SPV_NV_sample_mask_override_coverage"; - -//SPV_NV_geometry_shader_passthrough -const char* const E_SPV_NV_geometry_shader_passthrough = "SPV_NV_geometry_shader_passthrough"; - -//SPV_NV_viewport_array2 -const char* const E_SPV_NV_viewport_array2 = "SPV_NV_viewport_array2"; -const char* const E_ARB_shader_viewport_layer_array = "SPV_ARB_shader_viewport_layer_array"; - -//SPV_NV_stereo_view_rendering -const char* const E_SPV_NV_stereo_view_rendering = "SPV_NV_stereo_view_rendering"; - -//SPV_NVX_multiview_per_view_attributes -const char* const E_SPV_NVX_multiview_per_view_attributes = "SPV_NVX_multiview_per_view_attributes"; - -//SPV_NV_shader_subgroup_partitioned -const char* const E_SPV_NV_shader_subgroup_partitioned = "SPV_NV_shader_subgroup_partitioned"; - -#endif // #ifndef GLSLextNV_H \ No newline at end of file diff --git a/External/glslang/SPIRV/GLSL.std.450.h b/External/glslang/SPIRV/GLSL.std.450.h deleted file mode 100644 index df31092b..00000000 --- a/External/glslang/SPIRV/GLSL.std.450.h +++ /dev/null @@ -1,131 +0,0 @@ -/* -** Copyright (c) 2014-2016 The Khronos Group Inc. -** -** Permission is hereby granted, free of charge, to any person obtaining a copy -** of this software and/or associated documentation files (the "Materials"), -** to deal in the Materials without restriction, including without limitation -** the rights to use, copy, modify, merge, publish, distribute, sublicense, -** and/or sell copies of the Materials, and to permit persons to whom the -** Materials are furnished to do so, subject to the following conditions: -** -** The above copyright notice and this permission notice shall be included in -** all copies or substantial portions of the Materials. -** -** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS -** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND -** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ -** -** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS -** IN THE MATERIALS. -*/ - -#ifndef GLSLstd450_H -#define GLSLstd450_H - -static const int GLSLstd450Version = 100; -static const int GLSLstd450Revision = 1; - -enum GLSLstd450 { - GLSLstd450Bad = 0, // Don't use - - GLSLstd450Round = 1, - GLSLstd450RoundEven = 2, - GLSLstd450Trunc = 3, - GLSLstd450FAbs = 4, - GLSLstd450SAbs = 5, - GLSLstd450FSign = 6, - GLSLstd450SSign = 7, - GLSLstd450Floor = 8, - GLSLstd450Ceil = 9, - GLSLstd450Fract = 10, - - GLSLstd450Radians = 11, - GLSLstd450Degrees = 12, - GLSLstd450Sin = 13, - GLSLstd450Cos = 14, - GLSLstd450Tan = 15, - GLSLstd450Asin = 16, - GLSLstd450Acos = 17, - GLSLstd450Atan = 18, - GLSLstd450Sinh = 19, - GLSLstd450Cosh = 20, - GLSLstd450Tanh = 21, - GLSLstd450Asinh = 22, - GLSLstd450Acosh = 23, - GLSLstd450Atanh = 24, - GLSLstd450Atan2 = 25, - - GLSLstd450Pow = 26, - GLSLstd450Exp = 27, - GLSLstd450Log = 28, - GLSLstd450Exp2 = 29, - GLSLstd450Log2 = 30, - GLSLstd450Sqrt = 31, - GLSLstd450InverseSqrt = 32, - - GLSLstd450Determinant = 33, - GLSLstd450MatrixInverse = 34, - - GLSLstd450Modf = 35, // second operand needs an OpVariable to write to - GLSLstd450ModfStruct = 36, // no OpVariable operand - GLSLstd450FMin = 37, - GLSLstd450UMin = 38, - GLSLstd450SMin = 39, - GLSLstd450FMax = 40, - GLSLstd450UMax = 41, - GLSLstd450SMax = 42, - GLSLstd450FClamp = 43, - GLSLstd450UClamp = 44, - GLSLstd450SClamp = 45, - GLSLstd450FMix = 46, - GLSLstd450IMix = 47, // Reserved - GLSLstd450Step = 48, - GLSLstd450SmoothStep = 49, - - GLSLstd450Fma = 50, - GLSLstd450Frexp = 51, // second operand needs an OpVariable to write to - GLSLstd450FrexpStruct = 52, // no OpVariable operand - GLSLstd450Ldexp = 53, - - GLSLstd450PackSnorm4x8 = 54, - GLSLstd450PackUnorm4x8 = 55, - GLSLstd450PackSnorm2x16 = 56, - GLSLstd450PackUnorm2x16 = 57, - GLSLstd450PackHalf2x16 = 58, - GLSLstd450PackDouble2x32 = 59, - GLSLstd450UnpackSnorm2x16 = 60, - GLSLstd450UnpackUnorm2x16 = 61, - GLSLstd450UnpackHalf2x16 = 62, - GLSLstd450UnpackSnorm4x8 = 63, - GLSLstd450UnpackUnorm4x8 = 64, - GLSLstd450UnpackDouble2x32 = 65, - - GLSLstd450Length = 66, - GLSLstd450Distance = 67, - GLSLstd450Cross = 68, - GLSLstd450Normalize = 69, - GLSLstd450FaceForward = 70, - GLSLstd450Reflect = 71, - GLSLstd450Refract = 72, - - GLSLstd450FindILsb = 73, - GLSLstd450FindSMsb = 74, - GLSLstd450FindUMsb = 75, - - GLSLstd450InterpolateAtCentroid = 76, - GLSLstd450InterpolateAtSample = 77, - GLSLstd450InterpolateAtOffset = 78, - - GLSLstd450NMin = 79, - GLSLstd450NMax = 80, - GLSLstd450NClamp = 81, - - GLSLstd450Count -}; - -#endif // #ifndef GLSLstd450_H diff --git a/External/glslang/SPIRV/GlslangToSpv.cpp b/External/glslang/SPIRV/GlslangToSpv.cpp deleted file mode 100644 index 95b507b1..00000000 --- a/External/glslang/SPIRV/GlslangToSpv.cpp +++ /dev/null @@ -1,7019 +0,0 @@ -// -// Copyright (C) 2014-2016 LunarG, Inc. -// Copyright (C) 2015-2016 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. - -// -// Visit the nodes in the glslang intermediate tree representation to -// translate them to SPIR-V. -// - -#include "spirv.hpp" -#include "GlslangToSpv.h" -#include "SpvBuilder.h" -namespace spv { - #include "GLSL.std.450.h" - #include "GLSL.ext.KHR.h" - #include "GLSL.ext.EXT.h" -#ifdef AMD_EXTENSIONS - #include "GLSL.ext.AMD.h" -#endif -#ifdef NV_EXTENSIONS - #include "GLSL.ext.NV.h" -#endif -} - -#if ENABLE_OPT - #include "spirv-tools/optimizer.hpp" - #include "message.h" -#endif - -#if ENABLE_OPT -using namespace spvtools; -#endif - -// Glslang includes -#include "../glslang/MachineIndependent/localintermediate.h" -#include "../glslang/MachineIndependent/SymbolTable.h" -#include "../glslang/Include/Common.h" -#include "../glslang/Include/revision.h" - -#include -#include -#include -#include -#include -#include -#include - -namespace { - -namespace { -class SpecConstantOpModeGuard { -public: - SpecConstantOpModeGuard(spv::Builder* builder) - : builder_(builder) { - previous_flag_ = builder->isInSpecConstCodeGenMode(); - } - ~SpecConstantOpModeGuard() { - previous_flag_ ? builder_->setToSpecConstCodeGenMode() - : builder_->setToNormalCodeGenMode(); - } - void turnOnSpecConstantOpMode() { - builder_->setToSpecConstCodeGenMode(); - } - -private: - spv::Builder* builder_; - bool previous_flag_; -}; - -struct OpDecorations { - spv::Decoration precision; - spv::Decoration noContraction; - spv::Decoration nonUniform; -}; - -} // namespace - -// -// The main holder of information for translating glslang to SPIR-V. -// -// Derives from the AST walking base class. -// -class TGlslangToSpvTraverser : public glslang::TIntermTraverser { -public: - TGlslangToSpvTraverser(unsigned int spvVersion, const glslang::TIntermediate*, spv::SpvBuildLogger* logger, - glslang::SpvOptions& options); - virtual ~TGlslangToSpvTraverser() { } - - bool visitAggregate(glslang::TVisit, glslang::TIntermAggregate*); - bool visitBinary(glslang::TVisit, glslang::TIntermBinary*); - void visitConstantUnion(glslang::TIntermConstantUnion*); - bool visitSelection(glslang::TVisit, glslang::TIntermSelection*); - bool visitSwitch(glslang::TVisit, glslang::TIntermSwitch*); - void visitSymbol(glslang::TIntermSymbol* symbol); - bool visitUnary(glslang::TVisit, glslang::TIntermUnary*); - bool visitLoop(glslang::TVisit, glslang::TIntermLoop*); - bool visitBranch(glslang::TVisit visit, glslang::TIntermBranch*); - - void finishSpv(); - void dumpSpv(std::vector& out); - -protected: - TGlslangToSpvTraverser(TGlslangToSpvTraverser&); - TGlslangToSpvTraverser& operator=(TGlslangToSpvTraverser&); - - spv::Decoration TranslateInterpolationDecoration(const glslang::TQualifier& qualifier); - spv::Decoration TranslateAuxiliaryStorageDecoration(const glslang::TQualifier& qualifier); - spv::Decoration TranslateNonUniformDecoration(const glslang::TQualifier& qualifier); - spv::BuiltIn TranslateBuiltInDecoration(glslang::TBuiltInVariable, bool memberDeclaration); - spv::ImageFormat TranslateImageFormat(const glslang::TType& type); - spv::SelectionControlMask TranslateSelectionControl(const glslang::TIntermSelection&) const; - spv::SelectionControlMask TranslateSwitchControl(const glslang::TIntermSwitch&) const; - spv::LoopControlMask TranslateLoopControl(const glslang::TIntermLoop&, unsigned int& dependencyLength) const; - spv::StorageClass TranslateStorageClass(const glslang::TType&); - void addIndirectionIndexCapabilities(const glslang::TType& baseType, const glslang::TType& indexType); - spv::Id createSpvVariable(const glslang::TIntermSymbol*); - spv::Id getSampledType(const glslang::TSampler&); - spv::Id getInvertedSwizzleType(const glslang::TIntermTyped&); - spv::Id createInvertedSwizzle(spv::Decoration precision, const glslang::TIntermTyped&, spv::Id parentResult); - void convertSwizzle(const glslang::TIntermAggregate&, std::vector& swizzle); - spv::Id convertGlslangToSpvType(const glslang::TType& type); - spv::Id convertGlslangToSpvType(const glslang::TType& type, glslang::TLayoutPacking, const glslang::TQualifier&, - bool lastBufferBlockMember); - bool filterMember(const glslang::TType& member); - spv::Id convertGlslangStructToSpvType(const glslang::TType&, const glslang::TTypeList* glslangStruct, - glslang::TLayoutPacking, const glslang::TQualifier&); - void decorateStructType(const glslang::TType&, const glslang::TTypeList* glslangStruct, glslang::TLayoutPacking, - const glslang::TQualifier&, spv::Id); - spv::Id makeArraySizeId(const glslang::TArraySizes&, int dim); - spv::Id accessChainLoad(const glslang::TType& type); - void accessChainStore(const glslang::TType& type, spv::Id rvalue); - void multiTypeStore(const glslang::TType&, spv::Id rValue); - glslang::TLayoutPacking getExplicitLayout(const glslang::TType& type) const; - int getArrayStride(const glslang::TType& arrayType, glslang::TLayoutPacking, glslang::TLayoutMatrix); - int getMatrixStride(const glslang::TType& matrixType, glslang::TLayoutPacking, glslang::TLayoutMatrix); - void updateMemberOffset(const glslang::TType& structType, const glslang::TType& memberType, int& currentOffset, - int& nextOffset, glslang::TLayoutPacking, glslang::TLayoutMatrix); - void declareUseOfStructMember(const glslang::TTypeList& members, int glslangMember); - - bool isShaderEntryPoint(const glslang::TIntermAggregate* node); - bool writableParam(glslang::TStorageQualifier); - bool originalParam(glslang::TStorageQualifier, const glslang::TType&, bool implicitThisParam); - void makeFunctions(const glslang::TIntermSequence&); - void makeGlobalInitializers(const glslang::TIntermSequence&); - void visitFunctions(const glslang::TIntermSequence&); - void handleFunctionEntry(const glslang::TIntermAggregate* node); - void translateArguments(const glslang::TIntermAggregate& node, std::vector& arguments); - void translateArguments(glslang::TIntermUnary& node, std::vector& arguments); - spv::Id createImageTextureFunctionCall(glslang::TIntermOperator* node); - spv::Id handleUserFunctionCall(const glslang::TIntermAggregate*); - - spv::Id createBinaryOperation(glslang::TOperator op, OpDecorations&, spv::Id typeId, spv::Id left, spv::Id right, - glslang::TBasicType typeProxy, bool reduceComparison = true); - spv::Id createBinaryMatrixOperation(spv::Op, OpDecorations&, spv::Id typeId, spv::Id left, spv::Id right); - spv::Id createUnaryOperation(glslang::TOperator op, OpDecorations&, spv::Id typeId, spv::Id operand, - glslang::TBasicType typeProxy); - spv::Id createUnaryMatrixOperation(spv::Op op, OpDecorations&, spv::Id typeId, spv::Id operand, - glslang::TBasicType typeProxy); - spv::Id createConversion(glslang::TOperator op, OpDecorations&, spv::Id destTypeId, spv::Id operand, - glslang::TBasicType typeProxy); - spv::Id createConversionOperation(glslang::TOperator op, spv::Id operand, int vectorSize); - spv::Id makeSmearedConstant(spv::Id constant, int vectorSize); - spv::Id createAtomicOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId, std::vector& operands, glslang::TBasicType typeProxy); - spv::Id createInvocationsOperation(glslang::TOperator op, spv::Id typeId, std::vector& operands, glslang::TBasicType typeProxy); - spv::Id CreateInvocationsVectorOperation(spv::Op op, spv::GroupOperation groupOperation, spv::Id typeId, std::vector& operands); - spv::Id createSubgroupOperation(glslang::TOperator op, spv::Id typeId, std::vector& operands, glslang::TBasicType typeProxy); - spv::Id createMiscOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId, std::vector& operands, glslang::TBasicType typeProxy); - spv::Id createNoArgOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId); - spv::Id getSymbolId(const glslang::TIntermSymbol* node); - spv::Id createSpvConstant(const glslang::TIntermTyped&); - spv::Id createSpvConstantFromConstUnionArray(const glslang::TType& type, const glslang::TConstUnionArray&, int& nextConst, bool specConstant); - bool isTrivialLeaf(const glslang::TIntermTyped* node); - bool isTrivial(const glslang::TIntermTyped* node); - spv::Id createShortCircuit(glslang::TOperator, glslang::TIntermTyped& left, glslang::TIntermTyped& right); -#ifdef AMD_EXTENSIONS - spv::Id getExtBuiltins(const char* name); -#endif - void addPre13Extension(const char* ext) - { - if (builder.getSpvVersion() < glslang::EShTargetSpv_1_3) - builder.addExtension(ext); - } - - glslang::SpvOptions& options; - spv::Function* shaderEntry; - spv::Function* currentFunction; - spv::Instruction* entryPoint; - int sequenceDepth; - - spv::SpvBuildLogger* logger; - - // There is a 1:1 mapping between a spv builder and a module; this is thread safe - spv::Builder builder; - bool inEntryPoint; - bool entryPointTerminated; - bool linkageOnly; // true when visiting the set of objects in the AST present only for establishing interface, whether or not they were statically used - std::set iOSet; // all input/output variables from either static use or declaration of interface - const glslang::TIntermediate* glslangIntermediate; - spv::Id stdBuiltins; - std::unordered_map extBuiltinMap; - - std::unordered_map symbolValues; - std::unordered_set rValueParameters; // set of formal function parameters passed as rValues, rather than a pointer - std::unordered_map functionMap; - std::unordered_map structMap[glslang::ElpCount][glslang::ElmCount]; - // for mapping glslang block indices to spv indices (e.g., due to hidden members): - std::unordered_map > memberRemapper; - std::stack breakForLoop; // false means break for switch - std::unordered_map counterOriginator; -}; - -// -// Helper functions for translating glslang representations to SPIR-V enumerants. -// - -// Translate glslang profile to SPIR-V source language. -spv::SourceLanguage TranslateSourceLanguage(glslang::EShSource source, EProfile profile) -{ - switch (source) { - case glslang::EShSourceGlsl: - switch (profile) { - case ENoProfile: - case ECoreProfile: - case ECompatibilityProfile: - return spv::SourceLanguageGLSL; - case EEsProfile: - return spv::SourceLanguageESSL; - default: - return spv::SourceLanguageUnknown; - } - case glslang::EShSourceHlsl: - return spv::SourceLanguageHLSL; - default: - return spv::SourceLanguageUnknown; - } -} - -// Translate glslang language (stage) to SPIR-V execution model. -spv::ExecutionModel TranslateExecutionModel(EShLanguage stage) -{ - switch (stage) { - case EShLangVertex: return spv::ExecutionModelVertex; - case EShLangTessControl: return spv::ExecutionModelTessellationControl; - case EShLangTessEvaluation: return spv::ExecutionModelTessellationEvaluation; - case EShLangGeometry: return spv::ExecutionModelGeometry; - case EShLangFragment: return spv::ExecutionModelFragment; - case EShLangCompute: return spv::ExecutionModelGLCompute; - default: - assert(0); - return spv::ExecutionModelFragment; - } -} - -// Translate glslang sampler type to SPIR-V dimensionality. -spv::Dim TranslateDimensionality(const glslang::TSampler& sampler) -{ - switch (sampler.dim) { - case glslang::Esd1D: return spv::Dim1D; - case glslang::Esd2D: return spv::Dim2D; - case glslang::Esd3D: return spv::Dim3D; - case glslang::EsdCube: return spv::DimCube; - case glslang::EsdRect: return spv::DimRect; - case glslang::EsdBuffer: return spv::DimBuffer; - case glslang::EsdSubpass: return spv::DimSubpassData; - default: - assert(0); - return spv::Dim2D; - } -} - -// Translate glslang precision to SPIR-V precision decorations. -spv::Decoration TranslatePrecisionDecoration(glslang::TPrecisionQualifier glslangPrecision) -{ - switch (glslangPrecision) { - case glslang::EpqLow: return spv::DecorationRelaxedPrecision; - case glslang::EpqMedium: return spv::DecorationRelaxedPrecision; - default: - return spv::NoPrecision; - } -} - -// Translate glslang type to SPIR-V precision decorations. -spv::Decoration TranslatePrecisionDecoration(const glslang::TType& type) -{ - return TranslatePrecisionDecoration(type.getQualifier().precision); -} - -// Translate glslang type to SPIR-V block decorations. -spv::Decoration TranslateBlockDecoration(const glslang::TType& type, bool useStorageBuffer) -{ - if (type.getBasicType() == glslang::EbtBlock) { - switch (type.getQualifier().storage) { - case glslang::EvqUniform: return spv::DecorationBlock; - case glslang::EvqBuffer: return useStorageBuffer ? spv::DecorationBlock : spv::DecorationBufferBlock; - case glslang::EvqVaryingIn: return spv::DecorationBlock; - case glslang::EvqVaryingOut: return spv::DecorationBlock; - default: - assert(0); - break; - } - } - - return spv::DecorationMax; -} - -// Translate glslang type to SPIR-V memory decorations. -void TranslateMemoryDecoration(const glslang::TQualifier& qualifier, std::vector& memory) -{ - if (qualifier.coherent) - memory.push_back(spv::DecorationCoherent); - if (qualifier.volatil) - memory.push_back(spv::DecorationVolatile); - if (qualifier.restrict) - memory.push_back(spv::DecorationRestrict); - if (qualifier.readonly) - memory.push_back(spv::DecorationNonWritable); - if (qualifier.writeonly) - memory.push_back(spv::DecorationNonReadable); -} - -// Translate glslang type to SPIR-V layout decorations. -spv::Decoration TranslateLayoutDecoration(const glslang::TType& type, glslang::TLayoutMatrix matrixLayout) -{ - if (type.isMatrix()) { - switch (matrixLayout) { - case glslang::ElmRowMajor: - return spv::DecorationRowMajor; - case glslang::ElmColumnMajor: - return spv::DecorationColMajor; - default: - // opaque layouts don't need a majorness - return spv::DecorationMax; - } - } else { - switch (type.getBasicType()) { - default: - return spv::DecorationMax; - break; - case glslang::EbtBlock: - switch (type.getQualifier().storage) { - case glslang::EvqUniform: - case glslang::EvqBuffer: - switch (type.getQualifier().layoutPacking) { - case glslang::ElpShared: return spv::DecorationGLSLShared; - case glslang::ElpPacked: return spv::DecorationGLSLPacked; - default: - return spv::DecorationMax; - } - case glslang::EvqVaryingIn: - case glslang::EvqVaryingOut: - assert(type.getQualifier().layoutPacking == glslang::ElpNone); - return spv::DecorationMax; - default: - assert(0); - return spv::DecorationMax; - } - } - } -} - -// Translate glslang type to SPIR-V interpolation decorations. -// Returns spv::DecorationMax when no decoration -// should be applied. -spv::Decoration TGlslangToSpvTraverser::TranslateInterpolationDecoration(const glslang::TQualifier& qualifier) -{ - if (qualifier.smooth) - // Smooth decoration doesn't exist in SPIR-V 1.0 - return spv::DecorationMax; - else if (qualifier.nopersp) - return spv::DecorationNoPerspective; - else if (qualifier.flat) - return spv::DecorationFlat; -#ifdef AMD_EXTENSIONS - else if (qualifier.explicitInterp) { - builder.addExtension(spv::E_SPV_AMD_shader_explicit_vertex_parameter); - return spv::DecorationExplicitInterpAMD; - } -#endif - else - return spv::DecorationMax; -} - -// Translate glslang type to SPIR-V auxiliary storage decorations. -// Returns spv::DecorationMax when no decoration -// should be applied. -spv::Decoration TGlslangToSpvTraverser::TranslateAuxiliaryStorageDecoration(const glslang::TQualifier& qualifier) -{ - if (qualifier.patch) - return spv::DecorationPatch; - else if (qualifier.centroid) - return spv::DecorationCentroid; - else if (qualifier.sample) { - builder.addCapability(spv::CapabilitySampleRateShading); - return spv::DecorationSample; - } else - return spv::DecorationMax; -} - -// If glslang type is invariant, return SPIR-V invariant decoration. -spv::Decoration TranslateInvariantDecoration(const glslang::TQualifier& qualifier) -{ - if (qualifier.invariant) - return spv::DecorationInvariant; - else - return spv::DecorationMax; -} - -// If glslang type is noContraction, return SPIR-V NoContraction decoration. -spv::Decoration TranslateNoContractionDecoration(const glslang::TQualifier& qualifier) -{ - if (qualifier.noContraction) - return spv::DecorationNoContraction; - else - return spv::DecorationMax; -} - -// If glslang type is nonUniform, return SPIR-V NonUniform decoration. -spv::Decoration TGlslangToSpvTraverser::TranslateNonUniformDecoration(const glslang::TQualifier& qualifier) -{ - if (qualifier.isNonUniform()) { - builder.addExtension("SPV_EXT_descriptor_indexing"); - builder.addCapability(spv::CapabilityShaderNonUniformEXT); - return spv::DecorationNonUniformEXT; - } else - return spv::DecorationMax; -} - -// Translate a glslang built-in variable to a SPIR-V built in decoration. Also generate -// associated capabilities when required. For some built-in variables, a capability -// is generated only when using the variable in an executable instruction, but not when -// just declaring a struct member variable with it. This is true for PointSize, -// ClipDistance, and CullDistance. -spv::BuiltIn TGlslangToSpvTraverser::TranslateBuiltInDecoration(glslang::TBuiltInVariable builtIn, bool memberDeclaration) -{ - switch (builtIn) { - case glslang::EbvPointSize: - // Defer adding the capability until the built-in is actually used. - if (! memberDeclaration) { - switch (glslangIntermediate->getStage()) { - case EShLangGeometry: - builder.addCapability(spv::CapabilityGeometryPointSize); - break; - case EShLangTessControl: - case EShLangTessEvaluation: - builder.addCapability(spv::CapabilityTessellationPointSize); - break; - default: - break; - } - } - return spv::BuiltInPointSize; - - // These *Distance capabilities logically belong here, but if the member is declared and - // then never used, consumers of SPIR-V prefer the capability not be declared. - // They are now generated when used, rather than here when declared. - // Potentially, the specification should be more clear what the minimum - // use needed is to trigger the capability. - // - case glslang::EbvClipDistance: - if (!memberDeclaration) - builder.addCapability(spv::CapabilityClipDistance); - return spv::BuiltInClipDistance; - - case glslang::EbvCullDistance: - if (!memberDeclaration) - builder.addCapability(spv::CapabilityCullDistance); - return spv::BuiltInCullDistance; - - case glslang::EbvViewportIndex: - builder.addCapability(spv::CapabilityMultiViewport); - if (glslangIntermediate->getStage() == EShLangVertex || - glslangIntermediate->getStage() == EShLangTessControl || - glslangIntermediate->getStage() == EShLangTessEvaluation) { - - builder.addExtension(spv::E_SPV_EXT_shader_viewport_index_layer); - builder.addCapability(spv::CapabilityShaderViewportIndexLayerEXT); - } - return spv::BuiltInViewportIndex; - - case glslang::EbvSampleId: - builder.addCapability(spv::CapabilitySampleRateShading); - return spv::BuiltInSampleId; - - case glslang::EbvSamplePosition: - builder.addCapability(spv::CapabilitySampleRateShading); - return spv::BuiltInSamplePosition; - - case glslang::EbvSampleMask: - return spv::BuiltInSampleMask; - - case glslang::EbvLayer: - builder.addCapability(spv::CapabilityGeometry); - if (glslangIntermediate->getStage() == EShLangVertex || - glslangIntermediate->getStage() == EShLangTessControl || - glslangIntermediate->getStage() == EShLangTessEvaluation) { - - builder.addExtension(spv::E_SPV_EXT_shader_viewport_index_layer); - builder.addCapability(spv::CapabilityShaderViewportIndexLayerEXT); - } - return spv::BuiltInLayer; - - case glslang::EbvPosition: return spv::BuiltInPosition; - case glslang::EbvVertexId: return spv::BuiltInVertexId; - case glslang::EbvInstanceId: return spv::BuiltInInstanceId; - case glslang::EbvVertexIndex: return spv::BuiltInVertexIndex; - case glslang::EbvInstanceIndex: return spv::BuiltInInstanceIndex; - - case glslang::EbvBaseVertex: - addPre13Extension(spv::E_SPV_KHR_shader_draw_parameters); - builder.addCapability(spv::CapabilityDrawParameters); - return spv::BuiltInBaseVertex; - - case glslang::EbvBaseInstance: - addPre13Extension(spv::E_SPV_KHR_shader_draw_parameters); - builder.addCapability(spv::CapabilityDrawParameters); - return spv::BuiltInBaseInstance; - - case glslang::EbvDrawId: - addPre13Extension(spv::E_SPV_KHR_shader_draw_parameters); - builder.addCapability(spv::CapabilityDrawParameters); - return spv::BuiltInDrawIndex; - - case glslang::EbvPrimitiveId: - if (glslangIntermediate->getStage() == EShLangFragment) - builder.addCapability(spv::CapabilityGeometry); - return spv::BuiltInPrimitiveId; - - case glslang::EbvFragStencilRef: - builder.addExtension(spv::E_SPV_EXT_shader_stencil_export); - builder.addCapability(spv::CapabilityStencilExportEXT); - return spv::BuiltInFragStencilRefEXT; - - case glslang::EbvInvocationId: return spv::BuiltInInvocationId; - case glslang::EbvTessLevelInner: return spv::BuiltInTessLevelInner; - case glslang::EbvTessLevelOuter: return spv::BuiltInTessLevelOuter; - case glslang::EbvTessCoord: return spv::BuiltInTessCoord; - case glslang::EbvPatchVertices: return spv::BuiltInPatchVertices; - case glslang::EbvFragCoord: return spv::BuiltInFragCoord; - case glslang::EbvPointCoord: return spv::BuiltInPointCoord; - case glslang::EbvFace: return spv::BuiltInFrontFacing; - case glslang::EbvFragDepth: return spv::BuiltInFragDepth; - case glslang::EbvHelperInvocation: return spv::BuiltInHelperInvocation; - case glslang::EbvNumWorkGroups: return spv::BuiltInNumWorkgroups; - case glslang::EbvWorkGroupSize: return spv::BuiltInWorkgroupSize; - case glslang::EbvWorkGroupId: return spv::BuiltInWorkgroupId; - case glslang::EbvLocalInvocationId: return spv::BuiltInLocalInvocationId; - case glslang::EbvLocalInvocationIndex: return spv::BuiltInLocalInvocationIndex; - case glslang::EbvGlobalInvocationId: return spv::BuiltInGlobalInvocationId; - - case glslang::EbvSubGroupSize: - builder.addExtension(spv::E_SPV_KHR_shader_ballot); - builder.addCapability(spv::CapabilitySubgroupBallotKHR); - return spv::BuiltInSubgroupSize; - - case glslang::EbvSubGroupInvocation: - builder.addExtension(spv::E_SPV_KHR_shader_ballot); - builder.addCapability(spv::CapabilitySubgroupBallotKHR); - return spv::BuiltInSubgroupLocalInvocationId; - - case glslang::EbvSubGroupEqMask: - builder.addExtension(spv::E_SPV_KHR_shader_ballot); - builder.addCapability(spv::CapabilitySubgroupBallotKHR); - return spv::BuiltInSubgroupEqMaskKHR; - - case glslang::EbvSubGroupGeMask: - builder.addExtension(spv::E_SPV_KHR_shader_ballot); - builder.addCapability(spv::CapabilitySubgroupBallotKHR); - return spv::BuiltInSubgroupGeMaskKHR; - - case glslang::EbvSubGroupGtMask: - builder.addExtension(spv::E_SPV_KHR_shader_ballot); - builder.addCapability(spv::CapabilitySubgroupBallotKHR); - return spv::BuiltInSubgroupGtMaskKHR; - - case glslang::EbvSubGroupLeMask: - builder.addExtension(spv::E_SPV_KHR_shader_ballot); - builder.addCapability(spv::CapabilitySubgroupBallotKHR); - return spv::BuiltInSubgroupLeMaskKHR; - - case glslang::EbvSubGroupLtMask: - builder.addExtension(spv::E_SPV_KHR_shader_ballot); - builder.addCapability(spv::CapabilitySubgroupBallotKHR); - return spv::BuiltInSubgroupLtMaskKHR; - - case glslang::EbvNumSubgroups: - builder.addCapability(spv::CapabilityGroupNonUniform); - return spv::BuiltInNumSubgroups; - - case glslang::EbvSubgroupID: - builder.addCapability(spv::CapabilityGroupNonUniform); - return spv::BuiltInSubgroupId; - - case glslang::EbvSubgroupSize2: - builder.addCapability(spv::CapabilityGroupNonUniform); - return spv::BuiltInSubgroupSize; - - case glslang::EbvSubgroupInvocation2: - builder.addCapability(spv::CapabilityGroupNonUniform); - return spv::BuiltInSubgroupLocalInvocationId; - - case glslang::EbvSubgroupEqMask2: - builder.addCapability(spv::CapabilityGroupNonUniform); - builder.addCapability(spv::CapabilityGroupNonUniformBallot); - return spv::BuiltInSubgroupEqMask; - - case glslang::EbvSubgroupGeMask2: - builder.addCapability(spv::CapabilityGroupNonUniform); - builder.addCapability(spv::CapabilityGroupNonUniformBallot); - return spv::BuiltInSubgroupGeMask; - - case glslang::EbvSubgroupGtMask2: - builder.addCapability(spv::CapabilityGroupNonUniform); - builder.addCapability(spv::CapabilityGroupNonUniformBallot); - return spv::BuiltInSubgroupGtMask; - - case glslang::EbvSubgroupLeMask2: - builder.addCapability(spv::CapabilityGroupNonUniform); - builder.addCapability(spv::CapabilityGroupNonUniformBallot); - return spv::BuiltInSubgroupLeMask; - - case glslang::EbvSubgroupLtMask2: - builder.addCapability(spv::CapabilityGroupNonUniform); - builder.addCapability(spv::CapabilityGroupNonUniformBallot); - return spv::BuiltInSubgroupLtMask; -#ifdef AMD_EXTENSIONS - case glslang::EbvBaryCoordNoPersp: - builder.addExtension(spv::E_SPV_AMD_shader_explicit_vertex_parameter); - return spv::BuiltInBaryCoordNoPerspAMD; - - case glslang::EbvBaryCoordNoPerspCentroid: - builder.addExtension(spv::E_SPV_AMD_shader_explicit_vertex_parameter); - return spv::BuiltInBaryCoordNoPerspCentroidAMD; - - case glslang::EbvBaryCoordNoPerspSample: - builder.addExtension(spv::E_SPV_AMD_shader_explicit_vertex_parameter); - return spv::BuiltInBaryCoordNoPerspSampleAMD; - - case glslang::EbvBaryCoordSmooth: - builder.addExtension(spv::E_SPV_AMD_shader_explicit_vertex_parameter); - return spv::BuiltInBaryCoordSmoothAMD; - - case glslang::EbvBaryCoordSmoothCentroid: - builder.addExtension(spv::E_SPV_AMD_shader_explicit_vertex_parameter); - return spv::BuiltInBaryCoordSmoothCentroidAMD; - - case glslang::EbvBaryCoordSmoothSample: - builder.addExtension(spv::E_SPV_AMD_shader_explicit_vertex_parameter); - return spv::BuiltInBaryCoordSmoothSampleAMD; - - case glslang::EbvBaryCoordPullModel: - builder.addExtension(spv::E_SPV_AMD_shader_explicit_vertex_parameter); - return spv::BuiltInBaryCoordPullModelAMD; -#endif - - case glslang::EbvDeviceIndex: - addPre13Extension(spv::E_SPV_KHR_device_group); - builder.addCapability(spv::CapabilityDeviceGroup); - return spv::BuiltInDeviceIndex; - - case glslang::EbvViewIndex: - addPre13Extension(spv::E_SPV_KHR_multiview); - builder.addCapability(spv::CapabilityMultiView); - return spv::BuiltInViewIndex; - -#ifdef NV_EXTENSIONS - case glslang::EbvViewportMaskNV: - if (!memberDeclaration) { - builder.addExtension(spv::E_SPV_NV_viewport_array2); - builder.addCapability(spv::CapabilityShaderViewportMaskNV); - } - return spv::BuiltInViewportMaskNV; - case glslang::EbvSecondaryPositionNV: - if (!memberDeclaration) { - builder.addExtension(spv::E_SPV_NV_stereo_view_rendering); - builder.addCapability(spv::CapabilityShaderStereoViewNV); - } - return spv::BuiltInSecondaryPositionNV; - case glslang::EbvSecondaryViewportMaskNV: - if (!memberDeclaration) { - builder.addExtension(spv::E_SPV_NV_stereo_view_rendering); - builder.addCapability(spv::CapabilityShaderStereoViewNV); - } - return spv::BuiltInSecondaryViewportMaskNV; - case glslang::EbvPositionPerViewNV: - if (!memberDeclaration) { - builder.addExtension(spv::E_SPV_NVX_multiview_per_view_attributes); - builder.addCapability(spv::CapabilityPerViewAttributesNV); - } - return spv::BuiltInPositionPerViewNV; - case glslang::EbvViewportMaskPerViewNV: - if (!memberDeclaration) { - builder.addExtension(spv::E_SPV_NVX_multiview_per_view_attributes); - builder.addCapability(spv::CapabilityPerViewAttributesNV); - } - return spv::BuiltInViewportMaskPerViewNV; - case glslang::EbvFragFullyCoveredNV: - builder.addExtension(spv::E_SPV_EXT_fragment_fully_covered); - builder.addCapability(spv::CapabilityFragmentFullyCoveredEXT); - return spv::BuiltInFullyCoveredEXT; -#endif - default: - return spv::BuiltInMax; - } -} - -// Translate glslang image layout format to SPIR-V image format. -spv::ImageFormat TGlslangToSpvTraverser::TranslateImageFormat(const glslang::TType& type) -{ - assert(type.getBasicType() == glslang::EbtSampler); - - // Check for capabilities - switch (type.getQualifier().layoutFormat) { - case glslang::ElfRg32f: - case glslang::ElfRg16f: - case glslang::ElfR11fG11fB10f: - case glslang::ElfR16f: - case glslang::ElfRgba16: - case glslang::ElfRgb10A2: - case glslang::ElfRg16: - case glslang::ElfRg8: - case glslang::ElfR16: - case glslang::ElfR8: - case glslang::ElfRgba16Snorm: - case glslang::ElfRg16Snorm: - case glslang::ElfRg8Snorm: - case glslang::ElfR16Snorm: - case glslang::ElfR8Snorm: - - case glslang::ElfRg32i: - case glslang::ElfRg16i: - case glslang::ElfRg8i: - case glslang::ElfR16i: - case glslang::ElfR8i: - - case glslang::ElfRgb10a2ui: - case glslang::ElfRg32ui: - case glslang::ElfRg16ui: - case glslang::ElfRg8ui: - case glslang::ElfR16ui: - case glslang::ElfR8ui: - builder.addCapability(spv::CapabilityStorageImageExtendedFormats); - break; - - default: - break; - } - - // do the translation - switch (type.getQualifier().layoutFormat) { - case glslang::ElfNone: return spv::ImageFormatUnknown; - case glslang::ElfRgba32f: return spv::ImageFormatRgba32f; - case glslang::ElfRgba16f: return spv::ImageFormatRgba16f; - case glslang::ElfR32f: return spv::ImageFormatR32f; - case glslang::ElfRgba8: return spv::ImageFormatRgba8; - case glslang::ElfRgba8Snorm: return spv::ImageFormatRgba8Snorm; - case glslang::ElfRg32f: return spv::ImageFormatRg32f; - case glslang::ElfRg16f: return spv::ImageFormatRg16f; - case glslang::ElfR11fG11fB10f: return spv::ImageFormatR11fG11fB10f; - case glslang::ElfR16f: return spv::ImageFormatR16f; - case glslang::ElfRgba16: return spv::ImageFormatRgba16; - case glslang::ElfRgb10A2: return spv::ImageFormatRgb10A2; - case glslang::ElfRg16: return spv::ImageFormatRg16; - case glslang::ElfRg8: return spv::ImageFormatRg8; - case glslang::ElfR16: return spv::ImageFormatR16; - case glslang::ElfR8: return spv::ImageFormatR8; - case glslang::ElfRgba16Snorm: return spv::ImageFormatRgba16Snorm; - case glslang::ElfRg16Snorm: return spv::ImageFormatRg16Snorm; - case glslang::ElfRg8Snorm: return spv::ImageFormatRg8Snorm; - case glslang::ElfR16Snorm: return spv::ImageFormatR16Snorm; - case glslang::ElfR8Snorm: return spv::ImageFormatR8Snorm; - case glslang::ElfRgba32i: return spv::ImageFormatRgba32i; - case glslang::ElfRgba16i: return spv::ImageFormatRgba16i; - case glslang::ElfRgba8i: return spv::ImageFormatRgba8i; - case glslang::ElfR32i: return spv::ImageFormatR32i; - case glslang::ElfRg32i: return spv::ImageFormatRg32i; - case glslang::ElfRg16i: return spv::ImageFormatRg16i; - case glslang::ElfRg8i: return spv::ImageFormatRg8i; - case glslang::ElfR16i: return spv::ImageFormatR16i; - case glslang::ElfR8i: return spv::ImageFormatR8i; - case glslang::ElfRgba32ui: return spv::ImageFormatRgba32ui; - case glslang::ElfRgba16ui: return spv::ImageFormatRgba16ui; - case glslang::ElfRgba8ui: return spv::ImageFormatRgba8ui; - case glslang::ElfR32ui: return spv::ImageFormatR32ui; - case glslang::ElfRg32ui: return spv::ImageFormatRg32ui; - case glslang::ElfRg16ui: return spv::ImageFormatRg16ui; - case glslang::ElfRgb10a2ui: return spv::ImageFormatRgb10a2ui; - case glslang::ElfRg8ui: return spv::ImageFormatRg8ui; - case glslang::ElfR16ui: return spv::ImageFormatR16ui; - case glslang::ElfR8ui: return spv::ImageFormatR8ui; - default: return spv::ImageFormatMax; - } -} - -spv::SelectionControlMask TGlslangToSpvTraverser::TranslateSelectionControl(const glslang::TIntermSelection& selectionNode) const -{ - if (selectionNode.getFlatten()) - return spv::SelectionControlFlattenMask; - if (selectionNode.getDontFlatten()) - return spv::SelectionControlDontFlattenMask; - return spv::SelectionControlMaskNone; -} - -spv::SelectionControlMask TGlslangToSpvTraverser::TranslateSwitchControl(const glslang::TIntermSwitch& switchNode) const -{ - if (switchNode.getFlatten()) - return spv::SelectionControlFlattenMask; - if (switchNode.getDontFlatten()) - return spv::SelectionControlDontFlattenMask; - return spv::SelectionControlMaskNone; -} - -// return a non-0 dependency if the dependency argument must be set -spv::LoopControlMask TGlslangToSpvTraverser::TranslateLoopControl(const glslang::TIntermLoop& loopNode, - unsigned int& dependencyLength) const -{ - spv::LoopControlMask control = spv::LoopControlMaskNone; - - if (loopNode.getDontUnroll()) - control = control | spv::LoopControlDontUnrollMask; - if (loopNode.getUnroll()) - control = control | spv::LoopControlUnrollMask; - if (unsigned(loopNode.getLoopDependency()) == glslang::TIntermLoop::dependencyInfinite) - control = control | spv::LoopControlDependencyInfiniteMask; - else if (loopNode.getLoopDependency() > 0) { - control = control | spv::LoopControlDependencyLengthMask; - dependencyLength = loopNode.getLoopDependency(); - } - - return control; -} - -// Translate glslang type to SPIR-V storage class. -spv::StorageClass TGlslangToSpvTraverser::TranslateStorageClass(const glslang::TType& type) -{ - if (type.getQualifier().isPipeInput()) - return spv::StorageClassInput; - if (type.getQualifier().isPipeOutput()) - return spv::StorageClassOutput; - - if (glslangIntermediate->getSource() != glslang::EShSourceHlsl || - type.getQualifier().storage == glslang::EvqUniform) { - if (type.getBasicType() == glslang::EbtAtomicUint) - return spv::StorageClassAtomicCounter; - if (type.containsOpaque()) - return spv::StorageClassUniformConstant; - } - - if (glslangIntermediate->usingStorageBuffer() && type.getQualifier().storage == glslang::EvqBuffer) { - addPre13Extension(spv::E_SPV_KHR_storage_buffer_storage_class); - return spv::StorageClassStorageBuffer; - } - - if (type.getQualifier().isUniformOrBuffer()) { - if (type.getQualifier().layoutPushConstant) - return spv::StorageClassPushConstant; - if (type.getBasicType() == glslang::EbtBlock) - return spv::StorageClassUniform; - return spv::StorageClassUniformConstant; - } - - switch (type.getQualifier().storage) { - case glslang::EvqShared: return spv::StorageClassWorkgroup; - case glslang::EvqGlobal: return spv::StorageClassPrivate; - case glslang::EvqConstReadOnly: return spv::StorageClassFunction; - case glslang::EvqTemporary: return spv::StorageClassFunction; - default: - assert(0); - break; - } - - return spv::StorageClassFunction; -} - -// Add capabilities pertaining to how an array is indexed. -void TGlslangToSpvTraverser::addIndirectionIndexCapabilities(const glslang::TType& baseType, - const glslang::TType& indexType) -{ - if (indexType.getQualifier().isNonUniform()) { - // deal with an asserted non-uniform index - if (baseType.getBasicType() == glslang::EbtSampler) { - if (baseType.getQualifier().hasAttachment()) - builder.addCapability(spv::CapabilityInputAttachmentArrayNonUniformIndexingEXT); - else if (baseType.isImage() && baseType.getSampler().dim == glslang::EsdBuffer) - builder.addCapability(spv::CapabilityStorageTexelBufferArrayNonUniformIndexingEXT); - else if (baseType.isTexture() && baseType.getSampler().dim == glslang::EsdBuffer) - builder.addCapability(spv::CapabilityUniformTexelBufferArrayNonUniformIndexingEXT); - else if (baseType.isImage()) - builder.addCapability(spv::CapabilityStorageImageArrayNonUniformIndexingEXT); - else if (baseType.isTexture()) - builder.addCapability(spv::CapabilitySampledImageArrayNonUniformIndexingEXT); - } else if (baseType.getBasicType() == glslang::EbtBlock) { - if (baseType.getQualifier().storage == glslang::EvqBuffer) - builder.addCapability(spv::CapabilityStorageBufferArrayNonUniformIndexingEXT); - else if (baseType.getQualifier().storage == glslang::EvqUniform) - builder.addCapability(spv::CapabilityUniformBufferArrayNonUniformIndexingEXT); - } - } else { - // assume a dynamically uniform index - if (baseType.getBasicType() == glslang::EbtSampler) { - if (baseType.getQualifier().hasAttachment()) - builder.addCapability(spv::CapabilityInputAttachmentArrayDynamicIndexingEXT); - else if (baseType.isImage() && baseType.getSampler().dim == glslang::EsdBuffer) - builder.addCapability(spv::CapabilityStorageTexelBufferArrayDynamicIndexingEXT); - else if (baseType.isTexture() && baseType.getSampler().dim == glslang::EsdBuffer) - builder.addCapability(spv::CapabilityUniformTexelBufferArrayDynamicIndexingEXT); - } - } -} - -// Return whether or not the given type is something that should be tied to a -// descriptor set. -bool IsDescriptorResource(const glslang::TType& type) -{ - // uniform and buffer blocks are included, unless it is a push_constant - if (type.getBasicType() == glslang::EbtBlock) - return type.getQualifier().isUniformOrBuffer() && ! type.getQualifier().layoutPushConstant; - - // non block... - // basically samplerXXX/subpass/sampler/texture are all included - // if they are the global-scope-class, not the function parameter - // (or local, if they ever exist) class. - if (type.getBasicType() == glslang::EbtSampler) - return type.getQualifier().isUniformOrBuffer(); - - // None of the above. - return false; -} - -void InheritQualifiers(glslang::TQualifier& child, const glslang::TQualifier& parent) -{ - if (child.layoutMatrix == glslang::ElmNone) - child.layoutMatrix = parent.layoutMatrix; - - if (parent.invariant) - child.invariant = true; - if (parent.nopersp) - child.nopersp = true; -#ifdef AMD_EXTENSIONS - if (parent.explicitInterp) - child.explicitInterp = true; -#endif - if (parent.flat) - child.flat = true; - if (parent.centroid) - child.centroid = true; - if (parent.patch) - child.patch = true; - if (parent.sample) - child.sample = true; - if (parent.coherent) - child.coherent = true; - if (parent.volatil) - child.volatil = true; - if (parent.restrict) - child.restrict = true; - if (parent.readonly) - child.readonly = true; - if (parent.writeonly) - child.writeonly = true; -} - -bool HasNonLayoutQualifiers(const glslang::TType& type, const glslang::TQualifier& qualifier) -{ - // This should list qualifiers that simultaneous satisfy: - // - struct members might inherit from a struct declaration - // (note that non-block structs don't explicitly inherit, - // only implicitly, meaning no decoration involved) - // - affect decorations on the struct members - // (note smooth does not, and expecting something like volatile - // to effect the whole object) - // - are not part of the offset/st430/etc or row/column-major layout - return qualifier.invariant || (qualifier.hasLocation() && type.getBasicType() == glslang::EbtBlock); -} - -// -// Implement the TGlslangToSpvTraverser class. -// - -TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion, const glslang::TIntermediate* glslangIntermediate, - spv::SpvBuildLogger* buildLogger, glslang::SpvOptions& options) - : TIntermTraverser(true, false, true), - options(options), - shaderEntry(nullptr), currentFunction(nullptr), - sequenceDepth(0), logger(buildLogger), - builder(spvVersion, (glslang::GetKhronosToolId() << 16) | glslang::GetSpirvGeneratorVersion(), logger), - inEntryPoint(false), entryPointTerminated(false), linkageOnly(false), - glslangIntermediate(glslangIntermediate) -{ - spv::ExecutionModel executionModel = TranslateExecutionModel(glslangIntermediate->getStage()); - - builder.clearAccessChain(); - builder.setSource(TranslateSourceLanguage(glslangIntermediate->getSource(), glslangIntermediate->getProfile()), - glslangIntermediate->getVersion()); - - if (options.generateDebugInfo) { - builder.setEmitOpLines(); - builder.setSourceFile(glslangIntermediate->getSourceFile()); - - // Set the source shader's text. If for SPV version 1.0, include - // a preamble in comments stating the OpModuleProcessed instructions. - // Otherwise, emit those as actual instructions. - std::string text; - const std::vector& processes = glslangIntermediate->getProcesses(); - for (int p = 0; p < (int)processes.size(); ++p) { - if (glslangIntermediate->getSpv().spv < 0x00010100) { - text.append("// OpModuleProcessed "); - text.append(processes[p]); - text.append("\n"); - } else - builder.addModuleProcessed(processes[p]); - } - if (glslangIntermediate->getSpv().spv < 0x00010100 && (int)processes.size() > 0) - text.append("#line 1\n"); - text.append(glslangIntermediate->getSourceText()); - builder.setSourceText(text); - } - stdBuiltins = builder.import("GLSL.std.450"); - builder.setMemoryModel(spv::AddressingModelLogical, spv::MemoryModelGLSL450); - shaderEntry = builder.makeEntryPoint(glslangIntermediate->getEntryPointName().c_str()); - entryPoint = builder.addEntryPoint(executionModel, shaderEntry, glslangIntermediate->getEntryPointName().c_str()); - - // Add the source extensions - const auto& sourceExtensions = glslangIntermediate->getRequestedExtensions(); - for (auto it = sourceExtensions.begin(); it != sourceExtensions.end(); ++it) - builder.addSourceExtension(it->c_str()); - - // Add the top-level modes for this shader. - - if (glslangIntermediate->getXfbMode()) { - builder.addCapability(spv::CapabilityTransformFeedback); - builder.addExecutionMode(shaderEntry, spv::ExecutionModeXfb); - } - - unsigned int mode; - switch (glslangIntermediate->getStage()) { - case EShLangVertex: - builder.addCapability(spv::CapabilityShader); - break; - - case EShLangTessEvaluation: - case EShLangTessControl: - builder.addCapability(spv::CapabilityTessellation); - - glslang::TLayoutGeometry primitive; - - if (glslangIntermediate->getStage() == EShLangTessControl) { - builder.addExecutionMode(shaderEntry, spv::ExecutionModeOutputVertices, glslangIntermediate->getVertices()); - primitive = glslangIntermediate->getOutputPrimitive(); - } else { - primitive = glslangIntermediate->getInputPrimitive(); - } - - switch (primitive) { - case glslang::ElgTriangles: mode = spv::ExecutionModeTriangles; break; - case glslang::ElgQuads: mode = spv::ExecutionModeQuads; break; - case glslang::ElgIsolines: mode = spv::ExecutionModeIsolines; break; - default: mode = spv::ExecutionModeMax; break; - } - if (mode != spv::ExecutionModeMax) - builder.addExecutionMode(shaderEntry, (spv::ExecutionMode)mode); - - switch (glslangIntermediate->getVertexSpacing()) { - case glslang::EvsEqual: mode = spv::ExecutionModeSpacingEqual; break; - case glslang::EvsFractionalEven: mode = spv::ExecutionModeSpacingFractionalEven; break; - case glslang::EvsFractionalOdd: mode = spv::ExecutionModeSpacingFractionalOdd; break; - default: mode = spv::ExecutionModeMax; break; - } - if (mode != spv::ExecutionModeMax) - builder.addExecutionMode(shaderEntry, (spv::ExecutionMode)mode); - - switch (glslangIntermediate->getVertexOrder()) { - case glslang::EvoCw: mode = spv::ExecutionModeVertexOrderCw; break; - case glslang::EvoCcw: mode = spv::ExecutionModeVertexOrderCcw; break; - default: mode = spv::ExecutionModeMax; break; - } - if (mode != spv::ExecutionModeMax) - builder.addExecutionMode(shaderEntry, (spv::ExecutionMode)mode); - - if (glslangIntermediate->getPointMode()) - builder.addExecutionMode(shaderEntry, spv::ExecutionModePointMode); - break; - - case EShLangGeometry: - builder.addCapability(spv::CapabilityGeometry); - switch (glslangIntermediate->getInputPrimitive()) { - case glslang::ElgPoints: mode = spv::ExecutionModeInputPoints; break; - case glslang::ElgLines: mode = spv::ExecutionModeInputLines; break; - case glslang::ElgLinesAdjacency: mode = spv::ExecutionModeInputLinesAdjacency; break; - case glslang::ElgTriangles: mode = spv::ExecutionModeTriangles; break; - case glslang::ElgTrianglesAdjacency: mode = spv::ExecutionModeInputTrianglesAdjacency; break; - default: mode = spv::ExecutionModeMax; break; - } - if (mode != spv::ExecutionModeMax) - builder.addExecutionMode(shaderEntry, (spv::ExecutionMode)mode); - - builder.addExecutionMode(shaderEntry, spv::ExecutionModeInvocations, glslangIntermediate->getInvocations()); - - switch (glslangIntermediate->getOutputPrimitive()) { - case glslang::ElgPoints: mode = spv::ExecutionModeOutputPoints; break; - case glslang::ElgLineStrip: mode = spv::ExecutionModeOutputLineStrip; break; - case glslang::ElgTriangleStrip: mode = spv::ExecutionModeOutputTriangleStrip; break; - default: mode = spv::ExecutionModeMax; break; - } - if (mode != spv::ExecutionModeMax) - builder.addExecutionMode(shaderEntry, (spv::ExecutionMode)mode); - builder.addExecutionMode(shaderEntry, spv::ExecutionModeOutputVertices, glslangIntermediate->getVertices()); - break; - - case EShLangFragment: - builder.addCapability(spv::CapabilityShader); - if (glslangIntermediate->getPixelCenterInteger()) - builder.addExecutionMode(shaderEntry, spv::ExecutionModePixelCenterInteger); - - if (glslangIntermediate->getOriginUpperLeft()) - builder.addExecutionMode(shaderEntry, spv::ExecutionModeOriginUpperLeft); - else - builder.addExecutionMode(shaderEntry, spv::ExecutionModeOriginLowerLeft); - - if (glslangIntermediate->getEarlyFragmentTests()) - builder.addExecutionMode(shaderEntry, spv::ExecutionModeEarlyFragmentTests); - - if (glslangIntermediate->getPostDepthCoverage()) { - builder.addCapability(spv::CapabilitySampleMaskPostDepthCoverage); - builder.addExecutionMode(shaderEntry, spv::ExecutionModePostDepthCoverage); - builder.addExtension(spv::E_SPV_KHR_post_depth_coverage); - } - - switch(glslangIntermediate->getDepth()) { - case glslang::EldGreater: mode = spv::ExecutionModeDepthGreater; break; - case glslang::EldLess: mode = spv::ExecutionModeDepthLess; break; - default: mode = spv::ExecutionModeMax; break; - } - if (mode != spv::ExecutionModeMax) - builder.addExecutionMode(shaderEntry, (spv::ExecutionMode)mode); - - if (glslangIntermediate->getDepth() != glslang::EldUnchanged && glslangIntermediate->isDepthReplacing()) - builder.addExecutionMode(shaderEntry, spv::ExecutionModeDepthReplacing); - break; - - case EShLangCompute: - builder.addCapability(spv::CapabilityShader); - builder.addExecutionMode(shaderEntry, spv::ExecutionModeLocalSize, glslangIntermediate->getLocalSize(0), - glslangIntermediate->getLocalSize(1), - glslangIntermediate->getLocalSize(2)); - break; - - default: - break; - } -} - -// Finish creating SPV, after the traversal is complete. -void TGlslangToSpvTraverser::finishSpv() -{ - if (! entryPointTerminated) { - builder.setBuildPoint(shaderEntry->getLastBlock()); - builder.leaveFunction(); - } - - // finish off the entry-point SPV instruction by adding the Input/Output - for (auto it = iOSet.cbegin(); it != iOSet.cend(); ++it) - entryPoint->addIdOperand(*it); - - builder.eliminateDeadDecorations(); -} - -// Write the SPV into 'out'. -void TGlslangToSpvTraverser::dumpSpv(std::vector& out) -{ - builder.dump(out); -} - -// -// Implement the traversal functions. -// -// Return true from interior nodes to have the external traversal -// continue on to children. Return false if children were -// already processed. -// - -// -// Symbols can turn into -// - uniform/input reads -// - output writes -// - complex lvalue base setups: foo.bar[3].... , where we see foo and start up an access chain -// - something simple that degenerates into the last bullet -// -void TGlslangToSpvTraverser::visitSymbol(glslang::TIntermSymbol* symbol) -{ - SpecConstantOpModeGuard spec_constant_op_mode_setter(&builder); - if (symbol->getType().getQualifier().isSpecConstant()) - spec_constant_op_mode_setter.turnOnSpecConstantOpMode(); - - // getSymbolId() will set up all the IO decorations on the first call. - // Formal function parameters were mapped during makeFunctions(). - spv::Id id = getSymbolId(symbol); - - // Include all "static use" and "linkage only" interface variables on the OpEntryPoint instruction - if (builder.isPointer(id)) { - spv::StorageClass sc = builder.getStorageClass(id); - if (sc == spv::StorageClassInput || sc == spv::StorageClassOutput) { - if (!symbol->getType().isStruct() || symbol->getType().getStruct()->size() > 0) - iOSet.insert(id); - } - } - - // Only process non-linkage-only nodes for generating actual static uses - if (! linkageOnly || symbol->getQualifier().isSpecConstant()) { - // Prepare to generate code for the access - - // L-value chains will be computed left to right. We're on the symbol now, - // which is the left-most part of the access chain, so now is "clear" time, - // followed by setting the base. - builder.clearAccessChain(); - - // For now, we consider all user variables as being in memory, so they are pointers, - // except for - // A) R-Value arguments to a function, which are an intermediate object. - // See comments in handleUserFunctionCall(). - // B) Specialization constants (normal constants don't even come in as a variable), - // These are also pure R-values. - glslang::TQualifier qualifier = symbol->getQualifier(); - if (qualifier.isSpecConstant() || rValueParameters.find(symbol->getId()) != rValueParameters.end()) - builder.setAccessChainRValue(id); - else - builder.setAccessChainLValue(id); - } - - // Process linkage-only nodes for any special additional interface work. - if (linkageOnly) { - if (glslangIntermediate->getHlslFunctionality1()) { - // Map implicit counter buffers to their originating buffers, which should have been - // seen by now, given earlier pruning of unused counters, and preservation of order - // of declaration. - if (symbol->getType().getQualifier().isUniformOrBuffer()) { - if (!glslangIntermediate->hasCounterBufferName(symbol->getName())) { - // Save possible originating buffers for counter buffers, keyed by - // making the potential counter-buffer name. - std::string keyName = symbol->getName().c_str(); - keyName = glslangIntermediate->addCounterBufferName(keyName); - counterOriginator[keyName] = symbol; - } else { - // Handle a counter buffer, by finding the saved originating buffer. - std::string keyName = symbol->getName().c_str(); - auto it = counterOriginator.find(keyName); - if (it != counterOriginator.end()) { - id = getSymbolId(it->second); - if (id != spv::NoResult) { - spv::Id counterId = getSymbolId(symbol); - if (counterId != spv::NoResult) { - builder.addExtension("SPV_GOOGLE_hlsl_functionality1"); - builder.addDecorationId(id, spv::DecorationHlslCounterBufferGOOGLE, counterId); - } - } - } - } - } - } - } -} - -bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::TIntermBinary* node) -{ - builder.setLine(node->getLoc().line); - - SpecConstantOpModeGuard spec_constant_op_mode_setter(&builder); - if (node->getType().getQualifier().isSpecConstant()) - spec_constant_op_mode_setter.turnOnSpecConstantOpMode(); - - // First, handle special cases - switch (node->getOp()) { - case glslang::EOpAssign: - case glslang::EOpAddAssign: - case glslang::EOpSubAssign: - case glslang::EOpMulAssign: - case glslang::EOpVectorTimesMatrixAssign: - case glslang::EOpVectorTimesScalarAssign: - case glslang::EOpMatrixTimesScalarAssign: - case glslang::EOpMatrixTimesMatrixAssign: - case glslang::EOpDivAssign: - case glslang::EOpModAssign: - case glslang::EOpAndAssign: - case glslang::EOpInclusiveOrAssign: - case glslang::EOpExclusiveOrAssign: - case glslang::EOpLeftShiftAssign: - case glslang::EOpRightShiftAssign: - // A bin-op assign "a += b" means the same thing as "a = a + b" - // where a is evaluated before b. For a simple assignment, GLSL - // says to evaluate the left before the right. So, always, left - // node then right node. - { - // get the left l-value, save it away - builder.clearAccessChain(); - node->getLeft()->traverse(this); - spv::Builder::AccessChain lValue = builder.getAccessChain(); - - // evaluate the right - builder.clearAccessChain(); - node->getRight()->traverse(this); - spv::Id rValue = accessChainLoad(node->getRight()->getType()); - - if (node->getOp() != glslang::EOpAssign) { - // the left is also an r-value - builder.setAccessChain(lValue); - spv::Id leftRValue = accessChainLoad(node->getLeft()->getType()); - - // do the operation - OpDecorations decorations = { TranslatePrecisionDecoration(node->getOperationPrecision()), - TranslateNoContractionDecoration(node->getType().getQualifier()), - TranslateNonUniformDecoration(node->getType().getQualifier()) }; - rValue = createBinaryOperation(node->getOp(), decorations, - convertGlslangToSpvType(node->getType()), leftRValue, rValue, - node->getType().getBasicType()); - - // these all need their counterparts in createBinaryOperation() - assert(rValue != spv::NoResult); - } - - // store the result - builder.setAccessChain(lValue); - multiTypeStore(node->getType(), rValue); - - // assignments are expressions having an rValue after they are evaluated... - builder.clearAccessChain(); - builder.setAccessChainRValue(rValue); - } - return false; - case glslang::EOpIndexDirect: - case glslang::EOpIndexDirectStruct: - { - // Get the left part of the access chain. - node->getLeft()->traverse(this); - - // Add the next element in the chain - - const int glslangIndex = node->getRight()->getAsConstantUnion()->getConstArray()[0].getIConst(); - if (! node->getLeft()->getType().isArray() && - node->getLeft()->getType().isVector() && - node->getOp() == glslang::EOpIndexDirect) { - // This is essentially a hard-coded vector swizzle of size 1, - // so short circuit the access-chain stuff with a swizzle. - std::vector swizzle; - swizzle.push_back(glslangIndex); - builder.accessChainPushSwizzle(swizzle, convertGlslangToSpvType(node->getLeft()->getType())); - } else { - int spvIndex = glslangIndex; - if (node->getLeft()->getBasicType() == glslang::EbtBlock && - node->getOp() == glslang::EOpIndexDirectStruct) - { - // This may be, e.g., an anonymous block-member selection, which generally need - // index remapping due to hidden members in anonymous blocks. - std::vector& remapper = memberRemapper[node->getLeft()->getType().getStruct()]; - assert(remapper.size() > 0); - spvIndex = remapper[glslangIndex]; - } - - // normal case for indexing array or structure or block - builder.accessChainPush(builder.makeIntConstant(spvIndex)); - - // Add capabilities here for accessing PointSize and clip/cull distance. - // We have deferred generation of associated capabilities until now. - if (node->getLeft()->getType().isStruct() && ! node->getLeft()->getType().isArray()) - declareUseOfStructMember(*(node->getLeft()->getType().getStruct()), glslangIndex); - } - } - return false; - case glslang::EOpIndexIndirect: - { - // Structure or array or vector indirection. - // Will use native SPIR-V access-chain for struct and array indirection; - // matrices are arrays of vectors, so will also work for a matrix. - // Will use the access chain's 'component' for variable index into a vector. - - // This adapter is building access chains left to right. - // Set up the access chain to the left. - node->getLeft()->traverse(this); - - // save it so that computing the right side doesn't trash it - spv::Builder::AccessChain partial = builder.getAccessChain(); - - // compute the next index in the chain - builder.clearAccessChain(); - node->getRight()->traverse(this); - spv::Id index = accessChainLoad(node->getRight()->getType()); - - addIndirectionIndexCapabilities(node->getLeft()->getType(), node->getRight()->getType()); - - // restore the saved access chain - builder.setAccessChain(partial); - - if (! node->getLeft()->getType().isArray() && node->getLeft()->getType().isVector()) - builder.accessChainPushComponent(index, convertGlslangToSpvType(node->getLeft()->getType())); - else - builder.accessChainPush(index); - } - return false; - case glslang::EOpVectorSwizzle: - { - node->getLeft()->traverse(this); - std::vector swizzle; - convertSwizzle(*node->getRight()->getAsAggregate(), swizzle); - builder.accessChainPushSwizzle(swizzle, convertGlslangToSpvType(node->getLeft()->getType())); - } - return false; - case glslang::EOpMatrixSwizzle: - logger->missingFunctionality("matrix swizzle"); - return true; - case glslang::EOpLogicalOr: - case glslang::EOpLogicalAnd: - { - - // These may require short circuiting, but can sometimes be done as straight - // binary operations. The right operand must be short circuited if it has - // side effects, and should probably be if it is complex. - if (isTrivial(node->getRight()->getAsTyped())) - break; // handle below as a normal binary operation - // otherwise, we need to do dynamic short circuiting on the right operand - spv::Id result = createShortCircuit(node->getOp(), *node->getLeft()->getAsTyped(), *node->getRight()->getAsTyped()); - builder.clearAccessChain(); - builder.setAccessChainRValue(result); - } - return false; - default: - break; - } - - // Assume generic binary op... - - // get right operand - builder.clearAccessChain(); - node->getLeft()->traverse(this); - spv::Id left = accessChainLoad(node->getLeft()->getType()); - - // get left operand - builder.clearAccessChain(); - node->getRight()->traverse(this); - spv::Id right = accessChainLoad(node->getRight()->getType()); - - // get result - OpDecorations decorations = { TranslatePrecisionDecoration(node->getOperationPrecision()), - TranslateNoContractionDecoration(node->getType().getQualifier()), - TranslateNonUniformDecoration(node->getType().getQualifier()) }; - spv::Id result = createBinaryOperation(node->getOp(), decorations, - convertGlslangToSpvType(node->getType()), left, right, - node->getLeft()->getType().getBasicType()); - - builder.clearAccessChain(); - if (! result) { - logger->missingFunctionality("unknown glslang binary operation"); - return true; // pick up a child as the place-holder result - } else { - builder.setAccessChainRValue(result); - return false; - } -} - -bool TGlslangToSpvTraverser::visitUnary(glslang::TVisit /* visit */, glslang::TIntermUnary* node) -{ - builder.setLine(node->getLoc().line); - - SpecConstantOpModeGuard spec_constant_op_mode_setter(&builder); - if (node->getType().getQualifier().isSpecConstant()) - spec_constant_op_mode_setter.turnOnSpecConstantOpMode(); - - spv::Id result = spv::NoResult; - - // try texturing first - result = createImageTextureFunctionCall(node); - if (result != spv::NoResult) { - builder.clearAccessChain(); - builder.setAccessChainRValue(result); - - return false; // done with this node - } - - // Non-texturing. - - if (node->getOp() == glslang::EOpArrayLength) { - // Quite special; won't want to evaluate the operand. - - // Currently, the front-end does not allow .length() on an array until it is sized, - // except for the last block membeor of an SSBO. - // TODO: If this changes, link-time sized arrays might show up here, and need their - // size extracted. - - // Normal .length() would have been constant folded by the front-end. - // So, this has to be block.lastMember.length(). - // SPV wants "block" and member number as the operands, go get them. - - glslang::TIntermTyped* block = node->getOperand()->getAsBinaryNode()->getLeft(); - block->traverse(this); - unsigned int member = node->getOperand()->getAsBinaryNode()->getRight()->getAsConstantUnion()->getConstArray()[0].getUConst(); - spv::Id length = builder.createArrayLength(builder.accessChainGetLValue(), member); - - builder.clearAccessChain(); - builder.setAccessChainRValue(length); - - return false; - } - - // Start by evaluating the operand - - // Does it need a swizzle inversion? If so, evaluation is inverted; - // operate first on the swizzle base, then apply the swizzle. - spv::Id invertedType = spv::NoType; - auto resultType = [&invertedType, &node, this](){ return invertedType != spv::NoType ? invertedType : convertGlslangToSpvType(node->getType()); }; - if (node->getOp() == glslang::EOpInterpolateAtCentroid) - invertedType = getInvertedSwizzleType(*node->getOperand()); - - builder.clearAccessChain(); - if (invertedType != spv::NoType) - node->getOperand()->getAsBinaryNode()->getLeft()->traverse(this); - else - node->getOperand()->traverse(this); - - spv::Id operand = spv::NoResult; - - if (node->getOp() == glslang::EOpAtomicCounterIncrement || - node->getOp() == glslang::EOpAtomicCounterDecrement || - node->getOp() == glslang::EOpAtomicCounter || - node->getOp() == glslang::EOpInterpolateAtCentroid) - operand = builder.accessChainGetLValue(); // Special case l-value operands - else - operand = accessChainLoad(node->getOperand()->getType()); - - OpDecorations decorations = { TranslatePrecisionDecoration(node->getOperationPrecision()), - TranslateNoContractionDecoration(node->getType().getQualifier()), - TranslateNonUniformDecoration(node->getType().getQualifier()) }; - - // it could be a conversion - if (! result) - result = createConversion(node->getOp(), decorations, resultType(), operand, node->getOperand()->getBasicType()); - - // if not, then possibly an operation - if (! result) - result = createUnaryOperation(node->getOp(), decorations, resultType(), operand, node->getOperand()->getBasicType()); - - if (result) { - if (invertedType) { - result = createInvertedSwizzle(decorations.precision, *node->getOperand(), result); - builder.addDecoration(result, decorations.nonUniform); - } - - builder.clearAccessChain(); - builder.setAccessChainRValue(result); - - return false; // done with this node - } - - // it must be a special case, check... - switch (node->getOp()) { - case glslang::EOpPostIncrement: - case glslang::EOpPostDecrement: - case glslang::EOpPreIncrement: - case glslang::EOpPreDecrement: - { - // we need the integer value "1" or the floating point "1.0" to add/subtract - spv::Id one = 0; - if (node->getBasicType() == glslang::EbtFloat) - one = builder.makeFloatConstant(1.0F); - else if (node->getBasicType() == glslang::EbtDouble) - one = builder.makeDoubleConstant(1.0); - else if (node->getBasicType() == glslang::EbtFloat16) - one = builder.makeFloat16Constant(1.0F); - else if (node->getBasicType() == glslang::EbtInt8 || node->getBasicType() == glslang::EbtUint8) - one = builder.makeInt8Constant(1); - else if (node->getBasicType() == glslang::EbtInt16 || node->getBasicType() == glslang::EbtUint16) - one = builder.makeInt16Constant(1); - else if (node->getBasicType() == glslang::EbtInt64 || node->getBasicType() == glslang::EbtUint64) - one = builder.makeInt64Constant(1); - else - one = builder.makeIntConstant(1); - glslang::TOperator op; - if (node->getOp() == glslang::EOpPreIncrement || - node->getOp() == glslang::EOpPostIncrement) - op = glslang::EOpAdd; - else - op = glslang::EOpSub; - - spv::Id result = createBinaryOperation(op, decorations, - convertGlslangToSpvType(node->getType()), operand, one, - node->getType().getBasicType()); - assert(result != spv::NoResult); - - // The result of operation is always stored, but conditionally the - // consumed result. The consumed result is always an r-value. - builder.accessChainStore(result); - builder.clearAccessChain(); - if (node->getOp() == glslang::EOpPreIncrement || - node->getOp() == glslang::EOpPreDecrement) - builder.setAccessChainRValue(result); - else - builder.setAccessChainRValue(operand); - } - - return false; - - case glslang::EOpEmitStreamVertex: - builder.createNoResultOp(spv::OpEmitStreamVertex, operand); - return false; - case glslang::EOpEndStreamPrimitive: - builder.createNoResultOp(spv::OpEndStreamPrimitive, operand); - return false; - - default: - logger->missingFunctionality("unknown glslang unary"); - return true; // pick up operand as placeholder result - } -} - -bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TIntermAggregate* node) -{ - SpecConstantOpModeGuard spec_constant_op_mode_setter(&builder); - if (node->getType().getQualifier().isSpecConstant()) - spec_constant_op_mode_setter.turnOnSpecConstantOpMode(); - - spv::Id result = spv::NoResult; - spv::Id invertedType = spv::NoType; // to use to override the natural type of the node - auto resultType = [&invertedType, &node, this](){ return invertedType != spv::NoType ? invertedType : convertGlslangToSpvType(node->getType()); }; - - // try texturing - result = createImageTextureFunctionCall(node); - if (result != spv::NoResult) { - builder.clearAccessChain(); - builder.setAccessChainRValue(result); - - return false; -#ifdef AMD_EXTENSIONS - } else if (node->getOp() == glslang::EOpImageStore || node->getOp() == glslang::EOpImageStoreLod) { -#else - } else if (node->getOp() == glslang::EOpImageStore) { -#endif - // "imageStore" is a special case, which has no result - return false; - } - - glslang::TOperator binOp = glslang::EOpNull; - bool reduceComparison = true; - bool isMatrix = false; - bool noReturnValue = false; - bool atomic = false; - - assert(node->getOp()); - - spv::Decoration precision = TranslatePrecisionDecoration(node->getOperationPrecision()); - - switch (node->getOp()) { - case glslang::EOpSequence: - { - if (preVisit) - ++sequenceDepth; - else - --sequenceDepth; - - if (sequenceDepth == 1) { - // If this is the parent node of all the functions, we want to see them - // early, so all call points have actual SPIR-V functions to reference. - // In all cases, still let the traverser visit the children for us. - makeFunctions(node->getAsAggregate()->getSequence()); - - // Also, we want all globals initializers to go into the beginning of the entry point, before - // anything else gets there, so visit out of order, doing them all now. - makeGlobalInitializers(node->getAsAggregate()->getSequence()); - - // Initializers are done, don't want to visit again, but functions and link objects need to be processed, - // so do them manually. - visitFunctions(node->getAsAggregate()->getSequence()); - - return false; - } - - return true; - } - case glslang::EOpLinkerObjects: - { - if (visit == glslang::EvPreVisit) - linkageOnly = true; - else - linkageOnly = false; - - return true; - } - case glslang::EOpComma: - { - // processing from left to right naturally leaves the right-most - // lying around in the access chain - glslang::TIntermSequence& glslangOperands = node->getSequence(); - for (int i = 0; i < (int)glslangOperands.size(); ++i) - glslangOperands[i]->traverse(this); - - return false; - } - case glslang::EOpFunction: - if (visit == glslang::EvPreVisit) { - if (isShaderEntryPoint(node)) { - inEntryPoint = true; - builder.setBuildPoint(shaderEntry->getLastBlock()); - currentFunction = shaderEntry; - } else { - handleFunctionEntry(node); - } - } else { - if (inEntryPoint) - entryPointTerminated = true; - builder.leaveFunction(); - inEntryPoint = false; - } - - return true; - case glslang::EOpParameters: - // Parameters will have been consumed by EOpFunction processing, but not - // the body, so we still visited the function node's children, making this - // child redundant. - return false; - case glslang::EOpFunctionCall: - { - builder.setLine(node->getLoc().line); - if (node->isUserDefined()) - result = handleUserFunctionCall(node); - // assert(result); // this can happen for bad shaders because the call graph completeness checking is not yet done - if (result) { - builder.clearAccessChain(); - builder.setAccessChainRValue(result); - } else - logger->missingFunctionality("missing user function; linker needs to catch that"); - - return false; - } - case glslang::EOpConstructMat2x2: - case glslang::EOpConstructMat2x3: - case glslang::EOpConstructMat2x4: - case glslang::EOpConstructMat3x2: - case glslang::EOpConstructMat3x3: - case glslang::EOpConstructMat3x4: - case glslang::EOpConstructMat4x2: - case glslang::EOpConstructMat4x3: - case glslang::EOpConstructMat4x4: - case glslang::EOpConstructDMat2x2: - case glslang::EOpConstructDMat2x3: - case glslang::EOpConstructDMat2x4: - case glslang::EOpConstructDMat3x2: - case glslang::EOpConstructDMat3x3: - case glslang::EOpConstructDMat3x4: - case glslang::EOpConstructDMat4x2: - case glslang::EOpConstructDMat4x3: - case glslang::EOpConstructDMat4x4: - case glslang::EOpConstructIMat2x2: - case glslang::EOpConstructIMat2x3: - case glslang::EOpConstructIMat2x4: - case glslang::EOpConstructIMat3x2: - case glslang::EOpConstructIMat3x3: - case glslang::EOpConstructIMat3x4: - case glslang::EOpConstructIMat4x2: - case glslang::EOpConstructIMat4x3: - case glslang::EOpConstructIMat4x4: - case glslang::EOpConstructUMat2x2: - case glslang::EOpConstructUMat2x3: - case glslang::EOpConstructUMat2x4: - case glslang::EOpConstructUMat3x2: - case glslang::EOpConstructUMat3x3: - case glslang::EOpConstructUMat3x4: - case glslang::EOpConstructUMat4x2: - case glslang::EOpConstructUMat4x3: - case glslang::EOpConstructUMat4x4: - case glslang::EOpConstructBMat2x2: - case glslang::EOpConstructBMat2x3: - case glslang::EOpConstructBMat2x4: - case glslang::EOpConstructBMat3x2: - case glslang::EOpConstructBMat3x3: - case glslang::EOpConstructBMat3x4: - case glslang::EOpConstructBMat4x2: - case glslang::EOpConstructBMat4x3: - case glslang::EOpConstructBMat4x4: - case glslang::EOpConstructF16Mat2x2: - case glslang::EOpConstructF16Mat2x3: - case glslang::EOpConstructF16Mat2x4: - case glslang::EOpConstructF16Mat3x2: - case glslang::EOpConstructF16Mat3x3: - case glslang::EOpConstructF16Mat3x4: - case glslang::EOpConstructF16Mat4x2: - case glslang::EOpConstructF16Mat4x3: - case glslang::EOpConstructF16Mat4x4: - isMatrix = true; - // fall through - case glslang::EOpConstructFloat: - case glslang::EOpConstructVec2: - case glslang::EOpConstructVec3: - case glslang::EOpConstructVec4: - case glslang::EOpConstructDouble: - case glslang::EOpConstructDVec2: - case glslang::EOpConstructDVec3: - case glslang::EOpConstructDVec4: - case glslang::EOpConstructFloat16: - case glslang::EOpConstructF16Vec2: - case glslang::EOpConstructF16Vec3: - case glslang::EOpConstructF16Vec4: - case glslang::EOpConstructBool: - case glslang::EOpConstructBVec2: - case glslang::EOpConstructBVec3: - case glslang::EOpConstructBVec4: - case glslang::EOpConstructInt8: - case glslang::EOpConstructI8Vec2: - case glslang::EOpConstructI8Vec3: - case glslang::EOpConstructI8Vec4: - case glslang::EOpConstructUint8: - case glslang::EOpConstructU8Vec2: - case glslang::EOpConstructU8Vec3: - case glslang::EOpConstructU8Vec4: - case glslang::EOpConstructInt16: - case glslang::EOpConstructI16Vec2: - case glslang::EOpConstructI16Vec3: - case glslang::EOpConstructI16Vec4: - case glslang::EOpConstructUint16: - case glslang::EOpConstructU16Vec2: - case glslang::EOpConstructU16Vec3: - case glslang::EOpConstructU16Vec4: - case glslang::EOpConstructInt: - case glslang::EOpConstructIVec2: - case glslang::EOpConstructIVec3: - case glslang::EOpConstructIVec4: - case glslang::EOpConstructUint: - case glslang::EOpConstructUVec2: - case glslang::EOpConstructUVec3: - case glslang::EOpConstructUVec4: - case glslang::EOpConstructInt64: - case glslang::EOpConstructI64Vec2: - case glslang::EOpConstructI64Vec3: - case glslang::EOpConstructI64Vec4: - case glslang::EOpConstructUint64: - case glslang::EOpConstructU64Vec2: - case glslang::EOpConstructU64Vec3: - case glslang::EOpConstructU64Vec4: - case glslang::EOpConstructStruct: - case glslang::EOpConstructTextureSampler: - { - builder.setLine(node->getLoc().line); - std::vector arguments; - translateArguments(*node, arguments); - spv::Id constructed; - if (node->getOp() == glslang::EOpConstructTextureSampler) - constructed = builder.createOp(spv::OpSampledImage, resultType(), arguments); - else if (node->getOp() == glslang::EOpConstructStruct || node->getType().isArray()) { - std::vector constituents; - for (int c = 0; c < (int)arguments.size(); ++c) - constituents.push_back(arguments[c]); - constructed = builder.createCompositeConstruct(resultType(), constituents); - } else if (isMatrix) - constructed = builder.createMatrixConstructor(precision, arguments, resultType()); - else - constructed = builder.createConstructor(precision, arguments, resultType()); - - builder.clearAccessChain(); - builder.setAccessChainRValue(constructed); - - return false; - } - - // These six are component-wise compares with component-wise results. - // Forward on to createBinaryOperation(), requesting a vector result. - case glslang::EOpLessThan: - case glslang::EOpGreaterThan: - case glslang::EOpLessThanEqual: - case glslang::EOpGreaterThanEqual: - case glslang::EOpVectorEqual: - case glslang::EOpVectorNotEqual: - { - // Map the operation to a binary - binOp = node->getOp(); - reduceComparison = false; - switch (node->getOp()) { - case glslang::EOpVectorEqual: binOp = glslang::EOpVectorEqual; break; - case glslang::EOpVectorNotEqual: binOp = glslang::EOpVectorNotEqual; break; - default: binOp = node->getOp(); break; - } - - break; - } - case glslang::EOpMul: - // component-wise matrix multiply - binOp = glslang::EOpMul; - break; - case glslang::EOpOuterProduct: - // two vectors multiplied to make a matrix - binOp = glslang::EOpOuterProduct; - break; - case glslang::EOpDot: - { - // for scalar dot product, use multiply - glslang::TIntermSequence& glslangOperands = node->getSequence(); - if (glslangOperands[0]->getAsTyped()->getVectorSize() == 1) - binOp = glslang::EOpMul; - break; - } - case glslang::EOpMod: - // when an aggregate, this is the floating-point mod built-in function, - // which can be emitted by the one in createBinaryOperation() - binOp = glslang::EOpMod; - break; - case glslang::EOpEmitVertex: - case glslang::EOpEndPrimitive: - case glslang::EOpBarrier: - case glslang::EOpMemoryBarrier: - case glslang::EOpMemoryBarrierAtomicCounter: - case glslang::EOpMemoryBarrierBuffer: - case glslang::EOpMemoryBarrierImage: - case glslang::EOpMemoryBarrierShared: - case glslang::EOpGroupMemoryBarrier: - case glslang::EOpDeviceMemoryBarrier: - case glslang::EOpAllMemoryBarrierWithGroupSync: - case glslang::EOpDeviceMemoryBarrierWithGroupSync: - case glslang::EOpWorkgroupMemoryBarrier: - case glslang::EOpWorkgroupMemoryBarrierWithGroupSync: - case glslang::EOpSubgroupBarrier: - case glslang::EOpSubgroupMemoryBarrier: - case glslang::EOpSubgroupMemoryBarrierBuffer: - case glslang::EOpSubgroupMemoryBarrierImage: - case glslang::EOpSubgroupMemoryBarrierShared: - noReturnValue = true; - // These all have 0 operands and will naturally finish up in the code below for 0 operands - break; - - case glslang::EOpAtomicAdd: - case glslang::EOpAtomicMin: - case glslang::EOpAtomicMax: - case glslang::EOpAtomicAnd: - case glslang::EOpAtomicOr: - case glslang::EOpAtomicXor: - case glslang::EOpAtomicExchange: - case glslang::EOpAtomicCompSwap: - atomic = true; - break; - - case glslang::EOpAtomicCounterAdd: - case glslang::EOpAtomicCounterSubtract: - case glslang::EOpAtomicCounterMin: - case glslang::EOpAtomicCounterMax: - case glslang::EOpAtomicCounterAnd: - case glslang::EOpAtomicCounterOr: - case glslang::EOpAtomicCounterXor: - case glslang::EOpAtomicCounterExchange: - case glslang::EOpAtomicCounterCompSwap: - builder.addExtension("SPV_KHR_shader_atomic_counter_ops"); - builder.addCapability(spv::CapabilityAtomicStorageOps); - atomic = true; - break; - - default: - break; - } - - // - // See if it maps to a regular operation. - // - if (binOp != glslang::EOpNull) { - glslang::TIntermTyped* left = node->getSequence()[0]->getAsTyped(); - glslang::TIntermTyped* right = node->getSequence()[1]->getAsTyped(); - assert(left && right); - - builder.clearAccessChain(); - left->traverse(this); - spv::Id leftId = accessChainLoad(left->getType()); - - builder.clearAccessChain(); - right->traverse(this); - spv::Id rightId = accessChainLoad(right->getType()); - - builder.setLine(node->getLoc().line); - OpDecorations decorations = { precision, - TranslateNoContractionDecoration(node->getType().getQualifier()), - TranslateNonUniformDecoration(node->getType().getQualifier()) }; - result = createBinaryOperation(binOp, decorations, - resultType(), leftId, rightId, - left->getType().getBasicType(), reduceComparison); - - // code above should only make binOp that exists in createBinaryOperation - assert(result != spv::NoResult); - builder.clearAccessChain(); - builder.setAccessChainRValue(result); - - return false; - } - - // - // Create the list of operands. - // - glslang::TIntermSequence& glslangOperands = node->getSequence(); - std::vector operands; - for (int arg = 0; arg < (int)glslangOperands.size(); ++arg) { - // special case l-value operands; there are just a few - bool lvalue = false; - switch (node->getOp()) { - case glslang::EOpFrexp: - case glslang::EOpModf: - if (arg == 1) - lvalue = true; - break; - case glslang::EOpInterpolateAtSample: - case glslang::EOpInterpolateAtOffset: -#ifdef AMD_EXTENSIONS - case glslang::EOpInterpolateAtVertex: -#endif - if (arg == 0) { - lvalue = true; - - // Does it need a swizzle inversion? If so, evaluation is inverted; - // operate first on the swizzle base, then apply the swizzle. - if (glslangOperands[0]->getAsOperator() && - glslangOperands[0]->getAsOperator()->getOp() == glslang::EOpVectorSwizzle) - invertedType = convertGlslangToSpvType(glslangOperands[0]->getAsBinaryNode()->getLeft()->getType()); - } - break; - case glslang::EOpAtomicAdd: - case glslang::EOpAtomicMin: - case glslang::EOpAtomicMax: - case glslang::EOpAtomicAnd: - case glslang::EOpAtomicOr: - case glslang::EOpAtomicXor: - case glslang::EOpAtomicExchange: - case glslang::EOpAtomicCompSwap: - case glslang::EOpAtomicCounterAdd: - case glslang::EOpAtomicCounterSubtract: - case glslang::EOpAtomicCounterMin: - case glslang::EOpAtomicCounterMax: - case glslang::EOpAtomicCounterAnd: - case glslang::EOpAtomicCounterOr: - case glslang::EOpAtomicCounterXor: - case glslang::EOpAtomicCounterExchange: - case glslang::EOpAtomicCounterCompSwap: - if (arg == 0) - lvalue = true; - break; - case glslang::EOpAddCarry: - case glslang::EOpSubBorrow: - if (arg == 2) - lvalue = true; - break; - case glslang::EOpUMulExtended: - case glslang::EOpIMulExtended: - if (arg >= 2) - lvalue = true; - break; - default: - break; - } - builder.clearAccessChain(); - if (invertedType != spv::NoType && arg == 0) - glslangOperands[0]->getAsBinaryNode()->getLeft()->traverse(this); - else - glslangOperands[arg]->traverse(this); - if (lvalue) - operands.push_back(builder.accessChainGetLValue()); - else { - builder.setLine(node->getLoc().line); - operands.push_back(accessChainLoad(glslangOperands[arg]->getAsTyped()->getType())); - } - } - - builder.setLine(node->getLoc().line); - if (atomic) { - // Handle all atomics - result = createAtomicOperation(node->getOp(), precision, resultType(), operands, node->getBasicType()); - } else { - // Pass through to generic operations. - switch (glslangOperands.size()) { - case 0: - result = createNoArgOperation(node->getOp(), precision, resultType()); - break; - case 1: - { - OpDecorations decorations = { precision, - TranslateNoContractionDecoration(node->getType().getQualifier()), - TranslateNonUniformDecoration(node->getType().getQualifier()) }; - result = createUnaryOperation( - node->getOp(), decorations, - resultType(), operands.front(), - glslangOperands[0]->getAsTyped()->getBasicType()); - } - break; - default: - result = createMiscOperation(node->getOp(), precision, resultType(), operands, node->getBasicType()); - break; - } - if (invertedType) - result = createInvertedSwizzle(precision, *glslangOperands[0]->getAsBinaryNode(), result); - } - - if (noReturnValue) - return false; - - if (! result) { - logger->missingFunctionality("unknown glslang aggregate"); - return true; // pick up a child as a placeholder operand - } else { - builder.clearAccessChain(); - builder.setAccessChainRValue(result); - return false; - } -} - -// This path handles both if-then-else and ?: -// The if-then-else has a node type of void, while -// ?: has either a void or a non-void node type -// -// Leaving the result, when not void: -// GLSL only has r-values as the result of a :?, but -// if we have an l-value, that can be more efficient if it will -// become the base of a complex r-value expression, because the -// next layer copies r-values into memory to use the access-chain mechanism -bool TGlslangToSpvTraverser::visitSelection(glslang::TVisit /* visit */, glslang::TIntermSelection* node) -{ - // See if it simple and safe, or required, to execute both sides. - // Crucially, side effects must be either semantically required or avoided, - // and there are performance trade-offs. - // Return true if required or a good idea (and safe) to execute both sides, - // false otherwise. - const auto bothSidesPolicy = [&]() -> bool { - // do we have both sides? - if (node->getTrueBlock() == nullptr || - node->getFalseBlock() == nullptr) - return false; - - // required? (unless we write additional code to look for side effects - // and make performance trade-offs if none are present) - if (!node->getShortCircuit()) - return true; - - // if not required to execute both, decide based on performance/practicality... - - // see if OpSelect can handle it - if ((!node->getType().isScalar() && !node->getType().isVector()) || - node->getBasicType() == glslang::EbtVoid) - return false; - - assert(node->getType() == node->getTrueBlock() ->getAsTyped()->getType() && - node->getType() == node->getFalseBlock()->getAsTyped()->getType()); - - // return true if a single operand to ? : is okay for OpSelect - const auto operandOkay = [](glslang::TIntermTyped* node) { - return node->getAsSymbolNode() || node->getType().getQualifier().isConstant(); - }; - - return operandOkay(node->getTrueBlock() ->getAsTyped()) && - operandOkay(node->getFalseBlock()->getAsTyped()); - }; - - spv::Id result = spv::NoResult; // upcoming result selecting between trueValue and falseValue - // emit the condition before doing anything with selection - node->getCondition()->traverse(this); - spv::Id condition = accessChainLoad(node->getCondition()->getType()); - - // Find a way of executing both sides and selecting the right result. - const auto executeBothSides = [&]() -> void { - // execute both sides - node->getTrueBlock()->traverse(this); - spv::Id trueValue = accessChainLoad(node->getTrueBlock()->getAsTyped()->getType()); - node->getFalseBlock()->traverse(this); - spv::Id falseValue = accessChainLoad(node->getTrueBlock()->getAsTyped()->getType()); - - builder.setLine(node->getLoc().line); - - // done if void - if (node->getBasicType() == glslang::EbtVoid) - return; - - // emit code to select between trueValue and falseValue - - // see if OpSelect can handle it - if (node->getType().isScalar() || node->getType().isVector()) { - // Emit OpSelect for this selection. - - // smear condition to vector, if necessary (AST is always scalar) - if (builder.isVector(trueValue)) - condition = builder.smearScalar(spv::NoPrecision, condition, - builder.makeVectorType(builder.makeBoolType(), - builder.getNumComponents(trueValue))); - - // OpSelect - result = builder.createTriOp(spv::OpSelect, - convertGlslangToSpvType(node->getType()), condition, - trueValue, falseValue); - - builder.clearAccessChain(); - builder.setAccessChainRValue(result); - } else { - // We need control flow to select the result. - // TODO: Once SPIR-V OpSelect allows arbitrary types, eliminate this path. - result = builder.createVariable(spv::StorageClassFunction, convertGlslangToSpvType(node->getType())); - - // Selection control: - const spv::SelectionControlMask control = TranslateSelectionControl(*node); - - // make an "if" based on the value created by the condition - spv::Builder::If ifBuilder(condition, control, builder); - - // emit the "then" statement - builder.createStore(trueValue, result); - ifBuilder.makeBeginElse(); - // emit the "else" statement - builder.createStore(falseValue, result); - - // finish off the control flow - ifBuilder.makeEndIf(); - - builder.clearAccessChain(); - builder.setAccessChainLValue(result); - } - }; - - // Execute the one side needed, as per the condition - const auto executeOneSide = [&]() { - // Always emit control flow. - if (node->getBasicType() != glslang::EbtVoid) - result = builder.createVariable(spv::StorageClassFunction, convertGlslangToSpvType(node->getType())); - - // Selection control: - const spv::SelectionControlMask control = TranslateSelectionControl(*node); - - // make an "if" based on the value created by the condition - spv::Builder::If ifBuilder(condition, control, builder); - - // emit the "then" statement - if (node->getTrueBlock() != nullptr) { - node->getTrueBlock()->traverse(this); - if (result != spv::NoResult) - builder.createStore(accessChainLoad(node->getTrueBlock()->getAsTyped()->getType()), result); - } - - if (node->getFalseBlock() != nullptr) { - ifBuilder.makeBeginElse(); - // emit the "else" statement - node->getFalseBlock()->traverse(this); - if (result != spv::NoResult) - builder.createStore(accessChainLoad(node->getFalseBlock()->getAsTyped()->getType()), result); - } - - // finish off the control flow - ifBuilder.makeEndIf(); - - if (result != spv::NoResult) { - builder.clearAccessChain(); - builder.setAccessChainLValue(result); - } - }; - - // Try for OpSelect (or a requirement to execute both sides) - if (bothSidesPolicy()) { - SpecConstantOpModeGuard spec_constant_op_mode_setter(&builder); - if (node->getType().getQualifier().isSpecConstant()) - spec_constant_op_mode_setter.turnOnSpecConstantOpMode(); - executeBothSides(); - } else - executeOneSide(); - - return false; -} - -bool TGlslangToSpvTraverser::visitSwitch(glslang::TVisit /* visit */, glslang::TIntermSwitch* node) -{ - // emit and get the condition before doing anything with switch - node->getCondition()->traverse(this); - spv::Id selector = accessChainLoad(node->getCondition()->getAsTyped()->getType()); - - // Selection control: - const spv::SelectionControlMask control = TranslateSwitchControl(*node); - - // browse the children to sort out code segments - int defaultSegment = -1; - std::vector codeSegments; - glslang::TIntermSequence& sequence = node->getBody()->getSequence(); - std::vector caseValues; - std::vector valueIndexToSegment(sequence.size()); // note: probably not all are used, it is an overestimate - for (glslang::TIntermSequence::iterator c = sequence.begin(); c != sequence.end(); ++c) { - TIntermNode* child = *c; - if (child->getAsBranchNode() && child->getAsBranchNode()->getFlowOp() == glslang::EOpDefault) - defaultSegment = (int)codeSegments.size(); - else if (child->getAsBranchNode() && child->getAsBranchNode()->getFlowOp() == glslang::EOpCase) { - valueIndexToSegment[caseValues.size()] = (int)codeSegments.size(); - caseValues.push_back(child->getAsBranchNode()->getExpression()->getAsConstantUnion()->getConstArray()[0].getIConst()); - } else - codeSegments.push_back(child); - } - - // handle the case where the last code segment is missing, due to no code - // statements between the last case and the end of the switch statement - if ((caseValues.size() && (int)codeSegments.size() == valueIndexToSegment[caseValues.size() - 1]) || - (int)codeSegments.size() == defaultSegment) - codeSegments.push_back(nullptr); - - // make the switch statement - std::vector segmentBlocks; // returned, as the blocks allocated in the call - builder.makeSwitch(selector, control, (int)codeSegments.size(), caseValues, valueIndexToSegment, defaultSegment, segmentBlocks); - - // emit all the code in the segments - breakForLoop.push(false); - for (unsigned int s = 0; s < codeSegments.size(); ++s) { - builder.nextSwitchSegment(segmentBlocks, s); - if (codeSegments[s]) - codeSegments[s]->traverse(this); - else - builder.addSwitchBreak(); - } - breakForLoop.pop(); - - builder.endSwitch(segmentBlocks); - - return false; -} - -void TGlslangToSpvTraverser::visitConstantUnion(glslang::TIntermConstantUnion* node) -{ - int nextConst = 0; - spv::Id constant = createSpvConstantFromConstUnionArray(node->getType(), node->getConstArray(), nextConst, false); - - builder.clearAccessChain(); - builder.setAccessChainRValue(constant); -} - -bool TGlslangToSpvTraverser::visitLoop(glslang::TVisit /* visit */, glslang::TIntermLoop* node) -{ - auto blocks = builder.makeNewLoop(); - builder.createBranch(&blocks.head); - - // Loop control: - unsigned int dependencyLength = glslang::TIntermLoop::dependencyInfinite; - const spv::LoopControlMask control = TranslateLoopControl(*node, dependencyLength); - - // Spec requires back edges to target header blocks, and every header block - // must dominate its merge block. Make a header block first to ensure these - // conditions are met. By definition, it will contain OpLoopMerge, followed - // by a block-ending branch. But we don't want to put any other body/test - // instructions in it, since the body/test may have arbitrary instructions, - // including merges of its own. - builder.setLine(node->getLoc().line); - builder.setBuildPoint(&blocks.head); - builder.createLoopMerge(&blocks.merge, &blocks.continue_target, control, dependencyLength); - if (node->testFirst() && node->getTest()) { - spv::Block& test = builder.makeNewBlock(); - builder.createBranch(&test); - - builder.setBuildPoint(&test); - node->getTest()->traverse(this); - spv::Id condition = accessChainLoad(node->getTest()->getType()); - builder.createConditionalBranch(condition, &blocks.body, &blocks.merge); - - builder.setBuildPoint(&blocks.body); - breakForLoop.push(true); - if (node->getBody()) - node->getBody()->traverse(this); - builder.createBranch(&blocks.continue_target); - breakForLoop.pop(); - - builder.setBuildPoint(&blocks.continue_target); - if (node->getTerminal()) - node->getTerminal()->traverse(this); - builder.createBranch(&blocks.head); - } else { - builder.setLine(node->getLoc().line); - builder.createBranch(&blocks.body); - - breakForLoop.push(true); - builder.setBuildPoint(&blocks.body); - if (node->getBody()) - node->getBody()->traverse(this); - builder.createBranch(&blocks.continue_target); - breakForLoop.pop(); - - builder.setBuildPoint(&blocks.continue_target); - if (node->getTerminal()) - node->getTerminal()->traverse(this); - if (node->getTest()) { - node->getTest()->traverse(this); - spv::Id condition = - accessChainLoad(node->getTest()->getType()); - builder.createConditionalBranch(condition, &blocks.head, &blocks.merge); - } else { - // TODO: unless there was a break/return/discard instruction - // somewhere in the body, this is an infinite loop, so we should - // issue a warning. - builder.createBranch(&blocks.head); - } - } - builder.setBuildPoint(&blocks.merge); - builder.closeLoop(); - return false; -} - -bool TGlslangToSpvTraverser::visitBranch(glslang::TVisit /* visit */, glslang::TIntermBranch* node) -{ - if (node->getExpression()) - node->getExpression()->traverse(this); - - builder.setLine(node->getLoc().line); - - switch (node->getFlowOp()) { - case glslang::EOpKill: - builder.makeDiscard(); - break; - case glslang::EOpBreak: - if (breakForLoop.top()) - builder.createLoopExit(); - else - builder.addSwitchBreak(); - break; - case glslang::EOpContinue: - builder.createLoopContinue(); - break; - case glslang::EOpReturn: - if (node->getExpression()) { - const glslang::TType& glslangReturnType = node->getExpression()->getType(); - spv::Id returnId = accessChainLoad(glslangReturnType); - if (builder.getTypeId(returnId) != currentFunction->getReturnType()) { - builder.clearAccessChain(); - spv::Id copyId = builder.createVariable(spv::StorageClassFunction, currentFunction->getReturnType()); - builder.setAccessChainLValue(copyId); - multiTypeStore(glslangReturnType, returnId); - returnId = builder.createLoad(copyId); - } - builder.makeReturn(false, returnId); - } else - builder.makeReturn(false); - - builder.clearAccessChain(); - break; - - default: - assert(0); - break; - } - - return false; -} - -spv::Id TGlslangToSpvTraverser::createSpvVariable(const glslang::TIntermSymbol* node) -{ - // First, steer off constants, which are not SPIR-V variables, but - // can still have a mapping to a SPIR-V Id. - // This includes specialization constants. - if (node->getQualifier().isConstant()) { - return createSpvConstant(*node); - } - - // Now, handle actual variables - spv::StorageClass storageClass = TranslateStorageClass(node->getType()); - spv::Id spvType = convertGlslangToSpvType(node->getType()); - - const bool contains16BitType = node->getType().containsBasicType(glslang::EbtFloat16) || - node->getType().containsBasicType(glslang::EbtInt16) || - node->getType().containsBasicType(glslang::EbtUint16); - if (contains16BitType) { - if (storageClass == spv::StorageClassInput || storageClass == spv::StorageClassOutput) { - addPre13Extension(spv::E_SPV_KHR_16bit_storage); - builder.addCapability(spv::CapabilityStorageInputOutput16); - } else if (storageClass == spv::StorageClassPushConstant) { - addPre13Extension(spv::E_SPV_KHR_16bit_storage); - builder.addCapability(spv::CapabilityStoragePushConstant16); - } else if (storageClass == spv::StorageClassUniform) { - addPre13Extension(spv::E_SPV_KHR_16bit_storage); - builder.addCapability(spv::CapabilityStorageUniform16); - if (node->getType().getQualifier().storage == glslang::EvqBuffer) - builder.addCapability(spv::CapabilityStorageUniformBufferBlock16); - } - } - - const char* name = node->getName().c_str(); - if (glslang::IsAnonymous(name)) - name = ""; - - return builder.createVariable(storageClass, spvType, name); -} - -// Return type Id of the sampled type. -spv::Id TGlslangToSpvTraverser::getSampledType(const glslang::TSampler& sampler) -{ - switch (sampler.type) { - case glslang::EbtFloat: return builder.makeFloatType(32); -#ifdef AMD_EXTENSIONS - case glslang::EbtFloat16: - builder.addExtension(spv::E_SPV_AMD_gpu_shader_half_float_fetch); - builder.addCapability(spv::CapabilityFloat16ImageAMD); - return builder.makeFloatType(16); -#endif - case glslang::EbtInt: return builder.makeIntType(32); - case glslang::EbtUint: return builder.makeUintType(32); - default: - assert(0); - return builder.makeFloatType(32); - } -} - -// If node is a swizzle operation, return the type that should be used if -// the swizzle base is first consumed by another operation, before the swizzle -// is applied. -spv::Id TGlslangToSpvTraverser::getInvertedSwizzleType(const glslang::TIntermTyped& node) -{ - if (node.getAsOperator() && - node.getAsOperator()->getOp() == glslang::EOpVectorSwizzle) - return convertGlslangToSpvType(node.getAsBinaryNode()->getLeft()->getType()); - else - return spv::NoType; -} - -// When inverting a swizzle with a parent op, this function -// will apply the swizzle operation to a completed parent operation. -spv::Id TGlslangToSpvTraverser::createInvertedSwizzle(spv::Decoration precision, const glslang::TIntermTyped& node, spv::Id parentResult) -{ - std::vector swizzle; - convertSwizzle(*node.getAsBinaryNode()->getRight()->getAsAggregate(), swizzle); - return builder.createRvalueSwizzle(precision, convertGlslangToSpvType(node.getType()), parentResult, swizzle); -} - -// Convert a glslang AST swizzle node to a swizzle vector for building SPIR-V. -void TGlslangToSpvTraverser::convertSwizzle(const glslang::TIntermAggregate& node, std::vector& swizzle) -{ - const glslang::TIntermSequence& swizzleSequence = node.getSequence(); - for (int i = 0; i < (int)swizzleSequence.size(); ++i) - swizzle.push_back(swizzleSequence[i]->getAsConstantUnion()->getConstArray()[0].getIConst()); -} - -// Convert from a glslang type to an SPV type, by calling into a -// recursive version of this function. This establishes the inherited -// layout state rooted from the top-level type. -spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& type) -{ - return convertGlslangToSpvType(type, getExplicitLayout(type), type.getQualifier(), false); -} - -// Do full recursive conversion of an arbitrary glslang type to a SPIR-V Id. -// explicitLayout can be kept the same throughout the hierarchical recursive walk. -// Mutually recursive with convertGlslangStructToSpvType(). -spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& type, - glslang::TLayoutPacking explicitLayout, const glslang::TQualifier& qualifier, bool lastBufferBlockMember) -{ - spv::Id spvType = spv::NoResult; - - switch (type.getBasicType()) { - case glslang::EbtVoid: - spvType = builder.makeVoidType(); - assert (! type.isArray()); - break; - case glslang::EbtFloat: - spvType = builder.makeFloatType(32); - break; - case glslang::EbtDouble: - spvType = builder.makeFloatType(64); - break; - case glslang::EbtFloat16: - builder.addCapability(spv::CapabilityFloat16); -#if AMD_EXTENSIONS - if (builder.getSpvVersion() < glslang::EShTargetSpv_1_3) - builder.addExtension(spv::E_SPV_AMD_gpu_shader_half_float); -#endif - spvType = builder.makeFloatType(16); - break; - case glslang::EbtBool: - // "transparent" bool doesn't exist in SPIR-V. The GLSL convention is - // a 32-bit int where non-0 means true. - if (explicitLayout != glslang::ElpNone) - spvType = builder.makeUintType(32); - else - spvType = builder.makeBoolType(); - break; - case glslang::EbtInt8: - builder.addCapability(spv::CapabilityInt8); - spvType = builder.makeIntType(8); - break; - case glslang::EbtUint8: - builder.addCapability(spv::CapabilityInt8); - spvType = builder.makeUintType(8); - break; - case glslang::EbtInt16: - builder.addCapability(spv::CapabilityInt16); -#ifdef AMD_EXTENSIONS - if (builder.getSpvVersion() < glslang::EShTargetSpv_1_3) - builder.addExtension(spv::E_SPV_AMD_gpu_shader_int16); -#endif - spvType = builder.makeIntType(16); - break; - case glslang::EbtUint16: - builder.addCapability(spv::CapabilityInt16); -#ifdef AMD_EXTENSIONS - if (builder.getSpvVersion() < glslang::EShTargetSpv_1_3) - builder.addExtension(spv::E_SPV_AMD_gpu_shader_int16); -#endif - spvType = builder.makeUintType(16); - break; - case glslang::EbtInt: - spvType = builder.makeIntType(32); - break; - case glslang::EbtUint: - spvType = builder.makeUintType(32); - break; - case glslang::EbtInt64: - spvType = builder.makeIntType(64); - break; - case glslang::EbtUint64: - spvType = builder.makeUintType(64); - break; - case glslang::EbtAtomicUint: - builder.addCapability(spv::CapabilityAtomicStorage); - spvType = builder.makeUintType(32); - break; - case glslang::EbtSampler: - { - const glslang::TSampler& sampler = type.getSampler(); - if (sampler.sampler) { - // pure sampler - spvType = builder.makeSamplerType(); - } else { - // an image is present, make its type - spvType = builder.makeImageType(getSampledType(sampler), TranslateDimensionality(sampler), sampler.shadow, sampler.arrayed, sampler.ms, - sampler.image ? 2 : 1, TranslateImageFormat(type)); - if (sampler.combined) { - // already has both image and sampler, make the combined type - spvType = builder.makeSampledImageType(spvType); - } - } - } - break; - case glslang::EbtStruct: - case glslang::EbtBlock: - { - // If we've seen this struct type, return it - const glslang::TTypeList* glslangMembers = type.getStruct(); - - // Try to share structs for different layouts, but not yet for other - // kinds of qualification (primarily not yet including interpolant qualification). - if (! HasNonLayoutQualifiers(type, qualifier)) - spvType = structMap[explicitLayout][qualifier.layoutMatrix][glslangMembers]; - if (spvType != spv::NoResult) - break; - - // else, we haven't seen it... - if (type.getBasicType() == glslang::EbtBlock) - memberRemapper[glslangMembers].resize(glslangMembers->size()); - spvType = convertGlslangStructToSpvType(type, glslangMembers, explicitLayout, qualifier); - } - break; - default: - assert(0); - break; - } - - if (type.isMatrix()) - spvType = builder.makeMatrixType(spvType, type.getMatrixCols(), type.getMatrixRows()); - else { - // If this variable has a vector element count greater than 1, create a SPIR-V vector - if (type.getVectorSize() > 1) - spvType = builder.makeVectorType(spvType, type.getVectorSize()); - } - - if (type.isArray()) { - int stride = 0; // keep this 0 unless doing an explicit layout; 0 will mean no decoration, no stride - - // Do all but the outer dimension - if (type.getArraySizes()->getNumDims() > 1) { - // We need to decorate array strides for types needing explicit layout, except blocks. - if (explicitLayout != glslang::ElpNone && type.getBasicType() != glslang::EbtBlock) { - // Use a dummy glslang type for querying internal strides of - // arrays of arrays, but using just a one-dimensional array. - glslang::TType simpleArrayType(type, 0); // deference type of the array - while (simpleArrayType.getArraySizes()->getNumDims() > 1) - simpleArrayType.getArraySizes()->dereference(); - - // Will compute the higher-order strides here, rather than making a whole - // pile of types and doing repetitive recursion on their contents. - stride = getArrayStride(simpleArrayType, explicitLayout, qualifier.layoutMatrix); - } - - // make the arrays - for (int dim = type.getArraySizes()->getNumDims() - 1; dim > 0; --dim) { - spvType = builder.makeArrayType(spvType, makeArraySizeId(*type.getArraySizes(), dim), stride); - if (stride > 0) - builder.addDecoration(spvType, spv::DecorationArrayStride, stride); - stride *= type.getArraySizes()->getDimSize(dim); - } - } else { - // single-dimensional array, and don't yet have stride - - // We need to decorate array strides for types needing explicit layout, except blocks. - if (explicitLayout != glslang::ElpNone && type.getBasicType() != glslang::EbtBlock) - stride = getArrayStride(type, explicitLayout, qualifier.layoutMatrix); - } - - // Do the outer dimension, which might not be known for a runtime-sized array. - // (Unsized arrays that survive through linking will be runtime-sized arrays) - if (type.isSizedArray()) - spvType = builder.makeArrayType(spvType, makeArraySizeId(*type.getArraySizes(), 0), stride); - else { - if (!lastBufferBlockMember) { - builder.addExtension("SPV_EXT_descriptor_indexing"); - builder.addCapability(spv::CapabilityRuntimeDescriptorArrayEXT); - } - spvType = builder.makeRuntimeArray(spvType); - } - if (stride > 0) - builder.addDecoration(spvType, spv::DecorationArrayStride, stride); - } - - return spvType; -} - -// TODO: this functionality should exist at a higher level, in creating the AST -// -// Identify interface members that don't have their required extension turned on. -// -bool TGlslangToSpvTraverser::filterMember(const glslang::TType& member) -{ - auto& extensions = glslangIntermediate->getRequestedExtensions(); - - if (member.getFieldName() == "gl_ViewportMask" && - extensions.find("GL_NV_viewport_array2") == extensions.end()) - return true; - if (member.getFieldName() == "gl_SecondaryViewportMaskNV" && - extensions.find("GL_NV_stereo_view_rendering") == extensions.end()) - return true; - if (member.getFieldName() == "gl_SecondaryPositionNV" && - extensions.find("GL_NV_stereo_view_rendering") == extensions.end()) - return true; - if (member.getFieldName() == "gl_PositionPerViewNV" && - extensions.find("GL_NVX_multiview_per_view_attributes") == extensions.end()) - return true; - if (member.getFieldName() == "gl_ViewportMaskPerViewNV" && - extensions.find("GL_NVX_multiview_per_view_attributes") == extensions.end()) - return true; - - return false; -}; - -// Do full recursive conversion of a glslang structure (or block) type to a SPIR-V Id. -// explicitLayout can be kept the same throughout the hierarchical recursive walk. -// Mutually recursive with convertGlslangToSpvType(). -spv::Id TGlslangToSpvTraverser::convertGlslangStructToSpvType(const glslang::TType& type, - const glslang::TTypeList* glslangMembers, - glslang::TLayoutPacking explicitLayout, - const glslang::TQualifier& qualifier) -{ - // Create a vector of struct types for SPIR-V to consume - std::vector spvMembers; - int memberDelta = 0; // how much the member's index changes from glslang to SPIR-V, normally 0, except sometimes for blocks - for (int i = 0; i < (int)glslangMembers->size(); i++) { - glslang::TType& glslangMember = *(*glslangMembers)[i].type; - if (glslangMember.hiddenMember()) { - ++memberDelta; - if (type.getBasicType() == glslang::EbtBlock) - memberRemapper[glslangMembers][i] = -1; - } else { - if (type.getBasicType() == glslang::EbtBlock) { - memberRemapper[glslangMembers][i] = i - memberDelta; - if (filterMember(glslangMember)) - continue; - } - // modify just this child's view of the qualifier - glslang::TQualifier memberQualifier = glslangMember.getQualifier(); - InheritQualifiers(memberQualifier, qualifier); - - // manually inherit location - if (! memberQualifier.hasLocation() && qualifier.hasLocation()) - memberQualifier.layoutLocation = qualifier.layoutLocation; - - // recurse - bool lastBufferBlockMember = qualifier.storage == glslang::EvqBuffer && - i == (int)glslangMembers->size() - 1; - spvMembers.push_back( - convertGlslangToSpvType(glslangMember, explicitLayout, memberQualifier, lastBufferBlockMember)); - } - } - - // Make the SPIR-V type - spv::Id spvType = builder.makeStructType(spvMembers, type.getTypeName().c_str()); - if (! HasNonLayoutQualifiers(type, qualifier)) - structMap[explicitLayout][qualifier.layoutMatrix][glslangMembers] = spvType; - - // Decorate it - decorateStructType(type, glslangMembers, explicitLayout, qualifier, spvType); - - return spvType; -} - -void TGlslangToSpvTraverser::decorateStructType(const glslang::TType& type, - const glslang::TTypeList* glslangMembers, - glslang::TLayoutPacking explicitLayout, - const glslang::TQualifier& qualifier, - spv::Id spvType) -{ - // Name and decorate the non-hidden members - int offset = -1; - int locationOffset = 0; // for use within the members of this struct - for (int i = 0; i < (int)glslangMembers->size(); i++) { - glslang::TType& glslangMember = *(*glslangMembers)[i].type; - int member = i; - if (type.getBasicType() == glslang::EbtBlock) { - member = memberRemapper[glslangMembers][i]; - if (filterMember(glslangMember)) - continue; - } - - // modify just this child's view of the qualifier - glslang::TQualifier memberQualifier = glslangMember.getQualifier(); - InheritQualifiers(memberQualifier, qualifier); - - // using -1 above to indicate a hidden member - if (member < 0) - continue; - - builder.addMemberName(spvType, member, glslangMember.getFieldName().c_str()); - builder.addMemberDecoration(spvType, member, - TranslateLayoutDecoration(glslangMember, memberQualifier.layoutMatrix)); - builder.addMemberDecoration(spvType, member, TranslatePrecisionDecoration(glslangMember)); - // Add interpolation and auxiliary storage decorations only to - // top-level members of Input and Output storage classes - if (type.getQualifier().storage == glslang::EvqVaryingIn || - type.getQualifier().storage == glslang::EvqVaryingOut) { - if (type.getBasicType() == glslang::EbtBlock || - glslangIntermediate->getSource() == glslang::EShSourceHlsl) { - builder.addMemberDecoration(spvType, member, TranslateInterpolationDecoration(memberQualifier)); - builder.addMemberDecoration(spvType, member, TranslateAuxiliaryStorageDecoration(memberQualifier)); - } - } - builder.addMemberDecoration(spvType, member, TranslateInvariantDecoration(memberQualifier)); - - if (type.getBasicType() == glslang::EbtBlock && - qualifier.storage == glslang::EvqBuffer) { - // Add memory decorations only to top-level members of shader storage block - std::vector memory; - TranslateMemoryDecoration(memberQualifier, memory); - for (unsigned int i = 0; i < memory.size(); ++i) - builder.addMemberDecoration(spvType, member, memory[i]); - } - - // Location assignment was already completed correctly by the front end, - // just track whether a member needs to be decorated. - // Ignore member locations if the container is an array, as that's - // ill-specified and decisions have been made to not allow this. - if (! type.isArray() && memberQualifier.hasLocation()) - builder.addMemberDecoration(spvType, member, spv::DecorationLocation, memberQualifier.layoutLocation); - - if (qualifier.hasLocation()) // track for upcoming inheritance - locationOffset += glslangIntermediate->computeTypeLocationSize( - glslangMember, glslangIntermediate->getStage()); - - // component, XFB, others - if (glslangMember.getQualifier().hasComponent()) - builder.addMemberDecoration(spvType, member, spv::DecorationComponent, - glslangMember.getQualifier().layoutComponent); - if (glslangMember.getQualifier().hasXfbOffset()) - builder.addMemberDecoration(spvType, member, spv::DecorationOffset, - glslangMember.getQualifier().layoutXfbOffset); - else if (explicitLayout != glslang::ElpNone) { - // figure out what to do with offset, which is accumulating - int nextOffset; - updateMemberOffset(type, glslangMember, offset, nextOffset, explicitLayout, memberQualifier.layoutMatrix); - if (offset >= 0) - builder.addMemberDecoration(spvType, member, spv::DecorationOffset, offset); - offset = nextOffset; - } - - if (glslangMember.isMatrix() && explicitLayout != glslang::ElpNone) - builder.addMemberDecoration(spvType, member, spv::DecorationMatrixStride, - getMatrixStride(glslangMember, explicitLayout, memberQualifier.layoutMatrix)); - - // built-in variable decorations - spv::BuiltIn builtIn = TranslateBuiltInDecoration(glslangMember.getQualifier().builtIn, true); - if (builtIn != spv::BuiltInMax) - builder.addMemberDecoration(spvType, member, spv::DecorationBuiltIn, (int)builtIn); - - // nonuniform - builder.addMemberDecoration(spvType, member, TranslateNonUniformDecoration(glslangMember.getQualifier())); - - if (glslangIntermediate->getHlslFunctionality1() && memberQualifier.semanticName != nullptr) { - builder.addExtension("SPV_GOOGLE_hlsl_functionality1"); - builder.addMemberDecoration(spvType, member, (spv::Decoration)spv::DecorationHlslSemanticGOOGLE, - memberQualifier.semanticName); - } - -#ifdef NV_EXTENSIONS - if (builtIn == spv::BuiltInLayer) { - // SPV_NV_viewport_array2 extension - if (glslangMember.getQualifier().layoutViewportRelative){ - builder.addMemberDecoration(spvType, member, (spv::Decoration)spv::DecorationViewportRelativeNV); - builder.addCapability(spv::CapabilityShaderViewportMaskNV); - builder.addExtension(spv::E_SPV_NV_viewport_array2); - } - if (glslangMember.getQualifier().layoutSecondaryViewportRelativeOffset != -2048){ - builder.addMemberDecoration(spvType, member, - (spv::Decoration)spv::DecorationSecondaryViewportRelativeNV, - glslangMember.getQualifier().layoutSecondaryViewportRelativeOffset); - builder.addCapability(spv::CapabilityShaderStereoViewNV); - builder.addExtension(spv::E_SPV_NV_stereo_view_rendering); - } - } - if (glslangMember.getQualifier().layoutPassthrough) { - builder.addMemberDecoration(spvType, member, (spv::Decoration)spv::DecorationPassthroughNV); - builder.addCapability(spv::CapabilityGeometryShaderPassthroughNV); - builder.addExtension(spv::E_SPV_NV_geometry_shader_passthrough); - } -#endif - } - - // Decorate the structure - builder.addDecoration(spvType, TranslateLayoutDecoration(type, qualifier.layoutMatrix)); - builder.addDecoration(spvType, TranslateBlockDecoration(type, glslangIntermediate->usingStorageBuffer())); - if (type.getQualifier().hasStream() && glslangIntermediate->isMultiStream()) { - builder.addCapability(spv::CapabilityGeometryStreams); - builder.addDecoration(spvType, spv::DecorationStream, type.getQualifier().layoutStream); - } -} - -// Turn the expression forming the array size into an id. -// This is not quite trivial, because of specialization constants. -// Sometimes, a raw constant is turned into an Id, and sometimes -// a specialization constant expression is. -spv::Id TGlslangToSpvTraverser::makeArraySizeId(const glslang::TArraySizes& arraySizes, int dim) -{ - // First, see if this is sized with a node, meaning a specialization constant: - glslang::TIntermTyped* specNode = arraySizes.getDimNode(dim); - if (specNode != nullptr) { - builder.clearAccessChain(); - specNode->traverse(this); - return accessChainLoad(specNode->getAsTyped()->getType()); - } - - // Otherwise, need a compile-time (front end) size, get it: - int size = arraySizes.getDimSize(dim); - assert(size > 0); - return builder.makeUintConstant(size); -} - -// Wrap the builder's accessChainLoad to: -// - localize handling of RelaxedPrecision -// - use the SPIR-V inferred type instead of another conversion of the glslang type -// (avoids unnecessary work and possible type punning for structures) -// - do conversion of concrete to abstract type -spv::Id TGlslangToSpvTraverser::accessChainLoad(const glslang::TType& type) -{ - spv::Id nominalTypeId = builder.accessChainGetInferredType(); - spv::Id loadedId = builder.accessChainLoad(TranslatePrecisionDecoration(type), - TranslateNonUniformDecoration(type.getQualifier()), nominalTypeId); - - // Need to convert to abstract types when necessary - if (type.getBasicType() == glslang::EbtBool) { - if (builder.isScalarType(nominalTypeId)) { - // Conversion for bool - spv::Id boolType = builder.makeBoolType(); - if (nominalTypeId != boolType) - loadedId = builder.createBinOp(spv::OpINotEqual, boolType, loadedId, builder.makeUintConstant(0)); - } else if (builder.isVectorType(nominalTypeId)) { - // Conversion for bvec - int vecSize = builder.getNumTypeComponents(nominalTypeId); - spv::Id bvecType = builder.makeVectorType(builder.makeBoolType(), vecSize); - if (nominalTypeId != bvecType) - loadedId = builder.createBinOp(spv::OpINotEqual, bvecType, loadedId, makeSmearedConstant(builder.makeUintConstant(0), vecSize)); - } - } - - return loadedId; -} - -// Wrap the builder's accessChainStore to: -// - do conversion of concrete to abstract type -// -// Implicitly uses the existing builder.accessChain as the storage target. -void TGlslangToSpvTraverser::accessChainStore(const glslang::TType& type, spv::Id rvalue) -{ - // Need to convert to abstract types when necessary - if (type.getBasicType() == glslang::EbtBool) { - spv::Id nominalTypeId = builder.accessChainGetInferredType(); - - if (builder.isScalarType(nominalTypeId)) { - // Conversion for bool - spv::Id boolType = builder.makeBoolType(); - if (nominalTypeId != boolType) { - // keep these outside arguments, for determinant order-of-evaluation - spv::Id one = builder.makeUintConstant(1); - spv::Id zero = builder.makeUintConstant(0); - rvalue = builder.createTriOp(spv::OpSelect, nominalTypeId, rvalue, one, zero); - } else if (builder.getTypeId(rvalue) != boolType) - rvalue = builder.createBinOp(spv::OpINotEqual, boolType, rvalue, builder.makeUintConstant(0)); - } else if (builder.isVectorType(nominalTypeId)) { - // Conversion for bvec - int vecSize = builder.getNumTypeComponents(nominalTypeId); - spv::Id bvecType = builder.makeVectorType(builder.makeBoolType(), vecSize); - if (nominalTypeId != bvecType) { - // keep these outside arguments, for determinant order-of-evaluation - spv::Id one = makeSmearedConstant(builder.makeUintConstant(1), vecSize); - spv::Id zero = makeSmearedConstant(builder.makeUintConstant(0), vecSize); - rvalue = builder.createTriOp(spv::OpSelect, nominalTypeId, rvalue, one, zero); - } else if (builder.getTypeId(rvalue) != bvecType) - rvalue = builder.createBinOp(spv::OpINotEqual, bvecType, rvalue, - makeSmearedConstant(builder.makeUintConstant(0), vecSize)); - } - } - - builder.accessChainStore(rvalue); -} - -// For storing when types match at the glslang level, but not might match at the -// SPIR-V level. -// -// This especially happens when a single glslang type expands to multiple -// SPIR-V types, like a struct that is used in a member-undecorated way as well -// as in a member-decorated way. -// -// NOTE: This function can handle any store request; if it's not special it -// simplifies to a simple OpStore. -// -// Implicitly uses the existing builder.accessChain as the storage target. -void TGlslangToSpvTraverser::multiTypeStore(const glslang::TType& type, spv::Id rValue) -{ - // we only do the complex path here if it's an aggregate - if (! type.isStruct() && ! type.isArray()) { - accessChainStore(type, rValue); - return; - } - - // and, it has to be a case of type aliasing - spv::Id rType = builder.getTypeId(rValue); - spv::Id lValue = builder.accessChainGetLValue(); - spv::Id lType = builder.getContainedTypeId(builder.getTypeId(lValue)); - if (lType == rType) { - accessChainStore(type, rValue); - return; - } - - // Recursively (as needed) copy an aggregate type to a different aggregate type, - // where the two types were the same type in GLSL. This requires member - // by member copy, recursively. - - // If an array, copy element by element. - if (type.isArray()) { - glslang::TType glslangElementType(type, 0); - spv::Id elementRType = builder.getContainedTypeId(rType); - for (int index = 0; index < type.getOuterArraySize(); ++index) { - // get the source member - spv::Id elementRValue = builder.createCompositeExtract(rValue, elementRType, index); - - // set up the target storage - builder.clearAccessChain(); - builder.setAccessChainLValue(lValue); - builder.accessChainPush(builder.makeIntConstant(index)); - - // store the member - multiTypeStore(glslangElementType, elementRValue); - } - } else { - assert(type.isStruct()); - - // loop over structure members - const glslang::TTypeList& members = *type.getStruct(); - for (int m = 0; m < (int)members.size(); ++m) { - const glslang::TType& glslangMemberType = *members[m].type; - - // get the source member - spv::Id memberRType = builder.getContainedTypeId(rType, m); - spv::Id memberRValue = builder.createCompositeExtract(rValue, memberRType, m); - - // set up the target storage - builder.clearAccessChain(); - builder.setAccessChainLValue(lValue); - builder.accessChainPush(builder.makeIntConstant(m)); - - // store the member - multiTypeStore(glslangMemberType, memberRValue); - } - } -} - -// Decide whether or not this type should be -// decorated with offsets and strides, and if so -// whether std140 or std430 rules should be applied. -glslang::TLayoutPacking TGlslangToSpvTraverser::getExplicitLayout(const glslang::TType& type) const -{ - // has to be a block - if (type.getBasicType() != glslang::EbtBlock) - return glslang::ElpNone; - - // has to be a uniform or buffer block - if (type.getQualifier().storage != glslang::EvqUniform && - type.getQualifier().storage != glslang::EvqBuffer) - return glslang::ElpNone; - - // return the layout to use - switch (type.getQualifier().layoutPacking) { - case glslang::ElpStd140: - case glslang::ElpStd430: - return type.getQualifier().layoutPacking; - default: - return glslang::ElpNone; - } -} - -// Given an array type, returns the integer stride required for that array -int TGlslangToSpvTraverser::getArrayStride(const glslang::TType& arrayType, glslang::TLayoutPacking explicitLayout, glslang::TLayoutMatrix matrixLayout) -{ - int size; - int stride; - glslangIntermediate->getBaseAlignment(arrayType, size, stride, explicitLayout == glslang::ElpStd140, matrixLayout == glslang::ElmRowMajor); - - return stride; -} - -// Given a matrix type, or array (of array) of matrixes type, returns the integer stride required for that matrix -// when used as a member of an interface block -int TGlslangToSpvTraverser::getMatrixStride(const glslang::TType& matrixType, glslang::TLayoutPacking explicitLayout, glslang::TLayoutMatrix matrixLayout) -{ - glslang::TType elementType; - elementType.shallowCopy(matrixType); - elementType.clearArraySizes(); - - int size; - int stride; - glslangIntermediate->getBaseAlignment(elementType, size, stride, explicitLayout == glslang::ElpStd140, matrixLayout == glslang::ElmRowMajor); - - return stride; -} - -// Given a member type of a struct, realign the current offset for it, and compute -// the next (not yet aligned) offset for the next member, which will get aligned -// on the next call. -// 'currentOffset' should be passed in already initialized, ready to modify, and reflecting -// the migration of data from nextOffset -> currentOffset. It should be -1 on the first call. -// -1 means a non-forced member offset (no decoration needed). -void TGlslangToSpvTraverser::updateMemberOffset(const glslang::TType& structType, const glslang::TType& memberType, int& currentOffset, int& nextOffset, - glslang::TLayoutPacking explicitLayout, glslang::TLayoutMatrix matrixLayout) -{ - // this will get a positive value when deemed necessary - nextOffset = -1; - - // override anything in currentOffset with user-set offset - if (memberType.getQualifier().hasOffset()) - currentOffset = memberType.getQualifier().layoutOffset; - - // It could be that current linker usage in glslang updated all the layoutOffset, - // in which case the following code does not matter. But, that's not quite right - // once cross-compilation unit GLSL validation is done, as the original user - // settings are needed in layoutOffset, and then the following will come into play. - - if (explicitLayout == glslang::ElpNone) { - if (! memberType.getQualifier().hasOffset()) - currentOffset = -1; - - return; - } - - // Getting this far means we need explicit offsets - if (currentOffset < 0) - currentOffset = 0; - - // Now, currentOffset is valid (either 0, or from a previous nextOffset), - // but possibly not yet correctly aligned. - - int memberSize; - int dummyStride; - int memberAlignment = glslangIntermediate->getBaseAlignment(memberType, memberSize, dummyStride, explicitLayout == glslang::ElpStd140, matrixLayout == glslang::ElmRowMajor); - - // Adjust alignment for HLSL rules - // TODO: make this consistent in early phases of code: - // adjusting this late means inconsistencies with earlier code, which for reflection is an issue - // Until reflection is brought in sync with these adjustments, don't apply to $Global, - // which is the most likely to rely on reflection, and least likely to rely implicit layouts - if (glslangIntermediate->usingHlslOFfsets() && - ! memberType.isArray() && memberType.isVector() && structType.getTypeName().compare("$Global") != 0) { - int dummySize; - int componentAlignment = glslangIntermediate->getBaseAlignmentScalar(memberType, dummySize); - if (componentAlignment <= 4) - memberAlignment = componentAlignment; - } - - // Bump up to member alignment - glslang::RoundToPow2(currentOffset, memberAlignment); - - // Bump up to vec4 if there is a bad straddle - if (glslangIntermediate->improperStraddle(memberType, memberSize, currentOffset)) - glslang::RoundToPow2(currentOffset, 16); - - nextOffset = currentOffset + memberSize; -} - -void TGlslangToSpvTraverser::declareUseOfStructMember(const glslang::TTypeList& members, int glslangMember) -{ - const glslang::TBuiltInVariable glslangBuiltIn = members[glslangMember].type->getQualifier().builtIn; - switch (glslangBuiltIn) - { - case glslang::EbvClipDistance: - case glslang::EbvCullDistance: - case glslang::EbvPointSize: -#ifdef NV_EXTENSIONS - case glslang::EbvViewportMaskNV: - case glslang::EbvSecondaryPositionNV: - case glslang::EbvSecondaryViewportMaskNV: - case glslang::EbvPositionPerViewNV: - case glslang::EbvViewportMaskPerViewNV: -#endif - // Generate the associated capability. Delegate to TranslateBuiltInDecoration. - // Alternately, we could just call this for any glslang built-in, since the - // capability already guards against duplicates. - TranslateBuiltInDecoration(glslangBuiltIn, false); - break; - default: - // Capabilities were already generated when the struct was declared. - break; - } -} - -bool TGlslangToSpvTraverser::isShaderEntryPoint(const glslang::TIntermAggregate* node) -{ - return node->getName().compare(glslangIntermediate->getEntryPointMangledName().c_str()) == 0; -} - -// Does parameter need a place to keep writes, separate from the original? -// Assumes called after originalParam(), which filters out block/buffer/opaque-based -// qualifiers such that we should have only in/out/inout/constreadonly here. -bool TGlslangToSpvTraverser::writableParam(glslang::TStorageQualifier qualifier) -{ - assert(qualifier == glslang::EvqIn || - qualifier == glslang::EvqOut || - qualifier == glslang::EvqInOut || - qualifier == glslang::EvqConstReadOnly); - return qualifier != glslang::EvqConstReadOnly; -} - -// Is parameter pass-by-original? -bool TGlslangToSpvTraverser::originalParam(glslang::TStorageQualifier qualifier, const glslang::TType& paramType, - bool implicitThisParam) -{ - if (implicitThisParam) // implicit this - return true; - if (glslangIntermediate->getSource() == glslang::EShSourceHlsl) - return paramType.getBasicType() == glslang::EbtBlock; - return paramType.containsOpaque() || // sampler, etc. - (paramType.getBasicType() == glslang::EbtBlock && qualifier == glslang::EvqBuffer); // SSBO -} - -// Make all the functions, skeletally, without actually visiting their bodies. -void TGlslangToSpvTraverser::makeFunctions(const glslang::TIntermSequence& glslFunctions) -{ - const auto getParamDecorations = [](std::vector& decorations, const glslang::TType& type) { - spv::Decoration paramPrecision = TranslatePrecisionDecoration(type); - if (paramPrecision != spv::NoPrecision) - decorations.push_back(paramPrecision); - TranslateMemoryDecoration(type.getQualifier(), decorations); - }; - - for (int f = 0; f < (int)glslFunctions.size(); ++f) { - glslang::TIntermAggregate* glslFunction = glslFunctions[f]->getAsAggregate(); - if (! glslFunction || glslFunction->getOp() != glslang::EOpFunction || isShaderEntryPoint(glslFunction)) - continue; - - // We're on a user function. Set up the basic interface for the function now, - // so that it's available to call. Translating the body will happen later. - // - // Typically (except for a "const in" parameter), an address will be passed to the - // function. What it is an address of varies: - // - // - "in" parameters not marked as "const" can be written to without modifying the calling - // argument so that write needs to be to a copy, hence the address of a copy works. - // - // - "const in" parameters can just be the r-value, as no writes need occur. - // - // - "out" and "inout" arguments can't be done as pointers to the calling argument, because - // GLSL has copy-in/copy-out semantics. They can be handled though with a pointer to a copy. - - std::vector paramTypes; - std::vector> paramDecorations; // list of decorations per parameter - glslang::TIntermSequence& parameters = glslFunction->getSequence()[0]->getAsAggregate()->getSequence(); - - bool implicitThis = (int)parameters.size() > 0 && parameters[0]->getAsSymbolNode()->getName() == - glslangIntermediate->implicitThisName; - - paramDecorations.resize(parameters.size()); - for (int p = 0; p < (int)parameters.size(); ++p) { - const glslang::TType& paramType = parameters[p]->getAsTyped()->getType(); - spv::Id typeId = convertGlslangToSpvType(paramType); - if (originalParam(paramType.getQualifier().storage, paramType, implicitThis && p == 0)) - typeId = builder.makePointer(TranslateStorageClass(paramType), typeId); - else if (writableParam(paramType.getQualifier().storage)) - typeId = builder.makePointer(spv::StorageClassFunction, typeId); - else - rValueParameters.insert(parameters[p]->getAsSymbolNode()->getId()); - getParamDecorations(paramDecorations[p], paramType); - paramTypes.push_back(typeId); - } - - spv::Block* functionBlock; - spv::Function *function = builder.makeFunctionEntry(TranslatePrecisionDecoration(glslFunction->getType()), - convertGlslangToSpvType(glslFunction->getType()), - glslFunction->getName().c_str(), paramTypes, - paramDecorations, &functionBlock); - if (implicitThis) - function->setImplicitThis(); - - // Track function to emit/call later - functionMap[glslFunction->getName().c_str()] = function; - - // Set the parameter id's - for (int p = 0; p < (int)parameters.size(); ++p) { - symbolValues[parameters[p]->getAsSymbolNode()->getId()] = function->getParamId(p); - // give a name too - builder.addName(function->getParamId(p), parameters[p]->getAsSymbolNode()->getName().c_str()); - } - } -} - -// Process all the initializers, while skipping the functions and link objects -void TGlslangToSpvTraverser::makeGlobalInitializers(const glslang::TIntermSequence& initializers) -{ - builder.setBuildPoint(shaderEntry->getLastBlock()); - for (int i = 0; i < (int)initializers.size(); ++i) { - glslang::TIntermAggregate* initializer = initializers[i]->getAsAggregate(); - if (initializer && initializer->getOp() != glslang::EOpFunction && initializer->getOp() != glslang::EOpLinkerObjects) { - - // We're on a top-level node that's not a function. Treat as an initializer, whose - // code goes into the beginning of the entry point. - initializer->traverse(this); - } - } -} - -// Process all the functions, while skipping initializers. -void TGlslangToSpvTraverser::visitFunctions(const glslang::TIntermSequence& glslFunctions) -{ - for (int f = 0; f < (int)glslFunctions.size(); ++f) { - glslang::TIntermAggregate* node = glslFunctions[f]->getAsAggregate(); - if (node && (node->getOp() == glslang::EOpFunction || node->getOp() == glslang::EOpLinkerObjects)) - node->traverse(this); - } -} - -void TGlslangToSpvTraverser::handleFunctionEntry(const glslang::TIntermAggregate* node) -{ - // SPIR-V functions should already be in the functionMap from the prepass - // that called makeFunctions(). - currentFunction = functionMap[node->getName().c_str()]; - spv::Block* functionBlock = currentFunction->getEntryBlock(); - builder.setBuildPoint(functionBlock); -} - -void TGlslangToSpvTraverser::translateArguments(const glslang::TIntermAggregate& node, std::vector& arguments) -{ - const glslang::TIntermSequence& glslangArguments = node.getSequence(); - - glslang::TSampler sampler = {}; - bool cubeCompare = false; -#ifdef AMD_EXTENSIONS - bool f16ShadowCompare = false; -#endif - if (node.isTexture() || node.isImage()) { - sampler = glslangArguments[0]->getAsTyped()->getType().getSampler(); - cubeCompare = sampler.dim == glslang::EsdCube && sampler.arrayed && sampler.shadow; -#ifdef AMD_EXTENSIONS - f16ShadowCompare = sampler.shadow && glslangArguments[1]->getAsTyped()->getType().getBasicType() == glslang::EbtFloat16; -#endif - } - - for (int i = 0; i < (int)glslangArguments.size(); ++i) { - builder.clearAccessChain(); - glslangArguments[i]->traverse(this); - - // Special case l-value operands - bool lvalue = false; - switch (node.getOp()) { - case glslang::EOpImageAtomicAdd: - case glslang::EOpImageAtomicMin: - case glslang::EOpImageAtomicMax: - case glslang::EOpImageAtomicAnd: - case glslang::EOpImageAtomicOr: - case glslang::EOpImageAtomicXor: - case glslang::EOpImageAtomicExchange: - case glslang::EOpImageAtomicCompSwap: - if (i == 0) - lvalue = true; - break; - case glslang::EOpSparseImageLoad: - if ((sampler.ms && i == 3) || (! sampler.ms && i == 2)) - lvalue = true; - break; -#ifdef AMD_EXTENSIONS - case glslang::EOpSparseTexture: - if (((cubeCompare || f16ShadowCompare) && i == 3) || (! (cubeCompare || f16ShadowCompare) && i == 2)) - lvalue = true; - break; - case glslang::EOpSparseTextureClamp: - if (((cubeCompare || f16ShadowCompare) && i == 4) || (! (cubeCompare || f16ShadowCompare) && i == 3)) - lvalue = true; - break; - case glslang::EOpSparseTextureLod: - case glslang::EOpSparseTextureOffset: - if ((f16ShadowCompare && i == 4) || (! f16ShadowCompare && i == 3)) - lvalue = true; - break; -#else - case glslang::EOpSparseTexture: - if ((cubeCompare && i == 3) || (! cubeCompare && i == 2)) - lvalue = true; - break; - case glslang::EOpSparseTextureClamp: - if ((cubeCompare && i == 4) || (! cubeCompare && i == 3)) - lvalue = true; - break; - case glslang::EOpSparseTextureLod: - case glslang::EOpSparseTextureOffset: - if (i == 3) - lvalue = true; - break; -#endif - case glslang::EOpSparseTextureFetch: - if ((sampler.dim != glslang::EsdRect && i == 3) || (sampler.dim == glslang::EsdRect && i == 2)) - lvalue = true; - break; - case glslang::EOpSparseTextureFetchOffset: - if ((sampler.dim != glslang::EsdRect && i == 4) || (sampler.dim == glslang::EsdRect && i == 3)) - lvalue = true; - break; -#ifdef AMD_EXTENSIONS - case glslang::EOpSparseTextureLodOffset: - case glslang::EOpSparseTextureGrad: - case glslang::EOpSparseTextureOffsetClamp: - if ((f16ShadowCompare && i == 5) || (! f16ShadowCompare && i == 4)) - lvalue = true; - break; - case glslang::EOpSparseTextureGradOffset: - case glslang::EOpSparseTextureGradClamp: - if ((f16ShadowCompare && i == 6) || (! f16ShadowCompare && i == 5)) - lvalue = true; - break; - case glslang::EOpSparseTextureGradOffsetClamp: - if ((f16ShadowCompare && i == 7) || (! f16ShadowCompare && i == 6)) - lvalue = true; - break; -#else - case glslang::EOpSparseTextureLodOffset: - case glslang::EOpSparseTextureGrad: - case glslang::EOpSparseTextureOffsetClamp: - if (i == 4) - lvalue = true; - break; - case glslang::EOpSparseTextureGradOffset: - case glslang::EOpSparseTextureGradClamp: - if (i == 5) - lvalue = true; - break; - case glslang::EOpSparseTextureGradOffsetClamp: - if (i == 6) - lvalue = true; - break; -#endif - case glslang::EOpSparseTextureGather: - if ((sampler.shadow && i == 3) || (! sampler.shadow && i == 2)) - lvalue = true; - break; - case glslang::EOpSparseTextureGatherOffset: - case glslang::EOpSparseTextureGatherOffsets: - if ((sampler.shadow && i == 4) || (! sampler.shadow && i == 3)) - lvalue = true; - break; -#ifdef AMD_EXTENSIONS - case glslang::EOpSparseTextureGatherLod: - if (i == 3) - lvalue = true; - break; - case glslang::EOpSparseTextureGatherLodOffset: - case glslang::EOpSparseTextureGatherLodOffsets: - if (i == 4) - lvalue = true; - break; - case glslang::EOpSparseImageLoadLod: - if (i == 3) - lvalue = true; - break; -#endif - default: - break; - } - - if (lvalue) - arguments.push_back(builder.accessChainGetLValue()); - else - arguments.push_back(accessChainLoad(glslangArguments[i]->getAsTyped()->getType())); - } -} - -void TGlslangToSpvTraverser::translateArguments(glslang::TIntermUnary& node, std::vector& arguments) -{ - builder.clearAccessChain(); - node.getOperand()->traverse(this); - arguments.push_back(accessChainLoad(node.getOperand()->getType())); -} - -spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermOperator* node) -{ - if (! node->isImage() && ! node->isTexture()) - return spv::NoResult; - - builder.setLine(node->getLoc().line); - - // Process a GLSL texturing op (will be SPV image) - const glslang::TSampler sampler = node->getAsAggregate() ? node->getAsAggregate()->getSequence()[0]->getAsTyped()->getType().getSampler() - : node->getAsUnaryNode()->getOperand()->getAsTyped()->getType().getSampler(); -#ifdef AMD_EXTENSIONS - bool f16ShadowCompare = (sampler.shadow && node->getAsAggregate()) - ? node->getAsAggregate()->getSequence()[1]->getAsTyped()->getType().getBasicType() == glslang::EbtFloat16 - : false; -#endif - - std::vector arguments; - if (node->getAsAggregate()) - translateArguments(*node->getAsAggregate(), arguments); - else - translateArguments(*node->getAsUnaryNode(), arguments); - spv::Decoration precision = TranslatePrecisionDecoration(node->getOperationPrecision()); - - spv::Builder::TextureParameters params = { }; - params.sampler = arguments[0]; - - glslang::TCrackedTextureOp cracked; - node->crackTexture(sampler, cracked); - - const bool isUnsignedResult = node->getType().getBasicType() == glslang::EbtUint; - - // Check for queries - if (cracked.query) { - // OpImageQueryLod works on a sampled image, for other queries the image has to be extracted first - if (node->getOp() != glslang::EOpTextureQueryLod && builder.isSampledImage(params.sampler)) - params.sampler = builder.createUnaryOp(spv::OpImage, builder.getImageType(params.sampler), params.sampler); - - switch (node->getOp()) { - case glslang::EOpImageQuerySize: - case glslang::EOpTextureQuerySize: - if (arguments.size() > 1) { - params.lod = arguments[1]; - return builder.createTextureQueryCall(spv::OpImageQuerySizeLod, params, isUnsignedResult); - } else - return builder.createTextureQueryCall(spv::OpImageQuerySize, params, isUnsignedResult); - case glslang::EOpImageQuerySamples: - case glslang::EOpTextureQuerySamples: - return builder.createTextureQueryCall(spv::OpImageQuerySamples, params, isUnsignedResult); - case glslang::EOpTextureQueryLod: - params.coords = arguments[1]; - return builder.createTextureQueryCall(spv::OpImageQueryLod, params, isUnsignedResult); - case glslang::EOpTextureQueryLevels: - return builder.createTextureQueryCall(spv::OpImageQueryLevels, params, isUnsignedResult); - case glslang::EOpSparseTexelsResident: - return builder.createUnaryOp(spv::OpImageSparseTexelsResident, builder.makeBoolType(), arguments[0]); - default: - assert(0); - break; - } - } - - int components = node->getType().getVectorSize(); - - if (node->getOp() == glslang::EOpTextureFetch) { - // These must produce 4 components, per SPIR-V spec. We'll add a conversion constructor if needed. - // This will only happen through the HLSL path for operator[], so we do not have to handle e.g. - // the EOpTexture/Proj/Lod/etc family. It would be harmless to do so, but would need more logic - // here around e.g. which ones return scalars or other types. - components = 4; - } - - glslang::TType returnType(node->getType().getBasicType(), glslang::EvqTemporary, components); - - auto resultType = [&returnType,this]{ return convertGlslangToSpvType(returnType); }; - - // Check for image functions other than queries - if (node->isImage()) { - std::vector operands; - auto opIt = arguments.begin(); - operands.push_back(*(opIt++)); - - // Handle subpass operations - // TODO: GLSL should change to have the "MS" only on the type rather than the - // built-in function. - if (cracked.subpass) { - // add on the (0,0) coordinate - spv::Id zero = builder.makeIntConstant(0); - std::vector comps; - comps.push_back(zero); - comps.push_back(zero); - operands.push_back(builder.makeCompositeConstant(builder.makeVectorType(builder.makeIntType(32), 2), comps)); - if (sampler.ms) { - operands.push_back(spv::ImageOperandsSampleMask); - operands.push_back(*(opIt++)); - } - spv::Id result = builder.createOp(spv::OpImageRead, resultType(), operands); - builder.setPrecision(result, precision); - return result; - } - - operands.push_back(*(opIt++)); -#ifdef AMD_EXTENSIONS - if (node->getOp() == glslang::EOpImageLoad || node->getOp() == glslang::EOpImageLoadLod) { -#else - if (node->getOp() == glslang::EOpImageLoad) { -#endif - if (sampler.ms) { - operands.push_back(spv::ImageOperandsSampleMask); - operands.push_back(*opIt); -#ifdef AMD_EXTENSIONS - } else if (cracked.lod) { - builder.addExtension(spv::E_SPV_AMD_shader_image_load_store_lod); - builder.addCapability(spv::CapabilityImageReadWriteLodAMD); - - operands.push_back(spv::ImageOperandsLodMask); - operands.push_back(*opIt); -#endif - } - if (builder.getImageTypeFormat(builder.getImageType(operands.front())) == spv::ImageFormatUnknown) - builder.addCapability(spv::CapabilityStorageImageReadWithoutFormat); - - std::vector result( 1, builder.createOp(spv::OpImageRead, resultType(), operands) ); - builder.setPrecision(result[0], precision); - - // If needed, add a conversion constructor to the proper size. - if (components != node->getType().getVectorSize()) - result[0] = builder.createConstructor(precision, result, convertGlslangToSpvType(node->getType())); - - return result[0]; -#ifdef AMD_EXTENSIONS - } else if (node->getOp() == glslang::EOpImageStore || node->getOp() == glslang::EOpImageStoreLod) { -#else - } else if (node->getOp() == glslang::EOpImageStore) { -#endif - if (sampler.ms) { - operands.push_back(*(opIt + 1)); - operands.push_back(spv::ImageOperandsSampleMask); - operands.push_back(*opIt); -#ifdef AMD_EXTENSIONS - } else if (cracked.lod) { - builder.addExtension(spv::E_SPV_AMD_shader_image_load_store_lod); - builder.addCapability(spv::CapabilityImageReadWriteLodAMD); - - operands.push_back(*(opIt + 1)); - operands.push_back(spv::ImageOperandsLodMask); - operands.push_back(*opIt); -#endif - } else - operands.push_back(*opIt); - builder.createNoResultOp(spv::OpImageWrite, operands); - if (builder.getImageTypeFormat(builder.getImageType(operands.front())) == spv::ImageFormatUnknown) - builder.addCapability(spv::CapabilityStorageImageWriteWithoutFormat); - return spv::NoResult; -#ifdef AMD_EXTENSIONS - } else if (node->getOp() == glslang::EOpSparseImageLoad || node->getOp() == glslang::EOpSparseImageLoadLod) { -#else - } else if (node->getOp() == glslang::EOpSparseImageLoad) { -#endif - builder.addCapability(spv::CapabilitySparseResidency); - if (builder.getImageTypeFormat(builder.getImageType(operands.front())) == spv::ImageFormatUnknown) - builder.addCapability(spv::CapabilityStorageImageReadWithoutFormat); - - if (sampler.ms) { - operands.push_back(spv::ImageOperandsSampleMask); - operands.push_back(*opIt++); -#ifdef AMD_EXTENSIONS - } else if (cracked.lod) { - builder.addExtension(spv::E_SPV_AMD_shader_image_load_store_lod); - builder.addCapability(spv::CapabilityImageReadWriteLodAMD); - - operands.push_back(spv::ImageOperandsLodMask); - operands.push_back(*opIt++); -#endif - } - - // Create the return type that was a special structure - spv::Id texelOut = *opIt; - spv::Id typeId0 = resultType(); - spv::Id typeId1 = builder.getDerefTypeId(texelOut); - spv::Id resultTypeId = builder.makeStructResultType(typeId0, typeId1); - - spv::Id resultId = builder.createOp(spv::OpImageSparseRead, resultTypeId, operands); - - // Decode the return type - builder.createStore(builder.createCompositeExtract(resultId, typeId1, 1), texelOut); - return builder.createCompositeExtract(resultId, typeId0, 0); - } else { - // Process image atomic operations - - // GLSL "IMAGE_PARAMS" will involve in constructing an image texel pointer and this pointer, - // as the first source operand, is required by SPIR-V atomic operations. - operands.push_back(sampler.ms ? *(opIt++) : builder.makeUintConstant(0)); // For non-MS, the value should be 0 - - spv::Id resultTypeId = builder.makePointer(spv::StorageClassImage, resultType()); - spv::Id pointer = builder.createOp(spv::OpImageTexelPointer, resultTypeId, operands); - - std::vector operands; - operands.push_back(pointer); - for (; opIt != arguments.end(); ++opIt) - operands.push_back(*opIt); - - return createAtomicOperation(node->getOp(), precision, resultType(), operands, node->getBasicType()); - } - } - -#ifdef AMD_EXTENSIONS - // Check for fragment mask functions other than queries - if (cracked.fragMask) { - assert(sampler.ms); - - auto opIt = arguments.begin(); - std::vector operands; - - // Extract the image if necessary - if (builder.isSampledImage(params.sampler)) - params.sampler = builder.createUnaryOp(spv::OpImage, builder.getImageType(params.sampler), params.sampler); - - operands.push_back(params.sampler); - ++opIt; - - if (sampler.isSubpass()) { - // add on the (0,0) coordinate - spv::Id zero = builder.makeIntConstant(0); - std::vector comps; - comps.push_back(zero); - comps.push_back(zero); - operands.push_back(builder.makeCompositeConstant(builder.makeVectorType(builder.makeIntType(32), 2), comps)); - } - - for (; opIt != arguments.end(); ++opIt) - operands.push_back(*opIt); - - spv::Op fragMaskOp = spv::OpNop; - if (node->getOp() == glslang::EOpFragmentMaskFetch) - fragMaskOp = spv::OpFragmentMaskFetchAMD; - else if (node->getOp() == glslang::EOpFragmentFetch) - fragMaskOp = spv::OpFragmentFetchAMD; - - builder.addExtension(spv::E_SPV_AMD_shader_fragment_mask); - builder.addCapability(spv::CapabilityFragmentMaskAMD); - return builder.createOp(fragMaskOp, resultType(), operands); - } -#endif - - // Check for texture functions other than queries - bool sparse = node->isSparseTexture(); - bool cubeCompare = sampler.dim == glslang::EsdCube && sampler.arrayed && sampler.shadow; - - // check for bias argument - bool bias = false; -#ifdef AMD_EXTENSIONS - if (! cracked.lod && ! cracked.grad && ! cracked.fetch && ! cubeCompare) { -#else - if (! cracked.lod && ! cracked.gather && ! cracked.grad && ! cracked.fetch && ! cubeCompare) { -#endif - int nonBiasArgCount = 2; -#ifdef AMD_EXTENSIONS - if (cracked.gather) - ++nonBiasArgCount; // comp argument should be present when bias argument is present - - if (f16ShadowCompare) - ++nonBiasArgCount; -#endif - if (cracked.offset) - ++nonBiasArgCount; -#ifdef AMD_EXTENSIONS - else if (cracked.offsets) - ++nonBiasArgCount; -#endif - if (cracked.grad) - nonBiasArgCount += 2; - if (cracked.lodClamp) - ++nonBiasArgCount; - if (sparse) - ++nonBiasArgCount; - - if ((int)arguments.size() > nonBiasArgCount) - bias = true; - } - - // See if the sampler param should really be just the SPV image part - if (cracked.fetch) { - // a fetch needs to have the image extracted first - if (builder.isSampledImage(params.sampler)) - params.sampler = builder.createUnaryOp(spv::OpImage, builder.getImageType(params.sampler), params.sampler); - } - -#ifdef AMD_EXTENSIONS - if (cracked.gather) { - const auto& sourceExtensions = glslangIntermediate->getRequestedExtensions(); - if (bias || cracked.lod || - sourceExtensions.find(glslang::E_GL_AMD_texture_gather_bias_lod) != sourceExtensions.end()) { - builder.addExtension(spv::E_SPV_AMD_texture_gather_bias_lod); - builder.addCapability(spv::CapabilityImageGatherBiasLodAMD); - } - } -#endif - - // set the rest of the arguments - - params.coords = arguments[1]; - int extraArgs = 0; - bool noImplicitLod = false; - - // sort out where Dref is coming from -#ifdef AMD_EXTENSIONS - if (cubeCompare || f16ShadowCompare) { -#else - if (cubeCompare) { -#endif - params.Dref = arguments[2]; - ++extraArgs; - } else if (sampler.shadow && cracked.gather) { - params.Dref = arguments[2]; - ++extraArgs; - } else if (sampler.shadow) { - std::vector indexes; - int dRefComp; - if (cracked.proj) - dRefComp = 2; // "The resulting 3rd component of P in the shadow forms is used as Dref" - else - dRefComp = builder.getNumComponents(params.coords) - 1; - indexes.push_back(dRefComp); - params.Dref = builder.createCompositeExtract(params.coords, builder.getScalarTypeId(builder.getTypeId(params.coords)), indexes); - } - - // lod - if (cracked.lod) { - params.lod = arguments[2 + extraArgs]; - ++extraArgs; - } else if (glslangIntermediate->getStage() != EShLangFragment) { - // we need to invent the default lod for an explicit lod instruction for a non-fragment stage - noImplicitLod = true; - } - - // multisample - if (sampler.ms) { - params.sample = arguments[2 + extraArgs]; // For MS, "sample" should be specified - ++extraArgs; - } - - // gradient - if (cracked.grad) { - params.gradX = arguments[2 + extraArgs]; - params.gradY = arguments[3 + extraArgs]; - extraArgs += 2; - } - - // offset and offsets - if (cracked.offset) { - params.offset = arguments[2 + extraArgs]; - ++extraArgs; - } else if (cracked.offsets) { - params.offsets = arguments[2 + extraArgs]; - ++extraArgs; - } - - // lod clamp - if (cracked.lodClamp) { - params.lodClamp = arguments[2 + extraArgs]; - ++extraArgs; - } - - // sparse - if (sparse) { - params.texelOut = arguments[2 + extraArgs]; - ++extraArgs; - } - - // gather component - if (cracked.gather && ! sampler.shadow) { - // default component is 0, if missing, otherwise an argument - if (2 + extraArgs < (int)arguments.size()) { - params.component = arguments[2 + extraArgs]; - ++extraArgs; - } else - params.component = builder.makeIntConstant(0); - } - - // bias - if (bias) { - params.bias = arguments[2 + extraArgs]; - ++extraArgs; - } - - // projective component (might not to move) - // GLSL: "The texture coordinates consumed from P, not including the last component of P, - // are divided by the last component of P." - // SPIR-V: "... (u [, v] [, w], q)... It may be a vector larger than needed, but all - // unused components will appear after all used components." - if (cracked.proj) { - int projSourceComp = builder.getNumComponents(params.coords) - 1; - int projTargetComp; - switch (sampler.dim) { - case glslang::Esd1D: projTargetComp = 1; break; - case glslang::Esd2D: projTargetComp = 2; break; - case glslang::EsdRect: projTargetComp = 2; break; - default: projTargetComp = projSourceComp; break; - } - // copy the projective coordinate if we have to - if (projTargetComp != projSourceComp) { - spv::Id projComp = builder.createCompositeExtract(params.coords, - builder.getScalarTypeId(builder.getTypeId(params.coords)), - projSourceComp); - params.coords = builder.createCompositeInsert(projComp, params.coords, - builder.getTypeId(params.coords), projTargetComp); - } - } - - std::vector result( 1, - builder.createTextureCall(precision, resultType(), sparse, cracked.fetch, cracked.proj, cracked.gather, noImplicitLod, params) - ); - - if (components != node->getType().getVectorSize()) - result[0] = builder.createConstructor(precision, result, convertGlslangToSpvType(node->getType())); - - return result[0]; -} - -spv::Id TGlslangToSpvTraverser::handleUserFunctionCall(const glslang::TIntermAggregate* node) -{ - // Grab the function's pointer from the previously created function - spv::Function* function = functionMap[node->getName().c_str()]; - if (! function) - return 0; - - const glslang::TIntermSequence& glslangArgs = node->getSequence(); - const glslang::TQualifierList& qualifiers = node->getQualifierList(); - - // See comments in makeFunctions() for details about the semantics for parameter passing. - // - // These imply we need a four step process: - // 1. Evaluate the arguments - // 2. Allocate and make copies of in, out, and inout arguments - // 3. Make the call - // 4. Copy back the results - - // 1. Evaluate the arguments - std::vector lValues; - std::vector rValues; - std::vector argTypes; - for (int a = 0; a < (int)glslangArgs.size(); ++a) { - const glslang::TType& paramType = glslangArgs[a]->getAsTyped()->getType(); - // build l-value - builder.clearAccessChain(); - glslangArgs[a]->traverse(this); - argTypes.push_back(¶mType); - // keep outputs and pass-by-originals as l-values, evaluate others as r-values - if (originalParam(qualifiers[a], paramType, function->hasImplicitThis() && a == 0) || - writableParam(qualifiers[a])) { - // save l-value - lValues.push_back(builder.getAccessChain()); - } else { - // process r-value - rValues.push_back(accessChainLoad(*argTypes.back())); - } - } - - // 2. Allocate space for anything needing a copy, and if it's "in" or "inout" - // copy the original into that space. - // - // Also, build up the list of actual arguments to pass in for the call - int lValueCount = 0; - int rValueCount = 0; - std::vector spvArgs; - for (int a = 0; a < (int)glslangArgs.size(); ++a) { - const glslang::TType& paramType = glslangArgs[a]->getAsTyped()->getType(); - spv::Id arg; - if (originalParam(qualifiers[a], paramType, function->hasImplicitThis() && a == 0)) { - builder.setAccessChain(lValues[lValueCount]); - arg = builder.accessChainGetLValue(); - ++lValueCount; - } else if (writableParam(qualifiers[a])) { - // need space to hold the copy - arg = builder.createVariable(spv::StorageClassFunction, convertGlslangToSpvType(paramType), "param"); - if (qualifiers[a] == glslang::EvqIn || qualifiers[a] == glslang::EvqInOut) { - // need to copy the input into output space - builder.setAccessChain(lValues[lValueCount]); - spv::Id copy = accessChainLoad(*argTypes[a]); - builder.clearAccessChain(); - builder.setAccessChainLValue(arg); - multiTypeStore(paramType, copy); - } - ++lValueCount; - } else { - arg = rValues[rValueCount]; - ++rValueCount; - } - spvArgs.push_back(arg); - } - - // 3. Make the call. - spv::Id result = builder.createFunctionCall(function, spvArgs); - builder.setPrecision(result, TranslatePrecisionDecoration(node->getType())); - - // 4. Copy back out an "out" arguments. - lValueCount = 0; - for (int a = 0; a < (int)glslangArgs.size(); ++a) { - const glslang::TType& paramType = glslangArgs[a]->getAsTyped()->getType(); - if (originalParam(qualifiers[a], paramType, function->hasImplicitThis() && a == 0)) - ++lValueCount; - else if (writableParam(qualifiers[a])) { - if (qualifiers[a] == glslang::EvqOut || qualifiers[a] == glslang::EvqInOut) { - spv::Id copy = builder.createLoad(spvArgs[a]); - builder.setAccessChain(lValues[lValueCount]); - multiTypeStore(paramType, copy); - } - ++lValueCount; - } - } - - return result; -} - -// Translate AST operation to SPV operation, already having SPV-based operands/types. -spv::Id TGlslangToSpvTraverser::createBinaryOperation(glslang::TOperator op, OpDecorations& decorations, - spv::Id typeId, spv::Id left, spv::Id right, - glslang::TBasicType typeProxy, bool reduceComparison) -{ - bool isUnsigned = isTypeUnsignedInt(typeProxy); - bool isFloat = isTypeFloat(typeProxy); - bool isBool = typeProxy == glslang::EbtBool; - - spv::Op binOp = spv::OpNop; - bool needMatchingVectors = true; // for non-matrix ops, would a scalar need to smear to match a vector? - bool comparison = false; - - switch (op) { - case glslang::EOpAdd: - case glslang::EOpAddAssign: - if (isFloat) - binOp = spv::OpFAdd; - else - binOp = spv::OpIAdd; - break; - case glslang::EOpSub: - case glslang::EOpSubAssign: - if (isFloat) - binOp = spv::OpFSub; - else - binOp = spv::OpISub; - break; - case glslang::EOpMul: - case glslang::EOpMulAssign: - if (isFloat) - binOp = spv::OpFMul; - else - binOp = spv::OpIMul; - break; - case glslang::EOpVectorTimesScalar: - case glslang::EOpVectorTimesScalarAssign: - if (isFloat && (builder.isVector(left) || builder.isVector(right))) { - if (builder.isVector(right)) - std::swap(left, right); - assert(builder.isScalar(right)); - needMatchingVectors = false; - binOp = spv::OpVectorTimesScalar; - } else - binOp = spv::OpIMul; - break; - case glslang::EOpVectorTimesMatrix: - case glslang::EOpVectorTimesMatrixAssign: - binOp = spv::OpVectorTimesMatrix; - break; - case glslang::EOpMatrixTimesVector: - binOp = spv::OpMatrixTimesVector; - break; - case glslang::EOpMatrixTimesScalar: - case glslang::EOpMatrixTimesScalarAssign: - binOp = spv::OpMatrixTimesScalar; - break; - case glslang::EOpMatrixTimesMatrix: - case glslang::EOpMatrixTimesMatrixAssign: - binOp = spv::OpMatrixTimesMatrix; - break; - case glslang::EOpOuterProduct: - binOp = spv::OpOuterProduct; - needMatchingVectors = false; - break; - - case glslang::EOpDiv: - case glslang::EOpDivAssign: - if (isFloat) - binOp = spv::OpFDiv; - else if (isUnsigned) - binOp = spv::OpUDiv; - else - binOp = spv::OpSDiv; - break; - case glslang::EOpMod: - case glslang::EOpModAssign: - if (isFloat) - binOp = spv::OpFMod; - else if (isUnsigned) - binOp = spv::OpUMod; - else - binOp = spv::OpSMod; - break; - case glslang::EOpRightShift: - case glslang::EOpRightShiftAssign: - if (isUnsigned) - binOp = spv::OpShiftRightLogical; - else - binOp = spv::OpShiftRightArithmetic; - break; - case glslang::EOpLeftShift: - case glslang::EOpLeftShiftAssign: - binOp = spv::OpShiftLeftLogical; - break; - case glslang::EOpAnd: - case glslang::EOpAndAssign: - binOp = spv::OpBitwiseAnd; - break; - case glslang::EOpLogicalAnd: - needMatchingVectors = false; - binOp = spv::OpLogicalAnd; - break; - case glslang::EOpInclusiveOr: - case glslang::EOpInclusiveOrAssign: - binOp = spv::OpBitwiseOr; - break; - case glslang::EOpLogicalOr: - needMatchingVectors = false; - binOp = spv::OpLogicalOr; - break; - case glslang::EOpExclusiveOr: - case glslang::EOpExclusiveOrAssign: - binOp = spv::OpBitwiseXor; - break; - case glslang::EOpLogicalXor: - needMatchingVectors = false; - binOp = spv::OpLogicalNotEqual; - break; - - case glslang::EOpLessThan: - case glslang::EOpGreaterThan: - case glslang::EOpLessThanEqual: - case glslang::EOpGreaterThanEqual: - case glslang::EOpEqual: - case glslang::EOpNotEqual: - case glslang::EOpVectorEqual: - case glslang::EOpVectorNotEqual: - comparison = true; - break; - default: - break; - } - - // handle mapped binary operations (should be non-comparison) - if (binOp != spv::OpNop) { - assert(comparison == false); - if (builder.isMatrix(left) || builder.isMatrix(right)) - return createBinaryMatrixOperation(binOp, decorations, typeId, left, right); - - // No matrix involved; make both operands be the same number of components, if needed - if (needMatchingVectors) - builder.promoteScalar(decorations.precision, left, right); - - spv::Id result = builder.createBinOp(binOp, typeId, left, right); - builder.addDecoration(result, decorations.noContraction); - builder.addDecoration(result, decorations.nonUniform); - return builder.setPrecision(result, decorations.precision); - } - - if (! comparison) - return 0; - - // Handle comparison instructions - - if (reduceComparison && (op == glslang::EOpEqual || op == glslang::EOpNotEqual) - && (builder.isVector(left) || builder.isMatrix(left) || builder.isAggregate(left))) { - spv::Id result = builder.createCompositeCompare(decorations.precision, left, right, op == glslang::EOpEqual); - builder.addDecoration(result, decorations.nonUniform); - return result; - } - - switch (op) { - case glslang::EOpLessThan: - if (isFloat) - binOp = spv::OpFOrdLessThan; - else if (isUnsigned) - binOp = spv::OpULessThan; - else - binOp = spv::OpSLessThan; - break; - case glslang::EOpGreaterThan: - if (isFloat) - binOp = spv::OpFOrdGreaterThan; - else if (isUnsigned) - binOp = spv::OpUGreaterThan; - else - binOp = spv::OpSGreaterThan; - break; - case glslang::EOpLessThanEqual: - if (isFloat) - binOp = spv::OpFOrdLessThanEqual; - else if (isUnsigned) - binOp = spv::OpULessThanEqual; - else - binOp = spv::OpSLessThanEqual; - break; - case glslang::EOpGreaterThanEqual: - if (isFloat) - binOp = spv::OpFOrdGreaterThanEqual; - else if (isUnsigned) - binOp = spv::OpUGreaterThanEqual; - else - binOp = spv::OpSGreaterThanEqual; - break; - case glslang::EOpEqual: - case glslang::EOpVectorEqual: - if (isFloat) - binOp = spv::OpFOrdEqual; - else if (isBool) - binOp = spv::OpLogicalEqual; - else - binOp = spv::OpIEqual; - break; - case glslang::EOpNotEqual: - case glslang::EOpVectorNotEqual: - if (isFloat) - binOp = spv::OpFOrdNotEqual; - else if (isBool) - binOp = spv::OpLogicalNotEqual; - else - binOp = spv::OpINotEqual; - break; - default: - break; - } - - if (binOp != spv::OpNop) { - spv::Id result = builder.createBinOp(binOp, typeId, left, right); - builder.addDecoration(result, decorations.noContraction); - builder.addDecoration(result, decorations.nonUniform); - return builder.setPrecision(result, decorations.precision); - } - - return 0; -} - -// -// Translate AST matrix operation to SPV operation, already having SPV-based operands/types. -// These can be any of: -// -// matrix * scalar -// scalar * matrix -// matrix * matrix linear algebraic -// matrix * vector -// vector * matrix -// matrix * matrix componentwise -// matrix op matrix op in {+, -, /} -// matrix op scalar op in {+, -, /} -// scalar op matrix op in {+, -, /} -// -spv::Id TGlslangToSpvTraverser::createBinaryMatrixOperation(spv::Op op, OpDecorations& decorations, spv::Id typeId, - spv::Id left, spv::Id right) -{ - bool firstClass = true; - - // First, handle first-class matrix operations (* and matrix/scalar) - switch (op) { - case spv::OpFDiv: - if (builder.isMatrix(left) && builder.isScalar(right)) { - // turn matrix / scalar into a multiply... - spv::Id resultType = builder.getTypeId(right); - right = builder.createBinOp(spv::OpFDiv, resultType, builder.makeFpConstant(resultType, 1.0), right); - op = spv::OpMatrixTimesScalar; - } else - firstClass = false; - break; - case spv::OpMatrixTimesScalar: - if (builder.isMatrix(right)) - std::swap(left, right); - assert(builder.isScalar(right)); - break; - case spv::OpVectorTimesMatrix: - assert(builder.isVector(left)); - assert(builder.isMatrix(right)); - break; - case spv::OpMatrixTimesVector: - assert(builder.isMatrix(left)); - assert(builder.isVector(right)); - break; - case spv::OpMatrixTimesMatrix: - assert(builder.isMatrix(left)); - assert(builder.isMatrix(right)); - break; - default: - firstClass = false; - break; - } - - if (firstClass) { - spv::Id result = builder.createBinOp(op, typeId, left, right); - builder.addDecoration(result, decorations.noContraction); - builder.addDecoration(result, decorations.nonUniform); - return builder.setPrecision(result, decorations.precision); - } - - // Handle component-wise +, -, *, %, and / for all combinations of type. - // The result type of all of them is the same type as the (a) matrix operand. - // The algorithm is to: - // - break the matrix(es) into vectors - // - smear any scalar to a vector - // - do vector operations - // - make a matrix out the vector results - switch (op) { - case spv::OpFAdd: - case spv::OpFSub: - case spv::OpFDiv: - case spv::OpFMod: - case spv::OpFMul: - { - // one time set up... - bool leftMat = builder.isMatrix(left); - bool rightMat = builder.isMatrix(right); - unsigned int numCols = leftMat ? builder.getNumColumns(left) : builder.getNumColumns(right); - int numRows = leftMat ? builder.getNumRows(left) : builder.getNumRows(right); - spv::Id scalarType = builder.getScalarTypeId(typeId); - spv::Id vecType = builder.makeVectorType(scalarType, numRows); - std::vector results; - spv::Id smearVec = spv::NoResult; - if (builder.isScalar(left)) - smearVec = builder.smearScalar(decorations.precision, left, vecType); - else if (builder.isScalar(right)) - smearVec = builder.smearScalar(decorations.precision, right, vecType); - - // do each vector op - for (unsigned int c = 0; c < numCols; ++c) { - std::vector indexes; - indexes.push_back(c); - spv::Id leftVec = leftMat ? builder.createCompositeExtract( left, vecType, indexes) : smearVec; - spv::Id rightVec = rightMat ? builder.createCompositeExtract(right, vecType, indexes) : smearVec; - spv::Id result = builder.createBinOp(op, vecType, leftVec, rightVec); - builder.addDecoration(result, decorations.noContraction); - builder.addDecoration(result, decorations.nonUniform); - results.push_back(builder.setPrecision(result, decorations.precision)); - } - - // put the pieces together - spv::Id result = builder.setPrecision(builder.createCompositeConstruct(typeId, results), decorations.precision); - builder.addDecoration(result, decorations.nonUniform); - return result; - } - default: - assert(0); - return spv::NoResult; - } -} - -spv::Id TGlslangToSpvTraverser::createUnaryOperation(glslang::TOperator op, OpDecorations& decorations, spv::Id typeId, - spv::Id operand, glslang::TBasicType typeProxy) -{ - spv::Op unaryOp = spv::OpNop; - int extBuiltins = -1; - int libCall = -1; - bool isUnsigned = isTypeUnsignedInt(typeProxy); - bool isFloat = isTypeFloat(typeProxy); - - switch (op) { - case glslang::EOpNegative: - if (isFloat) { - unaryOp = spv::OpFNegate; - if (builder.isMatrixType(typeId)) - return createUnaryMatrixOperation(unaryOp, decorations, typeId, operand, typeProxy); - } else - unaryOp = spv::OpSNegate; - break; - - case glslang::EOpLogicalNot: - case glslang::EOpVectorLogicalNot: - unaryOp = spv::OpLogicalNot; - break; - case glslang::EOpBitwiseNot: - unaryOp = spv::OpNot; - break; - - case glslang::EOpDeterminant: - libCall = spv::GLSLstd450Determinant; - break; - case glslang::EOpMatrixInverse: - libCall = spv::GLSLstd450MatrixInverse; - break; - case glslang::EOpTranspose: - unaryOp = spv::OpTranspose; - break; - - case glslang::EOpRadians: - libCall = spv::GLSLstd450Radians; - break; - case glslang::EOpDegrees: - libCall = spv::GLSLstd450Degrees; - break; - case glslang::EOpSin: - libCall = spv::GLSLstd450Sin; - break; - case glslang::EOpCos: - libCall = spv::GLSLstd450Cos; - break; - case glslang::EOpTan: - libCall = spv::GLSLstd450Tan; - break; - case glslang::EOpAcos: - libCall = spv::GLSLstd450Acos; - break; - case glslang::EOpAsin: - libCall = spv::GLSLstd450Asin; - break; - case glslang::EOpAtan: - libCall = spv::GLSLstd450Atan; - break; - - case glslang::EOpAcosh: - libCall = spv::GLSLstd450Acosh; - break; - case glslang::EOpAsinh: - libCall = spv::GLSLstd450Asinh; - break; - case glslang::EOpAtanh: - libCall = spv::GLSLstd450Atanh; - break; - case glslang::EOpTanh: - libCall = spv::GLSLstd450Tanh; - break; - case glslang::EOpCosh: - libCall = spv::GLSLstd450Cosh; - break; - case glslang::EOpSinh: - libCall = spv::GLSLstd450Sinh; - break; - - case glslang::EOpLength: - libCall = spv::GLSLstd450Length; - break; - case glslang::EOpNormalize: - libCall = spv::GLSLstd450Normalize; - break; - - case glslang::EOpExp: - libCall = spv::GLSLstd450Exp; - break; - case glslang::EOpLog: - libCall = spv::GLSLstd450Log; - break; - case glslang::EOpExp2: - libCall = spv::GLSLstd450Exp2; - break; - case glslang::EOpLog2: - libCall = spv::GLSLstd450Log2; - break; - case glslang::EOpSqrt: - libCall = spv::GLSLstd450Sqrt; - break; - case glslang::EOpInverseSqrt: - libCall = spv::GLSLstd450InverseSqrt; - break; - - case glslang::EOpFloor: - libCall = spv::GLSLstd450Floor; - break; - case glslang::EOpTrunc: - libCall = spv::GLSLstd450Trunc; - break; - case glslang::EOpRound: - libCall = spv::GLSLstd450Round; - break; - case glslang::EOpRoundEven: - libCall = spv::GLSLstd450RoundEven; - break; - case glslang::EOpCeil: - libCall = spv::GLSLstd450Ceil; - break; - case glslang::EOpFract: - libCall = spv::GLSLstd450Fract; - break; - - case glslang::EOpIsNan: - unaryOp = spv::OpIsNan; - break; - case glslang::EOpIsInf: - unaryOp = spv::OpIsInf; - break; - case glslang::EOpIsFinite: - unaryOp = spv::OpIsFinite; - break; - - case glslang::EOpFloatBitsToInt: - case glslang::EOpFloatBitsToUint: - case glslang::EOpIntBitsToFloat: - case glslang::EOpUintBitsToFloat: - case glslang::EOpDoubleBitsToInt64: - case glslang::EOpDoubleBitsToUint64: - case glslang::EOpInt64BitsToDouble: - case glslang::EOpUint64BitsToDouble: - case glslang::EOpFloat16BitsToInt16: - case glslang::EOpFloat16BitsToUint16: - case glslang::EOpInt16BitsToFloat16: - case glslang::EOpUint16BitsToFloat16: - unaryOp = spv::OpBitcast; - break; - - case glslang::EOpPackSnorm2x16: - libCall = spv::GLSLstd450PackSnorm2x16; - break; - case glslang::EOpUnpackSnorm2x16: - libCall = spv::GLSLstd450UnpackSnorm2x16; - break; - case glslang::EOpPackUnorm2x16: - libCall = spv::GLSLstd450PackUnorm2x16; - break; - case glslang::EOpUnpackUnorm2x16: - libCall = spv::GLSLstd450UnpackUnorm2x16; - break; - case glslang::EOpPackHalf2x16: - libCall = spv::GLSLstd450PackHalf2x16; - break; - case glslang::EOpUnpackHalf2x16: - libCall = spv::GLSLstd450UnpackHalf2x16; - break; - case glslang::EOpPackSnorm4x8: - libCall = spv::GLSLstd450PackSnorm4x8; - break; - case glslang::EOpUnpackSnorm4x8: - libCall = spv::GLSLstd450UnpackSnorm4x8; - break; - case glslang::EOpPackUnorm4x8: - libCall = spv::GLSLstd450PackUnorm4x8; - break; - case glslang::EOpUnpackUnorm4x8: - libCall = spv::GLSLstd450UnpackUnorm4x8; - break; - case glslang::EOpPackDouble2x32: - libCall = spv::GLSLstd450PackDouble2x32; - break; - case glslang::EOpUnpackDouble2x32: - libCall = spv::GLSLstd450UnpackDouble2x32; - break; - - case glslang::EOpPackInt2x32: - case glslang::EOpUnpackInt2x32: - case glslang::EOpPackUint2x32: - case glslang::EOpUnpackUint2x32: - case glslang::EOpPack16: - case glslang::EOpPack32: - case glslang::EOpPack64: - case glslang::EOpUnpack32: - case glslang::EOpUnpack16: - case glslang::EOpUnpack8: - case glslang::EOpPackInt2x16: - case glslang::EOpUnpackInt2x16: - case glslang::EOpPackUint2x16: - case glslang::EOpUnpackUint2x16: - case glslang::EOpPackInt4x16: - case glslang::EOpUnpackInt4x16: - case glslang::EOpPackUint4x16: - case glslang::EOpUnpackUint4x16: - case glslang::EOpPackFloat2x16: - case glslang::EOpUnpackFloat2x16: - unaryOp = spv::OpBitcast; - break; - - case glslang::EOpDPdx: - unaryOp = spv::OpDPdx; - break; - case glslang::EOpDPdy: - unaryOp = spv::OpDPdy; - break; - case glslang::EOpFwidth: - unaryOp = spv::OpFwidth; - break; - case glslang::EOpDPdxFine: - builder.addCapability(spv::CapabilityDerivativeControl); - unaryOp = spv::OpDPdxFine; - break; - case glslang::EOpDPdyFine: - builder.addCapability(spv::CapabilityDerivativeControl); - unaryOp = spv::OpDPdyFine; - break; - case glslang::EOpFwidthFine: - builder.addCapability(spv::CapabilityDerivativeControl); - unaryOp = spv::OpFwidthFine; - break; - case glslang::EOpDPdxCoarse: - builder.addCapability(spv::CapabilityDerivativeControl); - unaryOp = spv::OpDPdxCoarse; - break; - case glslang::EOpDPdyCoarse: - builder.addCapability(spv::CapabilityDerivativeControl); - unaryOp = spv::OpDPdyCoarse; - break; - case glslang::EOpFwidthCoarse: - builder.addCapability(spv::CapabilityDerivativeControl); - unaryOp = spv::OpFwidthCoarse; - break; - case glslang::EOpInterpolateAtCentroid: - builder.addCapability(spv::CapabilityInterpolationFunction); - libCall = spv::GLSLstd450InterpolateAtCentroid; - break; - case glslang::EOpAny: - unaryOp = spv::OpAny; - break; - case glslang::EOpAll: - unaryOp = spv::OpAll; - break; - - case glslang::EOpAbs: - if (isFloat) - libCall = spv::GLSLstd450FAbs; - else - libCall = spv::GLSLstd450SAbs; - break; - case glslang::EOpSign: - if (isFloat) - libCall = spv::GLSLstd450FSign; - else - libCall = spv::GLSLstd450SSign; - break; - - case glslang::EOpAtomicCounterIncrement: - case glslang::EOpAtomicCounterDecrement: - case glslang::EOpAtomicCounter: - { - // Handle all of the atomics in one place, in createAtomicOperation() - std::vector operands; - operands.push_back(operand); - return createAtomicOperation(op, decorations.precision, typeId, operands, typeProxy); - } - - case glslang::EOpBitFieldReverse: - unaryOp = spv::OpBitReverse; - break; - case glslang::EOpBitCount: - unaryOp = spv::OpBitCount; - break; - case glslang::EOpFindLSB: - libCall = spv::GLSLstd450FindILsb; - break; - case glslang::EOpFindMSB: - if (isUnsigned) - libCall = spv::GLSLstd450FindUMsb; - else - libCall = spv::GLSLstd450FindSMsb; - break; - - case glslang::EOpBallot: - case glslang::EOpReadFirstInvocation: - case glslang::EOpAnyInvocation: - case glslang::EOpAllInvocations: - case glslang::EOpAllInvocationsEqual: -#ifdef AMD_EXTENSIONS - case glslang::EOpMinInvocations: - case glslang::EOpMaxInvocations: - case glslang::EOpAddInvocations: - case glslang::EOpMinInvocationsNonUniform: - case glslang::EOpMaxInvocationsNonUniform: - case glslang::EOpAddInvocationsNonUniform: - case glslang::EOpMinInvocationsInclusiveScan: - case glslang::EOpMaxInvocationsInclusiveScan: - case glslang::EOpAddInvocationsInclusiveScan: - case glslang::EOpMinInvocationsInclusiveScanNonUniform: - case glslang::EOpMaxInvocationsInclusiveScanNonUniform: - case glslang::EOpAddInvocationsInclusiveScanNonUniform: - case glslang::EOpMinInvocationsExclusiveScan: - case glslang::EOpMaxInvocationsExclusiveScan: - case glslang::EOpAddInvocationsExclusiveScan: - case glslang::EOpMinInvocationsExclusiveScanNonUniform: - case glslang::EOpMaxInvocationsExclusiveScanNonUniform: - case glslang::EOpAddInvocationsExclusiveScanNonUniform: -#endif - { - std::vector operands; - operands.push_back(operand); - return createInvocationsOperation(op, typeId, operands, typeProxy); - } - case glslang::EOpSubgroupAll: - case glslang::EOpSubgroupAny: - case glslang::EOpSubgroupAllEqual: - case glslang::EOpSubgroupBroadcastFirst: - case glslang::EOpSubgroupBallot: - case glslang::EOpSubgroupInverseBallot: - case glslang::EOpSubgroupBallotBitCount: - case glslang::EOpSubgroupBallotInclusiveBitCount: - case glslang::EOpSubgroupBallotExclusiveBitCount: - case glslang::EOpSubgroupBallotFindLSB: - case glslang::EOpSubgroupBallotFindMSB: - case glslang::EOpSubgroupAdd: - case glslang::EOpSubgroupMul: - case glslang::EOpSubgroupMin: - case glslang::EOpSubgroupMax: - case glslang::EOpSubgroupAnd: - case glslang::EOpSubgroupOr: - case glslang::EOpSubgroupXor: - case glslang::EOpSubgroupInclusiveAdd: - case glslang::EOpSubgroupInclusiveMul: - case glslang::EOpSubgroupInclusiveMin: - case glslang::EOpSubgroupInclusiveMax: - case glslang::EOpSubgroupInclusiveAnd: - case glslang::EOpSubgroupInclusiveOr: - case glslang::EOpSubgroupInclusiveXor: - case glslang::EOpSubgroupExclusiveAdd: - case glslang::EOpSubgroupExclusiveMul: - case glslang::EOpSubgroupExclusiveMin: - case glslang::EOpSubgroupExclusiveMax: - case glslang::EOpSubgroupExclusiveAnd: - case glslang::EOpSubgroupExclusiveOr: - case glslang::EOpSubgroupExclusiveXor: - case glslang::EOpSubgroupQuadSwapHorizontal: - case glslang::EOpSubgroupQuadSwapVertical: - case glslang::EOpSubgroupQuadSwapDiagonal: { - std::vector operands; - operands.push_back(operand); - return createSubgroupOperation(op, typeId, operands, typeProxy); - } -#ifdef AMD_EXTENSIONS - case glslang::EOpMbcnt: - extBuiltins = getExtBuiltins(spv::E_SPV_AMD_shader_ballot); - libCall = spv::MbcntAMD; - break; - - case glslang::EOpCubeFaceIndex: - extBuiltins = getExtBuiltins(spv::E_SPV_AMD_gcn_shader); - libCall = spv::CubeFaceIndexAMD; - break; - - case glslang::EOpCubeFaceCoord: - extBuiltins = getExtBuiltins(spv::E_SPV_AMD_gcn_shader); - libCall = spv::CubeFaceCoordAMD; - break; -#endif -#ifdef NV_EXTENSIONS - case glslang::EOpSubgroupPartition: - builder.addExtension(spv::E_SPV_NV_shader_subgroup_partitioned); - builder.addCapability(spv::CapabilityGroupNonUniformPartitionedNV); - unaryOp = spv::OpGroupNonUniformPartitionNV; - break; -#endif - default: - return 0; - } - - spv::Id id; - if (libCall >= 0) { - std::vector args; - args.push_back(operand); - id = builder.createBuiltinCall(typeId, extBuiltins >= 0 ? extBuiltins : stdBuiltins, libCall, args); - } else { - id = builder.createUnaryOp(unaryOp, typeId, operand); - } - - builder.addDecoration(id, decorations.noContraction); - builder.addDecoration(id, decorations.nonUniform); - return builder.setPrecision(id, decorations.precision); -} - -// Create a unary operation on a matrix -spv::Id TGlslangToSpvTraverser::createUnaryMatrixOperation(spv::Op op, OpDecorations& decorations, spv::Id typeId, - spv::Id operand, glslang::TBasicType /* typeProxy */) -{ - // Handle unary operations vector by vector. - // The result type is the same type as the original type. - // The algorithm is to: - // - break the matrix into vectors - // - apply the operation to each vector - // - make a matrix out the vector results - - // get the types sorted out - int numCols = builder.getNumColumns(operand); - int numRows = builder.getNumRows(operand); - spv::Id srcVecType = builder.makeVectorType(builder.getScalarTypeId(builder.getTypeId(operand)), numRows); - spv::Id destVecType = builder.makeVectorType(builder.getScalarTypeId(typeId), numRows); - std::vector results; - - // do each vector op - for (int c = 0; c < numCols; ++c) { - std::vector indexes; - indexes.push_back(c); - spv::Id srcVec = builder.createCompositeExtract(operand, srcVecType, indexes); - spv::Id destVec = builder.createUnaryOp(op, destVecType, srcVec); - builder.addDecoration(destVec, decorations.noContraction); - builder.addDecoration(destVec, decorations.nonUniform); - results.push_back(builder.setPrecision(destVec, decorations.precision)); - } - - // put the pieces together - spv::Id result = builder.setPrecision(builder.createCompositeConstruct(typeId, results), decorations.precision); - builder.addDecoration(result, decorations.nonUniform); - return result; -} - -spv::Id TGlslangToSpvTraverser::createConversionOperation(glslang::TOperator op, spv::Id operand, int vectorSize) -{ - spv::Op convOp = spv::OpNop; - spv::Id type = 0; - - spv::Id result = 0; - - switch(op) { - case glslang::EOpConvInt8ToUint16: - convOp = spv::OpSConvert; - type = builder.makeIntType(16); - break; - case glslang::EOpConvInt8ToUint: - convOp = spv::OpSConvert; - type = builder.makeIntType(32); - break; - case glslang::EOpConvInt8ToUint64: - convOp = spv::OpSConvert; - type = builder.makeIntType(64); - break; - case glslang::EOpConvInt16ToUint8: - convOp = spv::OpSConvert; - type = builder.makeIntType(8); - break; - case glslang::EOpConvInt16ToUint: - convOp = spv::OpSConvert; - type = builder.makeIntType(32); - break; - case glslang::EOpConvInt16ToUint64: - convOp = spv::OpSConvert; - type = builder.makeIntType(64); - break; - case glslang::EOpConvIntToUint8: - convOp = spv::OpSConvert; - type = builder.makeIntType(8); - break; - case glslang::EOpConvIntToUint16: - convOp = spv::OpSConvert; - type = builder.makeIntType(16); - break; - case glslang::EOpConvIntToUint64: - convOp = spv::OpSConvert; - type = builder.makeIntType(64); - break; - case glslang::EOpConvInt64ToUint8: - convOp = spv::OpSConvert; - type = builder.makeIntType(8); - break; - case glslang::EOpConvInt64ToUint16: - convOp = spv::OpSConvert; - type = builder.makeIntType(16); - break; - case glslang::EOpConvInt64ToUint: - convOp = spv::OpSConvert; - type = builder.makeIntType(32); - break; - case glslang::EOpConvUint8ToInt16: - convOp = spv::OpUConvert; - type = builder.makeIntType(16); - break; - case glslang::EOpConvUint8ToInt: - convOp = spv::OpUConvert; - type = builder.makeIntType(32); - break; - case glslang::EOpConvUint8ToInt64: - convOp = spv::OpUConvert; - type = builder.makeIntType(64); - break; - case glslang::EOpConvUint16ToInt8: - convOp = spv::OpUConvert; - type = builder.makeIntType(8); - break; - case glslang::EOpConvUint16ToInt: - convOp = spv::OpUConvert; - type = builder.makeIntType(32); - break; - case glslang::EOpConvUint16ToInt64: - convOp = spv::OpUConvert; - type = builder.makeIntType(64); - break; - case glslang::EOpConvUintToInt8: - convOp = spv::OpUConvert; - type = builder.makeIntType(8); - break; - case glslang::EOpConvUintToInt16: - convOp = spv::OpUConvert; - type = builder.makeIntType(16); - break; - case glslang::EOpConvUintToInt64: - convOp = spv::OpUConvert; - type = builder.makeIntType(64); - break; - case glslang::EOpConvUint64ToInt8: - convOp = spv::OpUConvert; - type = builder.makeIntType(8); - break; - case glslang::EOpConvUint64ToInt16: - convOp = spv::OpUConvert; - type = builder.makeIntType(16); - break; - case glslang::EOpConvUint64ToInt: - convOp = spv::OpUConvert; - type = builder.makeIntType(32); - break; - - default: - assert(false && "Default missing"); - break; - } - - if (vectorSize > 0) - type = builder.makeVectorType(type, vectorSize); - - result = builder.createUnaryOp(convOp, type, operand); - return result; -} - -spv::Id TGlslangToSpvTraverser::createConversion(glslang::TOperator op, OpDecorations& decorations, spv::Id destType, - spv::Id operand, glslang::TBasicType typeProxy) -{ - spv::Op convOp = spv::OpNop; - spv::Id zero = 0; - spv::Id one = 0; - - int vectorSize = builder.isVectorType(destType) ? builder.getNumTypeComponents(destType) : 0; - - switch (op) { - case glslang::EOpConvInt8ToBool: - case glslang::EOpConvUint8ToBool: - zero = builder.makeUint8Constant(0); - zero = makeSmearedConstant(zero, vectorSize); - return builder.createBinOp(spv::OpINotEqual, destType, operand, zero); - case glslang::EOpConvInt16ToBool: - case glslang::EOpConvUint16ToBool: - zero = builder.makeUint16Constant(0); - zero = makeSmearedConstant(zero, vectorSize); - return builder.createBinOp(spv::OpINotEqual, destType, operand, zero); - case glslang::EOpConvIntToBool: - case glslang::EOpConvUintToBool: - zero = builder.makeUintConstant(0); - zero = makeSmearedConstant(zero, vectorSize); - return builder.createBinOp(spv::OpINotEqual, destType, operand, zero); - case glslang::EOpConvInt64ToBool: - case glslang::EOpConvUint64ToBool: - zero = builder.makeUint64Constant(0); - zero = makeSmearedConstant(zero, vectorSize); - return builder.createBinOp(spv::OpINotEqual, destType, operand, zero); - - case glslang::EOpConvFloatToBool: - zero = builder.makeFloatConstant(0.0F); - zero = makeSmearedConstant(zero, vectorSize); - return builder.createBinOp(spv::OpFOrdNotEqual, destType, operand, zero); - - case glslang::EOpConvDoubleToBool: - zero = builder.makeDoubleConstant(0.0); - zero = makeSmearedConstant(zero, vectorSize); - return builder.createBinOp(spv::OpFOrdNotEqual, destType, operand, zero); - - case glslang::EOpConvFloat16ToBool: - zero = builder.makeFloat16Constant(0.0F); - zero = makeSmearedConstant(zero, vectorSize); - return builder.createBinOp(spv::OpFOrdNotEqual, destType, operand, zero); - - case glslang::EOpConvBoolToFloat: - convOp = spv::OpSelect; - zero = builder.makeFloatConstant(0.0F); - one = builder.makeFloatConstant(1.0F); - break; - - case glslang::EOpConvBoolToDouble: - convOp = spv::OpSelect; - zero = builder.makeDoubleConstant(0.0); - one = builder.makeDoubleConstant(1.0); - break; - - case glslang::EOpConvBoolToFloat16: - convOp = spv::OpSelect; - zero = builder.makeFloat16Constant(0.0F); - one = builder.makeFloat16Constant(1.0F); - break; - - case glslang::EOpConvBoolToInt8: - zero = builder.makeInt8Constant(0); - one = builder.makeInt8Constant(1); - convOp = spv::OpSelect; - break; - - case glslang::EOpConvBoolToUint8: - zero = builder.makeUint8Constant(0); - one = builder.makeUint8Constant(1); - convOp = spv::OpSelect; - break; - - case glslang::EOpConvBoolToInt16: - zero = builder.makeInt16Constant(0); - one = builder.makeInt16Constant(1); - convOp = spv::OpSelect; - break; - - case glslang::EOpConvBoolToUint16: - zero = builder.makeUint16Constant(0); - one = builder.makeUint16Constant(1); - convOp = spv::OpSelect; - break; - - case glslang::EOpConvBoolToInt: - case glslang::EOpConvBoolToInt64: - if (op == glslang::EOpConvBoolToInt64) - zero = builder.makeInt64Constant(0); - else - zero = builder.makeIntConstant(0); - - if (op == glslang::EOpConvBoolToInt64) - one = builder.makeInt64Constant(1); - else - one = builder.makeIntConstant(1); - - convOp = spv::OpSelect; - break; - - case glslang::EOpConvBoolToUint: - case glslang::EOpConvBoolToUint64: - if (op == glslang::EOpConvBoolToUint64) - zero = builder.makeUint64Constant(0); - else - zero = builder.makeUintConstant(0); - - if (op == glslang::EOpConvBoolToUint64) - one = builder.makeUint64Constant(1); - else - one = builder.makeUintConstant(1); - - convOp = spv::OpSelect; - break; - - case glslang::EOpConvInt8ToFloat16: - case glslang::EOpConvInt8ToFloat: - case glslang::EOpConvInt8ToDouble: - case glslang::EOpConvInt16ToFloat16: - case glslang::EOpConvInt16ToFloat: - case glslang::EOpConvInt16ToDouble: - case glslang::EOpConvIntToFloat16: - case glslang::EOpConvIntToFloat: - case glslang::EOpConvIntToDouble: - case glslang::EOpConvInt64ToFloat: - case glslang::EOpConvInt64ToDouble: - case glslang::EOpConvInt64ToFloat16: - convOp = spv::OpConvertSToF; - break; - - case glslang::EOpConvUint8ToFloat16: - case glslang::EOpConvUint8ToFloat: - case glslang::EOpConvUint8ToDouble: - case glslang::EOpConvUint16ToFloat16: - case glslang::EOpConvUint16ToFloat: - case glslang::EOpConvUint16ToDouble: - case glslang::EOpConvUintToFloat16: - case glslang::EOpConvUintToFloat: - case glslang::EOpConvUintToDouble: - case glslang::EOpConvUint64ToFloat: - case glslang::EOpConvUint64ToDouble: - case glslang::EOpConvUint64ToFloat16: - convOp = spv::OpConvertUToF; - break; - - case glslang::EOpConvDoubleToFloat: - case glslang::EOpConvFloatToDouble: - case glslang::EOpConvDoubleToFloat16: - case glslang::EOpConvFloat16ToDouble: - case glslang::EOpConvFloatToFloat16: - case glslang::EOpConvFloat16ToFloat: - convOp = spv::OpFConvert; - if (builder.isMatrixType(destType)) - return createUnaryMatrixOperation(convOp, decorations, destType, operand, typeProxy); - break; - - case glslang::EOpConvFloat16ToInt8: - case glslang::EOpConvFloatToInt8: - case glslang::EOpConvDoubleToInt8: - case glslang::EOpConvFloat16ToInt16: - case glslang::EOpConvFloatToInt16: - case glslang::EOpConvDoubleToInt16: - case glslang::EOpConvFloat16ToInt: - case glslang::EOpConvFloatToInt: - case glslang::EOpConvDoubleToInt: - case glslang::EOpConvFloat16ToInt64: - case glslang::EOpConvFloatToInt64: - case glslang::EOpConvDoubleToInt64: - convOp = spv::OpConvertFToS; - break; - - case glslang::EOpConvUint8ToInt8: - case glslang::EOpConvInt8ToUint8: - case glslang::EOpConvUint16ToInt16: - case glslang::EOpConvInt16ToUint16: - case glslang::EOpConvUintToInt: - case glslang::EOpConvIntToUint: - case glslang::EOpConvUint64ToInt64: - case glslang::EOpConvInt64ToUint64: - if (builder.isInSpecConstCodeGenMode()) { - // Build zero scalar or vector for OpIAdd. - if(op == glslang::EOpConvUint8ToInt8 || op == glslang::EOpConvInt8ToUint8) { - zero = builder.makeUint8Constant(0); - } else if (op == glslang::EOpConvUint16ToInt16 || op == glslang::EOpConvInt16ToUint16) { - zero = builder.makeUint16Constant(0); - } else if (op == glslang::EOpConvUint64ToInt64 || op == glslang::EOpConvInt64ToUint64) { - zero = builder.makeUint64Constant(0); - } else { - zero = builder.makeUintConstant(0); - } - zero = makeSmearedConstant(zero, vectorSize); - // Use OpIAdd, instead of OpBitcast to do the conversion when - // generating for OpSpecConstantOp instruction. - return builder.createBinOp(spv::OpIAdd, destType, operand, zero); - } - // For normal run-time conversion instruction, use OpBitcast. - convOp = spv::OpBitcast; - break; - - case glslang::EOpConvFloat16ToUint8: - case glslang::EOpConvFloatToUint8: - case glslang::EOpConvDoubleToUint8: - case glslang::EOpConvFloat16ToUint16: - case glslang::EOpConvFloatToUint16: - case glslang::EOpConvDoubleToUint16: - case glslang::EOpConvFloat16ToUint: - case glslang::EOpConvFloatToUint: - case glslang::EOpConvDoubleToUint: - case glslang::EOpConvFloatToUint64: - case glslang::EOpConvDoubleToUint64: - case glslang::EOpConvFloat16ToUint64: - convOp = spv::OpConvertFToU; - break; - - case glslang::EOpConvInt8ToInt16: - case glslang::EOpConvInt8ToInt: - case glslang::EOpConvInt8ToInt64: - case glslang::EOpConvInt16ToInt8: - case glslang::EOpConvInt16ToInt: - case glslang::EOpConvInt16ToInt64: - case glslang::EOpConvIntToInt8: - case glslang::EOpConvIntToInt16: - case glslang::EOpConvIntToInt64: - case glslang::EOpConvInt64ToInt8: - case glslang::EOpConvInt64ToInt16: - case glslang::EOpConvInt64ToInt: - convOp = spv::OpSConvert; - break; - - case glslang::EOpConvUint8ToUint16: - case glslang::EOpConvUint8ToUint: - case glslang::EOpConvUint8ToUint64: - case glslang::EOpConvUint16ToUint8: - case glslang::EOpConvUint16ToUint: - case glslang::EOpConvUint16ToUint64: - case glslang::EOpConvUintToUint8: - case glslang::EOpConvUintToUint16: - case glslang::EOpConvUintToUint64: - case glslang::EOpConvUint64ToUint8: - case glslang::EOpConvUint64ToUint16: - case glslang::EOpConvUint64ToUint: - convOp = spv::OpUConvert; - break; - - case glslang::EOpConvInt8ToUint16: - case glslang::EOpConvInt8ToUint: - case glslang::EOpConvInt8ToUint64: - case glslang::EOpConvInt16ToUint8: - case glslang::EOpConvInt16ToUint: - case glslang::EOpConvInt16ToUint64: - case glslang::EOpConvIntToUint8: - case glslang::EOpConvIntToUint16: - case glslang::EOpConvIntToUint64: - case glslang::EOpConvInt64ToUint8: - case glslang::EOpConvInt64ToUint16: - case glslang::EOpConvInt64ToUint: - case glslang::EOpConvUint8ToInt16: - case glslang::EOpConvUint8ToInt: - case glslang::EOpConvUint8ToInt64: - case glslang::EOpConvUint16ToInt8: - case glslang::EOpConvUint16ToInt: - case glslang::EOpConvUint16ToInt64: - case glslang::EOpConvUintToInt8: - case glslang::EOpConvUintToInt16: - case glslang::EOpConvUintToInt64: - case glslang::EOpConvUint64ToInt8: - case glslang::EOpConvUint64ToInt16: - case glslang::EOpConvUint64ToInt: - // OpSConvert/OpUConvert + OpBitCast - operand = createConversionOperation(op, operand, vectorSize); - - if (builder.isInSpecConstCodeGenMode()) { - // Build zero scalar or vector for OpIAdd. - switch(op) { - case glslang::EOpConvInt16ToUint8: - case glslang::EOpConvIntToUint8: - case glslang::EOpConvInt64ToUint8: - case glslang::EOpConvUint16ToInt8: - case glslang::EOpConvUintToInt8: - case glslang::EOpConvUint64ToInt8: - zero = builder.makeUint8Constant(0); - break; - case glslang::EOpConvInt8ToUint16: - case glslang::EOpConvIntToUint16: - case glslang::EOpConvInt64ToUint16: - case glslang::EOpConvUint8ToInt16: - case glslang::EOpConvUintToInt16: - case glslang::EOpConvUint64ToInt16: - zero = builder.makeUint16Constant(0); - break; - case glslang::EOpConvInt8ToUint: - case glslang::EOpConvInt16ToUint: - case glslang::EOpConvInt64ToUint: - case glslang::EOpConvUint8ToInt: - case glslang::EOpConvUint16ToInt: - case glslang::EOpConvUint64ToInt: - zero = builder.makeUintConstant(0); - break; - case glslang::EOpConvInt8ToUint64: - case glslang::EOpConvInt16ToUint64: - case glslang::EOpConvIntToUint64: - case glslang::EOpConvUint8ToInt64: - case glslang::EOpConvUint16ToInt64: - case glslang::EOpConvUintToInt64: - zero = builder.makeUint64Constant(0); - break; - default: - assert(false && "Default missing"); - break; - } - zero = makeSmearedConstant(zero, vectorSize); - // Use OpIAdd, instead of OpBitcast to do the conversion when - // generating for OpSpecConstantOp instruction. - return builder.createBinOp(spv::OpIAdd, destType, operand, zero); - } - // For normal run-time conversion instruction, use OpBitcast. - convOp = spv::OpBitcast; - break; - default: - break; - } - - spv::Id result = 0; - if (convOp == spv::OpNop) - return result; - - if (convOp == spv::OpSelect) { - zero = makeSmearedConstant(zero, vectorSize); - one = makeSmearedConstant(one, vectorSize); - result = builder.createTriOp(convOp, destType, operand, one, zero); - } else - result = builder.createUnaryOp(convOp, destType, operand); - - result = builder.setPrecision(result, decorations.precision); - builder.addDecoration(result, decorations.nonUniform); - return result; -} - -spv::Id TGlslangToSpvTraverser::makeSmearedConstant(spv::Id constant, int vectorSize) -{ - if (vectorSize == 0) - return constant; - - spv::Id vectorTypeId = builder.makeVectorType(builder.getTypeId(constant), vectorSize); - std::vector components; - for (int c = 0; c < vectorSize; ++c) - components.push_back(constant); - return builder.makeCompositeConstant(vectorTypeId, components); -} - -// For glslang ops that map to SPV atomic opCodes -spv::Id TGlslangToSpvTraverser::createAtomicOperation(glslang::TOperator op, spv::Decoration /*precision*/, spv::Id typeId, std::vector& operands, glslang::TBasicType typeProxy) -{ - spv::Op opCode = spv::OpNop; - - switch (op) { - case glslang::EOpAtomicAdd: - case glslang::EOpImageAtomicAdd: - case glslang::EOpAtomicCounterAdd: - opCode = spv::OpAtomicIAdd; - break; - case glslang::EOpAtomicCounterSubtract: - opCode = spv::OpAtomicISub; - break; - case glslang::EOpAtomicMin: - case glslang::EOpImageAtomicMin: - case glslang::EOpAtomicCounterMin: - opCode = (typeProxy == glslang::EbtUint || typeProxy == glslang::EbtUint64) ? spv::OpAtomicUMin : spv::OpAtomicSMin; - break; - case glslang::EOpAtomicMax: - case glslang::EOpImageAtomicMax: - case glslang::EOpAtomicCounterMax: - opCode = (typeProxy == glslang::EbtUint || typeProxy == glslang::EbtUint64) ? spv::OpAtomicUMax : spv::OpAtomicSMax; - break; - case glslang::EOpAtomicAnd: - case glslang::EOpImageAtomicAnd: - case glslang::EOpAtomicCounterAnd: - opCode = spv::OpAtomicAnd; - break; - case glslang::EOpAtomicOr: - case glslang::EOpImageAtomicOr: - case glslang::EOpAtomicCounterOr: - opCode = spv::OpAtomicOr; - break; - case glslang::EOpAtomicXor: - case glslang::EOpImageAtomicXor: - case glslang::EOpAtomicCounterXor: - opCode = spv::OpAtomicXor; - break; - case glslang::EOpAtomicExchange: - case glslang::EOpImageAtomicExchange: - case glslang::EOpAtomicCounterExchange: - opCode = spv::OpAtomicExchange; - break; - case glslang::EOpAtomicCompSwap: - case glslang::EOpImageAtomicCompSwap: - case glslang::EOpAtomicCounterCompSwap: - opCode = spv::OpAtomicCompareExchange; - break; - case glslang::EOpAtomicCounterIncrement: - opCode = spv::OpAtomicIIncrement; - break; - case glslang::EOpAtomicCounterDecrement: - opCode = spv::OpAtomicIDecrement; - break; - case glslang::EOpAtomicCounter: - opCode = spv::OpAtomicLoad; - break; - default: - assert(0); - break; - } - - if (typeProxy == glslang::EbtInt64 || typeProxy == glslang::EbtUint64) - builder.addCapability(spv::CapabilityInt64Atomics); - - // Sort out the operands - // - mapping from glslang -> SPV - // - there are extra SPV operands with no glslang source - // - compare-exchange swaps the value and comparator - // - compare-exchange has an extra memory semantics - // - EOpAtomicCounterDecrement needs a post decrement - std::vector spvAtomicOperands; // hold the spv operands - auto opIt = operands.begin(); // walk the glslang operands - spvAtomicOperands.push_back(*(opIt++)); - spvAtomicOperands.push_back(builder.makeUintConstant(spv::ScopeDevice)); // TBD: what is the correct scope? - spvAtomicOperands.push_back(builder.makeUintConstant(spv::MemorySemanticsMaskNone)); // TBD: what are the correct memory semantics? - if (opCode == spv::OpAtomicCompareExchange) { - // There are 2 memory semantics for compare-exchange. And the operand order of "comparator" and "new value" in GLSL - // differs from that in SPIR-V. Hence, special processing is required. - spvAtomicOperands.push_back(builder.makeUintConstant(spv::MemorySemanticsMaskNone)); - spvAtomicOperands.push_back(*(opIt + 1)); - spvAtomicOperands.push_back(*opIt); - opIt += 2; - } - - // Add the rest of the operands, skipping any that were dealt with above. - for (; opIt != operands.end(); ++opIt) - spvAtomicOperands.push_back(*opIt); - - spv::Id resultId = builder.createOp(opCode, typeId, spvAtomicOperands); - - // GLSL and HLSL atomic-counter decrement return post-decrement value, - // while SPIR-V returns pre-decrement value. Translate between these semantics. - if (op == glslang::EOpAtomicCounterDecrement) - resultId = builder.createBinOp(spv::OpISub, typeId, resultId, builder.makeIntConstant(1)); - - return resultId; -} - -// Create group invocation operations. -spv::Id TGlslangToSpvTraverser::createInvocationsOperation(glslang::TOperator op, spv::Id typeId, std::vector& operands, glslang::TBasicType typeProxy) -{ - bool isUnsigned = isTypeUnsignedInt(typeProxy); - bool isFloat = isTypeFloat(typeProxy); - - spv::Op opCode = spv::OpNop; - std::vector spvGroupOperands; - spv::GroupOperation groupOperation = spv::GroupOperationMax; - - if (op == glslang::EOpBallot || op == glslang::EOpReadFirstInvocation || - op == glslang::EOpReadInvocation) { - builder.addExtension(spv::E_SPV_KHR_shader_ballot); - builder.addCapability(spv::CapabilitySubgroupBallotKHR); - } else if (op == glslang::EOpAnyInvocation || - op == glslang::EOpAllInvocations || - op == glslang::EOpAllInvocationsEqual) { - builder.addExtension(spv::E_SPV_KHR_subgroup_vote); - builder.addCapability(spv::CapabilitySubgroupVoteKHR); - } else { - builder.addCapability(spv::CapabilityGroups); -#ifdef AMD_EXTENSIONS - if (op == glslang::EOpMinInvocationsNonUniform || - op == glslang::EOpMaxInvocationsNonUniform || - op == glslang::EOpAddInvocationsNonUniform || - op == glslang::EOpMinInvocationsInclusiveScanNonUniform || - op == glslang::EOpMaxInvocationsInclusiveScanNonUniform || - op == glslang::EOpAddInvocationsInclusiveScanNonUniform || - op == glslang::EOpMinInvocationsExclusiveScanNonUniform || - op == glslang::EOpMaxInvocationsExclusiveScanNonUniform || - op == glslang::EOpAddInvocationsExclusiveScanNonUniform) - builder.addExtension(spv::E_SPV_AMD_shader_ballot); -#endif - - spvGroupOperands.push_back(builder.makeUintConstant(spv::ScopeSubgroup)); -#ifdef AMD_EXTENSIONS - switch (op) { - case glslang::EOpMinInvocations: - case glslang::EOpMaxInvocations: - case glslang::EOpAddInvocations: - case glslang::EOpMinInvocationsNonUniform: - case glslang::EOpMaxInvocationsNonUniform: - case glslang::EOpAddInvocationsNonUniform: - groupOperation = spv::GroupOperationReduce; - spvGroupOperands.push_back(groupOperation); - break; - case glslang::EOpMinInvocationsInclusiveScan: - case glslang::EOpMaxInvocationsInclusiveScan: - case glslang::EOpAddInvocationsInclusiveScan: - case glslang::EOpMinInvocationsInclusiveScanNonUniform: - case glslang::EOpMaxInvocationsInclusiveScanNonUniform: - case glslang::EOpAddInvocationsInclusiveScanNonUniform: - groupOperation = spv::GroupOperationInclusiveScan; - spvGroupOperands.push_back(groupOperation); - break; - case glslang::EOpMinInvocationsExclusiveScan: - case glslang::EOpMaxInvocationsExclusiveScan: - case glslang::EOpAddInvocationsExclusiveScan: - case glslang::EOpMinInvocationsExclusiveScanNonUniform: - case glslang::EOpMaxInvocationsExclusiveScanNonUniform: - case glslang::EOpAddInvocationsExclusiveScanNonUniform: - groupOperation = spv::GroupOperationExclusiveScan; - spvGroupOperands.push_back(groupOperation); - break; - default: - break; - } -#endif - } - - for (auto opIt = operands.begin(); opIt != operands.end(); ++opIt) - spvGroupOperands.push_back(*opIt); - - switch (op) { - case glslang::EOpAnyInvocation: - opCode = spv::OpSubgroupAnyKHR; - break; - case glslang::EOpAllInvocations: - opCode = spv::OpSubgroupAllKHR; - break; - case glslang::EOpAllInvocationsEqual: - opCode = spv::OpSubgroupAllEqualKHR; - break; - case glslang::EOpReadInvocation: - opCode = spv::OpSubgroupReadInvocationKHR; - if (builder.isVectorType(typeId)) - return CreateInvocationsVectorOperation(opCode, groupOperation, typeId, operands); - break; - case glslang::EOpReadFirstInvocation: - opCode = spv::OpSubgroupFirstInvocationKHR; - break; - case glslang::EOpBallot: - { - // NOTE: According to the spec, the result type of "OpSubgroupBallotKHR" must be a 4 component vector of 32 - // bit integer types. The GLSL built-in function "ballotARB()" assumes the maximum number of invocations in - // a subgroup is 64. Thus, we have to convert uvec4.xy to uint64_t as follow: - // - // result = Bitcast(SubgroupBallotKHR(Predicate).xy) - // - spv::Id uintType = builder.makeUintType(32); - spv::Id uvec4Type = builder.makeVectorType(uintType, 4); - spv::Id result = builder.createOp(spv::OpSubgroupBallotKHR, uvec4Type, spvGroupOperands); - - std::vector components; - components.push_back(builder.createCompositeExtract(result, uintType, 0)); - components.push_back(builder.createCompositeExtract(result, uintType, 1)); - - spv::Id uvec2Type = builder.makeVectorType(uintType, 2); - return builder.createUnaryOp(spv::OpBitcast, typeId, - builder.createCompositeConstruct(uvec2Type, components)); - } - -#ifdef AMD_EXTENSIONS - case glslang::EOpMinInvocations: - case glslang::EOpMaxInvocations: - case glslang::EOpAddInvocations: - case glslang::EOpMinInvocationsInclusiveScan: - case glslang::EOpMaxInvocationsInclusiveScan: - case glslang::EOpAddInvocationsInclusiveScan: - case glslang::EOpMinInvocationsExclusiveScan: - case glslang::EOpMaxInvocationsExclusiveScan: - case glslang::EOpAddInvocationsExclusiveScan: - if (op == glslang::EOpMinInvocations || - op == glslang::EOpMinInvocationsInclusiveScan || - op == glslang::EOpMinInvocationsExclusiveScan) { - if (isFloat) - opCode = spv::OpGroupFMin; - else { - if (isUnsigned) - opCode = spv::OpGroupUMin; - else - opCode = spv::OpGroupSMin; - } - } else if (op == glslang::EOpMaxInvocations || - op == glslang::EOpMaxInvocationsInclusiveScan || - op == glslang::EOpMaxInvocationsExclusiveScan) { - if (isFloat) - opCode = spv::OpGroupFMax; - else { - if (isUnsigned) - opCode = spv::OpGroupUMax; - else - opCode = spv::OpGroupSMax; - } - } else { - if (isFloat) - opCode = spv::OpGroupFAdd; - else - opCode = spv::OpGroupIAdd; - } - - if (builder.isVectorType(typeId)) - return CreateInvocationsVectorOperation(opCode, groupOperation, typeId, operands); - - break; - case glslang::EOpMinInvocationsNonUniform: - case glslang::EOpMaxInvocationsNonUniform: - case glslang::EOpAddInvocationsNonUniform: - case glslang::EOpMinInvocationsInclusiveScanNonUniform: - case glslang::EOpMaxInvocationsInclusiveScanNonUniform: - case glslang::EOpAddInvocationsInclusiveScanNonUniform: - case glslang::EOpMinInvocationsExclusiveScanNonUniform: - case glslang::EOpMaxInvocationsExclusiveScanNonUniform: - case glslang::EOpAddInvocationsExclusiveScanNonUniform: - if (op == glslang::EOpMinInvocationsNonUniform || - op == glslang::EOpMinInvocationsInclusiveScanNonUniform || - op == glslang::EOpMinInvocationsExclusiveScanNonUniform) { - if (isFloat) - opCode = spv::OpGroupFMinNonUniformAMD; - else { - if (isUnsigned) - opCode = spv::OpGroupUMinNonUniformAMD; - else - opCode = spv::OpGroupSMinNonUniformAMD; - } - } - else if (op == glslang::EOpMaxInvocationsNonUniform || - op == glslang::EOpMaxInvocationsInclusiveScanNonUniform || - op == glslang::EOpMaxInvocationsExclusiveScanNonUniform) { - if (isFloat) - opCode = spv::OpGroupFMaxNonUniformAMD; - else { - if (isUnsigned) - opCode = spv::OpGroupUMaxNonUniformAMD; - else - opCode = spv::OpGroupSMaxNonUniformAMD; - } - } - else { - if (isFloat) - opCode = spv::OpGroupFAddNonUniformAMD; - else - opCode = spv::OpGroupIAddNonUniformAMD; - } - - if (builder.isVectorType(typeId)) - return CreateInvocationsVectorOperation(opCode, groupOperation, typeId, operands); - - break; -#endif - default: - logger->missingFunctionality("invocation operation"); - return spv::NoResult; - } - - assert(opCode != spv::OpNop); - return builder.createOp(opCode, typeId, spvGroupOperands); -} - -// Create group invocation operations on a vector -spv::Id TGlslangToSpvTraverser::CreateInvocationsVectorOperation(spv::Op op, spv::GroupOperation groupOperation, spv::Id typeId, std::vector& operands) -{ -#ifdef AMD_EXTENSIONS - assert(op == spv::OpGroupFMin || op == spv::OpGroupUMin || op == spv::OpGroupSMin || - op == spv::OpGroupFMax || op == spv::OpGroupUMax || op == spv::OpGroupSMax || - op == spv::OpGroupFAdd || op == spv::OpGroupIAdd || op == spv::OpGroupBroadcast || - op == spv::OpSubgroupReadInvocationKHR || - op == spv::OpGroupFMinNonUniformAMD || op == spv::OpGroupUMinNonUniformAMD || op == spv::OpGroupSMinNonUniformAMD || - op == spv::OpGroupFMaxNonUniformAMD || op == spv::OpGroupUMaxNonUniformAMD || op == spv::OpGroupSMaxNonUniformAMD || - op == spv::OpGroupFAddNonUniformAMD || op == spv::OpGroupIAddNonUniformAMD); -#else - assert(op == spv::OpGroupFMin || op == spv::OpGroupUMin || op == spv::OpGroupSMin || - op == spv::OpGroupFMax || op == spv::OpGroupUMax || op == spv::OpGroupSMax || - op == spv::OpGroupFAdd || op == spv::OpGroupIAdd || op == spv::OpGroupBroadcast || - op == spv::OpSubgroupReadInvocationKHR); -#endif - - // Handle group invocation operations scalar by scalar. - // The result type is the same type as the original type. - // The algorithm is to: - // - break the vector into scalars - // - apply the operation to each scalar - // - make a vector out the scalar results - - // get the types sorted out - int numComponents = builder.getNumComponents(operands[0]); - spv::Id scalarType = builder.getScalarTypeId(builder.getTypeId(operands[0])); - std::vector results; - - // do each scalar op - for (int comp = 0; comp < numComponents; ++comp) { - std::vector indexes; - indexes.push_back(comp); - spv::Id scalar = builder.createCompositeExtract(operands[0], scalarType, indexes); - std::vector spvGroupOperands; - if (op == spv::OpSubgroupReadInvocationKHR) { - spvGroupOperands.push_back(scalar); - spvGroupOperands.push_back(operands[1]); - } else if (op == spv::OpGroupBroadcast) { - spvGroupOperands.push_back(builder.makeUintConstant(spv::ScopeSubgroup)); - spvGroupOperands.push_back(scalar); - spvGroupOperands.push_back(operands[1]); - } else { - spvGroupOperands.push_back(builder.makeUintConstant(spv::ScopeSubgroup)); - spvGroupOperands.push_back(groupOperation); - spvGroupOperands.push_back(scalar); - } - - results.push_back(builder.createOp(op, scalarType, spvGroupOperands)); - } - - // put the pieces together - return builder.createCompositeConstruct(typeId, results); -} - -// Create subgroup invocation operations. -spv::Id TGlslangToSpvTraverser::createSubgroupOperation(glslang::TOperator op, spv::Id typeId, std::vector& operands, glslang::TBasicType typeProxy) -{ - // Add the required capabilities. - switch (op) { - case glslang::EOpSubgroupElect: - builder.addCapability(spv::CapabilityGroupNonUniform); - break; - case glslang::EOpSubgroupAll: - case glslang::EOpSubgroupAny: - case glslang::EOpSubgroupAllEqual: - builder.addCapability(spv::CapabilityGroupNonUniform); - builder.addCapability(spv::CapabilityGroupNonUniformVote); - break; - case glslang::EOpSubgroupBroadcast: - case glslang::EOpSubgroupBroadcastFirst: - case glslang::EOpSubgroupBallot: - case glslang::EOpSubgroupInverseBallot: - case glslang::EOpSubgroupBallotBitExtract: - case glslang::EOpSubgroupBallotBitCount: - case glslang::EOpSubgroupBallotInclusiveBitCount: - case glslang::EOpSubgroupBallotExclusiveBitCount: - case glslang::EOpSubgroupBallotFindLSB: - case glslang::EOpSubgroupBallotFindMSB: - builder.addCapability(spv::CapabilityGroupNonUniform); - builder.addCapability(spv::CapabilityGroupNonUniformBallot); - break; - case glslang::EOpSubgroupShuffle: - case glslang::EOpSubgroupShuffleXor: - builder.addCapability(spv::CapabilityGroupNonUniform); - builder.addCapability(spv::CapabilityGroupNonUniformShuffle); - break; - case glslang::EOpSubgroupShuffleUp: - case glslang::EOpSubgroupShuffleDown: - builder.addCapability(spv::CapabilityGroupNonUniform); - builder.addCapability(spv::CapabilityGroupNonUniformShuffleRelative); - break; - case glslang::EOpSubgroupAdd: - case glslang::EOpSubgroupMul: - case glslang::EOpSubgroupMin: - case glslang::EOpSubgroupMax: - case glslang::EOpSubgroupAnd: - case glslang::EOpSubgroupOr: - case glslang::EOpSubgroupXor: - case glslang::EOpSubgroupInclusiveAdd: - case glslang::EOpSubgroupInclusiveMul: - case glslang::EOpSubgroupInclusiveMin: - case glslang::EOpSubgroupInclusiveMax: - case glslang::EOpSubgroupInclusiveAnd: - case glslang::EOpSubgroupInclusiveOr: - case glslang::EOpSubgroupInclusiveXor: - case glslang::EOpSubgroupExclusiveAdd: - case glslang::EOpSubgroupExclusiveMul: - case glslang::EOpSubgroupExclusiveMin: - case glslang::EOpSubgroupExclusiveMax: - case glslang::EOpSubgroupExclusiveAnd: - case glslang::EOpSubgroupExclusiveOr: - case glslang::EOpSubgroupExclusiveXor: - builder.addCapability(spv::CapabilityGroupNonUniform); - builder.addCapability(spv::CapabilityGroupNonUniformArithmetic); - break; - case glslang::EOpSubgroupClusteredAdd: - case glslang::EOpSubgroupClusteredMul: - case glslang::EOpSubgroupClusteredMin: - case glslang::EOpSubgroupClusteredMax: - case glslang::EOpSubgroupClusteredAnd: - case glslang::EOpSubgroupClusteredOr: - case glslang::EOpSubgroupClusteredXor: - builder.addCapability(spv::CapabilityGroupNonUniform); - builder.addCapability(spv::CapabilityGroupNonUniformClustered); - break; - case glslang::EOpSubgroupQuadBroadcast: - case glslang::EOpSubgroupQuadSwapHorizontal: - case glslang::EOpSubgroupQuadSwapVertical: - case glslang::EOpSubgroupQuadSwapDiagonal: - builder.addCapability(spv::CapabilityGroupNonUniform); - builder.addCapability(spv::CapabilityGroupNonUniformQuad); - break; -#ifdef NV_EXTENSIONS - case glslang::EOpSubgroupPartitionedAdd: - case glslang::EOpSubgroupPartitionedMul: - case glslang::EOpSubgroupPartitionedMin: - case glslang::EOpSubgroupPartitionedMax: - case glslang::EOpSubgroupPartitionedAnd: - case glslang::EOpSubgroupPartitionedOr: - case glslang::EOpSubgroupPartitionedXor: - case glslang::EOpSubgroupPartitionedInclusiveAdd: - case glslang::EOpSubgroupPartitionedInclusiveMul: - case glslang::EOpSubgroupPartitionedInclusiveMin: - case glslang::EOpSubgroupPartitionedInclusiveMax: - case glslang::EOpSubgroupPartitionedInclusiveAnd: - case glslang::EOpSubgroupPartitionedInclusiveOr: - case glslang::EOpSubgroupPartitionedInclusiveXor: - case glslang::EOpSubgroupPartitionedExclusiveAdd: - case glslang::EOpSubgroupPartitionedExclusiveMul: - case glslang::EOpSubgroupPartitionedExclusiveMin: - case glslang::EOpSubgroupPartitionedExclusiveMax: - case glslang::EOpSubgroupPartitionedExclusiveAnd: - case glslang::EOpSubgroupPartitionedExclusiveOr: - case glslang::EOpSubgroupPartitionedExclusiveXor: - builder.addExtension(spv::E_SPV_NV_shader_subgroup_partitioned); - builder.addCapability(spv::CapabilityGroupNonUniformPartitionedNV); - break; -#endif - default: assert(0 && "Unhandled subgroup operation!"); - } - - const bool isUnsigned = typeProxy == glslang::EbtUint || typeProxy == glslang::EbtUint64; - const bool isFloat = typeProxy == glslang::EbtFloat || typeProxy == glslang::EbtDouble; - const bool isBool = typeProxy == glslang::EbtBool; - - spv::Op opCode = spv::OpNop; - - // Figure out which opcode to use. - switch (op) { - case glslang::EOpSubgroupElect: opCode = spv::OpGroupNonUniformElect; break; - case glslang::EOpSubgroupAll: opCode = spv::OpGroupNonUniformAll; break; - case glslang::EOpSubgroupAny: opCode = spv::OpGroupNonUniformAny; break; - case glslang::EOpSubgroupAllEqual: opCode = spv::OpGroupNonUniformAllEqual; break; - case glslang::EOpSubgroupBroadcast: opCode = spv::OpGroupNonUniformBroadcast; break; - case glslang::EOpSubgroupBroadcastFirst: opCode = spv::OpGroupNonUniformBroadcastFirst; break; - case glslang::EOpSubgroupBallot: opCode = spv::OpGroupNonUniformBallot; break; - case glslang::EOpSubgroupInverseBallot: opCode = spv::OpGroupNonUniformInverseBallot; break; - case glslang::EOpSubgroupBallotBitExtract: opCode = spv::OpGroupNonUniformBallotBitExtract; break; - case glslang::EOpSubgroupBallotBitCount: - case glslang::EOpSubgroupBallotInclusiveBitCount: - case glslang::EOpSubgroupBallotExclusiveBitCount: opCode = spv::OpGroupNonUniformBallotBitCount; break; - case glslang::EOpSubgroupBallotFindLSB: opCode = spv::OpGroupNonUniformBallotFindLSB; break; - case glslang::EOpSubgroupBallotFindMSB: opCode = spv::OpGroupNonUniformBallotFindMSB; break; - case glslang::EOpSubgroupShuffle: opCode = spv::OpGroupNonUniformShuffle; break; - case glslang::EOpSubgroupShuffleXor: opCode = spv::OpGroupNonUniformShuffleXor; break; - case glslang::EOpSubgroupShuffleUp: opCode = spv::OpGroupNonUniformShuffleUp; break; - case glslang::EOpSubgroupShuffleDown: opCode = spv::OpGroupNonUniformShuffleDown; break; - case glslang::EOpSubgroupAdd: - case glslang::EOpSubgroupInclusiveAdd: - case glslang::EOpSubgroupExclusiveAdd: - case glslang::EOpSubgroupClusteredAdd: -#ifdef NV_EXTENSIONS - case glslang::EOpSubgroupPartitionedAdd: - case glslang::EOpSubgroupPartitionedInclusiveAdd: - case glslang::EOpSubgroupPartitionedExclusiveAdd: -#endif - if (isFloat) { - opCode = spv::OpGroupNonUniformFAdd; - } else { - opCode = spv::OpGroupNonUniformIAdd; - } - break; - case glslang::EOpSubgroupMul: - case glslang::EOpSubgroupInclusiveMul: - case glslang::EOpSubgroupExclusiveMul: - case glslang::EOpSubgroupClusteredMul: -#ifdef NV_EXTENSIONS - case glslang::EOpSubgroupPartitionedMul: - case glslang::EOpSubgroupPartitionedInclusiveMul: - case glslang::EOpSubgroupPartitionedExclusiveMul: -#endif - if (isFloat) { - opCode = spv::OpGroupNonUniformFMul; - } else { - opCode = spv::OpGroupNonUniformIMul; - } - break; - case glslang::EOpSubgroupMin: - case glslang::EOpSubgroupInclusiveMin: - case glslang::EOpSubgroupExclusiveMin: - case glslang::EOpSubgroupClusteredMin: -#ifdef NV_EXTENSIONS - case glslang::EOpSubgroupPartitionedMin: - case glslang::EOpSubgroupPartitionedInclusiveMin: - case glslang::EOpSubgroupPartitionedExclusiveMin: -#endif - if (isFloat) { - opCode = spv::OpGroupNonUniformFMin; - } else if (isUnsigned) { - opCode = spv::OpGroupNonUniformUMin; - } else { - opCode = spv::OpGroupNonUniformSMin; - } - break; - case glslang::EOpSubgroupMax: - case glslang::EOpSubgroupInclusiveMax: - case glslang::EOpSubgroupExclusiveMax: - case glslang::EOpSubgroupClusteredMax: -#ifdef NV_EXTENSIONS - case glslang::EOpSubgroupPartitionedMax: - case glslang::EOpSubgroupPartitionedInclusiveMax: - case glslang::EOpSubgroupPartitionedExclusiveMax: -#endif - if (isFloat) { - opCode = spv::OpGroupNonUniformFMax; - } else if (isUnsigned) { - opCode = spv::OpGroupNonUniformUMax; - } else { - opCode = spv::OpGroupNonUniformSMax; - } - break; - case glslang::EOpSubgroupAnd: - case glslang::EOpSubgroupInclusiveAnd: - case glslang::EOpSubgroupExclusiveAnd: - case glslang::EOpSubgroupClusteredAnd: -#ifdef NV_EXTENSIONS - case glslang::EOpSubgroupPartitionedAnd: - case glslang::EOpSubgroupPartitionedInclusiveAnd: - case glslang::EOpSubgroupPartitionedExclusiveAnd: -#endif - if (isBool) { - opCode = spv::OpGroupNonUniformLogicalAnd; - } else { - opCode = spv::OpGroupNonUniformBitwiseAnd; - } - break; - case glslang::EOpSubgroupOr: - case glslang::EOpSubgroupInclusiveOr: - case glslang::EOpSubgroupExclusiveOr: - case glslang::EOpSubgroupClusteredOr: -#ifdef NV_EXTENSIONS - case glslang::EOpSubgroupPartitionedOr: - case glslang::EOpSubgroupPartitionedInclusiveOr: - case glslang::EOpSubgroupPartitionedExclusiveOr: -#endif - if (isBool) { - opCode = spv::OpGroupNonUniformLogicalOr; - } else { - opCode = spv::OpGroupNonUniformBitwiseOr; - } - break; - case glslang::EOpSubgroupXor: - case glslang::EOpSubgroupInclusiveXor: - case glslang::EOpSubgroupExclusiveXor: - case glslang::EOpSubgroupClusteredXor: -#ifdef NV_EXTENSIONS - case glslang::EOpSubgroupPartitionedXor: - case glslang::EOpSubgroupPartitionedInclusiveXor: - case glslang::EOpSubgroupPartitionedExclusiveXor: -#endif - if (isBool) { - opCode = spv::OpGroupNonUniformLogicalXor; - } else { - opCode = spv::OpGroupNonUniformBitwiseXor; - } - break; - case glslang::EOpSubgroupQuadBroadcast: opCode = spv::OpGroupNonUniformQuadBroadcast; break; - case glslang::EOpSubgroupQuadSwapHorizontal: - case glslang::EOpSubgroupQuadSwapVertical: - case glslang::EOpSubgroupQuadSwapDiagonal: opCode = spv::OpGroupNonUniformQuadSwap; break; - default: assert(0 && "Unhandled subgroup operation!"); - } - - std::vector spvGroupOperands; - - // Every operation begins with the Execution Scope operand. - spvGroupOperands.push_back(builder.makeUintConstant(spv::ScopeSubgroup)); - - // Next, for all operations that use a Group Operation, push that as an operand. - switch (op) { - default: break; - case glslang::EOpSubgroupBallotBitCount: - case glslang::EOpSubgroupAdd: - case glslang::EOpSubgroupMul: - case glslang::EOpSubgroupMin: - case glslang::EOpSubgroupMax: - case glslang::EOpSubgroupAnd: - case glslang::EOpSubgroupOr: - case glslang::EOpSubgroupXor: - spvGroupOperands.push_back(spv::GroupOperationReduce); - break; - case glslang::EOpSubgroupBallotInclusiveBitCount: - case glslang::EOpSubgroupInclusiveAdd: - case glslang::EOpSubgroupInclusiveMul: - case glslang::EOpSubgroupInclusiveMin: - case glslang::EOpSubgroupInclusiveMax: - case glslang::EOpSubgroupInclusiveAnd: - case glslang::EOpSubgroupInclusiveOr: - case glslang::EOpSubgroupInclusiveXor: - spvGroupOperands.push_back(spv::GroupOperationInclusiveScan); - break; - case glslang::EOpSubgroupBallotExclusiveBitCount: - case glslang::EOpSubgroupExclusiveAdd: - case glslang::EOpSubgroupExclusiveMul: - case glslang::EOpSubgroupExclusiveMin: - case glslang::EOpSubgroupExclusiveMax: - case glslang::EOpSubgroupExclusiveAnd: - case glslang::EOpSubgroupExclusiveOr: - case glslang::EOpSubgroupExclusiveXor: - spvGroupOperands.push_back(spv::GroupOperationExclusiveScan); - break; - case glslang::EOpSubgroupClusteredAdd: - case glslang::EOpSubgroupClusteredMul: - case glslang::EOpSubgroupClusteredMin: - case glslang::EOpSubgroupClusteredMax: - case glslang::EOpSubgroupClusteredAnd: - case glslang::EOpSubgroupClusteredOr: - case glslang::EOpSubgroupClusteredXor: - spvGroupOperands.push_back(spv::GroupOperationClusteredReduce); - break; -#ifdef NV_EXTENSIONS - case glslang::EOpSubgroupPartitionedAdd: - case glslang::EOpSubgroupPartitionedMul: - case glslang::EOpSubgroupPartitionedMin: - case glslang::EOpSubgroupPartitionedMax: - case glslang::EOpSubgroupPartitionedAnd: - case glslang::EOpSubgroupPartitionedOr: - case glslang::EOpSubgroupPartitionedXor: - spvGroupOperands.push_back(spv::GroupOperationPartitionedReduceNV); - break; - case glslang::EOpSubgroupPartitionedInclusiveAdd: - case glslang::EOpSubgroupPartitionedInclusiveMul: - case glslang::EOpSubgroupPartitionedInclusiveMin: - case glslang::EOpSubgroupPartitionedInclusiveMax: - case glslang::EOpSubgroupPartitionedInclusiveAnd: - case glslang::EOpSubgroupPartitionedInclusiveOr: - case glslang::EOpSubgroupPartitionedInclusiveXor: - spvGroupOperands.push_back(spv::GroupOperationPartitionedInclusiveScanNV); - break; - case glslang::EOpSubgroupPartitionedExclusiveAdd: - case glslang::EOpSubgroupPartitionedExclusiveMul: - case glslang::EOpSubgroupPartitionedExclusiveMin: - case glslang::EOpSubgroupPartitionedExclusiveMax: - case glslang::EOpSubgroupPartitionedExclusiveAnd: - case glslang::EOpSubgroupPartitionedExclusiveOr: - case glslang::EOpSubgroupPartitionedExclusiveXor: - spvGroupOperands.push_back(spv::GroupOperationPartitionedExclusiveScanNV); - break; -#endif - } - - // Push back the operands next. - for (auto opIt : operands) { - spvGroupOperands.push_back(opIt); - } - - // Some opcodes have additional operands. - switch (op) { - default: break; - case glslang::EOpSubgroupQuadSwapHorizontal: spvGroupOperands.push_back(builder.makeUintConstant(0)); break; - case glslang::EOpSubgroupQuadSwapVertical: spvGroupOperands.push_back(builder.makeUintConstant(1)); break; - case glslang::EOpSubgroupQuadSwapDiagonal: spvGroupOperands.push_back(builder.makeUintConstant(2)); break; - } - - return builder.createOp(opCode, typeId, spvGroupOperands); -} - -spv::Id TGlslangToSpvTraverser::createMiscOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId, std::vector& operands, glslang::TBasicType typeProxy) -{ - bool isUnsigned = isTypeUnsignedInt(typeProxy); - bool isFloat = isTypeFloat(typeProxy); - - spv::Op opCode = spv::OpNop; - int extBuiltins = -1; - int libCall = -1; - size_t consumedOperands = operands.size(); - spv::Id typeId0 = 0; - if (consumedOperands > 0) - typeId0 = builder.getTypeId(operands[0]); - spv::Id typeId1 = 0; - if (consumedOperands > 1) - typeId1 = builder.getTypeId(operands[1]); - spv::Id frexpIntType = 0; - - switch (op) { - case glslang::EOpMin: - if (isFloat) - libCall = spv::GLSLstd450FMin; - else if (isUnsigned) - libCall = spv::GLSLstd450UMin; - else - libCall = spv::GLSLstd450SMin; - builder.promoteScalar(precision, operands.front(), operands.back()); - break; - case glslang::EOpModf: - libCall = spv::GLSLstd450Modf; - break; - case glslang::EOpMax: - if (isFloat) - libCall = spv::GLSLstd450FMax; - else if (isUnsigned) - libCall = spv::GLSLstd450UMax; - else - libCall = spv::GLSLstd450SMax; - builder.promoteScalar(precision, operands.front(), operands.back()); - break; - case glslang::EOpPow: - libCall = spv::GLSLstd450Pow; - break; - case glslang::EOpDot: - opCode = spv::OpDot; - break; - case glslang::EOpAtan: - libCall = spv::GLSLstd450Atan2; - break; - - case glslang::EOpClamp: - if (isFloat) - libCall = spv::GLSLstd450FClamp; - else if (isUnsigned) - libCall = spv::GLSLstd450UClamp; - else - libCall = spv::GLSLstd450SClamp; - builder.promoteScalar(precision, operands.front(), operands[1]); - builder.promoteScalar(precision, operands.front(), operands[2]); - break; - case glslang::EOpMix: - if (! builder.isBoolType(builder.getScalarTypeId(builder.getTypeId(operands.back())))) { - assert(isFloat); - libCall = spv::GLSLstd450FMix; - } else { - opCode = spv::OpSelect; - std::swap(operands.front(), operands.back()); - } - builder.promoteScalar(precision, operands.front(), operands.back()); - break; - case glslang::EOpStep: - libCall = spv::GLSLstd450Step; - builder.promoteScalar(precision, operands.front(), operands.back()); - break; - case glslang::EOpSmoothStep: - libCall = spv::GLSLstd450SmoothStep; - builder.promoteScalar(precision, operands[0], operands[2]); - builder.promoteScalar(precision, operands[1], operands[2]); - break; - - case glslang::EOpDistance: - libCall = spv::GLSLstd450Distance; - break; - case glslang::EOpCross: - libCall = spv::GLSLstd450Cross; - break; - case glslang::EOpFaceForward: - libCall = spv::GLSLstd450FaceForward; - break; - case glslang::EOpReflect: - libCall = spv::GLSLstd450Reflect; - break; - case glslang::EOpRefract: - libCall = spv::GLSLstd450Refract; - break; - case glslang::EOpInterpolateAtSample: - builder.addCapability(spv::CapabilityInterpolationFunction); - libCall = spv::GLSLstd450InterpolateAtSample; - break; - case glslang::EOpInterpolateAtOffset: - builder.addCapability(spv::CapabilityInterpolationFunction); - libCall = spv::GLSLstd450InterpolateAtOffset; - break; - case glslang::EOpAddCarry: - opCode = spv::OpIAddCarry; - typeId = builder.makeStructResultType(typeId0, typeId0); - consumedOperands = 2; - break; - case glslang::EOpSubBorrow: - opCode = spv::OpISubBorrow; - typeId = builder.makeStructResultType(typeId0, typeId0); - consumedOperands = 2; - break; - case glslang::EOpUMulExtended: - opCode = spv::OpUMulExtended; - typeId = builder.makeStructResultType(typeId0, typeId0); - consumedOperands = 2; - break; - case glslang::EOpIMulExtended: - opCode = spv::OpSMulExtended; - typeId = builder.makeStructResultType(typeId0, typeId0); - consumedOperands = 2; - break; - case glslang::EOpBitfieldExtract: - if (isUnsigned) - opCode = spv::OpBitFieldUExtract; - else - opCode = spv::OpBitFieldSExtract; - break; - case glslang::EOpBitfieldInsert: - opCode = spv::OpBitFieldInsert; - break; - - case glslang::EOpFma: - libCall = spv::GLSLstd450Fma; - break; - case glslang::EOpFrexp: - { - libCall = spv::GLSLstd450FrexpStruct; - assert(builder.isPointerType(typeId1)); - typeId1 = builder.getContainedTypeId(typeId1); - int width = builder.getScalarTypeWidth(typeId1); - if (builder.getNumComponents(operands[0]) == 1) - frexpIntType = builder.makeIntegerType(width, true); - else - frexpIntType = builder.makeVectorType(builder.makeIntegerType(width, true), builder.getNumComponents(operands[0])); - typeId = builder.makeStructResultType(typeId0, frexpIntType); - consumedOperands = 1; - } - break; - case glslang::EOpLdexp: - libCall = spv::GLSLstd450Ldexp; - break; - - case glslang::EOpReadInvocation: - return createInvocationsOperation(op, typeId, operands, typeProxy); - - case glslang::EOpSubgroupBroadcast: - case glslang::EOpSubgroupBallotBitExtract: - case glslang::EOpSubgroupShuffle: - case glslang::EOpSubgroupShuffleXor: - case glslang::EOpSubgroupShuffleUp: - case glslang::EOpSubgroupShuffleDown: - case glslang::EOpSubgroupClusteredAdd: - case glslang::EOpSubgroupClusteredMul: - case glslang::EOpSubgroupClusteredMin: - case glslang::EOpSubgroupClusteredMax: - case glslang::EOpSubgroupClusteredAnd: - case glslang::EOpSubgroupClusteredOr: - case glslang::EOpSubgroupClusteredXor: - case glslang::EOpSubgroupQuadBroadcast: -#ifdef NV_EXTENSIONS - case glslang::EOpSubgroupPartitionedAdd: - case glslang::EOpSubgroupPartitionedMul: - case glslang::EOpSubgroupPartitionedMin: - case glslang::EOpSubgroupPartitionedMax: - case glslang::EOpSubgroupPartitionedAnd: - case glslang::EOpSubgroupPartitionedOr: - case glslang::EOpSubgroupPartitionedXor: - case glslang::EOpSubgroupPartitionedInclusiveAdd: - case glslang::EOpSubgroupPartitionedInclusiveMul: - case glslang::EOpSubgroupPartitionedInclusiveMin: - case glslang::EOpSubgroupPartitionedInclusiveMax: - case glslang::EOpSubgroupPartitionedInclusiveAnd: - case glslang::EOpSubgroupPartitionedInclusiveOr: - case glslang::EOpSubgroupPartitionedInclusiveXor: - case glslang::EOpSubgroupPartitionedExclusiveAdd: - case glslang::EOpSubgroupPartitionedExclusiveMul: - case glslang::EOpSubgroupPartitionedExclusiveMin: - case glslang::EOpSubgroupPartitionedExclusiveMax: - case glslang::EOpSubgroupPartitionedExclusiveAnd: - case glslang::EOpSubgroupPartitionedExclusiveOr: - case glslang::EOpSubgroupPartitionedExclusiveXor: -#endif - return createSubgroupOperation(op, typeId, operands, typeProxy); - -#ifdef AMD_EXTENSIONS - case glslang::EOpSwizzleInvocations: - extBuiltins = getExtBuiltins(spv::E_SPV_AMD_shader_ballot); - libCall = spv::SwizzleInvocationsAMD; - break; - case glslang::EOpSwizzleInvocationsMasked: - extBuiltins = getExtBuiltins(spv::E_SPV_AMD_shader_ballot); - libCall = spv::SwizzleInvocationsMaskedAMD; - break; - case glslang::EOpWriteInvocation: - extBuiltins = getExtBuiltins(spv::E_SPV_AMD_shader_ballot); - libCall = spv::WriteInvocationAMD; - break; - - case glslang::EOpMin3: - extBuiltins = getExtBuiltins(spv::E_SPV_AMD_shader_trinary_minmax); - if (isFloat) - libCall = spv::FMin3AMD; - else { - if (isUnsigned) - libCall = spv::UMin3AMD; - else - libCall = spv::SMin3AMD; - } - break; - case glslang::EOpMax3: - extBuiltins = getExtBuiltins(spv::E_SPV_AMD_shader_trinary_minmax); - if (isFloat) - libCall = spv::FMax3AMD; - else { - if (isUnsigned) - libCall = spv::UMax3AMD; - else - libCall = spv::SMax3AMD; - } - break; - case glslang::EOpMid3: - extBuiltins = getExtBuiltins(spv::E_SPV_AMD_shader_trinary_minmax); - if (isFloat) - libCall = spv::FMid3AMD; - else { - if (isUnsigned) - libCall = spv::UMid3AMD; - else - libCall = spv::SMid3AMD; - } - break; - - case glslang::EOpInterpolateAtVertex: - extBuiltins = getExtBuiltins(spv::E_SPV_AMD_shader_explicit_vertex_parameter); - libCall = spv::InterpolateAtVertexAMD; - break; -#endif - - default: - return 0; - } - - spv::Id id = 0; - if (libCall >= 0) { - // Use an extended instruction from the standard library. - // Construct the call arguments, without modifying the original operands vector. - // We might need the remaining arguments, e.g. in the EOpFrexp case. - std::vector callArguments(operands.begin(), operands.begin() + consumedOperands); - id = builder.createBuiltinCall(typeId, extBuiltins >= 0 ? extBuiltins : stdBuiltins, libCall, callArguments); - } else { - switch (consumedOperands) { - case 0: - // should all be handled by visitAggregate and createNoArgOperation - assert(0); - return 0; - case 1: - // should all be handled by createUnaryOperation - assert(0); - return 0; - case 2: - id = builder.createBinOp(opCode, typeId, operands[0], operands[1]); - break; - default: - // anything 3 or over doesn't have l-value operands, so all should be consumed - assert(consumedOperands == operands.size()); - id = builder.createOp(opCode, typeId, operands); - break; - } - } - - // Decode the return types that were structures - switch (op) { - case glslang::EOpAddCarry: - case glslang::EOpSubBorrow: - builder.createStore(builder.createCompositeExtract(id, typeId0, 1), operands[2]); - id = builder.createCompositeExtract(id, typeId0, 0); - break; - case glslang::EOpUMulExtended: - case glslang::EOpIMulExtended: - builder.createStore(builder.createCompositeExtract(id, typeId0, 0), operands[3]); - builder.createStore(builder.createCompositeExtract(id, typeId0, 1), operands[2]); - break; - case glslang::EOpFrexp: - { - assert(operands.size() == 2); - if (builder.isFloatType(builder.getScalarTypeId(typeId1))) { - // "exp" is floating-point type (from HLSL intrinsic) - spv::Id member1 = builder.createCompositeExtract(id, frexpIntType, 1); - member1 = builder.createUnaryOp(spv::OpConvertSToF, typeId1, member1); - builder.createStore(member1, operands[1]); - } else - // "exp" is integer type (from GLSL built-in function) - builder.createStore(builder.createCompositeExtract(id, frexpIntType, 1), operands[1]); - id = builder.createCompositeExtract(id, typeId0, 0); - } - break; - default: - break; - } - - return builder.setPrecision(id, precision); -} - -// Intrinsics with no arguments (or no return value, and no precision). -spv::Id TGlslangToSpvTraverser::createNoArgOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId) -{ - // TODO: get the barrier operands correct - - switch (op) { - case glslang::EOpEmitVertex: - builder.createNoResultOp(spv::OpEmitVertex); - return 0; - case glslang::EOpEndPrimitive: - builder.createNoResultOp(spv::OpEndPrimitive); - return 0; - case glslang::EOpBarrier: - if (glslangIntermediate->getStage() == EShLangTessControl) { - builder.createControlBarrier(spv::ScopeWorkgroup, spv::ScopeInvocation, spv::MemorySemanticsMaskNone); - // TODO: prefer the following, when available: - // builder.createControlBarrier(spv::ScopePatch, spv::ScopePatch, - // spv::MemorySemanticsPatchMask | - // spv::MemorySemanticsAcquireReleaseMask); - } else { - builder.createControlBarrier(spv::ScopeWorkgroup, spv::ScopeWorkgroup, - spv::MemorySemanticsWorkgroupMemoryMask | - spv::MemorySemanticsAcquireReleaseMask); - } - return 0; - case glslang::EOpMemoryBarrier: - builder.createMemoryBarrier(spv::ScopeDevice, spv::MemorySemanticsAllMemory | - spv::MemorySemanticsAcquireReleaseMask); - return 0; - case glslang::EOpMemoryBarrierAtomicCounter: - builder.createMemoryBarrier(spv::ScopeDevice, spv::MemorySemanticsAtomicCounterMemoryMask | - spv::MemorySemanticsAcquireReleaseMask); - return 0; - case glslang::EOpMemoryBarrierBuffer: - builder.createMemoryBarrier(spv::ScopeDevice, spv::MemorySemanticsUniformMemoryMask | - spv::MemorySemanticsAcquireReleaseMask); - return 0; - case glslang::EOpMemoryBarrierImage: - builder.createMemoryBarrier(spv::ScopeDevice, spv::MemorySemanticsImageMemoryMask | - spv::MemorySemanticsAcquireReleaseMask); - return 0; - case glslang::EOpMemoryBarrierShared: - builder.createMemoryBarrier(spv::ScopeDevice, spv::MemorySemanticsWorkgroupMemoryMask | - spv::MemorySemanticsAcquireReleaseMask); - return 0; - case glslang::EOpGroupMemoryBarrier: - builder.createMemoryBarrier(spv::ScopeWorkgroup, spv::MemorySemanticsAllMemory | - spv::MemorySemanticsAcquireReleaseMask); - return 0; - case glslang::EOpAllMemoryBarrierWithGroupSync: - builder.createControlBarrier(spv::ScopeWorkgroup, spv::ScopeDevice, - spv::MemorySemanticsAllMemory | - spv::MemorySemanticsAcquireReleaseMask); - return 0; - case glslang::EOpDeviceMemoryBarrier: - builder.createMemoryBarrier(spv::ScopeDevice, spv::MemorySemanticsUniformMemoryMask | - spv::MemorySemanticsImageMemoryMask | - spv::MemorySemanticsAcquireReleaseMask); - return 0; - case glslang::EOpDeviceMemoryBarrierWithGroupSync: - builder.createControlBarrier(spv::ScopeWorkgroup, spv::ScopeDevice, spv::MemorySemanticsUniformMemoryMask | - spv::MemorySemanticsImageMemoryMask | - spv::MemorySemanticsAcquireReleaseMask); - return 0; - case glslang::EOpWorkgroupMemoryBarrier: - builder.createMemoryBarrier(spv::ScopeWorkgroup, spv::MemorySemanticsWorkgroupMemoryMask | - spv::MemorySemanticsAcquireReleaseMask); - return 0; - case glslang::EOpWorkgroupMemoryBarrierWithGroupSync: - builder.createControlBarrier(spv::ScopeWorkgroup, spv::ScopeWorkgroup, - spv::MemorySemanticsWorkgroupMemoryMask | - spv::MemorySemanticsAcquireReleaseMask); - return 0; - case glslang::EOpSubgroupBarrier: - builder.createControlBarrier(spv::ScopeSubgroup, spv::ScopeSubgroup, spv::MemorySemanticsAllMemory | - spv::MemorySemanticsAcquireReleaseMask); - return spv::NoResult; - case glslang::EOpSubgroupMemoryBarrier: - builder.createMemoryBarrier(spv::ScopeSubgroup, spv::MemorySemanticsAllMemory | - spv::MemorySemanticsAcquireReleaseMask); - return spv::NoResult; - case glslang::EOpSubgroupMemoryBarrierBuffer: - builder.createMemoryBarrier(spv::ScopeSubgroup, spv::MemorySemanticsUniformMemoryMask | - spv::MemorySemanticsAcquireReleaseMask); - return spv::NoResult; - case glslang::EOpSubgroupMemoryBarrierImage: - builder.createMemoryBarrier(spv::ScopeSubgroup, spv::MemorySemanticsImageMemoryMask | - spv::MemorySemanticsAcquireReleaseMask); - return spv::NoResult; - case glslang::EOpSubgroupMemoryBarrierShared: - builder.createMemoryBarrier(spv::ScopeSubgroup, spv::MemorySemanticsWorkgroupMemoryMask | - spv::MemorySemanticsAcquireReleaseMask); - return spv::NoResult; - case glslang::EOpSubgroupElect: { - std::vector operands; - return createSubgroupOperation(op, typeId, operands, glslang::EbtVoid); - } -#ifdef AMD_EXTENSIONS - case glslang::EOpTime: - { - std::vector args; // Dummy arguments - spv::Id id = builder.createBuiltinCall(typeId, getExtBuiltins(spv::E_SPV_AMD_gcn_shader), spv::TimeAMD, args); - return builder.setPrecision(id, precision); - } -#endif - default: - logger->missingFunctionality("unknown operation with no arguments"); - return 0; - } -} - -spv::Id TGlslangToSpvTraverser::getSymbolId(const glslang::TIntermSymbol* symbol) -{ - auto iter = symbolValues.find(symbol->getId()); - spv::Id id; - if (symbolValues.end() != iter) { - id = iter->second; - return id; - } - - // it was not found, create it - id = createSpvVariable(symbol); - symbolValues[symbol->getId()] = id; - - if (symbol->getBasicType() != glslang::EbtBlock) { - builder.addDecoration(id, TranslatePrecisionDecoration(symbol->getType())); - builder.addDecoration(id, TranslateInterpolationDecoration(symbol->getType().getQualifier())); - builder.addDecoration(id, TranslateAuxiliaryStorageDecoration(symbol->getType().getQualifier())); - if (symbol->getType().getQualifier().hasSpecConstantId()) - builder.addDecoration(id, spv::DecorationSpecId, symbol->getType().getQualifier().layoutSpecConstantId); - if (symbol->getQualifier().hasIndex()) - builder.addDecoration(id, spv::DecorationIndex, symbol->getQualifier().layoutIndex); - if (symbol->getQualifier().hasComponent()) - builder.addDecoration(id, spv::DecorationComponent, symbol->getQualifier().layoutComponent); - // atomic counters use this: - if (symbol->getQualifier().hasOffset()) - builder.addDecoration(id, spv::DecorationOffset, symbol->getQualifier().layoutOffset); - } - - if (symbol->getQualifier().hasLocation()) - builder.addDecoration(id, spv::DecorationLocation, symbol->getQualifier().layoutLocation); - builder.addDecoration(id, TranslateInvariantDecoration(symbol->getType().getQualifier())); - if (symbol->getQualifier().hasStream() && glslangIntermediate->isMultiStream()) { - builder.addCapability(spv::CapabilityGeometryStreams); - builder.addDecoration(id, spv::DecorationStream, symbol->getQualifier().layoutStream); - } - if (symbol->getQualifier().hasSet()) - builder.addDecoration(id, spv::DecorationDescriptorSet, symbol->getQualifier().layoutSet); - else if (IsDescriptorResource(symbol->getType())) { - // default to 0 - builder.addDecoration(id, spv::DecorationDescriptorSet, 0); - } - if (symbol->getQualifier().hasBinding()) - builder.addDecoration(id, spv::DecorationBinding, symbol->getQualifier().layoutBinding); - if (symbol->getQualifier().hasAttachment()) - builder.addDecoration(id, spv::DecorationInputAttachmentIndex, symbol->getQualifier().layoutAttachment); - if (glslangIntermediate->getXfbMode()) { - builder.addCapability(spv::CapabilityTransformFeedback); - if (symbol->getQualifier().hasXfbStride()) - builder.addDecoration(id, spv::DecorationXfbStride, symbol->getQualifier().layoutXfbStride); - if (symbol->getQualifier().hasXfbBuffer()) { - builder.addDecoration(id, spv::DecorationXfbBuffer, symbol->getQualifier().layoutXfbBuffer); - unsigned stride = glslangIntermediate->getXfbStride(symbol->getQualifier().layoutXfbBuffer); - if (stride != glslang::TQualifier::layoutXfbStrideEnd) - builder.addDecoration(id, spv::DecorationXfbStride, stride); - } - if (symbol->getQualifier().hasXfbOffset()) - builder.addDecoration(id, spv::DecorationOffset, symbol->getQualifier().layoutXfbOffset); - } - - if (symbol->getType().isImage()) { - std::vector memory; - TranslateMemoryDecoration(symbol->getType().getQualifier(), memory); - for (unsigned int i = 0; i < memory.size(); ++i) - builder.addDecoration(id, memory[i]); - } - - // built-in variable decorations - spv::BuiltIn builtIn = TranslateBuiltInDecoration(symbol->getQualifier().builtIn, false); - if (builtIn != spv::BuiltInMax) - builder.addDecoration(id, spv::DecorationBuiltIn, (int)builtIn); - - // nonuniform - builder.addDecoration(id, TranslateNonUniformDecoration(symbol->getType().getQualifier())); - -#ifdef NV_EXTENSIONS - if (builtIn == spv::BuiltInSampleMask) { - spv::Decoration decoration; - // GL_NV_sample_mask_override_coverage extension - if (glslangIntermediate->getLayoutOverrideCoverage()) - decoration = (spv::Decoration)spv::DecorationOverrideCoverageNV; - else - decoration = (spv::Decoration)spv::DecorationMax; - builder.addDecoration(id, decoration); - if (decoration != spv::DecorationMax) { - builder.addExtension(spv::E_SPV_NV_sample_mask_override_coverage); - } - } - else if (builtIn == spv::BuiltInLayer) { - // SPV_NV_viewport_array2 extension - if (symbol->getQualifier().layoutViewportRelative) { - builder.addDecoration(id, (spv::Decoration)spv::DecorationViewportRelativeNV); - builder.addCapability(spv::CapabilityShaderViewportMaskNV); - builder.addExtension(spv::E_SPV_NV_viewport_array2); - } - if (symbol->getQualifier().layoutSecondaryViewportRelativeOffset != -2048) { - builder.addDecoration(id, (spv::Decoration)spv::DecorationSecondaryViewportRelativeNV, - symbol->getQualifier().layoutSecondaryViewportRelativeOffset); - builder.addCapability(spv::CapabilityShaderStereoViewNV); - builder.addExtension(spv::E_SPV_NV_stereo_view_rendering); - } - } - - if (symbol->getQualifier().layoutPassthrough) { - builder.addDecoration(id, spv::DecorationPassthroughNV); - builder.addCapability(spv::CapabilityGeometryShaderPassthroughNV); - builder.addExtension(spv::E_SPV_NV_geometry_shader_passthrough); - } -#endif - - if (glslangIntermediate->getHlslFunctionality1() && symbol->getType().getQualifier().semanticName != nullptr) { - builder.addExtension("SPV_GOOGLE_hlsl_functionality1"); - builder.addDecoration(id, (spv::Decoration)spv::DecorationHlslSemanticGOOGLE, - symbol->getType().getQualifier().semanticName); - } - - return id; -} - -// Make a full tree of instructions to build a SPIR-V specialization constant, -// or regular constant if possible. -// -// TBD: this is not yet done, nor verified to be the best design, it does do the leaf symbols though -// -// Recursively walk the nodes. The nodes form a tree whose leaves are -// regular constants, which themselves are trees that createSpvConstant() -// recursively walks. So, this function walks the "top" of the tree: -// - emit specialization constant-building instructions for specConstant -// - when running into a non-spec-constant, switch to createSpvConstant() -spv::Id TGlslangToSpvTraverser::createSpvConstant(const glslang::TIntermTyped& node) -{ - assert(node.getQualifier().isConstant()); - - // Handle front-end constants first (non-specialization constants). - if (! node.getQualifier().specConstant) { - // hand off to the non-spec-constant path - assert(node.getAsConstantUnion() != nullptr || node.getAsSymbolNode() != nullptr); - int nextConst = 0; - return createSpvConstantFromConstUnionArray(node.getType(), node.getAsConstantUnion() ? node.getAsConstantUnion()->getConstArray() : node.getAsSymbolNode()->getConstArray(), - nextConst, false); - } - - // We now know we have a specialization constant to build - - // gl_WorkGroupSize is a special case until the front-end handles hierarchical specialization constants, - // even then, it's specialization ids are handled by special case syntax in GLSL: layout(local_size_x = ... - if (node.getType().getQualifier().builtIn == glslang::EbvWorkGroupSize) { - std::vector dimConstId; - for (int dim = 0; dim < 3; ++dim) { - bool specConst = (glslangIntermediate->getLocalSizeSpecId(dim) != glslang::TQualifier::layoutNotSet); - dimConstId.push_back(builder.makeUintConstant(glslangIntermediate->getLocalSize(dim), specConst)); - if (specConst) { - builder.addDecoration(dimConstId.back(), spv::DecorationSpecId, - glslangIntermediate->getLocalSizeSpecId(dim)); - } - } - return builder.makeCompositeConstant(builder.makeVectorType(builder.makeUintType(32), 3), dimConstId, true); - } - - // An AST node labelled as specialization constant should be a symbol node. - // Its initializer should either be a sub tree with constant nodes, or a constant union array. - if (auto* sn = node.getAsSymbolNode()) { - if (auto* sub_tree = sn->getConstSubtree()) { - // Traverse the constant constructor sub tree like generating normal run-time instructions. - // During the AST traversal, if the node is marked as 'specConstant', SpecConstantOpModeGuard - // will set the builder into spec constant op instruction generating mode. - sub_tree->traverse(this); - return accessChainLoad(sub_tree->getType()); - } else if (auto* const_union_array = &sn->getConstArray()){ - int nextConst = 0; - spv::Id id = createSpvConstantFromConstUnionArray(sn->getType(), *const_union_array, nextConst, true); - builder.addName(id, sn->getName().c_str()); - return id; - } - } - - // Neither a front-end constant node, nor a specialization constant node with constant union array or - // constant sub tree as initializer. - logger->missingFunctionality("Neither a front-end constant nor a spec constant."); - exit(1); - return spv::NoResult; -} - -// Use 'consts' as the flattened glslang source of scalar constants to recursively -// build the aggregate SPIR-V constant. -// -// If there are not enough elements present in 'consts', 0 will be substituted; -// an empty 'consts' can be used to create a fully zeroed SPIR-V constant. -// -spv::Id TGlslangToSpvTraverser::createSpvConstantFromConstUnionArray(const glslang::TType& glslangType, const glslang::TConstUnionArray& consts, int& nextConst, bool specConstant) -{ - // vector of constants for SPIR-V - std::vector spvConsts; - - // Type is used for struct and array constants - spv::Id typeId = convertGlslangToSpvType(glslangType); - - if (glslangType.isArray()) { - glslang::TType elementType(glslangType, 0); - for (int i = 0; i < glslangType.getOuterArraySize(); ++i) - spvConsts.push_back(createSpvConstantFromConstUnionArray(elementType, consts, nextConst, false)); - } else if (glslangType.isMatrix()) { - glslang::TType vectorType(glslangType, 0); - for (int col = 0; col < glslangType.getMatrixCols(); ++col) - spvConsts.push_back(createSpvConstantFromConstUnionArray(vectorType, consts, nextConst, false)); - } else if (glslangType.getStruct()) { - glslang::TVector::const_iterator iter; - for (iter = glslangType.getStruct()->begin(); iter != glslangType.getStruct()->end(); ++iter) - spvConsts.push_back(createSpvConstantFromConstUnionArray(*iter->type, consts, nextConst, false)); - } else if (glslangType.getVectorSize() > 1) { - for (unsigned int i = 0; i < (unsigned int)glslangType.getVectorSize(); ++i) { - bool zero = nextConst >= consts.size(); - switch (glslangType.getBasicType()) { - case glslang::EbtInt8: - spvConsts.push_back(builder.makeInt8Constant(zero ? 0 : consts[nextConst].getI8Const())); - break; - case glslang::EbtUint8: - spvConsts.push_back(builder.makeUint8Constant(zero ? 0 : consts[nextConst].getU8Const())); - break; - case glslang::EbtInt16: - spvConsts.push_back(builder.makeInt16Constant(zero ? 0 : consts[nextConst].getI16Const())); - break; - case glslang::EbtUint16: - spvConsts.push_back(builder.makeUint16Constant(zero ? 0 : consts[nextConst].getU16Const())); - break; - case glslang::EbtInt: - spvConsts.push_back(builder.makeIntConstant(zero ? 0 : consts[nextConst].getIConst())); - break; - case glslang::EbtUint: - spvConsts.push_back(builder.makeUintConstant(zero ? 0 : consts[nextConst].getUConst())); - break; - case glslang::EbtInt64: - spvConsts.push_back(builder.makeInt64Constant(zero ? 0 : consts[nextConst].getI64Const())); - break; - case glslang::EbtUint64: - spvConsts.push_back(builder.makeUint64Constant(zero ? 0 : consts[nextConst].getU64Const())); - break; - case glslang::EbtFloat: - spvConsts.push_back(builder.makeFloatConstant(zero ? 0.0F : (float)consts[nextConst].getDConst())); - break; - case glslang::EbtDouble: - spvConsts.push_back(builder.makeDoubleConstant(zero ? 0.0 : consts[nextConst].getDConst())); - break; - case glslang::EbtFloat16: - spvConsts.push_back(builder.makeFloat16Constant(zero ? 0.0F : (float)consts[nextConst].getDConst())); - break; - case glslang::EbtBool: - spvConsts.push_back(builder.makeBoolConstant(zero ? false : consts[nextConst].getBConst())); - break; - default: - assert(0); - break; - } - ++nextConst; - } - } else { - // we have a non-aggregate (scalar) constant - bool zero = nextConst >= consts.size(); - spv::Id scalar = 0; - switch (glslangType.getBasicType()) { - case glslang::EbtInt8: - scalar = builder.makeInt8Constant(zero ? 0 : consts[nextConst].getI8Const(), specConstant); - break; - case glslang::EbtUint8: - scalar = builder.makeUint8Constant(zero ? 0 : consts[nextConst].getU8Const(), specConstant); - break; - case glslang::EbtInt16: - scalar = builder.makeInt16Constant(zero ? 0 : consts[nextConst].getI16Const(), specConstant); - break; - case glslang::EbtUint16: - scalar = builder.makeUint16Constant(zero ? 0 : consts[nextConst].getU16Const(), specConstant); - break; - case glslang::EbtInt: - scalar = builder.makeIntConstant(zero ? 0 : consts[nextConst].getIConst(), specConstant); - break; - case glslang::EbtUint: - scalar = builder.makeUintConstant(zero ? 0 : consts[nextConst].getUConst(), specConstant); - break; - case glslang::EbtInt64: - scalar = builder.makeInt64Constant(zero ? 0 : consts[nextConst].getI64Const(), specConstant); - break; - case glslang::EbtUint64: - scalar = builder.makeUint64Constant(zero ? 0 : consts[nextConst].getU64Const(), specConstant); - break; - case glslang::EbtFloat: - scalar = builder.makeFloatConstant(zero ? 0.0F : (float)consts[nextConst].getDConst(), specConstant); - break; - case glslang::EbtDouble: - scalar = builder.makeDoubleConstant(zero ? 0.0 : consts[nextConst].getDConst(), specConstant); - break; - case glslang::EbtFloat16: - scalar = builder.makeFloat16Constant(zero ? 0.0F : (float)consts[nextConst].getDConst(), specConstant); - break; - case glslang::EbtBool: - scalar = builder.makeBoolConstant(zero ? false : consts[nextConst].getBConst(), specConstant); - break; - default: - assert(0); - break; - } - ++nextConst; - return scalar; - } - - return builder.makeCompositeConstant(typeId, spvConsts); -} - -// Return true if the node is a constant or symbol whose reading has no -// non-trivial observable cost or effect. -bool TGlslangToSpvTraverser::isTrivialLeaf(const glslang::TIntermTyped* node) -{ - // don't know what this is - if (node == nullptr) - return false; - - // a constant is safe - if (node->getAsConstantUnion() != nullptr) - return true; - - // not a symbol means non-trivial - if (node->getAsSymbolNode() == nullptr) - return false; - - // a symbol, depends on what's being read - switch (node->getType().getQualifier().storage) { - case glslang::EvqTemporary: - case glslang::EvqGlobal: - case glslang::EvqIn: - case glslang::EvqInOut: - case glslang::EvqConst: - case glslang::EvqConstReadOnly: - case glslang::EvqUniform: - return true; - default: - return false; - } -} - -// A node is trivial if it is a single operation with no side effects. -// HLSL (and/or vectors) are always trivial, as it does not short circuit. -// Otherwise, error on the side of saying non-trivial. -// Return true if trivial. -bool TGlslangToSpvTraverser::isTrivial(const glslang::TIntermTyped* node) -{ - if (node == nullptr) - return false; - - // count non scalars as trivial, as well as anything coming from HLSL - if (! node->getType().isScalarOrVec1() || glslangIntermediate->getSource() == glslang::EShSourceHlsl) - return true; - - // symbols and constants are trivial - if (isTrivialLeaf(node)) - return true; - - // otherwise, it needs to be a simple operation or one or two leaf nodes - - // not a simple operation - const glslang::TIntermBinary* binaryNode = node->getAsBinaryNode(); - const glslang::TIntermUnary* unaryNode = node->getAsUnaryNode(); - if (binaryNode == nullptr && unaryNode == nullptr) - return false; - - // not on leaf nodes - if (binaryNode && (! isTrivialLeaf(binaryNode->getLeft()) || ! isTrivialLeaf(binaryNode->getRight()))) - return false; - - if (unaryNode && ! isTrivialLeaf(unaryNode->getOperand())) { - return false; - } - - switch (node->getAsOperator()->getOp()) { - case glslang::EOpLogicalNot: - case glslang::EOpConvIntToBool: - case glslang::EOpConvUintToBool: - case glslang::EOpConvFloatToBool: - case glslang::EOpConvDoubleToBool: - case glslang::EOpEqual: - case glslang::EOpNotEqual: - case glslang::EOpLessThan: - case glslang::EOpGreaterThan: - case glslang::EOpLessThanEqual: - case glslang::EOpGreaterThanEqual: - case glslang::EOpIndexDirect: - case glslang::EOpIndexDirectStruct: - case glslang::EOpLogicalXor: - case glslang::EOpAny: - case glslang::EOpAll: - return true; - default: - return false; - } -} - -// Emit short-circuiting code, where 'right' is never evaluated unless -// the left side is true (for &&) or false (for ||). -spv::Id TGlslangToSpvTraverser::createShortCircuit(glslang::TOperator op, glslang::TIntermTyped& left, glslang::TIntermTyped& right) -{ - spv::Id boolTypeId = builder.makeBoolType(); - - // emit left operand - builder.clearAccessChain(); - left.traverse(this); - spv::Id leftId = accessChainLoad(left.getType()); - - // Operands to accumulate OpPhi operands - std::vector phiOperands; - // accumulate left operand's phi information - phiOperands.push_back(leftId); - phiOperands.push_back(builder.getBuildPoint()->getId()); - - // Make the two kinds of operation symmetric with a "!" - // || => emit "if (! left) result = right" - // && => emit "if ( left) result = right" - // - // TODO: this runtime "not" for || could be avoided by adding functionality - // to 'builder' to have an "else" without an "then" - if (op == glslang::EOpLogicalOr) - leftId = builder.createUnaryOp(spv::OpLogicalNot, boolTypeId, leftId); - - // make an "if" based on the left value - spv::Builder::If ifBuilder(leftId, spv::SelectionControlMaskNone, builder); - - // emit right operand as the "then" part of the "if" - builder.clearAccessChain(); - right.traverse(this); - spv::Id rightId = accessChainLoad(right.getType()); - - // accumulate left operand's phi information - phiOperands.push_back(rightId); - phiOperands.push_back(builder.getBuildPoint()->getId()); - - // finish the "if" - ifBuilder.makeEndIf(); - - // phi together the two results - return builder.createOp(spv::OpPhi, boolTypeId, phiOperands); -} - -#ifdef AMD_EXTENSIONS -// Return type Id of the imported set of extended instructions corresponds to the name. -// Import this set if it has not been imported yet. -spv::Id TGlslangToSpvTraverser::getExtBuiltins(const char* name) -{ - if (extBuiltinMap.find(name) != extBuiltinMap.end()) - return extBuiltinMap[name]; - else { - builder.addExtension(name); - spv::Id extBuiltins = builder.import(name); - extBuiltinMap[name] = extBuiltins; - return extBuiltins; - } -} -#endif - -}; // end anonymous namespace - -namespace glslang { - -void GetSpirvVersion(std::string& version) -{ - const int bufSize = 100; - char buf[bufSize]; - snprintf(buf, bufSize, "0x%08x, Revision %d", spv::Version, spv::Revision); - version = buf; -} - -// For low-order part of the generator's magic number. Bump up -// when there is a change in the style (e.g., if SSA form changes, -// or a different instruction sequence to do something gets used). -int GetSpirvGeneratorVersion() -{ - // return 1; // start - // return 2; // EOpAtomicCounterDecrement gets a post decrement, to map between GLSL -> SPIR-V - // return 3; // change/correct barrier-instruction operands, to match memory model group decisions - // return 4; // some deeper access chains: for dynamic vector component, and local Boolean component - // return 5; // make OpArrayLength result type be an int with signedness of 0 - return 6; // revert version 5 change, which makes a different (new) kind of incorrect code, - // versions 4 and 6 each generate OpArrayLength as it has long been done -} - -// Write SPIR-V out to a binary file -void OutputSpvBin(const std::vector& spirv, const char* baseName) -{ - std::ofstream out; - out.open(baseName, std::ios::binary | std::ios::out); - if (out.fail()) - printf("ERROR: Failed to open file: %s\n", baseName); - for (int i = 0; i < (int)spirv.size(); ++i) { - unsigned int word = spirv[i]; - out.write((const char*)&word, 4); - } - out.close(); -} - -// Write SPIR-V out to a text file with 32-bit hexadecimal words -void OutputSpvHex(const std::vector& spirv, const char* baseName, const char* varName) -{ - std::ofstream out; - out.open(baseName, std::ios::binary | std::ios::out); - if (out.fail()) - printf("ERROR: Failed to open file: %s\n", baseName); - out << "\t// " << - glslang::GetSpirvGeneratorVersion() << "." << GLSLANG_MINOR_VERSION << "." << GLSLANG_PATCH_LEVEL << - std::endl; - if (varName != nullptr) { - out << "\t #pragma once" << std::endl; - out << "const uint32_t " << varName << "[] = {" << std::endl; - } - const int WORDS_PER_LINE = 8; - for (int i = 0; i < (int)spirv.size(); i += WORDS_PER_LINE) { - out << "\t"; - for (int j = 0; j < WORDS_PER_LINE && i + j < (int)spirv.size(); ++j) { - const unsigned int word = spirv[i + j]; - out << "0x" << std::hex << std::setw(8) << std::setfill('0') << word; - if (i + j + 1 < (int)spirv.size()) { - out << ","; - } - } - out << std::endl; - } - if (varName != nullptr) { - out << "};"; - } - out.close(); -} - -// -// Set up the glslang traversal -// -void GlslangToSpv(const glslang::TIntermediate& intermediate, std::vector& spirv, SpvOptions* options) -{ - spv::SpvBuildLogger logger; - GlslangToSpv(intermediate, spirv, &logger, options); -} - -void GlslangToSpv(const glslang::TIntermediate& intermediate, std::vector& spirv, - spv::SpvBuildLogger* logger, SpvOptions* options) -{ - TIntermNode* root = intermediate.getTreeRoot(); - - if (root == 0) - return; - - glslang::SpvOptions defaultOptions; - if (options == nullptr) - options = &defaultOptions; - - glslang::GetThreadPoolAllocator().push(); - - TGlslangToSpvTraverser it(intermediate.getSpv().spv, &intermediate, logger, *options); - root->traverse(&it); - it.finishSpv(); - it.dumpSpv(spirv); - -#if ENABLE_OPT - // If from HLSL, run spirv-opt to "legalize" the SPIR-V for Vulkan - // eg. forward and remove memory writes of opaque types. - if ((intermediate.getSource() == EShSourceHlsl || - options->optimizeSize) && - !options->disableOptimizer) { - spv_target_env target_env = SPV_ENV_UNIVERSAL_1_2; - - spvtools::Optimizer optimizer(target_env); - optimizer.SetMessageConsumer([](spv_message_level_t level, - const char* source, - const spv_position_t& position, - const char* message) { - std::cerr << StringifyMessage(level, source, position, message) - << std::endl; - }); - - optimizer.RegisterPass(CreateMergeReturnPass()); - optimizer.RegisterPass(CreateInlineExhaustivePass()); - optimizer.RegisterPass(CreateEliminateDeadFunctionsPass()); - optimizer.RegisterPass(CreateScalarReplacementPass()); - optimizer.RegisterPass(CreateLocalAccessChainConvertPass()); - optimizer.RegisterPass(CreateLocalSingleBlockLoadStoreElimPass()); - optimizer.RegisterPass(CreateLocalSingleStoreElimPass()); - optimizer.RegisterPass(CreateAggressiveDCEPass()); - optimizer.RegisterPass(CreateInsertExtractElimPass()); - optimizer.RegisterPass(CreateDeadInsertElimPass()); - optimizer.RegisterPass(CreateAggressiveDCEPass()); - optimizer.RegisterPass(CreateCCPPass()); - optimizer.RegisterPass(CreateSimplificationPass()); - optimizer.RegisterPass(CreateDeadBranchElimPass()); - optimizer.RegisterPass(CreateCFGCleanupPass()); - optimizer.RegisterPass(CreateBlockMergePass()); - optimizer.RegisterPass(CreateLocalMultiStoreElimPass()); - optimizer.RegisterPass(CreateAggressiveDCEPass()); - optimizer.RegisterPass(CreateInsertExtractElimPass()); - optimizer.RegisterPass(CreateDeadInsertElimPass()); - if (options->optimizeSize) { - optimizer.RegisterPass(CreateRedundancyEliminationPass()); - // TODO(greg-lunarg): Add this when AMD driver issues are resolved - // optimizer.RegisterPass(CreateCommonUniformElimPass()); - } - optimizer.RegisterPass(CreateAggressiveDCEPass()); - - if (!optimizer.Run(spirv.data(), spirv.size(), &spirv)) - return; - } -#endif - - glslang::GetThreadPoolAllocator().pop(); -} - -}; // end namespace glslang diff --git a/External/glslang/SPIRV/GlslangToSpv.h b/External/glslang/SPIRV/GlslangToSpv.h deleted file mode 100644 index f7f7cff6..00000000 --- a/External/glslang/SPIRV/GlslangToSpv.h +++ /dev/null @@ -1,67 +0,0 @@ -// -// Copyright (C) 2014 LunarG, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -#pragma once - -#if defined(_MSC_VER) && _MSC_VER >= 1900 - #pragma warning(disable : 4464) // relative include path contains '..' -#endif - -#include "../glslang/Include/intermediate.h" - -#include -#include - -#include "Logger.h" - -namespace glslang { - -struct SpvOptions { - SpvOptions() : generateDebugInfo(false), disableOptimizer(true), - optimizeSize(false) { } - bool generateDebugInfo; - bool disableOptimizer; - bool optimizeSize; -}; - -void GetSpirvVersion(std::string&); -int GetSpirvGeneratorVersion(); -void GlslangToSpv(const glslang::TIntermediate& intermediate, std::vector& spirv, - SpvOptions* options = nullptr); -void GlslangToSpv(const glslang::TIntermediate& intermediate, std::vector& spirv, - spv::SpvBuildLogger* logger, SpvOptions* options = nullptr); -void OutputSpvBin(const std::vector& spirv, const char* baseName); -void OutputSpvHex(const std::vector& spirv, const char* baseName, const char* varName); - -} diff --git a/External/glslang/SPIRV/InReadableOrder.cpp b/External/glslang/SPIRV/InReadableOrder.cpp deleted file mode 100644 index 52b29613..00000000 --- a/External/glslang/SPIRV/InReadableOrder.cpp +++ /dev/null @@ -1,113 +0,0 @@ -// -// Copyright (C) 2016 Google, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -// The SPIR-V spec requires code blocks to appear in an order satisfying the -// dominator-tree direction (ie, dominator before the dominated). This is, -// actually, easy to achieve: any pre-order CFG traversal algorithm will do it. -// Because such algorithms visit a block only after traversing some path to it -// from the root, they necessarily visit the block's idom first. -// -// But not every graph-traversal algorithm outputs blocks in an order that -// appears logical to human readers. The problem is that unrelated branches may -// be interspersed with each other, and merge blocks may come before some of the -// branches being merged. -// -// A good, human-readable order of blocks may be achieved by performing -// depth-first search but delaying merge nodes until after all their branches -// have been visited. This is implemented below by the inReadableOrder() -// function. - -#include "spvIR.h" - -#include -#include - -using spv::Block; -using spv::Id; - -namespace { -// Traverses CFG in a readable order, invoking a pre-set callback on each block. -// Use by calling visit() on the root block. -class ReadableOrderTraverser { -public: - explicit ReadableOrderTraverser(std::function callback) : callback_(callback) {} - // Visits the block if it hasn't been visited already and isn't currently - // being delayed. Invokes callback(block), then descends into its - // successors. Delays merge-block and continue-block processing until all - // the branches have been completed. - void visit(Block* block) - { - assert(block); - if (visited_.count(block) || delayed_.count(block)) - return; - callback_(block); - visited_.insert(block); - Block* mergeBlock = nullptr; - Block* continueBlock = nullptr; - auto mergeInst = block->getMergeInstruction(); - if (mergeInst) { - Id mergeId = mergeInst->getIdOperand(0); - mergeBlock = block->getParent().getParent().getInstruction(mergeId)->getBlock(); - delayed_.insert(mergeBlock); - if (mergeInst->getOpCode() == spv::OpLoopMerge) { - Id continueId = mergeInst->getIdOperand(1); - continueBlock = - block->getParent().getParent().getInstruction(continueId)->getBlock(); - delayed_.insert(continueBlock); - } - } - const auto successors = block->getSuccessors(); - for (auto it = successors.cbegin(); it != successors.cend(); ++it) - visit(*it); - if (continueBlock) { - delayed_.erase(continueBlock); - visit(continueBlock); - } - if (mergeBlock) { - delayed_.erase(mergeBlock); - visit(mergeBlock); - } - } - -private: - std::function callback_; - // Whether a block has already been visited or is being delayed. - std::unordered_set visited_, delayed_; -}; -} - -void spv::inReadableOrder(Block* root, std::function callback) -{ - ReadableOrderTraverser(callback).visit(root); -} diff --git a/External/glslang/SPIRV/Logger.cpp b/External/glslang/SPIRV/Logger.cpp deleted file mode 100644 index 48bd4e3a..00000000 --- a/External/glslang/SPIRV/Logger.cpp +++ /dev/null @@ -1,68 +0,0 @@ -// -// Copyright (C) 2016 Google, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -#include "Logger.h" - -#include -#include -#include - -namespace spv { - -void SpvBuildLogger::tbdFunctionality(const std::string& f) -{ - if (std::find(std::begin(tbdFeatures), std::end(tbdFeatures), f) == std::end(tbdFeatures)) - tbdFeatures.push_back(f); -} - -void SpvBuildLogger::missingFunctionality(const std::string& f) -{ - if (std::find(std::begin(missingFeatures), std::end(missingFeatures), f) == std::end(missingFeatures)) - missingFeatures.push_back(f); -} - -std::string SpvBuildLogger::getAllMessages() const { - std::ostringstream messages; - for (auto it = tbdFeatures.cbegin(); it != tbdFeatures.cend(); ++it) - messages << "TBD functionality: " << *it << "\n"; - for (auto it = missingFeatures.cbegin(); it != missingFeatures.cend(); ++it) - messages << "Missing functionality: " << *it << "\n"; - for (auto it = warnings.cbegin(); it != warnings.cend(); ++it) - messages << "warning: " << *it << "\n"; - for (auto it = errors.cbegin(); it != errors.cend(); ++it) - messages << "error: " << *it << "\n"; - return messages.str(); -} - -} // end spv namespace diff --git a/External/glslang/SPIRV/Logger.h b/External/glslang/SPIRV/Logger.h deleted file mode 100644 index 2e4ddaf5..00000000 --- a/External/glslang/SPIRV/Logger.h +++ /dev/null @@ -1,74 +0,0 @@ -// -// Copyright (C) 2016 Google, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -#ifndef GLSLANG_SPIRV_LOGGER_H -#define GLSLANG_SPIRV_LOGGER_H - -#include -#include - -namespace spv { - -// A class for holding all SPIR-V build status messages, including -// missing/TBD functionalities, warnings, and errors. -class SpvBuildLogger { -public: - SpvBuildLogger() {} - - // Registers a TBD functionality. - void tbdFunctionality(const std::string& f); - // Registers a missing functionality. - void missingFunctionality(const std::string& f); - - // Logs a warning. - void warning(const std::string& w) { warnings.push_back(w); } - // Logs an error. - void error(const std::string& e) { errors.push_back(e); } - - // Returns all messages accumulated in the order of: - // TBD functionalities, missing functionalities, warnings, errors. - std::string getAllMessages() const; - -private: - SpvBuildLogger(const SpvBuildLogger&); - - std::vector tbdFeatures; - std::vector missingFeatures; - std::vector warnings; - std::vector errors; -}; - -} // end spv namespace - -#endif // GLSLANG_SPIRV_LOGGER_H diff --git a/External/glslang/SPIRV/SPVRemapper.cpp b/External/glslang/SPIRV/SPVRemapper.cpp deleted file mode 100644 index 4bac1453..00000000 --- a/External/glslang/SPIRV/SPVRemapper.cpp +++ /dev/null @@ -1,1479 +0,0 @@ -// -// Copyright (C) 2015 LunarG, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -#include "SPVRemapper.h" -#include "doc.h" - -#if !defined (use_cpp11) -// ... not supported before C++11 -#else // defined (use_cpp11) - -#include -#include -#include "../glslang/Include/Common.h" - -namespace spv { - - // By default, just abort on error. Can be overridden via RegisterErrorHandler - spirvbin_t::errorfn_t spirvbin_t::errorHandler = [](const std::string&) { exit(5); }; - // By default, eat log messages. Can be overridden via RegisterLogHandler - spirvbin_t::logfn_t spirvbin_t::logHandler = [](const std::string&) { }; - - // This can be overridden to provide other message behavior if needed - void spirvbin_t::msg(int minVerbosity, int indent, const std::string& txt) const - { - if (verbose >= minVerbosity) - logHandler(std::string(indent, ' ') + txt); - } - - // hash opcode, with special handling for OpExtInst - std::uint32_t spirvbin_t::asOpCodeHash(unsigned word) - { - const spv::Op opCode = asOpCode(word); - - std::uint32_t offset = 0; - - switch (opCode) { - case spv::OpExtInst: - offset += asId(word + 4); break; - default: - break; - } - - return opCode * 19 + offset; // 19 = small prime - } - - spirvbin_t::range_t spirvbin_t::literalRange(spv::Op opCode) const - { - static const int maxCount = 1<<30; - - switch (opCode) { - case spv::OpTypeFloat: // fall through... - case spv::OpTypePointer: return range_t(2, 3); - case spv::OpTypeInt: return range_t(2, 4); - // TODO: case spv::OpTypeImage: - // TODO: case spv::OpTypeSampledImage: - case spv::OpTypeSampler: return range_t(3, 8); - case spv::OpTypeVector: // fall through - case spv::OpTypeMatrix: // ... - case spv::OpTypePipe: return range_t(3, 4); - case spv::OpConstant: return range_t(3, maxCount); - default: return range_t(0, 0); - } - } - - spirvbin_t::range_t spirvbin_t::typeRange(spv::Op opCode) const - { - static const int maxCount = 1<<30; - - if (isConstOp(opCode)) - return range_t(1, 2); - - switch (opCode) { - case spv::OpTypeVector: // fall through - case spv::OpTypeMatrix: // ... - case spv::OpTypeSampler: // ... - case spv::OpTypeArray: // ... - case spv::OpTypeRuntimeArray: // ... - case spv::OpTypePipe: return range_t(2, 3); - case spv::OpTypeStruct: // fall through - case spv::OpTypeFunction: return range_t(2, maxCount); - case spv::OpTypePointer: return range_t(3, 4); - default: return range_t(0, 0); - } - } - - spirvbin_t::range_t spirvbin_t::constRange(spv::Op opCode) const - { - static const int maxCount = 1<<30; - - switch (opCode) { - case spv::OpTypeArray: // fall through... - case spv::OpTypeRuntimeArray: return range_t(3, 4); - case spv::OpConstantComposite: return range_t(3, maxCount); - default: return range_t(0, 0); - } - } - - // Return the size of a type in 32-bit words. This currently only - // handles ints and floats, and is only invoked by queries which must be - // integer types. If ever needed, it can be generalized. - unsigned spirvbin_t::typeSizeInWords(spv::Id id) const - { - const unsigned typeStart = idPos(id); - const spv::Op opCode = asOpCode(typeStart); - - if (errorLatch) - return 0; - - switch (opCode) { - case spv::OpTypeInt: // fall through... - case spv::OpTypeFloat: return (spv[typeStart+2]+31)/32; - default: - return 0; - } - } - - // Looks up the type of a given const or variable ID, and - // returns its size in 32-bit words. - unsigned spirvbin_t::idTypeSizeInWords(spv::Id id) const - { - const auto tid_it = idTypeSizeMap.find(id); - if (tid_it == idTypeSizeMap.end()) { - error("type size for ID not found"); - return 0; - } - - return tid_it->second; - } - - // Is this an opcode we should remove when using --strip? - bool spirvbin_t::isStripOp(spv::Op opCode) const - { - switch (opCode) { - case spv::OpSource: - case spv::OpSourceExtension: - case spv::OpName: - case spv::OpMemberName: - case spv::OpLine: return true; - default: return false; - } - } - - // Return true if this opcode is flow control - bool spirvbin_t::isFlowCtrl(spv::Op opCode) const - { - switch (opCode) { - case spv::OpBranchConditional: - case spv::OpBranch: - case spv::OpSwitch: - case spv::OpLoopMerge: - case spv::OpSelectionMerge: - case spv::OpLabel: - case spv::OpFunction: - case spv::OpFunctionEnd: return true; - default: return false; - } - } - - // Return true if this opcode defines a type - bool spirvbin_t::isTypeOp(spv::Op opCode) const - { - switch (opCode) { - case spv::OpTypeVoid: - case spv::OpTypeBool: - case spv::OpTypeInt: - case spv::OpTypeFloat: - case spv::OpTypeVector: - case spv::OpTypeMatrix: - case spv::OpTypeImage: - case spv::OpTypeSampler: - case spv::OpTypeArray: - case spv::OpTypeRuntimeArray: - case spv::OpTypeStruct: - case spv::OpTypeOpaque: - case spv::OpTypePointer: - case spv::OpTypeFunction: - case spv::OpTypeEvent: - case spv::OpTypeDeviceEvent: - case spv::OpTypeReserveId: - case spv::OpTypeQueue: - case spv::OpTypeSampledImage: - case spv::OpTypePipe: return true; - default: return false; - } - } - - // Return true if this opcode defines a constant - bool spirvbin_t::isConstOp(spv::Op opCode) const - { - switch (opCode) { - case spv::OpConstantNull: - case spv::OpConstantSampler: - error("unimplemented constant type"); - return true; - - case spv::OpConstantTrue: - case spv::OpConstantFalse: - case spv::OpConstantComposite: - case spv::OpConstant: - return true; - - default: - return false; - } - } - - const auto inst_fn_nop = [](spv::Op, unsigned) { return false; }; - const auto op_fn_nop = [](spv::Id&) { }; - - // g++ doesn't like these defined in the class proper in an anonymous namespace. - // Dunno why. Also MSVC doesn't like the constexpr keyword. Also dunno why. - // Defining them externally seems to please both compilers, so, here they are. - const spv::Id spirvbin_t::unmapped = spv::Id(-10000); - const spv::Id spirvbin_t::unused = spv::Id(-10001); - const int spirvbin_t::header_size = 5; - - spv::Id spirvbin_t::nextUnusedId(spv::Id id) - { - while (isNewIdMapped(id)) // search for an unused ID - ++id; - - return id; - } - - spv::Id spirvbin_t::localId(spv::Id id, spv::Id newId) - { - //assert(id != spv::NoResult && newId != spv::NoResult); - - if (id > bound()) { - error(std::string("ID out of range: ") + std::to_string(id)); - return spirvbin_t::unused; - } - - if (id >= idMapL.size()) - idMapL.resize(id+1, unused); - - if (newId != unmapped && newId != unused) { - if (isOldIdUnused(id)) { - error(std::string("ID unused in module: ") + std::to_string(id)); - return spirvbin_t::unused; - } - - if (!isOldIdUnmapped(id)) { - error(std::string("ID already mapped: ") + std::to_string(id) + " -> " - + std::to_string(localId(id))); - - return spirvbin_t::unused; - } - - if (isNewIdMapped(newId)) { - error(std::string("ID already used in module: ") + std::to_string(newId)); - return spirvbin_t::unused; - } - - msg(4, 4, std::string("map: ") + std::to_string(id) + " -> " + std::to_string(newId)); - setMapped(newId); - largestNewId = std::max(largestNewId, newId); - } - - return idMapL[id] = newId; - } - - // Parse a literal string from the SPIR binary and return it as an std::string - // Due to C++11 RValue references, this doesn't copy the result string. - std::string spirvbin_t::literalString(unsigned word) const - { - std::string literal; - - literal.reserve(16); - - const char* bytes = reinterpret_cast(spv.data() + word); - - while (bytes && *bytes) - literal += *bytes++; - - return literal; - } - - void spirvbin_t::applyMap() - { - msg(3, 2, std::string("Applying map: ")); - - // Map local IDs through the ID map - process(inst_fn_nop, // ignore instructions - [this](spv::Id& id) { - id = localId(id); - - if (errorLatch) - return; - - assert(id != unused && id != unmapped); - } - ); - } - - // Find free IDs for anything we haven't mapped - void spirvbin_t::mapRemainder() - { - msg(3, 2, std::string("Remapping remainder: ")); - - spv::Id unusedId = 1; // can't use 0: that's NoResult - spirword_t maxBound = 0; - - for (spv::Id id = 0; id < idMapL.size(); ++id) { - if (isOldIdUnused(id)) - continue; - - // Find a new mapping for any used but unmapped IDs - if (isOldIdUnmapped(id)) { - localId(id, unusedId = nextUnusedId(unusedId)); - if (errorLatch) - return; - } - - if (isOldIdUnmapped(id)) { - error(std::string("old ID not mapped: ") + std::to_string(id)); - return; - } - - // Track max bound - maxBound = std::max(maxBound, localId(id) + 1); - - if (errorLatch) - return; - } - - bound(maxBound); // reset header ID bound to as big as it now needs to be - } - - // Mark debug instructions for stripping - void spirvbin_t::stripDebug() - { - // Strip instructions in the stripOp set: debug info. - process( - [&](spv::Op opCode, unsigned start) { - // remember opcodes we want to strip later - if (isStripOp(opCode)) - stripInst(start); - return true; - }, - op_fn_nop); - } - - // Mark instructions that refer to now-removed IDs for stripping - void spirvbin_t::stripDeadRefs() - { - process( - [&](spv::Op opCode, unsigned start) { - // strip opcodes pointing to removed data - switch (opCode) { - case spv::OpName: - case spv::OpMemberName: - case spv::OpDecorate: - case spv::OpMemberDecorate: - if (idPosR.find(asId(start+1)) == idPosR.end()) - stripInst(start); - break; - default: - break; // leave it alone - } - - return true; - }, - op_fn_nop); - - strip(); - } - - // Update local maps of ID, type, etc positions - void spirvbin_t::buildLocalMaps() - { - msg(2, 2, std::string("build local maps: ")); - - mapped.clear(); - idMapL.clear(); -// preserve nameMap, so we don't clear that. - fnPos.clear(); - fnCalls.clear(); - typeConstPos.clear(); - idPosR.clear(); - entryPoint = spv::NoResult; - largestNewId = 0; - - idMapL.resize(bound(), unused); - - int fnStart = 0; - spv::Id fnRes = spv::NoResult; - - // build local Id and name maps - process( - [&](spv::Op opCode, unsigned start) { - unsigned word = start+1; - spv::Id typeId = spv::NoResult; - - if (spv::InstructionDesc[opCode].hasType()) - typeId = asId(word++); - - // If there's a result ID, remember the size of its type - if (spv::InstructionDesc[opCode].hasResult()) { - const spv::Id resultId = asId(word++); - idPosR[resultId] = start; - - if (typeId != spv::NoResult) { - const unsigned idTypeSize = typeSizeInWords(typeId); - - if (errorLatch) - return false; - - if (idTypeSize != 0) - idTypeSizeMap[resultId] = idTypeSize; - } - } - - if (opCode == spv::Op::OpName) { - const spv::Id target = asId(start+1); - const std::string name = literalString(start+2); - nameMap[name] = target; - - } else if (opCode == spv::Op::OpFunctionCall) { - ++fnCalls[asId(start + 3)]; - } else if (opCode == spv::Op::OpEntryPoint) { - entryPoint = asId(start + 2); - } else if (opCode == spv::Op::OpFunction) { - if (fnStart != 0) { - error("nested function found"); - return false; - } - - fnStart = start; - fnRes = asId(start + 2); - } else if (opCode == spv::Op::OpFunctionEnd) { - assert(fnRes != spv::NoResult); - if (fnStart == 0) { - error("function end without function start"); - return false; - } - - fnPos[fnRes] = range_t(fnStart, start + asWordCount(start)); - fnStart = 0; - } else if (isConstOp(opCode)) { - if (errorLatch) - return false; - - assert(asId(start + 2) != spv::NoResult); - typeConstPos.insert(start); - } else if (isTypeOp(opCode)) { - assert(asId(start + 1) != spv::NoResult); - typeConstPos.insert(start); - } - - return false; - }, - - [this](spv::Id& id) { localId(id, unmapped); } - ); - } - - // Validate the SPIR header - void spirvbin_t::validate() const - { - msg(2, 2, std::string("validating: ")); - - if (spv.size() < header_size) { - error("file too short: "); - return; - } - - if (magic() != spv::MagicNumber) { - error("bad magic number"); - return; - } - - // field 1 = version - // field 2 = generator magic - // field 3 = result bound - - if (schemaNum() != 0) { - error("bad schema, must be 0"); - return; - } - } - - int spirvbin_t::processInstruction(unsigned word, instfn_t instFn, idfn_t idFn) - { - const auto instructionStart = word; - const unsigned wordCount = asWordCount(instructionStart); - const int nextInst = word++ + wordCount; - spv::Op opCode = asOpCode(instructionStart); - - if (nextInst > int(spv.size())) { - error("spir instruction terminated too early"); - return -1; - } - - // Base for computing number of operands; will be updated as more is learned - unsigned numOperands = wordCount - 1; - - if (instFn(opCode, instructionStart)) - return nextInst; - - // Read type and result ID from instruction desc table - if (spv::InstructionDesc[opCode].hasType()) { - idFn(asId(word++)); - --numOperands; - } - - if (spv::InstructionDesc[opCode].hasResult()) { - idFn(asId(word++)); - --numOperands; - } - - // Extended instructions: currently, assume everything is an ID. - // TODO: add whatever data we need for exceptions to that - if (opCode == spv::OpExtInst) { - word += 2; // instruction set, and instruction from set - numOperands -= 2; - - for (unsigned op=0; op < numOperands; ++op) - idFn(asId(word++)); // ID - - return nextInst; - } - - // Circular buffer so we can look back at previous unmapped values during the mapping pass. - static const unsigned idBufferSize = 4; - spv::Id idBuffer[idBufferSize]; - unsigned idBufferPos = 0; - - // Store IDs from instruction in our map - for (int op = 0; numOperands > 0; ++op, --numOperands) { - // SpecConstantOp is special: it includes the operands of another opcode which is - // given as a literal in the 3rd word. We will switch over to pretending that the - // opcode being processed is the literal opcode value of the SpecConstantOp. See the - // SPIRV spec for details. This way we will handle IDs and literals as appropriate for - // the embedded op. - if (opCode == spv::OpSpecConstantOp) { - if (op == 0) { - opCode = asOpCode(word++); // this is the opcode embedded in the SpecConstantOp. - --numOperands; - } - } - - switch (spv::InstructionDesc[opCode].operands.getClass(op)) { - case spv::OperandId: - case spv::OperandScope: - case spv::OperandMemorySemantics: - idBuffer[idBufferPos] = asId(word); - idBufferPos = (idBufferPos + 1) % idBufferSize; - idFn(asId(word++)); - break; - - case spv::OperandVariableIds: - for (unsigned i = 0; i < numOperands; ++i) - idFn(asId(word++)); - return nextInst; - - case spv::OperandVariableLiterals: - // for clarity - // if (opCode == spv::OpDecorate && asDecoration(word - 1) == spv::DecorationBuiltIn) { - // ++word; - // --numOperands; - // } - // word += numOperands; - return nextInst; - - case spv::OperandVariableLiteralId: { - if (opCode == OpSwitch) { - // word-2 is the position of the selector ID. OpSwitch Literals match its type. - // In case the IDs are currently being remapped, we get the word[-2] ID from - // the circular idBuffer. - const unsigned literalSizePos = (idBufferPos+idBufferSize-2) % idBufferSize; - const unsigned literalSize = idTypeSizeInWords(idBuffer[literalSizePos]); - const unsigned numLiteralIdPairs = (nextInst-word) / (1+literalSize); - - if (errorLatch) - return -1; - - for (unsigned arg=0; arg instPos; - instPos.reserve(unsigned(spv.size()) / 16); // initial estimate; can grow if needed. - - // Build local table of instruction start positions - process( - [&](spv::Op, unsigned start) { instPos.push_back(start); return true; }, - op_fn_nop); - - if (errorLatch) - return; - - // Window size for context-sensitive canonicalization values - // Empirical best size from a single data set. TODO: Would be a good tunable. - // We essentially perform a little convolution around each instruction, - // to capture the flavor of nearby code, to hopefully match to similar - // code in other modules. - static const unsigned windowSize = 2; - - for (unsigned entry = 0; entry < unsigned(instPos.size()); ++entry) { - const unsigned start = instPos[entry]; - const spv::Op opCode = asOpCode(start); - - if (opCode == spv::OpFunction) - fnId = asId(start + 2); - - if (opCode == spv::OpFunctionEnd) - fnId = spv::NoResult; - - if (fnId != spv::NoResult) { // if inside a function - if (spv::InstructionDesc[opCode].hasResult()) { - const unsigned word = start + (spv::InstructionDesc[opCode].hasType() ? 2 : 1); - const spv::Id resId = asId(word); - std::uint32_t hashval = fnId * 17; // small prime - - for (unsigned i = entry-1; i >= entry-windowSize; --i) { - if (asOpCode(instPos[i]) == spv::OpFunction) - break; - hashval = hashval * 30103 + asOpCodeHash(instPos[i]); // 30103 = semiarbitrary prime - } - - for (unsigned i = entry; i <= entry + windowSize; ++i) { - if (asOpCode(instPos[i]) == spv::OpFunctionEnd) - break; - hashval = hashval * 30103 + asOpCodeHash(instPos[i]); // 30103 = semiarbitrary prime - } - - if (isOldIdUnmapped(resId)) { - localId(resId, nextUnusedId(hashval % softTypeIdLimit + firstMappedID)); - if (errorLatch) - return; - } - - } - } - } - - spv::Op thisOpCode(spv::OpNop); - std::unordered_map opCounter; - int idCounter(0); - fnId = spv::NoResult; - - process( - [&](spv::Op opCode, unsigned start) { - switch (opCode) { - case spv::OpFunction: - // Reset counters at each function - idCounter = 0; - opCounter.clear(); - fnId = asId(start + 2); - break; - - case spv::OpImageSampleImplicitLod: - case spv::OpImageSampleExplicitLod: - case spv::OpImageSampleDrefImplicitLod: - case spv::OpImageSampleDrefExplicitLod: - case spv::OpImageSampleProjImplicitLod: - case spv::OpImageSampleProjExplicitLod: - case spv::OpImageSampleProjDrefImplicitLod: - case spv::OpImageSampleProjDrefExplicitLod: - case spv::OpDot: - case spv::OpCompositeExtract: - case spv::OpCompositeInsert: - case spv::OpVectorShuffle: - case spv::OpLabel: - case spv::OpVariable: - - case spv::OpAccessChain: - case spv::OpLoad: - case spv::OpStore: - case spv::OpCompositeConstruct: - case spv::OpFunctionCall: - ++opCounter[opCode]; - idCounter = 0; - thisOpCode = opCode; - break; - default: - thisOpCode = spv::OpNop; - } - - return false; - }, - - [&](spv::Id& id) { - if (thisOpCode != spv::OpNop) { - ++idCounter; - const std::uint32_t hashval = opCounter[thisOpCode] * thisOpCode * 50047 + idCounter + fnId * 117; - - if (isOldIdUnmapped(id)) - localId(id, nextUnusedId(hashval % softTypeIdLimit + firstMappedID)); - } - }); - } - - // EXPERIMENTAL: forward IO and uniform load/stores into operands - // This produces invalid Schema-0 SPIRV - void spirvbin_t::forwardLoadStores() - { - idset_t fnLocalVars; // set of function local vars - idmap_t idMap; // Map of load result IDs to what they load - - // EXPERIMENTAL: Forward input and access chain loads into consumptions - process( - [&](spv::Op opCode, unsigned start) { - // Add inputs and uniforms to the map - if ((opCode == spv::OpVariable && asWordCount(start) == 4) && - (spv[start+3] == spv::StorageClassUniform || - spv[start+3] == spv::StorageClassUniformConstant || - spv[start+3] == spv::StorageClassInput)) - fnLocalVars.insert(asId(start+2)); - - if (opCode == spv::OpAccessChain && fnLocalVars.count(asId(start+3)) > 0) - fnLocalVars.insert(asId(start+2)); - - if (opCode == spv::OpLoad && fnLocalVars.count(asId(start+3)) > 0) { - idMap[asId(start+2)] = asId(start+3); - stripInst(start); - } - - return false; - }, - - [&](spv::Id& id) { if (idMap.find(id) != idMap.end()) id = idMap[id]; } - ); - - if (errorLatch) - return; - - // EXPERIMENTAL: Implicit output stores - fnLocalVars.clear(); - idMap.clear(); - - process( - [&](spv::Op opCode, unsigned start) { - // Add inputs and uniforms to the map - if ((opCode == spv::OpVariable && asWordCount(start) == 4) && - (spv[start+3] == spv::StorageClassOutput)) - fnLocalVars.insert(asId(start+2)); - - if (opCode == spv::OpStore && fnLocalVars.count(asId(start+1)) > 0) { - idMap[asId(start+2)] = asId(start+1); - stripInst(start); - } - - return false; - }, - op_fn_nop); - - if (errorLatch) - return; - - process( - inst_fn_nop, - [&](spv::Id& id) { if (idMap.find(id) != idMap.end()) id = idMap[id]; } - ); - - if (errorLatch) - return; - - strip(); // strip out data we decided to eliminate - } - - // optimize loads and stores - void spirvbin_t::optLoadStore() - { - idset_t fnLocalVars; // candidates for removal (only locals) - idmap_t idMap; // Map of load result IDs to what they load - blockmap_t blockMap; // Map of IDs to blocks they first appear in - int blockNum = 0; // block count, to avoid crossing flow control - - // Find all the function local pointers stored at most once, and not via access chains - process( - [&](spv::Op opCode, unsigned start) { - const int wordCount = asWordCount(start); - - // Count blocks, so we can avoid crossing flow control - if (isFlowCtrl(opCode)) - ++blockNum; - - // Add local variables to the map - if ((opCode == spv::OpVariable && spv[start+3] == spv::StorageClassFunction && asWordCount(start) == 4)) { - fnLocalVars.insert(asId(start+2)); - return true; - } - - // Ignore process vars referenced via access chain - if ((opCode == spv::OpAccessChain || opCode == spv::OpInBoundsAccessChain) && fnLocalVars.count(asId(start+3)) > 0) { - fnLocalVars.erase(asId(start+3)); - idMap.erase(asId(start+3)); - return true; - } - - if (opCode == spv::OpLoad && fnLocalVars.count(asId(start+3)) > 0) { - const spv::Id varId = asId(start+3); - - // Avoid loads before stores - if (idMap.find(varId) == idMap.end()) { - fnLocalVars.erase(varId); - idMap.erase(varId); - } - - // don't do for volatile references - if (wordCount > 4 && (spv[start+4] & spv::MemoryAccessVolatileMask)) { - fnLocalVars.erase(varId); - idMap.erase(varId); - } - - // Handle flow control - if (blockMap.find(varId) == blockMap.end()) { - blockMap[varId] = blockNum; // track block we found it in. - } else if (blockMap[varId] != blockNum) { - fnLocalVars.erase(varId); // Ignore if crosses flow control - idMap.erase(varId); - } - - return true; - } - - if (opCode == spv::OpStore && fnLocalVars.count(asId(start+1)) > 0) { - const spv::Id varId = asId(start+1); - - if (idMap.find(varId) == idMap.end()) { - idMap[varId] = asId(start+2); - } else { - // Remove if it has more than one store to the same pointer - fnLocalVars.erase(varId); - idMap.erase(varId); - } - - // don't do for volatile references - if (wordCount > 3 && (spv[start+3] & spv::MemoryAccessVolatileMask)) { - fnLocalVars.erase(asId(start+3)); - idMap.erase(asId(start+3)); - } - - // Handle flow control - if (blockMap.find(varId) == blockMap.end()) { - blockMap[varId] = blockNum; // track block we found it in. - } else if (blockMap[varId] != blockNum) { - fnLocalVars.erase(varId); // Ignore if crosses flow control - idMap.erase(varId); - } - - return true; - } - - return false; - }, - - // If local var id used anywhere else, don't eliminate - [&](spv::Id& id) { - if (fnLocalVars.count(id) > 0) { - fnLocalVars.erase(id); - idMap.erase(id); - } - } - ); - - if (errorLatch) - return; - - process( - [&](spv::Op opCode, unsigned start) { - if (opCode == spv::OpLoad && fnLocalVars.count(asId(start+3)) > 0) - idMap[asId(start+2)] = idMap[asId(start+3)]; - return false; - }, - op_fn_nop); - - if (errorLatch) - return; - - // Chase replacements to their origins, in case there is a chain such as: - // 2 = store 1 - // 3 = load 2 - // 4 = store 3 - // 5 = load 4 - // We want to replace uses of 5 with 1. - for (const auto& idPair : idMap) { - spv::Id id = idPair.first; - while (idMap.find(id) != idMap.end()) // Chase to end of chain - id = idMap[id]; - - idMap[idPair.first] = id; // replace with final result - } - - // Remove the load/store/variables for the ones we've discovered - process( - [&](spv::Op opCode, unsigned start) { - if ((opCode == spv::OpLoad && fnLocalVars.count(asId(start+3)) > 0) || - (opCode == spv::OpStore && fnLocalVars.count(asId(start+1)) > 0) || - (opCode == spv::OpVariable && fnLocalVars.count(asId(start+2)) > 0)) { - - stripInst(start); - return true; - } - - return false; - }, - - [&](spv::Id& id) { - if (idMap.find(id) != idMap.end()) id = idMap[id]; - } - ); - - if (errorLatch) - return; - - strip(); // strip out data we decided to eliminate - } - - // remove bodies of uncalled functions - void spirvbin_t::dceFuncs() - { - msg(3, 2, std::string("Removing Dead Functions: ")); - - // TODO: There are more efficient ways to do this. - bool changed = true; - - while (changed) { - changed = false; - - for (auto fn = fnPos.begin(); fn != fnPos.end(); ) { - if (fn->first == entryPoint) { // don't DCE away the entry point! - ++fn; - continue; - } - - const auto call_it = fnCalls.find(fn->first); - - if (call_it == fnCalls.end() || call_it->second == 0) { - changed = true; - stripRange.push_back(fn->second); - - // decrease counts of called functions - process( - [&](spv::Op opCode, unsigned start) { - if (opCode == spv::Op::OpFunctionCall) { - const auto call_it = fnCalls.find(asId(start + 3)); - if (call_it != fnCalls.end()) { - if (--call_it->second <= 0) - fnCalls.erase(call_it); - } - } - - return true; - }, - op_fn_nop, - fn->second.first, - fn->second.second); - - if (errorLatch) - return; - - fn = fnPos.erase(fn); - } else ++fn; - } - } - } - - // remove unused function variables + decorations - void spirvbin_t::dceVars() - { - msg(3, 2, std::string("DCE Vars: ")); - - std::unordered_map varUseCount; - - // Count function variable use - process( - [&](spv::Op opCode, unsigned start) { - if (opCode == spv::OpVariable) { - ++varUseCount[asId(start+2)]; - return true; - } else if (opCode == spv::OpEntryPoint) { - const int wordCount = asWordCount(start); - for (int i = 4; i < wordCount; i++) { - ++varUseCount[asId(start+i)]; - } - return true; - } else - return false; - }, - - [&](spv::Id& id) { if (varUseCount[id]) ++varUseCount[id]; } - ); - - if (errorLatch) - return; - - // Remove single-use function variables + associated decorations and names - process( - [&](spv::Op opCode, unsigned start) { - spv::Id id = spv::NoResult; - if (opCode == spv::OpVariable) - id = asId(start+2); - if (opCode == spv::OpDecorate || opCode == spv::OpName) - id = asId(start+1); - - if (id != spv::NoResult && varUseCount[id] == 1) - stripInst(start); - - return true; - }, - op_fn_nop); - } - - // remove unused types - void spirvbin_t::dceTypes() - { - std::vector isType(bound(), false); - - // for speed, make O(1) way to get to type query (map is log(n)) - for (const auto typeStart : typeConstPos) - isType[asTypeConstId(typeStart)] = true; - - std::unordered_map typeUseCount; - - // This is not the most efficient algorithm, but this is an offline tool, and - // it's easy to write this way. Can be improved opportunistically if needed. - bool changed = true; - while (changed) { - changed = false; - strip(); - typeUseCount.clear(); - - // Count total type usage - process(inst_fn_nop, - [&](spv::Id& id) { if (isType[id]) ++typeUseCount[id]; } - ); - - if (errorLatch) - return; - - // Remove single reference types - for (const auto typeStart : typeConstPos) { - const spv::Id typeId = asTypeConstId(typeStart); - if (typeUseCount[typeId] == 1) { - changed = true; - --typeUseCount[typeId]; - stripInst(typeStart); - } - } - - if (errorLatch) - return; - } - } - -#ifdef NOTDEF - bool spirvbin_t::matchType(const spirvbin_t::globaltypes_t& globalTypes, spv::Id lt, spv::Id gt) const - { - // Find the local type id "lt" and global type id "gt" - const auto lt_it = typeConstPosR.find(lt); - if (lt_it == typeConstPosR.end()) - return false; - - const auto typeStart = lt_it->second; - - // Search for entry in global table - const auto gtype = globalTypes.find(gt); - if (gtype == globalTypes.end()) - return false; - - const auto& gdata = gtype->second; - - // local wordcount and opcode - const int wordCount = asWordCount(typeStart); - const spv::Op opCode = asOpCode(typeStart); - - // no type match if opcodes don't match, or operand count doesn't match - if (opCode != opOpCode(gdata[0]) || wordCount != opWordCount(gdata[0])) - return false; - - const unsigned numOperands = wordCount - 2; // all types have a result - - const auto cmpIdRange = [&](range_t range) { - for (int x=range.first; xsecond; - } - - // Hash types to canonical values. This can return ID collisions (it's a bit - // inevitable): it's up to the caller to handle that gracefully. - std::uint32_t spirvbin_t::hashType(unsigned typeStart) const - { - const unsigned wordCount = asWordCount(typeStart); - const spv::Op opCode = asOpCode(typeStart); - - switch (opCode) { - case spv::OpTypeVoid: return 0; - case spv::OpTypeBool: return 1; - case spv::OpTypeInt: return 3 + (spv[typeStart+3]); - case spv::OpTypeFloat: return 5; - case spv::OpTypeVector: - return 6 + hashType(idPos(spv[typeStart+2])) * (spv[typeStart+3] - 1); - case spv::OpTypeMatrix: - return 30 + hashType(idPos(spv[typeStart+2])) * (spv[typeStart+3] - 1); - case spv::OpTypeImage: - return 120 + hashType(idPos(spv[typeStart+2])) + - spv[typeStart+3] + // dimensionality - spv[typeStart+4] * 8 * 16 + // depth - spv[typeStart+5] * 4 * 16 + // arrayed - spv[typeStart+6] * 2 * 16 + // multisampled - spv[typeStart+7] * 1 * 16; // format - case spv::OpTypeSampler: - return 500; - case spv::OpTypeSampledImage: - return 502; - case spv::OpTypeArray: - return 501 + hashType(idPos(spv[typeStart+2])) * spv[typeStart+3]; - case spv::OpTypeRuntimeArray: - return 5000 + hashType(idPos(spv[typeStart+2])); - case spv::OpTypeStruct: - { - std::uint32_t hash = 10000; - for (unsigned w=2; w < wordCount; ++w) - hash += w * hashType(idPos(spv[typeStart+w])); - return hash; - } - - case spv::OpTypeOpaque: return 6000 + spv[typeStart+2]; - case spv::OpTypePointer: return 100000 + hashType(idPos(spv[typeStart+3])); - case spv::OpTypeFunction: - { - std::uint32_t hash = 200000; - for (unsigned w=2; w < wordCount; ++w) - hash += w * hashType(idPos(spv[typeStart+w])); - return hash; - } - - case spv::OpTypeEvent: return 300000; - case spv::OpTypeDeviceEvent: return 300001; - case spv::OpTypeReserveId: return 300002; - case spv::OpTypeQueue: return 300003; - case spv::OpTypePipe: return 300004; - - case spv::OpConstantNull: return 300005; - case spv::OpConstantSampler: return 300006; - - case spv::OpConstantTrue: return 300007; - case spv::OpConstantFalse: return 300008; - case spv::OpConstantComposite: - { - std::uint32_t hash = 300011 + hashType(idPos(spv[typeStart+1])); - for (unsigned w=3; w < wordCount; ++w) - hash += w * hashType(idPos(spv[typeStart+w])); - return hash; - } - case spv::OpConstant: - { - std::uint32_t hash = 400011 + hashType(idPos(spv[typeStart+1])); - for (unsigned w=3; w < wordCount; ++w) - hash += w * spv[typeStart+w]; - return hash; - } - - default: - error("unknown type opcode"); - return 0; - } - } - - void spirvbin_t::mapTypeConst() - { - globaltypes_t globalTypeMap; - - msg(3, 2, std::string("Remapping Consts & Types: ")); - - static const std::uint32_t softTypeIdLimit = 3011; // small prime. TODO: get from options - static const std::uint32_t firstMappedID = 8; // offset into ID space - - for (auto& typeStart : typeConstPos) { - const spv::Id resId = asTypeConstId(typeStart); - const std::uint32_t hashval = hashType(typeStart); - - if (errorLatch) - return; - - if (isOldIdUnmapped(resId)) { - localId(resId, nextUnusedId(hashval % softTypeIdLimit + firstMappedID)); - if (errorLatch) - return; - } - } - } - - // Strip a single binary by removing ranges given in stripRange - void spirvbin_t::strip() - { - if (stripRange.empty()) // nothing to do - return; - - // Sort strip ranges in order of traversal - std::sort(stripRange.begin(), stripRange.end()); - - // Allocate a new binary big enough to hold old binary - // We'll step this iterator through the strip ranges as we go through the binary - auto strip_it = stripRange.begin(); - - int strippedPos = 0; - for (unsigned word = 0; word < unsigned(spv.size()); ++word) { - while (strip_it != stripRange.end() && word >= strip_it->second) - ++strip_it; - - if (strip_it == stripRange.end() || word < strip_it->first || word >= strip_it->second) - spv[strippedPos++] = spv[word]; - } - - spv.resize(strippedPos); - stripRange.clear(); - - buildLocalMaps(); - } - - // Strip a single binary by removing ranges given in stripRange - void spirvbin_t::remap(std::uint32_t opts) - { - options = opts; - - // Set up opcode tables from SpvDoc - spv::Parameterize(); - - validate(); // validate header - buildLocalMaps(); // build ID maps - - msg(3, 4, std::string("ID bound: ") + std::to_string(bound())); - - if (options & STRIP) stripDebug(); - if (errorLatch) return; - - strip(); // strip out data we decided to eliminate - if (errorLatch) return; - - if (options & OPT_LOADSTORE) optLoadStore(); - if (errorLatch) return; - - if (options & OPT_FWD_LS) forwardLoadStores(); - if (errorLatch) return; - - if (options & DCE_FUNCS) dceFuncs(); - if (errorLatch) return; - - if (options & DCE_VARS) dceVars(); - if (errorLatch) return; - - if (options & DCE_TYPES) dceTypes(); - if (errorLatch) return; - - strip(); // strip out data we decided to eliminate - if (errorLatch) return; - - stripDeadRefs(); // remove references to things we DCEed - if (errorLatch) return; - - // after the last strip, we must clean any debug info referring to now-deleted data - - if (options & MAP_TYPES) mapTypeConst(); - if (errorLatch) return; - - if (options & MAP_NAMES) mapNames(); - if (errorLatch) return; - - if (options & MAP_FUNCS) mapFnBodies(); - if (errorLatch) return; - - if (options & MAP_ALL) { - mapRemainder(); // map any unmapped IDs - if (errorLatch) return; - - applyMap(); // Now remap each shader to the new IDs we've come up with - if (errorLatch) return; - } - } - - // remap from a memory image - void spirvbin_t::remap(std::vector& in_spv, std::uint32_t opts) - { - spv.swap(in_spv); - remap(opts); - spv.swap(in_spv); - } - -} // namespace SPV - -#endif // defined (use_cpp11) - diff --git a/External/glslang/SPIRV/SPVRemapper.h b/External/glslang/SPIRV/SPVRemapper.h deleted file mode 100644 index 97e3f31f..00000000 --- a/External/glslang/SPIRV/SPVRemapper.h +++ /dev/null @@ -1,304 +0,0 @@ -// -// Copyright (C) 2015 LunarG, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -#ifndef SPIRVREMAPPER_H -#define SPIRVREMAPPER_H - -#include -#include -#include -#include - -namespace spv { - -// MSVC defines __cplusplus as an older value, even when it supports almost all of 11. -// We handle that here by making our own symbol. -#if __cplusplus >= 201103L || _MSC_VER >= 1700 -# define use_cpp11 1 -#endif - -class spirvbin_base_t -{ -public: - enum Options { - NONE = 0, - STRIP = (1<<0), - MAP_TYPES = (1<<1), - MAP_NAMES = (1<<2), - MAP_FUNCS = (1<<3), - DCE_FUNCS = (1<<4), - DCE_VARS = (1<<5), - DCE_TYPES = (1<<6), - OPT_LOADSTORE = (1<<7), - OPT_FWD_LS = (1<<8), // EXPERIMENTAL: PRODUCES INVALID SCHEMA-0 SPIRV - MAP_ALL = (MAP_TYPES | MAP_NAMES | MAP_FUNCS), - DCE_ALL = (DCE_FUNCS | DCE_VARS | DCE_TYPES), - OPT_ALL = (OPT_LOADSTORE), - - ALL_BUT_STRIP = (MAP_ALL | DCE_ALL | OPT_ALL), - DO_EVERYTHING = (STRIP | ALL_BUT_STRIP) - }; -}; - -} // namespace SPV - -#if !defined (use_cpp11) -#include -#include - -namespace spv { -class spirvbin_t : public spirvbin_base_t -{ -public: - spirvbin_t(int /*verbose = 0*/) { } - - void remap(std::vector& /*spv*/, unsigned int /*opts = 0*/) - { - printf("Tool not compiled for C++11, which is required for SPIR-V remapping.\n"); - exit(5); - } -}; - -} // namespace SPV - -#else // defined (use_cpp11) - -#include -#include -#include -#include -#include -#include -#include - -#include "spirv.hpp" -#include "spvIR.h" - -namespace spv { - -// class to hold SPIR-V binary data for remapping, DCE, and debug stripping -class spirvbin_t : public spirvbin_base_t -{ -public: - spirvbin_t(int verbose = 0) : entryPoint(spv::NoResult), largestNewId(0), verbose(verbose), errorLatch(false) - { } - - virtual ~spirvbin_t() { } - - // remap on an existing binary in memory - void remap(std::vector& spv, std::uint32_t opts = DO_EVERYTHING); - - // Type for error/log handler functions - typedef std::function errorfn_t; - typedef std::function logfn_t; - - // Register error/log handling functions (can be lambda fn / functor / etc) - static void registerErrorHandler(errorfn_t handler) { errorHandler = handler; } - static void registerLogHandler(logfn_t handler) { logHandler = handler; } - -protected: - // This can be overridden to provide other message behavior if needed - virtual void msg(int minVerbosity, int indent, const std::string& txt) const; - -private: - // Local to global, or global to local ID map - typedef std::unordered_map idmap_t; - typedef std::unordered_set idset_t; - typedef std::unordered_map blockmap_t; - - void remap(std::uint32_t opts = DO_EVERYTHING); - - // Map of names to IDs - typedef std::unordered_map namemap_t; - - typedef std::uint32_t spirword_t; - - typedef std::pair range_t; - typedef std::function idfn_t; - typedef std::function instfn_t; - - // Special Values for ID map: - static const spv::Id unmapped; // unchanged from default value - static const spv::Id unused; // unused ID - static const int header_size; // SPIR header = 5 words - - class id_iterator_t; - - // For mapping type entries between different shaders - typedef std::vector typeentry_t; - typedef std::map globaltypes_t; - - // A set that preserves position order, and a reverse map - typedef std::set posmap_t; - typedef std::unordered_map posmap_rev_t; - - // Maps and ID to the size of its base type, if known. - typedef std::unordered_map typesize_map_t; - - // handle error - void error(const std::string& txt) const { errorLatch = true; errorHandler(txt); } - - bool isConstOp(spv::Op opCode) const; - bool isTypeOp(spv::Op opCode) const; - bool isStripOp(spv::Op opCode) const; - bool isFlowCtrl(spv::Op opCode) const; - range_t literalRange(spv::Op opCode) const; - range_t typeRange(spv::Op opCode) const; - range_t constRange(spv::Op opCode) const; - unsigned typeSizeInWords(spv::Id id) const; - unsigned idTypeSizeInWords(spv::Id id) const; - - spv::Id& asId(unsigned word) { return spv[word]; } - const spv::Id& asId(unsigned word) const { return spv[word]; } - spv::Op asOpCode(unsigned word) const { return opOpCode(spv[word]); } - std::uint32_t asOpCodeHash(unsigned word); - spv::Decoration asDecoration(unsigned word) const { return spv::Decoration(spv[word]); } - unsigned asWordCount(unsigned word) const { return opWordCount(spv[word]); } - spv::Id asTypeConstId(unsigned word) const { return asId(word + (isTypeOp(asOpCode(word)) ? 1 : 2)); } - unsigned idPos(spv::Id id) const; - - static unsigned opWordCount(spirword_t data) { return data >> spv::WordCountShift; } - static spv::Op opOpCode(spirword_t data) { return spv::Op(data & spv::OpCodeMask); } - - // Header access & set methods - spirword_t magic() const { return spv[0]; } // return magic number - spirword_t bound() const { return spv[3]; } // return Id bound from header - spirword_t bound(spirword_t b) { return spv[3] = b; }; - spirword_t genmagic() const { return spv[2]; } // generator magic - spirword_t genmagic(spirword_t m) { return spv[2] = m; } - spirword_t schemaNum() const { return spv[4]; } // schema number from header - - // Mapping fns: get - spv::Id localId(spv::Id id) const { return idMapL[id]; } - - // Mapping fns: set - inline spv::Id localId(spv::Id id, spv::Id newId); - void countIds(spv::Id id); - - // Return next unused new local ID. - // NOTE: boost::dynamic_bitset would be more efficient due to find_next(), - // which std::vector doens't have. - inline spv::Id nextUnusedId(spv::Id id); - - void buildLocalMaps(); - std::string literalString(unsigned word) const; // Return literal as a std::string - int literalStringWords(const std::string& str) const { return (int(str.size())+4)/4; } - - bool isNewIdMapped(spv::Id newId) const { return isMapped(newId); } - bool isOldIdUnmapped(spv::Id oldId) const { return localId(oldId) == unmapped; } - bool isOldIdUnused(spv::Id oldId) const { return localId(oldId) == unused; } - bool isOldIdMapped(spv::Id oldId) const { return !isOldIdUnused(oldId) && !isOldIdUnmapped(oldId); } - bool isFunction(spv::Id oldId) const { return fnPos.find(oldId) != fnPos.end(); } - - // bool matchType(const globaltypes_t& globalTypes, spv::Id lt, spv::Id gt) const; - // spv::Id findType(const globaltypes_t& globalTypes, spv::Id lt) const; - std::uint32_t hashType(unsigned typeStart) const; - - spirvbin_t& process(instfn_t, idfn_t, unsigned begin = 0, unsigned end = 0); - int processInstruction(unsigned word, instfn_t, idfn_t); - - void validate() const; - void mapTypeConst(); - void mapFnBodies(); - void optLoadStore(); - void dceFuncs(); - void dceVars(); - void dceTypes(); - void mapNames(); - void foldIds(); // fold IDs to smallest space - void forwardLoadStores(); // load store forwarding (EXPERIMENTAL) - void offsetIds(); // create relative offset IDs - - void applyMap(); // remap per local name map - void mapRemainder(); // map any IDs we haven't touched yet - void stripDebug(); // strip all debug info - void stripDeadRefs(); // strips debug info for now-dead references after DCE - void strip(); // remove debug symbols - - std::vector spv; // SPIR words - - namemap_t nameMap; // ID names from OpName - - // Since we want to also do binary ops, we can't use std::vector. we could use - // boost::dynamic_bitset, but we're trying to avoid a boost dependency. - typedef std::uint64_t bits_t; - std::vector mapped; // which new IDs have been mapped - static const int mBits = sizeof(bits_t) * 4; - - bool isMapped(spv::Id id) const { return id < maxMappedId() && ((mapped[id/mBits] & (1LL<<(id%mBits))) != 0); } - void setMapped(spv::Id id) { resizeMapped(id); mapped[id/mBits] |= (1LL<<(id%mBits)); } - void resizeMapped(spv::Id id) { if (id >= maxMappedId()) mapped.resize(id/mBits+1, 0); } - size_t maxMappedId() const { return mapped.size() * mBits; } - - // Add a strip range for a given instruction starting at 'start' - // Note: avoiding brace initializers to please older versions os MSVC. - void stripInst(unsigned start) { stripRange.push_back(range_t(start, start + asWordCount(start))); } - - // Function start and end. use unordered_map because we'll have - // many fewer functions than IDs. - std::unordered_map fnPos; - - // Which functions are called, anywhere in the module, with a call count - std::unordered_map fnCalls; - - posmap_t typeConstPos; // word positions that define types & consts (ordered) - posmap_rev_t idPosR; // reverse map from IDs to positions - typesize_map_t idTypeSizeMap; // maps each ID to its type size, if known. - - std::vector idMapL; // ID {M}ap from {L}ocal to {G}lobal IDs - - spv::Id entryPoint; // module entry point - spv::Id largestNewId; // biggest new ID we have mapped anything to - - // Sections of the binary to strip, given as [begin,end) - std::vector stripRange; - - // processing options: - std::uint32_t options; - int verbose; // verbosity level - - // Error latch: this is set if the error handler is ever executed. It would be better to - // use a try/catch block and throw, but that's not desired for certain environments, so - // this is the alternative. - mutable bool errorLatch; - - static errorfn_t errorHandler; - static logfn_t logHandler; -}; - -} // namespace SPV - -#endif // defined (use_cpp11) -#endif // SPIRVREMAPPER_H diff --git a/External/glslang/SPIRV/SpvBuilder.cpp b/External/glslang/SPIRV/SpvBuilder.cpp deleted file mode 100644 index 27ce71ca..00000000 --- a/External/glslang/SPIRV/SpvBuilder.cpp +++ /dev/null @@ -1,2775 +0,0 @@ -// -// Copyright (C) 2014-2015 LunarG, Inc. -// Copyright (C) 2015-2016 Google, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -// -// Helper for making SPIR-V IR. Generally, this is documented in the header -// SpvBuilder.h. -// - -#include -#include - -#include -#include - -#include "SpvBuilder.h" - -#include "hex_float.h" - -#ifndef _WIN32 - #include -#endif - -namespace spv { - -Builder::Builder(unsigned int spvVersion, unsigned int magicNumber, SpvBuildLogger* buildLogger) : - spvVersion(spvVersion), - source(SourceLanguageUnknown), - sourceVersion(0), - sourceFileStringId(NoResult), - currentLine(0), - emitOpLines(false), - addressModel(AddressingModelLogical), - memoryModel(MemoryModelGLSL450), - builderNumber(magicNumber), - buildPoint(0), - uniqueId(0), - entryPointFunction(0), - generatingOpCodeForSpecConst(false), - logger(buildLogger) -{ - clearAccessChain(); -} - -Builder::~Builder() -{ -} - -Id Builder::import(const char* name) -{ - Instruction* import = new Instruction(getUniqueId(), NoType, OpExtInstImport); - import->addStringOperand(name); - - imports.push_back(std::unique_ptr(import)); - return import->getResultId(); -} - -// Emit an OpLine if we've been asked to emit OpLines and the line number -// has changed since the last time, and is a valid line number. -void Builder::setLine(int lineNum) -{ - if (lineNum != 0 && lineNum != currentLine) { - currentLine = lineNum; - if (emitOpLines) - addLine(sourceFileStringId, currentLine, 0); - } -} - -void Builder::addLine(Id fileName, int lineNum, int column) -{ - Instruction* line = new Instruction(OpLine); - line->addIdOperand(fileName); - line->addImmediateOperand(lineNum); - line->addImmediateOperand(column); - buildPoint->addInstruction(std::unique_ptr(line)); -} - -// For creating new groupedTypes (will return old type if the requested one was already made). -Id Builder::makeVoidType() -{ - Instruction* type; - if (groupedTypes[OpTypeVoid].size() == 0) { - type = new Instruction(getUniqueId(), NoType, OpTypeVoid); - groupedTypes[OpTypeVoid].push_back(type); - constantsTypesGlobals.push_back(std::unique_ptr(type)); - module.mapInstruction(type); - } else - type = groupedTypes[OpTypeVoid].back(); - - return type->getResultId(); -} - -Id Builder::makeBoolType() -{ - Instruction* type; - if (groupedTypes[OpTypeBool].size() == 0) { - type = new Instruction(getUniqueId(), NoType, OpTypeBool); - groupedTypes[OpTypeBool].push_back(type); - constantsTypesGlobals.push_back(std::unique_ptr(type)); - module.mapInstruction(type); - } else - type = groupedTypes[OpTypeBool].back(); - - return type->getResultId(); -} - -Id Builder::makeSamplerType() -{ - Instruction* type; - if (groupedTypes[OpTypeSampler].size() == 0) { - type = new Instruction(getUniqueId(), NoType, OpTypeSampler); - groupedTypes[OpTypeSampler].push_back(type); - constantsTypesGlobals.push_back(std::unique_ptr(type)); - module.mapInstruction(type); - } else - type = groupedTypes[OpTypeSampler].back(); - - return type->getResultId(); -} - -Id Builder::makePointer(StorageClass storageClass, Id pointee) -{ - // try to find it - Instruction* type; - for (int t = 0; t < (int)groupedTypes[OpTypePointer].size(); ++t) { - type = groupedTypes[OpTypePointer][t]; - if (type->getImmediateOperand(0) == (unsigned)storageClass && - type->getIdOperand(1) == pointee) - return type->getResultId(); - } - - // not found, make it - type = new Instruction(getUniqueId(), NoType, OpTypePointer); - type->addImmediateOperand(storageClass); - type->addIdOperand(pointee); - groupedTypes[OpTypePointer].push_back(type); - constantsTypesGlobals.push_back(std::unique_ptr(type)); - module.mapInstruction(type); - - return type->getResultId(); -} - -Id Builder::makeIntegerType(int width, bool hasSign) -{ - // try to find it - Instruction* type; - for (int t = 0; t < (int)groupedTypes[OpTypeInt].size(); ++t) { - type = groupedTypes[OpTypeInt][t]; - if (type->getImmediateOperand(0) == (unsigned)width && - type->getImmediateOperand(1) == (hasSign ? 1u : 0u)) - return type->getResultId(); - } - - // not found, make it - type = new Instruction(getUniqueId(), NoType, OpTypeInt); - type->addImmediateOperand(width); - type->addImmediateOperand(hasSign ? 1 : 0); - groupedTypes[OpTypeInt].push_back(type); - constantsTypesGlobals.push_back(std::unique_ptr(type)); - module.mapInstruction(type); - - // deal with capabilities - switch (width) { - case 8: - addCapability(CapabilityInt8); - break; - case 16: - addCapability(CapabilityInt16); - break; - case 64: - addCapability(CapabilityInt64); - break; - default: - break; - } - - return type->getResultId(); -} - -Id Builder::makeFloatType(int width) -{ - // try to find it - Instruction* type; - for (int t = 0; t < (int)groupedTypes[OpTypeFloat].size(); ++t) { - type = groupedTypes[OpTypeFloat][t]; - if (type->getImmediateOperand(0) == (unsigned)width) - return type->getResultId(); - } - - // not found, make it - type = new Instruction(getUniqueId(), NoType, OpTypeFloat); - type->addImmediateOperand(width); - groupedTypes[OpTypeFloat].push_back(type); - constantsTypesGlobals.push_back(std::unique_ptr(type)); - module.mapInstruction(type); - - // deal with capabilities - switch (width) { - case 16: - addCapability(CapabilityFloat16); - break; - case 64: - addCapability(CapabilityFloat64); - break; - default: - break; - } - - return type->getResultId(); -} - -// Make a struct without checking for duplication. -// See makeStructResultType() for non-decorated structs -// needed as the result of some instructions, which does -// check for duplicates. -Id Builder::makeStructType(const std::vector& members, const char* name) -{ - // Don't look for previous one, because in the general case, - // structs can be duplicated except for decorations. - - // not found, make it - Instruction* type = new Instruction(getUniqueId(), NoType, OpTypeStruct); - for (int op = 0; op < (int)members.size(); ++op) - type->addIdOperand(members[op]); - groupedTypes[OpTypeStruct].push_back(type); - constantsTypesGlobals.push_back(std::unique_ptr(type)); - module.mapInstruction(type); - addName(type->getResultId(), name); - - return type->getResultId(); -} - -// Make a struct for the simple results of several instructions, -// checking for duplication. -Id Builder::makeStructResultType(Id type0, Id type1) -{ - // try to find it - Instruction* type; - for (int t = 0; t < (int)groupedTypes[OpTypeStruct].size(); ++t) { - type = groupedTypes[OpTypeStruct][t]; - if (type->getNumOperands() != 2) - continue; - if (type->getIdOperand(0) != type0 || - type->getIdOperand(1) != type1) - continue; - return type->getResultId(); - } - - // not found, make it - std::vector members; - members.push_back(type0); - members.push_back(type1); - - return makeStructType(members, "ResType"); -} - -Id Builder::makeVectorType(Id component, int size) -{ - // try to find it - Instruction* type; - for (int t = 0; t < (int)groupedTypes[OpTypeVector].size(); ++t) { - type = groupedTypes[OpTypeVector][t]; - if (type->getIdOperand(0) == component && - type->getImmediateOperand(1) == (unsigned)size) - return type->getResultId(); - } - - // not found, make it - type = new Instruction(getUniqueId(), NoType, OpTypeVector); - type->addIdOperand(component); - type->addImmediateOperand(size); - groupedTypes[OpTypeVector].push_back(type); - constantsTypesGlobals.push_back(std::unique_ptr(type)); - module.mapInstruction(type); - - return type->getResultId(); -} - -Id Builder::makeMatrixType(Id component, int cols, int rows) -{ - assert(cols <= maxMatrixSize && rows <= maxMatrixSize); - - Id column = makeVectorType(component, rows); - - // try to find it - Instruction* type; - for (int t = 0; t < (int)groupedTypes[OpTypeMatrix].size(); ++t) { - type = groupedTypes[OpTypeMatrix][t]; - if (type->getIdOperand(0) == column && - type->getImmediateOperand(1) == (unsigned)cols) - return type->getResultId(); - } - - // not found, make it - type = new Instruction(getUniqueId(), NoType, OpTypeMatrix); - type->addIdOperand(column); - type->addImmediateOperand(cols); - groupedTypes[OpTypeMatrix].push_back(type); - constantsTypesGlobals.push_back(std::unique_ptr(type)); - module.mapInstruction(type); - - return type->getResultId(); -} - -// TODO: performance: track arrays per stride -// If a stride is supplied (non-zero) make an array. -// If no stride (0), reuse previous array types. -// 'size' is an Id of a constant or specialization constant of the array size -Id Builder::makeArrayType(Id element, Id sizeId, int stride) -{ - Instruction* type; - if (stride == 0) { - // try to find existing type - for (int t = 0; t < (int)groupedTypes[OpTypeArray].size(); ++t) { - type = groupedTypes[OpTypeArray][t]; - if (type->getIdOperand(0) == element && - type->getIdOperand(1) == sizeId) - return type->getResultId(); - } - } - - // not found, make it - type = new Instruction(getUniqueId(), NoType, OpTypeArray); - type->addIdOperand(element); - type->addIdOperand(sizeId); - groupedTypes[OpTypeArray].push_back(type); - constantsTypesGlobals.push_back(std::unique_ptr(type)); - module.mapInstruction(type); - - return type->getResultId(); -} - -Id Builder::makeRuntimeArray(Id element) -{ - Instruction* type = new Instruction(getUniqueId(), NoType, OpTypeRuntimeArray); - type->addIdOperand(element); - constantsTypesGlobals.push_back(std::unique_ptr(type)); - module.mapInstruction(type); - - return type->getResultId(); -} - -Id Builder::makeFunctionType(Id returnType, const std::vector& paramTypes) -{ - // try to find it - Instruction* type; - for (int t = 0; t < (int)groupedTypes[OpTypeFunction].size(); ++t) { - type = groupedTypes[OpTypeFunction][t]; - if (type->getIdOperand(0) != returnType || (int)paramTypes.size() != type->getNumOperands() - 1) - continue; - bool mismatch = false; - for (int p = 0; p < (int)paramTypes.size(); ++p) { - if (paramTypes[p] != type->getIdOperand(p + 1)) { - mismatch = true; - break; - } - } - if (! mismatch) - return type->getResultId(); - } - - // not found, make it - type = new Instruction(getUniqueId(), NoType, OpTypeFunction); - type->addIdOperand(returnType); - for (int p = 0; p < (int)paramTypes.size(); ++p) - type->addIdOperand(paramTypes[p]); - groupedTypes[OpTypeFunction].push_back(type); - constantsTypesGlobals.push_back(std::unique_ptr(type)); - module.mapInstruction(type); - - return type->getResultId(); -} - -Id Builder::makeImageType(Id sampledType, Dim dim, bool depth, bool arrayed, bool ms, unsigned sampled, ImageFormat format) -{ - assert(sampled == 1 || sampled == 2); - - // try to find it - Instruction* type; - for (int t = 0; t < (int)groupedTypes[OpTypeImage].size(); ++t) { - type = groupedTypes[OpTypeImage][t]; - if (type->getIdOperand(0) == sampledType && - type->getImmediateOperand(1) == (unsigned int)dim && - type->getImmediateOperand(2) == ( depth ? 1u : 0u) && - type->getImmediateOperand(3) == (arrayed ? 1u : 0u) && - type->getImmediateOperand(4) == ( ms ? 1u : 0u) && - type->getImmediateOperand(5) == sampled && - type->getImmediateOperand(6) == (unsigned int)format) - return type->getResultId(); - } - - // not found, make it - type = new Instruction(getUniqueId(), NoType, OpTypeImage); - type->addIdOperand(sampledType); - type->addImmediateOperand( dim); - type->addImmediateOperand( depth ? 1 : 0); - type->addImmediateOperand(arrayed ? 1 : 0); - type->addImmediateOperand( ms ? 1 : 0); - type->addImmediateOperand(sampled); - type->addImmediateOperand((unsigned int)format); - - groupedTypes[OpTypeImage].push_back(type); - constantsTypesGlobals.push_back(std::unique_ptr(type)); - module.mapInstruction(type); - - // deal with capabilities - switch (dim) { - case DimBuffer: - if (sampled == 1) - addCapability(CapabilitySampledBuffer); - else - addCapability(CapabilityImageBuffer); - break; - case Dim1D: - if (sampled == 1) - addCapability(CapabilitySampled1D); - else - addCapability(CapabilityImage1D); - break; - case DimCube: - if (arrayed) { - if (sampled == 1) - addCapability(CapabilitySampledCubeArray); - else - addCapability(CapabilityImageCubeArray); - } - break; - case DimRect: - if (sampled == 1) - addCapability(CapabilitySampledRect); - else - addCapability(CapabilityImageRect); - break; - case DimSubpassData: - addCapability(CapabilityInputAttachment); - break; - default: - break; - } - - if (ms) { - if (sampled == 2) { - // Images used with subpass data are not storage - // images, so don't require the capability for them. - if (dim != Dim::DimSubpassData) - addCapability(CapabilityStorageImageMultisample); - if (arrayed) - addCapability(CapabilityImageMSArray); - } - } - - return type->getResultId(); -} - -Id Builder::makeSampledImageType(Id imageType) -{ - // try to find it - Instruction* type; - for (int t = 0; t < (int)groupedTypes[OpTypeSampledImage].size(); ++t) { - type = groupedTypes[OpTypeSampledImage][t]; - if (type->getIdOperand(0) == imageType) - return type->getResultId(); - } - - // not found, make it - type = new Instruction(getUniqueId(), NoType, OpTypeSampledImage); - type->addIdOperand(imageType); - - groupedTypes[OpTypeSampledImage].push_back(type); - constantsTypesGlobals.push_back(std::unique_ptr(type)); - module.mapInstruction(type); - - return type->getResultId(); -} - -Id Builder::getDerefTypeId(Id resultId) const -{ - Id typeId = getTypeId(resultId); - assert(isPointerType(typeId)); - - return module.getInstruction(typeId)->getImmediateOperand(1); -} - -Op Builder::getMostBasicTypeClass(Id typeId) const -{ - Instruction* instr = module.getInstruction(typeId); - - Op typeClass = instr->getOpCode(); - switch (typeClass) - { - case OpTypeVoid: - case OpTypeBool: - case OpTypeInt: - case OpTypeFloat: - case OpTypeStruct: - return typeClass; - case OpTypeVector: - case OpTypeMatrix: - case OpTypeArray: - case OpTypeRuntimeArray: - return getMostBasicTypeClass(instr->getIdOperand(0)); - case OpTypePointer: - return getMostBasicTypeClass(instr->getIdOperand(1)); - default: - assert(0); - return OpTypeFloat; - } -} - -int Builder::getNumTypeConstituents(Id typeId) const -{ - Instruction* instr = module.getInstruction(typeId); - - switch (instr->getOpCode()) - { - case OpTypeBool: - case OpTypeInt: - case OpTypeFloat: - return 1; - case OpTypeVector: - case OpTypeMatrix: - return instr->getImmediateOperand(1); - case OpTypeArray: - { - Id lengthId = instr->getImmediateOperand(1); - return module.getInstruction(lengthId)->getImmediateOperand(0); - } - case OpTypeStruct: - return instr->getNumOperands(); - default: - assert(0); - return 1; - } -} - -// Return the lowest-level type of scalar that an homogeneous composite is made out of. -// Typically, this is just to find out if something is made out of ints or floats. -// However, it includes returning a structure, if say, it is an array of structure. -Id Builder::getScalarTypeId(Id typeId) const -{ - Instruction* instr = module.getInstruction(typeId); - - Op typeClass = instr->getOpCode(); - switch (typeClass) - { - case OpTypeVoid: - case OpTypeBool: - case OpTypeInt: - case OpTypeFloat: - case OpTypeStruct: - return instr->getResultId(); - case OpTypeVector: - case OpTypeMatrix: - case OpTypeArray: - case OpTypeRuntimeArray: - case OpTypePointer: - return getScalarTypeId(getContainedTypeId(typeId)); - default: - assert(0); - return NoResult; - } -} - -// Return the type of 'member' of a composite. -Id Builder::getContainedTypeId(Id typeId, int member) const -{ - Instruction* instr = module.getInstruction(typeId); - - Op typeClass = instr->getOpCode(); - switch (typeClass) - { - case OpTypeVector: - case OpTypeMatrix: - case OpTypeArray: - case OpTypeRuntimeArray: - return instr->getIdOperand(0); - case OpTypePointer: - return instr->getIdOperand(1); - case OpTypeStruct: - return instr->getIdOperand(member); - default: - assert(0); - return NoResult; - } -} - -// Return the immediately contained type of a given composite type. -Id Builder::getContainedTypeId(Id typeId) const -{ - return getContainedTypeId(typeId, 0); -} - -// See if a scalar constant of this type has already been created, so it -// can be reused rather than duplicated. (Required by the specification). -Id Builder::findScalarConstant(Op typeClass, Op opcode, Id typeId, unsigned value) -{ - Instruction* constant; - for (int i = 0; i < (int)groupedConstants[typeClass].size(); ++i) { - constant = groupedConstants[typeClass][i]; - if (constant->getOpCode() == opcode && - constant->getTypeId() == typeId && - constant->getImmediateOperand(0) == value) - return constant->getResultId(); - } - - return 0; -} - -// Version of findScalarConstant (see above) for scalars that take two operands (e.g. a 'double' or 'int64'). -Id Builder::findScalarConstant(Op typeClass, Op opcode, Id typeId, unsigned v1, unsigned v2) -{ - Instruction* constant; - for (int i = 0; i < (int)groupedConstants[typeClass].size(); ++i) { - constant = groupedConstants[typeClass][i]; - if (constant->getOpCode() == opcode && - constant->getTypeId() == typeId && - constant->getImmediateOperand(0) == v1 && - constant->getImmediateOperand(1) == v2) - return constant->getResultId(); - } - - return 0; -} - -// Return true if consuming 'opcode' means consuming a constant. -// "constant" here means after final transform to executable code, -// the value consumed will be a constant, so includes specialization. -bool Builder::isConstantOpCode(Op opcode) const -{ - switch (opcode) { - case OpUndef: - case OpConstantTrue: - case OpConstantFalse: - case OpConstant: - case OpConstantComposite: - case OpConstantSampler: - case OpConstantNull: - case OpSpecConstantTrue: - case OpSpecConstantFalse: - case OpSpecConstant: - case OpSpecConstantComposite: - case OpSpecConstantOp: - return true; - default: - return false; - } -} - -// Return true if consuming 'opcode' means consuming a specialization constant. -bool Builder::isSpecConstantOpCode(Op opcode) const -{ - switch (opcode) { - case OpSpecConstantTrue: - case OpSpecConstantFalse: - case OpSpecConstant: - case OpSpecConstantComposite: - case OpSpecConstantOp: - return true; - default: - return false; - } -} - -Id Builder::makeBoolConstant(bool b, bool specConstant) -{ - Id typeId = makeBoolType(); - Instruction* constant; - Op opcode = specConstant ? (b ? OpSpecConstantTrue : OpSpecConstantFalse) : (b ? OpConstantTrue : OpConstantFalse); - - // See if we already made it. Applies only to regular constants, because specialization constants - // must remain distinct for the purpose of applying a SpecId decoration. - if (! specConstant) { - Id existing = 0; - for (int i = 0; i < (int)groupedConstants[OpTypeBool].size(); ++i) { - constant = groupedConstants[OpTypeBool][i]; - if (constant->getTypeId() == typeId && constant->getOpCode() == opcode) - existing = constant->getResultId(); - } - - if (existing) - return existing; - } - - // Make it - Instruction* c = new Instruction(getUniqueId(), typeId, opcode); - constantsTypesGlobals.push_back(std::unique_ptr(c)); - groupedConstants[OpTypeBool].push_back(c); - module.mapInstruction(c); - - return c->getResultId(); -} - -Id Builder::makeIntConstant(Id typeId, unsigned value, bool specConstant) -{ - Op opcode = specConstant ? OpSpecConstant : OpConstant; - - // See if we already made it. Applies only to regular constants, because specialization constants - // must remain distinct for the purpose of applying a SpecId decoration. - if (! specConstant) { - Id existing = findScalarConstant(OpTypeInt, opcode, typeId, value); - if (existing) - return existing; - } - - Instruction* c = new Instruction(getUniqueId(), typeId, opcode); - c->addImmediateOperand(value); - constantsTypesGlobals.push_back(std::unique_ptr(c)); - groupedConstants[OpTypeInt].push_back(c); - module.mapInstruction(c); - - return c->getResultId(); -} - -Id Builder::makeInt64Constant(Id typeId, unsigned long long value, bool specConstant) -{ - Op opcode = specConstant ? OpSpecConstant : OpConstant; - - unsigned op1 = value & 0xFFFFFFFF; - unsigned op2 = value >> 32; - - // See if we already made it. Applies only to regular constants, because specialization constants - // must remain distinct for the purpose of applying a SpecId decoration. - if (! specConstant) { - Id existing = findScalarConstant(OpTypeInt, opcode, typeId, op1, op2); - if (existing) - return existing; - } - - Instruction* c = new Instruction(getUniqueId(), typeId, opcode); - c->addImmediateOperand(op1); - c->addImmediateOperand(op2); - constantsTypesGlobals.push_back(std::unique_ptr(c)); - groupedConstants[OpTypeInt].push_back(c); - module.mapInstruction(c); - - return c->getResultId(); -} - -Id Builder::makeFloatConstant(float f, bool specConstant) -{ - Op opcode = specConstant ? OpSpecConstant : OpConstant; - Id typeId = makeFloatType(32); - union { float fl; unsigned int ui; } u; - u.fl = f; - unsigned value = u.ui; - - // See if we already made it. Applies only to regular constants, because specialization constants - // must remain distinct for the purpose of applying a SpecId decoration. - if (! specConstant) { - Id existing = findScalarConstant(OpTypeFloat, opcode, typeId, value); - if (existing) - return existing; - } - - Instruction* c = new Instruction(getUniqueId(), typeId, opcode); - c->addImmediateOperand(value); - constantsTypesGlobals.push_back(std::unique_ptr(c)); - groupedConstants[OpTypeFloat].push_back(c); - module.mapInstruction(c); - - return c->getResultId(); -} - -Id Builder::makeDoubleConstant(double d, bool specConstant) -{ - Op opcode = specConstant ? OpSpecConstant : OpConstant; - Id typeId = makeFloatType(64); - union { double db; unsigned long long ull; } u; - u.db = d; - unsigned long long value = u.ull; - unsigned op1 = value & 0xFFFFFFFF; - unsigned op2 = value >> 32; - - // See if we already made it. Applies only to regular constants, because specialization constants - // must remain distinct for the purpose of applying a SpecId decoration. - if (! specConstant) { - Id existing = findScalarConstant(OpTypeFloat, opcode, typeId, op1, op2); - if (existing) - return existing; - } - - Instruction* c = new Instruction(getUniqueId(), typeId, opcode); - c->addImmediateOperand(op1); - c->addImmediateOperand(op2); - constantsTypesGlobals.push_back(std::unique_ptr(c)); - groupedConstants[OpTypeFloat].push_back(c); - module.mapInstruction(c); - - return c->getResultId(); -} - -Id Builder::makeFloat16Constant(float f16, bool specConstant) -{ - Op opcode = specConstant ? OpSpecConstant : OpConstant; - Id typeId = makeFloatType(16); - - spvutils::HexFloat> fVal(f16); - spvutils::HexFloat> f16Val(0); - fVal.castTo(f16Val, spvutils::kRoundToZero); - - unsigned value = f16Val.value().getAsFloat().get_value(); - - // See if we already made it. Applies only to regular constants, because specialization constants - // must remain distinct for the purpose of applying a SpecId decoration. - if (!specConstant) { - Id existing = findScalarConstant(OpTypeFloat, opcode, typeId, value); - if (existing) - return existing; - } - - Instruction* c = new Instruction(getUniqueId(), typeId, opcode); - c->addImmediateOperand(value); - constantsTypesGlobals.push_back(std::unique_ptr(c)); - groupedConstants[OpTypeFloat].push_back(c); - module.mapInstruction(c); - - return c->getResultId(); -} - -Id Builder::makeFpConstant(Id type, double d, bool specConstant) -{ - assert(isFloatType(type)); - - switch (getScalarTypeWidth(type)) { - case 16: - return makeFloat16Constant((float)d, specConstant); - case 32: - return makeFloatConstant((float)d, specConstant); - case 64: - return makeDoubleConstant(d, specConstant); - default: - break; - } - - assert(false); - return NoResult; -} - -Id Builder::findCompositeConstant(Op typeClass, const std::vector& comps) -{ - Instruction* constant = 0; - bool found = false; - for (int i = 0; i < (int)groupedConstants[typeClass].size(); ++i) { - constant = groupedConstants[typeClass][i]; - - // same shape? - if (constant->getNumOperands() != (int)comps.size()) - continue; - - // same contents? - bool mismatch = false; - for (int op = 0; op < constant->getNumOperands(); ++op) { - if (constant->getIdOperand(op) != comps[op]) { - mismatch = true; - break; - } - } - if (! mismatch) { - found = true; - break; - } - } - - return found ? constant->getResultId() : NoResult; -} - -Id Builder::findStructConstant(Id typeId, const std::vector& comps) -{ - Instruction* constant = 0; - bool found = false; - for (int i = 0; i < (int)groupedStructConstants[typeId].size(); ++i) { - constant = groupedStructConstants[typeId][i]; - - // same contents? - bool mismatch = false; - for (int op = 0; op < constant->getNumOperands(); ++op) { - if (constant->getIdOperand(op) != comps[op]) { - mismatch = true; - break; - } - } - if (! mismatch) { - found = true; - break; - } - } - - return found ? constant->getResultId() : NoResult; -} - -// Comments in header -Id Builder::makeCompositeConstant(Id typeId, const std::vector& members, bool specConstant) -{ - Op opcode = specConstant ? OpSpecConstantComposite : OpConstantComposite; - assert(typeId); - Op typeClass = getTypeClass(typeId); - - switch (typeClass) { - case OpTypeVector: - case OpTypeArray: - case OpTypeMatrix: - if (! specConstant) { - Id existing = findCompositeConstant(typeClass, members); - if (existing) - return existing; - } - break; - case OpTypeStruct: - if (! specConstant) { - Id existing = findStructConstant(typeId, members); - if (existing) - return existing; - } - break; - default: - assert(0); - return makeFloatConstant(0.0); - } - - Instruction* c = new Instruction(getUniqueId(), typeId, opcode); - for (int op = 0; op < (int)members.size(); ++op) - c->addIdOperand(members[op]); - constantsTypesGlobals.push_back(std::unique_ptr(c)); - if (typeClass == OpTypeStruct) - groupedStructConstants[typeId].push_back(c); - else - groupedConstants[typeClass].push_back(c); - module.mapInstruction(c); - - return c->getResultId(); -} - -Instruction* Builder::addEntryPoint(ExecutionModel model, Function* function, const char* name) -{ - Instruction* entryPoint = new Instruction(OpEntryPoint); - entryPoint->addImmediateOperand(model); - entryPoint->addIdOperand(function->getId()); - entryPoint->addStringOperand(name); - - entryPoints.push_back(std::unique_ptr(entryPoint)); - - return entryPoint; -} - -// Currently relying on the fact that all 'value' of interest are small non-negative values. -void Builder::addExecutionMode(Function* entryPoint, ExecutionMode mode, int value1, int value2, int value3) -{ - Instruction* instr = new Instruction(OpExecutionMode); - instr->addIdOperand(entryPoint->getId()); - instr->addImmediateOperand(mode); - if (value1 >= 0) - instr->addImmediateOperand(value1); - if (value2 >= 0) - instr->addImmediateOperand(value2); - if (value3 >= 0) - instr->addImmediateOperand(value3); - - executionModes.push_back(std::unique_ptr(instr)); -} - -void Builder::addName(Id id, const char* string) -{ - Instruction* name = new Instruction(OpName); - name->addIdOperand(id); - name->addStringOperand(string); - - names.push_back(std::unique_ptr(name)); -} - -void Builder::addMemberName(Id id, int memberNumber, const char* string) -{ - Instruction* name = new Instruction(OpMemberName); - name->addIdOperand(id); - name->addImmediateOperand(memberNumber); - name->addStringOperand(string); - - names.push_back(std::unique_ptr(name)); -} - -void Builder::addDecoration(Id id, Decoration decoration, int num) -{ - if (decoration == spv::DecorationMax) - return; - - Instruction* dec = new Instruction(OpDecorate); - dec->addIdOperand(id); - dec->addImmediateOperand(decoration); - if (num >= 0) - dec->addImmediateOperand(num); - - decorations.push_back(std::unique_ptr(dec)); -} - -void Builder::addDecoration(Id id, Decoration decoration, const char* s) -{ - if (decoration == spv::DecorationMax) - return; - - Instruction* dec = new Instruction(OpDecorateStringGOOGLE); - dec->addIdOperand(id); - dec->addImmediateOperand(decoration); - dec->addStringOperand(s); - - decorations.push_back(std::unique_ptr(dec)); -} - -void Builder::addDecorationId(Id id, Decoration decoration, Id idDecoration) -{ - if (decoration == spv::DecorationMax) - return; - - Instruction* dec = new Instruction(OpDecorateId); - dec->addIdOperand(id); - dec->addImmediateOperand(decoration); - dec->addIdOperand(idDecoration); - - decorations.push_back(std::unique_ptr(dec)); -} - -void Builder::addMemberDecoration(Id id, unsigned int member, Decoration decoration, int num) -{ - if (decoration == spv::DecorationMax) - return; - - Instruction* dec = new Instruction(OpMemberDecorate); - dec->addIdOperand(id); - dec->addImmediateOperand(member); - dec->addImmediateOperand(decoration); - if (num >= 0) - dec->addImmediateOperand(num); - - decorations.push_back(std::unique_ptr(dec)); -} - -void Builder::addMemberDecoration(Id id, unsigned int member, Decoration decoration, const char *s) -{ - if (decoration == spv::DecorationMax) - return; - - Instruction* dec = new Instruction(OpMemberDecorateStringGOOGLE); - dec->addIdOperand(id); - dec->addImmediateOperand(member); - dec->addImmediateOperand(decoration); - dec->addStringOperand(s); - - decorations.push_back(std::unique_ptr(dec)); -} - -// Comments in header -Function* Builder::makeEntryPoint(const char* entryPoint) -{ - assert(! entryPointFunction); - - Block* entry; - std::vector params; - std::vector> decorations; - - entryPointFunction = makeFunctionEntry(NoPrecision, makeVoidType(), entryPoint, params, decorations, &entry); - - return entryPointFunction; -} - -// Comments in header -Function* Builder::makeFunctionEntry(Decoration precision, Id returnType, const char* name, - const std::vector& paramTypes, const std::vector>& decorations, Block **entry) -{ - // Make the function and initial instructions in it - Id typeId = makeFunctionType(returnType, paramTypes); - Id firstParamId = paramTypes.size() == 0 ? 0 : getUniqueIds((int)paramTypes.size()); - Function* function = new Function(getUniqueId(), returnType, typeId, firstParamId, module); - - // Set up the precisions - setPrecision(function->getId(), precision); - for (unsigned p = 0; p < (unsigned)decorations.size(); ++p) { - for (int d = 0; d < (int)decorations[p].size(); ++d) - addDecoration(firstParamId + p, decorations[p][d]); - } - - // CFG - if (entry) { - *entry = new Block(getUniqueId(), *function); - function->addBlock(*entry); - setBuildPoint(*entry); - } - - if (name) - addName(function->getId(), name); - - functions.push_back(std::unique_ptr(function)); - - return function; -} - -// Comments in header -void Builder::makeReturn(bool implicit, Id retVal) -{ - if (retVal) { - Instruction* inst = new Instruction(NoResult, NoType, OpReturnValue); - inst->addIdOperand(retVal); - buildPoint->addInstruction(std::unique_ptr(inst)); - } else - buildPoint->addInstruction(std::unique_ptr(new Instruction(NoResult, NoType, OpReturn))); - - if (! implicit) - createAndSetNoPredecessorBlock("post-return"); -} - -// Comments in header -void Builder::leaveFunction() -{ - Block* block = buildPoint; - Function& function = buildPoint->getParent(); - assert(block); - - // If our function did not contain a return, add a return void now. - if (! block->isTerminated()) { - if (function.getReturnType() == makeVoidType()) - makeReturn(true); - else { - makeReturn(true, createUndefined(function.getReturnType())); - } - } -} - -// Comments in header -void Builder::makeDiscard() -{ - buildPoint->addInstruction(std::unique_ptr(new Instruction(OpKill))); - createAndSetNoPredecessorBlock("post-discard"); -} - -// Comments in header -Id Builder::createVariable(StorageClass storageClass, Id type, const char* name) -{ - Id pointerType = makePointer(storageClass, type); - Instruction* inst = new Instruction(getUniqueId(), pointerType, OpVariable); - inst->addImmediateOperand(storageClass); - - switch (storageClass) { - case StorageClassFunction: - // Validation rules require the declaration in the entry block - buildPoint->getParent().addLocalVariable(std::unique_ptr(inst)); - break; - - default: - constantsTypesGlobals.push_back(std::unique_ptr(inst)); - module.mapInstruction(inst); - break; - } - - if (name) - addName(inst->getResultId(), name); - - return inst->getResultId(); -} - -// Comments in header -Id Builder::createUndefined(Id type) -{ - Instruction* inst = new Instruction(getUniqueId(), type, OpUndef); - buildPoint->addInstruction(std::unique_ptr(inst)); - return inst->getResultId(); -} - -// Comments in header -void Builder::createStore(Id rValue, Id lValue) -{ - Instruction* store = new Instruction(OpStore); - store->addIdOperand(lValue); - store->addIdOperand(rValue); - buildPoint->addInstruction(std::unique_ptr(store)); -} - -// Comments in header -Id Builder::createLoad(Id lValue) -{ - Instruction* load = new Instruction(getUniqueId(), getDerefTypeId(lValue), OpLoad); - load->addIdOperand(lValue); - buildPoint->addInstruction(std::unique_ptr(load)); - - return load->getResultId(); -} - -// Comments in header -Id Builder::createAccessChain(StorageClass storageClass, Id base, const std::vector& offsets) -{ - // Figure out the final resulting type. - spv::Id typeId = getTypeId(base); - assert(isPointerType(typeId) && offsets.size() > 0); - typeId = getContainedTypeId(typeId); - for (int i = 0; i < (int)offsets.size(); ++i) { - if (isStructType(typeId)) { - assert(isConstantScalar(offsets[i])); - typeId = getContainedTypeId(typeId, getConstantScalar(offsets[i])); - } else - typeId = getContainedTypeId(typeId, offsets[i]); - } - typeId = makePointer(storageClass, typeId); - - // Make the instruction - Instruction* chain = new Instruction(getUniqueId(), typeId, OpAccessChain); - chain->addIdOperand(base); - for (int i = 0; i < (int)offsets.size(); ++i) - chain->addIdOperand(offsets[i]); - buildPoint->addInstruction(std::unique_ptr(chain)); - - return chain->getResultId(); -} - -Id Builder::createArrayLength(Id base, unsigned int member) -{ - spv::Id intType = makeIntType(32); - Instruction* length = new Instruction(getUniqueId(), intType, OpArrayLength); - length->addIdOperand(base); - length->addImmediateOperand(member); - buildPoint->addInstruction(std::unique_ptr(length)); - - return length->getResultId(); -} - -Id Builder::createCompositeExtract(Id composite, Id typeId, unsigned index) -{ - // Generate code for spec constants if in spec constant operation - // generation mode. - if (generatingOpCodeForSpecConst) { - return createSpecConstantOp(OpCompositeExtract, typeId, std::vector(1, composite), std::vector(1, index)); - } - Instruction* extract = new Instruction(getUniqueId(), typeId, OpCompositeExtract); - extract->addIdOperand(composite); - extract->addImmediateOperand(index); - buildPoint->addInstruction(std::unique_ptr(extract)); - - return extract->getResultId(); -} - -Id Builder::createCompositeExtract(Id composite, Id typeId, const std::vector& indexes) -{ - // Generate code for spec constants if in spec constant operation - // generation mode. - if (generatingOpCodeForSpecConst) { - return createSpecConstantOp(OpCompositeExtract, typeId, std::vector(1, composite), indexes); - } - Instruction* extract = new Instruction(getUniqueId(), typeId, OpCompositeExtract); - extract->addIdOperand(composite); - for (int i = 0; i < (int)indexes.size(); ++i) - extract->addImmediateOperand(indexes[i]); - buildPoint->addInstruction(std::unique_ptr(extract)); - - return extract->getResultId(); -} - -Id Builder::createCompositeInsert(Id object, Id composite, Id typeId, unsigned index) -{ - Instruction* insert = new Instruction(getUniqueId(), typeId, OpCompositeInsert); - insert->addIdOperand(object); - insert->addIdOperand(composite); - insert->addImmediateOperand(index); - buildPoint->addInstruction(std::unique_ptr(insert)); - - return insert->getResultId(); -} - -Id Builder::createCompositeInsert(Id object, Id composite, Id typeId, const std::vector& indexes) -{ - Instruction* insert = new Instruction(getUniqueId(), typeId, OpCompositeInsert); - insert->addIdOperand(object); - insert->addIdOperand(composite); - for (int i = 0; i < (int)indexes.size(); ++i) - insert->addImmediateOperand(indexes[i]); - buildPoint->addInstruction(std::unique_ptr(insert)); - - return insert->getResultId(); -} - -Id Builder::createVectorExtractDynamic(Id vector, Id typeId, Id componentIndex) -{ - Instruction* extract = new Instruction(getUniqueId(), typeId, OpVectorExtractDynamic); - extract->addIdOperand(vector); - extract->addIdOperand(componentIndex); - buildPoint->addInstruction(std::unique_ptr(extract)); - - return extract->getResultId(); -} - -Id Builder::createVectorInsertDynamic(Id vector, Id typeId, Id component, Id componentIndex) -{ - Instruction* insert = new Instruction(getUniqueId(), typeId, OpVectorInsertDynamic); - insert->addIdOperand(vector); - insert->addIdOperand(component); - insert->addIdOperand(componentIndex); - buildPoint->addInstruction(std::unique_ptr(insert)); - - return insert->getResultId(); -} - -// An opcode that has no operands, no result id, and no type -void Builder::createNoResultOp(Op opCode) -{ - Instruction* op = new Instruction(opCode); - buildPoint->addInstruction(std::unique_ptr(op)); -} - -// An opcode that has one operand, no result id, and no type -void Builder::createNoResultOp(Op opCode, Id operand) -{ - Instruction* op = new Instruction(opCode); - op->addIdOperand(operand); - buildPoint->addInstruction(std::unique_ptr(op)); -} - -// An opcode that has one operand, no result id, and no type -void Builder::createNoResultOp(Op opCode, const std::vector& operands) -{ - Instruction* op = new Instruction(opCode); - for (auto it = operands.cbegin(); it != operands.cend(); ++it) - op->addIdOperand(*it); - buildPoint->addInstruction(std::unique_ptr(op)); -} - -void Builder::createControlBarrier(Scope execution, Scope memory, MemorySemanticsMask semantics) -{ - Instruction* op = new Instruction(OpControlBarrier); - op->addImmediateOperand(makeUintConstant(execution)); - op->addImmediateOperand(makeUintConstant(memory)); - op->addImmediateOperand(makeUintConstant(semantics)); - buildPoint->addInstruction(std::unique_ptr(op)); -} - -void Builder::createMemoryBarrier(unsigned executionScope, unsigned memorySemantics) -{ - Instruction* op = new Instruction(OpMemoryBarrier); - op->addImmediateOperand(makeUintConstant(executionScope)); - op->addImmediateOperand(makeUintConstant(memorySemantics)); - buildPoint->addInstruction(std::unique_ptr(op)); -} - -// An opcode that has one operands, a result id, and a type -Id Builder::createUnaryOp(Op opCode, Id typeId, Id operand) -{ - // Generate code for spec constants if in spec constant operation - // generation mode. - if (generatingOpCodeForSpecConst) { - return createSpecConstantOp(opCode, typeId, std::vector(1, operand), std::vector()); - } - Instruction* op = new Instruction(getUniqueId(), typeId, opCode); - op->addIdOperand(operand); - buildPoint->addInstruction(std::unique_ptr(op)); - - return op->getResultId(); -} - -Id Builder::createBinOp(Op opCode, Id typeId, Id left, Id right) -{ - // Generate code for spec constants if in spec constant operation - // generation mode. - if (generatingOpCodeForSpecConst) { - std::vector operands(2); - operands[0] = left; operands[1] = right; - return createSpecConstantOp(opCode, typeId, operands, std::vector()); - } - Instruction* op = new Instruction(getUniqueId(), typeId, opCode); - op->addIdOperand(left); - op->addIdOperand(right); - buildPoint->addInstruction(std::unique_ptr(op)); - - return op->getResultId(); -} - -Id Builder::createTriOp(Op opCode, Id typeId, Id op1, Id op2, Id op3) -{ - // Generate code for spec constants if in spec constant operation - // generation mode. - if (generatingOpCodeForSpecConst) { - std::vector operands(3); - operands[0] = op1; - operands[1] = op2; - operands[2] = op3; - return createSpecConstantOp( - opCode, typeId, operands, std::vector()); - } - Instruction* op = new Instruction(getUniqueId(), typeId, opCode); - op->addIdOperand(op1); - op->addIdOperand(op2); - op->addIdOperand(op3); - buildPoint->addInstruction(std::unique_ptr(op)); - - return op->getResultId(); -} - -Id Builder::createOp(Op opCode, Id typeId, const std::vector& operands) -{ - Instruction* op = new Instruction(getUniqueId(), typeId, opCode); - for (auto it = operands.cbegin(); it != operands.cend(); ++it) - op->addIdOperand(*it); - buildPoint->addInstruction(std::unique_ptr(op)); - - return op->getResultId(); -} - -Id Builder::createSpecConstantOp(Op opCode, Id typeId, const std::vector& operands, const std::vector& literals) -{ - Instruction* op = new Instruction(getUniqueId(), typeId, OpSpecConstantOp); - op->addImmediateOperand((unsigned) opCode); - for (auto it = operands.cbegin(); it != operands.cend(); ++it) - op->addIdOperand(*it); - for (auto it = literals.cbegin(); it != literals.cend(); ++it) - op->addImmediateOperand(*it); - module.mapInstruction(op); - constantsTypesGlobals.push_back(std::unique_ptr(op)); - - return op->getResultId(); -} - -Id Builder::createFunctionCall(spv::Function* function, const std::vector& args) -{ - Instruction* op = new Instruction(getUniqueId(), function->getReturnType(), OpFunctionCall); - op->addIdOperand(function->getId()); - for (int a = 0; a < (int)args.size(); ++a) - op->addIdOperand(args[a]); - buildPoint->addInstruction(std::unique_ptr(op)); - - return op->getResultId(); -} - -// Comments in header -Id Builder::createRvalueSwizzle(Decoration precision, Id typeId, Id source, const std::vector& channels) -{ - if (channels.size() == 1) - return setPrecision(createCompositeExtract(source, typeId, channels.front()), precision); - - if (generatingOpCodeForSpecConst) { - std::vector operands(2); - operands[0] = operands[1] = source; - return setPrecision(createSpecConstantOp(OpVectorShuffle, typeId, operands, channels), precision); - } - Instruction* swizzle = new Instruction(getUniqueId(), typeId, OpVectorShuffle); - assert(isVector(source)); - swizzle->addIdOperand(source); - swizzle->addIdOperand(source); - for (int i = 0; i < (int)channels.size(); ++i) - swizzle->addImmediateOperand(channels[i]); - buildPoint->addInstruction(std::unique_ptr(swizzle)); - - return setPrecision(swizzle->getResultId(), precision); -} - -// Comments in header -Id Builder::createLvalueSwizzle(Id typeId, Id target, Id source, const std::vector& channels) -{ - if (channels.size() == 1 && getNumComponents(source) == 1) - return createCompositeInsert(source, target, typeId, channels.front()); - - Instruction* swizzle = new Instruction(getUniqueId(), typeId, OpVectorShuffle); - - assert(isVector(target)); - swizzle->addIdOperand(target); - - assert(getNumComponents(source) == (int)channels.size()); - assert(isVector(source)); - swizzle->addIdOperand(source); - - // Set up an identity shuffle from the base value to the result value - unsigned int components[4]; - int numTargetComponents = getNumComponents(target); - for (int i = 0; i < numTargetComponents; ++i) - components[i] = i; - - // Punch in the l-value swizzle - for (int i = 0; i < (int)channels.size(); ++i) - components[channels[i]] = numTargetComponents + i; - - // finish the instruction with these components selectors - for (int i = 0; i < numTargetComponents; ++i) - swizzle->addImmediateOperand(components[i]); - buildPoint->addInstruction(std::unique_ptr(swizzle)); - - return swizzle->getResultId(); -} - -// Comments in header -void Builder::promoteScalar(Decoration precision, Id& left, Id& right) -{ - int direction = getNumComponents(right) - getNumComponents(left); - - if (direction > 0) - left = smearScalar(precision, left, makeVectorType(getTypeId(left), getNumComponents(right))); - else if (direction < 0) - right = smearScalar(precision, right, makeVectorType(getTypeId(right), getNumComponents(left))); - - return; -} - -// Comments in header -Id Builder::smearScalar(Decoration precision, Id scalar, Id vectorType) -{ - assert(getNumComponents(scalar) == 1); - assert(getTypeId(scalar) == getScalarTypeId(vectorType)); - - int numComponents = getNumTypeComponents(vectorType); - if (numComponents == 1) - return scalar; - - Instruction* smear = nullptr; - if (generatingOpCodeForSpecConst) { - auto members = std::vector(numComponents, scalar); - // Sometime even in spec-constant-op mode, the temporary vector created by - // promoting a scalar might not be a spec constant. This should depend on - // the scalar. - // e.g.: - // const vec2 spec_const_result = a_spec_const_vec2 + a_front_end_const_scalar; - // In such cases, the temporary vector created from a_front_end_const_scalar - // is not a spec constant vector, even though the binary operation node is marked - // as 'specConstant' and we are in spec-constant-op mode. - auto result_id = makeCompositeConstant(vectorType, members, isSpecConstant(scalar)); - smear = module.getInstruction(result_id); - } else { - smear = new Instruction(getUniqueId(), vectorType, OpCompositeConstruct); - for (int c = 0; c < numComponents; ++c) - smear->addIdOperand(scalar); - buildPoint->addInstruction(std::unique_ptr(smear)); - } - - return setPrecision(smear->getResultId(), precision); -} - -// Comments in header -Id Builder::createBuiltinCall(Id resultType, Id builtins, int entryPoint, const std::vector& args) -{ - Instruction* inst = new Instruction(getUniqueId(), resultType, OpExtInst); - inst->addIdOperand(builtins); - inst->addImmediateOperand(entryPoint); - for (int arg = 0; arg < (int)args.size(); ++arg) - inst->addIdOperand(args[arg]); - - buildPoint->addInstruction(std::unique_ptr(inst)); - - return inst->getResultId(); -} - -// Accept all parameters needed to create a texture instruction. -// Create the correct instruction based on the inputs, and make the call. -Id Builder::createTextureCall(Decoration precision, Id resultType, bool sparse, bool fetch, bool proj, bool gather, bool noImplicitLod, const TextureParameters& parameters) -{ - static const int maxTextureArgs = 10; - Id texArgs[maxTextureArgs] = {}; - - // - // Set up the fixed arguments - // - int numArgs = 0; - bool explicitLod = false; - texArgs[numArgs++] = parameters.sampler; - texArgs[numArgs++] = parameters.coords; - if (parameters.Dref != NoResult) - texArgs[numArgs++] = parameters.Dref; - if (parameters.component != NoResult) - texArgs[numArgs++] = parameters.component; - - // - // Set up the optional arguments - // - int optArgNum = numArgs; // track which operand, if it exists, is the mask of optional arguments - ++numArgs; // speculatively make room for the mask operand - ImageOperandsMask mask = ImageOperandsMaskNone; // the mask operand - if (parameters.bias) { - mask = (ImageOperandsMask)(mask | ImageOperandsBiasMask); - texArgs[numArgs++] = parameters.bias; - } - if (parameters.lod) { - mask = (ImageOperandsMask)(mask | ImageOperandsLodMask); - texArgs[numArgs++] = parameters.lod; - explicitLod = true; - } else if (parameters.gradX) { - mask = (ImageOperandsMask)(mask | ImageOperandsGradMask); - texArgs[numArgs++] = parameters.gradX; - texArgs[numArgs++] = parameters.gradY; - explicitLod = true; - } else if (noImplicitLod && ! fetch && ! gather) { - // have to explicitly use lod of 0 if not allowed to have them be implicit, and - // we would otherwise be about to issue an implicit instruction - mask = (ImageOperandsMask)(mask | ImageOperandsLodMask); - texArgs[numArgs++] = makeFloatConstant(0.0); - explicitLod = true; - } - if (parameters.offset) { - if (isConstant(parameters.offset)) - mask = (ImageOperandsMask)(mask | ImageOperandsConstOffsetMask); - else { - addCapability(CapabilityImageGatherExtended); - mask = (ImageOperandsMask)(mask | ImageOperandsOffsetMask); - } - texArgs[numArgs++] = parameters.offset; - } - if (parameters.offsets) { - mask = (ImageOperandsMask)(mask | ImageOperandsConstOffsetsMask); - texArgs[numArgs++] = parameters.offsets; - } - if (parameters.sample) { - mask = (ImageOperandsMask)(mask | ImageOperandsSampleMask); - texArgs[numArgs++] = parameters.sample; - } - if (parameters.lodClamp) { - // capability if this bit is used - addCapability(CapabilityMinLod); - - mask = (ImageOperandsMask)(mask | ImageOperandsMinLodMask); - texArgs[numArgs++] = parameters.lodClamp; - } - if (mask == ImageOperandsMaskNone) - --numArgs; // undo speculative reservation for the mask argument - else - texArgs[optArgNum] = mask; - - // - // Set up the instruction - // - Op opCode = OpNop; // All paths below need to set this - if (fetch) { - if (sparse) - opCode = OpImageSparseFetch; - else - opCode = OpImageFetch; - } else if (gather) { - if (parameters.Dref) - if (sparse) - opCode = OpImageSparseDrefGather; - else - opCode = OpImageDrefGather; - else - if (sparse) - opCode = OpImageSparseGather; - else - opCode = OpImageGather; - } else if (explicitLod) { - if (parameters.Dref) { - if (proj) - if (sparse) - opCode = OpImageSparseSampleProjDrefExplicitLod; - else - opCode = OpImageSampleProjDrefExplicitLod; - else - if (sparse) - opCode = OpImageSparseSampleDrefExplicitLod; - else - opCode = OpImageSampleDrefExplicitLod; - } else { - if (proj) - if (sparse) - opCode = OpImageSparseSampleProjExplicitLod; - else - opCode = OpImageSampleProjExplicitLod; - else - if (sparse) - opCode = OpImageSparseSampleExplicitLod; - else - opCode = OpImageSampleExplicitLod; - } - } else { - if (parameters.Dref) { - if (proj) - if (sparse) - opCode = OpImageSparseSampleProjDrefImplicitLod; - else - opCode = OpImageSampleProjDrefImplicitLod; - else - if (sparse) - opCode = OpImageSparseSampleDrefImplicitLod; - else - opCode = OpImageSampleDrefImplicitLod; - } else { - if (proj) - if (sparse) - opCode = OpImageSparseSampleProjImplicitLod; - else - opCode = OpImageSampleProjImplicitLod; - else - if (sparse) - opCode = OpImageSparseSampleImplicitLod; - else - opCode = OpImageSampleImplicitLod; - } - } - - // See if the result type is expecting a smeared result. - // This happens when a legacy shadow*() call is made, which - // gets a vec4 back instead of a float. - Id smearedType = resultType; - if (! isScalarType(resultType)) { - switch (opCode) { - case OpImageSampleDrefImplicitLod: - case OpImageSampleDrefExplicitLod: - case OpImageSampleProjDrefImplicitLod: - case OpImageSampleProjDrefExplicitLod: - resultType = getScalarTypeId(resultType); - break; - default: - break; - } - } - - Id typeId0 = 0; - Id typeId1 = 0; - - if (sparse) { - typeId0 = resultType; - typeId1 = getDerefTypeId(parameters.texelOut); - resultType = makeStructResultType(typeId0, typeId1); - } - - // Build the SPIR-V instruction - Instruction* textureInst = new Instruction(getUniqueId(), resultType, opCode); - for (int op = 0; op < optArgNum; ++op) - textureInst->addIdOperand(texArgs[op]); - if (optArgNum < numArgs) - textureInst->addImmediateOperand(texArgs[optArgNum]); - for (int op = optArgNum + 1; op < numArgs; ++op) - textureInst->addIdOperand(texArgs[op]); - setPrecision(textureInst->getResultId(), precision); - buildPoint->addInstruction(std::unique_ptr(textureInst)); - - Id resultId = textureInst->getResultId(); - - if (sparse) { - // set capability - addCapability(CapabilitySparseResidency); - - // Decode the return type that was a special structure - createStore(createCompositeExtract(resultId, typeId1, 1), parameters.texelOut); - resultId = createCompositeExtract(resultId, typeId0, 0); - setPrecision(resultId, precision); - } else { - // When a smear is needed, do it, as per what was computed - // above when resultType was changed to a scalar type. - if (resultType != smearedType) - resultId = smearScalar(precision, resultId, smearedType); - } - - return resultId; -} - -// Comments in header -Id Builder::createTextureQueryCall(Op opCode, const TextureParameters& parameters, bool isUnsignedResult) -{ - // All these need a capability - addCapability(CapabilityImageQuery); - - // Figure out the result type - Id resultType = 0; - switch (opCode) { - case OpImageQuerySize: - case OpImageQuerySizeLod: - { - int numComponents = 0; - switch (getTypeDimensionality(getImageType(parameters.sampler))) { - case Dim1D: - case DimBuffer: - numComponents = 1; - break; - case Dim2D: - case DimCube: - case DimRect: - case DimSubpassData: - numComponents = 2; - break; - case Dim3D: - numComponents = 3; - break; - - default: - assert(0); - break; - } - if (isArrayedImageType(getImageType(parameters.sampler))) - ++numComponents; - - Id intType = isUnsignedResult ? makeUintType(32) : makeIntType(32); - if (numComponents == 1) - resultType = intType; - else - resultType = makeVectorType(intType, numComponents); - - break; - } - case OpImageQueryLod: -#ifdef AMD_EXTENSIONS - resultType = makeVectorType(getScalarTypeId(getTypeId(parameters.coords)), 2); -#else - resultType = makeVectorType(makeFloatType(32), 2); -#endif - break; - case OpImageQueryLevels: - case OpImageQuerySamples: - resultType = isUnsignedResult ? makeUintType(32) : makeIntType(32); - break; - default: - assert(0); - break; - } - - Instruction* query = new Instruction(getUniqueId(), resultType, opCode); - query->addIdOperand(parameters.sampler); - if (parameters.coords) - query->addIdOperand(parameters.coords); - if (parameters.lod) - query->addIdOperand(parameters.lod); - buildPoint->addInstruction(std::unique_ptr(query)); - - return query->getResultId(); -} - -// External comments in header. -// Operates recursively to visit the composite's hierarchy. -Id Builder::createCompositeCompare(Decoration precision, Id value1, Id value2, bool equal) -{ - Id boolType = makeBoolType(); - Id valueType = getTypeId(value1); - - Id resultId = NoResult; - - int numConstituents = getNumTypeConstituents(valueType); - - // Scalars and Vectors - - if (isScalarType(valueType) || isVectorType(valueType)) { - assert(valueType == getTypeId(value2)); - // These just need a single comparison, just have - // to figure out what it is. - Op op; - switch (getMostBasicTypeClass(valueType)) { - case OpTypeFloat: - op = equal ? OpFOrdEqual : OpFOrdNotEqual; - break; - case OpTypeInt: - default: - op = equal ? OpIEqual : OpINotEqual; - break; - case OpTypeBool: - op = equal ? OpLogicalEqual : OpLogicalNotEqual; - precision = NoPrecision; - break; - } - - if (isScalarType(valueType)) { - // scalar - resultId = createBinOp(op, boolType, value1, value2); - } else { - // vector - resultId = createBinOp(op, makeVectorType(boolType, numConstituents), value1, value2); - setPrecision(resultId, precision); - // reduce vector compares... - resultId = createUnaryOp(equal ? OpAll : OpAny, boolType, resultId); - } - - return setPrecision(resultId, precision); - } - - // Only structs, arrays, and matrices should be left. - // They share in common the reduction operation across their constituents. - assert(isAggregateType(valueType) || isMatrixType(valueType)); - - // Compare each pair of constituents - for (int constituent = 0; constituent < numConstituents; ++constituent) { - std::vector indexes(1, constituent); - Id constituentType1 = getContainedTypeId(getTypeId(value1), constituent); - Id constituentType2 = getContainedTypeId(getTypeId(value2), constituent); - Id constituent1 = createCompositeExtract(value1, constituentType1, indexes); - Id constituent2 = createCompositeExtract(value2, constituentType2, indexes); - - Id subResultId = createCompositeCompare(precision, constituent1, constituent2, equal); - - if (constituent == 0) - resultId = subResultId; - else - resultId = setPrecision(createBinOp(equal ? OpLogicalAnd : OpLogicalOr, boolType, resultId, subResultId), precision); - } - - return resultId; -} - -// OpCompositeConstruct -Id Builder::createCompositeConstruct(Id typeId, const std::vector& constituents) -{ - assert(isAggregateType(typeId) || (getNumTypeConstituents(typeId) > 1 && getNumTypeConstituents(typeId) == (int)constituents.size())); - - if (generatingOpCodeForSpecConst) { - // Sometime, even in spec-constant-op mode, the constant composite to be - // constructed may not be a specialization constant. - // e.g.: - // const mat2 m2 = mat2(a_spec_const, a_front_end_const, another_front_end_const, third_front_end_const); - // The first column vector should be a spec constant one, as a_spec_const is a spec constant. - // The second column vector should NOT be spec constant, as it does not contain any spec constants. - // To handle such cases, we check the constituents of the constant vector to determine whether this - // vector should be created as a spec constant. - return makeCompositeConstant(typeId, constituents, - std::any_of(constituents.begin(), constituents.end(), - [&](spv::Id id) { return isSpecConstant(id); })); - } - - Instruction* op = new Instruction(getUniqueId(), typeId, OpCompositeConstruct); - for (int c = 0; c < (int)constituents.size(); ++c) - op->addIdOperand(constituents[c]); - buildPoint->addInstruction(std::unique_ptr(op)); - - return op->getResultId(); -} - -// Vector or scalar constructor -Id Builder::createConstructor(Decoration precision, const std::vector& sources, Id resultTypeId) -{ - Id result = NoResult; - unsigned int numTargetComponents = getNumTypeComponents(resultTypeId); - unsigned int targetComponent = 0; - - // Special case: when calling a vector constructor with a single scalar - // argument, smear the scalar - if (sources.size() == 1 && isScalar(sources[0]) && numTargetComponents > 1) - return smearScalar(precision, sources[0], resultTypeId); - - // accumulate the arguments for OpCompositeConstruct - std::vector constituents; - Id scalarTypeId = getScalarTypeId(resultTypeId); - - // lambda to store the result of visiting an argument component - const auto latchResult = [&](Id comp) { - if (numTargetComponents > 1) - constituents.push_back(comp); - else - result = comp; - ++targetComponent; - }; - - // lambda to visit a vector argument's components - const auto accumulateVectorConstituents = [&](Id sourceArg) { - unsigned int sourceSize = getNumComponents(sourceArg); - unsigned int sourcesToUse = sourceSize; - if (sourcesToUse + targetComponent > numTargetComponents) - sourcesToUse = numTargetComponents - targetComponent; - - for (unsigned int s = 0; s < sourcesToUse; ++s) { - std::vector swiz; - swiz.push_back(s); - latchResult(createRvalueSwizzle(precision, scalarTypeId, sourceArg, swiz)); - } - }; - - // lambda to visit a matrix argument's components - const auto accumulateMatrixConstituents = [&](Id sourceArg) { - unsigned int sourceSize = getNumColumns(sourceArg) * getNumRows(sourceArg); - unsigned int sourcesToUse = sourceSize; - if (sourcesToUse + targetComponent > numTargetComponents) - sourcesToUse = numTargetComponents - targetComponent; - - int col = 0; - int row = 0; - for (unsigned int s = 0; s < sourcesToUse; ++s) { - if (row >= getNumRows(sourceArg)) { - row = 0; - col++; - } - std::vector indexes; - indexes.push_back(col); - indexes.push_back(row); - latchResult(createCompositeExtract(sourceArg, scalarTypeId, indexes)); - row++; - } - }; - - // Go through the source arguments, each one could have either - // a single or multiple components to contribute. - for (unsigned int i = 0; i < sources.size(); ++i) { - if (isScalar(sources[i])) - latchResult(sources[i]); - else if (isVector(sources[i])) - accumulateVectorConstituents(sources[i]); - else if (isMatrix(sources[i])) - accumulateMatrixConstituents(sources[i]); - else - assert(0); - - if (targetComponent >= numTargetComponents) - break; - } - - // If the result is a vector, make it from the gathered constituents. - if (constituents.size() > 0) - result = createCompositeConstruct(resultTypeId, constituents); - - return setPrecision(result, precision); -} - -// Comments in header -Id Builder::createMatrixConstructor(Decoration precision, const std::vector& sources, Id resultTypeId) -{ - Id componentTypeId = getScalarTypeId(resultTypeId); - int numCols = getTypeNumColumns(resultTypeId); - int numRows = getTypeNumRows(resultTypeId); - - Instruction* instr = module.getInstruction(componentTypeId); - Id bitCount = instr->getIdOperand(0); - - // Will use a two step process - // 1. make a compile-time 2D array of values - // 2. construct a matrix from that array - - // Step 1. - - // initialize the array to the identity matrix - Id ids[maxMatrixSize][maxMatrixSize]; - Id one = (bitCount == 64 ? makeDoubleConstant(1.0) : makeFloatConstant(1.0)); - Id zero = (bitCount == 64 ? makeDoubleConstant(0.0) : makeFloatConstant(0.0)); - for (int col = 0; col < 4; ++col) { - for (int row = 0; row < 4; ++row) { - if (col == row) - ids[col][row] = one; - else - ids[col][row] = zero; - } - } - - // modify components as dictated by the arguments - if (sources.size() == 1 && isScalar(sources[0])) { - // a single scalar; resets the diagonals - for (int col = 0; col < 4; ++col) - ids[col][col] = sources[0]; - } else if (isMatrix(sources[0])) { - // constructing from another matrix; copy over the parts that exist in both the argument and constructee - Id matrix = sources[0]; - int minCols = std::min(numCols, getNumColumns(matrix)); - int minRows = std::min(numRows, getNumRows(matrix)); - for (int col = 0; col < minCols; ++col) { - std::vector indexes; - indexes.push_back(col); - for (int row = 0; row < minRows; ++row) { - indexes.push_back(row); - ids[col][row] = createCompositeExtract(matrix, componentTypeId, indexes); - indexes.pop_back(); - setPrecision(ids[col][row], precision); - } - } - } else { - // fill in the matrix in column-major order with whatever argument components are available - int row = 0; - int col = 0; - - for (int arg = 0; arg < (int)sources.size(); ++arg) { - Id argComp = sources[arg]; - for (int comp = 0; comp < getNumComponents(sources[arg]); ++comp) { - if (getNumComponents(sources[arg]) > 1) { - argComp = createCompositeExtract(sources[arg], componentTypeId, comp); - setPrecision(argComp, precision); - } - ids[col][row++] = argComp; - if (row == numRows) { - row = 0; - col++; - } - } - } - } - - // Step 2: Construct a matrix from that array. - // First make the column vectors, then make the matrix. - - // make the column vectors - Id columnTypeId = getContainedTypeId(resultTypeId); - std::vector matrixColumns; - for (int col = 0; col < numCols; ++col) { - std::vector vectorComponents; - for (int row = 0; row < numRows; ++row) - vectorComponents.push_back(ids[col][row]); - Id column = createCompositeConstruct(columnTypeId, vectorComponents); - setPrecision(column, precision); - matrixColumns.push_back(column); - } - - // make the matrix - return setPrecision(createCompositeConstruct(resultTypeId, matrixColumns), precision); -} - -// Comments in header -Builder::If::If(Id cond, unsigned int ctrl, Builder& gb) : - builder(gb), - condition(cond), - control(ctrl), - elseBlock(0) -{ - function = &builder.getBuildPoint()->getParent(); - - // make the blocks, but only put the then-block into the function, - // the else-block and merge-block will be added later, in order, after - // earlier code is emitted - thenBlock = new Block(builder.getUniqueId(), *function); - mergeBlock = new Block(builder.getUniqueId(), *function); - - // Save the current block, so that we can add in the flow control split when - // makeEndIf is called. - headerBlock = builder.getBuildPoint(); - - function->addBlock(thenBlock); - builder.setBuildPoint(thenBlock); -} - -// Comments in header -void Builder::If::makeBeginElse() -{ - // Close out the "then" by having it jump to the mergeBlock - builder.createBranch(mergeBlock); - - // Make the first else block and add it to the function - elseBlock = new Block(builder.getUniqueId(), *function); - function->addBlock(elseBlock); - - // Start building the else block - builder.setBuildPoint(elseBlock); -} - -// Comments in header -void Builder::If::makeEndIf() -{ - // jump to the merge block - builder.createBranch(mergeBlock); - - // Go back to the headerBlock and make the flow control split - builder.setBuildPoint(headerBlock); - builder.createSelectionMerge(mergeBlock, control); - if (elseBlock) - builder.createConditionalBranch(condition, thenBlock, elseBlock); - else - builder.createConditionalBranch(condition, thenBlock, mergeBlock); - - // add the merge block to the function - function->addBlock(mergeBlock); - builder.setBuildPoint(mergeBlock); -} - -// Comments in header -void Builder::makeSwitch(Id selector, unsigned int control, int numSegments, const std::vector& caseValues, - const std::vector& valueIndexToSegment, int defaultSegment, - std::vector& segmentBlocks) -{ - Function& function = buildPoint->getParent(); - - // make all the blocks - for (int s = 0; s < numSegments; ++s) - segmentBlocks.push_back(new Block(getUniqueId(), function)); - - Block* mergeBlock = new Block(getUniqueId(), function); - - // make and insert the switch's selection-merge instruction - createSelectionMerge(mergeBlock, control); - - // make the switch instruction - Instruction* switchInst = new Instruction(NoResult, NoType, OpSwitch); - switchInst->addIdOperand(selector); - auto defaultOrMerge = (defaultSegment >= 0) ? segmentBlocks[defaultSegment] : mergeBlock; - switchInst->addIdOperand(defaultOrMerge->getId()); - defaultOrMerge->addPredecessor(buildPoint); - for (int i = 0; i < (int)caseValues.size(); ++i) { - switchInst->addImmediateOperand(caseValues[i]); - switchInst->addIdOperand(segmentBlocks[valueIndexToSegment[i]]->getId()); - segmentBlocks[valueIndexToSegment[i]]->addPredecessor(buildPoint); - } - buildPoint->addInstruction(std::unique_ptr(switchInst)); - - // push the merge block - switchMerges.push(mergeBlock); -} - -// Comments in header -void Builder::addSwitchBreak() -{ - // branch to the top of the merge block stack - createBranch(switchMerges.top()); - createAndSetNoPredecessorBlock("post-switch-break"); -} - -// Comments in header -void Builder::nextSwitchSegment(std::vector& segmentBlock, int nextSegment) -{ - int lastSegment = nextSegment - 1; - if (lastSegment >= 0) { - // Close out previous segment by jumping, if necessary, to next segment - if (! buildPoint->isTerminated()) - createBranch(segmentBlock[nextSegment]); - } - Block* block = segmentBlock[nextSegment]; - block->getParent().addBlock(block); - setBuildPoint(block); -} - -// Comments in header -void Builder::endSwitch(std::vector& /*segmentBlock*/) -{ - // Close out previous segment by jumping, if necessary, to next segment - if (! buildPoint->isTerminated()) - addSwitchBreak(); - - switchMerges.top()->getParent().addBlock(switchMerges.top()); - setBuildPoint(switchMerges.top()); - - switchMerges.pop(); -} - -Block& Builder::makeNewBlock() -{ - Function& function = buildPoint->getParent(); - auto block = new Block(getUniqueId(), function); - function.addBlock(block); - return *block; -} - -Builder::LoopBlocks& Builder::makeNewLoop() -{ - // This verbosity is needed to simultaneously get the same behavior - // everywhere (id's in the same order), have a syntax that works - // across lots of versions of C++, have no warnings from pedantic - // compilation modes, and leave the rest of the code alone. - Block& head = makeNewBlock(); - Block& body = makeNewBlock(); - Block& merge = makeNewBlock(); - Block& continue_target = makeNewBlock(); - LoopBlocks blocks(head, body, merge, continue_target); - loops.push(blocks); - return loops.top(); -} - -void Builder::createLoopContinue() -{ - createBranch(&loops.top().continue_target); - // Set up a block for dead code. - createAndSetNoPredecessorBlock("post-loop-continue"); -} - -void Builder::createLoopExit() -{ - createBranch(&loops.top().merge); - // Set up a block for dead code. - createAndSetNoPredecessorBlock("post-loop-break"); -} - -void Builder::closeLoop() -{ - loops.pop(); -} - -void Builder::clearAccessChain() -{ - accessChain.base = NoResult; - accessChain.indexChain.clear(); - accessChain.instr = NoResult; - accessChain.swizzle.clear(); - accessChain.component = NoResult; - accessChain.preSwizzleBaseType = NoType; - accessChain.isRValue = false; -} - -// Comments in header -void Builder::accessChainPushSwizzle(std::vector& swizzle, Id preSwizzleBaseType) -{ - // swizzles can be stacked in GLSL, but simplified to a single - // one here; the base type doesn't change - if (accessChain.preSwizzleBaseType == NoType) - accessChain.preSwizzleBaseType = preSwizzleBaseType; - - // if needed, propagate the swizzle for the current access chain - if (accessChain.swizzle.size() > 0) { - std::vector oldSwizzle = accessChain.swizzle; - accessChain.swizzle.resize(0); - for (unsigned int i = 0; i < swizzle.size(); ++i) { - assert(swizzle[i] < oldSwizzle.size()); - accessChain.swizzle.push_back(oldSwizzle[swizzle[i]]); - } - } else - accessChain.swizzle = swizzle; - - // determine if we need to track this swizzle anymore - simplifyAccessChainSwizzle(); -} - -// Comments in header -void Builder::accessChainStore(Id rvalue) -{ - assert(accessChain.isRValue == false); - - transferAccessChainSwizzle(true); - Id base = collapseAccessChain(); - Id source = rvalue; - - // dynamic component should be gone - assert(accessChain.component == NoResult); - - // If swizzle still exists, it is out-of-order or not full, we must load the target vector, - // extract and insert elements to perform writeMask and/or swizzle. - if (accessChain.swizzle.size() > 0) { - Id tempBaseId = createLoad(base); - source = createLvalueSwizzle(getTypeId(tempBaseId), tempBaseId, source, accessChain.swizzle); - } - - createStore(source, base); -} - -// Comments in header -Id Builder::accessChainLoad(Decoration precision, Decoration nonUniform, Id resultType) -{ - Id id; - - if (accessChain.isRValue) { - // transfer access chain, but try to stay in registers - transferAccessChainSwizzle(false); - if (accessChain.indexChain.size() > 0) { - Id swizzleBase = accessChain.preSwizzleBaseType != NoType ? accessChain.preSwizzleBaseType : resultType; - - // if all the accesses are constants, we can use OpCompositeExtract - std::vector indexes; - bool constant = true; - for (int i = 0; i < (int)accessChain.indexChain.size(); ++i) { - if (isConstantScalar(accessChain.indexChain[i])) - indexes.push_back(getConstantScalar(accessChain.indexChain[i])); - else { - constant = false; - break; - } - } - - if (constant) - id = createCompositeExtract(accessChain.base, swizzleBase, indexes); - else { - // make a new function variable for this r-value - Id lValue = createVariable(StorageClassFunction, getTypeId(accessChain.base), "indexable"); - - // store into it - createStore(accessChain.base, lValue); - - // move base to the new variable - accessChain.base = lValue; - accessChain.isRValue = false; - - // load through the access chain - id = createLoad(collapseAccessChain()); - } - setPrecision(id, precision); - } else - id = accessChain.base; // no precision, it was set when this was defined - } else { - transferAccessChainSwizzle(true); - // load through the access chain - id = createLoad(collapseAccessChain()); - setPrecision(id, precision); - addDecoration(id, nonUniform); - } - - // Done, unless there are swizzles to do - if (accessChain.swizzle.size() == 0 && accessChain.component == NoResult) - return id; - - // Do remaining swizzling - - // Do the basic swizzle - if (accessChain.swizzle.size() > 0) { - Id swizzledType = getScalarTypeId(getTypeId(id)); - if (accessChain.swizzle.size() > 1) - swizzledType = makeVectorType(swizzledType, (int)accessChain.swizzle.size()); - id = createRvalueSwizzle(precision, swizzledType, id, accessChain.swizzle); - } - - // Do the dynamic component - if (accessChain.component != NoResult) - id = setPrecision(createVectorExtractDynamic(id, resultType, accessChain.component), precision); - - addDecoration(id, nonUniform); - return id; -} - -Id Builder::accessChainGetLValue() -{ - assert(accessChain.isRValue == false); - - transferAccessChainSwizzle(true); - Id lvalue = collapseAccessChain(); - - // If swizzle exists, it is out-of-order or not full, we must load the target vector, - // extract and insert elements to perform writeMask and/or swizzle. This does not - // go with getting a direct l-value pointer. - assert(accessChain.swizzle.size() == 0); - assert(accessChain.component == NoResult); - - return lvalue; -} - -// comment in header -Id Builder::accessChainGetInferredType() -{ - // anything to operate on? - if (accessChain.base == NoResult) - return NoType; - Id type = getTypeId(accessChain.base); - - // do initial dereference - if (! accessChain.isRValue) - type = getContainedTypeId(type); - - // dereference each index - for (auto it = accessChain.indexChain.cbegin(); it != accessChain.indexChain.cend(); ++it) { - if (isStructType(type)) - type = getContainedTypeId(type, getConstantScalar(*it)); - else - type = getContainedTypeId(type); - } - - // dereference swizzle - if (accessChain.swizzle.size() == 1) - type = getContainedTypeId(type); - else if (accessChain.swizzle.size() > 1) - type = makeVectorType(getContainedTypeId(type), (int)accessChain.swizzle.size()); - - // dereference component selection - if (accessChain.component) - type = getContainedTypeId(type); - - return type; -} - -// comment in header -void Builder::eliminateDeadDecorations() { - std::unordered_set reachable_blocks; - std::unordered_set unreachable_definitions; - // Collect IDs defined in unreachable blocks. For each function, label the - // reachable blocks first. Then for each unreachable block, collect the - // result IDs of the instructions in it. - for (std::vector::const_iterator fi = module.getFunctions().cbegin(); - fi != module.getFunctions().cend(); fi++) { - Function* f = *fi; - Block* entry = f->getEntryBlock(); - inReadableOrder(entry, [&reachable_blocks](const Block* b) { - reachable_blocks.insert(b); - }); - for (std::vector::const_iterator bi = f->getBlocks().cbegin(); - bi != f->getBlocks().cend(); bi++) { - Block* b = *bi; - if (!reachable_blocks.count(b)) { - for (std::vector >::const_iterator - ii = b->getInstructions().cbegin(); - ii != b->getInstructions().cend(); ii++) { - Instruction* i = ii->get(); - unreachable_definitions.insert(i->getResultId()); - } - } - } - } - decorations.erase(std::remove_if(decorations.begin(), decorations.end(), - [&unreachable_definitions](std::unique_ptr& I) -> bool { - Instruction* inst = I.get(); - Id decoration_id = inst->getIdOperand(0); - return unreachable_definitions.count(decoration_id) != 0; - }), - decorations.end()); -} - -void Builder::dump(std::vector& out) const -{ - // Header, before first instructions: - out.push_back(MagicNumber); - out.push_back(spvVersion); - out.push_back(builderNumber); - out.push_back(uniqueId + 1); - out.push_back(0); - - // Capabilities - for (auto it = capabilities.cbegin(); it != capabilities.cend(); ++it) { - Instruction capInst(0, 0, OpCapability); - capInst.addImmediateOperand(*it); - capInst.dump(out); - } - - for (auto it = extensions.cbegin(); it != extensions.cend(); ++it) { - Instruction extInst(0, 0, OpExtension); - extInst.addStringOperand(it->c_str()); - extInst.dump(out); - } - - dumpInstructions(out, imports); - Instruction memInst(0, 0, OpMemoryModel); - memInst.addImmediateOperand(addressModel); - memInst.addImmediateOperand(memoryModel); - memInst.dump(out); - - // Instructions saved up while building: - dumpInstructions(out, entryPoints); - dumpInstructions(out, executionModes); - - // Debug instructions - dumpInstructions(out, strings); - dumpSourceInstructions(out); - for (int e = 0; e < (int)sourceExtensions.size(); ++e) { - Instruction sourceExtInst(0, 0, OpSourceExtension); - sourceExtInst.addStringOperand(sourceExtensions[e]); - sourceExtInst.dump(out); - } - dumpInstructions(out, names); - dumpModuleProcesses(out); - - // Annotation instructions - dumpInstructions(out, decorations); - - dumpInstructions(out, constantsTypesGlobals); - dumpInstructions(out, externals); - - // The functions - module.dump(out); -} - -// -// Protected methods. -// - -// Turn the described access chain in 'accessChain' into an instruction(s) -// computing its address. This *cannot* include complex swizzles, which must -// be handled after this is called. -// -// Can generate code. -Id Builder::collapseAccessChain() -{ - assert(accessChain.isRValue == false); - - // did we already emit an access chain for this? - if (accessChain.instr != NoResult) - return accessChain.instr; - - // If we have a dynamic component, we can still transfer - // that into a final operand to the access chain. We need to remap the - // dynamic component through the swizzle to get a new dynamic component to - // update. - // - // This was not done in transferAccessChainSwizzle() because it might - // generate code. - remapDynamicSwizzle(); - if (accessChain.component != NoResult) { - // transfer the dynamic component to the access chain - accessChain.indexChain.push_back(accessChain.component); - accessChain.component = NoResult; - } - - // note that non-trivial swizzling is left pending - - // do we have an access chain? - if (accessChain.indexChain.size() == 0) - return accessChain.base; - - // emit the access chain - StorageClass storageClass = (StorageClass)module.getStorageClass(getTypeId(accessChain.base)); - accessChain.instr = createAccessChain(storageClass, accessChain.base, accessChain.indexChain); - - return accessChain.instr; -} - -// For a dynamic component selection of a swizzle. -// -// Turn the swizzle and dynamic component into just a dynamic component. -// -// Generates code. -void Builder::remapDynamicSwizzle() -{ - // do we have a swizzle to remap a dynamic component through? - if (accessChain.component != NoResult && accessChain.swizzle.size() > 1) { - // build a vector of the swizzle for the component to map into - std::vector components; - for (int c = 0; c < (int)accessChain.swizzle.size(); ++c) - components.push_back(makeUintConstant(accessChain.swizzle[c])); - Id mapType = makeVectorType(makeUintType(32), (int)accessChain.swizzle.size()); - Id map = makeCompositeConstant(mapType, components); - - // use it - accessChain.component = createVectorExtractDynamic(map, makeUintType(32), accessChain.component); - accessChain.swizzle.clear(); - } -} - -// clear out swizzle if it is redundant, that is reselecting the same components -// that would be present without the swizzle. -void Builder::simplifyAccessChainSwizzle() -{ - // If the swizzle has fewer components than the vector, it is subsetting, and must stay - // to preserve that fact. - if (getNumTypeComponents(accessChain.preSwizzleBaseType) > (int)accessChain.swizzle.size()) - return; - - // if components are out of order, it is a swizzle - for (unsigned int i = 0; i < accessChain.swizzle.size(); ++i) { - if (i != accessChain.swizzle[i]) - return; - } - - // otherwise, there is no need to track this swizzle - accessChain.swizzle.clear(); - if (accessChain.component == NoResult) - accessChain.preSwizzleBaseType = NoType; -} - -// To the extent any swizzling can become part of the chain -// of accesses instead of a post operation, make it so. -// If 'dynamic' is true, include transferring the dynamic component, -// otherwise, leave it pending. -// -// Does not generate code. just updates the access chain. -void Builder::transferAccessChainSwizzle(bool dynamic) -{ - // non existent? - if (accessChain.swizzle.size() == 0 && accessChain.component == NoResult) - return; - - // too complex? - // (this requires either a swizzle, or generating code for a dynamic component) - if (accessChain.swizzle.size() > 1) - return; - - // single component, either in the swizzle and/or dynamic component - if (accessChain.swizzle.size() == 1) { - assert(accessChain.component == NoResult); - // handle static component selection - accessChain.indexChain.push_back(makeUintConstant(accessChain.swizzle.front())); - accessChain.swizzle.clear(); - accessChain.preSwizzleBaseType = NoType; - } else if (dynamic && accessChain.component != NoResult) { - assert(accessChain.swizzle.size() == 0); - // handle dynamic component - accessChain.indexChain.push_back(accessChain.component); - accessChain.preSwizzleBaseType = NoType; - accessChain.component = NoResult; - } -} - -// Utility method for creating a new block and setting the insert point to -// be in it. This is useful for flow-control operations that need a "dummy" -// block proceeding them (e.g. instructions after a discard, etc). -void Builder::createAndSetNoPredecessorBlock(const char* /*name*/) -{ - Block* block = new Block(getUniqueId(), buildPoint->getParent()); - block->setUnreachable(); - buildPoint->getParent().addBlock(block); - setBuildPoint(block); - - // if (name) - // addName(block->getId(), name); -} - -// Comments in header -void Builder::createBranch(Block* block) -{ - Instruction* branch = new Instruction(OpBranch); - branch->addIdOperand(block->getId()); - buildPoint->addInstruction(std::unique_ptr(branch)); - block->addPredecessor(buildPoint); -} - -void Builder::createSelectionMerge(Block* mergeBlock, unsigned int control) -{ - Instruction* merge = new Instruction(OpSelectionMerge); - merge->addIdOperand(mergeBlock->getId()); - merge->addImmediateOperand(control); - buildPoint->addInstruction(std::unique_ptr(merge)); -} - -void Builder::createLoopMerge(Block* mergeBlock, Block* continueBlock, unsigned int control, - unsigned int dependencyLength) -{ - Instruction* merge = new Instruction(OpLoopMerge); - merge->addIdOperand(mergeBlock->getId()); - merge->addIdOperand(continueBlock->getId()); - merge->addImmediateOperand(control); - if ((control & LoopControlDependencyLengthMask) != 0) - merge->addImmediateOperand(dependencyLength); - buildPoint->addInstruction(std::unique_ptr(merge)); -} - -void Builder::createConditionalBranch(Id condition, Block* thenBlock, Block* elseBlock) -{ - Instruction* branch = new Instruction(OpBranchConditional); - branch->addIdOperand(condition); - branch->addIdOperand(thenBlock->getId()); - branch->addIdOperand(elseBlock->getId()); - buildPoint->addInstruction(std::unique_ptr(branch)); - thenBlock->addPredecessor(buildPoint); - elseBlock->addPredecessor(buildPoint); -} - -// OpSource -// [OpSourceContinued] -// ... -void Builder::dumpSourceInstructions(std::vector& out) const -{ - const int maxWordCount = 0xFFFF; - const int opSourceWordCount = 4; - const int nonNullBytesPerInstruction = 4 * (maxWordCount - opSourceWordCount) - 1; - - if (source != SourceLanguageUnknown) { - // OpSource Language Version File Source - Instruction sourceInst(NoResult, NoType, OpSource); - sourceInst.addImmediateOperand(source); - sourceInst.addImmediateOperand(sourceVersion); - // File operand - if (sourceFileStringId != NoResult) { - sourceInst.addIdOperand(sourceFileStringId); - // Source operand - if (sourceText.size() > 0) { - int nextByte = 0; - std::string subString; - while ((int)sourceText.size() - nextByte > 0) { - subString = sourceText.substr(nextByte, nonNullBytesPerInstruction); - if (nextByte == 0) { - // OpSource - sourceInst.addStringOperand(subString.c_str()); - sourceInst.dump(out); - } else { - // OpSourcContinued - Instruction sourceContinuedInst(OpSourceContinued); - sourceContinuedInst.addStringOperand(subString.c_str()); - sourceContinuedInst.dump(out); - } - nextByte += nonNullBytesPerInstruction; - } - } else - sourceInst.dump(out); - } else - sourceInst.dump(out); - } -} - -void Builder::dumpInstructions(std::vector& out, const std::vector >& instructions) const -{ - for (int i = 0; i < (int)instructions.size(); ++i) { - instructions[i]->dump(out); - } -} - -void Builder::dumpModuleProcesses(std::vector& out) const -{ - for (int i = 0; i < (int)moduleProcesses.size(); ++i) { - Instruction moduleProcessed(OpModuleProcessed); - moduleProcessed.addStringOperand(moduleProcesses[i]); - moduleProcessed.dump(out); - } -} - -}; // end spv namespace diff --git a/External/glslang/SPIRV/SpvBuilder.h b/External/glslang/SPIRV/SpvBuilder.h deleted file mode 100644 index 099b1d95..00000000 --- a/External/glslang/SPIRV/SpvBuilder.h +++ /dev/null @@ -1,648 +0,0 @@ -// -// Copyright (C) 2014-2015 LunarG, Inc. -// Copyright (C) 2015-2016 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. - -// -// "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 - -namespace spv { - -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; - } - void setSourceFile(const std::string& file) - { - Instruction* fileString = new Instruction(getUniqueId(), NoType, OpString); - fileString->addStringOperand(file.c_str()); - sourceFileStringId = fileString->getResultId(); - strings.push_back(std::unique_ptr(fileString)); - } - void setSourceText(const std::string& text) { sourceText = text; } - void addSourceExtension(const char* ext) { sourceExtensions.push_back(ext); } - void addModuleProcessed(const std::string& p) { moduleProcesses.push_back(p.c_str()); } - void setEmitOpLines() { emitOpLines = true; } - void addExtension(const char* ext) { extensions.insert(ext); } - Id import(const char*); - void setMemoryModel(spv::AddressingModel addr, spv::MemoryModel mem) - { - addressModel = addr; - memoryModel = mem; - } - - void addCapability(spv::Capability cap) { capabilities.insert(cap); } - - // To get a new for anything needing a new one. - Id getUniqueId() { return ++uniqueId; } - - // To get a set of new s, e.g., for a set of function parameters - Id getUniqueIds(int numIds) - { - Id id = uniqueId + 1; - uniqueId += numIds; - return id; - } - - // Log the current line, and if different than the last one, - // issue a new OpLine, using the current file name. - void setLine(int line); - // Low-level OpLine. See setLine() for a layered helper. - void addLine(Id fileName, int line, int column); - - // For creating new types (will return old type if the requested one was already made). - Id makeVoidType(); - Id makeBoolType(); - Id makePointer(StorageClass, Id type); - Id makeIntegerType(int width, bool hasSign); // generic - Id makeIntType(int width) { return makeIntegerType(width, true); } - Id makeUintType(int width) { return makeIntegerType(width, false); } - Id makeFloatType(int width); - Id makeStructType(const std::vector& members, const char*); - Id makeStructResultType(Id type0, Id type1); - Id makeVectorType(Id component, int size); - Id makeMatrixType(Id component, int cols, int rows); - Id makeArrayType(Id element, Id sizeId, int stride); // 0 stride means no stride decoration - Id makeRuntimeArray(Id element); - Id makeFunctionType(Id returnType, const std::vector& paramTypes); - Id makeImageType(Id sampledType, Dim, bool depth, bool arrayed, bool ms, unsigned sampled, ImageFormat format); - Id makeSamplerType(); - Id makeSampledImageType(Id imageType); - - // For querying about types. - Id getTypeId(Id resultId) const { return module.getTypeId(resultId); } - Id getDerefTypeId(Id resultId) const; - Op getOpCode(Id id) const { return module.getInstruction(id)->getOpCode(); } - Op getTypeClass(Id typeId) const { return getOpCode(typeId); } - Op getMostBasicTypeClass(Id typeId) const; - int getNumComponents(Id resultId) const { return getNumTypeComponents(getTypeId(resultId)); } - int getNumTypeConstituents(Id typeId) const; - int getNumTypeComponents(Id typeId) const { return getNumTypeConstituents(typeId); } - Id getScalarTypeId(Id typeId) const; - Id getContainedTypeId(Id typeId) const; - Id getContainedTypeId(Id typeId, int) const; - StorageClass getTypeStorageClass(Id typeId) const { return module.getStorageClass(typeId); } - ImageFormat getImageTypeFormat(Id typeId) const { return (ImageFormat)module.getInstruction(typeId)->getImmediateOperand(6); } - - bool isPointer(Id resultId) const { return isPointerType(getTypeId(resultId)); } - bool isScalar(Id resultId) const { return isScalarType(getTypeId(resultId)); } - bool isVector(Id resultId) const { return isVectorType(getTypeId(resultId)); } - bool isMatrix(Id resultId) const { return isMatrixType(getTypeId(resultId)); } - bool isAggregate(Id resultId) const { return isAggregateType(getTypeId(resultId)); } - bool isSampledImage(Id resultId) const { return isSampledImageType(getTypeId(resultId)); } - - bool isBoolType(Id typeId) { return groupedTypes[OpTypeBool].size() > 0 && typeId == groupedTypes[OpTypeBool].back()->getResultId(); } - bool isIntType(Id typeId) const { return getTypeClass(typeId) == OpTypeInt && module.getInstruction(typeId)->getImmediateOperand(1) != 0; } - bool isUintType(Id typeId) const { return getTypeClass(typeId) == OpTypeInt && module.getInstruction(typeId)->getImmediateOperand(1) == 0; } - bool isFloatType(Id typeId) const { return getTypeClass(typeId) == OpTypeFloat; } - bool isPointerType(Id typeId) const { return getTypeClass(typeId) == OpTypePointer; } - bool isScalarType(Id typeId) const { return getTypeClass(typeId) == OpTypeFloat || getTypeClass(typeId) == OpTypeInt || getTypeClass(typeId) == OpTypeBool; } - bool isVectorType(Id typeId) const { return getTypeClass(typeId) == OpTypeVector; } - bool isMatrixType(Id typeId) const { return getTypeClass(typeId) == OpTypeMatrix; } - bool isStructType(Id typeId) const { return getTypeClass(typeId) == OpTypeStruct; } - bool isArrayType(Id typeId) const { return getTypeClass(typeId) == OpTypeArray; } - bool isAggregateType(Id typeId) const { return isArrayType(typeId) || isStructType(typeId); } - bool isImageType(Id typeId) const { return getTypeClass(typeId) == OpTypeImage; } - bool isSamplerType(Id typeId) const { return getTypeClass(typeId) == OpTypeSampler; } - bool isSampledImageType(Id typeId) const { return getTypeClass(typeId) == OpTypeSampledImage; } - - bool isConstantOpCode(Op opcode) const; - bool isSpecConstantOpCode(Op opcode) const; - bool isConstant(Id resultId) const { return isConstantOpCode(getOpCode(resultId)); } - bool isConstantScalar(Id resultId) const { return getOpCode(resultId) == OpConstant; } - bool isSpecConstant(Id resultId) const { return isSpecConstantOpCode(getOpCode(resultId)); } - unsigned int getConstantScalar(Id resultId) const { return module.getInstruction(resultId)->getImmediateOperand(0); } - StorageClass getStorageClass(Id resultId) const { return getTypeStorageClass(getTypeId(resultId)); } - - int getScalarTypeWidth(Id typeId) const - { - Id scalarTypeId = getScalarTypeId(typeId); - assert(getTypeClass(scalarTypeId) == OpTypeInt || getTypeClass(scalarTypeId) == OpTypeFloat); - return module.getInstruction(scalarTypeId)->getImmediateOperand(0); - } - - int getTypeNumColumns(Id typeId) const - { - assert(isMatrixType(typeId)); - return getNumTypeConstituents(typeId); - } - int getNumColumns(Id resultId) const { return getTypeNumColumns(getTypeId(resultId)); } - int getTypeNumRows(Id typeId) const - { - assert(isMatrixType(typeId)); - return getNumTypeComponents(getContainedTypeId(typeId)); - } - int getNumRows(Id resultId) const { return getTypeNumRows(getTypeId(resultId)); } - - Dim getTypeDimensionality(Id typeId) const - { - assert(isImageType(typeId)); - return (Dim)module.getInstruction(typeId)->getImmediateOperand(1); - } - Id getImageType(Id resultId) const - { - Id typeId = getTypeId(resultId); - assert(isImageType(typeId) || isSampledImageType(typeId)); - return isSampledImageType(typeId) ? module.getInstruction(typeId)->getIdOperand(0) : typeId; - } - bool isArrayedImageType(Id typeId) const - { - assert(isImageType(typeId)); - return module.getInstruction(typeId)->getImmediateOperand(3) != 0; - } - - // For making new constants (will return old constant if the requested one was already made). - Id makeBoolConstant(bool b, bool specConstant = false); - Id 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); - - // Create an intermediate with an undefined value. - Id createUndefined(Id type); - - // Store into an Id and return the l-value - void createStore(Id rValue, Id lValue); - - // Load from an Id and return it - Id createLoad(Id lValue); - - // Create an OpAccessChain instruction - Id createAccessChain(StorageClass, Id base, const std::vector& offsets); - - // Create an OpArrayLength instruction - Id createArrayLength(Id base, unsigned int member); - - // Create an OpCompositeExtract instruction - Id createCompositeExtract(Id composite, Id typeId, unsigned index); - Id createCompositeExtract(Id composite, Id typeId, const std::vector& indexes); - Id createCompositeInsert(Id object, Id composite, Id typeId, unsigned index); - Id createCompositeInsert(Id object, Id composite, Id typeId, const std::vector& indexes); - - Id createVectorExtractDynamic(Id vector, Id typeId, Id componentIndex); - Id createVectorInsertDynamic(Id vector, Id typeId, Id component, Id componentIndex); - - void createNoResultOp(Op); - void createNoResultOp(Op, Id operand); - void createNoResultOp(Op, const std::vector& operands); - void createControlBarrier(Scope execution, Scope memory, MemorySemanticsMask); - void createMemoryBarrier(unsigned executionScope, unsigned memorySemantics); - Id createUnaryOp(Op, Id typeId, Id operand); - Id createBinOp(Op, Id typeId, Id operand1, Id operand2); - Id createTriOp(Op, Id typeId, Id operand1, Id operand2, Id operand3); - Id createOp(Op, Id typeId, const std::vector& operands); - Id createFunctionCall(spv::Function*, const std::vector&); - Id createSpecConstantOp(Op, Id typeId, const std::vector& operands, const std::vector& literals); - - // Take an rvalue (source) and a set of channels to extract from it to - // make a new rvalue, which is returned. - Id createRvalueSwizzle(Decoration precision, Id typeId, Id source, const std::vector& channels); - - // Take a copy of an lvalue (target) and a source of components, and set the - // source components into the lvalue where the 'channels' say to put them. - // An updated version of the target is returned. - // (No true lvalue or stores are used.) - Id createLvalueSwizzle(Id typeId, Id target, Id source, const std::vector& channels); - - // If both the id and precision are valid, the id - // gets tagged with the requested precision. - // The passed in id is always the returned id, to simplify use patterns. - Id setPrecision(Id id, Decoration precision) - { - if (precision != NoPrecision && id != NoResult) - addDecoration(id, precision); - - return id; - } - - // Can smear a scalar to a vector for the following forms: - // - promoteScalar(scalar, vector) // smear scalar to width of vector - // - promoteScalar(vector, scalar) // smear scalar to width of vector - // - promoteScalar(pointer, scalar) // smear scalar to width of what pointer points to - // - promoteScalar(scalar, scalar) // do nothing - // Other forms are not allowed. - // - // Generally, the type of 'scalar' does not need to be the same type as the components in 'vector'. - // The type of the created vector is a vector of components of the same type as the scalar. - // - // Note: One of the arguments will change, with the result coming back that way rather than - // through the return value. - void promoteScalar(Decoration precision, Id& left, Id& right); - - // Make a value by smearing the scalar to fill the type. - // vectorType should be the correct type for making a vector of scalarVal. - // (No conversions are done.) - Id smearScalar(Decoration precision, Id scalarVal, Id vectorType); - - // Create a call to a built-in function. - Id createBuiltinCall(Id resultType, Id builtins, int entryPoint, const std::vector& args); - - // List of parameters used to create a texture operation - struct TextureParameters { - Id sampler; - Id coords; - Id bias; - Id lod; - Id Dref; - Id offset; - Id offsets; - Id gradX; - Id gradY; - Id sample; - Id component; - Id texelOut; - Id lodClamp; - }; - - // Select the correct texture operation based on all inputs, and emit the correct instruction - Id createTextureCall(Decoration precision, Id resultType, bool sparse, bool fetch, bool proj, bool gather, bool noImplicit, const TextureParameters&); - - // Emit the OpTextureQuery* instruction that was passed in. - // Figure out the right return value and type, and return it. - Id createTextureQueryCall(Op, const TextureParameters&, bool isUnsignedResult); - - Id createSamplePositionCall(Decoration precision, Id, Id); - - Id createBitFieldExtractCall(Decoration precision, Id, Id, Id, bool isSigned); - Id createBitFieldInsertCall(Decoration precision, Id, Id, Id, Id); - - // Reduction comparison for composites: For equal and not-equal resulting in a scalar. - Id createCompositeCompare(Decoration precision, Id, Id, bool /* true if for equal, false if for not-equal */); - - // OpCompositeConstruct - Id createCompositeConstruct(Id typeId, const std::vector& constituents); - - // vector or scalar constructor - Id createConstructor(Decoration precision, const std::vector& sources, Id resultTypeId); - - // matrix constructor - Id createMatrixConstructor(Decoration precision, const std::vector& sources, Id constructee); - - // Helper to use for building nested control flow with if-then-else. - class If { - public: - If(Id condition, unsigned int ctrl, Builder& builder); - ~If() {} - - void makeBeginElse(); - void makeEndIf(); - - private: - If(const If&); - If& operator=(If&); - - Builder& builder; - Id condition; - unsigned int control; - Function* function; - Block* headerBlock; - Block* thenBlock; - Block* elseBlock; - Block* mergeBlock; - }; - - // Make a switch statement. A switch has 'numSegments' of pieces of code, not containing - // any case/default labels, all separated by one or more case/default labels. Each possible - // case value v is a jump to the caseValues[v] segment. The defaultSegment is also in this - // number space. How to compute the value is given by 'condition', as in switch(condition). - // - // The SPIR-V Builder will maintain the stack of post-switch merge blocks for nested switches. - // - // Use a defaultSegment < 0 if there is no default segment (to branch to post switch). - // - // Returns the right set of basic blocks to start each code segment with, so that the caller's - // recursion stack can hold the memory for it. - // - void makeSwitch(Id condition, unsigned int control, int numSegments, const std::vector& caseValues, - const std::vector& valueToSegment, int defaultSegment, std::vector& segmentBB); // return argument - - // Add a branch to the innermost switch's merge block. - void addSwitchBreak(); - - // Move to the next code segment, passing in the return argument in makeSwitch() - void nextSwitchSegment(std::vector& segmentBB, int segment); - - // Finish off the innermost switch. - void endSwitch(std::vector& segmentBB); - - struct LoopBlocks { - LoopBlocks(Block& head, Block& body, Block& merge, Block& continue_target) : - head(head), body(body), merge(merge), continue_target(continue_target) { } - Block &head, &body, &merge, &continue_target; - private: - LoopBlocks(); - LoopBlocks& operator=(const LoopBlocks&); - }; - - // Start a new loop and prepare the builder to generate code for it. Until - // closeLoop() is called for this loop, createLoopContinue() and - // createLoopExit() will target its corresponding blocks. - LoopBlocks& makeNewLoop(); - - // Create a new block in the function containing the build point. Memory is - // owned by the function object. - Block& makeNewBlock(); - - // Add a branch to the continue_target of the current (innermost) loop. - void createLoopContinue(); - - // Add an exit (e.g. "break") from the innermost loop that we're currently - // in. - void createLoopExit(); - - // Close the innermost loop that you're in - void closeLoop(); - - // - // Access chain design for an R-Value vs. L-Value: - // - // There is a single access chain the builder is building at - // any particular time. Such a chain can be used to either to a load or - // a store, when desired. - // - // Expressions can be r-values, l-values, or both, or only r-values: - // a[b.c].d = .... // l-value - // ... = a[b.c].d; // r-value, that also looks like an l-value - // ++a[b.c].d; // r-value and l-value - // (x + y)[2]; // r-value only, can't possibly be l-value - // - // Computing an r-value means generating code. Hence, - // r-values should only be computed when they are needed, not speculatively. - // - // Computing an l-value means saving away information for later use in the compiler, - // no code is generated until the l-value is later dereferenced. It is okay - // to speculatively generate an l-value, just not okay to speculatively dereference it. - // - // The base of the access chain (the left-most variable or expression - // from which everything is based) can be set either as an l-value - // or as an r-value. Most efficient would be to set an l-value if one - // is available. If an expression was evaluated, the resulting r-value - // can be set as the chain base. - // - // The users of this single access chain can save and restore if they - // want to nest or manage multiple chains. - // - - struct AccessChain { - Id base; // for l-values, pointer to the base object, for r-values, the base object - std::vector indexChain; - Id instr; // cache the instruction that generates this access chain - std::vector swizzle; // each std::vector element selects the next GLSL component number - Id component; // a dynamic component index, can coexist with a swizzle, done after the swizzle, NoResult if not present - Id preSwizzleBaseType; // dereferenced type, before swizzle or component is applied; NoType unless a swizzle or component is present - bool isRValue; // true if 'base' is an r-value, otherwise, base is an l-value - }; - - // - // the SPIR-V builder maintains a single active chain that - // the following methods operate on - // - - // for external save and restore - AccessChain getAccessChain() { return accessChain; } - void setAccessChain(AccessChain newChain) { accessChain = newChain; } - - // clear accessChain - void clearAccessChain(); - - // set new base as an l-value base - void setAccessChainLValue(Id lValue) - { - assert(isPointer(lValue)); - accessChain.base = lValue; - } - - // set new base value as an r-value - void setAccessChainRValue(Id rValue) - { - accessChain.isRValue = true; - accessChain.base = rValue; - } - - // push offset onto the end of the chain - void accessChainPush(Id offset) - { - accessChain.indexChain.push_back(offset); - } - - // push new swizzle onto the end of any existing swizzle, merging into a single swizzle - void accessChainPushSwizzle(std::vector& swizzle, Id preSwizzleBaseType); - - // push a dynamic component selection onto the access chain, only applicable with a - // non-trivial swizzle or no swizzle - void accessChainPushComponent(Id component, Id preSwizzleBaseType) - { - if (accessChain.swizzle.size() != 1) { - accessChain.component = component; - if (accessChain.preSwizzleBaseType == NoType) - accessChain.preSwizzleBaseType = preSwizzleBaseType; - } - } - - // use accessChain and swizzle to store value - void accessChainStore(Id rvalue); - - // use accessChain and swizzle to load an r-value - Id accessChainLoad(Decoration precision, Decoration nonUniform, Id ResultType); - - // get the direct pointer for an l-value - Id accessChainGetLValue(); - - // Get the inferred SPIR-V type of the result of the current access chain, - // based on the type of the base and the chain of dereferences. - Id accessChainGetInferredType(); - - // Remove OpDecorate instructions whose operands are defined in unreachable - // blocks. - void eliminateDeadDecorations(); - void dump(std::vector&) const; - - void createBranch(Block* block); - void createConditionalBranch(Id condition, Block* thenBlock, Block* elseBlock); - void createLoopMerge(Block* mergeBlock, Block* continueBlock, unsigned int control, unsigned int dependencyLength); - - // 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, 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 dumpInstructions(std::vector&, const std::vector >&) const; - void dumpModuleProcesses(std::vector&) const; - - unsigned int spvVersion; // the version of SPIR-V to emit in the header - SourceLanguage source; - int sourceVersion; - spv::Id sourceFileStringId; - std::string sourceText; - int currentLine; - bool emitOpLines; - std::set extensions; - std::vector sourceExtensions; - std::vector moduleProcesses; - AddressingModel addressModel; - MemoryModel memoryModel; - std::set capabilities; - int builderNumber; - Module module; - Block* buildPoint; - Id uniqueId; - Function* entryPointFunction; - bool generatingOpCodeForSpecConst; - AccessChain accessChain; - - // special blocks of instructions for output - std::vector > strings; - std::vector > imports; - std::vector > entryPoints; - std::vector > executionModes; - std::vector > names; - std::vector > decorations; - std::vector > constantsTypesGlobals; - std::vector > externals; - std::vector > functions; - - // not output, internally used for quick & dirty canonical (unique) creation - std::unordered_map> groupedConstants; // map type opcodes to constant inst. - std::unordered_map> groupedStructConstants; // map struct-id to constant instructions - std::unordered_map> groupedTypes; // map type opcodes to type instructions - - // stack of switches - std::stack switchMerges; - - // Our loop stack. - std::stack loops; - - // The stream for outputting warnings and errors. - SpvBuildLogger* logger; -}; // end Builder class - -}; // end spv namespace - -#endif // SpvBuilder_H diff --git a/External/glslang/SPIRV/bitutils.h b/External/glslang/SPIRV/bitutils.h deleted file mode 100644 index 31288ab6..00000000 --- a/External/glslang/SPIRV/bitutils.h +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright (c) 2015-2016 The Khronos Group Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef LIBSPIRV_UTIL_BITUTILS_H_ -#define LIBSPIRV_UTIL_BITUTILS_H_ - -#include -#include - -namespace spvutils { - -// Performs a bitwise copy of source to the destination type Dest. -template -Dest BitwiseCast(Src source) { - Dest dest; - static_assert(sizeof(source) == sizeof(dest), - "BitwiseCast: Source and destination must have the same size"); - std::memcpy(&dest, &source, sizeof(dest)); - return dest; -} - -// SetBits returns an integer of type with bits set -// for position through , counting from the least -// significant bit. In particular when Num == 0, no positions are set to 1. -// A static assert will be triggered if First + Num > sizeof(T) * 8, that is, -// a bit that will not fit in the underlying type is set. -template -struct SetBits { - static_assert(First < sizeof(T) * 8, - "Tried to set a bit that is shifted too far."); - const static T get = (T(1) << First) | SetBits::get; -}; - -template -struct SetBits { - const static T get = T(0); -}; - -// This is all compile-time so we can put our tests right here. -static_assert(SetBits::get == uint32_t(0x00000000), - "SetBits failed"); -static_assert(SetBits::get == uint32_t(0x00000001), - "SetBits failed"); -static_assert(SetBits::get == uint32_t(0x80000000), - "SetBits failed"); -static_assert(SetBits::get == uint32_t(0x00000006), - "SetBits failed"); -static_assert(SetBits::get == uint32_t(0xc0000000), - "SetBits failed"); -static_assert(SetBits::get == uint32_t(0x7FFFFFFF), - "SetBits failed"); -static_assert(SetBits::get == uint32_t(0xFFFFFFFF), - "SetBits failed"); -static_assert(SetBits::get == uint32_t(0xFFFF0000), - "SetBits failed"); - -static_assert(SetBits::get == uint64_t(0x0000000000000001LL), - "SetBits failed"); -static_assert(SetBits::get == uint64_t(0x8000000000000000LL), - "SetBits failed"); -static_assert(SetBits::get == uint64_t(0xc000000000000000LL), - "SetBits failed"); -static_assert(SetBits::get == uint64_t(0x0000000080000000LL), - "SetBits failed"); -static_assert(SetBits::get == uint64_t(0x00000000FFFF0000LL), - "SetBits failed"); - -} // namespace spvutils - -#endif // LIBSPIRV_UTIL_BITUTILS_H_ diff --git a/External/glslang/SPIRV/disassemble.cpp b/External/glslang/SPIRV/disassemble.cpp deleted file mode 100644 index c07dfc78..00000000 --- a/External/glslang/SPIRV/disassemble.cpp +++ /dev/null @@ -1,698 +0,0 @@ -// -// Copyright (C) 2014-2015 LunarG, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -// -// Disassembler for SPIR-V. -// - -#include -#include -#include -#include -#include -#include -#include - -#include "disassemble.h" -#include "doc.h" - -namespace spv { - extern "C" { - // Include C-based headers that don't have a namespace - #include "GLSL.std.450.h" -#ifdef AMD_EXTENSIONS - #include "GLSL.ext.AMD.h" -#endif - -#ifdef NV_EXTENSIONS - #include "GLSL.ext.NV.h" -#endif - } -} -const char* GlslStd450DebugNames[spv::GLSLstd450Count]; - -namespace spv { - -#ifdef AMD_EXTENSIONS -static const char* GLSLextAMDGetDebugNames(const char*, unsigned); -#endif - -#ifdef NV_EXTENSIONS -static const char* GLSLextNVGetDebugNames(const char*, unsigned); -#endif - -static void Kill(std::ostream& out, const char* message) -{ - out << std::endl << "Disassembly failed: " << message << std::endl; - exit(1); -} - -// used to identify the extended instruction library imported when printing -enum ExtInstSet { - GLSL450Inst, - -#ifdef AMD_EXTENSIONS - GLSLextAMDInst, -#endif - -#ifdef NV_EXTENSIONS - GLSLextNVInst, -#endif - - OpenCLExtInst, -}; - -// Container class for a single instance of a SPIR-V stream, with methods for disassembly. -class SpirvStream { -public: - SpirvStream(std::ostream& out, const std::vector& stream) : out(out), stream(stream), word(0), nextNestedControl(0) { } - virtual ~SpirvStream() { } - - void validate(); - void processInstructions(); - -protected: - SpirvStream(const SpirvStream&); - SpirvStream& operator=(const SpirvStream&); - Op getOpCode(int id) const { return idInstruction[id] ? (Op)(stream[idInstruction[id]] & OpCodeMask) : OpNop; } - - // Output methods - void outputIndent(); - void formatId(Id id, std::stringstream&); - void outputResultId(Id id); - void outputTypeId(Id id); - void outputId(Id id); - void outputMask(OperandClass operandClass, unsigned mask); - void disassembleImmediates(int numOperands); - void disassembleIds(int numOperands); - int disassembleString(); - void disassembleInstruction(Id resultId, Id typeId, Op opCode, int numOperands); - - // Data - std::ostream& out; // where to write the disassembly - const std::vector& stream; // the actual word stream - int size; // the size of the word stream - int word; // the next word of the stream to read - - // map each to the instruction that created it - Id bound; - std::vector idInstruction; // the word offset into the stream where the instruction for result [id] starts; 0 if not yet seen (forward reference or function parameter) - - std::vector idDescriptor; // the best text string known for explaining the - - // schema - unsigned int schema; - - // stack of structured-merge points - std::stack nestedControl; - Id nextNestedControl; // need a slight delay for when we are nested -}; - -void SpirvStream::validate() -{ - size = (int)stream.size(); - if (size < 4) - Kill(out, "stream is too short"); - - // Magic number - if (stream[word++] != MagicNumber) { - out << "Bad magic number"; - return; - } - - // Version - out << "// Module Version " << std::hex << stream[word++] << std::endl; - - // Generator's magic number - out << "// Generated by (magic number): " << std::hex << stream[word++] << std::dec << std::endl; - - // Result bound - bound = stream[word++]; - idInstruction.resize(bound); - idDescriptor.resize(bound); - out << "// Id's are bound by " << bound << std::endl; - out << std::endl; - - // Reserved schema, must be 0 for now - schema = stream[word++]; - if (schema != 0) - Kill(out, "bad schema, must be 0"); -} - -// Loop over all the instructions, in order, processing each. -// Boiler plate for each is handled here directly, the rest is dispatched. -void SpirvStream::processInstructions() -{ - // Instructions - while (word < size) { - int instructionStart = word; - - // Instruction wordCount and opcode - unsigned int firstWord = stream[word]; - unsigned wordCount = firstWord >> WordCountShift; - Op opCode = (Op)(firstWord & OpCodeMask); - int nextInst = word + wordCount; - ++word; - - // Presence of full instruction - if (nextInst > size) - Kill(out, "stream instruction terminated too early"); - - // Base for computing number of operands; will be updated as more is learned - unsigned numOperands = wordCount - 1; - - // Type - Id typeId = 0; - if (InstructionDesc[opCode].hasType()) { - typeId = stream[word++]; - --numOperands; - } - - // Result - Id resultId = 0; - if (InstructionDesc[opCode].hasResult()) { - resultId = stream[word++]; - --numOperands; - - // save instruction for future reference - idInstruction[resultId] = instructionStart; - } - - outputResultId(resultId); - outputTypeId(typeId); - outputIndent(); - - // Hand off the Op and all its operands - disassembleInstruction(resultId, typeId, opCode, numOperands); - if (word != nextInst) { - out << " ERROR, incorrect number of operands consumed. At " << word << " instead of " << nextInst << " instruction start was " << instructionStart; - word = nextInst; - } - out << std::endl; - } -} - -void SpirvStream::outputIndent() -{ - for (int i = 0; i < (int)nestedControl.size(); ++i) - out << " "; -} - -void SpirvStream::formatId(Id id, std::stringstream& idStream) -{ - if (id != 0) { - // On instructions with no IDs, this is called with "0", which does not - // have to be within ID bounds on null shaders. - if (id >= bound) - Kill(out, "Bad "); - - idStream << id; - if (idDescriptor[id].size() > 0) - idStream << "(" << idDescriptor[id] << ")"; - } -} - -void SpirvStream::outputResultId(Id id) -{ - const int width = 16; - std::stringstream idStream; - formatId(id, idStream); - out << std::setw(width) << std::right << idStream.str(); - if (id != 0) - out << ":"; - else - out << " "; - - if (nestedControl.size() && id == nestedControl.top()) - nestedControl.pop(); -} - -void SpirvStream::outputTypeId(Id id) -{ - const int width = 12; - std::stringstream idStream; - formatId(id, idStream); - out << std::setw(width) << std::right << idStream.str() << " "; -} - -void SpirvStream::outputId(Id id) -{ - if (id >= bound) - Kill(out, "Bad "); - - out << id; - if (idDescriptor[id].size() > 0) - out << "(" << idDescriptor[id] << ")"; -} - -void SpirvStream::outputMask(OperandClass operandClass, unsigned mask) -{ - if (mask == 0) - out << "None"; - else { - for (int m = 0; m < OperandClassParams[operandClass].ceiling; ++m) { - if (mask & (1 << m)) - out << OperandClassParams[operandClass].getName(m) << " "; - } - } -} - -void SpirvStream::disassembleImmediates(int numOperands) -{ - for (int i = 0; i < numOperands; ++i) { - out << stream[word++]; - if (i < numOperands - 1) - out << " "; - } -} - -void SpirvStream::disassembleIds(int numOperands) -{ - for (int i = 0; i < numOperands; ++i) { - outputId(stream[word++]); - if (i < numOperands - 1) - out << " "; - } -} - -// return the number of operands consumed by the string -int SpirvStream::disassembleString() -{ - int startWord = word; - - out << " \""; - - const char* wordString; - bool done = false; - do { - unsigned int content = stream[word]; - wordString = (const char*)&content; - for (int charCount = 0; charCount < 4; ++charCount) { - if (*wordString == 0) { - done = true; - break; - } - out << *(wordString++); - } - ++word; - } while (! done); - - out << "\""; - - return word - startWord; -} - -void SpirvStream::disassembleInstruction(Id resultId, Id /*typeId*/, Op opCode, int numOperands) -{ - // Process the opcode - - out << (OpcodeString(opCode) + 2); // leave out the "Op" - - if (opCode == OpLoopMerge || opCode == OpSelectionMerge) - nextNestedControl = stream[word]; - else if (opCode == OpBranchConditional || opCode == OpSwitch) { - if (nextNestedControl) { - nestedControl.push(nextNestedControl); - nextNestedControl = 0; - } - } else if (opCode == OpExtInstImport) { - idDescriptor[resultId] = (const char*)(&stream[word]); - } - else { - if (resultId != 0 && idDescriptor[resultId].size() == 0) { - switch (opCode) { - case OpTypeInt: - idDescriptor[resultId] = "int"; - break; - case OpTypeFloat: - idDescriptor[resultId] = "float"; - break; - case OpTypeBool: - idDescriptor[resultId] = "bool"; - break; - case OpTypeStruct: - idDescriptor[resultId] = "struct"; - break; - case OpTypePointer: - idDescriptor[resultId] = "ptr"; - break; - case OpTypeVector: - if (idDescriptor[stream[word]].size() > 0) - idDescriptor[resultId].append(idDescriptor[stream[word]].begin(), idDescriptor[stream[word]].begin() + 1); - idDescriptor[resultId].append("vec"); - switch (stream[word + 1]) { - case 2: idDescriptor[resultId].append("2"); break; - case 3: idDescriptor[resultId].append("3"); break; - case 4: idDescriptor[resultId].append("4"); break; - case 8: idDescriptor[resultId].append("8"); break; - case 16: idDescriptor[resultId].append("16"); break; - case 32: idDescriptor[resultId].append("32"); break; - default: break; - } - break; - default: - break; - } - } - } - - // Process the operands. Note, a new context-dependent set could be - // swapped in mid-traversal. - - // Handle images specially, so can put out helpful strings. - if (opCode == OpTypeImage) { - out << " "; - disassembleIds(1); - out << " " << DimensionString((Dim)stream[word++]); - out << (stream[word++] != 0 ? " depth" : ""); - out << (stream[word++] != 0 ? " array" : ""); - out << (stream[word++] != 0 ? " multi-sampled" : ""); - switch (stream[word++]) { - case 0: out << " runtime"; break; - case 1: out << " sampled"; break; - case 2: out << " nonsampled"; break; - } - out << " format:" << ImageFormatString((ImageFormat)stream[word++]); - - if (numOperands == 8) { - out << " " << AccessQualifierString(stream[word++]); - } - return; - } - - // Handle all the parameterized operands - for (int op = 0; op < InstructionDesc[opCode].operands.getNum() && numOperands > 0; ++op) { - out << " "; - OperandClass operandClass = InstructionDesc[opCode].operands.getClass(op); - switch (operandClass) { - case OperandId: - case OperandScope: - case OperandMemorySemantics: - disassembleIds(1); - --numOperands; - // Get names for printing "(XXX)" for readability, *after* this id - if (opCode == OpName) - idDescriptor[stream[word - 1]] = (const char*)(&stream[word]); - break; - case OperandVariableIds: - disassembleIds(numOperands); - return; - case OperandImageOperands: - outputMask(OperandImageOperands, stream[word++]); - --numOperands; - disassembleIds(numOperands); - return; - case OperandOptionalLiteral: - case OperandVariableLiterals: - if ((opCode == OpDecorate && stream[word - 1] == DecorationBuiltIn) || - (opCode == OpMemberDecorate && stream[word - 1] == DecorationBuiltIn)) { - out << BuiltInString(stream[word++]); - --numOperands; - ++op; - } - disassembleImmediates(numOperands); - return; - case OperandVariableIdLiteral: - while (numOperands > 0) { - out << std::endl; - outputResultId(0); - outputTypeId(0); - outputIndent(); - out << " Type "; - disassembleIds(1); - out << ", member "; - disassembleImmediates(1); - numOperands -= 2; - } - return; - case OperandVariableLiteralId: - while (numOperands > 0) { - out << std::endl; - outputResultId(0); - outputTypeId(0); - outputIndent(); - out << " case "; - disassembleImmediates(1); - out << ": "; - disassembleIds(1); - numOperands -= 2; - } - return; - case OperandLiteralNumber: - disassembleImmediates(1); - --numOperands; - if (opCode == OpExtInst) { - ExtInstSet extInstSet = GLSL450Inst; - const char* name = idDescriptor[stream[word - 2]].c_str(); - if (0 == memcmp("OpenCL", name, 6)) { - extInstSet = OpenCLExtInst; -#ifdef AMD_EXTENSIONS - } else if (strcmp(spv::E_SPV_AMD_shader_ballot, name) == 0 || - strcmp(spv::E_SPV_AMD_shader_trinary_minmax, name) == 0 || - strcmp(spv::E_SPV_AMD_shader_explicit_vertex_parameter, name) == 0 || - strcmp(spv::E_SPV_AMD_gcn_shader, name) == 0) { - extInstSet = GLSLextAMDInst; -#endif -#ifdef NV_EXTENSIONS - }else if (strcmp(spv::E_SPV_NV_sample_mask_override_coverage, name) == 0 || - strcmp(spv::E_SPV_NV_geometry_shader_passthrough, name) == 0 || - strcmp(spv::E_SPV_NV_viewport_array2, name) == 0 || - strcmp(spv::E_SPV_NVX_multiview_per_view_attributes, name) == 0) { - extInstSet = GLSLextNVInst; -#endif - } - unsigned entrypoint = stream[word - 1]; - if (extInstSet == GLSL450Inst) { - if (entrypoint < GLSLstd450Count) { - out << "(" << GlslStd450DebugNames[entrypoint] << ")"; - } -#ifdef AMD_EXTENSIONS - } else if (extInstSet == GLSLextAMDInst) { - out << "(" << GLSLextAMDGetDebugNames(name, entrypoint) << ")"; -#endif -#ifdef NV_EXTENSIONS - } - else if (extInstSet == GLSLextNVInst) { - out << "(" << GLSLextNVGetDebugNames(name, entrypoint) << ")"; -#endif - } - } - break; - case OperandOptionalLiteralString: - case OperandLiteralString: - numOperands -= disassembleString(); - break; - default: - assert(operandClass >= OperandSource && operandClass < OperandOpcode); - - if (OperandClassParams[operandClass].bitmask) - outputMask(operandClass, stream[word++]); - else - out << OperandClassParams[operandClass].getName(stream[word++]); - --numOperands; - - break; - } - } - - return; -} - -static void GLSLstd450GetDebugNames(const char** names) -{ - for (int i = 0; i < GLSLstd450Count; ++i) - names[i] = "Unknown"; - - names[GLSLstd450Round] = "Round"; - names[GLSLstd450RoundEven] = "RoundEven"; - names[GLSLstd450Trunc] = "Trunc"; - names[GLSLstd450FAbs] = "FAbs"; - names[GLSLstd450SAbs] = "SAbs"; - names[GLSLstd450FSign] = "FSign"; - names[GLSLstd450SSign] = "SSign"; - names[GLSLstd450Floor] = "Floor"; - names[GLSLstd450Ceil] = "Ceil"; - names[GLSLstd450Fract] = "Fract"; - names[GLSLstd450Radians] = "Radians"; - names[GLSLstd450Degrees] = "Degrees"; - names[GLSLstd450Sin] = "Sin"; - names[GLSLstd450Cos] = "Cos"; - names[GLSLstd450Tan] = "Tan"; - names[GLSLstd450Asin] = "Asin"; - names[GLSLstd450Acos] = "Acos"; - names[GLSLstd450Atan] = "Atan"; - names[GLSLstd450Sinh] = "Sinh"; - names[GLSLstd450Cosh] = "Cosh"; - names[GLSLstd450Tanh] = "Tanh"; - names[GLSLstd450Asinh] = "Asinh"; - names[GLSLstd450Acosh] = "Acosh"; - names[GLSLstd450Atanh] = "Atanh"; - names[GLSLstd450Atan2] = "Atan2"; - names[GLSLstd450Pow] = "Pow"; - names[GLSLstd450Exp] = "Exp"; - names[GLSLstd450Log] = "Log"; - names[GLSLstd450Exp2] = "Exp2"; - names[GLSLstd450Log2] = "Log2"; - names[GLSLstd450Sqrt] = "Sqrt"; - names[GLSLstd450InverseSqrt] = "InverseSqrt"; - names[GLSLstd450Determinant] = "Determinant"; - names[GLSLstd450MatrixInverse] = "MatrixInverse"; - names[GLSLstd450Modf] = "Modf"; - names[GLSLstd450ModfStruct] = "ModfStruct"; - names[GLSLstd450FMin] = "FMin"; - names[GLSLstd450SMin] = "SMin"; - names[GLSLstd450UMin] = "UMin"; - names[GLSLstd450FMax] = "FMax"; - names[GLSLstd450SMax] = "SMax"; - names[GLSLstd450UMax] = "UMax"; - names[GLSLstd450FClamp] = "FClamp"; - names[GLSLstd450SClamp] = "SClamp"; - names[GLSLstd450UClamp] = "UClamp"; - names[GLSLstd450FMix] = "FMix"; - names[GLSLstd450Step] = "Step"; - names[GLSLstd450SmoothStep] = "SmoothStep"; - names[GLSLstd450Fma] = "Fma"; - names[GLSLstd450Frexp] = "Frexp"; - names[GLSLstd450FrexpStruct] = "FrexpStruct"; - names[GLSLstd450Ldexp] = "Ldexp"; - names[GLSLstd450PackSnorm4x8] = "PackSnorm4x8"; - names[GLSLstd450PackUnorm4x8] = "PackUnorm4x8"; - names[GLSLstd450PackSnorm2x16] = "PackSnorm2x16"; - names[GLSLstd450PackUnorm2x16] = "PackUnorm2x16"; - names[GLSLstd450PackHalf2x16] = "PackHalf2x16"; - names[GLSLstd450PackDouble2x32] = "PackDouble2x32"; - names[GLSLstd450UnpackSnorm2x16] = "UnpackSnorm2x16"; - names[GLSLstd450UnpackUnorm2x16] = "UnpackUnorm2x16"; - names[GLSLstd450UnpackHalf2x16] = "UnpackHalf2x16"; - names[GLSLstd450UnpackSnorm4x8] = "UnpackSnorm4x8"; - names[GLSLstd450UnpackUnorm4x8] = "UnpackUnorm4x8"; - names[GLSLstd450UnpackDouble2x32] = "UnpackDouble2x32"; - names[GLSLstd450Length] = "Length"; - names[GLSLstd450Distance] = "Distance"; - names[GLSLstd450Cross] = "Cross"; - names[GLSLstd450Normalize] = "Normalize"; - names[GLSLstd450FaceForward] = "FaceForward"; - names[GLSLstd450Reflect] = "Reflect"; - names[GLSLstd450Refract] = "Refract"; - names[GLSLstd450FindILsb] = "FindILsb"; - names[GLSLstd450FindSMsb] = "FindSMsb"; - names[GLSLstd450FindUMsb] = "FindUMsb"; - names[GLSLstd450InterpolateAtCentroid] = "InterpolateAtCentroid"; - names[GLSLstd450InterpolateAtSample] = "InterpolateAtSample"; - names[GLSLstd450InterpolateAtOffset] = "InterpolateAtOffset"; -} - -#ifdef AMD_EXTENSIONS -static const char* GLSLextAMDGetDebugNames(const char* name, unsigned entrypoint) -{ - if (strcmp(name, spv::E_SPV_AMD_shader_ballot) == 0) { - switch (entrypoint) { - case SwizzleInvocationsAMD: return "SwizzleInvocationsAMD"; - case SwizzleInvocationsMaskedAMD: return "SwizzleInvocationsMaskedAMD"; - case WriteInvocationAMD: return "WriteInvocationAMD"; - case MbcntAMD: return "MbcntAMD"; - default: return "Bad"; - } - } else if (strcmp(name, spv::E_SPV_AMD_shader_trinary_minmax) == 0) { - switch (entrypoint) { - case FMin3AMD: return "FMin3AMD"; - case UMin3AMD: return "UMin3AMD"; - case SMin3AMD: return "SMin3AMD"; - case FMax3AMD: return "FMax3AMD"; - case UMax3AMD: return "UMax3AMD"; - case SMax3AMD: return "SMax3AMD"; - case FMid3AMD: return "FMid3AMD"; - case UMid3AMD: return "UMid3AMD"; - case SMid3AMD: return "SMid3AMD"; - default: return "Bad"; - } - } else if (strcmp(name, spv::E_SPV_AMD_shader_explicit_vertex_parameter) == 0) { - switch (entrypoint) { - case InterpolateAtVertexAMD: return "InterpolateAtVertexAMD"; - default: return "Bad"; - } - } - else if (strcmp(name, spv::E_SPV_AMD_gcn_shader) == 0) { - switch (entrypoint) { - case CubeFaceIndexAMD: return "CubeFaceIndexAMD"; - case CubeFaceCoordAMD: return "CubeFaceCoordAMD"; - case TimeAMD: return "TimeAMD"; - default: - break; - } - } - - return "Bad"; -} -#endif - -#ifdef NV_EXTENSIONS -static const char* GLSLextNVGetDebugNames(const char* name, unsigned entrypoint) -{ - if (strcmp(name, spv::E_SPV_NV_sample_mask_override_coverage) == 0 || - strcmp(name, spv::E_SPV_NV_geometry_shader_passthrough) == 0 || - strcmp(name, spv::E_ARB_shader_viewport_layer_array) == 0 || - strcmp(name, spv::E_SPV_NV_viewport_array2) == 0 || - strcmp(spv::E_SPV_NVX_multiview_per_view_attributes, name) == 0) { - switch (entrypoint) { - case DecorationOverrideCoverageNV: return "OverrideCoverageNV"; - case DecorationPassthroughNV: return "PassthroughNV"; - case CapabilityGeometryShaderPassthroughNV: return "GeometryShaderPassthroughNV"; - case DecorationViewportRelativeNV: return "ViewportRelativeNV"; - case BuiltInViewportMaskNV: return "ViewportMaskNV"; - case CapabilityShaderViewportMaskNV: return "ShaderViewportMaskNV"; - case DecorationSecondaryViewportRelativeNV: return "SecondaryViewportRelativeNV"; - case BuiltInSecondaryPositionNV: return "SecondaryPositionNV"; - case BuiltInSecondaryViewportMaskNV: return "SecondaryViewportMaskNV"; - case CapabilityShaderStereoViewNV: return "ShaderStereoViewNV"; - case BuiltInPositionPerViewNV: return "PositionPerViewNV"; - case BuiltInViewportMaskPerViewNV: return "ViewportMaskPerViewNV"; - case CapabilityPerViewAttributesNV: return "PerViewAttributesNV"; - default: return "Bad"; - } - } - return "Bad"; -} -#endif - -void Disassemble(std::ostream& out, const std::vector& stream) -{ - SpirvStream SpirvStream(out, stream); - spv::Parameterize(); - GLSLstd450GetDebugNames(GlslStd450DebugNames); - SpirvStream.validate(); - SpirvStream.processInstructions(); -} - -}; // end namespace spv diff --git a/External/glslang/SPIRV/disassemble.h b/External/glslang/SPIRV/disassemble.h deleted file mode 100644 index 47cef65a..00000000 --- a/External/glslang/SPIRV/disassemble.h +++ /dev/null @@ -1,52 +0,0 @@ -// -// Copyright (C) 2014-2015 LunarG, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -// -// Disassembler for SPIR-V. -// - -#pragma once -#ifndef disassembler_H -#define disassembler_H - -#include -#include - -namespace spv { - - void Disassemble(std::ostream& out, const std::vector&); - -}; // end namespace spv - -#endif // disassembler_H diff --git a/External/glslang/SPIRV/doc.cpp b/External/glslang/SPIRV/doc.cpp deleted file mode 100644 index a9059687..00000000 --- a/External/glslang/SPIRV/doc.cpp +++ /dev/null @@ -1,2568 +0,0 @@ -// -// Copyright (C) 2014-2015 LunarG, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -// -// 1) Programmatically fill in instruction/operand information. -// This can be used for disassembly, printing documentation, etc. -// -// 2) Print documentation from this parameterization. -// - -#include "doc.h" - -#include -#include -#include - -namespace spv { - extern "C" { - // Include C-based headers that don't have a namespace - #include "GLSL.ext.KHR.h" - #include "GLSL.ext.EXT.h" -#ifdef AMD_EXTENSIONS - #include "GLSL.ext.AMD.h" -#endif -#ifdef NV_EXTENSIONS - #include "GLSL.ext.NV.h" -#endif - } -} - -namespace spv { - -// -// Whole set of functions that translate enumerants to their text strings for -// the specification (or their sanitized versions for auto-generating the -// spirv headers. -// -// Also, for masks the ceilings are declared next to these, to help keep them in sync. -// Ceilings should be -// - one more than the maximum value an enumerant takes on, for non-mask enumerants -// (for non-sparse enums, this is the number of enumerants) -// - the number of bits consumed by the set of masks -// (for non-sparse mask enums, this is the number of enumerants) -// - -const char* SourceString(int source) -{ - switch (source) { - case 0: return "Unknown"; - case 1: return "ESSL"; - case 2: return "GLSL"; - case 3: return "OpenCL_C"; - case 4: return "OpenCL_CPP"; - case 5: return "HLSL"; - - default: return "Bad"; - } -} - -const char* ExecutionModelString(int model) -{ - switch (model) { - case 0: return "Vertex"; - case 1: return "TessellationControl"; - case 2: return "TessellationEvaluation"; - case 3: return "Geometry"; - case 4: return "Fragment"; - case 5: return "GLCompute"; - case 6: return "Kernel"; - - default: return "Bad"; - } -} - -const char* AddressingString(int addr) -{ - switch (addr) { - case 0: return "Logical"; - case 1: return "Physical32"; - case 2: return "Physical64"; - - default: return "Bad"; - } -} - -const char* MemoryString(int mem) -{ - switch (mem) { - case 0: return "Simple"; - case 1: return "GLSL450"; - case 2: return "OpenCL"; - - default: return "Bad"; - } -} - -const int ExecutionModeCeiling = 33; - -const char* ExecutionModeString(int mode) -{ - switch (mode) { - case 0: return "Invocations"; - case 1: return "SpacingEqual"; - case 2: return "SpacingFractionalEven"; - case 3: return "SpacingFractionalOdd"; - case 4: return "VertexOrderCw"; - case 5: return "VertexOrderCcw"; - case 6: return "PixelCenterInteger"; - case 7: return "OriginUpperLeft"; - case 8: return "OriginLowerLeft"; - case 9: return "EarlyFragmentTests"; - case 10: return "PointMode"; - case 11: return "Xfb"; - case 12: return "DepthReplacing"; - case 13: return "Bad"; - case 14: return "DepthGreater"; - case 15: return "DepthLess"; - case 16: return "DepthUnchanged"; - case 17: return "LocalSize"; - case 18: return "LocalSizeHint"; - case 19: return "InputPoints"; - case 20: return "InputLines"; - case 21: return "InputLinesAdjacency"; - case 22: return "Triangles"; - case 23: return "InputTrianglesAdjacency"; - case 24: return "Quads"; - case 25: return "Isolines"; - case 26: return "OutputVertices"; - case 27: return "OutputPoints"; - case 28: return "OutputLineStrip"; - case 29: return "OutputTriangleStrip"; - case 30: return "VecTypeHint"; - case 31: return "ContractionOff"; - case 32: return "Bad"; - - case 4446: return "PostDepthCoverage"; - case ExecutionModeCeiling: - default: return "Bad"; - } -} - -const char* StorageClassString(int StorageClass) -{ - switch (StorageClass) { - case 0: return "UniformConstant"; - case 1: return "Input"; - case 2: return "Uniform"; - case 3: return "Output"; - case 4: return "Workgroup"; - case 5: return "CrossWorkgroup"; - case 6: return "Private"; - case 7: return "Function"; - case 8: return "Generic"; - case 9: return "PushConstant"; - case 10: return "AtomicCounter"; - case 11: return "Image"; - case 12: return "StorageBuffer"; - - default: return "Bad"; - } -} - -const int DecorationCeiling = 45; - -const char* DecorationString(int decoration) -{ - switch (decoration) { - case 0: return "RelaxedPrecision"; - case 1: return "SpecId"; - case 2: return "Block"; - case 3: return "BufferBlock"; - case 4: return "RowMajor"; - case 5: return "ColMajor"; - case 6: return "ArrayStride"; - case 7: return "MatrixStride"; - case 8: return "GLSLShared"; - case 9: return "GLSLPacked"; - case 10: return "CPacked"; - case 11: return "BuiltIn"; - case 12: return "Bad"; - case 13: return "NoPerspective"; - case 14: return "Flat"; - case 15: return "Patch"; - case 16: return "Centroid"; - case 17: return "Sample"; - case 18: return "Invariant"; - case 19: return "Restrict"; - case 20: return "Aliased"; - case 21: return "Volatile"; - case 22: return "Constant"; - case 23: return "Coherent"; - case 24: return "NonWritable"; - case 25: return "NonReadable"; - case 26: return "Uniform"; - case 27: return "Bad"; - case 28: return "SaturatedConversion"; - case 29: return "Stream"; - case 30: return "Location"; - case 31: return "Component"; - case 32: return "Index"; - case 33: return "Binding"; - case 34: return "DescriptorSet"; - case 35: return "Offset"; - case 36: return "XfbBuffer"; - case 37: return "XfbStride"; - case 38: return "FuncParamAttr"; - case 39: return "FP Rounding Mode"; - case 40: return "FP Fast Math Mode"; - case 41: return "Linkage Attributes"; - case 42: return "NoContraction"; - case 43: return "InputAttachmentIndex"; - case 44: return "Alignment"; - - case DecorationCeiling: - default: return "Bad"; - -#ifdef AMD_EXTENSIONS - case DecorationExplicitInterpAMD: return "ExplicitInterpAMD"; -#endif -#ifdef NV_EXTENSIONS - case DecorationOverrideCoverageNV: return "OverrideCoverageNV"; - case DecorationPassthroughNV: return "PassthroughNV"; - case DecorationViewportRelativeNV: return "ViewportRelativeNV"; - case DecorationSecondaryViewportRelativeNV: return "SecondaryViewportRelativeNV"; -#endif - - case DecorationNonUniformEXT: return "DecorationNonUniformEXT"; - case DecorationHlslCounterBufferGOOGLE: return "DecorationHlslCounterBufferGOOGLE"; - case DecorationHlslSemanticGOOGLE: return "DecorationHlslSemanticGOOGLE"; - } -} - -const char* BuiltInString(int builtIn) -{ - switch (builtIn) { - case 0: return "Position"; - case 1: return "PointSize"; - case 2: return "Bad"; - case 3: return "ClipDistance"; - case 4: return "CullDistance"; - case 5: return "VertexId"; - case 6: return "InstanceId"; - case 7: return "PrimitiveId"; - case 8: return "InvocationId"; - case 9: return "Layer"; - case 10: return "ViewportIndex"; - case 11: return "TessLevelOuter"; - case 12: return "TessLevelInner"; - case 13: return "TessCoord"; - case 14: return "PatchVertices"; - case 15: return "FragCoord"; - case 16: return "PointCoord"; - case 17: return "FrontFacing"; - case 18: return "SampleId"; - case 19: return "SamplePosition"; - case 20: return "SampleMask"; - case 21: return "Bad"; - case 22: return "FragDepth"; - case 23: return "HelperInvocation"; - case 24: return "NumWorkgroups"; - case 25: return "WorkgroupSize"; - case 26: return "WorkgroupId"; - case 27: return "LocalInvocationId"; - case 28: return "GlobalInvocationId"; - case 29: return "LocalInvocationIndex"; - case 30: return "WorkDim"; - case 31: return "GlobalSize"; - case 32: return "EnqueuedWorkgroupSize"; - case 33: return "GlobalOffset"; - case 34: return "GlobalLinearId"; - case 35: return "Bad"; - case 36: return "SubgroupSize"; - case 37: return "SubgroupMaxSize"; - case 38: return "NumSubgroups"; - case 39: return "NumEnqueuedSubgroups"; - case 40: return "SubgroupId"; - case 41: return "SubgroupLocalInvocationId"; - case 42: return "VertexIndex"; // TBD: put next to VertexId? - case 43: return "InstanceIndex"; // TBD: put next to InstanceId? - - case 4416: return "SubgroupEqMaskKHR"; - case 4417: return "SubgroupGeMaskKHR"; - case 4418: return "SubgroupGtMaskKHR"; - case 4419: return "SubgroupLeMaskKHR"; - case 4420: return "SubgroupLtMaskKHR"; - case 4438: return "DeviceIndex"; - case 4440: return "ViewIndex"; - case 4424: return "BaseVertex"; - case 4425: return "BaseInstance"; - case 4426: return "DrawIndex"; - case 5014: return "FragStencilRefEXT"; - -#ifdef AMD_EXTENSIONS - case 4992: return "BaryCoordNoPerspAMD"; - case 4993: return "BaryCoordNoPerspCentroidAMD"; - case 4994: return "BaryCoordNoPerspSampleAMD"; - case 4995: return "BaryCoordSmoothAMD"; - case 4996: return "BaryCoordSmoothCentroidAMD"; - case 4997: return "BaryCoordSmoothSampleAMD"; - case 4998: return "BaryCoordPullModelAMD"; -#endif - -#ifdef NV_EXTENSIONS - case 5253: return "ViewportMaskNV"; - case 5257: return "SecondaryPositionNV"; - case 5258: return "SecondaryViewportMaskNV"; - case 5261: return "PositionPerViewNV"; - case 5262: return "ViewportMaskPerViewNV"; -#endif - - case 5264: return "FullyCoveredEXT"; - - default: return "Bad"; - } -} - -const char* DimensionString(int dim) -{ - switch (dim) { - case 0: return "1D"; - case 1: return "2D"; - case 2: return "3D"; - case 3: return "Cube"; - case 4: return "Rect"; - case 5: return "Buffer"; - case 6: return "SubpassData"; - - default: return "Bad"; - } -} - -const char* SamplerAddressingModeString(int mode) -{ - switch (mode) { - case 0: return "None"; - case 1: return "ClampToEdge"; - case 2: return "Clamp"; - case 3: return "Repeat"; - case 4: return "RepeatMirrored"; - - default: return "Bad"; - } -} - -const char* SamplerFilterModeString(int mode) -{ - switch (mode) { - case 0: return "Nearest"; - case 1: return "Linear"; - - default: return "Bad"; - } -} - -const char* ImageFormatString(int format) -{ - switch (format) { - case 0: return "Unknown"; - - // ES/Desktop float - case 1: return "Rgba32f"; - case 2: return "Rgba16f"; - case 3: return "R32f"; - case 4: return "Rgba8"; - case 5: return "Rgba8Snorm"; - - // Desktop float - case 6: return "Rg32f"; - case 7: return "Rg16f"; - case 8: return "R11fG11fB10f"; - case 9: return "R16f"; - case 10: return "Rgba16"; - case 11: return "Rgb10A2"; - case 12: return "Rg16"; - case 13: return "Rg8"; - case 14: return "R16"; - case 15: return "R8"; - case 16: return "Rgba16Snorm"; - case 17: return "Rg16Snorm"; - case 18: return "Rg8Snorm"; - case 19: return "R16Snorm"; - case 20: return "R8Snorm"; - - // ES/Desktop int - case 21: return "Rgba32i"; - case 22: return "Rgba16i"; - case 23: return "Rgba8i"; - case 24: return "R32i"; - - // Desktop int - case 25: return "Rg32i"; - case 26: return "Rg16i"; - case 27: return "Rg8i"; - case 28: return "R16i"; - case 29: return "R8i"; - - // ES/Desktop uint - case 30: return "Rgba32ui"; - case 31: return "Rgba16ui"; - case 32: return "Rgba8ui"; - case 33: return "R32ui"; - - // Desktop uint - case 34: return "Rgb10a2ui"; - case 35: return "Rg32ui"; - case 36: return "Rg16ui"; - case 37: return "Rg8ui"; - case 38: return "R16ui"; - case 39: return "R8ui"; - - default: - return "Bad"; - } -} - -const char* ImageChannelOrderString(int format) -{ - switch (format) { - case 0: return "R"; - case 1: return "A"; - case 2: return "RG"; - case 3: return "RA"; - case 4: return "RGB"; - case 5: return "RGBA"; - case 6: return "BGRA"; - case 7: return "ARGB"; - case 8: return "Intensity"; - case 9: return "Luminance"; - case 10: return "Rx"; - case 11: return "RGx"; - case 12: return "RGBx"; - case 13: return "Depth"; - case 14: return "DepthStencil"; - case 15: return "sRGB"; - case 16: return "sRGBx"; - case 17: return "sRGBA"; - case 18: return "sBGRA"; - - default: - return "Bad"; - } -} - -const char* ImageChannelDataTypeString(int type) -{ - switch (type) - { - case 0: return "SnormInt8"; - case 1: return "SnormInt16"; - case 2: return "UnormInt8"; - case 3: return "UnormInt16"; - case 4: return "UnormShort565"; - case 5: return "UnormShort555"; - case 6: return "UnormInt101010"; - case 7: return "SignedInt8"; - case 8: return "SignedInt16"; - case 9: return "SignedInt32"; - case 10: return "UnsignedInt8"; - case 11: return "UnsignedInt16"; - case 12: return "UnsignedInt32"; - case 13: return "HalfFloat"; - case 14: return "Float"; - case 15: return "UnormInt24"; - case 16: return "UnormInt101010_2"; - - default: - return "Bad"; - } -} - -const int ImageOperandsCeiling = 8; - -const char* ImageOperandsString(int format) -{ - switch (format) { - case 0: return "Bias"; - case 1: return "Lod"; - case 2: return "Grad"; - case 3: return "ConstOffset"; - case 4: return "Offset"; - case 5: return "ConstOffsets"; - case 6: return "Sample"; - case 7: return "MinLod"; - - case ImageOperandsCeiling: - default: - return "Bad"; - } -} - -const char* FPFastMathString(int mode) -{ - switch (mode) { - case 0: return "NotNaN"; - case 1: return "NotInf"; - case 2: return "NSZ"; - case 3: return "AllowRecip"; - case 4: return "Fast"; - - default: return "Bad"; - } -} - -const char* FPRoundingModeString(int mode) -{ - switch (mode) { - case 0: return "RTE"; - case 1: return "RTZ"; - case 2: return "RTP"; - case 3: return "RTN"; - - default: return "Bad"; - } -} - -const char* LinkageTypeString(int type) -{ - switch (type) { - case 0: return "Export"; - case 1: return "Import"; - - default: return "Bad"; - } -} - -const char* FuncParamAttrString(int attr) -{ - switch (attr) { - case 0: return "Zext"; - case 1: return "Sext"; - case 2: return "ByVal"; - case 3: return "Sret"; - case 4: return "NoAlias"; - case 5: return "NoCapture"; - case 6: return "NoWrite"; - case 7: return "NoReadWrite"; - - default: return "Bad"; - } -} - -const char* AccessQualifierString(int attr) -{ - switch (attr) { - case 0: return "ReadOnly"; - case 1: return "WriteOnly"; - case 2: return "ReadWrite"; - - default: return "Bad"; - } -} - -const int SelectControlCeiling = 2; - -const char* SelectControlString(int cont) -{ - switch (cont) { - case 0: return "Flatten"; - case 1: return "DontFlatten"; - - case SelectControlCeiling: - default: return "Bad"; - } -} - -const int LoopControlCeiling = 4; - -const char* LoopControlString(int cont) -{ - switch (cont) { - case 0: return "Unroll"; - case 1: return "DontUnroll"; - case 2: return "DependencyInfinite"; - case 3: return "DependencyLength"; - - case LoopControlCeiling: - default: return "Bad"; - } -} - -const int FunctionControlCeiling = 4; - -const char* FunctionControlString(int cont) -{ - switch (cont) { - case 0: return "Inline"; - case 1: return "DontInline"; - case 2: return "Pure"; - case 3: return "Const"; - - case FunctionControlCeiling: - default: return "Bad"; - } -} - -const char* MemorySemanticsString(int mem) -{ - // Note: No bits set (None) means "Relaxed" - switch (mem) { - case 0: return "Bad"; // Note: this is a placeholder for 'Consume' - case 1: return "Acquire"; - case 2: return "Release"; - case 3: return "AcquireRelease"; - case 4: return "SequentiallyConsistent"; - case 5: return "Bad"; // Note: reserved for future expansion - case 6: return "UniformMemory"; - case 7: return "SubgroupMemory"; - case 8: return "WorkgroupMemory"; - case 9: return "CrossWorkgroupMemory"; - case 10: return "AtomicCounterMemory"; - case 11: return "ImageMemory"; - - default: return "Bad"; - } -} - -const char* MemoryAccessString(int mem) -{ - switch (mem) { - case 0: return "Volatile"; - case 1: return "Aligned"; - case 2: return "Nontemporal"; - - default: return "Bad"; - } -} - -const char* ScopeString(int mem) -{ - switch (mem) { - case 0: return "CrossDevice"; - case 1: return "Device"; - case 2: return "Workgroup"; - case 3: return "Subgroup"; - case 4: return "Invocation"; - - default: return "Bad"; - } -} - -const char* GroupOperationString(int gop) -{ - - switch (gop) - { - case GroupOperationReduce: return "Reduce"; - case GroupOperationInclusiveScan: return "InclusiveScan"; - case GroupOperationExclusiveScan: return "ExclusiveScan"; - case GroupOperationClusteredReduce: return "ClusteredReduce"; -#ifdef NV_EXTENSIONS - case GroupOperationPartitionedReduceNV: return "PartitionedReduceNV"; - case GroupOperationPartitionedInclusiveScanNV: return "PartitionedInclusiveScanNV"; - case GroupOperationPartitionedExclusiveScanNV: return "PartitionedExclusiveScanNV"; -#endif - - default: return "Bad"; - } -} - -const char* KernelEnqueueFlagsString(int flag) -{ - switch (flag) - { - case 0: return "NoWait"; - case 1: return "WaitKernel"; - case 2: return "WaitWorkGroup"; - - default: return "Bad"; - } -} - -const char* KernelProfilingInfoString(int info) -{ - switch (info) - { - case 0: return "CmdExecTime"; - - default: return "Bad"; - } -} - -const char* CapabilityString(int info) -{ - switch (info) - { - case 0: return "Matrix"; - case 1: return "Shader"; - case 2: return "Geometry"; - case 3: return "Tessellation"; - case 4: return "Addresses"; - case 5: return "Linkage"; - case 6: return "Kernel"; - case 7: return "Vector16"; - case 8: return "Float16Buffer"; - case 9: return "Float16"; - case 10: return "Float64"; - case 11: return "Int64"; - case 12: return "Int64Atomics"; - case 13: return "ImageBasic"; - case 14: return "ImageReadWrite"; - case 15: return "ImageMipmap"; - case 16: return "Bad"; - case 17: return "Pipes"; - case 18: return "Groups"; - case 19: return "DeviceEnqueue"; - case 20: return "LiteralSampler"; - case 21: return "AtomicStorage"; - case 22: return "Int16"; - case 23: return "TessellationPointSize"; - case 24: return "GeometryPointSize"; - case 25: return "ImageGatherExtended"; - case 26: return "Bad"; - case 27: return "StorageImageMultisample"; - case 28: return "UniformBufferArrayDynamicIndexing"; - case 29: return "SampledImageArrayDynamicIndexing"; - case 30: return "StorageBufferArrayDynamicIndexing"; - case 31: return "StorageImageArrayDynamicIndexing"; - case 32: return "ClipDistance"; - case 33: return "CullDistance"; - case 34: return "ImageCubeArray"; - case 35: return "SampleRateShading"; - case 36: return "ImageRect"; - case 37: return "SampledRect"; - case 38: return "GenericPointer"; - case 39: return "Int8"; - case 40: return "InputAttachment"; - case 41: return "SparseResidency"; - case 42: return "MinLod"; - case 43: return "Sampled1D"; - case 44: return "Image1D"; - case 45: return "SampledCubeArray"; - case 46: return "SampledBuffer"; - case 47: return "ImageBuffer"; - case 48: return "ImageMSArray"; - case 49: return "StorageImageExtendedFormats"; - case 50: return "ImageQuery"; - case 51: return "DerivativeControl"; - case 52: return "InterpolationFunction"; - case 53: return "TransformFeedback"; - case 54: return "GeometryStreams"; - case 55: return "StorageImageReadWithoutFormat"; - case 56: return "StorageImageWriteWithoutFormat"; - case 57: return "MultiViewport"; - case 61: return "GroupNonUniform"; - case 62: return "GroupNonUniformVote"; - case 63: return "GroupNonUniformArithmetic"; - case 64: return "GroupNonUniformBallot"; - case 65: return "GroupNonUniformShuffle"; - case 66: return "GroupNonUniformShuffleRelative"; - case 67: return "GroupNonUniformClustered"; - case 68: return "GroupNonUniformQuad"; - - case CapabilitySubgroupBallotKHR: return "SubgroupBallotKHR"; - case CapabilityDrawParameters: return "DrawParameters"; - case CapabilitySubgroupVoteKHR: return "SubgroupVoteKHR"; - - case CapabilityStorageUniformBufferBlock16: return "StorageUniformBufferBlock16"; - case CapabilityStorageUniform16: return "StorageUniform16"; - case CapabilityStoragePushConstant16: return "StoragePushConstant16"; - case CapabilityStorageInputOutput16: return "StorageInputOutput16"; - - case CapabilityDeviceGroup: return "DeviceGroup"; - case CapabilityMultiView: return "MultiView"; - - case CapabilityStencilExportEXT: return "StencilExportEXT"; - -#ifdef AMD_EXTENSIONS - case CapabilityFloat16ImageAMD: return "Float16ImageAMD"; - case CapabilityImageGatherBiasLodAMD: return "ImageGatherBiasLodAMD"; - case CapabilityFragmentMaskAMD: return "FragmentMaskAMD"; - case CapabilityImageReadWriteLodAMD: return "ImageReadWriteLodAMD"; -#endif - - case CapabilityAtomicStorageOps: return "AtomicStorageOps"; - - case CapabilitySampleMaskPostDepthCoverage: return "SampleMaskPostDepthCoverage"; -#ifdef NV_EXTENSIONS - case CapabilityGeometryShaderPassthroughNV: return "GeometryShaderPassthroughNV"; - case CapabilityShaderViewportIndexLayerNV: return "ShaderViewportIndexLayerNV"; - case CapabilityShaderViewportMaskNV: return "ShaderViewportMaskNV"; - case CapabilityShaderStereoViewNV: return "ShaderStereoViewNV"; - case CapabilityPerViewAttributesNV: return "PerViewAttributesNV"; - case CapabilityGroupNonUniformPartitionedNV: return "GroupNonUniformPartitionedNV"; -#endif - - case CapabilityFragmentFullyCoveredEXT: return "FragmentFullyCoveredEXT"; - - case CapabilityShaderNonUniformEXT: return "CapabilityShaderNonUniformEXT"; - case CapabilityRuntimeDescriptorArrayEXT: return "CapabilityRuntimeDescriptorArrayEXT"; - case CapabilityInputAttachmentArrayDynamicIndexingEXT: return "CapabilityInputAttachmentArrayDynamicIndexingEXT"; - case CapabilityUniformTexelBufferArrayDynamicIndexingEXT: return "CapabilityUniformTexelBufferArrayDynamicIndexingEXT"; - case CapabilityStorageTexelBufferArrayDynamicIndexingEXT: return "CapabilityStorageTexelBufferArrayDynamicIndexingEXT"; - case CapabilityUniformBufferArrayNonUniformIndexingEXT: return "CapabilityUniformBufferArrayNonUniformIndexingEXT"; - case CapabilitySampledImageArrayNonUniformIndexingEXT: return "CapabilitySampledImageArrayNonUniformIndexingEXT"; - case CapabilityStorageBufferArrayNonUniformIndexingEXT: return "CapabilityStorageBufferArrayNonUniformIndexingEXT"; - case CapabilityStorageImageArrayNonUniformIndexingEXT: return "CapabilityStorageImageArrayNonUniformIndexingEXT"; - case CapabilityInputAttachmentArrayNonUniformIndexingEXT: return "CapabilityInputAttachmentArrayNonUniformIndexingEXT"; - case CapabilityUniformTexelBufferArrayNonUniformIndexingEXT: return "CapabilityUniformTexelBufferArrayNonUniformIndexingEXT"; - case CapabilityStorageTexelBufferArrayNonUniformIndexingEXT: return "CapabilityStorageTexelBufferArrayNonUniformIndexingEXT"; - - default: return "Bad"; - } -} - -const char* OpcodeString(int op) -{ - switch (op) { - case 0: return "OpNop"; - case 1: return "OpUndef"; - case 2: return "OpSourceContinued"; - case 3: return "OpSource"; - case 4: return "OpSourceExtension"; - case 5: return "OpName"; - case 6: return "OpMemberName"; - case 7: return "OpString"; - case 8: return "OpLine"; - case 9: return "Bad"; - case 10: return "OpExtension"; - case 11: return "OpExtInstImport"; - case 12: return "OpExtInst"; - case 13: return "Bad"; - case 14: return "OpMemoryModel"; - case 15: return "OpEntryPoint"; - case 16: return "OpExecutionMode"; - case 17: return "OpCapability"; - case 18: return "Bad"; - case 19: return "OpTypeVoid"; - case 20: return "OpTypeBool"; - case 21: return "OpTypeInt"; - case 22: return "OpTypeFloat"; - case 23: return "OpTypeVector"; - case 24: return "OpTypeMatrix"; - case 25: return "OpTypeImage"; - case 26: return "OpTypeSampler"; - case 27: return "OpTypeSampledImage"; - case 28: return "OpTypeArray"; - case 29: return "OpTypeRuntimeArray"; - case 30: return "OpTypeStruct"; - case 31: return "OpTypeOpaque"; - case 32: return "OpTypePointer"; - case 33: return "OpTypeFunction"; - case 34: return "OpTypeEvent"; - case 35: return "OpTypeDeviceEvent"; - case 36: return "OpTypeReserveId"; - case 37: return "OpTypeQueue"; - case 38: return "OpTypePipe"; - case 39: return "OpTypeForwardPointer"; - case 40: return "Bad"; - case 41: return "OpConstantTrue"; - case 42: return "OpConstantFalse"; - case 43: return "OpConstant"; - case 44: return "OpConstantComposite"; - case 45: return "OpConstantSampler"; - case 46: return "OpConstantNull"; - case 47: return "Bad"; - case 48: return "OpSpecConstantTrue"; - case 49: return "OpSpecConstantFalse"; - case 50: return "OpSpecConstant"; - case 51: return "OpSpecConstantComposite"; - case 52: return "OpSpecConstantOp"; - case 53: return "Bad"; - case 54: return "OpFunction"; - case 55: return "OpFunctionParameter"; - case 56: return "OpFunctionEnd"; - case 57: return "OpFunctionCall"; - case 58: return "Bad"; - case 59: return "OpVariable"; - case 60: return "OpImageTexelPointer"; - case 61: return "OpLoad"; - case 62: return "OpStore"; - case 63: return "OpCopyMemory"; - case 64: return "OpCopyMemorySized"; - case 65: return "OpAccessChain"; - case 66: return "OpInBoundsAccessChain"; - case 67: return "OpPtrAccessChain"; - case 68: return "OpArrayLength"; - case 69: return "OpGenericPtrMemSemantics"; - case 70: return "OpInBoundsPtrAccessChain"; - case 71: return "OpDecorate"; - case 72: return "OpMemberDecorate"; - case 73: return "OpDecorationGroup"; - case 74: return "OpGroupDecorate"; - case 75: return "OpGroupMemberDecorate"; - case 76: return "Bad"; - case 77: return "OpVectorExtractDynamic"; - case 78: return "OpVectorInsertDynamic"; - case 79: return "OpVectorShuffle"; - case 80: return "OpCompositeConstruct"; - case 81: return "OpCompositeExtract"; - case 82: return "OpCompositeInsert"; - case 83: return "OpCopyObject"; - case 84: return "OpTranspose"; - case 85: return "Bad"; - case 86: return "OpSampledImage"; - case 87: return "OpImageSampleImplicitLod"; - case 88: return "OpImageSampleExplicitLod"; - case 89: return "OpImageSampleDrefImplicitLod"; - case 90: return "OpImageSampleDrefExplicitLod"; - case 91: return "OpImageSampleProjImplicitLod"; - case 92: return "OpImageSampleProjExplicitLod"; - case 93: return "OpImageSampleProjDrefImplicitLod"; - case 94: return "OpImageSampleProjDrefExplicitLod"; - case 95: return "OpImageFetch"; - case 96: return "OpImageGather"; - case 97: return "OpImageDrefGather"; - case 98: return "OpImageRead"; - case 99: return "OpImageWrite"; - case 100: return "OpImage"; - case 101: return "OpImageQueryFormat"; - case 102: return "OpImageQueryOrder"; - case 103: return "OpImageQuerySizeLod"; - case 104: return "OpImageQuerySize"; - case 105: return "OpImageQueryLod"; - case 106: return "OpImageQueryLevels"; - case 107: return "OpImageQuerySamples"; - case 108: return "Bad"; - case 109: return "OpConvertFToU"; - case 110: return "OpConvertFToS"; - case 111: return "OpConvertSToF"; - case 112: return "OpConvertUToF"; - case 113: return "OpUConvert"; - case 114: return "OpSConvert"; - case 115: return "OpFConvert"; - case 116: return "OpQuantizeToF16"; - case 117: return "OpConvertPtrToU"; - case 118: return "OpSatConvertSToU"; - case 119: return "OpSatConvertUToS"; - case 120: return "OpConvertUToPtr"; - case 121: return "OpPtrCastToGeneric"; - case 122: return "OpGenericCastToPtr"; - case 123: return "OpGenericCastToPtrExplicit"; - case 124: return "OpBitcast"; - case 125: return "Bad"; - case 126: return "OpSNegate"; - case 127: return "OpFNegate"; - case 128: return "OpIAdd"; - case 129: return "OpFAdd"; - case 130: return "OpISub"; - case 131: return "OpFSub"; - case 132: return "OpIMul"; - case 133: return "OpFMul"; - case 134: return "OpUDiv"; - case 135: return "OpSDiv"; - case 136: return "OpFDiv"; - case 137: return "OpUMod"; - case 138: return "OpSRem"; - case 139: return "OpSMod"; - case 140: return "OpFRem"; - case 141: return "OpFMod"; - case 142: return "OpVectorTimesScalar"; - case 143: return "OpMatrixTimesScalar"; - case 144: return "OpVectorTimesMatrix"; - case 145: return "OpMatrixTimesVector"; - case 146: return "OpMatrixTimesMatrix"; - case 147: return "OpOuterProduct"; - case 148: return "OpDot"; - case 149: return "OpIAddCarry"; - case 150: return "OpISubBorrow"; - case 151: return "OpUMulExtended"; - case 152: return "OpSMulExtended"; - case 153: return "Bad"; - case 154: return "OpAny"; - case 155: return "OpAll"; - case 156: return "OpIsNan"; - case 157: return "OpIsInf"; - case 158: return "OpIsFinite"; - case 159: return "OpIsNormal"; - case 160: return "OpSignBitSet"; - case 161: return "OpLessOrGreater"; - case 162: return "OpOrdered"; - case 163: return "OpUnordered"; - case 164: return "OpLogicalEqual"; - case 165: return "OpLogicalNotEqual"; - case 166: return "OpLogicalOr"; - case 167: return "OpLogicalAnd"; - case 168: return "OpLogicalNot"; - case 169: return "OpSelect"; - case 170: return "OpIEqual"; - case 171: return "OpINotEqual"; - case 172: return "OpUGreaterThan"; - case 173: return "OpSGreaterThan"; - case 174: return "OpUGreaterThanEqual"; - case 175: return "OpSGreaterThanEqual"; - case 176: return "OpULessThan"; - case 177: return "OpSLessThan"; - case 178: return "OpULessThanEqual"; - case 179: return "OpSLessThanEqual"; - case 180: return "OpFOrdEqual"; - case 181: return "OpFUnordEqual"; - case 182: return "OpFOrdNotEqual"; - case 183: return "OpFUnordNotEqual"; - case 184: return "OpFOrdLessThan"; - case 185: return "OpFUnordLessThan"; - case 186: return "OpFOrdGreaterThan"; - case 187: return "OpFUnordGreaterThan"; - case 188: return "OpFOrdLessThanEqual"; - case 189: return "OpFUnordLessThanEqual"; - case 190: return "OpFOrdGreaterThanEqual"; - case 191: return "OpFUnordGreaterThanEqual"; - case 192: return "Bad"; - case 193: return "Bad"; - case 194: return "OpShiftRightLogical"; - case 195: return "OpShiftRightArithmetic"; - case 196: return "OpShiftLeftLogical"; - case 197: return "OpBitwiseOr"; - case 198: return "OpBitwiseXor"; - case 199: return "OpBitwiseAnd"; - case 200: return "OpNot"; - case 201: return "OpBitFieldInsert"; - case 202: return "OpBitFieldSExtract"; - case 203: return "OpBitFieldUExtract"; - case 204: return "OpBitReverse"; - case 205: return "OpBitCount"; - case 206: return "Bad"; - case 207: return "OpDPdx"; - case 208: return "OpDPdy"; - case 209: return "OpFwidth"; - case 210: return "OpDPdxFine"; - case 211: return "OpDPdyFine"; - case 212: return "OpFwidthFine"; - case 213: return "OpDPdxCoarse"; - case 214: return "OpDPdyCoarse"; - case 215: return "OpFwidthCoarse"; - case 216: return "Bad"; - case 217: return "Bad"; - case 218: return "OpEmitVertex"; - case 219: return "OpEndPrimitive"; - case 220: return "OpEmitStreamVertex"; - case 221: return "OpEndStreamPrimitive"; - case 222: return "Bad"; - case 223: return "Bad"; - case 224: return "OpControlBarrier"; - case 225: return "OpMemoryBarrier"; - case 226: return "Bad"; - case 227: return "OpAtomicLoad"; - case 228: return "OpAtomicStore"; - case 229: return "OpAtomicExchange"; - case 230: return "OpAtomicCompareExchange"; - case 231: return "OpAtomicCompareExchangeWeak"; - case 232: return "OpAtomicIIncrement"; - case 233: return "OpAtomicIDecrement"; - case 234: return "OpAtomicIAdd"; - case 235: return "OpAtomicISub"; - case 236: return "OpAtomicSMin"; - case 237: return "OpAtomicUMin"; - case 238: return "OpAtomicSMax"; - case 239: return "OpAtomicUMax"; - case 240: return "OpAtomicAnd"; - case 241: return "OpAtomicOr"; - case 242: return "OpAtomicXor"; - case 243: return "Bad"; - case 244: return "Bad"; - case 245: return "OpPhi"; - case 246: return "OpLoopMerge"; - case 247: return "OpSelectionMerge"; - case 248: return "OpLabel"; - case 249: return "OpBranch"; - case 250: return "OpBranchConditional"; - case 251: return "OpSwitch"; - case 252: return "OpKill"; - case 253: return "OpReturn"; - case 254: return "OpReturnValue"; - case 255: return "OpUnreachable"; - case 256: return "OpLifetimeStart"; - case 257: return "OpLifetimeStop"; - case 258: return "Bad"; - case 259: return "OpGroupAsyncCopy"; - case 260: return "OpGroupWaitEvents"; - case 261: return "OpGroupAll"; - case 262: return "OpGroupAny"; - case 263: return "OpGroupBroadcast"; - case 264: return "OpGroupIAdd"; - case 265: return "OpGroupFAdd"; - case 266: return "OpGroupFMin"; - case 267: return "OpGroupUMin"; - case 268: return "OpGroupSMin"; - case 269: return "OpGroupFMax"; - case 270: return "OpGroupUMax"; - case 271: return "OpGroupSMax"; - case 272: return "Bad"; - case 273: return "Bad"; - case 274: return "OpReadPipe"; - case 275: return "OpWritePipe"; - case 276: return "OpReservedReadPipe"; - case 277: return "OpReservedWritePipe"; - case 278: return "OpReserveReadPipePackets"; - case 279: return "OpReserveWritePipePackets"; - case 280: return "OpCommitReadPipe"; - case 281: return "OpCommitWritePipe"; - case 282: return "OpIsValidReserveId"; - case 283: return "OpGetNumPipePackets"; - case 284: return "OpGetMaxPipePackets"; - case 285: return "OpGroupReserveReadPipePackets"; - case 286: return "OpGroupReserveWritePipePackets"; - case 287: return "OpGroupCommitReadPipe"; - case 288: return "OpGroupCommitWritePipe"; - case 289: return "Bad"; - case 290: return "Bad"; - case 291: return "OpEnqueueMarker"; - case 292: return "OpEnqueueKernel"; - case 293: return "OpGetKernelNDrangeSubGroupCount"; - case 294: return "OpGetKernelNDrangeMaxSubGroupSize"; - case 295: return "OpGetKernelWorkGroupSize"; - case 296: return "OpGetKernelPreferredWorkGroupSizeMultiple"; - case 297: return "OpRetainEvent"; - case 298: return "OpReleaseEvent"; - case 299: return "OpCreateUserEvent"; - case 300: return "OpIsValidEvent"; - case 301: return "OpSetUserEventStatus"; - case 302: return "OpCaptureEventProfilingInfo"; - case 303: return "OpGetDefaultQueue"; - case 304: return "OpBuildNDRange"; - case 305: return "OpImageSparseSampleImplicitLod"; - case 306: return "OpImageSparseSampleExplicitLod"; - case 307: return "OpImageSparseSampleDrefImplicitLod"; - case 308: return "OpImageSparseSampleDrefExplicitLod"; - case 309: return "OpImageSparseSampleProjImplicitLod"; - case 310: return "OpImageSparseSampleProjExplicitLod"; - case 311: return "OpImageSparseSampleProjDrefImplicitLod"; - case 312: return "OpImageSparseSampleProjDrefExplicitLod"; - case 313: return "OpImageSparseFetch"; - case 314: return "OpImageSparseGather"; - case 315: return "OpImageSparseDrefGather"; - case 316: return "OpImageSparseTexelsResident"; - case 317: return "OpNoLine"; - case 318: return "OpAtomicFlagTestAndSet"; - case 319: return "OpAtomicFlagClear"; - case 320: return "OpImageSparseRead"; - - case OpModuleProcessed: return "OpModuleProcessed"; - case OpDecorateId: return "OpDecorateId"; - - case 333: return "OpGroupNonUniformElect"; - case 334: return "OpGroupNonUniformAll"; - case 335: return "OpGroupNonUniformAny"; - case 336: return "OpGroupNonUniformAllEqual"; - case 337: return "OpGroupNonUniformBroadcast"; - case 338: return "OpGroupNonUniformBroadcastFirst"; - case 339: return "OpGroupNonUniformBallot"; - case 340: return "OpGroupNonUniformInverseBallot"; - case 341: return "OpGroupNonUniformBallotBitExtract"; - case 342: return "OpGroupNonUniformBallotBitCount"; - case 343: return "OpGroupNonUniformBallotFindLSB"; - case 344: return "OpGroupNonUniformBallotFindMSB"; - case 345: return "OpGroupNonUniformShuffle"; - case 346: return "OpGroupNonUniformShuffleXor"; - case 347: return "OpGroupNonUniformShuffleUp"; - case 348: return "OpGroupNonUniformShuffleDown"; - case 349: return "OpGroupNonUniformIAdd"; - case 350: return "OpGroupNonUniformFAdd"; - case 351: return "OpGroupNonUniformIMul"; - case 352: return "OpGroupNonUniformFMul"; - case 353: return "OpGroupNonUniformSMin"; - case 354: return "OpGroupNonUniformUMin"; - case 355: return "OpGroupNonUniformFMin"; - case 356: return "OpGroupNonUniformSMax"; - case 357: return "OpGroupNonUniformUMax"; - case 358: return "OpGroupNonUniformFMax"; - case 359: return "OpGroupNonUniformBitwiseAnd"; - case 360: return "OpGroupNonUniformBitwiseOr"; - case 361: return "OpGroupNonUniformBitwiseXor"; - case 362: return "OpGroupNonUniformLogicalAnd"; - case 363: return "OpGroupNonUniformLogicalOr"; - case 364: return "OpGroupNonUniformLogicalXor"; - case 365: return "OpGroupNonUniformQuadBroadcast"; - case 366: return "OpGroupNonUniformQuadSwap"; - - case 4421: return "OpSubgroupBallotKHR"; - case 4422: return "OpSubgroupFirstInvocationKHR"; - case 4428: return "OpSubgroupAllKHR"; - case 4429: return "OpSubgroupAnyKHR"; - case 4430: return "OpSubgroupAllEqualKHR"; - case 4432: return "OpSubgroupReadInvocationKHR"; - -#ifdef AMD_EXTENSIONS - case 5000: return "OpGroupIAddNonUniformAMD"; - case 5001: return "OpGroupFAddNonUniformAMD"; - case 5002: return "OpGroupFMinNonUniformAMD"; - case 5003: return "OpGroupUMinNonUniformAMD"; - case 5004: return "OpGroupSMinNonUniformAMD"; - case 5005: return "OpGroupFMaxNonUniformAMD"; - case 5006: return "OpGroupUMaxNonUniformAMD"; - case 5007: return "OpGroupSMaxNonUniformAMD"; - - case 5011: return "OpFragmentMaskFetchAMD"; - case 5012: return "OpFragmentFetchAMD"; -#endif - - case OpDecorateStringGOOGLE: return "OpDecorateStringGOOGLE"; - case OpMemberDecorateStringGOOGLE: return "OpMemberDecorateStringGOOGLE"; - -#ifdef NV_EXTENSIONS - case OpGroupNonUniformPartitionNV: return "OpGroupNonUniformPartitionNV"; -#endif - default: - return "Bad"; - } -} - -// The set of objects that hold all the instruction/operand -// parameterization information. -InstructionParameters InstructionDesc[OpCodeMask + 1]; -OperandParameters ExecutionModeOperands[ExecutionModeCeiling]; -OperandParameters DecorationOperands[DecorationCeiling]; - -EnumDefinition OperandClassParams[OperandCount]; -EnumParameters ExecutionModeParams[ExecutionModeCeiling]; -EnumParameters ImageOperandsParams[ImageOperandsCeiling]; -EnumParameters DecorationParams[DecorationCeiling]; -EnumParameters LoopControlParams[FunctionControlCeiling]; -EnumParameters SelectionControlParams[SelectControlCeiling]; -EnumParameters FunctionControlParams[FunctionControlCeiling]; - -// Set up all the parameterizing descriptions of the opcodes, operands, etc. -void Parameterize() -{ - // only do this once. - static bool initialized = false; - if (initialized) - return; - initialized = true; - - // Exceptions to having a result and a resulting type . - // (Everything is initialized to have both). - - InstructionDesc[OpNop].setResultAndType(false, false); - InstructionDesc[OpSource].setResultAndType(false, false); - InstructionDesc[OpSourceContinued].setResultAndType(false, false); - InstructionDesc[OpSourceExtension].setResultAndType(false, false); - InstructionDesc[OpExtension].setResultAndType(false, false); - InstructionDesc[OpExtInstImport].setResultAndType(true, false); - InstructionDesc[OpCapability].setResultAndType(false, false); - InstructionDesc[OpMemoryModel].setResultAndType(false, false); - InstructionDesc[OpEntryPoint].setResultAndType(false, false); - InstructionDesc[OpExecutionMode].setResultAndType(false, false); - InstructionDesc[OpTypeVoid].setResultAndType(true, false); - InstructionDesc[OpTypeBool].setResultAndType(true, false); - InstructionDesc[OpTypeInt].setResultAndType(true, false); - InstructionDesc[OpTypeFloat].setResultAndType(true, false); - InstructionDesc[OpTypeVector].setResultAndType(true, false); - InstructionDesc[OpTypeMatrix].setResultAndType(true, false); - InstructionDesc[OpTypeImage].setResultAndType(true, false); - InstructionDesc[OpTypeSampler].setResultAndType(true, false); - InstructionDesc[OpTypeSampledImage].setResultAndType(true, false); - InstructionDesc[OpTypeArray].setResultAndType(true, false); - InstructionDesc[OpTypeRuntimeArray].setResultAndType(true, false); - InstructionDesc[OpTypeStruct].setResultAndType(true, false); - InstructionDesc[OpTypeOpaque].setResultAndType(true, false); - InstructionDesc[OpTypePointer].setResultAndType(true, false); - InstructionDesc[OpTypeForwardPointer].setResultAndType(false, false); - InstructionDesc[OpTypeFunction].setResultAndType(true, false); - InstructionDesc[OpTypeEvent].setResultAndType(true, false); - InstructionDesc[OpTypeDeviceEvent].setResultAndType(true, false); - InstructionDesc[OpTypeReserveId].setResultAndType(true, false); - InstructionDesc[OpTypeQueue].setResultAndType(true, false); - InstructionDesc[OpTypePipe].setResultAndType(true, false); - InstructionDesc[OpFunctionEnd].setResultAndType(false, false); - InstructionDesc[OpStore].setResultAndType(false, false); - InstructionDesc[OpImageWrite].setResultAndType(false, false); - InstructionDesc[OpDecorationGroup].setResultAndType(true, false); - InstructionDesc[OpDecorate].setResultAndType(false, false); - InstructionDesc[OpDecorateId].setResultAndType(false, false); - InstructionDesc[OpDecorateStringGOOGLE].setResultAndType(false, false); - InstructionDesc[OpMemberDecorate].setResultAndType(false, false); - InstructionDesc[OpMemberDecorateStringGOOGLE].setResultAndType(false, false); - InstructionDesc[OpGroupDecorate].setResultAndType(false, false); - InstructionDesc[OpGroupMemberDecorate].setResultAndType(false, false); - InstructionDesc[OpName].setResultAndType(false, false); - InstructionDesc[OpMemberName].setResultAndType(false, false); - InstructionDesc[OpString].setResultAndType(true, false); - InstructionDesc[OpLine].setResultAndType(false, false); - InstructionDesc[OpNoLine].setResultAndType(false, false); - InstructionDesc[OpCopyMemory].setResultAndType(false, false); - InstructionDesc[OpCopyMemorySized].setResultAndType(false, false); - InstructionDesc[OpEmitVertex].setResultAndType(false, false); - InstructionDesc[OpEndPrimitive].setResultAndType(false, false); - InstructionDesc[OpEmitStreamVertex].setResultAndType(false, false); - InstructionDesc[OpEndStreamPrimitive].setResultAndType(false, false); - InstructionDesc[OpControlBarrier].setResultAndType(false, false); - InstructionDesc[OpMemoryBarrier].setResultAndType(false, false); - InstructionDesc[OpAtomicStore].setResultAndType(false, false); - InstructionDesc[OpLoopMerge].setResultAndType(false, false); - InstructionDesc[OpSelectionMerge].setResultAndType(false, false); - InstructionDesc[OpLabel].setResultAndType(true, false); - InstructionDesc[OpBranch].setResultAndType(false, false); - InstructionDesc[OpBranchConditional].setResultAndType(false, false); - InstructionDesc[OpSwitch].setResultAndType(false, false); - InstructionDesc[OpKill].setResultAndType(false, false); - InstructionDesc[OpReturn].setResultAndType(false, false); - InstructionDesc[OpReturnValue].setResultAndType(false, false); - InstructionDesc[OpUnreachable].setResultAndType(false, false); - InstructionDesc[OpLifetimeStart].setResultAndType(false, false); - InstructionDesc[OpLifetimeStop].setResultAndType(false, false); - InstructionDesc[OpCommitReadPipe].setResultAndType(false, false); - InstructionDesc[OpCommitWritePipe].setResultAndType(false, false); - InstructionDesc[OpGroupCommitWritePipe].setResultAndType(false, false); - InstructionDesc[OpGroupCommitReadPipe].setResultAndType(false, false); - InstructionDesc[OpCaptureEventProfilingInfo].setResultAndType(false, false); - InstructionDesc[OpSetUserEventStatus].setResultAndType(false, false); - InstructionDesc[OpRetainEvent].setResultAndType(false, false); - InstructionDesc[OpReleaseEvent].setResultAndType(false, false); - InstructionDesc[OpGroupWaitEvents].setResultAndType(false, false); - InstructionDesc[OpAtomicFlagClear].setResultAndType(false, false); - InstructionDesc[OpModuleProcessed].setResultAndType(false, false); - - // Specific additional context-dependent operands - - ExecutionModeOperands[ExecutionModeInvocations].push(OperandLiteralNumber, "'Number of <>'"); - - ExecutionModeOperands[ExecutionModeLocalSize].push(OperandLiteralNumber, "'x size'"); - ExecutionModeOperands[ExecutionModeLocalSize].push(OperandLiteralNumber, "'y size'"); - ExecutionModeOperands[ExecutionModeLocalSize].push(OperandLiteralNumber, "'z size'"); - - ExecutionModeOperands[ExecutionModeLocalSizeHint].push(OperandLiteralNumber, "'x size'"); - ExecutionModeOperands[ExecutionModeLocalSizeHint].push(OperandLiteralNumber, "'y size'"); - ExecutionModeOperands[ExecutionModeLocalSizeHint].push(OperandLiteralNumber, "'z size'"); - - ExecutionModeOperands[ExecutionModeOutputVertices].push(OperandLiteralNumber, "'Vertex count'"); - ExecutionModeOperands[ExecutionModeVecTypeHint].push(OperandLiteralNumber, "'Vector type'"); - - DecorationOperands[DecorationStream].push(OperandLiteralNumber, "'Stream Number'"); - DecorationOperands[DecorationLocation].push(OperandLiteralNumber, "'Location'"); - DecorationOperands[DecorationComponent].push(OperandLiteralNumber, "'Component'"); - DecorationOperands[DecorationIndex].push(OperandLiteralNumber, "'Index'"); - DecorationOperands[DecorationBinding].push(OperandLiteralNumber, "'Binding Point'"); - DecorationOperands[DecorationDescriptorSet].push(OperandLiteralNumber, "'Descriptor Set'"); - DecorationOperands[DecorationOffset].push(OperandLiteralNumber, "'Byte Offset'"); - DecorationOperands[DecorationXfbBuffer].push(OperandLiteralNumber, "'XFB Buffer Number'"); - DecorationOperands[DecorationXfbStride].push(OperandLiteralNumber, "'XFB Stride'"); - DecorationOperands[DecorationArrayStride].push(OperandLiteralNumber, "'Array Stride'"); - DecorationOperands[DecorationMatrixStride].push(OperandLiteralNumber, "'Matrix Stride'"); - DecorationOperands[DecorationBuiltIn].push(OperandLiteralNumber, "See <>"); - DecorationOperands[DecorationFPRoundingMode].push(OperandFPRoundingMode, "'Floating-Point Rounding Mode'"); - DecorationOperands[DecorationFPFastMathMode].push(OperandFPFastMath, "'Fast-Math Mode'"); - DecorationOperands[DecorationLinkageAttributes].push(OperandLiteralString, "'Name'"); - DecorationOperands[DecorationLinkageAttributes].push(OperandLinkageType, "'Linkage Type'"); - DecorationOperands[DecorationFuncParamAttr].push(OperandFuncParamAttr, "'Function Parameter Attribute'"); - DecorationOperands[DecorationSpecId].push(OperandLiteralNumber, "'Specialization Constant ID'"); - DecorationOperands[DecorationInputAttachmentIndex].push(OperandLiteralNumber, "'Attachment Index'"); - DecorationOperands[DecorationAlignment].push(OperandLiteralNumber, "'Alignment'"); - - OperandClassParams[OperandSource].set(0, SourceString, 0); - OperandClassParams[OperandExecutionModel].set(0, ExecutionModelString, nullptr); - OperandClassParams[OperandAddressing].set(0, AddressingString, nullptr); - OperandClassParams[OperandMemory].set(0, MemoryString, nullptr); - OperandClassParams[OperandExecutionMode].set(ExecutionModeCeiling, ExecutionModeString, ExecutionModeParams); - OperandClassParams[OperandExecutionMode].setOperands(ExecutionModeOperands); - OperandClassParams[OperandStorage].set(0, StorageClassString, nullptr); - OperandClassParams[OperandDimensionality].set(0, DimensionString, nullptr); - OperandClassParams[OperandSamplerAddressingMode].set(0, SamplerAddressingModeString, nullptr); - OperandClassParams[OperandSamplerFilterMode].set(0, SamplerFilterModeString, nullptr); - OperandClassParams[OperandSamplerImageFormat].set(0, ImageFormatString, nullptr); - OperandClassParams[OperandImageChannelOrder].set(0, ImageChannelOrderString, nullptr); - OperandClassParams[OperandImageChannelDataType].set(0, ImageChannelDataTypeString, nullptr); - OperandClassParams[OperandImageOperands].set(ImageOperandsCeiling, ImageOperandsString, ImageOperandsParams, true); - OperandClassParams[OperandFPFastMath].set(0, FPFastMathString, nullptr, true); - OperandClassParams[OperandFPRoundingMode].set(0, FPRoundingModeString, nullptr); - OperandClassParams[OperandLinkageType].set(0, LinkageTypeString, nullptr); - OperandClassParams[OperandFuncParamAttr].set(0, FuncParamAttrString, nullptr); - OperandClassParams[OperandAccessQualifier].set(0, AccessQualifierString, nullptr); - OperandClassParams[OperandDecoration].set(DecorationCeiling, DecorationString, DecorationParams); - OperandClassParams[OperandDecoration].setOperands(DecorationOperands); - OperandClassParams[OperandBuiltIn].set(0, BuiltInString, nullptr); - OperandClassParams[OperandSelect].set(SelectControlCeiling, SelectControlString, SelectionControlParams, true); - OperandClassParams[OperandLoop].set(LoopControlCeiling, LoopControlString, LoopControlParams, true); - OperandClassParams[OperandFunction].set(FunctionControlCeiling, FunctionControlString, FunctionControlParams, true); - OperandClassParams[OperandMemorySemantics].set(0, MemorySemanticsString, nullptr, true); - OperandClassParams[OperandMemoryAccess].set(0, MemoryAccessString, nullptr, true); - OperandClassParams[OperandScope].set(0, ScopeString, nullptr); - OperandClassParams[OperandGroupOperation].set(0, GroupOperationString, nullptr); - OperandClassParams[OperandKernelEnqueueFlags].set(0, KernelEnqueueFlagsString, nullptr); - OperandClassParams[OperandKernelProfilingInfo].set(0, KernelProfilingInfoString, nullptr, true); - OperandClassParams[OperandCapability].set(0, CapabilityString, nullptr); - OperandClassParams[OperandOpcode].set(OpCodeMask + 1, OpcodeString, 0); - - // set name of operator, an initial set of style operands, and the description - - InstructionDesc[OpSource].operands.push(OperandSource, ""); - InstructionDesc[OpSource].operands.push(OperandLiteralNumber, "'Version'"); - InstructionDesc[OpSource].operands.push(OperandId, "'File'", true); - InstructionDesc[OpSource].operands.push(OperandLiteralString, "'Source'", true); - - InstructionDesc[OpSourceContinued].operands.push(OperandLiteralString, "'Continued Source'"); - - InstructionDesc[OpSourceExtension].operands.push(OperandLiteralString, "'Extension'"); - - InstructionDesc[OpName].operands.push(OperandId, "'Target'"); - InstructionDesc[OpName].operands.push(OperandLiteralString, "'Name'"); - - InstructionDesc[OpMemberName].operands.push(OperandId, "'Type'"); - InstructionDesc[OpMemberName].operands.push(OperandLiteralNumber, "'Member'"); - InstructionDesc[OpMemberName].operands.push(OperandLiteralString, "'Name'"); - - InstructionDesc[OpString].operands.push(OperandLiteralString, "'String'"); - - InstructionDesc[OpLine].operands.push(OperandId, "'File'"); - InstructionDesc[OpLine].operands.push(OperandLiteralNumber, "'Line'"); - InstructionDesc[OpLine].operands.push(OperandLiteralNumber, "'Column'"); - - InstructionDesc[OpExtension].operands.push(OperandLiteralString, "'Name'"); - - InstructionDesc[OpExtInstImport].operands.push(OperandLiteralString, "'Name'"); - - InstructionDesc[OpCapability].operands.push(OperandCapability, "'Capability'"); - - InstructionDesc[OpMemoryModel].operands.push(OperandAddressing, ""); - InstructionDesc[OpMemoryModel].operands.push(OperandMemory, ""); - - InstructionDesc[OpEntryPoint].operands.push(OperandExecutionModel, ""); - InstructionDesc[OpEntryPoint].operands.push(OperandId, "'Entry Point'"); - InstructionDesc[OpEntryPoint].operands.push(OperandLiteralString, "'Name'"); - InstructionDesc[OpEntryPoint].operands.push(OperandVariableIds, "'Interface'"); - - InstructionDesc[OpExecutionMode].operands.push(OperandId, "'Entry Point'"); - InstructionDesc[OpExecutionMode].operands.push(OperandExecutionMode, "'Mode'"); - InstructionDesc[OpExecutionMode].operands.push(OperandOptionalLiteral, "See <>"); - - InstructionDesc[OpTypeInt].operands.push(OperandLiteralNumber, "'Width'"); - InstructionDesc[OpTypeInt].operands.push(OperandLiteralNumber, "'Signedness'"); - - InstructionDesc[OpTypeFloat].operands.push(OperandLiteralNumber, "'Width'"); - - InstructionDesc[OpTypeVector].operands.push(OperandId, "'Component Type'"); - InstructionDesc[OpTypeVector].operands.push(OperandLiteralNumber, "'Component Count'"); - - InstructionDesc[OpTypeMatrix].operands.push(OperandId, "'Column Type'"); - InstructionDesc[OpTypeMatrix].operands.push(OperandLiteralNumber, "'Column Count'"); - - InstructionDesc[OpTypeImage].operands.push(OperandId, "'Sampled Type'"); - InstructionDesc[OpTypeImage].operands.push(OperandDimensionality, ""); - InstructionDesc[OpTypeImage].operands.push(OperandLiteralNumber, "'Depth'"); - InstructionDesc[OpTypeImage].operands.push(OperandLiteralNumber, "'Arrayed'"); - InstructionDesc[OpTypeImage].operands.push(OperandLiteralNumber, "'MS'"); - InstructionDesc[OpTypeImage].operands.push(OperandLiteralNumber, "'Sampled'"); - InstructionDesc[OpTypeImage].operands.push(OperandSamplerImageFormat, ""); - InstructionDesc[OpTypeImage].operands.push(OperandAccessQualifier, "", true); - - InstructionDesc[OpTypeSampledImage].operands.push(OperandId, "'Image Type'"); - - InstructionDesc[OpTypeArray].operands.push(OperandId, "'Element Type'"); - InstructionDesc[OpTypeArray].operands.push(OperandId, "'Length'"); - - InstructionDesc[OpTypeRuntimeArray].operands.push(OperandId, "'Element Type'"); - - InstructionDesc[OpTypeStruct].operands.push(OperandVariableIds, "'Member 0 type', +\n'member 1 type', +\n..."); - - InstructionDesc[OpTypeOpaque].operands.push(OperandLiteralString, "The name of the opaque type."); - - InstructionDesc[OpTypePointer].operands.push(OperandStorage, ""); - InstructionDesc[OpTypePointer].operands.push(OperandId, "'Type'"); - - InstructionDesc[OpTypeForwardPointer].operands.push(OperandId, "'Pointer Type'"); - InstructionDesc[OpTypeForwardPointer].operands.push(OperandStorage, ""); - - InstructionDesc[OpTypePipe].operands.push(OperandAccessQualifier, "'Qualifier'"); - - InstructionDesc[OpTypeFunction].operands.push(OperandId, "'Return Type'"); - InstructionDesc[OpTypeFunction].operands.push(OperandVariableIds, "'Parameter 0 Type', +\n'Parameter 1 Type', +\n..."); - - InstructionDesc[OpConstant].operands.push(OperandVariableLiterals, "'Value'"); - - InstructionDesc[OpConstantComposite].operands.push(OperandVariableIds, "'Constituents'"); - - InstructionDesc[OpConstantSampler].operands.push(OperandSamplerAddressingMode, ""); - InstructionDesc[OpConstantSampler].operands.push(OperandLiteralNumber, "'Param'"); - InstructionDesc[OpConstantSampler].operands.push(OperandSamplerFilterMode, ""); - - InstructionDesc[OpSpecConstant].operands.push(OperandVariableLiterals, "'Value'"); - - InstructionDesc[OpSpecConstantComposite].operands.push(OperandVariableIds, "'Constituents'"); - - InstructionDesc[OpSpecConstantOp].operands.push(OperandLiteralNumber, "'Opcode'"); - InstructionDesc[OpSpecConstantOp].operands.push(OperandVariableIds, "'Operands'"); - - InstructionDesc[OpVariable].operands.push(OperandStorage, ""); - InstructionDesc[OpVariable].operands.push(OperandId, "'Initializer'", true); - - InstructionDesc[OpFunction].operands.push(OperandFunction, ""); - InstructionDesc[OpFunction].operands.push(OperandId, "'Function Type'"); - - InstructionDesc[OpFunctionCall].operands.push(OperandId, "'Function'"); - InstructionDesc[OpFunctionCall].operands.push(OperandVariableIds, "'Argument 0', +\n'Argument 1', +\n..."); - - InstructionDesc[OpExtInst].operands.push(OperandId, "'Set'"); - InstructionDesc[OpExtInst].operands.push(OperandLiteralNumber, "'Instruction'"); - InstructionDesc[OpExtInst].operands.push(OperandVariableIds, "'Operand 1', +\n'Operand 2', +\n..."); - - InstructionDesc[OpLoad].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpLoad].operands.push(OperandMemoryAccess, "", true); - - InstructionDesc[OpStore].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpStore].operands.push(OperandId, "'Object'"); - InstructionDesc[OpStore].operands.push(OperandMemoryAccess, "", true); - - InstructionDesc[OpPhi].operands.push(OperandVariableIds, "'Variable, Parent, ...'"); - - InstructionDesc[OpDecorate].operands.push(OperandId, "'Target'"); - InstructionDesc[OpDecorate].operands.push(OperandDecoration, ""); - InstructionDesc[OpDecorate].operands.push(OperandVariableLiterals, "See <>."); - - InstructionDesc[OpDecorateId].operands.push(OperandId, "'Target'"); - InstructionDesc[OpDecorateId].operands.push(OperandDecoration, ""); - InstructionDesc[OpDecorateId].operands.push(OperandVariableIds, "See <>."); - - InstructionDesc[OpDecorateStringGOOGLE].operands.push(OperandId, "'Target'"); - InstructionDesc[OpDecorateStringGOOGLE].operands.push(OperandDecoration, ""); - InstructionDesc[OpDecorateStringGOOGLE].operands.push(OperandLiteralString, "'Literal String'"); - - InstructionDesc[OpMemberDecorate].operands.push(OperandId, "'Structure Type'"); - InstructionDesc[OpMemberDecorate].operands.push(OperandLiteralNumber, "'Member'"); - InstructionDesc[OpMemberDecorate].operands.push(OperandDecoration, ""); - InstructionDesc[OpMemberDecorate].operands.push(OperandVariableLiterals, "See <>."); - - InstructionDesc[OpMemberDecorateStringGOOGLE].operands.push(OperandId, "'Structure Type'"); - InstructionDesc[OpMemberDecorateStringGOOGLE].operands.push(OperandLiteralNumber, "'Member'"); - InstructionDesc[OpMemberDecorateStringGOOGLE].operands.push(OperandDecoration, ""); - InstructionDesc[OpMemberDecorateStringGOOGLE].operands.push(OperandLiteralString, "'Literal String'"); - - InstructionDesc[OpGroupDecorate].operands.push(OperandId, "'Decoration Group'"); - InstructionDesc[OpGroupDecorate].operands.push(OperandVariableIds, "'Targets'"); - - InstructionDesc[OpGroupMemberDecorate].operands.push(OperandId, "'Decoration Group'"); - InstructionDesc[OpGroupMemberDecorate].operands.push(OperandVariableIdLiteral, "'Targets'"); - - InstructionDesc[OpVectorExtractDynamic].operands.push(OperandId, "'Vector'"); - InstructionDesc[OpVectorExtractDynamic].operands.push(OperandId, "'Index'"); - - InstructionDesc[OpVectorInsertDynamic].operands.push(OperandId, "'Vector'"); - InstructionDesc[OpVectorInsertDynamic].operands.push(OperandId, "'Component'"); - InstructionDesc[OpVectorInsertDynamic].operands.push(OperandId, "'Index'"); - - InstructionDesc[OpVectorShuffle].operands.push(OperandId, "'Vector 1'"); - InstructionDesc[OpVectorShuffle].operands.push(OperandId, "'Vector 2'"); - InstructionDesc[OpVectorShuffle].operands.push(OperandVariableLiterals, "'Components'"); - - InstructionDesc[OpCompositeConstruct].operands.push(OperandVariableIds, "'Constituents'"); - - InstructionDesc[OpCompositeExtract].operands.push(OperandId, "'Composite'"); - InstructionDesc[OpCompositeExtract].operands.push(OperandVariableLiterals, "'Indexes'"); - - InstructionDesc[OpCompositeInsert].operands.push(OperandId, "'Object'"); - InstructionDesc[OpCompositeInsert].operands.push(OperandId, "'Composite'"); - InstructionDesc[OpCompositeInsert].operands.push(OperandVariableLiterals, "'Indexes'"); - - InstructionDesc[OpCopyObject].operands.push(OperandId, "'Operand'"); - - InstructionDesc[OpCopyMemory].operands.push(OperandId, "'Target'"); - InstructionDesc[OpCopyMemory].operands.push(OperandId, "'Source'"); - InstructionDesc[OpCopyMemory].operands.push(OperandMemoryAccess, "", true); - - InstructionDesc[OpCopyMemorySized].operands.push(OperandId, "'Target'"); - InstructionDesc[OpCopyMemorySized].operands.push(OperandId, "'Source'"); - InstructionDesc[OpCopyMemorySized].operands.push(OperandId, "'Size'"); - InstructionDesc[OpCopyMemorySized].operands.push(OperandMemoryAccess, "", true); - - InstructionDesc[OpSampledImage].operands.push(OperandId, "'Image'"); - InstructionDesc[OpSampledImage].operands.push(OperandId, "'Sampler'"); - - InstructionDesc[OpImage].operands.push(OperandId, "'Sampled Image'"); - - InstructionDesc[OpImageRead].operands.push(OperandId, "'Image'"); - InstructionDesc[OpImageRead].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageRead].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageRead].operands.push(OperandVariableIds, "", true); - - InstructionDesc[OpImageWrite].operands.push(OperandId, "'Image'"); - InstructionDesc[OpImageWrite].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageWrite].operands.push(OperandId, "'Texel'"); - InstructionDesc[OpImageWrite].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageWrite].operands.push(OperandVariableIds, "", true); - - InstructionDesc[OpImageSampleImplicitLod].operands.push(OperandId, "'Sampled Image'"); - InstructionDesc[OpImageSampleImplicitLod].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageSampleImplicitLod].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageSampleImplicitLod].operands.push(OperandVariableIds, "", true); - - InstructionDesc[OpImageSampleExplicitLod].operands.push(OperandId, "'Sampled Image'"); - InstructionDesc[OpImageSampleExplicitLod].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageSampleExplicitLod].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageSampleExplicitLod].operands.push(OperandVariableIds, "", true); - - InstructionDesc[OpImageSampleDrefImplicitLod].operands.push(OperandId, "'Sampled Image'"); - InstructionDesc[OpImageSampleDrefImplicitLod].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageSampleDrefImplicitLod].operands.push(OperandId, "'D~ref~'"); - InstructionDesc[OpImageSampleDrefImplicitLod].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageSampleDrefImplicitLod].operands.push(OperandVariableIds, "", true); - - InstructionDesc[OpImageSampleDrefExplicitLod].operands.push(OperandId, "'Sampled Image'"); - InstructionDesc[OpImageSampleDrefExplicitLod].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageSampleDrefExplicitLod].operands.push(OperandId, "'D~ref~'"); - InstructionDesc[OpImageSampleDrefExplicitLod].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageSampleDrefExplicitLod].operands.push(OperandVariableIds, "", true); - - InstructionDesc[OpImageSampleProjImplicitLod].operands.push(OperandId, "'Sampled Image'"); - InstructionDesc[OpImageSampleProjImplicitLod].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageSampleProjImplicitLod].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageSampleProjImplicitLod].operands.push(OperandVariableIds, "", true); - - InstructionDesc[OpImageSampleProjExplicitLod].operands.push(OperandId, "'Sampled Image'"); - InstructionDesc[OpImageSampleProjExplicitLod].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageSampleProjExplicitLod].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageSampleProjExplicitLod].operands.push(OperandVariableIds, "", true); - - InstructionDesc[OpImageSampleProjDrefImplicitLod].operands.push(OperandId, "'Sampled Image'"); - InstructionDesc[OpImageSampleProjDrefImplicitLod].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageSampleProjDrefImplicitLod].operands.push(OperandId, "'D~ref~'"); - InstructionDesc[OpImageSampleProjDrefImplicitLod].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageSampleProjDrefImplicitLod].operands.push(OperandVariableIds, "", true); - - InstructionDesc[OpImageSampleProjDrefExplicitLod].operands.push(OperandId, "'Sampled Image'"); - InstructionDesc[OpImageSampleProjDrefExplicitLod].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageSampleProjDrefExplicitLod].operands.push(OperandId, "'D~ref~'"); - InstructionDesc[OpImageSampleProjDrefExplicitLod].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageSampleProjDrefExplicitLod].operands.push(OperandVariableIds, "", true); - - InstructionDesc[OpImageFetch].operands.push(OperandId, "'Image'"); - InstructionDesc[OpImageFetch].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageFetch].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageFetch].operands.push(OperandVariableIds, "", true); - - InstructionDesc[OpImageGather].operands.push(OperandId, "'Sampled Image'"); - InstructionDesc[OpImageGather].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageGather].operands.push(OperandId, "'Component'"); - InstructionDesc[OpImageGather].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageGather].operands.push(OperandVariableIds, "", true); - - InstructionDesc[OpImageDrefGather].operands.push(OperandId, "'Sampled Image'"); - InstructionDesc[OpImageDrefGather].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageDrefGather].operands.push(OperandId, "'D~ref~'"); - InstructionDesc[OpImageDrefGather].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageDrefGather].operands.push(OperandVariableIds, "", true); - - InstructionDesc[OpImageSparseSampleImplicitLod].operands.push(OperandId, "'Sampled Image'"); - InstructionDesc[OpImageSparseSampleImplicitLod].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageSparseSampleImplicitLod].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageSparseSampleImplicitLod].operands.push(OperandVariableIds, "", true); - - InstructionDesc[OpImageSparseSampleExplicitLod].operands.push(OperandId, "'Sampled Image'"); - InstructionDesc[OpImageSparseSampleExplicitLod].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageSparseSampleExplicitLod].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageSparseSampleExplicitLod].operands.push(OperandVariableIds, "", true); - - InstructionDesc[OpImageSparseSampleDrefImplicitLod].operands.push(OperandId, "'Sampled Image'"); - InstructionDesc[OpImageSparseSampleDrefImplicitLod].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageSparseSampleDrefImplicitLod].operands.push(OperandId, "'D~ref~'"); - InstructionDesc[OpImageSparseSampleDrefImplicitLod].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageSparseSampleDrefImplicitLod].operands.push(OperandVariableIds, "", true); - - InstructionDesc[OpImageSparseSampleDrefExplicitLod].operands.push(OperandId, "'Sampled Image'"); - InstructionDesc[OpImageSparseSampleDrefExplicitLod].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageSparseSampleDrefExplicitLod].operands.push(OperandId, "'D~ref~'"); - InstructionDesc[OpImageSparseSampleDrefExplicitLod].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageSparseSampleDrefExplicitLod].operands.push(OperandVariableIds, "", true); - - InstructionDesc[OpImageSparseSampleProjImplicitLod].operands.push(OperandId, "'Sampled Image'"); - InstructionDesc[OpImageSparseSampleProjImplicitLod].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageSparseSampleProjImplicitLod].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageSparseSampleProjImplicitLod].operands.push(OperandVariableIds, "", true); - - InstructionDesc[OpImageSparseSampleProjExplicitLod].operands.push(OperandId, "'Sampled Image'"); - InstructionDesc[OpImageSparseSampleProjExplicitLod].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageSparseSampleProjExplicitLod].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageSparseSampleProjExplicitLod].operands.push(OperandVariableIds, "", true); - - InstructionDesc[OpImageSparseSampleProjDrefImplicitLod].operands.push(OperandId, "'Sampled Image'"); - InstructionDesc[OpImageSparseSampleProjDrefImplicitLod].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageSparseSampleProjDrefImplicitLod].operands.push(OperandId, "'D~ref~'"); - InstructionDesc[OpImageSparseSampleProjDrefImplicitLod].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageSparseSampleProjDrefImplicitLod].operands.push(OperandVariableIds, "", true); - - InstructionDesc[OpImageSparseSampleProjDrefExplicitLod].operands.push(OperandId, "'Sampled Image'"); - InstructionDesc[OpImageSparseSampleProjDrefExplicitLod].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageSparseSampleProjDrefExplicitLod].operands.push(OperandId, "'D~ref~'"); - InstructionDesc[OpImageSparseSampleProjDrefExplicitLod].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageSparseSampleProjDrefExplicitLod].operands.push(OperandVariableIds, "", true); - - InstructionDesc[OpImageSparseFetch].operands.push(OperandId, "'Image'"); - InstructionDesc[OpImageSparseFetch].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageSparseFetch].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageSparseFetch].operands.push(OperandVariableIds, "", true); - - InstructionDesc[OpImageSparseGather].operands.push(OperandId, "'Sampled Image'"); - InstructionDesc[OpImageSparseGather].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageSparseGather].operands.push(OperandId, "'Component'"); - InstructionDesc[OpImageSparseGather].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageSparseGather].operands.push(OperandVariableIds, "", true); - - InstructionDesc[OpImageSparseDrefGather].operands.push(OperandId, "'Sampled Image'"); - InstructionDesc[OpImageSparseDrefGather].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageSparseDrefGather].operands.push(OperandId, "'D~ref~'"); - InstructionDesc[OpImageSparseDrefGather].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageSparseDrefGather].operands.push(OperandVariableIds, "", true); - - InstructionDesc[OpImageSparseRead].operands.push(OperandId, "'Image'"); - InstructionDesc[OpImageSparseRead].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageSparseRead].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageSparseRead].operands.push(OperandVariableIds, "", true); - - InstructionDesc[OpImageSparseTexelsResident].operands.push(OperandId, "'Resident Code'"); - - InstructionDesc[OpImageQuerySizeLod].operands.push(OperandId, "'Image'"); - InstructionDesc[OpImageQuerySizeLod].operands.push(OperandId, "'Level of Detail'"); - - InstructionDesc[OpImageQuerySize].operands.push(OperandId, "'Image'"); - - InstructionDesc[OpImageQueryLod].operands.push(OperandId, "'Image'"); - InstructionDesc[OpImageQueryLod].operands.push(OperandId, "'Coordinate'"); - - InstructionDesc[OpImageQueryLevels].operands.push(OperandId, "'Image'"); - - InstructionDesc[OpImageQuerySamples].operands.push(OperandId, "'Image'"); - - InstructionDesc[OpImageQueryFormat].operands.push(OperandId, "'Image'"); - - InstructionDesc[OpImageQueryOrder].operands.push(OperandId, "'Image'"); - - InstructionDesc[OpAccessChain].operands.push(OperandId, "'Base'"); - InstructionDesc[OpAccessChain].operands.push(OperandVariableIds, "'Indexes'"); - - InstructionDesc[OpInBoundsAccessChain].operands.push(OperandId, "'Base'"); - InstructionDesc[OpInBoundsAccessChain].operands.push(OperandVariableIds, "'Indexes'"); - - InstructionDesc[OpPtrAccessChain].operands.push(OperandId, "'Base'"); - InstructionDesc[OpPtrAccessChain].operands.push(OperandId, "'Element'"); - InstructionDesc[OpPtrAccessChain].operands.push(OperandVariableIds, "'Indexes'"); - - InstructionDesc[OpInBoundsPtrAccessChain].operands.push(OperandId, "'Base'"); - InstructionDesc[OpInBoundsPtrAccessChain].operands.push(OperandId, "'Element'"); - InstructionDesc[OpInBoundsPtrAccessChain].operands.push(OperandVariableIds, "'Indexes'"); - - InstructionDesc[OpSNegate].operands.push(OperandId, "'Operand'"); - - InstructionDesc[OpFNegate].operands.push(OperandId, "'Operand'"); - - InstructionDesc[OpNot].operands.push(OperandId, "'Operand'"); - - InstructionDesc[OpAny].operands.push(OperandId, "'Vector'"); - - InstructionDesc[OpAll].operands.push(OperandId, "'Vector'"); - - InstructionDesc[OpConvertFToU].operands.push(OperandId, "'Float Value'"); - - InstructionDesc[OpConvertFToS].operands.push(OperandId, "'Float Value'"); - - InstructionDesc[OpConvertSToF].operands.push(OperandId, "'Signed Value'"); - - InstructionDesc[OpConvertUToF].operands.push(OperandId, "'Unsigned Value'"); - - InstructionDesc[OpUConvert].operands.push(OperandId, "'Unsigned Value'"); - - InstructionDesc[OpSConvert].operands.push(OperandId, "'Signed Value'"); - - InstructionDesc[OpFConvert].operands.push(OperandId, "'Float Value'"); - - InstructionDesc[OpSatConvertSToU].operands.push(OperandId, "'Signed Value'"); - - InstructionDesc[OpSatConvertUToS].operands.push(OperandId, "'Unsigned Value'"); - - InstructionDesc[OpConvertPtrToU].operands.push(OperandId, "'Pointer'"); - - InstructionDesc[OpConvertUToPtr].operands.push(OperandId, "'Integer Value'"); - - InstructionDesc[OpPtrCastToGeneric].operands.push(OperandId, "'Pointer'"); - - InstructionDesc[OpGenericCastToPtr].operands.push(OperandId, "'Pointer'"); - - InstructionDesc[OpGenericCastToPtrExplicit].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpGenericCastToPtrExplicit].operands.push(OperandStorage, "'Storage'"); - - InstructionDesc[OpGenericPtrMemSemantics].operands.push(OperandId, "'Pointer'"); - - InstructionDesc[OpBitcast].operands.push(OperandId, "'Operand'"); - - InstructionDesc[OpQuantizeToF16].operands.push(OperandId, "'Value'"); - - InstructionDesc[OpTranspose].operands.push(OperandId, "'Matrix'"); - - InstructionDesc[OpIsNan].operands.push(OperandId, "'x'"); - - InstructionDesc[OpIsInf].operands.push(OperandId, "'x'"); - - InstructionDesc[OpIsFinite].operands.push(OperandId, "'x'"); - - InstructionDesc[OpIsNormal].operands.push(OperandId, "'x'"); - - InstructionDesc[OpSignBitSet].operands.push(OperandId, "'x'"); - - InstructionDesc[OpLessOrGreater].operands.push(OperandId, "'x'"); - InstructionDesc[OpLessOrGreater].operands.push(OperandId, "'y'"); - - InstructionDesc[OpOrdered].operands.push(OperandId, "'x'"); - InstructionDesc[OpOrdered].operands.push(OperandId, "'y'"); - - InstructionDesc[OpUnordered].operands.push(OperandId, "'x'"); - InstructionDesc[OpUnordered].operands.push(OperandId, "'y'"); - - InstructionDesc[OpArrayLength].operands.push(OperandId, "'Structure'"); - InstructionDesc[OpArrayLength].operands.push(OperandLiteralNumber, "'Array member'"); - - InstructionDesc[OpIAdd].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpIAdd].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpFAdd].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpFAdd].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpISub].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpISub].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpFSub].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpFSub].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpIMul].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpIMul].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpFMul].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpFMul].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpUDiv].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpUDiv].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpSDiv].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpSDiv].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpFDiv].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpFDiv].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpUMod].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpUMod].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpSRem].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpSRem].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpSMod].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpSMod].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpFRem].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpFRem].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpFMod].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpFMod].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpVectorTimesScalar].operands.push(OperandId, "'Vector'"); - InstructionDesc[OpVectorTimesScalar].operands.push(OperandId, "'Scalar'"); - - InstructionDesc[OpMatrixTimesScalar].operands.push(OperandId, "'Matrix'"); - InstructionDesc[OpMatrixTimesScalar].operands.push(OperandId, "'Scalar'"); - - InstructionDesc[OpVectorTimesMatrix].operands.push(OperandId, "'Vector'"); - InstructionDesc[OpVectorTimesMatrix].operands.push(OperandId, "'Matrix'"); - - InstructionDesc[OpMatrixTimesVector].operands.push(OperandId, "'Matrix'"); - InstructionDesc[OpMatrixTimesVector].operands.push(OperandId, "'Vector'"); - - InstructionDesc[OpMatrixTimesMatrix].operands.push(OperandId, "'LeftMatrix'"); - InstructionDesc[OpMatrixTimesMatrix].operands.push(OperandId, "'RightMatrix'"); - - InstructionDesc[OpOuterProduct].operands.push(OperandId, "'Vector 1'"); - InstructionDesc[OpOuterProduct].operands.push(OperandId, "'Vector 2'"); - - InstructionDesc[OpDot].operands.push(OperandId, "'Vector 1'"); - InstructionDesc[OpDot].operands.push(OperandId, "'Vector 2'"); - - InstructionDesc[OpIAddCarry].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpIAddCarry].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpISubBorrow].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpISubBorrow].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpUMulExtended].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpUMulExtended].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpSMulExtended].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpSMulExtended].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpShiftRightLogical].operands.push(OperandId, "'Base'"); - InstructionDesc[OpShiftRightLogical].operands.push(OperandId, "'Shift'"); - - InstructionDesc[OpShiftRightArithmetic].operands.push(OperandId, "'Base'"); - InstructionDesc[OpShiftRightArithmetic].operands.push(OperandId, "'Shift'"); - - InstructionDesc[OpShiftLeftLogical].operands.push(OperandId, "'Base'"); - InstructionDesc[OpShiftLeftLogical].operands.push(OperandId, "'Shift'"); - - InstructionDesc[OpLogicalOr].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpLogicalOr].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpLogicalAnd].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpLogicalAnd].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpLogicalEqual].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpLogicalEqual].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpLogicalNotEqual].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpLogicalNotEqual].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpLogicalNot].operands.push(OperandId, "'Operand'"); - - InstructionDesc[OpBitwiseOr].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpBitwiseOr].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpBitwiseXor].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpBitwiseXor].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpBitwiseAnd].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpBitwiseAnd].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpBitFieldInsert].operands.push(OperandId, "'Base'"); - InstructionDesc[OpBitFieldInsert].operands.push(OperandId, "'Insert'"); - InstructionDesc[OpBitFieldInsert].operands.push(OperandId, "'Offset'"); - InstructionDesc[OpBitFieldInsert].operands.push(OperandId, "'Count'"); - - InstructionDesc[OpBitFieldSExtract].operands.push(OperandId, "'Base'"); - InstructionDesc[OpBitFieldSExtract].operands.push(OperandId, "'Offset'"); - InstructionDesc[OpBitFieldSExtract].operands.push(OperandId, "'Count'"); - - InstructionDesc[OpBitFieldUExtract].operands.push(OperandId, "'Base'"); - InstructionDesc[OpBitFieldUExtract].operands.push(OperandId, "'Offset'"); - InstructionDesc[OpBitFieldUExtract].operands.push(OperandId, "'Count'"); - - InstructionDesc[OpBitReverse].operands.push(OperandId, "'Base'"); - - InstructionDesc[OpBitCount].operands.push(OperandId, "'Base'"); - - InstructionDesc[OpSelect].operands.push(OperandId, "'Condition'"); - InstructionDesc[OpSelect].operands.push(OperandId, "'Object 1'"); - InstructionDesc[OpSelect].operands.push(OperandId, "'Object 2'"); - - InstructionDesc[OpIEqual].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpIEqual].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpFOrdEqual].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpFOrdEqual].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpFUnordEqual].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpFUnordEqual].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpINotEqual].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpINotEqual].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpFOrdNotEqual].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpFOrdNotEqual].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpFUnordNotEqual].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpFUnordNotEqual].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpULessThan].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpULessThan].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpSLessThan].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpSLessThan].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpFOrdLessThan].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpFOrdLessThan].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpFUnordLessThan].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpFUnordLessThan].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpUGreaterThan].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpUGreaterThan].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpSGreaterThan].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpSGreaterThan].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpFOrdGreaterThan].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpFOrdGreaterThan].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpFUnordGreaterThan].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpFUnordGreaterThan].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpULessThanEqual].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpULessThanEqual].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpSLessThanEqual].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpSLessThanEqual].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpFOrdLessThanEqual].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpFOrdLessThanEqual].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpFUnordLessThanEqual].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpFUnordLessThanEqual].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpUGreaterThanEqual].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpUGreaterThanEqual].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpSGreaterThanEqual].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpSGreaterThanEqual].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpFOrdGreaterThanEqual].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpFOrdGreaterThanEqual].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpFUnordGreaterThanEqual].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpFUnordGreaterThanEqual].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpDPdx].operands.push(OperandId, "'P'"); - - InstructionDesc[OpDPdy].operands.push(OperandId, "'P'"); - - InstructionDesc[OpFwidth].operands.push(OperandId, "'P'"); - - InstructionDesc[OpDPdxFine].operands.push(OperandId, "'P'"); - - InstructionDesc[OpDPdyFine].operands.push(OperandId, "'P'"); - - InstructionDesc[OpFwidthFine].operands.push(OperandId, "'P'"); - - InstructionDesc[OpDPdxCoarse].operands.push(OperandId, "'P'"); - - InstructionDesc[OpDPdyCoarse].operands.push(OperandId, "'P'"); - - InstructionDesc[OpFwidthCoarse].operands.push(OperandId, "'P'"); - - InstructionDesc[OpEmitStreamVertex].operands.push(OperandId, "'Stream'"); - - InstructionDesc[OpEndStreamPrimitive].operands.push(OperandId, "'Stream'"); - - InstructionDesc[OpControlBarrier].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpControlBarrier].operands.push(OperandScope, "'Memory'"); - InstructionDesc[OpControlBarrier].operands.push(OperandMemorySemantics, "'Semantics'"); - - InstructionDesc[OpMemoryBarrier].operands.push(OperandScope, "'Memory'"); - InstructionDesc[OpMemoryBarrier].operands.push(OperandMemorySemantics, "'Semantics'"); - - InstructionDesc[OpImageTexelPointer].operands.push(OperandId, "'Image'"); - InstructionDesc[OpImageTexelPointer].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageTexelPointer].operands.push(OperandId, "'Sample'"); - - InstructionDesc[OpAtomicLoad].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpAtomicLoad].operands.push(OperandScope, "'Scope'"); - InstructionDesc[OpAtomicLoad].operands.push(OperandMemorySemantics, "'Semantics'"); - - InstructionDesc[OpAtomicStore].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpAtomicStore].operands.push(OperandScope, "'Scope'"); - InstructionDesc[OpAtomicStore].operands.push(OperandMemorySemantics, "'Semantics'"); - InstructionDesc[OpAtomicStore].operands.push(OperandId, "'Value'"); - - InstructionDesc[OpAtomicExchange].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpAtomicExchange].operands.push(OperandScope, "'Scope'"); - InstructionDesc[OpAtomicExchange].operands.push(OperandMemorySemantics, "'Semantics'"); - InstructionDesc[OpAtomicExchange].operands.push(OperandId, "'Value'"); - - InstructionDesc[OpAtomicCompareExchange].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpAtomicCompareExchange].operands.push(OperandScope, "'Scope'"); - InstructionDesc[OpAtomicCompareExchange].operands.push(OperandMemorySemantics, "'Equal'"); - InstructionDesc[OpAtomicCompareExchange].operands.push(OperandMemorySemantics, "'Unequal'"); - InstructionDesc[OpAtomicCompareExchange].operands.push(OperandId, "'Value'"); - InstructionDesc[OpAtomicCompareExchange].operands.push(OperandId, "'Comparator'"); - - InstructionDesc[OpAtomicCompareExchangeWeak].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpAtomicCompareExchangeWeak].operands.push(OperandScope, "'Scope'"); - InstructionDesc[OpAtomicCompareExchangeWeak].operands.push(OperandMemorySemantics, "'Equal'"); - InstructionDesc[OpAtomicCompareExchangeWeak].operands.push(OperandMemorySemantics, "'Unequal'"); - InstructionDesc[OpAtomicCompareExchangeWeak].operands.push(OperandId, "'Value'"); - InstructionDesc[OpAtomicCompareExchangeWeak].operands.push(OperandId, "'Comparator'"); - - InstructionDesc[OpAtomicIIncrement].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpAtomicIIncrement].operands.push(OperandScope, "'Scope'"); - InstructionDesc[OpAtomicIIncrement].operands.push(OperandMemorySemantics, "'Semantics'"); - - InstructionDesc[OpAtomicIDecrement].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpAtomicIDecrement].operands.push(OperandScope, "'Scope'"); - InstructionDesc[OpAtomicIDecrement].operands.push(OperandMemorySemantics, "'Semantics'"); - - InstructionDesc[OpAtomicIAdd].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpAtomicIAdd].operands.push(OperandScope, "'Scope'"); - InstructionDesc[OpAtomicIAdd].operands.push(OperandMemorySemantics, "'Semantics'"); - InstructionDesc[OpAtomicIAdd].operands.push(OperandId, "'Value'"); - - InstructionDesc[OpAtomicISub].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpAtomicISub].operands.push(OperandScope, "'Scope'"); - InstructionDesc[OpAtomicISub].operands.push(OperandMemorySemantics, "'Semantics'"); - InstructionDesc[OpAtomicISub].operands.push(OperandId, "'Value'"); - - InstructionDesc[OpAtomicUMin].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpAtomicUMin].operands.push(OperandScope, "'Scope'"); - InstructionDesc[OpAtomicUMin].operands.push(OperandMemorySemantics, "'Semantics'"); - InstructionDesc[OpAtomicUMin].operands.push(OperandId, "'Value'"); - - InstructionDesc[OpAtomicUMax].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpAtomicUMax].operands.push(OperandScope, "'Scope'"); - InstructionDesc[OpAtomicUMax].operands.push(OperandMemorySemantics, "'Semantics'"); - InstructionDesc[OpAtomicUMax].operands.push(OperandId, "'Value'"); - - InstructionDesc[OpAtomicSMin].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpAtomicSMin].operands.push(OperandScope, "'Scope'"); - InstructionDesc[OpAtomicSMin].operands.push(OperandMemorySemantics, "'Semantics'"); - InstructionDesc[OpAtomicSMin].operands.push(OperandId, "'Value'"); - - InstructionDesc[OpAtomicSMax].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpAtomicSMax].operands.push(OperandScope, "'Scope'"); - InstructionDesc[OpAtomicSMax].operands.push(OperandMemorySemantics, "'Semantics'"); - InstructionDesc[OpAtomicSMax].operands.push(OperandId, "'Value'"); - - InstructionDesc[OpAtomicAnd].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpAtomicAnd].operands.push(OperandScope, "'Scope'"); - InstructionDesc[OpAtomicAnd].operands.push(OperandMemorySemantics, "'Semantics'"); - InstructionDesc[OpAtomicAnd].operands.push(OperandId, "'Value'"); - - InstructionDesc[OpAtomicOr].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpAtomicOr].operands.push(OperandScope, "'Scope'"); - InstructionDesc[OpAtomicOr].operands.push(OperandMemorySemantics, "'Semantics'"); - InstructionDesc[OpAtomicOr].operands.push(OperandId, "'Value'"); - - InstructionDesc[OpAtomicXor].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpAtomicXor].operands.push(OperandScope, "'Scope'"); - InstructionDesc[OpAtomicXor].operands.push(OperandMemorySemantics, "'Semantics'"); - InstructionDesc[OpAtomicXor].operands.push(OperandId, "'Value'"); - - InstructionDesc[OpAtomicFlagTestAndSet].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpAtomicFlagTestAndSet].operands.push(OperandScope, "'Scope'"); - InstructionDesc[OpAtomicFlagTestAndSet].operands.push(OperandMemorySemantics, "'Semantics'"); - - InstructionDesc[OpAtomicFlagClear].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpAtomicFlagClear].operands.push(OperandScope, "'Scope'"); - InstructionDesc[OpAtomicFlagClear].operands.push(OperandMemorySemantics, "'Semantics'"); - - InstructionDesc[OpLoopMerge].operands.push(OperandId, "'Merge Block'"); - InstructionDesc[OpLoopMerge].operands.push(OperandId, "'Continue Target'"); - InstructionDesc[OpLoopMerge].operands.push(OperandLoop, ""); - InstructionDesc[OpLoopMerge].operands.push(OperandOptionalLiteral, ""); - - InstructionDesc[OpSelectionMerge].operands.push(OperandId, "'Merge Block'"); - InstructionDesc[OpSelectionMerge].operands.push(OperandSelect, ""); - - InstructionDesc[OpBranch].operands.push(OperandId, "'Target Label'"); - - InstructionDesc[OpBranchConditional].operands.push(OperandId, "'Condition'"); - InstructionDesc[OpBranchConditional].operands.push(OperandId, "'True Label'"); - InstructionDesc[OpBranchConditional].operands.push(OperandId, "'False Label'"); - InstructionDesc[OpBranchConditional].operands.push(OperandVariableLiterals, "'Branch weights'"); - - InstructionDesc[OpSwitch].operands.push(OperandId, "'Selector'"); - InstructionDesc[OpSwitch].operands.push(OperandId, "'Default'"); - InstructionDesc[OpSwitch].operands.push(OperandVariableLiteralId, "'Target'"); - - - InstructionDesc[OpReturnValue].operands.push(OperandId, "'Value'"); - - InstructionDesc[OpLifetimeStart].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpLifetimeStart].operands.push(OperandLiteralNumber, "'Size'"); - - InstructionDesc[OpLifetimeStop].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpLifetimeStop].operands.push(OperandLiteralNumber, "'Size'"); - - InstructionDesc[OpGroupAsyncCopy].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupAsyncCopy].operands.push(OperandId, "'Destination'"); - InstructionDesc[OpGroupAsyncCopy].operands.push(OperandId, "'Source'"); - InstructionDesc[OpGroupAsyncCopy].operands.push(OperandId, "'Num Elements'"); - InstructionDesc[OpGroupAsyncCopy].operands.push(OperandId, "'Stride'"); - InstructionDesc[OpGroupAsyncCopy].operands.push(OperandId, "'Event'"); - - InstructionDesc[OpGroupWaitEvents].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupWaitEvents].operands.push(OperandId, "'Num Events'"); - InstructionDesc[OpGroupWaitEvents].operands.push(OperandId, "'Events List'"); - - InstructionDesc[OpGroupAll].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupAll].operands.push(OperandId, "'Predicate'"); - - InstructionDesc[OpGroupAny].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupAny].operands.push(OperandId, "'Predicate'"); - - InstructionDesc[OpGroupBroadcast].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupBroadcast].operands.push(OperandId, "'Value'"); - InstructionDesc[OpGroupBroadcast].operands.push(OperandId, "'LocalId'"); - - InstructionDesc[OpGroupIAdd].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupIAdd].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupIAdd].operands.push(OperandId, "'X'"); - - InstructionDesc[OpGroupFAdd].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupFAdd].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupFAdd].operands.push(OperandId, "'X'"); - - InstructionDesc[OpGroupUMin].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupUMin].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupUMin].operands.push(OperandId, "'X'"); - - InstructionDesc[OpGroupSMin].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupSMin].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupSMin].operands.push(OperandId, "X"); - - InstructionDesc[OpGroupFMin].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupFMin].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupFMin].operands.push(OperandId, "X"); - - InstructionDesc[OpGroupUMax].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupUMax].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupUMax].operands.push(OperandId, "X"); - - InstructionDesc[OpGroupSMax].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupSMax].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupSMax].operands.push(OperandId, "X"); - - InstructionDesc[OpGroupFMax].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupFMax].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupFMax].operands.push(OperandId, "X"); - - InstructionDesc[OpReadPipe].operands.push(OperandId, "'Pipe'"); - InstructionDesc[OpReadPipe].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpReadPipe].operands.push(OperandId, "'Packet Size'"); - InstructionDesc[OpReadPipe].operands.push(OperandId, "'Packet Alignment'"); - - InstructionDesc[OpWritePipe].operands.push(OperandId, "'Pipe'"); - InstructionDesc[OpWritePipe].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpWritePipe].operands.push(OperandId, "'Packet Size'"); - InstructionDesc[OpWritePipe].operands.push(OperandId, "'Packet Alignment'"); - - InstructionDesc[OpReservedReadPipe].operands.push(OperandId, "'Pipe'"); - InstructionDesc[OpReservedReadPipe].operands.push(OperandId, "'Reserve Id'"); - InstructionDesc[OpReservedReadPipe].operands.push(OperandId, "'Index'"); - InstructionDesc[OpReservedReadPipe].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpReservedReadPipe].operands.push(OperandId, "'Packet Size'"); - InstructionDesc[OpReservedReadPipe].operands.push(OperandId, "'Packet Alignment'"); - - InstructionDesc[OpReservedWritePipe].operands.push(OperandId, "'Pipe'"); - InstructionDesc[OpReservedWritePipe].operands.push(OperandId, "'Reserve Id'"); - InstructionDesc[OpReservedWritePipe].operands.push(OperandId, "'Index'"); - InstructionDesc[OpReservedWritePipe].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpReservedWritePipe].operands.push(OperandId, "'Packet Size'"); - InstructionDesc[OpReservedWritePipe].operands.push(OperandId, "'Packet Alignment'"); - - InstructionDesc[OpReserveReadPipePackets].operands.push(OperandId, "'Pipe'"); - InstructionDesc[OpReserveReadPipePackets].operands.push(OperandId, "'Num Packets'"); - InstructionDesc[OpReserveReadPipePackets].operands.push(OperandId, "'Packet Size'"); - InstructionDesc[OpReserveReadPipePackets].operands.push(OperandId, "'Packet Alignment'"); - - InstructionDesc[OpReserveWritePipePackets].operands.push(OperandId, "'Pipe'"); - InstructionDesc[OpReserveWritePipePackets].operands.push(OperandId, "'Num Packets'"); - InstructionDesc[OpReserveWritePipePackets].operands.push(OperandId, "'Packet Size'"); - InstructionDesc[OpReserveWritePipePackets].operands.push(OperandId, "'Packet Alignment'"); - - InstructionDesc[OpCommitReadPipe].operands.push(OperandId, "'Pipe'"); - InstructionDesc[OpCommitReadPipe].operands.push(OperandId, "'Reserve Id'"); - InstructionDesc[OpCommitReadPipe].operands.push(OperandId, "'Packet Size'"); - InstructionDesc[OpCommitReadPipe].operands.push(OperandId, "'Packet Alignment'"); - - InstructionDesc[OpCommitWritePipe].operands.push(OperandId, "'Pipe'"); - InstructionDesc[OpCommitWritePipe].operands.push(OperandId, "'Reserve Id'"); - InstructionDesc[OpCommitWritePipe].operands.push(OperandId, "'Packet Size'"); - InstructionDesc[OpCommitWritePipe].operands.push(OperandId, "'Packet Alignment'"); - - InstructionDesc[OpIsValidReserveId].operands.push(OperandId, "'Reserve Id'"); - - InstructionDesc[OpGetNumPipePackets].operands.push(OperandId, "'Pipe'"); - InstructionDesc[OpGetNumPipePackets].operands.push(OperandId, "'Packet Size'"); - InstructionDesc[OpGetNumPipePackets].operands.push(OperandId, "'Packet Alignment'"); - - InstructionDesc[OpGetMaxPipePackets].operands.push(OperandId, "'Pipe'"); - InstructionDesc[OpGetMaxPipePackets].operands.push(OperandId, "'Packet Size'"); - InstructionDesc[OpGetMaxPipePackets].operands.push(OperandId, "'Packet Alignment'"); - - InstructionDesc[OpGroupReserveReadPipePackets].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupReserveReadPipePackets].operands.push(OperandId, "'Pipe'"); - InstructionDesc[OpGroupReserveReadPipePackets].operands.push(OperandId, "'Num Packets'"); - InstructionDesc[OpGroupReserveReadPipePackets].operands.push(OperandId, "'Packet Size'"); - InstructionDesc[OpGroupReserveReadPipePackets].operands.push(OperandId, "'Packet Alignment'"); - - InstructionDesc[OpGroupReserveWritePipePackets].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupReserveWritePipePackets].operands.push(OperandId, "'Pipe'"); - InstructionDesc[OpGroupReserveWritePipePackets].operands.push(OperandId, "'Num Packets'"); - InstructionDesc[OpGroupReserveWritePipePackets].operands.push(OperandId, "'Packet Size'"); - InstructionDesc[OpGroupReserveWritePipePackets].operands.push(OperandId, "'Packet Alignment'"); - - InstructionDesc[OpGroupCommitReadPipe].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupCommitReadPipe].operands.push(OperandId, "'Pipe'"); - InstructionDesc[OpGroupCommitReadPipe].operands.push(OperandId, "'Reserve Id'"); - InstructionDesc[OpGroupCommitReadPipe].operands.push(OperandId, "'Packet Size'"); - InstructionDesc[OpGroupCommitReadPipe].operands.push(OperandId, "'Packet Alignment'"); - - InstructionDesc[OpGroupCommitWritePipe].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupCommitWritePipe].operands.push(OperandId, "'Pipe'"); - InstructionDesc[OpGroupCommitWritePipe].operands.push(OperandId, "'Reserve Id'"); - InstructionDesc[OpGroupCommitWritePipe].operands.push(OperandId, "'Packet Size'"); - InstructionDesc[OpGroupCommitWritePipe].operands.push(OperandId, "'Packet Alignment'"); - - InstructionDesc[OpBuildNDRange].operands.push(OperandId, "'GlobalWorkSize'"); - InstructionDesc[OpBuildNDRange].operands.push(OperandId, "'LocalWorkSize'"); - InstructionDesc[OpBuildNDRange].operands.push(OperandId, "'GlobalWorkOffset'"); - - InstructionDesc[OpCaptureEventProfilingInfo].operands.push(OperandId, "'Event'"); - InstructionDesc[OpCaptureEventProfilingInfo].operands.push(OperandId, "'Profiling Info'"); - InstructionDesc[OpCaptureEventProfilingInfo].operands.push(OperandId, "'Value'"); - - InstructionDesc[OpSetUserEventStatus].operands.push(OperandId, "'Event'"); - InstructionDesc[OpSetUserEventStatus].operands.push(OperandId, "'Status'"); - - InstructionDesc[OpIsValidEvent].operands.push(OperandId, "'Event'"); - - InstructionDesc[OpRetainEvent].operands.push(OperandId, "'Event'"); - - InstructionDesc[OpReleaseEvent].operands.push(OperandId, "'Event'"); - - InstructionDesc[OpGetKernelWorkGroupSize].operands.push(OperandId, "'Invoke'"); - InstructionDesc[OpGetKernelWorkGroupSize].operands.push(OperandId, "'Param'"); - InstructionDesc[OpGetKernelWorkGroupSize].operands.push(OperandId, "'Param Size'"); - InstructionDesc[OpGetKernelWorkGroupSize].operands.push(OperandId, "'Param Align'"); - - InstructionDesc[OpGetKernelPreferredWorkGroupSizeMultiple].operands.push(OperandId, "'Invoke'"); - InstructionDesc[OpGetKernelPreferredWorkGroupSizeMultiple].operands.push(OperandId, "'Param'"); - InstructionDesc[OpGetKernelPreferredWorkGroupSizeMultiple].operands.push(OperandId, "'Param Size'"); - InstructionDesc[OpGetKernelPreferredWorkGroupSizeMultiple].operands.push(OperandId, "'Param Align'"); - - InstructionDesc[OpGetKernelNDrangeSubGroupCount].operands.push(OperandId, "'ND Range'"); - InstructionDesc[OpGetKernelNDrangeSubGroupCount].operands.push(OperandId, "'Invoke'"); - InstructionDesc[OpGetKernelNDrangeSubGroupCount].operands.push(OperandId, "'Param'"); - InstructionDesc[OpGetKernelNDrangeSubGroupCount].operands.push(OperandId, "'Param Size'"); - InstructionDesc[OpGetKernelNDrangeSubGroupCount].operands.push(OperandId, "'Param Align'"); - - InstructionDesc[OpGetKernelNDrangeMaxSubGroupSize].operands.push(OperandId, "'ND Range'"); - InstructionDesc[OpGetKernelNDrangeMaxSubGroupSize].operands.push(OperandId, "'Invoke'"); - InstructionDesc[OpGetKernelNDrangeMaxSubGroupSize].operands.push(OperandId, "'Param'"); - InstructionDesc[OpGetKernelNDrangeMaxSubGroupSize].operands.push(OperandId, "'Param Size'"); - InstructionDesc[OpGetKernelNDrangeMaxSubGroupSize].operands.push(OperandId, "'Param Align'"); - - InstructionDesc[OpEnqueueKernel].operands.push(OperandId, "'Queue'"); - InstructionDesc[OpEnqueueKernel].operands.push(OperandId, "'Flags'"); - InstructionDesc[OpEnqueueKernel].operands.push(OperandId, "'ND Range'"); - InstructionDesc[OpEnqueueKernel].operands.push(OperandId, "'Num Events'"); - InstructionDesc[OpEnqueueKernel].operands.push(OperandId, "'Wait Events'"); - InstructionDesc[OpEnqueueKernel].operands.push(OperandId, "'Ret Event'"); - InstructionDesc[OpEnqueueKernel].operands.push(OperandId, "'Invoke'"); - InstructionDesc[OpEnqueueKernel].operands.push(OperandId, "'Param'"); - InstructionDesc[OpEnqueueKernel].operands.push(OperandId, "'Param Size'"); - InstructionDesc[OpEnqueueKernel].operands.push(OperandId, "'Param Align'"); - InstructionDesc[OpEnqueueKernel].operands.push(OperandVariableIds, "'Local Size'"); - - InstructionDesc[OpEnqueueMarker].operands.push(OperandId, "'Queue'"); - InstructionDesc[OpEnqueueMarker].operands.push(OperandId, "'Num Events'"); - InstructionDesc[OpEnqueueMarker].operands.push(OperandId, "'Wait Events'"); - InstructionDesc[OpEnqueueMarker].operands.push(OperandId, "'Ret Event'"); - - InstructionDesc[OpGroupNonUniformElect].operands.push(OperandScope, "'Execution'"); - - InstructionDesc[OpGroupNonUniformAll].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformAll].operands.push(OperandId, "X"); - - InstructionDesc[OpGroupNonUniformAny].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformAny].operands.push(OperandId, "X"); - - InstructionDesc[OpGroupNonUniformAllEqual].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformAllEqual].operands.push(OperandId, "X"); - - InstructionDesc[OpGroupNonUniformBroadcast].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformBroadcast].operands.push(OperandId, "X"); - InstructionDesc[OpGroupNonUniformBroadcast].operands.push(OperandId, "ID"); - - InstructionDesc[OpGroupNonUniformBroadcastFirst].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformBroadcastFirst].operands.push(OperandId, "X"); - - InstructionDesc[OpGroupNonUniformBallot].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformBallot].operands.push(OperandId, "X"); - - InstructionDesc[OpGroupNonUniformInverseBallot].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformInverseBallot].operands.push(OperandId, "X"); - - InstructionDesc[OpGroupNonUniformBallotBitExtract].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformBallotBitExtract].operands.push(OperandId, "X"); - InstructionDesc[OpGroupNonUniformBallotBitExtract].operands.push(OperandId, "Bit"); - - InstructionDesc[OpGroupNonUniformBallotBitCount].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformBallotBitCount].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupNonUniformBallotBitCount].operands.push(OperandId, "X"); - - InstructionDesc[OpGroupNonUniformBallotFindLSB].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformBallotFindLSB].operands.push(OperandId, "X"); - - InstructionDesc[OpGroupNonUniformBallotFindMSB].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformBallotFindMSB].operands.push(OperandId, "X"); - - InstructionDesc[OpGroupNonUniformShuffle].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformShuffle].operands.push(OperandId, "X"); - InstructionDesc[OpGroupNonUniformShuffle].operands.push(OperandId, "'Id'"); - - InstructionDesc[OpGroupNonUniformShuffleXor].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformShuffleXor].operands.push(OperandId, "X"); - InstructionDesc[OpGroupNonUniformShuffleXor].operands.push(OperandId, "Mask"); - - InstructionDesc[OpGroupNonUniformShuffleUp].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformShuffleUp].operands.push(OperandId, "X"); - InstructionDesc[OpGroupNonUniformShuffleUp].operands.push(OperandId, "Offset"); - - InstructionDesc[OpGroupNonUniformShuffleDown].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformShuffleDown].operands.push(OperandId, "X"); - InstructionDesc[OpGroupNonUniformShuffleDown].operands.push(OperandId, "Offset"); - - InstructionDesc[OpGroupNonUniformIAdd].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformIAdd].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupNonUniformIAdd].operands.push(OperandId, "X"); - InstructionDesc[OpGroupNonUniformIAdd].operands.push(OperandId, "'ClusterSize'", true); - - InstructionDesc[OpGroupNonUniformFAdd].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformFAdd].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupNonUniformFAdd].operands.push(OperandId, "X"); - InstructionDesc[OpGroupNonUniformFAdd].operands.push(OperandId, "'ClusterSize'", true); - - InstructionDesc[OpGroupNonUniformIMul].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformIMul].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupNonUniformIMul].operands.push(OperandId, "X"); - InstructionDesc[OpGroupNonUniformIMul].operands.push(OperandId, "'ClusterSize'", true); - - InstructionDesc[OpGroupNonUniformFMul].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformFMul].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupNonUniformFMul].operands.push(OperandId, "X"); - InstructionDesc[OpGroupNonUniformFMul].operands.push(OperandId, "'ClusterSize'", true); - - InstructionDesc[OpGroupNonUniformSMin].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformSMin].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupNonUniformSMin].operands.push(OperandId, "X"); - InstructionDesc[OpGroupNonUniformSMin].operands.push(OperandId, "'ClusterSize'", true); - - InstructionDesc[OpGroupNonUniformUMin].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformUMin].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupNonUniformUMin].operands.push(OperandId, "X"); - InstructionDesc[OpGroupNonUniformUMin].operands.push(OperandId, "'ClusterSize'", true); - - InstructionDesc[OpGroupNonUniformFMin].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformFMin].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupNonUniformFMin].operands.push(OperandId, "X"); - InstructionDesc[OpGroupNonUniformFMin].operands.push(OperandId, "'ClusterSize'", true); - - InstructionDesc[OpGroupNonUniformSMax].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformSMax].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupNonUniformSMax].operands.push(OperandId, "X"); - InstructionDesc[OpGroupNonUniformSMax].operands.push(OperandId, "'ClusterSize'", true); - - InstructionDesc[OpGroupNonUniformUMax].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformUMax].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupNonUniformUMax].operands.push(OperandId, "X"); - InstructionDesc[OpGroupNonUniformUMax].operands.push(OperandId, "'ClusterSize'", true); - - InstructionDesc[OpGroupNonUniformFMax].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformFMax].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupNonUniformFMax].operands.push(OperandId, "X"); - InstructionDesc[OpGroupNonUniformFMax].operands.push(OperandId, "'ClusterSize'", true); - - InstructionDesc[OpGroupNonUniformBitwiseAnd].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformBitwiseAnd].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupNonUniformBitwiseAnd].operands.push(OperandId, "X"); - InstructionDesc[OpGroupNonUniformBitwiseAnd].operands.push(OperandId, "'ClusterSize'", true); - - InstructionDesc[OpGroupNonUniformBitwiseOr].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformBitwiseOr].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupNonUniformBitwiseOr].operands.push(OperandId, "X"); - InstructionDesc[OpGroupNonUniformBitwiseOr].operands.push(OperandId, "'ClusterSize'", true); - - InstructionDesc[OpGroupNonUniformBitwiseXor].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformBitwiseXor].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupNonUniformBitwiseXor].operands.push(OperandId, "X"); - InstructionDesc[OpGroupNonUniformBitwiseXor].operands.push(OperandId, "'ClusterSize'", true); - - InstructionDesc[OpGroupNonUniformLogicalAnd].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformLogicalAnd].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupNonUniformLogicalAnd].operands.push(OperandId, "X"); - InstructionDesc[OpGroupNonUniformLogicalAnd].operands.push(OperandId, "'ClusterSize'", true); - - InstructionDesc[OpGroupNonUniformLogicalOr].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformLogicalOr].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupNonUniformLogicalOr].operands.push(OperandId, "X"); - InstructionDesc[OpGroupNonUniformLogicalOr].operands.push(OperandId, "'ClusterSize'", true); - - InstructionDesc[OpGroupNonUniformLogicalXor].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformLogicalXor].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupNonUniformLogicalXor].operands.push(OperandId, "X"); - InstructionDesc[OpGroupNonUniformLogicalXor].operands.push(OperandId, "'ClusterSize'", true); - - InstructionDesc[OpGroupNonUniformQuadBroadcast].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformQuadBroadcast].operands.push(OperandId, "X"); - InstructionDesc[OpGroupNonUniformQuadBroadcast].operands.push(OperandId, "'Id'"); - - InstructionDesc[OpGroupNonUniformQuadSwap].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformQuadSwap].operands.push(OperandId, "X"); - InstructionDesc[OpGroupNonUniformQuadSwap].operands.push(OperandLiteralNumber, "'Direction'"); - - InstructionDesc[OpSubgroupBallotKHR].operands.push(OperandId, "'Predicate'"); - - InstructionDesc[OpSubgroupFirstInvocationKHR].operands.push(OperandId, "'Value'"); - - InstructionDesc[OpSubgroupAnyKHR].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpSubgroupAnyKHR].operands.push(OperandId, "'Predicate'"); - - InstructionDesc[OpSubgroupAllKHR].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpSubgroupAllKHR].operands.push(OperandId, "'Predicate'"); - - InstructionDesc[OpSubgroupAllEqualKHR].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpSubgroupAllEqualKHR].operands.push(OperandId, "'Predicate'"); - - InstructionDesc[OpSubgroupReadInvocationKHR].operands.push(OperandId, "'Value'"); - InstructionDesc[OpSubgroupReadInvocationKHR].operands.push(OperandId, "'Index'"); - - InstructionDesc[OpModuleProcessed].operands.push(OperandLiteralString, "'process'"); - -#ifdef AMD_EXTENSIONS - InstructionDesc[OpGroupIAddNonUniformAMD].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupIAddNonUniformAMD].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupIAddNonUniformAMD].operands.push(OperandId, "'X'"); - - InstructionDesc[OpGroupFAddNonUniformAMD].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupFAddNonUniformAMD].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupFAddNonUniformAMD].operands.push(OperandId, "'X'"); - - InstructionDesc[OpGroupUMinNonUniformAMD].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupUMinNonUniformAMD].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupUMinNonUniformAMD].operands.push(OperandId, "'X'"); - - InstructionDesc[OpGroupSMinNonUniformAMD].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupSMinNonUniformAMD].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupSMinNonUniformAMD].operands.push(OperandId, "X"); - - InstructionDesc[OpGroupFMinNonUniformAMD].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupFMinNonUniformAMD].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupFMinNonUniformAMD].operands.push(OperandId, "X"); - - InstructionDesc[OpGroupUMaxNonUniformAMD].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupUMaxNonUniformAMD].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupUMaxNonUniformAMD].operands.push(OperandId, "X"); - - InstructionDesc[OpGroupSMaxNonUniformAMD].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupSMaxNonUniformAMD].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupSMaxNonUniformAMD].operands.push(OperandId, "X"); - - InstructionDesc[OpGroupFMaxNonUniformAMD].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupFMaxNonUniformAMD].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupFMaxNonUniformAMD].operands.push(OperandId, "X"); - - InstructionDesc[OpFragmentMaskFetchAMD].operands.push(OperandId, "'Image'"); - InstructionDesc[OpFragmentMaskFetchAMD].operands.push(OperandId, "'Coordinate'"); - - InstructionDesc[OpFragmentFetchAMD].operands.push(OperandId, "'Image'"); - InstructionDesc[OpFragmentFetchAMD].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpFragmentFetchAMD].operands.push(OperandId, "'Fragment Index'"); -#endif - -#ifdef NV_EXTENSIONS - InstructionDesc[OpGroupNonUniformPartitionNV].operands.push(OperandId, "X"); -#endif -} - -}; // end spv namespace diff --git a/External/glslang/SPIRV/doc.h b/External/glslang/SPIRV/doc.h deleted file mode 100644 index 7d0475d3..00000000 --- a/External/glslang/SPIRV/doc.h +++ /dev/null @@ -1,258 +0,0 @@ -// -// Copyright (C) 2014-2015 LunarG, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -// -// Parameterize the SPIR-V enumerants. -// - -#pragma once - -#include "spirv.hpp" - -#include - -namespace spv { - -// Fill in all the parameters -void Parameterize(); - -// Return the English names of all the enums. -const char* SourceString(int); -const char* AddressingString(int); -const char* MemoryString(int); -const char* ExecutionModelString(int); -const char* ExecutionModeString(int); -const char* StorageClassString(int); -const char* DecorationString(int); -const char* BuiltInString(int); -const char* DimensionString(int); -const char* SelectControlString(int); -const char* LoopControlString(int); -const char* FunctionControlString(int); -const char* SamplerAddressingModeString(int); -const char* SamplerFilterModeString(int); -const char* ImageFormatString(int); -const char* ImageChannelOrderString(int); -const char* ImageChannelTypeString(int); -const char* ImageChannelDataTypeString(int type); -const char* ImageOperandsString(int format); -const char* ImageOperands(int); -const char* FPFastMathString(int); -const char* FPRoundingModeString(int); -const char* LinkageTypeString(int); -const char* FuncParamAttrString(int); -const char* AccessQualifierString(int); -const char* MemorySemanticsString(int); -const char* MemoryAccessString(int); -const char* ExecutionScopeString(int); -const char* GroupOperationString(int); -const char* KernelEnqueueFlagsString(int); -const char* KernelProfilingInfoString(int); -const char* CapabilityString(int); -const char* OpcodeString(int); -const char* ScopeString(int mem); - -// For grouping opcodes into subsections -enum OpcodeClass { - OpClassMisc, - OpClassDebug, - OpClassAnnotate, - OpClassExtension, - OpClassMode, - OpClassType, - OpClassConstant, - OpClassMemory, - OpClassFunction, - OpClassImage, - OpClassConvert, - OpClassComposite, - OpClassArithmetic, - OpClassBit, - OpClassRelationalLogical, - OpClassDerivative, - OpClassFlowControl, - OpClassAtomic, - OpClassPrimitive, - OpClassBarrier, - OpClassGroup, - OpClassDeviceSideEnqueue, - OpClassPipe, - - OpClassCount, - OpClassMissing // all instructions start out as missing -}; - -// For parameterizing operands. -enum OperandClass { - OperandNone, - OperandId, - OperandVariableIds, - OperandOptionalLiteral, - OperandOptionalLiteralString, - OperandVariableLiterals, - OperandVariableIdLiteral, - OperandVariableLiteralId, - OperandLiteralNumber, - OperandLiteralString, - OperandSource, - OperandExecutionModel, - OperandAddressing, - OperandMemory, - OperandExecutionMode, - OperandStorage, - OperandDimensionality, - OperandSamplerAddressingMode, - OperandSamplerFilterMode, - OperandSamplerImageFormat, - OperandImageChannelOrder, - OperandImageChannelDataType, - OperandImageOperands, - OperandFPFastMath, - OperandFPRoundingMode, - OperandLinkageType, - OperandAccessQualifier, - OperandFuncParamAttr, - OperandDecoration, - OperandBuiltIn, - OperandSelect, - OperandLoop, - OperandFunction, - OperandMemorySemantics, - OperandMemoryAccess, - OperandScope, - OperandGroupOperation, - OperandKernelEnqueueFlags, - OperandKernelProfilingInfo, - OperandCapability, - - OperandOpcode, - - OperandCount -}; - -// Any specific enum can have a set of capabilities that allow it: -typedef std::vector EnumCaps; - -// Parameterize a set of operands with their OperandClass(es) and descriptions. -class OperandParameters { -public: - OperandParameters() { } - void push(OperandClass oc, const char* d, bool opt = false) - { - opClass.push_back(oc); - desc.push_back(d); - optional.push_back(opt); - } - void setOptional(); - OperandClass getClass(int op) const { return opClass[op]; } - const char* getDesc(int op) const { return desc[op]; } - bool isOptional(int op) const { return optional[op]; } - int getNum() const { return (int)opClass.size(); } - -protected: - std::vector opClass; - std::vector desc; - std::vector optional; -}; - -// Parameterize an enumerant -class EnumParameters { -public: - EnumParameters() : desc(0) { } - 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/External/glslang/SPIRV/hex_float.h b/External/glslang/SPIRV/hex_float.h deleted file mode 100644 index 905b21a4..00000000 --- a/External/glslang/SPIRV/hex_float.h +++ /dev/null @@ -1,1078 +0,0 @@ -// Copyright (c) 2015-2016 The Khronos Group Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef LIBSPIRV_UTIL_HEX_FLOAT_H_ -#define LIBSPIRV_UTIL_HEX_FLOAT_H_ - -#include -#include -#include -#include -#include -#include -#include - -#if defined(_MSC_VER) && _MSC_VER < 1800 -namespace std { -bool isnan(double f) -{ - return ::_isnan(f) != 0; -} -bool isinf(double f) -{ - return ::_finite(f) == 0; -} -} -#endif - -#include "bitutils.h" - -namespace spvutils { - -class Float16 { - public: - Float16(uint16_t v) : val(v) {} - Float16() {} - static bool isNan(const Float16& val) { - return ((val.val & 0x7C00) == 0x7C00) && ((val.val & 0x3FF) != 0); - } - // Returns true if the given value is any kind of infinity. - static bool isInfinity(const Float16& val) { - return ((val.val & 0x7C00) == 0x7C00) && ((val.val & 0x3FF) == 0); - } - Float16(const Float16& other) { val = other.val; } - uint16_t get_value() const { return val; } - - // Returns the maximum normal value. - static Float16 max() { return Float16(0x7bff); } - // Returns the lowest normal value. - static Float16 lowest() { return Float16(0xfbff); } - - private: - uint16_t val; -}; - -// To specialize this type, you must override uint_type to define -// an unsigned integer that can fit your floating point type. -// You must also add a isNan function that returns true if -// a value is Nan. -template -struct FloatProxyTraits { - typedef void uint_type; -}; - -template <> -struct FloatProxyTraits { - typedef uint32_t uint_type; - static bool isNan(float f) { return std::isnan(f); } - // Returns true if the given value is any kind of infinity. - static bool isInfinity(float f) { return std::isinf(f); } - // Returns the maximum normal value. - static float max() { return std::numeric_limits::max(); } - // Returns the lowest normal value. - static float lowest() { return std::numeric_limits::lowest(); } -}; - -template <> -struct FloatProxyTraits { - typedef uint64_t uint_type; - static bool isNan(double f) { return std::isnan(f); } - // Returns true if the given value is any kind of infinity. - static bool isInfinity(double f) { return std::isinf(f); } - // Returns the maximum normal value. - static double max() { return std::numeric_limits::max(); } - // Returns the lowest normal value. - static double lowest() { return std::numeric_limits::lowest(); } -}; - -template <> -struct FloatProxyTraits { - typedef uint16_t uint_type; - static bool isNan(Float16 f) { return Float16::isNan(f); } - // Returns true if the given value is any kind of infinity. - static bool isInfinity(Float16 f) { return Float16::isInfinity(f); } - // Returns the maximum normal value. - static Float16 max() { return Float16::max(); } - // Returns the lowest normal value. - static Float16 lowest() { return Float16::lowest(); } -}; - -// Since copying a floating point number (especially if it is NaN) -// does not guarantee that bits are preserved, this class lets us -// store the type and use it as a float when necessary. -template -class FloatProxy { - public: - typedef typename FloatProxyTraits::uint_type uint_type; - - // Since this is to act similar to the normal floats, - // do not initialize the data by default. - FloatProxy() {} - - // Intentionally non-explicit. This is a proxy type so - // implicit conversions allow us to use it more transparently. - FloatProxy(T val) { data_ = BitwiseCast(val); } - - // Intentionally non-explicit. This is a proxy type so - // implicit conversions allow us to use it more transparently. - FloatProxy(uint_type val) { data_ = val; } - - // This is helpful to have and is guaranteed not to stomp bits. - FloatProxy operator-() const { - return static_cast(data_ ^ - (uint_type(0x1) << (sizeof(T) * 8 - 1))); - } - - // Returns the data as a floating point value. - T getAsFloat() const { return BitwiseCast(data_); } - - // Returns the raw data. - uint_type data() const { return data_; } - - // Returns true if the value represents any type of NaN. - bool isNan() { return FloatProxyTraits::isNan(getAsFloat()); } - // Returns true if the value represents any type of infinity. - bool isInfinity() { return FloatProxyTraits::isInfinity(getAsFloat()); } - - // Returns the maximum normal value. - static FloatProxy max() { - return FloatProxy(FloatProxyTraits::max()); - } - // Returns the lowest normal value. - static FloatProxy lowest() { - return FloatProxy(FloatProxyTraits::lowest()); - } - - private: - uint_type data_; -}; - -template -bool operator==(const FloatProxy& first, const FloatProxy& second) { - return first.data() == second.data(); -} - -// Reads a FloatProxy value as a normal float from a stream. -template -std::istream& operator>>(std::istream& is, FloatProxy& value) { - T float_val; - is >> float_val; - value = FloatProxy(float_val); - return is; -} - -// This is an example traits. It is not meant to be used in practice, but will -// be the default for any non-specialized type. -template -struct HexFloatTraits { - // Integer type that can store this hex-float. - typedef void uint_type; - // Signed integer type that can store this hex-float. - typedef void int_type; - // The numerical type that this HexFloat represents. - typedef void underlying_type; - // The type needed to construct the underlying type. - typedef void native_type; - // The number of bits that are actually relevant in the uint_type. - // This allows us to deal with, for example, 24-bit values in a 32-bit - // integer. - static const uint32_t num_used_bits = 0; - // Number of bits that represent the exponent. - static const uint32_t num_exponent_bits = 0; - // Number of bits that represent the fractional part. - static const uint32_t num_fraction_bits = 0; - // The bias of the exponent. (How much we need to subtract from the stored - // value to get the correct value.) - static const uint32_t exponent_bias = 0; -}; - -// Traits for IEEE float. -// 1 sign bit, 8 exponent bits, 23 fractional bits. -template <> -struct HexFloatTraits> { - typedef uint32_t uint_type; - typedef int32_t int_type; - typedef FloatProxy underlying_type; - typedef float native_type; - static const uint_type num_used_bits = 32; - static const uint_type num_exponent_bits = 8; - static const uint_type num_fraction_bits = 23; - static const uint_type exponent_bias = 127; -}; - -// Traits for IEEE double. -// 1 sign bit, 11 exponent bits, 52 fractional bits. -template <> -struct HexFloatTraits> { - typedef uint64_t uint_type; - typedef int64_t int_type; - typedef FloatProxy underlying_type; - typedef double native_type; - static const uint_type num_used_bits = 64; - static const uint_type num_exponent_bits = 11; - static const uint_type num_fraction_bits = 52; - static const uint_type exponent_bias = 1023; -}; - -// Traits for IEEE half. -// 1 sign bit, 5 exponent bits, 10 fractional bits. -template <> -struct HexFloatTraits> { - typedef uint16_t uint_type; - typedef int16_t int_type; - typedef uint16_t underlying_type; - typedef uint16_t native_type; - static const uint_type num_used_bits = 16; - static const uint_type num_exponent_bits = 5; - static const uint_type num_fraction_bits = 10; - static const uint_type exponent_bias = 15; -}; - -enum round_direction { - kRoundToZero, - kRoundToNearestEven, - kRoundToPositiveInfinity, - kRoundToNegativeInfinity -}; - -// Template class that houses a floating pointer number. -// It exposes a number of constants based on the provided traits to -// assist in interpreting the bits of the value. -template > -class HexFloat { - public: - typedef typename Traits::uint_type uint_type; - typedef typename Traits::int_type int_type; - typedef typename Traits::underlying_type underlying_type; - typedef typename Traits::native_type native_type; - - explicit HexFloat(T f) : value_(f) {} - - T value() const { return value_; } - void set_value(T f) { value_ = f; } - - // These are all written like this because it is convenient to have - // compile-time constants for all of these values. - - // Pass-through values to save typing. - static const uint32_t num_used_bits = Traits::num_used_bits; - static const uint32_t exponent_bias = Traits::exponent_bias; - static const uint32_t num_exponent_bits = Traits::num_exponent_bits; - static const uint32_t num_fraction_bits = Traits::num_fraction_bits; - - // Number of bits to shift left to set the highest relevant bit. - static const uint32_t top_bit_left_shift = num_used_bits - 1; - // How many nibbles (hex characters) the fractional part takes up. - static const uint32_t fraction_nibbles = (num_fraction_bits + 3) / 4; - // If the fractional part does not fit evenly into a hex character (4-bits) - // then we have to left-shift to get rid of leading 0s. This is the amount - // we have to shift (might be 0). - static const uint32_t num_overflow_bits = - fraction_nibbles * 4 - num_fraction_bits; - - // The representation of the fraction, not the actual bits. This - // includes the leading bit that is usually implicit. - static const uint_type fraction_represent_mask = - spvutils::SetBits::get; - - // The topmost bit in the nibble-aligned fraction. - static const uint_type fraction_top_bit = - uint_type(1) << (num_fraction_bits + num_overflow_bits - 1); - - // The least significant bit in the exponent, which is also the bit - // immediately to the left of the significand. - static const uint_type first_exponent_bit = uint_type(1) - << (num_fraction_bits); - - // The mask for the encoded fraction. It does not include the - // implicit bit. - static const uint_type fraction_encode_mask = - spvutils::SetBits::get; - - // The bit that is used as a sign. - static const uint_type sign_mask = uint_type(1) << top_bit_left_shift; - - // The bits that represent the exponent. - static const uint_type exponent_mask = - spvutils::SetBits::get; - - // How far left the exponent is shifted. - static const uint32_t exponent_left_shift = num_fraction_bits; - - // How far from the right edge the fraction is shifted. - static const uint32_t fraction_right_shift = - static_cast(sizeof(uint_type) * 8) - num_fraction_bits; - - // The maximum representable unbiased exponent. - static const int_type max_exponent = - (exponent_mask >> num_fraction_bits) - exponent_bias; - // The minimum representable exponent for normalized numbers. - static const int_type min_exponent = -static_cast(exponent_bias); - - // Returns the bits associated with the value. - uint_type getBits() const { return spvutils::BitwiseCast(value_); } - - // Returns the bits associated with the value, without the leading sign bit. - uint_type getUnsignedBits() const { - return static_cast(spvutils::BitwiseCast(value_) & - ~sign_mask); - } - - // Returns the bits associated with the exponent, shifted to start at the - // lsb of the type. - const uint_type getExponentBits() const { - return static_cast((getBits() & exponent_mask) >> - num_fraction_bits); - } - - // Returns the exponent in unbiased form. This is the exponent in the - // human-friendly form. - const int_type getUnbiasedExponent() const { - return static_cast(getExponentBits() - exponent_bias); - } - - // Returns just the significand bits from the value. - const uint_type getSignificandBits() const { - return getBits() & fraction_encode_mask; - } - - // If the number was normalized, returns the unbiased exponent. - // If the number was denormal, normalize the exponent first. - const int_type getUnbiasedNormalizedExponent() const { - if ((getBits() & ~sign_mask) == 0) { // special case if everything is 0 - return 0; - } - int_type exp = getUnbiasedExponent(); - if (exp == min_exponent) { // We are in denorm land. - uint_type significand_bits = getSignificandBits(); - while ((significand_bits & (first_exponent_bit >> 1)) == 0) { - significand_bits = static_cast(significand_bits << 1); - exp = static_cast(exp - 1); - } - significand_bits &= fraction_encode_mask; - } - return exp; - } - - // Returns the signficand after it has been normalized. - const uint_type getNormalizedSignificand() const { - int_type unbiased_exponent = getUnbiasedNormalizedExponent(); - uint_type significand = getSignificandBits(); - for (int_type i = unbiased_exponent; i <= min_exponent; ++i) { - significand = static_cast(significand << 1); - } - significand &= fraction_encode_mask; - return significand; - } - - // Returns true if this number represents a negative value. - bool isNegative() const { return (getBits() & sign_mask) != 0; } - - // Sets this HexFloat from the individual components. - // Note this assumes EVERY significand is normalized, and has an implicit - // leading one. This means that the only way that this method will set 0, - // is if you set a number so denormalized that it underflows. - // Do not use this method with raw bits extracted from a subnormal number, - // since subnormals do not have an implicit leading 1 in the significand. - // The significand is also expected to be in the - // lowest-most num_fraction_bits of the uint_type. - // The exponent is expected to be unbiased, meaning an exponent of - // 0 actually means 0. - // If underflow_round_up is set, then on underflow, if a number is non-0 - // and would underflow, we round up to the smallest denorm. - void setFromSignUnbiasedExponentAndNormalizedSignificand( - bool negative, int_type exponent, uint_type significand, - bool round_denorm_up) { - bool significand_is_zero = significand == 0; - - if (exponent <= min_exponent) { - // If this was denormalized, then we have to shift the bit on, meaning - // the significand is not zero. - significand_is_zero = false; - significand |= first_exponent_bit; - significand = static_cast(significand >> 1); - } - - while (exponent < min_exponent) { - significand = static_cast(significand >> 1); - ++exponent; - } - - if (exponent == min_exponent) { - if (significand == 0 && !significand_is_zero && round_denorm_up) { - significand = static_cast(0x1); - } - } - - uint_type new_value = 0; - if (negative) { - new_value = static_cast(new_value | sign_mask); - } - exponent = static_cast(exponent + exponent_bias); - assert(exponent >= 0); - - // put it all together - exponent = static_cast((exponent << exponent_left_shift) & - exponent_mask); - significand = static_cast(significand & fraction_encode_mask); - new_value = static_cast(new_value | (exponent | significand)); - value_ = BitwiseCast(new_value); - } - - // Increments the significand of this number by the given amount. - // If this would spill the significand into the implicit bit, - // carry is set to true and the significand is shifted to fit into - // the correct location, otherwise carry is set to false. - // All significands and to_increment are assumed to be within the bounds - // for a valid significand. - static uint_type incrementSignificand(uint_type significand, - uint_type to_increment, bool* carry) { - significand = static_cast(significand + to_increment); - *carry = false; - if (significand & first_exponent_bit) { - *carry = true; - // The implicit 1-bit will have carried, so we should zero-out the - // top bit and shift back. - significand = static_cast(significand & ~first_exponent_bit); - significand = static_cast(significand >> 1); - } - return significand; - } - - // These exist because MSVC throws warnings on negative right-shifts - // even if they are not going to be executed. Eg: - // constant_number < 0? 0: constant_number - // These convert the negative left-shifts into right shifts. - - template - uint_type negatable_left_shift(int_type N, uint_type val) - { - if(N >= 0) - return val << N; - - return val >> -N; - } - - template - uint_type negatable_right_shift(int_type N, uint_type val) - { - if(N >= 0) - return val >> N; - - return val << -N; - } - - // Returns the significand, rounded to fit in a significand in - // other_T. This is shifted so that the most significant - // bit of the rounded number lines up with the most significant bit - // of the returned significand. - template - typename other_T::uint_type getRoundedNormalizedSignificand( - round_direction dir, bool* carry_bit) { - typedef typename other_T::uint_type other_uint_type; - static const int_type num_throwaway_bits = - static_cast(num_fraction_bits) - - static_cast(other_T::num_fraction_bits); - - static const uint_type last_significant_bit = - (num_throwaway_bits < 0) - ? 0 - : negatable_left_shift(num_throwaway_bits, 1u); - static const uint_type first_rounded_bit = - (num_throwaway_bits < 1) - ? 0 - : negatable_left_shift(num_throwaway_bits - 1, 1u); - - static const uint_type throwaway_mask_bits = - num_throwaway_bits > 0 ? num_throwaway_bits : 0; - static const uint_type throwaway_mask = - spvutils::SetBits::get; - - *carry_bit = false; - other_uint_type out_val = 0; - uint_type significand = getNormalizedSignificand(); - // If we are up-casting, then we just have to shift to the right location. - if (num_throwaway_bits <= 0) { - out_val = static_cast(significand); - uint_type shift_amount = static_cast(-num_throwaway_bits); - out_val = static_cast(out_val << shift_amount); - return out_val; - } - - // If every non-representable bit is 0, then we don't have any casting to - // do. - if ((significand & throwaway_mask) == 0) { - return static_cast( - negatable_right_shift(num_throwaway_bits, significand)); - } - - bool round_away_from_zero = false; - // We actually have to narrow the significand here, so we have to follow the - // rounding rules. - switch (dir) { - case kRoundToZero: - break; - case kRoundToPositiveInfinity: - round_away_from_zero = !isNegative(); - break; - case kRoundToNegativeInfinity: - round_away_from_zero = isNegative(); - break; - case kRoundToNearestEven: - // Have to round down, round bit is 0 - if ((first_rounded_bit & significand) == 0) { - break; - } - if (((significand & throwaway_mask) & ~first_rounded_bit) != 0) { - // If any subsequent bit of the rounded portion is non-0 then we round - // up. - round_away_from_zero = true; - break; - } - // We are exactly half-way between 2 numbers, pick even. - if ((significand & last_significant_bit) != 0) { - // 1 for our last bit, round up. - round_away_from_zero = true; - break; - } - break; - } - - if (round_away_from_zero) { - return static_cast( - negatable_right_shift(num_throwaway_bits, incrementSignificand( - significand, last_significant_bit, carry_bit))); - } else { - return static_cast( - negatable_right_shift(num_throwaway_bits, significand)); - } - } - - // Casts this value to another HexFloat. If the cast is widening, - // then round_dir is ignored. If the cast is narrowing, then - // the result is rounded in the direction specified. - // This number will retain Nan and Inf values. - // It will also saturate to Inf if the number overflows, and - // underflow to (0 or min depending on rounding) if the number underflows. - template - void castTo(other_T& other, round_direction round_dir) { - other = other_T(static_cast(0)); - bool negate = isNegative(); - if (getUnsignedBits() == 0) { - if (negate) { - other.set_value(-other.value()); - } - return; - } - uint_type significand = getSignificandBits(); - bool carried = false; - typename other_T::uint_type rounded_significand = - getRoundedNormalizedSignificand(round_dir, &carried); - - int_type exponent = getUnbiasedExponent(); - if (exponent == min_exponent) { - // If we are denormal, normalize the exponent, so that we can encode - // easily. - exponent = static_cast(exponent + 1); - for (uint_type check_bit = first_exponent_bit >> 1; check_bit != 0; - check_bit = static_cast(check_bit >> 1)) { - exponent = static_cast(exponent - 1); - if (check_bit & significand) break; - } - } - - bool is_nan = - (getBits() & exponent_mask) == exponent_mask && significand != 0; - bool is_inf = - !is_nan && - ((exponent + carried) > static_cast(other_T::exponent_bias) || - (significand == 0 && (getBits() & exponent_mask) == exponent_mask)); - - // If we are Nan or Inf we should pass that through. - if (is_inf) { - other.set_value(BitwiseCast( - static_cast( - (negate ? other_T::sign_mask : 0) | other_T::exponent_mask))); - return; - } - if (is_nan) { - typename other_T::uint_type shifted_significand; - shifted_significand = static_cast( - negatable_left_shift( - static_cast(other_T::num_fraction_bits) - - static_cast(num_fraction_bits), significand)); - - // We are some sort of Nan. We try to keep the bit-pattern of the Nan - // as close as possible. If we had to shift off bits so we are 0, then we - // just set the last bit. - other.set_value(BitwiseCast( - static_cast( - (negate ? other_T::sign_mask : 0) | other_T::exponent_mask | - (shifted_significand == 0 ? 0x1 : shifted_significand)))); - return; - } - - bool round_underflow_up = - isNegative() ? round_dir == kRoundToNegativeInfinity - : round_dir == kRoundToPositiveInfinity; - typedef typename other_T::int_type other_int_type; - // setFromSignUnbiasedExponentAndNormalizedSignificand will - // zero out any underflowing value (but retain the sign). - other.setFromSignUnbiasedExponentAndNormalizedSignificand( - negate, static_cast(exponent), rounded_significand, - round_underflow_up); - return; - } - - private: - T value_; - - static_assert(num_used_bits == - Traits::num_exponent_bits + Traits::num_fraction_bits + 1, - "The number of bits do not fit"); - static_assert(sizeof(T) == sizeof(uint_type), "The type sizes do not match"); -}; - -// Returns 4 bits represented by the hex character. -inline uint8_t get_nibble_from_character(int character) { - const char* dec = "0123456789"; - const char* lower = "abcdef"; - const char* upper = "ABCDEF"; - const char* p = nullptr; - if ((p = strchr(dec, character))) { - return static_cast(p - dec); - } else if ((p = strchr(lower, character))) { - return static_cast(p - lower + 0xa); - } else if ((p = strchr(upper, character))) { - return static_cast(p - upper + 0xa); - } - - assert(false && "This was called with a non-hex character"); - return 0; -} - -// Outputs the given HexFloat to the stream. -template -std::ostream& operator<<(std::ostream& os, const HexFloat& value) { - typedef HexFloat HF; - typedef typename HF::uint_type uint_type; - typedef typename HF::int_type int_type; - - static_assert(HF::num_used_bits != 0, - "num_used_bits must be non-zero for a valid float"); - static_assert(HF::num_exponent_bits != 0, - "num_exponent_bits must be non-zero for a valid float"); - static_assert(HF::num_fraction_bits != 0, - "num_fractin_bits must be non-zero for a valid float"); - - const uint_type bits = spvutils::BitwiseCast(value.value()); - const char* const sign = (bits & HF::sign_mask) ? "-" : ""; - const uint_type exponent = static_cast( - (bits & HF::exponent_mask) >> HF::num_fraction_bits); - - uint_type fraction = static_cast((bits & HF::fraction_encode_mask) - << HF::num_overflow_bits); - - const bool is_zero = exponent == 0 && fraction == 0; - const bool is_denorm = exponent == 0 && !is_zero; - - // exponent contains the biased exponent we have to convert it back into - // the normal range. - int_type int_exponent = static_cast(exponent - HF::exponent_bias); - // If the number is all zeros, then we actually have to NOT shift the - // exponent. - int_exponent = is_zero ? 0 : int_exponent; - - // If we are denorm, then start shifting, and decreasing the exponent until - // our leading bit is 1. - - if (is_denorm) { - while ((fraction & HF::fraction_top_bit) == 0) { - fraction = static_cast(fraction << 1); - int_exponent = static_cast(int_exponent - 1); - } - // Since this is denormalized, we have to consume the leading 1 since it - // will end up being implicit. - fraction = static_cast(fraction << 1); // eat the leading 1 - fraction &= HF::fraction_represent_mask; - } - - uint_type fraction_nibbles = HF::fraction_nibbles; - // We do not have to display any trailing 0s, since this represents the - // fractional part. - while (fraction_nibbles > 0 && (fraction & 0xF) == 0) { - // Shift off any trailing values; - fraction = static_cast(fraction >> 4); - --fraction_nibbles; - } - - const auto saved_flags = os.flags(); - const auto saved_fill = os.fill(); - - os << sign << "0x" << (is_zero ? '0' : '1'); - if (fraction_nibbles) { - // Make sure to keep the leading 0s in place, since this is the fractional - // part. - os << "." << std::setw(static_cast(fraction_nibbles)) - << std::setfill('0') << std::hex << fraction; - } - os << "p" << std::dec << (int_exponent >= 0 ? "+" : "") << int_exponent; - - os.flags(saved_flags); - os.fill(saved_fill); - - return os; -} - -// Returns true if negate_value is true and the next character on the -// input stream is a plus or minus sign. In that case we also set the fail bit -// on the stream and set the value to the zero value for its type. -template -inline bool RejectParseDueToLeadingSign(std::istream& is, bool negate_value, - HexFloat& value) { - if (negate_value) { - auto next_char = is.peek(); - if (next_char == '-' || next_char == '+') { - // Fail the parse. Emulate standard behaviour by setting the value to - // the zero value, and set the fail bit on the stream. - value = HexFloat(typename HexFloat::uint_type(0)); - is.setstate(std::ios_base::failbit); - return true; - } - } - return false; -} - -// Parses a floating point number from the given stream and stores it into the -// value parameter. -// If negate_value is true then the number may not have a leading minus or -// plus, and if it successfully parses, then the number is negated before -// being stored into the value parameter. -// If the value cannot be correctly parsed or overflows the target floating -// point type, then set the fail bit on the stream. -// TODO(dneto): Promise C++11 standard behavior in how the value is set in -// the error case, but only after all target platforms implement it correctly. -// In particular, the Microsoft C++ runtime appears to be out of spec. -template -inline std::istream& ParseNormalFloat(std::istream& is, bool negate_value, - HexFloat& value) { - if (RejectParseDueToLeadingSign(is, negate_value, value)) { - return is; - } - T val; - is >> val; - if (negate_value) { - val = -val; - } - value.set_value(val); - // In the failure case, map -0.0 to 0.0. - if (is.fail() && value.getUnsignedBits() == 0u) { - value = HexFloat(typename HexFloat::uint_type(0)); - } - if (val.isInfinity()) { - // Fail the parse. Emulate standard behaviour by setting the value to - // the closest normal value, and set the fail bit on the stream. - value.set_value((value.isNegative() | negate_value) ? T::lowest() - : T::max()); - is.setstate(std::ios_base::failbit); - } - return is; -} - -// Specialization of ParseNormalFloat for FloatProxy values. -// This will parse the float as it were a 32-bit floating point number, -// and then round it down to fit into a Float16 value. -// The number is rounded towards zero. -// If negate_value is true then the number may not have a leading minus or -// plus, and if it successfully parses, then the number is negated before -// being stored into the value parameter. -// If the value cannot be correctly parsed or overflows the target floating -// point type, then set the fail bit on the stream. -// TODO(dneto): Promise C++11 standard behavior in how the value is set in -// the error case, but only after all target platforms implement it correctly. -// In particular, the Microsoft C++ runtime appears to be out of spec. -template <> -inline std::istream& -ParseNormalFloat, HexFloatTraits>>( - std::istream& is, bool negate_value, - HexFloat, HexFloatTraits>>& value) { - // First parse as a 32-bit float. - HexFloat> float_val(0.0f); - ParseNormalFloat(is, negate_value, float_val); - - // Then convert to 16-bit float, saturating at infinities, and - // rounding toward zero. - float_val.castTo(value, kRoundToZero); - - // Overflow on 16-bit behaves the same as for 32- and 64-bit: set the - // fail bit and set the lowest or highest value. - if (Float16::isInfinity(value.value().getAsFloat())) { - value.set_value(value.isNegative() ? Float16::lowest() : Float16::max()); - is.setstate(std::ios_base::failbit); - } - return is; -} - -// Reads a HexFloat from the given stream. -// If the float is not encoded as a hex-float then it will be parsed -// as a regular float. -// This may fail if your stream does not support at least one unget. -// Nan values can be encoded with "0x1.p+exponent_bias". -// This would normally overflow a float and round to -// infinity but this special pattern is the exact representation for a NaN, -// and therefore is actually encoded as the correct NaN. To encode inf, -// either 0x0p+exponent_bias can be specified or any exponent greater than -// exponent_bias. -// Examples using IEEE 32-bit float encoding. -// 0x1.0p+128 (+inf) -// -0x1.0p-128 (-inf) -// -// 0x1.1p+128 (+Nan) -// -0x1.1p+128 (-Nan) -// -// 0x1p+129 (+inf) -// -0x1p+129 (-inf) -template -std::istream& operator>>(std::istream& is, HexFloat& value) { - using HF = HexFloat; - using uint_type = typename HF::uint_type; - using int_type = typename HF::int_type; - - value.set_value(static_cast(0.f)); - - if (is.flags() & std::ios::skipws) { - // If the user wants to skip whitespace , then we should obey that. - while (std::isspace(is.peek())) { - is.get(); - } - } - - auto next_char = is.peek(); - bool negate_value = false; - - if (next_char != '-' && next_char != '0') { - return ParseNormalFloat(is, negate_value, value); - } - - if (next_char == '-') { - negate_value = true; - is.get(); - next_char = is.peek(); - } - - if (next_char == '0') { - is.get(); // We may have to unget this. - auto maybe_hex_start = is.peek(); - if (maybe_hex_start != 'x' && maybe_hex_start != 'X') { - is.unget(); - return ParseNormalFloat(is, negate_value, value); - } else { - is.get(); // Throw away the 'x'; - } - } else { - return ParseNormalFloat(is, negate_value, value); - } - - // This "looks" like a hex-float so treat it as one. - bool seen_p = false; - bool seen_dot = false; - uint_type fraction_index = 0; - - uint_type fraction = 0; - int_type exponent = HF::exponent_bias; - - // Strip off leading zeros so we don't have to special-case them later. - while ((next_char = is.peek()) == '0') { - is.get(); - } - - bool is_denorm = - true; // Assume denorm "representation" until we hear otherwise. - // NB: This does not mean the value is actually denorm, - // it just means that it was written 0. - bool bits_written = false; // Stays false until we write a bit. - while (!seen_p && !seen_dot) { - // Handle characters that are left of the fractional part. - if (next_char == '.') { - seen_dot = true; - } else if (next_char == 'p') { - seen_p = true; - } else if (::isxdigit(next_char)) { - // We know this is not denormalized since we have stripped all leading - // zeroes and we are not a ".". - is_denorm = false; - int number = get_nibble_from_character(next_char); - for (int i = 0; i < 4; ++i, number <<= 1) { - uint_type write_bit = (number & 0x8) ? 0x1 : 0x0; - if (bits_written) { - // If we are here the bits represented belong in the fractional - // part of the float, and we have to adjust the exponent accordingly. - fraction = static_cast( - fraction | - static_cast( - write_bit << (HF::top_bit_left_shift - fraction_index++))); - exponent = static_cast(exponent + 1); - } - bits_written |= write_bit != 0; - } - } else { - // We have not found our exponent yet, so we have to fail. - is.setstate(std::ios::failbit); - return is; - } - is.get(); - next_char = is.peek(); - } - bits_written = false; - while (seen_dot && !seen_p) { - // Handle only fractional parts now. - if (next_char == 'p') { - seen_p = true; - } else if (::isxdigit(next_char)) { - int number = get_nibble_from_character(next_char); - for (int i = 0; i < 4; ++i, number <<= 1) { - uint_type write_bit = (number & 0x8) ? 0x01 : 0x00; - bits_written |= write_bit != 0; - if (is_denorm && !bits_written) { - // Handle modifying the exponent here this way we can handle - // an arbitrary number of hex values without overflowing our - // integer. - exponent = static_cast(exponent - 1); - } else { - fraction = static_cast( - fraction | - static_cast( - write_bit << (HF::top_bit_left_shift - fraction_index++))); - } - } - } else { - // We still have not found our 'p' exponent yet, so this is not a valid - // hex-float. - is.setstate(std::ios::failbit); - return is; - } - is.get(); - next_char = is.peek(); - } - - bool seen_sign = false; - int8_t exponent_sign = 1; - int_type written_exponent = 0; - while (true) { - if ((next_char == '-' || next_char == '+')) { - if (seen_sign) { - is.setstate(std::ios::failbit); - return is; - } - seen_sign = true; - exponent_sign = (next_char == '-') ? -1 : 1; - } else if (::isdigit(next_char)) { - // Hex-floats express their exponent as decimal. - written_exponent = static_cast(written_exponent * 10); - written_exponent = - static_cast(written_exponent + (next_char - '0')); - } else { - break; - } - is.get(); - next_char = is.peek(); - } - - written_exponent = static_cast(written_exponent * exponent_sign); - exponent = static_cast(exponent + written_exponent); - - bool is_zero = is_denorm && (fraction == 0); - if (is_denorm && !is_zero) { - fraction = static_cast(fraction << 1); - exponent = static_cast(exponent - 1); - } else if (is_zero) { - exponent = 0; - } - - if (exponent <= 0 && !is_zero) { - fraction = static_cast(fraction >> 1); - fraction |= static_cast(1) << HF::top_bit_left_shift; - } - - fraction = (fraction >> HF::fraction_right_shift) & HF::fraction_encode_mask; - - const int_type max_exponent = - SetBits::get; - - // Handle actual denorm numbers - while (exponent < 0 && !is_zero) { - fraction = static_cast(fraction >> 1); - exponent = static_cast(exponent + 1); - - fraction &= HF::fraction_encode_mask; - if (fraction == 0) { - // We have underflowed our fraction. We should clamp to zero. - is_zero = true; - exponent = 0; - } - } - - // We have overflowed so we should be inf/-inf. - if (exponent > max_exponent) { - exponent = max_exponent; - fraction = 0; - } - - uint_type output_bits = static_cast( - static_cast(negate_value ? 1 : 0) << HF::top_bit_left_shift); - output_bits |= fraction; - - uint_type shifted_exponent = static_cast( - static_cast(exponent << HF::exponent_left_shift) & - HF::exponent_mask); - output_bits |= shifted_exponent; - - T output_float = spvutils::BitwiseCast(output_bits); - value.set_value(output_float); - - return is; -} - -// Writes a FloatProxy value to a stream. -// Zero and normal numbers are printed in the usual notation, but with -// enough digits to fully reproduce the value. Other values (subnormal, -// NaN, and infinity) are printed as a hex float. -template -std::ostream& operator<<(std::ostream& os, const FloatProxy& value) { - auto float_val = value.getAsFloat(); - switch (std::fpclassify(float_val)) { - case FP_ZERO: - case FP_NORMAL: { - auto saved_precision = os.precision(); - os.precision(std::numeric_limits::digits10); - os << float_val; - os.precision(saved_precision); - } break; - default: - os << HexFloat>(value); - break; - } - return os; -} - -template <> -inline std::ostream& operator<<(std::ostream& os, - const FloatProxy& value) { - os << HexFloat>(value); - return os; -} -} - -#endif // LIBSPIRV_UTIL_HEX_FLOAT_H_ diff --git a/External/glslang/SPIRV/spirv.hpp b/External/glslang/SPIRV/spirv.hpp deleted file mode 100644 index e21762db..00000000 --- a/External/glslang/SPIRV/spirv.hpp +++ /dev/null @@ -1,1099 +0,0 @@ -// Copyright (c) 2014-2018 The Khronos Group Inc. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and/or associated documentation files (the "Materials"), -// to deal in the Materials without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Materials, and to permit persons to whom the -// Materials are furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Materials. -// -// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS -// STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND -// HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ -// -// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS -// IN THE MATERIALS. - -// This header is automatically generated by the same tool that creates -// the Binary Section of the SPIR-V specification. - -// Enumeration tokens for SPIR-V, in various styles: -// C, C++, C++11, JSON, Lua, Python -// -// - C will have tokens with a "Spv" prefix, e.g.: SpvSourceLanguageGLSL -// - C++ will have tokens in the "spv" name space, e.g.: spv::SourceLanguageGLSL -// - C++11 will use enum classes in the spv namespace, e.g.: spv::SourceLanguage::GLSL -// - Lua will use tables, e.g.: spv.SourceLanguage.GLSL -// - Python will use dictionaries, e.g.: spv['SourceLanguage']['GLSL'] -// -// Some tokens act like mask values, which can be OR'd together, -// while others are mutually exclusive. The mask-like ones have -// "Mask" in their name, and a parallel enum that has the shift -// amount (1 << x) for each corresponding enumerant. - -#ifndef spirv_HPP -#define spirv_HPP - -namespace spv { - -typedef unsigned int Id; - -#define SPV_VERSION 0x10300 -#define SPV_REVISION 1 - -static const unsigned int MagicNumber = 0x07230203; -static const unsigned int Version = 0x00010300; -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, - ExecutionModelMax = 0x7fffffff, -}; - -enum AddressingModel { - AddressingModelLogical = 0, - AddressingModelPhysical32 = 1, - AddressingModelPhysical64 = 2, - AddressingModelMax = 0x7fffffff, -}; - -enum MemoryModel { - MemoryModelSimple = 0, - MemoryModelGLSL450 = 1, - MemoryModelOpenCL = 2, - MemoryModelMax = 0x7fffffff, -}; - -enum ExecutionMode { - ExecutionModeInvocations = 0, - ExecutionModeSpacingEqual = 1, - ExecutionModeSpacingFractionalEven = 2, - ExecutionModeSpacingFractionalOdd = 3, - ExecutionModeVertexOrderCw = 4, - ExecutionModeVertexOrderCcw = 5, - ExecutionModePixelCenterInteger = 6, - ExecutionModeOriginUpperLeft = 7, - ExecutionModeOriginLowerLeft = 8, - ExecutionModeEarlyFragmentTests = 9, - ExecutionModePointMode = 10, - ExecutionModeXfb = 11, - ExecutionModeDepthReplacing = 12, - ExecutionModeDepthGreater = 14, - ExecutionModeDepthLess = 15, - ExecutionModeDepthUnchanged = 16, - ExecutionModeLocalSize = 17, - ExecutionModeLocalSizeHint = 18, - ExecutionModeInputPoints = 19, - ExecutionModeInputLines = 20, - ExecutionModeInputLinesAdjacency = 21, - ExecutionModeTriangles = 22, - ExecutionModeInputTrianglesAdjacency = 23, - ExecutionModeQuads = 24, - ExecutionModeIsolines = 25, - ExecutionModeOutputVertices = 26, - ExecutionModeOutputPoints = 27, - ExecutionModeOutputLineStrip = 28, - ExecutionModeOutputTriangleStrip = 29, - ExecutionModeVecTypeHint = 30, - ExecutionModeContractionOff = 31, - ExecutionModeInitializer = 33, - ExecutionModeFinalizer = 34, - ExecutionModeSubgroupSize = 35, - ExecutionModeSubgroupsPerWorkgroup = 36, - ExecutionModeSubgroupsPerWorkgroupId = 37, - ExecutionModeLocalSizeId = 38, - ExecutionModeLocalSizeHintId = 39, - ExecutionModePostDepthCoverage = 4446, - ExecutionModeStencilRefReplacingEXT = 5027, - ExecutionModeMax = 0x7fffffff, -}; - -enum StorageClass { - StorageClassUniformConstant = 0, - StorageClassInput = 1, - StorageClassUniform = 2, - StorageClassOutput = 3, - StorageClassWorkgroup = 4, - StorageClassCrossWorkgroup = 5, - StorageClassPrivate = 6, - StorageClassFunction = 7, - StorageClassGeneric = 8, - StorageClassPushConstant = 9, - StorageClassAtomicCounter = 10, - StorageClassImage = 11, - StorageClassStorageBuffer = 12, - StorageClassMax = 0x7fffffff, -}; - -enum Dim { - Dim1D = 0, - Dim2D = 1, - Dim3D = 2, - DimCube = 3, - DimRect = 4, - DimBuffer = 5, - DimSubpassData = 6, - DimMax = 0x7fffffff, -}; - -enum SamplerAddressingMode { - SamplerAddressingModeNone = 0, - SamplerAddressingModeClampToEdge = 1, - SamplerAddressingModeClamp = 2, - SamplerAddressingModeRepeat = 3, - SamplerAddressingModeRepeatMirrored = 4, - SamplerAddressingModeMax = 0x7fffffff, -}; - -enum SamplerFilterMode { - SamplerFilterModeNearest = 0, - SamplerFilterModeLinear = 1, - SamplerFilterModeMax = 0x7fffffff, -}; - -enum ImageFormat { - ImageFormatUnknown = 0, - ImageFormatRgba32f = 1, - ImageFormatRgba16f = 2, - ImageFormatR32f = 3, - ImageFormatRgba8 = 4, - ImageFormatRgba8Snorm = 5, - ImageFormatRg32f = 6, - ImageFormatRg16f = 7, - ImageFormatR11fG11fB10f = 8, - ImageFormatR16f = 9, - ImageFormatRgba16 = 10, - ImageFormatRgb10A2 = 11, - ImageFormatRg16 = 12, - ImageFormatRg8 = 13, - ImageFormatR16 = 14, - ImageFormatR8 = 15, - ImageFormatRgba16Snorm = 16, - ImageFormatRg16Snorm = 17, - ImageFormatRg8Snorm = 18, - ImageFormatR16Snorm = 19, - ImageFormatR8Snorm = 20, - ImageFormatRgba32i = 21, - ImageFormatRgba16i = 22, - ImageFormatRgba8i = 23, - ImageFormatR32i = 24, - ImageFormatRg32i = 25, - ImageFormatRg16i = 26, - ImageFormatRg8i = 27, - ImageFormatR16i = 28, - ImageFormatR8i = 29, - ImageFormatRgba32ui = 30, - ImageFormatRgba16ui = 31, - ImageFormatRgba8ui = 32, - ImageFormatR32ui = 33, - ImageFormatRgb10a2ui = 34, - ImageFormatRg32ui = 35, - ImageFormatRg16ui = 36, - ImageFormatRg8ui = 37, - ImageFormatR16ui = 38, - ImageFormatR8ui = 39, - ImageFormatMax = 0x7fffffff, -}; - -enum ImageChannelOrder { - ImageChannelOrderR = 0, - ImageChannelOrderA = 1, - ImageChannelOrderRG = 2, - ImageChannelOrderRA = 3, - ImageChannelOrderRGB = 4, - ImageChannelOrderRGBA = 5, - ImageChannelOrderBGRA = 6, - ImageChannelOrderARGB = 7, - ImageChannelOrderIntensity = 8, - ImageChannelOrderLuminance = 9, - ImageChannelOrderRx = 10, - ImageChannelOrderRGx = 11, - ImageChannelOrderRGBx = 12, - ImageChannelOrderDepth = 13, - ImageChannelOrderDepthStencil = 14, - ImageChannelOrdersRGB = 15, - ImageChannelOrdersRGBx = 16, - ImageChannelOrdersRGBA = 17, - ImageChannelOrdersBGRA = 18, - ImageChannelOrderABGR = 19, - ImageChannelOrderMax = 0x7fffffff, -}; - -enum ImageChannelDataType { - ImageChannelDataTypeSnormInt8 = 0, - ImageChannelDataTypeSnormInt16 = 1, - ImageChannelDataTypeUnormInt8 = 2, - ImageChannelDataTypeUnormInt16 = 3, - ImageChannelDataTypeUnormShort565 = 4, - ImageChannelDataTypeUnormShort555 = 5, - ImageChannelDataTypeUnormInt101010 = 6, - ImageChannelDataTypeSignedInt8 = 7, - ImageChannelDataTypeSignedInt16 = 8, - ImageChannelDataTypeSignedInt32 = 9, - ImageChannelDataTypeUnsignedInt8 = 10, - ImageChannelDataTypeUnsignedInt16 = 11, - ImageChannelDataTypeUnsignedInt32 = 12, - ImageChannelDataTypeHalfFloat = 13, - ImageChannelDataTypeFloat = 14, - ImageChannelDataTypeUnormInt24 = 15, - ImageChannelDataTypeUnormInt101010_2 = 16, - ImageChannelDataTypeMax = 0x7fffffff, -}; - -enum ImageOperandsShift { - ImageOperandsBiasShift = 0, - ImageOperandsLodShift = 1, - ImageOperandsGradShift = 2, - ImageOperandsConstOffsetShift = 3, - ImageOperandsOffsetShift = 4, - ImageOperandsConstOffsetsShift = 5, - ImageOperandsSampleShift = 6, - ImageOperandsMinLodShift = 7, - ImageOperandsMax = 0x7fffffff, -}; - -enum ImageOperandsMask { - ImageOperandsMaskNone = 0, - ImageOperandsBiasMask = 0x00000001, - ImageOperandsLodMask = 0x00000002, - ImageOperandsGradMask = 0x00000004, - ImageOperandsConstOffsetMask = 0x00000008, - ImageOperandsOffsetMask = 0x00000010, - ImageOperandsConstOffsetsMask = 0x00000020, - ImageOperandsSampleMask = 0x00000040, - ImageOperandsMinLodMask = 0x00000080, -}; - -enum FPFastMathModeShift { - FPFastMathModeNotNaNShift = 0, - FPFastMathModeNotInfShift = 1, - FPFastMathModeNSZShift = 2, - FPFastMathModeAllowRecipShift = 3, - FPFastMathModeFastShift = 4, - FPFastMathModeMax = 0x7fffffff, -}; - -enum FPFastMathModeMask { - FPFastMathModeMaskNone = 0, - FPFastMathModeNotNaNMask = 0x00000001, - FPFastMathModeNotInfMask = 0x00000002, - FPFastMathModeNSZMask = 0x00000004, - FPFastMathModeAllowRecipMask = 0x00000008, - FPFastMathModeFastMask = 0x00000010, -}; - -enum FPRoundingMode { - FPRoundingModeRTE = 0, - FPRoundingModeRTZ = 1, - FPRoundingModeRTP = 2, - FPRoundingModeRTN = 3, - FPRoundingModeMax = 0x7fffffff, -}; - -enum LinkageType { - LinkageTypeExport = 0, - LinkageTypeImport = 1, - LinkageTypeMax = 0x7fffffff, -}; - -enum AccessQualifier { - AccessQualifierReadOnly = 0, - AccessQualifierWriteOnly = 1, - AccessQualifierReadWrite = 2, - AccessQualifierMax = 0x7fffffff, -}; - -enum FunctionParameterAttribute { - FunctionParameterAttributeZext = 0, - FunctionParameterAttributeSext = 1, - FunctionParameterAttributeByVal = 2, - FunctionParameterAttributeSret = 3, - FunctionParameterAttributeNoAlias = 4, - FunctionParameterAttributeNoCapture = 5, - FunctionParameterAttributeNoWrite = 6, - FunctionParameterAttributeNoReadWrite = 7, - FunctionParameterAttributeMax = 0x7fffffff, -}; - -enum Decoration { - DecorationRelaxedPrecision = 0, - DecorationSpecId = 1, - DecorationBlock = 2, - DecorationBufferBlock = 3, - DecorationRowMajor = 4, - DecorationColMajor = 5, - DecorationArrayStride = 6, - DecorationMatrixStride = 7, - DecorationGLSLShared = 8, - DecorationGLSLPacked = 9, - DecorationCPacked = 10, - DecorationBuiltIn = 11, - DecorationNoPerspective = 13, - DecorationFlat = 14, - DecorationPatch = 15, - DecorationCentroid = 16, - DecorationSample = 17, - DecorationInvariant = 18, - DecorationRestrict = 19, - DecorationAliased = 20, - DecorationVolatile = 21, - DecorationConstant = 22, - DecorationCoherent = 23, - DecorationNonWritable = 24, - DecorationNonReadable = 25, - DecorationUniform = 26, - DecorationSaturatedConversion = 28, - DecorationStream = 29, - DecorationLocation = 30, - DecorationComponent = 31, - DecorationIndex = 32, - DecorationBinding = 33, - DecorationDescriptorSet = 34, - DecorationOffset = 35, - DecorationXfbBuffer = 36, - DecorationXfbStride = 37, - DecorationFuncParamAttr = 38, - DecorationFPRoundingMode = 39, - DecorationFPFastMathMode = 40, - DecorationLinkageAttributes = 41, - DecorationNoContraction = 42, - DecorationInputAttachmentIndex = 43, - DecorationAlignment = 44, - DecorationMaxByteOffset = 45, - DecorationAlignmentId = 46, - DecorationMaxByteOffsetId = 47, - DecorationExplicitInterpAMD = 4999, - DecorationOverrideCoverageNV = 5248, - DecorationPassthroughNV = 5250, - DecorationViewportRelativeNV = 5252, - DecorationSecondaryViewportRelativeNV = 5256, - DecorationNonUniformEXT = 5300, - DecorationHlslCounterBufferGOOGLE = 5634, - DecorationHlslSemanticGOOGLE = 5635, - 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, - BuiltInMax = 0x7fffffff, -}; - -enum SelectionControlShift { - SelectionControlFlattenShift = 0, - SelectionControlDontFlattenShift = 1, - SelectionControlMax = 0x7fffffff, -}; - -enum SelectionControlMask { - SelectionControlMaskNone = 0, - SelectionControlFlattenMask = 0x00000001, - SelectionControlDontFlattenMask = 0x00000002, -}; - -enum LoopControlShift { - LoopControlUnrollShift = 0, - LoopControlDontUnrollShift = 1, - LoopControlDependencyInfiniteShift = 2, - LoopControlDependencyLengthShift = 3, - LoopControlMax = 0x7fffffff, -}; - -enum LoopControlMask { - LoopControlMaskNone = 0, - LoopControlUnrollMask = 0x00000001, - LoopControlDontUnrollMask = 0x00000002, - LoopControlDependencyInfiniteMask = 0x00000004, - LoopControlDependencyLengthMask = 0x00000008, -}; - -enum FunctionControlShift { - FunctionControlInlineShift = 0, - FunctionControlDontInlineShift = 1, - FunctionControlPureShift = 2, - FunctionControlConstShift = 3, - FunctionControlMax = 0x7fffffff, -}; - -enum FunctionControlMask { - FunctionControlMaskNone = 0, - FunctionControlInlineMask = 0x00000001, - FunctionControlDontInlineMask = 0x00000002, - FunctionControlPureMask = 0x00000004, - FunctionControlConstMask = 0x00000008, -}; - -enum MemorySemanticsShift { - MemorySemanticsAcquireShift = 1, - MemorySemanticsReleaseShift = 2, - MemorySemanticsAcquireReleaseShift = 3, - MemorySemanticsSequentiallyConsistentShift = 4, - MemorySemanticsUniformMemoryShift = 6, - MemorySemanticsSubgroupMemoryShift = 7, - MemorySemanticsWorkgroupMemoryShift = 8, - MemorySemanticsCrossWorkgroupMemoryShift = 9, - MemorySemanticsAtomicCounterMemoryShift = 10, - MemorySemanticsImageMemoryShift = 11, - MemorySemanticsMax = 0x7fffffff, -}; - -enum MemorySemanticsMask { - MemorySemanticsMaskNone = 0, - MemorySemanticsAcquireMask = 0x00000002, - MemorySemanticsReleaseMask = 0x00000004, - MemorySemanticsAcquireReleaseMask = 0x00000008, - MemorySemanticsSequentiallyConsistentMask = 0x00000010, - MemorySemanticsUniformMemoryMask = 0x00000040, - MemorySemanticsSubgroupMemoryMask = 0x00000080, - MemorySemanticsWorkgroupMemoryMask = 0x00000100, - MemorySemanticsCrossWorkgroupMemoryMask = 0x00000200, - MemorySemanticsAtomicCounterMemoryMask = 0x00000400, - MemorySemanticsImageMemoryMask = 0x00000800, -}; - -enum MemoryAccessShift { - MemoryAccessVolatileShift = 0, - MemoryAccessAlignedShift = 1, - MemoryAccessNontemporalShift = 2, - MemoryAccessMax = 0x7fffffff, -}; - -enum MemoryAccessMask { - MemoryAccessMaskNone = 0, - MemoryAccessVolatileMask = 0x00000001, - MemoryAccessAlignedMask = 0x00000002, - MemoryAccessNontemporalMask = 0x00000004, -}; - -enum Scope { - ScopeCrossDevice = 0, - ScopeDevice = 1, - ScopeWorkgroup = 2, - ScopeSubgroup = 3, - ScopeInvocation = 4, - ScopeMax = 0x7fffffff, -}; - -enum GroupOperation { - GroupOperationReduce = 0, - GroupOperationInclusiveScan = 1, - GroupOperationExclusiveScan = 2, - 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, - 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, - CapabilityFloat16ImageAMD = 5008, - CapabilityImageGatherBiasLodAMD = 5009, - CapabilityFragmentMaskAMD = 5010, - CapabilityStencilExportEXT = 5013, - CapabilityImageReadWriteLodAMD = 5015, - CapabilitySampleMaskOverrideCoverageNV = 5249, - CapabilityGeometryShaderPassthroughNV = 5251, - CapabilityShaderViewportIndexLayerEXT = 5254, - CapabilityShaderViewportIndexLayerNV = 5254, - CapabilityShaderViewportMaskNV = 5255, - CapabilityShaderStereoViewNV = 5259, - CapabilityPerViewAttributesNV = 5260, - CapabilityFragmentFullyCoveredEXT = 5265, - CapabilityGroupNonUniformPartitionedNV = 5297, - CapabilityShaderNonUniformEXT = 5301, - CapabilityRuntimeDescriptorArrayEXT = 5302, - CapabilityInputAttachmentArrayDynamicIndexingEXT = 5303, - CapabilityUniformTexelBufferArrayDynamicIndexingEXT = 5304, - CapabilityStorageTexelBufferArrayDynamicIndexingEXT = 5305, - CapabilityUniformBufferArrayNonUniformIndexingEXT = 5306, - CapabilitySampledImageArrayNonUniformIndexingEXT = 5307, - CapabilityStorageBufferArrayNonUniformIndexingEXT = 5308, - CapabilityStorageImageArrayNonUniformIndexingEXT = 5309, - CapabilityInputAttachmentArrayNonUniformIndexingEXT = 5310, - CapabilityUniformTexelBufferArrayNonUniformIndexingEXT = 5311, - CapabilityStorageTexelBufferArrayNonUniformIndexingEXT = 5312, - CapabilitySubgroupShuffleINTEL = 5568, - CapabilitySubgroupBufferBlockIOINTEL = 5569, - CapabilitySubgroupImageBlockIOINTEL = 5570, - CapabilityMax = 0x7fffffff, -}; - -enum Op { - OpNop = 0, - OpUndef = 1, - OpSourceContinued = 2, - OpSource = 3, - OpSourceExtension = 4, - OpName = 5, - OpMemberName = 6, - OpString = 7, - OpLine = 8, - OpExtension = 10, - OpExtInstImport = 11, - OpExtInst = 12, - OpMemoryModel = 14, - OpEntryPoint = 15, - OpExecutionMode = 16, - OpCapability = 17, - OpTypeVoid = 19, - OpTypeBool = 20, - OpTypeInt = 21, - OpTypeFloat = 22, - OpTypeVector = 23, - OpTypeMatrix = 24, - OpTypeImage = 25, - OpTypeSampler = 26, - OpTypeSampledImage = 27, - OpTypeArray = 28, - OpTypeRuntimeArray = 29, - OpTypeStruct = 30, - OpTypeOpaque = 31, - OpTypePointer = 32, - OpTypeFunction = 33, - OpTypeEvent = 34, - OpTypeDeviceEvent = 35, - OpTypeReserveId = 36, - OpTypeQueue = 37, - OpTypePipe = 38, - OpTypeForwardPointer = 39, - OpConstantTrue = 41, - OpConstantFalse = 42, - OpConstant = 43, - OpConstantComposite = 44, - OpConstantSampler = 45, - OpConstantNull = 46, - OpSpecConstantTrue = 48, - OpSpecConstantFalse = 49, - OpSpecConstant = 50, - OpSpecConstantComposite = 51, - OpSpecConstantOp = 52, - OpFunction = 54, - OpFunctionParameter = 55, - OpFunctionEnd = 56, - OpFunctionCall = 57, - OpVariable = 59, - OpImageTexelPointer = 60, - OpLoad = 61, - OpStore = 62, - OpCopyMemory = 63, - OpCopyMemorySized = 64, - OpAccessChain = 65, - OpInBoundsAccessChain = 66, - OpPtrAccessChain = 67, - OpArrayLength = 68, - OpGenericPtrMemSemantics = 69, - OpInBoundsPtrAccessChain = 70, - OpDecorate = 71, - OpMemberDecorate = 72, - OpDecorationGroup = 73, - OpGroupDecorate = 74, - OpGroupMemberDecorate = 75, - OpVectorExtractDynamic = 77, - OpVectorInsertDynamic = 78, - OpVectorShuffle = 79, - OpCompositeConstruct = 80, - OpCompositeExtract = 81, - OpCompositeInsert = 82, - OpCopyObject = 83, - OpTranspose = 84, - OpSampledImage = 86, - OpImageSampleImplicitLod = 87, - OpImageSampleExplicitLod = 88, - OpImageSampleDrefImplicitLod = 89, - OpImageSampleDrefExplicitLod = 90, - OpImageSampleProjImplicitLod = 91, - OpImageSampleProjExplicitLod = 92, - OpImageSampleProjDrefImplicitLod = 93, - OpImageSampleProjDrefExplicitLod = 94, - OpImageFetch = 95, - OpImageGather = 96, - OpImageDrefGather = 97, - OpImageRead = 98, - OpImageWrite = 99, - OpImage = 100, - OpImageQueryFormat = 101, - OpImageQueryOrder = 102, - OpImageQuerySizeLod = 103, - OpImageQuerySize = 104, - OpImageQueryLod = 105, - OpImageQueryLevels = 106, - OpImageQuerySamples = 107, - OpConvertFToU = 109, - OpConvertFToS = 110, - OpConvertSToF = 111, - OpConvertUToF = 112, - OpUConvert = 113, - OpSConvert = 114, - OpFConvert = 115, - OpQuantizeToF16 = 116, - OpConvertPtrToU = 117, - OpSatConvertSToU = 118, - OpSatConvertUToS = 119, - OpConvertUToPtr = 120, - OpPtrCastToGeneric = 121, - OpGenericCastToPtr = 122, - OpGenericCastToPtrExplicit = 123, - OpBitcast = 124, - OpSNegate = 126, - OpFNegate = 127, - OpIAdd = 128, - OpFAdd = 129, - OpISub = 130, - OpFSub = 131, - OpIMul = 132, - OpFMul = 133, - OpUDiv = 134, - OpSDiv = 135, - OpFDiv = 136, - OpUMod = 137, - OpSRem = 138, - OpSMod = 139, - OpFRem = 140, - OpFMod = 141, - OpVectorTimesScalar = 142, - OpMatrixTimesScalar = 143, - OpVectorTimesMatrix = 144, - OpMatrixTimesVector = 145, - OpMatrixTimesMatrix = 146, - OpOuterProduct = 147, - OpDot = 148, - OpIAddCarry = 149, - OpISubBorrow = 150, - OpUMulExtended = 151, - OpSMulExtended = 152, - OpAny = 154, - OpAll = 155, - OpIsNan = 156, - OpIsInf = 157, - OpIsFinite = 158, - OpIsNormal = 159, - OpSignBitSet = 160, - OpLessOrGreater = 161, - OpOrdered = 162, - OpUnordered = 163, - OpLogicalEqual = 164, - OpLogicalNotEqual = 165, - OpLogicalOr = 166, - OpLogicalAnd = 167, - OpLogicalNot = 168, - OpSelect = 169, - OpIEqual = 170, - OpINotEqual = 171, - OpUGreaterThan = 172, - OpSGreaterThan = 173, - OpUGreaterThanEqual = 174, - OpSGreaterThanEqual = 175, - OpULessThan = 176, - OpSLessThan = 177, - OpULessThanEqual = 178, - OpSLessThanEqual = 179, - OpFOrdEqual = 180, - OpFUnordEqual = 181, - OpFOrdNotEqual = 182, - OpFUnordNotEqual = 183, - OpFOrdLessThan = 184, - OpFUnordLessThan = 185, - OpFOrdGreaterThan = 186, - OpFUnordGreaterThan = 187, - OpFOrdLessThanEqual = 188, - OpFUnordLessThanEqual = 189, - OpFOrdGreaterThanEqual = 190, - OpFUnordGreaterThanEqual = 191, - OpShiftRightLogical = 194, - OpShiftRightArithmetic = 195, - OpShiftLeftLogical = 196, - OpBitwiseOr = 197, - OpBitwiseXor = 198, - OpBitwiseAnd = 199, - OpNot = 200, - OpBitFieldInsert = 201, - OpBitFieldSExtract = 202, - OpBitFieldUExtract = 203, - OpBitReverse = 204, - OpBitCount = 205, - OpDPdx = 207, - OpDPdy = 208, - OpFwidth = 209, - OpDPdxFine = 210, - OpDPdyFine = 211, - OpFwidthFine = 212, - OpDPdxCoarse = 213, - OpDPdyCoarse = 214, - OpFwidthCoarse = 215, - OpEmitVertex = 218, - OpEndPrimitive = 219, - OpEmitStreamVertex = 220, - OpEndStreamPrimitive = 221, - OpControlBarrier = 224, - OpMemoryBarrier = 225, - OpAtomicLoad = 227, - OpAtomicStore = 228, - OpAtomicExchange = 229, - OpAtomicCompareExchange = 230, - OpAtomicCompareExchangeWeak = 231, - OpAtomicIIncrement = 232, - OpAtomicIDecrement = 233, - OpAtomicIAdd = 234, - OpAtomicISub = 235, - OpAtomicSMin = 236, - OpAtomicUMin = 237, - OpAtomicSMax = 238, - OpAtomicUMax = 239, - OpAtomicAnd = 240, - OpAtomicOr = 241, - OpAtomicXor = 242, - OpPhi = 245, - OpLoopMerge = 246, - OpSelectionMerge = 247, - OpLabel = 248, - OpBranch = 249, - OpBranchConditional = 250, - OpSwitch = 251, - OpKill = 252, - OpReturn = 253, - OpReturnValue = 254, - OpUnreachable = 255, - OpLifetimeStart = 256, - OpLifetimeStop = 257, - OpGroupAsyncCopy = 259, - OpGroupWaitEvents = 260, - OpGroupAll = 261, - OpGroupAny = 262, - OpGroupBroadcast = 263, - OpGroupIAdd = 264, - OpGroupFAdd = 265, - OpGroupFMin = 266, - OpGroupUMin = 267, - OpGroupSMin = 268, - OpGroupFMax = 269, - OpGroupUMax = 270, - OpGroupSMax = 271, - OpReadPipe = 274, - OpWritePipe = 275, - OpReservedReadPipe = 276, - OpReservedWritePipe = 277, - OpReserveReadPipePackets = 278, - OpReserveWritePipePackets = 279, - OpCommitReadPipe = 280, - OpCommitWritePipe = 281, - OpIsValidReserveId = 282, - OpGetNumPipePackets = 283, - OpGetMaxPipePackets = 284, - OpGroupReserveReadPipePackets = 285, - OpGroupReserveWritePipePackets = 286, - OpGroupCommitReadPipe = 287, - OpGroupCommitWritePipe = 288, - OpEnqueueMarker = 291, - OpEnqueueKernel = 292, - OpGetKernelNDrangeSubGroupCount = 293, - OpGetKernelNDrangeMaxSubGroupSize = 294, - OpGetKernelWorkGroupSize = 295, - OpGetKernelPreferredWorkGroupSizeMultiple = 296, - OpRetainEvent = 297, - OpReleaseEvent = 298, - OpCreateUserEvent = 299, - OpIsValidEvent = 300, - OpSetUserEventStatus = 301, - OpCaptureEventProfilingInfo = 302, - OpGetDefaultQueue = 303, - OpBuildNDRange = 304, - OpImageSparseSampleImplicitLod = 305, - OpImageSparseSampleExplicitLod = 306, - OpImageSparseSampleDrefImplicitLod = 307, - OpImageSparseSampleDrefExplicitLod = 308, - OpImageSparseSampleProjImplicitLod = 309, - OpImageSparseSampleProjExplicitLod = 310, - OpImageSparseSampleProjDrefImplicitLod = 311, - OpImageSparseSampleProjDrefExplicitLod = 312, - OpImageSparseFetch = 313, - OpImageSparseGather = 314, - OpImageSparseDrefGather = 315, - OpImageSparseTexelsResident = 316, - OpNoLine = 317, - OpAtomicFlagTestAndSet = 318, - OpAtomicFlagClear = 319, - OpImageSparseRead = 320, - OpSizeOf = 321, - OpTypePipeStorage = 322, - OpConstantPipeStorage = 323, - OpCreatePipeFromPipeStorage = 324, - OpGetKernelLocalSizeForSubgroupCount = 325, - OpGetKernelMaxNumSubgroups = 326, - OpTypeNamedBarrier = 327, - OpNamedBarrierInitialize = 328, - OpMemoryNamedBarrier = 329, - OpModuleProcessed = 330, - OpExecutionModeId = 331, - OpDecorateId = 332, - 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, - OpSubgroupBallotKHR = 4421, - OpSubgroupFirstInvocationKHR = 4422, - OpSubgroupAllKHR = 4428, - OpSubgroupAnyKHR = 4429, - OpSubgroupAllEqualKHR = 4430, - OpSubgroupReadInvocationKHR = 4432, - OpGroupIAddNonUniformAMD = 5000, - OpGroupFAddNonUniformAMD = 5001, - OpGroupFMinNonUniformAMD = 5002, - OpGroupUMinNonUniformAMD = 5003, - OpGroupSMinNonUniformAMD = 5004, - OpGroupFMaxNonUniformAMD = 5005, - OpGroupUMaxNonUniformAMD = 5006, - OpGroupSMaxNonUniformAMD = 5007, - OpFragmentMaskFetchAMD = 5011, - OpFragmentFetchAMD = 5012, - OpGroupNonUniformPartitionNV = 5296, - OpSubgroupShuffleINTEL = 5571, - OpSubgroupShuffleDownINTEL = 5572, - OpSubgroupShuffleUpINTEL = 5573, - OpSubgroupShuffleXorINTEL = 5574, - OpSubgroupBlockReadINTEL = 5575, - OpSubgroupBlockWriteINTEL = 5576, - OpSubgroupImageBlockReadINTEL = 5577, - OpSubgroupImageBlockWriteINTEL = 5578, - OpDecorateStringGOOGLE = 5632, - OpMemberDecorateStringGOOGLE = 5633, - OpMax = 0x7fffffff, -}; - -// Overload operator| for mask bit combining - -inline ImageOperandsMask operator|(ImageOperandsMask a, ImageOperandsMask b) { return ImageOperandsMask(unsigned(a) | unsigned(b)); } -inline FPFastMathModeMask operator|(FPFastMathModeMask a, FPFastMathModeMask b) { return FPFastMathModeMask(unsigned(a) | unsigned(b)); } -inline SelectionControlMask operator|(SelectionControlMask a, SelectionControlMask b) { return SelectionControlMask(unsigned(a) | unsigned(b)); } -inline LoopControlMask operator|(LoopControlMask a, LoopControlMask b) { return LoopControlMask(unsigned(a) | unsigned(b)); } -inline FunctionControlMask operator|(FunctionControlMask a, FunctionControlMask b) { return FunctionControlMask(unsigned(a) | unsigned(b)); } -inline MemorySemanticsMask operator|(MemorySemanticsMask a, MemorySemanticsMask b) { return MemorySemanticsMask(unsigned(a) | unsigned(b)); } -inline MemoryAccessMask operator|(MemoryAccessMask a, MemoryAccessMask b) { return MemoryAccessMask(unsigned(a) | unsigned(b)); } -inline KernelProfilingInfoMask operator|(KernelProfilingInfoMask a, KernelProfilingInfoMask b) { return KernelProfilingInfoMask(unsigned(a) | unsigned(b)); } - -} // end namespace spv - -#endif // #ifndef spirv_HPP - diff --git a/External/glslang/SPIRV/spvIR.h b/External/glslang/SPIRV/spvIR.h deleted file mode 100644 index faa2701f..00000000 --- a/External/glslang/SPIRV/spvIR.h +++ /dev/null @@ -1,407 +0,0 @@ -// -// Copyright (C) 2014 LunarG, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -// SPIRV-IR -// -// Simple in-memory representation (IR) of SPIRV. Just for holding -// Each function's CFG of blocks. Has this hierarchy: -// - Module, which is a list of -// - Function, which is a list of -// - Block, which is a list of -// - Instruction -// - -#pragma once -#ifndef spvIR_H -#define spvIR_H - -#include "spirv.hpp" - -#include -#include -#include -#include -#include -#include - -namespace spv { - -class Block; -class Function; -class Module; - -const Id NoResult = 0; -const Id NoType = 0; - -const Decoration NoPrecision = DecorationMax; - -#ifdef __GNUC__ -# define POTENTIALLY_UNUSED __attribute__((unused)) -#else -# define POTENTIALLY_UNUSED -#endif - -POTENTIALLY_UNUSED -const MemorySemanticsMask MemorySemanticsAllMemory = - (MemorySemanticsMask)(MemorySemanticsUniformMemoryMask | - MemorySemanticsWorkgroupMemoryMask | - MemorySemanticsAtomicCounterMemoryMask | - MemorySemanticsImageMemoryMask); - -// -// SPIR-V IR instruction. -// - -class Instruction { -public: - Instruction(Id resultId, Id typeId, Op opCode) : resultId(resultId), typeId(typeId), opCode(opCode), block(nullptr) { } - explicit Instruction(Op opCode) : resultId(NoResult), typeId(NoType), opCode(opCode), block(nullptr) { } - virtual ~Instruction() {} - void addIdOperand(Id id) { operands.push_back(id); } - void addImmediateOperand(unsigned int immediate) { operands.push_back(immediate); } - void addStringOperand(const char* str) - { - unsigned int word; - char* wordString = (char*)&word; - char* wordPtr = wordString; - int charCount = 0; - char c; - do { - c = *(str++); - *(wordPtr++) = c; - ++charCount; - if (charCount == 4) { - addImmediateOperand(word); - wordPtr = wordString; - charCount = 0; - } - } while (c != 0); - - // deal with partial last word - if (charCount > 0) { - // pad with 0s - for (; charCount < 4; ++charCount) - *(wordPtr++) = 0; - addImmediateOperand(word); - } - } - void setBlock(Block* b) { block = b; } - Block* getBlock() const { return block; } - Op getOpCode() const { return opCode; } - int getNumOperands() const { return (int)operands.size(); } - Id getResultId() const { return resultId; } - Id getTypeId() const { return typeId; } - Id getIdOperand(int op) const { return operands[op]; } - unsigned int getImmediateOperand(int op) const { return operands[op]; } - - // Write out the binary form. - void dump(std::vector& out) const - { - // Compute the wordCount - unsigned int wordCount = 1; - if (typeId) - ++wordCount; - if (resultId) - ++wordCount; - wordCount += (unsigned int)operands.size(); - - // Write out the beginning of the instruction - out.push_back(((wordCount) << WordCountShift) | opCode); - if (typeId) - out.push_back(typeId); - if (resultId) - out.push_back(resultId); - - // Write out the operands - for (int op = 0; op < (int)operands.size(); ++op) - out.push_back(operands[op]); - } - -protected: - Instruction(const Instruction&); - Id resultId; - Id typeId; - Op opCode; - std::vector operands; - Block* block; -}; - -// -// SPIR-V IR block. -// - -class Block { -public: - Block(Id id, Function& parent); - virtual ~Block() - { - } - - Id getId() { return instructions.front()->getResultId(); } - - Function& getParent() const { return parent; } - void addInstruction(std::unique_ptr inst); - void addPredecessor(Block* pred) { predecessors.push_back(pred); pred->successors.push_back(this);} - void addLocalVariable(std::unique_ptr inst) { localVariables.push_back(std::move(inst)); } - const std::vector& getPredecessors() const { return predecessors; } - const std::vector& getSuccessors() const { return successors; } - const std::vector >& getInstructions() const { - return instructions; - } - void setUnreachable() { unreachable = true; } - bool isUnreachable() const { return unreachable; } - // Returns the block's merge instruction, if one exists (otherwise null). - const Instruction* getMergeInstruction() const { - if (instructions.size() < 2) return nullptr; - const Instruction* nextToLast = (instructions.cend() - 2)->get(); - switch (nextToLast->getOpCode()) { - case OpSelectionMerge: - case OpLoopMerge: - return nextToLast; - default: - return nullptr; - } - return nullptr; - } - - bool isTerminated() const - { - switch (instructions.back()->getOpCode()) { - case OpBranch: - case OpBranchConditional: - case OpSwitch: - case OpKill: - case OpReturn: - case OpReturnValue: - return true; - default: - return false; - } - } - - void dump(std::vector& out) const - { - instructions[0]->dump(out); - for (int i = 0; i < (int)localVariables.size(); ++i) - localVariables[i]->dump(out); - for (int i = 1; i < (int)instructions.size(); ++i) - instructions[i]->dump(out); - } - -protected: - Block(const Block&); - Block& operator=(Block&); - - // To enforce keeping parent and ownership in sync: - friend Function; - - std::vector > instructions; - std::vector predecessors, successors; - std::vector > localVariables; - Function& parent; - - // track whether this block is known to be uncreachable (not necessarily - // true for all unreachable blocks, but should be set at least - // for the extraneous ones introduced by the builder). - bool unreachable; -}; - -// Traverses the control-flow graph rooted at root in an order suited for -// readable code generation. Invokes callback at every node in the traversal -// order. -void inReadableOrder(Block* root, std::function callback); - -// -// SPIR-V IR Function. -// - -class Function { -public: - Function(Id id, Id resultType, Id functionType, Id firstParam, Module& parent); - virtual ~Function() - { - for (int i = 0; i < (int)parameterInstructions.size(); ++i) - delete parameterInstructions[i]; - - for (int i = 0; i < (int)blocks.size(); ++i) - delete blocks[i]; - } - Id getId() const { return functionInstruction.getResultId(); } - Id getParamId(int p) { return parameterInstructions[p]->getResultId(); } - - void addBlock(Block* block) { blocks.push_back(block); } - void removeBlock(Block* block) - { - auto found = find(blocks.begin(), blocks.end(), block); - assert(found != blocks.end()); - blocks.erase(found); - delete block; - } - - Module& getParent() const { return parent; } - Block* getEntryBlock() const { return blocks.front(); } - Block* getLastBlock() const { return blocks.back(); } - const std::vector& getBlocks() const { return blocks; } - void addLocalVariable(std::unique_ptr inst); - Id getReturnType() const { return functionInstruction.getTypeId(); } - - void setImplicitThis() { implicitThis = true; } - bool hasImplicitThis() const { return implicitThis; } - - void dump(std::vector& out) const - { - // OpFunction - functionInstruction.dump(out); - - // OpFunctionParameter - for (int p = 0; p < (int)parameterInstructions.size(); ++p) - parameterInstructions[p]->dump(out); - - // Blocks - inReadableOrder(blocks[0], [&out](const Block* b) { b->dump(out); }); - Instruction end(0, 0, OpFunctionEnd); - end.dump(out); - } - -protected: - Function(const Function&); - Function& operator=(Function&); - - Module& parent; - Instruction functionInstruction; - std::vector parameterInstructions; - std::vector blocks; - bool implicitThis; // true if this is a member function expecting to be passed a 'this' as the first argument -}; - -// -// SPIR-V IR Module. -// - -class Module { -public: - Module() {} - virtual ~Module() - { - // TODO delete things - } - - void addFunction(Function *fun) { functions.push_back(fun); } - - void mapInstruction(Instruction *instruction) - { - spv::Id resultId = instruction->getResultId(); - // map the instruction's result id - if (resultId >= idToInstruction.size()) - idToInstruction.resize(resultId + 16); - idToInstruction[resultId] = instruction; - } - - Instruction* getInstruction(Id id) const { return idToInstruction[id]; } - const std::vector& getFunctions() const { return functions; } - spv::Id getTypeId(Id resultId) const { return idToInstruction[resultId]->getTypeId(); } - StorageClass getStorageClass(Id typeId) const - { - assert(idToInstruction[typeId]->getOpCode() == spv::OpTypePointer); - return (StorageClass)idToInstruction[typeId]->getImmediateOperand(0); - } - - void dump(std::vector& out) const - { - for (int f = 0; f < (int)functions.size(); ++f) - functions[f]->dump(out); - } - -protected: - Module(const Module&); - std::vector functions; - - // map from result id to instruction having that result id - std::vector idToInstruction; - - // map from a result id to its type id -}; - -// -// Implementation (it's here due to circular type definitions). -// - -// Add both -// - the OpFunction instruction -// - all the OpFunctionParameter instructions -__inline Function::Function(Id id, Id resultType, Id functionType, Id firstParamId, Module& parent) - : parent(parent), functionInstruction(id, resultType, OpFunction), implicitThis(false) -{ - // OpFunction - functionInstruction.addImmediateOperand(FunctionControlMaskNone); - functionInstruction.addIdOperand(functionType); - parent.mapInstruction(&functionInstruction); - parent.addFunction(this); - - // OpFunctionParameter - Instruction* typeInst = parent.getInstruction(functionType); - int numParams = typeInst->getNumOperands() - 1; - for (int p = 0; p < numParams; ++p) { - Instruction* param = new Instruction(firstParamId + p, typeInst->getIdOperand(p + 1), OpFunctionParameter); - parent.mapInstruction(param); - parameterInstructions.push_back(param); - } -} - -__inline void Function::addLocalVariable(std::unique_ptr inst) -{ - Instruction* raw_instruction = inst.get(); - blocks[0]->addLocalVariable(std::move(inst)); - parent.mapInstruction(raw_instruction); -} - -__inline Block::Block(Id id, Function& parent) : parent(parent), unreachable(false) -{ - instructions.push_back(std::unique_ptr(new Instruction(id, NoType, OpLabel))); - instructions.back()->setBlock(this); - parent.getParent().mapInstruction(instructions.back().get()); -} - -__inline void Block::addInstruction(std::unique_ptr inst) -{ - Instruction* raw_instruction = inst.get(); - instructions.push_back(std::move(inst)); - raw_instruction->setBlock(this); - if (raw_instruction->getResultId()) - parent.getParent().mapInstruction(raw_instruction); -} - -}; // end spv namespace - -#endif // spvIR_H diff --git a/External/glslang/StandAlone/CMakeLists.txt b/External/glslang/StandAlone/CMakeLists.txt deleted file mode 100644 index b0d863d3..00000000 --- a/External/glslang/StandAlone/CMakeLists.txt +++ /dev/null @@ -1,47 +0,0 @@ -add_library(glslang-default-resource-limits - ${CMAKE_CURRENT_SOURCE_DIR}/ResourceLimits.cpp) -set_property(TARGET glslang-default-resource-limits PROPERTY FOLDER glslang) -set_property(TARGET glslang-default-resource-limits PROPERTY POSITION_INDEPENDENT_CODE ON) - -target_include_directories(glslang-default-resource-limits - PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} - PUBLIC ${PROJECT_SOURCE_DIR}) - -set(SOURCES StandAlone.cpp DirStackFileIncluder.h) -set(REMAPPER_SOURCES spirv-remap.cpp) - -add_executable(glslangValidator ${SOURCES}) -add_executable(spirv-remap ${REMAPPER_SOURCES}) -set_property(TARGET glslangValidator PROPERTY FOLDER tools) -set_property(TARGET spirv-remap PROPERTY FOLDER tools) -glslang_set_link_args(glslangValidator) -glslang_set_link_args(spirv-remap) - -set(LIBRARIES - glslang - SPIRV - SPVRemapper - glslang-default-resource-limits) - -if(WIN32) - set(LIBRARIES ${LIBRARIES} psapi) -elseif(UNIX) - if(NOT ANDROID) - set(LIBRARIES ${LIBRARIES} pthread) - endif() -endif(WIN32) - -target_link_libraries(glslangValidator ${LIBRARIES}) -target_link_libraries(spirv-remap ${LIBRARIES}) - -if(WIN32) - source_group("Source" FILES ${SOURCES}) -endif(WIN32) - -if(ENABLE_GLSLANG_INSTALL) - install(TARGETS glslangValidator - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) - - install(TARGETS spirv-remap - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) -endif(ENABLE_GLSLANG_INSTALL) diff --git a/External/glslang/StandAlone/DirStackFileIncluder.h b/External/glslang/StandAlone/DirStackFileIncluder.h deleted file mode 100644 index 18734130..00000000 --- a/External/glslang/StandAlone/DirStackFileIncluder.h +++ /dev/null @@ -1,141 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// Copyright (C) 2017 Google, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -#pragma once - -#include -#include -#include -#include - -#include "./../glslang/Public/ShaderLang.h" - -// Default include class for normal include convention of search backward -// through the stack of active include paths (for nested includes). -// Can be overridden to customize. -class DirStackFileIncluder : public glslang::TShader::Includer { -public: - DirStackFileIncluder() : externalLocalDirectoryCount(0) { } - - virtual IncludeResult* includeLocal(const char* headerName, - const char* includerName, - size_t inclusionDepth) override - { - return readLocalPath(headerName, includerName, (int)inclusionDepth); - } - - virtual IncludeResult* includeSystem(const char* headerName, - const char* /*includerName*/, - size_t /*inclusionDepth*/) override - { - return readSystemPath(headerName); - } - - // Externally set directories. E.g., from a command-line -I. - // - Most-recently pushed are checked first. - // - All these are checked after the parse-time stack of local directories - // is checked. - // - This only applies to the "local" form of #include. - // - Makes its own copy of the path. - virtual void pushExternalLocalDirectory(const std::string& dir) - { - directoryStack.push_back(dir); - externalLocalDirectoryCount = (int)directoryStack.size(); - } - - virtual void releaseInclude(IncludeResult* result) override - { - if (result != nullptr) { - delete [] static_cast(result->userData); - delete result; - } - } - - virtual ~DirStackFileIncluder() override { } - -protected: - typedef char tUserDataElement; - std::vector directoryStack; - int externalLocalDirectoryCount; - - // Search for a valid "local" path based on combining the stack of include - // directories and the nominal name of the header. - virtual IncludeResult* readLocalPath(const char* headerName, const char* includerName, int depth) - { - // Discard popped include directories, and - // initialize when at parse-time first level. - directoryStack.resize(depth + externalLocalDirectoryCount); - if (depth == 1) - directoryStack.back() = getDirectory(includerName); - - // Find a directory that works, using a reverse search of the include stack. - for (auto it = directoryStack.rbegin(); it != directoryStack.rend(); ++it) { - std::string path = *it + '/' + headerName; - std::replace(path.begin(), path.end(), '\\', '/'); - std::ifstream file(path, std::ios_base::binary | std::ios_base::ate); - if (file) { - directoryStack.push_back(getDirectory(path)); - return newIncludeResult(path, file, (int)file.tellg()); - } - } - - return nullptr; - } - - // Search for a valid path. - // Not implemented yet; returning nullptr signals failure to find. - virtual IncludeResult* readSystemPath(const char* /*headerName*/) const - { - return nullptr; - } - - // Do actual reading of the file, filling in a new include result. - virtual IncludeResult* newIncludeResult(const std::string& path, std::ifstream& file, int length) const - { - char* content = new tUserDataElement [length]; - file.seekg(0, file.beg); - file.read(content, length); - return new IncludeResult(path, content, length, content); - } - - // If no path markers, return current working directory. - // Otherwise, strip file name and return path leading up to it. - virtual std::string getDirectory(const std::string path) const - { - size_t last = path.find_last_of("/\\"); - return last == std::string::npos ? "." : path.substr(0, last); - } -}; diff --git a/External/glslang/StandAlone/ResourceLimits.cpp b/External/glslang/StandAlone/ResourceLimits.cpp deleted file mode 100644 index e22ec801..00000000 --- a/External/glslang/StandAlone/ResourceLimits.cpp +++ /dev/null @@ -1,458 +0,0 @@ -// -// Copyright (C) 2016 Google, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -#include -#include -#include -#include - -#include "ResourceLimits.h" - -namespace glslang { - -const TBuiltInResource DefaultTBuiltInResource = { - /* .MaxLights = */ 32, - /* .MaxClipPlanes = */ 6, - /* .MaxTextureUnits = */ 32, - /* .MaxTextureCoords = */ 32, - /* .MaxVertexAttribs = */ 64, - /* .MaxVertexUniformComponents = */ 4096, - /* .MaxVaryingFloats = */ 64, - /* .MaxVertexTextureImageUnits = */ 32, - /* .MaxCombinedTextureImageUnits = */ 80, - /* .MaxTextureImageUnits = */ 32, - /* .MaxFragmentUniformComponents = */ 4096, - /* .MaxDrawBuffers = */ 32, - /* .MaxVertexUniformVectors = */ 128, - /* .MaxVaryingVectors = */ 8, - /* .MaxFragmentUniformVectors = */ 16, - /* .MaxVertexOutputVectors = */ 16, - /* .MaxFragmentInputVectors = */ 15, - /* .MinProgramTexelOffset = */ -8, - /* .MaxProgramTexelOffset = */ 7, - /* .MaxClipDistances = */ 8, - /* .MaxComputeWorkGroupCountX = */ 65535, - /* .MaxComputeWorkGroupCountY = */ 65535, - /* .MaxComputeWorkGroupCountZ = */ 65535, - /* .MaxComputeWorkGroupSizeX = */ 1024, - /* .MaxComputeWorkGroupSizeY = */ 1024, - /* .MaxComputeWorkGroupSizeZ = */ 64, - /* .MaxComputeUniformComponents = */ 1024, - /* .MaxComputeTextureImageUnits = */ 16, - /* .MaxComputeImageUniforms = */ 8, - /* .MaxComputeAtomicCounters = */ 8, - /* .MaxComputeAtomicCounterBuffers = */ 1, - /* .MaxVaryingComponents = */ 60, - /* .MaxVertexOutputComponents = */ 64, - /* .MaxGeometryInputComponents = */ 64, - /* .MaxGeometryOutputComponents = */ 128, - /* .MaxFragmentInputComponents = */ 128, - /* .MaxImageUnits = */ 8, - /* .MaxCombinedImageUnitsAndFragmentOutputs = */ 8, - /* .MaxCombinedShaderOutputResources = */ 8, - /* .MaxImageSamples = */ 0, - /* .MaxVertexImageUniforms = */ 0, - /* .MaxTessControlImageUniforms = */ 0, - /* .MaxTessEvaluationImageUniforms = */ 0, - /* .MaxGeometryImageUniforms = */ 0, - /* .MaxFragmentImageUniforms = */ 8, - /* .MaxCombinedImageUniforms = */ 8, - /* .MaxGeometryTextureImageUnits = */ 16, - /* .MaxGeometryOutputVertices = */ 256, - /* .MaxGeometryTotalOutputComponents = */ 1024, - /* .MaxGeometryUniformComponents = */ 1024, - /* .MaxGeometryVaryingComponents = */ 64, - /* .MaxTessControlInputComponents = */ 128, - /* .MaxTessControlOutputComponents = */ 128, - /* .MaxTessControlTextureImageUnits = */ 16, - /* .MaxTessControlUniformComponents = */ 1024, - /* .MaxTessControlTotalOutputComponents = */ 4096, - /* .MaxTessEvaluationInputComponents = */ 128, - /* .MaxTessEvaluationOutputComponents = */ 128, - /* .MaxTessEvaluationTextureImageUnits = */ 16, - /* .MaxTessEvaluationUniformComponents = */ 1024, - /* .MaxTessPatchComponents = */ 120, - /* .MaxPatchVertices = */ 32, - /* .MaxTessGenLevel = */ 64, - /* .MaxViewports = */ 16, - /* .MaxVertexAtomicCounters = */ 0, - /* .MaxTessControlAtomicCounters = */ 0, - /* .MaxTessEvaluationAtomicCounters = */ 0, - /* .MaxGeometryAtomicCounters = */ 0, - /* .MaxFragmentAtomicCounters = */ 8, - /* .MaxCombinedAtomicCounters = */ 8, - /* .MaxAtomicCounterBindings = */ 1, - /* .MaxVertexAtomicCounterBuffers = */ 0, - /* .MaxTessControlAtomicCounterBuffers = */ 0, - /* .MaxTessEvaluationAtomicCounterBuffers = */ 0, - /* .MaxGeometryAtomicCounterBuffers = */ 0, - /* .MaxFragmentAtomicCounterBuffers = */ 1, - /* .MaxCombinedAtomicCounterBuffers = */ 1, - /* .MaxAtomicCounterBufferSize = */ 16384, - /* .MaxTransformFeedbackBuffers = */ 4, - /* .MaxTransformFeedbackInterleavedComponents = */ 64, - /* .MaxCullDistances = */ 8, - /* .MaxCombinedClipAndCullDistances = */ 8, - /* .MaxSamples = */ 4, - /* .limits = */ { - /* .nonInductiveForLoops = */ 1, - /* .whileLoops = */ 1, - /* .doWhileLoops = */ 1, - /* .generalUniformIndexing = */ 1, - /* .generalAttributeMatrixVectorIndexing = */ 1, - /* .generalVaryingIndexing = */ 1, - /* .generalSamplerIndexing = */ 1, - /* .generalVariableIndexing = */ 1, - /* .generalConstantMatrixVectorIndexing = */ 1, - }}; - -std::string GetDefaultTBuiltInResourceString() -{ - std::ostringstream ostream; - - ostream << "MaxLights " << DefaultTBuiltInResource.maxLights << "\n" - << "MaxClipPlanes " << DefaultTBuiltInResource.maxClipPlanes << "\n" - << "MaxTextureUnits " << DefaultTBuiltInResource.maxTextureUnits << "\n" - << "MaxTextureCoords " << DefaultTBuiltInResource.maxTextureCoords << "\n" - << "MaxVertexAttribs " << DefaultTBuiltInResource.maxVertexAttribs << "\n" - << "MaxVertexUniformComponents " << DefaultTBuiltInResource.maxVertexUniformComponents << "\n" - << "MaxVaryingFloats " << DefaultTBuiltInResource.maxVaryingFloats << "\n" - << "MaxVertexTextureImageUnits " << DefaultTBuiltInResource.maxVertexTextureImageUnits << "\n" - << "MaxCombinedTextureImageUnits " << DefaultTBuiltInResource.maxCombinedTextureImageUnits << "\n" - << "MaxTextureImageUnits " << DefaultTBuiltInResource.maxTextureImageUnits << "\n" - << "MaxFragmentUniformComponents " << DefaultTBuiltInResource.maxFragmentUniformComponents << "\n" - << "MaxDrawBuffers " << DefaultTBuiltInResource.maxDrawBuffers << "\n" - << "MaxVertexUniformVectors " << DefaultTBuiltInResource.maxVertexUniformVectors << "\n" - << "MaxVaryingVectors " << DefaultTBuiltInResource.maxVaryingVectors << "\n" - << "MaxFragmentUniformVectors " << DefaultTBuiltInResource.maxFragmentUniformVectors << "\n" - << "MaxVertexOutputVectors " << DefaultTBuiltInResource.maxVertexOutputVectors << "\n" - << "MaxFragmentInputVectors " << DefaultTBuiltInResource.maxFragmentInputVectors << "\n" - << "MinProgramTexelOffset " << DefaultTBuiltInResource.minProgramTexelOffset << "\n" - << "MaxProgramTexelOffset " << DefaultTBuiltInResource.maxProgramTexelOffset << "\n" - << "MaxClipDistances " << DefaultTBuiltInResource.maxClipDistances << "\n" - << "MaxComputeWorkGroupCountX " << DefaultTBuiltInResource.maxComputeWorkGroupCountX << "\n" - << "MaxComputeWorkGroupCountY " << DefaultTBuiltInResource.maxComputeWorkGroupCountY << "\n" - << "MaxComputeWorkGroupCountZ " << DefaultTBuiltInResource.maxComputeWorkGroupCountZ << "\n" - << "MaxComputeWorkGroupSizeX " << DefaultTBuiltInResource.maxComputeWorkGroupSizeX << "\n" - << "MaxComputeWorkGroupSizeY " << DefaultTBuiltInResource.maxComputeWorkGroupSizeY << "\n" - << "MaxComputeWorkGroupSizeZ " << DefaultTBuiltInResource.maxComputeWorkGroupSizeZ << "\n" - << "MaxComputeUniformComponents " << DefaultTBuiltInResource.maxComputeUniformComponents << "\n" - << "MaxComputeTextureImageUnits " << DefaultTBuiltInResource.maxComputeTextureImageUnits << "\n" - << "MaxComputeImageUniforms " << DefaultTBuiltInResource.maxComputeImageUniforms << "\n" - << "MaxComputeAtomicCounters " << DefaultTBuiltInResource.maxComputeAtomicCounters << "\n" - << "MaxComputeAtomicCounterBuffers " << DefaultTBuiltInResource.maxComputeAtomicCounterBuffers << "\n" - << "MaxVaryingComponents " << DefaultTBuiltInResource.maxVaryingComponents << "\n" - << "MaxVertexOutputComponents " << DefaultTBuiltInResource.maxVertexOutputComponents << "\n" - << "MaxGeometryInputComponents " << DefaultTBuiltInResource.maxGeometryInputComponents << "\n" - << "MaxGeometryOutputComponents " << DefaultTBuiltInResource.maxGeometryOutputComponents << "\n" - << "MaxFragmentInputComponents " << DefaultTBuiltInResource.maxFragmentInputComponents << "\n" - << "MaxImageUnits " << DefaultTBuiltInResource.maxImageUnits << "\n" - << "MaxCombinedImageUnitsAndFragmentOutputs " << DefaultTBuiltInResource.maxCombinedImageUnitsAndFragmentOutputs << "\n" - << "MaxCombinedShaderOutputResources " << DefaultTBuiltInResource.maxCombinedShaderOutputResources << "\n" - << "MaxImageSamples " << DefaultTBuiltInResource.maxImageSamples << "\n" - << "MaxVertexImageUniforms " << DefaultTBuiltInResource.maxVertexImageUniforms << "\n" - << "MaxTessControlImageUniforms " << DefaultTBuiltInResource.maxTessControlImageUniforms << "\n" - << "MaxTessEvaluationImageUniforms " << DefaultTBuiltInResource.maxTessEvaluationImageUniforms << "\n" - << "MaxGeometryImageUniforms " << DefaultTBuiltInResource.maxGeometryImageUniforms << "\n" - << "MaxFragmentImageUniforms " << DefaultTBuiltInResource.maxFragmentImageUniforms << "\n" - << "MaxCombinedImageUniforms " << DefaultTBuiltInResource.maxCombinedImageUniforms << "\n" - << "MaxGeometryTextureImageUnits " << DefaultTBuiltInResource.maxGeometryTextureImageUnits << "\n" - << "MaxGeometryOutputVertices " << DefaultTBuiltInResource.maxGeometryOutputVertices << "\n" - << "MaxGeometryTotalOutputComponents " << DefaultTBuiltInResource.maxGeometryTotalOutputComponents << "\n" - << "MaxGeometryUniformComponents " << DefaultTBuiltInResource.maxGeometryUniformComponents << "\n" - << "MaxGeometryVaryingComponents " << DefaultTBuiltInResource.maxGeometryVaryingComponents << "\n" - << "MaxTessControlInputComponents " << DefaultTBuiltInResource.maxTessControlInputComponents << "\n" - << "MaxTessControlOutputComponents " << DefaultTBuiltInResource.maxTessControlOutputComponents << "\n" - << "MaxTessControlTextureImageUnits " << DefaultTBuiltInResource.maxTessControlTextureImageUnits << "\n" - << "MaxTessControlUniformComponents " << DefaultTBuiltInResource.maxTessControlUniformComponents << "\n" - << "MaxTessControlTotalOutputComponents " << DefaultTBuiltInResource.maxTessControlTotalOutputComponents << "\n" - << "MaxTessEvaluationInputComponents " << DefaultTBuiltInResource.maxTessEvaluationInputComponents << "\n" - << "MaxTessEvaluationOutputComponents " << DefaultTBuiltInResource.maxTessEvaluationOutputComponents << "\n" - << "MaxTessEvaluationTextureImageUnits " << DefaultTBuiltInResource.maxTessEvaluationTextureImageUnits << "\n" - << "MaxTessEvaluationUniformComponents " << DefaultTBuiltInResource.maxTessEvaluationUniformComponents << "\n" - << "MaxTessPatchComponents " << DefaultTBuiltInResource.maxTessPatchComponents << "\n" - << "MaxPatchVertices " << DefaultTBuiltInResource.maxPatchVertices << "\n" - << "MaxTessGenLevel " << DefaultTBuiltInResource.maxTessGenLevel << "\n" - << "MaxViewports " << DefaultTBuiltInResource.maxViewports << "\n" - << "MaxVertexAtomicCounters " << DefaultTBuiltInResource.maxVertexAtomicCounters << "\n" - << "MaxTessControlAtomicCounters " << DefaultTBuiltInResource.maxTessControlAtomicCounters << "\n" - << "MaxTessEvaluationAtomicCounters " << DefaultTBuiltInResource.maxTessEvaluationAtomicCounters << "\n" - << "MaxGeometryAtomicCounters " << DefaultTBuiltInResource.maxGeometryAtomicCounters << "\n" - << "MaxFragmentAtomicCounters " << DefaultTBuiltInResource.maxFragmentAtomicCounters << "\n" - << "MaxCombinedAtomicCounters " << DefaultTBuiltInResource.maxCombinedAtomicCounters << "\n" - << "MaxAtomicCounterBindings " << DefaultTBuiltInResource.maxAtomicCounterBindings << "\n" - << "MaxVertexAtomicCounterBuffers " << DefaultTBuiltInResource.maxVertexAtomicCounterBuffers << "\n" - << "MaxTessControlAtomicCounterBuffers " << DefaultTBuiltInResource.maxTessControlAtomicCounterBuffers << "\n" - << "MaxTessEvaluationAtomicCounterBuffers " << DefaultTBuiltInResource.maxTessEvaluationAtomicCounterBuffers << "\n" - << "MaxGeometryAtomicCounterBuffers " << DefaultTBuiltInResource.maxGeometryAtomicCounterBuffers << "\n" - << "MaxFragmentAtomicCounterBuffers " << DefaultTBuiltInResource.maxFragmentAtomicCounterBuffers << "\n" - << "MaxCombinedAtomicCounterBuffers " << DefaultTBuiltInResource.maxCombinedAtomicCounterBuffers << "\n" - << "MaxAtomicCounterBufferSize " << DefaultTBuiltInResource.maxAtomicCounterBufferSize << "\n" - << "MaxTransformFeedbackBuffers " << DefaultTBuiltInResource.maxTransformFeedbackBuffers << "\n" - << "MaxTransformFeedbackInterleavedComponents " << DefaultTBuiltInResource.maxTransformFeedbackInterleavedComponents << "\n" - << "MaxCullDistances " << DefaultTBuiltInResource.maxCullDistances << "\n" - << "MaxCombinedClipAndCullDistances " << DefaultTBuiltInResource.maxCombinedClipAndCullDistances << "\n" - << "MaxSamples " << DefaultTBuiltInResource.maxSamples << "\n" - - << "nonInductiveForLoops " << DefaultTBuiltInResource.limits.nonInductiveForLoops << "\n" - << "whileLoops " << DefaultTBuiltInResource.limits.whileLoops << "\n" - << "doWhileLoops " << DefaultTBuiltInResource.limits.doWhileLoops << "\n" - << "generalUniformIndexing " << DefaultTBuiltInResource.limits.generalUniformIndexing << "\n" - << "generalAttributeMatrixVectorIndexing " << DefaultTBuiltInResource.limits.generalAttributeMatrixVectorIndexing << "\n" - << "generalVaryingIndexing " << DefaultTBuiltInResource.limits.generalVaryingIndexing << "\n" - << "generalSamplerIndexing " << DefaultTBuiltInResource.limits.generalSamplerIndexing << "\n" - << "generalVariableIndexing " << DefaultTBuiltInResource.limits.generalVariableIndexing << "\n" - << "generalConstantMatrixVectorIndexing " << DefaultTBuiltInResource.limits.generalConstantMatrixVectorIndexing << "\n" - ; - - return ostream.str(); -} - -void DecodeResourceLimits(TBuiltInResource* resources, char* config) -{ - static const char* delims = " \t\n\r"; - - size_t pos = 0; - std::string configStr(config); - - while ((pos = configStr.find_first_not_of(delims, pos)) != std::string::npos) { - const size_t token_s = pos; - const size_t token_e = configStr.find_first_of(delims, token_s); - const size_t value_s = configStr.find_first_not_of(delims, token_e); - const size_t value_e = configStr.find_first_of(delims, value_s); - pos = value_e; - - // Faster to use compare(), but prefering readability. - const std::string tokenStr = configStr.substr(token_s, token_e-token_s); - const std::string valueStr = configStr.substr(value_s, value_e-value_s); - - if (value_s == std::string::npos || ! (valueStr[0] == '-' || isdigit(valueStr[0]))) { - printf("Error: '%s' bad .conf file. Each name must be followed by one number.\n", - valueStr.c_str()); - return; - } - - const int value = std::atoi(valueStr.c_str()); - - if (tokenStr == "MaxLights") - resources->maxLights = value; - else if (tokenStr == "MaxClipPlanes") - resources->maxClipPlanes = value; - else if (tokenStr == "MaxTextureUnits") - resources->maxTextureUnits = value; - else if (tokenStr == "MaxTextureCoords") - resources->maxTextureCoords = value; - else if (tokenStr == "MaxVertexAttribs") - resources->maxVertexAttribs = value; - else if (tokenStr == "MaxVertexUniformComponents") - resources->maxVertexUniformComponents = value; - else if (tokenStr == "MaxVaryingFloats") - resources->maxVaryingFloats = value; - else if (tokenStr == "MaxVertexTextureImageUnits") - resources->maxVertexTextureImageUnits = value; - else if (tokenStr == "MaxCombinedTextureImageUnits") - resources->maxCombinedTextureImageUnits = value; - else if (tokenStr == "MaxTextureImageUnits") - resources->maxTextureImageUnits = value; - else if (tokenStr == "MaxFragmentUniformComponents") - resources->maxFragmentUniformComponents = value; - else if (tokenStr == "MaxDrawBuffers") - resources->maxDrawBuffers = value; - else if (tokenStr == "MaxVertexUniformVectors") - resources->maxVertexUniformVectors = value; - else if (tokenStr == "MaxVaryingVectors") - resources->maxVaryingVectors = value; - else if (tokenStr == "MaxFragmentUniformVectors") - resources->maxFragmentUniformVectors = value; - else if (tokenStr == "MaxVertexOutputVectors") - resources->maxVertexOutputVectors = value; - else if (tokenStr == "MaxFragmentInputVectors") - resources->maxFragmentInputVectors = value; - else if (tokenStr == "MinProgramTexelOffset") - resources->minProgramTexelOffset = value; - else if (tokenStr == "MaxProgramTexelOffset") - resources->maxProgramTexelOffset = value; - else if (tokenStr == "MaxClipDistances") - resources->maxClipDistances = value; - else if (tokenStr == "MaxComputeWorkGroupCountX") - resources->maxComputeWorkGroupCountX = value; - else if (tokenStr == "MaxComputeWorkGroupCountY") - resources->maxComputeWorkGroupCountY = value; - else if (tokenStr == "MaxComputeWorkGroupCountZ") - resources->maxComputeWorkGroupCountZ = value; - else if (tokenStr == "MaxComputeWorkGroupSizeX") - resources->maxComputeWorkGroupSizeX = value; - else if (tokenStr == "MaxComputeWorkGroupSizeY") - resources->maxComputeWorkGroupSizeY = value; - else if (tokenStr == "MaxComputeWorkGroupSizeZ") - resources->maxComputeWorkGroupSizeZ = value; - else if (tokenStr == "MaxComputeUniformComponents") - resources->maxComputeUniformComponents = value; - else if (tokenStr == "MaxComputeTextureImageUnits") - resources->maxComputeTextureImageUnits = value; - else if (tokenStr == "MaxComputeImageUniforms") - resources->maxComputeImageUniforms = value; - else if (tokenStr == "MaxComputeAtomicCounters") - resources->maxComputeAtomicCounters = value; - else if (tokenStr == "MaxComputeAtomicCounterBuffers") - resources->maxComputeAtomicCounterBuffers = value; - else if (tokenStr == "MaxVaryingComponents") - resources->maxVaryingComponents = value; - else if (tokenStr == "MaxVertexOutputComponents") - resources->maxVertexOutputComponents = value; - else if (tokenStr == "MaxGeometryInputComponents") - resources->maxGeometryInputComponents = value; - else if (tokenStr == "MaxGeometryOutputComponents") - resources->maxGeometryOutputComponents = value; - else if (tokenStr == "MaxFragmentInputComponents") - resources->maxFragmentInputComponents = value; - else if (tokenStr == "MaxImageUnits") - resources->maxImageUnits = value; - else if (tokenStr == "MaxCombinedImageUnitsAndFragmentOutputs") - resources->maxCombinedImageUnitsAndFragmentOutputs = value; - else if (tokenStr == "MaxCombinedShaderOutputResources") - resources->maxCombinedShaderOutputResources = value; - else if (tokenStr == "MaxImageSamples") - resources->maxImageSamples = value; - else if (tokenStr == "MaxVertexImageUniforms") - resources->maxVertexImageUniforms = value; - else if (tokenStr == "MaxTessControlImageUniforms") - resources->maxTessControlImageUniforms = value; - else if (tokenStr == "MaxTessEvaluationImageUniforms") - resources->maxTessEvaluationImageUniforms = value; - else if (tokenStr == "MaxGeometryImageUniforms") - resources->maxGeometryImageUniforms = value; - else if (tokenStr == "MaxFragmentImageUniforms") - resources->maxFragmentImageUniforms = value; - else if (tokenStr == "MaxCombinedImageUniforms") - resources->maxCombinedImageUniforms = value; - else if (tokenStr == "MaxGeometryTextureImageUnits") - resources->maxGeometryTextureImageUnits = value; - else if (tokenStr == "MaxGeometryOutputVertices") - resources->maxGeometryOutputVertices = value; - else if (tokenStr == "MaxGeometryTotalOutputComponents") - resources->maxGeometryTotalOutputComponents = value; - else if (tokenStr == "MaxGeometryUniformComponents") - resources->maxGeometryUniformComponents = value; - else if (tokenStr == "MaxGeometryVaryingComponents") - resources->maxGeometryVaryingComponents = value; - else if (tokenStr == "MaxTessControlInputComponents") - resources->maxTessControlInputComponents = value; - else if (tokenStr == "MaxTessControlOutputComponents") - resources->maxTessControlOutputComponents = value; - else if (tokenStr == "MaxTessControlTextureImageUnits") - resources->maxTessControlTextureImageUnits = value; - else if (tokenStr == "MaxTessControlUniformComponents") - resources->maxTessControlUniformComponents = value; - else if (tokenStr == "MaxTessControlTotalOutputComponents") - resources->maxTessControlTotalOutputComponents = value; - else if (tokenStr == "MaxTessEvaluationInputComponents") - resources->maxTessEvaluationInputComponents = value; - else if (tokenStr == "MaxTessEvaluationOutputComponents") - resources->maxTessEvaluationOutputComponents = value; - else if (tokenStr == "MaxTessEvaluationTextureImageUnits") - resources->maxTessEvaluationTextureImageUnits = value; - else if (tokenStr == "MaxTessEvaluationUniformComponents") - resources->maxTessEvaluationUniformComponents = value; - else if (tokenStr == "MaxTessPatchComponents") - resources->maxTessPatchComponents = value; - else if (tokenStr == "MaxPatchVertices") - resources->maxPatchVertices = value; - else if (tokenStr == "MaxTessGenLevel") - resources->maxTessGenLevel = value; - else if (tokenStr == "MaxViewports") - resources->maxViewports = value; - else if (tokenStr == "MaxVertexAtomicCounters") - resources->maxVertexAtomicCounters = value; - else if (tokenStr == "MaxTessControlAtomicCounters") - resources->maxTessControlAtomicCounters = value; - else if (tokenStr == "MaxTessEvaluationAtomicCounters") - resources->maxTessEvaluationAtomicCounters = value; - else if (tokenStr == "MaxGeometryAtomicCounters") - resources->maxGeometryAtomicCounters = value; - else if (tokenStr == "MaxFragmentAtomicCounters") - resources->maxFragmentAtomicCounters = value; - else if (tokenStr == "MaxCombinedAtomicCounters") - resources->maxCombinedAtomicCounters = value; - else if (tokenStr == "MaxAtomicCounterBindings") - resources->maxAtomicCounterBindings = value; - else if (tokenStr == "MaxVertexAtomicCounterBuffers") - resources->maxVertexAtomicCounterBuffers = value; - else if (tokenStr == "MaxTessControlAtomicCounterBuffers") - resources->maxTessControlAtomicCounterBuffers = value; - else if (tokenStr == "MaxTessEvaluationAtomicCounterBuffers") - resources->maxTessEvaluationAtomicCounterBuffers = value; - else if (tokenStr == "MaxGeometryAtomicCounterBuffers") - resources->maxGeometryAtomicCounterBuffers = value; - else if (tokenStr == "MaxFragmentAtomicCounterBuffers") - resources->maxFragmentAtomicCounterBuffers = value; - else if (tokenStr == "MaxCombinedAtomicCounterBuffers") - resources->maxCombinedAtomicCounterBuffers = value; - else if (tokenStr == "MaxAtomicCounterBufferSize") - resources->maxAtomicCounterBufferSize = value; - else if (tokenStr == "MaxTransformFeedbackBuffers") - resources->maxTransformFeedbackBuffers = value; - else if (tokenStr == "MaxTransformFeedbackInterleavedComponents") - resources->maxTransformFeedbackInterleavedComponents = value; - else if (tokenStr == "MaxCullDistances") - resources->maxCullDistances = value; - else if (tokenStr == "MaxCombinedClipAndCullDistances") - resources->maxCombinedClipAndCullDistances = value; - else if (tokenStr == "MaxSamples") - resources->maxSamples = value; - else if (tokenStr == "nonInductiveForLoops") - resources->limits.nonInductiveForLoops = (value != 0); - else if (tokenStr == "whileLoops") - resources->limits.whileLoops = (value != 0); - else if (tokenStr == "doWhileLoops") - resources->limits.doWhileLoops = (value != 0); - else if (tokenStr == "generalUniformIndexing") - resources->limits.generalUniformIndexing = (value != 0); - else if (tokenStr == "generalAttributeMatrixVectorIndexing") - resources->limits.generalAttributeMatrixVectorIndexing = (value != 0); - else if (tokenStr == "generalVaryingIndexing") - resources->limits.generalVaryingIndexing = (value != 0); - else if (tokenStr == "generalSamplerIndexing") - resources->limits.generalSamplerIndexing = (value != 0); - else if (tokenStr == "generalVariableIndexing") - resources->limits.generalVariableIndexing = (value != 0); - else if (tokenStr == "generalConstantMatrixVectorIndexing") - resources->limits.generalConstantMatrixVectorIndexing = (value != 0); - else - printf("Warning: unrecognized limit (%s) in configuration file.\n", tokenStr.c_str()); - - } -} - -} // end namespace glslang diff --git a/External/glslang/StandAlone/ResourceLimits.h b/External/glslang/StandAlone/ResourceLimits.h deleted file mode 100644 index 9c3eb3e9..00000000 --- a/External/glslang/StandAlone/ResourceLimits.h +++ /dev/null @@ -1,57 +0,0 @@ -// -// Copyright (C) 2016 Google, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -#ifndef _STAND_ALONE_RESOURCE_LIMITS_INCLUDED_ -#define _STAND_ALONE_RESOURCE_LIMITS_INCLUDED_ - -#include - -#include "glslang/Include/ResourceLimits.h" - -namespace glslang { - -// These are the default resources for TBuiltInResources, used for both -// - parsing this string for the case where the user didn't supply one, -// - dumping out a template for user construction of a config file. -extern const TBuiltInResource DefaultTBuiltInResource; - -// Returns the DefaultTBuiltInResource as a human-readable string. -std::string GetDefaultTBuiltInResourceString(); - -// Decodes the resource limits from |config| to |resources|. -void DecodeResourceLimits(TBuiltInResource* resources, char* config); - -} // end namespace glslang - -#endif // _STAND_ALONE_RESOURCE_LIMITS_INCLUDED_ diff --git a/External/glslang/StandAlone/StandAlone.cpp b/External/glslang/StandAlone/StandAlone.cpp deleted file mode 100644 index 044662fe..00000000 --- a/External/glslang/StandAlone/StandAlone.cpp +++ /dev/null @@ -1,1489 +0,0 @@ -// -// 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. -// - -// this only applies to the standalone wrapper, not the front end in general -#ifndef _CRT_SECURE_NO_WARNINGS -#define _CRT_SECURE_NO_WARNINGS -#endif - -#include "ResourceLimits.h" -#include "Worklist.h" -#include "DirStackFileIncluder.h" -#include "./../glslang/Include/ShHandle.h" -#include "./../glslang/Include/revision.h" -#include "./../glslang/Public/ShaderLang.h" -#include "../SPIRV/GlslangToSpv.h" -#include "../SPIRV/GLSL.std.450.h" -#include "../SPIRV/doc.h" -#include "../SPIRV/disassemble.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../glslang/OSDependent/osinclude.h" - -extern "C" { - SH_IMPORT_EXPORT void ShOutputHtml(); -} - -// Command-line options -enum TOptions { - EOptionNone = 0, - EOptionIntermediate = (1 << 0), - EOptionSuppressInfolog = (1 << 1), - EOptionMemoryLeakMode = (1 << 2), - EOptionRelaxedErrors = (1 << 3), - EOptionGiveWarnings = (1 << 4), - EOptionLinkProgram = (1 << 5), - EOptionMultiThreaded = (1 << 6), - EOptionDumpConfig = (1 << 7), - EOptionDumpReflection = (1 << 8), - EOptionSuppressWarnings = (1 << 9), - EOptionDumpVersions = (1 << 10), - EOptionSpv = (1 << 11), - EOptionHumanReadableSpv = (1 << 12), - EOptionVulkanRules = (1 << 13), - EOptionDefaultDesktop = (1 << 14), - EOptionOutputPreprocessed = (1 << 15), - EOptionOutputHexadecimal = (1 << 16), - EOptionReadHlsl = (1 << 17), - EOptionCascadingErrors = (1 << 18), - EOptionAutoMapBindings = (1 << 19), - EOptionFlattenUniformArrays = (1 << 20), - EOptionNoStorageFormat = (1 << 21), - EOptionKeepUncalled = (1 << 22), - EOptionHlslOffsets = (1 << 23), - EOptionHlslIoMapping = (1 << 24), - EOptionAutoMapLocations = (1 << 25), - EOptionDebug = (1 << 26), - EOptionStdin = (1 << 27), - EOptionOptimizeDisable = (1 << 28), - EOptionOptimizeSize = (1 << 29), - EOptionInvertY = (1 << 30), - EOptionDumpBareVersion = (1 << 31), -}; -bool targetHlslFunctionality1 = false; - -// -// Return codes from main/exit(). -// -enum TFailCode { - ESuccess = 0, - EFailUsage, - EFailCompile, - EFailLink, - EFailCompilerCreate, - EFailThreadCreate, - EFailLinkerCreate -}; - -// -// Forward declarations. -// -EShLanguage FindLanguage(const std::string& name, bool parseSuffix=true); -void CompileFile(const char* fileName, ShHandle); -void usage(); -char* ReadFileData(const char* fileName); -void FreeFileData(char* data); -void InfoLogMsg(const char* msg, const char* name, const int num); - -// Globally track if any compile or link failure. -bool CompileFailed = false; -bool LinkFailed = false; - -// array of unique places to leave the shader names and infologs for the asynchronous compiles -std::vector> WorkItems; - -TBuiltInResource Resources; -std::string ConfigFile; - -// -// Parse either a .conf file provided by the user or the default from glslang::DefaultTBuiltInResource -// -void ProcessConfigFile() -{ - if (ConfigFile.size() == 0) - Resources = glslang::DefaultTBuiltInResource; - else { - char* configString = ReadFileData(ConfigFile.c_str()); - glslang::DecodeResourceLimits(&Resources, configString); - FreeFileData(configString); - } -} - -int Options = 0; -const char* ExecutableName = nullptr; -const char* binaryFileName = nullptr; -const char* entryPointName = nullptr; -const char* sourceEntryPointName = nullptr; -const char* shaderStageName = nullptr; -const char* variableName = nullptr; -bool HlslEnable16BitTypes = false; -std::vector IncludeDirectoryList; -int ClientInputSemanticsVersion = 100; // maps to, say, #define VULKAN 100 -glslang::EShTargetClientVersion VulkanClientVersion = - glslang::EShTargetVulkan_1_0; // would map to, say, Vulkan 1.0 -glslang::EShTargetClientVersion OpenGLClientVersion = - glslang::EShTargetOpenGL_450; // doesn't influence anything yet, but maps to OpenGL 4.50 -glslang::EShTargetLanguageVersion TargetVersion = - glslang::EShTargetSpv_1_0; // maps to, say, SPIR-V 1.0 -std::vector Processes; // what should be recorded by OpModuleProcessed, or equivalent - -// Per descriptor-set binding base data -typedef std::map TPerSetBaseBinding; - -std::array, glslang::EResCount> baseBinding; -std::array, glslang::EResCount> baseBindingForSet; -std::array, EShLangCount> baseResourceSetBinding; - -// Add things like "#define ..." to a preamble to use in the beginning of the shader. -class TPreamble { -public: - TPreamble() { } - - bool isSet() const { return text.size() > 0; } - const char* get() const { return text.c_str(); } - - // #define... - void addDef(std::string def) - { - text.append("#define "); - fixLine(def); - - Processes.push_back("D"); - Processes.back().append(def); - - // The first "=" needs to turn into a space - const size_t equal = def.find_first_of("="); - if (equal != def.npos) - def[equal] = ' '; - - text.append(def); - text.append("\n"); - } - - // #undef... - void addUndef(std::string undef) - { - text.append("#undef "); - fixLine(undef); - - Processes.push_back("U"); - Processes.back().append(undef); - - text.append(undef); - text.append("\n"); - } - -protected: - void fixLine(std::string& line) - { - // Can't go past a newline in the line - const size_t end = line.find_first_of("\n"); - if (end != line.npos) - line = line.substr(0, end); - } - - std::string text; // contents of preamble -}; - -TPreamble UserPreamble; - -// -// Create the default name for saving a binary if -o is not provided. -// -const char* GetBinaryName(EShLanguage stage) -{ - const char* name; - if (binaryFileName == nullptr) { - switch (stage) { - case EShLangVertex: name = "vert.spv"; break; - case EShLangTessControl: name = "tesc.spv"; break; - case EShLangTessEvaluation: name = "tese.spv"; break; - case EShLangGeometry: name = "geom.spv"; break; - case EShLangFragment: name = "frag.spv"; break; - case EShLangCompute: name = "comp.spv"; break; - default: name = "unknown"; break; - } - } else - name = binaryFileName; - - return name; -} - -// -// *.conf => this is a config file that can set limits/resources -// -bool SetConfigFile(const std::string& name) -{ - if (name.size() < 5) - return false; - - if (name.compare(name.size() - 5, 5, ".conf") == 0) { - ConfigFile = name; - return true; - } - - return false; -} - -// -// Give error and exit with failure code. -// -void Error(const char* message) -{ - fprintf(stderr, "%s: Error %s (use -h for usage)\n", ExecutableName, message); - exit(EFailUsage); -} - -// -// Process an optional binding base of one the forms: -// --argname [stage] base // base for stage (if given) or all stages (if not) -// --argname [stage] [base set]... // set/base pairs: set the base for given binding set. - -// Where stage is one of the forms accepted by FindLanguage, and base is an integer -// -void ProcessBindingBase(int& argc, char**& argv, glslang::TResourceType res) -{ - if (argc < 2) - usage(); - - EShLanguage lang = EShLangCount; - int singleBase = 0; - TPerSetBaseBinding perSetBase; - int arg = 1; - - // Parse stage, if given - if (!isdigit(argv[arg][0])) { - if (argc < 3) // this form needs one more argument - usage(); - - lang = FindLanguage(argv[arg++], false); - } - - if ((argc - arg) > 2 && isdigit(argv[arg+0][0]) && isdigit(argv[arg+1][0])) { - // Parse a per-set binding base - while ((argc - arg) > 2 && isdigit(argv[arg+0][0]) && isdigit(argv[arg+1][0])) { - const int baseNum = atoi(argv[arg++]); - const int setNum = atoi(argv[arg++]); - perSetBase[setNum] = baseNum; - } - } else { - // Parse single binding base - singleBase = atoi(argv[arg++]); - } - - argc -= (arg-1); - argv += (arg-1); - - // Set one or all languages - const int langMin = (lang < EShLangCount) ? lang+0 : 0; - const int langMax = (lang < EShLangCount) ? lang+1 : EShLangCount; - - for (int lang = langMin; lang < langMax; ++lang) { - if (!perSetBase.empty()) - baseBindingForSet[res][lang] = perSetBase; - else - baseBinding[res][lang] = singleBase; - } -} - -void ProcessResourceSetBindingBase(int& argc, char**& argv, std::array, EShLangCount>& base) -{ - if (argc < 2) - usage(); - - if (!isdigit(argv[1][0])) { - if (argc < 3) // this form needs one more argument - usage(); - - // Parse form: --argname stage [regname set base...], or: - // --argname stage set - const EShLanguage lang = FindLanguage(argv[1], false); - - argc--; - argv++; - - while (argc > 1 && argv[1] != nullptr && argv[1][0] != '-') { - base[lang].push_back(argv[1]); - - argc--; - argv++; - } - - // Must have one arg, or a multiple of three (for [regname set binding] triples) - if (base[lang].size() != 1 && (base[lang].size() % 3) != 0) - usage(); - - } else { - // Parse form: --argname set - for (int lang=0; lang>& workItems, int argc, char* argv[]) -{ - for (int res = 0; res < glslang::EResCount; ++res) - baseBinding[res].fill(0); - - ExecutableName = argv[0]; - workItems.reserve(argc); - - const auto bumpArg = [&]() { - if (argc > 0) { - argc--; - argv++; - } - }; - - // read a string directly attached to a single-letter option - const auto getStringOperand = [&](const char* desc) { - if (argv[0][2] == 0) { - printf("%s must immediately follow option (no spaces)\n", desc); - exit(EFailUsage); - } - return argv[0] + 2; - }; - - // read a number attached to a single-letter option - const auto getAttachedNumber = [&](const char* desc) { - int num = atoi(argv[0] + 2); - if (num == 0) { - printf("%s: expected attached non-0 number\n", desc); - exit(EFailUsage); - } - return num; - }; - - // minimum needed (without overriding something else) to target Vulkan SPIR-V - const auto setVulkanSpv = []() { - Options |= EOptionSpv; - Options |= EOptionVulkanRules; - Options |= EOptionLinkProgram; - }; - - // minimum needed (without overriding something else) to target OpenGL SPIR-V - const auto setOpenGlSpv = []() { - Options |= EOptionSpv; - Options |= EOptionLinkProgram; - // undo a -H default to Vulkan - Options &= ~EOptionVulkanRules; - }; - - for (bumpArg(); argc >= 1; bumpArg()) { - if (argv[0][0] == '-') { - switch (argv[0][1]) { - case '-': - { - std::string lowerword(argv[0]+2); - std::transform(lowerword.begin(), lowerword.end(), lowerword.begin(), ::tolower); - - // handle --word style options - if (lowerword == "auto-map-bindings" || // synonyms - lowerword == "auto-map-binding" || - lowerword == "amb") { - Options |= EOptionAutoMapBindings; - } else if (lowerword == "auto-map-locations" || // synonyms - lowerword == "aml") { - Options |= EOptionAutoMapLocations; - } else if (lowerword == "client") { - if (argc > 1) { - if (strcmp(argv[1], "vulkan100") == 0) - setVulkanSpv(); - else if (strcmp(argv[1], "opengl100") == 0) - setOpenGlSpv(); - else - Error("--client expects vulkan100 or opengl100"); - } - bumpArg(); - } else if (lowerword == "flatten-uniform-arrays" || // synonyms - lowerword == "flatten-uniform-array" || - lowerword == "fua") { - Options |= EOptionFlattenUniformArrays; - } else if (lowerword == "hlsl-offsets") { - Options |= EOptionHlslOffsets; - } else if (lowerword == "hlsl-iomap" || - lowerword == "hlsl-iomapper" || - lowerword == "hlsl-iomapping") { - Options |= EOptionHlslIoMapping; - } else if (lowerword == "hlsl-enable-16bit-types") { - HlslEnable16BitTypes = true; - } else if (lowerword == "invert-y" || // synonyms - lowerword == "iy") { - Options |= EOptionInvertY; - } else if (lowerword == "keep-uncalled" || // synonyms - lowerword == "ku") { - Options |= EOptionKeepUncalled; - } else if (lowerword == "no-storage-format" || // synonyms - lowerword == "nsf") { - Options |= EOptionNoStorageFormat; - } else if (lowerword == "relaxed-errors") { - Options |= EOptionRelaxedErrors; - } else if (lowerword == "resource-set-bindings" || // synonyms - lowerword == "resource-set-binding" || - lowerword == "rsb") { - ProcessResourceSetBindingBase(argc, argv, baseResourceSetBinding); - } else if (lowerword == "shift-image-bindings" || // synonyms - lowerword == "shift-image-binding" || - lowerword == "sib") { - ProcessBindingBase(argc, argv, glslang::EResImage); - } else if (lowerword == "shift-sampler-bindings" || // synonyms - lowerword == "shift-sampler-binding" || - lowerword == "ssb") { - ProcessBindingBase(argc, argv, glslang::EResSampler); - } else if (lowerword == "shift-uav-bindings" || // synonyms - lowerword == "shift-uav-binding" || - lowerword == "suavb") { - ProcessBindingBase(argc, argv, glslang::EResUav); - } else if (lowerword == "shift-texture-bindings" || // synonyms - lowerword == "shift-texture-binding" || - lowerword == "stb") { - ProcessBindingBase(argc, argv, glslang::EResTexture); - } else if (lowerword == "shift-ubo-bindings" || // synonyms - lowerword == "shift-ubo-binding" || - lowerword == "shift-cbuffer-bindings" || - lowerword == "shift-cbuffer-binding" || - lowerword == "sub" || - lowerword == "scb") { - ProcessBindingBase(argc, argv, glslang::EResUbo); - } else if (lowerword == "shift-ssbo-bindings" || // synonyms - lowerword == "shift-ssbo-binding" || - lowerword == "sbb") { - ProcessBindingBase(argc, argv, glslang::EResSsbo); - } else if (lowerword == "source-entrypoint" || // synonyms - lowerword == "sep") { - if (argc <= 1) - Error("no provided for --source-entrypoint"); - sourceEntryPointName = argv[1]; - bumpArg(); - break; - } else if (lowerword == "stdin") { - Options |= EOptionStdin; - shaderStageName = argv[1]; - } else if (lowerword == "suppress-warnings") { - Options |= EOptionSuppressWarnings; - } else if (lowerword == "target-env") { - if (argc > 1) { - if (strcmp(argv[1], "vulkan1.0") == 0) { - setVulkanSpv(); - VulkanClientVersion = glslang::EShTargetVulkan_1_0; - } else if (strcmp(argv[1], "vulkan1.1") == 0) { - setVulkanSpv(); - TargetVersion = glslang::EShTargetSpv_1_3; - VulkanClientVersion = glslang::EShTargetVulkan_1_1; - } else if (strcmp(argv[1], "opengl") == 0) { - setOpenGlSpv(); - OpenGLClientVersion = glslang::EShTargetOpenGL_450; - } else - Error("--target-env expected vulkan1.0, vulkan1.1, or opengl"); - } - bumpArg(); - } else if (lowerword == "variable-name" || // synonyms - lowerword == "vn") { - Options |= EOptionOutputHexadecimal; - if (argc <= 1) - Error("no provided for --variable-name"); - variableName = argv[1]; - bumpArg(); - break; - } else if (lowerword == "version") { - Options |= EOptionDumpVersions; - } else { - usage(); - } - } - break; - case 'C': - Options |= EOptionCascadingErrors; - break; - case 'D': - if (argv[0][2] == 0) - Options |= EOptionReadHlsl; - else - UserPreamble.addDef(getStringOperand("-D macro name")); - break; - case 'E': - Options |= EOptionOutputPreprocessed; - break; - case 'G': - // OpenGL Client - setOpenGlSpv(); - if (argv[0][2] != 0) - ClientInputSemanticsVersion = getAttachedNumber("-G client input semantics"); - break; - case 'H': - Options |= EOptionHumanReadableSpv; - if ((Options & EOptionSpv) == 0) { - // default to Vulkan - setVulkanSpv(); - } - break; - case 'I': - IncludeDirectoryList.push_back(getStringOperand("-I include path")); - break; - case 'O': - if (argv[0][2] == 'd') - Options |= EOptionOptimizeDisable; - else if (argv[0][2] == 's') -#if ENABLE_OPT - Options |= EOptionOptimizeSize; -#else - Error("-Os not available; optimizer not linked"); -#endif - else - Error("unknown -O option"); - break; - case 'S': - if (argc <= 1) - Error("no specified for -S"); - shaderStageName = argv[1]; - bumpArg(); - break; - case 'U': - UserPreamble.addUndef(getStringOperand("-U: macro name")); - break; - case 'V': - setVulkanSpv(); - if (argv[0][2] != 0) - ClientInputSemanticsVersion = getAttachedNumber("-V client input semantics"); - break; - case 'c': - Options |= EOptionDumpConfig; - break; - case 'd': - if (strncmp(&argv[0][1], "dumpversion", strlen(&argv[0][1]) + 1) == 0 || - strncmp(&argv[0][1], "dumpfullversion", strlen(&argv[0][1]) + 1) == 0) - Options |= EOptionDumpBareVersion; - else - Options |= EOptionDefaultDesktop; - break; - case 'e': - // HLSL todo: entry point handle needs much more sophistication. - // This is okay for one compilation unit with one entry point. - entryPointName = argv[1]; - if (argc <= 1) - Error("no provided for -e"); - bumpArg(); - break; - case 'f': - if (strcmp(&argv[0][2], "hlsl_functionality1") == 0) - targetHlslFunctionality1 = true; - else - Error("-f: expected hlsl_functionality1"); - break; - case 'g': - Options |= EOptionDebug; - break; - case 'h': - usage(); - break; - case 'i': - Options |= EOptionIntermediate; - break; - case 'l': - Options |= EOptionLinkProgram; - break; - case 'm': - Options |= EOptionMemoryLeakMode; - break; - case 'o': - if (argc <= 1) - Error("no provided for -o"); - binaryFileName = argv[1]; - bumpArg(); - break; - case 'q': - Options |= EOptionDumpReflection; - break; - case 'r': - Options |= EOptionRelaxedErrors; - break; - case 's': - Options |= EOptionSuppressInfolog; - break; - case 't': - Options |= EOptionMultiThreaded; - break; - case 'v': - Options |= EOptionDumpVersions; - break; - case 'w': - Options |= EOptionSuppressWarnings; - break; - case 'x': - Options |= EOptionOutputHexadecimal; - break; - default: - usage(); - break; - } - } else { - std::string name(argv[0]); - if (! SetConfigFile(name)) { - workItems.push_back(std::unique_ptr(new glslang::TWorkItem(name))); - } - } - } - - // Make sure that -S is always specified if --stdin is specified - if ((Options & EOptionStdin) && shaderStageName == nullptr) - Error("must provide -S when --stdin is given"); - - // Make sure that -E is not specified alongside linking (which includes SPV generation) - if ((Options & EOptionOutputPreprocessed) && (Options & EOptionLinkProgram)) - Error("can't use -E when linking is selected"); - - // -o or -x makes no sense if there is no target binary - if (binaryFileName && (Options & EOptionSpv) == 0) - Error("no binary generation requested (e.g., -V)"); - - if ((Options & EOptionFlattenUniformArrays) != 0 && - (Options & EOptionReadHlsl) == 0) - Error("uniform array flattening only valid when compiling HLSL source."); -} - -// -// Translate the meaningful subset of command-line options to parser-behavior options. -// -void SetMessageOptions(EShMessages& messages) -{ - if (Options & EOptionRelaxedErrors) - messages = (EShMessages)(messages | EShMsgRelaxedErrors); - if (Options & EOptionIntermediate) - messages = (EShMessages)(messages | EShMsgAST); - if (Options & EOptionSuppressWarnings) - messages = (EShMessages)(messages | EShMsgSuppressWarnings); - if (Options & EOptionSpv) - messages = (EShMessages)(messages | EShMsgSpvRules); - if (Options & EOptionVulkanRules) - messages = (EShMessages)(messages | EShMsgVulkanRules); - if (Options & EOptionOutputPreprocessed) - messages = (EShMessages)(messages | EShMsgOnlyPreprocessor); - if (Options & EOptionReadHlsl) - messages = (EShMessages)(messages | EShMsgReadHlsl); - if (Options & EOptionCascadingErrors) - messages = (EShMessages)(messages | EShMsgCascadingErrors); - if (Options & EOptionKeepUncalled) - messages = (EShMessages)(messages | EShMsgKeepUncalled); - if (Options & EOptionHlslOffsets) - messages = (EShMessages)(messages | EShMsgHlslOffsets); - if (Options & EOptionDebug) - messages = (EShMessages)(messages | EShMsgDebugInfo); - if (HlslEnable16BitTypes) - messages = (EShMessages)(messages | EShMsgHlslEnable16BitTypes); - if ((Options & EOptionOptimizeDisable) || !ENABLE_OPT) - messages = (EShMessages)(messages | EShMsgHlslLegalization); -} - -// -// Thread entry point, for non-linking asynchronous mode. -// -void CompileShaders(glslang::TWorklist& worklist) -{ - if (Options & EOptionDebug) - Error("cannot generate debug information unless linking to generate code"); - - glslang::TWorkItem* workItem; - if (Options & EOptionStdin) { - worklist.remove(workItem); - ShHandle compiler = ShConstructCompiler(FindLanguage("stdin"), Options); - if (compiler == 0) - return; - - CompileFile("stdin", compiler); - - if (! (Options & EOptionSuppressInfolog)) - workItem->results = ShGetInfoLog(compiler); - - ShDestruct(compiler); - } else { - while (worklist.remove(workItem)) { - ShHandle compiler = ShConstructCompiler(FindLanguage(workItem->name), Options); - if (compiler == 0) - return; - - CompileFile(workItem->name.c_str(), compiler); - - if (! (Options & EOptionSuppressInfolog)) - workItem->results = ShGetInfoLog(compiler); - - ShDestruct(compiler); - } - } -} - -// Outputs the given string, but only if it is non-null and non-empty. -// This prevents erroneous newlines from appearing. -void PutsIfNonEmpty(const char* str) -{ - if (str && str[0]) { - puts(str); - } -} - -// Outputs the given string to stderr, but only if it is non-null and non-empty. -// This prevents erroneous newlines from appearing. -void StderrIfNonEmpty(const char* str) -{ - if (str && str[0]) - fprintf(stderr, "%s\n", str); -} - -// Simple bundling of what makes a compilation unit for ease in passing around, -// and separation of handling file IO versus API (programmatic) compilation. -struct ShaderCompUnit { - EShLanguage stage; - static const int maxCount = 1; - int count; // live number of strings/names - const char* text[maxCount]; // memory owned/managed externally - std::string fileName[maxCount]; // hold's the memory, but... - const char* fileNameList[maxCount]; // downstream interface wants pointers - - ShaderCompUnit(EShLanguage stage) : stage(stage), count(0) { } - - ShaderCompUnit(const ShaderCompUnit& rhs) - { - stage = rhs.stage; - count = rhs.count; - for (int i = 0; i < count; ++i) { - fileName[i] = rhs.fileName[i]; - text[i] = rhs.text[i]; - fileNameList[i] = rhs.fileName[i].c_str(); - } - } - - void addString(std::string& ifileName, const char* itext) - { - assert(count < maxCount); - fileName[count] = ifileName; - text[count] = itext; - fileNameList[count] = fileName[count].c_str(); - ++count; - } -}; - -// -// For linking mode: Will independently parse each compilation unit, but then put them -// in the same program and link them together, making at most one linked module per -// pipeline stage. -// -// Uses the new C++ interface instead of the old handle-based interface. -// - -void CompileAndLinkShaderUnits(std::vector compUnits) -{ - // keep track of what to free - std::list shaders; - - EShMessages messages = EShMsgDefault; - SetMessageOptions(messages); - - // - // Per-shader processing... - // - - glslang::TProgram& program = *new glslang::TProgram; - for (auto it = compUnits.cbegin(); it != compUnits.cend(); ++it) { - const auto &compUnit = *it; - glslang::TShader* shader = new glslang::TShader(compUnit.stage); - shader->setStringsWithLengthsAndNames(compUnit.text, NULL, compUnit.fileNameList, compUnit.count); - if (entryPointName) // HLSL todo: this needs to be tracked per compUnits - shader->setEntryPoint(entryPointName); - if (sourceEntryPointName) { - if (entryPointName == nullptr) - printf("Warning: Changing source entry point name without setting an entry-point name.\n" - "Use '-e '.\n"); - shader->setSourceEntryPoint(sourceEntryPointName); - } - if (UserPreamble.isSet()) - shader->setPreamble(UserPreamble.get()); - shader->addProcesses(Processes); - - // Set IO mapper binding shift values - for (int r = 0; r < glslang::EResCount; ++r) { - const glslang::TResourceType res = glslang::TResourceType(r); - - // Set base bindings - shader->setShiftBinding(res, baseBinding[res][compUnit.stage]); - - // Set bindings for particular resource sets - // TODO: use a range based for loop here, when available in all environments. - for (auto i = baseBindingForSet[res][compUnit.stage].begin(); - i != baseBindingForSet[res][compUnit.stage].end(); ++i) - shader->setShiftBindingForSet(res, i->second, i->first); - } - - shader->setFlattenUniformArrays((Options & EOptionFlattenUniformArrays) != 0); - shader->setNoStorageFormat((Options & EOptionNoStorageFormat) != 0); - shader->setResourceSetBinding(baseResourceSetBinding[compUnit.stage]); - - if (Options & EOptionHlslIoMapping) - shader->setHlslIoMapping(true); - - if (Options & EOptionAutoMapBindings) - shader->setAutoMapBindings(true); - - if (Options & EOptionAutoMapLocations) - shader->setAutoMapLocations(true); - - if (Options & EOptionInvertY) - shader->setInvertY(true); - - // Set up the environment, some subsettings take precedence over earlier - // ways of setting things. - if (Options & EOptionSpv) { - if (Options & EOptionVulkanRules) { - shader->setEnvInput((Options & EOptionReadHlsl) ? glslang::EShSourceHlsl - : glslang::EShSourceGlsl, - compUnit.stage, glslang::EShClientVulkan, ClientInputSemanticsVersion); - shader->setEnvClient(glslang::EShClientVulkan, VulkanClientVersion); - } else { - shader->setEnvInput((Options & EOptionReadHlsl) ? glslang::EShSourceHlsl - : glslang::EShSourceGlsl, - compUnit.stage, glslang::EShClientOpenGL, ClientInputSemanticsVersion); - shader->setEnvClient(glslang::EShClientOpenGL, OpenGLClientVersion); - } - shader->setEnvTarget(glslang::EShTargetSpv, TargetVersion); - if (targetHlslFunctionality1) - shader->setEnvTargetHlslFunctionality1(); - } - - shaders.push_back(shader); - - const int defaultVersion = Options & EOptionDefaultDesktop ? 110 : 100; - - DirStackFileIncluder includer; - std::for_each(IncludeDirectoryList.rbegin(), IncludeDirectoryList.rend(), [&includer](const std::string& dir) { - includer.pushExternalLocalDirectory(dir); }); - if (Options & EOptionOutputPreprocessed) { - std::string str; - if (shader->preprocess(&Resources, defaultVersion, ENoProfile, false, false, - messages, &str, includer)) { - PutsIfNonEmpty(str.c_str()); - } else { - CompileFailed = true; - } - StderrIfNonEmpty(shader->getInfoLog()); - StderrIfNonEmpty(shader->getInfoDebugLog()); - continue; - } - if (! shader->parse(&Resources, defaultVersion, false, messages, includer)) - CompileFailed = true; - - program.addShader(shader); - - if (! (Options & EOptionSuppressInfolog) && - ! (Options & EOptionMemoryLeakMode)) { - PutsIfNonEmpty(compUnit.fileName[0].c_str()); - PutsIfNonEmpty(shader->getInfoLog()); - PutsIfNonEmpty(shader->getInfoDebugLog()); - } - } - - // - // Program-level processing... - // - - // Link - if (! (Options & EOptionOutputPreprocessed) && ! program.link(messages)) - LinkFailed = true; - - // Map IO - if (Options & EOptionSpv) { - if (!program.mapIO()) - LinkFailed = true; - } - - // Report - if (! (Options & EOptionSuppressInfolog) && - ! (Options & EOptionMemoryLeakMode)) { - PutsIfNonEmpty(program.getInfoLog()); - PutsIfNonEmpty(program.getInfoDebugLog()); - } - - // Reflect - if (Options & EOptionDumpReflection) { - program.buildReflection(); - program.dumpReflection(); - } - - // Dump SPIR-V - if (Options & EOptionSpv) { - if (CompileFailed || LinkFailed) - printf("SPIR-V is not generated for failed compile or link\n"); - else { - for (int stage = 0; stage < EShLangCount; ++stage) { - if (program.getIntermediate((EShLanguage)stage)) { - std::vector spirv; - std::string warningsErrors; - spv::SpvBuildLogger logger; - glslang::SpvOptions spvOptions; - if (Options & EOptionDebug) - spvOptions.generateDebugInfo = true; - spvOptions.disableOptimizer = (Options & EOptionOptimizeDisable) != 0; - spvOptions.optimizeSize = (Options & EOptionOptimizeSize) != 0; - glslang::GlslangToSpv(*program.getIntermediate((EShLanguage)stage), spirv, &logger, &spvOptions); - - // Dump the spv to a file or stdout, etc., but only if not doing - // memory/perf testing, as it's not internal to programmatic use. - if (! (Options & EOptionMemoryLeakMode)) { - printf("%s", logger.getAllMessages().c_str()); - if (Options & EOptionOutputHexadecimal) { - glslang::OutputSpvHex(spirv, GetBinaryName((EShLanguage)stage), variableName); - } else { - glslang::OutputSpvBin(spirv, GetBinaryName((EShLanguage)stage)); - } - if (Options & EOptionHumanReadableSpv) { - spv::Disassemble(std::cout, spirv); - } - } - } - } - } - } - - // Free everything up, program has to go before the shaders - // because it might have merged stuff from the shaders, and - // the stuff from the shaders has to have its destructors called - // before the pools holding the memory in the shaders is freed. - delete &program; - while (shaders.size() > 0) { - delete shaders.back(); - shaders.pop_back(); - } -} - -// -// Do file IO part of compile and link, handing off the pure -// API/programmatic mode to CompileAndLinkShaderUnits(), which can -// be put in a loop for testing memory footprint and performance. -// -// This is just for linking mode: meaning all the shaders will be put into the -// the same program linked together. -// -// This means there are a limited number of work items (not multi-threading mode) -// and that the point is testing at the linking level. Hence, to enable -// performance and memory testing, the actual compile/link can be put in -// a loop, independent of processing the work items and file IO. -// -void CompileAndLinkShaderFiles(glslang::TWorklist& Worklist) -{ - std::vector compUnits; - - // If this is using stdin, we can't really detect multiple different file - // units by input type. We need to assume that we're just being given one - // file of a certain type. - if ((Options & EOptionStdin) != 0) { - ShaderCompUnit compUnit(FindLanguage("stdin")); - std::istreambuf_iterator begin(std::cin), end; - std::string tempString(begin, end); - char* fileText = strdup(tempString.c_str()); - std::string fileName = "stdin"; - compUnit.addString(fileName, fileText); - compUnits.push_back(compUnit); - } else { - // Transfer all the work items from to a simple list of - // of compilation units. (We don't care about the thread - // work-item distribution properties in this path, which - // is okay due to the limited number of shaders, know since - // they are all getting linked together.) - glslang::TWorkItem* workItem; - while (Worklist.remove(workItem)) { - ShaderCompUnit compUnit(FindLanguage(workItem->name)); - char* fileText = ReadFileData(workItem->name.c_str()); - if (fileText == nullptr) - usage(); - compUnit.addString(workItem->name, fileText); - compUnits.push_back(compUnit); - } - } - - // Actual call to programmatic processing of compile and link, - // in a loop for testing memory and performance. This part contains - // all the perf/memory that a programmatic consumer will care about. - for (int i = 0; i < ((Options & EOptionMemoryLeakMode) ? 100 : 1); ++i) { - for (int j = 0; j < ((Options & EOptionMemoryLeakMode) ? 100 : 1); ++j) - CompileAndLinkShaderUnits(compUnits); - - if (Options & EOptionMemoryLeakMode) - glslang::OS_DumpMemoryCounters(); - } - - // free memory from ReadFileData, which got stored in a const char* - // as the first string above - for (auto it = compUnits.begin(); it != compUnits.end(); ++it) - FreeFileData(const_cast(it->text[0])); -} - -int singleMain() -{ - glslang::TWorklist workList; - std::for_each(WorkItems.begin(), WorkItems.end(), [&workList](std::unique_ptr& item) { - assert(item); - workList.add(item.get()); - }); - - if (Options & EOptionDumpConfig) { - printf("%s", glslang::GetDefaultTBuiltInResourceString().c_str()); - if (workList.empty()) - return ESuccess; - } - - if (Options & EOptionDumpBareVersion) { - printf("%d.%d.%d\n", - glslang::GetSpirvGeneratorVersion(), GLSLANG_MINOR_VERSION, GLSLANG_PATCH_LEVEL); - if (workList.empty()) - return ESuccess; - } else if (Options & EOptionDumpVersions) { - printf("Glslang Version: %d.%d.%d\n", - glslang::GetSpirvGeneratorVersion(), GLSLANG_MINOR_VERSION, GLSLANG_PATCH_LEVEL); - printf("ESSL Version: %s\n", glslang::GetEsslVersionString()); - printf("GLSL Version: %s\n", glslang::GetGlslVersionString()); - std::string spirvVersion; - glslang::GetSpirvVersion(spirvVersion); - printf("SPIR-V Version %s\n", spirvVersion.c_str()); - printf("GLSL.std.450 Version %d, Revision %d\n", GLSLstd450Version, GLSLstd450Revision); - printf("Khronos Tool ID %d\n", glslang::GetKhronosToolId()); - printf("SPIR-V Generator Version %d\n", glslang::GetSpirvGeneratorVersion()); - printf("GL_KHR_vulkan_glsl version %d\n", 100); - printf("ARB_GL_gl_spirv version %d\n", 100); - if (workList.empty()) - return ESuccess; - } - - if (workList.empty() && ((Options & EOptionStdin) == 0)) { - usage(); - } - - if (Options & EOptionStdin) { - WorkItems.push_back(std::unique_ptr{new glslang::TWorkItem("stdin")}); - workList.add(WorkItems.back().get()); - } - - ProcessConfigFile(); - - // - // Two modes: - // 1) linking all arguments together, single-threaded, new C++ interface - // 2) independent arguments, can be tackled by multiple asynchronous threads, for testing thread safety, using the old handle interface - // - if (Options & EOptionLinkProgram || - Options & EOptionOutputPreprocessed) { - glslang::InitializeProcess(); - glslang::InitializeProcess(); // also test reference counting of users - glslang::InitializeProcess(); // also test reference counting of users - glslang::FinalizeProcess(); // also test reference counting of users - glslang::FinalizeProcess(); // also test reference counting of users - CompileAndLinkShaderFiles(workList); - glslang::FinalizeProcess(); - } else { - ShInitialize(); - ShInitialize(); // also test reference counting of users - ShFinalize(); // also test reference counting of users - - bool printShaderNames = workList.size() > 1; - - if (Options & EOptionMultiThreaded) { - std::array threads; - for (unsigned int t = 0; t < threads.size(); ++t) { - threads[t] = std::thread(CompileShaders, std::ref(workList)); - if (threads[t].get_id() == std::thread::id()) { - fprintf(stderr, "Failed to create thread\n"); - return EFailThreadCreate; - } - } - - std::for_each(threads.begin(), threads.end(), [](std::thread& t) { t.join(); }); - } else - CompileShaders(workList); - - // Print out all the resulting infologs - for (size_t w = 0; w < WorkItems.size(); ++w) { - if (WorkItems[w]) { - if (printShaderNames || WorkItems[w]->results.size() > 0) - PutsIfNonEmpty(WorkItems[w]->name.c_str()); - PutsIfNonEmpty(WorkItems[w]->results.c_str()); - } - } - - ShFinalize(); - } - - if (CompileFailed) - return EFailCompile; - if (LinkFailed) - return EFailLink; - - return 0; -} - -int C_DECL main(int argc, char* argv[]) -{ - ProcessArguments(WorkItems, argc, argv); - - int ret = 0; - - // Loop over the entire init/finalize cycle to watch memory changes - const int iterations = 1; - if (iterations > 1) - glslang::OS_DumpMemoryCounters(); - for (int i = 0; i < iterations; ++i) { - ret = singleMain(); - if (iterations > 1) - glslang::OS_DumpMemoryCounters(); - } - - return ret; -} - -// -// Deduce the language from the filename. Files must end in one of the -// following extensions: -// -// .vert = vertex -// .tesc = tessellation control -// .tese = tessellation evaluation -// .geom = geometry -// .frag = fragment -// .comp = compute -// -EShLanguage FindLanguage(const std::string& name, bool parseSuffix) -{ - size_t ext = 0; - std::string suffix; - - if (shaderStageName) - suffix = shaderStageName; - else { - // Search for a suffix on a filename: e.g, "myfile.frag". If given - // the suffix directly, we skip looking for the '.' - if (parseSuffix) { - ext = name.rfind('.'); - if (ext == std::string::npos) { - usage(); - return EShLangVertex; - } - ++ext; - } - suffix = name.substr(ext, std::string::npos); - } - - if (suffix == "vert") - return EShLangVertex; - else if (suffix == "tesc") - return EShLangTessControl; - else if (suffix == "tese") - return EShLangTessEvaluation; - else if (suffix == "geom") - return EShLangGeometry; - else if (suffix == "frag") - return EShLangFragment; - else if (suffix == "comp") - return EShLangCompute; - - usage(); - return EShLangVertex; -} - -// -// Read a file's data into a string, and compile it using the old interface ShCompile, -// for non-linkable results. -// -void CompileFile(const char* fileName, ShHandle compiler) -{ - int ret = 0; - char* shaderString; - if ((Options & EOptionStdin) != 0) { - std::istreambuf_iterator begin(std::cin), end; - std::string tempString(begin, end); - shaderString = strdup(tempString.c_str()); - } else { - shaderString = ReadFileData(fileName); - } - - // move to length-based strings, rather than null-terminated strings - int* lengths = new int[1]; - lengths[0] = (int)strlen(shaderString); - - EShMessages messages = EShMsgDefault; - SetMessageOptions(messages); - - if (UserPreamble.isSet()) - Error("-D and -U options require -l (linking)\n"); - - for (int i = 0; i < ((Options & EOptionMemoryLeakMode) ? 100 : 1); ++i) { - for (int j = 0; j < ((Options & EOptionMemoryLeakMode) ? 100 : 1); ++j) { - // ret = ShCompile(compiler, shaderStrings, NumShaderStrings, lengths, EShOptNone, &Resources, Options, (Options & EOptionDefaultDesktop) ? 110 : 100, false, messages); - ret = ShCompile(compiler, &shaderString, 1, nullptr, EShOptNone, &Resources, Options, (Options & EOptionDefaultDesktop) ? 110 : 100, false, messages); - // const char* multi[12] = { "# ve", "rsion", " 300 e", "s", "\n#err", - // "or should be l", "ine 1", "string 5\n", "float glo", "bal", - // ";\n#error should be line 2\n void main() {", "global = 2.3;}" }; - // const char* multi[7] = { "/", "/", "\\", "\n", "\n", "#", "version 300 es" }; - // ret = ShCompile(compiler, multi, 7, nullptr, EShOptNone, &Resources, Options, (Options & EOptionDefaultDesktop) ? 110 : 100, false, messages); - } - - if (Options & EOptionMemoryLeakMode) - glslang::OS_DumpMemoryCounters(); - } - - delete [] lengths; - FreeFileData(shaderString); - - if (ret == 0) - CompileFailed = true; -} - -// -// print usage to stdout -// -void usage() -{ - printf("Usage: glslangValidator [option]... [file]...\n" - "\n" - "'file' can end in . for auto-stage classification, where is:\n" - " .conf to provide a config file that replaces the default configuration\n" - " (see -c option below for generating a template)\n" - " .vert for a vertex shader\n" - " .tesc for a tessellation control shader\n" - " .tese for a tessellation evaluation shader\n" - " .geom for a geometry shader\n" - " .frag for a fragment shader\n" - " .comp for a compute shader\n" - "\n" - "Options:\n" - " -C cascading errors; risk crash from accumulation of error recoveries\n" - " -D input is HLSL\n" - " -D\n" - " -D define a pre-processor macro\n" - " -E print pre-processed GLSL; cannot be used with -l;\n" - " errors will appear on stderr.\n" - " -G[ver] create SPIR-V binary, under OpenGL semantics; turns on -l;\n" - " default file name is .spv (-o overrides this)\n" - " 'ver', when present, is the version of the input semantics,\n" - " which will appear in #define GL_SPIRV ver\n" - " '--client opengl100' is the same as -G100\n" - " a '--target-env' for OpenGL will also imply '-G'\n" - " -H print human readable form of SPIR-V; turns on -V\n" - " -I add dir to the include search path; includer's directory\n" - " is searched first, followed by left-to-right order of -I\n" - " -Od disables optimization. May cause illegal SPIR-V for HLSL.\n" - " -Os optimizes SPIR-V to minimize size.\n" - " -S uses specified stage rather than parsing the file extension\n" - " choices for are vert, tesc, tese, geom, frag, or comp\n" - " -U undefine a pre-processor macro\n" - " -V[ver] create SPIR-V binary, under Vulkan semantics; turns on -l;\n" - " default file name is .spv (-o overrides this)\n" - " 'ver', when present, is the version of the input semantics,\n" - " which will appear in #define VULKAN ver\n" - " '--client vulkan100' is the same as -V100\n" - " a '--target-env' for Vulkan will also imply '-V'\n" - " -c configuration dump;\n" - " creates the default configuration file (redirect to a .conf file)\n" - " -d default to desktop (#version 110) when there is no shader #version\n" - " (default is ES version 100)\n" - " -e specify as the entry-point name\n" - " -f{hlsl_functionality1}\n" - " 'hlsl_functionality1' enables use of the\n" - " SPV_GOOGLE_hlsl_functionality1 extension\n" - " -g generate debug information\n" - " -h print this usage message\n" - " -i intermediate tree (glslang AST) is printed out\n" - " -l link all input files together to form a single module\n" - " -m memory leak mode\n" - " -o save binary to , requires a binary option (e.g., -V)\n" - " -q dump reflection query database\n" - " -r synonym for --relaxed-errors\n" - " -s silence syntax and semantic error reporting\n" - " -t multi-threaded mode\n" - " -v print version strings\n" - " -w synonym for --suppress-warnings\n" - " -x save binary output as text-based 32-bit hexadecimal numbers\n" - " --auto-map-bindings automatically bind uniform variables\n" - " without explicit bindings.\n" - " --amb synonym for --auto-map-bindings\n" - " --auto-map-locations automatically locate input/output lacking\n" - " 'location' (fragile, not cross stage)\n" - " --aml synonym for --auto-map-locations\n" - " --client {vulkan|opengl} see -V and -G\n" - " -dumpfullversion print bare major.minor.patchlevel\n" - " -dumpversion same as -dumpfullversion\n" - " --flatten-uniform-arrays flatten uniform texture/sampler arrays to\n" - " scalars\n" - " --fua synonym for --flatten-uniform-arrays\n" - " --hlsl-offsets Allow block offsets to follow HLSL rules\n" - " Works independently of source language\n" - " --hlsl-iomap Perform IO mapping in HLSL register space\n" - " --hlsl-enable-16bit-types Allow use of 16-bit types in SPIR-V for HLSL\n" - " --invert-y | --iy invert position.Y output in vertex shader\n" - " --keep-uncalled don't eliminate uncalled functions\n" - " --ku synonym for --keep-uncalled\n" - " --no-storage-format use Unknown image format\n" - " --nsf synonym for --no-storage-format\n" - " --relaxed-errors relaxed GLSL semantic error-checking mode\n" - " --resource-set-binding [stage] name set binding\n" - " Set descriptor set and binding for individual resources\n" - " --resource-set-binding [stage] set\n" - " Set descriptor set for all resources\n" - " --rsb [stage] type set binding synonym for --resource-set-binding\n" - " --shift-image-binding [stage] num base binding number for images (uav)\n" - " --shift-image-binding [stage] [num set]... per-descriptor-set shift values\n" - " --sib [stage] num synonym for --shift-image-binding\n" - " --shift-sampler-binding [stage] num base binding number for samplers\n" - " --shift-sampler-binding [stage] [num set]... per-descriptor-set shift values\n" - " --ssb [stage] num synonym for --shift-sampler-binding\n" - " --shift-ssbo-binding [stage] num base binding number for SSBOs\n" - " --shift-ssbo-binding [stage] [num set]... per-descriptor-set shift values\n" - " --sbb [stage] num synonym for --shift-ssbo-binding\n" - " --shift-texture-binding [stage] num base binding number for textures\n" - " --shift-texture-binding [stage] [num set]... per-descriptor-set shift values\n" - " --stb [stage] num synonym for --shift-texture-binding\n" - " --shift-uav-binding [stage] num base binding number for UAVs\n" - " --shift-uav-binding [stage] [num set]... per-descriptor-set shift values\n" - " --suavb [stage] num synonym for --shift-uav-binding\n" - " --shift-UBO-binding [stage] num base binding number for UBOs\n" - " --shift-UBO-binding [stage] [num set]... per-descriptor-set shift values\n" - " --shift-cbuffer-binding [stage] num synonym for --shift-UBO-binding\n" - " --shift-cbuffer-binding [stage] [num set]... per-descriptor-set shift values\n" - " --sub [stage] num synonym for --shift-UBO-binding\n" - " --source-entrypoint the given shader source function is\n" - " renamed to be the given in -e\n" - " --sep synonym for --source-entrypoint\n" - " --stdin Read from stdin instead of from a file.\n" - " You'll have to provide the shader stage\n" - " using -S.\n" - " --suppress-warnings suppress GLSL warnings\n" - " (except as required by #extension : warn)\n" - " --target-env {vulkan1.0 | vulkan1.1 | opengl} \n" - " set execution environment that emitted code\n" - " will execute in (as opposed to the language\n" - " semantics selected by --client) defaults:\n" - " 'vulkan1.0' under '--client vulkan'\n" - " 'opengl' under '--client opengl'\n" - " --variable-name Creates a C header file that contains a\n" - " uint32_t array named \n" - " initialized with the shader binary code.\n" - " --version synonym for -v\n" - " --vn synonym for --variable-name \n" - ); - - exit(EFailUsage); -} - -#if !defined _MSC_VER && !defined MINGW_HAS_SECURE_API - -#include - -int fopen_s( - FILE** pFile, - const char* filename, - const char* mode -) -{ - if (!pFile || !filename || !mode) { - return EINVAL; - } - - FILE* f = fopen(filename, mode); - if (! f) { - if (errno != 0) { - return errno; - } else { - return ENOENT; - } - } - *pFile = f; - - return 0; -} - -#endif - -// -// Malloc a string of sufficient size and read a string into it. -// -char* ReadFileData(const char* fileName) -{ - FILE *in = nullptr; - int errorCode = fopen_s(&in, fileName, "r"); - if (errorCode || in == nullptr) - Error("unable to open input file"); - - int count = 0; - while (fgetc(in) != EOF) - count++; - - fseek(in, 0, SEEK_SET); - - char* return_data = (char*)malloc(count + 1); // freed in FreeFileData() - if ((int)fread(return_data, 1, count, in) != count) { - free(return_data); - Error("can't read input file"); - } - - return_data[count] = '\0'; - fclose(in); - - return return_data; -} - -void FreeFileData(char* data) -{ - free(data); -} - -void InfoLogMsg(const char* msg, const char* name, const int num) -{ - if (num >= 0 ) - printf("#### %s %s %d INFO LOG ####\n", msg, name, num); - else - printf("#### %s %s INFO LOG ####\n", msg, name); -} diff --git a/External/glslang/StandAlone/Worklist.h b/External/glslang/StandAlone/Worklist.h deleted file mode 100644 index 91b6f516..00000000 --- a/External/glslang/StandAlone/Worklist.h +++ /dev/null @@ -1,95 +0,0 @@ -// -// 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 WORKLIST_H_INCLUDED -#define WORKLIST_H_INCLUDED - -#include "../glslang/OSDependent/osinclude.h" -#include -#include -#include - -namespace glslang { - - class TWorkItem { - public: - TWorkItem() { } - explicit TWorkItem(const std::string& s) : - name(s) { } - std::string name; - std::string results; - std::string resultsIndex; - }; - - class TWorklist { - public: - TWorklist() { } - virtual ~TWorklist() { } - - void add(TWorkItem* item) - { - std::lock_guard guard(mutex); - worklist.push_back(item); - } - - bool remove(TWorkItem*& item) - { - std::lock_guard guard(mutex); - - if (worklist.empty()) - return false; - item = worklist.front(); - worklist.pop_front(); - - return true; - } - - int size() - { - return (int)worklist.size(); - } - - bool empty() - { - return worklist.empty(); - } - - protected: - std::mutex mutex; - std::list worklist; - }; - -} // end namespace glslang - -#endif // WORKLIST_H_INCLUDED diff --git a/External/glslang/StandAlone/spirv-remap.cpp b/External/glslang/StandAlone/spirv-remap.cpp deleted file mode 100644 index 998f7428..00000000 --- a/External/glslang/StandAlone/spirv-remap.cpp +++ /dev/null @@ -1,343 +0,0 @@ -// -// Copyright (C) 2015 LunarG, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -#include -#include -#include -#include - -#include "../SPIRV/SPVRemapper.h" - -namespace { - - typedef unsigned int SpvWord; - - // Poor man's basename: given a complete path, return file portion. - // E.g: - // Linux: /foo/bar/test -> test - // Win: c:\foo\bar\test -> test - // It's not very efficient, but that doesn't matter for our minimal-duty use. - // Using boost::filesystem would be better in many ways, but want to avoid that dependency. - - // OS dependent path separator (avoiding boost::filesystem dependency) -#if defined(_WIN32) - char path_sep_char() { return '\\'; } -#else - char path_sep_char() { return '/'; } -#endif - - std::string basename(const std::string filename) - { - const size_t sepLoc = filename.find_last_of(path_sep_char()); - - return (sepLoc == filename.npos) ? filename : filename.substr(sepLoc+1); - } - - void errHandler(const std::string& str) { - std::cout << str << std::endl; - exit(5); - } - - void logHandler(const std::string& str) { - std::cout << str << std::endl; - } - - // Read word stream from disk - void read(std::vector& spv, const std::string& inFilename, int verbosity) - { - std::ifstream fp; - - if (verbosity > 0) - logHandler(std::string(" reading: ") + inFilename); - - spv.clear(); - fp.open(inFilename, std::fstream::in | std::fstream::binary); - - if (fp.fail()) - errHandler("error opening file for read: "); - - // Reserve space (for efficiency, not for correctness) - fp.seekg(0, fp.end); - spv.reserve(size_t(fp.tellg()) / sizeof(SpvWord)); - fp.seekg(0, fp.beg); - - while (!fp.eof()) { - SpvWord inWord; - fp.read((char *)&inWord, sizeof(inWord)); - - if (!fp.eof()) { - spv.push_back(inWord); - if (fp.fail()) - errHandler(std::string("error reading file: ") + inFilename); - } - } - } - - void write(std::vector& spv, const std::string& outFile, int verbosity) - { - if (outFile.empty()) - errHandler("missing output filename."); - - std::ofstream fp; - - if (verbosity > 0) - logHandler(std::string(" writing: ") + outFile); - - fp.open(outFile, std::fstream::out | std::fstream::binary); - - if (fp.fail()) - errHandler(std::string("error opening file for write: ") + outFile); - - for (auto it = spv.cbegin(); it != spv.cend(); ++it) { - SpvWord word = *it; - fp.write((char *)&word, sizeof(word)); - if (fp.fail()) - errHandler(std::string("error writing file: ") + outFile); - } - - // file is closed by destructor - } - - // Print helpful usage message to stdout, and exit - void usage(const char* const name, const char* const msg = 0) - { - if (msg) - std::cout << msg << std::endl << std::endl; - - std::cout << "Usage: " << std::endl; - - std::cout << " " << basename(name) - << " [-v[v[...]] | --verbose [int]]" - << " [--map (all|types|names|funcs)]" - << " [--dce (all|types|funcs)]" - << " [--opt (all|loadstore)]" - << " [--strip-all | --strip all | -s]" - << " [--do-everything]" - << " --input | -i file1 [file2...] --output|-o DESTDIR" - << std::endl; - - std::cout << " " << basename(name) << " [--version | -V]" << std::endl; - std::cout << " " << basename(name) << " [--help | -?]" << std::endl; - - exit(5); - } - - // grind through each SPIR in turn - void execute(const std::vector& inputFile, const std::string& outputDir, - int opts, int verbosity) - { - for (auto it = inputFile.cbegin(); it != inputFile.cend(); ++it) { - const std::string &filename = *it; - std::vector spv; - read(spv, filename, verbosity); - spv::spirvbin_t(verbosity).remap(spv, opts); - - const std::string outfile = outputDir + path_sep_char() + basename(filename); - - write(spv, outfile, verbosity); - } - - if (verbosity > 0) - std::cout << "Done: " << inputFile.size() << " file(s) processed" << std::endl; - } - - // Parse command line options - void parseCmdLine(int argc, char** argv, std::vector& inputFile, - std::string& outputDir, - int& options, - int& verbosity) - { - if (argc < 2) - usage(argv[0]); - - verbosity = 0; - options = spv::spirvbin_t::NONE; - - // Parse command line. - // boost::program_options would be quite a bit nicer, but we don't want to - // introduce a dependency on boost. - for (int a=1; a= argc) - usage(argv[0], "--output requires an argument"); - if (!outputDir.empty()) - usage(argv[0], "--output can be provided only once"); - - outputDir = argv[a++]; - - // Remove trailing directory separator characters - while (!outputDir.empty() && outputDir.back() == path_sep_char()) - outputDir.pop_back(); - - } - else if (arg == "-vv") { verbosity = 2; ++a; } // verbosity shortcuts - else if (arg == "-vvv") { verbosity = 3; ++a; } // ... - else if (arg == "-vvvv") { verbosity = 4; ++a; } // ... - else if (arg == "-vvvvv") { verbosity = 5; ++a; } // ... - - else if (arg == "--verbose" || arg == "-v") { - ++a; - verbosity = 1; - - if (a < argc) { - char* end_ptr = 0; - int verb = ::strtol(argv[a], &end_ptr, 10); - // If we have not read to the end of the string or - // the string contained no elements, then we do not want to - // store the value. - if (*end_ptr == '\0' && end_ptr != argv[a]) { - verbosity = verb; - ++a; - } - } - } - else if (arg == "--version" || arg == "-V") { - std::cout << basename(argv[0]) << " version 0.97 " << __DATE__ << " " << __TIME__ << std::endl; - exit(0); - } else if (arg == "--input" || arg == "-i") { - // Collect input files - for (++a; a < argc && argv[a][0] != '-'; ++a) - inputFile.push_back(argv[a]); - } else if (arg == "--do-everything") { - ++a; - options = options | spv::spirvbin_t::DO_EVERYTHING; - } else if (arg == "--strip-all" || arg == "-s") { - ++a; - options = options | spv::spirvbin_t::STRIP; - } else if (arg == "--strip") { - ++a; - if (strncmp(argv[a], "all", 3) == 0) { - options = options | spv::spirvbin_t::STRIP; - ++a; - } - } else if (arg == "--dce") { - // Parse comma (or colon, etc) separated list of things to dce - ++a; - for (const char* c = argv[a]; *c; ++c) { - if (strncmp(c, "all", 3) == 0) { - options = (options | spv::spirvbin_t::DCE_ALL); - c += 3; - } else if (strncmp(c, "*", 1) == 0) { - options = (options | spv::spirvbin_t::DCE_ALL); - c += 1; - } else if (strncmp(c, "funcs", 5) == 0) { - options = (options | spv::spirvbin_t::DCE_FUNCS); - c += 5; - } else if (strncmp(c, "types", 5) == 0) { - options = (options | spv::spirvbin_t::DCE_TYPES); - c += 5; - } - } - ++a; - } else if (arg == "--map") { - // Parse comma (or colon, etc) separated list of things to map - ++a; - for (const char* c = argv[a]; *c; ++c) { - if (strncmp(c, "all", 3) == 0) { - options = (options | spv::spirvbin_t::MAP_ALL); - c += 3; - } else if (strncmp(c, "*", 1) == 0) { - options = (options | spv::spirvbin_t::MAP_ALL); - c += 1; - } else if (strncmp(c, "types", 5) == 0) { - options = (options | spv::spirvbin_t::MAP_TYPES); - c += 5; - } else if (strncmp(c, "names", 5) == 0) { - options = (options | spv::spirvbin_t::MAP_NAMES); - c += 5; - } else if (strncmp(c, "funcs", 5) == 0) { - options = (options | spv::spirvbin_t::MAP_FUNCS); - c += 5; - } - } - ++a; - } else if (arg == "--opt") { - ++a; - for (const char* c = argv[a]; *c; ++c) { - if (strncmp(c, "all", 3) == 0) { - options = (options | spv::spirvbin_t::OPT_ALL); - c += 3; - } else if (strncmp(c, "*", 1) == 0) { - options = (options | spv::spirvbin_t::OPT_ALL); - c += 1; - } else if (strncmp(c, "loadstore", 9) == 0) { - options = (options | spv::spirvbin_t::OPT_LOADSTORE); - c += 9; - } - } - ++a; - } else if (arg == "--help" || arg == "-?") { - usage(argv[0]); - } else { - usage(argv[0], "Unknown command line option"); - } - } - } - -} // namespace - -int main(int argc, char** argv) -{ - std::vector inputFile; - std::string outputDir; - int opts; - int verbosity; - -#ifdef use_cpp11 - // handle errors by exiting - spv::spirvbin_t::registerErrorHandler(errHandler); - - // Log messages to std::cout - spv::spirvbin_t::registerLogHandler(logHandler); -#endif - - if (argc < 2) - usage(argv[0]); - - parseCmdLine(argc, argv, inputFile, outputDir, opts, verbosity); - - if (outputDir.empty()) - usage(argv[0], "Output directory required"); - - std::string errmsg; - - // Main operations: read, remap, and write. - execute(inputFile, outputDir, opts, verbosity); - - // If we get here, everything went OK! Nothing more to be done. -} diff --git a/External/glslang/glslang/CMakeLists.txt b/External/glslang/glslang/CMakeLists.txt deleted file mode 100644 index 4f33b539..00000000 --- a/External/glslang/glslang/CMakeLists.txt +++ /dev/null @@ -1,114 +0,0 @@ -if(WIN32) - add_subdirectory(OSDependent/Windows) -elseif(UNIX) - add_subdirectory(OSDependent/Unix) -else(WIN32) - message("unknown platform") -endif(WIN32) - -set(SOURCES - MachineIndependent/glslang.y - MachineIndependent/glslang_tab.cpp - MachineIndependent/attribute.cpp - MachineIndependent/Constant.cpp - MachineIndependent/iomapper.cpp - MachineIndependent/InfoSink.cpp - MachineIndependent/Initialize.cpp - MachineIndependent/IntermTraverse.cpp - MachineIndependent/Intermediate.cpp - MachineIndependent/ParseContextBase.cpp - MachineIndependent/ParseHelper.cpp - MachineIndependent/PoolAlloc.cpp - MachineIndependent/RemoveTree.cpp - MachineIndependent/Scan.cpp - MachineIndependent/ShaderLang.cpp - MachineIndependent/SymbolTable.cpp - MachineIndependent/Versions.cpp - MachineIndependent/intermOut.cpp - MachineIndependent/limits.cpp - MachineIndependent/linkValidate.cpp - MachineIndependent/parseConst.cpp - MachineIndependent/reflection.cpp - MachineIndependent/preprocessor/Pp.cpp - MachineIndependent/preprocessor/PpAtom.cpp - MachineIndependent/preprocessor/PpContext.cpp - MachineIndependent/preprocessor/PpScanner.cpp - MachineIndependent/preprocessor/PpTokens.cpp - MachineIndependent/propagateNoContraction.cpp - GenericCodeGen/CodeGen.cpp - GenericCodeGen/Link.cpp) - -set(HEADERS - Public/ShaderLang.h - Include/arrays.h - Include/BaseTypes.h - Include/Common.h - Include/ConstantUnion.h - Include/InfoSink.h - Include/InitializeGlobals.h - Include/intermediate.h - Include/PoolAlloc.h - Include/ResourceLimits.h - Include/revision.h - Include/ShHandle.h - Include/Types.h - MachineIndependent/attribute.h - MachineIndependent/glslang_tab.cpp.h - MachineIndependent/gl_types.h - MachineIndependent/Initialize.h - MachineIndependent/iomapper.h - MachineIndependent/LiveTraverser.h - MachineIndependent/localintermediate.h - MachineIndependent/ParseHelper.h - MachineIndependent/reflection.h - MachineIndependent/RemoveTree.h - MachineIndependent/Scan.h - MachineIndependent/ScanContext.h - MachineIndependent/SymbolTable.h - MachineIndependent/Versions.h - MachineIndependent/parseVersions.h - MachineIndependent/propagateNoContraction.h - MachineIndependent/preprocessor/PpContext.h - MachineIndependent/preprocessor/PpTokens.h) - -# This might be useful for making grammar changes: -# -# find_package(BISON) -# add_custom_command(OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/MachineIndependent/glslang_tab.cpp ${CMAKE_CURRENT_SOURCE_DIR}/MachineIndependent/glslang_tab.cpp.h -# COMMAND ${BISON_EXECUTABLE} --defines=${CMAKE_CURRENT_SOURCE_DIR}/MachineIndependent/glslang_tab.cpp.h -t ${CMAKE_CURRENT_SOURCE_DIR}/MachineIndependent/glslang.y -o ${CMAKE_CURRENT_SOURCE_DIR}/MachineIndependent/glslang_tab.cpp -# MAIN_DEPENDENCY MachineIndependent/glslang.y -# WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) -# set(BISON_GLSLParser_OUTPUT_SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/MachineIndependent/glslang_tab.cpp) - -add_library(glslang ${LIB_TYPE} ${BISON_GLSLParser_OUTPUT_SOURCE} ${SOURCES} ${HEADERS}) -set_property(TARGET glslang PROPERTY FOLDER glslang) -set_property(TARGET glslang PROPERTY POSITION_INDEPENDENT_CODE ON) -target_link_libraries(glslang OGLCompiler OSDependent) - -if(WIN32 AND BUILD_SHARED_LIBS) - set_target_properties(glslang PROPERTIES PREFIX "") -endif() - -if(ENABLE_HLSL) - target_link_libraries(glslang HLSL) -endif() - -if(WIN32) - source_group("Public" REGULAR_EXPRESSION "Public/*") - source_group("MachineIndependent" REGULAR_EXPRESSION "MachineIndependent/[^/]*") - source_group("Include" REGULAR_EXPRESSION "Include/[^/]*") - source_group("GenericCodeGen" REGULAR_EXPRESSION "GenericCodeGen/*") - source_group("MachineIndependent\\Preprocessor" REGULAR_EXPRESSION "MachineIndependent/preprocessor/*") -endif(WIN32) - -if(ENABLE_GLSLANG_INSTALL) - install(TARGETS glslang - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) -endif(ENABLE_GLSLANG_INSTALL) - -if(ENABLE_GLSLANG_INSTALL) - foreach(file ${HEADERS}) - get_filename_component(dir ${file} DIRECTORY) - install(FILES ${file} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/glslang/${dir}) - endforeach() -endif(ENABLE_GLSLANG_INSTALL) diff --git a/External/glslang/glslang/GenericCodeGen/CodeGen.cpp b/External/glslang/glslang/GenericCodeGen/CodeGen.cpp deleted file mode 100644 index b3c7226d..00000000 --- a/External/glslang/glslang/GenericCodeGen/CodeGen.cpp +++ /dev/null @@ -1,76 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -#include "../Include/Common.h" -#include "../Include/ShHandle.h" -#include "../MachineIndependent/Versions.h" - -// -// Here is where real machine specific high-level data would be defined. -// -class TGenericCompiler : public TCompiler { -public: - TGenericCompiler(EShLanguage l, int dOptions) : TCompiler(l, infoSink), debugOptions(dOptions) { } - virtual bool compile(TIntermNode* root, int version = 0, EProfile profile = ENoProfile); - TInfoSink infoSink; - int debugOptions; -}; - -// -// This function must be provided to create the actual -// compile object used by higher level code. It returns -// a subclass of TCompiler. -// -TCompiler* ConstructCompiler(EShLanguage language, int debugOptions) -{ - return new TGenericCompiler(language, debugOptions); -} - -// -// Delete the compiler made by ConstructCompiler -// -void DeleteCompiler(TCompiler* compiler) -{ - delete compiler; -} - -// -// Generate code from the given parse tree -// -bool TGenericCompiler::compile(TIntermNode* /*root*/, int /*version*/, EProfile /*profile*/) -{ - haveValidObjectCode = true; - - return haveValidObjectCode; -} diff --git a/External/glslang/glslang/GenericCodeGen/Link.cpp b/External/glslang/glslang/GenericCodeGen/Link.cpp deleted file mode 100644 index c38db0f6..00000000 --- a/External/glslang/glslang/GenericCodeGen/Link.cpp +++ /dev/null @@ -1,91 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -// -// The top level algorithms for linking multiple -// shaders together. -// -#include "../Include/Common.h" -#include "../Include/ShHandle.h" - -// -// Actual link object, derived from the shader handle base classes. -// -class TGenericLinker : public TLinker { -public: - TGenericLinker(EShExecutable e, int dOptions) : TLinker(e, infoSink), debugOptions(dOptions) { } - bool link(TCompilerList&, TUniformMap*) { return true; } - void getAttributeBindings(ShBindingTable const **) const { } - TInfoSink infoSink; - int debugOptions; -}; - -// -// The internal view of a uniform/float object exchanged with the driver. -// -class TUniformLinkedMap : public TUniformMap { -public: - TUniformLinkedMap() { } - virtual int getLocation(const char*) { return 0; } -}; - -TShHandleBase* ConstructLinker(EShExecutable executable, int debugOptions) -{ - return new TGenericLinker(executable, debugOptions); -} - -void DeleteLinker(TShHandleBase* linker) -{ - delete linker; -} - -TUniformMap* ConstructUniformMap() -{ - return new TUniformLinkedMap(); -} - -void DeleteUniformMap(TUniformMap* map) -{ - delete map; -} - -TShHandleBase* ConstructBindings() -{ - return 0; -} - -void DeleteBindingList(TShHandleBase* bindingList) -{ - delete bindingList; -} diff --git a/External/glslang/glslang/Include/BaseTypes.h b/External/glslang/glslang/Include/BaseTypes.h deleted file mode 100644 index 46fe159b..00000000 --- a/External/glslang/glslang/Include/BaseTypes.h +++ /dev/null @@ -1,464 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// Copyright (C) 2012-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 _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, - - // HLSL types that live only temporarily. - EbtString, - - EbtNumTypes -}; - -// -// Storage qualifiers. Should align with different kinds of storage or -// resource or GLSL storage qualifier. Expansion is deprecated. -// -// N.B.: You probably DON'T want to add anything here, but rather just add it -// to the built-in variables. See the comment above TBuiltInVariable. -// -// A new built-in variable will normally be an existing qualifier, like 'in', 'out', etc. -// DO NOT follow the design pattern of, say EvqInstanceId, etc. -// -enum TStorageQualifier { - EvqTemporary, // For temporaries (within a function), read/write - EvqGlobal, // For globals read/write - EvqConst, // User-defined constant values, will be semantically constant and constant folded - EvqVaryingIn, // pipeline input, read only, also supercategory for all built-ins not included in this enum (see TBuiltInVariable) - EvqVaryingOut, // pipeline output, read/write, also supercategory for all built-ins not included in this enum (see TBuiltInVariable) - EvqUniform, // read only, shared with app - EvqBuffer, // read/write, shared with app - EvqShared, // compute shader's read/write 'shared' qualifier - - // parameters - EvqIn, // also, for 'in' in the grammar before we know if it's a pipeline input or an 'in' parameter - EvqOut, // also, for 'out' in the grammar before we know if it's a pipeline output or an 'out' parameter - EvqInOut, - EvqConstReadOnly, // input; also other read-only types having neither a constant value nor constant-value semantics - - // built-ins read by vertex shader - EvqVertexId, - EvqInstanceId, - - // built-ins written by vertex shader - EvqPosition, - EvqPointSize, - EvqClipVertex, - - // built-ins read by fragment shader - EvqFace, - EvqFragCoord, - EvqPointCoord, - - // built-ins written by fragment shader - EvqFragColor, - EvqFragDepth, - - // end of list - EvqLast -}; - -// -// Subcategories of the TStorageQualifier, simply to give a direct mapping -// between built-in variable names and an numerical value (the enum). -// -// For backward compatibility, there is some redundancy between the -// TStorageQualifier and these. Existing members should both be maintained accurately. -// However, any new built-in variable (and any existing non-redundant one) -// must follow the pattern that the specific built-in is here, and only its -// general qualifier is in TStorageQualifier. -// -// Something like gl_Position, which is sometimes 'in' and sometimes 'out' -// shows up as two different built-in variables in a single stage, but -// only has a single enum in TBuiltInVariable, so both the -// TStorageQualifier and the TBuitinVariable are needed to distinguish -// between them. -// -enum TBuiltInVariable { - EbvNone, - EbvNumWorkGroups, - EbvWorkGroupSize, - EbvWorkGroupId, - EbvLocalInvocationId, - EbvGlobalInvocationId, - EbvLocalInvocationIndex, - 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, - -#ifdef AMD_EXTENSIONS - EbvBaryCoordNoPersp, - EbvBaryCoordNoPerspCentroid, - EbvBaryCoordNoPerspSample, - EbvBaryCoordSmooth, - EbvBaryCoordSmoothCentroid, - EbvBaryCoordSmoothSample, - EbvBaryCoordPullModel, -#endif - - EbvViewIndex, - EbvDeviceIndex, - -#ifdef NV_EXTENSIONS - EbvViewportMaskNV, - EbvSecondaryPositionNV, - EbvSecondaryViewportMaskNV, - EbvPositionPerViewNV, - EbvViewportMaskPerViewNV, - EbvFragFullyCoveredNV, -#endif - - // HLSL built-ins that live only temporarily, until they get remapped - // to one of the above. - EbvFragDepthGreater, - EbvFragDepthLesser, - EbvGsOutputStream, - EbvOutputPatch, - EbvInputPatch, - - // structbuffer types - EbvAppendConsume, // no need to differentiate append and consume - EbvRWStructuredBuffer, - EbvStructuredBuffer, - EbvByteAddressBuffer, - EbvRWByteAddressBuffer, - - EbvLast -}; - -// These will show up in error messages -__inline const char* GetStorageQualifierString(TStorageQualifier q) -{ - switch (q) { - case EvqTemporary: return "temp"; break; - case EvqGlobal: return "global"; break; - case EvqConst: return "const"; break; - case EvqConstReadOnly: return "const (read only)"; break; - case EvqVaryingIn: return "in"; break; - case EvqVaryingOut: return "out"; break; - case EvqUniform: return "uniform"; break; - case EvqBuffer: return "buffer"; break; - case EvqShared: return "shared"; break; - case EvqIn: return "in"; break; - case EvqOut: return "out"; break; - case EvqInOut: return "inout"; break; - case EvqVertexId: return "gl_VertexId"; break; - case EvqInstanceId: return "gl_InstanceId"; break; - case EvqPosition: return "gl_Position"; break; - case EvqPointSize: return "gl_PointSize"; break; - case EvqClipVertex: return "gl_ClipVertex"; break; - case EvqFace: return "gl_FrontFacing"; break; - case EvqFragCoord: return "gl_FragCoord"; break; - case EvqPointCoord: return "gl_PointCoord"; break; - case EvqFragColor: return "fragColor"; break; - case EvqFragDepth: return "gl_FragDepth"; break; - default: return "unknown qualifier"; - } -} - -__inline const char* GetBuiltInVariableString(TBuiltInVariable v) -{ - switch (v) { - case EbvNone: return ""; - case EbvNumWorkGroups: return "NumWorkGroups"; - case EbvWorkGroupSize: return "WorkGroupSize"; - case EbvWorkGroupId: return "WorkGroupID"; - case EbvLocalInvocationId: return "LocalInvocationID"; - case EbvGlobalInvocationId: return "GlobalInvocationID"; - case EbvLocalInvocationIndex: return "LocalInvocationIndex"; - case EbvSubGroupSize: return "SubGroupSize"; - case EbvSubGroupInvocation: return "SubGroupInvocation"; - case EbvSubGroupEqMask: return "SubGroupEqMask"; - case EbvSubGroupGeMask: return "SubGroupGeMask"; - case EbvSubGroupGtMask: return "SubGroupGtMask"; - case EbvSubGroupLeMask: return "SubGroupLeMask"; - case EbvSubGroupLtMask: return "SubGroupLtMask"; - case EbvVertexId: return "VertexId"; - case EbvInstanceId: return "InstanceId"; - case EbvVertexIndex: return "VertexIndex"; - case EbvInstanceIndex: return "InstanceIndex"; - case EbvBaseVertex: return "BaseVertex"; - case EbvBaseInstance: return "BaseInstance"; - case EbvDrawId: return "DrawId"; - case EbvPosition: return "Position"; - case EbvPointSize: return "PointSize"; - case EbvClipVertex: return "ClipVertex"; - case EbvClipDistance: return "ClipDistance"; - case EbvCullDistance: return "CullDistance"; - case EbvNormal: return "Normal"; - case EbvVertex: return "Vertex"; - case EbvMultiTexCoord0: return "MultiTexCoord0"; - case EbvMultiTexCoord1: return "MultiTexCoord1"; - case EbvMultiTexCoord2: return "MultiTexCoord2"; - case EbvMultiTexCoord3: return "MultiTexCoord3"; - case EbvMultiTexCoord4: return "MultiTexCoord4"; - case EbvMultiTexCoord5: return "MultiTexCoord5"; - case EbvMultiTexCoord6: return "MultiTexCoord6"; - case EbvMultiTexCoord7: return "MultiTexCoord7"; - case EbvFrontColor: return "FrontColor"; - case EbvBackColor: return "BackColor"; - case EbvFrontSecondaryColor: return "FrontSecondaryColor"; - case EbvBackSecondaryColor: return "BackSecondaryColor"; - case EbvTexCoord: return "TexCoord"; - case EbvFogFragCoord: return "FogFragCoord"; - case EbvInvocationId: return "InvocationID"; - case EbvPrimitiveId: return "PrimitiveID"; - case EbvLayer: return "Layer"; - case EbvViewportIndex: return "ViewportIndex"; - case EbvPatchVertices: return "PatchVertices"; - case EbvTessLevelOuter: return "TessLevelOuter"; - case EbvTessLevelInner: return "TessLevelInner"; - case EbvBoundingBox: return "BoundingBox"; - case EbvTessCoord: return "TessCoord"; - case EbvColor: return "Color"; - case EbvSecondaryColor: return "SecondaryColor"; - case EbvFace: return "Face"; - case EbvFragCoord: return "FragCoord"; - case EbvPointCoord: return "PointCoord"; - case EbvFragColor: return "FragColor"; - case EbvFragData: return "FragData"; - case EbvFragDepth: return "FragDepth"; - case EbvFragStencilRef: return "FragStencilRef"; - case EbvSampleId: return "SampleId"; - case EbvSamplePosition: return "SamplePosition"; - case EbvSampleMask: return "SampleMaskIn"; - case EbvHelperInvocation: return "HelperInvocation"; - -#ifdef AMD_EXTENSIONS - case EbvBaryCoordNoPersp: return "BaryCoordNoPersp"; - case EbvBaryCoordNoPerspCentroid: return "BaryCoordNoPerspCentroid"; - case EbvBaryCoordNoPerspSample: return "BaryCoordNoPerspSample"; - case EbvBaryCoordSmooth: return "BaryCoordSmooth"; - case EbvBaryCoordSmoothCentroid: return "BaryCoordSmoothCentroid"; - case EbvBaryCoordSmoothSample: return "BaryCoordSmoothSample"; - case EbvBaryCoordPullModel: return "BaryCoordPullModel"; -#endif - - case EbvViewIndex: return "ViewIndex"; - case EbvDeviceIndex: return "DeviceIndex"; - -#ifdef NV_EXTENSIONS - case EbvViewportMaskNV: return "ViewportMaskNV"; - case EbvSecondaryPositionNV: return "SecondaryPositionNV"; - case EbvSecondaryViewportMaskNV: return "SecondaryViewportMaskNV"; - case EbvPositionPerViewNV: return "PositionPerViewNV"; - case EbvViewportMaskPerViewNV: return "ViewportMaskPerViewNV"; - case EbvFragFullyCoveredNV: return "FragFullyCoveredNV"; -#endif - default: return "unknown built-in variable"; - } -} - -// In this enum, order matters; users can assume higher precision is a bigger value -// and EpqNone is 0. -enum TPrecisionQualifier { - EpqNone = 0, - EpqLow, - EpqMedium, - EpqHigh -}; - -__inline const char* GetPrecisionQualifierString(TPrecisionQualifier p) -{ - switch (p) { - case EpqNone: return ""; break; - case EpqLow: return "lowp"; break; - case EpqMedium: return "mediump"; break; - case EpqHigh: return "highp"; break; - default: return "unknown precision qualifier"; - } -} - -__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/External/glslang/glslang/Include/Common.h b/External/glslang/glslang/Include/Common.h deleted file mode 100644 index 35eaa310..00000000 --- a/External/glslang/glslang/Include/Common.h +++ /dev/null @@ -1,278 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// Copyright (C) 2012-2013 LunarG, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -#ifndef _COMMON_INCLUDED_ -#define _COMMON_INCLUDED_ - - -#if defined(__ANDROID__) || _MSC_VER < 1700 -#include -namespace std { -template -std::string to_string(const T& val) { - std::ostringstream os; - os << val; - return os.str(); -} -} -#endif - -#if (defined(_MSC_VER) && _MSC_VER < 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 "PoolAlloc.h" - -// -// Put POOL_ALLOCATOR_NEW_DELETE in base classes to make them use this scheme. -// -#define POOL_ALLOCATOR_NEW_DELETE(A) \ - void* operator new(size_t s) { return (A).allocate(s); } \ - void* operator new(size_t, void *_Where) { return (_Where); } \ - void operator delete(void*) { } \ - void operator delete(void *, void *) { } \ - void* operator new[](size_t s) { return (A).allocate(s); } \ - void* operator new[](size_t, void *_Where) { return (_Where); } \ - void operator delete[](void*) { } \ - void operator delete[](void *, void *) { } - -namespace glslang { - - // - // Pool version of string. - // - typedef pool_allocator TStringAllocator; - typedef std::basic_string , TStringAllocator> TString; - -} // end namespace glslang - -// Repackage the std::hash for use by unordered map/set with a TString key. -namespace std { - - template<> struct hash { - std::size_t operator()(const glslang::TString& s) const - { - const unsigned _FNV_offset_basis = 2166136261U; - const unsigned _FNV_prime = 16777619U; - unsigned _Val = _FNV_offset_basis; - size_t _Count = s.size(); - const char* _First = s.c_str(); - for (size_t _Next = 0; _Next < _Count; ++_Next) - { - _Val ^= (unsigned)_First[_Next]; - _Val *= _FNV_prime; - } - - return _Val; - } - }; -} - -namespace glslang { - -inline TString* NewPoolTString(const char* s) -{ - void* memory = GetThreadPoolAllocator().allocate(sizeof(TString)); - return new(memory) TString(s); -} - -template inline T* NewPoolObject(T*) -{ - return new(GetThreadPoolAllocator().allocate(sizeof(T))) T; -} - -template inline T* NewPoolObject(T, int instances) -{ - return new(GetThreadPoolAllocator().allocate(instances * sizeof(T))) T[instances]; -} - -// -// Pool allocator versions of vectors, lists, and maps -// -template class TVector : public std::vector > { -public: - POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator()) - - typedef typename std::vector >::size_type size_type; - TVector() : std::vector >() {} - TVector(const pool_allocator& a) : std::vector >(a) {} - TVector(size_type i) : std::vector >(i) {} - TVector(size_type i, const T& val) : std::vector >(i, val) {} -}; - -template class TList : public std::list > { -}; - -template > -class TMap : public std::map > > { -}; - -template , class PRED = std::equal_to > -class TUnorderedMap : public std::unordered_map > > { -}; - -// -// Persistent string memory. Should only be used for strings that survive -// across compiles/links. -// -typedef std::basic_string TPersistString; - -// -// templatized min and max functions. -// -template T Min(const T a, const T b) { return a < b ? a : b; } -template T Max(const T a, const T b) { return a > b ? a : b; } - -// -// Create a TString object from an integer. -// -#if defined _MSC_VER || defined MINGW_HAS_SECURE_API -inline const TString String(const int i, const int base = 10) -{ - char text[16]; // 32 bit ints are at most 10 digits in base 10 - _itoa_s(i, text, sizeof(text), base); - return text; -} -#else -inline const TString String(const int i, const int /*base*/ = 10) -{ - char text[16]; // 32 bit ints are at most 10 digits in base 10 - - // we assume base 10 for all cases - snprintf(text, sizeof(text), "%d", i); - - return text; -} -#endif - -struct TSourceLoc { - void init() { name = nullptr; string = 0; line = 0; column = 0; } - void init(int stringNum) { init(); string = stringNum; } - // Returns the name if it exists. Otherwise, returns the string number. - std::string getStringNameOrNum(bool quoteStringName = true) const - { - if (name != nullptr) - return quoteStringName ? ("\"" + std::string(name) + "\"") : name; - return std::to_string((long long)string); - } - const char* name; // descriptive name for this string - int string; - int line; - int column; -}; - -class TPragmaTable : public TMap { -public: - POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator()) -}; - -const int MaxTokenLength = 1024; - -template bool IsPow2(T powerOf2) -{ - if (powerOf2 <= 0) - return false; - - return (powerOf2 & (powerOf2 - 1)) == 0; -} - -// Round number up to a multiple of the given powerOf2, which is not -// a power, just a number that must be a power of 2. -template void RoundToPow2(T& number, int powerOf2) -{ - assert(IsPow2(powerOf2)); - number = (number + powerOf2 - 1) & ~(powerOf2 - 1); -} - -template bool IsMultipleOfPow2(T number, int powerOf2) -{ - assert(IsPow2(powerOf2)); - return ! (number & (powerOf2 - 1)); -} - -} // end namespace glslang - -#endif // _COMMON_INCLUDED_ diff --git a/External/glslang/glslang/Include/ConstantUnion.h b/External/glslang/glslang/Include/ConstantUnion.h deleted file mode 100644 index 3e933401..00000000 --- a/External/glslang/glslang/Include/ConstantUnion.h +++ /dev/null @@ -1,938 +0,0 @@ -// -// 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 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 EbtInt: - if (constant.iConst == iConst) - return true; - - break; - case EbtUint: - if (constant.uConst == uConst) - return true; - - break; - case EbtInt64: - if (constant.i64Const == i64Const) - return true; - - break; - case EbtUint64: - if (constant.u64Const == u64Const) - return true; - - break; - case EbtDouble: - if (constant.dConst == dConst) - return true; - - break; - case EbtBool: - if (constant.bConst == bConst) - return true; - - break; - default: - assert(false && "Default missing"); - } - - return false; - } - - bool operator!=(const 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 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 EbtInt: - if (iConst > constant.iConst) - return true; - - return false; - case EbtUint: - if (uConst > constant.uConst) - return true; - - return false; - case EbtInt64: - if (i64Const > constant.i64Const) - return true; - - return false; - case EbtUint64: - if (u64Const > constant.u64Const) - return true; - - return false; - case EbtDouble: - if (dConst > constant.dConst) - return true; - - return false; - default: - assert(false && "Default missing"); - return false; - } - } - - bool operator<(const TConstUnion& constant) const - { - assert(type == constant.type); - switch (type) { - case 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 EbtInt: - if (iConst < constant.iConst) - return true; - - return false; - case EbtUint: - if (uConst < constant.uConst) - return true; - - return false; - case EbtInt64: - if (i64Const < constant.i64Const) - return true; - - return false; - case EbtUint64: - if (u64Const < constant.u64Const) - return true; - - return false; - case EbtDouble: - if (dConst < constant.dConst) - return true; - - return false; - default: - assert(false && "Default missing"); - return false; - } - } - - TConstUnion operator+(const TConstUnion& constant) const - { - TConstUnion returnValue; - assert(type == constant.type); - switch (type) { - case EbtInt8: returnValue.setI8Const(i8Const + constant.i8Const); break; - case EbtInt16: returnValue.setI16Const(i16Const + constant.i16Const); break; - case EbtInt: returnValue.setIConst(iConst + constant.iConst); 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 EbtUint: returnValue.setUConst(uConst + constant.uConst); break; - case EbtUint64: returnValue.setU64Const(u64Const + constant.u64Const); break; - case EbtDouble: returnValue.setDConst(dConst + constant.dConst); break; - default: assert(false && "Default missing"); - } - - return returnValue; - } - - TConstUnion operator-(const TConstUnion& constant) const - { - TConstUnion returnValue; - assert(type == constant.type); - switch (type) { - case EbtInt8: returnValue.setI8Const(i8Const - constant.i8Const); break; - case EbtInt16: returnValue.setI16Const(i16Const - constant.i16Const); break; - case EbtInt: returnValue.setIConst(iConst - constant.iConst); 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 EbtUint: returnValue.setUConst(uConst - constant.uConst); break; - case EbtUint64: returnValue.setU64Const(u64Const - constant.u64Const); break; - case EbtDouble: returnValue.setDConst(dConst - constant.dConst); break; - default: assert(false && "Default missing"); - } - - return returnValue; - } - - TConstUnion operator*(const TConstUnion& constant) const - { - TConstUnion returnValue; - assert(type == constant.type); - switch (type) { - case EbtInt8: returnValue.setI8Const(i8Const * constant.i8Const); break; - case EbtInt16: returnValue.setI16Const(i16Const * constant.i16Const); break; - case EbtInt: returnValue.setIConst(iConst * constant.iConst); 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 EbtUint: returnValue.setUConst(uConst * constant.uConst); break; - case EbtUint64: returnValue.setU64Const(u64Const * constant.u64Const); break; - case EbtDouble: returnValue.setDConst(dConst * constant.dConst); break; - default: assert(false && "Default missing"); - } - - return returnValue; - } - - TConstUnion operator%(const TConstUnion& constant) const - { - TConstUnion returnValue; - assert(type == constant.type); - switch (type) { - case EbtInt8: returnValue.setI8Const(i8Const % constant.i8Const); break; - case EbtInt16: returnValue.setI8Const(i8Const % constant.i16Const); break; - case EbtInt: returnValue.setIConst(iConst % constant.iConst); 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 EbtUint: returnValue.setUConst(uConst % constant.uConst); break; - case EbtUint64: returnValue.setU64Const(u64Const % constant.u64Const); break; - default: assert(false && "Default missing"); - } - - return returnValue; - } - - TConstUnion operator>>(const TConstUnion& constant) const - { - TConstUnion returnValue; - switch (type) { - case 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 EbtInt: - switch (constant.type) { - 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 EbtInt: returnValue.setIConst(iConst >> constant.iConst); break; - case EbtUint: returnValue.setIConst(iConst >> constant.uConst); break; - case EbtInt64: returnValue.setIConst(iConst >> constant.i64Const); break; - case EbtUint64: returnValue.setIConst(iConst >> constant.u64Const); break; - default: assert(false && "Default missing"); - } - break; - case EbtUint: - switch (constant.type) { - case 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 EbtInt: returnValue.setUConst(uConst >> constant.iConst); break; - case EbtUint: returnValue.setUConst(uConst >> constant.uConst); break; - case EbtInt64: returnValue.setUConst(uConst >> constant.i64Const); break; - case EbtUint64: returnValue.setUConst(uConst >> constant.u64Const); break; - default: assert(false && "Default missing"); - } - break; - case EbtInt64: - switch (constant.type) { - case 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; - default: assert(false && "Default missing"); - } - - return returnValue; - } - - TConstUnion operator<<(const TConstUnion& constant) const - { - TConstUnion returnValue; - switch (type) { - 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 EbtInt: - switch (constant.type) { - 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 EbtInt: returnValue.setIConst(iConst << constant.iConst); break; - case EbtUint: returnValue.setIConst(iConst << constant.uConst); break; - case EbtInt64: returnValue.setIConst(iConst << constant.i64Const); break; - case EbtUint64: returnValue.setIConst(iConst << constant.u64Const); break; - default: assert(false && "Default missing"); - } - break; - case EbtUint: - switch (constant.type) { - case 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 EbtInt: returnValue.setUConst(uConst << constant.iConst); break; - case EbtUint: returnValue.setUConst(uConst << constant.uConst); break; - case EbtInt64: returnValue.setUConst(uConst << constant.i64Const); break; - case EbtUint64: returnValue.setUConst(uConst << constant.u64Const); break; - default: assert(false && "Default missing"); - } - break; - case EbtInt64: - switch (constant.type) { - case 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; - default: assert(false && "Default missing"); - } - - return returnValue; - } - - TConstUnion operator&(const TConstUnion& constant) const - { - TConstUnion returnValue; - assert(type == constant.type); - switch (type) { - 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 EbtInt: returnValue.setIConst(iConst & constant.iConst); break; - case EbtUint: returnValue.setUConst(uConst & constant.uConst); break; - case EbtInt64: returnValue.setI64Const(i64Const & constant.i64Const); break; - case EbtUint64: returnValue.setU64Const(u64Const & constant.u64Const); break; - default: assert(false && "Default missing"); - } - - return returnValue; - } - - TConstUnion operator|(const TConstUnion& constant) const - { - TConstUnion returnValue; - assert(type == constant.type); - switch (type) { - case 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 EbtInt: returnValue.setIConst(iConst | constant.iConst); break; - case EbtUint: returnValue.setUConst(uConst | constant.uConst); break; - case EbtInt64: returnValue.setI64Const(i64Const | constant.i64Const); break; - case EbtUint64: returnValue.setU64Const(u64Const | constant.u64Const); break; - default: assert(false && "Default missing"); - } - - return returnValue; - } - - TConstUnion operator^(const TConstUnion& constant) const - { - TConstUnion returnValue; - assert(type == constant.type); - switch (type) { - case 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 EbtInt: returnValue.setIConst(iConst ^ constant.iConst); break; - case EbtUint: returnValue.setUConst(uConst ^ constant.uConst); break; - case EbtInt64: returnValue.setI64Const(i64Const ^ constant.i64Const); break; - case EbtUint64: returnValue.setU64Const(u64Const ^ constant.u64Const); break; - default: assert(false && "Default missing"); - } - - return returnValue; - } - - TConstUnion operator~() const - { - TConstUnion returnValue; - switch (type) { - case EbtInt8: returnValue.setI8Const(~i8Const); break; - case EbtUint8: returnValue.setU8Const(~u8Const); break; - case EbtInt16: returnValue.setI16Const(~i16Const); break; - case EbtUint16: returnValue.setU16Const(~u16Const); break; - case EbtInt: returnValue.setIConst(~iConst); break; - case EbtUint: returnValue.setUConst(~uConst); break; - case EbtInt64: returnValue.setI64Const(~i64Const); break; - case EbtUint64: returnValue.setU64Const(~u64Const); break; - default: assert(false && "Default missing"); - } - - return returnValue; - } - - TConstUnion operator&&(const TConstUnion& constant) const - { - TConstUnion returnValue; - assert(type == constant.type); - switch (type) { - case EbtBool: returnValue.setBConst(bConst && constant.bConst); break; - default: assert(false && "Default missing"); - } - - return returnValue; - } - - TConstUnion operator||(const TConstUnion& constant) const - { - TConstUnion returnValue; - assert(type == constant.type); - switch (type) { - case EbtBool: returnValue.setBConst(bConst || constant.bConst); break; - default: assert(false && "Default missing"); - } - - return returnValue; - } - - TBasicType getType() const { return type; } - -private: - union { - 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) : unionArray(a.unionArray) { } - TConstUnionArray(const TConstUnionArray& a, int start, int size) - { - unionArray = new TConstUnionVector(size); - for (int i = 0; i < size; ++i) - (*unionArray)[i] = a[start + i]; - } - - // Use this constructor for a smear operation - TConstUnionArray(int size, const TConstUnion& val) - { - unionArray = new TConstUnionVector(size, val); - } - - int size() const { return unionArray ? (int)unionArray->size() : 0; } - TConstUnion& operator[](size_t index) { return (*unionArray)[index]; } - const TConstUnion& operator[](size_t index) const { return (*unionArray)[index]; } - bool operator==(const TConstUnionArray& rhs) const - { - // this includes the case that both are unallocated - if (unionArray == rhs.unionArray) - return true; - - if (! unionArray || ! rhs.unionArray) - return false; - - return *unionArray == *rhs.unionArray; - } - bool operator!=(const TConstUnionArray& rhs) const { return ! operator==(rhs); } - - double dot(const TConstUnionArray& rhs) - { - assert(rhs.unionArray->size() == unionArray->size()); - double sum = 0.0; - - for (size_t comp = 0; comp < unionArray->size(); ++comp) - sum += (*this)[comp].getDConst() * rhs[comp].getDConst(); - - return sum; - } - - bool empty() const { return unionArray == nullptr; } - -protected: - typedef TVector TConstUnionVector; - TConstUnionVector* unionArray; -}; - -} // end namespace glslang - -#endif // _CONSTANT_UNION_INCLUDED_ diff --git a/External/glslang/glslang/Include/InfoSink.h b/External/glslang/glslang/Include/InfoSink.h deleted file mode 100644 index dceb603c..00000000 --- a/External/glslang/glslang/Include/InfoSink.h +++ /dev/null @@ -1,144 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -#ifndef _INFOSINK_INCLUDED_ -#define _INFOSINK_INCLUDED_ - -#include "../Include/Common.h" -#include - -namespace glslang { - -// -// TPrefixType is used to centralize how info log messages start. -// See below. -// -enum TPrefixType { - EPrefixNone, - EPrefixWarning, - EPrefixError, - EPrefixInternalError, - EPrefixUnimplemented, - EPrefixNote -}; - -enum TOutputStream { - ENull = 0, - EDebugger = 0x01, - EStdOut = 0x02, - EString = 0x04, -}; -// -// Encapsulate info logs for all objects that have them. -// -// The methods are a general set of tools for getting a variety of -// messages and types inserted into the log. -// -class TInfoSinkBase { -public: - TInfoSinkBase() : outputStream(4) {} - void erase() { sink.erase(); } - TInfoSinkBase& operator<<(const TPersistString& t) { append(t); return *this; } - TInfoSinkBase& operator<<(char c) { append(1, c); return *this; } - TInfoSinkBase& operator<<(const char* s) { append(s); return *this; } - TInfoSinkBase& operator<<(int n) { append(String(n)); return *this; } - TInfoSinkBase& operator<<(unsigned int n) { append(String(n)); return *this; } - TInfoSinkBase& operator<<(float n) { const int size = 40; char buf[size]; - snprintf(buf, size, (fabs(n) > 1e-8 && fabs(n) < 1e8) || n == 0.0f ? "%f" : "%g", n); - append(buf); - return *this; } - TInfoSinkBase& operator+(const TPersistString& t) { append(t); return *this; } - TInfoSinkBase& operator+(const TString& t) { append(t); return *this; } - TInfoSinkBase& operator<<(const TString& t) { append(t); return *this; } - TInfoSinkBase& operator+(const char* s) { append(s); return *this; } - const char* c_str() const { return sink.c_str(); } - void prefix(TPrefixType message) { - switch(message) { - case EPrefixNone: break; - case EPrefixWarning: append("WARNING: "); break; - case EPrefixError: append("ERROR: "); break; - case EPrefixInternalError: append("INTERNAL ERROR: "); break; - case EPrefixUnimplemented: append("UNIMPLEMENTED: "); break; - case EPrefixNote: append("NOTE: "); break; - default: append("UNKNOWN ERROR: "); break; - } - } - void location(const TSourceLoc& loc) { - const int maxSize = 24; - char locText[maxSize]; - snprintf(locText, maxSize, ":%d", loc.line); - append(loc.getStringNameOrNum(false).c_str()); - append(locText); - append(": "); - } - void message(TPrefixType message, const char* s) { - prefix(message); - append(s); - append("\n"); - } - void message(TPrefixType message, const char* s, const TSourceLoc& loc) { - prefix(message); - location(loc); - append(s); - append("\n"); - } - - void setOutputStream(int output = 4) - { - outputStream = output; - } - -protected: - void append(const char* s); - - void append(int count, char c); - void append(const TPersistString& t); - void append(const TString& t); - - void checkMem(size_t growth) { if (sink.capacity() < sink.size() + growth + 2) - sink.reserve(sink.capacity() + sink.capacity() / 2); } - void appendToStream(const char* s); - TPersistString sink; - int outputStream; -}; - -} // end namespace glslang - -class TInfoSink { -public: - glslang::TInfoSinkBase info; - glslang::TInfoSinkBase debug; -}; - -#endif // _INFOSINK_INCLUDED_ diff --git a/External/glslang/glslang/Include/InitializeGlobals.h b/External/glslang/glslang/Include/InitializeGlobals.h deleted file mode 100644 index 95d0a40e..00000000 --- a/External/glslang/glslang/Include/InitializeGlobals.h +++ /dev/null @@ -1,44 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -#ifndef __INITIALIZE_GLOBALS_INCLUDED_ -#define __INITIALIZE_GLOBALS_INCLUDED_ - -namespace glslang { - -bool InitializePoolIndex(); - -} // end namespace glslang - -#endif // __INITIALIZE_GLOBALS_INCLUDED_ diff --git a/External/glslang/glslang/Include/PoolAlloc.h b/External/glslang/glslang/Include/PoolAlloc.h deleted file mode 100644 index 0e237a6a..00000000 --- a/External/glslang/glslang/Include/PoolAlloc.h +++ /dev/null @@ -1,317 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// Copyright (C) 2012-2013 LunarG, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -#ifndef _POOLALLOC_INCLUDED_ -#define _POOLALLOC_INCLUDED_ - -#ifdef _DEBUG -# define GUARD_BLOCKS // define to enable guard block sanity checking -#endif - -// -// This header defines an allocator that can be used to efficiently -// allocate a large number of small requests for heap memory, with the -// intention that they are not individually deallocated, but rather -// collectively deallocated at one time. -// -// This simultaneously -// -// * Makes each individual allocation much more efficient; the -// typical allocation is trivial. -// * Completely avoids the cost of doing individual deallocation. -// * Saves the trouble of tracking down and plugging a large class of leaks. -// -// Individual classes can use this allocator by supplying their own -// new and delete methods. -// -// STL containers can use this allocator by using the pool_allocator -// class as the allocator (second) template argument. -// - -#include -#include -#include - -namespace glslang { - -// If we are using guard blocks, we must track each individual -// allocation. If we aren't using guard blocks, these -// never get instantiated, so won't have any impact. -// - -class TAllocation { -public: - TAllocation(size_t size, unsigned char* mem, TAllocation* prev = 0) : - size(size), mem(mem), prevAlloc(prev) { - // Allocations are bracketed: - // [allocationHeader][initialGuardBlock][userData][finalGuardBlock] - // This would be cleaner with if (guardBlockSize)..., but that - // makes the compiler print warnings about 0 length memsets, - // even with the if() protecting them. -# ifdef GUARD_BLOCKS - memset(preGuard(), guardBlockBeginVal, guardBlockSize); - memset(data(), userDataFill, size); - memset(postGuard(), guardBlockEndVal, guardBlockSize); -# endif - } - - void check() const { - checkGuardBlock(preGuard(), guardBlockBeginVal, "before"); - checkGuardBlock(postGuard(), guardBlockEndVal, "after"); - } - - void checkAllocList() const; - - // Return total size needed to accommodate user buffer of 'size', - // plus our tracking data. - inline static size_t allocationSize(size_t size) { - return size + 2 * guardBlockSize + headerSize(); - } - - // Offset from surrounding buffer to get to user data buffer. - inline static unsigned char* offsetAllocation(unsigned char* m) { - return m + guardBlockSize + headerSize(); - } - -private: - void checkGuardBlock(unsigned char* blockMem, unsigned char val, const char* locText) const; - - // Find offsets to pre and post guard blocks, and user data buffer - unsigned char* preGuard() const { return mem + headerSize(); } - unsigned char* data() const { return preGuard() + guardBlockSize; } - unsigned char* postGuard() const { return data() + size; } - - size_t size; // size of the user data area - unsigned char* mem; // beginning of our allocation (pts to header) - TAllocation* prevAlloc; // prior allocation in the chain - - const static unsigned char guardBlockBeginVal; - const static unsigned char guardBlockEndVal; - const static unsigned char userDataFill; - - const static size_t guardBlockSize; -# ifdef GUARD_BLOCKS - inline static size_t headerSize() { return sizeof(TAllocation); } -# else - inline static size_t headerSize() { return 0; } -# endif -}; - -// -// There are several stacks. One is to track the pushing and popping -// of the user, and not yet implemented. The others are simply a -// repositories of free pages or used pages. -// -// Page stacks are linked together with a simple header at the beginning -// of each allocation obtained from the underlying OS. Multi-page allocations -// are returned to the OS. Individual page allocations are kept for future -// re-use. -// -// The "page size" used is not, nor must it match, the underlying OS -// page size. But, having it be about that size or equal to a set of -// pages is likely most optimal. -// -class TPoolAllocator { -public: - TPoolAllocator(int growthIncrement = 8*1024, int allocationAlignment = 16); - - // - // Don't call the destructor just to free up the memory, call pop() - // - ~TPoolAllocator(); - - // - // Call push() to establish a new place to pop memory too. Does not - // have to be called to get things started. - // - void push(); - - // - // Call pop() to free all memory allocated since the last call to push(), - // or if no last call to push, frees all memory since first allocation. - // - void pop(); - - // - // Call popAll() to free all memory allocated. - // - void popAll(); - - // - // Call allocate() to actually acquire memory. Returns 0 if no memory - // available, otherwise a properly aligned pointer to 'numBytes' of memory. - // - void* allocate(size_t numBytes); - - // - // There is no deallocate. The point of this class is that - // deallocation can be skipped by the user of it, as the model - // of use is to simultaneously deallocate everything at once - // by calling pop(), and to not have to solve memory leak problems. - // - -protected: - friend struct tHeader; - - struct tHeader { - tHeader(tHeader* nextPage, size_t pageCount) : -#ifdef GUARD_BLOCKS - lastAllocation(0), -#endif - nextPage(nextPage), pageCount(pageCount) { } - - ~tHeader() { -#ifdef GUARD_BLOCKS - if (lastAllocation) - lastAllocation->checkAllocList(); -#endif - } - -#ifdef GUARD_BLOCKS - TAllocation* lastAllocation; -#endif - tHeader* nextPage; - size_t pageCount; - }; - - struct tAllocState { - size_t offset; - tHeader* page; - }; - typedef std::vector tAllocStack; - - // Track allocations if and only if we're using guard blocks -#ifndef GUARD_BLOCKS - void* initializeAllocation(tHeader*, unsigned char* memory, size_t) { -#else - void* initializeAllocation(tHeader* block, unsigned char* memory, size_t numBytes) { - new(memory) TAllocation(numBytes, memory, block->lastAllocation); - block->lastAllocation = reinterpret_cast(memory); -#endif - - // This is optimized entirely away if GUARD_BLOCKS is not defined. - return TAllocation::offsetAllocation(memory); - } - - size_t pageSize; // granularity of allocation from the OS - size_t alignment; // all returned allocations will be aligned at - // this granularity, which will be a power of 2 - size_t alignmentMask; - size_t headerSkip; // amount of memory to skip to make room for the - // header (basically, size of header, rounded - // up to make it aligned - size_t currentPageOffset; // next offset in top of inUseList to allocate from - tHeader* freeList; // list of popped memory - tHeader* inUseList; // list of all memory currently being used - tAllocStack stack; // stack of where to allocate from, to partition pool - - int numCalls; // just an interesting statistic - size_t totalBytes; // just an interesting statistic -private: - TPoolAllocator& operator=(const TPoolAllocator&); // don't allow assignment operator - TPoolAllocator(const TPoolAllocator&); // don't allow default copy constructor -}; - -// -// There could potentially be many pools with pops happening at -// different times. But a simple use is to have a global pop -// with everyone using the same global allocator. -// -extern TPoolAllocator& GetThreadPoolAllocator(); -void SetThreadPoolAllocator(TPoolAllocator* poolAllocator); - -// -// This STL compatible allocator is intended to be used as the allocator -// parameter to templatized STL containers, like vector and map. -// -// It will use the pools for allocation, and not -// do any deallocation, but will still do destruction. -// -template -class pool_allocator { -public: - typedef size_t size_type; - typedef ptrdiff_t difference_type; - typedef T *pointer; - typedef const T *const_pointer; - typedef T& reference; - typedef const T& const_reference; - typedef T value_type; - template - struct rebind { - typedef pool_allocator other; - }; - pointer address(reference x) const { return &x; } - const_pointer address(const_reference x) const { return &x; } - - pool_allocator() : allocator(GetThreadPoolAllocator()) { } - pool_allocator(TPoolAllocator& a) : allocator(a) { } - pool_allocator(const pool_allocator& p) : allocator(p.allocator) { } - - template - pool_allocator(const pool_allocator& p) : allocator(p.getAllocator()) { } - - pointer allocate(size_type n) { - return reinterpret_cast(getAllocator().allocate(n * sizeof(T))); } - pointer allocate(size_type n, const void*) { - return reinterpret_cast(getAllocator().allocate(n * sizeof(T))); } - - void deallocate(void*, size_type) { } - void deallocate(pointer, size_type) { } - - pointer _Charalloc(size_t n) { - return reinterpret_cast(getAllocator().allocate(n)); } - - void construct(pointer p, const T& val) { new ((void *)p) T(val); } - void destroy(pointer p) { p->T::~T(); } - - bool operator==(const pool_allocator& rhs) const { return &getAllocator() == &rhs.getAllocator(); } - bool operator!=(const pool_allocator& rhs) const { return &getAllocator() != &rhs.getAllocator(); } - - size_type max_size() const { return static_cast(-1) / sizeof(T); } - size_type max_size(int size) const { return static_cast(-1) / size; } - - void setAllocator(TPoolAllocator* a) { allocator = *a; } - TPoolAllocator& getAllocator() const { return allocator; } - -protected: - pool_allocator& operator=(const pool_allocator&) { return *this; } - TPoolAllocator& allocator; -}; - -} // end namespace glslang - -#endif // _POOLALLOC_INCLUDED_ diff --git a/External/glslang/glslang/Include/ResourceLimits.h b/External/glslang/glslang/Include/ResourceLimits.h deleted file mode 100644 index 0d07b8c8..00000000 --- a/External/glslang/glslang/Include/ResourceLimits.h +++ /dev/null @@ -1,140 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// Copyright (C) 2013 LunarG, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -#ifndef _RESOURCE_LIMITS_INCLUDED_ -#define _RESOURCE_LIMITS_INCLUDED_ - -struct TLimits { - bool nonInductiveForLoops; - bool whileLoops; - bool doWhileLoops; - bool generalUniformIndexing; - bool generalAttributeMatrixVectorIndexing; - bool generalVaryingIndexing; - bool generalSamplerIndexing; - bool generalVariableIndexing; - bool generalConstantMatrixVectorIndexing; -}; - -struct TBuiltInResource { - int maxLights; - int maxClipPlanes; - int maxTextureUnits; - int maxTextureCoords; - int maxVertexAttribs; - int maxVertexUniformComponents; - int maxVaryingFloats; - int maxVertexTextureImageUnits; - int maxCombinedTextureImageUnits; - int maxTextureImageUnits; - int maxFragmentUniformComponents; - int maxDrawBuffers; - int maxVertexUniformVectors; - int maxVaryingVectors; - int maxFragmentUniformVectors; - int maxVertexOutputVectors; - int maxFragmentInputVectors; - int minProgramTexelOffset; - int maxProgramTexelOffset; - int maxClipDistances; - int maxComputeWorkGroupCountX; - int maxComputeWorkGroupCountY; - int maxComputeWorkGroupCountZ; - int maxComputeWorkGroupSizeX; - int maxComputeWorkGroupSizeY; - int maxComputeWorkGroupSizeZ; - int maxComputeUniformComponents; - int maxComputeTextureImageUnits; - int maxComputeImageUniforms; - int maxComputeAtomicCounters; - int maxComputeAtomicCounterBuffers; - int maxVaryingComponents; - int maxVertexOutputComponents; - int maxGeometryInputComponents; - int maxGeometryOutputComponents; - int maxFragmentInputComponents; - int maxImageUnits; - int maxCombinedImageUnitsAndFragmentOutputs; - int maxCombinedShaderOutputResources; - int maxImageSamples; - int maxVertexImageUniforms; - int maxTessControlImageUniforms; - int maxTessEvaluationImageUniforms; - int maxGeometryImageUniforms; - int maxFragmentImageUniforms; - int maxCombinedImageUniforms; - int maxGeometryTextureImageUnits; - int maxGeometryOutputVertices; - int maxGeometryTotalOutputComponents; - int maxGeometryUniformComponents; - int maxGeometryVaryingComponents; - int maxTessControlInputComponents; - int maxTessControlOutputComponents; - int maxTessControlTextureImageUnits; - int maxTessControlUniformComponents; - int maxTessControlTotalOutputComponents; - int maxTessEvaluationInputComponents; - int maxTessEvaluationOutputComponents; - int maxTessEvaluationTextureImageUnits; - int maxTessEvaluationUniformComponents; - int maxTessPatchComponents; - int maxPatchVertices; - int maxTessGenLevel; - int maxViewports; - int maxVertexAtomicCounters; - int maxTessControlAtomicCounters; - int maxTessEvaluationAtomicCounters; - int maxGeometryAtomicCounters; - int maxFragmentAtomicCounters; - int maxCombinedAtomicCounters; - int maxAtomicCounterBindings; - int maxVertexAtomicCounterBuffers; - int maxTessControlAtomicCounterBuffers; - int maxTessEvaluationAtomicCounterBuffers; - int maxGeometryAtomicCounterBuffers; - int maxFragmentAtomicCounterBuffers; - int maxCombinedAtomicCounterBuffers; - int maxAtomicCounterBufferSize; - int maxTransformFeedbackBuffers; - int maxTransformFeedbackInterleavedComponents; - int maxCullDistances; - int maxCombinedClipAndCullDistances; - int maxSamples; - - TLimits limits; -}; - -#endif // _RESOURCE_LIMITS_INCLUDED_ diff --git a/External/glslang/glslang/Include/ShHandle.h b/External/glslang/glslang/Include/ShHandle.h deleted file mode 100644 index df07bd8e..00000000 --- a/External/glslang/glslang/Include/ShHandle.h +++ /dev/null @@ -1,176 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -#ifndef _SHHANDLE_INCLUDED_ -#define _SHHANDLE_INCLUDED_ - -// -// Machine independent part of the compiler private objects -// sent as ShHandle to the driver. -// -// This should not be included by driver code. -// - -#define SH_EXPORTING -#include "../Public/ShaderLang.h" -#include "../MachineIndependent/Versions.h" -#include "InfoSink.h" - -class TCompiler; -class TLinker; -class TUniformMap; - -// -// The base class used to back handles returned to the driver. -// -class TShHandleBase { -public: - TShHandleBase() { pool = new glslang::TPoolAllocator; } - virtual ~TShHandleBase() { delete pool; } - virtual TCompiler* getAsCompiler() { return 0; } - virtual TLinker* getAsLinker() { return 0; } - virtual TUniformMap* getAsUniformMap() { return 0; } - virtual glslang::TPoolAllocator* getPool() const { return pool; } -private: - glslang::TPoolAllocator* pool; -}; - -// -// The base class for the machine dependent linker to derive from -// for managing where uniforms live. -// -class TUniformMap : public TShHandleBase { -public: - TUniformMap() { } - virtual ~TUniformMap() { } - virtual TUniformMap* getAsUniformMap() { return this; } - virtual int getLocation(const char* name) = 0; - virtual TInfoSink& getInfoSink() { return infoSink; } - TInfoSink infoSink; -}; - -class TIntermNode; - -// -// The base class for the machine dependent compiler to derive from -// for managing object code from the compile. -// -class TCompiler : public TShHandleBase { -public: - TCompiler(EShLanguage l, TInfoSink& sink) : infoSink(sink) , language(l), haveValidObjectCode(false) { } - virtual ~TCompiler() { } - EShLanguage getLanguage() { return language; } - virtual TInfoSink& getInfoSink() { return infoSink; } - - virtual bool compile(TIntermNode* root, int version = 0, EProfile profile = ENoProfile) = 0; - - virtual TCompiler* getAsCompiler() { return this; } - virtual bool linkable() { return haveValidObjectCode; } - - TInfoSink& infoSink; -protected: - TCompiler& operator=(TCompiler&); - - EShLanguage language; - bool haveValidObjectCode; -}; - -// -// Link operations are based on a list of compile results... -// -typedef glslang::TVector TCompilerList; -typedef glslang::TVector THandleList; - -// -// The base class for the machine dependent linker to derive from -// to manage the resulting executable. -// - -class TLinker : public TShHandleBase { -public: - TLinker(EShExecutable e, TInfoSink& iSink) : - infoSink(iSink), - executable(e), - haveReturnableObjectCode(false), - appAttributeBindings(0), - fixedAttributeBindings(0), - excludedAttributes(0), - excludedCount(0), - uniformBindings(0) { } - virtual TLinker* getAsLinker() { return this; } - virtual ~TLinker() { } - virtual bool link(TCompilerList&, TUniformMap*) = 0; - virtual bool link(THandleList&) { return false; } - virtual void setAppAttributeBindings(const ShBindingTable* t) { appAttributeBindings = t; } - virtual void setFixedAttributeBindings(const ShBindingTable* t) { fixedAttributeBindings = t; } - virtual void getAttributeBindings(ShBindingTable const **t) const = 0; - virtual void setExcludedAttributes(const int* attributes, int count) { excludedAttributes = attributes; excludedCount = count; } - virtual ShBindingTable* getUniformBindings() const { return uniformBindings; } - virtual const void* getObjectCode() const { return 0; } // a real compiler would be returning object code here - virtual TInfoSink& getInfoSink() { return infoSink; } - TInfoSink& infoSink; -protected: - TLinker& operator=(TLinker&); - EShExecutable executable; - bool haveReturnableObjectCode; // true when objectCode is acceptable to send to driver - - const ShBindingTable* appAttributeBindings; - const ShBindingTable* fixedAttributeBindings; - const int* excludedAttributes; - int excludedCount; - ShBindingTable* uniformBindings; // created by the linker -}; - -// -// This is the interface between the machine independent code -// and the machine dependent code. -// -// The machine dependent code should derive from the classes -// above. Then Construct*() and Delete*() will create and -// destroy the machine dependent objects, which contain the -// above machine independent information. -// -TCompiler* ConstructCompiler(EShLanguage, int); - -TShHandleBase* ConstructLinker(EShExecutable, int); -TShHandleBase* ConstructBindings(); -void DeleteLinker(TShHandleBase*); -void DeleteBindingList(TShHandleBase* bindingList); - -TUniformMap* ConstructUniformMap(); -void DeleteCompiler(TCompiler*); - -void DeleteUniformMap(TUniformMap*); - -#endif // _SHHANDLE_INCLUDED_ diff --git a/External/glslang/glslang/Include/Types.h b/External/glslang/glslang/Include/Types.h deleted file mode 100644 index 39d6737c..00000000 --- a/External/glslang/glslang/Include/Types.h +++ /dev/null @@ -1,1947 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// Copyright (C) 2012-2016 LunarG, Inc. -// Copyright (C) 2015-2016 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. -// - -#ifndef _TYPES_INCLUDED -#define _TYPES_INCLUDED - -#include "../Include/Common.h" -#include "../Include/BaseTypes.h" -#include "../Public/ShaderLang.h" -#include "arrays.h" - -#include - -namespace glslang { - -const int GlslangMaxTypeLength = 200; // TODO: need to print block/struct one member per line, so this can stay bounded - -const char* const AnonymousPrefix = "anon@"; // for something like a block whose members can be directly accessed -inline bool IsAnonymous(const TString& name) -{ - return name.compare(0, 5, AnonymousPrefix) == 0; -} - -// -// Details within a sampler type -// -enum TSamplerDim { - EsdNone, - Esd1D, - Esd2D, - Esd3D, - EsdCube, - EsdRect, - EsdBuffer, - EsdSubpass, // goes only with non-sampled image (image is true) - EsdNumDims -}; - -struct TSampler { // misnomer now; includes images, textures without sampler, and textures with sampler - TBasicType type : 8; // type returned by sampler - TSamplerDim dim : 8; - bool arrayed : 1; - bool shadow : 1; - bool ms : 1; - bool image : 1; // image, combined should be false - bool combined : 1; // true means texture is combined with a sampler, false means texture with no sampler - bool sampler : 1; // true means a pure sampler, other fields should be clear() - bool external : 1; // GL_OES_EGL_image_external - unsigned int vectorSize : 3; // vector return type size. - - // Some languages support structures as sample results. Storing the whole structure in the - // TSampler is too large, so there is an index to a separate table. - static const unsigned structReturnIndexBits = 4; // number of index bits to use. - static const unsigned structReturnSlots = (1< TTypeList; - -typedef TVector TIdentifierList; - -// -// Following are a series of helper enums for managing layouts and qualifiers, -// used for TPublicType, TType, others. -// - -enum TLayoutPacking { - ElpNone, - ElpShared, // default, but different than saying nothing - ElpStd140, - ElpStd430, - ElpPacked, - ElpCount // If expanding, see bitfield width below -}; - -enum TLayoutMatrix { - ElmNone, - ElmRowMajor, - ElmColumnMajor, // default, but different than saying nothing - ElmCount // If expanding, see bitfield width below -}; - -// Union of geometry shader and tessellation shader geometry types. -// They don't go into TType, but rather have current state per shader or -// active parser type (TPublicType). -enum TLayoutGeometry { - ElgNone, - ElgPoints, - ElgLines, - ElgLinesAdjacency, - ElgLineStrip, - ElgTriangles, - ElgTrianglesAdjacency, - ElgTriangleStrip, - ElgQuads, - ElgIsolines, -}; - -enum TVertexSpacing { - EvsNone, - EvsEqual, - EvsFractionalEven, - EvsFractionalOdd -}; - -enum TVertexOrder { - EvoNone, - EvoCw, - EvoCcw -}; - -// Note: order matters, as type of format is done by comparison. -enum TLayoutFormat { - ElfNone, - - // Float image - ElfRgba32f, - ElfRgba16f, - ElfR32f, - ElfRgba8, - ElfRgba8Snorm, - - ElfEsFloatGuard, // to help with comparisons - - ElfRg32f, - ElfRg16f, - ElfR11fG11fB10f, - ElfR16f, - ElfRgba16, - ElfRgb10A2, - ElfRg16, - ElfRg8, - ElfR16, - ElfR8, - ElfRgba16Snorm, - ElfRg16Snorm, - ElfRg8Snorm, - ElfR16Snorm, - ElfR8Snorm, - - ElfFloatGuard, // to help with comparisons - - // Int image - ElfRgba32i, - ElfRgba16i, - ElfRgba8i, - ElfR32i, - - ElfEsIntGuard, // to help with comparisons - - ElfRg32i, - ElfRg16i, - ElfRg8i, - ElfR16i, - ElfR8i, - - ElfIntGuard, // to help with comparisons - - // Uint image - ElfRgba32ui, - ElfRgba16ui, - ElfRgba8ui, - ElfR32ui, - - ElfEsUintGuard, // to help with comparisons - - ElfRg32ui, - ElfRg16ui, - ElfRgb10a2ui, - ElfRg8ui, - ElfR16ui, - ElfR8ui, - - ElfCount -}; - -enum TLayoutDepth { - EldNone, - EldAny, - EldGreater, - EldLess, - EldUnchanged, - - EldCount -}; - -enum TBlendEquationShift { - // No 'EBlendNone': - // These are used as bit-shift amounts. A mask of such shifts will have type 'int', - // and in that space, 0 means no bits set, or none. In this enum, 0 means (1 << 0), a bit is set. - EBlendMultiply, - EBlendScreen, - EBlendOverlay, - EBlendDarken, - EBlendLighten, - EBlendColordodge, - EBlendColorburn, - EBlendHardlight, - EBlendSoftlight, - EBlendDifference, - EBlendExclusion, - EBlendHslHue, - EBlendHslSaturation, - EBlendHslColor, - EBlendHslLuminosity, - EBlendAllEquations, - - EBlendCount -}; - -class TQualifier { -public: - static const int layoutNotSet = -1; - - void clear() - { - precision = EpqNone; - invariant = false; - noContraction = false; - makeTemporary(); - declaredBuiltIn = EbvNone; - } - - // drop qualifiers that don't belong in a temporary variable - void makeTemporary() - { - semanticName = nullptr; - storage = EvqTemporary; - builtIn = EbvNone; - clearInterstage(); - clearMemory(); - specConstant = false; - nonUniform = false; - clearLayout(); - } - - void clearInterstage() - { - clearInterpolation(); - patch = false; - sample = false; - } - - void clearInterpolation() - { - centroid = false; - smooth = false; - flat = false; - nopersp = false; -#ifdef AMD_EXTENSIONS - explicitInterp = false; -#endif - } - - void clearMemory() - { - coherent = false; - volatil = false; - restrict = false; - readonly = false; - writeonly = false; - } - - // Drop just the storage qualification, which perhaps should - // never be done, as it is fundamentally inconsistent, but need to - // explore what downstream consumers need. - // E.g., in a dereference, it is an inconsistency between: - // A) partially dereferenced resource is still in the storage class it started in - // B) partially dereferenced resource is a new temporary object - // If A, then nothing should change, if B, then everything should change, but this is half way. - void makePartialTemporary() - { - storage = EvqTemporary; - specConstant = false; - nonUniform = false; - } - - const char* semanticName; - TStorageQualifier storage : 6; - TBuiltInVariable builtIn : 8; - TBuiltInVariable declaredBuiltIn : 8; - TPrecisionQualifier precision : 3; - bool invariant : 1; // require canonical treatment for cross-shader invariance - bool noContraction: 1; // prevent contraction and reassociation, e.g., for 'precise' keyword, and expressions it affects - bool centroid : 1; - bool smooth : 1; - bool flat : 1; - bool nopersp : 1; -#ifdef AMD_EXTENSIONS - bool explicitInterp : 1; -#endif - bool patch : 1; - bool sample : 1; - bool coherent : 1; - bool volatil : 1; - bool restrict : 1; - bool readonly : 1; - bool writeonly : 1; - bool specConstant : 1; // having a constant_id is not sufficient: expressions have no id, but are still specConstant - bool nonUniform : 1; - - bool isMemory() const - { - return coherent || volatil || restrict || readonly || writeonly; - } - bool isInterpolation() const - { -#ifdef AMD_EXTENSIONS - return flat || smooth || nopersp || explicitInterp; -#else - return flat || smooth || nopersp; -#endif - } -#ifdef AMD_EXTENSIONS - bool isExplicitInterpolation() const - { - return explicitInterp; - } -#endif - bool isAuxiliary() const - { - return centroid || patch || sample; - } - - bool isPipeInput() const - { - switch (storage) { - case EvqVaryingIn: - case EvqFragCoord: - case EvqPointCoord: - case EvqFace: - case EvqVertexId: - case EvqInstanceId: - return true; - default: - return false; - } - } - - bool isPipeOutput() const - { - switch (storage) { - case EvqPosition: - case EvqPointSize: - case EvqClipVertex: - case EvqVaryingOut: - case EvqFragColor: - case EvqFragDepth: - return true; - default: - return false; - } - } - - bool isParamInput() const - { - switch (storage) { - case EvqIn: - case EvqInOut: - case EvqConstReadOnly: - return true; - default: - return false; - } - } - - bool isParamOutput() const - { - switch (storage) { - case EvqOut: - case EvqInOut: - return true; - default: - return false; - } - } - - bool isUniformOrBuffer() const - { - switch (storage) { - case EvqUniform: - case EvqBuffer: - return true; - default: - return false; - } - } - - bool isIo() const - { - switch (storage) { - case EvqUniform: - case EvqBuffer: - case EvqVaryingIn: - case EvqFragCoord: - case EvqPointCoord: - case EvqFace: - case EvqVertexId: - case EvqInstanceId: - case EvqPosition: - case EvqPointSize: - case EvqClipVertex: - case EvqVaryingOut: - case EvqFragColor: - case EvqFragDepth: - return true; - default: - return false; - } - } - - // True if this type of IO is supposed to be arrayed with extra level for per-vertex data - bool isArrayedIo(EShLanguage language) const - { - switch (language) { - case EShLangGeometry: - return isPipeInput(); - case EShLangTessControl: - return ! patch && (isPipeInput() || isPipeOutput()); - case EShLangTessEvaluation: - return ! patch && isPipeInput(); - default: - return false; - } - } - - // Implementing an embedded layout-qualifier class here, since C++ can't have a real class bitfield - void clearLayout() // all layout - { - clearUniformLayout(); - - layoutPushConstant = false; -#ifdef NV_EXTENSIONS - layoutPassthrough = false; - layoutViewportRelative = false; - // -2048 as the default value indicating layoutSecondaryViewportRelative is not set - layoutSecondaryViewportRelativeOffset = -2048; -#endif - - clearInterstageLayout(); - - layoutSpecConstantId = layoutSpecConstantIdEnd; - - layoutFormat = ElfNone; - } - void clearInterstageLayout() - { - layoutLocation = layoutLocationEnd; - layoutComponent = layoutComponentEnd; - layoutIndex = layoutIndexEnd; - clearStreamLayout(); - clearXfbLayout(); - } - void clearStreamLayout() - { - layoutStream = layoutStreamEnd; - } - void clearXfbLayout() - { - layoutXfbBuffer = layoutXfbBufferEnd; - layoutXfbStride = layoutXfbStrideEnd; - layoutXfbOffset = layoutXfbOffsetEnd; - } - - bool hasNonXfbLayout() const - { - return hasUniformLayout() || - hasAnyLocation() || - hasStream() || - hasFormat() || - layoutPushConstant; - } - bool hasLayout() const - { - return hasNonXfbLayout() || - hasXfb(); - } - TLayoutMatrix layoutMatrix : 3; - TLayoutPacking layoutPacking : 4; - int layoutOffset; - int layoutAlign; - - unsigned int layoutLocation :12; - static const unsigned int layoutLocationEnd = 0xFFF; - - unsigned int layoutComponent : 3; - static const unsigned int layoutComponentEnd = 4; - - unsigned int layoutSet : 7; - static const unsigned int layoutSetEnd = 0x3F; - - unsigned int layoutBinding : 16; - static const unsigned int layoutBindingEnd = 0xFFFF; - - unsigned int layoutIndex : 8; - static const unsigned int layoutIndexEnd = 0xFF; - - unsigned int layoutStream : 8; - static const unsigned int layoutStreamEnd = 0xFF; - - unsigned int layoutXfbBuffer : 4; - static const unsigned int layoutXfbBufferEnd = 0xF; - - unsigned int layoutXfbStride : 10; - static const unsigned int layoutXfbStrideEnd = 0x3FF; - - unsigned int layoutXfbOffset : 10; - static const unsigned int layoutXfbOffsetEnd = 0x3FF; - - unsigned int layoutAttachment : 8; // for input_attachment_index - static const unsigned int layoutAttachmentEnd = 0XFF; - - unsigned int layoutSpecConstantId : 11; - static const unsigned int layoutSpecConstantIdEnd = 0x7FF; - - TLayoutFormat layoutFormat : 8; - - bool layoutPushConstant; - -#ifdef NV_EXTENSIONS - bool layoutPassthrough; - bool layoutViewportRelative; - int layoutSecondaryViewportRelativeOffset; -#endif - - bool hasUniformLayout() const - { - return hasMatrix() || - hasPacking() || - hasOffset() || - hasBinding() || - hasSet() || - hasAlign(); - } - void clearUniformLayout() // only uniform specific - { - layoutMatrix = ElmNone; - layoutPacking = ElpNone; - layoutOffset = layoutNotSet; - layoutAlign = layoutNotSet; - - layoutSet = layoutSetEnd; - layoutBinding = layoutBindingEnd; - layoutAttachment = layoutAttachmentEnd; - } - - bool hasMatrix() const - { - return layoutMatrix != ElmNone; - } - bool hasPacking() const - { - return layoutPacking != ElpNone; - } - bool hasOffset() const - { - return layoutOffset != layoutNotSet; - } - bool hasAlign() const - { - return layoutAlign != layoutNotSet; - } - bool hasAnyLocation() const - { - return hasLocation() || - hasComponent() || - hasIndex(); - } - bool hasLocation() const - { - return layoutLocation != layoutLocationEnd; - } - bool hasComponent() const - { - return layoutComponent != layoutComponentEnd; - } - bool hasIndex() const - { - return layoutIndex != layoutIndexEnd; - } - bool hasSet() const - { - return layoutSet != layoutSetEnd; - } - bool hasBinding() const - { - return layoutBinding != layoutBindingEnd; - } - bool hasStream() const - { - return layoutStream != layoutStreamEnd; - } - bool hasFormat() const - { - return layoutFormat != ElfNone; - } - bool hasXfb() const - { - return hasXfbBuffer() || - hasXfbStride() || - hasXfbOffset(); - } - bool hasXfbBuffer() const - { - return layoutXfbBuffer != layoutXfbBufferEnd; - } - bool hasXfbStride() const - { - return layoutXfbStride != layoutXfbStrideEnd; - } - bool hasXfbOffset() const - { - return layoutXfbOffset != layoutXfbOffsetEnd; - } - bool hasAttachment() const - { - return layoutAttachment != layoutAttachmentEnd; - } - bool hasSpecConstantId() const - { - // Not the same thing as being a specialization constant, this - // is just whether or not it was declared with an ID. - return layoutSpecConstantId != layoutSpecConstantIdEnd; - } - bool isSpecConstant() const - { - // True if type is a specialization constant, whether or not it - // had a specialization-constant ID, and false if it is not a - // true front-end constant. - return specConstant; - } - bool isNonUniform() const - { - return nonUniform; - } - bool isFrontEndConstant() const - { - // True if the front-end knows the final constant value. - // This allows front-end constant folding. - return storage == EvqConst && ! specConstant; - } - bool isConstant() const - { - // True if is either kind of constant; specialization or regular. - return isFrontEndConstant() || isSpecConstant(); - } - void makeSpecConstant() - { - storage = EvqConst; - specConstant = true; - } - static const char* getLayoutPackingString(TLayoutPacking packing) - { - switch (packing) { - case ElpPacked: return "packed"; - case ElpShared: return "shared"; - case ElpStd140: return "std140"; - case ElpStd430: return "std430"; - default: return "none"; - } - } - static const char* getLayoutMatrixString(TLayoutMatrix m) - { - switch (m) { - case ElmColumnMajor: return "column_major"; - case ElmRowMajor: return "row_major"; - default: return "none"; - } - } - static const char* getLayoutFormatString(TLayoutFormat f) - { - switch (f) { - case ElfRgba32f: return "rgba32f"; - case ElfRgba16f: return "rgba16f"; - case ElfRg32f: return "rg32f"; - case ElfRg16f: return "rg16f"; - case ElfR11fG11fB10f: return "r11f_g11f_b10f"; - case ElfR32f: return "r32f"; - case ElfR16f: return "r16f"; - case ElfRgba16: return "rgba16"; - case ElfRgb10A2: return "rgb10_a2"; - case ElfRgba8: return "rgba8"; - case ElfRg16: return "rg16"; - case ElfRg8: return "rg8"; - case ElfR16: return "r16"; - case ElfR8: return "r8"; - case ElfRgba16Snorm: return "rgba16_snorm"; - case ElfRgba8Snorm: return "rgba8_snorm"; - case ElfRg16Snorm: return "rg16_snorm"; - case ElfRg8Snorm: return "rg8_snorm"; - case ElfR16Snorm: return "r16_snorm"; - case ElfR8Snorm: return "r8_snorm"; - - case ElfRgba32i: return "rgba32i"; - case ElfRgba16i: return "rgba16i"; - case ElfRgba8i: return "rgba8i"; - case ElfRg32i: return "rg32i"; - case ElfRg16i: return "rg16i"; - case ElfRg8i: return "rg8i"; - case ElfR32i: return "r32i"; - case ElfR16i: return "r16i"; - case ElfR8i: return "r8i"; - - case ElfRgba32ui: return "rgba32ui"; - case ElfRgba16ui: return "rgba16ui"; - case ElfRgba8ui: return "rgba8ui"; - case ElfRg32ui: return "rg32ui"; - case ElfRg16ui: return "rg16ui"; - case ElfRgb10a2ui: return "rgb10_a2ui"; - case ElfRg8ui: return "rg8ui"; - case ElfR32ui: return "r32ui"; - case ElfR16ui: return "r16ui"; - case ElfR8ui: return "r8ui"; - default: return "none"; - } - } - static const char* getLayoutDepthString(TLayoutDepth d) - { - switch (d) { - case EldAny: return "depth_any"; - case EldGreater: return "depth_greater"; - case EldLess: return "depth_less"; - case EldUnchanged: return "depth_unchanged"; - default: return "none"; - } - } - static const char* getBlendEquationString(TBlendEquationShift e) - { - switch (e) { - case EBlendMultiply: return "blend_support_multiply"; - case EBlendScreen: return "blend_support_screen"; - case EBlendOverlay: return "blend_support_overlay"; - case EBlendDarken: return "blend_support_darken"; - case EBlendLighten: return "blend_support_lighten"; - case EBlendColordodge: return "blend_support_colordodge"; - case EBlendColorburn: return "blend_support_colorburn"; - case EBlendHardlight: return "blend_support_hardlight"; - case EBlendSoftlight: return "blend_support_softlight"; - case EBlendDifference: return "blend_support_difference"; - case EBlendExclusion: return "blend_support_exclusion"; - case EBlendHslHue: return "blend_support_hsl_hue"; - case EBlendHslSaturation: return "blend_support_hsl_saturation"; - case EBlendHslColor: return "blend_support_hsl_color"; - case EBlendHslLuminosity: return "blend_support_hsl_luminosity"; - case EBlendAllEquations: return "blend_support_all_equations"; - default: return "unknown"; - } - } - static const char* getGeometryString(TLayoutGeometry geometry) - { - switch (geometry) { - case ElgPoints: return "points"; - case ElgLines: return "lines"; - case ElgLinesAdjacency: return "lines_adjacency"; - case ElgLineStrip: return "line_strip"; - case ElgTriangles: return "triangles"; - case ElgTrianglesAdjacency: return "triangles_adjacency"; - case ElgTriangleStrip: return "triangle_strip"; - case ElgQuads: return "quads"; - case ElgIsolines: return "isolines"; - default: return "none"; - } - } - static const char* getVertexSpacingString(TVertexSpacing spacing) - { - switch (spacing) { - case EvsEqual: return "equal_spacing"; - case EvsFractionalEven: return "fractional_even_spacing"; - case EvsFractionalOdd: return "fractional_odd_spacing"; - default: return "none"; - } - } - static const char* getVertexOrderString(TVertexOrder order) - { - switch (order) { - case EvoCw: return "cw"; - case EvoCcw: return "ccw"; - default: return "none"; - } - } - static int mapGeometryToSize(TLayoutGeometry geometry) - { - switch (geometry) { - case ElgPoints: return 1; - case ElgLines: return 2; - case ElgLinesAdjacency: return 4; - case ElgTriangles: return 3; - case ElgTrianglesAdjacency: return 6; - default: return 0; - } - } -}; - -// Qualifiers that don't need to be keep per object. They have shader scope, not object scope. -// So, they will not be part of TType, TQualifier, etc. -struct TShaderQualifiers { - TLayoutGeometry geometry; // geometry/tessellation shader in/out primitives - bool pixelCenterInteger; // fragment shader - bool originUpperLeft; // fragment shader - int invocations; - int vertices; // both for tessellation "vertices" and geometry "max_vertices" - TVertexSpacing spacing; - TVertexOrder order; - bool pointMode; - int localSize[3]; // compute shader - int localSizeSpecId[3]; // compute shader specialization id for gl_WorkGroupSize - bool earlyFragmentTests; // fragment input - bool postDepthCoverage; // fragment input - TLayoutDepth layoutDepth; - bool blendEquation; // true if any blend equation was specified - int numViews; // multiview extenstions - -#ifdef NV_EXTENSIONS - bool layoutOverrideCoverage; // true if layout override_coverage set -#endif - - void init() - { - geometry = ElgNone; - originUpperLeft = false; - pixelCenterInteger = false; - invocations = TQualifier::layoutNotSet; - vertices = TQualifier::layoutNotSet; - spacing = EvsNone; - order = EvoNone; - pointMode = false; - localSize[0] = 1; - localSize[1] = 1; - localSize[2] = 1; - localSizeSpecId[0] = TQualifier::layoutNotSet; - localSizeSpecId[1] = TQualifier::layoutNotSet; - localSizeSpecId[2] = TQualifier::layoutNotSet; - earlyFragmentTests = false; - postDepthCoverage = false; - layoutDepth = EldNone; - blendEquation = false; - numViews = TQualifier::layoutNotSet; -#ifdef NV_EXTENSIONS - layoutOverrideCoverage = false; -#endif - } - - // Merge in characteristics from the 'src' qualifier. They can override when - // set, but never erase when not set. - void merge(const TShaderQualifiers& src) - { - if (src.geometry != ElgNone) - geometry = src.geometry; - if (src.pixelCenterInteger) - pixelCenterInteger = src.pixelCenterInteger; - if (src.originUpperLeft) - originUpperLeft = src.originUpperLeft; - if (src.invocations != TQualifier::layoutNotSet) - invocations = src.invocations; - if (src.vertices != TQualifier::layoutNotSet) - vertices = src.vertices; - if (src.spacing != EvsNone) - spacing = src.spacing; - if (src.order != EvoNone) - order = src.order; - if (src.pointMode) - pointMode = true; - for (int i = 0; i < 3; ++i) { - if (src.localSize[i] > 1) - localSize[i] = src.localSize[i]; - } - for (int i = 0; i < 3; ++i) { - if (src.localSizeSpecId[i] != TQualifier::layoutNotSet) - localSizeSpecId[i] = src.localSizeSpecId[i]; - } - if (src.earlyFragmentTests) - earlyFragmentTests = true; - if (src.postDepthCoverage) - postDepthCoverage = true; - if (src.layoutDepth) - layoutDepth = src.layoutDepth; - if (src.blendEquation) - blendEquation = src.blendEquation; - if (src.numViews != TQualifier::layoutNotSet) - numViews = src.numViews; -#ifdef NV_EXTENSIONS - if (src.layoutOverrideCoverage) - layoutOverrideCoverage = src.layoutOverrideCoverage; -#endif - } -}; - -// -// TPublicType is just temporarily used while parsing and not quite the same -// information kept per node in TType. Due to the bison stack, it can't have -// types that it thinks have non-trivial constructors. It should -// just be used while recognizing the grammar, not anything else. -// Once enough is known about the situation, the proper information -// moved into a TType, or the parse context, etc. -// -class TPublicType { -public: - TBasicType basicType; - TSampler sampler; - TQualifier qualifier; - TShaderQualifiers shaderQualifiers; - int vectorSize : 4; - int matrixCols : 4; - int matrixRows : 4; - TArraySizes* arraySizes; - const TType* userDef; - TSourceLoc loc; - - void initType(const TSourceLoc& l) - { - basicType = EbtVoid; - vectorSize = 1; - matrixRows = 0; - matrixCols = 0; - arraySizes = nullptr; - userDef = nullptr; - loc = l; - } - - void initQualifiers(bool global = false) - { - qualifier.clear(); - if (global) - qualifier.storage = EvqGlobal; - } - - void init(const TSourceLoc& l, bool global = false) - { - initType(l); - sampler.clear(); - initQualifiers(global); - shaderQualifiers.init(); - } - - void setVector(int s) - { - matrixRows = 0; - matrixCols = 0; - vectorSize = s; - } - - void setMatrix(int c, int r) - { - matrixRows = r; - matrixCols = c; - vectorSize = 0; - } - - bool isScalar() const - { - return matrixCols == 0 && vectorSize == 1 && arraySizes == nullptr && userDef == nullptr; - } - - // "Image" is a superset of "Subpass" - bool isImage() const { return basicType == EbtSampler && sampler.isImage(); } - bool isSubpass() const { return basicType == EbtSampler && sampler.isSubpass(); } -}; - -// -// Base class for things that have a type. -// -class TType { -public: - POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator()) - - // for "empty" type (no args) or simple scalar/vector/matrix - explicit TType(TBasicType t = EbtVoid, TStorageQualifier q = EvqTemporary, int vs = 1, int mc = 0, int mr = 0, - bool isVector = false) : - basicType(t), vectorSize(vs), matrixCols(mc), matrixRows(mr), vector1(isVector && vs == 1), - arraySizes(nullptr), structure(nullptr), fieldName(nullptr), typeName(nullptr) - { - sampler.clear(); - qualifier.clear(); - qualifier.storage = q; - assert(!(isMatrix() && vectorSize != 0)); // prevent vectorSize != 0 on matrices - } - // for explicit precision qualifier - TType(TBasicType t, TStorageQualifier q, TPrecisionQualifier p, int vs = 1, int mc = 0, int mr = 0, - bool isVector = false) : - basicType(t), vectorSize(vs), matrixCols(mc), matrixRows(mr), vector1(isVector && vs == 1), - arraySizes(nullptr), structure(nullptr), fieldName(nullptr), typeName(nullptr) - { - sampler.clear(); - qualifier.clear(); - qualifier.storage = q; - qualifier.precision = p; - assert(p >= EpqNone && p <= EpqHigh); - assert(!(isMatrix() && vectorSize != 0)); // prevent vectorSize != 0 on matrices - } - // for turning a TPublicType into a TType, using a shallow copy - explicit TType(const TPublicType& p) : - basicType(p.basicType), - vectorSize(p.vectorSize), matrixCols(p.matrixCols), matrixRows(p.matrixRows), vector1(false), - arraySizes(p.arraySizes), structure(nullptr), fieldName(nullptr), typeName(nullptr) - { - if (basicType == EbtSampler) - sampler = p.sampler; - else - sampler.clear(); - qualifier = p.qualifier; - if (p.userDef) { - structure = p.userDef->getWritableStruct(); // public type is short-lived; there are no sharing issues - typeName = NewPoolTString(p.userDef->getTypeName().c_str()); - } - } - // for construction of sampler types - TType(const TSampler& sampler, TStorageQualifier q = EvqUniform, TArraySizes* as = nullptr) : - basicType(EbtSampler), vectorSize(1), matrixCols(0), matrixRows(0), vector1(false), - arraySizes(as), structure(nullptr), fieldName(nullptr), typeName(nullptr), - sampler(sampler) - { - qualifier.clear(); - qualifier.storage = q; - } - // to efficiently make a dereferenced type - // without ever duplicating the outer structure that will be thrown away - // and using only shallow copy - TType(const TType& type, int derefIndex, bool rowMajor = false) - { - if (type.isArray()) { - shallowCopy(type); - if (type.getArraySizes()->getNumDims() == 1) { - arraySizes = nullptr; - } else { - // want our own copy of the array, so we can edit it - arraySizes = new TArraySizes; - arraySizes->copyDereferenced(*type.arraySizes); - } - } else if (type.basicType == EbtStruct || type.basicType == EbtBlock) { - // do a structure dereference - const TTypeList& memberList = *type.getStruct(); - shallowCopy(*memberList[derefIndex].type); - return; - } else { - // do a vector/matrix dereference - shallowCopy(type); - if (matrixCols > 0) { - // dereference from matrix to vector - if (rowMajor) - vectorSize = matrixCols; - else - vectorSize = matrixRows; - matrixCols = 0; - matrixRows = 0; - if (vectorSize == 1) - vector1 = true; - } else if (isVector()) { - // dereference from vector to scalar - vectorSize = 1; - vector1 = false; - } - } - } - // for making structures, ... - TType(TTypeList* userDef, const TString& n) : - basicType(EbtStruct), vectorSize(1), matrixCols(0), matrixRows(0), vector1(false), - arraySizes(nullptr), structure(userDef), fieldName(nullptr) - { - sampler.clear(); - qualifier.clear(); - typeName = NewPoolTString(n.c_str()); - } - // For interface blocks - TType(TTypeList* userDef, const TString& n, const TQualifier& q) : - basicType(EbtBlock), vectorSize(1), matrixCols(0), matrixRows(0), vector1(false), - qualifier(q), arraySizes(nullptr), structure(userDef), fieldName(nullptr) - { - sampler.clear(); - typeName = NewPoolTString(n.c_str()); - } - virtual ~TType() {} - - // Not for use across pool pops; it will cause multiple instances of TType to point to the same information. - // This only works if that information (like a structure's list of types) does not change and - // the instances are sharing the same pool. - void shallowCopy(const TType& copyOf) - { - basicType = copyOf.basicType; - sampler = copyOf.sampler; - qualifier = copyOf.qualifier; - vectorSize = copyOf.vectorSize; - matrixCols = copyOf.matrixCols; - matrixRows = copyOf.matrixRows; - vector1 = copyOf.vector1; - arraySizes = copyOf.arraySizes; // copying the pointer only, not the contents - structure = copyOf.structure; - fieldName = copyOf.fieldName; - typeName = copyOf.typeName; - } - - // Make complete copy of the whole type graph rooted at 'copyOf'. - void deepCopy(const TType& copyOf) - { - TMap copied; // to enable copying a type graph as a graph, not a tree - deepCopy(copyOf, copied); - } - - // Recursively make temporary - void makeTemporary() - { - getQualifier().makeTemporary(); - - if (isStruct()) - for (unsigned int i = 0; i < structure->size(); ++i) - (*structure)[i].type->makeTemporary(); - } - - TType* clone() const - { - TType *newType = new TType(); - newType->deepCopy(*this); - - return newType; - } - - void makeVector() { vector1 = true; } - - 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; - } - - virtual TBasicType getBasicType() const { return basicType; } - virtual const TSampler& getSampler() const { return sampler; } - virtual TSampler& getSampler() { return sampler; } - - virtual TQualifier& getQualifier() { return qualifier; } - virtual const TQualifier& getQualifier() const { return qualifier; } - - virtual int getVectorSize() const { return vectorSize; } // returns 1 for either scalar or vector of size 1, valid for both - virtual int getMatrixCols() const { return matrixCols; } - virtual int getMatrixRows() const { return matrixRows; } - virtual int getOuterArraySize() const { return arraySizes->getOuterSize(); } - virtual TIntermTyped* getOuterArrayNode() const { return arraySizes->getOuterNode(); } - virtual int getCumulativeArraySize() const { return arraySizes->getCumulativeSize(); } - virtual bool isArrayOfArrays() const { return arraySizes != nullptr && arraySizes->getNumDims() > 1; } - virtual int getImplicitArraySize() const { return arraySizes->getImplicitSize(); } - virtual const TArraySizes* getArraySizes() const { return arraySizes; } - virtual TArraySizes* getArraySizes() { return arraySizes; } - - virtual bool isScalar() const { return ! isVector() && ! isMatrix() && ! isStruct() && ! isArray(); } - virtual bool isScalarOrVec1() const { return isScalar() || vector1; } - virtual bool isVector() const { return vectorSize > 1 || vector1; } - virtual bool isMatrix() const { return matrixCols ? true : false; } - virtual bool isArray() const { return arraySizes != nullptr; } - virtual bool 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 structure != nullptr; } - 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 || basicType == EbtAtomicUint; } - virtual bool isBuiltIn() const { return getQualifier().builtIn != EbvNone; } - - // "Image" is a superset of "Subpass" - virtual bool isImage() const { return basicType == EbtSampler && getSampler().isImage(); } - virtual bool isSubpass() const { return basicType == EbtSampler && getSampler().isSubpass(); } - virtual bool isTexture() const { return basicType == EbtSampler && getSampler().isTexture(); } - - // return true if this type contains any subtype which satisfies the given predicate. - template - bool contains(P predicate) const - { - if (predicate(this)) - return true; - - const auto hasa = [predicate](const TTypeLoc& tl) { return tl.type->contains(predicate); }; - - return structure && std::any_of(structure->begin(), structure->end(), hasa); - } - - // Recursively checks if the type contains the given basic type - virtual bool containsBasicType(TBasicType checkType) const - { - return contains([checkType](const TType* t) { return t->basicType == checkType; } ); - } - - // Recursively check the structure for any arrays, needed for some error checks - virtual bool containsArray() const - { - return contains([](const TType* t) { return t->isArray(); } ); - } - - // Check the structure for any structures, needed for some error checks - virtual bool containsStructure() const - { - return contains([this](const TType* t) { return t != this && t->isStruct(); } ); - } - - // Recursively check the structure for any 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: - return true; - default: - return false; - } - }; - - return contains(nonOpaque); - } - - virtual bool containsSpecializationSize() const - { - return contains([](const TType* t) { return t->isArray() && t->arraySizes->isOuterSpecialization(); } ); - } - - // Array editing methods. Array descriptors can be shared across - // type instances. This allows all uses of the same array - // to be updated at once. E.g., all nodes can be explicitly sized - // by tracking and correcting one implicit size. Or, all nodes - // can get the explicit size on a redeclaration that gives size. - // - // N.B.: Don't share with the shared symbol tables (symbols are - // marked as isReadOnly(). Such symbols with arrays that will be - // edited need to copyUp() on first use, so that - // A) the edits don't effect the shared symbol table, and - // B) the edits are shared across all users. - void updateArraySizes(const TType& type) - { - // For when we may already be sharing existing array descriptors, - // keeping the pointers the same, just updating the contents. - assert(arraySizes != nullptr); - assert(type.arraySizes != nullptr); - *arraySizes = *type.arraySizes; - } - void 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()); - 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); - } - } - - const char* getBasicString() const - { - return TType::getBasicString(basicType); - } - - static const char* getBasicString(TBasicType t) - { - switch (t) { - case EbtVoid: return "void"; - case EbtFloat: return "float"; - case EbtDouble: return "double"; - 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 EbtInt: return "int"; - case EbtUint: return "uint"; - case EbtInt64: return "int64_t"; - case EbtUint64: return "uint64_t"; - case EbtBool: return "bool"; - case EbtAtomicUint: return "atomic_uint"; - case EbtSampler: return "sampler/image"; - case EbtStruct: return "structure"; - case EbtBlock: return "block"; - default: return "unknown type"; - } - } - - TString getCompleteString() const - { - TString typeString; - - const auto appendStr = [&](const char* s) { typeString.append(s); }; - const auto appendUint = [&](unsigned int u) { typeString.append(std::to_string(u).c_str()); }; - const auto appendInt = [&](int i) { typeString.append(std::to_string(i).c_str()); }; - - if (qualifier.hasLayout()) { - // To reduce noise, skip this if the only layout is an xfb_buffer - // with no triggering xfb_offset. - TQualifier noXfbBuffer = qualifier; - noXfbBuffer.layoutXfbBuffer = TQualifier::layoutXfbBufferEnd; - if (noXfbBuffer.hasLayout()) { - appendStr("layout("); - if (qualifier.hasAnyLocation()) { - appendStr(" location="); - appendUint(qualifier.layoutLocation); - if (qualifier.hasComponent()) { - appendStr(" component="); - appendUint(qualifier.layoutComponent); - } - if (qualifier.hasIndex()) { - appendStr(" index="); - appendUint(qualifier.layoutIndex); - } - } - if (qualifier.hasSet()) { - appendStr(" set="); - appendUint(qualifier.layoutSet); - } - if (qualifier.hasBinding()) { - appendStr(" binding="); - appendUint(qualifier.layoutBinding); - } - if (qualifier.hasStream()) { - appendStr(" stream="); - appendUint(qualifier.layoutStream); - } - if (qualifier.hasMatrix()) { - appendStr(" "); - appendStr(TQualifier::getLayoutMatrixString(qualifier.layoutMatrix)); - } - if (qualifier.hasPacking()) { - appendStr(" "); - appendStr(TQualifier::getLayoutPackingString(qualifier.layoutPacking)); - } - if (qualifier.hasOffset()) { - appendStr(" offset="); - appendInt(qualifier.layoutOffset); - } - if (qualifier.hasAlign()) { - appendStr(" align="); - appendInt(qualifier.layoutAlign); - } - if (qualifier.hasFormat()) { - appendStr(" "); - appendStr(TQualifier::getLayoutFormatString(qualifier.layoutFormat)); - } - if (qualifier.hasXfbBuffer() && qualifier.hasXfbOffset()) { - appendStr(" xfb_buffer="); - appendUint(qualifier.layoutXfbBuffer); - } - if (qualifier.hasXfbOffset()) { - appendStr(" xfb_offset="); - appendUint(qualifier.layoutXfbOffset); - } - if (qualifier.hasXfbStride()) { - appendStr(" xfb_stride="); - appendUint(qualifier.layoutXfbStride); - } - if (qualifier.hasAttachment()) { - appendStr(" input_attachment_index="); - appendUint(qualifier.layoutAttachment); - } - if (qualifier.hasSpecConstantId()) { - appendStr(" constant_id="); - appendUint(qualifier.layoutSpecConstantId); - } - if (qualifier.layoutPushConstant) - appendStr(" push_constant"); - -#ifdef NV_EXTENSIONS - if (qualifier.layoutPassthrough) - appendStr(" passthrough"); - if (qualifier.layoutViewportRelative) - appendStr(" layoutViewportRelative"); - if (qualifier.layoutSecondaryViewportRelativeOffset != -2048) { - appendStr(" layoutSecondaryViewportRelativeOffset="); - appendInt(qualifier.layoutSecondaryViewportRelativeOffset); - } -#endif - - appendStr(")"); - } - } - - if (qualifier.invariant) - appendStr(" invariant"); - if (qualifier.noContraction) - appendStr(" noContraction"); - if (qualifier.centroid) - appendStr(" centroid"); - if (qualifier.smooth) - appendStr(" smooth"); - if (qualifier.flat) - appendStr(" flat"); - if (qualifier.nopersp) - appendStr(" noperspective"); -#ifdef AMD_EXTENSIONS - if (qualifier.explicitInterp) - appendStr(" __explicitInterpAMD"); -#endif - if (qualifier.patch) - appendStr(" patch"); - if (qualifier.sample) - appendStr(" sample"); - if (qualifier.coherent) - appendStr(" coherent"); - if (qualifier.volatil) - appendStr(" volatile"); - if (qualifier.restrict) - appendStr(" restrict"); - if (qualifier.readonly) - appendStr(" readonly"); - if (qualifier.writeonly) - appendStr(" writeonly"); - if (qualifier.specConstant) - appendStr(" specialization-constant"); - 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 (qualifier.precision != EpqNone) { - appendStr(" "); - appendStr(getPrecisionQualifierString()); - } - if (isMatrix()) { - appendStr(" "); - appendInt(matrixCols); - appendStr("X"); - appendInt(matrixRows); - appendStr(" matrix of"); - } else if (isVector()) { - appendStr(" "); - appendInt(vectorSize); - appendStr("-component vector of"); - } - - appendStr(" "); - typeString.append(getBasicTypeString()); - - if (qualifier.builtIn != EbvNone) { - appendStr(" "); - appendStr(getBuiltInVariableString()); - } - - // Add struct/block members - if (structure) { - appendStr("{"); - for (size_t i = 0; i < structure->size(); ++i) { - if (! (*structure)[i].type->hiddenMember()) { - typeString.append((*structure)[i].type->getCompleteString()); - typeString.append(" "); - typeString.append((*structure)[i].type->getFieldName()); - if (i < structure->size() - 1) - appendStr(", "); - } - } - appendStr("}"); - } - - return typeString; - } - - TString getBasicTypeString() const - { - if (basicType == EbtSampler) - return sampler.getString(); - else - return getBasicString(); - } - - const char* getStorageQualifierString() const { return GetStorageQualifierString(qualifier.storage); } - const char* getBuiltInVariableString() const { return GetBuiltInVariableString(qualifier.builtIn); } - const char* getPrecisionQualifierString() const { return GetPrecisionQualifierString(qualifier.precision); } - const TTypeList* getStruct() const { return structure; } - void setStruct(TTypeList* s) { structure = s; } - TTypeList* getWritableStruct() const { return structure; } // This should only be used when known to not be sharing with other threads - - int computeNumComponents() const - { - int components = 0; - - if (getBasicType() == EbtStruct || getBasicType() == EbtBlock) { - for (TTypeList::const_iterator tl = getStruct()->begin(); tl != getStruct()->end(); tl++) - components += ((*tl).type)->computeNumComponents(); - } else if (matrixCols) - components = matrixCols * matrixRows; - else - components = vectorSize; - - if (arraySizes != nullptr) { - components *= arraySizes->getCumulativeSize(); - } - - return components; - } - - // append this type's mangled name to the passed in 'name' - void appendMangledName(TString& name) const - { - buildMangledName(name); - name += ';' ; - } - - // Do two structure types match? They could be declared independently, - // in different places, but still might satisfy the definition of matching. - // From the spec: - // - // "Structures must have the same name, sequence of type names, and - // type definitions, and member names to be considered the same type. - // This rule applies recursively for nested or embedded types." - // - bool sameStructType(const TType& right) const - { - // Most commonly, they are both nullptr, or the same pointer to the same actual structure - if (structure == right.structure) - return true; - - // Both being nullptr was caught above, now they both have to be structures of the same number of elements - if (structure == nullptr || right.structure == nullptr || - structure->size() != right.structure->size()) - return false; - - // Structure names have to match - if (*typeName != *right.typeName) - return false; - - // Compare the names and types of all the members, which have to match - for (unsigned int i = 0; i < structure->size(); ++i) { - if ((*structure)[i].type->getFieldName() != (*right.structure)[i].type->getFieldName()) - return false; - - if (*(*structure)[i].type != *(*right.structure)[i].type) - return false; - } - - return true; - } - - // See if two types match, in all aspects except arrayness - bool sameElementType(const TType& right) const - { - return basicType == right.basicType && sameElementShape(right); - } - - // See if two type's arrayness match - bool sameArrayness(const TType& right) const - { - return ((arraySizes == nullptr && right.arraySizes == nullptr) || - (arraySizes != nullptr && right.arraySizes != nullptr && *arraySizes == *right.arraySizes)); - } - - // See if two type's arrayness match in everything except their outer dimension - bool sameInnerArrayness(const TType& right) const - { - assert(arraySizes != nullptr && right.arraySizes != nullptr); - return arraySizes->sameInnerArrayness(*right.arraySizes); - } - - // See if two type's elements match in all ways except basic type - bool sameElementShape(const TType& right) const - { - return sampler == right.sampler && - vectorSize == right.vectorSize && - matrixCols == right.matrixCols && - matrixRows == right.matrixRows && - vector1 == right.vector1 && - sameStructType(right); - } - - // See if two types match in all ways (just the actual type, not qualification) - bool operator==(const TType& right) const - { - return sameElementType(right) && sameArrayness(right); - } - - bool operator!=(const TType& right) const - { - return ! operator==(right); - } - -protected: - // Require consumer to pick between deep copy and shallow copy. - TType(const TType& type); - TType& operator=(const TType& type); - - // Recursively copy a type graph, while preserving the graph-like - // quality. That is, don't make more than one copy of a structure that - // gets reused multiple times in the type graph. - void deepCopy(const TType& copyOf, TMap& copiedMap) - { - shallowCopy(copyOf); - - if (copyOf.arraySizes) { - arraySizes = new TArraySizes; - *arraySizes = *copyOf.arraySizes; - } - - if (copyOf.structure) { - auto prevCopy = copiedMap.find(copyOf.structure); - if (prevCopy != copiedMap.end()) - structure = prevCopy->second; - else { - structure = new TTypeList; - copiedMap[copyOf.structure] = structure; - for (unsigned int i = 0; i < copyOf.structure->size(); ++i) { - TTypeLoc typeLoc; - typeLoc.loc = (*copyOf.structure)[i].loc; - typeLoc.type = new TType(); - typeLoc.type->deepCopy(*(*copyOf.structure)[i].type, copiedMap); - structure->push_back(typeLoc); - } - } - } - - if (copyOf.fieldName) - fieldName = NewPoolTString(copyOf.fieldName->c_str()); - if (copyOf.typeName) - typeName = NewPoolTString(copyOf.typeName->c_str()); - } - - - void buildMangledName(TString&) const; - - TBasicType basicType : 8; - int vectorSize : 4; // 1 means either scalar or 1-component vector; see vector1 to disambiguate. - int matrixCols : 4; - int matrixRows : 4; - bool vector1 : 1; // Backward-compatible tracking of a 1-component vector distinguished from a scalar. - // GLSL 4.5 never has a 1-component vector; so this will always be false until such - // functionality is added. - // HLSL does have a 1-component vectors, so this will be true to disambiguate - // from a scalar. - TQualifier qualifier; - - TArraySizes* arraySizes; // nullptr unless an array; can be shared across types - TTypeList* structure; // nullptr unless this is a struct; can be shared across types - TString *fieldName; // for structure field names - TString *typeName; // for structure type name - TSampler sampler; -}; - -} // end namespace glslang - -#endif // _TYPES_INCLUDED_ diff --git a/External/glslang/glslang/Include/arrays.h b/External/glslang/glslang/Include/arrays.h deleted file mode 100644 index af8f560b..00000000 --- a/External/glslang/glslang/Include/arrays.h +++ /dev/null @@ -1,339 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// Copyright (C) 2012-2013 LunarG, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -// -// Implement types for tracking GLSL arrays, arrays of arrays, etc. -// - -#ifndef _ARRAYS_INCLUDED -#define _ARRAYS_INCLUDED - -#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) { return sizes == rhs.sizes; } - bool operator!=(const TArraySizes& rhs) { 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/External/glslang/glslang/Include/intermediate.h b/External/glslang/glslang/Include/intermediate.h deleted file mode 100644 index 19eb7aa8..00000000 --- a/External/glslang/glslang/Include/intermediate.h +++ /dev/null @@ -1,1677 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// Copyright (C) 2012-2016 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. -// - -// -// 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, - - // (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, - - // - // 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, - -#ifdef AMD_EXTENSIONS - EOpMin3, - EOpMax3, - EOpMid3, -#endif - - EOpDPdx, // Fragment only - EOpDPdy, // Fragment only - EOpFwidth, // Fragment only - EOpDPdxFine, // Fragment only - EOpDPdyFine, // Fragment only - EOpFwidthFine, // Fragment only - EOpDPdxCoarse, // Fragment only - EOpDPdyCoarse, // Fragment only - EOpFwidthCoarse, // Fragment only - - EOpInterpolateAtCentroid, // Fragment only - EOpInterpolateAtSample, // Fragment only - EOpInterpolateAtOffset, // Fragment only - -#ifdef AMD_EXTENSIONS - EOpInterpolateAtVertex, -#endif - - EOpMatrixTimesMatrix, - EOpOuterProduct, - EOpDeterminant, - EOpMatrixInverse, - EOpTranspose, - - EOpFtransform, - - EOpNoise, - - EOpEmitVertex, // geometry only - EOpEndPrimitive, // geometry only - EOpEmitStreamVertex, // geometry only - EOpEndStreamPrimitive, // geometry only - - EOpBarrier, - EOpMemoryBarrier, - EOpMemoryBarrierAtomicCounter, - EOpMemoryBarrierBuffer, - EOpMemoryBarrierImage, - EOpMemoryBarrierShared, // compute only - EOpGroupMemoryBarrier, // compute only - - EOpBallot, - EOpReadInvocation, - EOpReadFirstInvocation, - - EOpAnyInvocation, - EOpAllInvocations, - EOpAllInvocationsEqual, - - 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, - -#ifdef NV_EXTENSIONS - EOpSubgroupPartition, - EOpSubgroupPartitionedAdd, - EOpSubgroupPartitionedMul, - EOpSubgroupPartitionedMin, - EOpSubgroupPartitionedMax, - EOpSubgroupPartitionedAnd, - EOpSubgroupPartitionedOr, - EOpSubgroupPartitionedXor, - EOpSubgroupPartitionedInclusiveAdd, - EOpSubgroupPartitionedInclusiveMul, - EOpSubgroupPartitionedInclusiveMin, - EOpSubgroupPartitionedInclusiveMax, - EOpSubgroupPartitionedInclusiveAnd, - EOpSubgroupPartitionedInclusiveOr, - EOpSubgroupPartitionedInclusiveXor, - EOpSubgroupPartitionedExclusiveAdd, - EOpSubgroupPartitionedExclusiveMul, - EOpSubgroupPartitionedExclusiveMin, - EOpSubgroupPartitionedExclusiveMax, - EOpSubgroupPartitionedExclusiveAnd, - EOpSubgroupPartitionedExclusiveOr, - EOpSubgroupPartitionedExclusiveXor, -#endif - - EOpSubgroupGuardStop, - -#ifdef AMD_EXTENSIONS - EOpMinInvocations, - EOpMaxInvocations, - EOpAddInvocations, - EOpMinInvocationsNonUniform, - EOpMaxInvocationsNonUniform, - EOpAddInvocationsNonUniform, - EOpMinInvocationsInclusiveScan, - EOpMaxInvocationsInclusiveScan, - EOpAddInvocationsInclusiveScan, - EOpMinInvocationsInclusiveScanNonUniform, - EOpMaxInvocationsInclusiveScanNonUniform, - EOpAddInvocationsInclusiveScanNonUniform, - EOpMinInvocationsExclusiveScan, - EOpMaxInvocationsExclusiveScan, - EOpAddInvocationsExclusiveScan, - EOpMinInvocationsExclusiveScanNonUniform, - EOpMaxInvocationsExclusiveScanNonUniform, - EOpAddInvocationsExclusiveScanNonUniform, - EOpSwizzleInvocations, - EOpSwizzleInvocationsMasked, - EOpWriteInvocation, - EOpMbcnt, - - EOpCubeFaceIndex, - EOpCubeFaceCoord, - EOpTime, -#endif - - EOpAtomicAdd, - EOpAtomicMin, - EOpAtomicMax, - EOpAtomicAnd, - EOpAtomicOr, - EOpAtomicXor, - EOpAtomicExchange, - EOpAtomicCompSwap, - - EOpAtomicCounterIncrement, // results in pre-increment value - EOpAtomicCounterDecrement, // results in post-decrement value - EOpAtomicCounter, - EOpAtomicCounterAdd, - EOpAtomicCounterSubtract, - EOpAtomicCounterMin, - EOpAtomicCounterMax, - EOpAtomicCounterAnd, - EOpAtomicCounterOr, - EOpAtomicCounterXor, - EOpAtomicCounterExchange, - EOpAtomicCounterCompSwap, - - EOpAny, - EOpAll, - - // - // Branch - // - - EOpKill, // Fragment only - EOpReturn, - EOpBreak, - EOpContinue, - EOpCase, - EOpDefault, - - // - // Constructors - // - - EOpConstructGuardStart, - EOpConstructInt, // these first scalar forms also identify what implicit conversion is needed - EOpConstructUint, - EOpConstructInt8, - EOpConstructUint8, - EOpConstructInt16, - EOpConstructUint16, - EOpConstructInt64, - EOpConstructUint64, - EOpConstructBool, - EOpConstructFloat, - EOpConstructDouble, - EOpConstructVec2, - EOpConstructVec3, - EOpConstructVec4, - 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, - EOpConstructMat2x2, - EOpConstructMat2x3, - EOpConstructMat2x4, - EOpConstructMat3x2, - EOpConstructMat3x3, - EOpConstructMat3x4, - EOpConstructMat4x2, - EOpConstructMat4x3, - EOpConstructMat4x4, - EOpConstructDMat2x2, - EOpConstructDMat2x3, - EOpConstructDMat2x4, - EOpConstructDMat3x2, - EOpConstructDMat3x3, - EOpConstructDMat3x4, - EOpConstructDMat4x2, - EOpConstructDMat4x3, - EOpConstructDMat4x4, - EOpConstructIMat2x2, - EOpConstructIMat2x3, - EOpConstructIMat2x4, - EOpConstructIMat3x2, - EOpConstructIMat3x3, - EOpConstructIMat3x4, - EOpConstructIMat4x2, - EOpConstructIMat4x3, - EOpConstructIMat4x4, - EOpConstructUMat2x2, - EOpConstructUMat2x3, - EOpConstructUMat2x4, - EOpConstructUMat3x2, - EOpConstructUMat3x3, - EOpConstructUMat3x4, - EOpConstructUMat4x2, - EOpConstructUMat4x3, - EOpConstructUMat4x4, - EOpConstructBMat2x2, - EOpConstructBMat2x3, - EOpConstructBMat2x4, - EOpConstructBMat3x2, - EOpConstructBMat3x3, - EOpConstructBMat3x4, - EOpConstructBMat4x2, - EOpConstructBMat4x3, - EOpConstructBMat4x4, - 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 - 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, -#ifdef AMD_EXTENSIONS - EOpImageLoadLod, - EOpImageStoreLod, -#endif - EOpImageAtomicAdd, - EOpImageAtomicMin, - EOpImageAtomicMax, - EOpImageAtomicAnd, - EOpImageAtomicOr, - EOpImageAtomicXor, - EOpImageAtomicExchange, - EOpImageAtomicCompSwap, - - EOpSubpassLoad, - EOpSubpassLoadMS, - EOpSparseImageLoad, -#ifdef AMD_EXTENSIONS - EOpSparseImageLoadLod, -#endif - - EOpImageGuardEnd, - - // - // Texture operations - // - - EOpTextureGuardBegin, - - EOpTextureQuerySize, - EOpTextureQueryLod, - EOpTextureQueryLevels, - EOpTextureQuerySamples, - - EOpSamplingGuardBegin, - - EOpTexture, - EOpTextureProj, - EOpTextureLod, - EOpTextureOffset, - EOpTextureFetch, - EOpTextureFetchOffset, - EOpTextureProjOffset, - EOpTextureLodOffset, - EOpTextureProjLod, - EOpTextureProjLodOffset, - EOpTextureGrad, - EOpTextureGradOffset, - EOpTextureProjGrad, - EOpTextureProjGradOffset, - EOpTextureGather, - EOpTextureGatherOffset, - EOpTextureGatherOffsets, - EOpTextureClamp, - EOpTextureOffsetClamp, - EOpTextureGradClamp, - EOpTextureGradOffsetClamp, -#ifdef AMD_EXTENSIONS - EOpTextureGatherLod, - EOpTextureGatherLodOffset, - EOpTextureGatherLodOffsets, - EOpFragmentMaskFetch, - EOpFragmentFetch, -#endif - - EOpSparseTextureGuardBegin, - - EOpSparseTexture, - EOpSparseTextureLod, - EOpSparseTextureOffset, - EOpSparseTextureFetch, - EOpSparseTextureFetchOffset, - EOpSparseTextureLodOffset, - EOpSparseTextureGrad, - EOpSparseTextureGradOffset, - EOpSparseTextureGather, - EOpSparseTextureGatherOffset, - EOpSparseTextureGatherOffsets, - EOpSparseTexelsResident, - EOpSparseTextureClamp, - EOpSparseTextureOffsetClamp, - EOpSparseTextureGradClamp, - EOpSparseTextureGradOffsetClamp, -#ifdef AMD_EXTENSIONS - EOpSparseTextureGatherLod, - EOpSparseTextureGatherLodOffset, - EOpSparseTextureGatherLodOffsets, -#endif - - EOpSparseTextureGuardEnd, - EOpSamplingGuardEnd, - EOpTextureGuardEnd, - - // - // Integer operations - // - - EOpAddCarry, - EOpSubBorrow, - EOpUMulExtended, - EOpIMulExtended, - EOpBitfieldExtract, - EOpBitfieldInsert, - EOpBitFieldReverse, - EOpBitCount, - EOpFindLSB, - EOpFindMSB, - - // - // HLSL operations - // - - EOpClip, // discard if input value < 0 - EOpIsFinite, - EOpLog10, // base 10 log - EOpRcp, // 1/x - EOpSaturate, // clamp from 0 to 1 - EOpSinCos, // sin and cos in out parameters - EOpGenMul, // mul(x,y) on any of mat/vec/scalars - EOpDst, // x = 1, y=src0.y * src1.y, z=src0.z, w=src1.w - EOpInterlockedAdd, // atomic ops, but uses [optional] out arg instead of return - EOpInterlockedAnd, // ... - EOpInterlockedCompareExchange, // ... - EOpInterlockedCompareStore, // ... - EOpInterlockedExchange, // ... - EOpInterlockedMax, // ... - EOpInterlockedMin, // ... - EOpInterlockedOr, // ... - EOpInterlockedXor, // ... - EOpAllMemoryBarrierWithGroupSync, // memory barriers without non-hlsl AST equivalents - EOpDeviceMemoryBarrier, // ... - EOpDeviceMemoryBarrierWithGroupSync, // ... - EOpWorkgroupMemoryBarrier, // ... - EOpWorkgroupMemoryBarrierWithGroupSync, // ... - EOpEvaluateAttributeSnapped, // InterpolateAtOffset with int position on 16x16 grid - EOpF32tof16, // HLSL conversion: half of a PackHalf2x16 - EOpF16tof32, // HLSL conversion: half of an UnpackHalf2x16 - EOpLit, // HLSL lighting coefficient vector - EOpTextureBias, // HLSL texture bias: will be lowered to EOpTexture - EOpAsDouble, // slightly different from EOpUint64BitsToDouble - EOpD3DCOLORtoUBYTE4, // convert and swizzle 4-component color to UBYTE4 range - - EOpMethodSample, // Texture object methods. These are translated to existing - EOpMethodSampleBias, // AST methods, and exist to represent HLSL semantics until that - EOpMethodSampleCmp, // translation is performed. See HlslParseContext::decomposeSampleMethods(). - EOpMethodSampleCmpLevelZero, // ... - EOpMethodSampleGrad, // ... - EOpMethodSampleLevel, // ... - EOpMethodLoad, // ... - EOpMethodGetDimensions, // ... - EOpMethodGetSamplePosition, // ... - EOpMethodGather, // ... - EOpMethodCalculateLevelOfDetail, // ... - EOpMethodCalculateLevelOfDetailUnclamped, // ... - - // Load already defined above for textures - EOpMethodLoad2, // Structure buffer object methods. These are translated to existing - EOpMethodLoad3, // AST methods, and exist to represent HLSL semantics until that - EOpMethodLoad4, // translation is performed. See HlslParseContext::decomposeSampleMethods(). - EOpMethodStore, // ... - EOpMethodStore2, // ... - EOpMethodStore3, // ... - EOpMethodStore4, // ... - EOpMethodIncrementCounter, // ... - EOpMethodDecrementCounter, // ... - // EOpMethodAppend is defined for geo shaders below - EOpMethodConsume, - - // SM5 texture methods - EOpMethodGatherRed, // These are covered under the above EOpMethodSample comment about - EOpMethodGatherGreen, // translation to existing AST opcodes. They exist temporarily - EOpMethodGatherBlue, // because HLSL arguments are slightly different. - EOpMethodGatherAlpha, // ... - EOpMethodGatherCmp, // ... - EOpMethodGatherCmpRed, // ... - EOpMethodGatherCmpGreen, // ... - EOpMethodGatherCmpBlue, // ... - EOpMethodGatherCmpAlpha, // ... - - // geometry methods - EOpMethodAppend, // Geometry shader methods - EOpMethodRestartStrip, // ... - - // matrix - EOpMatrixSwizzle, // select multiple matrix components (non-column) - - // 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()). -}; - -class TIntermTraverser; -class TIntermOperator; -class TIntermAggregate; -class TIntermUnary; -class TIntermBinary; -class TIntermConstantUnion; -class TIntermSelection; -class TIntermSwitch; -class TIntermBranch; -class TIntermTyped; -class TIntermMethod; -class TIntermSymbol; -class TIntermLoop; - -} // end namespace glslang - -// -// Base class for the tree nodes -// -// (Put outside the glslang namespace, as it's used as part of the external interface.) -// -class TIntermNode { -public: - POOL_ALLOCATOR_NEW_DELETE(glslang::GetThreadPoolAllocator()) - - TIntermNode() { loc.init(); } - virtual const glslang::TSourceLoc& getLoc() const { return loc; } - virtual void setLoc(const glslang::TSourceLoc& l) { loc = l; } - virtual void traverse(glslang::TIntermTraverser*) = 0; - virtual glslang::TIntermTyped* getAsTyped() { return 0; } - virtual glslang::TIntermOperator* getAsOperator() { return 0; } - virtual glslang::TIntermConstantUnion* getAsConstantUnion() { return 0; } - virtual glslang::TIntermAggregate* getAsAggregate() { return 0; } - virtual glslang::TIntermUnary* getAsUnaryNode() { return 0; } - virtual glslang::TIntermBinary* getAsBinaryNode() { return 0; } - virtual glslang::TIntermSelection* getAsSelectionNode() { return 0; } - virtual glslang::TIntermSwitch* getAsSwitchNode() { return 0; } - virtual glslang::TIntermMethod* getAsMethodNode() { return 0; } - virtual glslang::TIntermSymbol* getAsSymbolNode() { return 0; } - virtual glslang::TIntermBranch* getAsBranchNode() { return 0; } - virtual glslang::TIntermLoop* getAsLoopNode() { return 0; } - - virtual const glslang::TIntermTyped* getAsTyped() const { return 0; } - virtual const glslang::TIntermOperator* getAsOperator() const { return 0; } - virtual const glslang::TIntermConstantUnion* getAsConstantUnion() const { return 0; } - virtual const glslang::TIntermAggregate* getAsAggregate() const { return 0; } - virtual const glslang::TIntermUnary* getAsUnaryNode() const { return 0; } - virtual const glslang::TIntermBinary* getAsBinaryNode() const { return 0; } - virtual const glslang::TIntermSelection* getAsSelectionNode() const { return 0; } - virtual const glslang::TIntermSwitch* getAsSwitchNode() const { return 0; } - virtual const glslang::TIntermMethod* getAsMethodNode() const { return 0; } - virtual const glslang::TIntermSymbol* getAsSymbolNode() const { return 0; } - virtual const glslang::TIntermBranch* getAsBranchNode() const { return 0; } - virtual const glslang::TIntermLoop* getAsLoopNode() const { return 0; } - virtual ~TIntermNode() { } - -protected: - TIntermNode(const TIntermNode&); - TIntermNode& operator=(const TIntermNode&); - glslang::TSourceLoc loc; -}; - -namespace glslang { - -// -// This is just to help yacc. -// -struct TIntermNodePair { - TIntermNode* node1; - TIntermNode* node2; -}; - -// -// Intermediate class for nodes that have a type. -// -class TIntermTyped : public TIntermNode { -public: - TIntermTyped(const TType& t) { type.shallowCopy(t); } - TIntermTyped(TBasicType basicType) { TType bt(basicType); type.shallowCopy(bt); } - virtual TIntermTyped* getAsTyped() { return this; } - virtual const TIntermTyped* getAsTyped() const { return this; } - virtual void setType(const TType& t) { type.shallowCopy(t); } - virtual const TType& getType() const { return type; } - virtual TType& getWritableType() { return type; } - - virtual TBasicType getBasicType() const { return type.getBasicType(); } - virtual TQualifier& getQualifier() { return type.getQualifier(); } - virtual const TQualifier& getQualifier() const { return type.getQualifier(); } - virtual void propagatePrecision(TPrecisionQualifier); - virtual int getVectorSize() const { return type.getVectorSize(); } - virtual int getMatrixCols() const { return type.getMatrixCols(); } - virtual int getMatrixRows() const { return type.getMatrixRows(); } - virtual bool isMatrix() const { return type.isMatrix(); } - virtual bool isArray() const { return type.isArray(); } - virtual bool isVector() const { return type.isVector(); } - virtual bool isScalar() const { return type.isScalar(); } - virtual bool isStruct() const { return type.isStruct(); } - virtual bool isFloatingDomain() const { return type.isFloatingDomain(); } - virtual bool isIntegerDomain() const { return type.isIntegerDomain(); } - TString getCompleteString() const { return type.getCompleteString(); } - -protected: - TIntermTyped& operator=(const TIntermTyped&); - TType type; -}; - -// -// Handle for, do-while, and while loops. -// -class TIntermLoop : public TIntermNode { -public: - TIntermLoop(TIntermNode* aBody, TIntermTyped* aTest, TIntermTyped* aTerminal, bool testFirst) : - body(aBody), - test(aTest), - terminal(aTerminal), - first(testFirst), - unroll(false), - dontUnroll(false), - dependency(0) - { } - - virtual TIntermLoop* getAsLoopNode() { return this; } - virtual const TIntermLoop* getAsLoopNode() const { return this; } - virtual void traverse(TIntermTraverser*); - TIntermNode* getBody() const { return body; } - TIntermTyped* getTest() const { return test; } - TIntermTyped* getTerminal() const { return terminal; } - bool testFirst() const { return first; } - - void setUnroll() { unroll = true; } - void setDontUnroll() { dontUnroll = true; } - bool getUnroll() const { return unroll; } - bool getDontUnroll() const { return dontUnroll; } - - static const unsigned int dependencyInfinite = 0xFFFFFFFF; - void setLoopDependency(int d) { dependency = d; } - int getLoopDependency() const { return dependency; } - -protected: - TIntermNode* body; // code to loop over - TIntermTyped* test; // exit condition associated with loop, could be 0 for 'for' loops - TIntermTyped* terminal; // exists for for-loops - bool first; // true for while and for, not for do-while - bool unroll; // true if unroll requested - bool dontUnroll; // true if request to not unroll - unsigned int dependency; // loop dependency hint; 0 means not set or unknown -}; - -// -// Handle case, break, continue, return, and kill. -// -class TIntermBranch : public TIntermNode { -public: - TIntermBranch(TOperator op, TIntermTyped* e) : - flowOp(op), - expression(e) { } - virtual TIntermBranch* getAsBranchNode() { return this; } - virtual const TIntermBranch* getAsBranchNode() const { return this; } - virtual void traverse(TIntermTraverser*); - TOperator getFlowOp() const { return flowOp; } - TIntermTyped* getExpression() const { return expression; } -protected: - TOperator flowOp; - TIntermTyped* expression; -}; - -// -// Represent method names before seeing their calling signature -// or resolving them to operations. Just an expression as the base object -// and a textural name. -// -class TIntermMethod : public TIntermTyped { -public: - TIntermMethod(TIntermTyped* o, const TType& t, const TString& m) : TIntermTyped(t), object(o), method(m) { } - virtual TIntermMethod* getAsMethodNode() { return this; } - virtual const TIntermMethod* getAsMethodNode() const { return this; } - virtual const TString& getMethodName() const { return method; } - virtual TIntermTyped* getObject() const { return object; } - virtual void traverse(TIntermTraverser*); -protected: - TIntermTyped* object; - TString method; -}; - -// -// Nodes that correspond to symbols or constants in the source code. -// -class TIntermSymbol : public TIntermTyped { -public: - // if symbol is initialized as symbol(sym), the memory comes from the pool allocator of sym. If sym comes from - // per process threadPoolAllocator, then it causes increased memory usage per compile - // it is essential to use "symbol = sym" to assign to symbol - TIntermSymbol(int i, const TString& n, const TType& t) - : TIntermTyped(t), id(i), -#ifdef ENABLE_HLSL - flattenSubset(-1), -#endif - constSubtree(nullptr) - { name = n; } - virtual int getId() const { return id; } - virtual const TString& getName() const { return name; } - virtual void traverse(TIntermTraverser*); - virtual TIntermSymbol* getAsSymbolNode() { return this; } - virtual const TIntermSymbol* getAsSymbolNode() const { return this; } - void setConstArray(const TConstUnionArray& c) { constArray = c; } - const TConstUnionArray& getConstArray() const { return constArray; } - void setConstSubtree(TIntermTyped* subtree) { constSubtree = subtree; } - TIntermTyped* getConstSubtree() const { return constSubtree; } -#ifdef ENABLE_HLSL - void setFlattenSubset(int subset) { flattenSubset = subset; } - int getFlattenSubset() const { return flattenSubset; } // -1 means full object -#endif - - // This is meant for cases where a node has already been constructed, and - // later on, it becomes necessary to switch to a different symbol. - virtual void switchId(int newId) { id = newId; } - -protected: - int id; // the unique id of the symbol this node represents -#ifdef ENABLE_HLSL - int flattenSubset; // how deeply the flattened object rooted at id has been dereferenced -#endif - TString name; // the name of the symbol this node represents - TConstUnionArray constArray; // if the symbol is a front-end compile-time constant, this is its value - TIntermTyped* constSubtree; -}; - -class TIntermConstantUnion : public TIntermTyped { -public: - TIntermConstantUnion(const TConstUnionArray& ua, const TType& t) : TIntermTyped(t), constArray(ua), literal(false) { } - const TConstUnionArray& getConstArray() const { return constArray; } - virtual TIntermConstantUnion* getAsConstantUnion() { return this; } - virtual const TIntermConstantUnion* getAsConstantUnion() const { return this; } - virtual void traverse(TIntermTraverser*); - virtual TIntermTyped* fold(TOperator, const TIntermTyped*) const; - virtual TIntermTyped* fold(TOperator, const TType&) const; - void setLiteral() { literal = true; } - void setExpression() { literal = false; } - bool isLiteral() const { return literal; } - -protected: - TIntermConstantUnion& operator=(const TIntermConstantUnion&); - - const TConstUnionArray constArray; - bool literal; // true if node represents a literal in the source code -}; - -// Represent the independent aspects of a texturing TOperator -struct TCrackedTextureOp { - bool query; - bool proj; - bool lod; - bool fetch; - bool offset; - bool offsets; - bool gather; - bool grad; - bool subpass; - bool lodClamp; -#ifdef AMD_EXTENSIONS - bool fragMask; -#endif -}; - -// -// Intermediate class for node types that hold operators. -// -class TIntermOperator : public TIntermTyped { -public: - virtual TIntermOperator* getAsOperator() { return this; } - virtual const TIntermOperator* getAsOperator() const { return this; } - TOperator getOp() const { return op; } - void setOp(TOperator newOp) { op = newOp; } - bool modifiesState() const; - bool isConstructor() const; - bool isTexture() const { return op > EOpTextureGuardBegin && op < EOpTextureGuardEnd; } - bool isSampling() const { return op > EOpSamplingGuardBegin && op < EOpSamplingGuardEnd; } - bool isImage() const { return op > EOpImageGuardBegin && op < EOpImageGuardEnd; } - bool isSparseTexture() const { return op > EOpSparseTextureGuardBegin && op < EOpSparseTextureGuardEnd; } - bool isSparseImage() const { return op == EOpSparseImageLoad; } - - void setOperationPrecision(TPrecisionQualifier p) { operationPrecision = p; } - TPrecisionQualifier getOperationPrecision() const { return operationPrecision != EpqNone ? - operationPrecision : - type.getQualifier().precision; } - TString getCompleteString() const - { - TString cs = type.getCompleteString(); - if (getOperationPrecision() != type.getQualifier().precision) { - cs += ", operation at "; - cs += GetPrecisionQualifierString(getOperationPrecision()); - } - - return cs; - } - - // Crack the op into the individual dimensions of texturing operation. - void crackTexture(TSampler sampler, TCrackedTextureOp& cracked) const - { - cracked.query = false; - cracked.proj = false; - cracked.lod = false; - cracked.fetch = false; - cracked.offset = false; - cracked.offsets = false; - cracked.gather = false; - cracked.grad = false; - cracked.subpass = false; - cracked.lodClamp = false; -#ifdef AMD_EXTENSIONS - cracked.fragMask = false; -#endif - - switch (op) { - case EOpImageQuerySize: - case EOpImageQuerySamples: - case EOpTextureQuerySize: - case EOpTextureQueryLod: - case EOpTextureQueryLevels: - case EOpTextureQuerySamples: - case EOpSparseTexelsResident: - cracked.query = true; - break; - case EOpTexture: - case EOpSparseTexture: - break; - case EOpTextureClamp: - case EOpSparseTextureClamp: - cracked.lodClamp = true; - break; - case EOpTextureProj: - cracked.proj = true; - break; - case EOpTextureLod: - case EOpSparseTextureLod: - cracked.lod = true; - break; - case EOpTextureOffset: - case EOpSparseTextureOffset: - cracked.offset = true; - break; - case EOpTextureOffsetClamp: - case EOpSparseTextureOffsetClamp: - cracked.offset = true; - cracked.lodClamp = true; - break; - case EOpTextureFetch: - case EOpSparseTextureFetch: - cracked.fetch = true; - if (sampler.dim == Esd1D || (sampler.dim == Esd2D && ! sampler.ms) || sampler.dim == Esd3D) - cracked.lod = true; - break; - case EOpTextureFetchOffset: - case EOpSparseTextureFetchOffset: - cracked.fetch = true; - cracked.offset = true; - if (sampler.dim == Esd1D || (sampler.dim == Esd2D && ! sampler.ms) || sampler.dim == Esd3D) - cracked.lod = true; - break; - case EOpTextureProjOffset: - cracked.offset = true; - cracked.proj = true; - break; - case EOpTextureLodOffset: - case EOpSparseTextureLodOffset: - cracked.offset = true; - cracked.lod = true; - break; - case EOpTextureProjLod: - cracked.lod = true; - cracked.proj = true; - break; - case EOpTextureProjLodOffset: - cracked.offset = true; - cracked.lod = true; - cracked.proj = true; - break; - case EOpTextureGrad: - case EOpSparseTextureGrad: - cracked.grad = true; - break; - case EOpTextureGradClamp: - case EOpSparseTextureGradClamp: - cracked.grad = true; - cracked.lodClamp = true; - break; - case EOpTextureGradOffset: - case EOpSparseTextureGradOffset: - cracked.grad = true; - cracked.offset = true; - break; - case EOpTextureProjGrad: - cracked.grad = true; - cracked.proj = true; - break; - case EOpTextureProjGradOffset: - cracked.grad = true; - cracked.offset = true; - cracked.proj = true; - break; - case EOpTextureGradOffsetClamp: - case EOpSparseTextureGradOffsetClamp: - cracked.grad = true; - cracked.offset = true; - cracked.lodClamp = true; - break; - case EOpTextureGather: - case EOpSparseTextureGather: - cracked.gather = true; - break; - case EOpTextureGatherOffset: - case EOpSparseTextureGatherOffset: - cracked.gather = true; - cracked.offset = true; - break; - case EOpTextureGatherOffsets: - case EOpSparseTextureGatherOffsets: - cracked.gather = true; - cracked.offsets = true; - break; -#ifdef AMD_EXTENSIONS - case EOpTextureGatherLod: - case EOpSparseTextureGatherLod: - cracked.gather = true; - cracked.lod = true; - break; - case EOpTextureGatherLodOffset: - case EOpSparseTextureGatherLodOffset: - cracked.gather = true; - cracked.offset = true; - cracked.lod = true; - break; - case EOpTextureGatherLodOffsets: - case EOpSparseTextureGatherLodOffsets: - cracked.gather = true; - cracked.offsets = true; - cracked.lod = true; - break; - case EOpImageLoadLod: - case EOpImageStoreLod: - case EOpSparseImageLoadLod: - cracked.lod = true; - break; - case EOpFragmentMaskFetch: - cracked.subpass = sampler.dim == EsdSubpass; - cracked.fragMask = true; - break; - case EOpFragmentFetch: - cracked.subpass = sampler.dim == EsdSubpass; - cracked.fragMask = true; - break; -#endif - case EOpSubpassLoad: - case EOpSubpassLoadMS: - cracked.subpass = true; - break; - default: - break; - } - } - -protected: - TIntermOperator(TOperator o) : TIntermTyped(EbtFloat), op(o), operationPrecision(EpqNone) {} - TIntermOperator(TOperator o, TType& t) : TIntermTyped(t), op(o), operationPrecision(EpqNone) {} - TOperator op; - // The result precision is in the inherited TType, and is usually meant to be both - // the operation precision and the result precision. However, some more complex things, - // like built-in function calls, distinguish between the two, in which case non-EqpNone - // 'operationPrecision' overrides the result precision as far as operation precision - // is concerned. - TPrecisionQualifier operationPrecision; -}; - -// -// Nodes for all the basic binary math operators. -// -class TIntermBinary : public TIntermOperator { -public: - TIntermBinary(TOperator o) : TIntermOperator(o) {} - virtual void traverse(TIntermTraverser*); - virtual void setLeft(TIntermTyped* n) { left = n; } - virtual void setRight(TIntermTyped* n) { right = n; } - virtual TIntermTyped* getLeft() const { return left; } - virtual TIntermTyped* getRight() const { return right; } - virtual TIntermBinary* getAsBinaryNode() { return this; } - virtual const TIntermBinary* getAsBinaryNode() const { return this; } - virtual void updatePrecision(); -protected: - TIntermTyped* left; - TIntermTyped* right; -}; - -// -// Nodes for unary math operators. -// -class TIntermUnary : public TIntermOperator { -public: - TIntermUnary(TOperator o, TType& t) : TIntermOperator(o, t), operand(0) {} - TIntermUnary(TOperator o) : TIntermOperator(o), operand(0) {} - virtual void traverse(TIntermTraverser*); - virtual void setOperand(TIntermTyped* o) { operand = o; } - virtual TIntermTyped* getOperand() { return operand; } - virtual const TIntermTyped* getOperand() const { return operand; } - virtual TIntermUnary* getAsUnaryNode() { return this; } - virtual const TIntermUnary* getAsUnaryNode() const { return this; } - virtual void updatePrecision(); -protected: - TIntermTyped* operand; -}; - -typedef TVector TIntermSequence; -typedef TVector TQualifierList; -// -// Nodes that operate on an arbitrary sized set of children. -// -class TIntermAggregate : public TIntermOperator { -public: - TIntermAggregate() : TIntermOperator(EOpNull), userDefined(false), pragmaTable(nullptr) { } - TIntermAggregate(TOperator o) : TIntermOperator(o), pragmaTable(nullptr) { } - ~TIntermAggregate() { delete pragmaTable; } - virtual TIntermAggregate* getAsAggregate() { return this; } - virtual const TIntermAggregate* getAsAggregate() const { return this; } - virtual void setOperator(TOperator o) { op = o; } - virtual TIntermSequence& getSequence() { return sequence; } - virtual const TIntermSequence& getSequence() const { return sequence; } - virtual void setName(const TString& n) { name = n; } - virtual const TString& getName() const { return name; } - virtual void traverse(TIntermTraverser*); - virtual void setUserDefined() { userDefined = true; } - virtual bool isUserDefined() { return userDefined; } - virtual TQualifierList& getQualifierList() { return qualifier; } - virtual const TQualifierList& getQualifierList() const { return qualifier; } - void setOptimize(bool o) { optimize = o; } - void setDebug(bool d) { debug = d; } - bool getOptimize() const { return optimize; } - bool getDebug() const { return debug; } - void setPragmaTable(const TPragmaTable& pTable); - const TPragmaTable& getPragmaTable() const { return *pragmaTable; } -protected: - TIntermAggregate(const TIntermAggregate&); // disallow copy constructor - TIntermAggregate& operator=(const TIntermAggregate&); // disallow assignment operator - TIntermSequence sequence; - TQualifierList qualifier; - TString name; - bool userDefined; // used for user defined function names - bool optimize; - bool debug; - TPragmaTable* pragmaTable; -}; - -// -// For if tests. -// -class TIntermSelection : public TIntermTyped { -public: - TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB) : - TIntermTyped(EbtVoid), condition(cond), trueBlock(trueB), falseBlock(falseB), - 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/External/glslang/glslang/Include/revision.h b/External/glslang/glslang/Include/revision.h deleted file mode 100644 index 42992cd7..00000000 --- a/External/glslang/glslang/Include/revision.h +++ /dev/null @@ -1,3 +0,0 @@ -// This header is generated by the make-revision script. - -#define GLSLANG_PATCH_LEVEL 2702 diff --git a/External/glslang/glslang/Include/revision.template b/External/glslang/glslang/Include/revision.template deleted file mode 100644 index 6c13630b..00000000 --- a/External/glslang/glslang/Include/revision.template +++ /dev/null @@ -1,13 +0,0 @@ -// The file revision.h should be updated to the latest version, somehow, on -// check-in, if glslang has changed. -// -// revision.template is the source for revision.h when using SubWCRev as the -// method of updating revision.h. You don't have to do it this way, the -// requirement is only that revision.h gets updated. -// -// revision.h is under source control so that not all consumers of glslang -// source have to figure out how to create revision.h just to get a build -// going. However, if it is not updated, it can be a version behind. - -#define GLSLANG_REVISION "$WCREV$" -#define GLSLANG_DATE "$WCDATE$" diff --git a/External/glslang/glslang/MachineIndependent/Constant.cpp b/External/glslang/glslang/MachineIndependent/Constant.cpp deleted file mode 100644 index 142492dc..00000000 --- a/External/glslang/glslang/MachineIndependent/Constant.cpp +++ /dev/null @@ -1,1118 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// Copyright (C) 2012-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. -// - -#include "localintermediate.h" -#include -#include -#include -#include - -namespace { - -using namespace glslang; - -typedef union { - double d; - int i[2]; -} DoubleIntUnion; - -// Some helper functions - -bool isNan(double x) -{ - DoubleIntUnion u; - // tough to find a platform independent library function, do it directly - u.d = x; - int bitPatternL = u.i[0]; - int bitPatternH = u.i[1]; - return (bitPatternH & 0x7ff80000) == 0x7ff80000 && - ((bitPatternH & 0xFFFFF) != 0 || bitPatternL != 0); -} - -bool isInf(double x) -{ - DoubleIntUnion u; - // tough to find a platform independent library function, do it directly - u.d = x; - int bitPatternL = u.i[0]; - int bitPatternH = u.i[1]; - return (bitPatternH & 0x7ff00000) == 0x7ff00000 && - (bitPatternH & 0xFFFFF) == 0 && bitPatternL == 0; -} - -const double pi = 3.1415926535897932384626433832795; - -} // end anonymous namespace - - -namespace glslang { - -// -// The fold functions see if an operation on a constant can be done in place, -// without generating run-time code. -// -// Returns the node to keep using, which may or may not be the node passed in. -// -// Note: As of version 1.2, all constant operations must be folded. It is -// not opportunistic, but rather a semantic requirement. -// - -// -// Do folding between a pair of nodes. -// 'this' is the left-hand operand and 'rightConstantNode' is the right-hand operand. -// -// Returns a new node representing the result. -// -TIntermTyped* TIntermConstantUnion::fold(TOperator op, const TIntermTyped* rightConstantNode) const -{ - // For most cases, the return type matches the argument type, so set that - // up and just code to exceptions below. - TType returnType; - returnType.shallowCopy(getType()); - - // - // A pair of nodes is to be folded together - // - - const TIntermConstantUnion *rightNode = rightConstantNode->getAsConstantUnion(); - TConstUnionArray leftUnionArray = getConstArray(); - TConstUnionArray rightUnionArray = rightNode->getConstArray(); - - // Figure out the size of the result - int newComps; - int constComps; - switch(op) { - case EOpMatrixTimesMatrix: - newComps = rightNode->getMatrixCols() * getMatrixRows(); - break; - case EOpMatrixTimesVector: - newComps = getMatrixRows(); - break; - case EOpVectorTimesMatrix: - newComps = rightNode->getMatrixCols(); - break; - default: - newComps = getType().computeNumComponents(); - constComps = rightConstantNode->getType().computeNumComponents(); - if (constComps == 1 && newComps > 1) { - // for a case like vec4 f = vec4(2,3,4,5) + 1.2; - TConstUnionArray smearedArray(newComps, rightNode->getConstArray()[0]); - rightUnionArray = smearedArray; - } else if (constComps > 1 && newComps == 1) { - // for a case like vec4 f = 1.2 + vec4(2,3,4,5); - newComps = constComps; - rightUnionArray = rightNode->getConstArray(); - TConstUnionArray smearedArray(newComps, getConstArray()[0]); - leftUnionArray = smearedArray; - returnType.shallowCopy(rightNode->getType()); - } - break; - } - - TConstUnionArray newConstArray(newComps); - TType constBool(EbtBool, EvqConst); - - switch(op) { - case EOpAdd: - for (int i = 0; i < newComps; i++) - newConstArray[i] = leftUnionArray[i] + rightUnionArray[i]; - break; - case EOpSub: - for (int i = 0; i < newComps; i++) - newConstArray[i] = leftUnionArray[i] - rightUnionArray[i]; - break; - - case EOpMul: - case EOpVectorTimesScalar: - case EOpMatrixTimesScalar: - for (int i = 0; i < newComps; i++) - newConstArray[i] = leftUnionArray[i] * rightUnionArray[i]; - break; - case EOpMatrixTimesMatrix: - for (int row = 0; row < getMatrixRows(); row++) { - for (int column = 0; column < rightNode->getMatrixCols(); column++) { - double sum = 0.0f; - for (int i = 0; i < rightNode->getMatrixRows(); i++) - sum += leftUnionArray[i * getMatrixRows() + row].getDConst() * rightUnionArray[column * rightNode->getMatrixRows() + i].getDConst(); - newConstArray[column * getMatrixRows() + row].setDConst(sum); - } - } - returnType.shallowCopy(TType(getType().getBasicType(), EvqConst, 0, rightNode->getMatrixCols(), getMatrixRows())); - break; - case EOpDiv: - for (int i = 0; i < newComps; i++) { - switch (getType().getBasicType()) { - case EbtDouble: - case EbtFloat: - case EbtFloat16: - newConstArray[i].setDConst(leftUnionArray[i].getDConst() / rightUnionArray[i].getDConst()); - break; - case EbtInt8: - if (rightUnionArray[i] == 0) - newConstArray[i].setI8Const(0x7F); - else if (rightUnionArray[i].getI8Const() == -1 && leftUnionArray[i].getI8Const() == (signed char)0x80) - newConstArray[i].setI8Const((signed char)0x80); - else - newConstArray[i].setI8Const(leftUnionArray[i].getI8Const() / rightUnionArray[i].getI8Const()); - break; - - case EbtUint8: - if (rightUnionArray[i] == 0) { - newConstArray[i].setU8Const(0xFF); - } else - newConstArray[i].setU8Const(leftUnionArray[i].getU8Const() / rightUnionArray[i].getU8Const()); - break; - - case EbtInt16: - if (rightUnionArray[i] == 0) - newConstArray[i].setI16Const(0x7FFF); - else if (rightUnionArray[i].getI16Const() == -1 && leftUnionArray[i].getI16Const() == (signed short)0x8000) - newConstArray[i].setI16Const(short(0x8000)); - else - newConstArray[i].setI16Const(leftUnionArray[i].getI16Const() / rightUnionArray[i].getI16Const()); - break; - - case EbtUint16: - if (rightUnionArray[i] == 0) { - newConstArray[i].setU16Const(0xFFFF); - } else - newConstArray[i].setU16Const(leftUnionArray[i].getU16Const() / rightUnionArray[i].getU16Const()); - break; - - case EbtInt: - if (rightUnionArray[i] == 0) - newConstArray[i].setIConst(0x7FFFFFFF); - else if (rightUnionArray[i].getIConst() == -1 && leftUnionArray[i].getIConst() == (int)0x80000000) - newConstArray[i].setIConst(0x80000000); - else - newConstArray[i].setIConst(leftUnionArray[i].getIConst() / rightUnionArray[i].getIConst()); - break; - - case EbtUint: - if (rightUnionArray[i] == 0) { - newConstArray[i].setUConst(0xFFFFFFFFu); - } else - newConstArray[i].setUConst(leftUnionArray[i].getUConst() / rightUnionArray[i].getUConst()); - break; - - case EbtInt64: - if (rightUnionArray[i] == 0) - newConstArray[i].setI64Const(0x7FFFFFFFFFFFFFFFll); - else if (rightUnionArray[i].getI64Const() == -1 && leftUnionArray[i].getI64Const() == (long long)0x8000000000000000) - newConstArray[i].setI64Const(0x8000000000000000); - else - newConstArray[i].setI64Const(leftUnionArray[i].getI64Const() / rightUnionArray[i].getI64Const()); - break; - - case EbtUint64: - if (rightUnionArray[i] == 0) { - newConstArray[i].setU64Const(0xFFFFFFFFFFFFFFFFull); - } else - newConstArray[i].setU64Const(leftUnionArray[i].getU64Const() / rightUnionArray[i].getU64Const()); - break; - default: - return 0; - } - } - break; - - case EOpMatrixTimesVector: - for (int i = 0; i < getMatrixRows(); i++) { - double sum = 0.0f; - for (int j = 0; j < rightNode->getVectorSize(); j++) { - sum += leftUnionArray[j*getMatrixRows() + i].getDConst() * rightUnionArray[j].getDConst(); - } - newConstArray[i].setDConst(sum); - } - - returnType.shallowCopy(TType(getBasicType(), EvqConst, getMatrixRows())); - break; - - case EOpVectorTimesMatrix: - for (int i = 0; i < rightNode->getMatrixCols(); i++) { - double sum = 0.0f; - for (int j = 0; j < getVectorSize(); j++) - sum += leftUnionArray[j].getDConst() * rightUnionArray[i*rightNode->getMatrixRows() + j].getDConst(); - newConstArray[i].setDConst(sum); - } - - returnType.shallowCopy(TType(getBasicType(), EvqConst, rightNode->getMatrixCols())); - break; - - case EOpMod: - for (int i = 0; i < newComps; i++) { - if (rightUnionArray[i] == 0) - newConstArray[i] = leftUnionArray[i]; - else { - switch (getType().getBasicType()) { - case EbtInt: - if (rightUnionArray[i].getIConst() == -1 && leftUnionArray[i].getIConst() == INT_MIN) { - newConstArray[i].setIConst(0); - break; - } else goto modulo_default; - - case EbtInt64: - if (rightUnionArray[i].getI64Const() == -1 && leftUnionArray[i].getI64Const() == LLONG_MIN) { - newConstArray[i].setI64Const(0); - break; - } else goto modulo_default; -#ifdef AMD_EXTENSIONS - case EbtInt16: - if (rightUnionArray[i].getIConst() == -1 && leftUnionArray[i].getIConst() == SHRT_MIN) { - newConstArray[i].setIConst(0); - break; - } else goto modulo_default; -#endif - default: - modulo_default: - newConstArray[i] = leftUnionArray[i] % rightUnionArray[i]; - } - } - } - break; - - case EOpRightShift: - for (int i = 0; i < newComps; i++) - newConstArray[i] = leftUnionArray[i] >> rightUnionArray[i]; - break; - - case EOpLeftShift: - for (int i = 0; i < newComps; i++) - newConstArray[i] = leftUnionArray[i] << rightUnionArray[i]; - break; - - case EOpAnd: - for (int i = 0; i < newComps; i++) - newConstArray[i] = leftUnionArray[i] & rightUnionArray[i]; - break; - case EOpInclusiveOr: - for (int i = 0; i < newComps; i++) - newConstArray[i] = leftUnionArray[i] | rightUnionArray[i]; - break; - case EOpExclusiveOr: - for (int i = 0; i < newComps; i++) - newConstArray[i] = leftUnionArray[i] ^ rightUnionArray[i]; - break; - - case EOpLogicalAnd: // this code is written for possible future use, will not get executed currently - for (int i = 0; i < newComps; i++) - newConstArray[i] = leftUnionArray[i] && rightUnionArray[i]; - break; - - case EOpLogicalOr: // this code is written for possible future use, will not get executed currently - for (int i = 0; i < newComps; i++) - newConstArray[i] = leftUnionArray[i] || rightUnionArray[i]; - break; - - case EOpLogicalXor: - for (int i = 0; i < newComps; i++) { - switch (getType().getBasicType()) { - case EbtBool: newConstArray[i].setBConst((leftUnionArray[i] == rightUnionArray[i]) ? false : true); break; - default: assert(false && "Default missing"); - } - } - break; - - case EOpLessThan: - newConstArray[0].setBConst(leftUnionArray[0] < rightUnionArray[0]); - returnType.shallowCopy(constBool); - break; - case EOpGreaterThan: - newConstArray[0].setBConst(leftUnionArray[0] > rightUnionArray[0]); - returnType.shallowCopy(constBool); - break; - case EOpLessThanEqual: - newConstArray[0].setBConst(! (leftUnionArray[0] > rightUnionArray[0])); - returnType.shallowCopy(constBool); - break; - case EOpGreaterThanEqual: - newConstArray[0].setBConst(! (leftUnionArray[0] < rightUnionArray[0])); - returnType.shallowCopy(constBool); - break; - case EOpEqual: - newConstArray[0].setBConst(rightNode->getConstArray() == leftUnionArray); - returnType.shallowCopy(constBool); - break; - case EOpNotEqual: - newConstArray[0].setBConst(rightNode->getConstArray() != leftUnionArray); - returnType.shallowCopy(constBool); - break; - - default: - return 0; - } - - TIntermConstantUnion *newNode = new TIntermConstantUnion(newConstArray, returnType); - newNode->setLoc(getLoc()); - - return newNode; -} - -// -// Do single unary node folding -// -// Returns a new node representing the result. -// -TIntermTyped* TIntermConstantUnion::fold(TOperator op, const TType& returnType) const -{ - // First, size the result, which is mostly the same as the argument's size, - // but not always, and classify what is componentwise. - // Also, eliminate cases that can't be compile-time constant. - int resultSize; - bool componentWise = true; - - int objectSize = getType().computeNumComponents(); - switch (op) { - case EOpDeterminant: - case EOpAny: - case EOpAll: - case EOpLength: - componentWise = false; - resultSize = 1; - break; - - case EOpEmitStreamVertex: - case EOpEndStreamPrimitive: - // These don't actually fold - return 0; - - case EOpPackSnorm2x16: - case EOpPackUnorm2x16: - case EOpPackHalf2x16: - componentWise = false; - resultSize = 1; - break; - - case EOpUnpackSnorm2x16: - case EOpUnpackUnorm2x16: - case EOpUnpackHalf2x16: - componentWise = false; - resultSize = 2; - break; - - case EOpPack16: - case EOpPack32: - case EOpPack64: - case EOpUnpack32: - case EOpUnpack16: - case EOpUnpack8: - case EOpNormalize: - componentWise = false; - resultSize = objectSize; - break; - - default: - resultSize = objectSize; - break; - } - - // Set up for processing - TConstUnionArray newConstArray(resultSize); - const TConstUnionArray& unionArray = getConstArray(); - - // Process non-component-wise operations - switch (op) { - case EOpLength: - case EOpNormalize: - { - double sum = 0; - for (int i = 0; i < objectSize; i++) - sum += unionArray[i].getDConst() * unionArray[i].getDConst(); - double length = sqrt(sum); - if (op == EOpLength) - newConstArray[0].setDConst(length); - else { - for (int i = 0; i < objectSize; i++) - newConstArray[i].setDConst(unionArray[i].getDConst() / length); - } - break; - } - - case EOpAny: - { - bool result = false; - for (int i = 0; i < objectSize; i++) { - if (unionArray[i].getBConst()) - result = true; - } - newConstArray[0].setBConst(result); - break; - } - case EOpAll: - { - bool result = true; - for (int i = 0; i < objectSize; i++) { - if (! unionArray[i].getBConst()) - result = false; - } - newConstArray[0].setBConst(result); - break; - } - - // TODO: 3.0 Functionality: unary constant folding: the rest of the ops have to be fleshed out - - case EOpPackSnorm2x16: - case EOpPackUnorm2x16: - case EOpPackHalf2x16: - case EOpPack16: - case EOpPack32: - case EOpPack64: - case EOpUnpack32: - case EOpUnpack16: - case EOpUnpack8: - - case EOpUnpackSnorm2x16: - case EOpUnpackUnorm2x16: - case EOpUnpackHalf2x16: - - case EOpDeterminant: - case EOpMatrixInverse: - case EOpTranspose: - return 0; - - default: - assert(componentWise); - break; - } - - // Turn off the componentwise loop - if (! componentWise) - objectSize = 0; - - // Process component-wise operations - for (int i = 0; i < objectSize; i++) { - switch (op) { - case EOpNegative: - switch (getType().getBasicType()) { - case EbtDouble: - case EbtFloat16: - case EbtFloat: newConstArray[i].setDConst(-unionArray[i].getDConst()); break; - case EbtInt8: newConstArray[i].setI8Const(-unionArray[i].getI8Const()); break; - case EbtUint8: newConstArray[i].setU8Const(static_cast(-static_cast(unionArray[i].getU8Const()))); break; - case EbtInt16: newConstArray[i].setI16Const(-unionArray[i].getI16Const()); break; - case EbtUint16:newConstArray[i].setU16Const(static_cast(-static_cast(unionArray[i].getU16Const()))); break; - case EbtInt: newConstArray[i].setIConst(-unionArray[i].getIConst()); break; - case EbtUint: newConstArray[i].setUConst(static_cast(-static_cast(unionArray[i].getUConst()))); break; - case EbtInt64: newConstArray[i].setI64Const(-unionArray[i].getI64Const()); break; - case EbtUint64: newConstArray[i].setU64Const(static_cast(-static_cast(unionArray[i].getU64Const()))); break; - default: - return 0; - } - break; - case EOpLogicalNot: - case EOpVectorLogicalNot: - switch (getType().getBasicType()) { - case EbtBool: newConstArray[i].setBConst(!unionArray[i].getBConst()); break; - default: - return 0; - } - break; - case EOpBitwiseNot: - newConstArray[i] = ~unionArray[i]; - break; - case EOpRadians: - newConstArray[i].setDConst(unionArray[i].getDConst() * pi / 180.0); - break; - case EOpDegrees: - newConstArray[i].setDConst(unionArray[i].getDConst() * 180.0 / pi); - break; - case EOpSin: - newConstArray[i].setDConst(sin(unionArray[i].getDConst())); - break; - case EOpCos: - newConstArray[i].setDConst(cos(unionArray[i].getDConst())); - break; - case EOpTan: - newConstArray[i].setDConst(tan(unionArray[i].getDConst())); - break; - case EOpAsin: - newConstArray[i].setDConst(asin(unionArray[i].getDConst())); - break; - case EOpAcos: - newConstArray[i].setDConst(acos(unionArray[i].getDConst())); - break; - case EOpAtan: - newConstArray[i].setDConst(atan(unionArray[i].getDConst())); - break; - - case EOpDPdx: - case EOpDPdy: - case EOpFwidth: - case EOpDPdxFine: - case EOpDPdyFine: - case EOpFwidthFine: - case EOpDPdxCoarse: - case EOpDPdyCoarse: - case EOpFwidthCoarse: - // The derivatives are all mandated to create a constant 0. - newConstArray[i].setDConst(0.0); - break; - - case EOpExp: - newConstArray[i].setDConst(exp(unionArray[i].getDConst())); - break; - case EOpLog: - newConstArray[i].setDConst(log(unionArray[i].getDConst())); - break; - case EOpExp2: - { - const double inv_log2_e = 0.69314718055994530941723212145818; - newConstArray[i].setDConst(exp(unionArray[i].getDConst() * inv_log2_e)); - break; - } - case EOpLog2: - { - const double log2_e = 1.4426950408889634073599246810019; - newConstArray[i].setDConst(log2_e * log(unionArray[i].getDConst())); - break; - } - case EOpSqrt: - newConstArray[i].setDConst(sqrt(unionArray[i].getDConst())); - break; - case EOpInverseSqrt: - newConstArray[i].setDConst(1.0 / sqrt(unionArray[i].getDConst())); - break; - - case EOpAbs: - if (unionArray[i].getType() == EbtDouble) - newConstArray[i].setDConst(fabs(unionArray[i].getDConst())); - else if (unionArray[i].getType() == EbtInt) - newConstArray[i].setIConst(abs(unionArray[i].getIConst())); - else - newConstArray[i] = unionArray[i]; - break; - case EOpSign: - #define SIGN(X) (X == 0 ? 0 : (X < 0 ? -1 : 1)) - if (unionArray[i].getType() == EbtDouble) - newConstArray[i].setDConst(SIGN(unionArray[i].getDConst())); - else - newConstArray[i].setIConst(SIGN(unionArray[i].getIConst())); - break; - case EOpFloor: - newConstArray[i].setDConst(floor(unionArray[i].getDConst())); - break; - case EOpTrunc: - if (unionArray[i].getDConst() > 0) - newConstArray[i].setDConst(floor(unionArray[i].getDConst())); - else - newConstArray[i].setDConst(ceil(unionArray[i].getDConst())); - break; - case EOpRound: - newConstArray[i].setDConst(floor(0.5 + unionArray[i].getDConst())); - break; - case EOpRoundEven: - { - double flr = floor(unionArray[i].getDConst()); - bool even = flr / 2.0 == floor(flr / 2.0); - double rounded = even ? ceil(unionArray[i].getDConst() - 0.5) : floor(unionArray[i].getDConst() + 0.5); - newConstArray[i].setDConst(rounded); - break; - } - case EOpCeil: - newConstArray[i].setDConst(ceil(unionArray[i].getDConst())); - break; - case EOpFract: - { - double x = unionArray[i].getDConst(); - newConstArray[i].setDConst(x - floor(x)); - break; - } - - case EOpIsNan: - { - newConstArray[i].setBConst(isNan(unionArray[i].getDConst())); - break; - } - case EOpIsInf: - { - newConstArray[i].setBConst(isInf(unionArray[i].getDConst())); - break; - } - - // TODO: 3.0 Functionality: unary constant folding: the rest of the ops have to be fleshed out - - case EOpSinh: - case EOpCosh: - case EOpTanh: - case EOpAsinh: - case EOpAcosh: - case EOpAtanh: - - case EOpFloatBitsToInt: - case EOpFloatBitsToUint: - case EOpIntBitsToFloat: - case EOpUintBitsToFloat: - case EOpDoubleBitsToInt64: - case EOpDoubleBitsToUint64: - case EOpInt64BitsToDouble: - case EOpUint64BitsToDouble: - case EOpFloat16BitsToInt16: - case EOpFloat16BitsToUint16: - case EOpInt16BitsToFloat16: - case EOpUint16BitsToFloat16: - default: - return 0; - } - } - - TIntermConstantUnion *newNode = new TIntermConstantUnion(newConstArray, returnType); - newNode->getWritableType().getQualifier().storage = EvqConst; - newNode->setLoc(getLoc()); - - return newNode; -} - -// -// Do constant folding for an aggregate node that has all its children -// as constants and an operator that requires constant folding. -// -TIntermTyped* TIntermediate::fold(TIntermAggregate* aggrNode) -{ - if (aggrNode == nullptr) - return aggrNode; - - if (! areAllChildConst(aggrNode)) - return aggrNode; - - if (aggrNode->isConstructor()) - return foldConstructor(aggrNode); - - TIntermSequence& children = aggrNode->getSequence(); - - // First, see if this is an operation to constant fold, kick out if not, - // see what size the result is if so. - - bool componentwise = false; // will also say componentwise if a scalar argument gets repeated to make per-component results - int objectSize; - switch (aggrNode->getOp()) { - case EOpAtan: - case EOpPow: - case EOpMin: - case EOpMax: - case EOpMix: - case EOpClamp: - case EOpLessThan: - case EOpGreaterThan: - case EOpLessThanEqual: - case EOpGreaterThanEqual: - case EOpVectorEqual: - case EOpVectorNotEqual: - componentwise = true; - objectSize = children[0]->getAsConstantUnion()->getType().computeNumComponents(); - break; - case EOpCross: - case EOpReflect: - case EOpRefract: - case EOpFaceForward: - objectSize = children[0]->getAsConstantUnion()->getType().computeNumComponents(); - break; - case EOpDistance: - case EOpDot: - objectSize = 1; - break; - case EOpOuterProduct: - objectSize = children[0]->getAsTyped()->getType().getVectorSize() * - children[1]->getAsTyped()->getType().getVectorSize(); - break; - case EOpStep: - componentwise = true; - objectSize = std::max(children[0]->getAsTyped()->getType().getVectorSize(), - children[1]->getAsTyped()->getType().getVectorSize()); - break; - case EOpSmoothStep: - componentwise = true; - objectSize = std::max(children[0]->getAsTyped()->getType().getVectorSize(), - children[2]->getAsTyped()->getType().getVectorSize()); - break; - default: - return aggrNode; - } - TConstUnionArray newConstArray(objectSize); - - TVector childConstUnions; - for (unsigned int arg = 0; arg < children.size(); ++arg) - childConstUnions.push_back(children[arg]->getAsConstantUnion()->getConstArray()); - - if (componentwise) { - for (int comp = 0; comp < objectSize; comp++) { - - // some arguments are scalars instead of matching vectors; simulate a smear - int arg0comp = std::min(comp, children[0]->getAsTyped()->getType().getVectorSize() - 1); - int arg1comp = 0; - if (children.size() > 1) - arg1comp = std::min(comp, children[1]->getAsTyped()->getType().getVectorSize() - 1); - int arg2comp = 0; - if (children.size() > 2) - arg2comp = std::min(comp, children[2]->getAsTyped()->getType().getVectorSize() - 1); - - switch (aggrNode->getOp()) { - case EOpAtan: - newConstArray[comp].setDConst(atan2(childConstUnions[0][arg0comp].getDConst(), childConstUnions[1][arg1comp].getDConst())); - break; - case EOpPow: - newConstArray[comp].setDConst(pow(childConstUnions[0][arg0comp].getDConst(), childConstUnions[1][arg1comp].getDConst())); - break; - case EOpMin: - switch(children[0]->getAsTyped()->getBasicType()) { - case EbtFloat16: - case EbtFloat: - case EbtDouble: - newConstArray[comp].setDConst(std::min(childConstUnions[0][arg0comp].getDConst(), childConstUnions[1][arg1comp].getDConst())); - break; - case EbtInt8: - newConstArray[comp].setI8Const(std::min(childConstUnions[0][arg0comp].getI8Const(), childConstUnions[1][arg1comp].getI8Const())); - break; - case EbtUint8: - newConstArray[comp].setU8Const(std::min(childConstUnions[0][arg0comp].getU8Const(), childConstUnions[1][arg1comp].getU8Const())); - break; - case EbtInt16: - newConstArray[comp].setI16Const(std::min(childConstUnions[0][arg0comp].getI16Const(), childConstUnions[1][arg1comp].getI16Const())); - break; - case EbtUint16: - newConstArray[comp].setU16Const(std::min(childConstUnions[0][arg0comp].getU16Const(), childConstUnions[1][arg1comp].getU16Const())); - break; - case EbtInt: - newConstArray[comp].setIConst(std::min(childConstUnions[0][arg0comp].getIConst(), childConstUnions[1][arg1comp].getIConst())); - break; - case EbtUint: - newConstArray[comp].setUConst(std::min(childConstUnions[0][arg0comp].getUConst(), childConstUnions[1][arg1comp].getUConst())); - break; - case EbtInt64: - newConstArray[comp].setI64Const(std::min(childConstUnions[0][arg0comp].getI64Const(), childConstUnions[1][arg1comp].getI64Const())); - break; - case EbtUint64: - newConstArray[comp].setU64Const(std::min(childConstUnions[0][arg0comp].getU64Const(), childConstUnions[1][arg1comp].getU64Const())); - break; - default: assert(false && "Default missing"); - } - break; - case EOpMax: - switch(children[0]->getAsTyped()->getBasicType()) { - case EbtFloat16: - case EbtFloat: - case EbtDouble: - newConstArray[comp].setDConst(std::max(childConstUnions[0][arg0comp].getDConst(), childConstUnions[1][arg1comp].getDConst())); - break; - case EbtInt8: - newConstArray[comp].setI8Const(std::max(childConstUnions[0][arg0comp].getI8Const(), childConstUnions[1][arg1comp].getI8Const())); - break; - case EbtUint8: - newConstArray[comp].setU8Const(std::max(childConstUnions[0][arg0comp].getU8Const(), childConstUnions[1][arg1comp].getU8Const())); - break; - case EbtInt16: - newConstArray[comp].setI16Const(std::max(childConstUnions[0][arg0comp].getI16Const(), childConstUnions[1][arg1comp].getI16Const())); - break; - case EbtUint16: - newConstArray[comp].setU16Const(std::max(childConstUnions[0][arg0comp].getU16Const(), childConstUnions[1][arg1comp].getU16Const())); - break; - case EbtInt: - newConstArray[comp].setIConst(std::max(childConstUnions[0][arg0comp].getIConst(), childConstUnions[1][arg1comp].getIConst())); - break; - case EbtUint: - newConstArray[comp].setUConst(std::max(childConstUnions[0][arg0comp].getUConst(), childConstUnions[1][arg1comp].getUConst())); - break; - case EbtInt64: - newConstArray[comp].setI64Const(std::max(childConstUnions[0][arg0comp].getI64Const(), childConstUnions[1][arg1comp].getI64Const())); - break; - case EbtUint64: - newConstArray[comp].setU64Const(std::max(childConstUnions[0][arg0comp].getU64Const(), childConstUnions[1][arg1comp].getU64Const())); - break; - default: assert(false && "Default missing"); - } - break; - case EOpClamp: - switch(children[0]->getAsTyped()->getBasicType()) { - case EbtFloat16: - case EbtFloat: - case EbtDouble: - newConstArray[comp].setDConst(std::min(std::max(childConstUnions[0][arg0comp].getDConst(), childConstUnions[1][arg1comp].getDConst()), - childConstUnions[2][arg2comp].getDConst())); - break; - case EbtInt8: - newConstArray[comp].setI8Const(std::min(std::max(childConstUnions[0][arg0comp].getI8Const(), childConstUnions[1][arg1comp].getI8Const()), - childConstUnions[2][arg2comp].getI8Const())); - break; - case EbtUint8: - newConstArray[comp].setU8Const(std::min(std::max(childConstUnions[0][arg0comp].getU8Const(), childConstUnions[1][arg1comp].getU8Const()), - childConstUnions[2][arg2comp].getU8Const())); - break; - case EbtInt16: - newConstArray[comp].setI16Const(std::min(std::max(childConstUnions[0][arg0comp].getI16Const(), childConstUnions[1][arg1comp].getI16Const()), - childConstUnions[2][arg2comp].getI16Const())); - break; - case EbtUint16: - newConstArray[comp].setU16Const(std::min(std::max(childConstUnions[0][arg0comp].getU16Const(), childConstUnions[1][arg1comp].getU16Const()), - childConstUnions[2][arg2comp].getU16Const())); - break; - case EbtInt: - newConstArray[comp].setIConst(std::min(std::max(childConstUnions[0][arg0comp].getIConst(), childConstUnions[1][arg1comp].getIConst()), - childConstUnions[2][arg2comp].getIConst())); - break; - case EbtUint: - newConstArray[comp].setUConst(std::min(std::max(childConstUnions[0][arg0comp].getUConst(), childConstUnions[1][arg1comp].getUConst()), - childConstUnions[2][arg2comp].getUConst())); - break; - case EbtInt64: - newConstArray[comp].setI64Const(std::min(std::max(childConstUnions[0][arg0comp].getI64Const(), childConstUnions[1][arg1comp].getI64Const()), - childConstUnions[2][arg2comp].getI64Const())); - break; - case EbtUint64: - newConstArray[comp].setU64Const(std::min(std::max(childConstUnions[0][arg0comp].getU64Const(), childConstUnions[1][arg1comp].getU64Const()), - childConstUnions[2][arg2comp].getU64Const())); - break; - default: assert(false && "Default missing"); - } - break; - case EOpLessThan: - newConstArray[comp].setBConst(childConstUnions[0][arg0comp] < childConstUnions[1][arg1comp]); - break; - case EOpGreaterThan: - newConstArray[comp].setBConst(childConstUnions[0][arg0comp] > childConstUnions[1][arg1comp]); - break; - case EOpLessThanEqual: - newConstArray[comp].setBConst(! (childConstUnions[0][arg0comp] > childConstUnions[1][arg1comp])); - break; - case EOpGreaterThanEqual: - newConstArray[comp].setBConst(! (childConstUnions[0][arg0comp] < childConstUnions[1][arg1comp])); - break; - case EOpVectorEqual: - newConstArray[comp].setBConst(childConstUnions[0][arg0comp] == childConstUnions[1][arg1comp]); - break; - case EOpVectorNotEqual: - newConstArray[comp].setBConst(childConstUnions[0][arg0comp] != childConstUnions[1][arg1comp]); - break; - case EOpMix: - if (children[2]->getAsTyped()->getBasicType() == EbtBool) - newConstArray[comp].setDConst(childConstUnions[2][arg2comp].getBConst() ? childConstUnions[1][arg1comp].getDConst() : - childConstUnions[0][arg0comp].getDConst()); - else - newConstArray[comp].setDConst(childConstUnions[0][arg0comp].getDConst() * (1.0 - childConstUnions[2][arg2comp].getDConst()) + - childConstUnions[1][arg1comp].getDConst() * childConstUnions[2][arg2comp].getDConst()); - break; - case EOpStep: - newConstArray[comp].setDConst(childConstUnions[1][arg1comp].getDConst() < childConstUnions[0][arg0comp].getDConst() ? 0.0 : 1.0); - break; - case EOpSmoothStep: - { - double t = (childConstUnions[2][arg2comp].getDConst() - childConstUnions[0][arg0comp].getDConst()) / - (childConstUnions[1][arg1comp].getDConst() - childConstUnions[0][arg0comp].getDConst()); - if (t < 0.0) - t = 0.0; - if (t > 1.0) - t = 1.0; - newConstArray[comp].setDConst(t * t * (3.0 - 2.0 * t)); - break; - } - default: - return aggrNode; - } - } - } else { - // Non-componentwise... - - int numComps = children[0]->getAsConstantUnion()->getType().computeNumComponents(); - double dot; - - switch (aggrNode->getOp()) { - case EOpDistance: - { - double sum = 0.0; - for (int comp = 0; comp < numComps; ++comp) { - double diff = childConstUnions[1][comp].getDConst() - childConstUnions[0][comp].getDConst(); - sum += diff * diff; - } - newConstArray[0].setDConst(sqrt(sum)); - break; - } - case EOpDot: - newConstArray[0].setDConst(childConstUnions[0].dot(childConstUnions[1])); - break; - case EOpCross: - newConstArray[0] = childConstUnions[0][1] * childConstUnions[1][2] - childConstUnions[0][2] * childConstUnions[1][1]; - newConstArray[1] = childConstUnions[0][2] * childConstUnions[1][0] - childConstUnions[0][0] * childConstUnions[1][2]; - newConstArray[2] = childConstUnions[0][0] * childConstUnions[1][1] - childConstUnions[0][1] * childConstUnions[1][0]; - break; - case EOpFaceForward: - // If dot(Nref, I) < 0 return N, otherwise return -N: Arguments are (N, I, Nref). - dot = childConstUnions[1].dot(childConstUnions[2]); - for (int comp = 0; comp < numComps; ++comp) { - if (dot < 0.0) - newConstArray[comp] = childConstUnions[0][comp]; - else - newConstArray[comp].setDConst(-childConstUnions[0][comp].getDConst()); - } - break; - case EOpReflect: - // I - 2 * dot(N, I) * N: Arguments are (I, N). - dot = childConstUnions[0].dot(childConstUnions[1]); - dot *= 2.0; - for (int comp = 0; comp < numComps; ++comp) - newConstArray[comp].setDConst(childConstUnions[0][comp].getDConst() - dot * childConstUnions[1][comp].getDConst()); - break; - case EOpRefract: - { - // Arguments are (I, N, eta). - // k = 1.0 - eta * eta * (1.0 - dot(N, I) * dot(N, I)) - // if (k < 0.0) - // return dvec(0.0) - // else - // return eta * I - (eta * dot(N, I) + sqrt(k)) * N - dot = childConstUnions[0].dot(childConstUnions[1]); - double eta = childConstUnions[2][0].getDConst(); - double k = 1.0 - eta * eta * (1.0 - dot * dot); - if (k < 0.0) { - for (int comp = 0; comp < numComps; ++comp) - newConstArray[comp].setDConst(0.0); - } else { - for (int comp = 0; comp < numComps; ++comp) - newConstArray[comp].setDConst(eta * childConstUnions[0][comp].getDConst() - (eta * dot + sqrt(k)) * childConstUnions[1][comp].getDConst()); - } - break; - } - case EOpOuterProduct: - { - int numRows = numComps; - int numCols = children[1]->getAsConstantUnion()->getType().computeNumComponents(); - for (int row = 0; row < numRows; ++row) - for (int col = 0; col < numCols; ++col) - newConstArray[col * numRows + row] = childConstUnions[0][row] * childConstUnions[1][col]; - break; - } - default: - return aggrNode; - } - } - - TIntermConstantUnion *newNode = new TIntermConstantUnion(newConstArray, aggrNode->getType()); - newNode->getWritableType().getQualifier().storage = EvqConst; - newNode->setLoc(aggrNode->getLoc()); - - return newNode; -} - -bool TIntermediate::areAllChildConst(TIntermAggregate* aggrNode) -{ - bool allConstant = true; - - // check if all the child nodes are constants so that they can be inserted into - // the parent node - if (aggrNode) { - TIntermSequence& childSequenceVector = aggrNode->getSequence(); - for (TIntermSequence::iterator p = childSequenceVector.begin(); - p != childSequenceVector.end(); p++) { - if (!(*p)->getAsTyped()->getAsConstantUnion()) - return false; - } - } - - return allConstant; -} - -TIntermTyped* TIntermediate::foldConstructor(TIntermAggregate* aggrNode) -{ - bool error = false; - - TConstUnionArray unionArray(aggrNode->getType().computeNumComponents()); - if (aggrNode->getSequence().size() == 1) - error = parseConstTree(aggrNode, unionArray, aggrNode->getOp(), aggrNode->getType(), true); - else - error = parseConstTree(aggrNode, unionArray, aggrNode->getOp(), aggrNode->getType()); - - if (error) - return aggrNode; - - return addConstantUnion(unionArray, aggrNode->getType(), aggrNode->getLoc()); -} - -// -// Constant folding of a bracket (array-style) dereference or struct-like dot -// dereference. Can handle anything except a multi-character swizzle, though -// all swizzles may go to foldSwizzle(). -// -TIntermTyped* TIntermediate::foldDereference(TIntermTyped* node, int index, const TSourceLoc& loc) -{ - TType dereferencedType(node->getType(), index); - dereferencedType.getQualifier().storage = EvqConst; - TIntermTyped* result = 0; - int size = dereferencedType.computeNumComponents(); - - // arrays, vectors, matrices, all use simple multiplicative math - // while structures need to add up heterogeneous members - int start; - if (node->isArray() || ! node->isStruct()) - start = size * index; - else { - // it is a structure - assert(node->isStruct()); - start = 0; - for (int i = 0; i < index; ++i) - start += (*node->getType().getStruct())[i].type->computeNumComponents(); - } - - result = addConstantUnion(TConstUnionArray(node->getAsConstantUnion()->getConstArray(), start, size), node->getType(), loc); - - if (result == 0) - result = node; - else - result->setType(dereferencedType); - - return result; -} - -// -// Make a constant vector node or constant scalar node, representing a given -// constant vector and constant swizzle into it. -// -TIntermTyped* TIntermediate::foldSwizzle(TIntermTyped* node, TSwizzleSelectors& selectors, const TSourceLoc& loc) -{ - const TConstUnionArray& unionArray = node->getAsConstantUnion()->getConstArray(); - TConstUnionArray constArray(selectors.size()); - - for (int i = 0; i < selectors.size(); i++) - constArray[i] = unionArray[selectors[i]]; - - TIntermTyped* result = addConstantUnion(constArray, node->getType(), loc); - - if (result == 0) - result = node; - else - result->setType(TType(node->getBasicType(), EvqConst, selectors.size())); - - return result; -} - -} // end namespace glslang diff --git a/External/glslang/glslang/MachineIndependent/InfoSink.cpp b/External/glslang/glslang/MachineIndependent/InfoSink.cpp deleted file mode 100644 index d00c4225..00000000 --- a/External/glslang/glslang/MachineIndependent/InfoSink.cpp +++ /dev/null @@ -1,113 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -#include "../Include/InfoSink.h" - -#include - -namespace glslang { - -void TInfoSinkBase::append(const char* s) -{ - if (outputStream & EString) { - if (s == nullptr) - sink.append("(null)"); - else { - checkMem(strlen(s)); - sink.append(s); - } - } - -//#ifdef _WIN32 -// if (outputStream & EDebugger) -// OutputDebugString(s); -//#endif - - if (outputStream & EStdOut) - fprintf(stdout, "%s", s); -} - -void TInfoSinkBase::append(int count, char c) -{ - if (outputStream & EString) { - checkMem(count); - sink.append(count, c); - } - -//#ifdef _WIN32 -// if (outputStream & EDebugger) { -// char str[2]; -// str[0] = c; -// str[1] = '\0'; -// OutputDebugString(str); -// } -//#endif - - if (outputStream & EStdOut) - fprintf(stdout, "%c", c); -} - -void TInfoSinkBase::append(const TPersistString& t) -{ - if (outputStream & EString) { - checkMem(t.size()); - sink.append(t); - } - -//#ifdef _WIN32 -// if (outputStream & EDebugger) -// OutputDebugString(t.c_str()); -//#endif - - if (outputStream & EStdOut) - fprintf(stdout, "%s", t.c_str()); -} - -void TInfoSinkBase::append(const TString& t) -{ - if (outputStream & EString) { - checkMem(t.size()); - sink.append(t.c_str()); - } - -//#ifdef _WIN32 -// if (outputStream & EDebugger) -// OutputDebugString(t.c_str()); -//#endif - - if (outputStream & EStdOut) - fprintf(stdout, "%s", t.c_str()); -} - -} // end namespace glslang diff --git a/External/glslang/glslang/MachineIndependent/Initialize.cpp b/External/glslang/glslang/MachineIndependent/Initialize.cpp deleted file mode 100644 index 5ae4dbd0..00000000 --- a/External/glslang/glslang/MachineIndependent/Initialize.cpp +++ /dev/null @@ -1,8639 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// Copyright (C) 2012-2016 LunarG, Inc. -// Copyright (C) 2015-2017 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. -// - -// -// Create strings that declare built-in definitions, add built-ins programmatically -// that cannot be expressed in the strings, and establish mappings between -// built-in functions and operators. -// -// Where to put a built-in: -// TBuiltIns::initialize(version,profile) context-independent textual built-ins; add them to the right string -// TBuiltIns::initialize(resources,...) context-dependent textual built-ins; add them to the right string -// TBuiltIns::identifyBuiltIns(...,symbolTable) context-independent programmatic additions/mappings to the symbol table, -// including identifying what extensions are needed if a version does not allow a symbol -// TBuiltIns::identifyBuiltIns(...,symbolTable, resources) context-dependent programmatic additions/mappings to the symbol table, -// including identifying what extensions are needed if a version does not allow a symbol -// - -#include "../Include/intermediate.h" -#include "Initialize.h" - -namespace glslang { - -// TODO: ARB_Compatability: do full extension support -const bool ARBCompatibility = true; - -const bool ForwardCompatibility = false; - -// change this back to false if depending on textual spellings of texturing calls when consuming the AST -// Using PureOperatorBuiltins=false is deprecated. -bool PureOperatorBuiltins = true; - -inline bool IncludeLegacy(int version, EProfile profile, const SpvVersion& spvVersion) -{ - return profile != EEsProfile && (version <= 130 || (spvVersion.spv == 0 && ARBCompatibility) || profile == ECompatibilityProfile); -} - -// Construct TBuiltInParseables base class. This can be used for language-common constructs. -TBuiltInParseables::TBuiltInParseables() -{ -} - -// Destroy TBuiltInParseables. -TBuiltInParseables::~TBuiltInParseables() -{ -} - -TBuiltIns::TBuiltIns() -{ - // Set up textual representations for making all the permutations - // of texturing/imaging functions. - prefixes[EbtFloat] = ""; -#ifdef AMD_EXTENSIONS - prefixes[EbtFloat16] = "f16"; -#endif - prefixes[EbtInt8] = "i8"; - prefixes[EbtUint8] = "u8"; - prefixes[EbtInt16] = "i16"; - prefixes[EbtUint16] = "u16"; - prefixes[EbtInt] = "i"; - prefixes[EbtUint] = "u"; - postfixes[2] = "2"; - postfixes[3] = "3"; - postfixes[4] = "4"; - - // Map from symbolic class of texturing dimension to numeric dimensions. - dimMap[Esd1D] = 1; - dimMap[Esd2D] = 2; - dimMap[EsdRect] = 2; - dimMap[Esd3D] = 3; - dimMap[EsdCube] = 3; - dimMap[EsdBuffer] = 1; - dimMap[EsdSubpass] = 2; // potientially unused for now -} - -TBuiltIns::~TBuiltIns() -{ -} - - -// -// Add all context-independent built-in functions and variables that are present -// for the given version and profile. Share common ones across stages, otherwise -// make stage-specific entries. -// -// Most built-ins variables can be added as simple text strings. Some need to -// be added programmatically, which is done later in IdentifyBuiltIns() below. -// -void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvVersion) -{ - //============================================================================ - // - // Prototypes for built-in functions seen by both vertex and fragment shaders. - // - //============================================================================ - - // - // Angle and Trigonometric Functions. - // - commonBuiltins.append( - "float radians(float degrees);" - "vec2 radians(vec2 degrees);" - "vec3 radians(vec3 degrees);" - "vec4 radians(vec4 degrees);" - - "float degrees(float radians);" - "vec2 degrees(vec2 radians);" - "vec3 degrees(vec3 radians);" - "vec4 degrees(vec4 radians);" - - "float sin(float angle);" - "vec2 sin(vec2 angle);" - "vec3 sin(vec3 angle);" - "vec4 sin(vec4 angle);" - - "float cos(float angle);" - "vec2 cos(vec2 angle);" - "vec3 cos(vec3 angle);" - "vec4 cos(vec4 angle);" - - "float tan(float angle);" - "vec2 tan(vec2 angle);" - "vec3 tan(vec3 angle);" - "vec4 tan(vec4 angle);" - - "float asin(float x);" - "vec2 asin(vec2 x);" - "vec3 asin(vec3 x);" - "vec4 asin(vec4 x);" - - "float acos(float x);" - "vec2 acos(vec2 x);" - "vec3 acos(vec3 x);" - "vec4 acos(vec4 x);" - - "float atan(float y, float x);" - "vec2 atan(vec2 y, vec2 x);" - "vec3 atan(vec3 y, vec3 x);" - "vec4 atan(vec4 y, vec4 x);" - - "float atan(float y_over_x);" - "vec2 atan(vec2 y_over_x);" - "vec3 atan(vec3 y_over_x);" - "vec4 atan(vec4 y_over_x);" - - "\n"); - - if (version >= 130) { - commonBuiltins.append( - "float sinh(float angle);" - "vec2 sinh(vec2 angle);" - "vec3 sinh(vec3 angle);" - "vec4 sinh(vec4 angle);" - - "float cosh(float angle);" - "vec2 cosh(vec2 angle);" - "vec3 cosh(vec3 angle);" - "vec4 cosh(vec4 angle);" - - "float tanh(float angle);" - "vec2 tanh(vec2 angle);" - "vec3 tanh(vec3 angle);" - "vec4 tanh(vec4 angle);" - - "float asinh(float x);" - "vec2 asinh(vec2 x);" - "vec3 asinh(vec3 x);" - "vec4 asinh(vec4 x);" - - "float acosh(float x);" - "vec2 acosh(vec2 x);" - "vec3 acosh(vec3 x);" - "vec4 acosh(vec4 x);" - - "float atanh(float y_over_x);" - "vec2 atanh(vec2 y_over_x);" - "vec3 atanh(vec3 y_over_x);" - "vec4 atanh(vec4 y_over_x);" - - "\n"); - } - - // - // Exponential Functions. - // - commonBuiltins.append( - "float pow(float x, float y);" - "vec2 pow(vec2 x, vec2 y);" - "vec3 pow(vec3 x, vec3 y);" - "vec4 pow(vec4 x, vec4 y);" - - "float exp(float x);" - "vec2 exp(vec2 x);" - "vec3 exp(vec3 x);" - "vec4 exp(vec4 x);" - - "float log(float x);" - "vec2 log(vec2 x);" - "vec3 log(vec3 x);" - "vec4 log(vec4 x);" - - "float exp2(float x);" - "vec2 exp2(vec2 x);" - "vec3 exp2(vec3 x);" - "vec4 exp2(vec4 x);" - - "float log2(float x);" - "vec2 log2(vec2 x);" - "vec3 log2(vec3 x);" - "vec4 log2(vec4 x);" - - "float sqrt(float x);" - "vec2 sqrt(vec2 x);" - "vec3 sqrt(vec3 x);" - "vec4 sqrt(vec4 x);" - - "float inversesqrt(float x);" - "vec2 inversesqrt(vec2 x);" - "vec3 inversesqrt(vec3 x);" - "vec4 inversesqrt(vec4 x);" - - "\n"); - - // - // Common Functions. - // - commonBuiltins.append( - "float abs(float x);" - "vec2 abs(vec2 x);" - "vec3 abs(vec3 x);" - "vec4 abs(vec4 x);" - - "float sign(float x);" - "vec2 sign(vec2 x);" - "vec3 sign(vec3 x);" - "vec4 sign(vec4 x);" - - "float floor(float x);" - "vec2 floor(vec2 x);" - "vec3 floor(vec3 x);" - "vec4 floor(vec4 x);" - - "float ceil(float x);" - "vec2 ceil(vec2 x);" - "vec3 ceil(vec3 x);" - "vec4 ceil(vec4 x);" - - "float fract(float x);" - "vec2 fract(vec2 x);" - "vec3 fract(vec3 x);" - "vec4 fract(vec4 x);" - - "float mod(float x, float y);" - "vec2 mod(vec2 x, float y);" - "vec3 mod(vec3 x, float y);" - "vec4 mod(vec4 x, float y);" - "vec2 mod(vec2 x, vec2 y);" - "vec3 mod(vec3 x, vec3 y);" - "vec4 mod(vec4 x, vec4 y);" - - "float min(float x, float y);" - "vec2 min(vec2 x, float y);" - "vec3 min(vec3 x, float y);" - "vec4 min(vec4 x, float y);" - "vec2 min(vec2 x, vec2 y);" - "vec3 min(vec3 x, vec3 y);" - "vec4 min(vec4 x, vec4 y);" - - "float max(float x, float y);" - "vec2 max(vec2 x, float y);" - "vec3 max(vec3 x, float y);" - "vec4 max(vec4 x, float y);" - "vec2 max(vec2 x, vec2 y);" - "vec3 max(vec3 x, vec3 y);" - "vec4 max(vec4 x, vec4 y);" - - "float clamp(float x, float minVal, float maxVal);" - "vec2 clamp(vec2 x, float minVal, float maxVal);" - "vec3 clamp(vec3 x, float minVal, float maxVal);" - "vec4 clamp(vec4 x, float minVal, float maxVal);" - "vec2 clamp(vec2 x, vec2 minVal, vec2 maxVal);" - "vec3 clamp(vec3 x, vec3 minVal, vec3 maxVal);" - "vec4 clamp(vec4 x, vec4 minVal, vec4 maxVal);" - - "float mix(float x, float y, float a);" - "vec2 mix(vec2 x, vec2 y, float a);" - "vec3 mix(vec3 x, vec3 y, float a);" - "vec4 mix(vec4 x, vec4 y, float a);" - "vec2 mix(vec2 x, vec2 y, vec2 a);" - "vec3 mix(vec3 x, vec3 y, vec3 a);" - "vec4 mix(vec4 x, vec4 y, vec4 a);" - - "float step(float edge, float x);" - "vec2 step(vec2 edge, vec2 x);" - "vec3 step(vec3 edge, vec3 x);" - "vec4 step(vec4 edge, vec4 x);" - "vec2 step(float edge, vec2 x);" - "vec3 step(float edge, vec3 x);" - "vec4 step(float edge, vec4 x);" - - "float smoothstep(float edge0, float edge1, float x);" - "vec2 smoothstep(vec2 edge0, vec2 edge1, vec2 x);" - "vec3 smoothstep(vec3 edge0, vec3 edge1, vec3 x);" - "vec4 smoothstep(vec4 edge0, vec4 edge1, vec4 x);" - "vec2 smoothstep(float edge0, float edge1, vec2 x);" - "vec3 smoothstep(float edge0, float edge1, vec3 x);" - "vec4 smoothstep(float edge0, float edge1, vec4 x);" - - "\n"); - - if (version >= 130) { - commonBuiltins.append( - " int abs( int x);" - "ivec2 abs(ivec2 x);" - "ivec3 abs(ivec3 x);" - "ivec4 abs(ivec4 x);" - - " int sign( int x);" - "ivec2 sign(ivec2 x);" - "ivec3 sign(ivec3 x);" - "ivec4 sign(ivec4 x);" - - "float trunc(float x);" - "vec2 trunc(vec2 x);" - "vec3 trunc(vec3 x);" - "vec4 trunc(vec4 x);" - - "float round(float x);" - "vec2 round(vec2 x);" - "vec3 round(vec3 x);" - "vec4 round(vec4 x);" - - "float roundEven(float x);" - "vec2 roundEven(vec2 x);" - "vec3 roundEven(vec3 x);" - "vec4 roundEven(vec4 x);" - - "float modf(float, out float);" - "vec2 modf(vec2, out vec2 );" - "vec3 modf(vec3, out vec3 );" - "vec4 modf(vec4, out vec4 );" - - " int min(int x, int y);" - "ivec2 min(ivec2 x, int y);" - "ivec3 min(ivec3 x, int y);" - "ivec4 min(ivec4 x, int y);" - "ivec2 min(ivec2 x, ivec2 y);" - "ivec3 min(ivec3 x, ivec3 y);" - "ivec4 min(ivec4 x, ivec4 y);" - - " uint min(uint x, uint y);" - "uvec2 min(uvec2 x, uint y);" - "uvec3 min(uvec3 x, uint y);" - "uvec4 min(uvec4 x, uint y);" - "uvec2 min(uvec2 x, uvec2 y);" - "uvec3 min(uvec3 x, uvec3 y);" - "uvec4 min(uvec4 x, uvec4 y);" - - " int max(int x, int y);" - "ivec2 max(ivec2 x, int y);" - "ivec3 max(ivec3 x, int y);" - "ivec4 max(ivec4 x, int y);" - "ivec2 max(ivec2 x, ivec2 y);" - "ivec3 max(ivec3 x, ivec3 y);" - "ivec4 max(ivec4 x, ivec4 y);" - - " uint max(uint x, uint y);" - "uvec2 max(uvec2 x, uint y);" - "uvec3 max(uvec3 x, uint y);" - "uvec4 max(uvec4 x, uint y);" - "uvec2 max(uvec2 x, uvec2 y);" - "uvec3 max(uvec3 x, uvec3 y);" - "uvec4 max(uvec4 x, uvec4 y);" - - "int clamp(int x, int minVal, int maxVal);" - "ivec2 clamp(ivec2 x, int minVal, int maxVal);" - "ivec3 clamp(ivec3 x, int minVal, int maxVal);" - "ivec4 clamp(ivec4 x, int minVal, int maxVal);" - "ivec2 clamp(ivec2 x, ivec2 minVal, ivec2 maxVal);" - "ivec3 clamp(ivec3 x, ivec3 minVal, ivec3 maxVal);" - "ivec4 clamp(ivec4 x, ivec4 minVal, ivec4 maxVal);" - - "uint clamp(uint x, uint minVal, uint maxVal);" - "uvec2 clamp(uvec2 x, uint minVal, uint maxVal);" - "uvec3 clamp(uvec3 x, uint minVal, uint maxVal);" - "uvec4 clamp(uvec4 x, uint minVal, uint maxVal);" - "uvec2 clamp(uvec2 x, uvec2 minVal, uvec2 maxVal);" - "uvec3 clamp(uvec3 x, uvec3 minVal, uvec3 maxVal);" - "uvec4 clamp(uvec4 x, uvec4 minVal, uvec4 maxVal);" - - "float mix(float x, float y, bool a);" - "vec2 mix(vec2 x, vec2 y, bvec2 a);" - "vec3 mix(vec3 x, vec3 y, bvec3 a);" - "vec4 mix(vec4 x, vec4 y, bvec4 a);" - - "bool isnan(float x);" - "bvec2 isnan(vec2 x);" - "bvec3 isnan(vec3 x);" - "bvec4 isnan(vec4 x);" - - "bool isinf(float x);" - "bvec2 isinf(vec2 x);" - "bvec3 isinf(vec3 x);" - "bvec4 isinf(vec4 x);" - - "\n"); - } - - // - // double functions added to desktop 4.00, but not fma, frexp, ldexp, or pack/unpack - // - if (profile != EEsProfile && version >= 400) { - commonBuiltins.append( - - "double sqrt(double);" - "dvec2 sqrt(dvec2);" - "dvec3 sqrt(dvec3);" - "dvec4 sqrt(dvec4);" - - "double inversesqrt(double);" - "dvec2 inversesqrt(dvec2);" - "dvec3 inversesqrt(dvec3);" - "dvec4 inversesqrt(dvec4);" - - "double abs(double);" - "dvec2 abs(dvec2);" - "dvec3 abs(dvec3);" - "dvec4 abs(dvec4);" - - "double sign(double);" - "dvec2 sign(dvec2);" - "dvec3 sign(dvec3);" - "dvec4 sign(dvec4);" - - "double floor(double);" - "dvec2 floor(dvec2);" - "dvec3 floor(dvec3);" - "dvec4 floor(dvec4);" - - "double trunc(double);" - "dvec2 trunc(dvec2);" - "dvec3 trunc(dvec3);" - "dvec4 trunc(dvec4);" - - "double round(double);" - "dvec2 round(dvec2);" - "dvec3 round(dvec3);" - "dvec4 round(dvec4);" - - "double roundEven(double);" - "dvec2 roundEven(dvec2);" - "dvec3 roundEven(dvec3);" - "dvec4 roundEven(dvec4);" - - "double ceil(double);" - "dvec2 ceil(dvec2);" - "dvec3 ceil(dvec3);" - "dvec4 ceil(dvec4);" - - "double fract(double);" - "dvec2 fract(dvec2);" - "dvec3 fract(dvec3);" - "dvec4 fract(dvec4);" - - "double mod(double, double);" - "dvec2 mod(dvec2 , double);" - "dvec3 mod(dvec3 , double);" - "dvec4 mod(dvec4 , double);" - "dvec2 mod(dvec2 , dvec2);" - "dvec3 mod(dvec3 , dvec3);" - "dvec4 mod(dvec4 , dvec4);" - - "double modf(double, out double);" - "dvec2 modf(dvec2, out dvec2);" - "dvec3 modf(dvec3, out dvec3);" - "dvec4 modf(dvec4, out dvec4);" - - "double min(double, double);" - "dvec2 min(dvec2, double);" - "dvec3 min(dvec3, double);" - "dvec4 min(dvec4, double);" - "dvec2 min(dvec2, dvec2);" - "dvec3 min(dvec3, dvec3);" - "dvec4 min(dvec4, dvec4);" - - "double max(double, double);" - "dvec2 max(dvec2 , double);" - "dvec3 max(dvec3 , double);" - "dvec4 max(dvec4 , double);" - "dvec2 max(dvec2 , dvec2);" - "dvec3 max(dvec3 , dvec3);" - "dvec4 max(dvec4 , dvec4);" - - "double clamp(double, double, double);" - "dvec2 clamp(dvec2 , double, double);" - "dvec3 clamp(dvec3 , double, double);" - "dvec4 clamp(dvec4 , double, double);" - "dvec2 clamp(dvec2 , dvec2 , dvec2);" - "dvec3 clamp(dvec3 , dvec3 , dvec3);" - "dvec4 clamp(dvec4 , dvec4 , dvec4);" - - "double mix(double, double, double);" - "dvec2 mix(dvec2, dvec2, double);" - "dvec3 mix(dvec3, dvec3, double);" - "dvec4 mix(dvec4, dvec4, double);" - "dvec2 mix(dvec2, dvec2, dvec2);" - "dvec3 mix(dvec3, dvec3, dvec3);" - "dvec4 mix(dvec4, dvec4, dvec4);" - "double mix(double, double, bool);" - "dvec2 mix(dvec2, dvec2, bvec2);" - "dvec3 mix(dvec3, dvec3, bvec3);" - "dvec4 mix(dvec4, dvec4, bvec4);" - - "double step(double, double);" - "dvec2 step(dvec2 , dvec2);" - "dvec3 step(dvec3 , dvec3);" - "dvec4 step(dvec4 , dvec4);" - "dvec2 step(double, dvec2);" - "dvec3 step(double, dvec3);" - "dvec4 step(double, dvec4);" - - "double smoothstep(double, double, double);" - "dvec2 smoothstep(dvec2 , dvec2 , dvec2);" - "dvec3 smoothstep(dvec3 , dvec3 , dvec3);" - "dvec4 smoothstep(dvec4 , dvec4 , dvec4);" - "dvec2 smoothstep(double, double, dvec2);" - "dvec3 smoothstep(double, double, dvec3);" - "dvec4 smoothstep(double, double, dvec4);" - - "bool isnan(double);" - "bvec2 isnan(dvec2);" - "bvec3 isnan(dvec3);" - "bvec4 isnan(dvec4);" - - "bool isinf(double);" - "bvec2 isinf(dvec2);" - "bvec3 isinf(dvec3);" - "bvec4 isinf(dvec4);" - - "double length(double);" - "double length(dvec2);" - "double length(dvec3);" - "double length(dvec4);" - - "double distance(double, double);" - "double distance(dvec2 , dvec2);" - "double distance(dvec3 , dvec3);" - "double distance(dvec4 , dvec4);" - - "double dot(double, double);" - "double dot(dvec2 , dvec2);" - "double dot(dvec3 , dvec3);" - "double dot(dvec4 , dvec4);" - - "dvec3 cross(dvec3, dvec3);" - - "double normalize(double);" - "dvec2 normalize(dvec2);" - "dvec3 normalize(dvec3);" - "dvec4 normalize(dvec4);" - - "double faceforward(double, double, double);" - "dvec2 faceforward(dvec2, dvec2, dvec2);" - "dvec3 faceforward(dvec3, dvec3, dvec3);" - "dvec4 faceforward(dvec4, dvec4, dvec4);" - - "double reflect(double, double);" - "dvec2 reflect(dvec2 , dvec2 );" - "dvec3 reflect(dvec3 , dvec3 );" - "dvec4 reflect(dvec4 , dvec4 );" - - "double refract(double, double, double);" - "dvec2 refract(dvec2 , dvec2 , double);" - "dvec3 refract(dvec3 , dvec3 , double);" - "dvec4 refract(dvec4 , dvec4 , double);" - - "dmat2 matrixCompMult(dmat2, dmat2);" - "dmat3 matrixCompMult(dmat3, dmat3);" - "dmat4 matrixCompMult(dmat4, dmat4);" - "dmat2x3 matrixCompMult(dmat2x3, dmat2x3);" - "dmat2x4 matrixCompMult(dmat2x4, dmat2x4);" - "dmat3x2 matrixCompMult(dmat3x2, dmat3x2);" - "dmat3x4 matrixCompMult(dmat3x4, dmat3x4);" - "dmat4x2 matrixCompMult(dmat4x2, dmat4x2);" - "dmat4x3 matrixCompMult(dmat4x3, dmat4x3);" - - "dmat2 outerProduct(dvec2, dvec2);" - "dmat3 outerProduct(dvec3, dvec3);" - "dmat4 outerProduct(dvec4, dvec4);" - "dmat2x3 outerProduct(dvec3, dvec2);" - "dmat3x2 outerProduct(dvec2, dvec3);" - "dmat2x4 outerProduct(dvec4, dvec2);" - "dmat4x2 outerProduct(dvec2, dvec4);" - "dmat3x4 outerProduct(dvec4, dvec3);" - "dmat4x3 outerProduct(dvec3, dvec4);" - - "dmat2 transpose(dmat2);" - "dmat3 transpose(dmat3);" - "dmat4 transpose(dmat4);" - "dmat2x3 transpose(dmat3x2);" - "dmat3x2 transpose(dmat2x3);" - "dmat2x4 transpose(dmat4x2);" - "dmat4x2 transpose(dmat2x4);" - "dmat3x4 transpose(dmat4x3);" - "dmat4x3 transpose(dmat3x4);" - - "double determinant(dmat2);" - "double determinant(dmat3);" - "double determinant(dmat4);" - - "dmat2 inverse(dmat2);" - "dmat3 inverse(dmat3);" - "dmat4 inverse(dmat4);" - - "bvec2 lessThan(dvec2, dvec2);" - "bvec3 lessThan(dvec3, dvec3);" - "bvec4 lessThan(dvec4, dvec4);" - - "bvec2 lessThanEqual(dvec2, dvec2);" - "bvec3 lessThanEqual(dvec3, dvec3);" - "bvec4 lessThanEqual(dvec4, dvec4);" - - "bvec2 greaterThan(dvec2, dvec2);" - "bvec3 greaterThan(dvec3, dvec3);" - "bvec4 greaterThan(dvec4, dvec4);" - - "bvec2 greaterThanEqual(dvec2, dvec2);" - "bvec3 greaterThanEqual(dvec3, dvec3);" - "bvec4 greaterThanEqual(dvec4, dvec4);" - - "bvec2 equal(dvec2, dvec2);" - "bvec3 equal(dvec3, dvec3);" - "bvec4 equal(dvec4, dvec4);" - - "bvec2 notEqual(dvec2, dvec2);" - "bvec3 notEqual(dvec3, dvec3);" - "bvec4 notEqual(dvec4, dvec4);" - - "\n"); - } - - if (profile != EEsProfile && version >= 450) { - commonBuiltins.append( - - "int64_t abs(int64_t);" - "i64vec2 abs(i64vec2);" - "i64vec3 abs(i64vec3);" - "i64vec4 abs(i64vec4);" - - "int64_t sign(int64_t);" - "i64vec2 sign(i64vec2);" - "i64vec3 sign(i64vec3);" - "i64vec4 sign(i64vec4);" - - "int64_t min(int64_t, int64_t);" - "i64vec2 min(i64vec2, int64_t);" - "i64vec3 min(i64vec3, int64_t);" - "i64vec4 min(i64vec4, int64_t);" - "i64vec2 min(i64vec2, i64vec2);" - "i64vec3 min(i64vec3, i64vec3);" - "i64vec4 min(i64vec4, i64vec4);" - "uint64_t min(uint64_t, uint64_t);" - "u64vec2 min(u64vec2, uint64_t);" - "u64vec3 min(u64vec3, uint64_t);" - "u64vec4 min(u64vec4, uint64_t);" - "u64vec2 min(u64vec2, u64vec2);" - "u64vec3 min(u64vec3, u64vec3);" - "u64vec4 min(u64vec4, u64vec4);" - - "int64_t max(int64_t, int64_t);" - "i64vec2 max(i64vec2, int64_t);" - "i64vec3 max(i64vec3, int64_t);" - "i64vec4 max(i64vec4, int64_t);" - "i64vec2 max(i64vec2, i64vec2);" - "i64vec3 max(i64vec3, i64vec3);" - "i64vec4 max(i64vec4, i64vec4);" - "uint64_t max(uint64_t, uint64_t);" - "u64vec2 max(u64vec2, uint64_t);" - "u64vec3 max(u64vec3, uint64_t);" - "u64vec4 max(u64vec4, uint64_t);" - "u64vec2 max(u64vec2, u64vec2);" - "u64vec3 max(u64vec3, u64vec3);" - "u64vec4 max(u64vec4, u64vec4);" - - "int64_t clamp(int64_t, int64_t, int64_t);" - "i64vec2 clamp(i64vec2, int64_t, int64_t);" - "i64vec3 clamp(i64vec3, int64_t, int64_t);" - "i64vec4 clamp(i64vec4, int64_t, int64_t);" - "i64vec2 clamp(i64vec2, i64vec2, i64vec2);" - "i64vec3 clamp(i64vec3, i64vec3, i64vec3);" - "i64vec4 clamp(i64vec4, i64vec4, i64vec4);" - "uint64_t clamp(uint64_t, uint64_t, uint64_t);" - "u64vec2 clamp(u64vec2, uint64_t, uint64_t);" - "u64vec3 clamp(u64vec3, uint64_t, uint64_t);" - "u64vec4 clamp(u64vec4, uint64_t, uint64_t);" - "u64vec2 clamp(u64vec2, u64vec2, u64vec2);" - "u64vec3 clamp(u64vec3, u64vec3, u64vec3);" - "u64vec4 clamp(u64vec4, u64vec4, u64vec4);" - - "int64_t mix(int64_t, int64_t, bool);" - "i64vec2 mix(i64vec2, i64vec2, bvec2);" - "i64vec3 mix(i64vec3, i64vec3, bvec3);" - "i64vec4 mix(i64vec4, i64vec4, bvec4);" - "uint64_t mix(uint64_t, uint64_t, bool);" - "u64vec2 mix(u64vec2, u64vec2, bvec2);" - "u64vec3 mix(u64vec3, u64vec3, bvec3);" - "u64vec4 mix(u64vec4, u64vec4, bvec4);" - - "int64_t doubleBitsToInt64(double);" - "i64vec2 doubleBitsToInt64(dvec2);" - "i64vec3 doubleBitsToInt64(dvec3);" - "i64vec4 doubleBitsToInt64(dvec4);" - - "uint64_t doubleBitsToUint64(double);" - "u64vec2 doubleBitsToUint64(dvec2);" - "u64vec3 doubleBitsToUint64(dvec3);" - "u64vec4 doubleBitsToUint64(dvec4);" - - "double int64BitsToDouble(int64_t);" - "dvec2 int64BitsToDouble(i64vec2);" - "dvec3 int64BitsToDouble(i64vec3);" - "dvec4 int64BitsToDouble(i64vec4);" - - "double uint64BitsToDouble(uint64_t);" - "dvec2 uint64BitsToDouble(u64vec2);" - "dvec3 uint64BitsToDouble(u64vec3);" - "dvec4 uint64BitsToDouble(u64vec4);" - - "int64_t packInt2x32(ivec2);" - "uint64_t packUint2x32(uvec2);" - "ivec2 unpackInt2x32(int64_t);" - "uvec2 unpackUint2x32(uint64_t);" - - "bvec2 lessThan(i64vec2, i64vec2);" - "bvec3 lessThan(i64vec3, i64vec3);" - "bvec4 lessThan(i64vec4, i64vec4);" - "bvec2 lessThan(u64vec2, u64vec2);" - "bvec3 lessThan(u64vec3, u64vec3);" - "bvec4 lessThan(u64vec4, u64vec4);" - - "bvec2 lessThanEqual(i64vec2, i64vec2);" - "bvec3 lessThanEqual(i64vec3, i64vec3);" - "bvec4 lessThanEqual(i64vec4, i64vec4);" - "bvec2 lessThanEqual(u64vec2, u64vec2);" - "bvec3 lessThanEqual(u64vec3, u64vec3);" - "bvec4 lessThanEqual(u64vec4, u64vec4);" - - "bvec2 greaterThan(i64vec2, i64vec2);" - "bvec3 greaterThan(i64vec3, i64vec3);" - "bvec4 greaterThan(i64vec4, i64vec4);" - "bvec2 greaterThan(u64vec2, u64vec2);" - "bvec3 greaterThan(u64vec3, u64vec3);" - "bvec4 greaterThan(u64vec4, u64vec4);" - - "bvec2 greaterThanEqual(i64vec2, i64vec2);" - "bvec3 greaterThanEqual(i64vec3, i64vec3);" - "bvec4 greaterThanEqual(i64vec4, i64vec4);" - "bvec2 greaterThanEqual(u64vec2, u64vec2);" - "bvec3 greaterThanEqual(u64vec3, u64vec3);" - "bvec4 greaterThanEqual(u64vec4, u64vec4);" - - "bvec2 equal(i64vec2, i64vec2);" - "bvec3 equal(i64vec3, i64vec3);" - "bvec4 equal(i64vec4, i64vec4);" - "bvec2 equal(u64vec2, u64vec2);" - "bvec3 equal(u64vec3, u64vec3);" - "bvec4 equal(u64vec4, u64vec4);" - - "bvec2 notEqual(i64vec2, i64vec2);" - "bvec3 notEqual(i64vec3, i64vec3);" - "bvec4 notEqual(i64vec4, i64vec4);" - "bvec2 notEqual(u64vec2, u64vec2);" - "bvec3 notEqual(u64vec3, u64vec3);" - "bvec4 notEqual(u64vec4, u64vec4);" - - "int findLSB(int64_t);" - "ivec2 findLSB(i64vec2);" - "ivec3 findLSB(i64vec3);" - "ivec4 findLSB(i64vec4);" - - "int findLSB(uint64_t);" - "ivec2 findLSB(u64vec2);" - "ivec3 findLSB(u64vec3);" - "ivec4 findLSB(u64vec4);" - - "int findMSB(int64_t);" - "ivec2 findMSB(i64vec2);" - "ivec3 findMSB(i64vec3);" - "ivec4 findMSB(i64vec4);" - - "int findMSB(uint64_t);" - "ivec2 findMSB(u64vec2);" - "ivec3 findMSB(u64vec3);" - "ivec4 findMSB(u64vec4);" - - "\n" - ); - } - -#ifdef AMD_EXTENSIONS - // GL_AMD_shader_trinary_minmax - if (profile != EEsProfile && version >= 430) { - commonBuiltins.append( - "float min3(float, float, float);" - "vec2 min3(vec2, vec2, vec2);" - "vec3 min3(vec3, vec3, vec3);" - "vec4 min3(vec4, vec4, vec4);" - - "int min3(int, int, int);" - "ivec2 min3(ivec2, ivec2, ivec2);" - "ivec3 min3(ivec3, ivec3, ivec3);" - "ivec4 min3(ivec4, ivec4, ivec4);" - - "uint min3(uint, uint, uint);" - "uvec2 min3(uvec2, uvec2, uvec2);" - "uvec3 min3(uvec3, uvec3, uvec3);" - "uvec4 min3(uvec4, uvec4, uvec4);" - - "float max3(float, float, float);" - "vec2 max3(vec2, vec2, vec2);" - "vec3 max3(vec3, vec3, vec3);" - "vec4 max3(vec4, vec4, vec4);" - - "int max3(int, int, int);" - "ivec2 max3(ivec2, ivec2, ivec2);" - "ivec3 max3(ivec3, ivec3, ivec3);" - "ivec4 max3(ivec4, ivec4, ivec4);" - - "uint max3(uint, uint, uint);" - "uvec2 max3(uvec2, uvec2, uvec2);" - "uvec3 max3(uvec3, uvec3, uvec3);" - "uvec4 max3(uvec4, uvec4, uvec4);" - - "float mid3(float, float, float);" - "vec2 mid3(vec2, vec2, vec2);" - "vec3 mid3(vec3, vec3, vec3);" - "vec4 mid3(vec4, vec4, vec4);" - - "int mid3(int, int, int);" - "ivec2 mid3(ivec2, ivec2, ivec2);" - "ivec3 mid3(ivec3, ivec3, ivec3);" - "ivec4 mid3(ivec4, ivec4, ivec4);" - - "uint mid3(uint, uint, uint);" - "uvec2 mid3(uvec2, uvec2, uvec2);" - "uvec3 mid3(uvec3, uvec3, uvec3);" - "uvec4 mid3(uvec4, uvec4, uvec4);" - - "float16_t min3(float16_t, float16_t, float16_t);" - "f16vec2 min3(f16vec2, f16vec2, f16vec2);" - "f16vec3 min3(f16vec3, f16vec3, f16vec3);" - "f16vec4 min3(f16vec4, f16vec4, f16vec4);" - - "float16_t max3(float16_t, float16_t, float16_t);" - "f16vec2 max3(f16vec2, f16vec2, f16vec2);" - "f16vec3 max3(f16vec3, f16vec3, f16vec3);" - "f16vec4 max3(f16vec4, f16vec4, f16vec4);" - - "float16_t mid3(float16_t, float16_t, float16_t);" - "f16vec2 mid3(f16vec2, f16vec2, f16vec2);" - "f16vec3 mid3(f16vec3, f16vec3, f16vec3);" - "f16vec4 mid3(f16vec4, f16vec4, f16vec4);" - - "int16_t min3(int16_t, int16_t, int16_t);" - "i16vec2 min3(i16vec2, i16vec2, i16vec2);" - "i16vec3 min3(i16vec3, i16vec3, i16vec3);" - "i16vec4 min3(i16vec4, i16vec4, i16vec4);" - - "int16_t max3(int16_t, int16_t, int16_t);" - "i16vec2 max3(i16vec2, i16vec2, i16vec2);" - "i16vec3 max3(i16vec3, i16vec3, i16vec3);" - "i16vec4 max3(i16vec4, i16vec4, i16vec4);" - - "int16_t mid3(int16_t, int16_t, int16_t);" - "i16vec2 mid3(i16vec2, i16vec2, i16vec2);" - "i16vec3 mid3(i16vec3, i16vec3, i16vec3);" - "i16vec4 mid3(i16vec4, i16vec4, i16vec4);" - - "uint16_t min3(uint16_t, uint16_t, uint16_t);" - "u16vec2 min3(u16vec2, u16vec2, u16vec2);" - "u16vec3 min3(u16vec3, u16vec3, u16vec3);" - "u16vec4 min3(u16vec4, u16vec4, u16vec4);" - - "uint16_t max3(uint16_t, uint16_t, uint16_t);" - "u16vec2 max3(u16vec2, u16vec2, u16vec2);" - "u16vec3 max3(u16vec3, u16vec3, u16vec3);" - "u16vec4 max3(u16vec4, u16vec4, u16vec4);" - - "uint16_t mid3(uint16_t, uint16_t, uint16_t);" - "u16vec2 mid3(u16vec2, u16vec2, u16vec2);" - "u16vec3 mid3(u16vec3, u16vec3, u16vec3);" - "u16vec4 mid3(u16vec4, u16vec4, u16vec4);" - - "\n" - ); - } -#endif - - if ((profile == EEsProfile && version >= 310) || - (profile != EEsProfile && version >= 430)) { - commonBuiltins.append( - "uint atomicAdd(coherent volatile inout uint, uint);" - " int atomicAdd(coherent volatile inout int, int);" - - "uint atomicMin(coherent volatile inout uint, uint);" - " int atomicMin(coherent volatile inout int, int);" - - "uint atomicMax(coherent volatile inout uint, uint);" - " int atomicMax(coherent volatile inout int, int);" - - "uint atomicAnd(coherent volatile inout uint, uint);" - " int atomicAnd(coherent volatile inout int, int);" - - "uint atomicOr (coherent volatile inout uint, uint);" - " int atomicOr (coherent volatile inout int, int);" - - "uint atomicXor(coherent volatile inout uint, uint);" - " int atomicXor(coherent volatile inout int, int);" - - "uint atomicExchange(coherent volatile inout uint, uint);" - " int atomicExchange(coherent volatile inout int, int);" - - "uint atomicCompSwap(coherent volatile inout uint, uint, uint);" - " int atomicCompSwap(coherent volatile inout int, int, int);" - - "\n"); - } - -#ifdef NV_EXTENSIONS - if (profile != EEsProfile && version >= 440) { - commonBuiltins.append( - "uint64_t atomicMin(coherent volatile inout uint64_t, uint64_t);" - " int64_t atomicMin(coherent volatile inout int64_t, int64_t);" - - "uint64_t atomicMax(coherent volatile inout uint64_t, uint64_t);" - " int64_t atomicMax(coherent volatile inout int64_t, int64_t);" - - "uint64_t atomicAnd(coherent volatile inout uint64_t, uint64_t);" - " int64_t atomicAnd(coherent volatile inout int64_t, int64_t);" - - "uint64_t atomicOr (coherent volatile inout uint64_t, uint64_t);" - " int64_t atomicOr (coherent volatile inout int64_t, int64_t);" - - "uint64_t atomicXor(coherent volatile inout uint64_t, uint64_t);" - " int64_t atomicXor(coherent volatile inout int64_t, int64_t);" - - " int64_t atomicAdd(coherent volatile inout int64_t, int64_t);" - " int64_t atomicExchange(coherent volatile inout int64_t, int64_t);" - " int64_t atomicCompSwap(coherent volatile inout int64_t, int64_t, int64_t);" - - "\n"); - } -#endif - - if ((profile == EEsProfile && version >= 310) || - (profile != EEsProfile && version >= 450)) { - commonBuiltins.append( - "int mix(int x, int y, bool a);" - "ivec2 mix(ivec2 x, ivec2 y, bvec2 a);" - "ivec3 mix(ivec3 x, ivec3 y, bvec3 a);" - "ivec4 mix(ivec4 x, ivec4 y, bvec4 a);" - - "uint mix(uint x, uint y, bool a);" - "uvec2 mix(uvec2 x, uvec2 y, bvec2 a);" - "uvec3 mix(uvec3 x, uvec3 y, bvec3 a);" - "uvec4 mix(uvec4 x, uvec4 y, bvec4 a);" - - "bool mix(bool x, bool y, bool a);" - "bvec2 mix(bvec2 x, bvec2 y, bvec2 a);" - "bvec3 mix(bvec3 x, bvec3 y, bvec3 a);" - "bvec4 mix(bvec4 x, bvec4 y, bvec4 a);" - - "\n"); - } - - if ((profile == EEsProfile && version >= 300) || - (profile != EEsProfile && version >= 330)) { - commonBuiltins.append( - "int floatBitsToInt(highp float value);" - "ivec2 floatBitsToInt(highp vec2 value);" - "ivec3 floatBitsToInt(highp vec3 value);" - "ivec4 floatBitsToInt(highp vec4 value);" - - "uint floatBitsToUint(highp float value);" - "uvec2 floatBitsToUint(highp vec2 value);" - "uvec3 floatBitsToUint(highp vec3 value);" - "uvec4 floatBitsToUint(highp vec4 value);" - - "float intBitsToFloat(highp int value);" - "vec2 intBitsToFloat(highp ivec2 value);" - "vec3 intBitsToFloat(highp ivec3 value);" - "vec4 intBitsToFloat(highp ivec4 value);" - - "float uintBitsToFloat(highp uint value);" - "vec2 uintBitsToFloat(highp uvec2 value);" - "vec3 uintBitsToFloat(highp uvec3 value);" - "vec4 uintBitsToFloat(highp uvec4 value);" - - "\n"); - } - - if ((profile != EEsProfile && version >= 400) || - (profile == EEsProfile && version >= 310)) { // GL_OES_gpu_shader5 - - commonBuiltins.append( - "float fma(float, float, float );" - "vec2 fma(vec2, vec2, vec2 );" - "vec3 fma(vec3, vec3, vec3 );" - "vec4 fma(vec4, vec4, vec4 );" - "\n"); - - if (profile != EEsProfile) { - commonBuiltins.append( - "double fma(double, double, double);" - "dvec2 fma(dvec2, dvec2, dvec2 );" - "dvec3 fma(dvec3, dvec3, dvec3 );" - "dvec4 fma(dvec4, dvec4, dvec4 );" - "\n"); - } - } - - if ((profile == EEsProfile && version >= 310) || - (profile != EEsProfile && version >= 400)) { - commonBuiltins.append( - "float frexp(highp float, out highp int);" - "vec2 frexp(highp vec2, out highp ivec2);" - "vec3 frexp(highp vec3, out highp ivec3);" - "vec4 frexp(highp vec4, out highp ivec4);" - - "float ldexp(highp float, highp int);" - "vec2 ldexp(highp vec2, highp ivec2);" - "vec3 ldexp(highp vec3, highp ivec3);" - "vec4 ldexp(highp vec4, highp ivec4);" - - "\n"); - } - - if (profile != EEsProfile && version >= 400) { - commonBuiltins.append( - "double frexp(double, out int);" - "dvec2 frexp( dvec2, out ivec2);" - "dvec3 frexp( dvec3, out ivec3);" - "dvec4 frexp( dvec4, out ivec4);" - - "double ldexp(double, int);" - "dvec2 ldexp( dvec2, ivec2);" - "dvec3 ldexp( dvec3, ivec3);" - "dvec4 ldexp( dvec4, ivec4);" - - "double packDouble2x32(uvec2);" - "uvec2 unpackDouble2x32(double);" - - "\n"); - } - - if ((profile == EEsProfile && version >= 300) || - (profile != EEsProfile && version >= 400)) { - commonBuiltins.append( - "highp uint packUnorm2x16(vec2);" - "vec2 unpackUnorm2x16(highp uint);" - "\n"); - } - - if ((profile == EEsProfile && version >= 300) || - (profile != EEsProfile && version >= 420)) { - commonBuiltins.append( - "highp uint packSnorm2x16(vec2);" - " vec2 unpackSnorm2x16(highp uint);" - "highp uint packHalf2x16(vec2);" - "\n"); - } - - if (profile == EEsProfile && version >= 300) { - commonBuiltins.append( - "mediump vec2 unpackHalf2x16(highp uint);" - "\n"); - } else if (profile != EEsProfile && version >= 420) { - commonBuiltins.append( - " vec2 unpackHalf2x16(highp uint);" - "\n"); - } - - if ((profile == EEsProfile && version >= 310) || - (profile != EEsProfile && version >= 400)) { - commonBuiltins.append( - "highp uint packSnorm4x8(vec4);" - "highp uint packUnorm4x8(vec4);" - "\n"); - } - - if (profile == EEsProfile && version >= 310) { - commonBuiltins.append( - "mediump vec4 unpackSnorm4x8(highp uint);" - "mediump vec4 unpackUnorm4x8(highp uint);" - "\n"); - } else if (profile != EEsProfile && version >= 400) { - commonBuiltins.append( - "vec4 unpackSnorm4x8(highp uint);" - "vec4 unpackUnorm4x8(highp uint);" - "\n"); - } - - // - // Geometric Functions. - // - commonBuiltins.append( - "float length(float x);" - "float length(vec2 x);" - "float length(vec3 x);" - "float length(vec4 x);" - - "float distance(float p0, float p1);" - "float distance(vec2 p0, vec2 p1);" - "float distance(vec3 p0, vec3 p1);" - "float distance(vec4 p0, vec4 p1);" - - "float dot(float x, float y);" - "float dot(vec2 x, vec2 y);" - "float dot(vec3 x, vec3 y);" - "float dot(vec4 x, vec4 y);" - - "vec3 cross(vec3 x, vec3 y);" - "float normalize(float x);" - "vec2 normalize(vec2 x);" - "vec3 normalize(vec3 x);" - "vec4 normalize(vec4 x);" - - "float faceforward(float N, float I, float Nref);" - "vec2 faceforward(vec2 N, vec2 I, vec2 Nref);" - "vec3 faceforward(vec3 N, vec3 I, vec3 Nref);" - "vec4 faceforward(vec4 N, vec4 I, vec4 Nref);" - - "float reflect(float I, float N);" - "vec2 reflect(vec2 I, vec2 N);" - "vec3 reflect(vec3 I, vec3 N);" - "vec4 reflect(vec4 I, vec4 N);" - - "float refract(float I, float N, float eta);" - "vec2 refract(vec2 I, vec2 N, float eta);" - "vec3 refract(vec3 I, vec3 N, float eta);" - "vec4 refract(vec4 I, vec4 N, float eta);" - - "\n"); - - // - // Matrix Functions. - // - commonBuiltins.append( - "mat2 matrixCompMult(mat2 x, mat2 y);" - "mat3 matrixCompMult(mat3 x, mat3 y);" - "mat4 matrixCompMult(mat4 x, mat4 y);" - - "\n"); - - // 120 is correct for both ES and desktop - if (version >= 120) { - commonBuiltins.append( - "mat2 outerProduct(vec2 c, vec2 r);" - "mat3 outerProduct(vec3 c, vec3 r);" - "mat4 outerProduct(vec4 c, vec4 r);" - "mat2x3 outerProduct(vec3 c, vec2 r);" - "mat3x2 outerProduct(vec2 c, vec3 r);" - "mat2x4 outerProduct(vec4 c, vec2 r);" - "mat4x2 outerProduct(vec2 c, vec4 r);" - "mat3x4 outerProduct(vec4 c, vec3 r);" - "mat4x3 outerProduct(vec3 c, vec4 r);" - - "mat2 transpose(mat2 m);" - "mat3 transpose(mat3 m);" - "mat4 transpose(mat4 m);" - "mat2x3 transpose(mat3x2 m);" - "mat3x2 transpose(mat2x3 m);" - "mat2x4 transpose(mat4x2 m);" - "mat4x2 transpose(mat2x4 m);" - "mat3x4 transpose(mat4x3 m);" - "mat4x3 transpose(mat3x4 m);" - - "mat2x3 matrixCompMult(mat2x3, mat2x3);" - "mat2x4 matrixCompMult(mat2x4, mat2x4);" - "mat3x2 matrixCompMult(mat3x2, mat3x2);" - "mat3x4 matrixCompMult(mat3x4, mat3x4);" - "mat4x2 matrixCompMult(mat4x2, mat4x2);" - "mat4x3 matrixCompMult(mat4x3, mat4x3);" - - "\n"); - - // 150 is correct for both ES and desktop - if (version >= 150) { - commonBuiltins.append( - "float determinant(mat2 m);" - "float determinant(mat3 m);" - "float determinant(mat4 m);" - - "mat2 inverse(mat2 m);" - "mat3 inverse(mat3 m);" - "mat4 inverse(mat4 m);" - - "\n"); - } - } - - // - // Vector relational functions. - // - commonBuiltins.append( - "bvec2 lessThan(vec2 x, vec2 y);" - "bvec3 lessThan(vec3 x, vec3 y);" - "bvec4 lessThan(vec4 x, vec4 y);" - - "bvec2 lessThan(ivec2 x, ivec2 y);" - "bvec3 lessThan(ivec3 x, ivec3 y);" - "bvec4 lessThan(ivec4 x, ivec4 y);" - - "bvec2 lessThanEqual(vec2 x, vec2 y);" - "bvec3 lessThanEqual(vec3 x, vec3 y);" - "bvec4 lessThanEqual(vec4 x, vec4 y);" - - "bvec2 lessThanEqual(ivec2 x, ivec2 y);" - "bvec3 lessThanEqual(ivec3 x, ivec3 y);" - "bvec4 lessThanEqual(ivec4 x, ivec4 y);" - - "bvec2 greaterThan(vec2 x, vec2 y);" - "bvec3 greaterThan(vec3 x, vec3 y);" - "bvec4 greaterThan(vec4 x, vec4 y);" - - "bvec2 greaterThan(ivec2 x, ivec2 y);" - "bvec3 greaterThan(ivec3 x, ivec3 y);" - "bvec4 greaterThan(ivec4 x, ivec4 y);" - - "bvec2 greaterThanEqual(vec2 x, vec2 y);" - "bvec3 greaterThanEqual(vec3 x, vec3 y);" - "bvec4 greaterThanEqual(vec4 x, vec4 y);" - - "bvec2 greaterThanEqual(ivec2 x, ivec2 y);" - "bvec3 greaterThanEqual(ivec3 x, ivec3 y);" - "bvec4 greaterThanEqual(ivec4 x, ivec4 y);" - - "bvec2 equal(vec2 x, vec2 y);" - "bvec3 equal(vec3 x, vec3 y);" - "bvec4 equal(vec4 x, vec4 y);" - - "bvec2 equal(ivec2 x, ivec2 y);" - "bvec3 equal(ivec3 x, ivec3 y);" - "bvec4 equal(ivec4 x, ivec4 y);" - - "bvec2 equal(bvec2 x, bvec2 y);" - "bvec3 equal(bvec3 x, bvec3 y);" - "bvec4 equal(bvec4 x, bvec4 y);" - - "bvec2 notEqual(vec2 x, vec2 y);" - "bvec3 notEqual(vec3 x, vec3 y);" - "bvec4 notEqual(vec4 x, vec4 y);" - - "bvec2 notEqual(ivec2 x, ivec2 y);" - "bvec3 notEqual(ivec3 x, ivec3 y);" - "bvec4 notEqual(ivec4 x, ivec4 y);" - - "bvec2 notEqual(bvec2 x, bvec2 y);" - "bvec3 notEqual(bvec3 x, bvec3 y);" - "bvec4 notEqual(bvec4 x, bvec4 y);" - - "bool any(bvec2 x);" - "bool any(bvec3 x);" - "bool any(bvec4 x);" - - "bool all(bvec2 x);" - "bool all(bvec3 x);" - "bool all(bvec4 x);" - - "bvec2 not(bvec2 x);" - "bvec3 not(bvec3 x);" - "bvec4 not(bvec4 x);" - - "\n"); - - if (version >= 130) { - commonBuiltins.append( - "bvec2 lessThan(uvec2 x, uvec2 y);" - "bvec3 lessThan(uvec3 x, uvec3 y);" - "bvec4 lessThan(uvec4 x, uvec4 y);" - - "bvec2 lessThanEqual(uvec2 x, uvec2 y);" - "bvec3 lessThanEqual(uvec3 x, uvec3 y);" - "bvec4 lessThanEqual(uvec4 x, uvec4 y);" - - "bvec2 greaterThan(uvec2 x, uvec2 y);" - "bvec3 greaterThan(uvec3 x, uvec3 y);" - "bvec4 greaterThan(uvec4 x, uvec4 y);" - - "bvec2 greaterThanEqual(uvec2 x, uvec2 y);" - "bvec3 greaterThanEqual(uvec3 x, uvec3 y);" - "bvec4 greaterThanEqual(uvec4 x, uvec4 y);" - - "bvec2 equal(uvec2 x, uvec2 y);" - "bvec3 equal(uvec3 x, uvec3 y);" - "bvec4 equal(uvec4 x, uvec4 y);" - - "bvec2 notEqual(uvec2 x, uvec2 y);" - "bvec3 notEqual(uvec3 x, uvec3 y);" - "bvec4 notEqual(uvec4 x, uvec4 y);" - - "\n"); - } - - // - // Original-style texture functions existing in all stages. - // (Per-stage functions below.) - // - if ((profile == EEsProfile && version == 100) || - profile == ECompatibilityProfile || - (profile == ECoreProfile && version < 420) || - profile == ENoProfile) { - if (spvVersion.spv == 0) { - commonBuiltins.append( - "vec4 texture2D(sampler2D, vec2);" - - "vec4 texture2DProj(sampler2D, vec3);" - "vec4 texture2DProj(sampler2D, vec4);" - - "vec4 texture3D(sampler3D, vec3);" // OES_texture_3D, but caught by keyword check - "vec4 texture3DProj(sampler3D, vec4);" // OES_texture_3D, but caught by keyword check - - "vec4 textureCube(samplerCube, vec3);" - - "\n"); - } - } - - if ( profile == ECompatibilityProfile || - (profile == ECoreProfile && version < 420) || - profile == ENoProfile) { - if (spvVersion.spv == 0) { - commonBuiltins.append( - "vec4 texture1D(sampler1D, float);" - - "vec4 texture1DProj(sampler1D, vec2);" - "vec4 texture1DProj(sampler1D, vec4);" - - "vec4 shadow1D(sampler1DShadow, vec3);" - "vec4 shadow2D(sampler2DShadow, vec3);" - "vec4 shadow1DProj(sampler1DShadow, vec4);" - "vec4 shadow2DProj(sampler2DShadow, vec4);" - - "vec4 texture2DRect(sampler2DRect, vec2);" // GL_ARB_texture_rectangle, caught by keyword check - "vec4 texture2DRectProj(sampler2DRect, vec3);" // GL_ARB_texture_rectangle, caught by keyword check - "vec4 texture2DRectProj(sampler2DRect, vec4);" // GL_ARB_texture_rectangle, caught by keyword check - "vec4 shadow2DRect(sampler2DRectShadow, vec3);" // GL_ARB_texture_rectangle, caught by keyword check - "vec4 shadow2DRectProj(sampler2DRectShadow, vec4);" // GL_ARB_texture_rectangle, caught by keyword check - - "\n"); - } - } - - if (profile == EEsProfile) { - if (spvVersion.spv == 0) { - if (version < 300) { - commonBuiltins.append( - "vec4 texture2D(samplerExternalOES, vec2 coord);" // GL_OES_EGL_image_external - "vec4 texture2DProj(samplerExternalOES, vec3);" // GL_OES_EGL_image_external - "vec4 texture2DProj(samplerExternalOES, vec4);" // GL_OES_EGL_image_external - "\n"); - } else { - commonBuiltins.append( - "highp ivec2 textureSize(samplerExternalOES, int lod);" // GL_OES_EGL_image_external_essl3 - "vec4 texture(samplerExternalOES, vec2);" // GL_OES_EGL_image_external_essl3 - "vec4 texture(samplerExternalOES, vec2, float bias);" // GL_OES_EGL_image_external_essl3 - "vec4 textureProj(samplerExternalOES, vec3);" // GL_OES_EGL_image_external_essl3 - "vec4 textureProj(samplerExternalOES, vec3, float bias);" // GL_OES_EGL_image_external_essl3 - "vec4 textureProj(samplerExternalOES, vec4);" // GL_OES_EGL_image_external_essl3 - "vec4 textureProj(samplerExternalOES, vec4, float bias);" // GL_OES_EGL_image_external_essl3 - "vec4 texelFetch(samplerExternalOES, ivec2, int lod);" // GL_OES_EGL_image_external_essl3 - "\n"); - } - commonBuiltins.append( - "vec4 texture2DGradEXT(sampler2D, vec2, vec2, vec2);" // GL_EXT_shader_texture_lod - "vec4 texture2DProjGradEXT(sampler2D, vec3, vec2, vec2);" // GL_EXT_shader_texture_lod - "vec4 texture2DProjGradEXT(sampler2D, vec4, vec2, vec2);" // GL_EXT_shader_texture_lod - "vec4 textureCubeGradEXT(samplerCube, vec3, vec3, vec3);" // GL_EXT_shader_texture_lod - - "float shadow2DEXT(sampler2DShadow, vec3);" // GL_EXT_shadow_samplers - "float shadow2DProjEXT(sampler2DShadow, vec4);" // GL_EXT_shadow_samplers - - "\n"); - } - } - - // - // Noise functions. - // - if (spvVersion.spv == 0 && profile != EEsProfile) { - commonBuiltins.append( - "float noise1(float x);" - "float noise1(vec2 x);" - "float noise1(vec3 x);" - "float noise1(vec4 x);" - - "vec2 noise2(float x);" - "vec2 noise2(vec2 x);" - "vec2 noise2(vec3 x);" - "vec2 noise2(vec4 x);" - - "vec3 noise3(float x);" - "vec3 noise3(vec2 x);" - "vec3 noise3(vec3 x);" - "vec3 noise3(vec4 x);" - - "vec4 noise4(float x);" - "vec4 noise4(vec2 x);" - "vec4 noise4(vec3 x);" - "vec4 noise4(vec4 x);" - - "\n"); - } - - if (spvVersion.vulkan == 0) { - // - // Atomic counter functions. - // - if ((profile != EEsProfile && version >= 300) || - (profile == EEsProfile && version >= 310)) { - commonBuiltins.append( - "uint atomicCounterIncrement(atomic_uint);" - "uint atomicCounterDecrement(atomic_uint);" - "uint atomicCounter(atomic_uint);" - - "\n"); - } - if (profile != EEsProfile && version >= 460) { - commonBuiltins.append( - "uint atomicCounterAdd(atomic_uint, uint);" - "uint atomicCounterSubtract(atomic_uint, uint);" - "uint atomicCounterMin(atomic_uint, uint);" - "uint atomicCounterMax(atomic_uint, uint);" - "uint atomicCounterAnd(atomic_uint, uint);" - "uint atomicCounterOr(atomic_uint, uint);" - "uint atomicCounterXor(atomic_uint, uint);" - "uint atomicCounterExchange(atomic_uint, uint);" - "uint atomicCounterCompSwap(atomic_uint, uint, uint);" - - "\n"); - } - } - - // Bitfield - if ((profile == EEsProfile && version >= 310) || - (profile != EEsProfile && version >= 400)) { - commonBuiltins.append( - " int bitfieldExtract( int, int, int);" - "ivec2 bitfieldExtract(ivec2, int, int);" - "ivec3 bitfieldExtract(ivec3, int, int);" - "ivec4 bitfieldExtract(ivec4, int, int);" - - " uint bitfieldExtract( uint, int, int);" - "uvec2 bitfieldExtract(uvec2, int, int);" - "uvec3 bitfieldExtract(uvec3, int, int);" - "uvec4 bitfieldExtract(uvec4, int, int);" - - " int bitfieldInsert( int base, int, int, int);" - "ivec2 bitfieldInsert(ivec2 base, ivec2, int, int);" - "ivec3 bitfieldInsert(ivec3 base, ivec3, int, int);" - "ivec4 bitfieldInsert(ivec4 base, ivec4, int, int);" - - " uint bitfieldInsert( uint base, uint, int, int);" - "uvec2 bitfieldInsert(uvec2 base, uvec2, int, int);" - "uvec3 bitfieldInsert(uvec3 base, uvec3, int, int);" - "uvec4 bitfieldInsert(uvec4 base, uvec4, int, int);" - - "\n"); - } - - if (profile != EEsProfile && version >= 400) { - commonBuiltins.append( - " int findLSB( int);" - "ivec2 findLSB(ivec2);" - "ivec3 findLSB(ivec3);" - "ivec4 findLSB(ivec4);" - - " int findLSB( uint);" - "ivec2 findLSB(uvec2);" - "ivec3 findLSB(uvec3);" - "ivec4 findLSB(uvec4);" - - "\n"); - } else if (profile == EEsProfile && version >= 310) { - commonBuiltins.append( - "lowp int findLSB( int);" - "lowp ivec2 findLSB(ivec2);" - "lowp ivec3 findLSB(ivec3);" - "lowp ivec4 findLSB(ivec4);" - - "lowp int findLSB( uint);" - "lowp ivec2 findLSB(uvec2);" - "lowp ivec3 findLSB(uvec3);" - "lowp ivec4 findLSB(uvec4);" - - "\n"); - } - - if (profile != EEsProfile && version >= 400) { - commonBuiltins.append( - " int bitCount( int);" - "ivec2 bitCount(ivec2);" - "ivec3 bitCount(ivec3);" - "ivec4 bitCount(ivec4);" - - " int bitCount( uint);" - "ivec2 bitCount(uvec2);" - "ivec3 bitCount(uvec3);" - "ivec4 bitCount(uvec4);" - - " int findMSB(highp int);" - "ivec2 findMSB(highp ivec2);" - "ivec3 findMSB(highp ivec3);" - "ivec4 findMSB(highp ivec4);" - - " int findMSB(highp uint);" - "ivec2 findMSB(highp uvec2);" - "ivec3 findMSB(highp uvec3);" - "ivec4 findMSB(highp uvec4);" - - "\n"); - } - - if ((profile == EEsProfile && version >= 310) || - (profile != EEsProfile && version >= 400)) { - commonBuiltins.append( - " uint uaddCarry(highp uint, highp uint, out lowp uint carry);" - "uvec2 uaddCarry(highp uvec2, highp uvec2, out lowp uvec2 carry);" - "uvec3 uaddCarry(highp uvec3, highp uvec3, out lowp uvec3 carry);" - "uvec4 uaddCarry(highp uvec4, highp uvec4, out lowp uvec4 carry);" - - " uint usubBorrow(highp uint, highp uint, out lowp uint borrow);" - "uvec2 usubBorrow(highp uvec2, highp uvec2, out lowp uvec2 borrow);" - "uvec3 usubBorrow(highp uvec3, highp uvec3, out lowp uvec3 borrow);" - "uvec4 usubBorrow(highp uvec4, highp uvec4, out lowp uvec4 borrow);" - - "void umulExtended(highp uint, highp uint, out highp uint, out highp uint lsb);" - "void umulExtended(highp uvec2, highp uvec2, out highp uvec2, out highp uvec2 lsb);" - "void umulExtended(highp uvec3, highp uvec3, out highp uvec3, out highp uvec3 lsb);" - "void umulExtended(highp uvec4, highp uvec4, out highp uvec4, out highp uvec4 lsb);" - - "void imulExtended(highp int, highp int, out highp int, out highp int lsb);" - "void imulExtended(highp ivec2, highp ivec2, out highp ivec2, out highp ivec2 lsb);" - "void imulExtended(highp ivec3, highp ivec3, out highp ivec3, out highp ivec3 lsb);" - "void imulExtended(highp ivec4, highp ivec4, out highp ivec4, out highp ivec4 lsb);" - - " int bitfieldReverse(highp int);" - "ivec2 bitfieldReverse(highp ivec2);" - "ivec3 bitfieldReverse(highp ivec3);" - "ivec4 bitfieldReverse(highp ivec4);" - - " uint bitfieldReverse(highp uint);" - "uvec2 bitfieldReverse(highp uvec2);" - "uvec3 bitfieldReverse(highp uvec3);" - "uvec4 bitfieldReverse(highp uvec4);" - - "\n"); - } - - if (profile == EEsProfile && version >= 310) { - commonBuiltins.append( - "lowp int bitCount( int);" - "lowp ivec2 bitCount(ivec2);" - "lowp ivec3 bitCount(ivec3);" - "lowp ivec4 bitCount(ivec4);" - - "lowp int bitCount( uint);" - "lowp ivec2 bitCount(uvec2);" - "lowp ivec3 bitCount(uvec3);" - "lowp ivec4 bitCount(uvec4);" - - "lowp int findMSB(highp int);" - "lowp ivec2 findMSB(highp ivec2);" - "lowp ivec3 findMSB(highp ivec3);" - "lowp ivec4 findMSB(highp ivec4);" - - "lowp int findMSB(highp uint);" - "lowp ivec2 findMSB(highp uvec2);" - "lowp ivec3 findMSB(highp uvec3);" - "lowp ivec4 findMSB(highp uvec4);" - - "\n"); - } - - // GL_ARB_shader_ballot - if (profile != EEsProfile && version >= 450) { - commonBuiltins.append( - "uint64_t ballotARB(bool);" - - "float readInvocationARB(float, uint);" - "vec2 readInvocationARB(vec2, uint);" - "vec3 readInvocationARB(vec3, uint);" - "vec4 readInvocationARB(vec4, uint);" - - "int readInvocationARB(int, uint);" - "ivec2 readInvocationARB(ivec2, uint);" - "ivec3 readInvocationARB(ivec3, uint);" - "ivec4 readInvocationARB(ivec4, uint);" - - "uint readInvocationARB(uint, uint);" - "uvec2 readInvocationARB(uvec2, uint);" - "uvec3 readInvocationARB(uvec3, uint);" - "uvec4 readInvocationARB(uvec4, uint);" - - "float readFirstInvocationARB(float);" - "vec2 readFirstInvocationARB(vec2);" - "vec3 readFirstInvocationARB(vec3);" - "vec4 readFirstInvocationARB(vec4);" - - "int readFirstInvocationARB(int);" - "ivec2 readFirstInvocationARB(ivec2);" - "ivec3 readFirstInvocationARB(ivec3);" - "ivec4 readFirstInvocationARB(ivec4);" - - "uint readFirstInvocationARB(uint);" - "uvec2 readFirstInvocationARB(uvec2);" - "uvec3 readFirstInvocationARB(uvec3);" - "uvec4 readFirstInvocationARB(uvec4);" - - "\n"); - } - - // GL_ARB_shader_group_vote - if (profile != EEsProfile && version >= 430) { - commonBuiltins.append( - "bool anyInvocationARB(bool);" - "bool allInvocationsARB(bool);" - "bool allInvocationsEqualARB(bool);" - - "\n"); - } - - // GL_KHR_shader_subgroup - if (spvVersion.vulkan > 0) { - commonBuiltins.append( - "void subgroupBarrier();" - "void subgroupMemoryBarrier();" - "void subgroupMemoryBarrierBuffer();" - "void subgroupMemoryBarrierImage();" - "bool subgroupElect();" - - "bool subgroupAll(bool);\n" - "bool subgroupAny(bool);\n" - - "bool subgroupAllEqual(float);\n" - "bool subgroupAllEqual(vec2);\n" - "bool subgroupAllEqual(vec3);\n" - "bool subgroupAllEqual(vec4);\n" - "bool subgroupAllEqual(int);\n" - "bool subgroupAllEqual(ivec2);\n" - "bool subgroupAllEqual(ivec3);\n" - "bool subgroupAllEqual(ivec4);\n" - "bool subgroupAllEqual(uint);\n" - "bool subgroupAllEqual(uvec2);\n" - "bool subgroupAllEqual(uvec3);\n" - "bool subgroupAllEqual(uvec4);\n" - "bool subgroupAllEqual(bool);\n" - "bool subgroupAllEqual(bvec2);\n" - "bool subgroupAllEqual(bvec3);\n" - "bool subgroupAllEqual(bvec4);\n" - - "float subgroupBroadcast(float, uint);\n" - "vec2 subgroupBroadcast(vec2, uint);\n" - "vec3 subgroupBroadcast(vec3, uint);\n" - "vec4 subgroupBroadcast(vec4, uint);\n" - "int subgroupBroadcast(int, uint);\n" - "ivec2 subgroupBroadcast(ivec2, uint);\n" - "ivec3 subgroupBroadcast(ivec3, uint);\n" - "ivec4 subgroupBroadcast(ivec4, uint);\n" - "uint subgroupBroadcast(uint, uint);\n" - "uvec2 subgroupBroadcast(uvec2, uint);\n" - "uvec3 subgroupBroadcast(uvec3, uint);\n" - "uvec4 subgroupBroadcast(uvec4, uint);\n" - "bool subgroupBroadcast(bool, uint);\n" - "bvec2 subgroupBroadcast(bvec2, uint);\n" - "bvec3 subgroupBroadcast(bvec3, uint);\n" - "bvec4 subgroupBroadcast(bvec4, uint);\n" - - "float subgroupBroadcastFirst(float);\n" - "vec2 subgroupBroadcastFirst(vec2);\n" - "vec3 subgroupBroadcastFirst(vec3);\n" - "vec4 subgroupBroadcastFirst(vec4);\n" - "int subgroupBroadcastFirst(int);\n" - "ivec2 subgroupBroadcastFirst(ivec2);\n" - "ivec3 subgroupBroadcastFirst(ivec3);\n" - "ivec4 subgroupBroadcastFirst(ivec4);\n" - "uint subgroupBroadcastFirst(uint);\n" - "uvec2 subgroupBroadcastFirst(uvec2);\n" - "uvec3 subgroupBroadcastFirst(uvec3);\n" - "uvec4 subgroupBroadcastFirst(uvec4);\n" - "bool subgroupBroadcastFirst(bool);\n" - "bvec2 subgroupBroadcastFirst(bvec2);\n" - "bvec3 subgroupBroadcastFirst(bvec3);\n" - "bvec4 subgroupBroadcastFirst(bvec4);\n" - - "uvec4 subgroupBallot(bool);\n" - "bool subgroupInverseBallot(uvec4);\n" - "bool subgroupBallotBitExtract(uvec4, uint);\n" - "uint subgroupBallotBitCount(uvec4);\n" - "uint subgroupBallotInclusiveBitCount(uvec4);\n" - "uint subgroupBallotExclusiveBitCount(uvec4);\n" - "uint subgroupBallotFindLSB(uvec4);\n" - "uint subgroupBallotFindMSB(uvec4);\n" - - "float subgroupShuffle(float, uint);\n" - "vec2 subgroupShuffle(vec2, uint);\n" - "vec3 subgroupShuffle(vec3, uint);\n" - "vec4 subgroupShuffle(vec4, uint);\n" - "int subgroupShuffle(int, uint);\n" - "ivec2 subgroupShuffle(ivec2, uint);\n" - "ivec3 subgroupShuffle(ivec3, uint);\n" - "ivec4 subgroupShuffle(ivec4, uint);\n" - "uint subgroupShuffle(uint, uint);\n" - "uvec2 subgroupShuffle(uvec2, uint);\n" - "uvec3 subgroupShuffle(uvec3, uint);\n" - "uvec4 subgroupShuffle(uvec4, uint);\n" - "bool subgroupShuffle(bool, uint);\n" - "bvec2 subgroupShuffle(bvec2, uint);\n" - "bvec3 subgroupShuffle(bvec3, uint);\n" - "bvec4 subgroupShuffle(bvec4, uint);\n" - - "float subgroupShuffleXor(float, uint);\n" - "vec2 subgroupShuffleXor(vec2, uint);\n" - "vec3 subgroupShuffleXor(vec3, uint);\n" - "vec4 subgroupShuffleXor(vec4, uint);\n" - "int subgroupShuffleXor(int, uint);\n" - "ivec2 subgroupShuffleXor(ivec2, uint);\n" - "ivec3 subgroupShuffleXor(ivec3, uint);\n" - "ivec4 subgroupShuffleXor(ivec4, uint);\n" - "uint subgroupShuffleXor(uint, uint);\n" - "uvec2 subgroupShuffleXor(uvec2, uint);\n" - "uvec3 subgroupShuffleXor(uvec3, uint);\n" - "uvec4 subgroupShuffleXor(uvec4, uint);\n" - "bool subgroupShuffleXor(bool, uint);\n" - "bvec2 subgroupShuffleXor(bvec2, uint);\n" - "bvec3 subgroupShuffleXor(bvec3, uint);\n" - "bvec4 subgroupShuffleXor(bvec4, uint);\n" - - "float subgroupShuffleUp(float, uint delta);\n" - "vec2 subgroupShuffleUp(vec2, uint delta);\n" - "vec3 subgroupShuffleUp(vec3, uint delta);\n" - "vec4 subgroupShuffleUp(vec4, uint delta);\n" - "int subgroupShuffleUp(int, uint delta);\n" - "ivec2 subgroupShuffleUp(ivec2, uint delta);\n" - "ivec3 subgroupShuffleUp(ivec3, uint delta);\n" - "ivec4 subgroupShuffleUp(ivec4, uint delta);\n" - "uint subgroupShuffleUp(uint, uint delta);\n" - "uvec2 subgroupShuffleUp(uvec2, uint delta);\n" - "uvec3 subgroupShuffleUp(uvec3, uint delta);\n" - "uvec4 subgroupShuffleUp(uvec4, uint delta);\n" - "bool subgroupShuffleUp(bool, uint delta);\n" - "bvec2 subgroupShuffleUp(bvec2, uint delta);\n" - "bvec3 subgroupShuffleUp(bvec3, uint delta);\n" - "bvec4 subgroupShuffleUp(bvec4, uint delta);\n" - - "float subgroupShuffleDown(float, uint delta);\n" - "vec2 subgroupShuffleDown(vec2, uint delta);\n" - "vec3 subgroupShuffleDown(vec3, uint delta);\n" - "vec4 subgroupShuffleDown(vec4, uint delta);\n" - "int subgroupShuffleDown(int, uint delta);\n" - "ivec2 subgroupShuffleDown(ivec2, uint delta);\n" - "ivec3 subgroupShuffleDown(ivec3, uint delta);\n" - "ivec4 subgroupShuffleDown(ivec4, uint delta);\n" - "uint subgroupShuffleDown(uint, uint delta);\n" - "uvec2 subgroupShuffleDown(uvec2, uint delta);\n" - "uvec3 subgroupShuffleDown(uvec3, uint delta);\n" - "uvec4 subgroupShuffleDown(uvec4, uint delta);\n" - "bool subgroupShuffleDown(bool, uint delta);\n" - "bvec2 subgroupShuffleDown(bvec2, uint delta);\n" - "bvec3 subgroupShuffleDown(bvec3, uint delta);\n" - "bvec4 subgroupShuffleDown(bvec4, uint delta);\n" - - "float subgroupAdd(float);\n" - "vec2 subgroupAdd(vec2);\n" - "vec3 subgroupAdd(vec3);\n" - "vec4 subgroupAdd(vec4);\n" - "int subgroupAdd(int);\n" - "ivec2 subgroupAdd(ivec2);\n" - "ivec3 subgroupAdd(ivec3);\n" - "ivec4 subgroupAdd(ivec4);\n" - "uint subgroupAdd(uint);\n" - "uvec2 subgroupAdd(uvec2);\n" - "uvec3 subgroupAdd(uvec3);\n" - "uvec4 subgroupAdd(uvec4);\n" - - "float subgroupMul(float);\n" - "vec2 subgroupMul(vec2);\n" - "vec3 subgroupMul(vec3);\n" - "vec4 subgroupMul(vec4);\n" - "int subgroupMul(int);\n" - "ivec2 subgroupMul(ivec2);\n" - "ivec3 subgroupMul(ivec3);\n" - "ivec4 subgroupMul(ivec4);\n" - "uint subgroupMul(uint);\n" - "uvec2 subgroupMul(uvec2);\n" - "uvec3 subgroupMul(uvec3);\n" - "uvec4 subgroupMul(uvec4);\n" - - "float subgroupMin(float);\n" - "vec2 subgroupMin(vec2);\n" - "vec3 subgroupMin(vec3);\n" - "vec4 subgroupMin(vec4);\n" - "int subgroupMin(int);\n" - "ivec2 subgroupMin(ivec2);\n" - "ivec3 subgroupMin(ivec3);\n" - "ivec4 subgroupMin(ivec4);\n" - "uint subgroupMin(uint);\n" - "uvec2 subgroupMin(uvec2);\n" - "uvec3 subgroupMin(uvec3);\n" - "uvec4 subgroupMin(uvec4);\n" - - "float subgroupMax(float);\n" - "vec2 subgroupMax(vec2);\n" - "vec3 subgroupMax(vec3);\n" - "vec4 subgroupMax(vec4);\n" - "int subgroupMax(int);\n" - "ivec2 subgroupMax(ivec2);\n" - "ivec3 subgroupMax(ivec3);\n" - "ivec4 subgroupMax(ivec4);\n" - "uint subgroupMax(uint);\n" - "uvec2 subgroupMax(uvec2);\n" - "uvec3 subgroupMax(uvec3);\n" - "uvec4 subgroupMax(uvec4);\n" - - "int subgroupAnd(int);\n" - "ivec2 subgroupAnd(ivec2);\n" - "ivec3 subgroupAnd(ivec3);\n" - "ivec4 subgroupAnd(ivec4);\n" - "uint subgroupAnd(uint);\n" - "uvec2 subgroupAnd(uvec2);\n" - "uvec3 subgroupAnd(uvec3);\n" - "uvec4 subgroupAnd(uvec4);\n" - "bool subgroupAnd(bool);\n" - "bvec2 subgroupAnd(bvec2);\n" - "bvec3 subgroupAnd(bvec3);\n" - "bvec4 subgroupAnd(bvec4);\n" - - "int subgroupOr(int);\n" - "ivec2 subgroupOr(ivec2);\n" - "ivec3 subgroupOr(ivec3);\n" - "ivec4 subgroupOr(ivec4);\n" - "uint subgroupOr(uint);\n" - "uvec2 subgroupOr(uvec2);\n" - "uvec3 subgroupOr(uvec3);\n" - "uvec4 subgroupOr(uvec4);\n" - "bool subgroupOr(bool);\n" - "bvec2 subgroupOr(bvec2);\n" - "bvec3 subgroupOr(bvec3);\n" - "bvec4 subgroupOr(bvec4);\n" - - "int subgroupXor(int);\n" - "ivec2 subgroupXor(ivec2);\n" - "ivec3 subgroupXor(ivec3);\n" - "ivec4 subgroupXor(ivec4);\n" - "uint subgroupXor(uint);\n" - "uvec2 subgroupXor(uvec2);\n" - "uvec3 subgroupXor(uvec3);\n" - "uvec4 subgroupXor(uvec4);\n" - "bool subgroupXor(bool);\n" - "bvec2 subgroupXor(bvec2);\n" - "bvec3 subgroupXor(bvec3);\n" - "bvec4 subgroupXor(bvec4);\n" - - "float subgroupInclusiveAdd(float);\n" - "vec2 subgroupInclusiveAdd(vec2);\n" - "vec3 subgroupInclusiveAdd(vec3);\n" - "vec4 subgroupInclusiveAdd(vec4);\n" - "int subgroupInclusiveAdd(int);\n" - "ivec2 subgroupInclusiveAdd(ivec2);\n" - "ivec3 subgroupInclusiveAdd(ivec3);\n" - "ivec4 subgroupInclusiveAdd(ivec4);\n" - "uint subgroupInclusiveAdd(uint);\n" - "uvec2 subgroupInclusiveAdd(uvec2);\n" - "uvec3 subgroupInclusiveAdd(uvec3);\n" - "uvec4 subgroupInclusiveAdd(uvec4);\n" - - "float subgroupInclusiveMul(float);\n" - "vec2 subgroupInclusiveMul(vec2);\n" - "vec3 subgroupInclusiveMul(vec3);\n" - "vec4 subgroupInclusiveMul(vec4);\n" - "int subgroupInclusiveMul(int);\n" - "ivec2 subgroupInclusiveMul(ivec2);\n" - "ivec3 subgroupInclusiveMul(ivec3);\n" - "ivec4 subgroupInclusiveMul(ivec4);\n" - "uint subgroupInclusiveMul(uint);\n" - "uvec2 subgroupInclusiveMul(uvec2);\n" - "uvec3 subgroupInclusiveMul(uvec3);\n" - "uvec4 subgroupInclusiveMul(uvec4);\n" - - "float subgroupInclusiveMin(float);\n" - "vec2 subgroupInclusiveMin(vec2);\n" - "vec3 subgroupInclusiveMin(vec3);\n" - "vec4 subgroupInclusiveMin(vec4);\n" - "int subgroupInclusiveMin(int);\n" - "ivec2 subgroupInclusiveMin(ivec2);\n" - "ivec3 subgroupInclusiveMin(ivec3);\n" - "ivec4 subgroupInclusiveMin(ivec4);\n" - "uint subgroupInclusiveMin(uint);\n" - "uvec2 subgroupInclusiveMin(uvec2);\n" - "uvec3 subgroupInclusiveMin(uvec3);\n" - "uvec4 subgroupInclusiveMin(uvec4);\n" - - "float subgroupInclusiveMax(float);\n" - "vec2 subgroupInclusiveMax(vec2);\n" - "vec3 subgroupInclusiveMax(vec3);\n" - "vec4 subgroupInclusiveMax(vec4);\n" - "int subgroupInclusiveMax(int);\n" - "ivec2 subgroupInclusiveMax(ivec2);\n" - "ivec3 subgroupInclusiveMax(ivec3);\n" - "ivec4 subgroupInclusiveMax(ivec4);\n" - "uint subgroupInclusiveMax(uint);\n" - "uvec2 subgroupInclusiveMax(uvec2);\n" - "uvec3 subgroupInclusiveMax(uvec3);\n" - "uvec4 subgroupInclusiveMax(uvec4);\n" - - "int subgroupInclusiveAnd(int);\n" - "ivec2 subgroupInclusiveAnd(ivec2);\n" - "ivec3 subgroupInclusiveAnd(ivec3);\n" - "ivec4 subgroupInclusiveAnd(ivec4);\n" - "uint subgroupInclusiveAnd(uint);\n" - "uvec2 subgroupInclusiveAnd(uvec2);\n" - "uvec3 subgroupInclusiveAnd(uvec3);\n" - "uvec4 subgroupInclusiveAnd(uvec4);\n" - "bool subgroupInclusiveAnd(bool);\n" - "bvec2 subgroupInclusiveAnd(bvec2);\n" - "bvec3 subgroupInclusiveAnd(bvec3);\n" - "bvec4 subgroupInclusiveAnd(bvec4);\n" - - "int subgroupInclusiveOr(int);\n" - "ivec2 subgroupInclusiveOr(ivec2);\n" - "ivec3 subgroupInclusiveOr(ivec3);\n" - "ivec4 subgroupInclusiveOr(ivec4);\n" - "uint subgroupInclusiveOr(uint);\n" - "uvec2 subgroupInclusiveOr(uvec2);\n" - "uvec3 subgroupInclusiveOr(uvec3);\n" - "uvec4 subgroupInclusiveOr(uvec4);\n" - "bool subgroupInclusiveOr(bool);\n" - "bvec2 subgroupInclusiveOr(bvec2);\n" - "bvec3 subgroupInclusiveOr(bvec3);\n" - "bvec4 subgroupInclusiveOr(bvec4);\n" - - "int subgroupInclusiveXor(int);\n" - "ivec2 subgroupInclusiveXor(ivec2);\n" - "ivec3 subgroupInclusiveXor(ivec3);\n" - "ivec4 subgroupInclusiveXor(ivec4);\n" - "uint subgroupInclusiveXor(uint);\n" - "uvec2 subgroupInclusiveXor(uvec2);\n" - "uvec3 subgroupInclusiveXor(uvec3);\n" - "uvec4 subgroupInclusiveXor(uvec4);\n" - "bool subgroupInclusiveXor(bool);\n" - "bvec2 subgroupInclusiveXor(bvec2);\n" - "bvec3 subgroupInclusiveXor(bvec3);\n" - "bvec4 subgroupInclusiveXor(bvec4);\n" - - "float subgroupExclusiveAdd(float);\n" - "vec2 subgroupExclusiveAdd(vec2);\n" - "vec3 subgroupExclusiveAdd(vec3);\n" - "vec4 subgroupExclusiveAdd(vec4);\n" - "int subgroupExclusiveAdd(int);\n" - "ivec2 subgroupExclusiveAdd(ivec2);\n" - "ivec3 subgroupExclusiveAdd(ivec3);\n" - "ivec4 subgroupExclusiveAdd(ivec4);\n" - "uint subgroupExclusiveAdd(uint);\n" - "uvec2 subgroupExclusiveAdd(uvec2);\n" - "uvec3 subgroupExclusiveAdd(uvec3);\n" - "uvec4 subgroupExclusiveAdd(uvec4);\n" - - "float subgroupExclusiveMul(float);\n" - "vec2 subgroupExclusiveMul(vec2);\n" - "vec3 subgroupExclusiveMul(vec3);\n" - "vec4 subgroupExclusiveMul(vec4);\n" - "int subgroupExclusiveMul(int);\n" - "ivec2 subgroupExclusiveMul(ivec2);\n" - "ivec3 subgroupExclusiveMul(ivec3);\n" - "ivec4 subgroupExclusiveMul(ivec4);\n" - "uint subgroupExclusiveMul(uint);\n" - "uvec2 subgroupExclusiveMul(uvec2);\n" - "uvec3 subgroupExclusiveMul(uvec3);\n" - "uvec4 subgroupExclusiveMul(uvec4);\n" - - "float subgroupExclusiveMin(float);\n" - "vec2 subgroupExclusiveMin(vec2);\n" - "vec3 subgroupExclusiveMin(vec3);\n" - "vec4 subgroupExclusiveMin(vec4);\n" - "int subgroupExclusiveMin(int);\n" - "ivec2 subgroupExclusiveMin(ivec2);\n" - "ivec3 subgroupExclusiveMin(ivec3);\n" - "ivec4 subgroupExclusiveMin(ivec4);\n" - "uint subgroupExclusiveMin(uint);\n" - "uvec2 subgroupExclusiveMin(uvec2);\n" - "uvec3 subgroupExclusiveMin(uvec3);\n" - "uvec4 subgroupExclusiveMin(uvec4);\n" - - "float subgroupExclusiveMax(float);\n" - "vec2 subgroupExclusiveMax(vec2);\n" - "vec3 subgroupExclusiveMax(vec3);\n" - "vec4 subgroupExclusiveMax(vec4);\n" - "int subgroupExclusiveMax(int);\n" - "ivec2 subgroupExclusiveMax(ivec2);\n" - "ivec3 subgroupExclusiveMax(ivec3);\n" - "ivec4 subgroupExclusiveMax(ivec4);\n" - "uint subgroupExclusiveMax(uint);\n" - "uvec2 subgroupExclusiveMax(uvec2);\n" - "uvec3 subgroupExclusiveMax(uvec3);\n" - "uvec4 subgroupExclusiveMax(uvec4);\n" - - "int subgroupExclusiveAnd(int);\n" - "ivec2 subgroupExclusiveAnd(ivec2);\n" - "ivec3 subgroupExclusiveAnd(ivec3);\n" - "ivec4 subgroupExclusiveAnd(ivec4);\n" - "uint subgroupExclusiveAnd(uint);\n" - "uvec2 subgroupExclusiveAnd(uvec2);\n" - "uvec3 subgroupExclusiveAnd(uvec3);\n" - "uvec4 subgroupExclusiveAnd(uvec4);\n" - "bool subgroupExclusiveAnd(bool);\n" - "bvec2 subgroupExclusiveAnd(bvec2);\n" - "bvec3 subgroupExclusiveAnd(bvec3);\n" - "bvec4 subgroupExclusiveAnd(bvec4);\n" - - "int subgroupExclusiveOr(int);\n" - "ivec2 subgroupExclusiveOr(ivec2);\n" - "ivec3 subgroupExclusiveOr(ivec3);\n" - "ivec4 subgroupExclusiveOr(ivec4);\n" - "uint subgroupExclusiveOr(uint);\n" - "uvec2 subgroupExclusiveOr(uvec2);\n" - "uvec3 subgroupExclusiveOr(uvec3);\n" - "uvec4 subgroupExclusiveOr(uvec4);\n" - "bool subgroupExclusiveOr(bool);\n" - "bvec2 subgroupExclusiveOr(bvec2);\n" - "bvec3 subgroupExclusiveOr(bvec3);\n" - "bvec4 subgroupExclusiveOr(bvec4);\n" - - "int subgroupExclusiveXor(int);\n" - "ivec2 subgroupExclusiveXor(ivec2);\n" - "ivec3 subgroupExclusiveXor(ivec3);\n" - "ivec4 subgroupExclusiveXor(ivec4);\n" - "uint subgroupExclusiveXor(uint);\n" - "uvec2 subgroupExclusiveXor(uvec2);\n" - "uvec3 subgroupExclusiveXor(uvec3);\n" - "uvec4 subgroupExclusiveXor(uvec4);\n" - "bool subgroupExclusiveXor(bool);\n" - "bvec2 subgroupExclusiveXor(bvec2);\n" - "bvec3 subgroupExclusiveXor(bvec3);\n" - "bvec4 subgroupExclusiveXor(bvec4);\n" - - "float subgroupClusteredAdd(float, uint);\n" - "vec2 subgroupClusteredAdd(vec2, uint);\n" - "vec3 subgroupClusteredAdd(vec3, uint);\n" - "vec4 subgroupClusteredAdd(vec4, uint);\n" - "int subgroupClusteredAdd(int, uint);\n" - "ivec2 subgroupClusteredAdd(ivec2, uint);\n" - "ivec3 subgroupClusteredAdd(ivec3, uint);\n" - "ivec4 subgroupClusteredAdd(ivec4, uint);\n" - "uint subgroupClusteredAdd(uint, uint);\n" - "uvec2 subgroupClusteredAdd(uvec2, uint);\n" - "uvec3 subgroupClusteredAdd(uvec3, uint);\n" - "uvec4 subgroupClusteredAdd(uvec4, uint);\n" - - "float subgroupClusteredMul(float, uint);\n" - "vec2 subgroupClusteredMul(vec2, uint);\n" - "vec3 subgroupClusteredMul(vec3, uint);\n" - "vec4 subgroupClusteredMul(vec4, uint);\n" - "int subgroupClusteredMul(int, uint);\n" - "ivec2 subgroupClusteredMul(ivec2, uint);\n" - "ivec3 subgroupClusteredMul(ivec3, uint);\n" - "ivec4 subgroupClusteredMul(ivec4, uint);\n" - "uint subgroupClusteredMul(uint, uint);\n" - "uvec2 subgroupClusteredMul(uvec2, uint);\n" - "uvec3 subgroupClusteredMul(uvec3, uint);\n" - "uvec4 subgroupClusteredMul(uvec4, uint);\n" - - "float subgroupClusteredMin(float, uint);\n" - "vec2 subgroupClusteredMin(vec2, uint);\n" - "vec3 subgroupClusteredMin(vec3, uint);\n" - "vec4 subgroupClusteredMin(vec4, uint);\n" - "int subgroupClusteredMin(int, uint);\n" - "ivec2 subgroupClusteredMin(ivec2, uint);\n" - "ivec3 subgroupClusteredMin(ivec3, uint);\n" - "ivec4 subgroupClusteredMin(ivec4, uint);\n" - "uint subgroupClusteredMin(uint, uint);\n" - "uvec2 subgroupClusteredMin(uvec2, uint);\n" - "uvec3 subgroupClusteredMin(uvec3, uint);\n" - "uvec4 subgroupClusteredMin(uvec4, uint);\n" - - "float subgroupClusteredMax(float, uint);\n" - "vec2 subgroupClusteredMax(vec2, uint);\n" - "vec3 subgroupClusteredMax(vec3, uint);\n" - "vec4 subgroupClusteredMax(vec4, uint);\n" - "int subgroupClusteredMax(int, uint);\n" - "ivec2 subgroupClusteredMax(ivec2, uint);\n" - "ivec3 subgroupClusteredMax(ivec3, uint);\n" - "ivec4 subgroupClusteredMax(ivec4, uint);\n" - "uint subgroupClusteredMax(uint, uint);\n" - "uvec2 subgroupClusteredMax(uvec2, uint);\n" - "uvec3 subgroupClusteredMax(uvec3, uint);\n" - "uvec4 subgroupClusteredMax(uvec4, uint);\n" - - "int subgroupClusteredAnd(int, uint);\n" - "ivec2 subgroupClusteredAnd(ivec2, uint);\n" - "ivec3 subgroupClusteredAnd(ivec3, uint);\n" - "ivec4 subgroupClusteredAnd(ivec4, uint);\n" - "uint subgroupClusteredAnd(uint, uint);\n" - "uvec2 subgroupClusteredAnd(uvec2, uint);\n" - "uvec3 subgroupClusteredAnd(uvec3, uint);\n" - "uvec4 subgroupClusteredAnd(uvec4, uint);\n" - "bool subgroupClusteredAnd(bool, uint);\n" - "bvec2 subgroupClusteredAnd(bvec2, uint);\n" - "bvec3 subgroupClusteredAnd(bvec3, uint);\n" - "bvec4 subgroupClusteredAnd(bvec4, uint);\n" - - "int subgroupClusteredOr(int, uint);\n" - "ivec2 subgroupClusteredOr(ivec2, uint);\n" - "ivec3 subgroupClusteredOr(ivec3, uint);\n" - "ivec4 subgroupClusteredOr(ivec4, uint);\n" - "uint subgroupClusteredOr(uint, uint);\n" - "uvec2 subgroupClusteredOr(uvec2, uint);\n" - "uvec3 subgroupClusteredOr(uvec3, uint);\n" - "uvec4 subgroupClusteredOr(uvec4, uint);\n" - "bool subgroupClusteredOr(bool, uint);\n" - "bvec2 subgroupClusteredOr(bvec2, uint);\n" - "bvec3 subgroupClusteredOr(bvec3, uint);\n" - "bvec4 subgroupClusteredOr(bvec4, uint);\n" - - "int subgroupClusteredXor(int, uint);\n" - "ivec2 subgroupClusteredXor(ivec2, uint);\n" - "ivec3 subgroupClusteredXor(ivec3, uint);\n" - "ivec4 subgroupClusteredXor(ivec4, uint);\n" - "uint subgroupClusteredXor(uint, uint);\n" - "uvec2 subgroupClusteredXor(uvec2, uint);\n" - "uvec3 subgroupClusteredXor(uvec3, uint);\n" - "uvec4 subgroupClusteredXor(uvec4, uint);\n" - "bool subgroupClusteredXor(bool, uint);\n" - "bvec2 subgroupClusteredXor(bvec2, uint);\n" - "bvec3 subgroupClusteredXor(bvec3, uint);\n" - "bvec4 subgroupClusteredXor(bvec4, uint);\n" - - "float subgroupQuadBroadcast(float, uint);\n" - "vec2 subgroupQuadBroadcast(vec2, uint);\n" - "vec3 subgroupQuadBroadcast(vec3, uint);\n" - "vec4 subgroupQuadBroadcast(vec4, uint);\n" - "int subgroupQuadBroadcast(int, uint);\n" - "ivec2 subgroupQuadBroadcast(ivec2, uint);\n" - "ivec3 subgroupQuadBroadcast(ivec3, uint);\n" - "ivec4 subgroupQuadBroadcast(ivec4, uint);\n" - "uint subgroupQuadBroadcast(uint, uint);\n" - "uvec2 subgroupQuadBroadcast(uvec2, uint);\n" - "uvec3 subgroupQuadBroadcast(uvec3, uint);\n" - "uvec4 subgroupQuadBroadcast(uvec4, uint);\n" - "bool subgroupQuadBroadcast(bool, uint);\n" - "bvec2 subgroupQuadBroadcast(bvec2, uint);\n" - "bvec3 subgroupQuadBroadcast(bvec3, uint);\n" - "bvec4 subgroupQuadBroadcast(bvec4, uint);\n" - - "float subgroupQuadSwapHorizontal(float);\n" - "vec2 subgroupQuadSwapHorizontal(vec2);\n" - "vec3 subgroupQuadSwapHorizontal(vec3);\n" - "vec4 subgroupQuadSwapHorizontal(vec4);\n" - "int subgroupQuadSwapHorizontal(int);\n" - "ivec2 subgroupQuadSwapHorizontal(ivec2);\n" - "ivec3 subgroupQuadSwapHorizontal(ivec3);\n" - "ivec4 subgroupQuadSwapHorizontal(ivec4);\n" - "uint subgroupQuadSwapHorizontal(uint);\n" - "uvec2 subgroupQuadSwapHorizontal(uvec2);\n" - "uvec3 subgroupQuadSwapHorizontal(uvec3);\n" - "uvec4 subgroupQuadSwapHorizontal(uvec4);\n" - "bool subgroupQuadSwapHorizontal(bool);\n" - "bvec2 subgroupQuadSwapHorizontal(bvec2);\n" - "bvec3 subgroupQuadSwapHorizontal(bvec3);\n" - "bvec4 subgroupQuadSwapHorizontal(bvec4);\n" - - "float subgroupQuadSwapVertical(float);\n" - "vec2 subgroupQuadSwapVertical(vec2);\n" - "vec3 subgroupQuadSwapVertical(vec3);\n" - "vec4 subgroupQuadSwapVertical(vec4);\n" - "int subgroupQuadSwapVertical(int);\n" - "ivec2 subgroupQuadSwapVertical(ivec2);\n" - "ivec3 subgroupQuadSwapVertical(ivec3);\n" - "ivec4 subgroupQuadSwapVertical(ivec4);\n" - "uint subgroupQuadSwapVertical(uint);\n" - "uvec2 subgroupQuadSwapVertical(uvec2);\n" - "uvec3 subgroupQuadSwapVertical(uvec3);\n" - "uvec4 subgroupQuadSwapVertical(uvec4);\n" - "bool subgroupQuadSwapVertical(bool);\n" - "bvec2 subgroupQuadSwapVertical(bvec2);\n" - "bvec3 subgroupQuadSwapVertical(bvec3);\n" - "bvec4 subgroupQuadSwapVertical(bvec4);\n" - - "float subgroupQuadSwapDiagonal(float);\n" - "vec2 subgroupQuadSwapDiagonal(vec2);\n" - "vec3 subgroupQuadSwapDiagonal(vec3);\n" - "vec4 subgroupQuadSwapDiagonal(vec4);\n" - "int subgroupQuadSwapDiagonal(int);\n" - "ivec2 subgroupQuadSwapDiagonal(ivec2);\n" - "ivec3 subgroupQuadSwapDiagonal(ivec3);\n" - "ivec4 subgroupQuadSwapDiagonal(ivec4);\n" - "uint subgroupQuadSwapDiagonal(uint);\n" - "uvec2 subgroupQuadSwapDiagonal(uvec2);\n" - "uvec3 subgroupQuadSwapDiagonal(uvec3);\n" - "uvec4 subgroupQuadSwapDiagonal(uvec4);\n" - "bool subgroupQuadSwapDiagonal(bool);\n" - "bvec2 subgroupQuadSwapDiagonal(bvec2);\n" - "bvec3 subgroupQuadSwapDiagonal(bvec3);\n" - "bvec4 subgroupQuadSwapDiagonal(bvec4);\n" - -#ifdef NV_EXTENSIONS - "uvec4 subgroupPartitionNV(float);\n" - "uvec4 subgroupPartitionNV(vec2);\n" - "uvec4 subgroupPartitionNV(vec3);\n" - "uvec4 subgroupPartitionNV(vec4);\n" - "uvec4 subgroupPartitionNV(int);\n" - "uvec4 subgroupPartitionNV(ivec2);\n" - "uvec4 subgroupPartitionNV(ivec3);\n" - "uvec4 subgroupPartitionNV(ivec4);\n" - "uvec4 subgroupPartitionNV(uint);\n" - "uvec4 subgroupPartitionNV(uvec2);\n" - "uvec4 subgroupPartitionNV(uvec3);\n" - "uvec4 subgroupPartitionNV(uvec4);\n" - "uvec4 subgroupPartitionNV(bool);\n" - "uvec4 subgroupPartitionNV(bvec2);\n" - "uvec4 subgroupPartitionNV(bvec3);\n" - "uvec4 subgroupPartitionNV(bvec4);\n" - - "float subgroupPartitionedAddNV(float, uvec4 ballot);\n" - "vec2 subgroupPartitionedAddNV(vec2, uvec4 ballot);\n" - "vec3 subgroupPartitionedAddNV(vec3, uvec4 ballot);\n" - "vec4 subgroupPartitionedAddNV(vec4, uvec4 ballot);\n" - "int subgroupPartitionedAddNV(int, uvec4 ballot);\n" - "ivec2 subgroupPartitionedAddNV(ivec2, uvec4 ballot);\n" - "ivec3 subgroupPartitionedAddNV(ivec3, uvec4 ballot);\n" - "ivec4 subgroupPartitionedAddNV(ivec4, uvec4 ballot);\n" - "uint subgroupPartitionedAddNV(uint, uvec4 ballot);\n" - "uvec2 subgroupPartitionedAddNV(uvec2, uvec4 ballot);\n" - "uvec3 subgroupPartitionedAddNV(uvec3, uvec4 ballot);\n" - "uvec4 subgroupPartitionedAddNV(uvec4, uvec4 ballot);\n" - - "float subgroupPartitionedMulNV(float, uvec4 ballot);\n" - "vec2 subgroupPartitionedMulNV(vec2, uvec4 ballot);\n" - "vec3 subgroupPartitionedMulNV(vec3, uvec4 ballot);\n" - "vec4 subgroupPartitionedMulNV(vec4, uvec4 ballot);\n" - "int subgroupPartitionedMulNV(int, uvec4 ballot);\n" - "ivec2 subgroupPartitionedMulNV(ivec2, uvec4 ballot);\n" - "ivec3 subgroupPartitionedMulNV(ivec3, uvec4 ballot);\n" - "ivec4 subgroupPartitionedMulNV(ivec4, uvec4 ballot);\n" - "uint subgroupPartitionedMulNV(uint, uvec4 ballot);\n" - "uvec2 subgroupPartitionedMulNV(uvec2, uvec4 ballot);\n" - "uvec3 subgroupPartitionedMulNV(uvec3, uvec4 ballot);\n" - "uvec4 subgroupPartitionedMulNV(uvec4, uvec4 ballot);\n" - - "float subgroupPartitionedMinNV(float, uvec4 ballot);\n" - "vec2 subgroupPartitionedMinNV(vec2, uvec4 ballot);\n" - "vec3 subgroupPartitionedMinNV(vec3, uvec4 ballot);\n" - "vec4 subgroupPartitionedMinNV(vec4, uvec4 ballot);\n" - "int subgroupPartitionedMinNV(int, uvec4 ballot);\n" - "ivec2 subgroupPartitionedMinNV(ivec2, uvec4 ballot);\n" - "ivec3 subgroupPartitionedMinNV(ivec3, uvec4 ballot);\n" - "ivec4 subgroupPartitionedMinNV(ivec4, uvec4 ballot);\n" - "uint subgroupPartitionedMinNV(uint, uvec4 ballot);\n" - "uvec2 subgroupPartitionedMinNV(uvec2, uvec4 ballot);\n" - "uvec3 subgroupPartitionedMinNV(uvec3, uvec4 ballot);\n" - "uvec4 subgroupPartitionedMinNV(uvec4, uvec4 ballot);\n" - - "float subgroupPartitionedMaxNV(float, uvec4 ballot);\n" - "vec2 subgroupPartitionedMaxNV(vec2, uvec4 ballot);\n" - "vec3 subgroupPartitionedMaxNV(vec3, uvec4 ballot);\n" - "vec4 subgroupPartitionedMaxNV(vec4, uvec4 ballot);\n" - "int subgroupPartitionedMaxNV(int, uvec4 ballot);\n" - "ivec2 subgroupPartitionedMaxNV(ivec2, uvec4 ballot);\n" - "ivec3 subgroupPartitionedMaxNV(ivec3, uvec4 ballot);\n" - "ivec4 subgroupPartitionedMaxNV(ivec4, uvec4 ballot);\n" - "uint subgroupPartitionedMaxNV(uint, uvec4 ballot);\n" - "uvec2 subgroupPartitionedMaxNV(uvec2, uvec4 ballot);\n" - "uvec3 subgroupPartitionedMaxNV(uvec3, uvec4 ballot);\n" - "uvec4 subgroupPartitionedMaxNV(uvec4, uvec4 ballot);\n" - - "int subgroupPartitionedAndNV(int, uvec4 ballot);\n" - "ivec2 subgroupPartitionedAndNV(ivec2, uvec4 ballot);\n" - "ivec3 subgroupPartitionedAndNV(ivec3, uvec4 ballot);\n" - "ivec4 subgroupPartitionedAndNV(ivec4, uvec4 ballot);\n" - "uint subgroupPartitionedAndNV(uint, uvec4 ballot);\n" - "uvec2 subgroupPartitionedAndNV(uvec2, uvec4 ballot);\n" - "uvec3 subgroupPartitionedAndNV(uvec3, uvec4 ballot);\n" - "uvec4 subgroupPartitionedAndNV(uvec4, uvec4 ballot);\n" - "bool subgroupPartitionedAndNV(bool, uvec4 ballot);\n" - "bvec2 subgroupPartitionedAndNV(bvec2, uvec4 ballot);\n" - "bvec3 subgroupPartitionedAndNV(bvec3, uvec4 ballot);\n" - "bvec4 subgroupPartitionedAndNV(bvec4, uvec4 ballot);\n" - - "int subgroupPartitionedOrNV(int, uvec4 ballot);\n" - "ivec2 subgroupPartitionedOrNV(ivec2, uvec4 ballot);\n" - "ivec3 subgroupPartitionedOrNV(ivec3, uvec4 ballot);\n" - "ivec4 subgroupPartitionedOrNV(ivec4, uvec4 ballot);\n" - "uint subgroupPartitionedOrNV(uint, uvec4 ballot);\n" - "uvec2 subgroupPartitionedOrNV(uvec2, uvec4 ballot);\n" - "uvec3 subgroupPartitionedOrNV(uvec3, uvec4 ballot);\n" - "uvec4 subgroupPartitionedOrNV(uvec4, uvec4 ballot);\n" - "bool subgroupPartitionedOrNV(bool, uvec4 ballot);\n" - "bvec2 subgroupPartitionedOrNV(bvec2, uvec4 ballot);\n" - "bvec3 subgroupPartitionedOrNV(bvec3, uvec4 ballot);\n" - "bvec4 subgroupPartitionedOrNV(bvec4, uvec4 ballot);\n" - - "int subgroupPartitionedXorNV(int, uvec4 ballot);\n" - "ivec2 subgroupPartitionedXorNV(ivec2, uvec4 ballot);\n" - "ivec3 subgroupPartitionedXorNV(ivec3, uvec4 ballot);\n" - "ivec4 subgroupPartitionedXorNV(ivec4, uvec4 ballot);\n" - "uint subgroupPartitionedXorNV(uint, uvec4 ballot);\n" - "uvec2 subgroupPartitionedXorNV(uvec2, uvec4 ballot);\n" - "uvec3 subgroupPartitionedXorNV(uvec3, uvec4 ballot);\n" - "uvec4 subgroupPartitionedXorNV(uvec4, uvec4 ballot);\n" - "bool subgroupPartitionedXorNV(bool, uvec4 ballot);\n" - "bvec2 subgroupPartitionedXorNV(bvec2, uvec4 ballot);\n" - "bvec3 subgroupPartitionedXorNV(bvec3, uvec4 ballot);\n" - "bvec4 subgroupPartitionedXorNV(bvec4, uvec4 ballot);\n" - - "float subgroupPartitionedInclusiveAddNV(float, uvec4 ballot);\n" - "vec2 subgroupPartitionedInclusiveAddNV(vec2, uvec4 ballot);\n" - "vec3 subgroupPartitionedInclusiveAddNV(vec3, uvec4 ballot);\n" - "vec4 subgroupPartitionedInclusiveAddNV(vec4, uvec4 ballot);\n" - "int subgroupPartitionedInclusiveAddNV(int, uvec4 ballot);\n" - "ivec2 subgroupPartitionedInclusiveAddNV(ivec2, uvec4 ballot);\n" - "ivec3 subgroupPartitionedInclusiveAddNV(ivec3, uvec4 ballot);\n" - "ivec4 subgroupPartitionedInclusiveAddNV(ivec4, uvec4 ballot);\n" - "uint subgroupPartitionedInclusiveAddNV(uint, uvec4 ballot);\n" - "uvec2 subgroupPartitionedInclusiveAddNV(uvec2, uvec4 ballot);\n" - "uvec3 subgroupPartitionedInclusiveAddNV(uvec3, uvec4 ballot);\n" - "uvec4 subgroupPartitionedInclusiveAddNV(uvec4, uvec4 ballot);\n" - - "float subgroupPartitionedInclusiveMulNV(float, uvec4 ballot);\n" - "vec2 subgroupPartitionedInclusiveMulNV(vec2, uvec4 ballot);\n" - "vec3 subgroupPartitionedInclusiveMulNV(vec3, uvec4 ballot);\n" - "vec4 subgroupPartitionedInclusiveMulNV(vec4, uvec4 ballot);\n" - "int subgroupPartitionedInclusiveMulNV(int, uvec4 ballot);\n" - "ivec2 subgroupPartitionedInclusiveMulNV(ivec2, uvec4 ballot);\n" - "ivec3 subgroupPartitionedInclusiveMulNV(ivec3, uvec4 ballot);\n" - "ivec4 subgroupPartitionedInclusiveMulNV(ivec4, uvec4 ballot);\n" - "uint subgroupPartitionedInclusiveMulNV(uint, uvec4 ballot);\n" - "uvec2 subgroupPartitionedInclusiveMulNV(uvec2, uvec4 ballot);\n" - "uvec3 subgroupPartitionedInclusiveMulNV(uvec3, uvec4 ballot);\n" - "uvec4 subgroupPartitionedInclusiveMulNV(uvec4, uvec4 ballot);\n" - - "float subgroupPartitionedInclusiveMinNV(float, uvec4 ballot);\n" - "vec2 subgroupPartitionedInclusiveMinNV(vec2, uvec4 ballot);\n" - "vec3 subgroupPartitionedInclusiveMinNV(vec3, uvec4 ballot);\n" - "vec4 subgroupPartitionedInclusiveMinNV(vec4, uvec4 ballot);\n" - "int subgroupPartitionedInclusiveMinNV(int, uvec4 ballot);\n" - "ivec2 subgroupPartitionedInclusiveMinNV(ivec2, uvec4 ballot);\n" - "ivec3 subgroupPartitionedInclusiveMinNV(ivec3, uvec4 ballot);\n" - "ivec4 subgroupPartitionedInclusiveMinNV(ivec4, uvec4 ballot);\n" - "uint subgroupPartitionedInclusiveMinNV(uint, uvec4 ballot);\n" - "uvec2 subgroupPartitionedInclusiveMinNV(uvec2, uvec4 ballot);\n" - "uvec3 subgroupPartitionedInclusiveMinNV(uvec3, uvec4 ballot);\n" - "uvec4 subgroupPartitionedInclusiveMinNV(uvec4, uvec4 ballot);\n" - - "float subgroupPartitionedInclusiveMaxNV(float, uvec4 ballot);\n" - "vec2 subgroupPartitionedInclusiveMaxNV(vec2, uvec4 ballot);\n" - "vec3 subgroupPartitionedInclusiveMaxNV(vec3, uvec4 ballot);\n" - "vec4 subgroupPartitionedInclusiveMaxNV(vec4, uvec4 ballot);\n" - "int subgroupPartitionedInclusiveMaxNV(int, uvec4 ballot);\n" - "ivec2 subgroupPartitionedInclusiveMaxNV(ivec2, uvec4 ballot);\n" - "ivec3 subgroupPartitionedInclusiveMaxNV(ivec3, uvec4 ballot);\n" - "ivec4 subgroupPartitionedInclusiveMaxNV(ivec4, uvec4 ballot);\n" - "uint subgroupPartitionedInclusiveMaxNV(uint, uvec4 ballot);\n" - "uvec2 subgroupPartitionedInclusiveMaxNV(uvec2, uvec4 ballot);\n" - "uvec3 subgroupPartitionedInclusiveMaxNV(uvec3, uvec4 ballot);\n" - "uvec4 subgroupPartitionedInclusiveMaxNV(uvec4, uvec4 ballot);\n" - - "int subgroupPartitionedInclusiveAndNV(int, uvec4 ballot);\n" - "ivec2 subgroupPartitionedInclusiveAndNV(ivec2, uvec4 ballot);\n" - "ivec3 subgroupPartitionedInclusiveAndNV(ivec3, uvec4 ballot);\n" - "ivec4 subgroupPartitionedInclusiveAndNV(ivec4, uvec4 ballot);\n" - "uint subgroupPartitionedInclusiveAndNV(uint, uvec4 ballot);\n" - "uvec2 subgroupPartitionedInclusiveAndNV(uvec2, uvec4 ballot);\n" - "uvec3 subgroupPartitionedInclusiveAndNV(uvec3, uvec4 ballot);\n" - "uvec4 subgroupPartitionedInclusiveAndNV(uvec4, uvec4 ballot);\n" - "bool subgroupPartitionedInclusiveAndNV(bool, uvec4 ballot);\n" - "bvec2 subgroupPartitionedInclusiveAndNV(bvec2, uvec4 ballot);\n" - "bvec3 subgroupPartitionedInclusiveAndNV(bvec3, uvec4 ballot);\n" - "bvec4 subgroupPartitionedInclusiveAndNV(bvec4, uvec4 ballot);\n" - - "int subgroupPartitionedInclusiveOrNV(int, uvec4 ballot);\n" - "ivec2 subgroupPartitionedInclusiveOrNV(ivec2, uvec4 ballot);\n" - "ivec3 subgroupPartitionedInclusiveOrNV(ivec3, uvec4 ballot);\n" - "ivec4 subgroupPartitionedInclusiveOrNV(ivec4, uvec4 ballot);\n" - "uint subgroupPartitionedInclusiveOrNV(uint, uvec4 ballot);\n" - "uvec2 subgroupPartitionedInclusiveOrNV(uvec2, uvec4 ballot);\n" - "uvec3 subgroupPartitionedInclusiveOrNV(uvec3, uvec4 ballot);\n" - "uvec4 subgroupPartitionedInclusiveOrNV(uvec4, uvec4 ballot);\n" - "bool subgroupPartitionedInclusiveOrNV(bool, uvec4 ballot);\n" - "bvec2 subgroupPartitionedInclusiveOrNV(bvec2, uvec4 ballot);\n" - "bvec3 subgroupPartitionedInclusiveOrNV(bvec3, uvec4 ballot);\n" - "bvec4 subgroupPartitionedInclusiveOrNV(bvec4, uvec4 ballot);\n" - - "int subgroupPartitionedInclusiveXorNV(int, uvec4 ballot);\n" - "ivec2 subgroupPartitionedInclusiveXorNV(ivec2, uvec4 ballot);\n" - "ivec3 subgroupPartitionedInclusiveXorNV(ivec3, uvec4 ballot);\n" - "ivec4 subgroupPartitionedInclusiveXorNV(ivec4, uvec4 ballot);\n" - "uint subgroupPartitionedInclusiveXorNV(uint, uvec4 ballot);\n" - "uvec2 subgroupPartitionedInclusiveXorNV(uvec2, uvec4 ballot);\n" - "uvec3 subgroupPartitionedInclusiveXorNV(uvec3, uvec4 ballot);\n" - "uvec4 subgroupPartitionedInclusiveXorNV(uvec4, uvec4 ballot);\n" - "bool subgroupPartitionedInclusiveXorNV(bool, uvec4 ballot);\n" - "bvec2 subgroupPartitionedInclusiveXorNV(bvec2, uvec4 ballot);\n" - "bvec3 subgroupPartitionedInclusiveXorNV(bvec3, uvec4 ballot);\n" - "bvec4 subgroupPartitionedInclusiveXorNV(bvec4, uvec4 ballot);\n" - - "float subgroupPartitionedExclusiveAddNV(float, uvec4 ballot);\n" - "vec2 subgroupPartitionedExclusiveAddNV(vec2, uvec4 ballot);\n" - "vec3 subgroupPartitionedExclusiveAddNV(vec3, uvec4 ballot);\n" - "vec4 subgroupPartitionedExclusiveAddNV(vec4, uvec4 ballot);\n" - "int subgroupPartitionedExclusiveAddNV(int, uvec4 ballot);\n" - "ivec2 subgroupPartitionedExclusiveAddNV(ivec2, uvec4 ballot);\n" - "ivec3 subgroupPartitionedExclusiveAddNV(ivec3, uvec4 ballot);\n" - "ivec4 subgroupPartitionedExclusiveAddNV(ivec4, uvec4 ballot);\n" - "uint subgroupPartitionedExclusiveAddNV(uint, uvec4 ballot);\n" - "uvec2 subgroupPartitionedExclusiveAddNV(uvec2, uvec4 ballot);\n" - "uvec3 subgroupPartitionedExclusiveAddNV(uvec3, uvec4 ballot);\n" - "uvec4 subgroupPartitionedExclusiveAddNV(uvec4, uvec4 ballot);\n" - - "float subgroupPartitionedExclusiveMulNV(float, uvec4 ballot);\n" - "vec2 subgroupPartitionedExclusiveMulNV(vec2, uvec4 ballot);\n" - "vec3 subgroupPartitionedExclusiveMulNV(vec3, uvec4 ballot);\n" - "vec4 subgroupPartitionedExclusiveMulNV(vec4, uvec4 ballot);\n" - "int subgroupPartitionedExclusiveMulNV(int, uvec4 ballot);\n" - "ivec2 subgroupPartitionedExclusiveMulNV(ivec2, uvec4 ballot);\n" - "ivec3 subgroupPartitionedExclusiveMulNV(ivec3, uvec4 ballot);\n" - "ivec4 subgroupPartitionedExclusiveMulNV(ivec4, uvec4 ballot);\n" - "uint subgroupPartitionedExclusiveMulNV(uint, uvec4 ballot);\n" - "uvec2 subgroupPartitionedExclusiveMulNV(uvec2, uvec4 ballot);\n" - "uvec3 subgroupPartitionedExclusiveMulNV(uvec3, uvec4 ballot);\n" - "uvec4 subgroupPartitionedExclusiveMulNV(uvec4, uvec4 ballot);\n" - - "float subgroupPartitionedExclusiveMinNV(float, uvec4 ballot);\n" - "vec2 subgroupPartitionedExclusiveMinNV(vec2, uvec4 ballot);\n" - "vec3 subgroupPartitionedExclusiveMinNV(vec3, uvec4 ballot);\n" - "vec4 subgroupPartitionedExclusiveMinNV(vec4, uvec4 ballot);\n" - "int subgroupPartitionedExclusiveMinNV(int, uvec4 ballot);\n" - "ivec2 subgroupPartitionedExclusiveMinNV(ivec2, uvec4 ballot);\n" - "ivec3 subgroupPartitionedExclusiveMinNV(ivec3, uvec4 ballot);\n" - "ivec4 subgroupPartitionedExclusiveMinNV(ivec4, uvec4 ballot);\n" - "uint subgroupPartitionedExclusiveMinNV(uint, uvec4 ballot);\n" - "uvec2 subgroupPartitionedExclusiveMinNV(uvec2, uvec4 ballot);\n" - "uvec3 subgroupPartitionedExclusiveMinNV(uvec3, uvec4 ballot);\n" - "uvec4 subgroupPartitionedExclusiveMinNV(uvec4, uvec4 ballot);\n" - - "float subgroupPartitionedExclusiveMaxNV(float, uvec4 ballot);\n" - "vec2 subgroupPartitionedExclusiveMaxNV(vec2, uvec4 ballot);\n" - "vec3 subgroupPartitionedExclusiveMaxNV(vec3, uvec4 ballot);\n" - "vec4 subgroupPartitionedExclusiveMaxNV(vec4, uvec4 ballot);\n" - "int subgroupPartitionedExclusiveMaxNV(int, uvec4 ballot);\n" - "ivec2 subgroupPartitionedExclusiveMaxNV(ivec2, uvec4 ballot);\n" - "ivec3 subgroupPartitionedExclusiveMaxNV(ivec3, uvec4 ballot);\n" - "ivec4 subgroupPartitionedExclusiveMaxNV(ivec4, uvec4 ballot);\n" - "uint subgroupPartitionedExclusiveMaxNV(uint, uvec4 ballot);\n" - "uvec2 subgroupPartitionedExclusiveMaxNV(uvec2, uvec4 ballot);\n" - "uvec3 subgroupPartitionedExclusiveMaxNV(uvec3, uvec4 ballot);\n" - "uvec4 subgroupPartitionedExclusiveMaxNV(uvec4, uvec4 ballot);\n" - - "int subgroupPartitionedExclusiveAndNV(int, uvec4 ballot);\n" - "ivec2 subgroupPartitionedExclusiveAndNV(ivec2, uvec4 ballot);\n" - "ivec3 subgroupPartitionedExclusiveAndNV(ivec3, uvec4 ballot);\n" - "ivec4 subgroupPartitionedExclusiveAndNV(ivec4, uvec4 ballot);\n" - "uint subgroupPartitionedExclusiveAndNV(uint, uvec4 ballot);\n" - "uvec2 subgroupPartitionedExclusiveAndNV(uvec2, uvec4 ballot);\n" - "uvec3 subgroupPartitionedExclusiveAndNV(uvec3, uvec4 ballot);\n" - "uvec4 subgroupPartitionedExclusiveAndNV(uvec4, uvec4 ballot);\n" - "bool subgroupPartitionedExclusiveAndNV(bool, uvec4 ballot);\n" - "bvec2 subgroupPartitionedExclusiveAndNV(bvec2, uvec4 ballot);\n" - "bvec3 subgroupPartitionedExclusiveAndNV(bvec3, uvec4 ballot);\n" - "bvec4 subgroupPartitionedExclusiveAndNV(bvec4, uvec4 ballot);\n" - - "int subgroupPartitionedExclusiveOrNV(int, uvec4 ballot);\n" - "ivec2 subgroupPartitionedExclusiveOrNV(ivec2, uvec4 ballot);\n" - "ivec3 subgroupPartitionedExclusiveOrNV(ivec3, uvec4 ballot);\n" - "ivec4 subgroupPartitionedExclusiveOrNV(ivec4, uvec4 ballot);\n" - "uint subgroupPartitionedExclusiveOrNV(uint, uvec4 ballot);\n" - "uvec2 subgroupPartitionedExclusiveOrNV(uvec2, uvec4 ballot);\n" - "uvec3 subgroupPartitionedExclusiveOrNV(uvec3, uvec4 ballot);\n" - "uvec4 subgroupPartitionedExclusiveOrNV(uvec4, uvec4 ballot);\n" - "bool subgroupPartitionedExclusiveOrNV(bool, uvec4 ballot);\n" - "bvec2 subgroupPartitionedExclusiveOrNV(bvec2, uvec4 ballot);\n" - "bvec3 subgroupPartitionedExclusiveOrNV(bvec3, uvec4 ballot);\n" - "bvec4 subgroupPartitionedExclusiveOrNV(bvec4, uvec4 ballot);\n" - - "int subgroupPartitionedExclusiveXorNV(int, uvec4 ballot);\n" - "ivec2 subgroupPartitionedExclusiveXorNV(ivec2, uvec4 ballot);\n" - "ivec3 subgroupPartitionedExclusiveXorNV(ivec3, uvec4 ballot);\n" - "ivec4 subgroupPartitionedExclusiveXorNV(ivec4, uvec4 ballot);\n" - "uint subgroupPartitionedExclusiveXorNV(uint, uvec4 ballot);\n" - "uvec2 subgroupPartitionedExclusiveXorNV(uvec2, uvec4 ballot);\n" - "uvec3 subgroupPartitionedExclusiveXorNV(uvec3, uvec4 ballot);\n" - "uvec4 subgroupPartitionedExclusiveXorNV(uvec4, uvec4 ballot);\n" - "bool subgroupPartitionedExclusiveXorNV(bool, uvec4 ballot);\n" - "bvec2 subgroupPartitionedExclusiveXorNV(bvec2, uvec4 ballot);\n" - "bvec3 subgroupPartitionedExclusiveXorNV(bvec3, uvec4 ballot);\n" - "bvec4 subgroupPartitionedExclusiveXorNV(bvec4, uvec4 ballot);\n" -#endif - - "\n"); - - if (profile != EEsProfile && version >= 400) { - commonBuiltins.append( - "bool subgroupAllEqual(double);\n" - "bool subgroupAllEqual(dvec2);\n" - "bool subgroupAllEqual(dvec3);\n" - "bool subgroupAllEqual(dvec4);\n" - - "double subgroupBroadcast(double, uint);\n" - "dvec2 subgroupBroadcast(dvec2, uint);\n" - "dvec3 subgroupBroadcast(dvec3, uint);\n" - "dvec4 subgroupBroadcast(dvec4, uint);\n" - - "double subgroupBroadcastFirst(double);\n" - "dvec2 subgroupBroadcastFirst(dvec2);\n" - "dvec3 subgroupBroadcastFirst(dvec3);\n" - "dvec4 subgroupBroadcastFirst(dvec4);\n" - - "double subgroupShuffle(double, uint);\n" - "dvec2 subgroupShuffle(dvec2, uint);\n" - "dvec3 subgroupShuffle(dvec3, uint);\n" - "dvec4 subgroupShuffle(dvec4, uint);\n" - - "double subgroupShuffleXor(double, uint);\n" - "dvec2 subgroupShuffleXor(dvec2, uint);\n" - "dvec3 subgroupShuffleXor(dvec3, uint);\n" - "dvec4 subgroupShuffleXor(dvec4, uint);\n" - - "double subgroupShuffleUp(double, uint delta);\n" - "dvec2 subgroupShuffleUp(dvec2, uint delta);\n" - "dvec3 subgroupShuffleUp(dvec3, uint delta);\n" - "dvec4 subgroupShuffleUp(dvec4, uint delta);\n" - - "double subgroupShuffleDown(double, uint delta);\n" - "dvec2 subgroupShuffleDown(dvec2, uint delta);\n" - "dvec3 subgroupShuffleDown(dvec3, uint delta);\n" - "dvec4 subgroupShuffleDown(dvec4, uint delta);\n" - - "double subgroupAdd(double);\n" - "dvec2 subgroupAdd(dvec2);\n" - "dvec3 subgroupAdd(dvec3);\n" - "dvec4 subgroupAdd(dvec4);\n" - - "double subgroupMul(double);\n" - "dvec2 subgroupMul(dvec2);\n" - "dvec3 subgroupMul(dvec3);\n" - "dvec4 subgroupMul(dvec4);\n" - - "double subgroupMin(double);\n" - "dvec2 subgroupMin(dvec2);\n" - "dvec3 subgroupMin(dvec3);\n" - "dvec4 subgroupMin(dvec4);\n" - - "double subgroupMax(double);\n" - "dvec2 subgroupMax(dvec2);\n" - "dvec3 subgroupMax(dvec3);\n" - "dvec4 subgroupMax(dvec4);\n" - - "double subgroupInclusiveAdd(double);\n" - "dvec2 subgroupInclusiveAdd(dvec2);\n" - "dvec3 subgroupInclusiveAdd(dvec3);\n" - "dvec4 subgroupInclusiveAdd(dvec4);\n" - - "double subgroupInclusiveMul(double);\n" - "dvec2 subgroupInclusiveMul(dvec2);\n" - "dvec3 subgroupInclusiveMul(dvec3);\n" - "dvec4 subgroupInclusiveMul(dvec4);\n" - - "double subgroupInclusiveMin(double);\n" - "dvec2 subgroupInclusiveMin(dvec2);\n" - "dvec3 subgroupInclusiveMin(dvec3);\n" - "dvec4 subgroupInclusiveMin(dvec4);\n" - - "double subgroupInclusiveMax(double);\n" - "dvec2 subgroupInclusiveMax(dvec2);\n" - "dvec3 subgroupInclusiveMax(dvec3);\n" - "dvec4 subgroupInclusiveMax(dvec4);\n" - - "double subgroupExclusiveAdd(double);\n" - "dvec2 subgroupExclusiveAdd(dvec2);\n" - "dvec3 subgroupExclusiveAdd(dvec3);\n" - "dvec4 subgroupExclusiveAdd(dvec4);\n" - - "double subgroupExclusiveMul(double);\n" - "dvec2 subgroupExclusiveMul(dvec2);\n" - "dvec3 subgroupExclusiveMul(dvec3);\n" - "dvec4 subgroupExclusiveMul(dvec4);\n" - - "double subgroupExclusiveMin(double);\n" - "dvec2 subgroupExclusiveMin(dvec2);\n" - "dvec3 subgroupExclusiveMin(dvec3);\n" - "dvec4 subgroupExclusiveMin(dvec4);\n" - - "double subgroupExclusiveMax(double);\n" - "dvec2 subgroupExclusiveMax(dvec2);\n" - "dvec3 subgroupExclusiveMax(dvec3);\n" - "dvec4 subgroupExclusiveMax(dvec4);\n" - - "double subgroupClusteredAdd(double, uint);\n" - "dvec2 subgroupClusteredAdd(dvec2, uint);\n" - "dvec3 subgroupClusteredAdd(dvec3, uint);\n" - "dvec4 subgroupClusteredAdd(dvec4, uint);\n" - - "double subgroupClusteredMul(double, uint);\n" - "dvec2 subgroupClusteredMul(dvec2, uint);\n" - "dvec3 subgroupClusteredMul(dvec3, uint);\n" - "dvec4 subgroupClusteredMul(dvec4, uint);\n" - - "double subgroupClusteredMin(double, uint);\n" - "dvec2 subgroupClusteredMin(dvec2, uint);\n" - "dvec3 subgroupClusteredMin(dvec3, uint);\n" - "dvec4 subgroupClusteredMin(dvec4, uint);\n" - - "double subgroupClusteredMax(double, uint);\n" - "dvec2 subgroupClusteredMax(dvec2, uint);\n" - "dvec3 subgroupClusteredMax(dvec3, uint);\n" - "dvec4 subgroupClusteredMax(dvec4, uint);\n" - - "double subgroupQuadBroadcast(double, uint);\n" - "dvec2 subgroupQuadBroadcast(dvec2, uint);\n" - "dvec3 subgroupQuadBroadcast(dvec3, uint);\n" - "dvec4 subgroupQuadBroadcast(dvec4, uint);\n" - - "double subgroupQuadSwapHorizontal(double);\n" - "dvec2 subgroupQuadSwapHorizontal(dvec2);\n" - "dvec3 subgroupQuadSwapHorizontal(dvec3);\n" - "dvec4 subgroupQuadSwapHorizontal(dvec4);\n" - - "double subgroupQuadSwapVertical(double);\n" - "dvec2 subgroupQuadSwapVertical(dvec2);\n" - "dvec3 subgroupQuadSwapVertical(dvec3);\n" - "dvec4 subgroupQuadSwapVertical(dvec4);\n" - - "double subgroupQuadSwapDiagonal(double);\n" - "dvec2 subgroupQuadSwapDiagonal(dvec2);\n" - "dvec3 subgroupQuadSwapDiagonal(dvec3);\n" - "dvec4 subgroupQuadSwapDiagonal(dvec4);\n" - - -#ifdef NV_EXTENSIONS - "uvec4 subgroupPartitionNV(double);\n" - "uvec4 subgroupPartitionNV(dvec2);\n" - "uvec4 subgroupPartitionNV(dvec3);\n" - "uvec4 subgroupPartitionNV(dvec4);\n" - - "double subgroupPartitionedAddNV(double, uvec4 ballot);\n" - "dvec2 subgroupPartitionedAddNV(dvec2, uvec4 ballot);\n" - "dvec3 subgroupPartitionedAddNV(dvec3, uvec4 ballot);\n" - "dvec4 subgroupPartitionedAddNV(dvec4, uvec4 ballot);\n" - - "double subgroupPartitionedMulNV(double, uvec4 ballot);\n" - "dvec2 subgroupPartitionedMulNV(dvec2, uvec4 ballot);\n" - "dvec3 subgroupPartitionedMulNV(dvec3, uvec4 ballot);\n" - "dvec4 subgroupPartitionedMulNV(dvec4, uvec4 ballot);\n" - - "double subgroupPartitionedMinNV(double, uvec4 ballot);\n" - "dvec2 subgroupPartitionedMinNV(dvec2, uvec4 ballot);\n" - "dvec3 subgroupPartitionedMinNV(dvec3, uvec4 ballot);\n" - "dvec4 subgroupPartitionedMinNV(dvec4, uvec4 ballot);\n" - - "double subgroupPartitionedMaxNV(double, uvec4 ballot);\n" - "dvec2 subgroupPartitionedMaxNV(dvec2, uvec4 ballot);\n" - "dvec3 subgroupPartitionedMaxNV(dvec3, uvec4 ballot);\n" - "dvec4 subgroupPartitionedMaxNV(dvec4, uvec4 ballot);\n" - - "double subgroupPartitionedInclusiveAddNV(double, uvec4 ballot);\n" - "dvec2 subgroupPartitionedInclusiveAddNV(dvec2, uvec4 ballot);\n" - "dvec3 subgroupPartitionedInclusiveAddNV(dvec3, uvec4 ballot);\n" - "dvec4 subgroupPartitionedInclusiveAddNV(dvec4, uvec4 ballot);\n" - - "double subgroupPartitionedInclusiveMulNV(double, uvec4 ballot);\n" - "dvec2 subgroupPartitionedInclusiveMulNV(dvec2, uvec4 ballot);\n" - "dvec3 subgroupPartitionedInclusiveMulNV(dvec3, uvec4 ballot);\n" - "dvec4 subgroupPartitionedInclusiveMulNV(dvec4, uvec4 ballot);\n" - - "double subgroupPartitionedInclusiveMinNV(double, uvec4 ballot);\n" - "dvec2 subgroupPartitionedInclusiveMinNV(dvec2, uvec4 ballot);\n" - "dvec3 subgroupPartitionedInclusiveMinNV(dvec3, uvec4 ballot);\n" - "dvec4 subgroupPartitionedInclusiveMinNV(dvec4, uvec4 ballot);\n" - - "double subgroupPartitionedInclusiveMaxNV(double, uvec4 ballot);\n" - "dvec2 subgroupPartitionedInclusiveMaxNV(dvec2, uvec4 ballot);\n" - "dvec3 subgroupPartitionedInclusiveMaxNV(dvec3, uvec4 ballot);\n" - "dvec4 subgroupPartitionedInclusiveMaxNV(dvec4, uvec4 ballot);\n" - - "double subgroupPartitionedExclusiveAddNV(double, uvec4 ballot);\n" - "dvec2 subgroupPartitionedExclusiveAddNV(dvec2, uvec4 ballot);\n" - "dvec3 subgroupPartitionedExclusiveAddNV(dvec3, uvec4 ballot);\n" - "dvec4 subgroupPartitionedExclusiveAddNV(dvec4, uvec4 ballot);\n" - - "double subgroupPartitionedExclusiveMulNV(double, uvec4 ballot);\n" - "dvec2 subgroupPartitionedExclusiveMulNV(dvec2, uvec4 ballot);\n" - "dvec3 subgroupPartitionedExclusiveMulNV(dvec3, uvec4 ballot);\n" - "dvec4 subgroupPartitionedExclusiveMulNV(dvec4, uvec4 ballot);\n" - - "double subgroupPartitionedExclusiveMinNV(double, uvec4 ballot);\n" - "dvec2 subgroupPartitionedExclusiveMinNV(dvec2, uvec4 ballot);\n" - "dvec3 subgroupPartitionedExclusiveMinNV(dvec3, uvec4 ballot);\n" - "dvec4 subgroupPartitionedExclusiveMinNV(dvec4, uvec4 ballot);\n" - - "double subgroupPartitionedExclusiveMaxNV(double, uvec4 ballot);\n" - "dvec2 subgroupPartitionedExclusiveMaxNV(dvec2, uvec4 ballot);\n" - "dvec3 subgroupPartitionedExclusiveMaxNV(dvec3, uvec4 ballot);\n" - "dvec4 subgroupPartitionedExclusiveMaxNV(dvec4, uvec4 ballot);\n" -#endif - - "\n"); - } - - stageBuiltins[EShLangCompute].append( - "void subgroupMemoryBarrierShared();" - - "\n" - ); - } - - if (profile != EEsProfile && version >= 460) { - commonBuiltins.append( - "bool anyInvocation(bool);" - "bool allInvocations(bool);" - "bool allInvocationsEqual(bool);" - - "\n"); - } - -#ifdef AMD_EXTENSIONS - // GL_AMD_shader_ballot - if (profile != EEsProfile && version >= 450) { - commonBuiltins.append( - "float minInvocationsAMD(float);" - "vec2 minInvocationsAMD(vec2);" - "vec3 minInvocationsAMD(vec3);" - "vec4 minInvocationsAMD(vec4);" - - "int minInvocationsAMD(int);" - "ivec2 minInvocationsAMD(ivec2);" - "ivec3 minInvocationsAMD(ivec3);" - "ivec4 minInvocationsAMD(ivec4);" - - "uint minInvocationsAMD(uint);" - "uvec2 minInvocationsAMD(uvec2);" - "uvec3 minInvocationsAMD(uvec3);" - "uvec4 minInvocationsAMD(uvec4);" - - "double minInvocationsAMD(double);" - "dvec2 minInvocationsAMD(dvec2);" - "dvec3 minInvocationsAMD(dvec3);" - "dvec4 minInvocationsAMD(dvec4);" - - "int64_t minInvocationsAMD(int64_t);" - "i64vec2 minInvocationsAMD(i64vec2);" - "i64vec3 minInvocationsAMD(i64vec3);" - "i64vec4 minInvocationsAMD(i64vec4);" - - "uint64_t minInvocationsAMD(uint64_t);" - "u64vec2 minInvocationsAMD(u64vec2);" - "u64vec3 minInvocationsAMD(u64vec3);" - "u64vec4 minInvocationsAMD(u64vec4);" - - "float16_t minInvocationsAMD(float16_t);" - "f16vec2 minInvocationsAMD(f16vec2);" - "f16vec3 minInvocationsAMD(f16vec3);" - "f16vec4 minInvocationsAMD(f16vec4);" - - "int16_t minInvocationsAMD(int16_t);" - "i16vec2 minInvocationsAMD(i16vec2);" - "i16vec3 minInvocationsAMD(i16vec3);" - "i16vec4 minInvocationsAMD(i16vec4);" - - "uint16_t minInvocationsAMD(uint16_t);" - "u16vec2 minInvocationsAMD(u16vec2);" - "u16vec3 minInvocationsAMD(u16vec3);" - "u16vec4 minInvocationsAMD(u16vec4);" - - "float minInvocationsInclusiveScanAMD(float);" - "vec2 minInvocationsInclusiveScanAMD(vec2);" - "vec3 minInvocationsInclusiveScanAMD(vec3);" - "vec4 minInvocationsInclusiveScanAMD(vec4);" - - "int minInvocationsInclusiveScanAMD(int);" - "ivec2 minInvocationsInclusiveScanAMD(ivec2);" - "ivec3 minInvocationsInclusiveScanAMD(ivec3);" - "ivec4 minInvocationsInclusiveScanAMD(ivec4);" - - "uint minInvocationsInclusiveScanAMD(uint);" - "uvec2 minInvocationsInclusiveScanAMD(uvec2);" - "uvec3 minInvocationsInclusiveScanAMD(uvec3);" - "uvec4 minInvocationsInclusiveScanAMD(uvec4);" - - "double minInvocationsInclusiveScanAMD(double);" - "dvec2 minInvocationsInclusiveScanAMD(dvec2);" - "dvec3 minInvocationsInclusiveScanAMD(dvec3);" - "dvec4 minInvocationsInclusiveScanAMD(dvec4);" - - "int64_t minInvocationsInclusiveScanAMD(int64_t);" - "i64vec2 minInvocationsInclusiveScanAMD(i64vec2);" - "i64vec3 minInvocationsInclusiveScanAMD(i64vec3);" - "i64vec4 minInvocationsInclusiveScanAMD(i64vec4);" - - "uint64_t minInvocationsInclusiveScanAMD(uint64_t);" - "u64vec2 minInvocationsInclusiveScanAMD(u64vec2);" - "u64vec3 minInvocationsInclusiveScanAMD(u64vec3);" - "u64vec4 minInvocationsInclusiveScanAMD(u64vec4);" - - "float16_t minInvocationsInclusiveScanAMD(float16_t);" - "f16vec2 minInvocationsInclusiveScanAMD(f16vec2);" - "f16vec3 minInvocationsInclusiveScanAMD(f16vec3);" - "f16vec4 minInvocationsInclusiveScanAMD(f16vec4);" - - "int16_t minInvocationsInclusiveScanAMD(int16_t);" - "i16vec2 minInvocationsInclusiveScanAMD(i16vec2);" - "i16vec3 minInvocationsInclusiveScanAMD(i16vec3);" - "i16vec4 minInvocationsInclusiveScanAMD(i16vec4);" - - "uint16_t minInvocationsInclusiveScanAMD(uint16_t);" - "u16vec2 minInvocationsInclusiveScanAMD(u16vec2);" - "u16vec3 minInvocationsInclusiveScanAMD(u16vec3);" - "u16vec4 minInvocationsInclusiveScanAMD(u16vec4);" - - "float minInvocationsExclusiveScanAMD(float);" - "vec2 minInvocationsExclusiveScanAMD(vec2);" - "vec3 minInvocationsExclusiveScanAMD(vec3);" - "vec4 minInvocationsExclusiveScanAMD(vec4);" - - "int minInvocationsExclusiveScanAMD(int);" - "ivec2 minInvocationsExclusiveScanAMD(ivec2);" - "ivec3 minInvocationsExclusiveScanAMD(ivec3);" - "ivec4 minInvocationsExclusiveScanAMD(ivec4);" - - "uint minInvocationsExclusiveScanAMD(uint);" - "uvec2 minInvocationsExclusiveScanAMD(uvec2);" - "uvec3 minInvocationsExclusiveScanAMD(uvec3);" - "uvec4 minInvocationsExclusiveScanAMD(uvec4);" - - "double minInvocationsExclusiveScanAMD(double);" - "dvec2 minInvocationsExclusiveScanAMD(dvec2);" - "dvec3 minInvocationsExclusiveScanAMD(dvec3);" - "dvec4 minInvocationsExclusiveScanAMD(dvec4);" - - "int64_t minInvocationsExclusiveScanAMD(int64_t);" - "i64vec2 minInvocationsExclusiveScanAMD(i64vec2);" - "i64vec3 minInvocationsExclusiveScanAMD(i64vec3);" - "i64vec4 minInvocationsExclusiveScanAMD(i64vec4);" - - "uint64_t minInvocationsExclusiveScanAMD(uint64_t);" - "u64vec2 minInvocationsExclusiveScanAMD(u64vec2);" - "u64vec3 minInvocationsExclusiveScanAMD(u64vec3);" - "u64vec4 minInvocationsExclusiveScanAMD(u64vec4);" - - "float16_t minInvocationsExclusiveScanAMD(float16_t);" - "f16vec2 minInvocationsExclusiveScanAMD(f16vec2);" - "f16vec3 minInvocationsExclusiveScanAMD(f16vec3);" - "f16vec4 minInvocationsExclusiveScanAMD(f16vec4);" - - "int16_t minInvocationsExclusiveScanAMD(int16_t);" - "i16vec2 minInvocationsExclusiveScanAMD(i16vec2);" - "i16vec3 minInvocationsExclusiveScanAMD(i16vec3);" - "i16vec4 minInvocationsExclusiveScanAMD(i16vec4);" - - "uint16_t minInvocationsExclusiveScanAMD(uint16_t);" - "u16vec2 minInvocationsExclusiveScanAMD(u16vec2);" - "u16vec3 minInvocationsExclusiveScanAMD(u16vec3);" - "u16vec4 minInvocationsExclusiveScanAMD(u16vec4);" - - "float maxInvocationsAMD(float);" - "vec2 maxInvocationsAMD(vec2);" - "vec3 maxInvocationsAMD(vec3);" - "vec4 maxInvocationsAMD(vec4);" - - "int maxInvocationsAMD(int);" - "ivec2 maxInvocationsAMD(ivec2);" - "ivec3 maxInvocationsAMD(ivec3);" - "ivec4 maxInvocationsAMD(ivec4);" - - "uint maxInvocationsAMD(uint);" - "uvec2 maxInvocationsAMD(uvec2);" - "uvec3 maxInvocationsAMD(uvec3);" - "uvec4 maxInvocationsAMD(uvec4);" - - "double maxInvocationsAMD(double);" - "dvec2 maxInvocationsAMD(dvec2);" - "dvec3 maxInvocationsAMD(dvec3);" - "dvec4 maxInvocationsAMD(dvec4);" - - "int64_t maxInvocationsAMD(int64_t);" - "i64vec2 maxInvocationsAMD(i64vec2);" - "i64vec3 maxInvocationsAMD(i64vec3);" - "i64vec4 maxInvocationsAMD(i64vec4);" - - "uint64_t maxInvocationsAMD(uint64_t);" - "u64vec2 maxInvocationsAMD(u64vec2);" - "u64vec3 maxInvocationsAMD(u64vec3);" - "u64vec4 maxInvocationsAMD(u64vec4);" - - "float16_t maxInvocationsAMD(float16_t);" - "f16vec2 maxInvocationsAMD(f16vec2);" - "f16vec3 maxInvocationsAMD(f16vec3);" - "f16vec4 maxInvocationsAMD(f16vec4);" - - "int16_t maxInvocationsAMD(int16_t);" - "i16vec2 maxInvocationsAMD(i16vec2);" - "i16vec3 maxInvocationsAMD(i16vec3);" - "i16vec4 maxInvocationsAMD(i16vec4);" - - "uint16_t maxInvocationsAMD(uint16_t);" - "u16vec2 maxInvocationsAMD(u16vec2);" - "u16vec3 maxInvocationsAMD(u16vec3);" - "u16vec4 maxInvocationsAMD(u16vec4);" - - "float maxInvocationsInclusiveScanAMD(float);" - "vec2 maxInvocationsInclusiveScanAMD(vec2);" - "vec3 maxInvocationsInclusiveScanAMD(vec3);" - "vec4 maxInvocationsInclusiveScanAMD(vec4);" - - "int maxInvocationsInclusiveScanAMD(int);" - "ivec2 maxInvocationsInclusiveScanAMD(ivec2);" - "ivec3 maxInvocationsInclusiveScanAMD(ivec3);" - "ivec4 maxInvocationsInclusiveScanAMD(ivec4);" - - "uint maxInvocationsInclusiveScanAMD(uint);" - "uvec2 maxInvocationsInclusiveScanAMD(uvec2);" - "uvec3 maxInvocationsInclusiveScanAMD(uvec3);" - "uvec4 maxInvocationsInclusiveScanAMD(uvec4);" - - "double maxInvocationsInclusiveScanAMD(double);" - "dvec2 maxInvocationsInclusiveScanAMD(dvec2);" - "dvec3 maxInvocationsInclusiveScanAMD(dvec3);" - "dvec4 maxInvocationsInclusiveScanAMD(dvec4);" - - "int64_t maxInvocationsInclusiveScanAMD(int64_t);" - "i64vec2 maxInvocationsInclusiveScanAMD(i64vec2);" - "i64vec3 maxInvocationsInclusiveScanAMD(i64vec3);" - "i64vec4 maxInvocationsInclusiveScanAMD(i64vec4);" - - "uint64_t maxInvocationsInclusiveScanAMD(uint64_t);" - "u64vec2 maxInvocationsInclusiveScanAMD(u64vec2);" - "u64vec3 maxInvocationsInclusiveScanAMD(u64vec3);" - "u64vec4 maxInvocationsInclusiveScanAMD(u64vec4);" - - "float16_t maxInvocationsInclusiveScanAMD(float16_t);" - "f16vec2 maxInvocationsInclusiveScanAMD(f16vec2);" - "f16vec3 maxInvocationsInclusiveScanAMD(f16vec3);" - "f16vec4 maxInvocationsInclusiveScanAMD(f16vec4);" - - "int16_t maxInvocationsInclusiveScanAMD(int16_t);" - "i16vec2 maxInvocationsInclusiveScanAMD(i16vec2);" - "i16vec3 maxInvocationsInclusiveScanAMD(i16vec3);" - "i16vec4 maxInvocationsInclusiveScanAMD(i16vec4);" - - "uint16_t maxInvocationsInclusiveScanAMD(uint16_t);" - "u16vec2 maxInvocationsInclusiveScanAMD(u16vec2);" - "u16vec3 maxInvocationsInclusiveScanAMD(u16vec3);" - "u16vec4 maxInvocationsInclusiveScanAMD(u16vec4);" - - "float maxInvocationsExclusiveScanAMD(float);" - "vec2 maxInvocationsExclusiveScanAMD(vec2);" - "vec3 maxInvocationsExclusiveScanAMD(vec3);" - "vec4 maxInvocationsExclusiveScanAMD(vec4);" - - "int maxInvocationsExclusiveScanAMD(int);" - "ivec2 maxInvocationsExclusiveScanAMD(ivec2);" - "ivec3 maxInvocationsExclusiveScanAMD(ivec3);" - "ivec4 maxInvocationsExclusiveScanAMD(ivec4);" - - "uint maxInvocationsExclusiveScanAMD(uint);" - "uvec2 maxInvocationsExclusiveScanAMD(uvec2);" - "uvec3 maxInvocationsExclusiveScanAMD(uvec3);" - "uvec4 maxInvocationsExclusiveScanAMD(uvec4);" - - "double maxInvocationsExclusiveScanAMD(double);" - "dvec2 maxInvocationsExclusiveScanAMD(dvec2);" - "dvec3 maxInvocationsExclusiveScanAMD(dvec3);" - "dvec4 maxInvocationsExclusiveScanAMD(dvec4);" - - "int64_t maxInvocationsExclusiveScanAMD(int64_t);" - "i64vec2 maxInvocationsExclusiveScanAMD(i64vec2);" - "i64vec3 maxInvocationsExclusiveScanAMD(i64vec3);" - "i64vec4 maxInvocationsExclusiveScanAMD(i64vec4);" - - "uint64_t maxInvocationsExclusiveScanAMD(uint64_t);" - "u64vec2 maxInvocationsExclusiveScanAMD(u64vec2);" - "u64vec3 maxInvocationsExclusiveScanAMD(u64vec3);" - "u64vec4 maxInvocationsExclusiveScanAMD(u64vec4);" - - "float16_t maxInvocationsExclusiveScanAMD(float16_t);" - "f16vec2 maxInvocationsExclusiveScanAMD(f16vec2);" - "f16vec3 maxInvocationsExclusiveScanAMD(f16vec3);" - "f16vec4 maxInvocationsExclusiveScanAMD(f16vec4);" - - "int16_t maxInvocationsExclusiveScanAMD(int16_t);" - "i16vec2 maxInvocationsExclusiveScanAMD(i16vec2);" - "i16vec3 maxInvocationsExclusiveScanAMD(i16vec3);" - "i16vec4 maxInvocationsExclusiveScanAMD(i16vec4);" - - "uint16_t maxInvocationsExclusiveScanAMD(uint16_t);" - "u16vec2 maxInvocationsExclusiveScanAMD(u16vec2);" - "u16vec3 maxInvocationsExclusiveScanAMD(u16vec3);" - "u16vec4 maxInvocationsExclusiveScanAMD(u16vec4);" - - "float addInvocationsAMD(float);" - "vec2 addInvocationsAMD(vec2);" - "vec3 addInvocationsAMD(vec3);" - "vec4 addInvocationsAMD(vec4);" - - "int addInvocationsAMD(int);" - "ivec2 addInvocationsAMD(ivec2);" - "ivec3 addInvocationsAMD(ivec3);" - "ivec4 addInvocationsAMD(ivec4);" - - "uint addInvocationsAMD(uint);" - "uvec2 addInvocationsAMD(uvec2);" - "uvec3 addInvocationsAMD(uvec3);" - "uvec4 addInvocationsAMD(uvec4);" - - "double addInvocationsAMD(double);" - "dvec2 addInvocationsAMD(dvec2);" - "dvec3 addInvocationsAMD(dvec3);" - "dvec4 addInvocationsAMD(dvec4);" - - "int64_t addInvocationsAMD(int64_t);" - "i64vec2 addInvocationsAMD(i64vec2);" - "i64vec3 addInvocationsAMD(i64vec3);" - "i64vec4 addInvocationsAMD(i64vec4);" - - "uint64_t addInvocationsAMD(uint64_t);" - "u64vec2 addInvocationsAMD(u64vec2);" - "u64vec3 addInvocationsAMD(u64vec3);" - "u64vec4 addInvocationsAMD(u64vec4);" - - "float16_t addInvocationsAMD(float16_t);" - "f16vec2 addInvocationsAMD(f16vec2);" - "f16vec3 addInvocationsAMD(f16vec3);" - "f16vec4 addInvocationsAMD(f16vec4);" - - "int16_t addInvocationsAMD(int16_t);" - "i16vec2 addInvocationsAMD(i16vec2);" - "i16vec3 addInvocationsAMD(i16vec3);" - "i16vec4 addInvocationsAMD(i16vec4);" - - "uint16_t addInvocationsAMD(uint16_t);" - "u16vec2 addInvocationsAMD(u16vec2);" - "u16vec3 addInvocationsAMD(u16vec3);" - "u16vec4 addInvocationsAMD(u16vec4);" - - "float addInvocationsInclusiveScanAMD(float);" - "vec2 addInvocationsInclusiveScanAMD(vec2);" - "vec3 addInvocationsInclusiveScanAMD(vec3);" - "vec4 addInvocationsInclusiveScanAMD(vec4);" - - "int addInvocationsInclusiveScanAMD(int);" - "ivec2 addInvocationsInclusiveScanAMD(ivec2);" - "ivec3 addInvocationsInclusiveScanAMD(ivec3);" - "ivec4 addInvocationsInclusiveScanAMD(ivec4);" - - "uint addInvocationsInclusiveScanAMD(uint);" - "uvec2 addInvocationsInclusiveScanAMD(uvec2);" - "uvec3 addInvocationsInclusiveScanAMD(uvec3);" - "uvec4 addInvocationsInclusiveScanAMD(uvec4);" - - "double addInvocationsInclusiveScanAMD(double);" - "dvec2 addInvocationsInclusiveScanAMD(dvec2);" - "dvec3 addInvocationsInclusiveScanAMD(dvec3);" - "dvec4 addInvocationsInclusiveScanAMD(dvec4);" - - "int64_t addInvocationsInclusiveScanAMD(int64_t);" - "i64vec2 addInvocationsInclusiveScanAMD(i64vec2);" - "i64vec3 addInvocationsInclusiveScanAMD(i64vec3);" - "i64vec4 addInvocationsInclusiveScanAMD(i64vec4);" - - "uint64_t addInvocationsInclusiveScanAMD(uint64_t);" - "u64vec2 addInvocationsInclusiveScanAMD(u64vec2);" - "u64vec3 addInvocationsInclusiveScanAMD(u64vec3);" - "u64vec4 addInvocationsInclusiveScanAMD(u64vec4);" - - "float16_t addInvocationsInclusiveScanAMD(float16_t);" - "f16vec2 addInvocationsInclusiveScanAMD(f16vec2);" - "f16vec3 addInvocationsInclusiveScanAMD(f16vec3);" - "f16vec4 addInvocationsInclusiveScanAMD(f16vec4);" - - "int16_t addInvocationsInclusiveScanAMD(int16_t);" - "i16vec2 addInvocationsInclusiveScanAMD(i16vec2);" - "i16vec3 addInvocationsInclusiveScanAMD(i16vec3);" - "i16vec4 addInvocationsInclusiveScanAMD(i16vec4);" - - "uint16_t addInvocationsInclusiveScanAMD(uint16_t);" - "u16vec2 addInvocationsInclusiveScanAMD(u16vec2);" - "u16vec3 addInvocationsInclusiveScanAMD(u16vec3);" - "u16vec4 addInvocationsInclusiveScanAMD(u16vec4);" - - "float addInvocationsExclusiveScanAMD(float);" - "vec2 addInvocationsExclusiveScanAMD(vec2);" - "vec3 addInvocationsExclusiveScanAMD(vec3);" - "vec4 addInvocationsExclusiveScanAMD(vec4);" - - "int addInvocationsExclusiveScanAMD(int);" - "ivec2 addInvocationsExclusiveScanAMD(ivec2);" - "ivec3 addInvocationsExclusiveScanAMD(ivec3);" - "ivec4 addInvocationsExclusiveScanAMD(ivec4);" - - "uint addInvocationsExclusiveScanAMD(uint);" - "uvec2 addInvocationsExclusiveScanAMD(uvec2);" - "uvec3 addInvocationsExclusiveScanAMD(uvec3);" - "uvec4 addInvocationsExclusiveScanAMD(uvec4);" - - "double addInvocationsExclusiveScanAMD(double);" - "dvec2 addInvocationsExclusiveScanAMD(dvec2);" - "dvec3 addInvocationsExclusiveScanAMD(dvec3);" - "dvec4 addInvocationsExclusiveScanAMD(dvec4);" - - "int64_t addInvocationsExclusiveScanAMD(int64_t);" - "i64vec2 addInvocationsExclusiveScanAMD(i64vec2);" - "i64vec3 addInvocationsExclusiveScanAMD(i64vec3);" - "i64vec4 addInvocationsExclusiveScanAMD(i64vec4);" - - "uint64_t addInvocationsExclusiveScanAMD(uint64_t);" - "u64vec2 addInvocationsExclusiveScanAMD(u64vec2);" - "u64vec3 addInvocationsExclusiveScanAMD(u64vec3);" - "u64vec4 addInvocationsExclusiveScanAMD(u64vec4);" - - "float16_t addInvocationsExclusiveScanAMD(float16_t);" - "f16vec2 addInvocationsExclusiveScanAMD(f16vec2);" - "f16vec3 addInvocationsExclusiveScanAMD(f16vec3);" - "f16vec4 addInvocationsExclusiveScanAMD(f16vec4);" - - "int16_t addInvocationsExclusiveScanAMD(int16_t);" - "i16vec2 addInvocationsExclusiveScanAMD(i16vec2);" - "i16vec3 addInvocationsExclusiveScanAMD(i16vec3);" - "i16vec4 addInvocationsExclusiveScanAMD(i16vec4);" - - "uint16_t addInvocationsExclusiveScanAMD(uint16_t);" - "u16vec2 addInvocationsExclusiveScanAMD(u16vec2);" - "u16vec3 addInvocationsExclusiveScanAMD(u16vec3);" - "u16vec4 addInvocationsExclusiveScanAMD(u16vec4);" - - "float minInvocationsNonUniformAMD(float);" - "vec2 minInvocationsNonUniformAMD(vec2);" - "vec3 minInvocationsNonUniformAMD(vec3);" - "vec4 minInvocationsNonUniformAMD(vec4);" - - "int minInvocationsNonUniformAMD(int);" - "ivec2 minInvocationsNonUniformAMD(ivec2);" - "ivec3 minInvocationsNonUniformAMD(ivec3);" - "ivec4 minInvocationsNonUniformAMD(ivec4);" - - "uint minInvocationsNonUniformAMD(uint);" - "uvec2 minInvocationsNonUniformAMD(uvec2);" - "uvec3 minInvocationsNonUniformAMD(uvec3);" - "uvec4 minInvocationsNonUniformAMD(uvec4);" - - "double minInvocationsNonUniformAMD(double);" - "dvec2 minInvocationsNonUniformAMD(dvec2);" - "dvec3 minInvocationsNonUniformAMD(dvec3);" - "dvec4 minInvocationsNonUniformAMD(dvec4);" - - "int64_t minInvocationsNonUniformAMD(int64_t);" - "i64vec2 minInvocationsNonUniformAMD(i64vec2);" - "i64vec3 minInvocationsNonUniformAMD(i64vec3);" - "i64vec4 minInvocationsNonUniformAMD(i64vec4);" - - "uint64_t minInvocationsNonUniformAMD(uint64_t);" - "u64vec2 minInvocationsNonUniformAMD(u64vec2);" - "u64vec3 minInvocationsNonUniformAMD(u64vec3);" - "u64vec4 minInvocationsNonUniformAMD(u64vec4);" - - "float16_t minInvocationsNonUniformAMD(float16_t);" - "f16vec2 minInvocationsNonUniformAMD(f16vec2);" - "f16vec3 minInvocationsNonUniformAMD(f16vec3);" - "f16vec4 minInvocationsNonUniformAMD(f16vec4);" - - "int16_t minInvocationsNonUniformAMD(int16_t);" - "i16vec2 minInvocationsNonUniformAMD(i16vec2);" - "i16vec3 minInvocationsNonUniformAMD(i16vec3);" - "i16vec4 minInvocationsNonUniformAMD(i16vec4);" - - "uint16_t minInvocationsNonUniformAMD(uint16_t);" - "u16vec2 minInvocationsNonUniformAMD(u16vec2);" - "u16vec3 minInvocationsNonUniformAMD(u16vec3);" - "u16vec4 minInvocationsNonUniformAMD(u16vec4);" - - "float minInvocationsInclusiveScanNonUniformAMD(float);" - "vec2 minInvocationsInclusiveScanNonUniformAMD(vec2);" - "vec3 minInvocationsInclusiveScanNonUniformAMD(vec3);" - "vec4 minInvocationsInclusiveScanNonUniformAMD(vec4);" - - "int minInvocationsInclusiveScanNonUniformAMD(int);" - "ivec2 minInvocationsInclusiveScanNonUniformAMD(ivec2);" - "ivec3 minInvocationsInclusiveScanNonUniformAMD(ivec3);" - "ivec4 minInvocationsInclusiveScanNonUniformAMD(ivec4);" - - "uint minInvocationsInclusiveScanNonUniformAMD(uint);" - "uvec2 minInvocationsInclusiveScanNonUniformAMD(uvec2);" - "uvec3 minInvocationsInclusiveScanNonUniformAMD(uvec3);" - "uvec4 minInvocationsInclusiveScanNonUniformAMD(uvec4);" - - "double minInvocationsInclusiveScanNonUniformAMD(double);" - "dvec2 minInvocationsInclusiveScanNonUniformAMD(dvec2);" - "dvec3 minInvocationsInclusiveScanNonUniformAMD(dvec3);" - "dvec4 minInvocationsInclusiveScanNonUniformAMD(dvec4);" - - "int64_t minInvocationsInclusiveScanNonUniformAMD(int64_t);" - "i64vec2 minInvocationsInclusiveScanNonUniformAMD(i64vec2);" - "i64vec3 minInvocationsInclusiveScanNonUniformAMD(i64vec3);" - "i64vec4 minInvocationsInclusiveScanNonUniformAMD(i64vec4);" - - "uint64_t minInvocationsInclusiveScanNonUniformAMD(uint64_t);" - "u64vec2 minInvocationsInclusiveScanNonUniformAMD(u64vec2);" - "u64vec3 minInvocationsInclusiveScanNonUniformAMD(u64vec3);" - "u64vec4 minInvocationsInclusiveScanNonUniformAMD(u64vec4);" - - "float16_t minInvocationsInclusiveScanNonUniformAMD(float16_t);" - "f16vec2 minInvocationsInclusiveScanNonUniformAMD(f16vec2);" - "f16vec3 minInvocationsInclusiveScanNonUniformAMD(f16vec3);" - "f16vec4 minInvocationsInclusiveScanNonUniformAMD(f16vec4);" - - "int16_t minInvocationsInclusiveScanNonUniformAMD(int16_t);" - "i16vec2 minInvocationsInclusiveScanNonUniformAMD(i16vec2);" - "i16vec3 minInvocationsInclusiveScanNonUniformAMD(i16vec3);" - "i16vec4 minInvocationsInclusiveScanNonUniformAMD(i16vec4);" - - "uint16_t minInvocationsInclusiveScanNonUniformAMD(uint16_t);" - "u16vec2 minInvocationsInclusiveScanNonUniformAMD(u16vec2);" - "u16vec3 minInvocationsInclusiveScanNonUniformAMD(u16vec3);" - "u16vec4 minInvocationsInclusiveScanNonUniformAMD(u16vec4);" - - "float minInvocationsExclusiveScanNonUniformAMD(float);" - "vec2 minInvocationsExclusiveScanNonUniformAMD(vec2);" - "vec3 minInvocationsExclusiveScanNonUniformAMD(vec3);" - "vec4 minInvocationsExclusiveScanNonUniformAMD(vec4);" - - "int minInvocationsExclusiveScanNonUniformAMD(int);" - "ivec2 minInvocationsExclusiveScanNonUniformAMD(ivec2);" - "ivec3 minInvocationsExclusiveScanNonUniformAMD(ivec3);" - "ivec4 minInvocationsExclusiveScanNonUniformAMD(ivec4);" - - "uint minInvocationsExclusiveScanNonUniformAMD(uint);" - "uvec2 minInvocationsExclusiveScanNonUniformAMD(uvec2);" - "uvec3 minInvocationsExclusiveScanNonUniformAMD(uvec3);" - "uvec4 minInvocationsExclusiveScanNonUniformAMD(uvec4);" - - "double minInvocationsExclusiveScanNonUniformAMD(double);" - "dvec2 minInvocationsExclusiveScanNonUniformAMD(dvec2);" - "dvec3 minInvocationsExclusiveScanNonUniformAMD(dvec3);" - "dvec4 minInvocationsExclusiveScanNonUniformAMD(dvec4);" - - "int64_t minInvocationsExclusiveScanNonUniformAMD(int64_t);" - "i64vec2 minInvocationsExclusiveScanNonUniformAMD(i64vec2);" - "i64vec3 minInvocationsExclusiveScanNonUniformAMD(i64vec3);" - "i64vec4 minInvocationsExclusiveScanNonUniformAMD(i64vec4);" - - "uint64_t minInvocationsExclusiveScanNonUniformAMD(uint64_t);" - "u64vec2 minInvocationsExclusiveScanNonUniformAMD(u64vec2);" - "u64vec3 minInvocationsExclusiveScanNonUniformAMD(u64vec3);" - "u64vec4 minInvocationsExclusiveScanNonUniformAMD(u64vec4);" - - "float16_t minInvocationsExclusiveScanNonUniformAMD(float16_t);" - "f16vec2 minInvocationsExclusiveScanNonUniformAMD(f16vec2);" - "f16vec3 minInvocationsExclusiveScanNonUniformAMD(f16vec3);" - "f16vec4 minInvocationsExclusiveScanNonUniformAMD(f16vec4);" - - "int16_t minInvocationsExclusiveScanNonUniformAMD(int16_t);" - "i16vec2 minInvocationsExclusiveScanNonUniformAMD(i16vec2);" - "i16vec3 minInvocationsExclusiveScanNonUniformAMD(i16vec3);" - "i16vec4 minInvocationsExclusiveScanNonUniformAMD(i16vec4);" - - "uint16_t minInvocationsExclusiveScanNonUniformAMD(uint16_t);" - "u16vec2 minInvocationsExclusiveScanNonUniformAMD(u16vec2);" - "u16vec3 minInvocationsExclusiveScanNonUniformAMD(u16vec3);" - "u16vec4 minInvocationsExclusiveScanNonUniformAMD(u16vec4);" - - "float maxInvocationsNonUniformAMD(float);" - "vec2 maxInvocationsNonUniformAMD(vec2);" - "vec3 maxInvocationsNonUniformAMD(vec3);" - "vec4 maxInvocationsNonUniformAMD(vec4);" - - "int maxInvocationsNonUniformAMD(int);" - "ivec2 maxInvocationsNonUniformAMD(ivec2);" - "ivec3 maxInvocationsNonUniformAMD(ivec3);" - "ivec4 maxInvocationsNonUniformAMD(ivec4);" - - "uint maxInvocationsNonUniformAMD(uint);" - "uvec2 maxInvocationsNonUniformAMD(uvec2);" - "uvec3 maxInvocationsNonUniformAMD(uvec3);" - "uvec4 maxInvocationsNonUniformAMD(uvec4);" - - "double maxInvocationsNonUniformAMD(double);" - "dvec2 maxInvocationsNonUniformAMD(dvec2);" - "dvec3 maxInvocationsNonUniformAMD(dvec3);" - "dvec4 maxInvocationsNonUniformAMD(dvec4);" - - "int64_t maxInvocationsNonUniformAMD(int64_t);" - "i64vec2 maxInvocationsNonUniformAMD(i64vec2);" - "i64vec3 maxInvocationsNonUniformAMD(i64vec3);" - "i64vec4 maxInvocationsNonUniformAMD(i64vec4);" - - "uint64_t maxInvocationsNonUniformAMD(uint64_t);" - "u64vec2 maxInvocationsNonUniformAMD(u64vec2);" - "u64vec3 maxInvocationsNonUniformAMD(u64vec3);" - "u64vec4 maxInvocationsNonUniformAMD(u64vec4);" - - "float16_t maxInvocationsNonUniformAMD(float16_t);" - "f16vec2 maxInvocationsNonUniformAMD(f16vec2);" - "f16vec3 maxInvocationsNonUniformAMD(f16vec3);" - "f16vec4 maxInvocationsNonUniformAMD(f16vec4);" - - "int16_t maxInvocationsNonUniformAMD(int16_t);" - "i16vec2 maxInvocationsNonUniformAMD(i16vec2);" - "i16vec3 maxInvocationsNonUniformAMD(i16vec3);" - "i16vec4 maxInvocationsNonUniformAMD(i16vec4);" - - "uint16_t maxInvocationsNonUniformAMD(uint16_t);" - "u16vec2 maxInvocationsNonUniformAMD(u16vec2);" - "u16vec3 maxInvocationsNonUniformAMD(u16vec3);" - "u16vec4 maxInvocationsNonUniformAMD(u16vec4);" - - "float maxInvocationsInclusiveScanNonUniformAMD(float);" - "vec2 maxInvocationsInclusiveScanNonUniformAMD(vec2);" - "vec3 maxInvocationsInclusiveScanNonUniformAMD(vec3);" - "vec4 maxInvocationsInclusiveScanNonUniformAMD(vec4);" - - "int maxInvocationsInclusiveScanNonUniformAMD(int);" - "ivec2 maxInvocationsInclusiveScanNonUniformAMD(ivec2);" - "ivec3 maxInvocationsInclusiveScanNonUniformAMD(ivec3);" - "ivec4 maxInvocationsInclusiveScanNonUniformAMD(ivec4);" - - "uint maxInvocationsInclusiveScanNonUniformAMD(uint);" - "uvec2 maxInvocationsInclusiveScanNonUniformAMD(uvec2);" - "uvec3 maxInvocationsInclusiveScanNonUniformAMD(uvec3);" - "uvec4 maxInvocationsInclusiveScanNonUniformAMD(uvec4);" - - "double maxInvocationsInclusiveScanNonUniformAMD(double);" - "dvec2 maxInvocationsInclusiveScanNonUniformAMD(dvec2);" - "dvec3 maxInvocationsInclusiveScanNonUniformAMD(dvec3);" - "dvec4 maxInvocationsInclusiveScanNonUniformAMD(dvec4);" - - "int64_t maxInvocationsInclusiveScanNonUniformAMD(int64_t);" - "i64vec2 maxInvocationsInclusiveScanNonUniformAMD(i64vec2);" - "i64vec3 maxInvocationsInclusiveScanNonUniformAMD(i64vec3);" - "i64vec4 maxInvocationsInclusiveScanNonUniformAMD(i64vec4);" - - "uint64_t maxInvocationsInclusiveScanNonUniformAMD(uint64_t);" - "u64vec2 maxInvocationsInclusiveScanNonUniformAMD(u64vec2);" - "u64vec3 maxInvocationsInclusiveScanNonUniformAMD(u64vec3);" - "u64vec4 maxInvocationsInclusiveScanNonUniformAMD(u64vec4);" - - "float16_t maxInvocationsInclusiveScanNonUniformAMD(float16_t);" - "f16vec2 maxInvocationsInclusiveScanNonUniformAMD(f16vec2);" - "f16vec3 maxInvocationsInclusiveScanNonUniformAMD(f16vec3);" - "f16vec4 maxInvocationsInclusiveScanNonUniformAMD(f16vec4);" - - "int16_t maxInvocationsInclusiveScanNonUniformAMD(int16_t);" - "i16vec2 maxInvocationsInclusiveScanNonUniformAMD(i16vec2);" - "i16vec3 maxInvocationsInclusiveScanNonUniformAMD(i16vec3);" - "i16vec4 maxInvocationsInclusiveScanNonUniformAMD(i16vec4);" - - "uint16_t maxInvocationsInclusiveScanNonUniformAMD(uint16_t);" - "u16vec2 maxInvocationsInclusiveScanNonUniformAMD(u16vec2);" - "u16vec3 maxInvocationsInclusiveScanNonUniformAMD(u16vec3);" - "u16vec4 maxInvocationsInclusiveScanNonUniformAMD(u16vec4);" - - "float maxInvocationsExclusiveScanNonUniformAMD(float);" - "vec2 maxInvocationsExclusiveScanNonUniformAMD(vec2);" - "vec3 maxInvocationsExclusiveScanNonUniformAMD(vec3);" - "vec4 maxInvocationsExclusiveScanNonUniformAMD(vec4);" - - "int maxInvocationsExclusiveScanNonUniformAMD(int);" - "ivec2 maxInvocationsExclusiveScanNonUniformAMD(ivec2);" - "ivec3 maxInvocationsExclusiveScanNonUniformAMD(ivec3);" - "ivec4 maxInvocationsExclusiveScanNonUniformAMD(ivec4);" - - "uint maxInvocationsExclusiveScanNonUniformAMD(uint);" - "uvec2 maxInvocationsExclusiveScanNonUniformAMD(uvec2);" - "uvec3 maxInvocationsExclusiveScanNonUniformAMD(uvec3);" - "uvec4 maxInvocationsExclusiveScanNonUniformAMD(uvec4);" - - "double maxInvocationsExclusiveScanNonUniformAMD(double);" - "dvec2 maxInvocationsExclusiveScanNonUniformAMD(dvec2);" - "dvec3 maxInvocationsExclusiveScanNonUniformAMD(dvec3);" - "dvec4 maxInvocationsExclusiveScanNonUniformAMD(dvec4);" - - "int64_t maxInvocationsExclusiveScanNonUniformAMD(int64_t);" - "i64vec2 maxInvocationsExclusiveScanNonUniformAMD(i64vec2);" - "i64vec3 maxInvocationsExclusiveScanNonUniformAMD(i64vec3);" - "i64vec4 maxInvocationsExclusiveScanNonUniformAMD(i64vec4);" - - "uint64_t maxInvocationsExclusiveScanNonUniformAMD(uint64_t);" - "u64vec2 maxInvocationsExclusiveScanNonUniformAMD(u64vec2);" - "u64vec3 maxInvocationsExclusiveScanNonUniformAMD(u64vec3);" - "u64vec4 maxInvocationsExclusiveScanNonUniformAMD(u64vec4);" - - "float16_t maxInvocationsExclusiveScanNonUniformAMD(float16_t);" - "f16vec2 maxInvocationsExclusiveScanNonUniformAMD(f16vec2);" - "f16vec3 maxInvocationsExclusiveScanNonUniformAMD(f16vec3);" - "f16vec4 maxInvocationsExclusiveScanNonUniformAMD(f16vec4);" - - "int16_t maxInvocationsExclusiveScanNonUniformAMD(int16_t);" - "i16vec2 maxInvocationsExclusiveScanNonUniformAMD(i16vec2);" - "i16vec3 maxInvocationsExclusiveScanNonUniformAMD(i16vec3);" - "i16vec4 maxInvocationsExclusiveScanNonUniformAMD(i16vec4);" - - "uint16_t maxInvocationsExclusiveScanNonUniformAMD(uint16_t);" - "u16vec2 maxInvocationsExclusiveScanNonUniformAMD(u16vec2);" - "u16vec3 maxInvocationsExclusiveScanNonUniformAMD(u16vec3);" - "u16vec4 maxInvocationsExclusiveScanNonUniformAMD(u16vec4);" - - "float addInvocationsNonUniformAMD(float);" - "vec2 addInvocationsNonUniformAMD(vec2);" - "vec3 addInvocationsNonUniformAMD(vec3);" - "vec4 addInvocationsNonUniformAMD(vec4);" - - "int addInvocationsNonUniformAMD(int);" - "ivec2 addInvocationsNonUniformAMD(ivec2);" - "ivec3 addInvocationsNonUniformAMD(ivec3);" - "ivec4 addInvocationsNonUniformAMD(ivec4);" - - "uint addInvocationsNonUniformAMD(uint);" - "uvec2 addInvocationsNonUniformAMD(uvec2);" - "uvec3 addInvocationsNonUniformAMD(uvec3);" - "uvec4 addInvocationsNonUniformAMD(uvec4);" - - "double addInvocationsNonUniformAMD(double);" - "dvec2 addInvocationsNonUniformAMD(dvec2);" - "dvec3 addInvocationsNonUniformAMD(dvec3);" - "dvec4 addInvocationsNonUniformAMD(dvec4);" - - "int64_t addInvocationsNonUniformAMD(int64_t);" - "i64vec2 addInvocationsNonUniformAMD(i64vec2);" - "i64vec3 addInvocationsNonUniformAMD(i64vec3);" - "i64vec4 addInvocationsNonUniformAMD(i64vec4);" - - "uint64_t addInvocationsNonUniformAMD(uint64_t);" - "u64vec2 addInvocationsNonUniformAMD(u64vec2);" - "u64vec3 addInvocationsNonUniformAMD(u64vec3);" - "u64vec4 addInvocationsNonUniformAMD(u64vec4);" - - "float16_t addInvocationsNonUniformAMD(float16_t);" - "f16vec2 addInvocationsNonUniformAMD(f16vec2);" - "f16vec3 addInvocationsNonUniformAMD(f16vec3);" - "f16vec4 addInvocationsNonUniformAMD(f16vec4);" - - "int16_t addInvocationsNonUniformAMD(int16_t);" - "i16vec2 addInvocationsNonUniformAMD(i16vec2);" - "i16vec3 addInvocationsNonUniformAMD(i16vec3);" - "i16vec4 addInvocationsNonUniformAMD(i16vec4);" - - "uint16_t addInvocationsNonUniformAMD(uint16_t);" - "u16vec2 addInvocationsNonUniformAMD(u16vec2);" - "u16vec3 addInvocationsNonUniformAMD(u16vec3);" - "u16vec4 addInvocationsNonUniformAMD(u16vec4);" - - "float addInvocationsInclusiveScanNonUniformAMD(float);" - "vec2 addInvocationsInclusiveScanNonUniformAMD(vec2);" - "vec3 addInvocationsInclusiveScanNonUniformAMD(vec3);" - "vec4 addInvocationsInclusiveScanNonUniformAMD(vec4);" - - "int addInvocationsInclusiveScanNonUniformAMD(int);" - "ivec2 addInvocationsInclusiveScanNonUniformAMD(ivec2);" - "ivec3 addInvocationsInclusiveScanNonUniformAMD(ivec3);" - "ivec4 addInvocationsInclusiveScanNonUniformAMD(ivec4);" - - "uint addInvocationsInclusiveScanNonUniformAMD(uint);" - "uvec2 addInvocationsInclusiveScanNonUniformAMD(uvec2);" - "uvec3 addInvocationsInclusiveScanNonUniformAMD(uvec3);" - "uvec4 addInvocationsInclusiveScanNonUniformAMD(uvec4);" - - "double addInvocationsInclusiveScanNonUniformAMD(double);" - "dvec2 addInvocationsInclusiveScanNonUniformAMD(dvec2);" - "dvec3 addInvocationsInclusiveScanNonUniformAMD(dvec3);" - "dvec4 addInvocationsInclusiveScanNonUniformAMD(dvec4);" - - "int64_t addInvocationsInclusiveScanNonUniformAMD(int64_t);" - "i64vec2 addInvocationsInclusiveScanNonUniformAMD(i64vec2);" - "i64vec3 addInvocationsInclusiveScanNonUniformAMD(i64vec3);" - "i64vec4 addInvocationsInclusiveScanNonUniformAMD(i64vec4);" - - "uint64_t addInvocationsInclusiveScanNonUniformAMD(uint64_t);" - "u64vec2 addInvocationsInclusiveScanNonUniformAMD(u64vec2);" - "u64vec3 addInvocationsInclusiveScanNonUniformAMD(u64vec3);" - "u64vec4 addInvocationsInclusiveScanNonUniformAMD(u64vec4);" - - "float16_t addInvocationsInclusiveScanNonUniformAMD(float16_t);" - "f16vec2 addInvocationsInclusiveScanNonUniformAMD(f16vec2);" - "f16vec3 addInvocationsInclusiveScanNonUniformAMD(f16vec3);" - "f16vec4 addInvocationsInclusiveScanNonUniformAMD(f16vec4);" - - "int16_t addInvocationsInclusiveScanNonUniformAMD(int16_t);" - "i16vec2 addInvocationsInclusiveScanNonUniformAMD(i16vec2);" - "i16vec3 addInvocationsInclusiveScanNonUniformAMD(i16vec3);" - "i16vec4 addInvocationsInclusiveScanNonUniformAMD(i16vec4);" - - "uint16_t addInvocationsInclusiveScanNonUniformAMD(uint16_t);" - "u16vec2 addInvocationsInclusiveScanNonUniformAMD(u16vec2);" - "u16vec3 addInvocationsInclusiveScanNonUniformAMD(u16vec3);" - "u16vec4 addInvocationsInclusiveScanNonUniformAMD(u16vec4);" - - "float addInvocationsExclusiveScanNonUniformAMD(float);" - "vec2 addInvocationsExclusiveScanNonUniformAMD(vec2);" - "vec3 addInvocationsExclusiveScanNonUniformAMD(vec3);" - "vec4 addInvocationsExclusiveScanNonUniformAMD(vec4);" - - "int addInvocationsExclusiveScanNonUniformAMD(int);" - "ivec2 addInvocationsExclusiveScanNonUniformAMD(ivec2);" - "ivec3 addInvocationsExclusiveScanNonUniformAMD(ivec3);" - "ivec4 addInvocationsExclusiveScanNonUniformAMD(ivec4);" - - "uint addInvocationsExclusiveScanNonUniformAMD(uint);" - "uvec2 addInvocationsExclusiveScanNonUniformAMD(uvec2);" - "uvec3 addInvocationsExclusiveScanNonUniformAMD(uvec3);" - "uvec4 addInvocationsExclusiveScanNonUniformAMD(uvec4);" - - "double addInvocationsExclusiveScanNonUniformAMD(double);" - "dvec2 addInvocationsExclusiveScanNonUniformAMD(dvec2);" - "dvec3 addInvocationsExclusiveScanNonUniformAMD(dvec3);" - "dvec4 addInvocationsExclusiveScanNonUniformAMD(dvec4);" - - "int64_t addInvocationsExclusiveScanNonUniformAMD(int64_t);" - "i64vec2 addInvocationsExclusiveScanNonUniformAMD(i64vec2);" - "i64vec3 addInvocationsExclusiveScanNonUniformAMD(i64vec3);" - "i64vec4 addInvocationsExclusiveScanNonUniformAMD(i64vec4);" - - "uint64_t addInvocationsExclusiveScanNonUniformAMD(uint64_t);" - "u64vec2 addInvocationsExclusiveScanNonUniformAMD(u64vec2);" - "u64vec3 addInvocationsExclusiveScanNonUniformAMD(u64vec3);" - "u64vec4 addInvocationsExclusiveScanNonUniformAMD(u64vec4);" - - "float16_t addInvocationsExclusiveScanNonUniformAMD(float16_t);" - "f16vec2 addInvocationsExclusiveScanNonUniformAMD(f16vec2);" - "f16vec3 addInvocationsExclusiveScanNonUniformAMD(f16vec3);" - "f16vec4 addInvocationsExclusiveScanNonUniformAMD(f16vec4);" - - "int16_t addInvocationsExclusiveScanNonUniformAMD(int16_t);" - "i16vec2 addInvocationsExclusiveScanNonUniformAMD(i16vec2);" - "i16vec3 addInvocationsExclusiveScanNonUniformAMD(i16vec3);" - "i16vec4 addInvocationsExclusiveScanNonUniformAMD(i16vec4);" - - "uint16_t addInvocationsExclusiveScanNonUniformAMD(uint16_t);" - "u16vec2 addInvocationsExclusiveScanNonUniformAMD(u16vec2);" - "u16vec3 addInvocationsExclusiveScanNonUniformAMD(u16vec3);" - "u16vec4 addInvocationsExclusiveScanNonUniformAMD(u16vec4);" - - "float swizzleInvocationsAMD(float, uvec4);" - "vec2 swizzleInvocationsAMD(vec2, uvec4);" - "vec3 swizzleInvocationsAMD(vec3, uvec4);" - "vec4 swizzleInvocationsAMD(vec4, uvec4);" - - "int swizzleInvocationsAMD(int, uvec4);" - "ivec2 swizzleInvocationsAMD(ivec2, uvec4);" - "ivec3 swizzleInvocationsAMD(ivec3, uvec4);" - "ivec4 swizzleInvocationsAMD(ivec4, uvec4);" - - "uint swizzleInvocationsAMD(uint, uvec4);" - "uvec2 swizzleInvocationsAMD(uvec2, uvec4);" - "uvec3 swizzleInvocationsAMD(uvec3, uvec4);" - "uvec4 swizzleInvocationsAMD(uvec4, uvec4);" - - "float swizzleInvocationsMaskedAMD(float, uvec3);" - "vec2 swizzleInvocationsMaskedAMD(vec2, uvec3);" - "vec3 swizzleInvocationsMaskedAMD(vec3, uvec3);" - "vec4 swizzleInvocationsMaskedAMD(vec4, uvec3);" - - "int swizzleInvocationsMaskedAMD(int, uvec3);" - "ivec2 swizzleInvocationsMaskedAMD(ivec2, uvec3);" - "ivec3 swizzleInvocationsMaskedAMD(ivec3, uvec3);" - "ivec4 swizzleInvocationsMaskedAMD(ivec4, uvec3);" - - "uint swizzleInvocationsMaskedAMD(uint, uvec3);" - "uvec2 swizzleInvocationsMaskedAMD(uvec2, uvec3);" - "uvec3 swizzleInvocationsMaskedAMD(uvec3, uvec3);" - "uvec4 swizzleInvocationsMaskedAMD(uvec4, uvec3);" - - "float writeInvocationAMD(float, float, uint);" - "vec2 writeInvocationAMD(vec2, vec2, uint);" - "vec3 writeInvocationAMD(vec3, vec3, uint);" - "vec4 writeInvocationAMD(vec4, vec4, uint);" - - "int writeInvocationAMD(int, int, uint);" - "ivec2 writeInvocationAMD(ivec2, ivec2, uint);" - "ivec3 writeInvocationAMD(ivec3, ivec3, uint);" - "ivec4 writeInvocationAMD(ivec4, ivec4, uint);" - - "uint writeInvocationAMD(uint, uint, uint);" - "uvec2 writeInvocationAMD(uvec2, uvec2, uint);" - "uvec3 writeInvocationAMD(uvec3, uvec3, uint);" - "uvec4 writeInvocationAMD(uvec4, uvec4, uint);" - - "uint mbcntAMD(uint64_t);" - - "\n"); - } - - // GL_AMD_gcn_shader - if (profile != EEsProfile && version >= 450) { - commonBuiltins.append( - "float cubeFaceIndexAMD(vec3);" - "vec2 cubeFaceCoordAMD(vec3);" - "uint64_t timeAMD();" - - "\n"); - } - - // GL_AMD_shader_fragment_mask - if (profile != EEsProfile && version >= 450) { - commonBuiltins.append( - "uint fragmentMaskFetchAMD(sampler2DMS, ivec2);" - "uint fragmentMaskFetchAMD(isampler2DMS, ivec2);" - "uint fragmentMaskFetchAMD(usampler2DMS, ivec2);" - - "uint fragmentMaskFetchAMD(sampler2DMSArray, ivec3);" - "uint fragmentMaskFetchAMD(isampler2DMSArray, ivec3);" - "uint fragmentMaskFetchAMD(usampler2DMSArray, ivec3);" - - "vec4 fragmentFetchAMD(sampler2DMS, ivec2, uint);" - "ivec4 fragmentFetchAMD(isampler2DMS, ivec2, uint);" - "uvec4 fragmentFetchAMD(usampler2DMS, ivec2, uint);" - - "vec4 fragmentFetchAMD(sampler2DMSArray, ivec3, uint);" - "ivec4 fragmentFetchAMD(isampler2DMSArray, ivec3, uint);" - "uvec4 fragmentFetchAMD(usampler2DMSArray, ivec3, uint);" - - "\n"); - } - -#endif // AMD_EXTENSIONS - - // GL_AMD_gpu_shader_half_float/Explicit types - if (profile != EEsProfile && version >= 450) { - commonBuiltins.append( - "float16_t radians(float16_t);" - "f16vec2 radians(f16vec2);" - "f16vec3 radians(f16vec3);" - "f16vec4 radians(f16vec4);" - - "float16_t degrees(float16_t);" - "f16vec2 degrees(f16vec2);" - "f16vec3 degrees(f16vec3);" - "f16vec4 degrees(f16vec4);" - - "float16_t sin(float16_t);" - "f16vec2 sin(f16vec2);" - "f16vec3 sin(f16vec3);" - "f16vec4 sin(f16vec4);" - - "float16_t cos(float16_t);" - "f16vec2 cos(f16vec2);" - "f16vec3 cos(f16vec3);" - "f16vec4 cos(f16vec4);" - - "float16_t tan(float16_t);" - "f16vec2 tan(f16vec2);" - "f16vec3 tan(f16vec3);" - "f16vec4 tan(f16vec4);" - - "float16_t asin(float16_t);" - "f16vec2 asin(f16vec2);" - "f16vec3 asin(f16vec3);" - "f16vec4 asin(f16vec4);" - - "float16_t acos(float16_t);" - "f16vec2 acos(f16vec2);" - "f16vec3 acos(f16vec3);" - "f16vec4 acos(f16vec4);" - - "float16_t atan(float16_t, float16_t);" - "f16vec2 atan(f16vec2, f16vec2);" - "f16vec3 atan(f16vec3, f16vec3);" - "f16vec4 atan(f16vec4, f16vec4);" - - "float16_t atan(float16_t);" - "f16vec2 atan(f16vec2);" - "f16vec3 atan(f16vec3);" - "f16vec4 atan(f16vec4);" - - "float16_t sinh(float16_t);" - "f16vec2 sinh(f16vec2);" - "f16vec3 sinh(f16vec3);" - "f16vec4 sinh(f16vec4);" - - "float16_t cosh(float16_t);" - "f16vec2 cosh(f16vec2);" - "f16vec3 cosh(f16vec3);" - "f16vec4 cosh(f16vec4);" - - "float16_t tanh(float16_t);" - "f16vec2 tanh(f16vec2);" - "f16vec3 tanh(f16vec3);" - "f16vec4 tanh(f16vec4);" - - "float16_t asinh(float16_t);" - "f16vec2 asinh(f16vec2);" - "f16vec3 asinh(f16vec3);" - "f16vec4 asinh(f16vec4);" - - "float16_t acosh(float16_t);" - "f16vec2 acosh(f16vec2);" - "f16vec3 acosh(f16vec3);" - "f16vec4 acosh(f16vec4);" - - "float16_t atanh(float16_t);" - "f16vec2 atanh(f16vec2);" - "f16vec3 atanh(f16vec3);" - "f16vec4 atanh(f16vec4);" - - "float16_t pow(float16_t, float16_t);" - "f16vec2 pow(f16vec2, f16vec2);" - "f16vec3 pow(f16vec3, f16vec3);" - "f16vec4 pow(f16vec4, f16vec4);" - - "float16_t exp(float16_t);" - "f16vec2 exp(f16vec2);" - "f16vec3 exp(f16vec3);" - "f16vec4 exp(f16vec4);" - - "float16_t log(float16_t);" - "f16vec2 log(f16vec2);" - "f16vec3 log(f16vec3);" - "f16vec4 log(f16vec4);" - - "float16_t exp2(float16_t);" - "f16vec2 exp2(f16vec2);" - "f16vec3 exp2(f16vec3);" - "f16vec4 exp2(f16vec4);" - - "float16_t log2(float16_t);" - "f16vec2 log2(f16vec2);" - "f16vec3 log2(f16vec3);" - "f16vec4 log2(f16vec4);" - - "float16_t sqrt(float16_t);" - "f16vec2 sqrt(f16vec2);" - "f16vec3 sqrt(f16vec3);" - "f16vec4 sqrt(f16vec4);" - - "float16_t inversesqrt(float16_t);" - "f16vec2 inversesqrt(f16vec2);" - "f16vec3 inversesqrt(f16vec3);" - "f16vec4 inversesqrt(f16vec4);" - - "float16_t abs(float16_t);" - "f16vec2 abs(f16vec2);" - "f16vec3 abs(f16vec3);" - "f16vec4 abs(f16vec4);" - - "float16_t sign(float16_t);" - "f16vec2 sign(f16vec2);" - "f16vec3 sign(f16vec3);" - "f16vec4 sign(f16vec4);" - - "float16_t floor(float16_t);" - "f16vec2 floor(f16vec2);" - "f16vec3 floor(f16vec3);" - "f16vec4 floor(f16vec4);" - - "float16_t trunc(float16_t);" - "f16vec2 trunc(f16vec2);" - "f16vec3 trunc(f16vec3);" - "f16vec4 trunc(f16vec4);" - - "float16_t round(float16_t);" - "f16vec2 round(f16vec2);" - "f16vec3 round(f16vec3);" - "f16vec4 round(f16vec4);" - - "float16_t roundEven(float16_t);" - "f16vec2 roundEven(f16vec2);" - "f16vec3 roundEven(f16vec3);" - "f16vec4 roundEven(f16vec4);" - - "float16_t ceil(float16_t);" - "f16vec2 ceil(f16vec2);" - "f16vec3 ceil(f16vec3);" - "f16vec4 ceil(f16vec4);" - - "float16_t fract(float16_t);" - "f16vec2 fract(f16vec2);" - "f16vec3 fract(f16vec3);" - "f16vec4 fract(f16vec4);" - - "float16_t mod(float16_t, float16_t);" - "f16vec2 mod(f16vec2, float16_t);" - "f16vec3 mod(f16vec3, float16_t);" - "f16vec4 mod(f16vec4, float16_t);" - "f16vec2 mod(f16vec2, f16vec2);" - "f16vec3 mod(f16vec3, f16vec3);" - "f16vec4 mod(f16vec4, f16vec4);" - - "float16_t modf(float16_t, out float16_t);" - "f16vec2 modf(f16vec2, out f16vec2);" - "f16vec3 modf(f16vec3, out f16vec3);" - "f16vec4 modf(f16vec4, out f16vec4);" - - "float16_t min(float16_t, float16_t);" - "f16vec2 min(f16vec2, float16_t);" - "f16vec3 min(f16vec3, float16_t);" - "f16vec4 min(f16vec4, float16_t);" - "f16vec2 min(f16vec2, f16vec2);" - "f16vec3 min(f16vec3, f16vec3);" - "f16vec4 min(f16vec4, f16vec4);" - - "float16_t max(float16_t, float16_t);" - "f16vec2 max(f16vec2, float16_t);" - "f16vec3 max(f16vec3, float16_t);" - "f16vec4 max(f16vec4, float16_t);" - "f16vec2 max(f16vec2, f16vec2);" - "f16vec3 max(f16vec3, f16vec3);" - "f16vec4 max(f16vec4, f16vec4);" - - "float16_t clamp(float16_t, float16_t, float16_t);" - "f16vec2 clamp(f16vec2, float16_t, float16_t);" - "f16vec3 clamp(f16vec3, float16_t, float16_t);" - "f16vec4 clamp(f16vec4, float16_t, float16_t);" - "f16vec2 clamp(f16vec2, f16vec2, f16vec2);" - "f16vec3 clamp(f16vec3, f16vec3, f16vec3);" - "f16vec4 clamp(f16vec4, f16vec4, f16vec4);" - - "float16_t mix(float16_t, float16_t, float16_t);" - "f16vec2 mix(f16vec2, f16vec2, float16_t);" - "f16vec3 mix(f16vec3, f16vec3, float16_t);" - "f16vec4 mix(f16vec4, f16vec4, float16_t);" - "f16vec2 mix(f16vec2, f16vec2, f16vec2);" - "f16vec3 mix(f16vec3, f16vec3, f16vec3);" - "f16vec4 mix(f16vec4, f16vec4, f16vec4);" - "float16_t mix(float16_t, float16_t, bool);" - "f16vec2 mix(f16vec2, f16vec2, bvec2);" - "f16vec3 mix(f16vec3, f16vec3, bvec3);" - "f16vec4 mix(f16vec4, f16vec4, bvec4);" - - "float16_t step(float16_t, float16_t);" - "f16vec2 step(f16vec2, f16vec2);" - "f16vec3 step(f16vec3, f16vec3);" - "f16vec4 step(f16vec4, f16vec4);" - "f16vec2 step(float16_t, f16vec2);" - "f16vec3 step(float16_t, f16vec3);" - "f16vec4 step(float16_t, f16vec4);" - - "float16_t smoothstep(float16_t, float16_t, float16_t);" - "f16vec2 smoothstep(f16vec2, f16vec2, f16vec2);" - "f16vec3 smoothstep(f16vec3, f16vec3, f16vec3);" - "f16vec4 smoothstep(f16vec4, f16vec4, f16vec4);" - "f16vec2 smoothstep(float16_t, float16_t, f16vec2);" - "f16vec3 smoothstep(float16_t, float16_t, f16vec3);" - "f16vec4 smoothstep(float16_t, float16_t, f16vec4);" - - "bool isnan(float16_t);" - "bvec2 isnan(f16vec2);" - "bvec3 isnan(f16vec3);" - "bvec4 isnan(f16vec4);" - - "bool isinf(float16_t);" - "bvec2 isinf(f16vec2);" - "bvec3 isinf(f16vec3);" - "bvec4 isinf(f16vec4);" - - "float16_t fma(float16_t, float16_t, float16_t);" - "f16vec2 fma(f16vec2, f16vec2, f16vec2);" - "f16vec3 fma(f16vec3, f16vec3, f16vec3);" - "f16vec4 fma(f16vec4, f16vec4, f16vec4);" - - "float16_t frexp(float16_t, out int);" - "f16vec2 frexp(f16vec2, out ivec2);" - "f16vec3 frexp(f16vec3, out ivec3);" - "f16vec4 frexp(f16vec4, out ivec4);" - - "float16_t ldexp(float16_t, in int);" - "f16vec2 ldexp(f16vec2, in ivec2);" - "f16vec3 ldexp(f16vec3, in ivec3);" - "f16vec4 ldexp(f16vec4, in ivec4);" - - "uint packFloat2x16(f16vec2);" - "f16vec2 unpackFloat2x16(uint);" - - "float16_t length(float16_t);" - "float16_t length(f16vec2);" - "float16_t length(f16vec3);" - "float16_t length(f16vec4);" - - "float16_t distance(float16_t, float16_t);" - "float16_t distance(f16vec2, f16vec2);" - "float16_t distance(f16vec3, f16vec3);" - "float16_t distance(f16vec4, f16vec4);" - - "float16_t dot(float16_t, float16_t);" - "float16_t dot(f16vec2, f16vec2);" - "float16_t dot(f16vec3, f16vec3);" - "float16_t dot(f16vec4, f16vec4);" - - "f16vec3 cross(f16vec3, f16vec3);" - - "float16_t normalize(float16_t);" - "f16vec2 normalize(f16vec2);" - "f16vec3 normalize(f16vec3);" - "f16vec4 normalize(f16vec4);" - - "float16_t faceforward(float16_t, float16_t, float16_t);" - "f16vec2 faceforward(f16vec2, f16vec2, f16vec2);" - "f16vec3 faceforward(f16vec3, f16vec3, f16vec3);" - "f16vec4 faceforward(f16vec4, f16vec4, f16vec4);" - - "float16_t reflect(float16_t, float16_t);" - "f16vec2 reflect(f16vec2, f16vec2);" - "f16vec3 reflect(f16vec3, f16vec3);" - "f16vec4 reflect(f16vec4, f16vec4);" - - "float16_t refract(float16_t, float16_t, float16_t);" - "f16vec2 refract(f16vec2, f16vec2, float16_t);" - "f16vec3 refract(f16vec3, f16vec3, float16_t);" - "f16vec4 refract(f16vec4, f16vec4, float16_t);" - - "f16mat2 matrixCompMult(f16mat2, f16mat2);" - "f16mat3 matrixCompMult(f16mat3, f16mat3);" - "f16mat4 matrixCompMult(f16mat4, f16mat4);" - "f16mat2x3 matrixCompMult(f16mat2x3, f16mat2x3);" - "f16mat2x4 matrixCompMult(f16mat2x4, f16mat2x4);" - "f16mat3x2 matrixCompMult(f16mat3x2, f16mat3x2);" - "f16mat3x4 matrixCompMult(f16mat3x4, f16mat3x4);" - "f16mat4x2 matrixCompMult(f16mat4x2, f16mat4x2);" - "f16mat4x3 matrixCompMult(f16mat4x3, f16mat4x3);" - - "f16mat2 outerProduct(f16vec2, f16vec2);" - "f16mat3 outerProduct(f16vec3, f16vec3);" - "f16mat4 outerProduct(f16vec4, f16vec4);" - "f16mat2x3 outerProduct(f16vec3, f16vec2);" - "f16mat3x2 outerProduct(f16vec2, f16vec3);" - "f16mat2x4 outerProduct(f16vec4, f16vec2);" - "f16mat4x2 outerProduct(f16vec2, f16vec4);" - "f16mat3x4 outerProduct(f16vec4, f16vec3);" - "f16mat4x3 outerProduct(f16vec3, f16vec4);" - - "f16mat2 transpose(f16mat2);" - "f16mat3 transpose(f16mat3);" - "f16mat4 transpose(f16mat4);" - "f16mat2x3 transpose(f16mat3x2);" - "f16mat3x2 transpose(f16mat2x3);" - "f16mat2x4 transpose(f16mat4x2);" - "f16mat4x2 transpose(f16mat2x4);" - "f16mat3x4 transpose(f16mat4x3);" - "f16mat4x3 transpose(f16mat3x4);" - - "float16_t determinant(f16mat2);" - "float16_t determinant(f16mat3);" - "float16_t determinant(f16mat4);" - - "f16mat2 inverse(f16mat2);" - "f16mat3 inverse(f16mat3);" - "f16mat4 inverse(f16mat4);" - - "bvec2 lessThan(f16vec2, f16vec2);" - "bvec3 lessThan(f16vec3, f16vec3);" - "bvec4 lessThan(f16vec4, f16vec4);" - - "bvec2 lessThanEqual(f16vec2, f16vec2);" - "bvec3 lessThanEqual(f16vec3, f16vec3);" - "bvec4 lessThanEqual(f16vec4, f16vec4);" - - "bvec2 greaterThan(f16vec2, f16vec2);" - "bvec3 greaterThan(f16vec3, f16vec3);" - "bvec4 greaterThan(f16vec4, f16vec4);" - - "bvec2 greaterThanEqual(f16vec2, f16vec2);" - "bvec3 greaterThanEqual(f16vec3, f16vec3);" - "bvec4 greaterThanEqual(f16vec4, f16vec4);" - - "bvec2 equal(f16vec2, f16vec2);" - "bvec3 equal(f16vec3, f16vec3);" - "bvec4 equal(f16vec4, f16vec4);" - - "bvec2 notEqual(f16vec2, f16vec2);" - "bvec3 notEqual(f16vec3, f16vec3);" - "bvec4 notEqual(f16vec4, f16vec4);" - - "\n"); - } - - // Explicit types - if (profile != EEsProfile && version >= 450) { - commonBuiltins.append( - "int8_t abs(int8_t);" - "i8vec2 abs(i8vec2);" - "i8vec3 abs(i8vec3);" - "i8vec4 abs(i8vec4);" - - "int8_t sign(int8_t);" - "i8vec2 sign(i8vec2);" - "i8vec3 sign(i8vec3);" - "i8vec4 sign(i8vec4);" - - "int8_t min(int8_t x, int8_t y);" - "i8vec2 min(i8vec2 x, int8_t y);" - "i8vec3 min(i8vec3 x, int8_t y);" - "i8vec4 min(i8vec4 x, int8_t y);" - "i8vec2 min(i8vec2 x, i8vec2 y);" - "i8vec3 min(i8vec3 x, i8vec3 y);" - "i8vec4 min(i8vec4 x, i8vec4 y);" - - "uint8_t min(uint8_t x, uint8_t y);" - "u8vec2 min(u8vec2 x, uint8_t y);" - "u8vec3 min(u8vec3 x, uint8_t y);" - "u8vec4 min(u8vec4 x, uint8_t y);" - "u8vec2 min(u8vec2 x, u8vec2 y);" - "u8vec3 min(u8vec3 x, u8vec3 y);" - "u8vec4 min(u8vec4 x, u8vec4 y);" - - "int8_t max(int8_t x, int8_t y);" - "i8vec2 max(i8vec2 x, int8_t y);" - "i8vec3 max(i8vec3 x, int8_t y);" - "i8vec4 max(i8vec4 x, int8_t y);" - "i8vec2 max(i8vec2 x, i8vec2 y);" - "i8vec3 max(i8vec3 x, i8vec3 y);" - "i8vec4 max(i8vec4 x, i8vec4 y);" - - "uint8_t max(uint8_t x, uint8_t y);" - "u8vec2 max(u8vec2 x, uint8_t y);" - "u8vec3 max(u8vec3 x, uint8_t y);" - "u8vec4 max(u8vec4 x, uint8_t y);" - "u8vec2 max(u8vec2 x, u8vec2 y);" - "u8vec3 max(u8vec3 x, u8vec3 y);" - "u8vec4 max(u8vec4 x, u8vec4 y);" - - "int8_t clamp(int8_t x, int8_t minVal, int8_t maxVal);" - "i8vec2 clamp(i8vec2 x, int8_t minVal, int8_t maxVal);" - "i8vec3 clamp(i8vec3 x, int8_t minVal, int8_t maxVal);" - "i8vec4 clamp(i8vec4 x, int8_t minVal, int8_t maxVal);" - "i8vec2 clamp(i8vec2 x, i8vec2 minVal, i8vec2 maxVal);" - "i8vec3 clamp(i8vec3 x, i8vec3 minVal, i8vec3 maxVal);" - "i8vec4 clamp(i8vec4 x, i8vec4 minVal, i8vec4 maxVal);" - - "uint8_t clamp(uint8_t x, uint8_t minVal, uint8_t maxVal);" - "u8vec2 clamp(u8vec2 x, uint8_t minVal, uint8_t maxVal);" - "u8vec3 clamp(u8vec3 x, uint8_t minVal, uint8_t maxVal);" - "u8vec4 clamp(u8vec4 x, uint8_t minVal, uint8_t maxVal);" - "u8vec2 clamp(u8vec2 x, u8vec2 minVal, u8vec2 maxVal);" - "u8vec3 clamp(u8vec3 x, u8vec3 minVal, u8vec3 maxVal);" - "u8vec4 clamp(u8vec4 x, u8vec4 minVal, u8vec4 maxVal);" - - "int8_t mix(int8_t, int8_t, bool);" - "i8vec2 mix(i8vec2, i8vec2, bvec2);" - "i8vec3 mix(i8vec3, i8vec3, bvec3);" - "i8vec4 mix(i8vec4, i8vec4, bvec4);" - "uint8_t mix(uint8_t, uint8_t, bool);" - "u8vec2 mix(u8vec2, u8vec2, bvec2);" - "u8vec3 mix(u8vec3, u8vec3, bvec3);" - "u8vec4 mix(u8vec4, u8vec4, bvec4);" - - "bvec2 lessThan(i8vec2, i8vec2);" - "bvec3 lessThan(i8vec3, i8vec3);" - "bvec4 lessThan(i8vec4, i8vec4);" - "bvec2 lessThan(u8vec2, u8vec2);" - "bvec3 lessThan(u8vec3, u8vec3);" - "bvec4 lessThan(u8vec4, u8vec4);" - - "bvec2 lessThanEqual(i8vec2, i8vec2);" - "bvec3 lessThanEqual(i8vec3, i8vec3);" - "bvec4 lessThanEqual(i8vec4, i8vec4);" - "bvec2 lessThanEqual(u8vec2, u8vec2);" - "bvec3 lessThanEqual(u8vec3, u8vec3);" - "bvec4 lessThanEqual(u8vec4, u8vec4);" - - "bvec2 greaterThan(i8vec2, i8vec2);" - "bvec3 greaterThan(i8vec3, i8vec3);" - "bvec4 greaterThan(i8vec4, i8vec4);" - "bvec2 greaterThan(u8vec2, u8vec2);" - "bvec3 greaterThan(u8vec3, u8vec3);" - "bvec4 greaterThan(u8vec4, u8vec4);" - - "bvec2 greaterThanEqual(i8vec2, i8vec2);" - "bvec3 greaterThanEqual(i8vec3, i8vec3);" - "bvec4 greaterThanEqual(i8vec4, i8vec4);" - "bvec2 greaterThanEqual(u8vec2, u8vec2);" - "bvec3 greaterThanEqual(u8vec3, u8vec3);" - "bvec4 greaterThanEqual(u8vec4, u8vec4);" - - "bvec2 equal(i8vec2, i8vec2);" - "bvec3 equal(i8vec3, i8vec3);" - "bvec4 equal(i8vec4, i8vec4);" - "bvec2 equal(u8vec2, u8vec2);" - "bvec3 equal(u8vec3, u8vec3);" - "bvec4 equal(u8vec4, u8vec4);" - - "bvec2 notEqual(i8vec2, i8vec2);" - "bvec3 notEqual(i8vec3, i8vec3);" - "bvec4 notEqual(i8vec4, i8vec4);" - "bvec2 notEqual(u8vec2, u8vec2);" - "bvec3 notEqual(u8vec3, u8vec3);" - "bvec4 notEqual(u8vec4, u8vec4);" - - " int8_t bitfieldExtract( int8_t, int8_t, int8_t);" - "i8vec2 bitfieldExtract(i8vec2, int8_t, int8_t);" - "i8vec3 bitfieldExtract(i8vec3, int8_t, int8_t);" - "i8vec4 bitfieldExtract(i8vec4, int8_t, int8_t);" - - " uint8_t bitfieldExtract( uint8_t, int8_t, int8_t);" - "u8vec2 bitfieldExtract(u8vec2, int8_t, int8_t);" - "u8vec3 bitfieldExtract(u8vec3, int8_t, int8_t);" - "u8vec4 bitfieldExtract(u8vec4, int8_t, int8_t);" - - " int8_t bitfieldInsert( int8_t base, int8_t, int8_t, int8_t);" - "i8vec2 bitfieldInsert(i8vec2 base, i8vec2, int8_t, int8_t);" - "i8vec3 bitfieldInsert(i8vec3 base, i8vec3, int8_t, int8_t);" - "i8vec4 bitfieldInsert(i8vec4 base, i8vec4, int8_t, int8_t);" - - " uint8_t bitfieldInsert( uint8_t base, uint8_t, int8_t, int8_t);" - "u8vec2 bitfieldInsert(u8vec2 base, u8vec2, int8_t, int8_t);" - "u8vec3 bitfieldInsert(u8vec3 base, u8vec3, int8_t, int8_t);" - "u8vec4 bitfieldInsert(u8vec4 base, u8vec4, int8_t, int8_t);" - - " int8_t bitCount( int8_t);" - "i8vec2 bitCount(i8vec2);" - "i8vec3 bitCount(i8vec3);" - "i8vec4 bitCount(i8vec4);" - - " int8_t bitCount( uint8_t);" - "i8vec2 bitCount(u8vec2);" - "i8vec3 bitCount(u8vec3);" - "i8vec4 bitCount(u8vec4);" - - " int8_t findLSB( int8_t);" - "i8vec2 findLSB(i8vec2);" - "i8vec3 findLSB(i8vec3);" - "i8vec4 findLSB(i8vec4);" - - " int8_t findLSB( uint8_t);" - "i8vec2 findLSB(u8vec2);" - "i8vec3 findLSB(u8vec3);" - "i8vec4 findLSB(u8vec4);" - - " int8_t findMSB( int8_t);" - "i8vec2 findMSB(i8vec2);" - "i8vec3 findMSB(i8vec3);" - "i8vec4 findMSB(i8vec4);" - - " int8_t findMSB( uint8_t);" - "i8vec2 findMSB(u8vec2);" - "i8vec3 findMSB(u8vec3);" - "i8vec4 findMSB(u8vec4);" - - "int16_t abs(int16_t);" - "i16vec2 abs(i16vec2);" - "i16vec3 abs(i16vec3);" - "i16vec4 abs(i16vec4);" - - "int16_t sign(int16_t);" - "i16vec2 sign(i16vec2);" - "i16vec3 sign(i16vec3);" - "i16vec4 sign(i16vec4);" - - "int16_t min(int16_t x, int16_t y);" - "i16vec2 min(i16vec2 x, int16_t y);" - "i16vec3 min(i16vec3 x, int16_t y);" - "i16vec4 min(i16vec4 x, int16_t y);" - "i16vec2 min(i16vec2 x, i16vec2 y);" - "i16vec3 min(i16vec3 x, i16vec3 y);" - "i16vec4 min(i16vec4 x, i16vec4 y);" - - "uint16_t min(uint16_t x, uint16_t y);" - "u16vec2 min(u16vec2 x, uint16_t y);" - "u16vec3 min(u16vec3 x, uint16_t y);" - "u16vec4 min(u16vec4 x, uint16_t y);" - "u16vec2 min(u16vec2 x, u16vec2 y);" - "u16vec3 min(u16vec3 x, u16vec3 y);" - "u16vec4 min(u16vec4 x, u16vec4 y);" - - "int16_t max(int16_t x, int16_t y);" - "i16vec2 max(i16vec2 x, int16_t y);" - "i16vec3 max(i16vec3 x, int16_t y);" - "i16vec4 max(i16vec4 x, int16_t y);" - "i16vec2 max(i16vec2 x, i16vec2 y);" - "i16vec3 max(i16vec3 x, i16vec3 y);" - "i16vec4 max(i16vec4 x, i16vec4 y);" - - "uint16_t max(uint16_t x, uint16_t y);" - "u16vec2 max(u16vec2 x, uint16_t y);" - "u16vec3 max(u16vec3 x, uint16_t y);" - "u16vec4 max(u16vec4 x, uint16_t y);" - "u16vec2 max(u16vec2 x, u16vec2 y);" - "u16vec3 max(u16vec3 x, u16vec3 y);" - "u16vec4 max(u16vec4 x, u16vec4 y);" - - "int16_t clamp(int16_t x, int16_t minVal, int16_t maxVal);" - "i16vec2 clamp(i16vec2 x, int16_t minVal, int16_t maxVal);" - "i16vec3 clamp(i16vec3 x, int16_t minVal, int16_t maxVal);" - "i16vec4 clamp(i16vec4 x, int16_t minVal, int16_t maxVal);" - "i16vec2 clamp(i16vec2 x, i16vec2 minVal, i16vec2 maxVal);" - "i16vec3 clamp(i16vec3 x, i16vec3 minVal, i16vec3 maxVal);" - "i16vec4 clamp(i16vec4 x, i16vec4 minVal, i16vec4 maxVal);" - - "uint16_t clamp(uint16_t x, uint16_t minVal, uint16_t maxVal);" - "u16vec2 clamp(u16vec2 x, uint16_t minVal, uint16_t maxVal);" - "u16vec3 clamp(u16vec3 x, uint16_t minVal, uint16_t maxVal);" - "u16vec4 clamp(u16vec4 x, uint16_t minVal, uint16_t maxVal);" - "u16vec2 clamp(u16vec2 x, u16vec2 minVal, u16vec2 maxVal);" - "u16vec3 clamp(u16vec3 x, u16vec3 minVal, u16vec3 maxVal);" - "u16vec4 clamp(u16vec4 x, u16vec4 minVal, u16vec4 maxVal);" - - "int16_t mix(int16_t, int16_t, bool);" - "i16vec2 mix(i16vec2, i16vec2, bvec2);" - "i16vec3 mix(i16vec3, i16vec3, bvec3);" - "i16vec4 mix(i16vec4, i16vec4, bvec4);" - "uint16_t mix(uint16_t, uint16_t, bool);" - "u16vec2 mix(u16vec2, u16vec2, bvec2);" - "u16vec3 mix(u16vec3, u16vec3, bvec3);" - "u16vec4 mix(u16vec4, u16vec4, bvec4);" - - "float16_t frexp(float16_t, out int16_t);" - "f16vec2 frexp(f16vec2, out i16vec2);" - "f16vec3 frexp(f16vec3, out i16vec3);" - "f16vec4 frexp(f16vec4, out i16vec4);" - - "float16_t ldexp(float16_t, int16_t);" - "f16vec2 ldexp(f16vec2, i16vec2);" - "f16vec3 ldexp(f16vec3, i16vec3);" - "f16vec4 ldexp(f16vec4, i16vec4);" - - "int16_t halfBitsToInt16(float16_t);" - "i16vec2 halfBitsToInt16(f16vec2);" - "i16vec3 halhBitsToInt16(f16vec3);" - "i16vec4 halfBitsToInt16(f16vec4);" - - "uint16_t halfBitsToUint16(float16_t);" - "u16vec2 halfBitsToUint16(f16vec2);" - "u16vec3 halfBitsToUint16(f16vec3);" - "u16vec4 halfBitsToUint16(f16vec4);" - - "int16_t float16BitsToInt16(float16_t);" - "i16vec2 float16BitsToInt16(f16vec2);" - "i16vec3 float16BitsToInt16(f16vec3);" - "i16vec4 float16BitsToInt16(f16vec4);" - - "uint16_t float16BitsToUint16(float16_t);" - "u16vec2 float16BitsToUint16(f16vec2);" - "u16vec3 float16BitsToUint16(f16vec3);" - "u16vec4 float16BitsToUint16(f16vec4);" - - "float16_t int16BitsToFloat16(int16_t);" - "f16vec2 int16BitsToFloat16(i16vec2);" - "f16vec3 int16BitsToFloat16(i16vec3);" - "f16vec4 int16BitsToFloat16(i16vec4);" - - "float16_t uint16BitsToFloat16(uint16_t);" - "f16vec2 uint16BitsToFloat16(u16vec2);" - "f16vec3 uint16BitsToFloat16(u16vec3);" - "f16vec4 uint16BitsToFloat16(u16vec4);" - - "float16_t int16BitsToHalf(int16_t);" - "f16vec2 int16BitsToHalf(i16vec2);" - "f16vec3 int16BitsToHalf(i16vec3);" - "f16vec4 int16BitsToHalf(i16vec4);" - - "float16_t uint16BitsToHalf(uint16_t);" - "f16vec2 uint16BitsToHalf(u16vec2);" - "f16vec3 uint16BitsToHalf(u16vec3);" - "f16vec4 uint16BitsToHalf(u16vec4);" - - "int packInt2x16(i16vec2);" - "uint packUint2x16(u16vec2);" - "int64_t packInt4x16(i16vec4);" - "uint64_t packUint4x16(u16vec4);" - "i16vec2 unpackInt2x16(int);" - "u16vec2 unpackUint2x16(uint);" - "i16vec4 unpackInt4x16(int64_t);" - "u16vec4 unpackUint4x16(uint64_t);" - - "bvec2 lessThan(i16vec2, i16vec2);" - "bvec3 lessThan(i16vec3, i16vec3);" - "bvec4 lessThan(i16vec4, i16vec4);" - "bvec2 lessThan(u16vec2, u16vec2);" - "bvec3 lessThan(u16vec3, u16vec3);" - "bvec4 lessThan(u16vec4, u16vec4);" - - "bvec2 lessThanEqual(i16vec2, i16vec2);" - "bvec3 lessThanEqual(i16vec3, i16vec3);" - "bvec4 lessThanEqual(i16vec4, i16vec4);" - "bvec2 lessThanEqual(u16vec2, u16vec2);" - "bvec3 lessThanEqual(u16vec3, u16vec3);" - "bvec4 lessThanEqual(u16vec4, u16vec4);" - - "bvec2 greaterThan(i16vec2, i16vec2);" - "bvec3 greaterThan(i16vec3, i16vec3);" - "bvec4 greaterThan(i16vec4, i16vec4);" - "bvec2 greaterThan(u16vec2, u16vec2);" - "bvec3 greaterThan(u16vec3, u16vec3);" - "bvec4 greaterThan(u16vec4, u16vec4);" - - "bvec2 greaterThanEqual(i16vec2, i16vec2);" - "bvec3 greaterThanEqual(i16vec3, i16vec3);" - "bvec4 greaterThanEqual(i16vec4, i16vec4);" - "bvec2 greaterThanEqual(u16vec2, u16vec2);" - "bvec3 greaterThanEqual(u16vec3, u16vec3);" - "bvec4 greaterThanEqual(u16vec4, u16vec4);" - - "bvec2 equal(i16vec2, i16vec2);" - "bvec3 equal(i16vec3, i16vec3);" - "bvec4 equal(i16vec4, i16vec4);" - "bvec2 equal(u16vec2, u16vec2);" - "bvec3 equal(u16vec3, u16vec3);" - "bvec4 equal(u16vec4, u16vec4);" - - "bvec2 notEqual(i16vec2, i16vec2);" - "bvec3 notEqual(i16vec3, i16vec3);" - "bvec4 notEqual(i16vec4, i16vec4);" - "bvec2 notEqual(u16vec2, u16vec2);" - "bvec3 notEqual(u16vec3, u16vec3);" - "bvec4 notEqual(u16vec4, u16vec4);" - - " int16_t bitfieldExtract( int16_t, int16_t, int16_t);" - "i16vec2 bitfieldExtract(i16vec2, int16_t, int16_t);" - "i16vec3 bitfieldExtract(i16vec3, int16_t, int16_t);" - "i16vec4 bitfieldExtract(i16vec4, int16_t, int16_t);" - - " uint16_t bitfieldExtract( uint16_t, int16_t, int16_t);" - "u16vec2 bitfieldExtract(u16vec2, int16_t, int16_t);" - "u16vec3 bitfieldExtract(u16vec3, int16_t, int16_t);" - "u16vec4 bitfieldExtract(u16vec4, int16_t, int16_t);" - - " int16_t bitfieldInsert( int16_t base, int16_t, int16_t, int16_t);" - "i16vec2 bitfieldInsert(i16vec2 base, i16vec2, int16_t, int16_t);" - "i16vec3 bitfieldInsert(i16vec3 base, i16vec3, int16_t, int16_t);" - "i16vec4 bitfieldInsert(i16vec4 base, i16vec4, int16_t, int16_t);" - - " uint16_t bitfieldInsert( uint16_t base, uint16_t, int16_t, int16_t);" - "u16vec2 bitfieldInsert(u16vec2 base, u16vec2, int16_t, int16_t);" - "u16vec3 bitfieldInsert(u16vec3 base, u16vec3, int16_t, int16_t);" - "u16vec4 bitfieldInsert(u16vec4 base, u16vec4, int16_t, int16_t);" - - " int16_t bitCount( int16_t);" - "i16vec2 bitCount(i16vec2);" - "i16vec3 bitCount(i16vec3);" - "i16vec4 bitCount(i16vec4);" - - " int16_t bitCount( uint16_t);" - "i16vec2 bitCount(u16vec2);" - "i16vec3 bitCount(u16vec3);" - "i16vec4 bitCount(u16vec4);" - - " int16_t findLSB( int16_t);" - "i16vec2 findLSB(i16vec2);" - "i16vec3 findLSB(i16vec3);" - "i16vec4 findLSB(i16vec4);" - - " int16_t findLSB( uint16_t);" - "i16vec2 findLSB(u16vec2);" - "i16vec3 findLSB(u16vec3);" - "i16vec4 findLSB(u16vec4);" - - " int16_t findMSB( int16_t);" - "i16vec2 findMSB(i16vec2);" - "i16vec3 findMSB(i16vec3);" - "i16vec4 findMSB(i16vec4);" - - " int16_t findMSB( uint16_t);" - "i16vec2 findMSB(u16vec2);" - "i16vec3 findMSB(u16vec3);" - "i16vec4 findMSB(u16vec4);" - - "int16_t pack16(i8vec2);" - "uint16_t pack16(u8vec2);" - "int32_t pack32(i8vec4);" - "uint32_t pack32(u8vec4);" - "int32_t pack32(i16vec2);" - "uint32_t pack32(u16vec2);" - "int64_t pack64(i16vec4);" - "uint64_t pack64(u16vec4);" - "int64_t pack64(i32vec2);" - "uint64_t pack64(u32vec2);" - - "i8vec2 unpack8(int16_t);" - "u8vec2 unpack8(uint16_t);" - "i8vec4 unpack8(int32_t);" - "u8vec4 unpack8(uint32_t);" - "i16vec2 unpack16(int32_t);" - "u16vec2 unpack16(uint32_t);" - "i16vec4 unpack16(int64_t);" - "u16vec4 unpack16(uint64_t);" - "i32vec2 unpack32(int64_t);" - "u32vec2 unpack32(uint64_t);" - - "float64_t radians(float64_t);" - "f64vec2 radians(f64vec2);" - "f64vec3 radians(f64vec3);" - "f64vec4 radians(f64vec4);" - - "float64_t degrees(float64_t);" - "f64vec2 degrees(f64vec2);" - "f64vec3 degrees(f64vec3);" - "f64vec4 degrees(f64vec4);" - - "float64_t sin(float64_t);" - "f64vec2 sin(f64vec2);" - "f64vec3 sin(f64vec3);" - "f64vec4 sin(f64vec4);" - - "float64_t cos(float64_t);" - "f64vec2 cos(f64vec2);" - "f64vec3 cos(f64vec3);" - "f64vec4 cos(f64vec4);" - - "float64_t tan(float64_t);" - "f64vec2 tan(f64vec2);" - "f64vec3 tan(f64vec3);" - "f64vec4 tan(f64vec4);" - - "float64_t asin(float64_t);" - "f64vec2 asin(f64vec2);" - "f64vec3 asin(f64vec3);" - "f64vec4 asin(f64vec4);" - - "float64_t acos(float64_t);" - "f64vec2 acos(f64vec2);" - "f64vec3 acos(f64vec3);" - "f64vec4 acos(f64vec4);" - - "float64_t atan(float64_t, float64_t);" - "f64vec2 atan(f64vec2, f64vec2);" - "f64vec3 atan(f64vec3, f64vec3);" - "f64vec4 atan(f64vec4, f64vec4);" - - "float64_t atan(float64_t);" - "f64vec2 atan(f64vec2);" - "f64vec3 atan(f64vec3);" - "f64vec4 atan(f64vec4);" - - "float64_t sinh(float64_t);" - "f64vec2 sinh(f64vec2);" - "f64vec3 sinh(f64vec3);" - "f64vec4 sinh(f64vec4);" - - "float64_t cosh(float64_t);" - "f64vec2 cosh(f64vec2);" - "f64vec3 cosh(f64vec3);" - "f64vec4 cosh(f64vec4);" - - "float64_t tanh(float64_t);" - "f64vec2 tanh(f64vec2);" - "f64vec3 tanh(f64vec3);" - "f64vec4 tanh(f64vec4);" - - "float64_t asinh(float64_t);" - "f64vec2 asinh(f64vec2);" - "f64vec3 asinh(f64vec3);" - "f64vec4 asinh(f64vec4);" - - "float64_t acosh(float64_t);" - "f64vec2 acosh(f64vec2);" - "f64vec3 acosh(f64vec3);" - "f64vec4 acosh(f64vec4);" - - "float64_t atanh(float64_t);" - "f64vec2 atanh(f64vec2);" - "f64vec3 atanh(f64vec3);" - "f64vec4 atanh(f64vec4);" - - "float64_t pow(float64_t, float64_t);" - "f64vec2 pow(f64vec2, f64vec2);" - "f64vec3 pow(f64vec3, f64vec3);" - "f64vec4 pow(f64vec4, f64vec4);" - - "float64_t exp(float64_t);" - "f64vec2 exp(f64vec2);" - "f64vec3 exp(f64vec3);" - "f64vec4 exp(f64vec4);" - - "float64_t log(float64_t);" - "f64vec2 log(f64vec2);" - "f64vec3 log(f64vec3);" - "f64vec4 log(f64vec4);" - - "float64_t exp2(float64_t);" - "f64vec2 exp2(f64vec2);" - "f64vec3 exp2(f64vec3);" - "f64vec4 exp2(f64vec4);" - - "float64_t log2(float64_t);" - "f64vec2 log2(f64vec2);" - "f64vec3 log2(f64vec3);" - "f64vec4 log2(f64vec4);" - "\n"); - } - if (profile != EEsProfile && version >= 450) { - stageBuiltins[EShLangFragment].append( - "float64_t dFdx(float64_t);" - "f64vec2 dFdx(f64vec2);" - "f64vec3 dFdx(f64vec3);" - "f64vec4 dFdx(f64vec4);" - - "float64_t dFdy(float64_t);" - "f64vec2 dFdy(f64vec2);" - "f64vec3 dFdy(f64vec3);" - "f64vec4 dFdy(f64vec4);" - - "float64_t dFdxFine(float64_t);" - "f64vec2 dFdxFine(f64vec2);" - "f64vec3 dFdxFine(f64vec3);" - "f64vec4 dFdxFine(f64vec4);" - - "float64_t dFdyFine(float64_t);" - "f64vec2 dFdyFine(f64vec2);" - "f64vec3 dFdyFine(f64vec3);" - "f64vec4 dFdyFine(f64vec4);" - - "float64_t dFdxCoarse(float64_t);" - "f64vec2 dFdxCoarse(f64vec2);" - "f64vec3 dFdxCoarse(f64vec3);" - "f64vec4 dFdxCoarse(f64vec4);" - - "float64_t dFdyCoarse(float64_t);" - "f64vec2 dFdyCoarse(f64vec2);" - "f64vec3 dFdyCoarse(f64vec3);" - "f64vec4 dFdyCoarse(f64vec4);" - - "float64_t fwidth(float64_t);" - "f64vec2 fwidth(f64vec2);" - "f64vec3 fwidth(f64vec3);" - "f64vec4 fwidth(f64vec4);" - - "float64_t fwidthFine(float64_t);" - "f64vec2 fwidthFine(f64vec2);" - "f64vec3 fwidthFine(f64vec3);" - "f64vec4 fwidthFine(f64vec4);" - - "float64_t fwidthCoarse(float64_t);" - "f64vec2 fwidthCoarse(f64vec2);" - "f64vec3 fwidthCoarse(f64vec3);" - "f64vec4 fwidthCoarse(f64vec4);" - - "float64_t interpolateAtCentroid(float64_t);" - "f64vec2 interpolateAtCentroid(f64vec2);" - "f64vec3 interpolateAtCentroid(f64vec3);" - "f64vec4 interpolateAtCentroid(f64vec4);" - - "float64_t interpolateAtSample(float64_t, int);" - "f64vec2 interpolateAtSample(f64vec2, int);" - "f64vec3 interpolateAtSample(f64vec3, int);" - "f64vec4 interpolateAtSample(f64vec4, int);" - - "float64_t interpolateAtOffset(float64_t, f64vec2);" - "f64vec2 interpolateAtOffset(f64vec2, f64vec2);" - "f64vec3 interpolateAtOffset(f64vec3, f64vec2);" - "f64vec4 interpolateAtOffset(f64vec4, f64vec2);" - - "\n"); - - } - - //============================================================================ - // - // Prototypes for built-in functions seen by vertex shaders only. - // (Except legacy lod functions, where it depends which release they are - // vertex only.) - // - //============================================================================ - - // - // Geometric Functions. - // - if (IncludeLegacy(version, profile, spvVersion)) - stageBuiltins[EShLangVertex].append("vec4 ftransform();"); - - // - // Original-style texture Functions with lod. - // - TString* s; - if (version == 100) - s = &stageBuiltins[EShLangVertex]; - else - s = &commonBuiltins; - if ((profile == EEsProfile && version == 100) || - profile == ECompatibilityProfile || - (profile == ECoreProfile && version < 420) || - profile == ENoProfile) { - if (spvVersion.spv == 0) { - s->append( - "vec4 texture2DLod(sampler2D, vec2, float);" // GL_ARB_shader_texture_lod - "vec4 texture2DProjLod(sampler2D, vec3, float);" // GL_ARB_shader_texture_lod - "vec4 texture2DProjLod(sampler2D, vec4, float);" // GL_ARB_shader_texture_lod - "vec4 texture3DLod(sampler3D, vec3, float);" // GL_ARB_shader_texture_lod // OES_texture_3D, but caught by keyword check - "vec4 texture3DProjLod(sampler3D, vec4, float);" // GL_ARB_shader_texture_lod // OES_texture_3D, but caught by keyword check - "vec4 textureCubeLod(samplerCube, vec3, float);" // GL_ARB_shader_texture_lod - - "\n"); - } - } - if ( profile == ECompatibilityProfile || - (profile == ECoreProfile && version < 420) || - profile == ENoProfile) { - if (spvVersion.spv == 0) { - s->append( - "vec4 texture1DLod(sampler1D, float, float);" // GL_ARB_shader_texture_lod - "vec4 texture1DProjLod(sampler1D, vec2, float);" // GL_ARB_shader_texture_lod - "vec4 texture1DProjLod(sampler1D, vec4, float);" // GL_ARB_shader_texture_lod - "vec4 shadow1DLod(sampler1DShadow, vec3, float);" // GL_ARB_shader_texture_lod - "vec4 shadow2DLod(sampler2DShadow, vec3, float);" // GL_ARB_shader_texture_lod - "vec4 shadow1DProjLod(sampler1DShadow, vec4, float);" // GL_ARB_shader_texture_lod - "vec4 shadow2DProjLod(sampler2DShadow, vec4, float);" // GL_ARB_shader_texture_lod - - "vec4 texture1DGradARB(sampler1D, float, float, float);" // GL_ARB_shader_texture_lod - "vec4 texture1DProjGradARB(sampler1D, vec2, float, float);" // GL_ARB_shader_texture_lod - "vec4 texture1DProjGradARB(sampler1D, vec4, float, float);" // GL_ARB_shader_texture_lod - "vec4 texture2DGradARB(sampler2D, vec2, vec2, vec2);" // GL_ARB_shader_texture_lod - "vec4 texture2DProjGradARB(sampler2D, vec3, vec2, vec2);" // GL_ARB_shader_texture_lod - "vec4 texture2DProjGradARB(sampler2D, vec4, vec2, vec2);" // GL_ARB_shader_texture_lod - "vec4 texture3DGradARB(sampler3D, vec3, vec3, vec3);" // GL_ARB_shader_texture_lod - "vec4 texture3DProjGradARB(sampler3D, vec4, vec3, vec3);" // GL_ARB_shader_texture_lod - "vec4 textureCubeGradARB(samplerCube, vec3, vec3, vec3);" // GL_ARB_shader_texture_lod - "vec4 shadow1DGradARB(sampler1DShadow, vec3, float, float);" // GL_ARB_shader_texture_lod - "vec4 shadow1DProjGradARB( sampler1DShadow, vec4, float, float);" // GL_ARB_shader_texture_lod - "vec4 shadow2DGradARB(sampler2DShadow, vec3, vec2, vec2);" // GL_ARB_shader_texture_lod - "vec4 shadow2DProjGradARB( sampler2DShadow, vec4, vec2, vec2);" // GL_ARB_shader_texture_lod - "vec4 texture2DRectGradARB(sampler2DRect, vec2, vec2, vec2);" // GL_ARB_shader_texture_lod - "vec4 texture2DRectProjGradARB( sampler2DRect, vec3, vec2, vec2);" // GL_ARB_shader_texture_lod - "vec4 texture2DRectProjGradARB( sampler2DRect, vec4, vec2, vec2);" // GL_ARB_shader_texture_lod - "vec4 shadow2DRectGradARB( sampler2DRectShadow, vec3, vec2, vec2);" // GL_ARB_shader_texture_lod - "vec4 shadow2DRectProjGradARB(sampler2DRectShadow, vec4, vec2, vec2);" // GL_ARB_shader_texture_lod - - "\n"); - } - } - - if ((profile != EEsProfile && version >= 150) || - (profile == EEsProfile && version >= 310)) { - //============================================================================ - // - // Prototypes for built-in functions seen by geometry shaders only. - // - //============================================================================ - - if (profile != EEsProfile && version >= 400) { - stageBuiltins[EShLangGeometry].append( - "void EmitStreamVertex(int);" - "void EndStreamPrimitive(int);" - ); - } - stageBuiltins[EShLangGeometry].append( - "void EmitVertex();" - "void EndPrimitive();" - "\n"); - } - - //============================================================================ - // - // Prototypes for all control functions. - // - //============================================================================ - bool esBarrier = (profile == EEsProfile && version >= 310); - if ((profile != EEsProfile && version >= 150) || esBarrier) - stageBuiltins[EShLangTessControl].append( - "void barrier();" - ); - if ((profile != EEsProfile && version >= 420) || esBarrier) - stageBuiltins[EShLangCompute].append( - "void barrier();" - ); - if ((profile != EEsProfile && version >= 130) || esBarrier) - commonBuiltins.append( - "void memoryBarrier();" - ); - if ((profile != EEsProfile && version >= 420) || esBarrier) { - commonBuiltins.append( - "void memoryBarrierAtomicCounter();" - "void memoryBarrierBuffer();" - "void memoryBarrierImage();" - ); - stageBuiltins[EShLangCompute].append( - "void memoryBarrierShared();" - "void groupMemoryBarrier();" - ); - } - - //============================================================================ - // - // Prototypes for built-in functions seen by fragment shaders only. - // - //============================================================================ - - // - // Original-style texture Functions with bias. - // - if (spvVersion.spv == 0 && (profile != EEsProfile || version == 100)) { - stageBuiltins[EShLangFragment].append( - "vec4 texture2D(sampler2D, vec2, float);" - "vec4 texture2DProj(sampler2D, vec3, float);" - "vec4 texture2DProj(sampler2D, vec4, float);" - "vec4 texture3D(sampler3D, vec3, float);" // OES_texture_3D - "vec4 texture3DProj(sampler3D, vec4, float);" // OES_texture_3D - "vec4 textureCube(samplerCube, vec3, float);" - - "\n"); - } - if (spvVersion.spv == 0 && (profile != EEsProfile && version > 100)) { - stageBuiltins[EShLangFragment].append( - "vec4 texture1D(sampler1D, float, float);" - "vec4 texture1DProj(sampler1D, vec2, float);" - "vec4 texture1DProj(sampler1D, vec4, float);" - "vec4 shadow1D(sampler1DShadow, vec3, float);" - "vec4 shadow2D(sampler2DShadow, vec3, float);" - "vec4 shadow1DProj(sampler1DShadow, vec4, float);" - "vec4 shadow2DProj(sampler2DShadow, vec4, float);" - - "\n"); - } - if (spvVersion.spv == 0 && profile == EEsProfile) { - stageBuiltins[EShLangFragment].append( - "vec4 texture2DLodEXT(sampler2D, vec2, float);" // GL_EXT_shader_texture_lod - "vec4 texture2DProjLodEXT(sampler2D, vec3, float);" // GL_EXT_shader_texture_lod - "vec4 texture2DProjLodEXT(sampler2D, vec4, float);" // GL_EXT_shader_texture_lod - "vec4 textureCubeLodEXT(samplerCube, vec3, float);" // GL_EXT_shader_texture_lod - - "\n"); - } - - stageBuiltins[EShLangFragment].append( - "float dFdx(float p);" - "vec2 dFdx(vec2 p);" - "vec3 dFdx(vec3 p);" - "vec4 dFdx(vec4 p);" - - "float dFdy(float p);" - "vec2 dFdy(vec2 p);" - "vec3 dFdy(vec3 p);" - "vec4 dFdy(vec4 p);" - - "float fwidth(float p);" - "vec2 fwidth(vec2 p);" - "vec3 fwidth(vec3 p);" - "vec4 fwidth(vec4 p);" - - "\n"); - - // GL_ARB_derivative_control - if (profile != EEsProfile && version >= 400) { - stageBuiltins[EShLangFragment].append( - "float dFdxFine(float p);" - "vec2 dFdxFine(vec2 p);" - "vec3 dFdxFine(vec3 p);" - "vec4 dFdxFine(vec4 p);" - - "float dFdyFine(float p);" - "vec2 dFdyFine(vec2 p);" - "vec3 dFdyFine(vec3 p);" - "vec4 dFdyFine(vec4 p);" - - "float fwidthFine(float p);" - "vec2 fwidthFine(vec2 p);" - "vec3 fwidthFine(vec3 p);" - "vec4 fwidthFine(vec4 p);" - - "\n"); - - stageBuiltins[EShLangFragment].append( - "float dFdxCoarse(float p);" - "vec2 dFdxCoarse(vec2 p);" - "vec3 dFdxCoarse(vec3 p);" - "vec4 dFdxCoarse(vec4 p);" - - "float dFdyCoarse(float p);" - "vec2 dFdyCoarse(vec2 p);" - "vec3 dFdyCoarse(vec3 p);" - "vec4 dFdyCoarse(vec4 p);" - - "float fwidthCoarse(float p);" - "vec2 fwidthCoarse(vec2 p);" - "vec3 fwidthCoarse(vec3 p);" - "vec4 fwidthCoarse(vec4 p);" - - "\n"); - } - - // GL_OES_shader_multisample_interpolation - if ((profile == EEsProfile && version >= 310) || - (profile != EEsProfile && version >= 400)) { - stageBuiltins[EShLangFragment].append( - "float interpolateAtCentroid(float);" - "vec2 interpolateAtCentroid(vec2);" - "vec3 interpolateAtCentroid(vec3);" - "vec4 interpolateAtCentroid(vec4);" - - "float interpolateAtSample(float, int);" - "vec2 interpolateAtSample(vec2, int);" - "vec3 interpolateAtSample(vec3, int);" - "vec4 interpolateAtSample(vec4, int);" - - "float interpolateAtOffset(float, vec2);" - "vec2 interpolateAtOffset(vec2, vec2);" - "vec3 interpolateAtOffset(vec3, vec2);" - "vec4 interpolateAtOffset(vec4, vec2);" - - "\n"); - } - -#ifdef AMD_EXTENSIONS - // GL_AMD_shader_explicit_vertex_parameter - if (profile != EEsProfile && version >= 450) { - stageBuiltins[EShLangFragment].append( - "float interpolateAtVertexAMD(float, uint);" - "vec2 interpolateAtVertexAMD(vec2, uint);" - "vec3 interpolateAtVertexAMD(vec3, uint);" - "vec4 interpolateAtVertexAMD(vec4, uint);" - - "int interpolateAtVertexAMD(int, uint);" - "ivec2 interpolateAtVertexAMD(ivec2, uint);" - "ivec3 interpolateAtVertexAMD(ivec3, uint);" - "ivec4 interpolateAtVertexAMD(ivec4, uint);" - - "uint interpolateAtVertexAMD(uint, uint);" - "uvec2 interpolateAtVertexAMD(uvec2, uint);" - "uvec3 interpolateAtVertexAMD(uvec3, uint);" - "uvec4 interpolateAtVertexAMD(uvec4, uint);" - - "float16_t interpolateAtVertexAMD(float16_t, uint);" - "f16vec2 interpolateAtVertexAMD(f16vec2, uint);" - "f16vec3 interpolateAtVertexAMD(f16vec3, uint);" - "f16vec4 interpolateAtVertexAMD(f16vec4, uint);" - - "\n"); - } - - // GL_AMD_gpu_shader_half_float - if (profile != EEsProfile && version >= 450) { - stageBuiltins[EShLangFragment].append( - "float16_t dFdx(float16_t);" - "f16vec2 dFdx(f16vec2);" - "f16vec3 dFdx(f16vec3);" - "f16vec4 dFdx(f16vec4);" - - "float16_t dFdy(float16_t);" - "f16vec2 dFdy(f16vec2);" - "f16vec3 dFdy(f16vec3);" - "f16vec4 dFdy(f16vec4);" - - "float16_t dFdxFine(float16_t);" - "f16vec2 dFdxFine(f16vec2);" - "f16vec3 dFdxFine(f16vec3);" - "f16vec4 dFdxFine(f16vec4);" - - "float16_t dFdyFine(float16_t);" - "f16vec2 dFdyFine(f16vec2);" - "f16vec3 dFdyFine(f16vec3);" - "f16vec4 dFdyFine(f16vec4);" - - "float16_t dFdxCoarse(float16_t);" - "f16vec2 dFdxCoarse(f16vec2);" - "f16vec3 dFdxCoarse(f16vec3);" - "f16vec4 dFdxCoarse(f16vec4);" - - "float16_t dFdyCoarse(float16_t);" - "f16vec2 dFdyCoarse(f16vec2);" - "f16vec3 dFdyCoarse(f16vec3);" - "f16vec4 dFdyCoarse(f16vec4);" - - "float16_t fwidth(float16_t);" - "f16vec2 fwidth(f16vec2);" - "f16vec3 fwidth(f16vec3);" - "f16vec4 fwidth(f16vec4);" - - "float16_t fwidthFine(float16_t);" - "f16vec2 fwidthFine(f16vec2);" - "f16vec3 fwidthFine(f16vec3);" - "f16vec4 fwidthFine(f16vec4);" - - "float16_t fwidthCoarse(float16_t);" - "f16vec2 fwidthCoarse(f16vec2);" - "f16vec3 fwidthCoarse(f16vec3);" - "f16vec4 fwidthCoarse(f16vec4);" - - "float16_t interpolateAtCentroid(float16_t);" - "f16vec2 interpolateAtCentroid(f16vec2);" - "f16vec3 interpolateAtCentroid(f16vec3);" - "f16vec4 interpolateAtCentroid(f16vec4);" - - "float16_t interpolateAtSample(float16_t, int);" - "f16vec2 interpolateAtSample(f16vec2, int);" - "f16vec3 interpolateAtSample(f16vec3, int);" - "f16vec4 interpolateAtSample(f16vec4, int);" - - "float16_t interpolateAtOffset(float16_t, f16vec2);" - "f16vec2 interpolateAtOffset(f16vec2, f16vec2);" - "f16vec3 interpolateAtOffset(f16vec3, f16vec2);" - "f16vec4 interpolateAtOffset(f16vec4, f16vec2);" - - "\n"); - } - - // GL_AMD_shader_fragment_mask - if (profile != EEsProfile && version >= 450 && spvVersion.vulkan > 0) { - stageBuiltins[EShLangFragment].append( - "uint fragmentMaskFetchAMD(subpassInputMS);" - "uint fragmentMaskFetchAMD(isubpassInputMS);" - "uint fragmentMaskFetchAMD(usubpassInputMS);" - - "vec4 fragmentFetchAMD(subpassInputMS, uint);" - "ivec4 fragmentFetchAMD(isubpassInputMS, uint);" - "uvec4 fragmentFetchAMD(usubpassInputMS, uint);" - - "\n"); - } -#endif - - //============================================================================ - // - // Standard Uniforms - // - //============================================================================ - - // - // Depth range in window coordinates, p. 33 - // - if (spvVersion.spv == 0) { - commonBuiltins.append( - "struct gl_DepthRangeParameters {" - ); - if (profile == EEsProfile) { - commonBuiltins.append( - "highp float near;" // n - "highp float far;" // f - "highp float diff;" // f - n - ); - } else { - commonBuiltins.append( - "float near;" // n - "float far;" // f - "float diff;" // f - n - ); - } - - commonBuiltins.append( - "};" - "uniform gl_DepthRangeParameters gl_DepthRange;" - "\n"); - } - - if (spvVersion.spv == 0 && IncludeLegacy(version, profile, spvVersion)) { - // - // Matrix state. p. 31, 32, 37, 39, 40. - // - commonBuiltins.append( - "uniform mat4 gl_ModelViewMatrix;" - "uniform mat4 gl_ProjectionMatrix;" - "uniform mat4 gl_ModelViewProjectionMatrix;" - - // - // Derived matrix state that provides inverse and transposed versions - // of the matrices above. - // - "uniform mat3 gl_NormalMatrix;" - - "uniform mat4 gl_ModelViewMatrixInverse;" - "uniform mat4 gl_ProjectionMatrixInverse;" - "uniform mat4 gl_ModelViewProjectionMatrixInverse;" - - "uniform mat4 gl_ModelViewMatrixTranspose;" - "uniform mat4 gl_ProjectionMatrixTranspose;" - "uniform mat4 gl_ModelViewProjectionMatrixTranspose;" - - "uniform mat4 gl_ModelViewMatrixInverseTranspose;" - "uniform mat4 gl_ProjectionMatrixInverseTranspose;" - "uniform mat4 gl_ModelViewProjectionMatrixInverseTranspose;" - - // - // Normal scaling p. 39. - // - "uniform float gl_NormalScale;" - - // - // Point Size, p. 66, 67. - // - "struct gl_PointParameters {" - "float size;" - "float sizeMin;" - "float sizeMax;" - "float fadeThresholdSize;" - "float distanceConstantAttenuation;" - "float distanceLinearAttenuation;" - "float distanceQuadraticAttenuation;" - "};" - - "uniform gl_PointParameters gl_Point;" - - // - // Material State p. 50, 55. - // - "struct gl_MaterialParameters {" - "vec4 emission;" // Ecm - "vec4 ambient;" // Acm - "vec4 diffuse;" // Dcm - "vec4 specular;" // Scm - "float shininess;" // Srm - "};" - "uniform gl_MaterialParameters gl_FrontMaterial;" - "uniform gl_MaterialParameters gl_BackMaterial;" - - // - // Light State p 50, 53, 55. - // - "struct gl_LightSourceParameters {" - "vec4 ambient;" // Acli - "vec4 diffuse;" // Dcli - "vec4 specular;" // Scli - "vec4 position;" // Ppli - "vec4 halfVector;" // Derived: Hi - "vec3 spotDirection;" // Sdli - "float spotExponent;" // Srli - "float spotCutoff;" // Crli - // (range: [0.0,90.0], 180.0) - "float spotCosCutoff;" // Derived: cos(Crli) - // (range: [1.0,0.0],-1.0) - "float constantAttenuation;" // K0 - "float linearAttenuation;" // K1 - "float quadraticAttenuation;"// K2 - "};" - - "struct gl_LightModelParameters {" - "vec4 ambient;" // Acs - "};" - - "uniform gl_LightModelParameters gl_LightModel;" - - // - // Derived state from products of light and material. - // - "struct gl_LightModelProducts {" - "vec4 sceneColor;" // Derived. Ecm + Acm * Acs - "};" - - "uniform gl_LightModelProducts gl_FrontLightModelProduct;" - "uniform gl_LightModelProducts gl_BackLightModelProduct;" - - "struct gl_LightProducts {" - "vec4 ambient;" // Acm * Acli - "vec4 diffuse;" // Dcm * Dcli - "vec4 specular;" // Scm * Scli - "};" - - // - // Fog p. 161 - // - "struct gl_FogParameters {" - "vec4 color;" - "float density;" - "float start;" - "float end;" - "float scale;" // 1 / (gl_FogEnd - gl_FogStart) - "};" - - "uniform gl_FogParameters gl_Fog;" - - "\n"); - } - - //============================================================================ - // - // Define the interface to the compute shader. - // - //============================================================================ - - if ((profile != EEsProfile && version >= 420) || - (profile == EEsProfile && version >= 310)) { - stageBuiltins[EShLangCompute].append( - "in highp uvec3 gl_NumWorkGroups;" - "const highp uvec3 gl_WorkGroupSize = uvec3(1,1,1);" - - "in highp uvec3 gl_WorkGroupID;" - "in highp uvec3 gl_LocalInvocationID;" - - "in highp uvec3 gl_GlobalInvocationID;" - "in highp uint gl_LocalInvocationIndex;" - - "\n"); - } - - if ((profile != EEsProfile && version >= 140) || - (profile == EEsProfile && version >= 310)) { - stageBuiltins[EShLangCompute].append( - "in highp int gl_DeviceIndex;" // GL_EXT_device_group - "\n"); - } - - //============================================================================ - // - // Define the interface to the vertex shader. - // - //============================================================================ - - if (profile != EEsProfile) { - if (version < 130) { - stageBuiltins[EShLangVertex].append( - "attribute vec4 gl_Color;" - "attribute vec4 gl_SecondaryColor;" - "attribute vec3 gl_Normal;" - "attribute vec4 gl_Vertex;" - "attribute vec4 gl_MultiTexCoord0;" - "attribute vec4 gl_MultiTexCoord1;" - "attribute vec4 gl_MultiTexCoord2;" - "attribute vec4 gl_MultiTexCoord3;" - "attribute vec4 gl_MultiTexCoord4;" - "attribute vec4 gl_MultiTexCoord5;" - "attribute vec4 gl_MultiTexCoord6;" - "attribute vec4 gl_MultiTexCoord7;" - "attribute float gl_FogCoord;" - "\n"); - } else if (IncludeLegacy(version, profile, spvVersion)) { - stageBuiltins[EShLangVertex].append( - "in vec4 gl_Color;" - "in vec4 gl_SecondaryColor;" - "in vec3 gl_Normal;" - "in vec4 gl_Vertex;" - "in vec4 gl_MultiTexCoord0;" - "in vec4 gl_MultiTexCoord1;" - "in vec4 gl_MultiTexCoord2;" - "in vec4 gl_MultiTexCoord3;" - "in vec4 gl_MultiTexCoord4;" - "in vec4 gl_MultiTexCoord5;" - "in vec4 gl_MultiTexCoord6;" - "in vec4 gl_MultiTexCoord7;" - "in float gl_FogCoord;" - "\n"); - } - - if (version < 150) { - if (version < 130) { - stageBuiltins[EShLangVertex].append( - " vec4 gl_ClipVertex;" // needs qualifier fixed later - "varying vec4 gl_FrontColor;" - "varying vec4 gl_BackColor;" - "varying vec4 gl_FrontSecondaryColor;" - "varying vec4 gl_BackSecondaryColor;" - "varying vec4 gl_TexCoord[];" - "varying float gl_FogFragCoord;" - "\n"); - } else if (IncludeLegacy(version, profile, spvVersion)) { - stageBuiltins[EShLangVertex].append( - " vec4 gl_ClipVertex;" // needs qualifier fixed later - "out vec4 gl_FrontColor;" - "out vec4 gl_BackColor;" - "out vec4 gl_FrontSecondaryColor;" - "out vec4 gl_BackSecondaryColor;" - "out vec4 gl_TexCoord[];" - "out float gl_FogFragCoord;" - "\n"); - } - stageBuiltins[EShLangVertex].append( - "vec4 gl_Position;" // needs qualifier fixed later - "float gl_PointSize;" // needs qualifier fixed later - ); - - if (version == 130 || version == 140) - stageBuiltins[EShLangVertex].append( - "out float gl_ClipDistance[];" - ); - } else { - // version >= 150 - stageBuiltins[EShLangVertex].append( - "out gl_PerVertex {" - "vec4 gl_Position;" // needs qualifier fixed later - "float gl_PointSize;" // needs qualifier fixed later - "float gl_ClipDistance[];" - ); - if (IncludeLegacy(version, profile, spvVersion)) - stageBuiltins[EShLangVertex].append( - "vec4 gl_ClipVertex;" // needs qualifier fixed later - "vec4 gl_FrontColor;" - "vec4 gl_BackColor;" - "vec4 gl_FrontSecondaryColor;" - "vec4 gl_BackSecondaryColor;" - "vec4 gl_TexCoord[];" - "float gl_FogFragCoord;" - ); - if (version >= 450) - stageBuiltins[EShLangVertex].append( - "float gl_CullDistance[];" - ); - stageBuiltins[EShLangVertex].append( - "};" - "\n"); - } - if (version >= 130 && spvVersion.vulkan == 0) - stageBuiltins[EShLangVertex].append( - "int gl_VertexID;" // needs qualifier fixed later - ); - if (version >= 140 && spvVersion.vulkan == 0) - stageBuiltins[EShLangVertex].append( - "int gl_InstanceID;" // needs qualifier fixed later - ); - if (spvVersion.vulkan > 0 && version >= 140) - stageBuiltins[EShLangVertex].append( - "in int gl_VertexIndex;" - "in int gl_InstanceIndex;" - ); - if (version >= 440) { - stageBuiltins[EShLangVertex].append( - "in int gl_BaseVertexARB;" - "in int gl_BaseInstanceARB;" - "in int gl_DrawIDARB;" - ); - } - if (version >= 410) { - stageBuiltins[EShLangVertex].append( - "out int gl_ViewportIndex;" - "out int gl_Layer;" - ); - } - if (version >= 460) { - stageBuiltins[EShLangVertex].append( - "in int gl_BaseVertex;" - "in int gl_BaseInstance;" - "in int gl_DrawID;" - ); - } - -#ifdef NV_EXTENSIONS - if (version >= 450) - stageBuiltins[EShLangVertex].append( - "out int gl_ViewportMask[];" // GL_NV_viewport_array2 - "out int gl_SecondaryViewportMaskNV[];" // GL_NV_stereo_view_rendering - "out vec4 gl_SecondaryPositionNV;" // GL_NV_stereo_view_rendering - "out vec4 gl_PositionPerViewNV[];" // GL_NVX_multiview_per_view_attributes - "out int gl_ViewportMaskPerViewNV[];" // GL_NVX_multiview_per_view_attributes - ); -#endif - - } else { - // ES profile - if (version == 100) { - stageBuiltins[EShLangVertex].append( - "highp vec4 gl_Position;" // needs qualifier fixed later - "mediump float gl_PointSize;" // needs qualifier fixed later - ); - } else { - if (spvVersion.vulkan == 0) - stageBuiltins[EShLangVertex].append( - "in highp int gl_VertexID;" // needs qualifier fixed later - "in highp int gl_InstanceID;" // needs qualifier fixed later - ); - if (spvVersion.vulkan > 0) - stageBuiltins[EShLangVertex].append( - "in highp int gl_VertexIndex;" - "in highp int gl_InstanceIndex;" - ); - if (version < 310) - stageBuiltins[EShLangVertex].append( - "highp vec4 gl_Position;" // needs qualifier fixed later - "highp float gl_PointSize;" // needs qualifier fixed later - ); - else - stageBuiltins[EShLangVertex].append( - "out gl_PerVertex {" - "highp vec4 gl_Position;" // needs qualifier fixed later - "highp float gl_PointSize;" // needs qualifier fixed later - "};" - ); - } - } - - if ((profile != EEsProfile && version >= 140) || - (profile == EEsProfile && version >= 310)) { - stageBuiltins[EShLangVertex].append( - "in highp int gl_DeviceIndex;" // GL_EXT_device_group - "in highp int gl_ViewIndex;" // GL_EXT_multiview - "\n"); - } - - if (version >= 300 /* both ES and non-ES */) { - stageBuiltins[EShLangVertex].append( - "in highp uint gl_ViewID_OVR;" // GL_OVR_multiview, GL_OVR_multiview2 - "\n"); - } - - - //============================================================================ - // - // Define the interface to the geometry shader. - // - //============================================================================ - - if (profile == ECoreProfile || profile == ECompatibilityProfile) { - stageBuiltins[EShLangGeometry].append( - "in gl_PerVertex {" - "vec4 gl_Position;" - "float gl_PointSize;" - "float gl_ClipDistance[];" - ); - if (profile == ECompatibilityProfile) - stageBuiltins[EShLangGeometry].append( - "vec4 gl_ClipVertex;" - "vec4 gl_FrontColor;" - "vec4 gl_BackColor;" - "vec4 gl_FrontSecondaryColor;" - "vec4 gl_BackSecondaryColor;" - "vec4 gl_TexCoord[];" - "float gl_FogFragCoord;" - ); - if (version >= 450) - stageBuiltins[EShLangGeometry].append( - "float gl_CullDistance[];" -#ifdef NV_EXTENSIONS - "vec4 gl_SecondaryPositionNV;" // GL_NV_stereo_view_rendering - "vec4 gl_PositionPerViewNV[];" // GL_NVX_multiview_per_view_attributes -#endif - ); - stageBuiltins[EShLangGeometry].append( - "} gl_in[];" - - "in int gl_PrimitiveIDIn;" - "out gl_PerVertex {" - "vec4 gl_Position;" - "float gl_PointSize;" - "float gl_ClipDistance[];" - "\n"); - if (profile == ECompatibilityProfile && version >= 400) - stageBuiltins[EShLangGeometry].append( - "vec4 gl_ClipVertex;" - "vec4 gl_FrontColor;" - "vec4 gl_BackColor;" - "vec4 gl_FrontSecondaryColor;" - "vec4 gl_BackSecondaryColor;" - "vec4 gl_TexCoord[];" - "float gl_FogFragCoord;" - ); - if (version >= 450) - stageBuiltins[EShLangGeometry].append( - "float gl_CullDistance[];" - ); - stageBuiltins[EShLangGeometry].append( - "};" - - "out int gl_PrimitiveID;" - "out int gl_Layer;"); - - if (version >= 150) - stageBuiltins[EShLangGeometry].append( - "out int gl_ViewportIndex;" - ); - - if (profile == ECompatibilityProfile && version < 400) - stageBuiltins[EShLangGeometry].append( - "out vec4 gl_ClipVertex;" - ); - - if (version >= 400) - stageBuiltins[EShLangGeometry].append( - "in int gl_InvocationID;" - ); - -#ifdef NV_EXTENSIONS - if (version >= 450) - stageBuiltins[EShLangGeometry].append( - "out int gl_ViewportMask[];" // GL_NV_viewport_array2 - "out int gl_SecondaryViewportMaskNV[];" // GL_NV_stereo_view_rendering - "out vec4 gl_SecondaryPositionNV;" // GL_NV_stereo_view_rendering - "out vec4 gl_PositionPerViewNV[];" // GL_NVX_multiview_per_view_attributes - "out int gl_ViewportMaskPerViewNV[];" // GL_NVX_multiview_per_view_attributes - ); -#endif - - stageBuiltins[EShLangGeometry].append("\n"); - } else if (profile == EEsProfile && version >= 310) { - stageBuiltins[EShLangGeometry].append( - "in gl_PerVertex {" - "highp vec4 gl_Position;" - "highp float gl_PointSize;" - "} gl_in[];" - "\n" - "in highp int gl_PrimitiveIDIn;" - "in highp int gl_InvocationID;" - "\n" - "out gl_PerVertex {" - "highp vec4 gl_Position;" - "highp float gl_PointSize;" - "};" - "\n" - "out highp int gl_PrimitiveID;" - "out highp int gl_Layer;" - "\n" - ); - } - - if ((profile != EEsProfile && version >= 140) || - (profile == EEsProfile && version >= 310)) { - stageBuiltins[EShLangGeometry].append( - "in highp int gl_DeviceIndex;" // GL_EXT_device_group - "in highp int gl_ViewIndex;" // GL_EXT_multiview - "\n"); - } - - //============================================================================ - // - // Define the interface to the tessellation control shader. - // - //============================================================================ - - if (profile != EEsProfile && version >= 150) { - // Note: "in gl_PerVertex {...} gl_in[gl_MaxPatchVertices];" is declared in initialize() below, - // as it depends on the resource sizing of gl_MaxPatchVertices. - - stageBuiltins[EShLangTessControl].append( - "in int gl_PatchVerticesIn;" - "in int gl_PrimitiveID;" - "in int gl_InvocationID;" - - "out gl_PerVertex {" - "vec4 gl_Position;" - "float gl_PointSize;" - "float gl_ClipDistance[];" - ); - if (profile == ECompatibilityProfile) - stageBuiltins[EShLangTessControl].append( - "vec4 gl_ClipVertex;" - "vec4 gl_FrontColor;" - "vec4 gl_BackColor;" - "vec4 gl_FrontSecondaryColor;" - "vec4 gl_BackSecondaryColor;" - "vec4 gl_TexCoord[];" - "float gl_FogFragCoord;" - ); - if (version >= 450) - stageBuiltins[EShLangTessControl].append( - "float gl_CullDistance[];" -#ifdef NV_EXTENSIONS - "int gl_ViewportMask[];" // GL_NV_viewport_array2 - "vec4 gl_SecondaryPositionNV;" // GL_NV_stereo_view_rendering - "int gl_SecondaryViewportMaskNV[];" // GL_NV_stereo_view_rendering - "vec4 gl_PositionPerViewNV[];" // GL_NVX_multiview_per_view_attributes - "int gl_ViewportMaskPerViewNV[];" // GL_NVX_multiview_per_view_attributes -#endif - ); - stageBuiltins[EShLangTessControl].append( - "} gl_out[];" - - "patch out float gl_TessLevelOuter[4];" - "patch out float gl_TessLevelInner[2];" - "\n"); - - if (version >= 410) - stageBuiltins[EShLangTessControl].append( - "out int gl_ViewportIndex;" - "out int gl_Layer;" - "\n"); - - } else { - // Note: "in gl_PerVertex {...} gl_in[gl_MaxPatchVertices];" is declared in initialize() below, - // as it depends on the resource sizing of gl_MaxPatchVertices. - - stageBuiltins[EShLangTessControl].append( - "in highp int gl_PatchVerticesIn;" - "in highp int gl_PrimitiveID;" - "in highp int gl_InvocationID;" - - "out gl_PerVertex {" - "highp vec4 gl_Position;" - "highp float gl_PointSize;" - ); - stageBuiltins[EShLangTessControl].append( - "} gl_out[];" - - "patch out highp float gl_TessLevelOuter[4];" - "patch out highp float gl_TessLevelInner[2];" - "patch out highp vec4 gl_BoundingBoxOES[2];" - "\n"); - } - - if ((profile != EEsProfile && version >= 140) || - (profile == EEsProfile && version >= 310)) { - stageBuiltins[EShLangTessControl].append( - "in highp int gl_DeviceIndex;" // GL_EXT_device_group - "in highp int gl_ViewIndex;" // GL_EXT_multiview - "\n"); - } - - //============================================================================ - // - // Define the interface to the tessellation evaluation shader. - // - //============================================================================ - - if (profile != EEsProfile && version >= 150) { - // Note: "in gl_PerVertex {...} gl_in[gl_MaxPatchVertices];" is declared in initialize() below, - // as it depends on the resource sizing of gl_MaxPatchVertices. - - stageBuiltins[EShLangTessEvaluation].append( - "in int gl_PatchVerticesIn;" - "in int gl_PrimitiveID;" - "in vec3 gl_TessCoord;" - - "patch in float gl_TessLevelOuter[4];" - "patch in float gl_TessLevelInner[2];" - - "out gl_PerVertex {" - "vec4 gl_Position;" - "float gl_PointSize;" - "float gl_ClipDistance[];" - ); - if (version >= 400 && profile == ECompatibilityProfile) - stageBuiltins[EShLangTessEvaluation].append( - "vec4 gl_ClipVertex;" - "vec4 gl_FrontColor;" - "vec4 gl_BackColor;" - "vec4 gl_FrontSecondaryColor;" - "vec4 gl_BackSecondaryColor;" - "vec4 gl_TexCoord[];" - "float gl_FogFragCoord;" - ); - if (version >= 450) - stageBuiltins[EShLangTessEvaluation].append( - "float gl_CullDistance[];" - ); - stageBuiltins[EShLangTessEvaluation].append( - "};" - "\n"); - - if (version >= 410) - stageBuiltins[EShLangTessEvaluation].append( - "out int gl_ViewportIndex;" - "out int gl_Layer;" - "\n"); - -#ifdef NV_EXTENSIONS - if (version >= 450) - stageBuiltins[EShLangTessEvaluation].append( - "out int gl_ViewportMask[];" // GL_NV_viewport_array2 - "out vec4 gl_SecondaryPositionNV;" // GL_NV_stereo_view_rendering - "out int gl_SecondaryViewportMaskNV[];" // GL_NV_stereo_view_rendering - "out vec4 gl_PositionPerViewNV[];" // GL_NVX_multiview_per_view_attributes - "out int gl_ViewportMaskPerViewNV[];" // GL_NVX_multiview_per_view_attributes - ); -#endif - - } else if (profile == EEsProfile && version >= 310) { - // Note: "in gl_PerVertex {...} gl_in[gl_MaxPatchVertices];" is declared in initialize() below, - // as it depends on the resource sizing of gl_MaxPatchVertices. - - stageBuiltins[EShLangTessEvaluation].append( - "in highp int gl_PatchVerticesIn;" - "in highp int gl_PrimitiveID;" - "in highp vec3 gl_TessCoord;" - - "patch in highp float gl_TessLevelOuter[4];" - "patch in highp float gl_TessLevelInner[2];" - - "out gl_PerVertex {" - "highp vec4 gl_Position;" - "highp float gl_PointSize;" - ); - stageBuiltins[EShLangTessEvaluation].append( - "};" - "\n"); - } - - if ((profile != EEsProfile && version >= 140) || - (profile == EEsProfile && version >= 310)) { - stageBuiltins[EShLangTessEvaluation].append( - "in highp int gl_DeviceIndex;" // GL_EXT_device_group - "in highp int gl_ViewIndex;" // GL_EXT_multiview - "\n"); - } - - //============================================================================ - // - // Define the interface to the fragment shader. - // - //============================================================================ - - if (profile != EEsProfile) { - - stageBuiltins[EShLangFragment].append( - "vec4 gl_FragCoord;" // needs qualifier fixed later - "bool gl_FrontFacing;" // needs qualifier fixed later - "float gl_FragDepth;" // needs qualifier fixed later - ); - if (version >= 120) - stageBuiltins[EShLangFragment].append( - "vec2 gl_PointCoord;" // needs qualifier fixed later - ); - if (version >= 140) - stageBuiltins[EShLangFragment].append( - "out int gl_FragStencilRefARB;" - ); - if (IncludeLegacy(version, profile, spvVersion) || (! ForwardCompatibility && version < 420)) - stageBuiltins[EShLangFragment].append( - "vec4 gl_FragColor;" // needs qualifier fixed later - ); - - if (version < 130) { - stageBuiltins[EShLangFragment].append( - "varying vec4 gl_Color;" - "varying vec4 gl_SecondaryColor;" - "varying vec4 gl_TexCoord[];" - "varying float gl_FogFragCoord;" - ); - } else { - stageBuiltins[EShLangFragment].append( - "in float gl_ClipDistance[];" - ); - - if (IncludeLegacy(version, profile, spvVersion)) { - if (version < 150) - stageBuiltins[EShLangFragment].append( - "in float gl_FogFragCoord;" - "in vec4 gl_TexCoord[];" - "in vec4 gl_Color;" - "in vec4 gl_SecondaryColor;" - ); - else - stageBuiltins[EShLangFragment].append( - "in gl_PerFragment {" - "in float gl_FogFragCoord;" - "in vec4 gl_TexCoord[];" - "in vec4 gl_Color;" - "in vec4 gl_SecondaryColor;" - "};" - ); - } - } - - if (version >= 150) - stageBuiltins[EShLangFragment].append( - "flat in int gl_PrimitiveID;" - ); - - if (version >= 400) { - stageBuiltins[EShLangFragment].append( - "flat in int gl_SampleID;" - " in vec2 gl_SamplePosition;" - "flat in int gl_SampleMaskIn[];" - " out int gl_SampleMask[];" - ); - if (spvVersion.spv == 0) - stageBuiltins[EShLangFragment].append( - "uniform int gl_NumSamples;" - ); - } - - if (version >= 430) - stageBuiltins[EShLangFragment].append( - "flat in int gl_Layer;" - "flat in int gl_ViewportIndex;" - ); - - if (version >= 450) - stageBuiltins[EShLangFragment].append( - "in float gl_CullDistance[];" - "bool gl_HelperInvocation;" // needs qualifier fixed later - ); - -#ifdef AMD_EXTENSIONS - if (version >= 450) - stageBuiltins[EShLangFragment].append( - "in vec2 gl_BaryCoordNoPerspAMD;" - "in vec2 gl_BaryCoordNoPerspCentroidAMD;" - "in vec2 gl_BaryCoordNoPerspSampleAMD;" - "in vec2 gl_BaryCoordSmoothAMD;" - "in vec2 gl_BaryCoordSmoothCentroidAMD;" - "in vec2 gl_BaryCoordSmoothSampleAMD;" - "in vec3 gl_BaryCoordPullModelAMD;" - ); -#endif - -#ifdef NV_EXTENSIONS - if (version >= 430) - stageBuiltins[EShLangFragment].append( - "in bool gl_FragFullyCoveredNV;" - ); -#endif - } else { - // ES profile - - if (version == 100) { - stageBuiltins[EShLangFragment].append( - "mediump vec4 gl_FragCoord;" // needs qualifier fixed later - " bool gl_FrontFacing;" // needs qualifier fixed later - "mediump vec4 gl_FragColor;" // needs qualifier fixed later - "mediump vec2 gl_PointCoord;" // needs qualifier fixed later - ); - } - if (version >= 300) { - stageBuiltins[EShLangFragment].append( - "highp vec4 gl_FragCoord;" // needs qualifier fixed later - " bool gl_FrontFacing;" // needs qualifier fixed later - "mediump vec2 gl_PointCoord;" // needs qualifier fixed later - "highp float gl_FragDepth;" // needs qualifier fixed later - ); - } - if (version >= 310) { - stageBuiltins[EShLangFragment].append( - "bool gl_HelperInvocation;" // needs qualifier fixed later - "flat in highp int gl_PrimitiveID;" // needs qualifier fixed later - "flat in highp int gl_Layer;" // needs qualifier fixed later - ); - - stageBuiltins[EShLangFragment].append( // GL_OES_sample_variables - "flat in lowp int gl_SampleID;" - " in mediump vec2 gl_SamplePosition;" - "flat in highp int gl_SampleMaskIn[];" - " out highp int gl_SampleMask[];" - ); - if (spvVersion.spv == 0) - stageBuiltins[EShLangFragment].append( // GL_OES_sample_variables - "uniform lowp int gl_NumSamples;" - ); - } - stageBuiltins[EShLangFragment].append( - "highp float gl_FragDepthEXT;" // GL_EXT_frag_depth - ); - } - stageBuiltins[EShLangFragment].append("\n"); - - if (version >= 130) - add2ndGenerationSamplingImaging(version, profile, spvVersion); - - // GL_ARB_shader_ballot - if (profile != EEsProfile && version >= 450) { - const char* ballotDecls = - "uniform uint gl_SubGroupSizeARB;" - "in uint gl_SubGroupInvocationARB;" - "in uint64_t gl_SubGroupEqMaskARB;" - "in uint64_t gl_SubGroupGeMaskARB;" - "in uint64_t gl_SubGroupGtMaskARB;" - "in uint64_t gl_SubGroupLeMaskARB;" - "in uint64_t gl_SubGroupLtMaskARB;" - "\n"; - const char* fragmentBallotDecls = - "uniform uint gl_SubGroupSizeARB;" - "flat in uint gl_SubGroupInvocationARB;" - "flat in uint64_t gl_SubGroupEqMaskARB;" - "flat in uint64_t gl_SubGroupGeMaskARB;" - "flat in uint64_t gl_SubGroupGtMaskARB;" - "flat in uint64_t gl_SubGroupLeMaskARB;" - "flat in uint64_t gl_SubGroupLtMaskARB;" - "\n"; - stageBuiltins[EShLangVertex] .append(ballotDecls); - stageBuiltins[EShLangTessControl] .append(ballotDecls); - stageBuiltins[EShLangTessEvaluation].append(ballotDecls); - stageBuiltins[EShLangGeometry] .append(ballotDecls); - stageBuiltins[EShLangCompute] .append(ballotDecls); - stageBuiltins[EShLangFragment] .append(fragmentBallotDecls); - } - - if ((profile != EEsProfile && version >= 140) || - (profile == EEsProfile && version >= 310)) { - stageBuiltins[EShLangFragment].append( - "flat in highp int gl_DeviceIndex;" // GL_EXT_device_group - "flat in highp int gl_ViewIndex;" // GL_EXT_multiview - "\n"); - } - - // GL_KHR_shader_subgroup - if (spvVersion.vulkan > 0) { - const char* ballotDecls = - "in mediump uint gl_SubgroupSize;" - "in mediump uint gl_SubgroupInvocationID;" - "in highp uvec4 gl_SubgroupEqMask;" - "in highp uvec4 gl_SubgroupGeMask;" - "in highp uvec4 gl_SubgroupGtMask;" - "in highp uvec4 gl_SubgroupLeMask;" - "in highp uvec4 gl_SubgroupLtMask;" - "\n"; - const char* fragmentBallotDecls = - "flat in mediump uint gl_SubgroupSize;" - "flat in mediump uint gl_SubgroupInvocationID;" - "flat in highp uvec4 gl_SubgroupEqMask;" - "flat in highp uvec4 gl_SubgroupGeMask;" - "flat in highp uvec4 gl_SubgroupGtMask;" - "flat in highp uvec4 gl_SubgroupLeMask;" - "flat in highp uvec4 gl_SubgroupLtMask;" - "\n"; - stageBuiltins[EShLangVertex] .append(ballotDecls); - stageBuiltins[EShLangTessControl] .append(ballotDecls); - stageBuiltins[EShLangTessEvaluation].append(ballotDecls); - stageBuiltins[EShLangGeometry] .append(ballotDecls); - stageBuiltins[EShLangCompute] .append(ballotDecls); - stageBuiltins[EShLangFragment] .append(fragmentBallotDecls); - - stageBuiltins[EShLangCompute].append( - "highp in uint gl_NumSubgroups;" - "highp in uint gl_SubgroupID;" - "\n"); - } - - if (version >= 300 /* both ES and non-ES */) { - stageBuiltins[EShLangFragment].append( - "flat in highp uint gl_ViewID_OVR;" // GL_OVR_multiview, GL_OVR_multiview2 - "\n"); - } - - // printf("%s\n", commonBuiltins.c_str()); - // printf("%s\n", stageBuiltins[EShLangFragment].c_str()); -} - -// -// Helper function for initialize(), to add the second set of names for texturing, -// when adding context-independent built-in functions. -// -void TBuiltIns::add2ndGenerationSamplingImaging(int version, EProfile profile, const SpvVersion& spvVersion) -{ - // - // In this function proper, enumerate the types, then calls the next set of functions - // to enumerate all the uses for that type. - // -#ifdef AMD_EXTENSIONS - TBasicType bTypes[4] = { EbtFloat, EbtFloat16, EbtInt, EbtUint }; -#else - TBasicType bTypes[3] = { EbtFloat, EbtInt, EbtUint }; -#endif - bool skipBuffer = (profile == EEsProfile && version < 310) || (profile != EEsProfile && version < 140); - bool skipCubeArrayed = (profile == EEsProfile && version < 310) || (profile != EEsProfile && version < 130); - - // enumerate all the types - for (int image = 0; image <= 1; ++image) { // loop over "bool" image vs sampler - - for (int shadow = 0; shadow <= 1; ++shadow) { // loop over "bool" shadow or not - for (int ms = 0; ms <=1; ++ms) { - if ((ms || image) && shadow) - continue; - if (ms && profile != EEsProfile && version < 150) - continue; - if (ms && image && profile == EEsProfile) - continue; - if (ms && profile == EEsProfile && version < 310) - continue; - - for (int arrayed = 0; arrayed <= 1; ++arrayed) { // loop over "bool" arrayed or not - for (int dim = Esd1D; dim < EsdNumDims; ++dim) { // 1D, 2D, ..., buffer - if (dim == EsdSubpass && spvVersion.vulkan == 0) - continue; - if (dim == EsdSubpass && (image || shadow || arrayed)) - continue; - if ((dim == Esd1D || dim == EsdRect) && profile == EEsProfile) - continue; - if (dim != Esd2D && dim != EsdSubpass && ms) - continue; - if ((dim == Esd3D || dim == EsdRect) && arrayed) - continue; - if (dim == Esd3D && shadow) - continue; - if (dim == EsdCube && arrayed && skipCubeArrayed) - continue; - if (dim == EsdBuffer && skipBuffer) - continue; - if (dim == EsdBuffer && (shadow || arrayed || ms)) - continue; - if (ms && arrayed && profile == EEsProfile && version < 310) - continue; -#ifdef AMD_EXTENSIONS - for (int bType = 0; bType < 4; ++bType) { // float, float16, int, uint results - - if (shadow && bType > 1) - continue; - - if (bTypes[bType] == EbtFloat16 && (profile == EEsProfile ||version < 450)) - continue; -#else - for (int bType = 0; bType < 3; ++bType) { // float, int, uint results - - if (shadow && bType > 0) - continue; -#endif - if (dim == EsdRect && version < 140 && bType > 0) - continue; - - // - // Now, make all the function prototypes for the type we just built... - // - - TSampler sampler; - if (dim == EsdSubpass) { - sampler.setSubpass(bTypes[bType], ms ? true : false); - } else if (image) { - sampler.setImage(bTypes[bType], (TSamplerDim)dim, arrayed ? true : false, - shadow ? true : false, - ms ? true : false); - } else { - sampler.set(bTypes[bType], (TSamplerDim)dim, arrayed ? true : false, - shadow ? true : false, - ms ? true : false); - } - - TString typeName = sampler.getString(); - - if (dim == EsdSubpass) { - addSubpassSampling(sampler, typeName, version, profile); - continue; - } - - addQueryFunctions(sampler, typeName, version, profile); - - if (image) - addImageFunctions(sampler, typeName, version, profile); - else { - addSamplingFunctions(sampler, typeName, version, profile); - addGatherFunctions(sampler, typeName, version, profile); - - if (spvVersion.vulkan > 0 && sampler.dim == EsdBuffer && sampler.isCombined()) { - // Vulkan wants a textureBuffer to allow texelFetch() -- - // a sampled image with no sampler. - // So, add sampling functions for both the - // samplerBuffer and textureBuffer types. - sampler.setTexture(sampler.type, sampler.dim, sampler.arrayed, sampler.shadow, - sampler.ms); - TString textureTypeName = sampler.getString(); - addSamplingFunctions(sampler, textureTypeName, version, profile); - } - } - } - } - } - } - } - } - - // - // sparseTexelsResidentARB() - // - - if (profile != EEsProfile && version >= 450) { - commonBuiltins.append("bool sparseTexelsResidentARB(int code);\n"); - } -} - -// -// Helper function for add2ndGenerationSamplingImaging(), -// when adding context-independent built-in functions. -// -// Add all the query functions for the given type. -// -void TBuiltIns::addQueryFunctions(TSampler sampler, const TString& typeName, int version, EProfile profile) -{ - if (sampler.image && ((profile == EEsProfile && version < 310) || (profile != EEsProfile && version < 430))) - return; - - // - // textureSize() and imageSize() - // - - int sizeDims = dimMap[sampler.dim] + (sampler.arrayed ? 1 : 0) - (sampler.dim == EsdCube ? 1 : 0); - if (profile == EEsProfile) - commonBuiltins.append("highp "); - if (sizeDims == 1) - commonBuiltins.append("int"); - else { - commonBuiltins.append("ivec"); - commonBuiltins.append(postfixes[sizeDims]); - } - if (sampler.image) - commonBuiltins.append(" imageSize(readonly writeonly volatile coherent "); - else - commonBuiltins.append(" textureSize("); - commonBuiltins.append(typeName); - if (! sampler.image && sampler.dim != EsdRect && sampler.dim != EsdBuffer && ! sampler.ms) - commonBuiltins.append(",int);\n"); - else - commonBuiltins.append(");\n"); - - // - // textureSamples() and imageSamples() - // - - // GL_ARB_shader_texture_image_samples - // TODO: spec issue? there are no memory qualifiers; how to query a writeonly/readonly image, etc? - if (profile != EEsProfile && version >= 430 && sampler.ms) { - commonBuiltins.append("int "); - if (sampler.image) - commonBuiltins.append("imageSamples(readonly writeonly volatile coherent "); - else - commonBuiltins.append("textureSamples("); - commonBuiltins.append(typeName); - commonBuiltins.append(");\n"); - } - - // - // textureQueryLod(), fragment stage only - // - - if (profile != EEsProfile && version >= 400 && ! sampler.image && sampler.dim != EsdRect && ! sampler.ms && sampler.dim != EsdBuffer) { -#ifdef AMD_EXTENSIONS - for (int f16TexAddr = 0; f16TexAddr < 2; ++f16TexAddr) { - if (f16TexAddr && sampler.type != EbtFloat16) - continue; -#endif - stageBuiltins[EShLangFragment].append("vec2 textureQueryLod("); - stageBuiltins[EShLangFragment].append(typeName); - if (dimMap[sampler.dim] == 1) -#ifdef AMD_EXTENSIONS - if (f16TexAddr) - stageBuiltins[EShLangFragment].append(", float16_t"); - else - stageBuiltins[EShLangFragment].append(", float"); -#else - stageBuiltins[EShLangFragment].append(", float"); -#endif - else { -#ifdef AMD_EXTENSIONS - if (f16TexAddr) - stageBuiltins[EShLangFragment].append(", f16vec"); - else - stageBuiltins[EShLangFragment].append(", vec"); -#else - stageBuiltins[EShLangFragment].append(", vec"); -#endif - stageBuiltins[EShLangFragment].append(postfixes[dimMap[sampler.dim]]); - } - stageBuiltins[EShLangFragment].append(");\n"); -#ifdef AMD_EXTENSIONS - } -#endif - } - - // - // textureQueryLevels() - // - - if (profile != EEsProfile && version >= 430 && ! sampler.image && sampler.dim != EsdRect && ! sampler.ms && sampler.dim != EsdBuffer) { - commonBuiltins.append("int textureQueryLevels("); - commonBuiltins.append(typeName); - commonBuiltins.append(");\n"); - } -} - -// -// Helper function for add2ndGenerationSamplingImaging(), -// when adding context-independent built-in functions. -// -// Add all the image access functions for the given type. -// -void TBuiltIns::addImageFunctions(TSampler sampler, const TString& typeName, int version, EProfile profile) -{ - int dims = dimMap[sampler.dim]; - // most things with an array add a dimension, except for cubemaps - if (sampler.arrayed && sampler.dim != EsdCube) - ++dims; - - TString imageParams = typeName; - if (dims == 1) - imageParams.append(", int"); - else { - imageParams.append(", ivec"); - imageParams.append(postfixes[dims]); - } - if (sampler.ms) - imageParams.append(", int"); - - if (profile == EEsProfile) - commonBuiltins.append("highp "); - commonBuiltins.append(prefixes[sampler.type]); - commonBuiltins.append("vec4 imageLoad(readonly volatile coherent "); - commonBuiltins.append(imageParams); - commonBuiltins.append(");\n"); - - commonBuiltins.append("void imageStore(writeonly volatile coherent "); - commonBuiltins.append(imageParams); - commonBuiltins.append(", "); - commonBuiltins.append(prefixes[sampler.type]); - commonBuiltins.append("vec4);\n"); - - if (sampler.dim != Esd1D && sampler.dim != EsdBuffer && profile != EEsProfile && version >= 450) { - commonBuiltins.append("int sparseImageLoadARB(readonly volatile coherent "); - commonBuiltins.append(imageParams); - commonBuiltins.append(", out "); - commonBuiltins.append(prefixes[sampler.type]); - commonBuiltins.append("vec4"); - commonBuiltins.append(");\n"); - } - - if ( profile != EEsProfile || - (profile == EEsProfile && version >= 310)) { - if (sampler.type == EbtInt || sampler.type == EbtUint) { - const char* dataType = sampler.type == EbtInt ? "highp int" : "highp uint"; - - const int numBuiltins = 7; - - static const char* atomicFunc[numBuiltins] = { - " imageAtomicAdd(volatile coherent ", - " imageAtomicMin(volatile coherent ", - " imageAtomicMax(volatile coherent ", - " imageAtomicAnd(volatile coherent ", - " imageAtomicOr(volatile coherent ", - " imageAtomicXor(volatile coherent ", - " imageAtomicExchange(volatile coherent " - }; - - for (size_t i = 0; i < numBuiltins; ++i) { - commonBuiltins.append(dataType); - commonBuiltins.append(atomicFunc[i]); - commonBuiltins.append(imageParams); - commonBuiltins.append(", "); - commonBuiltins.append(dataType); - commonBuiltins.append(");\n"); - } - - commonBuiltins.append(dataType); - commonBuiltins.append(" imageAtomicCompSwap(volatile coherent "); - commonBuiltins.append(imageParams); - commonBuiltins.append(", "); - commonBuiltins.append(dataType); - commonBuiltins.append(", "); - commonBuiltins.append(dataType); - commonBuiltins.append(");\n"); - } else { - // not int or uint - // GL_ARB_ES3_1_compatibility - // TODO: spec issue: are there restrictions on the kind of layout() that can be used? what about dropping memory qualifiers? - if ((profile != EEsProfile && version >= 450) || - (profile == EEsProfile && version >= 310)) { - commonBuiltins.append("float imageAtomicExchange(volatile coherent "); - commonBuiltins.append(imageParams); - commonBuiltins.append(", float);\n"); - } - } - } - -#ifdef AMD_EXTENSIONS - if (sampler.dim == EsdRect || sampler.dim == EsdBuffer || sampler.shadow || sampler.ms) - return; - - if (profile == EEsProfile || version < 450) - return; - - TString imageLodParams = typeName; - if (dims == 1) - imageLodParams.append(", int"); - else { - imageLodParams.append(", ivec"); - imageLodParams.append(postfixes[dims]); - } - imageLodParams.append(", int"); - - commonBuiltins.append(prefixes[sampler.type]); - commonBuiltins.append("vec4 imageLoadLodAMD(readonly volatile coherent "); - commonBuiltins.append(imageLodParams); - commonBuiltins.append(");\n"); - - commonBuiltins.append("void imageStoreLodAMD(writeonly volatile coherent "); - commonBuiltins.append(imageLodParams); - commonBuiltins.append(", "); - commonBuiltins.append(prefixes[sampler.type]); - commonBuiltins.append("vec4);\n"); - - if (sampler.dim != Esd1D) { - commonBuiltins.append("int sparseImageLoadLodAMD(readonly volatile coherent "); - commonBuiltins.append(imageLodParams); - commonBuiltins.append(", out "); - commonBuiltins.append(prefixes[sampler.type]); - commonBuiltins.append("vec4"); - commonBuiltins.append(");\n"); - } -#endif -} - -// -// Helper function for initialize(), -// when adding context-independent built-in functions. -// -// Add all the subpass access functions for the given type. -// -void TBuiltIns::addSubpassSampling(TSampler sampler, const TString& typeName, int /*version*/, EProfile /*profile*/) -{ - stageBuiltins[EShLangFragment].append(prefixes[sampler.type]); - stageBuiltins[EShLangFragment].append("vec4 subpassLoad"); - stageBuiltins[EShLangFragment].append("("); - stageBuiltins[EShLangFragment].append(typeName.c_str()); - if (sampler.ms) - stageBuiltins[EShLangFragment].append(", int"); - stageBuiltins[EShLangFragment].append(");\n"); -} - -// -// Helper function for add2ndGenerationSamplingImaging(), -// when adding context-independent built-in functions. -// -// Add all the texture lookup functions for the given type. -// -void TBuiltIns::addSamplingFunctions(TSampler sampler, const TString& typeName, int version, EProfile profile) -{ - // - // texturing - // - for (int proj = 0; proj <= 1; ++proj) { // loop over "bool" projective or not - - if (proj && (sampler.dim == EsdCube || sampler.dim == EsdBuffer || sampler.arrayed || sampler.ms)) - continue; - - for (int lod = 0; lod <= 1; ++lod) { - - if (lod && (sampler.dim == EsdBuffer || sampler.dim == EsdRect || sampler.ms)) - continue; - if (lod && sampler.dim == Esd2D && sampler.arrayed && sampler.shadow) - continue; - if (lod && sampler.dim == EsdCube && sampler.shadow) - continue; - - for (int bias = 0; bias <= 1; ++bias) { - - if (bias && (lod || sampler.ms)) - continue; - if (bias && (sampler.dim == Esd2D || sampler.dim == EsdCube) && sampler.shadow && sampler.arrayed) - continue; - if (bias && (sampler.dim == EsdRect || sampler.dim == EsdBuffer)) - continue; - - for (int offset = 0; offset <= 1; ++offset) { // loop over "bool" offset or not - - if (proj + offset + bias + lod > 3) - continue; - if (offset && (sampler.dim == EsdCube || sampler.dim == EsdBuffer || sampler.ms)) - continue; - - for (int fetch = 0; fetch <= 1; ++fetch) { // loop over "bool" fetch or not - - if (proj + offset + fetch + bias + lod > 3) - continue; - if (fetch && (lod || bias)) - continue; - if (fetch && (sampler.shadow || sampler.dim == EsdCube)) - continue; - if (fetch == 0 && (sampler.ms || sampler.dim == EsdBuffer)) - continue; - - for (int grad = 0; grad <= 1; ++grad) { // loop over "bool" grad or not - - if (grad && (lod || bias || sampler.ms)) - continue; - if (grad && sampler.dim == EsdBuffer) - continue; - if (proj + offset + fetch + grad + bias + lod > 3) - continue; - - for (int extraProj = 0; extraProj <= 1; ++extraProj) { - bool compare = false; - int totalDims = dimMap[sampler.dim] + (sampler.arrayed ? 1 : 0); - // skip dummy unused second component for 1D non-array shadows - if (sampler.shadow && totalDims < 2) - totalDims = 2; - totalDims += (sampler.shadow ? 1 : 0) + proj; - if (totalDims > 4 && sampler.shadow) { - compare = true; - totalDims = 4; - } - assert(totalDims <= 4); - - if (extraProj && ! proj) - continue; - if (extraProj && (sampler.dim == Esd3D || sampler.shadow)) - continue; -#ifdef AMD_EXTENSIONS - for (int f16TexAddr = 0; f16TexAddr <= 1; ++f16TexAddr) { // loop over 16-bit floating-point texel addressing - - if (f16TexAddr && sampler.type != EbtFloat16) - continue; - if (f16TexAddr && sampler.shadow && ! compare) { - compare = true; // compare argument is always present - totalDims--; - } -#endif - for (int lodClamp = 0; lodClamp <= 1 ;++lodClamp) { // loop over "bool" lod clamp - - if (lodClamp && (profile == EEsProfile || version < 450)) - continue; - if (lodClamp && (proj || lod || fetch)) - continue; - - for (int sparse = 0; sparse <= 1; ++sparse) { // loop over "bool" sparse or not - - if (sparse && (profile == EEsProfile || version < 450)) - continue; - // Sparse sampling is not for 1D/1D array texture, buffer texture, and projective texture - if (sparse && (sampler.dim == Esd1D || sampler.dim == EsdBuffer || proj)) - continue; - - TString s; - - // return type - if (sparse) - s.append("int "); - else { - if (sampler.shadow) -#ifdef AMD_EXTENSIONS - if (sampler.type == EbtFloat16) - s.append("float16_t "); - else - s.append("float "); -#else - s.append("float "); -#endif - else { - s.append(prefixes[sampler.type]); - s.append("vec4 "); - } - } - - // name - if (sparse) { - if (fetch) - s.append("sparseTexel"); - else - s.append("sparseTexture"); - } - else { - if (fetch) - s.append("texel"); - else - s.append("texture"); - } - if (proj) - s.append("Proj"); - if (lod) - s.append("Lod"); - if (grad) - s.append("Grad"); - if (fetch) - s.append("Fetch"); - if (offset) - s.append("Offset"); - if (lodClamp) - s.append("Clamp"); - if (lodClamp || sparse) - s.append("ARB"); - s.append("("); - - // sampler type - s.append(typeName); -#ifdef AMD_EXTENSIONS - // P coordinate - if (extraProj) { - if (f16TexAddr) - s.append(",f16vec4"); - else - s.append(",vec4"); - } else { - s.append(","); - TBasicType t = fetch ? EbtInt : (f16TexAddr ? EbtFloat16 : EbtFloat); - if (totalDims == 1) - s.append(TType::getBasicString(t)); - else { - s.append(prefixes[t]); - s.append("vec"); - s.append(postfixes[totalDims]); - } - } -#else - // P coordinate - if (extraProj) - s.append(",vec4"); - else { - s.append(","); - TBasicType t = fetch ? EbtInt : EbtFloat; - if (totalDims == 1) - s.append(TType::getBasicString(t)); - else { - s.append(prefixes[t]); - s.append("vec"); - s.append(postfixes[totalDims]); - } - } -#endif - // non-optional compare - if (compare) - s.append(",float"); - - // non-optional lod argument (lod that's not driven by lod loop) or sample - if ((fetch && sampler.dim != EsdBuffer && sampler.dim != EsdRect && !sampler.ms) || - (sampler.ms && fetch)) - s.append(",int"); -#ifdef AMD_EXTENSIONS - // non-optional lod - if (lod) { - if (f16TexAddr) - s.append(",float16_t"); - else - s.append(",float"); - } - - // gradient arguments - if (grad) { - if (dimMap[sampler.dim] == 1) { - if (f16TexAddr) - s.append(",float16_t,float16_t"); - else - s.append(",float,float"); - } else { - if (f16TexAddr) - s.append(",f16vec"); - else - s.append(",vec"); - s.append(postfixes[dimMap[sampler.dim]]); - if (f16TexAddr) - s.append(",f16vec"); - else - s.append(",vec"); - s.append(postfixes[dimMap[sampler.dim]]); - } - } -#else - // non-optional lod - if (lod) - s.append(",float"); - - // gradient arguments - if (grad) { - if (dimMap[sampler.dim] == 1) - s.append(",float,float"); - else { - s.append(",vec"); - s.append(postfixes[dimMap[sampler.dim]]); - s.append(",vec"); - s.append(postfixes[dimMap[sampler.dim]]); - } - } -#endif - // offset - if (offset) { - if (dimMap[sampler.dim] == 1) - s.append(",int"); - else { - s.append(",ivec"); - s.append(postfixes[dimMap[sampler.dim]]); - } - } - -#ifdef AMD_EXTENSIONS - // lod clamp - if (lodClamp) { - if (f16TexAddr) - s.append(",float16_t"); - else - s.append(",float"); - } -#else - // lod clamp - if (lodClamp) - s.append(",float"); -#endif - // texel out (for sparse texture) - if (sparse) { - s.append(",out "); - if (sampler.shadow) -#ifdef AMD_EXTENSIONS - if (sampler.type == EbtFloat16) - s.append("float16_t"); - else - s.append("float"); -#else - s.append("float"); -#endif - else { - s.append(prefixes[sampler.type]); - s.append("vec4"); - } - } -#ifdef AMD_EXTENSIONS - // optional bias - if (bias) { - if (f16TexAddr) - s.append(",float16_t"); - else - s.append(",float"); - } -#else - // optional bias - if (bias) - s.append(",float"); -#endif - s.append(");\n"); - - // Add to the per-language set of built-ins - if (bias || lodClamp) - stageBuiltins[EShLangFragment].append(s); - else - commonBuiltins.append(s); - - } - } -#ifdef AMD_EXTENSIONS - } -#endif - } - } - } - } - } - } - } -} - -// -// Helper function for add2ndGenerationSamplingImaging(), -// when adding context-independent built-in functions. -// -// Add all the texture gather functions for the given type. -// -void TBuiltIns::addGatherFunctions(TSampler sampler, const TString& typeName, int version, EProfile profile) -{ - switch (sampler.dim) { - case Esd2D: - case EsdRect: - case EsdCube: - break; - default: - return; - } - - if (sampler.ms) - return; - - if (version < 140 && sampler.dim == EsdRect && sampler.type != EbtFloat) - return; - -#ifdef AMD_EXTENSIONS - for (int f16TexAddr = 0; f16TexAddr <= 1; ++f16TexAddr) { // loop over 16-bit floating-point texel addressing - - if (f16TexAddr && sampler.type != EbtFloat16) - continue; -#endif - for (int offset = 0; offset < 3; ++offset) { // loop over three forms of offset in the call name: none, Offset, and Offsets - - for (int comp = 0; comp < 2; ++comp) { // loop over presence of comp argument - - if (comp > 0 && sampler.shadow) - continue; - - if (offset > 0 && sampler.dim == EsdCube) - continue; - - for (int sparse = 0; sparse <= 1; ++sparse) { // loop over "bool" sparse or not - if (sparse && (profile == EEsProfile || version < 450)) - continue; - - TString s; - - // return type - if (sparse) - s.append("int "); - else { - s.append(prefixes[sampler.type]); - s.append("vec4 "); - } - - // name - if (sparse) - s.append("sparseTextureGather"); - else - s.append("textureGather"); - switch (offset) { - case 1: - s.append("Offset"); - break; - case 2: - s.append("Offsets"); - default: - break; - } - if (sparse) - s.append("ARB"); - s.append("("); - - // sampler type argument - s.append(typeName); - - // P coordinate argument -#ifdef AMD_EXTENSIONS - if (f16TexAddr) - s.append(",f16vec"); - else - s.append(",vec"); -#else - s.append(",vec"); -#endif - int totalDims = dimMap[sampler.dim] + (sampler.arrayed ? 1 : 0); - s.append(postfixes[totalDims]); - - // refZ argument - if (sampler.shadow) - s.append(",float"); - - // offset argument - if (offset > 0) { - s.append(",ivec2"); - if (offset == 2) - s.append("[4]"); - } - - // texel out (for sparse texture) - if (sparse) { - s.append(",out "); - s.append(prefixes[sampler.type]); - s.append("vec4 "); - } - - // comp argument - if (comp) - s.append(",int"); - - s.append(");\n"); - commonBuiltins.append(s); -#ifdef AMD_EXTENSIONS - } -#endif - } - } - } - -#ifdef AMD_EXTENSIONS - if (sampler.dim == EsdRect || sampler.shadow) - return; - - if (profile == EEsProfile || version < 450) - return; - - for (int bias = 0; bias < 2; ++bias) { // loop over presence of bias argument - - for (int lod = 0; lod < 2; ++lod) { // loop over presence of lod argument - - if ((lod && bias) || (lod == 0 && bias == 0)) - continue; - - for (int f16TexAddr = 0; f16TexAddr <= 1; ++f16TexAddr) { // loop over 16-bit floating-point texel addressing - - if (f16TexAddr && sampler.type != EbtFloat16) - continue; - - for (int offset = 0; offset < 3; ++offset) { // loop over three forms of offset in the call name: none, Offset, and Offsets - - for (int comp = 0; comp < 2; ++comp) { // loop over presence of comp argument - - if (comp == 0 && bias) - continue; - - if (offset > 0 && sampler.dim == EsdCube) - continue; - - for (int sparse = 0; sparse <= 1; ++sparse) { // loop over "bool" sparse or not - if (sparse && (profile == EEsProfile || version < 450)) - continue; - - TString s; - - // return type - if (sparse) - s.append("int "); - else { - s.append(prefixes[sampler.type]); - s.append("vec4 "); - } - - // name - if (sparse) - s.append("sparseTextureGather"); - else - s.append("textureGather"); - - if (lod) - s.append("Lod"); - - switch (offset) { - case 1: - s.append("Offset"); - break; - case 2: - s.append("Offsets"); - default: - break; - } - - if (lod) - s.append("AMD"); - else if (sparse) - s.append("ARB"); - - s.append("("); - - // sampler type argument - s.append(typeName); - - // P coordinate argument - if (f16TexAddr) - s.append(",f16vec"); - else - s.append(",vec"); - int totalDims = dimMap[sampler.dim] + (sampler.arrayed ? 1 : 0); - s.append(postfixes[totalDims]); - - // lod argument - if (lod) { - if (f16TexAddr) - s.append(",float16_t"); - else - s.append(",float"); - } - - // offset argument - if (offset > 0) { - s.append(",ivec2"); - if (offset == 2) - s.append("[4]"); - } - - // texel out (for sparse texture) - if (sparse) { - s.append(",out "); - s.append(prefixes[sampler.type]); - s.append("vec4 "); - } - - // comp argument - if (comp) - s.append(",int"); - - // bias argument - if (bias) { - if (f16TexAddr) - s.append(",float16_t"); - else - s.append(",float"); - } - - s.append(");\n"); - if (bias) - stageBuiltins[EShLangFragment].append(s); - else - commonBuiltins.append(s); - } - } - } - } - } - } -#endif -} - -// -// Add context-dependent built-in functions and variables that are present -// for the given version and profile. All the results are put into just the -// commonBuiltins, because it is called for just a specific stage. So, -// add stage-specific entries to the commonBuiltins, and only if that stage -// was requested. -// -void TBuiltIns::initialize(const TBuiltInResource &resources, int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage language) -{ - // - // Initialize the context-dependent (resource-dependent) built-in strings for parsing. - // - - //============================================================================ - // - // Standard Uniforms - // - //============================================================================ - - TString& s = commonBuiltins; - const int maxSize = 80; - char builtInConstant[maxSize]; - - // - // Build string of implementation dependent constants. - // - - if (profile == EEsProfile) { - snprintf(builtInConstant, maxSize, "const mediump int gl_MaxVertexAttribs = %d;", resources.maxVertexAttribs); - s.append(builtInConstant); - - snprintf(builtInConstant, maxSize, "const mediump int gl_MaxVertexUniformVectors = %d;", resources.maxVertexUniformVectors); - s.append(builtInConstant); - - snprintf(builtInConstant, maxSize, "const mediump int gl_MaxVertexTextureImageUnits = %d;", resources.maxVertexTextureImageUnits); - s.append(builtInConstant); - - snprintf(builtInConstant, maxSize, "const mediump int gl_MaxCombinedTextureImageUnits = %d;", resources.maxCombinedTextureImageUnits); - s.append(builtInConstant); - - snprintf(builtInConstant, maxSize, "const mediump int gl_MaxTextureImageUnits = %d;", resources.maxTextureImageUnits); - s.append(builtInConstant); - - snprintf(builtInConstant, maxSize, "const mediump int gl_MaxFragmentUniformVectors = %d;", resources.maxFragmentUniformVectors); - s.append(builtInConstant); - - snprintf(builtInConstant, maxSize, "const mediump int gl_MaxDrawBuffers = %d;", resources.maxDrawBuffers); - s.append(builtInConstant); - - if (version == 100) { - snprintf(builtInConstant, maxSize, "const mediump int gl_MaxVaryingVectors = %d;", resources.maxVaryingVectors); - s.append(builtInConstant); - } else { - snprintf(builtInConstant, maxSize, "const mediump int gl_MaxVertexOutputVectors = %d;", resources.maxVertexOutputVectors); - s.append(builtInConstant); - - snprintf(builtInConstant, maxSize, "const mediump int gl_MaxFragmentInputVectors = %d;", resources.maxFragmentInputVectors); - s.append(builtInConstant); - - snprintf(builtInConstant, maxSize, "const mediump int gl_MinProgramTexelOffset = %d;", resources.minProgramTexelOffset); - s.append(builtInConstant); - - snprintf(builtInConstant, maxSize, "const mediump int gl_MaxProgramTexelOffset = %d;", resources.maxProgramTexelOffset); - s.append(builtInConstant); - } - - if (version >= 310) { - // geometry - - snprintf(builtInConstant, maxSize, "const int gl_MaxGeometryInputComponents = %d;", resources.maxGeometryInputComponents); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxGeometryOutputComponents = %d;", resources.maxGeometryOutputComponents); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxGeometryImageUniforms = %d;", resources.maxGeometryImageUniforms); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxGeometryTextureImageUnits = %d;", resources.maxGeometryTextureImageUnits); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxGeometryOutputVertices = %d;", resources.maxGeometryOutputVertices); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxGeometryTotalOutputComponents = %d;", resources.maxGeometryTotalOutputComponents); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxGeometryUniformComponents = %d;", resources.maxGeometryUniformComponents); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxGeometryAtomicCounters = %d;", resources.maxGeometryAtomicCounters); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxGeometryAtomicCounterBuffers = %d;", resources.maxGeometryAtomicCounterBuffers); - s.append(builtInConstant); - - // tessellation - - snprintf(builtInConstant, maxSize, "const int gl_MaxTessControlInputComponents = %d;", resources.maxTessControlInputComponents); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxTessControlOutputComponents = %d;", resources.maxTessControlOutputComponents); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxTessControlTextureImageUnits = %d;", resources.maxTessControlTextureImageUnits); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxTessControlUniformComponents = %d;", resources.maxTessControlUniformComponents); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxTessControlTotalOutputComponents = %d;", resources.maxTessControlTotalOutputComponents); - s.append(builtInConstant); - - snprintf(builtInConstant, maxSize, "const int gl_MaxTessEvaluationInputComponents = %d;", resources.maxTessEvaluationInputComponents); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxTessEvaluationOutputComponents = %d;", resources.maxTessEvaluationOutputComponents); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxTessEvaluationTextureImageUnits = %d;", resources.maxTessEvaluationTextureImageUnits); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxTessEvaluationUniformComponents = %d;", resources.maxTessEvaluationUniformComponents); - s.append(builtInConstant); - - snprintf(builtInConstant, maxSize, "const int gl_MaxTessPatchComponents = %d;", resources.maxTessPatchComponents); - s.append(builtInConstant); - - snprintf(builtInConstant, maxSize, "const int gl_MaxPatchVertices = %d;", resources.maxPatchVertices); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxTessGenLevel = %d;", resources.maxTessGenLevel); - s.append(builtInConstant); - - // this is here instead of with the others in initialize(version, profile) due to the dependence on gl_MaxPatchVertices - if (language == EShLangTessControl || language == EShLangTessEvaluation) { - s.append( - "in gl_PerVertex {" - "highp vec4 gl_Position;" - "highp float gl_PointSize;" -#ifdef NV_EXTENSIONS - "highp vec4 gl_SecondaryPositionNV;" // GL_NV_stereo_view_rendering - "highp vec4 gl_PositionPerViewNV[];" // GL_NVX_multiview_per_view_attributes -#endif - "} gl_in[gl_MaxPatchVertices];" - "\n"); - } - } - - } else { - // non-ES profile - - snprintf(builtInConstant, maxSize, "const int gl_MaxVertexAttribs = %d;", resources.maxVertexAttribs); - s.append(builtInConstant); - - snprintf(builtInConstant, maxSize, "const int gl_MaxVertexTextureImageUnits = %d;", resources.maxVertexTextureImageUnits); - s.append(builtInConstant); - - snprintf(builtInConstant, maxSize, "const int gl_MaxCombinedTextureImageUnits = %d;", resources.maxCombinedTextureImageUnits); - s.append(builtInConstant); - - snprintf(builtInConstant, maxSize, "const int gl_MaxTextureImageUnits = %d;", resources.maxTextureImageUnits); - s.append(builtInConstant); - - snprintf(builtInConstant, maxSize, "const int gl_MaxDrawBuffers = %d;", resources.maxDrawBuffers); - s.append(builtInConstant); - - snprintf(builtInConstant, maxSize, "const int gl_MaxLights = %d;", resources.maxLights); - s.append(builtInConstant); - - snprintf(builtInConstant, maxSize, "const int gl_MaxClipPlanes = %d;", resources.maxClipPlanes); - s.append(builtInConstant); - - snprintf(builtInConstant, maxSize, "const int gl_MaxTextureUnits = %d;", resources.maxTextureUnits); - s.append(builtInConstant); - - snprintf(builtInConstant, maxSize, "const int gl_MaxTextureCoords = %d;", resources.maxTextureCoords); - s.append(builtInConstant); - - snprintf(builtInConstant, maxSize, "const int gl_MaxVertexUniformComponents = %d;", resources.maxVertexUniformComponents); - s.append(builtInConstant); - - if (version < 150 || ARBCompatibility) { - snprintf(builtInConstant, maxSize, "const int gl_MaxVaryingFloats = %d;", resources.maxVaryingFloats); - s.append(builtInConstant); - } - - snprintf(builtInConstant, maxSize, "const int gl_MaxFragmentUniformComponents = %d;", resources.maxFragmentUniformComponents); - s.append(builtInConstant); - - if (spvVersion.spv == 0 && IncludeLegacy(version, profile, spvVersion)) { - // - // OpenGL'uniform' state. Page numbers are in reference to version - // 1.4 of the OpenGL specification. - // - - // - // Matrix state. p. 31, 32, 37, 39, 40. - // - s.append("uniform mat4 gl_TextureMatrix[gl_MaxTextureCoords];" - - // - // Derived matrix state that provides inverse and transposed versions - // of the matrices above. - // - "uniform mat4 gl_TextureMatrixInverse[gl_MaxTextureCoords];" - - "uniform mat4 gl_TextureMatrixTranspose[gl_MaxTextureCoords];" - - "uniform mat4 gl_TextureMatrixInverseTranspose[gl_MaxTextureCoords];" - - // - // Clip planes p. 42. - // - "uniform vec4 gl_ClipPlane[gl_MaxClipPlanes];" - - // - // Light State p 50, 53, 55. - // - "uniform gl_LightSourceParameters gl_LightSource[gl_MaxLights];" - - // - // Derived state from products of light. - // - "uniform gl_LightProducts gl_FrontLightProduct[gl_MaxLights];" - "uniform gl_LightProducts gl_BackLightProduct[gl_MaxLights];" - - // - // Texture Environment and Generation, p. 152, p. 40-42. - // - "uniform vec4 gl_TextureEnvColor[gl_MaxTextureImageUnits];" - "uniform vec4 gl_EyePlaneS[gl_MaxTextureCoords];" - "uniform vec4 gl_EyePlaneT[gl_MaxTextureCoords];" - "uniform vec4 gl_EyePlaneR[gl_MaxTextureCoords];" - "uniform vec4 gl_EyePlaneQ[gl_MaxTextureCoords];" - "uniform vec4 gl_ObjectPlaneS[gl_MaxTextureCoords];" - "uniform vec4 gl_ObjectPlaneT[gl_MaxTextureCoords];" - "uniform vec4 gl_ObjectPlaneR[gl_MaxTextureCoords];" - "uniform vec4 gl_ObjectPlaneQ[gl_MaxTextureCoords];"); - } - - if (version >= 130) { - snprintf(builtInConstant, maxSize, "const int gl_MaxClipDistances = %d;", resources.maxClipDistances); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxVaryingComponents = %d;", resources.maxVaryingComponents); - s.append(builtInConstant); - - // GL_ARB_shading_language_420pack - snprintf(builtInConstant, maxSize, "const mediump int gl_MinProgramTexelOffset = %d;", resources.minProgramTexelOffset); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const mediump int gl_MaxProgramTexelOffset = %d;", resources.maxProgramTexelOffset); - s.append(builtInConstant); - } - - // geometry - if (version >= 150) { - snprintf(builtInConstant, maxSize, "const int gl_MaxGeometryInputComponents = %d;", resources.maxGeometryInputComponents); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxGeometryOutputComponents = %d;", resources.maxGeometryOutputComponents); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxGeometryTextureImageUnits = %d;", resources.maxGeometryTextureImageUnits); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxGeometryOutputVertices = %d;", resources.maxGeometryOutputVertices); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxGeometryTotalOutputComponents = %d;", resources.maxGeometryTotalOutputComponents); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxGeometryUniformComponents = %d;", resources.maxGeometryUniformComponents); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxGeometryVaryingComponents = %d;", resources.maxGeometryVaryingComponents); - s.append(builtInConstant); - - } - - if (version >= 150) { - snprintf(builtInConstant, maxSize, "const int gl_MaxVertexOutputComponents = %d;", resources.maxVertexOutputComponents); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxFragmentInputComponents = %d;", resources.maxFragmentInputComponents); - s.append(builtInConstant); - } - - // tessellation - if (version >= 150) { - snprintf(builtInConstant, maxSize, "const int gl_MaxTessControlInputComponents = %d;", resources.maxTessControlInputComponents); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxTessControlOutputComponents = %d;", resources.maxTessControlOutputComponents); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxTessControlTextureImageUnits = %d;", resources.maxTessControlTextureImageUnits); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxTessControlUniformComponents = %d;", resources.maxTessControlUniformComponents); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxTessControlTotalOutputComponents = %d;", resources.maxTessControlTotalOutputComponents); - s.append(builtInConstant); - - snprintf(builtInConstant, maxSize, "const int gl_MaxTessEvaluationInputComponents = %d;", resources.maxTessEvaluationInputComponents); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxTessEvaluationOutputComponents = %d;", resources.maxTessEvaluationOutputComponents); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxTessEvaluationTextureImageUnits = %d;", resources.maxTessEvaluationTextureImageUnits); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxTessEvaluationUniformComponents = %d;", resources.maxTessEvaluationUniformComponents); - s.append(builtInConstant); - - snprintf(builtInConstant, maxSize, "const int gl_MaxTessPatchComponents = %d;", resources.maxTessPatchComponents); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxTessGenLevel = %d;", resources.maxTessGenLevel); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxPatchVertices = %d;", resources.maxPatchVertices); - s.append(builtInConstant); - - // this is here instead of with the others in initialize(version, profile) due to the dependence on gl_MaxPatchVertices - if (language == EShLangTessControl || language == EShLangTessEvaluation) { - s.append( - "in gl_PerVertex {" - "vec4 gl_Position;" - "float gl_PointSize;" - "float gl_ClipDistance[];" - ); - if (profile == ECompatibilityProfile) - s.append( - "vec4 gl_ClipVertex;" - "vec4 gl_FrontColor;" - "vec4 gl_BackColor;" - "vec4 gl_FrontSecondaryColor;" - "vec4 gl_BackSecondaryColor;" - "vec4 gl_TexCoord[];" - "float gl_FogFragCoord;" - ); - if (profile != EEsProfile && version >= 450) - s.append( - "float gl_CullDistance[];" -#ifdef NV_EXTENSIONS - "vec4 gl_SecondaryPositionNV;" // GL_NV_stereo_view_rendering - "vec4 gl_PositionPerViewNV[];" // GL_NVX_multiview_per_view_attributes -#endif - ); - s.append( - "} gl_in[gl_MaxPatchVertices];" - "\n"); - } - } - - if (version >= 150) { - snprintf(builtInConstant, maxSize, "const int gl_MaxViewports = %d;", resources.maxViewports); - s.append(builtInConstant); - } - - // images - if (version >= 130) { - snprintf(builtInConstant, maxSize, "const int gl_MaxCombinedImageUnitsAndFragmentOutputs = %d;", resources.maxCombinedImageUnitsAndFragmentOutputs); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxImageSamples = %d;", resources.maxImageSamples); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxTessControlImageUniforms = %d;", resources.maxTessControlImageUniforms); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxTessEvaluationImageUniforms = %d;", resources.maxTessEvaluationImageUniforms); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxGeometryImageUniforms = %d;", resources.maxGeometryImageUniforms); - s.append(builtInConstant); - } - - // enhanced layouts - if (version >= 430) { - snprintf(builtInConstant, maxSize, "const int gl_MaxTransformFeedbackBuffers = %d;", resources.maxTransformFeedbackBuffers); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxTransformFeedbackInterleavedComponents = %d;", resources.maxTransformFeedbackInterleavedComponents); - s.append(builtInConstant); - } - } - - // images (some in compute below) - if ((profile == EEsProfile && version >= 310) || - (profile != EEsProfile && version >= 130)) { - snprintf(builtInConstant, maxSize, "const int gl_MaxImageUnits = %d;", resources.maxImageUnits); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxCombinedShaderOutputResources = %d;", resources.maxCombinedShaderOutputResources); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxVertexImageUniforms = %d;", resources.maxVertexImageUniforms); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxFragmentImageUniforms = %d;", resources.maxFragmentImageUniforms); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxCombinedImageUniforms = %d;", resources.maxCombinedImageUniforms); - s.append(builtInConstant); - } - - // atomic counters (some in compute below) - if ((profile == EEsProfile && version >= 310) || - (profile != EEsProfile && version >= 420)) { - snprintf(builtInConstant, maxSize, "const int gl_MaxVertexAtomicCounters = %d;", resources. maxVertexAtomicCounters); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxFragmentAtomicCounters = %d;", resources. maxFragmentAtomicCounters); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxCombinedAtomicCounters = %d;", resources. maxCombinedAtomicCounters); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxAtomicCounterBindings = %d;", resources. maxAtomicCounterBindings); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxVertexAtomicCounterBuffers = %d;", resources. maxVertexAtomicCounterBuffers); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxFragmentAtomicCounterBuffers = %d;", resources. maxFragmentAtomicCounterBuffers); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxCombinedAtomicCounterBuffers = %d;", resources. maxCombinedAtomicCounterBuffers); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxAtomicCounterBufferSize = %d;", resources. maxAtomicCounterBufferSize); - s.append(builtInConstant); - } - if (profile != EEsProfile && version >= 420) { - snprintf(builtInConstant, maxSize, "const int gl_MaxTessControlAtomicCounters = %d;", resources. maxTessControlAtomicCounters); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxTessEvaluationAtomicCounters = %d;", resources. maxTessEvaluationAtomicCounters); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxGeometryAtomicCounters = %d;", resources. maxGeometryAtomicCounters); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxTessControlAtomicCounterBuffers = %d;", resources. maxTessControlAtomicCounterBuffers); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxTessEvaluationAtomicCounterBuffers = %d;", resources. maxTessEvaluationAtomicCounterBuffers); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxGeometryAtomicCounterBuffers = %d;", resources. maxGeometryAtomicCounterBuffers); - s.append(builtInConstant); - - s.append("\n"); - } - - // compute - if ((profile == EEsProfile && version >= 310) || (profile != EEsProfile && version >= 420)) { - snprintf(builtInConstant, maxSize, "const ivec3 gl_MaxComputeWorkGroupCount = ivec3(%d,%d,%d);", resources.maxComputeWorkGroupCountX, - resources.maxComputeWorkGroupCountY, - resources.maxComputeWorkGroupCountZ); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const ivec3 gl_MaxComputeWorkGroupSize = ivec3(%d,%d,%d);", resources.maxComputeWorkGroupSizeX, - resources.maxComputeWorkGroupSizeY, - resources.maxComputeWorkGroupSizeZ); - s.append(builtInConstant); - - snprintf(builtInConstant, maxSize, "const int gl_MaxComputeUniformComponents = %d;", resources.maxComputeUniformComponents); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxComputeTextureImageUnits = %d;", resources.maxComputeTextureImageUnits); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxComputeImageUniforms = %d;", resources.maxComputeImageUniforms); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxComputeAtomicCounters = %d;", resources.maxComputeAtomicCounters); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxComputeAtomicCounterBuffers = %d;", resources.maxComputeAtomicCounterBuffers); - s.append(builtInConstant); - - s.append("\n"); - } - - // GL_ARB_cull_distance - if (profile != EEsProfile && version >= 450) { - snprintf(builtInConstant, maxSize, "const int gl_MaxCullDistances = %d;", resources.maxCullDistances); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxCombinedClipAndCullDistances = %d;", resources.maxCombinedClipAndCullDistances); - s.append(builtInConstant); - } - - // GL_ARB_ES3_1_compatibility - if ((profile != EEsProfile && version >= 450) || - (profile == EEsProfile && version >= 310)) { - snprintf(builtInConstant, maxSize, "const int gl_MaxSamples = %d;", resources.maxSamples); - s.append(builtInConstant); - } - -#ifdef AMD_EXTENSIONS - // GL_AMD_gcn_shader - if (profile != EEsProfile && version >= 450) { - snprintf(builtInConstant, maxSize, "const int gl_SIMDGroupSizeAMD = 64;"); - s.append(builtInConstant); - } -#endif - - s.append("\n"); -} - -// -// To support special built-ins that have a special qualifier that cannot be declared textually -// in a shader, like gl_Position. -// -// This lets the type of the built-in be declared textually, and then have just its qualifier be -// updated afterward. -// -// Safe to call even if name is not present. -// -// Only use this for built-in variables that have a special qualifier in TStorageQualifier. -// New built-in variables should use a generic (textually declarable) qualifier in -// TStoraregQualifier and only call BuiltInVariable(). -// -static void SpecialQualifier(const char* name, TStorageQualifier qualifier, TBuiltInVariable builtIn, TSymbolTable& symbolTable) -{ - TSymbol* symbol = symbolTable.find(name); - if (symbol) { - TQualifier& symQualifier = symbol->getWritableType().getQualifier(); - symQualifier.storage = qualifier; - symQualifier.builtIn = builtIn; - } -} - -// -// To tag built-in variables with their TBuiltInVariable enum. Use this when the -// normal declaration text already gets the qualifier right, and all that's needed -// is setting the builtIn field. This should be the normal way for all new -// built-in variables. -// -// If SpecialQualifier() was called, this does not need to be called. -// -// Safe to call even if name is not present. -// -static void BuiltInVariable(const char* name, TBuiltInVariable builtIn, TSymbolTable& symbolTable) -{ - TSymbol* symbol = symbolTable.find(name); - if (! symbol) - return; - - TQualifier& symQualifier = symbol->getWritableType().getQualifier(); - symQualifier.builtIn = builtIn; -} - -// -// For built-in variables inside a named block. -// SpecialQualifier() won't ever go inside a block; their member's qualifier come -// from the qualification of the block. -// -// See comments above for other detail. -// -static void BuiltInVariable(const char* blockName, const char* name, TBuiltInVariable builtIn, TSymbolTable& symbolTable) -{ - TSymbol* symbol = symbolTable.find(blockName); - if (! symbol) - return; - - TTypeList& structure = *symbol->getWritableType().getWritableStruct(); - for (int i = 0; i < (int)structure.size(); ++i) { - if (structure[i].type->getFieldName().compare(name) == 0) { - structure[i].type->getQualifier().builtIn = builtIn; - return; - } - } -} - -// -// Finish adding/processing context-independent built-in symbols. -// 1) Programmatically add symbols that could not be added by simple text strings above. -// 2) Map built-in functions to operators, for those that will turn into an operation node -// instead of remaining a function call. -// 3) Tag extension-related symbols added to their base version with their extensions, so -// that if an early version has the extension turned off, there is an error reported on use. -// -void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage language, TSymbolTable& symbolTable) -{ - // - // Tag built-in variables and functions with additional qualifier and extension information - // that cannot be declared with the text strings. - // - - // N.B.: a symbol should only be tagged once, and this function is called multiple times, once - // per stage that's used for this profile. So - // - generally, stick common ones in the fragment stage to ensure they are tagged exactly once - // - for ES, which has different precisions for different stages, the coarsest-grained tagging - // for a built-in used in many stages needs to be once for the fragment stage and once for - // the vertex stage - - switch(language) { - case EShLangVertex: - if (profile != EEsProfile) { - if (version >= 440) { - symbolTable.setVariableExtensions("gl_BaseVertexARB", 1, &E_GL_ARB_shader_draw_parameters); - symbolTable.setVariableExtensions("gl_BaseInstanceARB", 1, &E_GL_ARB_shader_draw_parameters); - symbolTable.setVariableExtensions("gl_DrawIDARB", 1, &E_GL_ARB_shader_draw_parameters); - BuiltInVariable("gl_BaseVertexARB", EbvBaseVertex, symbolTable); - BuiltInVariable("gl_BaseInstanceARB", EbvBaseInstance, symbolTable); - BuiltInVariable("gl_DrawIDARB", EbvDrawId, symbolTable); - } - if (version >= 460) { - BuiltInVariable("gl_BaseVertex", EbvBaseVertex, symbolTable); - BuiltInVariable("gl_BaseInstance", EbvBaseInstance, symbolTable); - BuiltInVariable("gl_DrawID", EbvDrawId, symbolTable); - } - symbolTable.setVariableExtensions("gl_SubGroupSizeARB", 1, &E_GL_ARB_shader_ballot); - symbolTable.setVariableExtensions("gl_SubGroupInvocationARB", 1, &E_GL_ARB_shader_ballot); - symbolTable.setVariableExtensions("gl_SubGroupEqMaskARB", 1, &E_GL_ARB_shader_ballot); - symbolTable.setVariableExtensions("gl_SubGroupGeMaskARB", 1, &E_GL_ARB_shader_ballot); - symbolTable.setVariableExtensions("gl_SubGroupGtMaskARB", 1, &E_GL_ARB_shader_ballot); - symbolTable.setVariableExtensions("gl_SubGroupLeMaskARB", 1, &E_GL_ARB_shader_ballot); - symbolTable.setVariableExtensions("gl_SubGroupLtMaskARB", 1, &E_GL_ARB_shader_ballot); - - symbolTable.setFunctionExtensions("ballotARB", 1, &E_GL_ARB_shader_ballot); - symbolTable.setFunctionExtensions("readInvocationARB", 1, &E_GL_ARB_shader_ballot); - symbolTable.setFunctionExtensions("readFirstInvocationARB", 1, &E_GL_ARB_shader_ballot); - - BuiltInVariable("gl_SubGroupInvocationARB", EbvSubGroupInvocation, symbolTable); - BuiltInVariable("gl_SubGroupEqMaskARB", EbvSubGroupEqMask, symbolTable); - BuiltInVariable("gl_SubGroupGeMaskARB", EbvSubGroupGeMask, symbolTable); - BuiltInVariable("gl_SubGroupGtMaskARB", EbvSubGroupGtMask, symbolTable); - BuiltInVariable("gl_SubGroupLeMaskARB", EbvSubGroupLeMask, symbolTable); - BuiltInVariable("gl_SubGroupLtMaskARB", EbvSubGroupLtMask, symbolTable); - - if (spvVersion.vulkan > 0) - // Treat "gl_SubGroupSizeARB" as shader input instead of uniform for Vulkan - SpecialQualifier("gl_SubGroupSizeARB", EvqVaryingIn, EbvSubGroupSize, symbolTable); - else - BuiltInVariable("gl_SubGroupSizeARB", EbvSubGroupSize, symbolTable); - - if (version >= 430) { - symbolTable.setFunctionExtensions("anyInvocationARB", 1, &E_GL_ARB_shader_group_vote); - symbolTable.setFunctionExtensions("allInvocationsARB", 1, &E_GL_ARB_shader_group_vote); - symbolTable.setFunctionExtensions("allInvocationsEqualARB", 1, &E_GL_ARB_shader_group_vote); - } - } - -#ifdef AMD_EXTENSIONS - if (profile != EEsProfile) { - symbolTable.setFunctionExtensions("minInvocationsAMD", 1, &E_GL_AMD_shader_ballot); - symbolTable.setFunctionExtensions("maxInvocationsAMD", 1, &E_GL_AMD_shader_ballot); - symbolTable.setFunctionExtensions("addInvocationsAMD", 1, &E_GL_AMD_shader_ballot); - symbolTable.setFunctionExtensions("minInvocationsNonUniformAMD", 1, &E_GL_AMD_shader_ballot); - symbolTable.setFunctionExtensions("maxInvocationsNonUniformAMD", 1, &E_GL_AMD_shader_ballot); - symbolTable.setFunctionExtensions("addInvocationsNonUniformAMD", 1, &E_GL_AMD_shader_ballot); - symbolTable.setFunctionExtensions("swizzleInvocationsAMD", 1, &E_GL_AMD_shader_ballot); - symbolTable.setFunctionExtensions("swizzleInvocationsWithPatternAMD", 1, &E_GL_AMD_shader_ballot); - symbolTable.setFunctionExtensions("writeInvocationAMD", 1, &E_GL_AMD_shader_ballot); - symbolTable.setFunctionExtensions("mbcntAMD", 1, &E_GL_AMD_shader_ballot); - - symbolTable.setFunctionExtensions("minInvocationsInclusiveScanAMD", 1, &E_GL_AMD_shader_ballot); - symbolTable.setFunctionExtensions("maxInvocationsInclusiveScanAMD", 1, &E_GL_AMD_shader_ballot); - symbolTable.setFunctionExtensions("addInvocationsInclusiveScanAMD", 1, &E_GL_AMD_shader_ballot); - symbolTable.setFunctionExtensions("minInvocationsInclusiveScanNonUniformAMD", 1, &E_GL_AMD_shader_ballot); - symbolTable.setFunctionExtensions("maxInvocationsInclusiveScanNonUniformAMD", 1, &E_GL_AMD_shader_ballot); - symbolTable.setFunctionExtensions("addInvocationsInclusiveScanNonUniformAMD", 1, &E_GL_AMD_shader_ballot); - symbolTable.setFunctionExtensions("minInvocationsExclusiveScanAMD", 1, &E_GL_AMD_shader_ballot); - symbolTable.setFunctionExtensions("maxInvocationsExclusiveScanAMD", 1, &E_GL_AMD_shader_ballot); - symbolTable.setFunctionExtensions("addInvocationsExclusiveScanAMD", 1, &E_GL_AMD_shader_ballot); - symbolTable.setFunctionExtensions("minInvocationsExclusiveScanNonUniformAMD", 1, &E_GL_AMD_shader_ballot); - symbolTable.setFunctionExtensions("maxInvocationsExclusiveScanNonUniformAMD", 1, &E_GL_AMD_shader_ballot); - symbolTable.setFunctionExtensions("addInvocationsExclusiveScanNonUniformAMD", 1, &E_GL_AMD_shader_ballot); - } - - if (profile != EEsProfile) { - symbolTable.setFunctionExtensions("min3", 1, &E_GL_AMD_shader_trinary_minmax); - symbolTable.setFunctionExtensions("max3", 1, &E_GL_AMD_shader_trinary_minmax); - symbolTable.setFunctionExtensions("mid3", 1, &E_GL_AMD_shader_trinary_minmax); - } - - if (profile != EEsProfile) { - symbolTable.setFunctionExtensions("cubeFaceIndexAMD", 1, &E_GL_AMD_gcn_shader); - symbolTable.setFunctionExtensions("cubeFaceCoordAMD", 1, &E_GL_AMD_gcn_shader); - symbolTable.setFunctionExtensions("timeAMD", 1, &E_GL_AMD_gcn_shader); - } - - if (profile != EEsProfile) { - symbolTable.setFunctionExtensions("fragmentMaskFetchAMD", 1, &E_GL_AMD_shader_fragment_mask); - symbolTable.setFunctionExtensions("fragmentFetchAMD", 1, &E_GL_AMD_shader_fragment_mask); - } -#endif - - // Compatibility variables, vertex only - if (spvVersion.spv == 0) { - BuiltInVariable("gl_Color", EbvColor, symbolTable); - BuiltInVariable("gl_SecondaryColor", EbvSecondaryColor, symbolTable); - BuiltInVariable("gl_Normal", EbvNormal, symbolTable); - BuiltInVariable("gl_Vertex", EbvVertex, symbolTable); - BuiltInVariable("gl_MultiTexCoord0", EbvMultiTexCoord0, symbolTable); - BuiltInVariable("gl_MultiTexCoord1", EbvMultiTexCoord1, symbolTable); - BuiltInVariable("gl_MultiTexCoord2", EbvMultiTexCoord2, symbolTable); - BuiltInVariable("gl_MultiTexCoord3", EbvMultiTexCoord3, symbolTable); - BuiltInVariable("gl_MultiTexCoord4", EbvMultiTexCoord4, symbolTable); - BuiltInVariable("gl_MultiTexCoord5", EbvMultiTexCoord5, symbolTable); - BuiltInVariable("gl_MultiTexCoord6", EbvMultiTexCoord6, symbolTable); - BuiltInVariable("gl_MultiTexCoord7", EbvMultiTexCoord7, symbolTable); - BuiltInVariable("gl_FogCoord", EbvFogFragCoord, symbolTable); - } - - if (profile == EEsProfile) { - if (spvVersion.spv == 0) { - symbolTable.setFunctionExtensions("texture2DGradEXT", 1, &E_GL_EXT_shader_texture_lod); - symbolTable.setFunctionExtensions("texture2DProjGradEXT", 1, &E_GL_EXT_shader_texture_lod); - symbolTable.setFunctionExtensions("textureCubeGradEXT", 1, &E_GL_EXT_shader_texture_lod); - if (version == 310) - symbolTable.setFunctionExtensions("textureGatherOffsets", Num_AEP_gpu_shader5, AEP_gpu_shader5); - } - if (version == 310) - symbolTable.setFunctionExtensions("fma", Num_AEP_gpu_shader5, AEP_gpu_shader5); - } - - if (profile == EEsProfile && version < 320) { - symbolTable.setFunctionExtensions("imageAtomicAdd", 1, &E_GL_OES_shader_image_atomic); - symbolTable.setFunctionExtensions("imageAtomicMin", 1, &E_GL_OES_shader_image_atomic); - symbolTable.setFunctionExtensions("imageAtomicMax", 1, &E_GL_OES_shader_image_atomic); - symbolTable.setFunctionExtensions("imageAtomicAnd", 1, &E_GL_OES_shader_image_atomic); - symbolTable.setFunctionExtensions("imageAtomicOr", 1, &E_GL_OES_shader_image_atomic); - symbolTable.setFunctionExtensions("imageAtomicXor", 1, &E_GL_OES_shader_image_atomic); - symbolTable.setFunctionExtensions("imageAtomicExchange", 1, &E_GL_OES_shader_image_atomic); - symbolTable.setFunctionExtensions("imageAtomicCompSwap", 1, &E_GL_OES_shader_image_atomic); - } - - if (spvVersion.vulkan == 0) { - SpecialQualifier("gl_VertexID", EvqVertexId, EbvVertexId, symbolTable); - SpecialQualifier("gl_InstanceID", EvqInstanceId, EbvInstanceId, symbolTable); - } - - if (spvVersion.vulkan > 0) { - BuiltInVariable("gl_VertexIndex", EbvVertexIndex, symbolTable); - BuiltInVariable("gl_InstanceIndex", EbvInstanceIndex, symbolTable); - } - - if (version >= 300 /* both ES and non-ES */) { - symbolTable.setVariableExtensions("gl_ViewID_OVR", Num_OVR_multiview_EXTs, OVR_multiview_EXTs); - BuiltInVariable("gl_ViewID_OVR", EbvViewIndex, symbolTable); - } - - if (profile == EEsProfile) { - symbolTable.setFunctionExtensions("shadow2DEXT", 1, &E_GL_EXT_shadow_samplers); - symbolTable.setFunctionExtensions("shadow2DProjEXT", 1, &E_GL_EXT_shadow_samplers); - } - - // Fall through - - case EShLangTessControl: - if (profile == EEsProfile && version >= 310) { - BuiltInVariable("gl_BoundingBoxOES", EbvBoundingBox, symbolTable); - if (version < 320) - symbolTable.setVariableExtensions("gl_BoundingBoxOES", Num_AEP_primitive_bounding_box, - AEP_primitive_bounding_box); - } - - // Fall through - - case EShLangTessEvaluation: - case EShLangGeometry: - SpecialQualifier("gl_Position", EvqPosition, EbvPosition, symbolTable); - SpecialQualifier("gl_PointSize", EvqPointSize, EbvPointSize, symbolTable); - SpecialQualifier("gl_ClipVertex", EvqClipVertex, EbvClipVertex, symbolTable); - - BuiltInVariable("gl_in", "gl_Position", EbvPosition, symbolTable); - BuiltInVariable("gl_in", "gl_PointSize", EbvPointSize, symbolTable); - BuiltInVariable("gl_in", "gl_ClipDistance", EbvClipDistance, symbolTable); - BuiltInVariable("gl_in", "gl_CullDistance", EbvCullDistance, symbolTable); - - BuiltInVariable("gl_out", "gl_Position", EbvPosition, symbolTable); - BuiltInVariable("gl_out", "gl_PointSize", EbvPointSize, symbolTable); - BuiltInVariable("gl_out", "gl_ClipDistance", EbvClipDistance, symbolTable); - BuiltInVariable("gl_out", "gl_CullDistance", EbvCullDistance, symbolTable); - - BuiltInVariable("gl_ClipDistance", EbvClipDistance, symbolTable); - BuiltInVariable("gl_CullDistance", EbvCullDistance, symbolTable); - BuiltInVariable("gl_PrimitiveIDIn", EbvPrimitiveId, symbolTable); - BuiltInVariable("gl_PrimitiveID", EbvPrimitiveId, symbolTable); - BuiltInVariable("gl_InvocationID", EbvInvocationId, symbolTable); - BuiltInVariable("gl_Layer", EbvLayer, symbolTable); - BuiltInVariable("gl_ViewportIndex", EbvViewportIndex, symbolTable); - -#ifdef NV_EXTENSIONS - if (language != EShLangGeometry) { - symbolTable.setVariableExtensions("gl_Layer", Num_viewportEXTs, viewportEXTs); - symbolTable.setVariableExtensions("gl_ViewportIndex", Num_viewportEXTs, viewportEXTs); - } -#else - if (language != EShLangGeometry && version >= 410) { - symbolTable.setVariableExtensions("gl_Layer", 1, &E_GL_ARB_shader_viewport_layer_array); - symbolTable.setVariableExtensions("gl_ViewportIndex", 1, &E_GL_ARB_shader_viewport_layer_array); - } -#endif - -#ifdef NV_EXTENSIONS - symbolTable.setVariableExtensions("gl_ViewportMask", 1, &E_GL_NV_viewport_array2); - symbolTable.setVariableExtensions("gl_SecondaryPositionNV", 1, &E_GL_NV_stereo_view_rendering); - symbolTable.setVariableExtensions("gl_SecondaryViewportMaskNV", 1, &E_GL_NV_stereo_view_rendering); - symbolTable.setVariableExtensions("gl_PositionPerViewNV", 1, &E_GL_NVX_multiview_per_view_attributes); - symbolTable.setVariableExtensions("gl_ViewportMaskPerViewNV", 1, &E_GL_NVX_multiview_per_view_attributes); - - BuiltInVariable("gl_ViewportMask", EbvViewportMaskNV, symbolTable); - BuiltInVariable("gl_SecondaryPositionNV", EbvSecondaryPositionNV, symbolTable); - BuiltInVariable("gl_SecondaryViewportMaskNV", EbvSecondaryViewportMaskNV, symbolTable); - BuiltInVariable("gl_PositionPerViewNV", EbvPositionPerViewNV, symbolTable); - BuiltInVariable("gl_ViewportMaskPerViewNV", EbvViewportMaskPerViewNV, symbolTable); - - if (language != EShLangVertex) { - BuiltInVariable("gl_in", "gl_SecondaryPositionNV", EbvSecondaryPositionNV, symbolTable); - BuiltInVariable("gl_in", "gl_PositionPerViewNV", EbvPositionPerViewNV, symbolTable); - } - BuiltInVariable("gl_out", "gl_ViewportMask", EbvViewportMaskNV, symbolTable); - BuiltInVariable("gl_out", "gl_SecondaryPositionNV", EbvSecondaryPositionNV, symbolTable); - BuiltInVariable("gl_out", "gl_SecondaryViewportMaskNV", EbvSecondaryViewportMaskNV, symbolTable); - BuiltInVariable("gl_out", "gl_PositionPerViewNV", EbvPositionPerViewNV, symbolTable); - BuiltInVariable("gl_out", "gl_ViewportMaskPerViewNV", EbvViewportMaskPerViewNV, symbolTable); -#endif - - BuiltInVariable("gl_PatchVerticesIn", EbvPatchVertices, symbolTable); - BuiltInVariable("gl_TessLevelOuter", EbvTessLevelOuter, symbolTable); - BuiltInVariable("gl_TessLevelInner", EbvTessLevelInner, symbolTable); - BuiltInVariable("gl_TessCoord", EbvTessCoord, symbolTable); - - if (version < 410) - symbolTable.setVariableExtensions("gl_ViewportIndex", 1, &E_GL_ARB_viewport_array); - - // Compatibility variables - - BuiltInVariable("gl_in", "gl_ClipVertex", EbvClipVertex, symbolTable); - BuiltInVariable("gl_in", "gl_FrontColor", EbvFrontColor, symbolTable); - BuiltInVariable("gl_in", "gl_BackColor", EbvBackColor, symbolTable); - BuiltInVariable("gl_in", "gl_FrontSecondaryColor", EbvFrontSecondaryColor, symbolTable); - BuiltInVariable("gl_in", "gl_BackSecondaryColor", EbvBackSecondaryColor, symbolTable); - BuiltInVariable("gl_in", "gl_TexCoord", EbvTexCoord, symbolTable); - BuiltInVariable("gl_in", "gl_FogFragCoord", EbvFogFragCoord, symbolTable); - - BuiltInVariable("gl_out", "gl_ClipVertex", EbvClipVertex, symbolTable); - BuiltInVariable("gl_out", "gl_FrontColor", EbvFrontColor, symbolTable); - BuiltInVariable("gl_out", "gl_BackColor", EbvBackColor, symbolTable); - BuiltInVariable("gl_out", "gl_FrontSecondaryColor", EbvFrontSecondaryColor, symbolTable); - BuiltInVariable("gl_out", "gl_BackSecondaryColor", EbvBackSecondaryColor, symbolTable); - BuiltInVariable("gl_out", "gl_TexCoord", EbvTexCoord, symbolTable); - BuiltInVariable("gl_out", "gl_FogFragCoord", EbvFogFragCoord, symbolTable); - - BuiltInVariable("gl_ClipVertex", EbvClipVertex, symbolTable); - BuiltInVariable("gl_FrontColor", EbvFrontColor, symbolTable); - BuiltInVariable("gl_BackColor", EbvBackColor, symbolTable); - BuiltInVariable("gl_FrontSecondaryColor", EbvFrontSecondaryColor, symbolTable); - BuiltInVariable("gl_BackSecondaryColor", EbvBackSecondaryColor, symbolTable); - BuiltInVariable("gl_TexCoord", EbvTexCoord, symbolTable); - BuiltInVariable("gl_FogFragCoord", EbvFogFragCoord, symbolTable); - - // gl_PointSize, when it needs to be tied to an extension, is always a member of a block. - // (Sometimes with an instance name, sometimes anonymous). - // However, the current automatic extension scheme does not work per block member, - // so for now check when parsing. - // - // if (profile == EEsProfile) { - // if (language == EShLangGeometry) - // symbolTable.setVariableExtensions("gl_PointSize", Num_AEP_geometry_point_size, AEP_geometry_point_size); - // else if (language == EShLangTessEvaluation || language == EShLangTessControl) - // symbolTable.setVariableExtensions("gl_PointSize", Num_AEP_tessellation_point_size, AEP_tessellation_point_size); - //} - - if ((profile != EEsProfile && version >= 140) || - (profile == EEsProfile && version >= 310)) { - symbolTable.setVariableExtensions("gl_DeviceIndex", 1, &E_GL_EXT_device_group); - BuiltInVariable("gl_DeviceIndex", EbvDeviceIndex, symbolTable); - symbolTable.setVariableExtensions("gl_ViewIndex", 1, &E_GL_EXT_multiview); - BuiltInVariable("gl_ViewIndex", EbvViewIndex, symbolTable); - } - - // GL_KHR_shader_subgroup - if (spvVersion.vulkan > 0) { - symbolTable.setVariableExtensions("gl_SubgroupSize", 1, &E_GL_KHR_shader_subgroup_basic); - symbolTable.setVariableExtensions("gl_SubgroupInvocationID", 1, &E_GL_KHR_shader_subgroup_basic); - symbolTable.setVariableExtensions("gl_SubgroupEqMask", 1, &E_GL_KHR_shader_subgroup_ballot); - symbolTable.setVariableExtensions("gl_SubgroupGeMask", 1, &E_GL_KHR_shader_subgroup_ballot); - symbolTable.setVariableExtensions("gl_SubgroupGtMask", 1, &E_GL_KHR_shader_subgroup_ballot); - symbolTable.setVariableExtensions("gl_SubgroupLeMask", 1, &E_GL_KHR_shader_subgroup_ballot); - symbolTable.setVariableExtensions("gl_SubgroupLtMask", 1, &E_GL_KHR_shader_subgroup_ballot); - - BuiltInVariable("gl_SubgroupSize", EbvSubgroupSize2, symbolTable); - BuiltInVariable("gl_SubgroupInvocationID", EbvSubgroupInvocation2, symbolTable); - BuiltInVariable("gl_SubgroupEqMask", EbvSubgroupEqMask2, symbolTable); - BuiltInVariable("gl_SubgroupGeMask", EbvSubgroupGeMask2, symbolTable); - BuiltInVariable("gl_SubgroupGtMask", EbvSubgroupGtMask2, symbolTable); - BuiltInVariable("gl_SubgroupLeMask", EbvSubgroupLeMask2, symbolTable); - BuiltInVariable("gl_SubgroupLtMask", EbvSubgroupLtMask2, symbolTable); - } - - break; - - case EShLangFragment: - SpecialQualifier("gl_FrontFacing", EvqFace, EbvFace, symbolTable); - SpecialQualifier("gl_FragCoord", EvqFragCoord, EbvFragCoord, symbolTable); - SpecialQualifier("gl_PointCoord", EvqPointCoord, EbvPointCoord, symbolTable); - if (spvVersion.spv == 0) - SpecialQualifier("gl_FragColor", EvqFragColor, EbvFragColor, symbolTable); - else { - TSymbol* symbol = symbolTable.find("gl_FragColor"); - if (symbol) { - symbol->getWritableType().getQualifier().storage = EvqVaryingOut; - symbol->getWritableType().getQualifier().layoutLocation = 0; - } - } - SpecialQualifier("gl_FragDepth", EvqFragDepth, EbvFragDepth, symbolTable); - SpecialQualifier("gl_FragDepthEXT", EvqFragDepth, EbvFragDepth, symbolTable); - SpecialQualifier("gl_HelperInvocation", EvqVaryingIn, EbvHelperInvocation, symbolTable); - - BuiltInVariable("gl_ClipDistance", EbvClipDistance, symbolTable); - BuiltInVariable("gl_CullDistance", EbvCullDistance, symbolTable); - BuiltInVariable("gl_PrimitiveID", EbvPrimitiveId, symbolTable); - - if (profile != EEsProfile && version >= 140) { - symbolTable.setVariableExtensions("gl_FragStencilRefARB", 1, &E_GL_ARB_shader_stencil_export); - BuiltInVariable("gl_FragStencilRefARB", EbvFragStencilRef, symbolTable); - } - - if ((profile != EEsProfile && version >= 400) || - (profile == EEsProfile && version >= 310)) { - BuiltInVariable("gl_SampleID", EbvSampleId, symbolTable); - BuiltInVariable("gl_SamplePosition", EbvSamplePosition, symbolTable); - BuiltInVariable("gl_SampleMaskIn", EbvSampleMask, symbolTable); - BuiltInVariable("gl_SampleMask", EbvSampleMask, symbolTable); - if (profile == EEsProfile && version < 320) { - symbolTable.setVariableExtensions("gl_SampleID", 1, &E_GL_OES_sample_variables); - symbolTable.setVariableExtensions("gl_SamplePosition", 1, &E_GL_OES_sample_variables); - symbolTable.setVariableExtensions("gl_SampleMaskIn", 1, &E_GL_OES_sample_variables); - symbolTable.setVariableExtensions("gl_SampleMask", 1, &E_GL_OES_sample_variables); - symbolTable.setVariableExtensions("gl_NumSamples", 1, &E_GL_OES_sample_variables); - } - } - - BuiltInVariable("gl_Layer", EbvLayer, symbolTable); - BuiltInVariable("gl_ViewportIndex", EbvViewportIndex, symbolTable); - - // Compatibility variables - - BuiltInVariable("gl_in", "gl_FogFragCoord", EbvFogFragCoord, symbolTable); - BuiltInVariable("gl_in", "gl_TexCoord", EbvTexCoord, symbolTable); - BuiltInVariable("gl_in", "gl_Color", EbvColor, symbolTable); - BuiltInVariable("gl_in", "gl_SecondaryColor", EbvSecondaryColor, symbolTable); - - BuiltInVariable("gl_FogFragCoord", EbvFogFragCoord, symbolTable); - BuiltInVariable("gl_TexCoord", EbvTexCoord, symbolTable); - BuiltInVariable("gl_Color", EbvColor, symbolTable); - BuiltInVariable("gl_SecondaryColor", EbvSecondaryColor, symbolTable); - - // built-in functions - - if (profile == EEsProfile) { - if (spvVersion.spv == 0) { - symbolTable.setFunctionExtensions("texture2DLodEXT", 1, &E_GL_EXT_shader_texture_lod); - symbolTable.setFunctionExtensions("texture2DProjLodEXT", 1, &E_GL_EXT_shader_texture_lod); - symbolTable.setFunctionExtensions("textureCubeLodEXT", 1, &E_GL_EXT_shader_texture_lod); - symbolTable.setFunctionExtensions("texture2DGradEXT", 1, &E_GL_EXT_shader_texture_lod); - symbolTable.setFunctionExtensions("texture2DProjGradEXT", 1, &E_GL_EXT_shader_texture_lod); - symbolTable.setFunctionExtensions("textureCubeGradEXT", 1, &E_GL_EXT_shader_texture_lod); - if (version < 320) - symbolTable.setFunctionExtensions("textureGatherOffsets", Num_AEP_gpu_shader5, AEP_gpu_shader5); - } - if (version == 100) { - symbolTable.setFunctionExtensions("dFdx", 1, &E_GL_OES_standard_derivatives); - symbolTable.setFunctionExtensions("dFdy", 1, &E_GL_OES_standard_derivatives); - symbolTable.setFunctionExtensions("fwidth", 1, &E_GL_OES_standard_derivatives); - } - if (version == 310) { - symbolTable.setFunctionExtensions("fma", Num_AEP_gpu_shader5, AEP_gpu_shader5); - symbolTable.setFunctionExtensions("interpolateAtCentroid", 1, &E_GL_OES_shader_multisample_interpolation); - symbolTable.setFunctionExtensions("interpolateAtSample", 1, &E_GL_OES_shader_multisample_interpolation); - symbolTable.setFunctionExtensions("interpolateAtOffset", 1, &E_GL_OES_shader_multisample_interpolation); - } - } else if (version < 130) { - if (spvVersion.spv == 0) { - symbolTable.setFunctionExtensions("texture1DLod", 1, &E_GL_ARB_shader_texture_lod); - symbolTable.setFunctionExtensions("texture2DLod", 1, &E_GL_ARB_shader_texture_lod); - symbolTable.setFunctionExtensions("texture3DLod", 1, &E_GL_ARB_shader_texture_lod); - symbolTable.setFunctionExtensions("textureCubeLod", 1, &E_GL_ARB_shader_texture_lod); - symbolTable.setFunctionExtensions("texture1DProjLod", 1, &E_GL_ARB_shader_texture_lod); - symbolTable.setFunctionExtensions("texture2DProjLod", 1, &E_GL_ARB_shader_texture_lod); - symbolTable.setFunctionExtensions("texture3DProjLod", 1, &E_GL_ARB_shader_texture_lod); - symbolTable.setFunctionExtensions("shadow1DLod", 1, &E_GL_ARB_shader_texture_lod); - symbolTable.setFunctionExtensions("shadow2DLod", 1, &E_GL_ARB_shader_texture_lod); - symbolTable.setFunctionExtensions("shadow1DProjLod", 1, &E_GL_ARB_shader_texture_lod); - symbolTable.setFunctionExtensions("shadow2DProjLod", 1, &E_GL_ARB_shader_texture_lod); - } - } - - // E_GL_ARB_shader_texture_lod functions usable only with the extension enabled - if (profile != EEsProfile && spvVersion.spv == 0) { - symbolTable.setFunctionExtensions("texture1DGradARB", 1, &E_GL_ARB_shader_texture_lod); - symbolTable.setFunctionExtensions("texture1DProjGradARB", 1, &E_GL_ARB_shader_texture_lod); - symbolTable.setFunctionExtensions("texture2DGradARB", 1, &E_GL_ARB_shader_texture_lod); - symbolTable.setFunctionExtensions("texture2DProjGradARB", 1, &E_GL_ARB_shader_texture_lod); - symbolTable.setFunctionExtensions("texture3DGradARB", 1, &E_GL_ARB_shader_texture_lod); - symbolTable.setFunctionExtensions("texture3DProjGradARB", 1, &E_GL_ARB_shader_texture_lod); - symbolTable.setFunctionExtensions("textureCubeGradARB", 1, &E_GL_ARB_shader_texture_lod); - symbolTable.setFunctionExtensions("shadow1DGradARB", 1, &E_GL_ARB_shader_texture_lod); - symbolTable.setFunctionExtensions("shadow1DProjGradARB", 1, &E_GL_ARB_shader_texture_lod); - symbolTable.setFunctionExtensions("shadow2DGradARB", 1, &E_GL_ARB_shader_texture_lod); - symbolTable.setFunctionExtensions("shadow2DProjGradARB", 1, &E_GL_ARB_shader_texture_lod); - symbolTable.setFunctionExtensions("texture2DRectGradARB", 1, &E_GL_ARB_shader_texture_lod); - symbolTable.setFunctionExtensions("texture2DRectProjGradARB", 1, &E_GL_ARB_shader_texture_lod); - symbolTable.setFunctionExtensions("shadow2DRectGradARB", 1, &E_GL_ARB_shader_texture_lod); - symbolTable.setFunctionExtensions("shadow2DRectProjGradARB", 1, &E_GL_ARB_shader_texture_lod); - } - - // E_GL_ARB_shader_image_load_store - if (profile != EEsProfile && version < 420) - symbolTable.setFunctionExtensions("memoryBarrier", 1, &E_GL_ARB_shader_image_load_store); - // All the image access functions are protected by checks on the type of the first argument. - - // E_GL_ARB_shader_atomic_counters - if (profile != EEsProfile && version < 420) { - symbolTable.setFunctionExtensions("atomicCounterIncrement", 1, &E_GL_ARB_shader_atomic_counters); - symbolTable.setFunctionExtensions("atomicCounterDecrement", 1, &E_GL_ARB_shader_atomic_counters); - symbolTable.setFunctionExtensions("atomicCounter" , 1, &E_GL_ARB_shader_atomic_counters); - } - - // E_GL_ARB_derivative_control - if (profile != EEsProfile && version < 450) { - symbolTable.setFunctionExtensions("dFdxFine", 1, &E_GL_ARB_derivative_control); - symbolTable.setFunctionExtensions("dFdyFine", 1, &E_GL_ARB_derivative_control); - symbolTable.setFunctionExtensions("fwidthFine", 1, &E_GL_ARB_derivative_control); - symbolTable.setFunctionExtensions("dFdxCoarse", 1, &E_GL_ARB_derivative_control); - symbolTable.setFunctionExtensions("dFdyCoarse", 1, &E_GL_ARB_derivative_control); - symbolTable.setFunctionExtensions("fwidthCoarse", 1, &E_GL_ARB_derivative_control); - } - - // E_GL_ARB_sparse_texture2 - if (profile != EEsProfile) - { - symbolTable.setFunctionExtensions("sparseTextureARB", 1, &E_GL_ARB_sparse_texture2); - symbolTable.setFunctionExtensions("sparseTextureLodARB", 1, &E_GL_ARB_sparse_texture2); - symbolTable.setFunctionExtensions("sparseTextureOffsetARB", 1, &E_GL_ARB_sparse_texture2); - symbolTable.setFunctionExtensions("sparseTexelFetchARB", 1, &E_GL_ARB_sparse_texture2); - symbolTable.setFunctionExtensions("sparseTexelFetchOffsetARB", 1, &E_GL_ARB_sparse_texture2); - symbolTable.setFunctionExtensions("sparseTextureLodOffsetARB", 1, &E_GL_ARB_sparse_texture2); - symbolTable.setFunctionExtensions("sparseTextureGradARB", 1, &E_GL_ARB_sparse_texture2); - symbolTable.setFunctionExtensions("sparseTextureGradOffsetARB", 1, &E_GL_ARB_sparse_texture2); - symbolTable.setFunctionExtensions("sparseTextureGatherARB", 1, &E_GL_ARB_sparse_texture2); - symbolTable.setFunctionExtensions("sparseTextureGatherOffsetARB", 1, &E_GL_ARB_sparse_texture2); - symbolTable.setFunctionExtensions("sparseTextureGatherOffsetsARB", 1, &E_GL_ARB_sparse_texture2); - symbolTable.setFunctionExtensions("sparseImageLoadARB", 1, &E_GL_ARB_sparse_texture2); - symbolTable.setFunctionExtensions("sparseTexelsResident", 1, &E_GL_ARB_sparse_texture2); - } - - // E_GL_ARB_sparse_texture_clamp - if (profile != EEsProfile) - { - symbolTable.setFunctionExtensions("sparseTextureClampARB", 1, &E_GL_ARB_sparse_texture_clamp); - symbolTable.setFunctionExtensions("sparseTextureOffsetClampARB", 1, &E_GL_ARB_sparse_texture_clamp); - symbolTable.setFunctionExtensions("sparseTextureGradClampARB", 1, &E_GL_ARB_sparse_texture_clamp); - symbolTable.setFunctionExtensions("sparseTextureGradOffsetClampARB", 1, &E_GL_ARB_sparse_texture_clamp); - symbolTable.setFunctionExtensions("textureClampARB", 1, &E_GL_ARB_sparse_texture_clamp); - symbolTable.setFunctionExtensions("textureOffsetClampARB", 1, &E_GL_ARB_sparse_texture_clamp); - symbolTable.setFunctionExtensions("textureGradClampARB", 1, &E_GL_ARB_sparse_texture_clamp); - symbolTable.setFunctionExtensions("textureGradOffsetClampARB", 1, &E_GL_ARB_sparse_texture_clamp); - } - -#ifdef AMD_EXTENSIONS - // E_GL_AMD_shader_explicit_vertex_parameter - if (profile != EEsProfile) { - symbolTable.setVariableExtensions("gl_BaryCoordNoPerspAMD", 1, &E_GL_AMD_shader_explicit_vertex_parameter); - symbolTable.setVariableExtensions("gl_BaryCoordNoPerspCentroidAMD", 1, &E_GL_AMD_shader_explicit_vertex_parameter); - symbolTable.setVariableExtensions("gl_BaryCoordNoPerspSampleAMD", 1, &E_GL_AMD_shader_explicit_vertex_parameter); - symbolTable.setVariableExtensions("gl_BaryCoordSmoothAMD", 1, &E_GL_AMD_shader_explicit_vertex_parameter); - symbolTable.setVariableExtensions("gl_BaryCoordSmoothCentroidAMD", 1, &E_GL_AMD_shader_explicit_vertex_parameter); - symbolTable.setVariableExtensions("gl_BaryCoordSmoothSampleAMD", 1, &E_GL_AMD_shader_explicit_vertex_parameter); - symbolTable.setVariableExtensions("gl_BaryCoordPullModelAMD", 1, &E_GL_AMD_shader_explicit_vertex_parameter); - - symbolTable.setFunctionExtensions("interpolateAtVertexAMD", 1, &E_GL_AMD_shader_explicit_vertex_parameter); - - BuiltInVariable("gl_BaryCoordNoPerspAMD", EbvBaryCoordNoPersp, symbolTable); - BuiltInVariable("gl_BaryCoordNoPerspCentroidAMD", EbvBaryCoordNoPerspCentroid, symbolTable); - BuiltInVariable("gl_BaryCoordNoPerspSampleAMD", EbvBaryCoordNoPerspSample, symbolTable); - BuiltInVariable("gl_BaryCoordSmoothAMD", EbvBaryCoordSmooth, symbolTable); - BuiltInVariable("gl_BaryCoordSmoothCentroidAMD", EbvBaryCoordSmoothCentroid, symbolTable); - BuiltInVariable("gl_BaryCoordSmoothSampleAMD", EbvBaryCoordSmoothSample, symbolTable); - BuiltInVariable("gl_BaryCoordPullModelAMD", EbvBaryCoordPullModel, symbolTable); - } - - // E_GL_AMD_texture_gather_bias_lod - if (profile != EEsProfile) { - symbolTable.setFunctionExtensions("textureGatherLodAMD", 1, &E_GL_AMD_texture_gather_bias_lod); - symbolTable.setFunctionExtensions("textureGatherLodOffsetAMD", 1, &E_GL_AMD_texture_gather_bias_lod); - symbolTable.setFunctionExtensions("textureGatherLodOffsetsAMD", 1, &E_GL_AMD_texture_gather_bias_lod); - symbolTable.setFunctionExtensions("sparseTextureGatherLodAMD", 1, &E_GL_AMD_texture_gather_bias_lod); - symbolTable.setFunctionExtensions("sparseTextureGatherLodOffsetAMD", 1, &E_GL_AMD_texture_gather_bias_lod); - symbolTable.setFunctionExtensions("sparseTextureGatherLodOffsetsAMD", 1, &E_GL_AMD_texture_gather_bias_lod); - } - - // E_GL_AMD_shader_image_load_store_lod - if (profile != EEsProfile) { - symbolTable.setFunctionExtensions("imageLoadLodAMD", 1, &E_GL_AMD_shader_image_load_store_lod); - symbolTable.setFunctionExtensions("imageStoreLodAMD", 1, &E_GL_AMD_shader_image_load_store_lod); - symbolTable.setFunctionExtensions("sparseImageLoadLodAMD", 1, &E_GL_AMD_shader_image_load_store_lod); - } -#endif - -#ifdef NV_EXTENSIONS - if (profile != EEsProfile && version >= 430) { - symbolTable.setVariableExtensions("gl_FragFullyCoveredNV", 1, &E_GL_NV_conservative_raster_underestimation); - BuiltInVariable("gl_FragFullyCoveredNV", EbvFragFullyCoveredNV, symbolTable); - } -#endif - - symbolTable.setVariableExtensions("gl_FragDepthEXT", 1, &E_GL_EXT_frag_depth); - - if (profile == EEsProfile && version < 320) { - symbolTable.setVariableExtensions("gl_PrimitiveID", Num_AEP_geometry_shader, AEP_geometry_shader); - symbolTable.setVariableExtensions("gl_Layer", Num_AEP_geometry_shader, AEP_geometry_shader); - } - - if (profile == EEsProfile && version < 320) { - symbolTable.setFunctionExtensions("imageAtomicAdd", 1, &E_GL_OES_shader_image_atomic); - symbolTable.setFunctionExtensions("imageAtomicMin", 1, &E_GL_OES_shader_image_atomic); - symbolTable.setFunctionExtensions("imageAtomicMax", 1, &E_GL_OES_shader_image_atomic); - symbolTable.setFunctionExtensions("imageAtomicAnd", 1, &E_GL_OES_shader_image_atomic); - symbolTable.setFunctionExtensions("imageAtomicOr", 1, &E_GL_OES_shader_image_atomic); - symbolTable.setFunctionExtensions("imageAtomicXor", 1, &E_GL_OES_shader_image_atomic); - symbolTable.setFunctionExtensions("imageAtomicExchange", 1, &E_GL_OES_shader_image_atomic); - symbolTable.setFunctionExtensions("imageAtomicCompSwap", 1, &E_GL_OES_shader_image_atomic); - } - - symbolTable.setVariableExtensions("gl_DeviceIndex", 1, &E_GL_EXT_device_group); - BuiltInVariable("gl_DeviceIndex", EbvDeviceIndex, symbolTable); - symbolTable.setVariableExtensions("gl_ViewIndex", 1, &E_GL_EXT_multiview); - BuiltInVariable("gl_ViewIndex", EbvViewIndex, symbolTable); - if (version >= 300 /* both ES and non-ES */) { - symbolTable.setVariableExtensions("gl_ViewID_OVR", Num_OVR_multiview_EXTs, OVR_multiview_EXTs); - BuiltInVariable("gl_ViewID_OVR", EbvViewIndex, symbolTable); - } - - // GL_ARB_shader_ballot - if (profile != EEsProfile) { - symbolTable.setVariableExtensions("gl_SubGroupSizeARB", 1, &E_GL_ARB_shader_ballot); - symbolTable.setVariableExtensions("gl_SubGroupInvocationARB", 1, &E_GL_ARB_shader_ballot); - symbolTable.setVariableExtensions("gl_SubGroupEqMaskARB", 1, &E_GL_ARB_shader_ballot); - symbolTable.setVariableExtensions("gl_SubGroupGeMaskARB", 1, &E_GL_ARB_shader_ballot); - symbolTable.setVariableExtensions("gl_SubGroupGtMaskARB", 1, &E_GL_ARB_shader_ballot); - symbolTable.setVariableExtensions("gl_SubGroupLeMaskARB", 1, &E_GL_ARB_shader_ballot); - symbolTable.setVariableExtensions("gl_SubGroupLtMaskARB", 1, &E_GL_ARB_shader_ballot); - - BuiltInVariable("gl_SubGroupInvocationARB", EbvSubGroupInvocation, symbolTable); - BuiltInVariable("gl_SubGroupEqMaskARB", EbvSubGroupEqMask, symbolTable); - BuiltInVariable("gl_SubGroupGeMaskARB", EbvSubGroupGeMask, symbolTable); - BuiltInVariable("gl_SubGroupGtMaskARB", EbvSubGroupGtMask, symbolTable); - BuiltInVariable("gl_SubGroupLeMaskARB", EbvSubGroupLeMask, symbolTable); - BuiltInVariable("gl_SubGroupLtMaskARB", EbvSubGroupLtMask, symbolTable); - - if (spvVersion.vulkan > 0) - // Treat "gl_SubGroupSizeARB" as shader input instead of uniform for Vulkan - SpecialQualifier("gl_SubGroupSizeARB", EvqVaryingIn, EbvSubGroupSize, symbolTable); - else - BuiltInVariable("gl_SubGroupSizeARB", EbvSubGroupSize, symbolTable); - } - - // GL_KHR_shader_subgroup - if (spvVersion.vulkan > 0) { - symbolTable.setVariableExtensions("gl_SubgroupSize", 1, &E_GL_KHR_shader_subgroup_basic); - symbolTable.setVariableExtensions("gl_SubgroupInvocationID", 1, &E_GL_KHR_shader_subgroup_basic); - symbolTable.setVariableExtensions("gl_SubgroupEqMask", 1, &E_GL_KHR_shader_subgroup_ballot); - symbolTable.setVariableExtensions("gl_SubgroupGeMask", 1, &E_GL_KHR_shader_subgroup_ballot); - symbolTable.setVariableExtensions("gl_SubgroupGtMask", 1, &E_GL_KHR_shader_subgroup_ballot); - symbolTable.setVariableExtensions("gl_SubgroupLeMask", 1, &E_GL_KHR_shader_subgroup_ballot); - symbolTable.setVariableExtensions("gl_SubgroupLtMask", 1, &E_GL_KHR_shader_subgroup_ballot); - - BuiltInVariable("gl_SubgroupSize", EbvSubgroupSize2, symbolTable); - BuiltInVariable("gl_SubgroupInvocationID", EbvSubgroupInvocation2, symbolTable); - BuiltInVariable("gl_SubgroupEqMask", EbvSubgroupEqMask2, symbolTable); - BuiltInVariable("gl_SubgroupGeMask", EbvSubgroupGeMask2, symbolTable); - BuiltInVariable("gl_SubgroupGtMask", EbvSubgroupGtMask2, symbolTable); - BuiltInVariable("gl_SubgroupLeMask", EbvSubgroupLeMask2, symbolTable); - BuiltInVariable("gl_SubgroupLtMask", EbvSubgroupLtMask2, symbolTable); - - symbolTable.setFunctionExtensions("subgroupBarrier", 1, &E_GL_KHR_shader_subgroup_basic); - symbolTable.setFunctionExtensions("subgroupMemoryBarrier", 1, &E_GL_KHR_shader_subgroup_basic); - symbolTable.setFunctionExtensions("subgroupMemoryBarrierBuffer", 1, &E_GL_KHR_shader_subgroup_basic); - symbolTable.setFunctionExtensions("subgroupMemoryBarrierImage", 1, &E_GL_KHR_shader_subgroup_basic); - symbolTable.setFunctionExtensions("subgroupElect", 1, &E_GL_KHR_shader_subgroup_basic); - symbolTable.setFunctionExtensions("subgroupAll", 1, &E_GL_KHR_shader_subgroup_vote); - symbolTable.setFunctionExtensions("subgroupAny", 1, &E_GL_KHR_shader_subgroup_vote); - symbolTable.setFunctionExtensions("subgroupAllEqual", 1, &E_GL_KHR_shader_subgroup_vote); - symbolTable.setFunctionExtensions("subgroupBroadcast", 1, &E_GL_KHR_shader_subgroup_ballot); - symbolTable.setFunctionExtensions("subgroupBroadcastFirst", 1, &E_GL_KHR_shader_subgroup_ballot); - symbolTable.setFunctionExtensions("subgroupBallot", 1, &E_GL_KHR_shader_subgroup_ballot); - symbolTable.setFunctionExtensions("subgroupInverseBallot", 1, &E_GL_KHR_shader_subgroup_ballot); - symbolTable.setFunctionExtensions("subgroupBallotBitExtract", 1, &E_GL_KHR_shader_subgroup_ballot); - symbolTable.setFunctionExtensions("subgroupBallotBitCount", 1, &E_GL_KHR_shader_subgroup_ballot); - symbolTable.setFunctionExtensions("subgroupBallotInclusiveBitCount", 1, &E_GL_KHR_shader_subgroup_ballot); - symbolTable.setFunctionExtensions("subgroupBallotExclusiveBitCount", 1, &E_GL_KHR_shader_subgroup_ballot); - symbolTable.setFunctionExtensions("subgroupBallotFindLSB", 1, &E_GL_KHR_shader_subgroup_ballot); - symbolTable.setFunctionExtensions("subgroupBallotFindMSB", 1, &E_GL_KHR_shader_subgroup_ballot); - symbolTable.setFunctionExtensions("subgroupShuffle", 1, &E_GL_KHR_shader_subgroup_shuffle); - symbolTable.setFunctionExtensions("subgroupShuffleXor", 1, &E_GL_KHR_shader_subgroup_shuffle); - symbolTable.setFunctionExtensions("subgroupShuffleUp", 1, &E_GL_KHR_shader_subgroup_shuffle_relative); - symbolTable.setFunctionExtensions("subgroupShuffleDown", 1, &E_GL_KHR_shader_subgroup_shuffle_relative); - symbolTable.setFunctionExtensions("subgroupAdd", 1, &E_GL_KHR_shader_subgroup_arithmetic); - symbolTable.setFunctionExtensions("subgroupMul", 1, &E_GL_KHR_shader_subgroup_arithmetic); - symbolTable.setFunctionExtensions("subgroupMin", 1, &E_GL_KHR_shader_subgroup_arithmetic); - symbolTable.setFunctionExtensions("subgroupMax", 1, &E_GL_KHR_shader_subgroup_arithmetic); - symbolTable.setFunctionExtensions("subgroupAnd", 1, &E_GL_KHR_shader_subgroup_arithmetic); - symbolTable.setFunctionExtensions("subgroupOr", 1, &E_GL_KHR_shader_subgroup_arithmetic); - symbolTable.setFunctionExtensions("subgroupXor", 1, &E_GL_KHR_shader_subgroup_arithmetic); - symbolTable.setFunctionExtensions("subgroupInclusiveAdd", 1, &E_GL_KHR_shader_subgroup_arithmetic); - symbolTable.setFunctionExtensions("subgroupInclusiveMul", 1, &E_GL_KHR_shader_subgroup_arithmetic); - symbolTable.setFunctionExtensions("subgroupInclusiveMin", 1, &E_GL_KHR_shader_subgroup_arithmetic); - symbolTable.setFunctionExtensions("subgroupInclusiveMax", 1, &E_GL_KHR_shader_subgroup_arithmetic); - symbolTable.setFunctionExtensions("subgroupInclusiveAnd", 1, &E_GL_KHR_shader_subgroup_arithmetic); - symbolTable.setFunctionExtensions("subgroupInclusiveOr", 1, &E_GL_KHR_shader_subgroup_arithmetic); - symbolTable.setFunctionExtensions("subgroupInclusiveXor", 1, &E_GL_KHR_shader_subgroup_arithmetic); - symbolTable.setFunctionExtensions("subgroupExclusiveAdd", 1, &E_GL_KHR_shader_subgroup_arithmetic); - symbolTable.setFunctionExtensions("subgroupExclusiveMul", 1, &E_GL_KHR_shader_subgroup_arithmetic); - symbolTable.setFunctionExtensions("subgroupExclusiveMin", 1, &E_GL_KHR_shader_subgroup_arithmetic); - symbolTable.setFunctionExtensions("subgroupExclusiveMax", 1, &E_GL_KHR_shader_subgroup_arithmetic); - symbolTable.setFunctionExtensions("subgroupExclusiveAnd", 1, &E_GL_KHR_shader_subgroup_arithmetic); - symbolTable.setFunctionExtensions("subgroupExclusiveOr", 1, &E_GL_KHR_shader_subgroup_arithmetic); - symbolTable.setFunctionExtensions("subgroupExclusiveXor", 1, &E_GL_KHR_shader_subgroup_arithmetic); - symbolTable.setFunctionExtensions("subgroupClusteredAdd", 1, &E_GL_KHR_shader_subgroup_clustered); - symbolTable.setFunctionExtensions("subgroupClusteredMul", 1, &E_GL_KHR_shader_subgroup_clustered); - symbolTable.setFunctionExtensions("subgroupClusteredMin", 1, &E_GL_KHR_shader_subgroup_clustered); - symbolTable.setFunctionExtensions("subgroupClusteredMax", 1, &E_GL_KHR_shader_subgroup_clustered); - symbolTable.setFunctionExtensions("subgroupClusteredAnd", 1, &E_GL_KHR_shader_subgroup_clustered); - symbolTable.setFunctionExtensions("subgroupClusteredOr", 1, &E_GL_KHR_shader_subgroup_clustered); - symbolTable.setFunctionExtensions("subgroupClusteredXor", 1, &E_GL_KHR_shader_subgroup_clustered); - symbolTable.setFunctionExtensions("subgroupQuadBroadcast", 1, &E_GL_KHR_shader_subgroup_quad); - symbolTable.setFunctionExtensions("subgroupQuadSwapHorizontal", 1, &E_GL_KHR_shader_subgroup_quad); - symbolTable.setFunctionExtensions("subgroupQuadSwapVertical", 1, &E_GL_KHR_shader_subgroup_quad); - symbolTable.setFunctionExtensions("subgroupQuadSwapDiagonal", 1, &E_GL_KHR_shader_subgroup_quad); - -#ifdef NV_EXTENSIONS - symbolTable.setFunctionExtensions("subgroupPartitionNV", 1, &E_GL_NV_shader_subgroup_partitioned); - symbolTable.setFunctionExtensions("subgroupPartitionedAddNV", 1, &E_GL_NV_shader_subgroup_partitioned); - symbolTable.setFunctionExtensions("subgroupPartitionedMulNV", 1, &E_GL_NV_shader_subgroup_partitioned); - symbolTable.setFunctionExtensions("subgroupPartitionedMinNV", 1, &E_GL_NV_shader_subgroup_partitioned); - symbolTable.setFunctionExtensions("subgroupPartitionedMaxNV", 1, &E_GL_NV_shader_subgroup_partitioned); - symbolTable.setFunctionExtensions("subgroupPartitionedAndNV", 1, &E_GL_NV_shader_subgroup_partitioned); - symbolTable.setFunctionExtensions("subgroupPartitionedOrNV", 1, &E_GL_NV_shader_subgroup_partitioned); - symbolTable.setFunctionExtensions("subgroupPartitionedXorNV", 1, &E_GL_NV_shader_subgroup_partitioned); - symbolTable.setFunctionExtensions("subgroupPartitionedInclusiveAddNV", 1, &E_GL_NV_shader_subgroup_partitioned); - symbolTable.setFunctionExtensions("subgroupPartitionedInclusiveMulNV", 1, &E_GL_NV_shader_subgroup_partitioned); - symbolTable.setFunctionExtensions("subgroupPartitionedInclusiveMinNV", 1, &E_GL_NV_shader_subgroup_partitioned); - symbolTable.setFunctionExtensions("subgroupPartitionedInclusiveMaxNV", 1, &E_GL_NV_shader_subgroup_partitioned); - symbolTable.setFunctionExtensions("subgroupPartitionedInclusiveAndNV", 1, &E_GL_NV_shader_subgroup_partitioned); - symbolTable.setFunctionExtensions("subgroupPartitionedInclusiveOrNV", 1, &E_GL_NV_shader_subgroup_partitioned); - symbolTable.setFunctionExtensions("subgroupPartitionedInclusiveXorNV", 1, &E_GL_NV_shader_subgroup_partitioned); - symbolTable.setFunctionExtensions("subgroupPartitionedExclusiveAddNV", 1, &E_GL_NV_shader_subgroup_partitioned); - symbolTable.setFunctionExtensions("subgroupPartitionedExclusiveMulNV", 1, &E_GL_NV_shader_subgroup_partitioned); - symbolTable.setFunctionExtensions("subgroupPartitionedExclusiveMinNV", 1, &E_GL_NV_shader_subgroup_partitioned); - symbolTable.setFunctionExtensions("subgroupPartitionedExclusiveMaxNV", 1, &E_GL_NV_shader_subgroup_partitioned); - symbolTable.setFunctionExtensions("subgroupPartitionedExclusiveAndNV", 1, &E_GL_NV_shader_subgroup_partitioned); - symbolTable.setFunctionExtensions("subgroupPartitionedExclusiveOrNV", 1, &E_GL_NV_shader_subgroup_partitioned); - symbolTable.setFunctionExtensions("subgroupPartitionedExclusiveXorNV", 1, &E_GL_NV_shader_subgroup_partitioned); -#endif - - } - - if (profile == EEsProfile) { - symbolTable.setFunctionExtensions("shadow2DEXT", 1, &E_GL_EXT_shadow_samplers); - symbolTable.setFunctionExtensions("shadow2DProjEXT", 1, &E_GL_EXT_shadow_samplers); - } - break; - - case EShLangCompute: - BuiltInVariable("gl_NumWorkGroups", EbvNumWorkGroups, symbolTable); - BuiltInVariable("gl_WorkGroupSize", EbvWorkGroupSize, symbolTable); - BuiltInVariable("gl_WorkGroupID", EbvWorkGroupId, symbolTable); - BuiltInVariable("gl_LocalInvocationID", EbvLocalInvocationId, symbolTable); - BuiltInVariable("gl_GlobalInvocationID", EbvGlobalInvocationId, symbolTable); - BuiltInVariable("gl_LocalInvocationIndex", EbvLocalInvocationIndex, symbolTable); - - if (profile != EEsProfile && version < 430) { - symbolTable.setVariableExtensions("gl_NumWorkGroups", 1, &E_GL_ARB_compute_shader); - symbolTable.setVariableExtensions("gl_WorkGroupSize", 1, &E_GL_ARB_compute_shader); - symbolTable.setVariableExtensions("gl_WorkGroupID", 1, &E_GL_ARB_compute_shader); - symbolTable.setVariableExtensions("gl_LocalInvocationID", 1, &E_GL_ARB_compute_shader); - symbolTable.setVariableExtensions("gl_GlobalInvocationID", 1, &E_GL_ARB_compute_shader); - symbolTable.setVariableExtensions("gl_LocalInvocationIndex", 1, &E_GL_ARB_compute_shader); - - symbolTable.setVariableExtensions("gl_MaxComputeWorkGroupCount", 1, &E_GL_ARB_compute_shader); - symbolTable.setVariableExtensions("gl_MaxComputeWorkGroupSize", 1, &E_GL_ARB_compute_shader); - symbolTable.setVariableExtensions("gl_MaxComputeUniformComponents", 1, &E_GL_ARB_compute_shader); - symbolTable.setVariableExtensions("gl_MaxComputeTextureImageUnits", 1, &E_GL_ARB_compute_shader); - symbolTable.setVariableExtensions("gl_MaxComputeImageUniforms", 1, &E_GL_ARB_compute_shader); - symbolTable.setVariableExtensions("gl_MaxComputeAtomicCounters", 1, &E_GL_ARB_compute_shader); - symbolTable.setVariableExtensions("gl_MaxComputeAtomicCounterBuffers", 1, &E_GL_ARB_compute_shader); - - symbolTable.setFunctionExtensions("barrier", 1, &E_GL_ARB_compute_shader); - symbolTable.setFunctionExtensions("memoryBarrierAtomicCounter", 1, &E_GL_ARB_compute_shader); - symbolTable.setFunctionExtensions("memoryBarrierBuffer", 1, &E_GL_ARB_compute_shader); - symbolTable.setFunctionExtensions("memoryBarrierImage", 1, &E_GL_ARB_compute_shader); - symbolTable.setFunctionExtensions("memoryBarrierShared", 1, &E_GL_ARB_compute_shader); - symbolTable.setFunctionExtensions("groupMemoryBarrier", 1, &E_GL_ARB_compute_shader); - } - - // GL_ARB_shader_ballot - if (profile != EEsProfile) { - symbolTable.setVariableExtensions("gl_SubGroupSizeARB", 1, &E_GL_ARB_shader_ballot); - symbolTable.setVariableExtensions("gl_SubGroupInvocationARB", 1, &E_GL_ARB_shader_ballot); - symbolTable.setVariableExtensions("gl_SubGroupEqMaskARB", 1, &E_GL_ARB_shader_ballot); - symbolTable.setVariableExtensions("gl_SubGroupGeMaskARB", 1, &E_GL_ARB_shader_ballot); - symbolTable.setVariableExtensions("gl_SubGroupGtMaskARB", 1, &E_GL_ARB_shader_ballot); - symbolTable.setVariableExtensions("gl_SubGroupLeMaskARB", 1, &E_GL_ARB_shader_ballot); - symbolTable.setVariableExtensions("gl_SubGroupLtMaskARB", 1, &E_GL_ARB_shader_ballot); - - BuiltInVariable("gl_SubGroupInvocationARB", EbvSubGroupInvocation, symbolTable); - BuiltInVariable("gl_SubGroupEqMaskARB", EbvSubGroupEqMask, symbolTable); - BuiltInVariable("gl_SubGroupGeMaskARB", EbvSubGroupGeMask, symbolTable); - BuiltInVariable("gl_SubGroupGtMaskARB", EbvSubGroupGtMask, symbolTable); - BuiltInVariable("gl_SubGroupLeMaskARB", EbvSubGroupLeMask, symbolTable); - BuiltInVariable("gl_SubGroupLtMaskARB", EbvSubGroupLtMask, symbolTable); - - if (spvVersion.vulkan > 0) - // Treat "gl_SubGroupSizeARB" as shader input instead of uniform for Vulkan - SpecialQualifier("gl_SubGroupSizeARB", EvqVaryingIn, EbvSubGroupSize, symbolTable); - else - BuiltInVariable("gl_SubGroupSizeARB", EbvSubGroupSize, symbolTable); - } - - // GL_ARB_shader_ballot - if (spvVersion.vulkan > 0) { - symbolTable.setVariableExtensions("gl_SubgroupSize", 1, &E_GL_KHR_shader_subgroup_basic); - symbolTable.setVariableExtensions("gl_SubgroupInvocationID", 1, &E_GL_KHR_shader_subgroup_basic); - symbolTable.setVariableExtensions("gl_SubgroupEqMask", 1, &E_GL_KHR_shader_subgroup_ballot); - symbolTable.setVariableExtensions("gl_SubgroupGeMask", 1, &E_GL_KHR_shader_subgroup_ballot); - symbolTable.setVariableExtensions("gl_SubgroupGtMask", 1, &E_GL_KHR_shader_subgroup_ballot); - symbolTable.setVariableExtensions("gl_SubgroupLeMask", 1, &E_GL_KHR_shader_subgroup_ballot); - symbolTable.setVariableExtensions("gl_SubgroupLtMask", 1, &E_GL_KHR_shader_subgroup_ballot); - - BuiltInVariable("gl_SubgroupSize", EbvSubgroupSize2, symbolTable); - BuiltInVariable("gl_SubgroupInvocationID", EbvSubgroupInvocation2, symbolTable); - BuiltInVariable("gl_SubgroupEqMask", EbvSubgroupEqMask2, symbolTable); - BuiltInVariable("gl_SubgroupGeMask", EbvSubgroupGeMask2, symbolTable); - BuiltInVariable("gl_SubgroupGtMask", EbvSubgroupGtMask2, symbolTable); - BuiltInVariable("gl_SubgroupLeMask", EbvSubgroupLeMask2, symbolTable); - BuiltInVariable("gl_SubgroupLtMask", EbvSubgroupLtMask2, symbolTable); - } - - if ((profile != EEsProfile && version >= 140) || - (profile == EEsProfile && version >= 310)) { - symbolTable.setVariableExtensions("gl_DeviceIndex", 1, &E_GL_EXT_device_group); - BuiltInVariable("gl_DeviceIndex", EbvDeviceIndex, symbolTable); - symbolTable.setVariableExtensions("gl_ViewIndex", 1, &E_GL_EXT_multiview); - BuiltInVariable("gl_ViewIndex", EbvViewIndex, symbolTable); - } - - // GL_KHR_shader_subgroup - if (spvVersion.vulkan > 0) { - symbolTable.setVariableExtensions("gl_NumSubgroups", 1, &E_GL_KHR_shader_subgroup_basic); - symbolTable.setVariableExtensions("gl_SubgroupID", 1, &E_GL_KHR_shader_subgroup_basic); - - BuiltInVariable("gl_NumSubgroups", EbvNumSubgroups, symbolTable); - BuiltInVariable("gl_SubgroupID", EbvSubgroupID, symbolTable); - - symbolTable.setFunctionExtensions("subgroupMemoryBarrierShared", 1, &E_GL_KHR_shader_subgroup_basic); - } - break; - - default: - assert(false && "Language not supported"); - break; - } - - // - // Next, identify which built-ins have a mapping to an operator. - // If PureOperatorBuiltins is false, those that are not identified as such are - // expected to be resolved through a library of functions, versus as - // operations. - // - symbolTable.relateToOperator("not", EOpVectorLogicalNot); - - symbolTable.relateToOperator("matrixCompMult", EOpMul); - // 120 and 150 are correct for both ES and desktop - if (version >= 120) { - symbolTable.relateToOperator("outerProduct", EOpOuterProduct); - symbolTable.relateToOperator("transpose", EOpTranspose); - if (version >= 150) { - symbolTable.relateToOperator("determinant", EOpDeterminant); - symbolTable.relateToOperator("inverse", EOpMatrixInverse); - } - } - - symbolTable.relateToOperator("mod", EOpMod); - symbolTable.relateToOperator("modf", EOpModf); - - symbolTable.relateToOperator("equal", EOpVectorEqual); - symbolTable.relateToOperator("notEqual", EOpVectorNotEqual); - symbolTable.relateToOperator("lessThan", EOpLessThan); - symbolTable.relateToOperator("greaterThan", EOpGreaterThan); - symbolTable.relateToOperator("lessThanEqual", EOpLessThanEqual); - symbolTable.relateToOperator("greaterThanEqual", EOpGreaterThanEqual); - - symbolTable.relateToOperator("radians", EOpRadians); - symbolTable.relateToOperator("degrees", EOpDegrees); - symbolTable.relateToOperator("sin", EOpSin); - symbolTable.relateToOperator("cos", EOpCos); - symbolTable.relateToOperator("tan", EOpTan); - symbolTable.relateToOperator("asin", EOpAsin); - symbolTable.relateToOperator("acos", EOpAcos); - symbolTable.relateToOperator("atan", EOpAtan); - symbolTable.relateToOperator("sinh", EOpSinh); - symbolTable.relateToOperator("cosh", EOpCosh); - symbolTable.relateToOperator("tanh", EOpTanh); - symbolTable.relateToOperator("asinh", EOpAsinh); - symbolTable.relateToOperator("acosh", EOpAcosh); - symbolTable.relateToOperator("atanh", EOpAtanh); - - symbolTable.relateToOperator("pow", EOpPow); - symbolTable.relateToOperator("exp2", EOpExp2); - symbolTable.relateToOperator("log", EOpLog); - symbolTable.relateToOperator("exp", EOpExp); - symbolTable.relateToOperator("log2", EOpLog2); - symbolTable.relateToOperator("sqrt", EOpSqrt); - symbolTable.relateToOperator("inversesqrt", EOpInverseSqrt); - - symbolTable.relateToOperator("abs", EOpAbs); - symbolTable.relateToOperator("sign", EOpSign); - symbolTable.relateToOperator("floor", EOpFloor); - symbolTable.relateToOperator("trunc", EOpTrunc); - symbolTable.relateToOperator("round", EOpRound); - symbolTable.relateToOperator("roundEven", EOpRoundEven); - symbolTable.relateToOperator("ceil", EOpCeil); - symbolTable.relateToOperator("fract", EOpFract); - symbolTable.relateToOperator("min", EOpMin); - symbolTable.relateToOperator("max", EOpMax); - symbolTable.relateToOperator("clamp", EOpClamp); - symbolTable.relateToOperator("mix", EOpMix); - symbolTable.relateToOperator("step", EOpStep); - symbolTable.relateToOperator("smoothstep", EOpSmoothStep); - - symbolTable.relateToOperator("isnan", EOpIsNan); - symbolTable.relateToOperator("isinf", EOpIsInf); - - symbolTable.relateToOperator("floatBitsToInt", EOpFloatBitsToInt); - symbolTable.relateToOperator("floatBitsToUint", EOpFloatBitsToUint); - symbolTable.relateToOperator("intBitsToFloat", EOpIntBitsToFloat); - symbolTable.relateToOperator("uintBitsToFloat", EOpUintBitsToFloat); - symbolTable.relateToOperator("doubleBitsToInt64", EOpDoubleBitsToInt64); - symbolTable.relateToOperator("doubleBitsToUint64", EOpDoubleBitsToUint64); - symbolTable.relateToOperator("int64BitsToDouble", EOpInt64BitsToDouble); - symbolTable.relateToOperator("uint64BitsToDouble", EOpUint64BitsToDouble); - symbolTable.relateToOperator("halfBitsToInt16", EOpFloat16BitsToInt16); - symbolTable.relateToOperator("halfBitsToUint16", EOpFloat16BitsToUint16); - symbolTable.relateToOperator("float16BitsToInt16", EOpFloat16BitsToInt16); - symbolTable.relateToOperator("float16BitsToUint16", EOpFloat16BitsToUint16); - symbolTable.relateToOperator("int16BitsToFloat16", EOpInt16BitsToFloat16); - symbolTable.relateToOperator("uint16BitsToFloat16", EOpUint16BitsToFloat16); - - symbolTable.relateToOperator("int16BitsToHalf", EOpInt16BitsToFloat16); - symbolTable.relateToOperator("uint16BitsToHalf", EOpUint16BitsToFloat16); - - symbolTable.relateToOperator("packSnorm2x16", EOpPackSnorm2x16); - symbolTable.relateToOperator("unpackSnorm2x16", EOpUnpackSnorm2x16); - symbolTable.relateToOperator("packUnorm2x16", EOpPackUnorm2x16); - symbolTable.relateToOperator("unpackUnorm2x16", EOpUnpackUnorm2x16); - - symbolTable.relateToOperator("packSnorm4x8", EOpPackSnorm4x8); - symbolTable.relateToOperator("unpackSnorm4x8", EOpUnpackSnorm4x8); - symbolTable.relateToOperator("packUnorm4x8", EOpPackUnorm4x8); - symbolTable.relateToOperator("unpackUnorm4x8", EOpUnpackUnorm4x8); - - symbolTable.relateToOperator("packDouble2x32", EOpPackDouble2x32); - symbolTable.relateToOperator("unpackDouble2x32", EOpUnpackDouble2x32); - - symbolTable.relateToOperator("packHalf2x16", EOpPackHalf2x16); - symbolTable.relateToOperator("unpackHalf2x16", EOpUnpackHalf2x16); - - symbolTable.relateToOperator("packInt2x32", EOpPackInt2x32); - symbolTable.relateToOperator("unpackInt2x32", EOpUnpackInt2x32); - symbolTable.relateToOperator("packUint2x32", EOpPackUint2x32); - symbolTable.relateToOperator("unpackUint2x32", EOpUnpackUint2x32); - - symbolTable.relateToOperator("packInt2x16", EOpPackInt2x16); - symbolTable.relateToOperator("unpackInt2x16", EOpUnpackInt2x16); - symbolTable.relateToOperator("packUint2x16", EOpPackUint2x16); - symbolTable.relateToOperator("unpackUint2x16", EOpUnpackUint2x16); - - symbolTable.relateToOperator("packInt4x16", EOpPackInt4x16); - symbolTable.relateToOperator("unpackInt4x16", EOpUnpackInt4x16); - symbolTable.relateToOperator("packUint4x16", EOpPackUint4x16); - symbolTable.relateToOperator("unpackUint4x16", EOpUnpackUint4x16); - symbolTable.relateToOperator("packFloat2x16", EOpPackFloat2x16); - symbolTable.relateToOperator("unpackFloat2x16", EOpUnpackFloat2x16); - - symbolTable.relateToOperator("pack16", EOpPack16); - symbolTable.relateToOperator("pack32", EOpPack32); - symbolTable.relateToOperator("pack64", EOpPack64); - - symbolTable.relateToOperator("unpack32", EOpUnpack32); - symbolTable.relateToOperator("unpack16", EOpUnpack16); - symbolTable.relateToOperator("unpack8", EOpUnpack8); - - symbolTable.relateToOperator("length", EOpLength); - symbolTable.relateToOperator("distance", EOpDistance); - symbolTable.relateToOperator("dot", EOpDot); - symbolTable.relateToOperator("cross", EOpCross); - symbolTable.relateToOperator("normalize", EOpNormalize); - symbolTable.relateToOperator("faceforward", EOpFaceForward); - symbolTable.relateToOperator("reflect", EOpReflect); - symbolTable.relateToOperator("refract", EOpRefract); - - symbolTable.relateToOperator("any", EOpAny); - symbolTable.relateToOperator("all", EOpAll); - - symbolTable.relateToOperator("barrier", EOpBarrier); - symbolTable.relateToOperator("memoryBarrier", EOpMemoryBarrier); - symbolTable.relateToOperator("memoryBarrierAtomicCounter", EOpMemoryBarrierAtomicCounter); - symbolTable.relateToOperator("memoryBarrierBuffer", EOpMemoryBarrierBuffer); - symbolTable.relateToOperator("memoryBarrierImage", EOpMemoryBarrierImage); - - symbolTable.relateToOperator("atomicAdd", EOpAtomicAdd); - symbolTable.relateToOperator("atomicMin", EOpAtomicMin); - symbolTable.relateToOperator("atomicMax", EOpAtomicMax); - symbolTable.relateToOperator("atomicAnd", EOpAtomicAnd); - symbolTable.relateToOperator("atomicOr", EOpAtomicOr); - symbolTable.relateToOperator("atomicXor", EOpAtomicXor); - symbolTable.relateToOperator("atomicExchange", EOpAtomicExchange); - symbolTable.relateToOperator("atomicCompSwap", EOpAtomicCompSwap); - - symbolTable.relateToOperator("atomicCounterIncrement", EOpAtomicCounterIncrement); - symbolTable.relateToOperator("atomicCounterDecrement", EOpAtomicCounterDecrement); - symbolTable.relateToOperator("atomicCounter", EOpAtomicCounter); - - if (profile != EEsProfile && version >= 460) { - symbolTable.relateToOperator("atomicCounterAdd", EOpAtomicCounterAdd); - symbolTable.relateToOperator("atomicCounterSubtract", EOpAtomicCounterSubtract); - symbolTable.relateToOperator("atomicCounterMin", EOpAtomicCounterMin); - symbolTable.relateToOperator("atomicCounterMax", EOpAtomicCounterMax); - symbolTable.relateToOperator("atomicCounterAnd", EOpAtomicCounterAnd); - symbolTable.relateToOperator("atomicCounterOr", EOpAtomicCounterOr); - symbolTable.relateToOperator("atomicCounterXor", EOpAtomicCounterXor); - symbolTable.relateToOperator("atomicCounterExchange", EOpAtomicCounterExchange); - symbolTable.relateToOperator("atomicCounterCompSwap", EOpAtomicCounterCompSwap); - } - - symbolTable.relateToOperator("fma", EOpFma); - symbolTable.relateToOperator("frexp", EOpFrexp); - symbolTable.relateToOperator("ldexp", EOpLdexp); - symbolTable.relateToOperator("uaddCarry", EOpAddCarry); - symbolTable.relateToOperator("usubBorrow", EOpSubBorrow); - symbolTable.relateToOperator("umulExtended", EOpUMulExtended); - symbolTable.relateToOperator("imulExtended", EOpIMulExtended); - symbolTable.relateToOperator("bitfieldExtract", EOpBitfieldExtract); - symbolTable.relateToOperator("bitfieldInsert", EOpBitfieldInsert); - symbolTable.relateToOperator("bitfieldReverse", EOpBitFieldReverse); - symbolTable.relateToOperator("bitCount", EOpBitCount); - symbolTable.relateToOperator("findLSB", EOpFindLSB); - symbolTable.relateToOperator("findMSB", EOpFindMSB); - - if (PureOperatorBuiltins) { - symbolTable.relateToOperator("imageSize", EOpImageQuerySize); - symbolTable.relateToOperator("imageSamples", EOpImageQuerySamples); - symbolTable.relateToOperator("imageLoad", EOpImageLoad); - symbolTable.relateToOperator("imageStore", EOpImageStore); - symbolTable.relateToOperator("imageAtomicAdd", EOpImageAtomicAdd); - symbolTable.relateToOperator("imageAtomicMin", EOpImageAtomicMin); - symbolTable.relateToOperator("imageAtomicMax", EOpImageAtomicMax); - symbolTable.relateToOperator("imageAtomicAnd", EOpImageAtomicAnd); - symbolTable.relateToOperator("imageAtomicOr", EOpImageAtomicOr); - symbolTable.relateToOperator("imageAtomicXor", EOpImageAtomicXor); - symbolTable.relateToOperator("imageAtomicExchange", EOpImageAtomicExchange); - symbolTable.relateToOperator("imageAtomicCompSwap", EOpImageAtomicCompSwap); - - symbolTable.relateToOperator("subpassLoad", EOpSubpassLoad); - symbolTable.relateToOperator("subpassLoadMS", EOpSubpassLoadMS); - - symbolTable.relateToOperator("textureSize", EOpTextureQuerySize); - symbolTable.relateToOperator("textureQueryLod", EOpTextureQueryLod); - symbolTable.relateToOperator("textureQueryLevels", EOpTextureQueryLevels); - symbolTable.relateToOperator("textureSamples", EOpTextureQuerySamples); - symbolTable.relateToOperator("texture", EOpTexture); - symbolTable.relateToOperator("textureProj", EOpTextureProj); - symbolTable.relateToOperator("textureLod", EOpTextureLod); - symbolTable.relateToOperator("textureOffset", EOpTextureOffset); - symbolTable.relateToOperator("texelFetch", EOpTextureFetch); - symbolTable.relateToOperator("texelFetchOffset", EOpTextureFetchOffset); - symbolTable.relateToOperator("textureProjOffset", EOpTextureProjOffset); - symbolTable.relateToOperator("textureLodOffset", EOpTextureLodOffset); - symbolTable.relateToOperator("textureProjLod", EOpTextureProjLod); - symbolTable.relateToOperator("textureProjLodOffset", EOpTextureProjLodOffset); - symbolTable.relateToOperator("textureGrad", EOpTextureGrad); - symbolTable.relateToOperator("textureGradOffset", EOpTextureGradOffset); - symbolTable.relateToOperator("textureProjGrad", EOpTextureProjGrad); - symbolTable.relateToOperator("textureProjGradOffset", EOpTextureProjGradOffset); - symbolTable.relateToOperator("textureGather", EOpTextureGather); - symbolTable.relateToOperator("textureGatherOffset", EOpTextureGatherOffset); - symbolTable.relateToOperator("textureGatherOffsets", EOpTextureGatherOffsets); - - symbolTable.relateToOperator("noise1", EOpNoise); - symbolTable.relateToOperator("noise2", EOpNoise); - symbolTable.relateToOperator("noise3", EOpNoise); - symbolTable.relateToOperator("noise4", EOpNoise); - - if (spvVersion.spv == 0 && (IncludeLegacy(version, profile, spvVersion) || - (profile == EEsProfile && version == 100))) { - symbolTable.relateToOperator("ftransform", EOpFtransform); - - symbolTable.relateToOperator("texture1D", EOpTexture); - symbolTable.relateToOperator("texture1DGradARB", EOpTextureGrad); - symbolTable.relateToOperator("texture1DProj", EOpTextureProj); - symbolTable.relateToOperator("texture1DProjGradARB", EOpTextureProjGrad); - symbolTable.relateToOperator("texture1DLod", EOpTextureLod); - symbolTable.relateToOperator("texture1DProjLod", EOpTextureProjLod); - - symbolTable.relateToOperator("texture2DRect", EOpTexture); - symbolTable.relateToOperator("texture2DRectProj", EOpTextureProj); - symbolTable.relateToOperator("texture2DRectGradARB", EOpTextureGrad); - symbolTable.relateToOperator("texture2DRectProjGradARB", EOpTextureProjGrad); - symbolTable.relateToOperator("shadow2DRect", EOpTexture); - symbolTable.relateToOperator("shadow2DRectProj", EOpTextureProj); - symbolTable.relateToOperator("shadow2DRectGradARB", EOpTextureGrad); - symbolTable.relateToOperator("shadow2DRectProjGradARB", EOpTextureProjGrad); - - symbolTable.relateToOperator("texture2D", EOpTexture); - symbolTable.relateToOperator("texture2DProj", EOpTextureProj); - symbolTable.relateToOperator("texture2DGradEXT", EOpTextureGrad); - symbolTable.relateToOperator("texture2DGradARB", EOpTextureGrad); - symbolTable.relateToOperator("texture2DProjGradEXT", EOpTextureProjGrad); - symbolTable.relateToOperator("texture2DProjGradARB", EOpTextureProjGrad); - symbolTable.relateToOperator("texture2DLod", EOpTextureLod); - symbolTable.relateToOperator("texture2DLodEXT", EOpTextureLod); - symbolTable.relateToOperator("texture2DProjLod", EOpTextureProjLod); - symbolTable.relateToOperator("texture2DProjLodEXT", EOpTextureProjLod); - - symbolTable.relateToOperator("texture3D", EOpTexture); - symbolTable.relateToOperator("texture3DGradARB", EOpTextureGrad); - symbolTable.relateToOperator("texture3DProj", EOpTextureProj); - symbolTable.relateToOperator("texture3DProjGradARB", EOpTextureProjGrad); - symbolTable.relateToOperator("texture3DLod", EOpTextureLod); - symbolTable.relateToOperator("texture3DProjLod", EOpTextureProjLod); - symbolTable.relateToOperator("textureCube", EOpTexture); - symbolTable.relateToOperator("textureCubeGradEXT", EOpTextureGrad); - symbolTable.relateToOperator("textureCubeGradARB", EOpTextureGrad); - symbolTable.relateToOperator("textureCubeLod", EOpTextureLod); - symbolTable.relateToOperator("textureCubeLodEXT", EOpTextureLod); - symbolTable.relateToOperator("shadow1D", EOpTexture); - symbolTable.relateToOperator("shadow1DGradARB", EOpTextureGrad); - symbolTable.relateToOperator("shadow2D", EOpTexture); - symbolTable.relateToOperator("shadow2DGradARB", EOpTextureGrad); - symbolTable.relateToOperator("shadow1DProj", EOpTextureProj); - symbolTable.relateToOperator("shadow2DProj", EOpTextureProj); - symbolTable.relateToOperator("shadow1DProjGradARB", EOpTextureProjGrad); - symbolTable.relateToOperator("shadow2DProjGradARB", EOpTextureProjGrad); - symbolTable.relateToOperator("shadow1DLod", EOpTextureLod); - symbolTable.relateToOperator("shadow2DLod", EOpTextureLod); - symbolTable.relateToOperator("shadow1DProjLod", EOpTextureProjLod); - symbolTable.relateToOperator("shadow2DProjLod", EOpTextureProjLod); - } - - if (profile != EEsProfile) { - symbolTable.relateToOperator("sparseTextureARB", EOpSparseTexture); - symbolTable.relateToOperator("sparseTextureLodARB", EOpSparseTextureLod); - symbolTable.relateToOperator("sparseTextureOffsetARB", EOpSparseTextureOffset); - symbolTable.relateToOperator("sparseTexelFetchARB", EOpSparseTextureFetch); - symbolTable.relateToOperator("sparseTexelFetchOffsetARB", EOpSparseTextureFetchOffset); - symbolTable.relateToOperator("sparseTextureLodOffsetARB", EOpSparseTextureLodOffset); - symbolTable.relateToOperator("sparseTextureGradARB", EOpSparseTextureGrad); - symbolTable.relateToOperator("sparseTextureGradOffsetARB", EOpSparseTextureGradOffset); - symbolTable.relateToOperator("sparseTextureGatherARB", EOpSparseTextureGather); - symbolTable.relateToOperator("sparseTextureGatherOffsetARB", EOpSparseTextureGatherOffset); - symbolTable.relateToOperator("sparseTextureGatherOffsetsARB", EOpSparseTextureGatherOffsets); - symbolTable.relateToOperator("sparseImageLoadARB", EOpSparseImageLoad); - symbolTable.relateToOperator("sparseTexelsResidentARB", EOpSparseTexelsResident); - - symbolTable.relateToOperator("sparseTextureClampARB", EOpSparseTextureClamp); - symbolTable.relateToOperator("sparseTextureOffsetClampARB", EOpSparseTextureOffsetClamp); - symbolTable.relateToOperator("sparseTextureGradClampARB", EOpSparseTextureGradClamp); - symbolTable.relateToOperator("sparseTextureGradOffsetClampARB", EOpSparseTextureGradOffsetClamp); - symbolTable.relateToOperator("textureClampARB", EOpTextureClamp); - symbolTable.relateToOperator("textureOffsetClampARB", EOpTextureOffsetClamp); - symbolTable.relateToOperator("textureGradClampARB", EOpTextureGradClamp); - symbolTable.relateToOperator("textureGradOffsetClampARB", EOpTextureGradOffsetClamp); - - symbolTable.relateToOperator("ballotARB", EOpBallot); - symbolTable.relateToOperator("readInvocationARB", EOpReadInvocation); - symbolTable.relateToOperator("readFirstInvocationARB", EOpReadFirstInvocation); - - if (version >= 430) { - symbolTable.relateToOperator("anyInvocationARB", EOpAnyInvocation); - symbolTable.relateToOperator("allInvocationsARB", EOpAllInvocations); - symbolTable.relateToOperator("allInvocationsEqualARB", EOpAllInvocationsEqual); - } - if (version >= 460) { - symbolTable.relateToOperator("anyInvocation", EOpAnyInvocation); - symbolTable.relateToOperator("allInvocations", EOpAllInvocations); - symbolTable.relateToOperator("allInvocationsEqual", EOpAllInvocationsEqual); - } -#ifdef AMD_EXTENSIONS - symbolTable.relateToOperator("minInvocationsAMD", EOpMinInvocations); - symbolTable.relateToOperator("maxInvocationsAMD", EOpMaxInvocations); - symbolTable.relateToOperator("addInvocationsAMD", EOpAddInvocations); - symbolTable.relateToOperator("minInvocationsNonUniformAMD", EOpMinInvocationsNonUniform); - symbolTable.relateToOperator("maxInvocationsNonUniformAMD", EOpMaxInvocationsNonUniform); - symbolTable.relateToOperator("addInvocationsNonUniformAMD", EOpAddInvocationsNonUniform); - symbolTable.relateToOperator("minInvocationsInclusiveScanAMD", EOpMinInvocationsInclusiveScan); - symbolTable.relateToOperator("maxInvocationsInclusiveScanAMD", EOpMaxInvocationsInclusiveScan); - symbolTable.relateToOperator("addInvocationsInclusiveScanAMD", EOpAddInvocationsInclusiveScan); - symbolTable.relateToOperator("minInvocationsInclusiveScanNonUniformAMD", EOpMinInvocationsInclusiveScanNonUniform); - symbolTable.relateToOperator("maxInvocationsInclusiveScanNonUniformAMD", EOpMaxInvocationsInclusiveScanNonUniform); - symbolTable.relateToOperator("addInvocationsInclusiveScanNonUniformAMD", EOpAddInvocationsInclusiveScanNonUniform); - symbolTable.relateToOperator("minInvocationsExclusiveScanAMD", EOpMinInvocationsExclusiveScan); - symbolTable.relateToOperator("maxInvocationsExclusiveScanAMD", EOpMaxInvocationsExclusiveScan); - symbolTable.relateToOperator("addInvocationsExclusiveScanAMD", EOpAddInvocationsExclusiveScan); - symbolTable.relateToOperator("minInvocationsExclusiveScanNonUniformAMD", EOpMinInvocationsExclusiveScanNonUniform); - symbolTable.relateToOperator("maxInvocationsExclusiveScanNonUniformAMD", EOpMaxInvocationsExclusiveScanNonUniform); - symbolTable.relateToOperator("addInvocationsExclusiveScanNonUniformAMD", EOpAddInvocationsExclusiveScanNonUniform); - symbolTable.relateToOperator("swizzleInvocationsAMD", EOpSwizzleInvocations); - symbolTable.relateToOperator("swizzleInvocationsMaskedAMD", EOpSwizzleInvocationsMasked); - symbolTable.relateToOperator("writeInvocationAMD", EOpWriteInvocation); - symbolTable.relateToOperator("mbcntAMD", EOpMbcnt); - - symbolTable.relateToOperator("min3", EOpMin3); - symbolTable.relateToOperator("max3", EOpMax3); - symbolTable.relateToOperator("mid3", EOpMid3); - - symbolTable.relateToOperator("cubeFaceIndexAMD", EOpCubeFaceIndex); - symbolTable.relateToOperator("cubeFaceCoordAMD", EOpCubeFaceCoord); - symbolTable.relateToOperator("timeAMD", EOpTime); - - symbolTable.relateToOperator("textureGatherLodAMD", EOpTextureGatherLod); - symbolTable.relateToOperator("textureGatherLodOffsetAMD", EOpTextureGatherLodOffset); - symbolTable.relateToOperator("textureGatherLodOffsetsAMD", EOpTextureGatherLodOffsets); - symbolTable.relateToOperator("sparseTextureGatherLodAMD", EOpSparseTextureGatherLod); - symbolTable.relateToOperator("sparseTextureGatherLodOffsetAMD", EOpSparseTextureGatherLodOffset); - symbolTable.relateToOperator("sparseTextureGatherLodOffsetsAMD", EOpSparseTextureGatherLodOffsets); - - symbolTable.relateToOperator("imageLoadLodAMD", EOpImageLoadLod); - symbolTable.relateToOperator("imageStoreLodAMD", EOpImageStoreLod); - symbolTable.relateToOperator("sparseImageLoadLodAMD", EOpSparseImageLoadLod); - - symbolTable.relateToOperator("fragmentMaskFetchAMD", EOpFragmentMaskFetch); - symbolTable.relateToOperator("fragmentFetchAMD", EOpFragmentFetch); -#endif - } - - // GL_KHR_shader_subgroup - if (spvVersion.vulkan > 0) { - symbolTable.relateToOperator("subgroupBarrier", EOpSubgroupBarrier); - symbolTable.relateToOperator("subgroupMemoryBarrier", EOpSubgroupMemoryBarrier); - symbolTable.relateToOperator("subgroupMemoryBarrierBuffer", EOpSubgroupMemoryBarrierBuffer); - symbolTable.relateToOperator("subgroupMemoryBarrierImage", EOpSubgroupMemoryBarrierImage); - symbolTable.relateToOperator("subgroupElect", EOpSubgroupElect); - symbolTable.relateToOperator("subgroupAll", EOpSubgroupAll); - symbolTable.relateToOperator("subgroupAny", EOpSubgroupAny); - symbolTable.relateToOperator("subgroupAllEqual", EOpSubgroupAllEqual); - symbolTable.relateToOperator("subgroupBroadcast", EOpSubgroupBroadcast); - symbolTable.relateToOperator("subgroupBroadcastFirst", EOpSubgroupBroadcastFirst); - symbolTable.relateToOperator("subgroupBallot", EOpSubgroupBallot); - symbolTable.relateToOperator("subgroupInverseBallot", EOpSubgroupInverseBallot); - symbolTable.relateToOperator("subgroupBallotBitExtract", EOpSubgroupBallotBitExtract); - symbolTable.relateToOperator("subgroupBallotBitCount", EOpSubgroupBallotBitCount); - symbolTable.relateToOperator("subgroupBallotInclusiveBitCount", EOpSubgroupBallotInclusiveBitCount); - symbolTable.relateToOperator("subgroupBallotExclusiveBitCount", EOpSubgroupBallotExclusiveBitCount); - symbolTable.relateToOperator("subgroupBallotFindLSB", EOpSubgroupBallotFindLSB); - symbolTable.relateToOperator("subgroupBallotFindMSB", EOpSubgroupBallotFindMSB); - symbolTable.relateToOperator("subgroupShuffle", EOpSubgroupShuffle); - symbolTable.relateToOperator("subgroupShuffleXor", EOpSubgroupShuffleXor); - symbolTable.relateToOperator("subgroupShuffleUp", EOpSubgroupShuffleUp); - symbolTable.relateToOperator("subgroupShuffleDown", EOpSubgroupShuffleDown); - symbolTable.relateToOperator("subgroupAdd", EOpSubgroupAdd); - symbolTable.relateToOperator("subgroupMul", EOpSubgroupMul); - symbolTable.relateToOperator("subgroupMin", EOpSubgroupMin); - symbolTable.relateToOperator("subgroupMax", EOpSubgroupMax); - symbolTable.relateToOperator("subgroupAnd", EOpSubgroupAnd); - symbolTable.relateToOperator("subgroupOr", EOpSubgroupOr); - symbolTable.relateToOperator("subgroupXor", EOpSubgroupXor); - symbolTable.relateToOperator("subgroupInclusiveAdd", EOpSubgroupInclusiveAdd); - symbolTable.relateToOperator("subgroupInclusiveMul", EOpSubgroupInclusiveMul); - symbolTable.relateToOperator("subgroupInclusiveMin", EOpSubgroupInclusiveMin); - symbolTable.relateToOperator("subgroupInclusiveMax", EOpSubgroupInclusiveMax); - symbolTable.relateToOperator("subgroupInclusiveAnd", EOpSubgroupInclusiveAnd); - symbolTable.relateToOperator("subgroupInclusiveOr", EOpSubgroupInclusiveOr); - symbolTable.relateToOperator("subgroupInclusiveXor", EOpSubgroupInclusiveXor); - symbolTable.relateToOperator("subgroupExclusiveAdd", EOpSubgroupExclusiveAdd); - symbolTable.relateToOperator("subgroupExclusiveMul", EOpSubgroupExclusiveMul); - symbolTable.relateToOperator("subgroupExclusiveMin", EOpSubgroupExclusiveMin); - symbolTable.relateToOperator("subgroupExclusiveMax", EOpSubgroupExclusiveMax); - symbolTable.relateToOperator("subgroupExclusiveAnd", EOpSubgroupExclusiveAnd); - symbolTable.relateToOperator("subgroupExclusiveOr", EOpSubgroupExclusiveOr); - symbolTable.relateToOperator("subgroupExclusiveXor", EOpSubgroupExclusiveXor); - symbolTable.relateToOperator("subgroupClusteredAdd", EOpSubgroupClusteredAdd); - symbolTable.relateToOperator("subgroupClusteredMul", EOpSubgroupClusteredMul); - symbolTable.relateToOperator("subgroupClusteredMin", EOpSubgroupClusteredMin); - symbolTable.relateToOperator("subgroupClusteredMax", EOpSubgroupClusteredMax); - symbolTable.relateToOperator("subgroupClusteredAnd", EOpSubgroupClusteredAnd); - symbolTable.relateToOperator("subgroupClusteredOr", EOpSubgroupClusteredOr); - symbolTable.relateToOperator("subgroupClusteredXor", EOpSubgroupClusteredXor); - symbolTable.relateToOperator("subgroupQuadBroadcast", EOpSubgroupQuadBroadcast); - symbolTable.relateToOperator("subgroupQuadSwapHorizontal", EOpSubgroupQuadSwapHorizontal); - symbolTable.relateToOperator("subgroupQuadSwapVertical", EOpSubgroupQuadSwapVertical); - symbolTable.relateToOperator("subgroupQuadSwapDiagonal", EOpSubgroupQuadSwapDiagonal); - -#ifdef NV_EXTENSIONS - symbolTable.relateToOperator("subgroupPartitionNV", EOpSubgroupPartition); - symbolTable.relateToOperator("subgroupPartitionedAddNV", EOpSubgroupPartitionedAdd); - symbolTable.relateToOperator("subgroupPartitionedMulNV", EOpSubgroupPartitionedMul); - symbolTable.relateToOperator("subgroupPartitionedMinNV", EOpSubgroupPartitionedMin); - symbolTable.relateToOperator("subgroupPartitionedMaxNV", EOpSubgroupPartitionedMax); - symbolTable.relateToOperator("subgroupPartitionedAndNV", EOpSubgroupPartitionedAnd); - symbolTable.relateToOperator("subgroupPartitionedOrNV", EOpSubgroupPartitionedOr); - symbolTable.relateToOperator("subgroupPartitionedXorNV", EOpSubgroupPartitionedXor); - symbolTable.relateToOperator("subgroupPartitionedInclusiveAddNV", EOpSubgroupPartitionedInclusiveAdd); - symbolTable.relateToOperator("subgroupPartitionedInclusiveMulNV", EOpSubgroupPartitionedInclusiveMul); - symbolTable.relateToOperator("subgroupPartitionedInclusiveMinNV", EOpSubgroupPartitionedInclusiveMin); - symbolTable.relateToOperator("subgroupPartitionedInclusiveMaxNV", EOpSubgroupPartitionedInclusiveMax); - symbolTable.relateToOperator("subgroupPartitionedInclusiveAndNV", EOpSubgroupPartitionedInclusiveAnd); - symbolTable.relateToOperator("subgroupPartitionedInclusiveOrNV", EOpSubgroupPartitionedInclusiveOr); - symbolTable.relateToOperator("subgroupPartitionedInclusiveXorNV", EOpSubgroupPartitionedInclusiveXor); - symbolTable.relateToOperator("subgroupPartitionedExclusiveAddNV", EOpSubgroupPartitionedExclusiveAdd); - symbolTable.relateToOperator("subgroupPartitionedExclusiveMulNV", EOpSubgroupPartitionedExclusiveMul); - symbolTable.relateToOperator("subgroupPartitionedExclusiveMinNV", EOpSubgroupPartitionedExclusiveMin); - symbolTable.relateToOperator("subgroupPartitionedExclusiveMaxNV", EOpSubgroupPartitionedExclusiveMax); - symbolTable.relateToOperator("subgroupPartitionedExclusiveAndNV", EOpSubgroupPartitionedExclusiveAnd); - symbolTable.relateToOperator("subgroupPartitionedExclusiveOrNV", EOpSubgroupPartitionedExclusiveOr); - symbolTable.relateToOperator("subgroupPartitionedExclusiveXorNV", EOpSubgroupPartitionedExclusiveXor); -#endif - } - - if (profile == EEsProfile) { - symbolTable.relateToOperator("shadow2DEXT", EOpTexture); - symbolTable.relateToOperator("shadow2DProjEXT", EOpTextureProj); - } - } - - switch(language) { - case EShLangVertex: - break; - - case EShLangTessControl: - case EShLangTessEvaluation: - break; - - case EShLangGeometry: - symbolTable.relateToOperator("EmitStreamVertex", EOpEmitStreamVertex); - symbolTable.relateToOperator("EndStreamPrimitive", EOpEndStreamPrimitive); - symbolTable.relateToOperator("EmitVertex", EOpEmitVertex); - symbolTable.relateToOperator("EndPrimitive", EOpEndPrimitive); - break; - - case EShLangFragment: - symbolTable.relateToOperator("dFdx", EOpDPdx); - symbolTable.relateToOperator("dFdy", EOpDPdy); - symbolTable.relateToOperator("fwidth", EOpFwidth); - if (profile != EEsProfile && version >= 400) { - symbolTable.relateToOperator("dFdxFine", EOpDPdxFine); - symbolTable.relateToOperator("dFdyFine", EOpDPdyFine); - symbolTable.relateToOperator("fwidthFine", EOpFwidthFine); - symbolTable.relateToOperator("dFdxCoarse", EOpDPdxCoarse); - symbolTable.relateToOperator("dFdyCoarse", EOpDPdyCoarse); - symbolTable.relateToOperator("fwidthCoarse", EOpFwidthCoarse); - } - symbolTable.relateToOperator("interpolateAtCentroid", EOpInterpolateAtCentroid); - symbolTable.relateToOperator("interpolateAtSample", EOpInterpolateAtSample); - symbolTable.relateToOperator("interpolateAtOffset", EOpInterpolateAtOffset); - -#ifdef AMD_EXTENSIONS - if (profile != EEsProfile) - symbolTable.relateToOperator("interpolateAtVertexAMD", EOpInterpolateAtVertex); -#endif - break; - - case EShLangCompute: - symbolTable.relateToOperator("memoryBarrierShared", EOpMemoryBarrierShared); - symbolTable.relateToOperator("groupMemoryBarrier", EOpGroupMemoryBarrier); - symbolTable.relateToOperator("subgroupMemoryBarrierShared", EOpSubgroupMemoryBarrierShared); - break; - - default: - assert(false && "Language not supported"); - } -} - -// -// Add context-dependent (resource-specific) built-ins not handled by the above. These -// would be ones that need to be programmatically added because they cannot -// be added by simple text strings. For these, also -// 1) Map built-in functions to operators, for those that will turn into an operation node -// instead of remaining a function call. -// 2) Tag extension-related symbols added to their base version with their extensions, so -// that if an early version has the extension turned off, there is an error reported on use. -// -void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage language, TSymbolTable& symbolTable, const TBuiltInResource &resources) -{ - if (profile != EEsProfile && version >= 430 && version < 440) { - symbolTable.setVariableExtensions("gl_MaxTransformFeedbackBuffers", 1, &E_GL_ARB_enhanced_layouts); - symbolTable.setVariableExtensions("gl_MaxTransformFeedbackInterleavedComponents", 1, &E_GL_ARB_enhanced_layouts); - } - if (profile != EEsProfile && version >= 130 && version < 420) { - symbolTable.setVariableExtensions("gl_MinProgramTexelOffset", 1, &E_GL_ARB_shading_language_420pack); - symbolTable.setVariableExtensions("gl_MaxProgramTexelOffset", 1, &E_GL_ARB_shading_language_420pack); - } - if (profile != EEsProfile && version >= 150 && version < 410) - symbolTable.setVariableExtensions("gl_MaxViewports", 1, &E_GL_ARB_viewport_array); - - switch(language) { - case EShLangFragment: - // Set up gl_FragData based on current array size. - if (version == 100 || IncludeLegacy(version, profile, spvVersion) || (! ForwardCompatibility && profile != EEsProfile && version < 420)) { - TPrecisionQualifier pq = profile == EEsProfile ? EpqMedium : EpqNone; - TType fragData(EbtFloat, EvqFragColor, pq, 4); - TArraySizes* arraySizes = new TArraySizes; - arraySizes->addInnerSize(resources.maxDrawBuffers); - fragData.transferArraySizes(arraySizes); - symbolTable.insert(*new TVariable(NewPoolTString("gl_FragData"), fragData)); - SpecialQualifier("gl_FragData", EvqFragColor, EbvFragData, symbolTable); - } - break; - - case EShLangTessControl: - case EShLangTessEvaluation: - // Because of the context-dependent array size (gl_MaxPatchVertices), - // these variables were added later than the others and need to be mapped now. - - // standard members - BuiltInVariable("gl_in", "gl_Position", EbvPosition, symbolTable); - BuiltInVariable("gl_in", "gl_PointSize", EbvPointSize, symbolTable); - BuiltInVariable("gl_in", "gl_ClipDistance", EbvClipDistance, symbolTable); - BuiltInVariable("gl_in", "gl_CullDistance", EbvCullDistance, symbolTable); - - // compatibility members - BuiltInVariable("gl_in", "gl_ClipVertex", EbvClipVertex, symbolTable); - BuiltInVariable("gl_in", "gl_FrontColor", EbvFrontColor, symbolTable); - BuiltInVariable("gl_in", "gl_BackColor", EbvBackColor, symbolTable); - BuiltInVariable("gl_in", "gl_FrontSecondaryColor", EbvFrontSecondaryColor, symbolTable); - BuiltInVariable("gl_in", "gl_BackSecondaryColor", EbvBackSecondaryColor, symbolTable); - BuiltInVariable("gl_in", "gl_TexCoord", EbvTexCoord, symbolTable); - BuiltInVariable("gl_in", "gl_FogFragCoord", EbvFogFragCoord, symbolTable); - break; - - default: - break; - } -} - -} // end namespace glslang diff --git a/External/glslang/glslang/MachineIndependent/Initialize.h b/External/glslang/glslang/MachineIndependent/Initialize.h deleted file mode 100644 index b5de3242..00000000 --- a/External/glslang/glslang/MachineIndependent/Initialize.h +++ /dev/null @@ -1,110 +0,0 @@ -// -// 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 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/External/glslang/glslang/MachineIndependent/IntermTraverse.cpp b/External/glslang/glslang/MachineIndependent/IntermTraverse.cpp deleted file mode 100644 index f46010b7..00000000 --- a/External/glslang/glslang/MachineIndependent/IntermTraverse.cpp +++ /dev/null @@ -1,302 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// Copyright (C) 2013 LunarG, Inc. -// Copyright (c) 2002-2010 The ANGLE Project Authors. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -#include "../Include/intermediate.h" - -namespace glslang { - -// -// Traverse the intermediate representation tree, and -// call a node type specific function for each node. -// Done recursively through the member function Traverse(). -// Node types can be skipped if their function to call is 0, -// but their subtree will still be traversed. -// Nodes with children can have their whole subtree skipped -// if preVisit is turned on and the type specific function -// returns false. -// -// preVisit, postVisit, and rightToLeft control what order -// nodes are visited in. -// - -// -// Traversal functions for terminals are straightforward.... -// -void TIntermMethod::traverse(TIntermTraverser*) -{ - // Tree should always resolve all methods as a non-method. -} - -void TIntermSymbol::traverse(TIntermTraverser *it) -{ - it->visitSymbol(this); -} - -void TIntermConstantUnion::traverse(TIntermTraverser *it) -{ - it->visitConstantUnion(this); -} - -// -// Traverse a binary node. -// -void TIntermBinary::traverse(TIntermTraverser *it) -{ - bool visit = true; - - // - // visit the node before children if pre-visiting. - // - if (it->preVisit) - visit = it->visitBinary(EvPreVisit, this); - - // - // Visit the children, in the right order. - // - if (visit) { - it->incrementDepth(this); - - if (it->rightToLeft) { - if (right) - right->traverse(it); - - if (it->inVisit) - visit = it->visitBinary(EvInVisit, this); - - if (visit && left) - left->traverse(it); - } else { - if (left) - left->traverse(it); - - if (it->inVisit) - visit = it->visitBinary(EvInVisit, this); - - if (visit && right) - right->traverse(it); - } - - it->decrementDepth(); - } - - // - // Visit the node after the children, if requested and the traversal - // hasn't been canceled yet. - // - if (visit && it->postVisit) - it->visitBinary(EvPostVisit, this); -} - -// -// Traverse a unary node. Same comments in binary node apply here. -// -void TIntermUnary::traverse(TIntermTraverser *it) -{ - bool visit = true; - - if (it->preVisit) - visit = it->visitUnary(EvPreVisit, this); - - if (visit) { - it->incrementDepth(this); - operand->traverse(it); - it->decrementDepth(); - } - - if (visit && it->postVisit) - it->visitUnary(EvPostVisit, this); -} - -// -// Traverse an aggregate node. Same comments in binary node apply here. -// -void TIntermAggregate::traverse(TIntermTraverser *it) -{ - bool visit = true; - - if (it->preVisit) - visit = it->visitAggregate(EvPreVisit, this); - - if (visit) { - it->incrementDepth(this); - - if (it->rightToLeft) { - for (TIntermSequence::reverse_iterator sit = sequence.rbegin(); sit != sequence.rend(); sit++) { - (*sit)->traverse(it); - - if (visit && it->inVisit) { - if (*sit != sequence.front()) - visit = it->visitAggregate(EvInVisit, this); - } - } - } else { - for (TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); sit++) { - (*sit)->traverse(it); - - if (visit && it->inVisit) { - if (*sit != sequence.back()) - visit = it->visitAggregate(EvInVisit, this); - } - } - } - - it->decrementDepth(); - } - - if (visit && it->postVisit) - it->visitAggregate(EvPostVisit, this); -} - -// -// Traverse a selection node. Same comments in binary node apply here. -// -void TIntermSelection::traverse(TIntermTraverser *it) -{ - bool visit = true; - - if (it->preVisit) - visit = it->visitSelection(EvPreVisit, this); - - if (visit) { - it->incrementDepth(this); - if (it->rightToLeft) { - if (falseBlock) - falseBlock->traverse(it); - if (trueBlock) - trueBlock->traverse(it); - condition->traverse(it); - } else { - condition->traverse(it); - if (trueBlock) - trueBlock->traverse(it); - if (falseBlock) - falseBlock->traverse(it); - } - it->decrementDepth(); - } - - if (visit && it->postVisit) - it->visitSelection(EvPostVisit, this); -} - -// -// Traverse a loop node. Same comments in binary node apply here. -// -void TIntermLoop::traverse(TIntermTraverser *it) -{ - bool visit = true; - - if (it->preVisit) - visit = it->visitLoop(EvPreVisit, this); - - if (visit) { - it->incrementDepth(this); - - if (it->rightToLeft) { - if (terminal) - terminal->traverse(it); - - if (body) - body->traverse(it); - - if (test) - test->traverse(it); - } else { - if (test) - test->traverse(it); - - if (body) - body->traverse(it); - - if (terminal) - terminal->traverse(it); - } - - it->decrementDepth(); - } - - if (visit && it->postVisit) - it->visitLoop(EvPostVisit, this); -} - -// -// Traverse a branch node. Same comments in binary node apply here. -// -void TIntermBranch::traverse(TIntermTraverser *it) -{ - bool visit = true; - - if (it->preVisit) - visit = it->visitBranch(EvPreVisit, this); - - if (visit && expression) { - it->incrementDepth(this); - expression->traverse(it); - it->decrementDepth(); - } - - if (visit && it->postVisit) - it->visitBranch(EvPostVisit, this); -} - -// -// Traverse a switch node. -// -void TIntermSwitch::traverse(TIntermTraverser* it) -{ - bool visit = true; - - if (it->preVisit) - visit = it->visitSwitch(EvPreVisit, this); - - if (visit) { - it->incrementDepth(this); - if (it->rightToLeft) { - body->traverse(it); - condition->traverse(it); - } else { - condition->traverse(it); - body->traverse(it); - } - it->decrementDepth(); - } - - if (visit && it->postVisit) - it->visitSwitch(EvPostVisit, this); -} - -} // end namespace glslang diff --git a/External/glslang/glslang/MachineIndependent/Intermediate.cpp b/External/glslang/glslang/MachineIndependent/Intermediate.cpp deleted file mode 100644 index 0333e5d0..00000000 --- a/External/glslang/glslang/MachineIndependent/Intermediate.cpp +++ /dev/null @@ -1,3815 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// Copyright (C) 2012-2015 LunarG, Inc. -// Copyright (C) 2015-2016 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. -// - -// -// Build the intermediate representation. -// - -#include "localintermediate.h" -#include "RemoveTree.h" -#include "SymbolTable.h" -#include "propagateNoContraction.h" - -#include -#include -#include - -namespace glslang { - -//////////////////////////////////////////////////////////////////////////// -// -// First set of functions are to help build the intermediate representation. -// These functions are not member functions of the nodes. -// They are called from parser productions. -// -///////////////////////////////////////////////////////////////////////////// - -// -// Add a terminal node for an identifier in an expression. -// -// Returns the added node. -// - -TIntermSymbol* TIntermediate::addSymbol(int id, const TString& name, const TType& type, const TConstUnionArray& constArray, - TIntermTyped* constSubtree, const TSourceLoc& loc) -{ - TIntermSymbol* node = new TIntermSymbol(id, name, type); - node->setLoc(loc); - node->setConstArray(constArray); - node->setConstSubtree(constSubtree); - - return node; -} - -TIntermSymbol* TIntermediate::addSymbol(const TIntermSymbol& intermSymbol) -{ - return addSymbol(intermSymbol.getId(), - intermSymbol.getName(), - intermSymbol.getType(), - intermSymbol.getConstArray(), - intermSymbol.getConstSubtree(), - intermSymbol.getLoc()); -} - -TIntermSymbol* TIntermediate::addSymbol(const TVariable& variable) -{ - glslang::TSourceLoc loc; // just a null location - loc.init(); - - return addSymbol(variable, loc); -} - -TIntermSymbol* TIntermediate::addSymbol(const TVariable& variable, const TSourceLoc& loc) -{ - return addSymbol(variable.getUniqueId(), variable.getName(), variable.getType(), variable.getConstArray(), variable.getConstSubtree(), loc); -} - -TIntermSymbol* TIntermediate::addSymbol(const TType& type, const TSourceLoc& loc) -{ - TConstUnionArray unionArray; // just a null constant - - return addSymbol(0, "", type, unionArray, nullptr, loc); -} - -// -// Connect two nodes with a new parent that does a binary operation on the nodes. -// -// Returns the added node. -// -// Returns nullptr if the working conversions and promotions could not be found. -// -TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc loc) -{ - // No operations work on blocks - if (left->getType().getBasicType() == EbtBlock || right->getType().getBasicType() == EbtBlock) - return nullptr; - - // Try converting the children's base types to compatible types. - auto children = addConversion(op, left, right); - left = std::get<0>(children); - right = std::get<1>(children); - - if (left == nullptr || right == nullptr) - return nullptr; - - // Convert the children's type shape to be compatible. - addBiShapeConversion(op, left, right); - if (left == nullptr || right == nullptr) - return nullptr; - - // - // Need a new node holding things together. Make - // one and promote it to the right type. - // - TIntermBinary* node = addBinaryNode(op, left, right, loc); - if (! promote(node)) - return nullptr; - - node->updatePrecision(); - - // - // If they are both (non-specialization) constants, they must be folded. - // (Unless it's the sequence (comma) operator, but that's handled in addComma().) - // - TIntermConstantUnion *leftTempConstant = node->getLeft()->getAsConstantUnion(); - TIntermConstantUnion *rightTempConstant = node->getRight()->getAsConstantUnion(); - if (leftTempConstant && rightTempConstant) { - TIntermTyped* folded = leftTempConstant->fold(node->getOp(), rightTempConstant); - if (folded) - return folded; - } - - // If can propagate spec-constantness and if the operation is an allowed - // specialization-constant operation, make a spec-constant. - if (specConstantPropagates(*node->getLeft(), *node->getRight()) && isSpecializationOperation(*node)) - node->getWritableType().getQualifier().makeSpecConstant(); - - // If must propagate nonuniform, make a nonuniform. - if ((node->getLeft()->getQualifier().nonUniform || node->getRight()->getQualifier().nonUniform) && - isNonuniformPropagating(node->getOp())) - node->getWritableType().getQualifier().nonUniform = true; - - return node; -} - -// -// Low level: add binary node (no promotions or other argument modifications) -// -TIntermBinary* TIntermediate::addBinaryNode(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc loc) const -{ - // build the node - TIntermBinary* node = new TIntermBinary(op); - if (loc.line == 0) - loc = left->getLoc(); - node->setLoc(loc); - node->setLeft(left); - node->setRight(right); - - return node; -} - -// -// like non-type form, but sets node's type. -// -TIntermBinary* TIntermediate::addBinaryNode(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc loc, const TType& type) const -{ - TIntermBinary* node = addBinaryNode(op, left, right, loc); - node->setType(type); - return node; -} - -// -// Low level: add unary node (no promotions or other argument modifications) -// -TIntermUnary* TIntermediate::addUnaryNode(TOperator op, TIntermTyped* child, TSourceLoc loc) const -{ - TIntermUnary* node = new TIntermUnary(op); - if (loc.line == 0) - loc = child->getLoc(); - node->setLoc(loc); - node->setOperand(child); - - return node; -} - -// -// like non-type form, but sets node's type. -// -TIntermUnary* TIntermediate::addUnaryNode(TOperator op, TIntermTyped* child, TSourceLoc loc, const TType& type) const -{ - TIntermUnary* node = addUnaryNode(op, child, loc); - node->setType(type); - return node; -} - -// -// Connect two nodes through an assignment. -// -// Returns the added node. -// -// Returns nullptr if the 'right' type could not be converted to match the 'left' type, -// or the resulting operation cannot be properly promoted. -// -TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc loc) -{ - // No block assignment - if (left->getType().getBasicType() == EbtBlock || right->getType().getBasicType() == EbtBlock) - return nullptr; - - // - // Like adding binary math, except the conversion can only go - // from right to left. - // - - // convert base types, nullptr return means not possible - right = addConversion(op, left->getType(), right); - if (right == nullptr) - return nullptr; - - // convert shape - right = addUniShapeConversion(op, left->getType(), right); - - // build the node - TIntermBinary* node = addBinaryNode(op, left, right, loc); - - if (! promote(node)) - return nullptr; - - node->updatePrecision(); - - return node; -} - -// -// Connect two nodes through an index operator, where the left node is the base -// of an array or struct, and the right node is a direct or indirect offset. -// -// Returns the added node. -// The caller should set the type of the returned node. -// -TIntermTyped* TIntermediate::addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, TSourceLoc loc) -{ - // caller should set the type - return addBinaryNode(op, base, index, loc); -} - -// -// Add one node as the parent of another that it operates on. -// -// Returns the added node. -// -TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermTyped* child, TSourceLoc loc) -{ - if (child == 0) - return nullptr; - - if (child->getType().getBasicType() == EbtBlock) - return nullptr; - - switch (op) { - case EOpLogicalNot: - if (source == EShSourceHlsl) { - break; // HLSL can promote logical not - } - - if (child->getType().getBasicType() != EbtBool || child->getType().isMatrix() || child->getType().isArray() || child->getType().isVector()) { - return nullptr; - } - break; - - case EOpPostIncrement: - case EOpPreIncrement: - case EOpPostDecrement: - case EOpPreDecrement: - case EOpNegative: - if (child->getType().getBasicType() == EbtStruct || child->getType().isArray()) - return nullptr; - default: break; // some compilers want this - } - - // - // Do we need to promote the operand? - // - TBasicType newType = EbtVoid; - switch (op) { - case EOpConstructInt8: newType = EbtInt8; break; - case EOpConstructUint8: newType = EbtUint8; break; - case EOpConstructInt16: newType = EbtInt16; break; - case EOpConstructUint16: newType = EbtUint16; break; - case EOpConstructInt: newType = EbtInt; break; - case EOpConstructUint: newType = EbtUint; break; - case EOpConstructInt64: newType = EbtInt64; break; - case EOpConstructUint64: newType = EbtUint64; break; - case EOpConstructBool: newType = EbtBool; break; - case EOpConstructFloat: newType = EbtFloat; break; - case EOpConstructDouble: newType = EbtDouble; break; - case EOpConstructFloat16: newType = EbtFloat16; break; - default: break; // some compilers want this - } - - if (newType != EbtVoid) { - child = addConversion(op, TType(newType, EvqTemporary, child->getVectorSize(), - child->getMatrixCols(), - child->getMatrixRows(), - child->isVector()), - child); - if (child == nullptr) - return nullptr; - } - - // - // For constructors, we are now done, it was all in the conversion. - // TODO: but, did this bypass constant folding? - // - switch (op) { - case EOpConstructInt8: - case EOpConstructUint8: - case EOpConstructInt16: - case EOpConstructUint16: - case EOpConstructInt: - case EOpConstructUint: - case EOpConstructInt64: - case EOpConstructUint64: - case EOpConstructBool: - case EOpConstructFloat: - case EOpConstructDouble: - case EOpConstructFloat16: - return child; - default: break; // some compilers want this - } - - // - // Make a new node for the operator. - // - TIntermUnary* node = addUnaryNode(op, child, loc); - - if (! promote(node)) - return nullptr; - - node->updatePrecision(); - - // If it's a (non-specialization) constant, it must be folded. - if (node->getOperand()->getAsConstantUnion()) - return node->getOperand()->getAsConstantUnion()->fold(op, node->getType()); - - // If it's a specialization constant, the result is too, - // if the operation is allowed for specialization constants. - if (node->getOperand()->getType().getQualifier().isSpecConstant() && isSpecializationOperation(*node)) - node->getWritableType().getQualifier().makeSpecConstant(); - - // If must propagate nonuniform, make a nonuniform. - if (node->getOperand()->getQualifier().nonUniform && isNonuniformPropagating(node->getOp())) - node->getWritableType().getQualifier().nonUniform = true; - - return node; -} - -TIntermTyped* TIntermediate::addBuiltInFunctionCall(const TSourceLoc& loc, TOperator op, bool unary, - TIntermNode* childNode, const TType& returnType) -{ - if (unary) { - // - // Treat it like a unary operator. - // addUnaryMath() should get the type correct on its own; - // including constness (which would differ from the prototype). - // - TIntermTyped* child = childNode->getAsTyped(); - if (child == nullptr) - return nullptr; - - if (child->getAsConstantUnion()) { - TIntermTyped* folded = child->getAsConstantUnion()->fold(op, returnType); - if (folded) - return folded; - } - - return addUnaryNode(op, child, child->getLoc(), returnType); - } else { - // setAggregateOperater() calls fold() for constant folding - TIntermTyped* node = setAggregateOperator(childNode, op, returnType, loc); - - return node; - } -} - -// -// This is the safe way to change the operator on an aggregate, as it -// does lots of error checking and fixing. Especially for establishing -// a function call's operation on it's set of parameters. Sequences -// of instructions are also aggregates, but they just directly set -// their operator to EOpSequence. -// -// Returns an aggregate node, which could be the one passed in if -// it was already an aggregate. -// -TIntermTyped* TIntermediate::setAggregateOperator(TIntermNode* node, TOperator op, const TType& type, TSourceLoc loc) -{ - TIntermAggregate* aggNode; - - // - // Make sure we have an aggregate. If not turn it into one. - // - if (node != nullptr) { - aggNode = node->getAsAggregate(); - if (aggNode == nullptr || aggNode->getOp() != EOpNull) { - // - // Make an aggregate containing this node. - // - aggNode = new TIntermAggregate(); - aggNode->getSequence().push_back(node); - if (loc.line == 0) - loc = node->getLoc(); - } - } else - aggNode = new TIntermAggregate(); - - // - // Set the operator. - // - aggNode->setOperator(op); - if (loc.line != 0) - aggNode->setLoc(loc); - - aggNode->setType(type); - - return fold(aggNode); -} - -bool TIntermediate::isConversionAllowed(TOperator op, TIntermTyped* node) const -{ - // - // Does the base type even allow the operation? - // - switch (node->getBasicType()) { - case EbtVoid: - return false; - case EbtAtomicUint: - case EbtSampler: - // opaque types can be passed to functions - if (op == EOpFunction) - break; - - // HLSL can assign samplers directly (no constructor) - if (source == EShSourceHlsl && node->getBasicType() == EbtSampler) - break; - - // samplers can get assigned via a sampler constructor - // (well, not yet, but code in the rest of this function is ready for it) - if (node->getBasicType() == EbtSampler && op == EOpAssign && - node->getAsOperator() != nullptr && node->getAsOperator()->getOp() == EOpConstructTextureSampler) - break; - - // otherwise, opaque types can't even be operated on, let alone converted - return false; - default: - break; - } - - return true; -} - -// This is 'mechanism' here, it does any conversion told. -// It is about basic type, not about shape. -// The policy comes from the shader or the calling code. -TIntermUnary* TIntermediate::createConversion(TBasicType convertTo, TIntermTyped* node) const -{ - // - // Add a new newNode for the conversion. - // - TIntermUnary* newNode = nullptr; - - TOperator newOp = EOpNull; - - switch (convertTo) { - case EbtDouble: - switch (node->getBasicType()) { - case EbtInt8: newOp = EOpConvInt8ToDouble; break; - case EbtUint8: newOp = EOpConvUint8ToDouble; break; - case EbtInt16: newOp = EOpConvInt16ToDouble; break; - case EbtUint16: newOp = EOpConvUint16ToDouble; break; - case EbtInt: newOp = EOpConvIntToDouble; break; - case EbtUint: newOp = EOpConvUintToDouble; break; - case EbtBool: newOp = EOpConvBoolToDouble; break; - case EbtFloat: newOp = EOpConvFloatToDouble; break; - case EbtFloat16: newOp = EOpConvFloat16ToDouble; break; - case EbtInt64: newOp = EOpConvInt64ToDouble; break; - case EbtUint64: newOp = EOpConvUint64ToDouble; break; - default: - return nullptr; - } - break; - case EbtFloat: - switch (node->getBasicType()) { - case EbtInt8: newOp = EOpConvInt8ToFloat; break; - case EbtUint8: newOp = EOpConvUint8ToFloat; break; - case EbtInt16: newOp = EOpConvInt16ToFloat; break; - case EbtUint16: newOp = EOpConvUint16ToFloat; break; - case EbtInt: newOp = EOpConvIntToFloat; break; - case EbtUint: newOp = EOpConvUintToFloat; break; - case EbtBool: newOp = EOpConvBoolToFloat; break; - case EbtDouble: newOp = EOpConvDoubleToFloat; break; - case EbtFloat16: newOp = EOpConvFloat16ToFloat; break; - case EbtInt64: newOp = EOpConvInt64ToFloat; break; - case EbtUint64: newOp = EOpConvUint64ToFloat; break; - default: - return nullptr; - } - break; - case EbtFloat16: - switch (node->getBasicType()) { - case EbtInt8: newOp = EOpConvInt8ToFloat16; break; - case EbtUint8: newOp = EOpConvUint8ToFloat16; break; - case EbtInt16: newOp = EOpConvInt16ToFloat16; break; - case EbtUint16: newOp = EOpConvUint16ToFloat16; break; - case EbtInt: newOp = EOpConvIntToFloat16; break; - case EbtUint: newOp = EOpConvUintToFloat16; break; - case EbtBool: newOp = EOpConvBoolToFloat16; break; - case EbtFloat: newOp = EOpConvFloatToFloat16; break; - case EbtDouble: newOp = EOpConvDoubleToFloat16; break; - case EbtInt64: newOp = EOpConvInt64ToFloat16; break; - case EbtUint64: newOp = EOpConvUint64ToFloat16; break; - default: - return nullptr; - } - break; - case EbtBool: - switch (node->getBasicType()) { - case EbtInt8: newOp = EOpConvInt8ToBool; break; - case EbtUint8: newOp = EOpConvUint8ToBool; break; - case EbtInt16: newOp = EOpConvInt16ToBool; break; - case EbtUint16: newOp = EOpConvUint16ToBool; break; - case EbtInt: newOp = EOpConvIntToBool; break; - case EbtUint: newOp = EOpConvUintToBool; break; - case EbtFloat: newOp = EOpConvFloatToBool; break; - case EbtDouble: newOp = EOpConvDoubleToBool; break; - case EbtFloat16: newOp = EOpConvFloat16ToBool; break; - case EbtInt64: newOp = EOpConvInt64ToBool; break; - case EbtUint64: newOp = EOpConvUint64ToBool; break; - default: - return nullptr; - } - break; - case EbtInt8: - switch (node->getBasicType()) { - case EbtUint8: newOp = EOpConvUint8ToInt8; break; - case EbtInt16: newOp = EOpConvInt16ToInt8; break; - case EbtUint16: newOp = EOpConvUint16ToInt8; break; - case EbtInt: newOp = EOpConvIntToInt8; break; - case EbtUint: newOp = EOpConvUintToInt8; break; - case EbtInt64: newOp = EOpConvInt64ToInt8; break; - case EbtUint64: newOp = EOpConvUint64ToInt8; break; - case EbtBool: newOp = EOpConvBoolToInt8; break; - case EbtFloat: newOp = EOpConvFloatToInt8; break; - case EbtDouble: newOp = EOpConvDoubleToInt8; break; - case EbtFloat16: newOp = EOpConvFloat16ToInt8; break; - default: - return nullptr; - } - break; - case EbtUint8: - switch (node->getBasicType()) { - case EbtInt8: newOp = EOpConvInt8ToUint8; break; - case EbtInt16: newOp = EOpConvInt16ToUint8; break; - case EbtUint16: newOp = EOpConvUint16ToUint8; break; - case EbtInt: newOp = EOpConvIntToUint8; break; - case EbtUint: newOp = EOpConvUintToUint8; break; - case EbtInt64: newOp = EOpConvInt64ToUint8; break; - case EbtUint64: newOp = EOpConvUint64ToUint8; break; - case EbtBool: newOp = EOpConvBoolToUint8; break; - case EbtFloat: newOp = EOpConvFloatToUint8; break; - case EbtDouble: newOp = EOpConvDoubleToUint8; break; - case EbtFloat16: newOp = EOpConvFloat16ToUint8; break; - default: - return nullptr; - } - break; - - case EbtInt16: - switch (node->getBasicType()) { - case EbtUint8: newOp = EOpConvUint8ToInt16; break; - case EbtInt8: newOp = EOpConvInt8ToInt16; break; - case EbtUint16: newOp = EOpConvUint16ToInt16; break; - case EbtInt: newOp = EOpConvIntToInt16; break; - case EbtUint: newOp = EOpConvUintToInt16; break; - case EbtInt64: newOp = EOpConvInt64ToInt16; break; - case EbtUint64: newOp = EOpConvUint64ToInt16; break; - case EbtBool: newOp = EOpConvBoolToInt16; break; - case EbtFloat: newOp = EOpConvFloatToInt16; break; - case EbtDouble: newOp = EOpConvDoubleToInt16; break; - case EbtFloat16: newOp = EOpConvFloat16ToInt16; break; - default: - return nullptr; - } - break; - case EbtUint16: - switch (node->getBasicType()) { - case EbtInt8: newOp = EOpConvInt8ToUint16; break; - case EbtUint8: newOp = EOpConvUint8ToUint16; break; - case EbtInt16: newOp = EOpConvInt16ToUint16; break; - case EbtInt: newOp = EOpConvIntToUint16; break; - case EbtUint: newOp = EOpConvUintToUint16; break; - case EbtInt64: newOp = EOpConvInt64ToUint16; break; - case EbtUint64: newOp = EOpConvUint64ToUint16; break; - case EbtBool: newOp = EOpConvBoolToUint16; break; - case EbtFloat: newOp = EOpConvFloatToUint16; break; - case EbtDouble: newOp = EOpConvDoubleToUint16; break; - case EbtFloat16: newOp = EOpConvFloat16ToUint16; break; - default: - return nullptr; - } - break; - - case EbtInt: - switch (node->getBasicType()) { - case EbtInt8: newOp = EOpConvInt8ToInt; break; - case EbtUint8: newOp = EOpConvUint8ToInt; break; - case EbtInt16: newOp = EOpConvInt16ToInt; break; - case EbtUint16: newOp = EOpConvUint16ToInt; break; - case EbtUint: newOp = EOpConvUintToInt; break; - case EbtBool: newOp = EOpConvBoolToInt; break; - case EbtFloat: newOp = EOpConvFloatToInt; break; - case EbtDouble: newOp = EOpConvDoubleToInt; break; - case EbtFloat16: newOp = EOpConvFloat16ToInt; break; - case EbtInt64: newOp = EOpConvInt64ToInt; break; - case EbtUint64: newOp = EOpConvUint64ToInt; break; - default: - return nullptr; - } - break; - case EbtUint: - switch (node->getBasicType()) { - case EbtInt8: newOp = EOpConvInt8ToUint; break; - case EbtUint8: newOp = EOpConvUint8ToUint; break; - case EbtInt16: newOp = EOpConvInt16ToUint; break; - case EbtUint16: newOp = EOpConvUint16ToUint; break; - case EbtInt: newOp = EOpConvIntToUint; break; - case EbtBool: newOp = EOpConvBoolToUint; break; - case EbtFloat: newOp = EOpConvFloatToUint; break; - case EbtDouble: newOp = EOpConvDoubleToUint; break; - case EbtFloat16: newOp = EOpConvFloat16ToUint; break; - case EbtInt64: newOp = EOpConvInt64ToUint; break; - case EbtUint64: newOp = EOpConvUint64ToUint; break; - default: - return nullptr; - } - break; - case EbtInt64: - switch (node->getBasicType()) { - case EbtInt8: newOp = EOpConvInt8ToInt64; break; - case EbtUint8: newOp = EOpConvUint8ToInt64; break; - case EbtInt16: newOp = EOpConvInt16ToInt64; break; - case EbtUint16: newOp = EOpConvUint16ToInt64; break; - case EbtInt: newOp = EOpConvIntToInt64; break; - case EbtUint: newOp = EOpConvUintToInt64; break; - case EbtBool: newOp = EOpConvBoolToInt64; break; - case EbtFloat: newOp = EOpConvFloatToInt64; break; - case EbtDouble: newOp = EOpConvDoubleToInt64; break; - case EbtFloat16: newOp = EOpConvFloat16ToInt64; break; - case EbtUint64: newOp = EOpConvUint64ToInt64; break; - default: - return nullptr; - } - break; - case EbtUint64: - switch (node->getBasicType()) { - case EbtInt8: newOp = EOpConvInt8ToUint64; break; - case EbtUint8: newOp = EOpConvUint8ToUint64; break; - case EbtInt16: newOp = EOpConvInt16ToUint64; break; - case EbtUint16: newOp = EOpConvUint16ToUint64; break; - case EbtInt: newOp = EOpConvIntToUint64; break; - case EbtUint: newOp = EOpConvUintToUint64; break; - case EbtBool: newOp = EOpConvBoolToUint64; break; - case EbtFloat: newOp = EOpConvFloatToUint64; break; - case EbtDouble: newOp = EOpConvDoubleToUint64; break; - case EbtFloat16: newOp = EOpConvFloat16ToUint64; break; - case EbtInt64: newOp = EOpConvInt64ToUint64; break; - default: - return nullptr; - } - break; - default: - return nullptr; - } - - TType newType(convertTo, EvqTemporary, node->getVectorSize(), node->getMatrixCols(), node->getMatrixRows()); - newNode = addUnaryNode(newOp, node, node->getLoc(), newType); - - // TODO: it seems that some unary folding operations should occur here, but are not - - // Propagate specialization-constant-ness, if allowed - if (node->getType().getQualifier().isSpecConstant() && isSpecializationOperation(*newNode)) - newNode->getWritableType().getQualifier().makeSpecConstant(); - - return newNode; -} - -// For converting a pair of operands to a binary operation to compatible -// types with each other, relative to the operation in 'op'. -// This does not cover assignment operations, which is asymmetric in that the -// left type is not changeable. -// See addConversion(op, type, node) for assignments and unary operation -// conversions. -// -// Generally, this is focused on basic type conversion, not shape conversion. -// See addShapeConversion() for shape conversions. -// -// Returns the converted pair of nodes. -// Returns when there is no conversion. -std::tuple -TIntermediate::addConversion(TOperator op, TIntermTyped* node0, TIntermTyped* node1) const -{ - if (!isConversionAllowed(op, node0) || !isConversionAllowed(op, node1)) - return std::make_tuple(nullptr, nullptr); - - if (node0->getType() != node1->getType()) { - // If differing structure, then no conversions. - if (node0->isStruct() || node1->isStruct()) - return std::make_tuple(nullptr, nullptr); - - // If differing arrays, then no conversions. - if (node0->getType().isArray() || node1->getType().isArray()) - return std::make_tuple(nullptr, nullptr); - } - - auto promoteTo = std::make_tuple(EbtNumTypes, EbtNumTypes); - - switch (op) { - // - // List all the binary ops that can implicitly convert one operand to the other's type; - // This implements the 'policy' for implicit type conversion. - // - case EOpLessThan: - case EOpGreaterThan: - case EOpLessThanEqual: - case EOpGreaterThanEqual: - case EOpEqual: - case EOpNotEqual: - - case EOpAdd: - case EOpSub: - case EOpMul: - case EOpDiv: - case EOpMod: - - case EOpVectorTimesScalar: - case EOpVectorTimesMatrix: - case EOpMatrixTimesVector: - case EOpMatrixTimesScalar: - - case EOpAnd: - case EOpInclusiveOr: - case EOpExclusiveOr: - - case EOpSequence: // used by ?: - - if (node0->getBasicType() == node1->getBasicType()) - return std::make_tuple(node0, node1); - - promoteTo = getConversionDestinatonType(node0->getBasicType(), node1->getBasicType(), op); - if (std::get<0>(promoteTo) == EbtNumTypes || std::get<1>(promoteTo) == EbtNumTypes) - return std::make_tuple(nullptr, nullptr); - - break; - - case EOpLogicalAnd: - case EOpLogicalOr: - case EOpLogicalXor: - if (source == EShSourceHlsl) - promoteTo = std::make_tuple(EbtBool, EbtBool); - else - return std::make_tuple(node0, node1); - break; - - // There are no conversions needed for GLSL; the shift amount just needs to be an - // integer type, as does the base. - // HLSL can promote bools to ints to make this work. - case EOpLeftShift: - case EOpRightShift: - if (source == EShSourceHlsl) { - TBasicType node0BasicType = node0->getBasicType(); - if (node0BasicType == EbtBool) - node0BasicType = EbtInt; - if (node1->getBasicType() == EbtBool) - promoteTo = std::make_tuple(node0BasicType, EbtInt); - else - promoteTo = std::make_tuple(node0BasicType, node1->getBasicType()); - } else { - if (isTypeInt(node0->getBasicType()) && isTypeInt(node1->getBasicType())) - return std::make_tuple(node0, node1); - else - return std::make_tuple(nullptr, nullptr); - } - break; - - default: - if (node0->getType() == node1->getType()) - return std::make_tuple(node0, node1); - - return std::make_tuple(nullptr, nullptr); - } - - TIntermTyped* newNode0; - TIntermTyped* newNode1; - - if (std::get<0>(promoteTo) != node0->getType().getBasicType()) { - if (node0->getAsConstantUnion()) - newNode0 = promoteConstantUnion(std::get<0>(promoteTo), node0->getAsConstantUnion()); - else - newNode0 = createConversion(std::get<0>(promoteTo), node0); - } else - newNode0 = node0; - - if (std::get<1>(promoteTo) != node1->getType().getBasicType()) { - if (node1->getAsConstantUnion()) - newNode1 = promoteConstantUnion(std::get<1>(promoteTo), node1->getAsConstantUnion()); - else - newNode1 = createConversion(std::get<1>(promoteTo), node1); - } else - newNode1 = node1; - - return std::make_tuple(newNode0, newNode1); -} - -// -// Convert the node's type to the given type, as allowed by the operation involved: 'op'. -// For implicit conversions, 'op' is not the requested conversion, it is the explicit -// operation requiring the implicit conversion. -// -// Binary operation conversions should be handled by addConversion(op, node, node), not here. -// -// Returns a node representing the conversion, which could be the same -// node passed in if no conversion was needed. -// -// Generally, this is focused on basic type conversion, not shape conversion. -// See addShapeConversion() for shape conversions. -// -// Return nullptr if a conversion can't be done. -// -TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TIntermTyped* node) const -{ - if (!isConversionAllowed(op, node)) - return nullptr; - - // Otherwise, if types are identical, no problem - if (type == node->getType()) - return node; - - // If one's a structure, then no conversions. - if (type.isStruct() || node->isStruct()) - return nullptr; - - // If one's an array, then no conversions. - if (type.isArray() || node->getType().isArray()) - return nullptr; - - // Note: callers are responsible for other aspects of shape, - // like vector and matrix sizes. - - TBasicType promoteTo; - - switch (op) { - // - // Explicit conversions (unary operations) - // - case EOpConstructBool: - promoteTo = EbtBool; - break; - case EOpConstructFloat: - promoteTo = EbtFloat; - break; - case EOpConstructDouble: - promoteTo = EbtDouble; - break; - case EOpConstructFloat16: - promoteTo = EbtFloat16; - break; - case EOpConstructInt8: - promoteTo = EbtInt8; - break; - case EOpConstructUint8: - promoteTo = EbtUint8; - break; - case EOpConstructInt16: - promoteTo = EbtInt16; - break; - case EOpConstructUint16: - promoteTo = EbtUint16; - break; - case EOpConstructInt: - promoteTo = EbtInt; - break; - case EOpConstructUint: - promoteTo = EbtUint; - break; - case EOpConstructInt64: - promoteTo = EbtInt64; - break; - case EOpConstructUint64: - promoteTo = EbtUint64; - break; - - case EOpLogicalNot: - - case EOpFunctionCall: - - case EOpReturn: - case EOpAssign: - case EOpAddAssign: - case EOpSubAssign: - case EOpMulAssign: - case EOpVectorTimesScalarAssign: - case EOpMatrixTimesScalarAssign: - case EOpDivAssign: - case EOpModAssign: - case EOpAndAssign: - case EOpInclusiveOrAssign: - case EOpExclusiveOrAssign: - - case EOpAtan: - case EOpClamp: - case EOpCross: - case EOpDistance: - case EOpDot: - case EOpDst: - case EOpFaceForward: - case EOpFma: - case EOpFrexp: - case EOpLdexp: - case EOpMix: - case EOpLit: - case EOpMax: - case EOpMin: - case EOpModf: - case EOpPow: - case EOpReflect: - case EOpRefract: - case EOpSmoothStep: - case EOpStep: - - case EOpSequence: - case EOpConstructStruct: - - if (type.getBasicType() == node->getType().getBasicType()) - return node; - - if (canImplicitlyPromote(node->getBasicType(), type.getBasicType(), op)) - promoteTo = type.getBasicType(); - else - return nullptr; - break; - - // For GLSL, there are no conversions needed; the shift amount just needs to be an - // integer type, as do the base/result. - // HLSL can convert the shift from a bool to an int. - case EOpLeftShiftAssign: - case EOpRightShiftAssign: - { - if (source == EShSourceHlsl && node->getType().getBasicType() == EbtBool) - promoteTo = type.getBasicType(); - else { - if (isTypeInt(type.getBasicType()) && isTypeInt(node->getBasicType())) - return node; - else - return nullptr; - } - break; - } - - default: - // default is to require a match; all exceptions should have case statements above - - if (type.getBasicType() == node->getType().getBasicType()) - return node; - else - return nullptr; - } - - if (node->getAsConstantUnion()) - return promoteConstantUnion(promoteTo, node->getAsConstantUnion()); - - // - // Add a new newNode for the conversion. - // - TIntermUnary* newNode = createConversion(promoteTo, node); - - return newNode; -} - -// Convert the node's shape of type for the given type, as allowed by the -// operation involved: 'op'. This is for situations where there is only one -// direction to consider doing the shape conversion. -// -// This implements policy, it call addShapeConversion() for the mechanism. -// -// Generally, the AST represents allowed GLSL shapes, so this isn't needed -// for GLSL. Bad shapes are caught in conversion or promotion. -// -// Return 'node' if no conversion was done. Promotion handles final shape -// checking. -// -TIntermTyped* TIntermediate::addUniShapeConversion(TOperator op, const TType& type, TIntermTyped* node) -{ - // some source languages don't do this - switch (source) { - case EShSourceHlsl: - break; - case EShSourceGlsl: - default: - return node; - } - - // some operations don't do this - switch (op) { - case EOpFunctionCall: - case EOpReturn: - break; - - case EOpMulAssign: - // want to support vector *= scalar native ops in AST and lower, not smear, similarly for - // matrix *= scalar, etc. - - case EOpAddAssign: - case EOpSubAssign: - case EOpDivAssign: - case EOpAndAssign: - case EOpInclusiveOrAssign: - case EOpExclusiveOrAssign: - case EOpRightShiftAssign: - case EOpLeftShiftAssign: - if (node->getVectorSize() == 1) - return node; - break; - - case EOpAssign: - break; - - case EOpMix: - break; - - default: - return node; - } - - return addShapeConversion(type, node); -} - -// Convert the nodes' shapes to be compatible for the operation 'op'. -// -// This implements policy, it call addShapeConversion() for the mechanism. -// -// Generally, the AST represents allowed GLSL shapes, so this isn't needed -// for GLSL. Bad shapes are caught in conversion or promotion. -// -void TIntermediate::addBiShapeConversion(TOperator op, TIntermTyped*& lhsNode, TIntermTyped*& rhsNode) -{ - // some source languages don't do this - switch (source) { - case EShSourceHlsl: - break; - case EShSourceGlsl: - default: - return; - } - - // some operations don't do this - // 'break' will mean attempt bidirectional conversion - switch (op) { - case EOpMulAssign: - case EOpAssign: - case EOpAddAssign: - case EOpSubAssign: - case EOpDivAssign: - case EOpAndAssign: - case EOpInclusiveOrAssign: - case EOpExclusiveOrAssign: - case EOpRightShiftAssign: - case EOpLeftShiftAssign: - // switch to unidirectional conversion (the lhs can't change) - rhsNode = addUniShapeConversion(op, lhsNode->getType(), rhsNode); - return; - - case EOpAdd: - case EOpSub: - case EOpMul: - case EOpDiv: - // want to support vector * scalar native ops in AST and lower, not smear, similarly for - // matrix * vector, etc. - if (lhsNode->getVectorSize() == 1 || rhsNode->getVectorSize() == 1) - return; - break; - - case EOpRightShift: - case EOpLeftShift: - // can natively support the right operand being a scalar and the left a vector, - // but not the reverse - if (rhsNode->getVectorSize() == 1) - return; - break; - - case EOpLessThan: - case EOpGreaterThan: - case EOpLessThanEqual: - case EOpGreaterThanEqual: - - case EOpEqual: - case EOpNotEqual: - - case EOpLogicalAnd: - case EOpLogicalOr: - case EOpLogicalXor: - - case EOpAnd: - case EOpInclusiveOr: - case EOpExclusiveOr: - - case EOpMix: - break; - - default: - return; - } - - // Do bidirectional conversions - if (lhsNode->getType().isScalarOrVec1() || rhsNode->getType().isScalarOrVec1()) { - if (lhsNode->getType().isScalarOrVec1()) - lhsNode = addShapeConversion(rhsNode->getType(), lhsNode); - else - rhsNode = addShapeConversion(lhsNode->getType(), rhsNode); - } - lhsNode = addShapeConversion(rhsNode->getType(), lhsNode); - rhsNode = addShapeConversion(lhsNode->getType(), rhsNode); -} - -// Convert the node's shape of type for the given type, as allowed by the -// operation involved: 'op'. -// -// Generally, the AST represents allowed GLSL shapes, so this isn't needed -// for GLSL. Bad shapes are caught in conversion or promotion. -// -// Return 'node' if no conversion was done. Promotion handles final shape -// checking. -// -TIntermTyped* TIntermediate::addShapeConversion(const TType& type, TIntermTyped* node) -{ - // no conversion needed - if (node->getType() == type) - return node; - - // structures and arrays don't change shape, either to or from - if (node->getType().isStruct() || node->getType().isArray() || - type.isStruct() || type.isArray()) - return node; - - // The new node that handles the conversion - TOperator constructorOp = mapTypeToConstructorOp(type); - - // HLSL has custom semantics for scalar->mat shape conversions. - if (source == EShSourceHlsl) { - if (node->getType().isScalarOrVec1() && type.isMatrix()) { - - // HLSL semantics: the scalar (or vec1) is replicated to every component of the matrix. Left to its - // own devices, the constructor from a scalar would populate the diagonal. This forces replication - // to every matrix element. - - // Note that if the node is complex (e.g, a function call), we don't want to duplicate it here - // repeatedly, so we copy it to a temp, then use the temp. - const int matSize = type.getMatrixRows() * type.getMatrixCols(); - TIntermAggregate* rhsAggregate = new TIntermAggregate(); - - const bool isSimple = (node->getAsSymbolNode() != nullptr) || (node->getAsConstantUnion() != nullptr); - - if (!isSimple) { - assert(0); // TODO: use node replicator service when available. - } - - for (int x=0; xgetSequence().push_back(node); - - return setAggregateOperator(rhsAggregate, constructorOp, type, node->getLoc()); - } - } - - // scalar -> vector or vec1 -> vector or - // vector -> scalar or - // bigger vector -> smaller vector - if ((node->getType().isScalarOrVec1() && type.isVector()) || - (node->getType().isVector() && type.isScalar()) || - (node->isVector() && type.isVector() && node->getVectorSize() > type.getVectorSize())) - return setAggregateOperator(makeAggregate(node), constructorOp, type, node->getLoc()); - - return node; -} - -bool TIntermediate::isIntegralPromotion(TBasicType from, TBasicType to) const -{ - // integral promotions - if (to == EbtInt) { - switch(from) { - case EbtInt8: - case EbtInt16: - case EbtUint8: - case EbtUint16: - return true; - default: - break; - } - } - return false; -} - -bool TIntermediate::isFPPromotion(TBasicType from, TBasicType to) const -{ - // floating-point promotions - if (to == EbtDouble) { - switch(from) { - case EbtFloat16: - case EbtFloat: - return true; - default: - break; - } - } - return false; -} - -bool TIntermediate::isIntegralConversion(TBasicType from, TBasicType to) const -{ - switch (from) { - case EbtInt8: - switch (to) { - case EbtUint8: - case EbtInt16: - case EbtUint16: - case EbtUint: - case EbtInt64: - case EbtUint64: - return true; - default: - break; - } - break; - case EbtUint8: - switch (to) { - case EbtInt16: - case EbtUint16: - case EbtUint: - case EbtInt64: - case EbtUint64: - return true; - default: - break; - } - break; - case EbtInt16: - switch(to) { - case EbtUint16: - case EbtUint: - case EbtInt64: - case EbtUint64: - return true; - default: - break; - } - break; - case EbtUint16: - switch(to) { - case EbtUint: - case EbtInt64: - case EbtUint64: - return true; - default: - break; - } - break; - case EbtInt: - switch(to) { - case EbtUint: - return version >= 400 || (source == EShSourceHlsl); - case EbtInt64: - case EbtUint64: - return true; - default: - break; - } - break; - case EbtUint: - switch(to) { - case EbtInt64: - case EbtUint64: - return true; - default: - break; - } - break; - case EbtInt64: - if (to == EbtUint64) { - return true; - } - break; - default: - break; - } - return false; -} - -bool TIntermediate::isFPConversion(TBasicType from, TBasicType to) const -{ - if (to == EbtFloat && from == EbtFloat16) { - return true; - } else { - return false; - } -} - -bool TIntermediate::isFPIntegralConversion(TBasicType from, TBasicType to) const -{ - switch (from) { - case EbtInt8: - case EbtUint8: - case EbtInt16: - case EbtUint16: - switch (to) { - case EbtFloat16: - case EbtFloat: - case EbtDouble: - return true; - default: - break; - } - break; - case EbtInt: - case EbtUint: - switch(to) { - case EbtFloat: - case EbtDouble: - return true; - default: - break; - } - break; - case EbtInt64: - case EbtUint64: - if (to == EbtDouble) { - return true; - } - break; - - default: - break; - } - return false; -} - -// -// See if the 'from' type is allowed to be implicitly converted to the -// 'to' type. This is not about vector/array/struct, only about basic type. -// -bool TIntermediate::canImplicitlyPromote(TBasicType from, TBasicType to, TOperator op) const -{ - if (profile == EEsProfile || version == 110) - return false; - - if (from == to) - return true; - - // TODO: Move more policies into language-specific handlers. - // Some languages allow more general (or potentially, more specific) conversions under some conditions. - if (source == EShSourceHlsl) { - const bool fromConvertable = (from == EbtFloat || from == EbtDouble || from == EbtInt || from == EbtUint || from == EbtBool); - const bool toConvertable = (to == EbtFloat || to == EbtDouble || to == EbtInt || to == EbtUint || to == EbtBool); - - if (fromConvertable && toConvertable) { - switch (op) { - case EOpAndAssign: // assignments can perform arbitrary conversions - case EOpInclusiveOrAssign: // ... - case EOpExclusiveOrAssign: // ... - case EOpAssign: // ... - case EOpAddAssign: // ... - case EOpSubAssign: // ... - case EOpMulAssign: // ... - case EOpVectorTimesScalarAssign: // ... - case EOpMatrixTimesScalarAssign: // ... - case EOpDivAssign: // ... - case EOpModAssign: // ... - case EOpReturn: // function returns can also perform arbitrary conversions - case EOpFunctionCall: // conversion of a calling parameter - case EOpLogicalNot: - case EOpLogicalAnd: - case EOpLogicalOr: - case EOpLogicalXor: - case EOpConstructStruct: - return true; - default: - break; - } - } - } - - bool explicitTypesEnabled = extensionRequested(E_GL_KHX_shader_explicit_arithmetic_types) || - extensionRequested(E_GL_KHX_shader_explicit_arithmetic_types_int8) || - extensionRequested(E_GL_KHX_shader_explicit_arithmetic_types_int16) || - extensionRequested(E_GL_KHX_shader_explicit_arithmetic_types_int32) || - extensionRequested(E_GL_KHX_shader_explicit_arithmetic_types_int64) || - extensionRequested(E_GL_KHX_shader_explicit_arithmetic_types_float16) || - extensionRequested(E_GL_KHX_shader_explicit_arithmetic_types_float32) || - extensionRequested(E_GL_KHX_shader_explicit_arithmetic_types_float64); - - if (explicitTypesEnabled) { - // integral promotions - if (isIntegralPromotion(from, to)) { - return true; - } - - // floating-point promotions - if (isFPPromotion(from, to)) { - return true; - } - - // integral conversions - if (isIntegralConversion(from, to)) { - return true; - } - - // floating-point conversions - if (isFPConversion(from, to)) { - return true; - } - - // floating-integral conversions - if (isFPIntegralConversion(from, to)) { - return true; - } - - // hlsl supported conversions - if (source == EShSourceHlsl) { - if (from == EbtBool && (to == EbtInt || to == EbtUint || to == EbtFloat)) - return true; - } - } else { - switch (to) { - case EbtDouble: - switch (from) { - case EbtInt: - case EbtUint: - case EbtInt64: - case EbtUint64: -#ifdef AMD_EXTENSIONS - case EbtInt16: - case EbtUint16: -#endif - case EbtFloat: - case EbtDouble: -#ifdef AMD_EXTENSIONS - case EbtFloat16: -#endif - return true; - default: - return false; - } - case EbtFloat: - switch (from) { - case EbtInt: - case EbtUint: -#ifdef AMD_EXTENSIONS - case EbtInt16: - case EbtUint16: -#endif - case EbtFloat: -#ifdef AMD_EXTENSIONS - case EbtFloat16: -#endif - return true; - case EbtBool: - return (source == EShSourceHlsl); - default: - return false; - } - case EbtUint: - switch (from) { - case EbtInt: - return version >= 400 || (source == EShSourceHlsl); - case EbtUint: -#ifdef AMD_EXTENSIONS - case EbtInt16: - case EbtUint16: -#endif - return true; - case EbtBool: - return (source == EShSourceHlsl); - default: - return false; - } - case EbtInt: - switch (from) { - case EbtInt: -#ifdef AMD_EXTENSIONS - case EbtInt16: -#endif - return true; - case EbtBool: - return (source == EShSourceHlsl); - default: - return false; - } - case EbtUint64: - switch (from) { - case EbtInt: - case EbtUint: - case EbtInt64: - case EbtUint64: -#ifdef AMD_EXTENSIONS - case EbtInt16: - case EbtUint16: -#endif - return true; - default: - return false; - } - case EbtInt64: - switch (from) { - case EbtInt: - case EbtInt64: -#ifdef AMD_EXTENSIONS - case EbtInt16: -#endif - return true; - default: - return false; - } -#ifdef AMD_EXTENSIONS - case EbtFloat16: - switch (from) { - case EbtInt16: - case EbtUint16: - case EbtFloat16: - return true; - default: - return false; - } - case EbtUint16: - switch (from) { - case EbtInt16: - case EbtUint16: - return true; - default: - return false; - } -#endif - default: - return false; - } - } - - return false; -} - -static bool canSignedIntTypeRepresentAllUnsignedValues(TBasicType sintType, TBasicType uintType) { - switch(sintType) { - case EbtInt8: - switch(uintType) { - case EbtUint8: - case EbtUint16: - case EbtUint: - case EbtUint64: - return false; - default: - assert(false); - return false; - } - break; - case EbtInt16: - switch(uintType) { - case EbtUint8: - return true; - case EbtUint16: - case EbtUint: - case EbtUint64: - return false; - default: - assert(false); - return false; - } - break; - case EbtInt: - switch(uintType) { - case EbtUint8: - case EbtUint16: - return true; - case EbtUint: - return false; - default: - assert(false); - return false; - } - break; - case EbtInt64: - switch(uintType) { - case EbtUint8: - case EbtUint16: - case EbtUint: - return true; - case EbtUint64: - return false; - default: - assert(false); - return false; - } - break; - default: - assert(false); - return false; - } -} - - -static TBasicType getCorrespondingUnsignedType(TBasicType type) { - switch(type) { - case EbtInt8: - return EbtUint8; - case EbtInt16: - return EbtUint16; - case EbtInt: - return EbtUint; - case EbtInt64: - return EbtUint64; - default: - assert(false); - return EbtNumTypes; - } -} - -// Implements the following rules -// - If either operand has type float64_t or derived from float64_t, -// the other shall be converted to float64_t or derived type. -// - Otherwise, if either operand has type float32_t or derived from -// float32_t, the other shall be converted to float32_t or derived type. -// - Otherwise, if either operand has type float16_t or derived from -// float16_t, the other shall be converted to float16_t or derived type. -// - Otherwise, if both operands have integer types the following rules -// shall be applied to the operands: -// - If both operands have the same type, no further conversion -// is needed. -// - Otherwise, if both operands have signed integer types or both -// have unsigned integer types, the operand with the type of lesser -// integer conversion rank shall be converted to the type of the -// operand with greater rank. -// - Otherwise, if the operand that has unsigned integer type has rank -// greater than or equal to the rank of the type of the other -// operand, the operand with signed integer type shall be converted -// to the type of the operand with unsigned integer type. -// - Otherwise, if the type of the operand with signed integer type can -// represent all of the values of the type of the operand with -// unsigned integer type, the operand with unsigned integer type -// shall be converted to the type of the operand with signed -// integer type. -// - Otherwise, both operands shall be converted to the unsigned -// integer type corresponding to the type of the operand with signed -// integer type. - -std::tuple TIntermediate::getConversionDestinatonType(TBasicType type0, TBasicType type1, TOperator op) const -{ - TBasicType res0 = EbtNumTypes; - TBasicType res1 = EbtNumTypes; - - if (profile == EEsProfile || version == 110) - return std::make_tuple(res0, res1);; - - if (source == EShSourceHlsl) { - if (canImplicitlyPromote(type1, type0, op)) { - res0 = type0; - res1 = type0; - } else if (canImplicitlyPromote(type0, type1, op)) { - res0 = type1; - res1 = type1; - } - return std::make_tuple(res0, res1); - } - - if ((type0 == EbtDouble && canImplicitlyPromote(type1, EbtDouble, op)) || - (type1 == EbtDouble && canImplicitlyPromote(type0, EbtDouble, op)) ) { - res0 = EbtDouble; - res1 = EbtDouble; - } else if ((type0 == EbtFloat && canImplicitlyPromote(type1, EbtFloat, op)) || - (type1 == EbtFloat && canImplicitlyPromote(type0, EbtFloat, op)) ) { - res0 = EbtFloat; - res1 = EbtFloat; - } else if ((type0 == EbtFloat16 && canImplicitlyPromote(type1, EbtFloat16, op)) || - (type1 == EbtFloat16 && canImplicitlyPromote(type0, EbtFloat16, op)) ) { - res0 = EbtFloat16; - res1 = EbtFloat16; - } else if (isTypeInt(type0) && isTypeInt(type1) && - (canImplicitlyPromote(type0, type1, op) || canImplicitlyPromote(type1, type0, op))) { - if ((isTypeSignedInt(type0) && isTypeSignedInt(type1)) || - (isTypeUnsignedInt(type0) && isTypeUnsignedInt(type1))) { - if (getTypeRank(type0) < getTypeRank(type1)) { - res0 = type1; - res1 = type1; - } else { - res0 = type0; - res1 = type0; - } - } else if (isTypeUnsignedInt(type0) && (getTypeRank(type0) > getTypeRank(type1))) { - res0 = type0; - res1 = type0; - } else if (isTypeUnsignedInt(type1) && (getTypeRank(type1) > getTypeRank(type0))) { - res0 = type1; - res1 = type1; - } else if (isTypeSignedInt(type0)) { - if (canSignedIntTypeRepresentAllUnsignedValues(type0, type1)) { - res0 = type0; - res1 = type0; - } else { - res0 = getCorrespondingUnsignedType(type0); - res1 = getCorrespondingUnsignedType(type0); - } - } else if (isTypeSignedInt(type1)) { - if (canSignedIntTypeRepresentAllUnsignedValues(type1, type0)) { - res0 = type1; - res1 = type1; - } else { - res0 = getCorrespondingUnsignedType(type1); - res1 = getCorrespondingUnsignedType(type1); - } - } - } - - return std::make_tuple(res0, res1); -} - -// -// Given a type, find what operation would fully construct it. -// -TOperator TIntermediate::mapTypeToConstructorOp(const TType& type) const -{ - TOperator op = EOpNull; - - if (type.getQualifier().nonUniform) - return EOpConstructNonuniform; - - switch (type.getBasicType()) { - case EbtStruct: - op = EOpConstructStruct; - break; - case EbtSampler: - if (type.getSampler().combined) - op = EOpConstructTextureSampler; - break; - case EbtFloat: - if (type.isMatrix()) { - switch (type.getMatrixCols()) { - case 2: - switch (type.getMatrixRows()) { - case 2: op = EOpConstructMat2x2; break; - case 3: op = EOpConstructMat2x3; break; - case 4: op = EOpConstructMat2x4; break; - default: break; // some compilers want this - } - break; - case 3: - switch (type.getMatrixRows()) { - case 2: op = EOpConstructMat3x2; break; - case 3: op = EOpConstructMat3x3; break; - case 4: op = EOpConstructMat3x4; break; - default: break; // some compilers want this - } - break; - case 4: - switch (type.getMatrixRows()) { - case 2: op = EOpConstructMat4x2; break; - case 3: op = EOpConstructMat4x3; break; - case 4: op = EOpConstructMat4x4; break; - default: break; // some compilers want this - } - break; - default: break; // some compilers want this - } - } else { - switch(type.getVectorSize()) { - case 1: op = EOpConstructFloat; break; - case 2: op = EOpConstructVec2; break; - case 3: op = EOpConstructVec3; break; - case 4: op = EOpConstructVec4; break; - default: break; // some compilers want this - } - } - break; - case EbtDouble: - if (type.getMatrixCols()) { - switch (type.getMatrixCols()) { - case 2: - switch (type.getMatrixRows()) { - case 2: op = EOpConstructDMat2x2; break; - case 3: op = EOpConstructDMat2x3; break; - case 4: op = EOpConstructDMat2x4; break; - default: break; // some compilers want this - } - break; - case 3: - switch (type.getMatrixRows()) { - case 2: op = EOpConstructDMat3x2; break; - case 3: op = EOpConstructDMat3x3; break; - case 4: op = EOpConstructDMat3x4; break; - default: break; // some compilers want this - } - break; - case 4: - switch (type.getMatrixRows()) { - case 2: op = EOpConstructDMat4x2; break; - case 3: op = EOpConstructDMat4x3; break; - case 4: op = EOpConstructDMat4x4; break; - default: break; // some compilers want this - } - break; - } - } else { - switch(type.getVectorSize()) { - case 1: op = EOpConstructDouble; break; - case 2: op = EOpConstructDVec2; break; - case 3: op = EOpConstructDVec3; break; - case 4: op = EOpConstructDVec4; break; - default: break; // some compilers want this - } - } - break; - case EbtFloat16: - if (type.getMatrixCols()) { - switch (type.getMatrixCols()) { - case 2: - switch (type.getMatrixRows()) { - case 2: op = EOpConstructF16Mat2x2; break; - case 3: op = EOpConstructF16Mat2x3; break; - case 4: op = EOpConstructF16Mat2x4; break; - default: break; // some compilers want this - } - break; - case 3: - switch (type.getMatrixRows()) { - case 2: op = EOpConstructF16Mat3x2; break; - case 3: op = EOpConstructF16Mat3x3; break; - case 4: op = EOpConstructF16Mat3x4; break; - default: break; // some compilers want this - } - break; - case 4: - switch (type.getMatrixRows()) { - case 2: op = EOpConstructF16Mat4x2; break; - case 3: op = EOpConstructF16Mat4x3; break; - case 4: op = EOpConstructF16Mat4x4; break; - default: break; // some compilers want this - } - break; - } - } - else { - switch (type.getVectorSize()) { - case 1: op = EOpConstructFloat16; break; - case 2: op = EOpConstructF16Vec2; break; - case 3: op = EOpConstructF16Vec3; break; - case 4: op = EOpConstructF16Vec4; break; - default: break; // some compilers want this - } - } - break; - case EbtInt8: - switch(type.getVectorSize()) { - case 1: op = EOpConstructInt8; break; - case 2: op = EOpConstructI8Vec2; break; - case 3: op = EOpConstructI8Vec3; break; - case 4: op = EOpConstructI8Vec4; break; - default: break; // some compilers want this - } - break; - case EbtUint8: - switch(type.getVectorSize()) { - case 1: op = EOpConstructUint8; break; - case 2: op = EOpConstructU8Vec2; break; - case 3: op = EOpConstructU8Vec3; break; - case 4: op = EOpConstructU8Vec4; break; - default: break; // some compilers want this - } - break; - case EbtInt16: - switch(type.getVectorSize()) { - case 1: op = EOpConstructInt16; break; - case 2: op = EOpConstructI16Vec2; break; - case 3: op = EOpConstructI16Vec3; break; - case 4: op = EOpConstructI16Vec4; break; - default: break; // some compilers want this - } - break; - case EbtUint16: - switch(type.getVectorSize()) { - case 1: op = EOpConstructUint16; break; - case 2: op = EOpConstructU16Vec2; break; - case 3: op = EOpConstructU16Vec3; break; - case 4: op = EOpConstructU16Vec4; break; - default: break; // some compilers want this - } - break; - case EbtInt: - if (type.getMatrixCols()) { - switch (type.getMatrixCols()) { - case 2: - switch (type.getMatrixRows()) { - case 2: op = EOpConstructIMat2x2; break; - case 3: op = EOpConstructIMat2x3; break; - case 4: op = EOpConstructIMat2x4; break; - default: break; // some compilers want this - } - break; - case 3: - switch (type.getMatrixRows()) { - case 2: op = EOpConstructIMat3x2; break; - case 3: op = EOpConstructIMat3x3; break; - case 4: op = EOpConstructIMat3x4; break; - default: break; // some compilers want this - } - break; - case 4: - switch (type.getMatrixRows()) { - case 2: op = EOpConstructIMat4x2; break; - case 3: op = EOpConstructIMat4x3; break; - case 4: op = EOpConstructIMat4x4; break; - default: break; // some compilers want this - } - break; - } - } else { - switch(type.getVectorSize()) { - case 1: op = EOpConstructInt; break; - case 2: op = EOpConstructIVec2; break; - case 3: op = EOpConstructIVec3; break; - case 4: op = EOpConstructIVec4; break; - default: break; // some compilers want this - } - } - break; - case EbtUint: - if (type.getMatrixCols()) { - switch (type.getMatrixCols()) { - case 2: - switch (type.getMatrixRows()) { - case 2: op = EOpConstructUMat2x2; break; - case 3: op = EOpConstructUMat2x3; break; - case 4: op = EOpConstructUMat2x4; break; - default: break; // some compilers want this - } - break; - case 3: - switch (type.getMatrixRows()) { - case 2: op = EOpConstructUMat3x2; break; - case 3: op = EOpConstructUMat3x3; break; - case 4: op = EOpConstructUMat3x4; break; - default: break; // some compilers want this - } - break; - case 4: - switch (type.getMatrixRows()) { - case 2: op = EOpConstructUMat4x2; break; - case 3: op = EOpConstructUMat4x3; break; - case 4: op = EOpConstructUMat4x4; break; - default: break; // some compilers want this - } - break; - } - } else { - switch(type.getVectorSize()) { - case 1: op = EOpConstructUint; break; - case 2: op = EOpConstructUVec2; break; - case 3: op = EOpConstructUVec3; break; - case 4: op = EOpConstructUVec4; break; - default: break; // some compilers want this - } - } - break; - case EbtInt64: - switch(type.getVectorSize()) { - case 1: op = EOpConstructInt64; break; - case 2: op = EOpConstructI64Vec2; break; - case 3: op = EOpConstructI64Vec3; break; - case 4: op = EOpConstructI64Vec4; break; - default: break; // some compilers want this - } - break; - case EbtUint64: - switch(type.getVectorSize()) { - case 1: op = EOpConstructUint64; break; - case 2: op = EOpConstructU64Vec2; break; - case 3: op = EOpConstructU64Vec3; break; - case 4: op = EOpConstructU64Vec4; break; - default: break; // some compilers want this - } - break; - case EbtBool: - if (type.getMatrixCols()) { - switch (type.getMatrixCols()) { - case 2: - switch (type.getMatrixRows()) { - case 2: op = EOpConstructBMat2x2; break; - case 3: op = EOpConstructBMat2x3; break; - case 4: op = EOpConstructBMat2x4; break; - default: break; // some compilers want this - } - break; - case 3: - switch (type.getMatrixRows()) { - case 2: op = EOpConstructBMat3x2; break; - case 3: op = EOpConstructBMat3x3; break; - case 4: op = EOpConstructBMat3x4; break; - default: break; // some compilers want this - } - break; - case 4: - switch (type.getMatrixRows()) { - case 2: op = EOpConstructBMat4x2; break; - case 3: op = EOpConstructBMat4x3; break; - case 4: op = EOpConstructBMat4x4; break; - default: break; // some compilers want this - } - break; - } - } else { - switch(type.getVectorSize()) { - case 1: op = EOpConstructBool; break; - case 2: op = EOpConstructBVec2; break; - case 3: op = EOpConstructBVec3; break; - case 4: op = EOpConstructBVec4; break; - default: break; // some compilers want this - } - } - break; - default: - break; - } - - return op; -} - -// -// Safe way to combine two nodes into an aggregate. Works with null pointers, -// a node that's not a aggregate yet, etc. -// -// Returns the resulting aggregate, unless nullptr was passed in for -// both existing nodes. -// -TIntermAggregate* TIntermediate::growAggregate(TIntermNode* left, TIntermNode* right) -{ - if (left == nullptr && right == nullptr) - return nullptr; - - TIntermAggregate* aggNode = nullptr; - if (left != nullptr) - aggNode = left->getAsAggregate(); - if (aggNode == nullptr || aggNode->getOp() != EOpNull) { - aggNode = new TIntermAggregate; - if (left != nullptr) - aggNode->getSequence().push_back(left); - } - - if (right != nullptr) - aggNode->getSequence().push_back(right); - - return aggNode; -} - -TIntermAggregate* TIntermediate::growAggregate(TIntermNode* left, TIntermNode* right, const TSourceLoc& loc) -{ - TIntermAggregate* aggNode = growAggregate(left, right); - if (aggNode) - aggNode->setLoc(loc); - - return aggNode; -} - -// -// Turn an existing node into an aggregate. -// -// Returns an aggregate, unless nullptr was passed in for the existing node. -// -TIntermAggregate* TIntermediate::makeAggregate(TIntermNode* node) -{ - if (node == nullptr) - return nullptr; - - TIntermAggregate* aggNode = new TIntermAggregate; - aggNode->getSequence().push_back(node); - aggNode->setLoc(node->getLoc()); - - return aggNode; -} - -TIntermAggregate* TIntermediate::makeAggregate(TIntermNode* node, const TSourceLoc& loc) -{ - if (node == nullptr) - return nullptr; - - TIntermAggregate* aggNode = new TIntermAggregate; - aggNode->getSequence().push_back(node); - aggNode->setLoc(loc); - - return aggNode; -} - -// -// Make an aggregate with an empty sequence. -// -TIntermAggregate* TIntermediate::makeAggregate(const TSourceLoc& loc) -{ - TIntermAggregate* aggNode = new TIntermAggregate; - aggNode->setLoc(loc); - - return aggNode; -} - -// -// For "if" test nodes. There are three children; a condition, -// a true path, and a false path. The two paths are in the -// nodePair. -// -// Returns the selection node created. -// -TIntermSelection* TIntermediate::addSelection(TIntermTyped* cond, TIntermNodePair nodePair, const TSourceLoc& loc) -{ - // - // Don't prune the false path for compile-time constants; it's needed - // for static access analysis. - // - - TIntermSelection* node = new TIntermSelection(cond, nodePair.node1, nodePair.node2); - node->setLoc(loc); - - return node; -} - -TIntermTyped* TIntermediate::addComma(TIntermTyped* left, TIntermTyped* right, const TSourceLoc& loc) -{ - // However, the lowest precedence operators of the sequence operator ( , ) and the assignment operators - // ... are not included in the operators that can create a constant expression. - // - // if (left->getType().getQualifier().storage == EvqConst && - // right->getType().getQualifier().storage == EvqConst) { - - // return right; - //} - - TIntermTyped *commaAggregate = growAggregate(left, right, loc); - commaAggregate->getAsAggregate()->setOperator(EOpComma); - commaAggregate->setType(right->getType()); - commaAggregate->getWritableType().getQualifier().makeTemporary(); - - return commaAggregate; -} - -TIntermTyped* TIntermediate::addMethod(TIntermTyped* object, const TType& type, const TString* name, const TSourceLoc& loc) -{ - TIntermMethod* method = new TIntermMethod(object, type, *name); - method->setLoc(loc); - - return method; -} - -// -// For "?:" test nodes. There are three children; a condition, -// a true path, and a false path. The two paths are specified -// as separate parameters. For vector 'cond', the true and false -// are not paths, but vectors to mix. -// -// Specialization constant operations include -// - The ternary operator ( ? : ) -// -// Returns the selection node created, or nullptr if one could not be. -// -TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, - const TSourceLoc& loc) -{ - // If it's void, go to the if-then-else selection() - if (trueBlock->getBasicType() == EbtVoid && falseBlock->getBasicType() == EbtVoid) { - TIntermNodePair pair = { trueBlock, falseBlock }; - TIntermSelection* selection = addSelection(cond, pair, loc); - if (getSource() == EShSourceHlsl) - selection->setNoShortCircuit(); - - return selection; - } - - // - // Get compatible types. - // - auto children = addConversion(EOpSequence, trueBlock, falseBlock); - trueBlock = std::get<0>(children); - falseBlock = std::get<1>(children); - - if (trueBlock == nullptr || falseBlock == nullptr) - return nullptr; - - // Handle a vector condition as a mix - if (!cond->getType().isScalarOrVec1()) { - TType targetVectorType(trueBlock->getType().getBasicType(), EvqTemporary, - cond->getType().getVectorSize()); - // smear true/false operands as needed - trueBlock = addUniShapeConversion(EOpMix, targetVectorType, trueBlock); - falseBlock = addUniShapeConversion(EOpMix, targetVectorType, falseBlock); - - // After conversion, types have to match. - if (falseBlock->getType() != trueBlock->getType()) - return nullptr; - - // make the mix operation - TIntermAggregate* mix = makeAggregate(loc); - mix = growAggregate(mix, falseBlock); - mix = growAggregate(mix, trueBlock); - mix = growAggregate(mix, cond); - mix->setType(targetVectorType); - mix->setOp(EOpMix); - - return mix; - } - - // Now have a scalar condition... - - // Convert true and false expressions to matching types - addBiShapeConversion(EOpMix, trueBlock, falseBlock); - - // After conversion, types have to match. - if (falseBlock->getType() != trueBlock->getType()) - return nullptr; - - // Eliminate the selection when the condition is a scalar and all operands are constant. - if (cond->getAsConstantUnion() && trueBlock->getAsConstantUnion() && falseBlock->getAsConstantUnion()) { - if (cond->getAsConstantUnion()->getConstArray()[0].getBConst()) - return trueBlock; - else - return falseBlock; - } - - // - // Make a selection node. - // - TIntermSelection* node = new TIntermSelection(cond, trueBlock, falseBlock, trueBlock->getType()); - node->setLoc(loc); - node->getQualifier().precision = std::max(trueBlock->getQualifier().precision, falseBlock->getQualifier().precision); - - if ((cond->getQualifier().isConstant() && specConstantPropagates(*trueBlock, *falseBlock)) || - (cond->getQualifier().isSpecConstant() && trueBlock->getQualifier().isConstant() && - falseBlock->getQualifier().isConstant())) - node->getQualifier().makeSpecConstant(); - else - node->getQualifier().makeTemporary(); - - if (getSource() == EShSourceHlsl) - node->setNoShortCircuit(); - - return node; -} - -// -// Constant terminal nodes. Has a union that contains bool, float or int constants -// -// Returns the constant union node created. -// - -TIntermConstantUnion* TIntermediate::addConstantUnion(const TConstUnionArray& unionArray, const TType& t, const TSourceLoc& loc, bool literal) const -{ - TIntermConstantUnion* node = new TIntermConstantUnion(unionArray, t); - node->getQualifier().storage = EvqConst; - node->setLoc(loc); - if (literal) - node->setLiteral(); - - return node; -} -TIntermConstantUnion* TIntermediate::addConstantUnion(signed char i8, const TSourceLoc& loc, bool literal) const -{ - TConstUnionArray unionArray(1); - unionArray[0].setI8Const(i8); - - return addConstantUnion(unionArray, TType(EbtInt8, EvqConst), loc, literal); -} - -TIntermConstantUnion* TIntermediate::addConstantUnion(unsigned char u8, const TSourceLoc& loc, bool literal) const -{ - TConstUnionArray unionArray(1); - unionArray[0].setUConst(u8); - - return addConstantUnion(unionArray, TType(EbtUint8, EvqConst), loc, literal); -} - -TIntermConstantUnion* TIntermediate::addConstantUnion(signed short i16, const TSourceLoc& loc, bool literal) const -{ - TConstUnionArray unionArray(1); - unionArray[0].setI16Const(i16); - - return addConstantUnion(unionArray, TType(EbtInt16, EvqConst), loc, literal); -} - -TIntermConstantUnion* TIntermediate::addConstantUnion(unsigned short u16, const TSourceLoc& loc, bool literal) const -{ - TConstUnionArray unionArray(1); - unionArray[0].setU16Const(u16); - - return addConstantUnion(unionArray, TType(EbtUint16, EvqConst), loc, literal); -} - -TIntermConstantUnion* TIntermediate::addConstantUnion(int i, const TSourceLoc& loc, bool literal) const -{ - TConstUnionArray unionArray(1); - unionArray[0].setIConst(i); - - return addConstantUnion(unionArray, TType(EbtInt, EvqConst), loc, literal); -} - -TIntermConstantUnion* TIntermediate::addConstantUnion(unsigned int u, const TSourceLoc& loc, bool literal) const -{ - TConstUnionArray unionArray(1); - unionArray[0].setUConst(u); - - return addConstantUnion(unionArray, TType(EbtUint, EvqConst), loc, literal); -} - -TIntermConstantUnion* TIntermediate::addConstantUnion(long long i64, const TSourceLoc& loc, bool literal) const -{ - TConstUnionArray unionArray(1); - unionArray[0].setI64Const(i64); - - return addConstantUnion(unionArray, TType(EbtInt64, EvqConst), loc, literal); -} - -TIntermConstantUnion* TIntermediate::addConstantUnion(unsigned long long u64, const TSourceLoc& loc, bool literal) const -{ - TConstUnionArray unionArray(1); - unionArray[0].setU64Const(u64); - - return addConstantUnion(unionArray, TType(EbtUint64, EvqConst), loc, literal); -} - -TIntermConstantUnion* TIntermediate::addConstantUnion(bool b, const TSourceLoc& loc, bool literal) const -{ - TConstUnionArray unionArray(1); - unionArray[0].setBConst(b); - - return addConstantUnion(unionArray, TType(EbtBool, EvqConst), loc, literal); -} - -TIntermConstantUnion* TIntermediate::addConstantUnion(double d, TBasicType baseType, const TSourceLoc& loc, bool literal) const -{ - assert(baseType == EbtFloat || baseType == EbtDouble || baseType == EbtFloat16); - - TConstUnionArray unionArray(1); - unionArray[0].setDConst(d); - - return addConstantUnion(unionArray, TType(baseType, EvqConst), loc, literal); -} - -TIntermConstantUnion* TIntermediate::addConstantUnion(const TString* s, const TSourceLoc& loc, bool literal) const -{ - TConstUnionArray unionArray(1); - unionArray[0].setSConst(s); - - return addConstantUnion(unionArray, TType(EbtString, EvqConst), loc, literal); -} - -// Put vector swizzle selectors onto the given sequence -void TIntermediate::pushSelector(TIntermSequence& sequence, const TVectorSelector& selector, const TSourceLoc& loc) -{ - TIntermConstantUnion* constIntNode = addConstantUnion(selector, loc); - sequence.push_back(constIntNode); -} - -// Put matrix swizzle selectors onto the given sequence -void TIntermediate::pushSelector(TIntermSequence& sequence, const TMatrixSelector& selector, const TSourceLoc& loc) -{ - TIntermConstantUnion* constIntNode = addConstantUnion(selector.coord1, loc); - sequence.push_back(constIntNode); - constIntNode = addConstantUnion(selector.coord2, loc); - sequence.push_back(constIntNode); -} - -// Make an aggregate node that has a sequence of all selectors. -template TIntermTyped* TIntermediate::addSwizzle(TSwizzleSelectors& selector, const TSourceLoc& loc); -template TIntermTyped* TIntermediate::addSwizzle(TSwizzleSelectors& selector, const TSourceLoc& loc); -template -TIntermTyped* TIntermediate::addSwizzle(TSwizzleSelectors& selector, const TSourceLoc& loc) -{ - TIntermAggregate* node = new TIntermAggregate(EOpSequence); - - node->setLoc(loc); - TIntermSequence &sequenceVector = node->getSequence(); - - for (int i = 0; i < selector.size(); i++) - pushSelector(sequenceVector, selector[i], loc); - - return node; -} - -// -// Follow the left branches down to the root of an l-value -// expression (just "." and []). -// -// Return the base of the l-value (where following indexing quits working). -// Return nullptr if a chain following dereferences cannot be followed. -// -// 'swizzleOkay' says whether or not it is okay to consider a swizzle -// a valid part of the dereference chain. -// -const TIntermTyped* TIntermediate::findLValueBase(const TIntermTyped* node, bool swizzleOkay) -{ - do { - const TIntermBinary* binary = node->getAsBinaryNode(); - if (binary == nullptr) - return node; - TOperator op = binary->getOp(); - if (op != EOpIndexDirect && op != EOpIndexIndirect && op != EOpIndexDirectStruct && op != EOpVectorSwizzle && op != EOpMatrixSwizzle) - return nullptr; - if (! swizzleOkay) { - if (op == EOpVectorSwizzle || op == EOpMatrixSwizzle) - return nullptr; - if ((op == EOpIndexDirect || op == EOpIndexIndirect) && - (binary->getLeft()->getType().isVector() || binary->getLeft()->getType().isScalar()) && - ! binary->getLeft()->getType().isArray()) - return nullptr; - } - node = node->getAsBinaryNode()->getLeft(); - } while (true); -} - -// -// Create while and do-while loop nodes. -// -TIntermLoop* TIntermediate::addLoop(TIntermNode* body, TIntermTyped* test, TIntermTyped* terminal, bool testFirst, - const TSourceLoc& loc) -{ - TIntermLoop* node = new TIntermLoop(body, test, terminal, testFirst); - node->setLoc(loc); - - return node; -} - -// -// Create a for-loop sequence. -// -TIntermAggregate* TIntermediate::addForLoop(TIntermNode* body, TIntermNode* initializer, TIntermTyped* test, - TIntermTyped* terminal, bool testFirst, const TSourceLoc& loc, TIntermLoop*& node) -{ - node = new TIntermLoop(body, test, terminal, testFirst); - node->setLoc(loc); - - // make a sequence of the initializer and statement, but try to reuse the - // aggregate already created for whatever is in the initializer, if there is one - TIntermAggregate* loopSequence = (initializer == nullptr || - initializer->getAsAggregate() == nullptr) ? makeAggregate(initializer, loc) - : initializer->getAsAggregate(); - if (loopSequence != nullptr && loopSequence->getOp() == EOpSequence) - loopSequence->setOp(EOpNull); - loopSequence = growAggregate(loopSequence, node); - loopSequence->setOperator(EOpSequence); - - return loopSequence; -} - -// -// Add branches. -// -TIntermBranch* TIntermediate::addBranch(TOperator branchOp, const TSourceLoc& loc) -{ - return addBranch(branchOp, nullptr, loc); -} - -TIntermBranch* TIntermediate::addBranch(TOperator branchOp, TIntermTyped* expression, const TSourceLoc& loc) -{ - TIntermBranch* node = new TIntermBranch(branchOp, expression); - node->setLoc(loc); - - return node; -} - -// -// This is to be executed after the final root is put on top by the parsing -// process. -// -bool TIntermediate::postProcess(TIntermNode* root, EShLanguage /*language*/) -{ - if (root == nullptr) - return true; - - // Finish off the top-level sequence - TIntermAggregate* aggRoot = root->getAsAggregate(); - if (aggRoot && aggRoot->getOp() == EOpNull) - aggRoot->setOperator(EOpSequence); - - // Propagate 'noContraction' label in backward from 'precise' variables. - glslang::PropagateNoContraction(*this); - - switch (textureSamplerTransformMode) { - case EShTexSampTransKeep: - break; - case EShTexSampTransUpgradeTextureRemoveSampler: - performTextureUpgradeAndSamplerRemovalTransformation(root); - break; - } - - return true; -} - -void TIntermediate::addSymbolLinkageNodes(TIntermAggregate*& linkage, EShLanguage language, TSymbolTable& symbolTable) -{ - // Add top-level nodes for declarations that must be checked cross - // compilation unit by a linker, yet might not have been referenced - // by the AST. - // - // Almost entirely, translation of symbols is driven by what's present - // in the AST traversal, not by translating the symbol table. - // - // However, there are some special cases: - // - From the specification: "Special built-in inputs gl_VertexID and - // gl_InstanceID are also considered active vertex attributes." - // - Linker-based type mismatch error reporting needs to see all - // uniforms/ins/outs variables and blocks. - // - ftransform() can make gl_Vertex and gl_ModelViewProjectionMatrix active. - // - - // if (ftransformUsed) { - // TODO: 1.1 lowering functionality: track ftransform() usage - // addSymbolLinkageNode(root, symbolTable, "gl_Vertex"); - // addSymbolLinkageNode(root, symbolTable, "gl_ModelViewProjectionMatrix"); - //} - - if (language == EShLangVertex) { - // the names won't be found in the symbol table unless the versions are right, - // so version logic does not need to be repeated here - addSymbolLinkageNode(linkage, symbolTable, "gl_VertexID"); - addSymbolLinkageNode(linkage, symbolTable, "gl_InstanceID"); - } - - // Add a child to the root node for the linker objects - linkage->setOperator(EOpLinkerObjects); - treeRoot = growAggregate(treeRoot, linkage); -} - -// -// Add the given name or symbol to the list of nodes at the end of the tree used -// for link-time checking and external linkage. -// - -void TIntermediate::addSymbolLinkageNode(TIntermAggregate*& linkage, TSymbolTable& symbolTable, const TString& name) -{ - TSymbol* symbol = symbolTable.find(name); - if (symbol) - addSymbolLinkageNode(linkage, *symbol->getAsVariable()); -} - -void TIntermediate::addSymbolLinkageNode(TIntermAggregate*& linkage, const TSymbol& symbol) -{ - const TVariable* variable = symbol.getAsVariable(); - if (! variable) { - // This must be a member of an anonymous block, and we need to add the whole block - const TAnonMember* anon = symbol.getAsAnonMember(); - variable = &anon->getAnonContainer(); - } - TIntermSymbol* node = addSymbol(*variable); - linkage = growAggregate(linkage, node); -} - -// -// Add a caller->callee relationship to the call graph. -// Assumes the strings are unique per signature. -// -void TIntermediate::addToCallGraph(TInfoSink& /*infoSink*/, const TString& caller, const TString& callee) -{ - // Duplicates are okay, but faster to not keep them, and they come grouped by caller, - // as long as new ones are push on the same end we check on for duplicates - for (TGraph::const_iterator call = callGraph.begin(); call != callGraph.end(); ++call) { - if (call->caller != caller) - break; - if (call->callee == callee) - return; - } - - callGraph.push_front(TCall(caller, callee)); -} - -// -// This deletes the tree. -// -void TIntermediate::removeTree() -{ - if (treeRoot) - RemoveAllTreeNodes(treeRoot); -} - -// -// Implement the part of KHR_vulkan_glsl that lists the set of operations -// that can result in a specialization constant operation. -// -// "5.x Specialization Constant Operations" -// -// Only some operations discussed in this section may be applied to a -// specialization constant and still yield a result that is as -// specialization constant. The operations allowed are listed below. -// When a specialization constant is operated on with one of these -// operators and with another constant or specialization constant, the -// result is implicitly a specialization constant. -// -// - int(), uint(), and bool() constructors for type conversions -// from any of the following types to any of the following types: -// * int -// * uint -// * bool -// - vector versions of the above conversion constructors -// - allowed implicit conversions of the above -// - swizzles (e.g., foo.yx) -// - The following when applied to integer or unsigned integer types: -// * unary negative ( - ) -// * binary operations ( + , - , * , / , % ) -// * shift ( <<, >> ) -// * bitwise operations ( & , | , ^ ) -// - The following when applied to integer or unsigned integer scalar types: -// * comparison ( == , != , > , >= , < , <= ) -// - The following when applied to the Boolean scalar type: -// * not ( ! ) -// * logical operations ( && , || , ^^ ) -// * comparison ( == , != )" -// -// This function just handles binary and unary nodes. Construction -// rules are handled in construction paths that are not covered by the unary -// and binary paths, while required conversions will still show up here -// as unary converters in the from a construction operator. -// -bool TIntermediate::isSpecializationOperation(const TIntermOperator& node) const -{ - // The operations resulting in floating point are quite limited - // (However, some floating-point operations result in bool, like ">", - // so are handled later.) - if (node.getType().isFloatingDomain()) { - switch (node.getOp()) { - case EOpIndexDirect: - case EOpIndexIndirect: - case EOpIndexDirectStruct: - case EOpVectorSwizzle: - case EOpConvFloatToDouble: - case EOpConvDoubleToFloat: - case EOpConvFloat16ToFloat: - case EOpConvFloatToFloat16: - case EOpConvFloat16ToDouble: - case EOpConvDoubleToFloat16: - return true; - default: - return false; - } - } - - // Check for floating-point arguments - if (const TIntermBinary* bin = node.getAsBinaryNode()) - if (bin->getLeft() ->getType().isFloatingDomain() || - bin->getRight()->getType().isFloatingDomain()) - return false; - - // So, for now, we can assume everything left is non-floating-point... - - // Now check for integer/bool-based operations - switch (node.getOp()) { - - // dereference/swizzle - case EOpIndexDirect: - case EOpIndexIndirect: - case EOpIndexDirectStruct: - case EOpVectorSwizzle: - - // (u)int* -> bool - case EOpConvInt8ToBool: - case EOpConvInt16ToBool: - case EOpConvIntToBool: - case EOpConvInt64ToBool: - case EOpConvUint8ToBool: - case EOpConvUint16ToBool: - case EOpConvUintToBool: - case EOpConvUint64ToBool: - - // bool -> (u)int* - case EOpConvBoolToInt8: - case EOpConvBoolToInt16: - case EOpConvBoolToInt: - case EOpConvBoolToInt64: - case EOpConvBoolToUint8: - case EOpConvBoolToUint16: - case EOpConvBoolToUint: - case EOpConvBoolToUint64: - - // int8_t -> (u)int* - case EOpConvInt8ToInt16: - case EOpConvInt8ToInt: - case EOpConvInt8ToInt64: - case EOpConvInt8ToUint8: - case EOpConvInt8ToUint16: - case EOpConvInt8ToUint: - case EOpConvInt8ToUint64: - - // int16_t -> (u)int* - case EOpConvInt16ToInt8: - case EOpConvInt16ToInt: - case EOpConvInt16ToInt64: - case EOpConvInt16ToUint8: - case EOpConvInt16ToUint16: - case EOpConvInt16ToUint: - case EOpConvInt16ToUint64: - - // int32_t -> (u)int* - case EOpConvIntToInt8: - case EOpConvIntToInt16: - case EOpConvIntToInt64: - case EOpConvIntToUint8: - case EOpConvIntToUint16: - case EOpConvIntToUint: - case EOpConvIntToUint64: - - // int64_t -> (u)int* - case EOpConvInt64ToInt8: - case EOpConvInt64ToInt16: - case EOpConvInt64ToInt: - case EOpConvInt64ToUint8: - case EOpConvInt64ToUint16: - case EOpConvInt64ToUint: - case EOpConvInt64ToUint64: - - // uint8_t -> (u)int* - case EOpConvUint8ToInt8: - case EOpConvUint8ToInt16: - case EOpConvUint8ToInt: - case EOpConvUint8ToInt64: - case EOpConvUint8ToUint16: - case EOpConvUint8ToUint: - case EOpConvUint8ToUint64: - - // uint16_t -> (u)int* - case EOpConvUint16ToInt8: - case EOpConvUint16ToInt16: - case EOpConvUint16ToInt: - case EOpConvUint16ToInt64: - case EOpConvUint16ToUint8: - case EOpConvUint16ToUint: - case EOpConvUint16ToUint64: - - // uint32_t -> (u)int* - case EOpConvUintToInt8: - case EOpConvUintToInt16: - case EOpConvUintToInt: - case EOpConvUintToInt64: - case EOpConvUintToUint8: - case EOpConvUintToUint16: - case EOpConvUintToUint64: - - // uint64_t -> (u)int* - case EOpConvUint64ToInt8: - case EOpConvUint64ToInt16: - case EOpConvUint64ToInt: - case EOpConvUint64ToInt64: - case EOpConvUint64ToUint8: - case EOpConvUint64ToUint16: - case EOpConvUint64ToUint: - - // unary operations - case EOpNegative: - case EOpLogicalNot: - case EOpBitwiseNot: - - // binary operations - case EOpAdd: - case EOpSub: - case EOpMul: - case EOpVectorTimesScalar: - case EOpDiv: - case EOpMod: - case EOpRightShift: - case EOpLeftShift: - case EOpAnd: - case EOpInclusiveOr: - case EOpExclusiveOr: - case EOpLogicalOr: - case EOpLogicalXor: - case EOpLogicalAnd: - case EOpEqual: - case EOpNotEqual: - case EOpLessThan: - case EOpGreaterThan: - case EOpLessThanEqual: - case EOpGreaterThanEqual: - return true; - default: - return false; - } -} - -// Is the operation one that must propagate nonuniform? -bool TIntermediate::isNonuniformPropagating(TOperator op) const -{ - // "* All Operators in Section 5.1 (Operators), except for assignment, - // arithmetic assignment, and sequence - // * Component selection in Section 5.5 - // * Matrix components in Section 5.6 - // * Structure and Array Operations in Section 5.7, except for the length - // method." - switch (op) { - case EOpPostIncrement: - case EOpPostDecrement: - case EOpPreIncrement: - case EOpPreDecrement: - - case EOpNegative: - case EOpLogicalNot: - case EOpVectorLogicalNot: - case EOpBitwiseNot: - - case EOpAdd: - case EOpSub: - case EOpMul: - case EOpDiv: - case EOpMod: - case EOpRightShift: - case EOpLeftShift: - case EOpAnd: - case EOpInclusiveOr: - case EOpExclusiveOr: - case EOpEqual: - case EOpNotEqual: - case EOpLessThan: - case EOpGreaterThan: - case EOpLessThanEqual: - case EOpGreaterThanEqual: - case EOpVectorTimesScalar: - case EOpVectorTimesMatrix: - case EOpMatrixTimesVector: - case EOpMatrixTimesScalar: - - case EOpLogicalOr: - case EOpLogicalXor: - case EOpLogicalAnd: - - case EOpIndexDirect: - case EOpIndexIndirect: - case EOpIndexDirectStruct: - case EOpVectorSwizzle: - return true; - - default: - break; - } - - return false; -} - -//////////////////////////////////////////////////////////////// -// -// Member functions of the nodes used for building the tree. -// -//////////////////////////////////////////////////////////////// - -// -// Say whether or not an operation node changes the value of a variable. -// -// Returns true if state is modified. -// -bool TIntermOperator::modifiesState() const -{ - switch (op) { - case EOpPostIncrement: - case EOpPostDecrement: - case EOpPreIncrement: - case EOpPreDecrement: - case EOpAssign: - case EOpAddAssign: - case EOpSubAssign: - case EOpMulAssign: - case EOpVectorTimesMatrixAssign: - case EOpVectorTimesScalarAssign: - case EOpMatrixTimesScalarAssign: - case EOpMatrixTimesMatrixAssign: - case EOpDivAssign: - case EOpModAssign: - case EOpAndAssign: - case EOpInclusiveOrAssign: - case EOpExclusiveOrAssign: - case EOpLeftShiftAssign: - case EOpRightShiftAssign: - return true; - default: - return false; - } -} - -// -// returns true if the operator is for one of the constructors -// -bool TIntermOperator::isConstructor() const -{ - return op > EOpConstructGuardStart && op < EOpConstructGuardEnd; -} - -// -// Make sure the type of an operator is appropriate for its -// combination of operation and operand type. This will invoke -// promoteUnary, promoteBinary, etc as needed. -// -// Returns false if nothing makes sense. -// -bool TIntermediate::promote(TIntermOperator* node) -{ - if (node == nullptr) - return false; - - if (node->getAsUnaryNode()) - return promoteUnary(*node->getAsUnaryNode()); - - if (node->getAsBinaryNode()) - return promoteBinary(*node->getAsBinaryNode()); - - if (node->getAsAggregate()) - return promoteAggregate(*node->getAsAggregate()); - - return false; -} - -// -// See TIntermediate::promote -// -bool TIntermediate::promoteUnary(TIntermUnary& node) -{ - const TOperator op = node.getOp(); - TIntermTyped* operand = node.getOperand(); - - switch (op) { - case EOpLogicalNot: - // Convert operand to a boolean type - if (operand->getBasicType() != EbtBool) { - // Add constructor to boolean type. If that fails, we can't do it, so return false. - TIntermTyped* converted = addConversion(op, TType(EbtBool), operand); - if (converted == nullptr) - return false; - - // Use the result of converting the node to a bool. - node.setOperand(operand = converted); // also updates stack variable - } - break; - case EOpBitwiseNot: - if (!isTypeInt(operand->getBasicType())) - return false; - break; - case EOpNegative: - case EOpPostIncrement: - case EOpPostDecrement: - case EOpPreIncrement: - case EOpPreDecrement: - if (!isTypeInt(operand->getBasicType()) && - operand->getBasicType() != EbtFloat && - operand->getBasicType() != EbtFloat16 && - operand->getBasicType() != EbtDouble) - - return false; - break; - - default: - if (operand->getBasicType() != EbtFloat) - - return false; - } - - node.setType(operand->getType()); - node.getWritableType().getQualifier().makeTemporary(); - - return true; -} - -void TIntermUnary::updatePrecision() -{ - if (getBasicType() == EbtInt || getBasicType() == EbtUint || getBasicType() == EbtFloat || getBasicType() == EbtFloat16) { - if (operand->getQualifier().precision > getQualifier().precision) - getQualifier().precision = operand->getQualifier().precision; - } -} - -// -// See TIntermediate::promote -// -bool TIntermediate::promoteBinary(TIntermBinary& node) -{ - TOperator op = node.getOp(); - TIntermTyped* left = node.getLeft(); - TIntermTyped* right = node.getRight(); - - // Arrays and structures have to be exact matches. - if ((left->isArray() || right->isArray() || left->getBasicType() == EbtStruct || right->getBasicType() == EbtStruct) - && left->getType() != right->getType()) - return false; - - // Base assumption: just make the type the same as the left - // operand. Only deviations from this will be coded. - node.setType(left->getType()); - node.getWritableType().getQualifier().clear(); - - // Composite and opaque types don't having pending operator changes, e.g., - // array, structure, and samplers. Just establish final type and correctness. - if (left->isArray() || left->getBasicType() == EbtStruct || left->getBasicType() == EbtSampler) { - switch (op) { - case EOpEqual: - case EOpNotEqual: - if (left->getBasicType() == EbtSampler) { - // can't compare samplers - return false; - } else { - // Promote to conditional - node.setType(TType(EbtBool)); - } - - return true; - - case EOpAssign: - // Keep type from above - - return true; - - default: - return false; - } - } - - // - // We now have only scalars, vectors, and matrices to worry about. - // - - // HLSL implicitly promotes bool -> int for numeric operations. - // (Implicit conversions to make the operands match each other's types were already done.) - if (getSource() == EShSourceHlsl && - (left->getBasicType() == EbtBool || right->getBasicType() == EbtBool)) { - switch (op) { - case EOpLessThan: - case EOpGreaterThan: - case EOpLessThanEqual: - case EOpGreaterThanEqual: - - case EOpRightShift: - case EOpLeftShift: - - case EOpMod: - - case EOpAnd: - case EOpInclusiveOr: - case EOpExclusiveOr: - - case EOpAdd: - case EOpSub: - case EOpDiv: - case EOpMul: - if (left->getBasicType() == EbtBool) - left = createConversion(EbtInt, left); - if (right->getBasicType() == EbtBool) - right = createConversion(EbtInt, right); - if (left == nullptr || right == nullptr) - return false; - node.setLeft(left); - node.setRight(right); - - // Update the original base assumption on result type.. - node.setType(left->getType()); - node.getWritableType().getQualifier().clear(); - - break; - - default: - break; - } - } - - // Do general type checks against individual operands (comparing left and right is coming up, checking mixed shapes after that) - switch (op) { - case EOpLessThan: - case EOpGreaterThan: - case EOpLessThanEqual: - case EOpGreaterThanEqual: - // Relational comparisons need numeric types and will promote to scalar Boolean. - if (left->getBasicType() == EbtBool) - return false; - - node.setType(TType(EbtBool, EvqTemporary, left->getVectorSize())); - break; - - case EOpEqual: - case EOpNotEqual: - if (getSource() == EShSourceHlsl) { - const int resultWidth = std::max(left->getVectorSize(), right->getVectorSize()); - - // In HLSL, == or != on vectors means component-wise comparison. - if (resultWidth > 1) { - op = (op == EOpEqual) ? EOpVectorEqual : EOpVectorNotEqual; - node.setOp(op); - } - - node.setType(TType(EbtBool, EvqTemporary, resultWidth)); - } else { - // All the above comparisons result in a bool (but not the vector compares) - node.setType(TType(EbtBool)); - } - break; - - case EOpLogicalAnd: - case EOpLogicalOr: - case EOpLogicalXor: - // logical ops operate only on Booleans or vectors of Booleans. - if (left->getBasicType() != EbtBool || left->isMatrix()) - return false; - - if (getSource() == EShSourceGlsl) { - // logical ops operate only on scalar Booleans and will promote to scalar Boolean. - if (left->isVector()) - return false; - } - - node.setType(TType(EbtBool, EvqTemporary, left->getVectorSize())); - break; - - case EOpRightShift: - case EOpLeftShift: - case EOpRightShiftAssign: - case EOpLeftShiftAssign: - - case EOpMod: - case EOpModAssign: - - case EOpAnd: - case EOpInclusiveOr: - case EOpExclusiveOr: - case EOpAndAssign: - case EOpInclusiveOrAssign: - case EOpExclusiveOrAssign: - if (getSource() == EShSourceHlsl) - break; - - // Check for integer-only operands. - if (!isTypeInt(left->getBasicType()) && !isTypeInt(right->getBasicType())) - return false; - if (left->isMatrix() || right->isMatrix()) - return false; - - break; - - case EOpAdd: - case EOpSub: - case EOpDiv: - case EOpMul: - case EOpAddAssign: - case EOpSubAssign: - case EOpMulAssign: - case EOpDivAssign: - // check for non-Boolean operands - if (left->getBasicType() == EbtBool || right->getBasicType() == EbtBool) - return false; - - default: - break; - } - - // Compare left and right, and finish with the cases where the operand types must match - switch (op) { - case EOpLessThan: - case EOpGreaterThan: - case EOpLessThanEqual: - case EOpGreaterThanEqual: - - case EOpEqual: - case EOpNotEqual: - case EOpVectorEqual: - case EOpVectorNotEqual: - - case EOpLogicalAnd: - case EOpLogicalOr: - case EOpLogicalXor: - return left->getType() == right->getType(); - - case EOpMod: - case EOpModAssign: - - case EOpAnd: - case EOpInclusiveOr: - case EOpExclusiveOr: - case EOpAndAssign: - case EOpInclusiveOrAssign: - case EOpExclusiveOrAssign: - - case EOpAdd: - case EOpSub: - case EOpDiv: - - case EOpAddAssign: - case EOpSubAssign: - case EOpDivAssign: - // Quick out in case the types do match - if (left->getType() == right->getType()) - return true; - - // Fall through - - case EOpMul: - case EOpMulAssign: - // At least the basic type has to match - if (left->getBasicType() != right->getBasicType()) - return false; - - default: - break; - } - - // Finish handling the case, for all ops, where both operands are scalars. - if (left->isScalar() && right->isScalar()) - return true; - - // Finish handling the case, for all ops, where there are two vectors of different sizes - if (left->isVector() && right->isVector() && left->getVectorSize() != right->getVectorSize() && right->getVectorSize() > 1) - return false; - - // - // We now have a mix of scalars, vectors, or matrices, for non-relational operations. - // - - // Can these two operands be combined, what is the resulting type? - TBasicType basicType = left->getBasicType(); - switch (op) { - case EOpMul: - if (!left->isMatrix() && right->isMatrix()) { - if (left->isVector()) { - if (left->getVectorSize() != right->getMatrixRows()) - return false; - node.setOp(op = EOpVectorTimesMatrix); - node.setType(TType(basicType, EvqTemporary, right->getMatrixCols())); - } else { - node.setOp(op = EOpMatrixTimesScalar); - node.setType(TType(basicType, EvqTemporary, 0, right->getMatrixCols(), right->getMatrixRows())); - } - } else if (left->isMatrix() && !right->isMatrix()) { - if (right->isVector()) { - if (left->getMatrixCols() != right->getVectorSize()) - return false; - node.setOp(op = EOpMatrixTimesVector); - node.setType(TType(basicType, EvqTemporary, left->getMatrixRows())); - } else { - node.setOp(op = EOpMatrixTimesScalar); - } - } else if (left->isMatrix() && right->isMatrix()) { - if (left->getMatrixCols() != right->getMatrixRows()) - return false; - node.setOp(op = EOpMatrixTimesMatrix); - node.setType(TType(basicType, EvqTemporary, 0, right->getMatrixCols(), left->getMatrixRows())); - } else if (! left->isMatrix() && ! right->isMatrix()) { - if (left->isVector() && right->isVector()) { - ; // leave as component product - } else if (left->isVector() || right->isVector()) { - node.setOp(op = EOpVectorTimesScalar); - if (right->isVector()) - node.setType(TType(basicType, EvqTemporary, right->getVectorSize())); - } - } else { - return false; - } - break; - case EOpMulAssign: - if (! left->isMatrix() && right->isMatrix()) { - if (left->isVector()) { - if (left->getVectorSize() != right->getMatrixRows() || left->getVectorSize() != right->getMatrixCols()) - return false; - node.setOp(op = EOpVectorTimesMatrixAssign); - } else { - return false; - } - } else if (left->isMatrix() && !right->isMatrix()) { - if (right->isVector()) { - return false; - } else { - node.setOp(op = EOpMatrixTimesScalarAssign); - } - } else if (left->isMatrix() && right->isMatrix()) { - if (left->getMatrixCols() != right->getMatrixCols() || left->getMatrixCols() != right->getMatrixRows()) - return false; - node.setOp(op = EOpMatrixTimesMatrixAssign); - } else if (!left->isMatrix() && !right->isMatrix()) { - if (left->isVector() && right->isVector()) { - // leave as component product - } else if (left->isVector() || right->isVector()) { - if (! left->isVector()) - return false; - node.setOp(op = EOpVectorTimesScalarAssign); - } - } else { - return false; - } - break; - - case EOpRightShift: - case EOpLeftShift: - case EOpRightShiftAssign: - case EOpLeftShiftAssign: - if (right->isVector() && (! left->isVector() || right->getVectorSize() != left->getVectorSize())) - return false; - break; - - case EOpAssign: - if (left->getVectorSize() != right->getVectorSize() || left->getMatrixCols() != right->getMatrixCols() || left->getMatrixRows() != right->getMatrixRows()) - return false; - // fall through - - case EOpAdd: - case EOpSub: - case EOpDiv: - case EOpMod: - case EOpAnd: - case EOpInclusiveOr: - case EOpExclusiveOr: - case EOpAddAssign: - case EOpSubAssign: - case EOpDivAssign: - case EOpModAssign: - case EOpAndAssign: - case EOpInclusiveOrAssign: - case EOpExclusiveOrAssign: - - if ((left->isMatrix() && right->isVector()) || - (left->isVector() && right->isMatrix()) || - left->getBasicType() != right->getBasicType()) - return false; - if (left->isMatrix() && right->isMatrix() && (left->getMatrixCols() != right->getMatrixCols() || left->getMatrixRows() != right->getMatrixRows())) - return false; - if (left->isVector() && right->isVector() && left->getVectorSize() != right->getVectorSize()) - return false; - if (right->isVector() || right->isMatrix()) { - node.getWritableType().shallowCopy(right->getType()); - node.getWritableType().getQualifier().makeTemporary(); - } - break; - - default: - return false; - } - - // - // One more check for assignment. - // - switch (op) { - // The resulting type has to match the left operand. - case EOpAssign: - case EOpAddAssign: - case EOpSubAssign: - case EOpMulAssign: - case EOpDivAssign: - case EOpModAssign: - case EOpAndAssign: - case EOpInclusiveOrAssign: - case EOpExclusiveOrAssign: - case EOpLeftShiftAssign: - case EOpRightShiftAssign: - if (node.getType() != left->getType()) - return false; - break; - default: - break; - } - - return true; -} - -// -// See TIntermediate::promote -// -bool TIntermediate::promoteAggregate(TIntermAggregate& node) -{ - TOperator op = node.getOp(); - TIntermSequence& args = node.getSequence(); - const int numArgs = static_cast(args.size()); - - // Presently, only hlsl does intrinsic promotions. - if (getSource() != EShSourceHlsl) - return true; - - // set of opcodes that can be promoted in this manner. - switch (op) { - case EOpAtan: - case EOpClamp: - case EOpCross: - case EOpDistance: - case EOpDot: - case EOpDst: - case EOpFaceForward: - // case EOpFindMSB: TODO: - // case EOpFindLSB: TODO: - case EOpFma: - case EOpMod: - case EOpFrexp: - case EOpLdexp: - case EOpMix: - case EOpLit: - case EOpMax: - case EOpMin: - case EOpModf: - // case EOpGenMul: TODO: - case EOpPow: - case EOpReflect: - case EOpRefract: - // case EOpSinCos: TODO: - case EOpSmoothStep: - case EOpStep: - break; - default: - return true; - } - - // TODO: array and struct behavior - - // Try converting all nodes to the given node's type - TIntermSequence convertedArgs(numArgs, nullptr); - - // Try to convert all types to the nonConvArg type. - for (int nonConvArg = 0; nonConvArg < numArgs; ++nonConvArg) { - // Try converting all args to this arg's type - for (int convArg = 0; convArg < numArgs; ++convArg) { - convertedArgs[convArg] = addConversion(op, args[nonConvArg]->getAsTyped()->getType(), - args[convArg]->getAsTyped()); - } - - // If we successfully converted all the args, use the result. - if (std::all_of(convertedArgs.begin(), convertedArgs.end(), - [](const TIntermNode* node) { return node != nullptr; })) { - - std::swap(args, convertedArgs); - return true; - } - } - - return false; -} - -void TIntermBinary::updatePrecision() -{ - if (getBasicType() == EbtInt || getBasicType() == EbtUint || getBasicType() == EbtFloat || getBasicType() == EbtFloat16) { - getQualifier().precision = std::max(right->getQualifier().precision, left->getQualifier().precision); - if (getQualifier().precision != EpqNone) { - left->propagatePrecision(getQualifier().precision); - right->propagatePrecision(getQualifier().precision); - } - } -} - -void TIntermTyped::propagatePrecision(TPrecisionQualifier newPrecision) -{ - if (getQualifier().precision != EpqNone || (getBasicType() != EbtInt && getBasicType() != EbtUint && getBasicType() != EbtFloat && getBasicType() != EbtFloat16)) - return; - - getQualifier().precision = newPrecision; - - TIntermBinary* binaryNode = getAsBinaryNode(); - if (binaryNode) { - binaryNode->getLeft()->propagatePrecision(newPrecision); - binaryNode->getRight()->propagatePrecision(newPrecision); - - return; - } - - TIntermUnary* unaryNode = getAsUnaryNode(); - if (unaryNode) { - unaryNode->getOperand()->propagatePrecision(newPrecision); - - return; - } - - TIntermAggregate* aggregateNode = getAsAggregate(); - if (aggregateNode) { - TIntermSequence operands = aggregateNode->getSequence(); - for (unsigned int i = 0; i < operands.size(); ++i) { - TIntermTyped* typedNode = operands[i]->getAsTyped(); - if (! typedNode) - break; - typedNode->propagatePrecision(newPrecision); - } - - return; - } - - TIntermSelection* selectionNode = getAsSelectionNode(); - if (selectionNode) { - TIntermTyped* typedNode = selectionNode->getTrueBlock()->getAsTyped(); - if (typedNode) { - typedNode->propagatePrecision(newPrecision); - typedNode = selectionNode->getFalseBlock()->getAsTyped(); - if (typedNode) - typedNode->propagatePrecision(newPrecision); - } - - return; - } -} - -TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermConstantUnion* node) const -{ - const TConstUnionArray& rightUnionArray = node->getConstArray(); - int size = node->getType().computeNumComponents(); - - TConstUnionArray leftUnionArray(size); - - for (int i=0; i < size; i++) { - switch (promoteTo) { - case EbtFloat: - switch (node->getType().getBasicType()) { - case EbtInt: - leftUnionArray[i].setDConst(static_cast(rightUnionArray[i].getIConst())); - break; - case EbtUint: - leftUnionArray[i].setDConst(static_cast(rightUnionArray[i].getUConst())); - break; - case EbtInt64: - leftUnionArray[i].setDConst(static_cast(rightUnionArray[i].getI64Const())); - break; - case EbtUint64: - leftUnionArray[i].setDConst(static_cast(rightUnionArray[i].getU64Const())); - break; - case EbtBool: - leftUnionArray[i].setDConst(static_cast(rightUnionArray[i].getBConst())); - break; - case EbtFloat: - case EbtDouble: - case EbtFloat16: - leftUnionArray[i] = rightUnionArray[i]; - break; - default: - return node; - } - break; - case EbtDouble: - switch (node->getType().getBasicType()) { - case EbtInt: - leftUnionArray[i].setDConst(static_cast(rightUnionArray[i].getIConst())); - break; - case EbtUint: - leftUnionArray[i].setDConst(static_cast(rightUnionArray[i].getUConst())); - break; - case EbtInt64: - leftUnionArray[i].setDConst(static_cast(rightUnionArray[i].getI64Const())); - break; - case EbtUint64: - leftUnionArray[i].setDConst(static_cast(rightUnionArray[i].getU64Const())); - break; - case EbtBool: - leftUnionArray[i].setDConst(static_cast(rightUnionArray[i].getBConst())); - break; - case EbtFloat: - case EbtDouble: - case EbtFloat16: - leftUnionArray[i] = rightUnionArray[i]; - break; - default: - return node; - } - break; - case EbtFloat16: - switch (node->getType().getBasicType()) { - case EbtInt: - leftUnionArray[i].setDConst(static_cast(rightUnionArray[i].getIConst())); - break; - case EbtUint: - leftUnionArray[i].setDConst(static_cast(rightUnionArray[i].getUConst())); - break; - case EbtInt64: - leftUnionArray[i].setDConst(static_cast(rightUnionArray[i].getI64Const())); - break; - case EbtUint64: - leftUnionArray[i].setDConst(static_cast(rightUnionArray[i].getU64Const())); - break; - case EbtBool: - leftUnionArray[i].setDConst(static_cast(rightUnionArray[i].getBConst())); - break; - case EbtFloat: - case EbtDouble: - case EbtFloat16: - leftUnionArray[i] = rightUnionArray[i]; - break; - default: - return node; - } - break; - case EbtInt: - switch (node->getType().getBasicType()) { - case EbtInt: - leftUnionArray[i] = rightUnionArray[i]; - break; - case EbtUint: - leftUnionArray[i].setIConst(static_cast(rightUnionArray[i].getUConst())); - break; - case EbtInt64: - leftUnionArray[i].setIConst(static_cast(rightUnionArray[i].getI64Const())); - break; - case EbtUint64: - leftUnionArray[i].setIConst(static_cast(rightUnionArray[i].getU64Const())); - break; - case EbtBool: - leftUnionArray[i].setIConst(static_cast(rightUnionArray[i].getBConst())); - break; - case EbtFloat: - case EbtDouble: - case EbtFloat16: - leftUnionArray[i].setIConst(static_cast(rightUnionArray[i].getDConst())); - break; - default: - return node; - } - break; - case EbtUint: - switch (node->getType().getBasicType()) { - case EbtInt: - leftUnionArray[i].setUConst(static_cast(rightUnionArray[i].getIConst())); - break; - case EbtUint: - leftUnionArray[i] = rightUnionArray[i]; - break; - case EbtInt64: - leftUnionArray[i].setUConst(static_cast(rightUnionArray[i].getI64Const())); - break; - case EbtUint64: - leftUnionArray[i].setUConst(static_cast(rightUnionArray[i].getU64Const())); - break; - case EbtBool: - leftUnionArray[i].setUConst(static_cast(rightUnionArray[i].getBConst())); - break; - case EbtFloat: - case EbtDouble: - case EbtFloat16: - leftUnionArray[i].setUConst(static_cast(rightUnionArray[i].getDConst())); - break; - default: - return node; - } - break; - case EbtBool: - switch (node->getType().getBasicType()) { - case EbtInt: - leftUnionArray[i].setBConst(rightUnionArray[i].getIConst() != 0); - break; - case EbtUint: - leftUnionArray[i].setBConst(rightUnionArray[i].getUConst() != 0); - break; - case EbtInt64: - leftUnionArray[i].setBConst(rightUnionArray[i].getI64Const() != 0); - break; - case EbtUint64: - leftUnionArray[i].setBConst(rightUnionArray[i].getU64Const() != 0); - break; - case EbtBool: - leftUnionArray[i] = rightUnionArray[i]; - break; - case EbtFloat: - case EbtDouble: - case EbtFloat16: - leftUnionArray[i].setBConst(rightUnionArray[i].getDConst() != 0.0); - break; - default: - return node; - } - break; - case EbtInt64: - switch (node->getType().getBasicType()) { - case EbtInt: - leftUnionArray[i].setI64Const(static_cast(rightUnionArray[i].getIConst())); - break; - case EbtUint: - leftUnionArray[i].setI64Const(static_cast(rightUnionArray[i].getUConst())); - break; - case EbtInt64: - leftUnionArray[i] = rightUnionArray[i]; - break; - case EbtUint64: - leftUnionArray[i].setI64Const(static_cast(rightUnionArray[i].getU64Const())); - break; - case EbtBool: - leftUnionArray[i].setI64Const(static_cast(rightUnionArray[i].getBConst())); - break; - case EbtFloat: - case EbtDouble: - case EbtFloat16: - leftUnionArray[i].setI64Const(static_cast(rightUnionArray[i].getDConst())); - break; - default: - return node; - } - break; - case EbtUint64: - switch (node->getType().getBasicType()) { - case EbtInt: - leftUnionArray[i].setU64Const(static_cast(rightUnionArray[i].getIConst())); - break; - case EbtUint: - leftUnionArray[i].setU64Const(static_cast(rightUnionArray[i].getUConst())); - break; - case EbtInt64: - leftUnionArray[i].setU64Const(static_cast(rightUnionArray[i].getI64Const())); - break; - case EbtUint64: - leftUnionArray[i] = rightUnionArray[i]; - break; - case EbtBool: - leftUnionArray[i].setU64Const(static_cast(rightUnionArray[i].getBConst())); - break; - case EbtFloat: - case EbtDouble: - case EbtFloat16: - leftUnionArray[i].setU64Const(static_cast(rightUnionArray[i].getDConst())); - break; - default: - return node; - } - break; - default: - return node; - } - } - - const TType& t = node->getType(); - - return addConstantUnion(leftUnionArray, TType(promoteTo, t.getQualifier().storage, t.getVectorSize(), t.getMatrixCols(), t.getMatrixRows()), - node->getLoc()); -} - -void TIntermAggregate::setPragmaTable(const TPragmaTable& pTable) -{ - assert(pragmaTable == nullptr); - pragmaTable = new TPragmaTable; - *pragmaTable = pTable; -} - -// If either node is a specialization constant, while the other is -// a constant (or specialization constant), the result is still -// a specialization constant. -bool TIntermediate::specConstantPropagates(const TIntermTyped& node1, const TIntermTyped& node2) -{ - return (node1.getType().getQualifier().isSpecConstant() && node2.getType().getQualifier().isConstant()) || - (node2.getType().getQualifier().isSpecConstant() && node1.getType().getQualifier().isConstant()); -} - -struct TextureUpgradeAndSamplerRemovalTransform : public TIntermTraverser { - void visitSymbol(TIntermSymbol* symbol) override { - if (symbol->getBasicType() == EbtSampler && symbol->getType().getSampler().isTexture()) { - symbol->getWritableType().getSampler().combined = true; - } - } - bool visitAggregate(TVisit, TIntermAggregate* ag) override { - using namespace std; - TIntermSequence& seq = ag->getSequence(); - // remove pure sampler variables - TIntermSequence::iterator newEnd = remove_if(seq.begin(), seq.end(), [](TIntermNode* node) { - TIntermSymbol* symbol = node->getAsSymbolNode(); - if (!symbol) - return false; - - return (symbol->getBasicType() == EbtSampler && symbol->getType().getSampler().isPureSampler()); - }); - seq.erase(newEnd, seq.end()); - // replace constructors with sampler/textures - for_each(seq.begin(), seq.end(), [](TIntermNode*& node) { - TIntermAggregate *constructor = node->getAsAggregate(); - if (constructor && constructor->getOp() == EOpConstructTextureSampler) { - if (!constructor->getSequence().empty()) - node = constructor->getSequence()[0]; - } - }); - return true; - } -}; - -void TIntermediate::performTextureUpgradeAndSamplerRemovalTransformation(TIntermNode* root) -{ - TextureUpgradeAndSamplerRemovalTransform transform; - root->traverse(&transform); -} - -const char* TIntermediate::getResourceName(TResourceType res) -{ - switch (res) { - case EResSampler: return "shift-sampler-binding"; - case EResTexture: return "shift-texture-binding"; - case EResImage: return "shift-image-binding"; - case EResUbo: return "shift-UBO-binding"; - case EResSsbo: return "shift-ssbo-binding"; - case EResUav: return "shift-uav-binding"; - default: - assert(0); // internal error: should only be called with valid resource types. - return nullptr; - } -} - - -} // end namespace glslang diff --git a/External/glslang/glslang/MachineIndependent/LiveTraverser.h b/External/glslang/glslang/MachineIndependent/LiveTraverser.h deleted file mode 100644 index 7333bc96..00000000 --- a/External/glslang/glslang/MachineIndependent/LiveTraverser.h +++ /dev/null @@ -1,138 +0,0 @@ -// -// 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/External/glslang/glslang/MachineIndependent/ParseContextBase.cpp b/External/glslang/glslang/MachineIndependent/ParseContextBase.cpp deleted file mode 100644 index bfa9de4d..00000000 --- a/External/glslang/glslang/MachineIndependent/ParseContextBase.cpp +++ /dev/null @@ -1,613 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// Copyright (C) 2016 Google, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -// Implement the TParseContextBase class. - -#include - -#include "ParseHelper.h" - -extern int yyparse(glslang::TParseContext*); - -namespace glslang { - -// -// Used to output syntax, parsing, and semantic errors. -// - -void TParseContextBase::outputMessage(const TSourceLoc& loc, const char* szReason, - const char* szToken, - const char* szExtraInfoFormat, - TPrefixType prefix, va_list args) -{ - const int maxSize = MaxTokenLength + 200; - char szExtraInfo[maxSize]; - - safe_vsprintf(szExtraInfo, maxSize, szExtraInfoFormat, args); - - infoSink.info.prefix(prefix); - infoSink.info.location(loc); - infoSink.info << "'" << szToken << "' : " << szReason << " " << szExtraInfo << "\n"; - - if (prefix == EPrefixError) { - ++numErrors; - } -} - -void C_DECL TParseContextBase::error(const TSourceLoc& loc, const char* szReason, const char* szToken, - const char* szExtraInfoFormat, ...) -{ - if (messages & EShMsgOnlyPreprocessor) - return; - va_list args; - va_start(args, szExtraInfoFormat); - outputMessage(loc, szReason, szToken, szExtraInfoFormat, EPrefixError, args); - va_end(args); - - if ((messages & EShMsgCascadingErrors) == 0) - currentScanner->setEndOfInput(); -} - -void C_DECL TParseContextBase::warn(const TSourceLoc& loc, const char* szReason, const char* szToken, - const char* szExtraInfoFormat, ...) -{ - if (suppressWarnings()) - return; - va_list args; - va_start(args, szExtraInfoFormat); - outputMessage(loc, szReason, szToken, szExtraInfoFormat, EPrefixWarning, args); - va_end(args); -} - -void C_DECL TParseContextBase::ppError(const TSourceLoc& loc, const char* szReason, const char* szToken, - const char* szExtraInfoFormat, ...) -{ - va_list args; - va_start(args, szExtraInfoFormat); - outputMessage(loc, szReason, szToken, szExtraInfoFormat, EPrefixError, args); - va_end(args); - - if ((messages & EShMsgCascadingErrors) == 0) - currentScanner->setEndOfInput(); -} - -void C_DECL TParseContextBase::ppWarn(const TSourceLoc& loc, const char* szReason, const char* szToken, - const char* szExtraInfoFormat, ...) -{ - va_list args; - va_start(args, szExtraInfoFormat); - outputMessage(loc, szReason, szToken, szExtraInfoFormat, EPrefixWarning, args); - va_end(args); -} - -// -// Both test and if necessary, spit out an error, to see if the node is really -// an l-value that can be operated on this way. -// -// Returns true if there was an error. -// -bool TParseContextBase::lValueErrorCheck(const TSourceLoc& loc, const char* op, TIntermTyped* node) -{ - TIntermBinary* binaryNode = node->getAsBinaryNode(); - - if (binaryNode) { - switch(binaryNode->getOp()) { - case EOpIndexDirect: - case EOpIndexIndirect: // fall through - case EOpIndexDirectStruct: // fall through - case EOpVectorSwizzle: - case EOpMatrixSwizzle: - return lValueErrorCheck(loc, op, binaryNode->getLeft()); - default: - break; - } - error(loc, " l-value required", op, "", ""); - - return true; - } - - const char* symbol = nullptr; - TIntermSymbol* symNode = node->getAsSymbolNode(); - if (symNode != nullptr) - symbol = symNode->getName().c_str(); - - const char* message = nullptr; - switch (node->getQualifier().storage) { - case EvqConst: message = "can't modify a const"; break; - case EvqConstReadOnly: message = "can't modify a const"; break; - case EvqUniform: message = "can't modify a uniform"; break; - case EvqBuffer: - if (node->getQualifier().readonly) - message = "can't modify a readonly buffer"; - break; - - default: - // - // Type that can't be written to? - // - switch (node->getBasicType()) { - case EbtSampler: - message = "can't modify a sampler"; - break; - case EbtAtomicUint: - message = "can't modify an atomic_uint"; - break; - case EbtVoid: - message = "can't modify void"; - break; - default: - break; - } - } - - if (message == nullptr && binaryNode == nullptr && symNode == nullptr) { - error(loc, " l-value required", op, "", ""); - - return true; - } - - // - // Everything else is okay, no error. - // - if (message == nullptr) - return false; - - // - // If we get here, we have an error and a message. - // - if (symNode) - error(loc, " l-value required", op, "\"%s\" (%s)", symbol, message); - else - error(loc, " l-value required", op, "(%s)", message); - - return true; -} - -// Test for and give an error if the node can't be read from. -void TParseContextBase::rValueErrorCheck(const TSourceLoc& loc, const char* op, TIntermTyped* node) -{ - if (! node) - return; - - TIntermBinary* binaryNode = node->getAsBinaryNode(); - if (binaryNode) { - switch(binaryNode->getOp()) { - case EOpIndexDirect: - case EOpIndexIndirect: - case EOpIndexDirectStruct: - case EOpVectorSwizzle: - case EOpMatrixSwizzle: - rValueErrorCheck(loc, op, binaryNode->getLeft()); - default: - break; - } - - return; - } - - TIntermSymbol* symNode = node->getAsSymbolNode(); - if (symNode && symNode->getQualifier().writeonly) - error(loc, "can't read from writeonly object: ", op, symNode->getName().c_str()); -} - -// Add 'symbol' to the list of deferred linkage symbols, which -// are later processed in finish(), at which point the symbol -// must still be valid. -// It is okay if the symbol's type will be subsequently edited; -// the modifications will be tracked. -// Order is preserved, to avoid creating novel forward references. -void TParseContextBase::trackLinkage(TSymbol& symbol) -{ - if (!parsingBuiltins) - linkageSymbols.push_back(&symbol); -} - -// Ensure index is in bounds, correct if necessary. -// Give an error if not. -void TParseContextBase::checkIndex(const TSourceLoc& loc, const TType& type, int& index) -{ - if (index < 0) { - error(loc, "", "[", "index out of range '%d'", index); - index = 0; - } else if (type.isArray()) { - if (type.isSizedArray() && index >= type.getOuterArraySize()) { - error(loc, "", "[", "array index out of range '%d'", index); - index = type.getOuterArraySize() - 1; - } - } else if (type.isVector()) { - if (index >= type.getVectorSize()) { - error(loc, "", "[", "vector index out of range '%d'", index); - index = type.getVectorSize() - 1; - } - } else if (type.isMatrix()) { - if (index >= type.getMatrixCols()) { - error(loc, "", "[", "matrix index out of range '%d'", index); - index = type.getMatrixCols() - 1; - } - } -} - -// Make a shared symbol have a non-shared version that can be edited by the current -// compile, such that editing its type will not change the shared version and will -// effect all nodes already sharing it (non-shallow type), -// or adopting its full type after being edited (shallow type). -void TParseContextBase::makeEditable(TSymbol*& symbol) -{ - // copyUp() does a deep copy of the type. - symbol = symbolTable.copyUp(symbol); - - // Save it (deferred, so it can be edited first) in the AST for linker use. - if (symbol) - trackLinkage(*symbol); -} - -// Return a writable version of the variable 'name'. -// -// Return nullptr if 'name' is not found. This should mean -// something is seriously wrong (e.g., compiler asking self for -// built-in that doesn't exist). -TVariable* TParseContextBase::getEditableVariable(const char* name) -{ - bool builtIn; - TSymbol* symbol = symbolTable.find(name, &builtIn); - - assert(symbol != nullptr); - if (symbol == nullptr) - return nullptr; - - if (builtIn) - makeEditable(symbol); - - return symbol->getAsVariable(); -} - -// Select the best matching function for 'call' from 'candidateList'. -// -// Assumptions -// -// There is no exact match, so a selection algorithm needs to run. That is, the -// language-specific handler should check for exact match first, to -// decide what to do, before calling this selector. -// -// Input -// -// * list of candidate signatures to select from -// * the call -// * a predicate function convertible(from, to) that says whether or not type -// 'from' can implicitly convert to type 'to' (it includes the case of what -// the calling language would consider a matching type with no conversion -// needed) -// * a predicate function better(from1, from2, to1, to2) that says whether or -// not a conversion from <-> to2 is considered better than a conversion -// from <-> to1 (both in and out directions need testing, as declared by the -// formal parameter) -// -// Output -// -// * best matching candidate (or none, if no viable candidates found) -// * whether there was a tie for the best match (ambiguous overload selection, -// caller's choice for how to report) -// -const TFunction* TParseContextBase::selectFunction( - const TVector candidateList, - const TFunction& call, - std::function convertible, - std::function better, - /* output */ bool& tie) -{ -// -// Operation -// -// 1. Prune the input list of candidates down to a list of viable candidates, -// where each viable candidate has -// -// * at least as many parameters as there are calling arguments, with any -// remaining parameters being optional or having default values -// * each parameter is true under convertible(A, B), where A is the calling -// type for in and B is the formal type, and in addition, for out B is the -// calling type and A is the formal type -// -// 2. If there are no viable candidates, return with no match. -// -// 3. If there is only one viable candidate, it is the best match. -// -// 4. If there are multiple viable candidates, select the first viable candidate -// as the incumbent. Compare the incumbent to the next viable candidate, and if -// that candidate is better (bullets below), make it the incumbent. Repeat, with -// a linear walk through the viable candidate list. The final incumbent will be -// returned as the best match. A viable candidate is better than the incumbent if -// -// * it has a function argument with a better(...) conversion than the incumbent, -// for all directions needed by in and out -// * the incumbent has no argument with a better(...) conversion then the -// candidate, for either in or out (as needed) -// -// 5. Check for ambiguity by comparing the best match against all other viable -// candidates. If any other viable candidate has a function argument with a -// better(...) conversion than the best candidate (for either in or out -// directions), return that there was a tie for best. -// - - tie = false; - - // 1. prune to viable... - TVector viableCandidates; - for (auto it = candidateList.begin(); it != candidateList.end(); ++it) { - const TFunction& candidate = *(*it); - - // to even be a potential match, number of arguments must be >= the number of - // fixed (non-default) parameters, and <= the total (including parameter with defaults). - if (call.getParamCount() < candidate.getFixedParamCount() || - call.getParamCount() > candidate.getParamCount()) - continue; - - // see if arguments are convertible - bool viable = true; - - // The call can have fewer parameters than the candidate, if some have defaults. - const int paramCount = std::min(call.getParamCount(), candidate.getParamCount()); - for (int param = 0; param < paramCount; ++param) { - if (candidate[param].type->getQualifier().isParamInput()) { - if (! convertible(*call[param].type, *candidate[param].type, candidate.getBuiltInOp(), param)) { - viable = false; - break; - } - } - if (candidate[param].type->getQualifier().isParamOutput()) { - if (! convertible(*candidate[param].type, *call[param].type, candidate.getBuiltInOp(), param)) { - viable = false; - break; - } - } - } - - if (viable) - viableCandidates.push_back(&candidate); - } - - // 2. none viable... - if (viableCandidates.size() == 0) - return nullptr; - - // 3. only one viable... - if (viableCandidates.size() == 1) - return viableCandidates.front(); - - // 4. find best... - const auto betterParam = [&call, &better](const TFunction& can1, const TFunction& can2) -> bool { - // is call -> can2 better than call -> can1 for any parameter - bool hasBetterParam = false; - for (int param = 0; param < call.getParamCount(); ++param) { - if (better(*call[param].type, *can1[param].type, *can2[param].type)) { - hasBetterParam = true; - break; - } - } - return hasBetterParam; - }; - - const auto equivalentParams = [&call, &better](const TFunction& can1, const TFunction& can2) -> bool { - // is call -> can2 equivalent to call -> can1 for all the call parameters? - for (int param = 0; param < call.getParamCount(); ++param) { - if (better(*call[param].type, *can1[param].type, *can2[param].type) || - better(*call[param].type, *can2[param].type, *can1[param].type)) - return false; - } - return true; - }; - - const TFunction* incumbent = viableCandidates.front(); - for (auto it = viableCandidates.begin() + 1; it != viableCandidates.end(); ++it) { - const TFunction& candidate = *(*it); - if (betterParam(*incumbent, candidate) && ! betterParam(candidate, *incumbent)) - incumbent = &candidate; - } - - // 5. ambiguity... - for (auto it = viableCandidates.begin(); it != viableCandidates.end(); ++it) { - if (incumbent == *it) - continue; - const TFunction& candidate = *(*it); - - // In the case of default parameters, it may have an identical initial set, which is - // also ambiguous - if (betterParam(*incumbent, candidate) || equivalentParams(*incumbent, candidate)) - tie = true; - } - - return incumbent; -} - -// -// Look at a '.' field selector string and change it into numerical selectors -// for a vector or scalar. -// -// Always return some form of swizzle, so the result is always usable. -// -void TParseContextBase::parseSwizzleSelector(const TSourceLoc& loc, const TString& compString, int vecSize, - TSwizzleSelectors& selector) -{ - // Too long? - if (compString.size() > MaxSwizzleSelectors) - error(loc, "vector swizzle too long", compString.c_str(), ""); - - // Use this to test that all swizzle characters are from the same swizzle-namespace-set - enum { - exyzw, - ergba, - estpq, - } fieldSet[MaxSwizzleSelectors]; - - // Decode the swizzle string. - int size = std::min(MaxSwizzleSelectors, (int)compString.size()); - for (int i = 0; i < size; ++i) { - switch (compString[i]) { - case 'x': - selector.push_back(0); - fieldSet[i] = exyzw; - break; - case 'r': - selector.push_back(0); - fieldSet[i] = ergba; - break; - case 's': - selector.push_back(0); - fieldSet[i] = estpq; - break; - - case 'y': - selector.push_back(1); - fieldSet[i] = exyzw; - break; - case 'g': - selector.push_back(1); - fieldSet[i] = ergba; - break; - case 't': - selector.push_back(1); - fieldSet[i] = estpq; - break; - - case 'z': - selector.push_back(2); - fieldSet[i] = exyzw; - break; - case 'b': - selector.push_back(2); - fieldSet[i] = ergba; - break; - case 'p': - selector.push_back(2); - fieldSet[i] = estpq; - break; - - case 'w': - selector.push_back(3); - fieldSet[i] = exyzw; - break; - case 'a': - selector.push_back(3); - fieldSet[i] = ergba; - break; - case 'q': - selector.push_back(3); - fieldSet[i] = estpq; - break; - - default: - error(loc, "unknown swizzle selection", compString.c_str(), ""); - break; - } - } - - // Additional error checking. - for (int i = 0; i < selector.size(); ++i) { - if (selector[i] >= vecSize) { - error(loc, "vector swizzle selection out of range", compString.c_str(), ""); - selector.resize(i); - break; - } - - if (i > 0 && fieldSet[i] != fieldSet[i-1]) { - error(loc, "vector swizzle selectors not from the same set", compString.c_str(), ""); - selector.resize(i); - break; - } - } - - // Ensure it is valid. - if (selector.size() == 0) - selector.push_back(0); -} - -// -// Make the passed-in variable information become a member of the -// global uniform block. If this doesn't exist yet, make it. -// -void TParseContextBase::growGlobalUniformBlock(const TSourceLoc& loc, TType& memberType, const TString& memberName, TTypeList* typeList) -{ - // Make the global block, if not yet made. - if (globalUniformBlock == nullptr) { - TQualifier blockQualifier; - blockQualifier.clear(); - blockQualifier.storage = EvqUniform; - TType blockType(new TTypeList, *NewPoolTString(getGlobalUniformBlockName()), blockQualifier); - setUniformBlockDefaults(blockType); - globalUniformBlock = new TVariable(NewPoolTString(""), blockType, true); - firstNewMember = 0; - } - - // Update with binding and set - globalUniformBlock->getWritableType().getQualifier().layoutBinding = globalUniformBinding; - globalUniformBlock->getWritableType().getQualifier().layoutSet = globalUniformSet; - - // Add the requested member as a member to the global block. - TType* type = new TType; - type->shallowCopy(memberType); - type->setFieldName(memberName); - if (typeList) - type->setStruct(typeList); - TTypeLoc typeLoc = {type, loc}; - globalUniformBlock->getType().getWritableStruct()->push_back(typeLoc); - - // Insert into the symbol table. - if (firstNewMember == 0) { - // This is the first request; we need a normal symbol table insert - if (symbolTable.insert(*globalUniformBlock)) - trackLinkage(*globalUniformBlock); - else - error(loc, "failed to insert the global constant buffer", "uniform", ""); - } else { - // This is a follow-on request; we need to amend the first insert - symbolTable.amend(*globalUniformBlock, firstNewMember); - } - - ++firstNewMember; -} - -void TParseContextBase::finish() -{ - if (parsingBuiltins) - return; - - // Transfer the linkage symbols to AST nodes, preserving order. - TIntermAggregate* linkage = new TIntermAggregate; - for (auto i = linkageSymbols.begin(); i != linkageSymbols.end(); ++i) - intermediate.addSymbolLinkageNode(linkage, **i); - intermediate.addSymbolLinkageNodes(linkage, getLanguage(), symbolTable); -} - -} // end namespace glslang diff --git a/External/glslang/glslang/MachineIndependent/ParseHelper.cpp b/External/glslang/glslang/MachineIndependent/ParseHelper.cpp deleted file mode 100644 index 45c050d4..00000000 --- a/External/glslang/glslang/MachineIndependent/ParseHelper.cpp +++ /dev/null @@ -1,6736 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// Copyright (C) 2012-2015 LunarG, Inc. -// Copyright (C) 2015-2016 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. -// - -#include "ParseHelper.h" -#include "Scan.h" - -#include "../OSDependent/osinclude.h" -#include - -#include "preprocessor/PpContext.h" - -extern int yyparse(glslang::TParseContext*); - -namespace glslang { - -TParseContext::TParseContext(TSymbolTable& symbolTable, TIntermediate& interm, bool parsingBuiltins, - int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage language, - TInfoSink& infoSink, bool forwardCompatible, EShMessages messages, - const TString* entryPoint) : - TParseContextBase(symbolTable, interm, parsingBuiltins, version, profile, spvVersion, language, - infoSink, forwardCompatible, messages, entryPoint), - inMain(false), - blockName(nullptr), - limits(resources.limits), - atomicUintOffsets(nullptr), anyIndexLimits(false) -{ - // decide whether precision qualifiers should be ignored or respected - if (profile == EEsProfile || spvVersion.vulkan > 0) { - precisionManager.respectPrecisionQualifiers(); - if (! parsingBuiltins && language == EShLangFragment && profile != EEsProfile && spvVersion.vulkan > 0) - precisionManager.warnAboutDefaults(); - } - - setPrecisionDefaults(); - - globalUniformDefaults.clear(); - globalUniformDefaults.layoutMatrix = ElmColumnMajor; - globalUniformDefaults.layoutPacking = spvVersion.spv != 0 ? ElpStd140 : ElpShared; - - globalBufferDefaults.clear(); - globalBufferDefaults.layoutMatrix = ElmColumnMajor; - globalBufferDefaults.layoutPacking = spvVersion.spv != 0 ? ElpStd430 : ElpShared; - - globalInputDefaults.clear(); - globalOutputDefaults.clear(); - - // "Shaders in the transform - // feedback capturing mode have an initial global default of - // layout(xfb_buffer = 0) out;" - if (language == EShLangVertex || - language == EShLangTessControl || - language == EShLangTessEvaluation || - language == EShLangGeometry) - globalOutputDefaults.layoutXfbBuffer = 0; - - if (language == EShLangGeometry) - globalOutputDefaults.layoutStream = 0; - - if (entryPoint != nullptr && entryPoint->size() > 0 && *entryPoint != "main") - infoSink.info.message(EPrefixError, "Source entry point must be \"main\""); -} - -TParseContext::~TParseContext() -{ - delete [] atomicUintOffsets; -} - -// Set up all default precisions as needed by the current environment. -// Intended just as a TParseContext constructor helper. -void TParseContext::setPrecisionDefaults() -{ - // Set all precision defaults to EpqNone, which is correct for all types - // when not obeying precision qualifiers, and correct for types that don't - // have defaults (thus getting an error on use) when obeying precision - // qualifiers. - - for (int type = 0; type < EbtNumTypes; ++type) - defaultPrecision[type] = EpqNone; - - for (int type = 0; type < maxSamplerIndex; ++type) - defaultSamplerPrecision[type] = EpqNone; - - // replace with real precision defaults for those that have them - if (obeyPrecisionQualifiers()) { - if (profile == EEsProfile) { - // Most don't have defaults, a few default to lowp. - TSampler sampler; - sampler.set(EbtFloat, Esd2D); - defaultSamplerPrecision[computeSamplerTypeIndex(sampler)] = EpqLow; - sampler.set(EbtFloat, EsdCube); - defaultSamplerPrecision[computeSamplerTypeIndex(sampler)] = EpqLow; - sampler.set(EbtFloat, Esd2D); - sampler.external = true; - defaultSamplerPrecision[computeSamplerTypeIndex(sampler)] = EpqLow; - } - - // If we are parsing built-in computational variables/functions, it is meaningful to record - // whether the built-in has no precision qualifier, as that ambiguity - // is used to resolve the precision from the supplied arguments/operands instead. - // So, we don't actually want to replace EpqNone with a default precision for built-ins. - if (! parsingBuiltins) { - if (profile == EEsProfile && language == EShLangFragment) { - defaultPrecision[EbtInt] = EpqMedium; - defaultPrecision[EbtUint] = EpqMedium; - } else { - defaultPrecision[EbtInt] = EpqHigh; - defaultPrecision[EbtUint] = EpqHigh; - defaultPrecision[EbtFloat] = EpqHigh; - } - - if (profile != EEsProfile) { - // Non-ES profile - // All sampler precisions default to highp. - for (int type = 0; type < maxSamplerIndex; ++type) - defaultSamplerPrecision[type] = EpqHigh; - } - } - - defaultPrecision[EbtSampler] = EpqLow; - defaultPrecision[EbtAtomicUint] = EpqHigh; - } -} - -void TParseContext::setLimits(const TBuiltInResource& r) -{ - resources = r; - - anyIndexLimits = ! limits.generalAttributeMatrixVectorIndexing || - ! limits.generalConstantMatrixVectorIndexing || - ! limits.generalSamplerIndexing || - ! limits.generalUniformIndexing || - ! limits.generalVariableIndexing || - ! limits.generalVaryingIndexing; - - intermediate.setLimits(resources); - - // "Each binding point tracks its own current default offset for - // inheritance of subsequent variables using the same binding. The initial state of compilation is that all - // binding points have an offset of 0." - atomicUintOffsets = new int[resources.maxAtomicCounterBindings]; - for (int b = 0; b < resources.maxAtomicCounterBindings; ++b) - atomicUintOffsets[b] = 0; -} - -// -// Parse an array of strings using yyparse, going through the -// preprocessor to tokenize the shader strings, then through -// the GLSL scanner. -// -// Returns true for successful acceptance of the shader, false if any errors. -// -bool TParseContext::parseShaderStrings(TPpContext& ppContext, TInputScanner& input, bool versionWillBeError) -{ - currentScanner = &input; - ppContext.setInput(input, versionWillBeError); - yyparse(this); - - finish(); - - return numErrors == 0; -} - -// This is called from bison when it has a parse (syntax) error -// Note though that to stop cascading errors, we set EOF, which -// will usually cause a syntax error, so be more accurate that -// compilation is terminating. -void TParseContext::parserError(const char* s) -{ - if (! getScanner()->atEndOfInput() || numErrors == 0) - error(getCurrentLoc(), "", "", s, ""); - else - error(getCurrentLoc(), "compilation terminated", "", ""); -} - -void TParseContext::handlePragma(const TSourceLoc& loc, const TVector& tokens) -{ - if (pragmaCallback) - pragmaCallback(loc.line, tokens); - - if (tokens.size() == 0) - return; - - if (tokens[0].compare("optimize") == 0) { - if (tokens.size() != 4) { - error(loc, "optimize pragma syntax is incorrect", "#pragma", ""); - return; - } - - if (tokens[1].compare("(") != 0) { - error(loc, "\"(\" expected after 'optimize' keyword", "#pragma", ""); - return; - } - - if (tokens[2].compare("on") == 0) - contextPragma.optimize = true; - else if (tokens[2].compare("off") == 0) - contextPragma.optimize = false; - else { - error(loc, "\"on\" or \"off\" expected after '(' for 'optimize' pragma", "#pragma", ""); - return; - } - - if (tokens[3].compare(")") != 0) { - error(loc, "\")\" expected to end 'optimize' pragma", "#pragma", ""); - return; - } - } else if (tokens[0].compare("debug") == 0) { - if (tokens.size() != 4) { - error(loc, "debug pragma syntax is incorrect", "#pragma", ""); - return; - } - - if (tokens[1].compare("(") != 0) { - error(loc, "\"(\" expected after 'debug' keyword", "#pragma", ""); - return; - } - - if (tokens[2].compare("on") == 0) - contextPragma.debug = true; - else if (tokens[2].compare("off") == 0) - contextPragma.debug = false; - else { - error(loc, "\"on\" or \"off\" expected after '(' for 'debug' pragma", "#pragma", ""); - return; - } - - if (tokens[3].compare(")") != 0) { - error(loc, "\")\" expected to end 'debug' pragma", "#pragma", ""); - return; - } - } else if (spvVersion.spv > 0 && tokens[0].compare("use_storage_buffer") == 0) { - if (tokens.size() != 1) - error(loc, "extra tokens", "#pragma", ""); - intermediate.setUseStorageBuffer(); - } else if (tokens[0].compare("once") == 0) { - warn(loc, "not implemented", "#pragma once", ""); - } -} - -// -// Handle seeing a variable identifier in the grammar. -// -TIntermTyped* TParseContext::handleVariable(const TSourceLoc& loc, TSymbol* symbol, const TString* string) -{ - TIntermTyped* node = nullptr; - - // Error check for requiring specific extensions present. - if (symbol && symbol->getNumExtensions()) - requireExtensions(loc, symbol->getNumExtensions(), symbol->getExtensions(), symbol->getName().c_str()); - - if (symbol && symbol->isReadOnly()) { - // All shared things containing an unsized array must be copied up - // on first use, so that all future references will share its array structure, - // so that editing the implicit size will effect all nodes consuming it, - // and so that editing the implicit size won't change the shared one. - // - // If this is a variable or a block, check it and all it contains, but if this - // is a member of an anonymous block, check the whole block, as the whole block - // will need to be copied up if it contains an unsized array. - if (symbol->getType().containsUnsizedArray() || - (symbol->getAsAnonMember() && - symbol->getAsAnonMember()->getAnonContainer().getType().containsUnsizedArray())) - makeEditable(symbol); - } - - const TVariable* variable; - const TAnonMember* anon = symbol ? symbol->getAsAnonMember() : nullptr; - if (anon) { - // It was a member of an anonymous container. - - // The "getNumExtensions()" mechanism above doesn't yet work for block members - blockMemberExtensionCheck(loc, nullptr, *string); - - // Create a subtree for its dereference. - variable = anon->getAnonContainer().getAsVariable(); - TIntermTyped* container = intermediate.addSymbol(*variable, loc); - TIntermTyped* constNode = intermediate.addConstantUnion(anon->getMemberNumber(), loc); - node = intermediate.addIndex(EOpIndexDirectStruct, container, constNode, loc); - - node->setType(*(*variable->getType().getStruct())[anon->getMemberNumber()].type); - if (node->getType().hiddenMember()) - error(loc, "member of nameless block was not redeclared", string->c_str(), ""); - } else { - // Not a member of an anonymous container. - - // The symbol table search was done in the lexical phase. - // See if it was a variable. - variable = symbol ? symbol->getAsVariable() : nullptr; - if (variable) { - if ((variable->getType().getBasicType() == EbtBlock || - variable->getType().getBasicType() == EbtStruct) && variable->getType().getStruct() == nullptr) { - error(loc, "cannot be used (maybe an instance name is needed)", string->c_str(), ""); - variable = nullptr; - } - } else { - if (symbol) - error(loc, "variable name expected", string->c_str(), ""); - } - - // Recovery, if it wasn't found or was not a variable. - if (! variable) - variable = new TVariable(string, TType(EbtVoid)); - - if (variable->getType().getQualifier().isFrontEndConstant()) - node = intermediate.addConstantUnion(variable->getConstArray(), variable->getType(), loc); - else - node = intermediate.addSymbol(*variable, loc); - } - - if (variable->getType().getQualifier().isIo()) - intermediate.addIoAccessed(*string); - - return node; -} - -// -// Handle seeing a base[index] dereference in the grammar. -// -TIntermTyped* TParseContext::handleBracketDereference(const TSourceLoc& loc, TIntermTyped* base, TIntermTyped* index) -{ - TIntermTyped* result = nullptr; - - int indexValue = 0; - if (index->getQualifier().isFrontEndConstant()) - indexValue = index->getAsConstantUnion()->getConstArray()[0].getIConst(); - - variableCheck(base); - if (! base->isArray() && ! base->isMatrix() && ! base->isVector()) { - if (base->getAsSymbolNode()) - error(loc, " left of '[' is not of type array, matrix, or vector ", base->getAsSymbolNode()->getName().c_str(), ""); - else - error(loc, " left of '[' is not of type array, matrix, or vector ", "expression", ""); - } else if (base->getType().getQualifier().isFrontEndConstant() && index->getQualifier().isFrontEndConstant()) { - // both base and index are front-end constants - checkIndex(loc, base->getType(), indexValue); - return intermediate.foldDereference(base, indexValue, loc); - } else { - // at least one of base and index is not a front-end constant variable... - - if (index->getQualifier().isFrontEndConstant()) - checkIndex(loc, base->getType(), indexValue); - - if (base->getAsSymbolNode() && isIoResizeArray(base->getType())) - handleIoResizeArrayAccess(loc, base); - - if (index->getQualifier().isFrontEndConstant()) { - if (base->getType().isUnsizedArray()) - base->getWritableType().updateImplicitArraySize(indexValue + 1); - else - checkIndex(loc, base->getType(), indexValue); - result = intermediate.addIndex(EOpIndexDirect, base, index, loc); - } else { - if (base->getType().isUnsizedArray()) { - // we have a variable index into an unsized array, which is okay, - // depending on the situation - if (base->getAsSymbolNode() && isIoResizeArray(base->getType())) - error(loc, "", "[", "array must be sized by a redeclaration or layout qualifier before being indexed with a variable"); - else { - // it is okay for a run-time sized array - checkRuntimeSizable(loc, *base); - } - base->getWritableType().setArrayVariablyIndexed(); - } - if (base->getBasicType() == EbtBlock) { - if (base->getQualifier().storage == EvqBuffer) - requireProfile(base->getLoc(), ~EEsProfile, "variable indexing buffer block array"); - else if (base->getQualifier().storage == EvqUniform) - profileRequires(base->getLoc(), EEsProfile, 320, Num_AEP_gpu_shader5, AEP_gpu_shader5, - "variable indexing uniform block array"); - else { - // input/output blocks either don't exist or can be variable indexed - } - } else if (language == EShLangFragment && base->getQualifier().isPipeOutput()) - requireProfile(base->getLoc(), ~EEsProfile, "variable indexing fragment shader output array"); - else if (base->getBasicType() == EbtSampler && version >= 130) { - const char* explanation = "variable indexing sampler array"; - requireProfile(base->getLoc(), EEsProfile | ECoreProfile | ECompatibilityProfile, explanation); - profileRequires(base->getLoc(), EEsProfile, 320, Num_AEP_gpu_shader5, AEP_gpu_shader5, explanation); - profileRequires(base->getLoc(), ECoreProfile | ECompatibilityProfile, 400, nullptr, explanation); - } - - result = intermediate.addIndex(EOpIndexIndirect, base, index, loc); - } - } - - if (result == nullptr) { - // Insert dummy error-recovery result - result = intermediate.addConstantUnion(0.0, EbtFloat, loc); - } else { - // Insert valid dereferenced result - TType newType(base->getType(), 0); // dereferenced type - if (base->getType().getQualifier().isConstant() && index->getQualifier().isConstant()) { - newType.getQualifier().storage = EvqConst; - // If base or index is a specialization constant, the result should also be a specialization constant. - if (base->getType().getQualifier().isSpecConstant() || index->getQualifier().isSpecConstant()) { - newType.getQualifier().makeSpecConstant(); - } - } else { - newType.getQualifier().makePartialTemporary(); - } - result->setType(newType); - - // Propagate nonuniform - if (base->getQualifier().isNonUniform() || index->getQualifier().isNonUniform()) - result->getWritableType().getQualifier().nonUniform = true; - - if (anyIndexLimits) - handleIndexLimits(loc, base, index); - } - - return result; -} - -// for ES 2.0 (version 100) limitations for almost all index operations except vertex-shader uniforms -void TParseContext::handleIndexLimits(const TSourceLoc& /*loc*/, TIntermTyped* base, TIntermTyped* index) -{ - if ((! limits.generalSamplerIndexing && base->getBasicType() == EbtSampler) || - (! limits.generalUniformIndexing && base->getQualifier().isUniformOrBuffer() && language != EShLangVertex) || - (! limits.generalAttributeMatrixVectorIndexing && base->getQualifier().isPipeInput() && language == EShLangVertex && (base->getType().isMatrix() || base->getType().isVector())) || - (! limits.generalConstantMatrixVectorIndexing && base->getAsConstantUnion()) || - (! limits.generalVariableIndexing && ! base->getType().getQualifier().isUniformOrBuffer() && - ! base->getType().getQualifier().isPipeInput() && - ! base->getType().getQualifier().isPipeOutput() && - ! base->getType().getQualifier().isConstant()) || - (! limits.generalVaryingIndexing && (base->getType().getQualifier().isPipeInput() || - base->getType().getQualifier().isPipeOutput()))) { - // it's too early to know what the inductive variables are, save it for post processing - needsIndexLimitationChecking.push_back(index); - } -} - -// Make a shared symbol have a non-shared version that can be edited by the current -// compile, such that editing its type will not change the shared version and will -// effect all nodes sharing it. -void TParseContext::makeEditable(TSymbol*& symbol) -{ - TParseContextBase::makeEditable(symbol); - - // See if it's tied to IO resizing - if (isIoResizeArray(symbol->getType())) - ioArraySymbolResizeList.push_back(symbol); -} - -// Return true if this is a geometry shader input array or tessellation control output array. -bool TParseContext::isIoResizeArray(const TType& type) const -{ - return type.isArray() && - ((language == EShLangGeometry && type.getQualifier().storage == EvqVaryingIn) || - (language == EShLangTessControl && type.getQualifier().storage == EvqVaryingOut && ! type.getQualifier().patch)); -} - -// If an array is not isIoResizeArray() but is an io array, make sure it has the right size -void TParseContext::fixIoArraySize(const TSourceLoc& loc, TType& type) -{ - if (! type.isArray() || type.getQualifier().patch || symbolTable.atBuiltInLevel()) - return; - - assert(! isIoResizeArray(type)); - - if (type.getQualifier().storage != EvqVaryingIn || type.getQualifier().patch) - return; - - if (language == EShLangTessControl || language == EShLangTessEvaluation) { - if (type.getOuterArraySize() != resources.maxPatchVertices) { - if (type.isSizedArray()) - error(loc, "tessellation input array size must be gl_MaxPatchVertices or implicitly sized", "[]", ""); - type.changeOuterArraySize(resources.maxPatchVertices); - } - } -} - -// Issue any errors if the non-array object is missing arrayness WRT -// shader I/O that has array requirements. -// All arrayness checking is handled in array paths, this is for -void TParseContext::ioArrayCheck(const TSourceLoc& loc, const TType& type, const TString& identifier) -{ - if (! type.isArray() && ! symbolTable.atBuiltInLevel()) { - if (type.getQualifier().isArrayedIo(language) -#ifdef NV_EXTENSIONS - && !type.getQualifier().layoutPassthrough -#endif - ) - error(loc, "type must be an array:", type.getStorageQualifierString(), identifier.c_str()); - } -} - -// Handle a dereference of a geometry shader input array or tessellation control output array. -// See ioArraySymbolResizeList comment in ParseHelper.h. -// -void TParseContext::handleIoResizeArrayAccess(const TSourceLoc& /*loc*/, TIntermTyped* base) -{ - TIntermSymbol* symbolNode = base->getAsSymbolNode(); - assert(symbolNode); - if (! symbolNode) - return; - - // fix array size, if it can be fixed and needs to be fixed (will allow variable indexing) - if (symbolNode->getType().isUnsizedArray()) { - int newSize = getIoArrayImplicitSize(); - if (newSize > 0) - symbolNode->getWritableType().changeOuterArraySize(newSize); - } -} - -// If there has been an input primitive declaration (geometry shader) or an output -// number of vertices declaration(tessellation shader), make sure all input array types -// match it in size. Types come either from nodes in the AST or symbols in the -// symbol table. -// -// Types without an array size will be given one. -// Types already having a size that is wrong will get an error. -// -void TParseContext::checkIoArraysConsistency(const TSourceLoc& loc, bool tailOnly) -{ - int requiredSize = getIoArrayImplicitSize(); - if (requiredSize == 0) - return; - - const char* feature; - if (language == EShLangGeometry) - feature = TQualifier::getGeometryString(intermediate.getInputPrimitive()); - else if (language == EShLangTessControl) - feature = "vertices"; - else - feature = "unknown"; - - if (tailOnly) { - checkIoArrayConsistency(loc, requiredSize, feature, ioArraySymbolResizeList.back()->getWritableType(), ioArraySymbolResizeList.back()->getName()); - return; - } - - for (size_t i = 0; i < ioArraySymbolResizeList.size(); ++i) - checkIoArrayConsistency(loc, requiredSize, feature, ioArraySymbolResizeList[i]->getWritableType(), ioArraySymbolResizeList[i]->getName()); -} - -int TParseContext::getIoArrayImplicitSize() const -{ - if (language == EShLangGeometry) - return TQualifier::mapGeometryToSize(intermediate.getInputPrimitive()); - else if (language == EShLangTessControl) - return intermediate.getVertices() != TQualifier::layoutNotSet ? intermediate.getVertices() : 0; - else - return 0; -} - -void TParseContext::checkIoArrayConsistency(const TSourceLoc& loc, int requiredSize, const char* feature, TType& type, const TString& name) -{ - if (type.isUnsizedArray()) - type.changeOuterArraySize(requiredSize); - else if (type.getOuterArraySize() != requiredSize) { - if (language == EShLangGeometry) - error(loc, "inconsistent input primitive for array size of", feature, name.c_str()); - else if (language == EShLangTessControl) - error(loc, "inconsistent output number of vertices for array size of", feature, name.c_str()); - else - assert(0); - } -} - -// Handle seeing a binary node with a math operation. -// Returns nullptr if not semantically allowed. -TIntermTyped* TParseContext::handleBinaryMath(const TSourceLoc& loc, const char* str, TOperator op, TIntermTyped* left, TIntermTyped* right) -{ - rValueErrorCheck(loc, str, left->getAsTyped()); - rValueErrorCheck(loc, str, right->getAsTyped()); - - bool allowed = true; - switch (op) { - // TODO: Bring more source language-specific checks up from intermediate.cpp - // to the specific parse helpers for that source language. - case EOpLessThan: - case EOpGreaterThan: - case EOpLessThanEqual: - case EOpGreaterThanEqual: - if (! left->isScalar() || ! right->isScalar()) - allowed = false; - break; - default: - break; - } - - TIntermTyped* result = nullptr; - if (allowed) - result = intermediate.addBinaryMath(op, left, right, loc); - - if (result == nullptr) - binaryOpError(loc, str, left->getCompleteString(), right->getCompleteString()); - - return result; -} - -// Handle seeing a unary node with a math operation. -TIntermTyped* TParseContext::handleUnaryMath(const TSourceLoc& loc, const char* str, TOperator op, TIntermTyped* childNode) -{ - rValueErrorCheck(loc, str, childNode); - - TIntermTyped* result = intermediate.addUnaryMath(op, childNode, loc); - - if (result) - return result; - else - unaryOpError(loc, str, childNode->getCompleteString()); - - return childNode; -} - -// -// Handle seeing a base.field dereference in the grammar. -// -TIntermTyped* TParseContext::handleDotDereference(const TSourceLoc& loc, TIntermTyped* base, const TString& field) -{ - variableCheck(base); - - // - // .length() can't be resolved until we later see the function-calling syntax. - // Save away the name in the AST for now. Processing is completed in - // handleLengthMethod(). - // - if (field == "length") { - if (base->isArray()) { - profileRequires(loc, ENoProfile, 120, E_GL_3DL_array_objects, ".length"); - profileRequires(loc, EEsProfile, 300, nullptr, ".length"); - } else if (base->isVector() || base->isMatrix()) { - const char* feature = ".length() on vectors and matrices"; - requireProfile(loc, ~EEsProfile, feature); - profileRequires(loc, ~EEsProfile, 420, E_GL_ARB_shading_language_420pack, feature); - } else { - error(loc, "does not operate on this type:", field.c_str(), base->getType().getCompleteString().c_str()); - - return base; - } - - return intermediate.addMethod(base, TType(EbtInt), &field, loc); - } - - // It's not .length() if we get to here. - - if (base->isArray()) { - error(loc, "cannot apply to an array:", ".", field.c_str()); - - return base; - } - - // It's neither an array nor .length() if we get here, - // leaving swizzles and struct/block dereferences. - - TIntermTyped* result = base; - if ((base->isVector() || base->isScalar()) && - (base->isFloatingDomain() || base->isIntegerDomain() || base->getBasicType() == EbtBool)) { - if (base->isScalar()) { - const char* dotFeature = "scalar swizzle"; - requireProfile(loc, ~EEsProfile, dotFeature); - profileRequires(loc, ~EEsProfile, 420, E_GL_ARB_shading_language_420pack, dotFeature); - } - - TSwizzleSelectors selectors; - parseSwizzleSelector(loc, field, base->getVectorSize(), selectors); - - if (base->isScalar()) { - if (selectors.size() == 1) - return result; - else { - TType type(base->getBasicType(), EvqTemporary, selectors.size()); - // Swizzle operations propagate specialization-constantness - if (base->getQualifier().isSpecConstant()) - type.getQualifier().makeSpecConstant(); - return addConstructor(loc, base, type); - } - } - - if (base->getType().getQualifier().isFrontEndConstant()) - result = intermediate.foldSwizzle(base, selectors, loc); - else { - if (selectors.size() == 1) { - TIntermTyped* index = intermediate.addConstantUnion(selectors[0], loc); - result = intermediate.addIndex(EOpIndexDirect, base, index, loc); - result->setType(TType(base->getBasicType(), EvqTemporary, base->getType().getQualifier().precision)); - } else { - TIntermTyped* index = intermediate.addSwizzle(selectors, loc); - result = intermediate.addIndex(EOpVectorSwizzle, base, index, loc); - result->setType(TType(base->getBasicType(), EvqTemporary, base->getType().getQualifier().precision, selectors.size())); - } - // Swizzle operations propagate specialization-constantness - if (base->getType().getQualifier().isSpecConstant()) - result->getWritableType().getQualifier().makeSpecConstant(); - } - } else if (base->getBasicType() == EbtStruct || base->getBasicType() == EbtBlock) { - const TTypeList* fields = base->getType().getStruct(); - bool fieldFound = false; - int member; - for (member = 0; member < (int)fields->size(); ++member) { - if ((*fields)[member].type->getFieldName() == field) { - fieldFound = true; - break; - } - } - if (fieldFound) { - if (base->getType().getQualifier().isFrontEndConstant()) - result = intermediate.foldDereference(base, member, loc); - else { - blockMemberExtensionCheck(loc, base, field); - TIntermTyped* index = intermediate.addConstantUnion(member, loc); - result = intermediate.addIndex(EOpIndexDirectStruct, base, index, loc); - result->setType(*(*fields)[member].type); - } - } else - error(loc, "no such field in structure", field.c_str(), ""); - } else - error(loc, "does not apply to this type:", field.c_str(), base->getType().getCompleteString().c_str()); - - // Propagate noContraction up the dereference chain - if (base->getQualifier().noContraction) - result->getWritableType().getQualifier().noContraction = true; - - // Propagate nonuniform - if (base->getQualifier().isNonUniform()) - result->getWritableType().getQualifier().nonUniform = true; - - return result; -} - -void TParseContext::blockMemberExtensionCheck(const TSourceLoc& loc, const TIntermTyped* /*base*/, const TString& field) -{ - if (profile == EEsProfile && field == "gl_PointSize") { - if (language == EShLangGeometry) - requireExtensions(loc, Num_AEP_geometry_point_size, AEP_geometry_point_size, "gl_PointSize"); - else if (language == EShLangTessControl || language == EShLangTessEvaluation) - requireExtensions(loc, Num_AEP_tessellation_point_size, AEP_tessellation_point_size, "gl_PointSize"); - } -} - -// -// Handle seeing a function declarator in the grammar. This is the precursor -// to recognizing a function prototype or function definition. -// -TFunction* TParseContext::handleFunctionDeclarator(const TSourceLoc& loc, TFunction& function, bool prototype) -{ - // ES can't declare prototypes inside functions - if (! symbolTable.atGlobalLevel()) - requireProfile(loc, ~EEsProfile, "local function declaration"); - - // - // Multiple declarations of the same function name are allowed. - // - // If this is a definition, the definition production code will check for redefinitions - // (we don't know at this point if it's a definition or not). - // - // Redeclarations (full signature match) are allowed. But, return types and parameter qualifiers must also match. - // - except ES 100, which only allows a single prototype - // - // ES 100 does not allow redefining, but does allow overloading of built-in functions. - // ES 300 does not allow redefining or overloading of built-in functions. - // - bool builtIn; - TSymbol* symbol = symbolTable.find(function.getMangledName(), &builtIn); - if (symbol && symbol->getAsFunction() && builtIn) - requireProfile(loc, ~EEsProfile, "redefinition of built-in function"); - const TFunction* prevDec = symbol ? symbol->getAsFunction() : 0; - if (prevDec) { - if (prevDec->isPrototyped() && prototype) - profileRequires(loc, EEsProfile, 300, nullptr, "multiple prototypes for same function"); - if (prevDec->getType() != function.getType()) - error(loc, "overloaded functions must have the same return type", function.getName().c_str(), ""); - for (int i = 0; i < prevDec->getParamCount(); ++i) { - if ((*prevDec)[i].type->getQualifier().storage != function[i].type->getQualifier().storage) - error(loc, "overloaded functions must have the same parameter storage qualifiers for argument", function[i].type->getStorageQualifierString(), "%d", i+1); - - if ((*prevDec)[i].type->getQualifier().precision != function[i].type->getQualifier().precision) - error(loc, "overloaded functions must have the same parameter precision qualifiers for argument", function[i].type->getPrecisionQualifierString(), "%d", i+1); - } - } - - arrayObjectCheck(loc, function.getType(), "array in function return type"); - - if (prototype) { - // All built-in functions are defined, even though they don't have a body. - // Count their prototype as a definition instead. - if (symbolTable.atBuiltInLevel()) - function.setDefined(); - else { - if (prevDec && ! builtIn) - symbol->getAsFunction()->setPrototyped(); // need a writable one, but like having prevDec as a const - function.setPrototyped(); - } - } - - // This insert won't actually insert it if it's a duplicate signature, but it will still check for - // other forms of name collisions. - if (! symbolTable.insert(function)) - error(loc, "function name is redeclaration of existing name", function.getName().c_str(), ""); - - // - // If this is a redeclaration, it could also be a definition, - // in which case, we need to use the parameter names from this one, and not the one that's - // being redeclared. So, pass back this declaration, not the one in the symbol table. - // - return &function; -} - -// -// Handle seeing the function prototype in front of a function definition in the grammar. -// The body is handled after this function returns. -// -TIntermAggregate* TParseContext::handleFunctionDefinition(const TSourceLoc& loc, TFunction& function) -{ - currentCaller = function.getMangledName(); - TSymbol* symbol = symbolTable.find(function.getMangledName()); - TFunction* prevDec = symbol ? symbol->getAsFunction() : nullptr; - - if (! prevDec) - error(loc, "can't find function", function.getName().c_str(), ""); - // Note: 'prevDec' could be 'function' if this is the first time we've seen function - // as it would have just been put in the symbol table. Otherwise, we're looking up - // an earlier occurrence. - - if (prevDec && prevDec->isDefined()) { - // Then this function already has a body. - error(loc, "function already has a body", function.getName().c_str(), ""); - } - if (prevDec && ! prevDec->isDefined()) { - prevDec->setDefined(); - - // Remember the return type for later checking for RETURN statements. - currentFunctionType = &(prevDec->getType()); - } else - currentFunctionType = new TType(EbtVoid); - functionReturnsValue = false; - - // Check for entry point - if (function.getName().compare(intermediate.getEntryPointName().c_str()) == 0) { - intermediate.setEntryPointMangledName(function.getMangledName().c_str()); - intermediate.incrementEntryPointCount(); - inMain = true; - } else - inMain = false; - - // - // Raise error message if main function takes any parameters or returns anything other than void - // - if (inMain) { - if (function.getParamCount() > 0) - error(loc, "function cannot take any parameter(s)", function.getName().c_str(), ""); - if (function.getType().getBasicType() != EbtVoid) - error(loc, "", function.getType().getBasicTypeString().c_str(), "entry point cannot return a value"); - } - - // - // New symbol table scope for body of function plus its arguments - // - symbolTable.push(); - - // - // Insert parameters into the symbol table. - // If the parameter has no name, it's not an error, just don't insert it - // (could be used for unused args). - // - // Also, accumulate the list of parameters into the HIL, so lower level code - // knows where to find parameters. - // - TIntermAggregate* paramNodes = new TIntermAggregate; - for (int i = 0; i < function.getParamCount(); i++) { - TParameter& param = function[i]; - if (param.name != nullptr) { - TVariable *variable = new TVariable(param.name, *param.type); - - // Insert the parameters with name in the symbol table. - if (! symbolTable.insert(*variable)) - error(loc, "redefinition", variable->getName().c_str(), ""); - else { - // Transfer ownership of name pointer to symbol table. - param.name = nullptr; - - // Add the parameter to the HIL - paramNodes = intermediate.growAggregate(paramNodes, - intermediate.addSymbol(*variable, loc), - loc); - } - } else - paramNodes = intermediate.growAggregate(paramNodes, intermediate.addSymbol(*param.type, loc), loc); - } - intermediate.setAggregateOperator(paramNodes, EOpParameters, TType(EbtVoid), loc); - loopNestingLevel = 0; - statementNestingLevel = 0; - controlFlowNestingLevel = 0; - postEntryPointReturn = false; - - return paramNodes; -} - -// -// Handle seeing function call syntax in the grammar, which could be any of -// - .length() method -// - constructor -// - a call to a built-in function mapped to an operator -// - a call to a built-in function that will remain a function call (e.g., texturing) -// - user function -// - subroutine call (not implemented yet) -// -TIntermTyped* TParseContext::handleFunctionCall(const TSourceLoc& loc, TFunction* function, TIntermNode* arguments) -{ - TIntermTyped* result = nullptr; - - if (function->getBuiltInOp() == EOpArrayLength) - result = handleLengthMethod(loc, function, arguments); - else if (function->getBuiltInOp() != EOpNull) { - // - // Then this should be a constructor. - // Don't go through the symbol table for constructors. - // Their parameters will be verified algorithmically. - // - TType type(EbtVoid); // use this to get the type back - if (! constructorError(loc, arguments, *function, function->getBuiltInOp(), type)) { - // - // It's a constructor, of type 'type'. - // - result = addConstructor(loc, arguments, type); - if (result == nullptr) - error(loc, "cannot construct with these arguments", type.getCompleteString().c_str(), ""); - } - } else { - // - // Find it in the symbol table. - // - const TFunction* fnCandidate; - bool builtIn; - fnCandidate = findFunction(loc, *function, builtIn); - if (fnCandidate) { - // This is a declared function that might map to - // - a built-in operator, - // - a built-in function not mapped to an operator, or - // - a user function. - - // Error check for a function requiring specific extensions present. - if (builtIn && fnCandidate->getNumExtensions()) - requireExtensions(loc, fnCandidate->getNumExtensions(), fnCandidate->getExtensions(), fnCandidate->getName().c_str()); - - if (arguments != nullptr) { - // Make sure qualifications work for these arguments. - TIntermAggregate* aggregate = arguments->getAsAggregate(); - for (int i = 0; i < fnCandidate->getParamCount(); ++i) { - // At this early point there is a slight ambiguity between whether an aggregate 'arguments' - // is the single argument itself or its children are the arguments. Only one argument - // means take 'arguments' itself as the one argument. - TIntermNode* arg = fnCandidate->getParamCount() == 1 ? arguments : (aggregate ? aggregate->getSequence()[i] : arguments); - TQualifier& formalQualifier = (*fnCandidate)[i].type->getQualifier(); - if (formalQualifier.isParamOutput()) { - if (lValueErrorCheck(arguments->getLoc(), "assign", arg->getAsTyped())) - error(arguments->getLoc(), "Non-L-value cannot be passed for 'out' or 'inout' parameters.", "out", ""); - } - TQualifier& argQualifier = arg->getAsTyped()->getQualifier(); - if (argQualifier.isMemory()) { - const char* message = "argument cannot drop memory qualifier when passed to formal parameter"; - if (argQualifier.volatil && ! formalQualifier.volatil) - error(arguments->getLoc(), message, "volatile", ""); - if (argQualifier.coherent && ! formalQualifier.coherent) - error(arguments->getLoc(), message, "coherent", ""); - if (argQualifier.readonly && ! formalQualifier.readonly) - error(arguments->getLoc(), message, "readonly", ""); - if (argQualifier.writeonly && ! formalQualifier.writeonly) - error(arguments->getLoc(), message, "writeonly", ""); - } - // TODO 4.5 functionality: A shader will fail to compile - // if the value passed to the memargument of an atomic memory function does not correspond to a buffer or - // shared variable. It is acceptable to pass an element of an array or a single component of a vector to the - // memargument of an atomic memory function, as long as the underlying array or vector is a buffer or - // shared variable. - } - - // Convert 'in' arguments - addInputArgumentConversions(*fnCandidate, arguments); // arguments may be modified if it's just a single argument node - } - - if (builtIn && fnCandidate->getBuiltInOp() != EOpNull) { - // A function call mapped to a built-in operation. - result = handleBuiltInFunctionCall(loc, arguments, *fnCandidate); - } else { - // This is a function call not mapped to built-in operator. - // It could still be a built-in function, but only if PureOperatorBuiltins == false. - result = intermediate.setAggregateOperator(arguments, EOpFunctionCall, fnCandidate->getType(), loc); - TIntermAggregate* call = result->getAsAggregate(); - call->setName(fnCandidate->getMangledName()); - - // this is how we know whether the given function is a built-in function or a user-defined function - // if builtIn == false, it's a userDefined -> could be an overloaded built-in function also - // if builtIn == true, it's definitely a built-in function with EOpNull - if (! builtIn) { - call->setUserDefined(); - if (symbolTable.atGlobalLevel()) { - requireProfile(loc, ~EEsProfile, "calling user function from global scope"); - intermediate.addToCallGraph(infoSink, "main(", fnCandidate->getMangledName()); - } else - intermediate.addToCallGraph(infoSink, currentCaller, fnCandidate->getMangledName()); - } - - if (builtIn) - nonOpBuiltInCheck(loc, *fnCandidate, *call); - else - userFunctionCallCheck(loc, *call); - } - - // Convert 'out' arguments. If it was a constant folded built-in, it won't be an aggregate anymore. - // Built-ins with a single argument aren't called with an aggregate, but they also don't have an output. - // Also, build the qualifier list for user function calls, which are always called with an aggregate. - if (result->getAsAggregate()) { - TQualifierList& qualifierList = result->getAsAggregate()->getQualifierList(); - for (int i = 0; i < fnCandidate->getParamCount(); ++i) { - TStorageQualifier qual = (*fnCandidate)[i].type->getQualifier().storage; - qualifierList.push_back(qual); - } - result = addOutputArgumentConversions(*fnCandidate, *result->getAsAggregate()); - } - } - } - - // generic error recovery - // TODO: simplification: localize all the error recoveries that look like this, and taking type into account to reduce cascades - if (result == nullptr) - result = intermediate.addConstantUnion(0.0, EbtFloat, loc); - - return result; -} - -TIntermTyped* TParseContext::handleBuiltInFunctionCall(TSourceLoc loc, TIntermNode* arguments, - const TFunction& function) -{ - checkLocation(loc, function.getBuiltInOp()); - TIntermTyped *result = intermediate.addBuiltInFunctionCall(loc, function.getBuiltInOp(), - function.getParamCount() == 1, - arguments, function.getType()); - if (obeyPrecisionQualifiers()) - computeBuiltinPrecisions(*result, function); - - if (result == nullptr) { - if (arguments == nullptr) - error(loc, " wrong operand type", "Internal Error", - "built in unary operator function. Type: %s", ""); - else - error(arguments->getLoc(), " wrong operand type", "Internal Error", - "built in unary operator function. Type: %s", - static_cast(arguments)->getCompleteString().c_str()); - } else if (result->getAsOperator()) - builtInOpCheck(loc, function, *result->getAsOperator()); - - return result; -} - -// "The operation of a built-in function can have a different precision -// qualification than the precision qualification of the resulting value. -// These two precision qualifications are established as follows. -// -// The precision qualification of the operation of a built-in function is -// based on the precision qualification of its input arguments and formal -// parameters: When a formal parameter specifies a precision qualifier, -// that is used, otherwise, the precision qualification of the calling -// argument is used. The highest precision of these will be the precision -// qualification of the operation of the built-in function. Generally, -// this is applied across all arguments to a built-in function, with the -// exceptions being: -// - bitfieldExtract and bitfieldInsert ignore the 'offset' and 'bits' -// arguments. -// - interpolateAt* functions only look at the 'interpolant' argument. -// -// The precision qualification of the result of a built-in function is -// determined in one of the following ways: -// -// - For the texture sampling, image load, and image store functions, -// the precision of the return type matches the precision of the -// sampler type -// -// Otherwise: -// -// - For prototypes that do not specify a resulting precision qualifier, -// the precision will be the same as the precision of the operation. -// -// - For prototypes that do specify a resulting precision qualifier, -// the specified precision qualifier is the precision qualification of -// the result." -// -void TParseContext::computeBuiltinPrecisions(TIntermTyped& node, const TFunction& function) -{ - TPrecisionQualifier operationPrecision = EpqNone; - TPrecisionQualifier resultPrecision = EpqNone; - - TIntermOperator* opNode = node.getAsOperator(); - if (opNode == nullptr) - return; - - if (TIntermUnary* unaryNode = node.getAsUnaryNode()) { - operationPrecision = std::max(function[0].type->getQualifier().precision, - unaryNode->getOperand()->getType().getQualifier().precision); - if (function.getType().getBasicType() != EbtBool) - resultPrecision = function.getType().getQualifier().precision == EpqNone ? - operationPrecision : - function.getType().getQualifier().precision; - } else if (TIntermAggregate* agg = node.getAsAggregate()) { - TIntermSequence& sequence = agg->getSequence(); - unsigned int numArgs = (unsigned int)sequence.size(); - switch (agg->getOp()) { - case EOpBitfieldExtract: - numArgs = 1; - break; - case EOpBitfieldInsert: - numArgs = 2; - break; - case EOpInterpolateAtCentroid: - case EOpInterpolateAtOffset: - case EOpInterpolateAtSample: - numArgs = 1; - break; - default: - break; - } - // find the maximum precision from the arguments and parameters - for (unsigned int arg = 0; arg < numArgs; ++arg) { - operationPrecision = std::max(operationPrecision, sequence[arg]->getAsTyped()->getQualifier().precision); - operationPrecision = std::max(operationPrecision, function[arg].type->getQualifier().precision); - } - // compute the result precision -#ifdef AMD_EXTENSIONS - if (agg->isSampling() || - agg->getOp() == EOpImageLoad || agg->getOp() == EOpImageStore || - agg->getOp() == EOpImageLoadLod || agg->getOp() == EOpImageStoreLod) -#else - if (agg->isSampling() || agg->getOp() == EOpImageLoad || agg->getOp() == EOpImageStore) -#endif - resultPrecision = sequence[0]->getAsTyped()->getQualifier().precision; - else if (function.getType().getBasicType() != EbtBool) - resultPrecision = function.getType().getQualifier().precision == EpqNone ? - operationPrecision : - function.getType().getQualifier().precision; - } - - // Propagate precision through this node and its children. That algorithm stops - // when a precision is found, so start by clearing this subroot precision - opNode->getQualifier().precision = EpqNone; - if (operationPrecision != EpqNone) { - opNode->propagatePrecision(operationPrecision); - opNode->setOperationPrecision(operationPrecision); - } - // Now, set the result precision, which might not match - opNode->getQualifier().precision = resultPrecision; -} - -TIntermNode* TParseContext::handleReturnValue(const TSourceLoc& loc, TIntermTyped* value) -{ - functionReturnsValue = true; - if (currentFunctionType->getBasicType() == EbtVoid) { - error(loc, "void function cannot return a value", "return", ""); - return intermediate.addBranch(EOpReturn, loc); - } else if (*currentFunctionType != value->getType()) { - TIntermTyped* converted = intermediate.addConversion(EOpReturn, *currentFunctionType, value); - if (converted) { - if (*currentFunctionType != converted->getType()) - error(loc, "cannot convert return value to function return type", "return", ""); - if (version < 420) - warn(loc, "type conversion on return values was not explicitly allowed until version 420", "return", ""); - return intermediate.addBranch(EOpReturn, converted, loc); - } else { - error(loc, "type does not match, or is not convertible to, the function's return type", "return", ""); - return intermediate.addBranch(EOpReturn, value, loc); - } - } else - return intermediate.addBranch(EOpReturn, value, loc); -} - -// See if the operation is being done in an illegal location. -void TParseContext::checkLocation(const TSourceLoc& loc, TOperator op) -{ - switch (op) { - case EOpBarrier: - if (language == EShLangTessControl) { - if (controlFlowNestingLevel > 0) - error(loc, "tessellation control barrier() cannot be placed within flow control", "", ""); - if (! inMain) - error(loc, "tessellation control barrier() must be in main()", "", ""); - else if (postEntryPointReturn) - error(loc, "tessellation control barrier() cannot be placed after a return from main()", "", ""); - } - break; - default: - break; - } -} - -// Finish processing object.length(). This started earlier in handleDotDereference(), where -// the ".length" part was recognized and semantically checked, and finished here where the -// function syntax "()" is recognized. -// -// Return resulting tree node. -TIntermTyped* TParseContext::handleLengthMethod(const TSourceLoc& loc, TFunction* function, TIntermNode* intermNode) -{ - int length = 0; - - if (function->getParamCount() > 0) - error(loc, "method does not accept any arguments", function->getName().c_str(), ""); - else { - const TType& type = intermNode->getAsTyped()->getType(); - if (type.isArray()) { - if (type.isUnsizedArray()) { - if (intermNode->getAsSymbolNode() && isIoResizeArray(type)) { - // We could be between a layout declaration that gives a built-in io array implicit size and - // a user redeclaration of that array, meaning we have to substitute its implicit size here - // without actually redeclaring the array. (It is an error to use a member before the - // redeclaration, but not an error to use the array name itself.) - const TString& name = intermNode->getAsSymbolNode()->getName(); - if (name == "gl_in" || name == "gl_out") - length = getIoArrayImplicitSize(); - } - if (length == 0) { - if (intermNode->getAsSymbolNode() && isIoResizeArray(type)) - error(loc, "", function->getName().c_str(), "array must first be sized by a redeclaration or layout qualifier"); - else if (isRuntimeLength(*intermNode->getAsTyped())) { - // Create a unary op and let the back end handle it - return intermediate.addBuiltInFunctionCall(loc, EOpArrayLength, true, intermNode, TType(EbtInt)); - } else - error(loc, "", function->getName().c_str(), "array must be declared with a size before using this method"); - } - } else if (type.getOuterArrayNode()) { - // If the array's outer size is specified by an intermediate node, it means the array's length - // was specified by a specialization constant. In such a case, we should return the node of the - // specialization constants to represent the length. - return type.getOuterArrayNode(); - } else - length = type.getOuterArraySize(); - } else if (type.isMatrix()) - length = type.getMatrixCols(); - else if (type.isVector()) - length = type.getVectorSize(); - else { - // we should not get here, because earlier semantic checking should have prevented this path - error(loc, ".length()", "unexpected use of .length()", ""); - } - } - - if (length == 0) - length = 1; - - return intermediate.addConstantUnion(length, loc); -} - -// -// Add any needed implicit conversions for function-call arguments to input parameters. -// -void TParseContext::addInputArgumentConversions(const TFunction& function, TIntermNode*& arguments) const -{ - TIntermAggregate* aggregate = arguments->getAsAggregate(); - - // Process each argument's conversion - for (int i = 0; i < function.getParamCount(); ++i) { - // At this early point there is a slight ambiguity between whether an aggregate 'arguments' - // is the single argument itself or its children are the arguments. Only one argument - // means take 'arguments' itself as the one argument. - TIntermTyped* arg = function.getParamCount() == 1 ? arguments->getAsTyped() : (aggregate ? aggregate->getSequence()[i]->getAsTyped() : arguments->getAsTyped()); - if (*function[i].type != arg->getType()) { - if (function[i].type->getQualifier().isParamInput()) { - // In-qualified arguments just need an extra node added above the argument to - // convert to the correct type. - arg = intermediate.addConversion(EOpFunctionCall, *function[i].type, arg); - if (arg) { - if (function.getParamCount() == 1) - arguments = arg; - else { - if (aggregate) - aggregate->getSequence()[i] = arg; - else - arguments = arg; - } - } - } - } - } -} - -// -// Add any needed implicit output conversions for function-call arguments. This -// can require a new tree topology, complicated further by whether the function -// has a return value. -// -// Returns a node of a subtree that evaluates to the return value of the function. -// -TIntermTyped* TParseContext::addOutputArgumentConversions(const TFunction& function, TIntermAggregate& intermNode) const -{ - TIntermSequence& arguments = intermNode.getSequence(); - - // Will there be any output conversions? - bool outputConversions = false; - for (int i = 0; i < function.getParamCount(); ++i) { - if (*function[i].type != arguments[i]->getAsTyped()->getType() && function[i].type->getQualifier().isParamOutput()) { - outputConversions = true; - break; - } - } - - if (! outputConversions) - return &intermNode; - - // Setup for the new tree, if needed: - // - // Output conversions need a different tree topology. - // Out-qualified arguments need a temporary of the correct type, with the call - // followed by an assignment of the temporary to the original argument: - // void: function(arg, ...) -> ( function(tempArg, ...), arg = tempArg, ...) - // ret = function(arg, ...) -> ret = (tempRet = function(tempArg, ...), arg = tempArg, ..., tempRet) - // Where the "tempArg" type needs no conversion as an argument, but will convert on assignment. - TIntermTyped* conversionTree = nullptr; - TVariable* tempRet = nullptr; - if (intermNode.getBasicType() != EbtVoid) { - // do the "tempRet = function(...), " bit from above - tempRet = makeInternalVariable("tempReturn", intermNode.getType()); - TIntermSymbol* tempRetNode = intermediate.addSymbol(*tempRet, intermNode.getLoc()); - conversionTree = intermediate.addAssign(EOpAssign, tempRetNode, &intermNode, intermNode.getLoc()); - } else - conversionTree = &intermNode; - - conversionTree = intermediate.makeAggregate(conversionTree); - - // Process each argument's conversion - for (int i = 0; i < function.getParamCount(); ++i) { - if (*function[i].type != arguments[i]->getAsTyped()->getType()) { - if (function[i].type->getQualifier().isParamOutput()) { - // Out-qualified arguments need to use the topology set up above. - // do the " ...(tempArg, ...), arg = tempArg" bit from above - TVariable* tempArg = makeInternalVariable("tempArg", *function[i].type); - tempArg->getWritableType().getQualifier().makeTemporary(); - TIntermSymbol* tempArgNode = intermediate.addSymbol(*tempArg, intermNode.getLoc()); - TIntermTyped* tempAssign = intermediate.addAssign(EOpAssign, arguments[i]->getAsTyped(), tempArgNode, arguments[i]->getLoc()); - conversionTree = intermediate.growAggregate(conversionTree, tempAssign, arguments[i]->getLoc()); - // replace the argument with another node for the same tempArg variable - arguments[i] = intermediate.addSymbol(*tempArg, intermNode.getLoc()); - } - } - } - - // Finalize the tree topology (see bigger comment above). - if (tempRet) { - // do the "..., tempRet" bit from above - TIntermSymbol* tempRetNode = intermediate.addSymbol(*tempRet, intermNode.getLoc()); - conversionTree = intermediate.growAggregate(conversionTree, tempRetNode, intermNode.getLoc()); - } - conversionTree = intermediate.setAggregateOperator(conversionTree, EOpComma, intermNode.getType(), intermNode.getLoc()); - - return conversionTree; -} - -// -// Do additional checking of built-in function calls that is not caught -// by normal semantic checks on argument type, extension tagging, etc. -// -// Assumes there has been a semantically correct match to a built-in function prototype. -// -void TParseContext::builtInOpCheck(const TSourceLoc& loc, const TFunction& fnCandidate, TIntermOperator& callNode) -{ - // Set up convenience accessors to the argument(s). There is almost always - // multiple arguments for the cases below, but when there might be one, - // check the unaryArg first. - const TIntermSequence* argp = nullptr; // confusing to use [] syntax on a pointer, so this is to help get a reference - const TIntermTyped* unaryArg = nullptr; - const TIntermTyped* arg0 = nullptr; - if (callNode.getAsAggregate()) { - argp = &callNode.getAsAggregate()->getSequence(); - if (argp->size() > 0) - arg0 = (*argp)[0]->getAsTyped(); - } else { - assert(callNode.getAsUnaryNode()); - unaryArg = callNode.getAsUnaryNode()->getOperand(); - arg0 = unaryArg; - } - - TString featureString; - const char* feature = nullptr; - switch (callNode.getOp()) { - case EOpTextureGather: - case EOpTextureGatherOffset: - case EOpTextureGatherOffsets: - { - // Figure out which variants are allowed by what extensions, - // and what arguments must be constant for which situations. - - featureString = fnCandidate.getName(); - featureString += "(...)"; - feature = featureString.c_str(); - profileRequires(loc, EEsProfile, 310, nullptr, feature); - int compArg = -1; // track which argument, if any, is the constant component argument - switch (callNode.getOp()) { - case EOpTextureGather: - // More than two arguments needs gpu_shader5, and rectangular or shadow needs gpu_shader5, - // otherwise, need GL_ARB_texture_gather. - if (fnCandidate.getParamCount() > 2 || fnCandidate[0].type->getSampler().dim == EsdRect || fnCandidate[0].type->getSampler().shadow) { - profileRequires(loc, ~EEsProfile, 400, E_GL_ARB_gpu_shader5, feature); - if (! fnCandidate[0].type->getSampler().shadow) - compArg = 2; - } else - profileRequires(loc, ~EEsProfile, 400, E_GL_ARB_texture_gather, feature); - break; - case EOpTextureGatherOffset: - // GL_ARB_texture_gather is good enough for 2D non-shadow textures with no component argument - if (fnCandidate[0].type->getSampler().dim == Esd2D && ! fnCandidate[0].type->getSampler().shadow && fnCandidate.getParamCount() == 3) - profileRequires(loc, ~EEsProfile, 400, E_GL_ARB_texture_gather, feature); - else - profileRequires(loc, ~EEsProfile, 400, E_GL_ARB_gpu_shader5, feature); - if (! (*argp)[fnCandidate[0].type->getSampler().shadow ? 3 : 2]->getAsConstantUnion()) - profileRequires(loc, EEsProfile, 320, Num_AEP_gpu_shader5, AEP_gpu_shader5, - "non-constant offset argument"); - if (! fnCandidate[0].type->getSampler().shadow) - compArg = 3; - break; - case EOpTextureGatherOffsets: - profileRequires(loc, ~EEsProfile, 400, E_GL_ARB_gpu_shader5, feature); - if (! fnCandidate[0].type->getSampler().shadow) - compArg = 3; - // check for constant offsets - if (! (*argp)[fnCandidate[0].type->getSampler().shadow ? 3 : 2]->getAsConstantUnion()) - error(loc, "must be a compile-time constant:", feature, "offsets argument"); - break; - default: - break; - } - - if (compArg > 0 && compArg < fnCandidate.getParamCount()) { - if ((*argp)[compArg]->getAsConstantUnion()) { - int value = (*argp)[compArg]->getAsConstantUnion()->getConstArray()[0].getIConst(); - if (value < 0 || value > 3) - error(loc, "must be 0, 1, 2, or 3:", feature, "component argument"); - } else - error(loc, "must be a compile-time constant:", feature, "component argument"); - } - -#ifdef AMD_EXTENSIONS - bool bias = false; - if (callNode.getOp() == EOpTextureGather) - bias = fnCandidate.getParamCount() > 3; - else if (callNode.getOp() == EOpTextureGatherOffset || - callNode.getOp() == EOpTextureGatherOffsets) - bias = fnCandidate.getParamCount() > 4; - - if (bias) { - featureString = fnCandidate.getName(); - featureString += "with bias argument"; - feature = featureString.c_str(); - profileRequires(loc, ~EEsProfile, 450, nullptr, feature); - requireExtensions(loc, 1, &E_GL_AMD_texture_gather_bias_lod, feature); - } -#endif - - break; - } - -#ifdef AMD_EXTENSIONS - case EOpSparseTextureGather: - case EOpSparseTextureGatherOffset: - case EOpSparseTextureGatherOffsets: - { - bool bias = false; - if (callNode.getOp() == EOpSparseTextureGather) - bias = fnCandidate.getParamCount() > 4; - else if (callNode.getOp() == EOpSparseTextureGatherOffset || - callNode.getOp() == EOpSparseTextureGatherOffsets) - bias = fnCandidate.getParamCount() > 5; - - if (bias) { - featureString = fnCandidate.getName(); - featureString += "with bias argument"; - feature = featureString.c_str(); - profileRequires(loc, ~EEsProfile, 450, nullptr, feature); - requireExtensions(loc, 1, &E_GL_AMD_texture_gather_bias_lod, feature); - } - - break; - } - - case EOpSparseTextureGatherLod: - case EOpSparseTextureGatherLodOffset: - case EOpSparseTextureGatherLodOffsets: - { - requireExtensions(loc, 1, &E_GL_ARB_sparse_texture2, fnCandidate.getName().c_str()); - break; - } - - case EOpSwizzleInvocations: - { - if (! (*argp)[1]->getAsConstantUnion()) - error(loc, "argument must be compile-time constant", "offset", ""); - else { - unsigned offset[4] = {}; - offset[0] = (*argp)[1]->getAsConstantUnion()->getConstArray()[0].getUConst(); - offset[1] = (*argp)[1]->getAsConstantUnion()->getConstArray()[1].getUConst(); - offset[2] = (*argp)[1]->getAsConstantUnion()->getConstArray()[2].getUConst(); - offset[3] = (*argp)[1]->getAsConstantUnion()->getConstArray()[3].getUConst(); - if (offset[0] > 3 || offset[1] > 3 || offset[2] > 3 || offset[3] > 3) - error(loc, "components must be in the range [0, 3]", "offset", ""); - } - - break; - } - - case EOpSwizzleInvocationsMasked: - { - if (! (*argp)[1]->getAsConstantUnion()) - error(loc, "argument must be compile-time constant", "mask", ""); - else { - unsigned mask[3] = {}; - mask[0] = (*argp)[1]->getAsConstantUnion()->getConstArray()[0].getUConst(); - mask[1] = (*argp)[1]->getAsConstantUnion()->getConstArray()[1].getUConst(); - mask[2] = (*argp)[1]->getAsConstantUnion()->getConstArray()[2].getUConst(); - if (mask[0] > 31 || mask[1] > 31 || mask[2] > 31) - error(loc, "components must be in the range [0, 31]", "mask", ""); - } - - break; - } -#endif - - case EOpTextureOffset: - case EOpTextureFetchOffset: - case EOpTextureProjOffset: - case EOpTextureLodOffset: - case EOpTextureProjLodOffset: - case EOpTextureGradOffset: - case EOpTextureProjGradOffset: - { - // Handle texture-offset limits checking - // Pick which argument has to hold constant offsets - int arg = -1; - switch (callNode.getOp()) { - case EOpTextureOffset: arg = 2; break; - case EOpTextureFetchOffset: arg = (arg0->getType().getSampler().dim != EsdRect) ? 3 : 2; break; - case EOpTextureProjOffset: arg = 2; break; - case EOpTextureLodOffset: arg = 3; break; - case EOpTextureProjLodOffset: arg = 3; break; - case EOpTextureGradOffset: arg = 4; break; - case EOpTextureProjGradOffset: arg = 4; break; - default: - assert(0); - break; - } - - if (arg > 0) { - -#ifdef AMD_EXTENSIONS - bool f16ShadowCompare = (*argp)[1]->getAsTyped()->getBasicType() == EbtFloat16 && arg0->getType().getSampler().shadow; - if (f16ShadowCompare) - ++arg; -#endif - if (! (*argp)[arg]->getAsConstantUnion()) - error(loc, "argument must be compile-time constant", "texel offset", ""); - else { - const TType& type = (*argp)[arg]->getAsTyped()->getType(); - for (int c = 0; c < type.getVectorSize(); ++c) { - int offset = (*argp)[arg]->getAsConstantUnion()->getConstArray()[c].getIConst(); - if (offset > resources.maxProgramTexelOffset || offset < resources.minProgramTexelOffset) - error(loc, "value is out of range:", "texel offset", "[gl_MinProgramTexelOffset, gl_MaxProgramTexelOffset]"); - } - } - } - - break; - } - - case EOpTextureQuerySamples: - case EOpImageQuerySamples: - // GL_ARB_shader_texture_image_samples - profileRequires(loc, ~EEsProfile, 450, E_GL_ARB_shader_texture_image_samples, "textureSamples and imageSamples"); - break; - - case EOpImageAtomicAdd: - case EOpImageAtomicMin: - case EOpImageAtomicMax: - case EOpImageAtomicAnd: - case EOpImageAtomicOr: - case EOpImageAtomicXor: - case EOpImageAtomicExchange: - case EOpImageAtomicCompSwap: - { - // Make sure the image types have the correct layout() format and correct argument types - const TType& imageType = arg0->getType(); - if (imageType.getSampler().type == EbtInt || imageType.getSampler().type == EbtUint) { - if (imageType.getQualifier().layoutFormat != ElfR32i && imageType.getQualifier().layoutFormat != ElfR32ui) - error(loc, "only supported on image with format r32i or r32ui", fnCandidate.getName().c_str(), ""); - } else { - if (fnCandidate.getName().compare(0, 19, "imageAtomicExchange") != 0) - error(loc, "only supported on integer images", fnCandidate.getName().c_str(), ""); - else if (imageType.getQualifier().layoutFormat != ElfR32f && profile == EEsProfile) - error(loc, "only supported on image with format r32f", fnCandidate.getName().c_str(), ""); - } - - break; - } - -#ifdef NV_EXTENSIONS - case EOpAtomicAdd: - case EOpAtomicMin: - case EOpAtomicMax: - case EOpAtomicAnd: - case EOpAtomicOr: - case EOpAtomicXor: - case EOpAtomicExchange: - case EOpAtomicCompSwap: - { - if (arg0->getType().getBasicType() == EbtInt64 || arg0->getType().getBasicType() == EbtUint64) - requireExtensions(loc, 1, &E_GL_NV_shader_atomic_int64, fnCandidate.getName().c_str()); - - break; - } -#endif - - case EOpInterpolateAtCentroid: - case EOpInterpolateAtSample: - case EOpInterpolateAtOffset: -#ifdef AMD_EXTENSIONS - case EOpInterpolateAtVertex: -#endif - // Make sure the first argument is an interpolant, or an array element of an interpolant - if (arg0->getType().getQualifier().storage != EvqVaryingIn) { - // It might still be an array element. - // - // We could check more, but the semantics of the first argument are already met; the - // only way to turn an array into a float/vec* is array dereference and swizzle. - // - // ES and desktop 4.3 and earlier: swizzles may not be used - // desktop 4.4 and later: swizzles may be used - bool swizzleOkay = (profile != EEsProfile) && (version >= 440); - const TIntermTyped* base = TIntermediate::findLValueBase(arg0, swizzleOkay); - if (base == nullptr || base->getType().getQualifier().storage != EvqVaryingIn) - error(loc, "first argument must be an interpolant, or interpolant-array element", fnCandidate.getName().c_str(), ""); - } - -#ifdef AMD_EXTENSIONS - if (callNode.getOp() == EOpInterpolateAtVertex) { - if (!arg0->getType().getQualifier().isExplicitInterpolation()) - error(loc, "argument must be qualified as __explicitInterpAMD in", "interpolant", ""); - else { - if (! (*argp)[1]->getAsConstantUnion()) - error(loc, "argument must be compile-time constant", "vertex index", ""); - else { - unsigned vertexIdx = (*argp)[1]->getAsConstantUnion()->getConstArray()[0].getUConst(); - if (vertexIdx > 2) - error(loc, "must be in the range [0, 2]", "vertex index", ""); - } - } - } -#endif - - break; - - case EOpEmitStreamVertex: - case EOpEndStreamPrimitive: - intermediate.setMultiStream(); - break; - - case EOpSubgroupClusteredAdd: - case EOpSubgroupClusteredMul: - case EOpSubgroupClusteredMin: - case EOpSubgroupClusteredMax: - case EOpSubgroupClusteredAnd: - case EOpSubgroupClusteredOr: - case EOpSubgroupClusteredXor: - if ((*argp)[1]->getAsConstantUnion() == nullptr) - error(loc, "argument must be compile-time constant", "cluster size", ""); - else { - int size = (*argp)[1]->getAsConstantUnion()->getConstArray()[0].getIConst(); - if (size < 1) - error(loc, "argument must be at least 1", "cluster size", ""); - else if (!IsPow2(size)) - error(loc, "argument must be a power of 2", "cluster size", ""); - } - break; - - default: - break; - } - - if (callNode.getOp() > EOpSubgroupGuardStart && callNode.getOp() < EOpSubgroupGuardStop) { - // these require SPIR-V 1.3 - if (spvVersion.spv > 0 && spvVersion.spv < EShTargetSpv_1_3) - error(loc, "requires SPIR-V 1.3", "subgroup op", ""); - } -} - -extern bool PureOperatorBuiltins; - -// Deprecated! Use PureOperatorBuiltins == true instead, in which case this -// functionality is handled in builtInOpCheck() instead of here. -// -// Do additional checking of built-in function calls that were not mapped -// to built-in operations (e.g., texturing functions). -// -// Assumes there has been a semantically correct match to a built-in function. -// -void TParseContext::nonOpBuiltInCheck(const TSourceLoc& loc, const TFunction& fnCandidate, TIntermAggregate& callNode) -{ - // Further maintenance of this function is deprecated, because the "correct" - // future-oriented design is to not have to do string compares on function names. - - // If PureOperatorBuiltins == true, then all built-ins should be mapped - // to a TOperator, and this function would then never get called. - - assert(PureOperatorBuiltins == false); - - // built-in texturing functions get their return value precision from the precision of the sampler - if (fnCandidate.getType().getQualifier().precision == EpqNone && - fnCandidate.getParamCount() > 0 && fnCandidate[0].type->getBasicType() == EbtSampler) - callNode.getQualifier().precision = callNode.getSequence()[0]->getAsTyped()->getQualifier().precision; - - if (fnCandidate.getName().compare(0, 7, "texture") == 0) { - if (fnCandidate.getName().compare(0, 13, "textureGather") == 0) { - TString featureString = fnCandidate.getName() + "(...)"; - const char* feature = featureString.c_str(); - profileRequires(loc, EEsProfile, 310, nullptr, feature); - - int compArg = -1; // track which argument, if any, is the constant component argument - if (fnCandidate.getName().compare("textureGatherOffset") == 0) { - // GL_ARB_texture_gather is good enough for 2D non-shadow textures with no component argument - if (fnCandidate[0].type->getSampler().dim == Esd2D && ! fnCandidate[0].type->getSampler().shadow && fnCandidate.getParamCount() == 3) - profileRequires(loc, ~EEsProfile, 400, E_GL_ARB_texture_gather, feature); - else - profileRequires(loc, ~EEsProfile, 400, E_GL_ARB_gpu_shader5, feature); - int offsetArg = fnCandidate[0].type->getSampler().shadow ? 3 : 2; - if (! callNode.getSequence()[offsetArg]->getAsConstantUnion()) - profileRequires(loc, EEsProfile, 320, Num_AEP_gpu_shader5, AEP_gpu_shader5, - "non-constant offset argument"); - if (! fnCandidate[0].type->getSampler().shadow) - compArg = 3; - } else if (fnCandidate.getName().compare("textureGatherOffsets") == 0) { - profileRequires(loc, ~EEsProfile, 400, E_GL_ARB_gpu_shader5, feature); - if (! fnCandidate[0].type->getSampler().shadow) - compArg = 3; - // check for constant offsets - int offsetArg = fnCandidate[0].type->getSampler().shadow ? 3 : 2; - if (! callNode.getSequence()[offsetArg]->getAsConstantUnion()) - error(loc, "must be a compile-time constant:", feature, "offsets argument"); - } else if (fnCandidate.getName().compare("textureGather") == 0) { - // More than two arguments needs gpu_shader5, and rectangular or shadow needs gpu_shader5, - // otherwise, need GL_ARB_texture_gather. - if (fnCandidate.getParamCount() > 2 || fnCandidate[0].type->getSampler().dim == EsdRect || fnCandidate[0].type->getSampler().shadow) { - profileRequires(loc, ~EEsProfile, 400, E_GL_ARB_gpu_shader5, feature); - if (! fnCandidate[0].type->getSampler().shadow) - compArg = 2; - } else - profileRequires(loc, ~EEsProfile, 400, E_GL_ARB_texture_gather, feature); - } - - if (compArg > 0 && compArg < fnCandidate.getParamCount()) { - if (callNode.getSequence()[compArg]->getAsConstantUnion()) { - int value = callNode.getSequence()[compArg]->getAsConstantUnion()->getConstArray()[0].getIConst(); - if (value < 0 || value > 3) - error(loc, "must be 0, 1, 2, or 3:", feature, "component argument"); - } else - error(loc, "must be a compile-time constant:", feature, "component argument"); - } - } else { - // this is only for functions not starting "textureGather"... - if (fnCandidate.getName().find("Offset") != TString::npos) { - - // Handle texture-offset limits checking - int arg = -1; - if (fnCandidate.getName().compare("textureOffset") == 0) - arg = 2; - else if (fnCandidate.getName().compare("texelFetchOffset") == 0) - arg = 3; - else if (fnCandidate.getName().compare("textureProjOffset") == 0) - arg = 2; - else if (fnCandidate.getName().compare("textureLodOffset") == 0) - arg = 3; - else if (fnCandidate.getName().compare("textureProjLodOffset") == 0) - arg = 3; - else if (fnCandidate.getName().compare("textureGradOffset") == 0) - arg = 4; - else if (fnCandidate.getName().compare("textureProjGradOffset") == 0) - arg = 4; - - if (arg > 0) { - if (! callNode.getSequence()[arg]->getAsConstantUnion()) - error(loc, "argument must be compile-time constant", "texel offset", ""); - else { - const TType& type = callNode.getSequence()[arg]->getAsTyped()->getType(); - for (int c = 0; c < type.getVectorSize(); ++c) { - int offset = callNode.getSequence()[arg]->getAsConstantUnion()->getConstArray()[c].getIConst(); - if (offset > resources.maxProgramTexelOffset || offset < resources.minProgramTexelOffset) - error(loc, "value is out of range:", "texel offset", "[gl_MinProgramTexelOffset, gl_MaxProgramTexelOffset]"); - } - } - } - } - } - } - - // GL_ARB_shader_texture_image_samples - if (fnCandidate.getName().compare(0, 14, "textureSamples") == 0 || fnCandidate.getName().compare(0, 12, "imageSamples") == 0) - profileRequires(loc, ~EEsProfile, 450, E_GL_ARB_shader_texture_image_samples, "textureSamples and imageSamples"); - - if (fnCandidate.getName().compare(0, 11, "imageAtomic") == 0) { - const TType& imageType = callNode.getSequence()[0]->getAsTyped()->getType(); - if (imageType.getSampler().type == EbtInt || imageType.getSampler().type == EbtUint) { - if (imageType.getQualifier().layoutFormat != ElfR32i && imageType.getQualifier().layoutFormat != ElfR32ui) - error(loc, "only supported on image with format r32i or r32ui", fnCandidate.getName().c_str(), ""); - } else { - if (fnCandidate.getName().compare(0, 19, "imageAtomicExchange") != 0) - error(loc, "only supported on integer images", fnCandidate.getName().c_str(), ""); - else if (imageType.getQualifier().layoutFormat != ElfR32f && profile == EEsProfile) - error(loc, "only supported on image with format r32f", fnCandidate.getName().c_str(), ""); - } - } -} - -// -// Do any extra checking for a user function call. -// -void TParseContext::userFunctionCallCheck(const TSourceLoc& loc, TIntermAggregate& callNode) -{ - TIntermSequence& arguments = callNode.getSequence(); - - for (int i = 0; i < (int)arguments.size(); ++i) - samplerConstructorLocationCheck(loc, "call argument", arguments[i]); -} - -// -// Emit an error if this is a sampler constructor -// -void TParseContext::samplerConstructorLocationCheck(const TSourceLoc& loc, const char* token, TIntermNode* node) -{ - if (node->getAsOperator() && node->getAsOperator()->getOp() == EOpConstructTextureSampler) - error(loc, "sampler constructor must appear at point of use", token, ""); -} - -// -// Handle seeing a built-in constructor in a grammar production. -// -TFunction* TParseContext::handleConstructorCall(const TSourceLoc& loc, const TPublicType& publicType) -{ - TType type(publicType); - type.getQualifier().precision = EpqNone; - - if (type.isArray()) { - profileRequires(loc, ENoProfile, 120, E_GL_3DL_array_objects, "arrayed constructor"); - profileRequires(loc, EEsProfile, 300, nullptr, "arrayed constructor"); - } - - TOperator op = intermediate.mapTypeToConstructorOp(type); - - if (op == EOpNull) { - error(loc, "cannot construct this type", type.getBasicString(), ""); - op = EOpConstructFloat; - TType errorType(EbtFloat); - type.shallowCopy(errorType); - } - - TString empty(""); - - return new TFunction(&empty, type, op); -} - -// Handle seeing a precision qualifier in the grammar. -void TParseContext::handlePrecisionQualifier(const TSourceLoc& /*loc*/, TQualifier& qualifier, TPrecisionQualifier precision) -{ - if (obeyPrecisionQualifiers()) - qualifier.precision = precision; -} - -// Check for messages to give on seeing a precision qualifier used in a -// declaration in the grammar. -void TParseContext::checkPrecisionQualifier(const TSourceLoc& loc, TPrecisionQualifier) -{ - if (precisionManager.shouldWarnAboutDefaults()) { - warn(loc, "all default precisions are highp; use precision statements to quiet warning, e.g.:\n" - " \"precision mediump int; precision highp float;\"", "", ""); - precisionManager.defaultWarningGiven(); - } -} - -// -// Same error message for all places assignments don't work. -// -void TParseContext::assignError(const TSourceLoc& loc, const char* op, TString left, TString right) -{ - error(loc, "", op, "cannot convert from '%s' to '%s'", - right.c_str(), left.c_str()); -} - -// -// Same error message for all places unary operations don't work. -// -void TParseContext::unaryOpError(const TSourceLoc& loc, const char* op, TString operand) -{ - error(loc, " wrong operand type", op, - "no operation '%s' exists that takes an operand of type %s (or there is no acceptable conversion)", - op, operand.c_str()); -} - -// -// Same error message for all binary operations don't work. -// -void TParseContext::binaryOpError(const TSourceLoc& loc, const char* op, TString left, TString right) -{ - error(loc, " wrong operand types:", op, - "no operation '%s' exists that takes a left-hand operand of type '%s' and " - "a right operand of type '%s' (or there is no acceptable conversion)", - op, left.c_str(), right.c_str()); -} - -// -// A basic type of EbtVoid is a key that the name string was seen in the source, but -// it was not found as a variable in the symbol table. If so, give the error -// message and insert a dummy variable in the symbol table to prevent future errors. -// -void TParseContext::variableCheck(TIntermTyped*& nodePtr) -{ - TIntermSymbol* symbol = nodePtr->getAsSymbolNode(); - if (! symbol) - return; - - if (symbol->getType().getBasicType() == EbtVoid) { - const char *extraInfoFormat = ""; - if (spvVersion.vulkan != 0 && symbol->getName() == "gl_VertexID") { - extraInfoFormat = "(Did you mean gl_VertexIndex?)"; - } else if (spvVersion.vulkan != 0 && symbol->getName() == "gl_InstanceID") { - extraInfoFormat = "(Did you mean gl_InstanceIndex?)"; - } - error(symbol->getLoc(), "undeclared identifier", symbol->getName().c_str(), extraInfoFormat); - - // Add to symbol table to prevent future error messages on the same name - if (symbol->getName().size() > 0) { - TVariable* fakeVariable = new TVariable(&symbol->getName(), TType(EbtFloat)); - symbolTable.insert(*fakeVariable); - - // substitute a symbol node for this new variable - nodePtr = intermediate.addSymbol(*fakeVariable, symbol->getLoc()); - } - } else { - switch (symbol->getQualifier().storage) { - case EvqPointCoord: - profileRequires(symbol->getLoc(), ENoProfile, 120, nullptr, "gl_PointCoord"); - break; - default: break; // some compilers want this - } - } -} - -// -// Both test and if necessary, spit out an error, to see if the node is really -// an l-value that can be operated on this way. -// -// Returns true if there was an error. -// -bool TParseContext::lValueErrorCheck(const TSourceLoc& loc, const char* op, TIntermTyped* node) -{ - TIntermBinary* binaryNode = node->getAsBinaryNode(); - - if (binaryNode) { - bool errorReturn = false; - - switch(binaryNode->getOp()) { - case EOpIndexDirect: - case EOpIndexIndirect: - // ... tessellation control shader ... - // If a per-vertex output variable is used as an l-value, it is a - // compile-time or link-time error if the expression indicating the - // vertex index is not the identifier gl_InvocationID. - if (language == EShLangTessControl) { - const TType& leftType = binaryNode->getLeft()->getType(); - if (leftType.getQualifier().storage == EvqVaryingOut && ! leftType.getQualifier().patch && binaryNode->getLeft()->getAsSymbolNode()) { - // we have a per-vertex output - const TIntermSymbol* rightSymbol = binaryNode->getRight()->getAsSymbolNode(); - if (! rightSymbol || rightSymbol->getQualifier().builtIn != EbvInvocationId) - error(loc, "tessellation-control per-vertex output l-value must be indexed with gl_InvocationID", "[]", ""); - } - } - - break; // left node is checked by base class - case EOpIndexDirectStruct: - break; // left node is checked by base class - case EOpVectorSwizzle: - errorReturn = lValueErrorCheck(loc, op, binaryNode->getLeft()); - if (!errorReturn) { - int offset[4] = {0,0,0,0}; - - TIntermTyped* rightNode = binaryNode->getRight(); - TIntermAggregate *aggrNode = rightNode->getAsAggregate(); - - for (TIntermSequence::iterator p = aggrNode->getSequence().begin(); - p != aggrNode->getSequence().end(); p++) { - int value = (*p)->getAsTyped()->getAsConstantUnion()->getConstArray()[0].getIConst(); - offset[value]++; - if (offset[value] > 1) { - error(loc, " l-value of swizzle cannot have duplicate components", op, "", ""); - - return true; - } - } - } - - return errorReturn; - default: - break; - } - - if (errorReturn) { - error(loc, " l-value required", op, "", ""); - return true; - } - } - - // Let the base class check errors - if (TParseContextBase::lValueErrorCheck(loc, op, node)) - return true; - - const char* symbol = nullptr; - TIntermSymbol* symNode = node->getAsSymbolNode(); - if (symNode != nullptr) - symbol = symNode->getName().c_str(); - - const char* message = nullptr; - switch (node->getQualifier().storage) { - case EvqVaryingIn: message = "can't modify shader input"; break; - case EvqInstanceId: message = "can't modify gl_InstanceID"; break; - case EvqVertexId: message = "can't modify gl_VertexID"; break; - case EvqFace: message = "can't modify gl_FrontFace"; break; - case EvqFragCoord: message = "can't modify gl_FragCoord"; break; - case EvqPointCoord: message = "can't modify gl_PointCoord"; break; - case EvqFragDepth: - intermediate.setDepthReplacing(); - // "In addition, it is an error to statically write to gl_FragDepth in the fragment shader." - if (profile == EEsProfile && intermediate.getEarlyFragmentTests()) - message = "can't modify gl_FragDepth if using early_fragment_tests"; - break; - - default: - break; - } - - if (message == nullptr && binaryNode == nullptr && symNode == nullptr) { - error(loc, " l-value required", op, "", ""); - - return true; - } - - // - // Everything else is okay, no error. - // - if (message == nullptr) - return false; - - // - // If we get here, we have an error and a message. - // - if (symNode) - error(loc, " l-value required", op, "\"%s\" (%s)", symbol, message); - else - error(loc, " l-value required", op, "(%s)", message); - - return true; -} - -// Test for and give an error if the node can't be read from. -void TParseContext::rValueErrorCheck(const TSourceLoc& loc, const char* op, TIntermTyped* node) -{ - // Let the base class check errors - TParseContextBase::rValueErrorCheck(loc, op, node); - -#ifdef AMD_EXTENSIONS - TIntermSymbol* symNode = node->getAsSymbolNode(); - if (!(symNode && symNode->getQualifier().writeonly)) // base class checks - if (symNode && symNode->getQualifier().explicitInterp) - error(loc, "can't read from explicitly-interpolated object: ", op, symNode->getName().c_str()); -#endif -} - -// -// Both test, and if necessary spit out an error, to see if the node is really -// a constant. -// -void TParseContext::constantValueCheck(TIntermTyped* node, const char* token) -{ - if (! node->getQualifier().isConstant()) - error(node->getLoc(), "constant expression required", token, ""); -} - -// -// Both test, and if necessary spit out an error, to see if the node is really -// an integer. -// -void TParseContext::integerCheck(const TIntermTyped* node, const char* token) -{ - if ((node->getBasicType() == EbtInt || node->getBasicType() == EbtUint) && node->isScalar()) - return; - - error(node->getLoc(), "scalar integer expression required", token, ""); -} - -// -// Both test, and if necessary spit out an error, to see if we are currently -// globally scoped. -// -void TParseContext::globalCheck(const TSourceLoc& loc, const char* token) -{ - if (! symbolTable.atGlobalLevel()) - error(loc, "not allowed in nested scope", token, ""); -} - -// -// Reserved errors for GLSL. -// -void TParseContext::reservedErrorCheck(const TSourceLoc& loc, const TString& identifier) -{ - // "Identifiers starting with "gl_" are reserved for use by OpenGL, and may not be - // declared in a shader; this results in a compile-time error." - if (! symbolTable.atBuiltInLevel()) { - if (builtInName(identifier)) - error(loc, "identifiers starting with \"gl_\" are reserved", identifier.c_str(), ""); - - // "__" are not supposed to be an error. ES 310 (and desktop) added the clarification: - // "In addition, all identifiers containing two consecutive underscores (__) are - // reserved; using such a name does not itself result in an error, but may result - // in undefined behavior." - // however, before that, ES tests required an error. - if (identifier.find("__") != TString::npos) { - if (profile == EEsProfile && version <= 300) - error(loc, "identifiers containing consecutive underscores (\"__\") are reserved, and an error if version <= 300", identifier.c_str(), ""); - else - warn(loc, "identifiers containing consecutive underscores (\"__\") are reserved", identifier.c_str(), ""); - } - } -} - -// -// Reserved errors for the preprocessor. -// -void TParseContext::reservedPpErrorCheck(const TSourceLoc& loc, const char* identifier, const char* op) -{ - // "__" are not supposed to be an error. ES 310 (and desktop) added the clarification: - // "All macro names containing two consecutive underscores ( __ ) are reserved; - // defining such a name does not itself result in an error, but may result in - // undefined behavior. All macro names prefixed with "GL_" ("GL" followed by a - // single underscore) are also reserved, and defining such a name results in a - // compile-time error." - // however, before that, ES tests required an error. - if (strncmp(identifier, "GL_", 3) == 0) - ppError(loc, "names beginning with \"GL_\" can't be (un)defined:", op, identifier); - else if (strncmp(identifier, "defined", 8) == 0) - ppError(loc, "\"defined\" can't be (un)defined:", op, identifier); - else if (strstr(identifier, "__") != 0) { - if (profile == EEsProfile && version >= 300 && - (strcmp(identifier, "__LINE__") == 0 || - strcmp(identifier, "__FILE__") == 0 || - strcmp(identifier, "__VERSION__") == 0)) - ppError(loc, "predefined names can't be (un)defined:", op, identifier); - else { - if (profile == EEsProfile && version <= 300) - ppError(loc, "names containing consecutive underscores are reserved, and an error if version <= 300:", op, identifier); - else - ppWarn(loc, "names containing consecutive underscores are reserved:", op, identifier); - } - } -} - -// -// See if this version/profile allows use of the line-continuation character '\'. -// -// Returns true if a line continuation should be done. -// -bool TParseContext::lineContinuationCheck(const TSourceLoc& loc, bool endOfComment) -{ - const char* message = "line continuation"; - - bool lineContinuationAllowed = (profile == EEsProfile && version >= 300) || - (profile != EEsProfile && (version >= 420 || extensionTurnedOn(E_GL_ARB_shading_language_420pack))); - - if (endOfComment) { - if (lineContinuationAllowed) - warn(loc, "used at end of comment; the following line is still part of the comment", message, ""); - else - warn(loc, "used at end of comment, but this version does not provide line continuation", message, ""); - - return lineContinuationAllowed; - } - - if (relaxedErrors()) { - if (! lineContinuationAllowed) - warn(loc, "not allowed in this version", message, ""); - return true; - } else { - profileRequires(loc, EEsProfile, 300, nullptr, message); - profileRequires(loc, ~EEsProfile, 420, E_GL_ARB_shading_language_420pack, message); - } - - return lineContinuationAllowed; -} - -bool TParseContext::builtInName(const TString& identifier) -{ - return identifier.compare(0, 3, "gl_") == 0; -} - -// -// Make sure there is enough data and not too many arguments provided to the -// constructor to build something of the type of the constructor. Also returns -// the type of the constructor. -// -// Part of establishing type is establishing specialization-constness. -// We don't yet know "top down" whether type is a specialization constant, -// but a const constructor can becomes a specialization constant if any of -// its children are, subject to KHR_vulkan_glsl rules: -// -// - int(), uint(), and bool() constructors for type conversions -// from any of the following types to any of the following types: -// * int -// * uint -// * bool -// - vector versions of the above conversion constructors -// -// Returns true if there was an error in construction. -// -bool TParseContext::constructorError(const TSourceLoc& loc, TIntermNode* node, TFunction& function, TOperator op, TType& type) -{ - type.shallowCopy(function.getType()); - - bool constructingMatrix = false; - switch(op) { - case EOpConstructTextureSampler: - return constructorTextureSamplerError(loc, function); - case EOpConstructMat2x2: - case EOpConstructMat2x3: - case EOpConstructMat2x4: - case EOpConstructMat3x2: - case EOpConstructMat3x3: - case EOpConstructMat3x4: - case EOpConstructMat4x2: - case EOpConstructMat4x3: - case EOpConstructMat4x4: - case EOpConstructDMat2x2: - case EOpConstructDMat2x3: - case EOpConstructDMat2x4: - case EOpConstructDMat3x2: - case EOpConstructDMat3x3: - case EOpConstructDMat3x4: - case EOpConstructDMat4x2: - case EOpConstructDMat4x3: - case EOpConstructDMat4x4: - case EOpConstructF16Mat2x2: - case EOpConstructF16Mat2x3: - case EOpConstructF16Mat2x4: - case EOpConstructF16Mat3x2: - case EOpConstructF16Mat3x3: - case EOpConstructF16Mat3x4: - case EOpConstructF16Mat4x2: - case EOpConstructF16Mat4x3: - case EOpConstructF16Mat4x4: - constructingMatrix = true; - break; - default: - break; - } - - // - // Walk the arguments for first-pass checks and collection of information. - // - - int size = 0; - bool constType = true; - bool specConstType = false; // value is only valid if constType is true - bool full = false; - bool overFull = false; - bool matrixInMatrix = false; - bool arrayArg = false; - bool floatArgument = false; - for (int arg = 0; arg < function.getParamCount(); ++arg) { - if (function[arg].type->isArray()) { - if (function[arg].type->isUnsizedArray()) { - // Can't construct from an unsized array. - error(loc, "array argument must be sized", "constructor", ""); - return true; - } - arrayArg = true; - } - if (constructingMatrix && function[arg].type->isMatrix()) - matrixInMatrix = true; - - // 'full' will go to true when enough args have been seen. If we loop - // again, there is an extra argument. - if (full) { - // For vectors and matrices, it's okay to have too many components - // available, but not okay to have unused arguments. - overFull = true; - } - - size += function[arg].type->computeNumComponents(); - if (op != EOpConstructStruct && ! type.isArray() && size >= type.computeNumComponents()) - full = true; - - if (! function[arg].type->getQualifier().isConstant()) - constType = false; - if (function[arg].type->getQualifier().isSpecConstant()) - specConstType = true; - if (function[arg].type->isFloatingDomain()) - floatArgument = true; - } - - // inherit constness from children - if (constType) { - bool makeSpecConst; - // Finish pinning down spec-const semantics - if (specConstType) { - switch (op) { - case EOpConstructInt8: - case EOpConstructUint8: - case EOpConstructInt16: - case EOpConstructUint16: - case EOpConstructInt: - case EOpConstructUint: - case EOpConstructInt64: - case EOpConstructUint64: - case EOpConstructBool: - case EOpConstructBVec2: - case EOpConstructBVec3: - case EOpConstructBVec4: - case EOpConstructI8Vec2: - case EOpConstructI8Vec3: - case EOpConstructI8Vec4: - case EOpConstructU8Vec2: - case EOpConstructU8Vec3: - case EOpConstructU8Vec4: - case EOpConstructI16Vec2: - case EOpConstructI16Vec3: - case EOpConstructI16Vec4: - case EOpConstructU16Vec2: - case EOpConstructU16Vec3: - case EOpConstructU16Vec4: - case EOpConstructIVec2: - case EOpConstructIVec3: - case EOpConstructIVec4: - case EOpConstructUVec2: - case EOpConstructUVec3: - case EOpConstructUVec4: - case EOpConstructI64Vec2: - case EOpConstructI64Vec3: - case EOpConstructI64Vec4: - case EOpConstructU64Vec2: - case EOpConstructU64Vec3: - case EOpConstructU64Vec4: - // This was the list of valid ones, if they aren't converting from float - // and aren't making an array. - makeSpecConst = ! floatArgument && ! type.isArray(); - break; - default: - // anything else wasn't white-listed in the spec as a conversion - makeSpecConst = false; - break; - } - } else - makeSpecConst = false; - - if (makeSpecConst) - type.getQualifier().makeSpecConstant(); - else if (specConstType) - type.getQualifier().makeTemporary(); - else - type.getQualifier().storage = EvqConst; - } - - if (type.isArray()) { - if (function.getParamCount() == 0) { - error(loc, "array constructor must have at least one argument", "constructor", ""); - return true; - } - - if (type.isUnsizedArray()) { - // auto adapt the constructor type to the number of arguments - type.changeOuterArraySize(function.getParamCount()); - } else if (type.getOuterArraySize() != function.getParamCount()) { - error(loc, "array constructor needs one argument per array element", "constructor", ""); - return true; - } - - if (type.isArrayOfArrays()) { - // Types have to match, but we're still making the type. - // Finish making the type, and the comparison is done later - // when checking for conversion. - TArraySizes& arraySizes = *type.getArraySizes(); - - // At least the dimensionalities have to match. - if (! function[0].type->isArray() || - arraySizes.getNumDims() != function[0].type->getArraySizes()->getNumDims() + 1) { - error(loc, "array constructor argument not correct type to construct array element", "constructor", ""); - return true; - } - - if (arraySizes.isInnerUnsized()) { - // "Arrays of arrays ..., and the size for any dimension is optional" - // That means we need to adopt (from the first argument) the other array sizes into the type. - for (int d = 1; d < arraySizes.getNumDims(); ++d) { - if (arraySizes.getDimSize(d) == UnsizedArraySize) { - arraySizes.setDimSize(d, function[0].type->getArraySizes()->getDimSize(d - 1)); - } - } - } - } - } - - if (arrayArg && op != EOpConstructStruct && ! type.isArrayOfArrays()) { - error(loc, "constructing non-array constituent from array argument", "constructor", ""); - return true; - } - - if (matrixInMatrix && ! type.isArray()) { - profileRequires(loc, ENoProfile, 120, nullptr, "constructing matrix from matrix"); - - // "If a matrix argument is given to a matrix constructor, - // it is a compile-time error to have any other arguments." - if (function.getParamCount() != 1) - error(loc, "matrix constructed from matrix can only have one argument", "constructor", ""); - return false; - } - - if (overFull) { - error(loc, "too many arguments", "constructor", ""); - return true; - } - - if (op == EOpConstructStruct && ! type.isArray() && (int)type.getStruct()->size() != function.getParamCount()) { - error(loc, "Number of constructor parameters does not match the number of structure fields", "constructor", ""); - return true; - } - - if ((op != EOpConstructStruct && size != 1 && size < type.computeNumComponents()) || - (op == EOpConstructStruct && size < type.computeNumComponents())) { - error(loc, "not enough data provided for construction", "constructor", ""); - return true; - } - - TIntermTyped* typed = node->getAsTyped(); - if (typed == nullptr) { - error(loc, "constructor argument does not have a type", "constructor", ""); - return true; - } - if (op != EOpConstructStruct && typed->getBasicType() == EbtSampler) { - error(loc, "cannot convert a sampler", "constructor", ""); - return true; - } - if (op != EOpConstructStruct && typed->getBasicType() == EbtAtomicUint) { - error(loc, "cannot convert an atomic_uint", "constructor", ""); - return true; - } - if (typed->getBasicType() == EbtVoid) { - error(loc, "cannot convert a void", "constructor", ""); - return true; - } - - return false; -} - -// Verify all the correct semantics for constructing a combined texture/sampler. -// Return true if the semantics are incorrect. -bool TParseContext::constructorTextureSamplerError(const TSourceLoc& loc, const TFunction& function) -{ - TString constructorName = function.getType().getBasicTypeString(); // TODO: performance: should not be making copy; interface needs to change - const char* token = constructorName.c_str(); - - // exactly two arguments needed - if (function.getParamCount() != 2) { - error(loc, "sampler-constructor requires two arguments", token, ""); - return true; - } - - // For now, not allowing arrayed constructors, the rest of this function - // is set up to allow them, if this test is removed: - if (function.getType().isArray()) { - error(loc, "sampler-constructor cannot make an array of samplers", token, ""); - return true; - } - - // first argument - // * the constructor's first argument must be a texture type - // * the dimensionality (1D, 2D, 3D, Cube, Rect, Buffer, MS, and Array) - // of the texture type must match that of the constructed sampler type - // (that is, the suffixes of the type of the first argument and the - // type of the constructor will be spelled the same way) - if (function[0].type->getBasicType() != EbtSampler || - ! function[0].type->getSampler().isTexture() || - function[0].type->isArray()) { - error(loc, "sampler-constructor first argument must be a scalar textureXXX type", token, ""); - return true; - } - // simulate the first argument's impact on the result type, so it can be compared with the encapsulated operator!=() - TSampler texture = function.getType().getSampler(); - texture.combined = false; - texture.shadow = false; - if (texture != function[0].type->getSampler()) { - error(loc, "sampler-constructor first argument must match type and dimensionality of constructor type", token, ""); - return true; - } - - // second argument - // * the constructor's second argument must be a scalar of type - // *sampler* or *samplerShadow* - // * the presence or absence of depth comparison (Shadow) must match - // between the constructed sampler type and the type of the second argument - if ( function[1].type->getBasicType() != EbtSampler || - ! function[1].type->getSampler().isPureSampler() || - function[1].type->isArray()) { - error(loc, "sampler-constructor second argument must be a scalar type 'sampler'", token, ""); - return true; - } - if (function.getType().getSampler().shadow != function[1].type->getSampler().shadow) { - error(loc, "sampler-constructor second argument presence of shadow must match constructor presence of shadow", token, ""); - return true; - } - - return false; -} - -// Checks to see if a void variable has been declared and raise an error message for such a case -// -// returns true in case of an error -// -bool TParseContext::voidErrorCheck(const TSourceLoc& loc, const TString& identifier, const TBasicType basicType) -{ - if (basicType == EbtVoid) { - error(loc, "illegal use of type 'void'", identifier.c_str(), ""); - return true; - } - - return false; -} - -// Checks to see if the node (for the expression) contains a scalar boolean expression or not -void TParseContext::boolCheck(const TSourceLoc& loc, const TIntermTyped* type) -{ - if (type->getBasicType() != EbtBool || type->isArray() || type->isMatrix() || type->isVector()) - error(loc, "boolean expression expected", "", ""); -} - -// This function checks to see if the node (for the expression) contains a scalar boolean expression or not -void TParseContext::boolCheck(const TSourceLoc& loc, const TPublicType& pType) -{ - if (pType.basicType != EbtBool || pType.arraySizes || pType.matrixCols > 1 || (pType.vectorSize > 1)) - error(loc, "boolean expression expected", "", ""); -} - -void TParseContext::samplerCheck(const TSourceLoc& loc, const TType& type, const TString& identifier, TIntermTyped* /*initializer*/) -{ - // Check that the appropriate extension is enabled if external sampler is used. - // There are two extensions. The correct one must be used based on GLSL version. - if (type.getBasicType() == EbtSampler && type.getSampler().external) { - if (version < 300) { - requireExtensions(loc, 1, &E_GL_OES_EGL_image_external, "samplerExternalOES"); - } else { - requireExtensions(loc, 1, &E_GL_OES_EGL_image_external_essl3, "samplerExternalOES"); - } - } - - if (type.getQualifier().storage == EvqUniform) - return; - - if (type.getBasicType() == EbtStruct && containsFieldWithBasicType(type, EbtSampler)) - error(loc, "non-uniform struct contains a sampler or image:", type.getBasicTypeString().c_str(), identifier.c_str()); - else if (type.getBasicType() == EbtSampler && type.getQualifier().storage != EvqUniform) { - // non-uniform sampler - // not yet: okay if it has an initializer - // if (! initializer) - error(loc, "sampler/image types can only be used in uniform variables or function parameters:", type.getBasicTypeString().c_str(), identifier.c_str()); - } -} - -void TParseContext::atomicUintCheck(const TSourceLoc& loc, const TType& type, const TString& identifier) -{ - if (type.getQualifier().storage == EvqUniform) - return; - - if (type.getBasicType() == EbtStruct && containsFieldWithBasicType(type, EbtAtomicUint)) - error(loc, "non-uniform struct contains an atomic_uint:", type.getBasicTypeString().c_str(), identifier.c_str()); - else if (type.getBasicType() == EbtAtomicUint && type.getQualifier().storage != EvqUniform) - error(loc, "atomic_uints can only be used in uniform variables or function parameters:", type.getBasicTypeString().c_str(), identifier.c_str()); -} - -void TParseContext::transparentOpaqueCheck(const TSourceLoc& loc, const TType& type, const TString& identifier) -{ - if (parsingBuiltins) - return; - - if (type.getQualifier().storage != EvqUniform) - return; - - if (type.containsNonOpaque()) { - // Vulkan doesn't allow transparent uniforms outside of blocks - if (spvVersion.vulkan > 0) - vulkanRemoved(loc, "non-opaque uniforms outside a block"); - // OpenGL wants locations on these (unless they are getting automapped) - if (spvVersion.openGl > 0 && !type.getQualifier().hasLocation() && !intermediate.getAutoMapLocations()) - error(loc, "non-opaque uniform variables need a layout(location=L)", identifier.c_str(), ""); - } -} - -// -// Qualifier checks knowing the qualifier and that it is a member of a struct/block. -// -void TParseContext::memberQualifierCheck(glslang::TPublicType& publicType) -{ - globalQualifierFixCheck(publicType.loc, publicType.qualifier); - checkNoShaderLayouts(publicType.loc, publicType.shaderQualifiers); - if (publicType.qualifier.isNonUniform()) { - error(publicType.loc, "not allowed on block or structure members", "nonuniformEXT", ""); - publicType.qualifier.nonUniform = false; - } -} - -// -// Check/fix just a full qualifier (no variables or types yet, but qualifier is complete) at global level. -// -void TParseContext::globalQualifierFixCheck(const TSourceLoc& loc, TQualifier& qualifier) -{ - bool nonuniformOkay = false; - - // move from parameter/unknown qualifiers to pipeline in/out qualifiers - switch (qualifier.storage) { - case EvqIn: - profileRequires(loc, ENoProfile, 130, nullptr, "in for stage inputs"); - profileRequires(loc, EEsProfile, 300, nullptr, "in for stage inputs"); - qualifier.storage = EvqVaryingIn; - nonuniformOkay = true; - break; - case EvqOut: - profileRequires(loc, ENoProfile, 130, nullptr, "out for stage outputs"); - profileRequires(loc, EEsProfile, 300, nullptr, "out for stage outputs"); - qualifier.storage = EvqVaryingOut; - break; - case EvqInOut: - qualifier.storage = EvqVaryingIn; - error(loc, "cannot use 'inout' at global scope", "", ""); - break; - case EvqGlobal: - case EvqTemporary: - nonuniformOkay = true; - break; - default: - break; - } - - if (!nonuniformOkay && qualifier.nonUniform) - error(loc, "for non-parameter, can only apply to 'in' or no storage qualifier", "nonuniformEXT", ""); - - invariantCheck(loc, qualifier); -} - -// -// Check a full qualifier and type (no variable yet) at global level. -// -void TParseContext::globalQualifierTypeCheck(const TSourceLoc& loc, const TQualifier& qualifier, const TPublicType& publicType) -{ - if (! symbolTable.atGlobalLevel()) - return; - - if (qualifier.isMemory() && ! publicType.isImage() && publicType.qualifier.storage != EvqBuffer) - error(loc, "memory qualifiers cannot be used on this type", "", ""); - - if (qualifier.storage == EvqBuffer && publicType.basicType != EbtBlock) - error(loc, "buffers can be declared only as blocks", "buffer", ""); - - if (qualifier.storage != EvqVaryingIn && qualifier.storage != EvqVaryingOut) - return; - - if (publicType.shaderQualifiers.blendEquation) - error(loc, "can only be applied to a standalone 'out'", "blend equation", ""); - - // now, knowing it is a shader in/out, do all the in/out semantic checks - - if (publicType.basicType == EbtBool && !parsingBuiltins) { - error(loc, "cannot be bool", GetStorageQualifierString(qualifier.storage), ""); - return; - } - - if (isTypeInt(publicType.basicType) || publicType.basicType == EbtDouble) - profileRequires(loc, EEsProfile, 300, nullptr, "shader input/output"); - -#ifdef AMD_EXTENSIONS - if (! qualifier.flat && ! qualifier.explicitInterp) { -#else - if (!qualifier.flat) { -#endif - if (isTypeInt(publicType.basicType) || - publicType.basicType == EbtDouble || - (publicType.userDef && (publicType.userDef->containsBasicType(EbtInt8) || - publicType.userDef->containsBasicType(EbtUint8) || - publicType.userDef->containsBasicType(EbtInt16) || - publicType.userDef->containsBasicType(EbtUint16) || - publicType.userDef->containsBasicType(EbtInt) || - publicType.userDef->containsBasicType(EbtUint) || - publicType.userDef->containsBasicType(EbtInt64) || - publicType.userDef->containsBasicType(EbtUint64) || - publicType.userDef->containsBasicType(EbtDouble)))) { - if (qualifier.storage == EvqVaryingIn && language == EShLangFragment) - error(loc, "must be qualified as flat", TType::getBasicString(publicType.basicType), GetStorageQualifierString(qualifier.storage)); - else if (qualifier.storage == EvqVaryingOut && language == EShLangVertex && version == 300) - error(loc, "must be qualified as flat", TType::getBasicString(publicType.basicType), GetStorageQualifierString(qualifier.storage)); - } - } - - if (qualifier.patch && qualifier.isInterpolation()) - error(loc, "cannot use interpolation qualifiers with patch", "patch", ""); - - if (qualifier.storage == EvqVaryingIn) { - switch (language) { - case EShLangVertex: - if (publicType.basicType == EbtStruct) { - error(loc, "cannot be a structure or array", GetStorageQualifierString(qualifier.storage), ""); - return; - } - if (publicType.arraySizes) { - requireProfile(loc, ~EEsProfile, "vertex input arrays"); - profileRequires(loc, ENoProfile, 150, nullptr, "vertex input arrays"); - } - if (publicType.basicType == EbtDouble) - profileRequires(loc, ~EEsProfile, 410, nullptr, "vertex-shader `double` type input"); - if (qualifier.isAuxiliary() || qualifier.isInterpolation() || qualifier.isMemory() || qualifier.invariant) - error(loc, "vertex input cannot be further qualified", "", ""); - break; - - case EShLangTessControl: - if (qualifier.patch) - error(loc, "can only use on output in tessellation-control shader", "patch", ""); - break; - - case EShLangTessEvaluation: - break; - - case EShLangGeometry: - break; - - case EShLangFragment: - if (publicType.userDef) { - profileRequires(loc, EEsProfile, 300, nullptr, "fragment-shader struct input"); - profileRequires(loc, ~EEsProfile, 150, nullptr, "fragment-shader struct input"); - if (publicType.userDef->containsStructure()) - requireProfile(loc, ~EEsProfile, "fragment-shader struct input containing structure"); - if (publicType.userDef->containsArray()) - requireProfile(loc, ~EEsProfile, "fragment-shader struct input containing an array"); - } - break; - - case EShLangCompute: - if (! symbolTable.atBuiltInLevel()) - error(loc, "global storage input qualifier cannot be used in a compute shader", "in", ""); - break; - - default: - break; - } - } else { - // qualifier.storage == EvqVaryingOut - switch (language) { - case EShLangVertex: - if (publicType.userDef) { - profileRequires(loc, EEsProfile, 300, nullptr, "vertex-shader struct output"); - profileRequires(loc, ~EEsProfile, 150, nullptr, "vertex-shader struct output"); - if (publicType.userDef->containsStructure()) - requireProfile(loc, ~EEsProfile, "vertex-shader struct output containing structure"); - if (publicType.userDef->containsArray()) - requireProfile(loc, ~EEsProfile, "vertex-shader struct output containing an array"); - } - - break; - - case EShLangTessControl: - break; - - case EShLangTessEvaluation: - if (qualifier.patch) - error(loc, "can only use on input in tessellation-evaluation shader", "patch", ""); - break; - - case EShLangGeometry: - break; - - case EShLangFragment: - profileRequires(loc, EEsProfile, 300, nullptr, "fragment shader output"); - if (publicType.basicType == EbtStruct) { - error(loc, "cannot be a structure", GetStorageQualifierString(qualifier.storage), ""); - return; - } - if (publicType.matrixRows > 0) { - error(loc, "cannot be a matrix", GetStorageQualifierString(qualifier.storage), ""); - return; - } - if (qualifier.isAuxiliary()) - error(loc, "can't use auxiliary qualifier on a fragment output", "centroid/sample/patch", ""); - if (qualifier.isInterpolation()) - error(loc, "can't use interpolation qualifier on a fragment output", "flat/smooth/noperspective", ""); - if (publicType.basicType == EbtDouble || publicType.basicType == EbtInt64 || publicType.basicType == EbtUint64) - error(loc, "cannot contain a double, int64, or uint64", GetStorageQualifierString(qualifier.storage), ""); - break; - - case EShLangCompute: - error(loc, "global storage output qualifier cannot be used in a compute shader", "out", ""); - break; - - default: - break; - } - } -} - -// -// Merge characteristics of the 'src' qualifier into the 'dst'. -// If there is duplication, issue error messages, unless 'force' -// is specified, which means to just override default settings. -// -// Also, when force is false, it will be assumed that 'src' follows -// 'dst', for the purpose of error checking order for versions -// that require specific orderings of qualifiers. -// -void TParseContext::mergeQualifiers(const TSourceLoc& loc, TQualifier& dst, const TQualifier& src, bool force) -{ - // Multiple auxiliary qualifiers (mostly done later by 'individual qualifiers') - if (src.isAuxiliary() && dst.isAuxiliary()) - error(loc, "can only have one auxiliary qualifier (centroid, patch, and sample)", "", ""); - - // Multiple interpolation qualifiers (mostly done later by 'individual qualifiers') - if (src.isInterpolation() && dst.isInterpolation()) -#ifdef AMD_EXTENSIONS - error(loc, "can only have one interpolation qualifier (flat, smooth, noperspective, __explicitInterpAMD)", "", ""); -#else - error(loc, "can only have one interpolation qualifier (flat, smooth, noperspective)", "", ""); -#endif - - // Ordering - if (! force && ((profile != EEsProfile && version < 420) || - (profile == EEsProfile && version < 310)) - && ! extensionTurnedOn(E_GL_ARB_shading_language_420pack)) { - // non-function parameters - if (src.noContraction && (dst.invariant || dst.isInterpolation() || dst.isAuxiliary() || dst.storage != EvqTemporary || dst.precision != EpqNone)) - error(loc, "precise qualifier must appear first", "", ""); - if (src.invariant && (dst.isInterpolation() || dst.isAuxiliary() || dst.storage != EvqTemporary || dst.precision != EpqNone)) - error(loc, "invariant qualifier must appear before interpolation, storage, and precision qualifiers ", "", ""); - else if (src.isInterpolation() && (dst.isAuxiliary() || dst.storage != EvqTemporary || dst.precision != EpqNone)) - error(loc, "interpolation qualifiers must appear before storage and precision qualifiers", "", ""); - else if (src.isAuxiliary() && (dst.storage != EvqTemporary || dst.precision != EpqNone)) - error(loc, "Auxiliary qualifiers (centroid, patch, and sample) must appear before storage and precision qualifiers", "", ""); - else if (src.storage != EvqTemporary && (dst.precision != EpqNone)) - error(loc, "precision qualifier must appear as last qualifier", "", ""); - - // function parameters - if (src.noContraction && (dst.storage == EvqConst || dst.storage == EvqIn || dst.storage == EvqOut)) - error(loc, "precise qualifier must appear first", "", ""); - if (src.storage == EvqConst && (dst.storage == EvqIn || dst.storage == EvqOut)) - error(loc, "in/out must appear before const", "", ""); - } - - // Storage qualification - if (dst.storage == EvqTemporary || dst.storage == EvqGlobal) - dst.storage = src.storage; - else if ((dst.storage == EvqIn && src.storage == EvqOut) || - (dst.storage == EvqOut && src.storage == EvqIn)) - dst.storage = EvqInOut; - else if ((dst.storage == EvqIn && src.storage == EvqConst) || - (dst.storage == EvqConst && src.storage == EvqIn)) - dst.storage = EvqConstReadOnly; - else if (src.storage != EvqTemporary && - src.storage != EvqGlobal) - error(loc, "too many storage qualifiers", GetStorageQualifierString(src.storage), ""); - - // Precision qualifiers - if (! force && src.precision != EpqNone && dst.precision != EpqNone) - error(loc, "only one precision qualifier allowed", GetPrecisionQualifierString(src.precision), ""); - if (dst.precision == EpqNone || (force && src.precision != EpqNone)) - dst.precision = src.precision; - - // Layout qualifiers - mergeObjectLayoutQualifiers(dst, src, false); - - // individual qualifiers - bool repeated = false; - #define MERGE_SINGLETON(field) repeated |= dst.field && src.field; dst.field |= src.field; - MERGE_SINGLETON(invariant); - MERGE_SINGLETON(noContraction); - MERGE_SINGLETON(centroid); - MERGE_SINGLETON(smooth); - MERGE_SINGLETON(flat); - MERGE_SINGLETON(nopersp); -#ifdef AMD_EXTENSIONS - MERGE_SINGLETON(explicitInterp); -#endif - MERGE_SINGLETON(patch); - MERGE_SINGLETON(sample); - MERGE_SINGLETON(coherent); - MERGE_SINGLETON(volatil); - MERGE_SINGLETON(restrict); - MERGE_SINGLETON(readonly); - MERGE_SINGLETON(writeonly); - MERGE_SINGLETON(specConstant); - MERGE_SINGLETON(nonUniform); - - if (repeated) - error(loc, "replicated qualifiers", "", ""); -} - -void TParseContext::setDefaultPrecision(const TSourceLoc& loc, TPublicType& publicType, TPrecisionQualifier qualifier) -{ - TBasicType basicType = publicType.basicType; - - if (basicType == EbtSampler) { - defaultSamplerPrecision[computeSamplerTypeIndex(publicType.sampler)] = qualifier; - - return; // all is well - } - - if (basicType == EbtInt || basicType == EbtFloat) { - if (publicType.isScalar()) { - defaultPrecision[basicType] = qualifier; - if (basicType == EbtInt) { - defaultPrecision[EbtUint] = qualifier; - precisionManager.explicitIntDefaultSeen(); - } else - precisionManager.explicitFloatDefaultSeen(); - - return; // all is well - } - } - - if (basicType == EbtAtomicUint) { - if (qualifier != EpqHigh) - error(loc, "can only apply highp to atomic_uint", "precision", ""); - - return; - } - - error(loc, "cannot apply precision statement to this type; use 'float', 'int' or a sampler type", TType::getBasicString(basicType), ""); -} - -// used to flatten the sampler type space into a single dimension -// correlates with the declaration of defaultSamplerPrecision[] -int TParseContext::computeSamplerTypeIndex(TSampler& sampler) -{ - int arrayIndex = sampler.arrayed ? 1 : 0; - int shadowIndex = sampler.shadow ? 1 : 0; - int externalIndex = sampler.external? 1 : 0; - int imageIndex = sampler.image ? 1 : 0; - int msIndex = sampler.ms ? 1 : 0; - - int flattened = EsdNumDims * (EbtNumTypes * (2 * (2 * (2 * (2 * arrayIndex + msIndex) + imageIndex) + shadowIndex) + - externalIndex) + sampler.type) + sampler.dim; - assert(flattened < maxSamplerIndex); - - return flattened; -} - -TPrecisionQualifier TParseContext::getDefaultPrecision(TPublicType& publicType) -{ - if (publicType.basicType == EbtSampler) - return defaultSamplerPrecision[computeSamplerTypeIndex(publicType.sampler)]; - else - return defaultPrecision[publicType.basicType]; -} - -void TParseContext::precisionQualifierCheck(const TSourceLoc& loc, TBasicType baseType, TQualifier& qualifier) -{ - // Built-in symbols are allowed some ambiguous precisions, to be pinned down - // later by context. - if (! obeyPrecisionQualifiers() || parsingBuiltins) - return; - - if (baseType == EbtAtomicUint && qualifier.precision != EpqNone && qualifier.precision != EpqHigh) - error(loc, "atomic counters can only be highp", "atomic_uint", ""); - - if (baseType == EbtFloat || baseType == EbtUint || baseType == EbtInt || baseType == EbtSampler || baseType == EbtAtomicUint) { - if (qualifier.precision == EpqNone) { - if (relaxedErrors()) - warn(loc, "type requires declaration of default precision qualifier", TType::getBasicString(baseType), "substituting 'mediump'"); - else - error(loc, "type requires declaration of default precision qualifier", TType::getBasicString(baseType), ""); - qualifier.precision = EpqMedium; - defaultPrecision[baseType] = EpqMedium; - } - } else if (qualifier.precision != EpqNone) - error(loc, "type cannot have precision qualifier", TType::getBasicString(baseType), ""); -} - -void TParseContext::parameterTypeCheck(const TSourceLoc& loc, TStorageQualifier qualifier, const TType& type) -{ - if ((qualifier == EvqOut || qualifier == EvqInOut) && type.isOpaque()) - error(loc, "samplers and atomic_uints cannot be output parameters", type.getBasicTypeString().c_str(), ""); -} - -bool TParseContext::containsFieldWithBasicType(const TType& type, TBasicType basicType) -{ - if (type.getBasicType() == basicType) - return true; - - if (type.getBasicType() == EbtStruct) { - const TTypeList& structure = *type.getStruct(); - for (unsigned int i = 0; i < structure.size(); ++i) { - if (containsFieldWithBasicType(*structure[i].type, basicType)) - return true; - } - } - - return false; -} - -// -// Do size checking for an array type's size. -// -void TParseContext::arraySizeCheck(const TSourceLoc& loc, TIntermTyped* expr, TArraySize& sizePair) -{ - bool isConst = false; - sizePair.node = nullptr; - - int size = 1; - - TIntermConstantUnion* constant = expr->getAsConstantUnion(); - if (constant) { - // handle true (non-specialization) constant - size = constant->getConstArray()[0].getIConst(); - isConst = true; - } else { - // see if it's a specialization constant instead - if (expr->getQualifier().isSpecConstant()) { - isConst = true; - sizePair.node = expr; - TIntermSymbol* symbol = expr->getAsSymbolNode(); - if (symbol && symbol->getConstArray().size() > 0) - size = symbol->getConstArray()[0].getIConst(); - } - } - - sizePair.size = size; - - if (! isConst || (expr->getBasicType() != EbtInt && expr->getBasicType() != EbtUint)) { - error(loc, "array size must be a constant integer expression", "", ""); - return; - } - - if (size <= 0) { - error(loc, "array size must be a positive integer", "", ""); - return; - } -} - -// -// See if this qualifier can be an array. -// -// Returns true if there is an error. -// -bool TParseContext::arrayQualifierError(const TSourceLoc& loc, const TQualifier& qualifier) -{ - if (qualifier.storage == EvqConst) { - profileRequires(loc, ENoProfile, 120, E_GL_3DL_array_objects, "const array"); - profileRequires(loc, EEsProfile, 300, nullptr, "const array"); - } - - if (qualifier.storage == EvqVaryingIn && language == EShLangVertex) { - requireProfile(loc, ~EEsProfile, "vertex input arrays"); - profileRequires(loc, ENoProfile, 150, nullptr, "vertex input arrays"); - } - - return false; -} - -// -// See if this qualifier and type combination can be an array. -// Assumes arrayQualifierError() was also called to catch the type-invariant tests. -// -// Returns true if there is an error. -// -bool TParseContext::arrayError(const TSourceLoc& loc, const TType& type) -{ - if (type.getQualifier().storage == EvqVaryingOut && language == EShLangVertex) { - if (type.isArrayOfArrays()) - requireProfile(loc, ~EEsProfile, "vertex-shader array-of-array output"); - else if (type.isStruct()) - requireProfile(loc, ~EEsProfile, "vertex-shader array-of-struct output"); - } - if (type.getQualifier().storage == EvqVaryingIn && language == EShLangFragment) { - if (type.isArrayOfArrays()) - requireProfile(loc, ~EEsProfile, "fragment-shader array-of-array input"); - else if (type.isStruct()) - requireProfile(loc, ~EEsProfile, "fragment-shader array-of-struct input"); - } - if (type.getQualifier().storage == EvqVaryingOut && language == EShLangFragment) { - if (type.isArrayOfArrays()) - requireProfile(loc, ~EEsProfile, "fragment-shader array-of-array output"); - } - - return false; -} - -// -// Require array to be completely sized -// -void TParseContext::arraySizeRequiredCheck(const TSourceLoc& loc, const TArraySizes& arraySizes) -{ - if (arraySizes.hasUnsized()) - error(loc, "array size required", "", ""); -} - -void TParseContext::structArrayCheck(const TSourceLoc& /*loc*/, const TType& type) -{ - const TTypeList& structure = *type.getStruct(); - for (int m = 0; m < (int)structure.size(); ++m) { - const TType& member = *structure[m].type; - if (member.isArray()) - arraySizeRequiredCheck(structure[m].loc, *member.getArraySizes()); - } -} - -void TParseContext::arraySizesCheck(const TSourceLoc& loc, const TQualifier& qualifier, TArraySizes* arraySizes, bool initializer, bool lastMember) -{ - assert(arraySizes); - - // always allow special built-in ins/outs sized to topologies - if (parsingBuiltins) - return; - - // always allow an initializer to set any unknown array sizes - if (initializer) - return; - - // No environment allows any non-outer-dimension to be implicitly sized - if (arraySizes->isInnerUnsized()) { - error(loc, "only outermost dimension of an array of arrays can be implicitly sized", "[]", ""); - arraySizes->clearInnerUnsized(); - } - - if (arraySizes->isInnerSpecialization()) - error(loc, "only outermost dimension of an array of arrays can be a specialization constant", "[]", ""); - - // desktop always allows outer-dimension-unsized variable arrays, - if (profile != EEsProfile) - return; - - // for ES, if size isn't coming from an initializer, it has to be explicitly declared now, - // with very few exceptions - - // last member of ssbo block exception: - if (qualifier.storage == EvqBuffer && lastMember) - return; - - // implicitly-sized io exceptions: - switch (language) { - case EShLangGeometry: - if (qualifier.storage == EvqVaryingIn) - if ((profile == EEsProfile && version >= 320) || - extensionsTurnedOn(Num_AEP_geometry_shader, AEP_geometry_shader)) - return; - break; - case EShLangTessControl: - if ( qualifier.storage == EvqVaryingIn || - (qualifier.storage == EvqVaryingOut && ! qualifier.patch)) - if ((profile == EEsProfile && version >= 320) || - extensionsTurnedOn(Num_AEP_tessellation_shader, AEP_tessellation_shader)) - return; - break; - case EShLangTessEvaluation: - if ((qualifier.storage == EvqVaryingIn && ! qualifier.patch) || - qualifier.storage == EvqVaryingOut) - if ((profile == EEsProfile && version >= 320) || - extensionsTurnedOn(Num_AEP_tessellation_shader, AEP_tessellation_shader)) - return; - break; - default: - break; - } - - arraySizeRequiredCheck(loc, *arraySizes); -} - -void TParseContext::arrayOfArrayVersionCheck(const TSourceLoc& loc, const TArraySizes* sizes) -{ - if (sizes == nullptr || sizes->getNumDims() == 1) - return; - - const char* feature = "arrays of arrays"; - - requireProfile(loc, EEsProfile | ECoreProfile | ECompatibilityProfile, feature); - profileRequires(loc, EEsProfile, 310, nullptr, feature); - profileRequires(loc, ECoreProfile | ECompatibilityProfile, 430, nullptr, feature); -} - -// -// Do all the semantic checking for declaring or redeclaring an array, with and -// without a size, and make the right changes to the symbol table. -// -void TParseContext::declareArray(const TSourceLoc& loc, const TString& identifier, const TType& type, TSymbol*& symbol) -{ - if (symbol == nullptr) { - bool currentScope; - symbol = symbolTable.find(identifier, nullptr, ¤tScope); - - if (symbol && builtInName(identifier) && ! symbolTable.atBuiltInLevel()) { - // bad shader (errors already reported) trying to redeclare a built-in name as an array - symbol = nullptr; - return; - } - if (symbol == nullptr || ! currentScope) { - // - // Successfully process a new definition. - // (Redeclarations have to take place at the same scope; otherwise they are hiding declarations) - // - symbol = new TVariable(&identifier, type); - symbolTable.insert(*symbol); - if (symbolTable.atGlobalLevel()) - trackLinkage(*symbol); - - if (! symbolTable.atBuiltInLevel()) { - if (isIoResizeArray(type)) { - ioArraySymbolResizeList.push_back(symbol); - checkIoArraysConsistency(loc, true); - } else - fixIoArraySize(loc, symbol->getWritableType()); - } - - return; - } - if (symbol->getAsAnonMember()) { - error(loc, "cannot redeclare a user-block member array", identifier.c_str(), ""); - symbol = nullptr; - return; - } - } - - // - // Process a redeclaration. - // - - if (symbol == nullptr) { - error(loc, "array variable name expected", identifier.c_str(), ""); - return; - } - - // redeclareBuiltinVariable() should have already done the copyUp() - TType& existingType = symbol->getWritableType(); - - if (! existingType.isArray()) { - error(loc, "redeclaring non-array as array", identifier.c_str(), ""); - return; - } - - if (! existingType.sameElementType(type)) { - error(loc, "redeclaration of array with a different element type", identifier.c_str(), ""); - return; - } - - if (! existingType.sameInnerArrayness(type)) { - error(loc, "redeclaration of array with a different array dimensions or sizes", identifier.c_str(), ""); - return; - } - - if (existingType.isSizedArray()) { - // be more leniant for input arrays to geometry shaders and tessellation control outputs, where the redeclaration is the same size - if (! (isIoResizeArray(type) && existingType.getOuterArraySize() == type.getOuterArraySize())) - error(loc, "redeclaration of array with size", identifier.c_str(), ""); - return; - } - - arrayLimitCheck(loc, identifier, type.getOuterArraySize()); - - existingType.updateArraySizes(type); - - if (isIoResizeArray(type)) - checkIoArraysConsistency(loc); -} - -// Policy and error check for needing a runtime sized array. -void TParseContext::checkRuntimeSizable(const TSourceLoc& loc, const TIntermTyped& base) -{ - // runtime length implies runtime sizeable, so no problem - if (isRuntimeLength(base)) - return; - - // check for additional things allowed by GL_EXT_nonuniform_qualifier - if (base.getBasicType() == EbtSampler || - (base.getBasicType() == EbtBlock && base.getType().getQualifier().isUniformOrBuffer())) - requireExtensions(loc, 1, &E_GL_EXT_nonuniform_qualifier, "variable index"); - else - error(loc, "", "[", "array must be redeclared with a size before being indexed with a variable"); -} - -// Policy decision for whether a run-time .length() is allowed. -bool TParseContext::isRuntimeLength(const TIntermTyped& base) const -{ - if (base.getType().getQualifier().storage == EvqBuffer) { - // in a buffer block - const TIntermBinary* binary = base.getAsBinaryNode(); - if (binary != nullptr && binary->getOp() == EOpIndexDirectStruct) { - // is it the last member? - const int index = binary->getRight()->getAsConstantUnion()->getConstArray()[0].getIConst(); - const int memberCount = (int)binary->getLeft()->getType().getStruct()->size(); - if (index == memberCount - 1) - return true; - } - } - - return false; -} - -// Returns true if the first argument to the #line directive is the line number for the next line. -// -// Desktop, pre-version 3.30: "After processing this directive -// (including its new-line), the implementation will behave as if it is compiling at line number line+1 and -// source string number source-string-number." -// -// Desktop, version 3.30 and later, and ES: "After processing this directive -// (including its new-line), the implementation will behave as if it is compiling at line number line and -// source string number source-string-number. -bool TParseContext::lineDirectiveShouldSetNextLine() const -{ - return profile == EEsProfile || version >= 330; -} - -// -// Enforce non-initializer type/qualifier rules. -// -void TParseContext::nonInitConstCheck(const TSourceLoc& loc, TString& identifier, TType& type) -{ - // - // Make the qualifier make sense, given that there is not an initializer. - // - if (type.getQualifier().storage == EvqConst || - type.getQualifier().storage == EvqConstReadOnly) { - type.getQualifier().makeTemporary(); - error(loc, "variables with qualifier 'const' must be initialized", identifier.c_str(), ""); - } -} - -// -// See if the identifier is a built-in symbol that can be redeclared, and if so, -// copy the symbol table's read-only built-in variable to the current -// global level, where it can be modified based on the passed in type. -// -// Returns nullptr if no redeclaration took place; meaning a normal declaration still -// needs to occur for it, not necessarily an error. -// -// Returns a redeclared and type-modified variable if a redeclarated occurred. -// -TSymbol* TParseContext::redeclareBuiltinVariable(const TSourceLoc& loc, const TString& identifier, - const TQualifier& qualifier, const TShaderQualifiers& publicType) -{ - if (! builtInName(identifier) || symbolTable.atBuiltInLevel() || ! symbolTable.atGlobalLevel()) - return nullptr; - - bool nonEsRedecls = (profile != EEsProfile && (version >= 130 || identifier == "gl_TexCoord")); - bool esRedecls = (profile == EEsProfile && - (version >= 320 || extensionsTurnedOn(Num_AEP_shader_io_blocks, AEP_shader_io_blocks))); - if (! esRedecls && ! nonEsRedecls) - return nullptr; - - // Special case when using GL_ARB_separate_shader_objects - bool ssoPre150 = false; // means the only reason this variable is redeclared is due to this combination - if (profile != EEsProfile && version <= 140 && extensionTurnedOn(E_GL_ARB_separate_shader_objects)) { - if (identifier == "gl_Position" || - identifier == "gl_PointSize" || - identifier == "gl_ClipVertex" || - identifier == "gl_FogFragCoord") - ssoPre150 = true; - } - - // Potentially redeclaring a built-in variable... - - if (ssoPre150 || - (identifier == "gl_FragDepth" && ((nonEsRedecls && version >= 420) || esRedecls)) || - (identifier == "gl_FragCoord" && ((nonEsRedecls && version >= 150) || esRedecls)) || - identifier == "gl_ClipDistance" || - identifier == "gl_CullDistance" || - identifier == "gl_FrontColor" || - identifier == "gl_BackColor" || - identifier == "gl_FrontSecondaryColor" || - identifier == "gl_BackSecondaryColor" || - identifier == "gl_SecondaryColor" || - (identifier == "gl_Color" && language == EShLangFragment) || -#ifdef NV_EXTENSIONS - identifier == "gl_SampleMask" || - identifier == "gl_Layer" || -#endif - identifier == "gl_TexCoord") { - - // Find the existing symbol, if any. - bool builtIn; - TSymbol* symbol = symbolTable.find(identifier, &builtIn); - - // If the symbol was not found, this must be a version/profile/stage - // that doesn't have it. - if (! symbol) - return nullptr; - - // If it wasn't at a built-in level, then it's already been redeclared; - // that is, this is a redeclaration of a redeclaration; reuse that initial - // redeclaration. Otherwise, make the new one. - if (builtIn) - makeEditable(symbol); - - // Now, modify the type of the copy, as per the type of the current redeclaration. - - TQualifier& symbolQualifier = symbol->getWritableType().getQualifier(); - if (ssoPre150) { - if (intermediate.inIoAccessed(identifier)) - error(loc, "cannot redeclare after use", identifier.c_str(), ""); - if (qualifier.hasLayout()) - error(loc, "cannot apply layout qualifier to", "redeclaration", symbol->getName().c_str()); - if (qualifier.isMemory() || qualifier.isAuxiliary() || (language == EShLangVertex && qualifier.storage != EvqVaryingOut) || - (language == EShLangFragment && qualifier.storage != EvqVaryingIn)) - error(loc, "cannot change storage, memory, or auxiliary qualification of", "redeclaration", symbol->getName().c_str()); - if (! qualifier.smooth) - error(loc, "cannot change interpolation qualification of", "redeclaration", symbol->getName().c_str()); - } else if (identifier == "gl_FrontColor" || - identifier == "gl_BackColor" || - identifier == "gl_FrontSecondaryColor" || - identifier == "gl_BackSecondaryColor" || - identifier == "gl_SecondaryColor" || - identifier == "gl_Color") { - symbolQualifier.flat = qualifier.flat; - symbolQualifier.smooth = qualifier.smooth; - symbolQualifier.nopersp = qualifier.nopersp; - if (qualifier.hasLayout()) - error(loc, "cannot apply layout qualifier to", "redeclaration", symbol->getName().c_str()); - if (qualifier.isMemory() || qualifier.isAuxiliary() || symbol->getType().getQualifier().storage != qualifier.storage) - error(loc, "cannot change storage, memory, or auxiliary qualification of", "redeclaration", symbol->getName().c_str()); - } else if (identifier == "gl_TexCoord" || - identifier == "gl_ClipDistance" || - identifier == "gl_CullDistance") { - if (qualifier.hasLayout() || qualifier.isMemory() || qualifier.isAuxiliary() || - qualifier.nopersp != symbolQualifier.nopersp || qualifier.flat != symbolQualifier.flat || - symbolQualifier.storage != qualifier.storage) - error(loc, "cannot change qualification of", "redeclaration", symbol->getName().c_str()); - } else if (identifier == "gl_FragCoord") { - if (intermediate.inIoAccessed("gl_FragCoord")) - error(loc, "cannot redeclare after use", "gl_FragCoord", ""); - if (qualifier.nopersp != symbolQualifier.nopersp || qualifier.flat != symbolQualifier.flat || - qualifier.isMemory() || qualifier.isAuxiliary()) - error(loc, "can only change layout qualification of", "redeclaration", symbol->getName().c_str()); - if (qualifier.storage != EvqVaryingIn) - error(loc, "cannot change input storage qualification of", "redeclaration", symbol->getName().c_str()); - if (! builtIn && (publicType.pixelCenterInteger != intermediate.getPixelCenterInteger() || - publicType.originUpperLeft != intermediate.getOriginUpperLeft())) - error(loc, "cannot redeclare with different qualification:", "redeclaration", symbol->getName().c_str()); - if (publicType.pixelCenterInteger) - intermediate.setPixelCenterInteger(); - if (publicType.originUpperLeft) - intermediate.setOriginUpperLeft(); - } else if (identifier == "gl_FragDepth") { - if (qualifier.nopersp != symbolQualifier.nopersp || qualifier.flat != symbolQualifier.flat || - qualifier.isMemory() || qualifier.isAuxiliary()) - error(loc, "can only change layout qualification of", "redeclaration", symbol->getName().c_str()); - if (qualifier.storage != EvqVaryingOut) - error(loc, "cannot change output storage qualification of", "redeclaration", symbol->getName().c_str()); - if (publicType.layoutDepth != EldNone) { - if (intermediate.inIoAccessed("gl_FragDepth")) - error(loc, "cannot redeclare after use", "gl_FragDepth", ""); - if (! intermediate.setDepth(publicType.layoutDepth)) - error(loc, "all redeclarations must use the same depth layout on", "redeclaration", symbol->getName().c_str()); - } - } -#ifdef NV_EXTENSIONS - else if (identifier == "gl_SampleMask") { - if (!publicType.layoutOverrideCoverage) { - error(loc, "redeclaration only allowed for override_coverage layout", "redeclaration", symbol->getName().c_str()); - } - intermediate.setLayoutOverrideCoverage(); - } - else if (identifier == "gl_Layer") { - if (!qualifier.layoutViewportRelative && qualifier.layoutSecondaryViewportRelativeOffset == -2048) - error(loc, "redeclaration only allowed for viewport_relative or secondary_view_offset layout", "redeclaration", symbol->getName().c_str()); - symbolQualifier.layoutViewportRelative = qualifier.layoutViewportRelative; - symbolQualifier.layoutSecondaryViewportRelativeOffset = qualifier.layoutSecondaryViewportRelativeOffset; - } -#endif - - // TODO: semantics quality: separate smooth from nothing declared, then use IsInterpolation for several tests above - - return symbol; - } - - return nullptr; -} - -// -// Either redeclare the requested block, or give an error message why it can't be done. -// -// TODO: functionality: explicitly sizing members of redeclared blocks is not giving them an explicit size -void TParseContext::redeclareBuiltinBlock(const TSourceLoc& loc, TTypeList& newTypeList, const TString& blockName, const TString* instanceName, TArraySizes* arraySizes) -{ - const char* feature = "built-in block redeclaration"; - profileRequires(loc, EEsProfile, 320, Num_AEP_shader_io_blocks, AEP_shader_io_blocks, feature); - profileRequires(loc, ~EEsProfile, 410, E_GL_ARB_separate_shader_objects, feature); - - if (blockName != "gl_PerVertex" && blockName != "gl_PerFragment") { - error(loc, "cannot redeclare block: ", "block declaration", blockName.c_str()); - return; - } - - // Redeclaring a built-in block... - - if (instanceName && ! builtInName(*instanceName)) { - error(loc, "cannot redeclare a built-in block with a user name", instanceName->c_str(), ""); - return; - } - - // Blocks with instance names are easy to find, lookup the instance name, - // Anonymous blocks need to be found via a member. - bool builtIn; - TSymbol* block; - if (instanceName) - block = symbolTable.find(*instanceName, &builtIn); - else - block = symbolTable.find(newTypeList.front().type->getFieldName(), &builtIn); - - // If the block was not found, this must be a version/profile/stage - // that doesn't have it, or the instance name is wrong. - const char* errorName = instanceName ? instanceName->c_str() : newTypeList.front().type->getFieldName().c_str(); - if (! block) { - error(loc, "no declaration found for redeclaration", errorName, ""); - return; - } - // Built-in blocks cannot be redeclared more than once, which if happened, - // we'd be finding the already redeclared one here, rather than the built in. - if (! builtIn) { - error(loc, "can only redeclare a built-in block once, and before any use", blockName.c_str(), ""); - return; - } - - // Copy the block to make a writable version, to insert into the block table after editing. - block = symbolTable.copyUpDeferredInsert(block); - - if (block->getType().getBasicType() != EbtBlock) { - error(loc, "cannot redeclare a non block as a block", errorName, ""); - return; - } - - // Fix XFB stuff up, it applies to the order of the redeclaration, not - // the order of the original members. - if (currentBlockQualifier.storage == EvqVaryingOut && globalOutputDefaults.hasXfbBuffer()) { - if (!currentBlockQualifier.hasXfbBuffer()) - currentBlockQualifier.layoutXfbBuffer = globalOutputDefaults.layoutXfbBuffer; - fixBlockXfbOffsets(currentBlockQualifier, newTypeList); - } - - // Edit and error check the container against the redeclaration - // - remove unused members - // - ensure remaining qualifiers/types match - - TType& type = block->getWritableType(); - -#ifdef NV_EXTENSIONS - // if gl_PerVertex is redeclared for the purpose of passing through "gl_Position" - // for passthrough purpose, the redeclared block should have the same qualifers as - // the current one - if (currentBlockQualifier.layoutPassthrough) { - type.getQualifier().layoutPassthrough = currentBlockQualifier.layoutPassthrough; - type.getQualifier().storage = currentBlockQualifier.storage; - type.getQualifier().layoutStream = currentBlockQualifier.layoutStream; - type.getQualifier().layoutXfbBuffer = currentBlockQualifier.layoutXfbBuffer; - } -#endif - - TTypeList::iterator member = type.getWritableStruct()->begin(); - size_t numOriginalMembersFound = 0; - while (member != type.getStruct()->end()) { - // look for match - bool found = false; - TTypeList::const_iterator newMember; - TSourceLoc memberLoc; - memberLoc.init(); - for (newMember = newTypeList.begin(); newMember != newTypeList.end(); ++newMember) { - if (member->type->getFieldName() == newMember->type->getFieldName()) { - found = true; - memberLoc = newMember->loc; - break; - } - } - - if (found) { - ++numOriginalMembersFound; - // - ensure match between redeclared members' types - // - check for things that can't be changed - // - update things that can be changed - TType& oldType = *member->type; - const TType& newType = *newMember->type; - if (! newType.sameElementType(oldType)) - error(memberLoc, "cannot redeclare block member with a different type", member->type->getFieldName().c_str(), ""); - if (oldType.isArray() != newType.isArray()) - error(memberLoc, "cannot change arrayness of redeclared block member", member->type->getFieldName().c_str(), ""); - else if (! oldType.sameArrayness(newType) && oldType.isSizedArray()) - error(memberLoc, "cannot change array size of redeclared block member", member->type->getFieldName().c_str(), ""); - else if (newType.isArray()) - arrayLimitCheck(loc, member->type->getFieldName(), newType.getOuterArraySize()); - if (newType.getQualifier().isMemory()) - error(memberLoc, "cannot add memory qualifier to redeclared block member", member->type->getFieldName().c_str(), ""); - if (newType.getQualifier().hasNonXfbLayout()) - error(memberLoc, "cannot add non-XFB layout to redeclared block member", member->type->getFieldName().c_str(), ""); - if (newType.getQualifier().patch) - error(memberLoc, "cannot add patch to redeclared block member", member->type->getFieldName().c_str(), ""); - if (newType.getQualifier().hasXfbBuffer() && - newType.getQualifier().layoutXfbBuffer != currentBlockQualifier.layoutXfbBuffer) - error(memberLoc, "member cannot contradict block (or what block inherited from global)", "xfb_buffer", ""); - oldType.getQualifier().centroid = newType.getQualifier().centroid; - oldType.getQualifier().sample = newType.getQualifier().sample; - oldType.getQualifier().invariant = newType.getQualifier().invariant; - oldType.getQualifier().noContraction = newType.getQualifier().noContraction; - oldType.getQualifier().smooth = newType.getQualifier().smooth; - oldType.getQualifier().flat = newType.getQualifier().flat; - oldType.getQualifier().nopersp = newType.getQualifier().nopersp; - oldType.getQualifier().layoutXfbOffset = newType.getQualifier().layoutXfbOffset; - oldType.getQualifier().layoutXfbBuffer = newType.getQualifier().layoutXfbBuffer; - oldType.getQualifier().layoutXfbStride = newType.getQualifier().layoutXfbStride; - if (oldType.getQualifier().layoutXfbOffset != TQualifier::layoutXfbBufferEnd) { - // if any member as an xfb_offset, then the block's xfb_buffer inherents current xfb_buffer, - // and for xfb processing, the member needs it as well, along with xfb_stride - type.getQualifier().layoutXfbBuffer = currentBlockQualifier.layoutXfbBuffer; - oldType.getQualifier().layoutXfbBuffer = currentBlockQualifier.layoutXfbBuffer; - } - if (oldType.isUnsizedArray() && newType.isSizedArray()) - oldType.changeOuterArraySize(newType.getOuterArraySize()); - - // check and process the member's type, which will include managing xfb information - layoutTypeCheck(loc, oldType); - - // go to next member - ++member; - } else { - // For missing members of anonymous blocks that have been redeclared, - // hide the original (shared) declaration. - // Instance-named blocks can just have the member removed. - if (instanceName) - member = type.getWritableStruct()->erase(member); - else { - member->type->hideMember(); - ++member; - } - } - } - - if (numOriginalMembersFound < newTypeList.size()) - error(loc, "block redeclaration has extra members", blockName.c_str(), ""); - if (type.isArray() != (arraySizes != nullptr)) - error(loc, "cannot change arrayness of redeclared block", blockName.c_str(), ""); - else if (type.isArray()) { - if (type.isSizedArray() && !arraySizes->isSized()) - error(loc, "block already declared with size, can't redeclare as unsized", blockName.c_str(), ""); - else if (type.isSizedArray() && *type.getArraySizes() != *arraySizes) - error(loc, "cannot change array size of redeclared block", blockName.c_str(), ""); - else if (!type.isSizedArray() && arraySizes->isSized()) - type.changeOuterArraySize(arraySizes->getOuterSize()); - } - - symbolTable.insert(*block); - - // Check for general layout qualifier errors - layoutObjectCheck(loc, *block); - - // Tracking for implicit sizing of array - if (isIoResizeArray(block->getType())) { - ioArraySymbolResizeList.push_back(block); - checkIoArraysConsistency(loc, true); - } else if (block->getType().isArray()) - fixIoArraySize(loc, block->getWritableType()); - - // Save it in the AST for linker use. - trackLinkage(*block); -} - -void TParseContext::paramCheckFixStorage(const TSourceLoc& loc, const TStorageQualifier& qualifier, TType& type) -{ - switch (qualifier) { - case EvqConst: - case EvqConstReadOnly: - type.getQualifier().storage = EvqConstReadOnly; - break; - case EvqIn: - case EvqOut: - case EvqInOut: - type.getQualifier().storage = qualifier; - break; - case EvqGlobal: - case EvqTemporary: - type.getQualifier().storage = EvqIn; - break; - default: - type.getQualifier().storage = EvqIn; - error(loc, "storage qualifier not allowed on function parameter", GetStorageQualifierString(qualifier), ""); - break; - } -} - -void TParseContext::paramCheckFix(const TSourceLoc& loc, const TQualifier& qualifier, TType& type) -{ - if (qualifier.isMemory()) { - type.getQualifier().volatil = qualifier.volatil; - type.getQualifier().coherent = qualifier.coherent; - type.getQualifier().readonly = qualifier.readonly; - type.getQualifier().writeonly = qualifier.writeonly; - type.getQualifier().restrict = qualifier.restrict; - } - - if (qualifier.isAuxiliary() || - qualifier.isInterpolation()) - error(loc, "cannot use auxiliary or interpolation qualifiers on a function parameter", "", ""); - if (qualifier.hasLayout()) - error(loc, "cannot use layout qualifiers on a function parameter", "", ""); - if (qualifier.invariant) - error(loc, "cannot use invariant qualifier on a function parameter", "", ""); - if (qualifier.noContraction) { - if (qualifier.isParamOutput()) - type.getQualifier().noContraction = true; - else - warn(loc, "qualifier has no effect on non-output parameters", "precise", ""); - } - if (qualifier.isNonUniform()) - type.getQualifier().nonUniform = qualifier.nonUniform; - - paramCheckFixStorage(loc, qualifier.storage, type); -} - -void TParseContext::nestedBlockCheck(const TSourceLoc& loc) -{ - if (structNestingLevel > 0) - error(loc, "cannot nest a block definition inside a structure or block", "", ""); - ++structNestingLevel; -} - -void TParseContext::nestedStructCheck(const TSourceLoc& loc) -{ - if (structNestingLevel > 0) - error(loc, "cannot nest a structure definition inside a structure or block", "", ""); - ++structNestingLevel; -} - -void TParseContext::arrayObjectCheck(const TSourceLoc& loc, const TType& type, const char* op) -{ - // Some versions don't allow comparing arrays or structures containing arrays - if (type.containsArray()) { - profileRequires(loc, ENoProfile, 120, E_GL_3DL_array_objects, op); - profileRequires(loc, EEsProfile, 300, nullptr, op); - } -} - -void TParseContext::opaqueCheck(const TSourceLoc& loc, const TType& type, const char* op) -{ - if (containsFieldWithBasicType(type, EbtSampler)) - error(loc, "can't use with samplers or structs containing samplers", op, ""); -} - -void TParseContext::specializationCheck(const TSourceLoc& loc, const TType& type, const char* op) -{ - if (type.containsSpecializationSize()) - error(loc, "can't use with types containing arrays sized with a specialization constant", op, ""); -} - -void TParseContext::structTypeCheck(const TSourceLoc& /*loc*/, TPublicType& publicType) -{ - const TTypeList& typeList = *publicType.userDef->getStruct(); - - // fix and check for member storage qualifiers and types that don't belong within a structure - for (unsigned int member = 0; member < typeList.size(); ++member) { - TQualifier& memberQualifier = typeList[member].type->getQualifier(); - const TSourceLoc& memberLoc = typeList[member].loc; - if (memberQualifier.isAuxiliary() || - memberQualifier.isInterpolation() || - (memberQualifier.storage != EvqTemporary && memberQualifier.storage != EvqGlobal)) - error(memberLoc, "cannot use storage or interpolation qualifiers on structure members", typeList[member].type->getFieldName().c_str(), ""); - if (memberQualifier.isMemory()) - error(memberLoc, "cannot use memory qualifiers on structure members", typeList[member].type->getFieldName().c_str(), ""); - if (memberQualifier.hasLayout()) { - error(memberLoc, "cannot use layout qualifiers on structure members", typeList[member].type->getFieldName().c_str(), ""); - memberQualifier.clearLayout(); - } - if (memberQualifier.invariant) - error(memberLoc, "cannot use invariant qualifier on structure members", typeList[member].type->getFieldName().c_str(), ""); - } -} - -// -// See if this loop satisfies the limitations for ES 2.0 (version 100) for loops in Appendex A: -// -// "The loop index has type int or float. -// -// "The for statement has the form: -// for ( init-declaration ; condition ; expression ) -// init-declaration has the form: type-specifier identifier = constant-expression -// condition has the form: loop-index relational_operator constant-expression -// where relational_operator is one of: > >= < <= == or != -// expression [sic] has one of the following forms: -// loop-index++ -// loop-index-- -// loop-index += constant-expression -// loop-index -= constant-expression -// -// The body is handled in an AST traversal. -// -void TParseContext::inductiveLoopCheck(const TSourceLoc& loc, TIntermNode* init, TIntermLoop* loop) -{ - // loop index init must exist and be a declaration, which shows up in the AST as an aggregate of size 1 of the declaration - bool badInit = false; - if (! init || ! init->getAsAggregate() || init->getAsAggregate()->getSequence().size() != 1) - badInit = true; - TIntermBinary* binaryInit = 0; - if (! badInit) { - // get the declaration assignment - binaryInit = init->getAsAggregate()->getSequence()[0]->getAsBinaryNode(); - if (! binaryInit) - badInit = true; - } - if (badInit) { - error(loc, "inductive-loop init-declaration requires the form \"type-specifier loop-index = constant-expression\"", "limitations", ""); - return; - } - - // loop index must be type int or float - if (! binaryInit->getType().isScalar() || (binaryInit->getBasicType() != EbtInt && binaryInit->getBasicType() != EbtFloat)) { - error(loc, "inductive loop requires a scalar 'int' or 'float' loop index", "limitations", ""); - return; - } - - // init is the form "loop-index = constant" - if (binaryInit->getOp() != EOpAssign || ! binaryInit->getLeft()->getAsSymbolNode() || ! binaryInit->getRight()->getAsConstantUnion()) { - error(loc, "inductive-loop init-declaration requires the form \"type-specifier loop-index = constant-expression\"", "limitations", ""); - return; - } - - // get the unique id of the loop index - int loopIndex = binaryInit->getLeft()->getAsSymbolNode()->getId(); - inductiveLoopIds.insert(loopIndex); - - // condition's form must be "loop-index relational-operator constant-expression" - bool badCond = ! loop->getTest(); - if (! badCond) { - TIntermBinary* binaryCond = loop->getTest()->getAsBinaryNode(); - badCond = ! binaryCond; - if (! badCond) { - switch (binaryCond->getOp()) { - case EOpGreaterThan: - case EOpGreaterThanEqual: - case EOpLessThan: - case EOpLessThanEqual: - case EOpEqual: - case EOpNotEqual: - break; - default: - badCond = true; - } - } - if (binaryCond && (! binaryCond->getLeft()->getAsSymbolNode() || - binaryCond->getLeft()->getAsSymbolNode()->getId() != loopIndex || - ! binaryCond->getRight()->getAsConstantUnion())) - badCond = true; - } - if (badCond) { - error(loc, "inductive-loop condition requires the form \"loop-index constant-expression\"", "limitations", ""); - return; - } - - // loop-index++ - // loop-index-- - // loop-index += constant-expression - // loop-index -= constant-expression - bool badTerminal = ! loop->getTerminal(); - if (! badTerminal) { - TIntermUnary* unaryTerminal = loop->getTerminal()->getAsUnaryNode(); - TIntermBinary* binaryTerminal = loop->getTerminal()->getAsBinaryNode(); - if (unaryTerminal || binaryTerminal) { - switch(loop->getTerminal()->getAsOperator()->getOp()) { - case EOpPostDecrement: - case EOpPostIncrement: - case EOpAddAssign: - case EOpSubAssign: - break; - default: - badTerminal = true; - } - } else - badTerminal = true; - if (binaryTerminal && (! binaryTerminal->getLeft()->getAsSymbolNode() || - binaryTerminal->getLeft()->getAsSymbolNode()->getId() != loopIndex || - ! binaryTerminal->getRight()->getAsConstantUnion())) - badTerminal = true; - if (unaryTerminal && (! unaryTerminal->getOperand()->getAsSymbolNode() || - unaryTerminal->getOperand()->getAsSymbolNode()->getId() != loopIndex)) - badTerminal = true; - } - if (badTerminal) { - error(loc, "inductive-loop termination requires the form \"loop-index++, loop-index--, loop-index += constant-expression, or loop-index -= constant-expression\"", "limitations", ""); - return; - } - - // the body - inductiveLoopBodyCheck(loop->getBody(), loopIndex, symbolTable); -} - -// Do limit checks for built-in arrays. -void TParseContext::arrayLimitCheck(const TSourceLoc& loc, const TString& identifier, int size) -{ - if (identifier.compare("gl_TexCoord") == 0) - limitCheck(loc, size, "gl_MaxTextureCoords", "gl_TexCoord array size"); - else if (identifier.compare("gl_ClipDistance") == 0) - limitCheck(loc, size, "gl_MaxClipDistances", "gl_ClipDistance array size"); - else if (identifier.compare("gl_CullDistance") == 0) - limitCheck(loc, size, "gl_MaxCullDistances", "gl_CullDistance array size"); -} - -// See if the provided value is less than or equal to the symbol indicated by limit, -// which should be a constant in the symbol table. -void TParseContext::limitCheck(const TSourceLoc& loc, int value, const char* limit, const char* feature) -{ - TSymbol* symbol = symbolTable.find(limit); - assert(symbol->getAsVariable()); - const TConstUnionArray& constArray = symbol->getAsVariable()->getConstArray(); - assert(! constArray.empty()); - if (value > constArray[0].getIConst()) - error(loc, "must be less than or equal to", feature, "%s (%d)", limit, constArray[0].getIConst()); -} - -// -// Do any additional error checking, etc., once we know the parsing is done. -// -void TParseContext::finish() -{ - TParseContextBase::finish(); - - if (parsingBuiltins) - return; - - // Check on array indexes for ES 2.0 (version 100) limitations. - for (size_t i = 0; i < needsIndexLimitationChecking.size(); ++i) - constantIndexExpressionCheck(needsIndexLimitationChecking[i]); - - // Check for stages that are enabled by extension. - // Can't do this at the beginning, it is chicken and egg to add a stage by - // extension. - // Stage-specific features were correctly tested for already, this is just - // about the stage itself. - switch (language) { - case EShLangGeometry: - if (profile == EEsProfile && version == 310) - requireExtensions(getCurrentLoc(), Num_AEP_geometry_shader, AEP_geometry_shader, "geometry shaders"); - break; - case EShLangTessControl: - case EShLangTessEvaluation: - if (profile == EEsProfile && version == 310) - requireExtensions(getCurrentLoc(), Num_AEP_tessellation_shader, AEP_tessellation_shader, "tessellation shaders"); - else if (profile != EEsProfile && version < 400) - requireExtensions(getCurrentLoc(), 1, &E_GL_ARB_tessellation_shader, "tessellation shaders"); - break; - case EShLangCompute: - if (profile != EEsProfile && version < 430) - requireExtensions(getCurrentLoc(), 1, &E_GL_ARB_compute_shader, "compute shaders"); - break; - default: - break; - } - -#ifdef NV_EXTENSIONS - // Set default outputs for GL_NV_geometry_shader_passthrough - if (language == EShLangGeometry && extensionTurnedOn(E_SPV_NV_geometry_shader_passthrough)) { - if (intermediate.getOutputPrimitive() == ElgNone) { - switch (intermediate.getInputPrimitive()) { - case ElgPoints: intermediate.setOutputPrimitive(ElgPoints); break; - case ElgLines: intermediate.setOutputPrimitive(ElgLineStrip); break; - case ElgTriangles: intermediate.setOutputPrimitive(ElgTriangles); break; - default: break; - } - } - if (intermediate.getVertices() == TQualifier::layoutNotSet) { - switch (intermediate.getInputPrimitive()) { - case ElgPoints: intermediate.setVertices(1); break; - case ElgLines: intermediate.setVertices(2); break; - case ElgTriangles: intermediate.setVertices(3); break; - default: break; - } - } - } -#endif -} - -// -// Layout qualifier stuff. -// - -// Put the id's layout qualification into the public type, for qualifiers not having a number set. -// This is before we know any type information for error checking. -void TParseContext::setLayoutQualifier(const TSourceLoc& loc, TPublicType& publicType, TString& id) -{ - std::transform(id.begin(), id.end(), id.begin(), ::tolower); - - if (id == TQualifier::getLayoutMatrixString(ElmColumnMajor)) { - publicType.qualifier.layoutMatrix = ElmColumnMajor; - return; - } - if (id == TQualifier::getLayoutMatrixString(ElmRowMajor)) { - publicType.qualifier.layoutMatrix = ElmRowMajor; - return; - } - if (id == TQualifier::getLayoutPackingString(ElpPacked)) { - if (spvVersion.spv != 0) - spvRemoved(loc, "packed"); - publicType.qualifier.layoutPacking = ElpPacked; - return; - } - if (id == TQualifier::getLayoutPackingString(ElpShared)) { - if (spvVersion.spv != 0) - spvRemoved(loc, "shared"); - publicType.qualifier.layoutPacking = ElpShared; - return; - } - if (id == TQualifier::getLayoutPackingString(ElpStd140)) { - publicType.qualifier.layoutPacking = ElpStd140; - return; - } - if (id == TQualifier::getLayoutPackingString(ElpStd430)) { - requireProfile(loc, EEsProfile | ECoreProfile | ECompatibilityProfile, "std430"); - profileRequires(loc, ECoreProfile | ECompatibilityProfile, 430, nullptr, "std430"); - profileRequires(loc, EEsProfile, 310, nullptr, "std430"); - publicType.qualifier.layoutPacking = ElpStd430; - return; - } - // TODO: compile-time performance: may need to stop doing linear searches - for (TLayoutFormat format = (TLayoutFormat)(ElfNone + 1); format < ElfCount; format = (TLayoutFormat)(format + 1)) { - if (id == TQualifier::getLayoutFormatString(format)) { - if ((format > ElfEsFloatGuard && format < ElfFloatGuard) || - (format > ElfEsIntGuard && format < ElfIntGuard) || - (format > ElfEsUintGuard && format < ElfCount)) - requireProfile(loc, ENoProfile | ECoreProfile | ECompatibilityProfile, "image load-store format"); - profileRequires(loc, ENoProfile | ECoreProfile | ECompatibilityProfile, 420, E_GL_ARB_shader_image_load_store, "image load store"); - profileRequires(loc, EEsProfile, 310, E_GL_ARB_shader_image_load_store, "image load store"); - publicType.qualifier.layoutFormat = format; - return; - } - } - if (id == "push_constant") { - requireVulkan(loc, "push_constant"); - publicType.qualifier.layoutPushConstant = true; - return; - } - if (language == EShLangGeometry || language == EShLangTessEvaluation) { - if (id == TQualifier::getGeometryString(ElgTriangles)) { - publicType.shaderQualifiers.geometry = ElgTriangles; - return; - } - if (language == EShLangGeometry) { - if (id == TQualifier::getGeometryString(ElgPoints)) { - publicType.shaderQualifiers.geometry = ElgPoints; - return; - } - if (id == TQualifier::getGeometryString(ElgLineStrip)) { - publicType.shaderQualifiers.geometry = ElgLineStrip; - return; - } - if (id == TQualifier::getGeometryString(ElgLines)) { - publicType.shaderQualifiers.geometry = ElgLines; - return; - } - if (id == TQualifier::getGeometryString(ElgLinesAdjacency)) { - publicType.shaderQualifiers.geometry = ElgLinesAdjacency; - return; - } - if (id == TQualifier::getGeometryString(ElgTrianglesAdjacency)) { - publicType.shaderQualifiers.geometry = ElgTrianglesAdjacency; - return; - } - if (id == TQualifier::getGeometryString(ElgTriangleStrip)) { - publicType.shaderQualifiers.geometry = ElgTriangleStrip; - return; - } -#ifdef NV_EXTENSIONS - if (id == "passthrough") { - requireExtensions(loc, 1, &E_SPV_NV_geometry_shader_passthrough, "geometry shader passthrough"); - publicType.qualifier.layoutPassthrough = true; - intermediate.setGeoPassthroughEXT(); - return; - } -#endif - } else { - assert(language == EShLangTessEvaluation); - - // input primitive - if (id == TQualifier::getGeometryString(ElgTriangles)) { - publicType.shaderQualifiers.geometry = ElgTriangles; - return; - } - if (id == TQualifier::getGeometryString(ElgQuads)) { - publicType.shaderQualifiers.geometry = ElgQuads; - return; - } - if (id == TQualifier::getGeometryString(ElgIsolines)) { - publicType.shaderQualifiers.geometry = ElgIsolines; - return; - } - - // vertex spacing - if (id == TQualifier::getVertexSpacingString(EvsEqual)) { - publicType.shaderQualifiers.spacing = EvsEqual; - return; - } - if (id == TQualifier::getVertexSpacingString(EvsFractionalEven)) { - publicType.shaderQualifiers.spacing = EvsFractionalEven; - return; - } - if (id == TQualifier::getVertexSpacingString(EvsFractionalOdd)) { - publicType.shaderQualifiers.spacing = EvsFractionalOdd; - return; - } - - // triangle order - if (id == TQualifier::getVertexOrderString(EvoCw)) { - publicType.shaderQualifiers.order = EvoCw; - return; - } - if (id == TQualifier::getVertexOrderString(EvoCcw)) { - publicType.shaderQualifiers.order = EvoCcw; - return; - } - - // point mode - if (id == "point_mode") { - publicType.shaderQualifiers.pointMode = true; - return; - } - } - } - if (language == EShLangFragment) { - if (id == "origin_upper_left") { - requireProfile(loc, ECoreProfile | ECompatibilityProfile, "origin_upper_left"); - publicType.shaderQualifiers.originUpperLeft = true; - return; - } - if (id == "pixel_center_integer") { - requireProfile(loc, ECoreProfile | ECompatibilityProfile, "pixel_center_integer"); - publicType.shaderQualifiers.pixelCenterInteger = true; - return; - } - if (id == "early_fragment_tests") { - profileRequires(loc, ENoProfile | ECoreProfile | ECompatibilityProfile, 420, E_GL_ARB_shader_image_load_store, "early_fragment_tests"); - profileRequires(loc, EEsProfile, 310, nullptr, "early_fragment_tests"); - publicType.shaderQualifiers.earlyFragmentTests = true; - return; - } - if (id == "post_depth_coverage") { - requireExtensions(loc, Num_post_depth_coverageEXTs, post_depth_coverageEXTs, "post depth coverage"); - if (extensionTurnedOn(E_GL_ARB_post_depth_coverage)) { - publicType.shaderQualifiers.earlyFragmentTests = true; - } - publicType.shaderQualifiers.postDepthCoverage = true; - return; - } - for (TLayoutDepth depth = (TLayoutDepth)(EldNone + 1); depth < EldCount; depth = (TLayoutDepth)(depth+1)) { - if (id == TQualifier::getLayoutDepthString(depth)) { - requireProfile(loc, ECoreProfile | ECompatibilityProfile, "depth layout qualifier"); - profileRequires(loc, ECoreProfile | ECompatibilityProfile, 420, nullptr, "depth layout qualifier"); - publicType.shaderQualifiers.layoutDepth = depth; - return; - } - } - if (id.compare(0, 13, "blend_support") == 0) { - bool found = false; - for (TBlendEquationShift be = (TBlendEquationShift)0; be < EBlendCount; be = (TBlendEquationShift)(be + 1)) { - if (id == TQualifier::getBlendEquationString(be)) { - profileRequires(loc, EEsProfile, 320, E_GL_KHR_blend_equation_advanced, "blend equation"); - profileRequires(loc, ~EEsProfile, 0, E_GL_KHR_blend_equation_advanced, "blend equation"); - intermediate.addBlendEquation(be); - publicType.shaderQualifiers.blendEquation = true; - found = true; - break; - } - } - if (! found) - error(loc, "unknown blend equation", "blend_support", ""); - return; - } -#ifdef NV_EXTENSIONS - if (id == "override_coverage") { - requireExtensions(loc, 1, &E_GL_NV_sample_mask_override_coverage, "sample mask override coverage"); - publicType.shaderQualifiers.layoutOverrideCoverage = true; - return; - } - } - if (language == EShLangVertex || - language == EShLangTessControl || - language == EShLangTessEvaluation || - language == EShLangGeometry ) { - if (id == "viewport_relative") { - requireExtensions(loc, 1, &E_GL_NV_viewport_array2, "view port array2"); - publicType.qualifier.layoutViewportRelative = true; - return; - } - } -#else - } -#endif - error(loc, "unrecognized layout identifier, or qualifier requires assignment (e.g., binding = 4)", id.c_str(), ""); -} - -// Put the id's layout qualifier value into the public type, for qualifiers having a number set. -// This is before we know any type information for error checking. -void TParseContext::setLayoutQualifier(const TSourceLoc& loc, TPublicType& publicType, TString& id, const TIntermTyped* node) -{ - const char* feature = "layout-id value"; - const char* nonLiteralFeature = "non-literal layout-id value"; - - integerCheck(node, feature); - const TIntermConstantUnion* constUnion = node->getAsConstantUnion(); - int value; - if (constUnion) { - value = constUnion->getConstArray()[0].getIConst(); - if (! constUnion->isLiteral()) { - requireProfile(loc, ECoreProfile | ECompatibilityProfile, nonLiteralFeature); - profileRequires(loc, ECoreProfile | ECompatibilityProfile, 440, E_GL_ARB_enhanced_layouts, nonLiteralFeature); - } - } else { - // grammar should have give out the error message - value = 0; - } - - if (value < 0) { - error(loc, "cannot be negative", feature, ""); - return; - } - - std::transform(id.begin(), id.end(), id.begin(), ::tolower); - - if (id == "offset") { - // "offset" can be for either - // - uniform offsets - // - atomic_uint offsets - const char* feature = "offset"; - if (spvVersion.spv == 0) { - requireProfile(loc, EEsProfile | ECoreProfile | ECompatibilityProfile, feature); - const char* exts[2] = { E_GL_ARB_enhanced_layouts, E_GL_ARB_shader_atomic_counters }; - profileRequires(loc, ECoreProfile | ECompatibilityProfile, 420, 2, exts, feature); - profileRequires(loc, EEsProfile, 310, nullptr, feature); - } - publicType.qualifier.layoutOffset = value; - return; - } else if (id == "align") { - const char* feature = "uniform buffer-member align"; - if (spvVersion.spv == 0) { - requireProfile(loc, ECoreProfile | ECompatibilityProfile, feature); - profileRequires(loc, ECoreProfile | ECompatibilityProfile, 440, E_GL_ARB_enhanced_layouts, feature); - } - // "The specified alignment must be a power of 2, or a compile-time error results." - if (! IsPow2(value)) - error(loc, "must be a power of 2", "align", ""); - else - publicType.qualifier.layoutAlign = value; - return; - } else if (id == "location") { - profileRequires(loc, EEsProfile, 300, nullptr, "location"); - const char* exts[2] = { E_GL_ARB_separate_shader_objects, E_GL_ARB_explicit_attrib_location }; - profileRequires(loc, ~EEsProfile, 330, 2, exts, "location"); - if ((unsigned int)value >= TQualifier::layoutLocationEnd) - error(loc, "location is too large", id.c_str(), ""); - else - publicType.qualifier.layoutLocation = value; - return; - } else if (id == "set") { - if ((unsigned int)value >= TQualifier::layoutSetEnd) - error(loc, "set is too large", id.c_str(), ""); - else - publicType.qualifier.layoutSet = value; - if (value != 0) - requireVulkan(loc, "descriptor set"); - return; - } else if (id == "binding") { - profileRequires(loc, ~EEsProfile, 420, E_GL_ARB_shading_language_420pack, "binding"); - profileRequires(loc, EEsProfile, 310, nullptr, "binding"); - if ((unsigned int)value >= TQualifier::layoutBindingEnd) - error(loc, "binding is too large", id.c_str(), ""); - else - publicType.qualifier.layoutBinding = value; - return; - } else if (id == "component") { - requireProfile(loc, ECoreProfile | ECompatibilityProfile, "component"); - profileRequires(loc, ECoreProfile | ECompatibilityProfile, 440, E_GL_ARB_enhanced_layouts, "component"); - if ((unsigned)value >= TQualifier::layoutComponentEnd) - error(loc, "component is too large", id.c_str(), ""); - else - publicType.qualifier.layoutComponent = value; - return; - } else if (id.compare(0, 4, "xfb_") == 0) { - // "Any shader making any static use (after preprocessing) of any of these - // *xfb_* qualifiers will cause the shader to be in a transform feedback - // capturing mode and hence responsible for describing the transform feedback - // setup." - intermediate.setXfbMode(); - const char* feature = "transform feedback qualifier"; - requireStage(loc, (EShLanguageMask)(EShLangVertexMask | EShLangGeometryMask | EShLangTessControlMask | EShLangTessEvaluationMask), feature); - requireProfile(loc, ECoreProfile | ECompatibilityProfile, feature); - profileRequires(loc, ECoreProfile | ECompatibilityProfile, 440, E_GL_ARB_enhanced_layouts, feature); - if (id == "xfb_buffer") { - // "It is a compile-time error to specify an *xfb_buffer* that is greater than - // the implementation-dependent constant gl_MaxTransformFeedbackBuffers." - if (value >= resources.maxTransformFeedbackBuffers) - error(loc, "buffer is too large:", id.c_str(), "gl_MaxTransformFeedbackBuffers is %d", resources.maxTransformFeedbackBuffers); - if (value >= (int)TQualifier::layoutXfbBufferEnd) - error(loc, "buffer is too large:", id.c_str(), "internal max is %d", TQualifier::layoutXfbBufferEnd-1); - else - publicType.qualifier.layoutXfbBuffer = value; - return; - } else if (id == "xfb_offset") { - if (value >= (int)TQualifier::layoutXfbOffsetEnd) - error(loc, "offset is too large:", id.c_str(), "internal max is %d", TQualifier::layoutXfbOffsetEnd-1); - else - publicType.qualifier.layoutXfbOffset = value; - return; - } else if (id == "xfb_stride") { - // "The resulting stride (implicit or explicit), when divided by 4, must be less than or equal to the - // implementation-dependent constant gl_MaxTransformFeedbackInterleavedComponents." - if (value > 4 * resources.maxTransformFeedbackInterleavedComponents) - error(loc, "1/4 stride is too large:", id.c_str(), "gl_MaxTransformFeedbackInterleavedComponents is %d", resources.maxTransformFeedbackInterleavedComponents); - else if (value >= (int)TQualifier::layoutXfbStrideEnd) - error(loc, "stride is too large:", id.c_str(), "internal max is %d", TQualifier::layoutXfbStrideEnd-1); - if (value < (int)TQualifier::layoutXfbStrideEnd) - publicType.qualifier.layoutXfbStride = value; - return; - } - } - - if (id == "input_attachment_index") { - requireVulkan(loc, "input_attachment_index"); - if (value >= (int)TQualifier::layoutAttachmentEnd) - error(loc, "attachment index is too large", id.c_str(), ""); - else - publicType.qualifier.layoutAttachment = value; - return; - } - if (id == "constant_id") { - requireSpv(loc, "constant_id"); - if (value >= (int)TQualifier::layoutSpecConstantIdEnd) { - error(loc, "specialization-constant id is too large", id.c_str(), ""); - } else { - publicType.qualifier.layoutSpecConstantId = value; - publicType.qualifier.specConstant = true; - if (! intermediate.addUsedConstantId(value)) - error(loc, "specialization-constant id already used", id.c_str(), ""); - } - return; - } - if (id == "num_views") { - requireExtensions(loc, Num_OVR_multiview_EXTs, OVR_multiview_EXTs, "num_views"); - publicType.shaderQualifiers.numViews = value; - return; - } - -#if NV_EXTENSIONS - if (language == EShLangVertex || - language == EShLangTessControl || - language == EShLangTessEvaluation || - language == EShLangGeometry) { - if (id == "secondary_view_offset") { - requireExtensions(loc, 1, &E_GL_NV_stereo_view_rendering, "stereo view rendering"); - publicType.qualifier.layoutSecondaryViewportRelativeOffset = value; - return; - } - } -#endif - - switch (language) { - case EShLangVertex: - break; - - case EShLangTessControl: - if (id == "vertices") { - if (value == 0) - error(loc, "must be greater than 0", "vertices", ""); - else - publicType.shaderQualifiers.vertices = value; - return; - } - break; - - case EShLangTessEvaluation: - break; - - case EShLangGeometry: - if (id == "invocations") { - profileRequires(loc, ECompatibilityProfile | ECoreProfile, 400, nullptr, "invocations"); - if (value == 0) - error(loc, "must be at least 1", "invocations", ""); - else - publicType.shaderQualifiers.invocations = value; - return; - } - if (id == "max_vertices") { - publicType.shaderQualifiers.vertices = value; - if (value > resources.maxGeometryOutputVertices) - error(loc, "too large, must be less than gl_MaxGeometryOutputVertices", "max_vertices", ""); - return; - } - if (id == "stream") { - requireProfile(loc, ~EEsProfile, "selecting output stream"); - publicType.qualifier.layoutStream = value; - if (value > 0) - intermediate.setMultiStream(); - return; - } - break; - - case EShLangFragment: - if (id == "index") { - requireProfile(loc, ECompatibilityProfile | ECoreProfile, "index layout qualifier on fragment output"); - const char* exts[2] = { E_GL_ARB_separate_shader_objects, E_GL_ARB_explicit_attrib_location }; - profileRequires(loc, ECompatibilityProfile | ECoreProfile, 330, 2, exts, "index layout qualifier on fragment output"); - - // "It is also a compile-time error if a fragment shader sets a layout index to less than 0 or greater than 1." - if (value < 0 || value > 1) { - value = 0; - error(loc, "value must be 0 or 1", "index", ""); - } - - publicType.qualifier.layoutIndex = value; - return; - } - break; - - case EShLangCompute: - if (id.compare(0, 11, "local_size_") == 0) { - profileRequires(loc, EEsProfile, 310, 0, "gl_WorkGroupSize"); - profileRequires(loc, ~EEsProfile, 430, E_GL_ARB_compute_shader, "gl_WorkGroupSize"); - if (id.size() == 12 && value == 0) { - error(loc, "must be at least 1", id.c_str(), ""); - return; - } - if (id == "local_size_x") { - publicType.shaderQualifiers.localSize[0] = value; - return; - } - if (id == "local_size_y") { - publicType.shaderQualifiers.localSize[1] = value; - return; - } - if (id == "local_size_z") { - publicType.shaderQualifiers.localSize[2] = value; - return; - } - if (spvVersion.spv != 0) { - if (id == "local_size_x_id") { - publicType.shaderQualifiers.localSizeSpecId[0] = value; - return; - } - if (id == "local_size_y_id") { - publicType.shaderQualifiers.localSizeSpecId[1] = value; - return; - } - if (id == "local_size_z_id") { - publicType.shaderQualifiers.localSizeSpecId[2] = value; - return; - } - } - } - break; - - default: - break; - } - - error(loc, "there is no such layout identifier for this stage taking an assigned value", id.c_str(), ""); -} - -// Merge any layout qualifier information from src into dst, leaving everything else in dst alone -// -// "More than one layout qualifier may appear in a single declaration. -// Additionally, the same layout-qualifier-name can occur multiple times -// within a layout qualifier or across multiple layout qualifiers in the -// same declaration. When the same layout-qualifier-name occurs -// multiple times, in a single declaration, the last occurrence overrides -// the former occurrence(s). Further, if such a layout-qualifier-name -// will effect subsequent declarations or other observable behavior, it -// is only the last occurrence that will have any effect, behaving as if -// the earlier occurrence(s) within the declaration are not present. -// This is also true for overriding layout-qualifier-names, where one -// overrides the other (e.g., row_major vs. column_major); only the last -// occurrence has any effect." -void TParseContext::mergeObjectLayoutQualifiers(TQualifier& dst, const TQualifier& src, bool inheritOnly) -{ - if (src.hasMatrix()) - dst.layoutMatrix = src.layoutMatrix; - if (src.hasPacking()) - dst.layoutPacking = src.layoutPacking; - - if (src.hasStream()) - dst.layoutStream = src.layoutStream; - - if (src.hasFormat()) - dst.layoutFormat = src.layoutFormat; - - if (src.hasXfbBuffer()) - dst.layoutXfbBuffer = src.layoutXfbBuffer; - - if (src.hasAlign()) - dst.layoutAlign = src.layoutAlign; - - if (! inheritOnly) { - if (src.hasLocation()) - dst.layoutLocation = src.layoutLocation; - if (src.hasComponent()) - dst.layoutComponent = src.layoutComponent; - if (src.hasIndex()) - dst.layoutIndex = src.layoutIndex; - - if (src.hasOffset()) - dst.layoutOffset = src.layoutOffset; - - if (src.hasSet()) - dst.layoutSet = src.layoutSet; - if (src.layoutBinding != TQualifier::layoutBindingEnd) - dst.layoutBinding = src.layoutBinding; - - if (src.hasXfbStride()) - dst.layoutXfbStride = src.layoutXfbStride; - if (src.hasXfbOffset()) - dst.layoutXfbOffset = src.layoutXfbOffset; - if (src.hasAttachment()) - dst.layoutAttachment = src.layoutAttachment; - if (src.hasSpecConstantId()) - dst.layoutSpecConstantId = src.layoutSpecConstantId; - - if (src.layoutPushConstant) - dst.layoutPushConstant = true; - -#ifdef NV_EXTENSIONS - if (src.layoutPassthrough) - dst.layoutPassthrough = true; - if (src.layoutViewportRelative) - dst.layoutViewportRelative = true; - if (src.layoutSecondaryViewportRelativeOffset != -2048) - dst.layoutSecondaryViewportRelativeOffset = src.layoutSecondaryViewportRelativeOffset; -#endif - } -} - -// Do error layout error checking given a full variable/block declaration. -void TParseContext::layoutObjectCheck(const TSourceLoc& loc, const TSymbol& symbol) -{ - const TType& type = symbol.getType(); - const TQualifier& qualifier = type.getQualifier(); - - // first, cross check WRT to just the type - layoutTypeCheck(loc, type); - - // now, any remaining error checking based on the object itself - - if (qualifier.hasAnyLocation()) { - switch (qualifier.storage) { - case EvqUniform: - case EvqBuffer: - if (symbol.getAsVariable() == nullptr) - error(loc, "can only be used on variable declaration", "location", ""); - break; - default: - break; - } - } - - // user-variable location check, which are required for SPIR-V in/out: - // - variables have it directly, - // - blocks have it on each member (already enforced), so check first one - if (spvVersion.spv > 0 && !parsingBuiltins && qualifier.builtIn == EbvNone && - !qualifier.hasLocation() && !intermediate.getAutoMapLocations()) { - - switch (qualifier.storage) { - case EvqVaryingIn: - case EvqVaryingOut: - if (type.getBasicType() != EbtBlock || - (!(*type.getStruct())[0].type->getQualifier().hasLocation() && - (*type.getStruct())[0].type->getQualifier().builtIn == EbvNone)) - error(loc, "SPIR-V requires location for user input/output", "location", ""); - break; - default: - break; - } - } - - // Check packing and matrix - if (qualifier.hasUniformLayout()) { - switch (qualifier.storage) { - case EvqUniform: - case EvqBuffer: - if (type.getBasicType() != EbtBlock) { - if (qualifier.hasMatrix()) - error(loc, "cannot specify matrix layout on a variable declaration", "layout", ""); - if (qualifier.hasPacking()) - error(loc, "cannot specify packing on a variable declaration", "layout", ""); - // "The offset qualifier can only be used on block members of blocks..." - if (qualifier.hasOffset() && type.getBasicType() != EbtAtomicUint) - error(loc, "cannot specify on a variable declaration", "offset", ""); - // "The align qualifier can only be used on blocks or block members..." - if (qualifier.hasAlign()) - error(loc, "cannot specify on a variable declaration", "align", ""); - if (qualifier.layoutPushConstant) - error(loc, "can only specify on a uniform block", "push_constant", ""); - } - break; - default: - // these were already filtered by layoutTypeCheck() (or its callees) - break; - } - } -} - -// "For some blocks declared as arrays, the location can only be applied at the block level: -// When a block is declared as an array where additional locations are needed for each member -// for each block array element, it is a compile-time error to specify locations on the block -// members. That is, when locations would be under specified by applying them on block members, -// they are not allowed on block members. For arrayed interfaces (those generally having an -// extra level of arrayness due to interface expansion), the outer array is stripped before -// applying this rule." -void TParseContext::layoutMemberLocationArrayCheck(const TSourceLoc& loc, bool memberWithLocation, - TArraySizes* arraySizes) -{ - if (memberWithLocation && arraySizes != nullptr) { - if (arraySizes->getNumDims() > (currentBlockQualifier.isArrayedIo(language) ? 1 : 0)) - error(loc, "cannot use in a block array where new locations are needed for each block element", - "location", ""); - } -} - -// Do layout error checking with respect to a type. -void TParseContext::layoutTypeCheck(const TSourceLoc& loc, const TType& type) -{ - const TQualifier& qualifier = type.getQualifier(); - - // first, intra-layout qualifier-only error checking - layoutQualifierCheck(loc, qualifier); - - // now, error checking combining type and qualifier - - if (qualifier.hasAnyLocation()) { - if (qualifier.hasLocation()) { - if (qualifier.storage == EvqVaryingOut && language == EShLangFragment) { - if (qualifier.layoutLocation >= (unsigned int)resources.maxDrawBuffers) - error(loc, "too large for fragment output", "location", ""); - } - } - if (qualifier.hasComponent()) { - // "It is a compile-time error if this sequence of components gets larger than 3." - if (qualifier.layoutComponent + type.getVectorSize() * (type.getBasicType() == EbtDouble ? 2 : 1) > 4) - error(loc, "type overflows the available 4 components", "component", ""); - - // "It is a compile-time error to apply the component qualifier to a matrix, a structure, a block, or an array containing any of these." - if (type.isMatrix() || type.getBasicType() == EbtBlock || type.getBasicType() == EbtStruct) - error(loc, "cannot apply to a matrix, structure, or block", "component", ""); - - // " It is a compile-time error to use component 1 or 3 as the beginning of a double or dvec2." - if (type.getBasicType() == EbtDouble) - if (qualifier.layoutComponent & 1) - error(loc, "doubles cannot start on an odd-numbered component", "component", ""); - } - - switch (qualifier.storage) { - case EvqVaryingIn: - case EvqVaryingOut: - if (type.getBasicType() == EbtBlock) - profileRequires(loc, ECoreProfile | ECompatibilityProfile, 440, E_GL_ARB_enhanced_layouts, "location qualifier on in/out block"); - break; - case EvqUniform: - case EvqBuffer: - if (type.getBasicType() == EbtBlock) - error(loc, "cannot apply to uniform or buffer block", "location", ""); - break; - default: - error(loc, "can only apply to uniform, buffer, in, or out storage qualifiers", "location", ""); - break; - } - - bool typeCollision; - int repeated = intermediate.addUsedLocation(qualifier, type, typeCollision); - if (repeated >= 0 && ! typeCollision) - error(loc, "overlapping use of location", "location", "%d", repeated); - // "fragment-shader outputs ... if two variables are placed within the same - // location, they must have the same underlying type (floating-point or integer)" - if (typeCollision && language == EShLangFragment && qualifier.isPipeOutput()) - error(loc, "fragment outputs sharing the same location must be the same basic type", "location", "%d", repeated); - } - - if (qualifier.hasXfbOffset() && qualifier.hasXfbBuffer()) { - int repeated = intermediate.addXfbBufferOffset(type); - if (repeated >= 0) - error(loc, "overlapping offsets at", "xfb_offset", "offset %d in buffer %d", repeated, qualifier.layoutXfbBuffer); - - // "The offset must be a multiple of the size of the first component of the first - // qualified variable or block member, or a compile-time error results. Further, if applied to an aggregate - // containing a double, the offset must also be a multiple of 8..." - if (type.containsBasicType(EbtDouble) && ! IsMultipleOfPow2(qualifier.layoutXfbOffset, 8)) - error(loc, "type contains double; xfb_offset must be a multiple of 8", "xfb_offset", ""); - // ..., if applied to an aggregate containing a float16_t, the offset must also be a multiple of 2..." - else if (type.containsBasicType(EbtFloat16) && !IsMultipleOfPow2(qualifier.layoutXfbOffset, 2)) - error(loc, "type contains half float; xfb_offset must be a multiple of 2", "xfb_offset", ""); - else if (! IsMultipleOfPow2(qualifier.layoutXfbOffset, 4)) - error(loc, "must be a multiple of size of first component", "xfb_offset", ""); - } - - if (qualifier.hasXfbStride() && qualifier.hasXfbBuffer()) { - if (! intermediate.setXfbBufferStride(qualifier.layoutXfbBuffer, qualifier.layoutXfbStride)) - error(loc, "all stride settings must match for xfb buffer", "xfb_stride", "%d", qualifier.layoutXfbBuffer); - } - - if (qualifier.hasBinding()) { - // Binding checking, from the spec: - // - // "If the binding point for any uniform or shader storage block instance is less than zero, or greater than or - // equal to the implementation-dependent maximum number of uniform buffer bindings, a compile-time - // error will occur. When the binding identifier is used with a uniform or shader storage block instanced as - // an array of size N, all elements of the array from binding through binding + N - 1 must be within this - // range." - // - if (! type.isOpaque() && type.getBasicType() != EbtBlock) - error(loc, "requires block, or sampler/image, or atomic-counter type", "binding", ""); - if (type.getBasicType() == EbtSampler) { - int lastBinding = qualifier.layoutBinding; - if (type.isArray()) { - if (spvVersion.vulkan > 0) - lastBinding += 1; - else { - if (type.isSizedArray()) - lastBinding += type.getCumulativeArraySize(); - else { - lastBinding += 1; - if (spvVersion.vulkan == 0) - warn(loc, "assuming binding count of one for compile-time checking of binding numbers for unsized array", "[]", ""); - } - } - } - if (spvVersion.vulkan == 0 && lastBinding >= resources.maxCombinedTextureImageUnits) - error(loc, "sampler binding not less than gl_MaxCombinedTextureImageUnits", "binding", type.isArray() ? "(using array)" : ""); - } - if (type.getBasicType() == EbtAtomicUint) { - if (qualifier.layoutBinding >= (unsigned int)resources.maxAtomicCounterBindings) { - error(loc, "atomic_uint binding is too large; see gl_MaxAtomicCounterBindings", "binding", ""); - return; - } - } - } else if (!intermediate.getAutoMapBindings()) { - // some types require bindings - - // atomic_uint - if (type.getBasicType() == EbtAtomicUint) - error(loc, "layout(binding=X) is required", "atomic_uint", ""); - - // SPIR-V - if (spvVersion.spv > 0) { - if (qualifier.isUniformOrBuffer()) { - if (type.getBasicType() == EbtBlock && !qualifier.layoutPushConstant && - !qualifier.layoutAttachment) - error(loc, "uniform/buffer blocks require layout(binding=X)", "binding", ""); - else if (spvVersion.vulkan > 0 && type.getBasicType() == EbtSampler) - error(loc, "sampler/texture/image requires layout(binding=X)", "binding", ""); - } - } - } - - // "The offset qualifier can only be used on block members of blocks..." - if (qualifier.hasOffset()) { - if (type.getBasicType() == EbtBlock) - error(loc, "only applies to block members, not blocks", "offset", ""); - } - - // Image format - if (qualifier.hasFormat()) { - if (! type.isImage()) - error(loc, "only apply to images", TQualifier::getLayoutFormatString(qualifier.layoutFormat), ""); - else { - if (type.getSampler().type == EbtFloat && qualifier.layoutFormat > ElfFloatGuard) - error(loc, "does not apply to floating point images", TQualifier::getLayoutFormatString(qualifier.layoutFormat), ""); - if (type.getSampler().type == EbtInt && (qualifier.layoutFormat < ElfFloatGuard || qualifier.layoutFormat > ElfIntGuard)) - error(loc, "does not apply to signed integer images", TQualifier::getLayoutFormatString(qualifier.layoutFormat), ""); - if (type.getSampler().type == EbtUint && qualifier.layoutFormat < ElfIntGuard) - error(loc, "does not apply to unsigned integer images", TQualifier::getLayoutFormatString(qualifier.layoutFormat), ""); - - if (profile == EEsProfile) { - // "Except for image variables qualified with the format qualifiers r32f, r32i, and r32ui, image variables must - // specify either memory qualifier readonly or the memory qualifier writeonly." - if (! (qualifier.layoutFormat == ElfR32f || qualifier.layoutFormat == ElfR32i || qualifier.layoutFormat == ElfR32ui)) { - if (! qualifier.readonly && ! qualifier.writeonly) - error(loc, "format requires readonly or writeonly memory qualifier", TQualifier::getLayoutFormatString(qualifier.layoutFormat), ""); - } - } - } - } else if (type.isImage() && ! qualifier.writeonly) { - const char *explanation = "image variables not declared 'writeonly' and without a format layout qualifier"; - requireProfile(loc, ECoreProfile | ECompatibilityProfile, explanation); - profileRequires(loc, ECoreProfile | ECompatibilityProfile, 0, E_GL_EXT_shader_image_load_formatted, explanation); - } - - if (qualifier.layoutPushConstant && type.getBasicType() != EbtBlock) - error(loc, "can only be used with a block", "push_constant", ""); - - // input attachment - if (type.isSubpass()) { - if (! qualifier.hasAttachment()) - error(loc, "requires an input_attachment_index layout qualifier", "subpass", ""); - } else { - if (qualifier.hasAttachment()) - error(loc, "can only be used with a subpass", "input_attachment_index", ""); - } - - // specialization-constant id - if (qualifier.hasSpecConstantId()) { - if (type.getQualifier().storage != EvqConst) - error(loc, "can only be applied to 'const'-qualified scalar", "constant_id", ""); - if (! type.isScalar()) - error(loc, "can only be applied to a scalar", "constant_id", ""); - switch (type.getBasicType()) - { - case EbtInt8: - case EbtUint8: - case EbtInt16: - case EbtUint16: - case EbtInt: - case EbtUint: - case EbtInt64: - case EbtUint64: - case EbtBool: - case EbtFloat: - case EbtDouble: - case EbtFloat16: - break; - default: - error(loc, "cannot be applied to this type", "constant_id", ""); - break; - } - } -} - -// Do layout error checking that can be done within a layout qualifier proper, not needing to know -// if there are blocks, atomic counters, variables, etc. -void TParseContext::layoutQualifierCheck(const TSourceLoc& loc, const TQualifier& qualifier) -{ - if (qualifier.storage == EvqShared && qualifier.hasLayout()) - error(loc, "cannot apply layout qualifiers to a shared variable", "shared", ""); - - // "It is a compile-time error to use *component* without also specifying the location qualifier (order does not matter)." - if (qualifier.hasComponent() && ! qualifier.hasLocation()) - error(loc, "must specify 'location' to use 'component'", "component", ""); - - if (qualifier.hasAnyLocation()) { - - // "As with input layout qualifiers, all shaders except compute shaders - // allow *location* layout qualifiers on output variable declarations, - // output block declarations, and output block member declarations." - - switch (qualifier.storage) { - case EvqVaryingIn: - { - const char* feature = "location qualifier on input"; - if (profile == EEsProfile && version < 310) - requireStage(loc, EShLangVertex, feature); - else - requireStage(loc, (EShLanguageMask)~EShLangComputeMask, feature); - if (language == EShLangVertex) { - const char* exts[2] = { E_GL_ARB_separate_shader_objects, E_GL_ARB_explicit_attrib_location }; - profileRequires(loc, ~EEsProfile, 330, 2, exts, feature); - profileRequires(loc, EEsProfile, 300, nullptr, feature); - } else { - profileRequires(loc, ~EEsProfile, 410, E_GL_ARB_separate_shader_objects, feature); - profileRequires(loc, EEsProfile, 310, nullptr, feature); - } - break; - } - case EvqVaryingOut: - { - const char* feature = "location qualifier on output"; - if (profile == EEsProfile && version < 310) - requireStage(loc, EShLangFragment, feature); - else - requireStage(loc, (EShLanguageMask)~EShLangComputeMask, feature); - if (language == EShLangFragment) { - const char* exts[2] = { E_GL_ARB_separate_shader_objects, E_GL_ARB_explicit_attrib_location }; - profileRequires(loc, ~EEsProfile, 330, 2, exts, feature); - profileRequires(loc, EEsProfile, 300, nullptr, feature); - } else { - profileRequires(loc, ~EEsProfile, 410, E_GL_ARB_separate_shader_objects, feature); - profileRequires(loc, EEsProfile, 310, nullptr, feature); - } - break; - } - case EvqUniform: - case EvqBuffer: - { - const char* feature = "location qualifier on uniform or buffer"; - requireProfile(loc, EEsProfile | ECoreProfile | ECompatibilityProfile, feature); - profileRequires(loc, ECoreProfile | ECompatibilityProfile, 430, nullptr, feature); - profileRequires(loc, EEsProfile, 310, nullptr, feature); - break; - } - default: - break; - } - if (qualifier.hasIndex()) { - if (qualifier.storage != EvqVaryingOut) - error(loc, "can only be used on an output", "index", ""); - if (! qualifier.hasLocation()) - error(loc, "can only be used with an explicit location", "index", ""); - } - } - - if (qualifier.hasBinding()) { - if (! qualifier.isUniformOrBuffer()) - error(loc, "requires uniform or buffer storage qualifier", "binding", ""); - } - if (qualifier.hasStream()) { - if (!qualifier.isPipeOutput()) - error(loc, "can only be used on an output", "stream", ""); - } - if (qualifier.hasXfb()) { - if (!qualifier.isPipeOutput()) - error(loc, "can only be used on an output", "xfb layout qualifier", ""); - } - if (qualifier.hasUniformLayout()) { - if (! qualifier.isUniformOrBuffer()) { - if (qualifier.hasMatrix() || qualifier.hasPacking()) - error(loc, "matrix or packing qualifiers can only be used on a uniform or buffer", "layout", ""); - if (qualifier.hasOffset() || qualifier.hasAlign()) - error(loc, "offset/align can only be used on a uniform or buffer", "layout", ""); - } - } - if (qualifier.layoutPushConstant) { - if (qualifier.storage != EvqUniform) - error(loc, "can only be used with a uniform", "push_constant", ""); - if (qualifier.hasSet()) - error(loc, "cannot be used with push_constant", "set", ""); - } -} - -// For places that can't have shader-level layout qualifiers -void TParseContext::checkNoShaderLayouts(const TSourceLoc& loc, const TShaderQualifiers& shaderQualifiers) -{ - const char* message = "can only apply to a standalone qualifier"; - - if (shaderQualifiers.geometry != ElgNone) - error(loc, message, TQualifier::getGeometryString(shaderQualifiers.geometry), ""); - if (shaderQualifiers.spacing != EvsNone) - error(loc, message, TQualifier::getVertexSpacingString(shaderQualifiers.spacing), ""); - if (shaderQualifiers.order != EvoNone) - error(loc, message, TQualifier::getVertexOrderString(shaderQualifiers.order), ""); - if (shaderQualifiers.pointMode) - error(loc, message, "point_mode", ""); - if (shaderQualifiers.invocations != TQualifier::layoutNotSet) - error(loc, message, "invocations", ""); - if (shaderQualifiers.earlyFragmentTests) - error(loc, message, "early_fragment_tests", ""); - if (shaderQualifiers.postDepthCoverage) - error(loc, message, "post_depth_coverage", ""); - for (int i = 0; i < 3; ++i) { - if (shaderQualifiers.localSize[i] > 1) - error(loc, message, "local_size", ""); - if (shaderQualifiers.localSizeSpecId[i] != TQualifier::layoutNotSet) - error(loc, message, "local_size id", ""); - } - if (shaderQualifiers.vertices != TQualifier::layoutNotSet) { - if (language == EShLangGeometry) - error(loc, message, "max_vertices", ""); - else if (language == EShLangTessControl) - error(loc, message, "vertices", ""); - else - assert(0); - } - if (shaderQualifiers.blendEquation) - error(loc, message, "blend equation", ""); - if (shaderQualifiers.numViews != TQualifier::layoutNotSet) - error(loc, message, "num_views", ""); -} - -// Correct and/or advance an object's offset layout qualifier. -void TParseContext::fixOffset(const TSourceLoc& loc, TSymbol& symbol) -{ - const TQualifier& qualifier = symbol.getType().getQualifier(); - if (symbol.getType().getBasicType() == EbtAtomicUint) { - if (qualifier.hasBinding() && (int)qualifier.layoutBinding < resources.maxAtomicCounterBindings) { - - // Set the offset - int offset; - if (qualifier.hasOffset()) - offset = qualifier.layoutOffset; - else - offset = atomicUintOffsets[qualifier.layoutBinding]; - symbol.getWritableType().getQualifier().layoutOffset = offset; - - // Check for overlap - int numOffsets = 4; - if (symbol.getType().isArray()) { - if (symbol.getType().isSizedArray() && !symbol.getType().getArraySizes()->isInnerUnsized()) - numOffsets *= symbol.getType().getCumulativeArraySize(); - else { - // "It is a compile-time error to declare an unsized array of atomic_uint." - error(loc, "array must be explicitly sized", "atomic_uint", ""); - } - } - int repeated = intermediate.addUsedOffsets(qualifier.layoutBinding, offset, numOffsets); - if (repeated >= 0) - error(loc, "atomic counters sharing the same offset:", "offset", "%d", repeated); - - // Bump the default offset - atomicUintOffsets[qualifier.layoutBinding] = offset + numOffsets; - } - } -} - -// -// Look up a function name in the symbol table, and make sure it is a function. -// -// Return the function symbol if found, otherwise nullptr. -// -const TFunction* TParseContext::findFunction(const TSourceLoc& loc, const TFunction& call, bool& builtIn) -{ - const TFunction* function = nullptr; - - if (symbolTable.isFunctionNameVariable(call.getName())) { - error(loc, "can't use function syntax on variable", call.getName().c_str(), ""); - return nullptr; - } - - bool explicitTypesEnabled = extensionTurnedOn(E_GL_KHX_shader_explicit_arithmetic_types) || - extensionTurnedOn(E_GL_KHX_shader_explicit_arithmetic_types_int8) || - extensionTurnedOn(E_GL_KHX_shader_explicit_arithmetic_types_int16) || - extensionTurnedOn(E_GL_KHX_shader_explicit_arithmetic_types_int32) || - extensionTurnedOn(E_GL_KHX_shader_explicit_arithmetic_types_int64) || - extensionTurnedOn(E_GL_KHX_shader_explicit_arithmetic_types_float16) || - extensionTurnedOn(E_GL_KHX_shader_explicit_arithmetic_types_float32) || - extensionTurnedOn(E_GL_KHX_shader_explicit_arithmetic_types_float64); - - if (profile == EEsProfile || version < 120) - function = findFunctionExact(loc, call, builtIn); - else if (version < 400) - function = findFunction120(loc, call, builtIn); - else if (explicitTypesEnabled) - function = findFunctionExplicitTypes(loc, call, builtIn); - else - function = findFunction400(loc, call, builtIn); - - return function; -} - -// Function finding algorithm for ES and desktop 110. -const TFunction* TParseContext::findFunctionExact(const TSourceLoc& loc, const TFunction& call, bool& builtIn) -{ - TSymbol* symbol = symbolTable.find(call.getMangledName(), &builtIn); - if (symbol == nullptr) { - error(loc, "no matching overloaded function found", call.getName().c_str(), ""); - - return nullptr; - } - - return symbol->getAsFunction(); -} - -// Function finding algorithm for desktop versions 120 through 330. -const TFunction* TParseContext::findFunction120(const TSourceLoc& loc, const TFunction& call, bool& builtIn) -{ - // first, look for an exact match - TSymbol* symbol = symbolTable.find(call.getMangledName(), &builtIn); - if (symbol) - return symbol->getAsFunction(); - - // exact match not found, look through a list of overloaded functions of the same name - - // "If no exact match is found, then [implicit conversions] will be applied to find a match. Mismatched types - // on input parameters (in or inout or default) must have a conversion from the calling argument type to the - // formal parameter type. Mismatched types on output parameters (out or inout) must have a conversion - // from the formal parameter type to the calling argument type. When argument conversions are used to find - // a match, it is a semantic error if there are multiple ways to apply these conversions to make the call match - // more than one function." - - const TFunction* candidate = nullptr; - TVector candidateList; - symbolTable.findFunctionNameList(call.getMangledName(), candidateList, builtIn); - - for (auto it = candidateList.begin(); it != candidateList.end(); ++it) { - const TFunction& function = *(*it); - - // to even be a potential match, number of arguments has to match - if (call.getParamCount() != function.getParamCount()) - continue; - - bool possibleMatch = true; - for (int i = 0; i < function.getParamCount(); ++i) { - // same types is easy - if (*function[i].type == *call[i].type) - continue; - - // We have a mismatch in type, see if it is implicitly convertible - - if (function[i].type->isArray() || call[i].type->isArray() || - ! function[i].type->sameElementShape(*call[i].type)) - possibleMatch = false; - else { - // do direction-specific checks for conversion of basic type - if (function[i].type->getQualifier().isParamInput()) { - if (! intermediate.canImplicitlyPromote(call[i].type->getBasicType(), function[i].type->getBasicType())) - possibleMatch = false; - } - if (function[i].type->getQualifier().isParamOutput()) { - if (! intermediate.canImplicitlyPromote(function[i].type->getBasicType(), call[i].type->getBasicType())) - possibleMatch = false; - } - } - if (! possibleMatch) - break; - } - if (possibleMatch) { - if (candidate) { - // our second match, meaning ambiguity - error(loc, "ambiguous function signature match: multiple signatures match under implicit type conversion", call.getName().c_str(), ""); - } else - candidate = &function; - } - } - - if (candidate == nullptr) - error(loc, "no matching overloaded function found", call.getName().c_str(), ""); - - return candidate; -} - -// Function finding algorithm for desktop version 400 and above. -// -// "When function calls are resolved, an exact type match for all the arguments -// is sought. If an exact match is found, all other functions are ignored, and -// the exact match is used. If no exact match is found, then the implicit -// conversions in section 4.1.10 Implicit Conversions will be applied to find -// a match. Mismatched types on input parameters (in or inout or default) must -// have a conversion from the calling argument type to the formal parameter type. -// Mismatched types on output parameters (out or inout) must have a conversion -// from the formal parameter type to the calling argument type. -// -// "If implicit conversions can be used to find more than one matching function, -// a single best-matching function is sought. To determine a best match, the -// conversions between calling argument and formal parameter types are compared -// for each function argument and pair of matching functions. After these -// comparisons are performed, each pair of matching functions are compared. -// A function declaration A is considered a better match than function -// declaration B if -// -// * for at least one function argument, the conversion for that argument in A -// is better than the corresponding conversion in B; and -// * there is no function argument for which the conversion in B is better than -// the corresponding conversion in A. -// -// "If a single function declaration is considered a better match than every -// other matching function declaration, it will be used. Otherwise, a -// compile-time semantic error for an ambiguous overloaded function call occurs. -// -// "To determine whether the conversion for a single argument in one match is -// better than that for another match, the following rules are applied, in order: -// -// 1. An exact match is better than a match involving any implicit conversion. -// 2. A match involving an implicit conversion from float to double is better -// than a match involving any other implicit conversion. -// 3. A match involving an implicit conversion from either int or uint to float -// is better than a match involving an implicit conversion from either int -// or uint to double. -// -// "If none of the rules above apply to a particular pair of conversions, neither -// conversion is considered better than the other." -// -const TFunction* TParseContext::findFunction400(const TSourceLoc& loc, const TFunction& call, bool& builtIn) -{ - // first, look for an exact match - TSymbol* symbol = symbolTable.find(call.getMangledName(), &builtIn); - if (symbol) - return symbol->getAsFunction(); - - // no exact match, use the generic selector, parameterized by the GLSL rules - - // create list of candidates to send - TVector candidateList; - symbolTable.findFunctionNameList(call.getMangledName(), candidateList, builtIn); - - // can 'from' convert to 'to'? - const auto convertible = [this](const TType& from, const TType& to, TOperator, int) -> bool { - if (from == to) - return true; - if (from.isArray() || to.isArray() || ! from.sameElementShape(to)) - return false; - return intermediate.canImplicitlyPromote(from.getBasicType(), to.getBasicType()); - }; - - // Is 'to2' a better conversion than 'to1'? - // Ties should not be considered as better. - // Assumes 'convertible' already said true. - const auto better = [](const TType& from, const TType& to1, const TType& to2) -> bool { - // 1. exact match - if (from == to2) - return from != to1; - if (from == to1) - return false; - - // 2. float -> double is better - if (from.getBasicType() == EbtFloat) { - if (to2.getBasicType() == EbtDouble && to1.getBasicType() != EbtDouble) - return true; - } - - // 3. -> float is better than -> double - return to2.getBasicType() == EbtFloat && to1.getBasicType() == EbtDouble; - }; - - // for ambiguity reporting - bool tie = false; - - // send to the generic selector - const TFunction* bestMatch = selectFunction(candidateList, call, convertible, better, tie); - - if (bestMatch == nullptr) - error(loc, "no matching overloaded function found", call.getName().c_str(), ""); - else if (tie) - error(loc, "ambiguous best function under implicit type conversion", call.getName().c_str(), ""); - - return bestMatch; -} - -// "To determine whether the conversion for a single argument in one match -// is better than that for another match, the conversion is assigned of the -// three ranks ordered from best to worst: -// 1. Exact match: no conversion. -// 2. Promotion: integral or floating-point promotion. -// 3. Conversion: integral conversion, floating-point conversion, -// floating-integral conversion. -// A conversion C1 is better than a conversion C2 if the rank of C1 is -// better than the rank of C2." -const TFunction* TParseContext::findFunctionExplicitTypes(const TSourceLoc& loc, const TFunction& call, bool& builtIn) -{ - // first, look for an exact match - TSymbol* symbol = symbolTable.find(call.getMangledName(), &builtIn); - if (symbol) - return symbol->getAsFunction(); - - // no exact match, use the generic selector, parameterized by the GLSL rules - - // create list of candidates to send - TVector candidateList; - symbolTable.findFunctionNameList(call.getMangledName(), candidateList, builtIn); - - // can 'from' convert to 'to'? - const auto convertible = [this](const TType& from, const TType& to, TOperator, int) -> bool { - if (from == to) - return true; - if (from.isArray() || to.isArray() || ! from.sameElementShape(to)) - return false; - return intermediate.canImplicitlyPromote(from.getBasicType(), to.getBasicType()); - }; - - // Is 'to2' a better conversion than 'to1'? - // Ties should not be considered as better. - // Assumes 'convertible' already said true. - const auto better = [this](const TType& from, const TType& to1, const TType& to2) -> bool { - // 1. exact match - if (from == to2) - return from != to1; - if (from == to1) - return false; - - // 2. Promotion (integral, floating-point) is better - TBasicType from_type = from.getBasicType(); - TBasicType to1_type = to1.getBasicType(); - TBasicType to2_type = to2.getBasicType(); - bool isPromotion1 = (intermediate.isIntegralPromotion(from_type, to1_type) || - intermediate.isFPPromotion(from_type, to1_type)); - bool isPromotion2 = (intermediate.isIntegralPromotion(from_type, to2_type) || - intermediate.isFPPromotion(from_type, to2_type)); - if (isPromotion2) - return !isPromotion1; - if(isPromotion1) - return false; - - // 3. Conversion (integral, floating-point , floating-integral) - bool isConversion1 = (intermediate.isIntegralConversion(from_type, to1_type) || - intermediate.isFPConversion(from_type, to1_type) || - intermediate.isFPIntegralConversion(from_type, to1_type)); - bool isConversion2 = (intermediate.isIntegralConversion(from_type, to2_type) || - intermediate.isFPConversion(from_type, to2_type) || - intermediate.isFPIntegralConversion(from_type, to2_type)); - - return isConversion2 && !isConversion1; - }; - - // for ambiguity reporting - bool tie = false; - - // send to the generic selector - const TFunction* bestMatch = selectFunction(candidateList, call, convertible, better, tie); - - if (bestMatch == nullptr) - error(loc, "no matching overloaded function found", call.getName().c_str(), ""); - else if (tie) - error(loc, "ambiguous best function under implicit type conversion", call.getName().c_str(), ""); - - return bestMatch; -} - -// When a declaration includes a type, but not a variable name, it can be -// to establish defaults. -void TParseContext::declareTypeDefaults(const TSourceLoc& loc, const TPublicType& publicType) -{ - if (publicType.basicType == EbtAtomicUint && publicType.qualifier.hasBinding() && publicType.qualifier.hasOffset()) { - if (publicType.qualifier.layoutBinding >= (unsigned int)resources.maxAtomicCounterBindings) { - error(loc, "atomic_uint binding is too large", "binding", ""); - return; - } - atomicUintOffsets[publicType.qualifier.layoutBinding] = publicType.qualifier.layoutOffset; - return; - } - - if (publicType.qualifier.hasLayout()) - warn(loc, "useless application of layout qualifier", "layout", ""); -} - -// -// Do everything necessary to handle a variable (non-block) declaration. -// Either redeclaring a variable, or making a new one, updating the symbol -// table, and all error checking. -// -// Returns a subtree node that computes an initializer, if needed. -// Returns nullptr if there is no code to execute for initialization. -// -// 'publicType' is the type part of the declaration (to the left) -// 'arraySizes' is the arrayness tagged on the identifier (to the right) -// -TIntermNode* TParseContext::declareVariable(const TSourceLoc& loc, TString& identifier, const TPublicType& publicType, - TArraySizes* arraySizes, TIntermTyped* initializer) -{ - // Make a fresh type that combines the characteristics from the individual - // identifier syntax and the declaration-type syntax. - TType type(publicType); - type.transferArraySizes(arraySizes); - type.copyArrayInnerSizes(publicType.arraySizes); - arrayOfArrayVersionCheck(loc, type.getArraySizes()); - - if (voidErrorCheck(loc, identifier, type.getBasicType())) - return nullptr; - - if (initializer) - rValueErrorCheck(loc, "initializer", initializer); - else - nonInitConstCheck(loc, identifier, type); - - samplerCheck(loc, type, identifier, initializer); - atomicUintCheck(loc, type, identifier); - transparentOpaqueCheck(loc, type, identifier); - - if (identifier != "gl_FragCoord" && (publicType.shaderQualifiers.originUpperLeft || publicType.shaderQualifiers.pixelCenterInteger)) - error(loc, "can only apply origin_upper_left and pixel_center_origin to gl_FragCoord", "layout qualifier", ""); - if (identifier != "gl_FragDepth" && publicType.shaderQualifiers.layoutDepth != EldNone) - error(loc, "can only apply depth layout to gl_FragDepth", "layout qualifier", ""); - - // Check for redeclaration of built-ins and/or attempting to declare a reserved name - TSymbol* symbol = redeclareBuiltinVariable(loc, identifier, type.getQualifier(), publicType.shaderQualifiers); - if (symbol == nullptr) - reservedErrorCheck(loc, identifier); - - inheritGlobalDefaults(type.getQualifier()); - - // Declare the variable - if (type.isArray()) { - // Check that implicit sizing is only where allowed. - arraySizesCheck(loc, type.getQualifier(), type.getArraySizes(), initializer != nullptr, false); - - if (! arrayQualifierError(loc, type.getQualifier()) && ! arrayError(loc, type)) - declareArray(loc, identifier, type, symbol); - - if (initializer) { - profileRequires(loc, ENoProfile, 120, E_GL_3DL_array_objects, "initializer"); - profileRequires(loc, EEsProfile, 300, nullptr, "initializer"); - } - } else { - // non-array case - if (symbol == nullptr) - symbol = declareNonArray(loc, identifier, type); - else if (type != symbol->getType()) - error(loc, "cannot change the type of", "redeclaration", symbol->getName().c_str()); - } - - if (symbol == nullptr) - return nullptr; - - // Deal with initializer - TIntermNode* initNode = nullptr; - if (symbol != nullptr && initializer) { - TVariable* variable = symbol->getAsVariable(); - if (! variable) { - error(loc, "initializer requires a variable, not a member", identifier.c_str(), ""); - return nullptr; - } - initNode = executeInitializer(loc, initializer, variable); - } - - // look for errors in layout qualifier use - layoutObjectCheck(loc, *symbol); - - // fix up - fixOffset(loc, *symbol); - - return initNode; -} - -// Pick up global defaults from the provide global defaults into dst. -void TParseContext::inheritGlobalDefaults(TQualifier& dst) const -{ - if (dst.storage == EvqVaryingOut) { - if (! dst.hasStream() && language == EShLangGeometry) - dst.layoutStream = globalOutputDefaults.layoutStream; - if (! dst.hasXfbBuffer()) - dst.layoutXfbBuffer = globalOutputDefaults.layoutXfbBuffer; - } -} - -// -// Make an internal-only variable whose name is for debug purposes only -// and won't be searched for. Callers will only use the return value to use -// the variable, not the name to look it up. It is okay if the name -// is the same as other names; there won't be any conflict. -// -TVariable* TParseContext::makeInternalVariable(const char* name, const TType& type) const -{ - TString* nameString = NewPoolTString(name); - TVariable* variable = new TVariable(nameString, type); - symbolTable.makeInternalVariable(*variable); - - return variable; -} - -// -// Declare a non-array variable, the main point being there is no redeclaration -// for resizing allowed. -// -// Return the successfully declared variable. -// -TVariable* TParseContext::declareNonArray(const TSourceLoc& loc, const TString& identifier, const TType& type) -{ - // make a new variable - TVariable* variable = new TVariable(&identifier, type); - - ioArrayCheck(loc, type, identifier); - - // add variable to symbol table - if (symbolTable.insert(*variable)) { - if (symbolTable.atGlobalLevel()) - trackLinkage(*variable); - return variable; - } - - error(loc, "redefinition", variable->getName().c_str(), ""); - return nullptr; -} - -// -// Handle all types of initializers from the grammar. -// -// Returning nullptr just means there is no code to execute to handle the -// initializer, which will, for example, be the case for constant initializers. -// -TIntermNode* TParseContext::executeInitializer(const TSourceLoc& loc, TIntermTyped* initializer, TVariable* variable) -{ - // - // Identifier must be of type constant, a global, or a temporary, and - // starting at version 120, desktop allows uniforms to have initializers. - // - TStorageQualifier qualifier = variable->getType().getQualifier().storage; - if (! (qualifier == EvqTemporary || qualifier == EvqGlobal || qualifier == EvqConst || - (qualifier == EvqUniform && profile != EEsProfile && version >= 120))) { - error(loc, " cannot initialize this type of qualifier ", variable->getType().getStorageQualifierString(), ""); - return nullptr; - } - arrayObjectCheck(loc, variable->getType(), "array initializer"); - - // - // If the initializer was from braces { ... }, we convert the whole subtree to a - // constructor-style subtree, allowing the rest of the code to operate - // identically for both kinds of initializers. - // - // Type can't be deduced from the initializer list, so a skeletal type to - // follow has to be passed in. Constness and specialization-constness - // should be deduced bottom up, not dictated by the skeletal type. - // - TType skeletalType; - skeletalType.shallowCopy(variable->getType()); - skeletalType.getQualifier().makeTemporary(); - initializer = convertInitializerList(loc, skeletalType, initializer); - if (! initializer) { - // error recovery; don't leave const without constant values - if (qualifier == EvqConst) - variable->getWritableType().getQualifier().makeTemporary(); - return nullptr; - } - - // Fix outer arrayness if variable is unsized, getting size from the initializer - if (initializer->getType().isSizedArray() && variable->getType().isUnsizedArray()) - variable->getWritableType().changeOuterArraySize(initializer->getType().getOuterArraySize()); - - // Inner arrayness can also get set by an initializer - if (initializer->getType().isArrayOfArrays() && variable->getType().isArrayOfArrays() && - initializer->getType().getArraySizes()->getNumDims() == - variable->getType().getArraySizes()->getNumDims()) { - // adopt unsized sizes from the initializer's sizes - for (int d = 1; d < variable->getType().getArraySizes()->getNumDims(); ++d) { - if (variable->getType().getArraySizes()->getDimSize(d) == UnsizedArraySize) { - variable->getWritableType().getArraySizes()->setDimSize(d, - initializer->getType().getArraySizes()->getDimSize(d)); - } - } - } - - // Uniforms require a compile-time constant initializer - if (qualifier == EvqUniform && ! initializer->getType().getQualifier().isFrontEndConstant()) { - error(loc, "uniform initializers must be constant", "=", "'%s'", variable->getType().getCompleteString().c_str()); - variable->getWritableType().getQualifier().makeTemporary(); - return nullptr; - } - // Global consts require a constant initializer (specialization constant is okay) - if (qualifier == EvqConst && symbolTable.atGlobalLevel() && ! initializer->getType().getQualifier().isConstant()) { - error(loc, "global const initializers must be constant", "=", "'%s'", variable->getType().getCompleteString().c_str()); - variable->getWritableType().getQualifier().makeTemporary(); - return nullptr; - } - - // Const variables require a constant initializer, depending on version - if (qualifier == EvqConst) { - if (! initializer->getType().getQualifier().isConstant()) { - const char* initFeature = "non-constant initializer"; - requireProfile(loc, ~EEsProfile, initFeature); - profileRequires(loc, ~EEsProfile, 420, E_GL_ARB_shading_language_420pack, initFeature); - variable->getWritableType().getQualifier().storage = EvqConstReadOnly; - qualifier = EvqConstReadOnly; - } - } else { - // Non-const global variables in ES need a const initializer. - // - // "In declarations of global variables with no storage qualifier or with a const - // qualifier any initializer must be a constant expression." - if (symbolTable.atGlobalLevel() && ! initializer->getType().getQualifier().isConstant()) { - const char* initFeature = "non-constant global initializer (needs GL_EXT_shader_non_constant_global_initializers)"; - if (profile == EEsProfile) { - if (relaxedErrors() && ! extensionTurnedOn(E_GL_EXT_shader_non_constant_global_initializers)) - warn(loc, "not allowed in this version", initFeature, ""); - else - profileRequires(loc, EEsProfile, 0, E_GL_EXT_shader_non_constant_global_initializers, initFeature); - } - } - } - - if (qualifier == EvqConst || qualifier == EvqUniform) { - // Compile-time tagging of the variable with its constant value... - - initializer = intermediate.addConversion(EOpAssign, variable->getType(), initializer); - if (! initializer || ! initializer->getType().getQualifier().isConstant() || variable->getType() != initializer->getType()) { - error(loc, "non-matching or non-convertible constant type for const initializer", - variable->getType().getStorageQualifierString(), ""); - variable->getWritableType().getQualifier().makeTemporary(); - return nullptr; - } - - // We either have a folded constant in getAsConstantUnion, or we have to use - // the initializer's subtree in the AST to represent the computation of a - // specialization constant. - assert(initializer->getAsConstantUnion() || initializer->getType().getQualifier().isSpecConstant()); - if (initializer->getAsConstantUnion()) - variable->setConstArray(initializer->getAsConstantUnion()->getConstArray()); - else { - // It's a specialization constant. - variable->getWritableType().getQualifier().makeSpecConstant(); - - // Keep the subtree that computes the specialization constant with the variable. - // Later, a symbol node will adopt the subtree from the variable. - variable->setConstSubtree(initializer); - } - } else { - // normal assigning of a value to a variable... - specializationCheck(loc, initializer->getType(), "initializer"); - TIntermSymbol* intermSymbol = intermediate.addSymbol(*variable, loc); - TIntermTyped* initNode = intermediate.addAssign(EOpAssign, intermSymbol, initializer, loc); - if (! initNode) - assignError(loc, "=", intermSymbol->getCompleteString(), initializer->getCompleteString()); - - return initNode; - } - - return nullptr; -} - -// -// Reprocess any initializer-list (the "{ ... }" syntax) parts of the -// initializer. -// -// Need to hierarchically assign correct types and implicit -// conversions. Will do this mimicking the same process used for -// creating a constructor-style initializer, ensuring we get the -// same form. However, it has to in parallel walk the 'type' -// passed in, as type cannot be deduced from an initializer list. -// -TIntermTyped* TParseContext::convertInitializerList(const TSourceLoc& loc, const TType& type, TIntermTyped* initializer) -{ - // Will operate recursively. Once a subtree is found that is constructor style, - // everything below it is already good: Only the "top part" of the initializer - // can be an initializer list, where "top part" can extend for several (or all) levels. - - // see if we have bottomed out in the tree within the initializer-list part - TIntermAggregate* initList = initializer->getAsAggregate(); - if (! initList || initList->getOp() != EOpNull) - return initializer; - - // Of the initializer-list set of nodes, need to process bottom up, - // so recurse deep, then process on the way up. - - // Go down the tree here... - if (type.isArray()) { - // The type's array might be unsized, which could be okay, so base sizes on the size of the aggregate. - // Later on, initializer execution code will deal with array size logic. - TType arrayType; - arrayType.shallowCopy(type); // sharing struct stuff is fine - arrayType.copyArraySizes(*type.getArraySizes()); // but get a fresh copy of the array information, to edit below - - // edit array sizes to fill in unsized dimensions - arrayType.changeOuterArraySize((int)initList->getSequence().size()); - TIntermTyped* firstInit = initList->getSequence()[0]->getAsTyped(); - if (arrayType.isArrayOfArrays() && firstInit->getType().isArray() && - arrayType.getArraySizes()->getNumDims() == firstInit->getType().getArraySizes()->getNumDims() + 1) { - for (int d = 1; d < arrayType.getArraySizes()->getNumDims(); ++d) { - if (arrayType.getArraySizes()->getDimSize(d) == UnsizedArraySize) - arrayType.getArraySizes()->setDimSize(d, firstInit->getType().getArraySizes()->getDimSize(d - 1)); - } - } - - TType elementType(arrayType, 0); // dereferenced type - for (size_t i = 0; i < initList->getSequence().size(); ++i) { - initList->getSequence()[i] = convertInitializerList(loc, elementType, initList->getSequence()[i]->getAsTyped()); - if (initList->getSequence()[i] == nullptr) - return nullptr; - } - - return addConstructor(loc, initList, arrayType); - } else if (type.isStruct()) { - if (type.getStruct()->size() != initList->getSequence().size()) { - error(loc, "wrong number of structure members", "initializer list", ""); - return nullptr; - } - for (size_t i = 0; i < type.getStruct()->size(); ++i) { - initList->getSequence()[i] = convertInitializerList(loc, *(*type.getStruct())[i].type, initList->getSequence()[i]->getAsTyped()); - if (initList->getSequence()[i] == nullptr) - return nullptr; - } - } else if (type.isMatrix()) { - if (type.getMatrixCols() != (int)initList->getSequence().size()) { - error(loc, "wrong number of matrix columns:", "initializer list", type.getCompleteString().c_str()); - return nullptr; - } - TType vectorType(type, 0); // dereferenced type - for (int i = 0; i < type.getMatrixCols(); ++i) { - initList->getSequence()[i] = convertInitializerList(loc, vectorType, initList->getSequence()[i]->getAsTyped()); - if (initList->getSequence()[i] == nullptr) - return nullptr; - } - } else if (type.isVector()) { - if (type.getVectorSize() != (int)initList->getSequence().size()) { - error(loc, "wrong vector size (or rows in a matrix column):", "initializer list", type.getCompleteString().c_str()); - return nullptr; - } - } else { - error(loc, "unexpected initializer-list type:", "initializer list", type.getCompleteString().c_str()); - return nullptr; - } - - // Now that the subtree is processed, process this node as if the - // initializer list is a set of arguments to a constructor. - TIntermNode* emulatedConstructorArguments; - if (initList->getSequence().size() == 1) - emulatedConstructorArguments = initList->getSequence()[0]; - else - emulatedConstructorArguments = initList; - return addConstructor(loc, emulatedConstructorArguments, type); -} - -// -// Test for the correctness of the parameters passed to various constructor functions -// and also convert them to the right data type, if allowed and required. -// -// 'node' is what to construct from. -// 'type' is what type to construct. -// -// Returns nullptr for an error or the constructed node (aggregate or typed) for no error. -// -TIntermTyped* TParseContext::addConstructor(const TSourceLoc& loc, TIntermNode* node, const TType& type) -{ - if (node == nullptr || node->getAsTyped() == nullptr) - return nullptr; - rValueErrorCheck(loc, "constructor", node->getAsTyped()); - - TIntermAggregate* aggrNode = node->getAsAggregate(); - TOperator op = intermediate.mapTypeToConstructorOp(type); - - // Combined texture-sampler constructors are completely semantic checked - // in constructorTextureSamplerError() - if (op == EOpConstructTextureSampler) - return intermediate.setAggregateOperator(aggrNode, op, type, loc); - - TTypeList::const_iterator memberTypes; - if (op == EOpConstructStruct) - memberTypes = type.getStruct()->begin(); - - TType elementType; - if (type.isArray()) { - TType dereferenced(type, 0); - elementType.shallowCopy(dereferenced); - } else - elementType.shallowCopy(type); - - bool singleArg; - if (aggrNode) { - if (aggrNode->getOp() != EOpNull) - singleArg = true; - else - singleArg = false; - } else - singleArg = true; - - TIntermTyped *newNode; - if (singleArg) { - // If structure constructor or array constructor is being called - // for only one parameter inside the structure, we need to call constructAggregate function once. - if (type.isArray()) - newNode = constructAggregate(node, elementType, 1, node->getLoc()); - else if (op == EOpConstructStruct) - newNode = constructAggregate(node, *(*memberTypes).type, 1, node->getLoc()); - else - newNode = constructBuiltIn(type, op, node->getAsTyped(), node->getLoc(), false); - - if (newNode && (type.isArray() || op == EOpConstructStruct)) - newNode = intermediate.setAggregateOperator(newNode, EOpConstructStruct, type, loc); - - return newNode; - } - - // - // Handle list of arguments. - // - TIntermSequence &sequenceVector = aggrNode->getSequence(); // Stores the information about the parameter to the constructor - // if the structure constructor contains more than one parameter, then construct - // each parameter - - int paramCount = 0; // keeps track of the constructor parameter number being checked - - // for each parameter to the constructor call, check to see if the right type is passed or convert them - // to the right type if possible (and allowed). - // for structure constructors, just check if the right type is passed, no conversion is allowed. - for (TIntermSequence::iterator p = sequenceVector.begin(); - p != sequenceVector.end(); p++, paramCount++) { - if (type.isArray()) - newNode = constructAggregate(*p, elementType, paramCount+1, node->getLoc()); - else if (op == EOpConstructStruct) - newNode = constructAggregate(*p, *(memberTypes[paramCount]).type, paramCount+1, node->getLoc()); - else - newNode = constructBuiltIn(type, op, (*p)->getAsTyped(), node->getLoc(), true); - - if (newNode) - *p = newNode; - else - return nullptr; - } - - return intermediate.setAggregateOperator(aggrNode, op, type, loc); -} - -// Function for constructor implementation. Calls addUnaryMath with appropriate EOp value -// for the parameter to the constructor (passed to this function). Essentially, it converts -// the parameter types correctly. If a constructor expects an int (like ivec2) and is passed a -// float, then float is converted to int. -// -// Returns nullptr for an error or the constructed node. -// -TIntermTyped* TParseContext::constructBuiltIn(const TType& type, TOperator op, TIntermTyped* node, const TSourceLoc& loc, - bool subset) -{ - // If we are changing a matrix in both domain of basic type and to a non matrix, - // do the shape change first (by default, below, basic type is changed before shape). - // This avoids requesting a matrix of a new type that is going to be discarded anyway. - // TODO: This could be generalized to more type combinations, but that would require - // more extensive testing and full algorithm rework. For now, the need to do two changes makes - // the recursive call work, and avoids the most aggregious case of creating integer matrices. - if (node->getType().isMatrix() && (type.isScalar() || type.isVector()) && - type.isFloatingDomain() != node->getType().isFloatingDomain()) { - TType transitionType(node->getBasicType(), glslang::EvqTemporary, type.getVectorSize(), 0, 0, node->isVector()); - TOperator transitionOp = intermediate.mapTypeToConstructorOp(transitionType); - node = constructBuiltIn(transitionType, transitionOp, node, loc, false); - } - - TIntermTyped* newNode; - TOperator basicOp; - - // - // First, convert types as needed. - // - switch (op) { - case EOpConstructVec2: - case EOpConstructVec3: - case EOpConstructVec4: - case EOpConstructMat2x2: - case EOpConstructMat2x3: - case EOpConstructMat2x4: - case EOpConstructMat3x2: - case EOpConstructMat3x3: - case EOpConstructMat3x4: - case EOpConstructMat4x2: - case EOpConstructMat4x3: - case EOpConstructMat4x4: - case EOpConstructFloat: - basicOp = EOpConstructFloat; - break; - - case EOpConstructDVec2: - case EOpConstructDVec3: - case EOpConstructDVec4: - case EOpConstructDMat2x2: - case EOpConstructDMat2x3: - case EOpConstructDMat2x4: - case EOpConstructDMat3x2: - case EOpConstructDMat3x3: - case EOpConstructDMat3x4: - case EOpConstructDMat4x2: - case EOpConstructDMat4x3: - case EOpConstructDMat4x4: - case EOpConstructDouble: - basicOp = EOpConstructDouble; - break; - - case EOpConstructF16Vec2: - case EOpConstructF16Vec3: - case EOpConstructF16Vec4: - case EOpConstructF16Mat2x2: - case EOpConstructF16Mat2x3: - case EOpConstructF16Mat2x4: - case EOpConstructF16Mat3x2: - case EOpConstructF16Mat3x3: - case EOpConstructF16Mat3x4: - case EOpConstructF16Mat4x2: - case EOpConstructF16Mat4x3: - case EOpConstructF16Mat4x4: - case EOpConstructFloat16: - basicOp = EOpConstructFloat16; - break; - - case EOpConstructI8Vec2: - case EOpConstructI8Vec3: - case EOpConstructI8Vec4: - case EOpConstructInt8: - basicOp = EOpConstructInt8; - break; - - case EOpConstructU8Vec2: - case EOpConstructU8Vec3: - case EOpConstructU8Vec4: - case EOpConstructUint8: - basicOp = EOpConstructUint8; - break; - - case EOpConstructI16Vec2: - case EOpConstructI16Vec3: - case EOpConstructI16Vec4: - case EOpConstructInt16: - basicOp = EOpConstructInt16; - break; - - case EOpConstructU16Vec2: - case EOpConstructU16Vec3: - case EOpConstructU16Vec4: - case EOpConstructUint16: - basicOp = EOpConstructUint16; - break; - - case EOpConstructIVec2: - case EOpConstructIVec3: - case EOpConstructIVec4: - case EOpConstructInt: - basicOp = EOpConstructInt; - break; - - case EOpConstructUVec2: - case EOpConstructUVec3: - case EOpConstructUVec4: - case EOpConstructUint: - basicOp = EOpConstructUint; - break; - - case EOpConstructI64Vec2: - case EOpConstructI64Vec3: - case EOpConstructI64Vec4: - case EOpConstructInt64: - basicOp = EOpConstructInt64; - break; - - case EOpConstructU64Vec2: - case EOpConstructU64Vec3: - case EOpConstructU64Vec4: - case EOpConstructUint64: - basicOp = EOpConstructUint64; - break; - - case EOpConstructBVec2: - case EOpConstructBVec3: - case EOpConstructBVec4: - case EOpConstructBool: - basicOp = EOpConstructBool; - break; - - case EOpConstructNonuniform: - node->getWritableType().getQualifier().nonUniform = true; - return node; - break; - - default: - error(loc, "unsupported construction", "", ""); - - return nullptr; - } - newNode = intermediate.addUnaryMath(basicOp, node, node->getLoc()); - if (newNode == nullptr) { - error(loc, "can't convert", "constructor", ""); - return nullptr; - } - - // - // Now, if there still isn't an operation to do the construction, and we need one, add one. - // - - // Otherwise, skip out early. - if (subset || (newNode != node && newNode->getType() == type)) - return newNode; - - // setAggregateOperator will insert a new node for the constructor, as needed. - return intermediate.setAggregateOperator(newNode, op, type, loc); -} - -// This function tests for the type of the parameters to the structure or array constructor. Raises -// an error message if the expected type does not match the parameter passed to the constructor. -// -// Returns nullptr for an error or the input node itself if the expected and the given parameter types match. -// -TIntermTyped* TParseContext::constructAggregate(TIntermNode* node, const TType& type, int paramCount, const TSourceLoc& loc) -{ - TIntermTyped* converted = intermediate.addConversion(EOpConstructStruct, type, node->getAsTyped()); - if (! converted || converted->getType() != type) { - error(loc, "", "constructor", "cannot convert parameter %d from '%s' to '%s'", paramCount, - node->getAsTyped()->getType().getCompleteString().c_str(), type.getCompleteString().c_str()); - - return nullptr; - } - - return converted; -} - -// -// Do everything needed to add an interface block. -// -void TParseContext::declareBlock(const TSourceLoc& loc, TTypeList& typeList, const TString* instanceName, - TArraySizes* arraySizes) -{ - blockStageIoCheck(loc, currentBlockQualifier); - blockQualifierCheck(loc, currentBlockQualifier, instanceName != nullptr); - if (arraySizes != nullptr) { - arraySizesCheck(loc, currentBlockQualifier, arraySizes, false, false); - arrayOfArrayVersionCheck(loc, arraySizes); - if (arraySizes->getNumDims() > 1) - requireProfile(loc, ~EEsProfile, "array-of-array of block"); - } - - // fix and check for member storage qualifiers and types that don't belong within a block - for (unsigned int member = 0; member < typeList.size(); ++member) { - TType& memberType = *typeList[member].type; - TQualifier& memberQualifier = memberType.getQualifier(); - const TSourceLoc& memberLoc = typeList[member].loc; - globalQualifierFixCheck(memberLoc, memberQualifier); - if (memberQualifier.storage != EvqTemporary && memberQualifier.storage != EvqGlobal && memberQualifier.storage != currentBlockQualifier.storage) - error(memberLoc, "member storage qualifier cannot contradict block storage qualifier", memberType.getFieldName().c_str(), ""); - memberQualifier.storage = currentBlockQualifier.storage; - if ((currentBlockQualifier.storage == EvqUniform || currentBlockQualifier.storage == EvqBuffer) && (memberQualifier.isInterpolation() || memberQualifier.isAuxiliary())) - error(memberLoc, "member of uniform or buffer block cannot have an auxiliary or interpolation qualifier", memberType.getFieldName().c_str(), ""); - if (memberType.isArray()) - arraySizesCheck(memberLoc, currentBlockQualifier, memberType.getArraySizes(), false, member == typeList.size() - 1); - if (memberQualifier.hasOffset()) { - if (spvVersion.spv == 0) { - requireProfile(memberLoc, ~EEsProfile, "offset on block member"); - profileRequires(memberLoc, ~EEsProfile, 440, E_GL_ARB_enhanced_layouts, "offset on block member"); - } - } - - if (memberType.containsOpaque()) - error(memberLoc, "member of block cannot be or contain a sampler, image, or atomic_uint type", typeList[member].type->getFieldName().c_str(), ""); - } - - // This might be a redeclaration of a built-in block. If so, redeclareBuiltinBlock() will - // do all the rest. - if (! symbolTable.atBuiltInLevel() && builtInName(*blockName)) { - redeclareBuiltinBlock(loc, typeList, *blockName, instanceName, arraySizes); - return; - } - - // Not a redeclaration of a built-in; check that all names are user names. - reservedErrorCheck(loc, *blockName); - if (instanceName) - reservedErrorCheck(loc, *instanceName); - for (unsigned int member = 0; member < typeList.size(); ++member) - reservedErrorCheck(typeList[member].loc, typeList[member].type->getFieldName()); - - // Make default block qualification, and adjust the member qualifications - - TQualifier defaultQualification; - switch (currentBlockQualifier.storage) { - case EvqUniform: defaultQualification = globalUniformDefaults; break; - case EvqBuffer: defaultQualification = globalBufferDefaults; break; - case EvqVaryingIn: defaultQualification = globalInputDefaults; break; - case EvqVaryingOut: defaultQualification = globalOutputDefaults; break; - default: defaultQualification.clear(); break; - } - - // Special case for "push_constant uniform", which has a default of std430, - // contrary to normal uniform defaults, and can't have a default tracked for it. - if (currentBlockQualifier.layoutPushConstant && !currentBlockQualifier.hasPacking()) - currentBlockQualifier.layoutPacking = ElpStd430; - - // fix and check for member layout qualifiers - - mergeObjectLayoutQualifiers(defaultQualification, currentBlockQualifier, true); - - // "The align qualifier can only be used on blocks or block members, and only for blocks declared with std140 or std430 layouts." - if (currentBlockQualifier.hasAlign()) { - if (defaultQualification.layoutPacking != ElpStd140 && defaultQualification.layoutPacking != ElpStd430) { - error(loc, "can only be used with std140 or std430 layout packing", "align", ""); - defaultQualification.layoutAlign = -1; - } - } - - bool memberWithLocation = false; - bool memberWithoutLocation = false; - for (unsigned int member = 0; member < typeList.size(); ++member) { - TQualifier& memberQualifier = typeList[member].type->getQualifier(); - const TSourceLoc& memberLoc = typeList[member].loc; - if (memberQualifier.hasStream()) { - if (defaultQualification.layoutStream != memberQualifier.layoutStream) - error(memberLoc, "member cannot contradict block", "stream", ""); - } - - // "This includes a block's inheritance of the - // current global default buffer, a block member's inheritance of the block's - // buffer, and the requirement that any *xfb_buffer* declared on a block - // member must match the buffer inherited from the block." - if (memberQualifier.hasXfbBuffer()) { - if (defaultQualification.layoutXfbBuffer != memberQualifier.layoutXfbBuffer) - error(memberLoc, "member cannot contradict block (or what block inherited from global)", "xfb_buffer", ""); - } - - if (memberQualifier.hasPacking()) - error(memberLoc, "member of block cannot have a packing layout qualifier", typeList[member].type->getFieldName().c_str(), ""); - if (memberQualifier.hasLocation()) { - const char* feature = "location on block member"; - switch (currentBlockQualifier.storage) { - case EvqVaryingIn: - case EvqVaryingOut: - requireProfile(memberLoc, ECoreProfile | ECompatibilityProfile | EEsProfile, feature); - profileRequires(memberLoc, ECoreProfile | ECompatibilityProfile, 440, E_GL_ARB_enhanced_layouts, feature); - profileRequires(memberLoc, EEsProfile, 320, Num_AEP_shader_io_blocks, AEP_shader_io_blocks, feature); - memberWithLocation = true; - break; - default: - error(memberLoc, "can only use in an in/out block", feature, ""); - break; - } - } else - memberWithoutLocation = true; - - // "The offset qualifier can only be used on block members of blocks declared with std140 or std430 layouts." - // "The align qualifier can only be used on blocks or block members, and only for blocks declared with std140 or std430 layouts." - if (memberQualifier.hasAlign() || memberQualifier.hasOffset()) { - if (defaultQualification.layoutPacking != ElpStd140 && defaultQualification.layoutPacking != ElpStd430) - error(memberLoc, "can only be used with std140 or std430 layout packing", "offset/align", ""); - } - - TQualifier newMemberQualification = defaultQualification; - mergeQualifiers(memberLoc, newMemberQualification, memberQualifier, false); - memberQualifier = newMemberQualification; - } - - layoutMemberLocationArrayCheck(loc, memberWithLocation, arraySizes); - - // Process the members - fixBlockLocations(loc, currentBlockQualifier, typeList, memberWithLocation, memberWithoutLocation); - fixBlockXfbOffsets(currentBlockQualifier, typeList); - fixBlockUniformOffsets(currentBlockQualifier, typeList); - for (unsigned int member = 0; member < typeList.size(); ++member) - layoutTypeCheck(typeList[member].loc, *typeList[member].type); - - // reverse merge, so that currentBlockQualifier now has all layout information - // (can't use defaultQualification directly, it's missing other non-layout-default-class qualifiers) - mergeObjectLayoutQualifiers(currentBlockQualifier, defaultQualification, true); - - // - // Build and add the interface block as a new type named 'blockName' - // - - TType blockType(&typeList, *blockName, currentBlockQualifier); - if (arraySizes != nullptr) - blockType.transferArraySizes(arraySizes); - else - ioArrayCheck(loc, blockType, instanceName ? *instanceName : *blockName); - - // - // Don't make a user-defined type out of block name; that will cause an error - // if the same block name gets reused in a different interface. - // - // "Block names have no other use within a shader - // beyond interface matching; it is a compile-time error to use a block name at global scope for anything - // other than as a block name (e.g., use of a block name for a global variable name or function name is - // currently reserved)." - // - // Use the symbol table to prevent normal reuse of the block's name, as a variable entry, - // whose type is EbtBlock, but without all the structure; that will come from the type - // the instances point to. - // - TType blockNameType(EbtBlock, blockType.getQualifier().storage); - TVariable* blockNameVar = new TVariable(blockName, blockNameType); - if (! symbolTable.insert(*blockNameVar)) { - TSymbol* existingName = symbolTable.find(*blockName); - if (existingName->getType().getBasicType() == EbtBlock) { - if (existingName->getType().getQualifier().storage == blockType.getQualifier().storage) { - error(loc, "Cannot reuse block name within the same interface:", blockName->c_str(), blockType.getStorageQualifierString()); - return; - } - } else { - error(loc, "block name cannot redefine a non-block name", blockName->c_str(), ""); - return; - } - } - - // Add the variable, as anonymous or named instanceName. - // Make an anonymous variable if no name was provided. - if (! instanceName) - instanceName = NewPoolTString(""); - - TVariable& variable = *new TVariable(instanceName, blockType); - if (! symbolTable.insert(variable)) { - if (*instanceName == "") - error(loc, "nameless block contains a member that already has a name at global scope", blockName->c_str(), ""); - else - error(loc, "block instance name redefinition", variable.getName().c_str(), ""); - - return; - } - - // Check for general layout qualifier errors - layoutObjectCheck(loc, variable); - - // fix up - if (isIoResizeArray(blockType)) { - ioArraySymbolResizeList.push_back(&variable); - checkIoArraysConsistency(loc, true); - } else - fixIoArraySize(loc, variable.getWritableType()); - - // Save it in the AST for linker use. - trackLinkage(variable); -} - -// Do all block-declaration checking regarding the combination of in/out/uniform/buffer -// with a particular stage. -void TParseContext::blockStageIoCheck(const TSourceLoc& loc, const TQualifier& qualifier) -{ - switch (qualifier.storage) { - case EvqUniform: - profileRequires(loc, EEsProfile, 300, nullptr, "uniform block"); - profileRequires(loc, ENoProfile, 140, nullptr, "uniform block"); - if (currentBlockQualifier.layoutPacking == ElpStd430 && ! currentBlockQualifier.layoutPushConstant) - error(loc, "requires the 'buffer' storage qualifier", "std430", ""); - break; - case EvqBuffer: - requireProfile(loc, EEsProfile | ECoreProfile | ECompatibilityProfile, "buffer block"); - profileRequires(loc, ECoreProfile | ECompatibilityProfile, 430, nullptr, "buffer block"); - profileRequires(loc, EEsProfile, 310, nullptr, "buffer block"); - break; - case EvqVaryingIn: - profileRequires(loc, ~EEsProfile, 150, E_GL_ARB_separate_shader_objects, "input block"); - // It is a compile-time error to have an input block in a vertex shader or an output block in a fragment shader - // "Compute shaders do not permit user-defined input variables..." - requireStage(loc, (EShLanguageMask)(EShLangTessControlMask|EShLangTessEvaluationMask|EShLangGeometryMask|EShLangFragmentMask), "input block"); - if (language == EShLangFragment) - profileRequires(loc, EEsProfile, 320, Num_AEP_shader_io_blocks, AEP_shader_io_blocks, "fragment input block"); - break; - case EvqVaryingOut: - profileRequires(loc, ~EEsProfile, 150, E_GL_ARB_separate_shader_objects, "output block"); - requireStage(loc, (EShLanguageMask)(EShLangVertexMask|EShLangTessControlMask|EShLangTessEvaluationMask|EShLangGeometryMask), "output block"); - // ES 310 can have a block before shader_io is turned on, so skip this test for built-ins - if (language == EShLangVertex && ! parsingBuiltins) - profileRequires(loc, EEsProfile, 320, Num_AEP_shader_io_blocks, AEP_shader_io_blocks, "vertex output block"); - break; - default: - error(loc, "only uniform, buffer, in, or out blocks are supported", blockName->c_str(), ""); - break; - } -} - -// Do all block-declaration checking regarding its qualifiers. -void TParseContext::blockQualifierCheck(const TSourceLoc& loc, const TQualifier& qualifier, bool /*instanceName*/) -{ - // The 4.5 specification says: - // - // interface-block : - // layout-qualifieropt interface-qualifier block-name { member-list } instance-nameopt ; - // - // interface-qualifier : - // in - // out - // patch in - // patch out - // uniform - // buffer - // - // Note however memory qualifiers aren't included, yet the specification also says - // - // "...memory qualifiers may also be used in the declaration of shader storage blocks..." - - if (qualifier.isInterpolation()) - error(loc, "cannot use interpolation qualifiers on an interface block", "flat/smooth/noperspective", ""); - if (qualifier.centroid) - error(loc, "cannot use centroid qualifier on an interface block", "centroid", ""); - if (qualifier.sample) - error(loc, "cannot use sample qualifier on an interface block", "sample", ""); - if (qualifier.invariant) - error(loc, "cannot use invariant qualifier on an interface block", "invariant", ""); - if (qualifier.layoutPushConstant) - intermediate.addPushConstantCount(); -} - -// -// "For a block, this process applies to the entire block, or until the first member -// is reached that has a location layout qualifier. When a block member is declared with a location -// qualifier, its location comes from that qualifier: The member's location qualifier overrides the block-level -// declaration. Subsequent members are again assigned consecutive locations, based on the newest location, -// until the next member declared with a location qualifier. The values used for locations do not have to be -// declared in increasing order." -void TParseContext::fixBlockLocations(const TSourceLoc& loc, TQualifier& qualifier, TTypeList& typeList, bool memberWithLocation, bool memberWithoutLocation) -{ - // "If a block has no block-level location layout qualifier, it is required that either all or none of its members - // have a location layout qualifier, or a compile-time error results." - if (! qualifier.hasLocation() && memberWithLocation && memberWithoutLocation) - error(loc, "either the block needs a location, or all members need a location, or no members have a location", "location", ""); - else { - if (memberWithLocation) { - // remove any block-level location and make it per *every* member - int nextLocation = 0; // by the rule above, initial value is not relevant - if (qualifier.hasAnyLocation()) { - nextLocation = qualifier.layoutLocation; - qualifier.layoutLocation = TQualifier::layoutLocationEnd; - if (qualifier.hasComponent()) { - // "It is a compile-time error to apply the *component* qualifier to a ... block" - error(loc, "cannot apply to a block", "component", ""); - } - if (qualifier.hasIndex()) { - error(loc, "cannot apply to a block", "index", ""); - } - } - for (unsigned int member = 0; member < typeList.size(); ++member) { - TQualifier& memberQualifier = typeList[member].type->getQualifier(); - const TSourceLoc& memberLoc = typeList[member].loc; - if (! memberQualifier.hasLocation()) { - if (nextLocation >= (int)TQualifier::layoutLocationEnd) - error(memberLoc, "location is too large", "location", ""); - memberQualifier.layoutLocation = nextLocation; - memberQualifier.layoutComponent = TQualifier::layoutComponentEnd; - } - nextLocation = memberQualifier.layoutLocation + intermediate.computeTypeLocationSize( - *typeList[member].type, language); - } - } - } -} - -void TParseContext::fixBlockXfbOffsets(TQualifier& qualifier, TTypeList& typeList) -{ - // "If a block is qualified with xfb_offset, all its - // members are assigned transform feedback buffer offsets. If a block is not qualified with xfb_offset, any - // members of that block not qualified with an xfb_offset will not be assigned transform feedback buffer - // offsets." - - if (! qualifier.hasXfbBuffer() || ! qualifier.hasXfbOffset()) - return; - - int nextOffset = qualifier.layoutXfbOffset; - for (unsigned int member = 0; member < typeList.size(); ++member) { - TQualifier& memberQualifier = typeList[member].type->getQualifier(); - bool containsDouble = false; - int memberSize = intermediate.computeTypeXfbSize(*typeList[member].type, containsDouble); - // see if we need to auto-assign an offset to this member - if (! memberQualifier.hasXfbOffset()) { - // "if applied to an aggregate containing a double, the offset must also be a multiple of 8" - if (containsDouble) - RoundToPow2(nextOffset, 8); - memberQualifier.layoutXfbOffset = nextOffset; - } else - nextOffset = memberQualifier.layoutXfbOffset; - nextOffset += memberSize; - } - - // The above gave all block members an offset, so we can take it off the block now, - // which will avoid double counting the offset usage. - qualifier.layoutXfbOffset = TQualifier::layoutXfbOffsetEnd; -} - -// Calculate and save the offset of each block member, using the recursively -// defined block offset rules and the user-provided offset and align. -// -// Also, compute and save the total size of the block. For the block's size, arrayness -// is not taken into account, as each element is backed by a separate buffer. -// -void TParseContext::fixBlockUniformOffsets(TQualifier& qualifier, TTypeList& typeList) -{ - if (! qualifier.isUniformOrBuffer()) - return; - if (qualifier.layoutPacking != ElpStd140 && qualifier.layoutPacking != ElpStd430) - return; - - int offset = 0; - int memberSize; - for (unsigned int member = 0; member < typeList.size(); ++member) { - TQualifier& memberQualifier = typeList[member].type->getQualifier(); - const TSourceLoc& memberLoc = typeList[member].loc; - - // "When align is applied to an array, it effects only the start of the array, not the array's internal stride." - - // modify just the children's view of matrix layout, if there is one for this member - TLayoutMatrix subMatrixLayout = typeList[member].type->getQualifier().layoutMatrix; - int dummyStride; - int memberAlignment = intermediate.getBaseAlignment(*typeList[member].type, memberSize, dummyStride, qualifier.layoutPacking == ElpStd140, - subMatrixLayout != ElmNone ? subMatrixLayout == ElmRowMajor : qualifier.layoutMatrix == ElmRowMajor); - if (memberQualifier.hasOffset()) { - // "The specified offset must be a multiple - // of the base alignment of the type of the block member it qualifies, or a compile-time error results." - if (! IsMultipleOfPow2(memberQualifier.layoutOffset, memberAlignment)) - error(memberLoc, "must be a multiple of the member's alignment", "offset", ""); - - // GLSL: "It is a compile-time error to specify an offset that is smaller than the offset of the previous - // member in the block or that lies within the previous member of the block" - if (spvVersion.spv == 0) { - if (memberQualifier.layoutOffset < offset) - error(memberLoc, "cannot lie in previous members", "offset", ""); - - // "The offset qualifier forces the qualified member to start at or after the specified - // integral-constant expression, which will be its byte offset from the beginning of the buffer. - // "The actual offset of a member is computed as - // follows: If offset was declared, start with that offset, otherwise start with the next available offset." - offset = std::max(offset, memberQualifier.layoutOffset); - } else { - // TODO: Vulkan: "It is a compile-time error to have any offset, explicit or assigned, - // that lies within another member of the block." - - offset = memberQualifier.layoutOffset; - } - } - - // "The actual alignment of a member will be the greater of the specified align alignment and the standard - // (e.g., std140) base alignment for the member's type." - if (memberQualifier.hasAlign()) - memberAlignment = std::max(memberAlignment, memberQualifier.layoutAlign); - - // "If the resulting offset is not a multiple of the actual alignment, - // increase it to the first offset that is a multiple of - // the actual alignment." - RoundToPow2(offset, memberAlignment); - typeList[member].type->getQualifier().layoutOffset = offset; - offset += memberSize; - } -} - -// For an identifier that is already declared, add more qualification to it. -void TParseContext::addQualifierToExisting(const TSourceLoc& loc, TQualifier qualifier, const TString& identifier) -{ - TSymbol* symbol = symbolTable.find(identifier); - if (! symbol) { - error(loc, "identifier not previously declared", identifier.c_str(), ""); - return; - } - if (symbol->getAsFunction()) { - error(loc, "cannot re-qualify a function name", identifier.c_str(), ""); - return; - } - - if (qualifier.isAuxiliary() || - qualifier.isMemory() || - qualifier.isInterpolation() || - qualifier.hasLayout() || - qualifier.storage != EvqTemporary || - qualifier.precision != EpqNone) { - error(loc, "cannot add storage, auxiliary, memory, interpolation, layout, or precision qualifier to an existing variable", identifier.c_str(), ""); - return; - } - - // For read-only built-ins, add a new symbol for holding the modified qualifier. - // This will bring up an entire block, if a block type has to be modified (e.g., gl_Position inside a block) - if (symbol->isReadOnly()) - symbol = symbolTable.copyUp(symbol); - - if (qualifier.invariant) { - if (intermediate.inIoAccessed(identifier)) - error(loc, "cannot change qualification after use", "invariant", ""); - symbol->getWritableType().getQualifier().invariant = true; - invariantCheck(loc, symbol->getType().getQualifier()); - } else if (qualifier.noContraction) { - if (intermediate.inIoAccessed(identifier)) - error(loc, "cannot change qualification after use", "precise", ""); - symbol->getWritableType().getQualifier().noContraction = true; - } else if (qualifier.specConstant) { - symbol->getWritableType().getQualifier().makeSpecConstant(); - if (qualifier.hasSpecConstantId()) - symbol->getWritableType().getQualifier().layoutSpecConstantId = qualifier.layoutSpecConstantId; - } else - warn(loc, "unknown requalification", "", ""); -} - -void TParseContext::addQualifierToExisting(const TSourceLoc& loc, TQualifier qualifier, TIdentifierList& identifiers) -{ - for (unsigned int i = 0; i < identifiers.size(); ++i) - addQualifierToExisting(loc, qualifier, *identifiers[i]); -} - -// Make sure 'invariant' isn't being applied to a non-allowed object. -void TParseContext::invariantCheck(const TSourceLoc& loc, const TQualifier& qualifier) -{ - if (! qualifier.invariant) - return; - - bool pipeOut = qualifier.isPipeOutput(); - bool pipeIn = qualifier.isPipeInput(); - if (version >= 300 || (profile != EEsProfile && version >= 420)) { - if (! pipeOut) - error(loc, "can only apply to an output", "invariant", ""); - } else { - if ((language == EShLangVertex && pipeIn) || (! pipeOut && ! pipeIn)) - error(loc, "can only apply to an output, or to an input in a non-vertex stage\n", "invariant", ""); - } -} - -// -// Updating default qualifier for the case of a declaration with just a qualifier, -// no type, block, or identifier. -// -void TParseContext::updateStandaloneQualifierDefaults(const TSourceLoc& loc, const TPublicType& publicType) -{ - if (publicType.shaderQualifiers.vertices != TQualifier::layoutNotSet) { - assert(language == EShLangTessControl || language == EShLangGeometry); - const char* id = (language == EShLangTessControl) ? "vertices" : "max_vertices"; - - if (publicType.qualifier.storage != EvqVaryingOut) - error(loc, "can only apply to 'out'", id, ""); - if (! intermediate.setVertices(publicType.shaderQualifiers.vertices)) - error(loc, "cannot change previously set layout value", id, ""); - - if (language == EShLangTessControl) - checkIoArraysConsistency(loc); - } - if (publicType.shaderQualifiers.invocations != TQualifier::layoutNotSet) { - if (publicType.qualifier.storage != EvqVaryingIn) - error(loc, "can only apply to 'in'", "invocations", ""); - if (! intermediate.setInvocations(publicType.shaderQualifiers.invocations)) - error(loc, "cannot change previously set layout value", "invocations", ""); - } - if (publicType.shaderQualifiers.geometry != ElgNone) { - if (publicType.qualifier.storage == EvqVaryingIn) { - switch (publicType.shaderQualifiers.geometry) { - case ElgPoints: - case ElgLines: - case ElgLinesAdjacency: - case ElgTriangles: - case ElgTrianglesAdjacency: - case ElgQuads: - case ElgIsolines: - if (intermediate.setInputPrimitive(publicType.shaderQualifiers.geometry)) { - if (language == EShLangGeometry) - checkIoArraysConsistency(loc); - } else - error(loc, "cannot change previously set input primitive", TQualifier::getGeometryString(publicType.shaderQualifiers.geometry), ""); - break; - default: - error(loc, "cannot apply to input", TQualifier::getGeometryString(publicType.shaderQualifiers.geometry), ""); - } - } else if (publicType.qualifier.storage == EvqVaryingOut) { - switch (publicType.shaderQualifiers.geometry) { - case ElgPoints: - case ElgLineStrip: - case ElgTriangleStrip: - if (! intermediate.setOutputPrimitive(publicType.shaderQualifiers.geometry)) - error(loc, "cannot change previously set output primitive", TQualifier::getGeometryString(publicType.shaderQualifiers.geometry), ""); - break; - default: - error(loc, "cannot apply to 'out'", TQualifier::getGeometryString(publicType.shaderQualifiers.geometry), ""); - } - } else - error(loc, "cannot apply to:", TQualifier::getGeometryString(publicType.shaderQualifiers.geometry), GetStorageQualifierString(publicType.qualifier.storage)); - } - if (publicType.shaderQualifiers.spacing != EvsNone) { - if (publicType.qualifier.storage == EvqVaryingIn) { - if (! intermediate.setVertexSpacing(publicType.shaderQualifiers.spacing)) - error(loc, "cannot change previously set vertex spacing", TQualifier::getVertexSpacingString(publicType.shaderQualifiers.spacing), ""); - } else - error(loc, "can only apply to 'in'", TQualifier::getVertexSpacingString(publicType.shaderQualifiers.spacing), ""); - } - if (publicType.shaderQualifiers.order != EvoNone) { - if (publicType.qualifier.storage == EvqVaryingIn) { - if (! intermediate.setVertexOrder(publicType.shaderQualifiers.order)) - error(loc, "cannot change previously set vertex order", TQualifier::getVertexOrderString(publicType.shaderQualifiers.order), ""); - } else - error(loc, "can only apply to 'in'", TQualifier::getVertexOrderString(publicType.shaderQualifiers.order), ""); - } - if (publicType.shaderQualifiers.pointMode) { - if (publicType.qualifier.storage == EvqVaryingIn) - intermediate.setPointMode(); - else - error(loc, "can only apply to 'in'", "point_mode", ""); - } - for (int i = 0; i < 3; ++i) { - if (publicType.shaderQualifiers.localSize[i] > 1) { - if (publicType.qualifier.storage == EvqVaryingIn) { - if (! intermediate.setLocalSize(i, publicType.shaderQualifiers.localSize[i])) - error(loc, "cannot change previously set size", "local_size", ""); - else { - int max = 0; - switch (i) { - case 0: max = resources.maxComputeWorkGroupSizeX; break; - case 1: max = resources.maxComputeWorkGroupSizeY; break; - case 2: max = resources.maxComputeWorkGroupSizeZ; break; - default: break; - } - if (intermediate.getLocalSize(i) > (unsigned int)max) - error(loc, "too large; see gl_MaxComputeWorkGroupSize", "local_size", ""); - - // Fix the existing constant gl_WorkGroupSize with this new information. - TVariable* workGroupSize = getEditableVariable("gl_WorkGroupSize"); - if (workGroupSize != nullptr) - workGroupSize->getWritableConstArray()[i].setUConst(intermediate.getLocalSize(i)); - } - } else - error(loc, "can only apply to 'in'", "local_size", ""); - } - if (publicType.shaderQualifiers.localSizeSpecId[i] != TQualifier::layoutNotSet) { - if (publicType.qualifier.storage == EvqVaryingIn) { - if (! intermediate.setLocalSizeSpecId(i, publicType.shaderQualifiers.localSizeSpecId[i])) - error(loc, "cannot change previously set size", "local_size", ""); - } else - error(loc, "can only apply to 'in'", "local_size id", ""); - // Set the workgroup built-in variable as a specialization constant - TVariable* workGroupSize = getEditableVariable("gl_WorkGroupSize"); - if (workGroupSize != nullptr) - workGroupSize->getWritableType().getQualifier().specConstant = true; - } - } - if (publicType.shaderQualifiers.earlyFragmentTests) { - if (publicType.qualifier.storage == EvqVaryingIn) - intermediate.setEarlyFragmentTests(); - else - error(loc, "can only apply to 'in'", "early_fragment_tests", ""); - } - if (publicType.shaderQualifiers.postDepthCoverage) { - if (publicType.qualifier.storage == EvqVaryingIn) - intermediate.setPostDepthCoverage(); - else - error(loc, "can only apply to 'in'", "post_coverage_coverage", ""); - } - if (publicType.shaderQualifiers.blendEquation) { - if (publicType.qualifier.storage != EvqVaryingOut) - error(loc, "can only apply to 'out'", "blend equation", ""); - } - - const TQualifier& qualifier = publicType.qualifier; - - if (qualifier.isAuxiliary() || - qualifier.isMemory() || - qualifier.isInterpolation() || - qualifier.precision != EpqNone) - error(loc, "cannot use auxiliary, memory, interpolation, or precision qualifier in a default qualifier declaration (declaration with no type)", "qualifier", ""); - // "The offset qualifier can only be used on block members of blocks..." - // "The align qualifier can only be used on blocks or block members..." - if (qualifier.hasOffset() || - qualifier.hasAlign()) - error(loc, "cannot use offset or align qualifiers in a default qualifier declaration (declaration with no type)", "layout qualifier", ""); - - layoutQualifierCheck(loc, qualifier); - - switch (qualifier.storage) { - case EvqUniform: - if (qualifier.hasMatrix()) - globalUniformDefaults.layoutMatrix = qualifier.layoutMatrix; - if (qualifier.hasPacking()) - globalUniformDefaults.layoutPacking = qualifier.layoutPacking; - break; - case EvqBuffer: - if (qualifier.hasMatrix()) - globalBufferDefaults.layoutMatrix = qualifier.layoutMatrix; - if (qualifier.hasPacking()) - globalBufferDefaults.layoutPacking = qualifier.layoutPacking; - break; - case EvqVaryingIn: - break; - case EvqVaryingOut: - if (qualifier.hasStream()) - globalOutputDefaults.layoutStream = qualifier.layoutStream; - if (qualifier.hasXfbBuffer()) - globalOutputDefaults.layoutXfbBuffer = qualifier.layoutXfbBuffer; - if (globalOutputDefaults.hasXfbBuffer() && qualifier.hasXfbStride()) { - if (! intermediate.setXfbBufferStride(globalOutputDefaults.layoutXfbBuffer, qualifier.layoutXfbStride)) - error(loc, "all stride settings must match for xfb buffer", "xfb_stride", "%d", qualifier.layoutXfbBuffer); - } - break; - default: - error(loc, "default qualifier requires 'uniform', 'buffer', 'in', or 'out' storage qualification", "", ""); - return; - } - - if (qualifier.hasBinding()) - error(loc, "cannot declare a default, include a type or full declaration", "binding", ""); - if (qualifier.hasAnyLocation()) - error(loc, "cannot declare a default, use a full declaration", "location/component/index", ""); - if (qualifier.hasXfbOffset()) - error(loc, "cannot declare a default, use a full declaration", "xfb_offset", ""); - if (qualifier.layoutPushConstant) - error(loc, "cannot declare a default, can only be used on a block", "push_constant", ""); - if (qualifier.hasSpecConstantId()) - error(loc, "cannot declare a default, can only be used on a scalar", "constant_id", ""); -} - -// -// Take the sequence of statements that has been built up since the last case/default, -// put it on the list of top-level nodes for the current (inner-most) switch statement, -// and follow that by the case/default we are on now. (See switch topology comment on -// TIntermSwitch.) -// -void TParseContext::wrapupSwitchSubsequence(TIntermAggregate* statements, TIntermNode* branchNode) -{ - TIntermSequence* switchSequence = switchSequenceStack.back(); - - if (statements) { - if (switchSequence->size() == 0) - error(statements->getLoc(), "cannot have statements before first case/default label", "switch", ""); - statements->setOperator(EOpSequence); - switchSequence->push_back(statements); - } - if (branchNode) { - // check all previous cases for the same label (or both are 'default') - for (unsigned int s = 0; s < switchSequence->size(); ++s) { - TIntermBranch* prevBranch = (*switchSequence)[s]->getAsBranchNode(); - if (prevBranch) { - TIntermTyped* prevExpression = prevBranch->getExpression(); - TIntermTyped* newExpression = branchNode->getAsBranchNode()->getExpression(); - if (prevExpression == nullptr && newExpression == nullptr) - error(branchNode->getLoc(), "duplicate label", "default", ""); - else if (prevExpression != nullptr && - newExpression != nullptr && - prevExpression->getAsConstantUnion() && - newExpression->getAsConstantUnion() && - prevExpression->getAsConstantUnion()->getConstArray()[0].getIConst() == - newExpression->getAsConstantUnion()->getConstArray()[0].getIConst()) - error(branchNode->getLoc(), "duplicated value", "case", ""); - } - } - switchSequence->push_back(branchNode); - } -} - -// -// Turn the top-level node sequence built up of wrapupSwitchSubsequence9) -// into a switch node. -// -TIntermNode* TParseContext::addSwitch(const TSourceLoc& loc, TIntermTyped* expression, TIntermAggregate* lastStatements) -{ - profileRequires(loc, EEsProfile, 300, nullptr, "switch statements"); - profileRequires(loc, ENoProfile, 130, nullptr, "switch statements"); - - wrapupSwitchSubsequence(lastStatements, nullptr); - - if (expression == nullptr || - (expression->getBasicType() != EbtInt && expression->getBasicType() != EbtUint) || - expression->getType().isArray() || expression->getType().isMatrix() || expression->getType().isVector()) - error(loc, "condition must be a scalar integer expression", "switch", ""); - - // If there is nothing to do, drop the switch but still execute the expression - TIntermSequence* switchSequence = switchSequenceStack.back(); - if (switchSequence->size() == 0) - return expression; - - if (lastStatements == nullptr) { - // This was originally an ERRROR, because early versions of the specification said - // "it is an error to have no statement between a label and the end of the switch statement." - // The specifications were updated to remove this (being ill-defined what a "statement" was), - // so, this became a warning. However, 3.0 tests still check for the error. - if (profile == EEsProfile && version <= 300 && ! relaxedErrors()) - error(loc, "last case/default label not followed by statements", "switch", ""); - else - warn(loc, "last case/default label not followed by statements", "switch", ""); - - // emulate a break for error recovery - lastStatements = intermediate.makeAggregate(intermediate.addBranch(EOpBreak, loc)); - lastStatements->setOperator(EOpSequence); - switchSequence->push_back(lastStatements); - } - - TIntermAggregate* body = new TIntermAggregate(EOpSequence); - body->getSequence() = *switchSequenceStack.back(); - body->setLoc(loc); - - TIntermSwitch* switchNode = new TIntermSwitch(expression, body); - switchNode->setLoc(loc); - - return switchNode; -} - -} // end namespace glslang diff --git a/External/glslang/glslang/MachineIndependent/ParseHelper.h b/External/glslang/glslang/MachineIndependent/ParseHelper.h deleted file mode 100644 index 21779c71..00000000 --- a/External/glslang/glslang/MachineIndependent/ParseHelper.h +++ /dev/null @@ -1,503 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// Copyright (C) 2012-2013 LunarG, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -// -// 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), - parsingBuiltins(parsingBuiltins), scanContext(nullptr), ppContext(nullptr), - limits(resources.limits), - globalUniformBlock(nullptr), - globalUniformBinding(TQualifier::layoutBindingEnd), - globalUniformSet(TQualifier::layoutSetEnd) - { - if (entryPoint != nullptr) - sourceEntryPointName = *entryPoint; - } - virtual ~TParseContextBase() { } - - 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, ...); - - 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); - } - - // Manage the global uniform block (default uniforms in GLSL, $Global in HLSL) - virtual void growGlobalUniformBlock(const TSourceLoc&, TType&, const TString& memberName, TTypeList* typeList = nullptr); - - // 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; - -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); - - void makeEditable(TSymbol*&) override; - bool isIoResizeArray(const TType&) const; - void fixIoArraySize(const TSourceLoc&, TType&); - void ioArrayCheck(const TSourceLoc&, const TType&, const TString& identifier); - void handleIoResizeArrayAccess(const TSourceLoc&, TIntermTyped* base); - void checkIoArraysConsistency(const TSourceLoc&, bool tailOnly = false); - int getIoArrayImplicitSize() 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, const TString& field); - 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 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&); - 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*, bool 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 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 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 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 fixBlockXfbOffsets(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); - - 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*); - -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); - void finish() override; - -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; - int* atomicUintOffsets; // to become an array of the right size to hold an offset per binding point - TString currentCaller; // name of last function body entered (not valid when at global scope) - TIdSetType inductiveLoopIds; - bool anyIndexLimits; - 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; -}; - -} // end namespace glslang - -#endif // _PARSER_HELPER_INCLUDED_ diff --git a/External/glslang/glslang/MachineIndependent/PoolAlloc.cpp b/External/glslang/glslang/MachineIndependent/PoolAlloc.cpp deleted file mode 100644 index 84c40f4e..00000000 --- a/External/glslang/glslang/MachineIndependent/PoolAlloc.cpp +++ /dev/null @@ -1,315 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -#include "../Include/Common.h" -#include "../Include/PoolAlloc.h" - -#include "../Include/InitializeGlobals.h" -#include "../OSDependent/osinclude.h" - -namespace glslang { - -// Process-wide TLS index -OS_TLSIndex PoolIndex; - -// Return the thread-specific current pool. -TPoolAllocator& GetThreadPoolAllocator() -{ - return *static_cast(OS_GetTLSValue(PoolIndex)); -} - -// Set the thread-specific current pool. -void SetThreadPoolAllocator(TPoolAllocator* poolAllocator) -{ - OS_SetTLSValue(PoolIndex, poolAllocator); -} - -// Process-wide set up of the TLS pool storage. -bool InitializePoolIndex() -{ - // Allocate a TLS index. - if ((PoolIndex = OS_AllocTLSIndex()) == OS_INVALID_TLS_INDEX) - return false; - - return true; -} - -// -// Implement the functionality of the TPoolAllocator class, which -// is documented in PoolAlloc.h. -// -TPoolAllocator::TPoolAllocator(int growthIncrement, int allocationAlignment) : - pageSize(growthIncrement), - alignment(allocationAlignment), - freeList(nullptr), - inUseList(nullptr), - numCalls(0) -{ - // - // Don't allow page sizes we know are smaller than all common - // OS page sizes. - // - if (pageSize < 4*1024) - pageSize = 4*1024; - - // - // A large currentPageOffset indicates a new page needs to - // be obtained to allocate memory. - // - currentPageOffset = pageSize; - - // - // Adjust alignment to be at least pointer aligned and - // power of 2. - // - size_t minAlign = sizeof(void*); - alignment &= ~(minAlign - 1); - if (alignment < minAlign) - alignment = minAlign; - size_t a = 1; - while (a < alignment) - a <<= 1; - alignment = a; - alignmentMask = a - 1; - - // - // Align header skip - // - headerSkip = minAlign; - if (headerSkip < sizeof(tHeader)) { - headerSkip = (sizeof(tHeader) + alignmentMask) & ~alignmentMask; - } - - push(); -} - -TPoolAllocator::~TPoolAllocator() -{ - while (inUseList) { - tHeader* next = inUseList->nextPage; - inUseList->~tHeader(); - delete [] reinterpret_cast(inUseList); - inUseList = next; - } - - // - // Always delete the free list memory - it can't be being - // (correctly) referenced, whether the pool allocator was - // global or not. We should not check the guard blocks - // here, because we did it already when the block was - // placed into the free list. - // - while (freeList) { - tHeader* next = freeList->nextPage; - delete [] reinterpret_cast(freeList); - freeList = next; - } -} - -const unsigned char TAllocation::guardBlockBeginVal = 0xfb; -const unsigned char TAllocation::guardBlockEndVal = 0xfe; -const unsigned char TAllocation::userDataFill = 0xcd; - -# ifdef GUARD_BLOCKS - const size_t TAllocation::guardBlockSize = 16; -# else - const size_t TAllocation::guardBlockSize = 0; -# endif - -// -// Check a single guard block for damage -// -#ifdef GUARD_BLOCKS -void TAllocation::checkGuardBlock(unsigned char* blockMem, unsigned char val, const char* locText) const -#else -void TAllocation::checkGuardBlock(unsigned char*, unsigned char, const char*) const -#endif -{ -#ifdef GUARD_BLOCKS - for (size_t x = 0; x < guardBlockSize; x++) { - if (blockMem[x] != val) { - const int maxSize = 80; - char assertMsg[maxSize]; - - // We don't print the assert message. It's here just to be helpful. - snprintf(assertMsg, maxSize, "PoolAlloc: Damage %s %zu byte allocation at 0x%p\n", - locText, size, data()); - assert(0 && "PoolAlloc: Damage in guard block"); - } - } -#else - assert(guardBlockSize == 0); -#endif -} - -void TPoolAllocator::push() -{ - tAllocState state = { currentPageOffset, inUseList }; - - stack.push_back(state); - - // - // Indicate there is no current page to allocate from. - // - currentPageOffset = pageSize; -} - -// -// Do a mass-deallocation of all the individual allocations -// that have occurred since the last push(), or since the -// last pop(), or since the object's creation. -// -// The deallocated pages are saved for future allocations. -// -void TPoolAllocator::pop() -{ - if (stack.size() < 1) - return; - - tHeader* page = stack.back().page; - currentPageOffset = stack.back().offset; - - while (inUseList != page) { - tHeader* nextInUse = inUseList->nextPage; - size_t pageCount = inUseList->pageCount; - - // This technically ends the lifetime of the header as C++ object, - // but we will still control the memory and reuse it. - inUseList->~tHeader(); // currently, just a debug allocation checker - - if (pageCount > 1) { - delete [] reinterpret_cast(inUseList); - } else { - inUseList->nextPage = freeList; - freeList = inUseList; - } - inUseList = nextInUse; - } - - stack.pop_back(); -} - -// -// Do a mass-deallocation of all the individual allocations -// that have occurred. -// -void TPoolAllocator::popAll() -{ - while (stack.size() > 0) - pop(); -} - -void* TPoolAllocator::allocate(size_t numBytes) -{ - // If we are using guard blocks, all allocations are bracketed by - // them: [guardblock][allocation][guardblock]. numBytes is how - // much memory the caller asked for. allocationSize is the total - // size including guard blocks. In release build, - // guardBlockSize=0 and this all gets optimized away. - size_t allocationSize = TAllocation::allocationSize(numBytes); - - // - // Just keep some interesting statistics. - // - ++numCalls; - totalBytes += numBytes; - - // - // Do the allocation, most likely case first, for efficiency. - // This step could be moved to be inline sometime. - // - if (currentPageOffset + allocationSize <= pageSize) { - // - // Safe to allocate from currentPageOffset. - // - unsigned char* memory = reinterpret_cast(inUseList) + currentPageOffset; - currentPageOffset += allocationSize; - currentPageOffset = (currentPageOffset + alignmentMask) & ~alignmentMask; - - return initializeAllocation(inUseList, memory, numBytes); - } - - if (allocationSize + headerSkip > pageSize) { - // - // Do a multi-page allocation. Don't mix these with the others. - // The OS is efficient and allocating and free-ing multiple pages. - // - size_t numBytesToAlloc = allocationSize + headerSkip; - tHeader* memory = reinterpret_cast(::new char[numBytesToAlloc]); - if (memory == 0) - return 0; - - // Use placement-new to initialize header - new(memory) tHeader(inUseList, (numBytesToAlloc + pageSize - 1) / pageSize); - inUseList = memory; - - currentPageOffset = pageSize; // make next allocation come from a new page - - // No guard blocks for multi-page allocations (yet) - return reinterpret_cast(reinterpret_cast(memory) + headerSkip); - } - - // - // Need a simple page to allocate from. - // - tHeader* memory; - if (freeList) { - memory = freeList; - freeList = freeList->nextPage; - } else { - memory = reinterpret_cast(::new char[pageSize]); - if (memory == 0) - return 0; - } - - // Use placement-new to initialize header - new(memory) tHeader(inUseList, 1); - inUseList = memory; - - unsigned char* ret = reinterpret_cast(inUseList) + headerSkip; - currentPageOffset = (headerSkip + allocationSize + alignmentMask) & ~alignmentMask; - - return initializeAllocation(inUseList, ret, numBytes); -} - -// -// Check all allocations in a list for damage by calling check on each. -// -void TAllocation::checkAllocList() const -{ - for (const TAllocation* alloc = this; alloc != 0; alloc = alloc->prevAlloc) - alloc->check(); -} - -} // end namespace glslang diff --git a/External/glslang/glslang/MachineIndependent/RemoveTree.cpp b/External/glslang/glslang/MachineIndependent/RemoveTree.cpp deleted file mode 100644 index 1d33bfd2..00000000 --- a/External/glslang/glslang/MachineIndependent/RemoveTree.cpp +++ /dev/null @@ -1,118 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// Copyright (C) 2013 LunarG, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -#include "../Include/intermediate.h" -#include "RemoveTree.h" - -namespace glslang { - -// -// Code to recursively delete the intermediate tree. -// -struct TRemoveTraverser : TIntermTraverser { - TRemoveTraverser() : TIntermTraverser(false, false, true, false) {} - - virtual void visitSymbol(TIntermSymbol* node) - { - delete node; - } - - virtual bool visitBinary(TVisit /* visit*/ , TIntermBinary* node) - { - delete node; - - return true; - } - - virtual bool visitUnary(TVisit /* visit */, TIntermUnary* node) - { - delete node; - - return true; - } - - virtual bool visitAggregate(TVisit /* visit*/ , TIntermAggregate* node) - { - delete node; - - return true; - } - - virtual bool visitSelection(TVisit /* visit*/ , TIntermSelection* node) - { - delete node; - - return true; - } - - virtual bool visitSwitch(TVisit /* visit*/ , TIntermSwitch* node) - { - delete node; - - return true; - } - - virtual void visitConstantUnion(TIntermConstantUnion* node) - { - delete node; - } - - virtual bool visitLoop(TVisit /* visit*/ , TIntermLoop* node) - { - delete node; - - return true; - } - - virtual bool visitBranch(TVisit /* visit*/ , TIntermBranch* node) - { - delete node; - - return true; - } -}; - -// -// Entry point. -// -void RemoveAllTreeNodes(TIntermNode* root) -{ - TRemoveTraverser it; - - root->traverse(&it); -} - -} // end namespace glslang diff --git a/External/glslang/glslang/MachineIndependent/RemoveTree.h b/External/glslang/glslang/MachineIndependent/RemoveTree.h deleted file mode 100644 index 1ed01562..00000000 --- a/External/glslang/glslang/MachineIndependent/RemoveTree.h +++ /dev/null @@ -1,41 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -#pragma once - -namespace glslang { - -void RemoveAllTreeNodes(TIntermNode*); - -} // end namespace glslang diff --git a/External/glslang/glslang/MachineIndependent/Scan.cpp b/External/glslang/glslang/MachineIndependent/Scan.cpp deleted file mode 100644 index 7232baeb..00000000 --- a/External/glslang/glslang/MachineIndependent/Scan.cpp +++ /dev/null @@ -1,1694 +0,0 @@ -// -// 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. -// - -// -// GLSL scanning, leveraging the scanning done by the preprocessor. -// - -#include -#include -#include - -#include "../Include/Types.h" -#include "SymbolTable.h" -#include "ParseHelper.h" -#include "attribute.h" -#include "glslang_tab.cpp.h" -#include "ScanContext.h" -#include "Scan.h" - -// preprocessor includes -#include "preprocessor/PpContext.h" -#include "preprocessor/PpTokens.h" - -// Required to avoid missing prototype warnings for some compilers -int yylex(YYSTYPE*, glslang::TParseContext&); - -namespace glslang { - -// read past any white space -void TInputScanner::consumeWhiteSpace(bool& foundNonSpaceTab) -{ - int c = peek(); // don't accidentally consume anything other than whitespace - while (c == ' ' || c == '\t' || c == '\r' || c == '\n') { - if (c == '\r' || c == '\n') - foundNonSpaceTab = true; - get(); - c = peek(); - } -} - -// return true if a comment was actually consumed -bool TInputScanner::consumeComment() -{ - if (peek() != '/') - return false; - - get(); // consume the '/' - int c = peek(); - if (c == '/') { - - // a '//' style comment - get(); // consume the second '/' - c = get(); - do { - while (c != EndOfInput && c != '\\' && c != '\r' && c != '\n') - c = get(); - - if (c == EndOfInput || c == '\r' || c == '\n') { - while (c == '\r' || c == '\n') - c = get(); - - // we reached the end of the comment - break; - } else { - // it's a '\', so we need to keep going, after skipping what's escaped - - // read the skipped character - c = get(); - - // if it's a two-character newline, skip both characters - if (c == '\r' && peek() == '\n') - get(); - c = get(); - } - } while (true); - - // put back the last non-comment character - if (c != EndOfInput) - unget(); - - return true; - } else if (c == '*') { - - // a '/*' style comment - get(); // consume the '*' - c = get(); - do { - while (c != EndOfInput && c != '*') - c = get(); - if (c == '*') { - c = get(); - if (c == '/') - break; // end of comment - // not end of comment - } else // end of input - break; - } while (true); - - return true; - } else { - // it's not a comment, put the '/' back - unget(); - - return false; - } -} - -// skip whitespace, then skip a comment, rinse, repeat -void TInputScanner::consumeWhitespaceComment(bool& foundNonSpaceTab) -{ - do { - consumeWhiteSpace(foundNonSpaceTab); - - // if not starting a comment now, then done - int c = peek(); - if (c != '/' || c == EndOfInput) - return; - - // skip potential comment - foundNonSpaceTab = true; - if (! consumeComment()) - return; - - } while (true); -} - -// Returns true if there was non-white space (e.g., a comment, newline) before the #version -// or no #version was found; otherwise, returns false. There is no error case, it always -// succeeds, but will leave version == 0 if no #version was found. -// -// Sets notFirstToken based on whether tokens (beyond white space and comments) -// appeared before the #version. -// -// N.B. does not attempt to leave input in any particular known state. The assumption -// is that scanning will start anew, following the rules for the chosen version/profile, -// and with a corresponding parsing context. -// -bool TInputScanner::scanVersion(int& version, EProfile& profile, bool& notFirstToken) -{ - // This function doesn't have to get all the semantics correct, - // just find the #version if there is a correct one present. - // The preprocessor will have the responsibility of getting all the semantics right. - - bool versionNotFirst = false; // means not first WRT comments and white space, nothing more - notFirstToken = false; // means not first WRT to real tokens - version = 0; // means not found - profile = ENoProfile; - - bool foundNonSpaceTab = false; - bool lookingInMiddle = false; - int c; - do { - if (lookingInMiddle) { - notFirstToken = true; - // make forward progress by finishing off the current line plus extra new lines - if (peek() == '\n' || peek() == '\r') { - while (peek() == '\n' || peek() == '\r') - get(); - } else - do { - c = get(); - } while (c != EndOfInput && c != '\n' && c != '\r'); - while (peek() == '\n' || peek() == '\r') - get(); - if (peek() == EndOfInput) - return true; - } - lookingInMiddle = true; - - // Nominal start, skipping the desktop allowed comments and white space, but tracking if - // something else was found for ES: - consumeWhitespaceComment(foundNonSpaceTab); - if (foundNonSpaceTab) - versionNotFirst = true; - - // "#" - if (get() != '#') { - versionNotFirst = true; - continue; - } - - // whitespace - do { - c = get(); - } while (c == ' ' || c == '\t'); - - // "version" - if ( c != 'v' || - get() != 'e' || - get() != 'r' || - get() != 's' || - get() != 'i' || - get() != 'o' || - get() != 'n') { - versionNotFirst = true; - continue; - } - - // whitespace - do { - c = get(); - } while (c == ' ' || c == '\t'); - - // version number - while (c >= '0' && c <= '9') { - version = 10 * version + (c - '0'); - c = get(); - } - if (version == 0) { - versionNotFirst = true; - continue; - } - - // whitespace - while (c == ' ' || c == '\t') - c = get(); - - // profile - const int maxProfileLength = 13; // not including any 0 - char profileString[maxProfileLength]; - int profileLength; - for (profileLength = 0; profileLength < maxProfileLength; ++profileLength) { - if (c == EndOfInput || c == ' ' || c == '\t' || c == '\n' || c == '\r') - break; - profileString[profileLength] = (char)c; - c = get(); - } - if (c != EndOfInput && c != ' ' && c != '\t' && c != '\n' && c != '\r') { - versionNotFirst = true; - continue; - } - - if (profileLength == 2 && strncmp(profileString, "es", profileLength) == 0) - profile = EEsProfile; - else if (profileLength == 4 && strncmp(profileString, "core", profileLength) == 0) - profile = ECoreProfile; - else if (profileLength == 13 && strncmp(profileString, "compatibility", profileLength) == 0) - profile = ECompatibilityProfile; - - return versionNotFirst; - } while (true); -} - -// Fill this in when doing glslang-level scanning, to hand back to the parser. -class TParserToken { -public: - explicit TParserToken(YYSTYPE& b) : sType(b) { } - - YYSTYPE& sType; -protected: - TParserToken(TParserToken&); - TParserToken& operator=(TParserToken&); -}; - -} // end namespace glslang - -// This is the function the glslang parser (i.e., bison) calls to get its next token -int yylex(YYSTYPE* glslangTokenDesc, glslang::TParseContext& parseContext) -{ - glslang::TParserToken token(*glslangTokenDesc); - - return parseContext.getScanContext()->tokenize(parseContext.getPpContext(), token); -} - -namespace { - -struct str_eq -{ - bool operator()(const char* lhs, const char* rhs) const - { - return strcmp(lhs, rhs) == 0; - } -}; - -struct str_hash -{ - size_t operator()(const char* str) const - { - // djb2 - unsigned long hash = 5381; - int c; - - while ((c = *str++) != 0) - hash = ((hash << 5) + hash) + c; - - return hash; - } -}; - -// A single global usable by all threads, by all versions, by all languages. -// After a single process-level initialization, this is read only and thread safe -std::unordered_map* KeywordMap = nullptr; -std::unordered_set* ReservedSet = nullptr; - -}; - -namespace glslang { - -void TScanContext::fillInKeywordMap() -{ - if (KeywordMap != nullptr) { - // this is really an error, as this should called only once per process - // but, the only risk is if two threads called simultaneously - return; - } - KeywordMap = new std::unordered_map; - - (*KeywordMap)["const"] = CONST; - (*KeywordMap)["uniform"] = UNIFORM; - (*KeywordMap)["nonuniformEXT"] = NONUNIFORM; - (*KeywordMap)["in"] = IN; - (*KeywordMap)["out"] = OUT; - (*KeywordMap)["inout"] = INOUT; - (*KeywordMap)["struct"] = STRUCT; - (*KeywordMap)["break"] = BREAK; - (*KeywordMap)["continue"] = CONTINUE; - (*KeywordMap)["do"] = DO; - (*KeywordMap)["for"] = FOR; - (*KeywordMap)["while"] = WHILE; - (*KeywordMap)["switch"] = SWITCH; - (*KeywordMap)["case"] = CASE; - (*KeywordMap)["default"] = DEFAULT; - (*KeywordMap)["if"] = IF; - (*KeywordMap)["else"] = ELSE; - (*KeywordMap)["discard"] = DISCARD; - (*KeywordMap)["return"] = RETURN; - (*KeywordMap)["void"] = VOID; - (*KeywordMap)["bool"] = BOOL; - (*KeywordMap)["float"] = FLOAT; - (*KeywordMap)["int"] = INT; - (*KeywordMap)["bvec2"] = BVEC2; - (*KeywordMap)["bvec3"] = BVEC3; - (*KeywordMap)["bvec4"] = BVEC4; - (*KeywordMap)["vec2"] = VEC2; - (*KeywordMap)["vec3"] = VEC3; - (*KeywordMap)["vec4"] = VEC4; - (*KeywordMap)["ivec2"] = IVEC2; - (*KeywordMap)["ivec3"] = IVEC3; - (*KeywordMap)["ivec4"] = IVEC4; - (*KeywordMap)["mat2"] = MAT2; - (*KeywordMap)["mat3"] = MAT3; - (*KeywordMap)["mat4"] = MAT4; - (*KeywordMap)["true"] = BOOLCONSTANT; - (*KeywordMap)["false"] = BOOLCONSTANT; - (*KeywordMap)["attribute"] = ATTRIBUTE; - (*KeywordMap)["varying"] = VARYING; - (*KeywordMap)["buffer"] = BUFFER; - (*KeywordMap)["coherent"] = COHERENT; - (*KeywordMap)["restrict"] = RESTRICT; - (*KeywordMap)["readonly"] = READONLY; - (*KeywordMap)["writeonly"] = WRITEONLY; - (*KeywordMap)["atomic_uint"] = ATOMIC_UINT; - (*KeywordMap)["volatile"] = VOLATILE; - (*KeywordMap)["layout"] = LAYOUT; - (*KeywordMap)["shared"] = SHARED; - (*KeywordMap)["patch"] = PATCH; - (*KeywordMap)["sample"] = SAMPLE; - (*KeywordMap)["subroutine"] = SUBROUTINE; - (*KeywordMap)["highp"] = HIGH_PRECISION; - (*KeywordMap)["mediump"] = MEDIUM_PRECISION; - (*KeywordMap)["lowp"] = LOW_PRECISION; - (*KeywordMap)["precision"] = PRECISION; - (*KeywordMap)["mat2x2"] = MAT2X2; - (*KeywordMap)["mat2x3"] = MAT2X3; - (*KeywordMap)["mat2x4"] = MAT2X4; - (*KeywordMap)["mat3x2"] = MAT3X2; - (*KeywordMap)["mat3x3"] = MAT3X3; - (*KeywordMap)["mat3x4"] = MAT3X4; - (*KeywordMap)["mat4x2"] = MAT4X2; - (*KeywordMap)["mat4x3"] = MAT4X3; - (*KeywordMap)["mat4x4"] = MAT4X4; - (*KeywordMap)["dmat2"] = DMAT2; - (*KeywordMap)["dmat3"] = DMAT3; - (*KeywordMap)["dmat4"] = DMAT4; - (*KeywordMap)["dmat2x2"] = DMAT2X2; - (*KeywordMap)["dmat2x3"] = DMAT2X3; - (*KeywordMap)["dmat2x4"] = DMAT2X4; - (*KeywordMap)["dmat3x2"] = DMAT3X2; - (*KeywordMap)["dmat3x3"] = DMAT3X3; - (*KeywordMap)["dmat3x4"] = DMAT3X4; - (*KeywordMap)["dmat4x2"] = DMAT4X2; - (*KeywordMap)["dmat4x3"] = DMAT4X3; - (*KeywordMap)["dmat4x4"] = DMAT4X4; - (*KeywordMap)["image1D"] = IMAGE1D; - (*KeywordMap)["iimage1D"] = IIMAGE1D; - (*KeywordMap)["uimage1D"] = UIMAGE1D; - (*KeywordMap)["image2D"] = IMAGE2D; - (*KeywordMap)["iimage2D"] = IIMAGE2D; - (*KeywordMap)["uimage2D"] = UIMAGE2D; - (*KeywordMap)["image3D"] = IMAGE3D; - (*KeywordMap)["iimage3D"] = IIMAGE3D; - (*KeywordMap)["uimage3D"] = UIMAGE3D; - (*KeywordMap)["image2DRect"] = IMAGE2DRECT; - (*KeywordMap)["iimage2DRect"] = IIMAGE2DRECT; - (*KeywordMap)["uimage2DRect"] = UIMAGE2DRECT; - (*KeywordMap)["imageCube"] = IMAGECUBE; - (*KeywordMap)["iimageCube"] = IIMAGECUBE; - (*KeywordMap)["uimageCube"] = UIMAGECUBE; - (*KeywordMap)["imageBuffer"] = IMAGEBUFFER; - (*KeywordMap)["iimageBuffer"] = IIMAGEBUFFER; - (*KeywordMap)["uimageBuffer"] = UIMAGEBUFFER; - (*KeywordMap)["image1DArray"] = IMAGE1DARRAY; - (*KeywordMap)["iimage1DArray"] = IIMAGE1DARRAY; - (*KeywordMap)["uimage1DArray"] = UIMAGE1DARRAY; - (*KeywordMap)["image2DArray"] = IMAGE2DARRAY; - (*KeywordMap)["iimage2DArray"] = IIMAGE2DARRAY; - (*KeywordMap)["uimage2DArray"] = UIMAGE2DARRAY; - (*KeywordMap)["imageCubeArray"] = IMAGECUBEARRAY; - (*KeywordMap)["iimageCubeArray"] = IIMAGECUBEARRAY; - (*KeywordMap)["uimageCubeArray"] = UIMAGECUBEARRAY; - (*KeywordMap)["image2DMS"] = IMAGE2DMS; - (*KeywordMap)["iimage2DMS"] = IIMAGE2DMS; - (*KeywordMap)["uimage2DMS"] = UIMAGE2DMS; - (*KeywordMap)["image2DMSArray"] = IMAGE2DMSARRAY; - (*KeywordMap)["iimage2DMSArray"] = IIMAGE2DMSARRAY; - (*KeywordMap)["uimage2DMSArray"] = UIMAGE2DMSARRAY; - (*KeywordMap)["double"] = DOUBLE; - (*KeywordMap)["dvec2"] = DVEC2; - (*KeywordMap)["dvec3"] = DVEC3; - (*KeywordMap)["dvec4"] = DVEC4; - (*KeywordMap)["uint"] = UINT; - (*KeywordMap)["uvec2"] = UVEC2; - (*KeywordMap)["uvec3"] = UVEC3; - (*KeywordMap)["uvec4"] = UVEC4; - - (*KeywordMap)["int64_t"] = INT64_T; - (*KeywordMap)["uint64_t"] = UINT64_T; - (*KeywordMap)["i64vec2"] = I64VEC2; - (*KeywordMap)["i64vec3"] = I64VEC3; - (*KeywordMap)["i64vec4"] = I64VEC4; - (*KeywordMap)["u64vec2"] = U64VEC2; - (*KeywordMap)["u64vec3"] = U64VEC3; - (*KeywordMap)["u64vec4"] = U64VEC4; - - // GL_KHX_shader_explicit_arithmetic_types - (*KeywordMap)["int8_t"] = INT8_T; - (*KeywordMap)["i8vec2"] = I8VEC2; - (*KeywordMap)["i8vec3"] = I8VEC3; - (*KeywordMap)["i8vec4"] = I8VEC4; - (*KeywordMap)["uint8_t"] = UINT8_T; - (*KeywordMap)["u8vec2"] = U8VEC2; - (*KeywordMap)["u8vec3"] = U8VEC3; - (*KeywordMap)["u8vec4"] = U8VEC4; - - (*KeywordMap)["int16_t"] = INT16_T; - (*KeywordMap)["i16vec2"] = I16VEC2; - (*KeywordMap)["i16vec3"] = I16VEC3; - (*KeywordMap)["i16vec4"] = I16VEC4; - (*KeywordMap)["uint16_t"] = UINT16_T; - (*KeywordMap)["u16vec2"] = U16VEC2; - (*KeywordMap)["u16vec3"] = U16VEC3; - (*KeywordMap)["u16vec4"] = U16VEC4; - - (*KeywordMap)["int32_t"] = INT32_T; - (*KeywordMap)["i32vec2"] = I32VEC2; - (*KeywordMap)["i32vec3"] = I32VEC3; - (*KeywordMap)["i32vec4"] = I32VEC4; - (*KeywordMap)["uint32_t"] = UINT32_T; - (*KeywordMap)["u32vec2"] = U32VEC2; - (*KeywordMap)["u32vec3"] = U32VEC3; - (*KeywordMap)["u32vec4"] = U32VEC4; - - (*KeywordMap)["float16_t"] = FLOAT16_T; - (*KeywordMap)["f16vec2"] = F16VEC2; - (*KeywordMap)["f16vec3"] = F16VEC3; - (*KeywordMap)["f16vec4"] = F16VEC4; - (*KeywordMap)["f16mat2"] = F16MAT2; - (*KeywordMap)["f16mat3"] = F16MAT3; - (*KeywordMap)["f16mat4"] = F16MAT4; - (*KeywordMap)["f16mat2x2"] = F16MAT2X2; - (*KeywordMap)["f16mat2x3"] = F16MAT2X3; - (*KeywordMap)["f16mat2x4"] = F16MAT2X4; - (*KeywordMap)["f16mat3x2"] = F16MAT3X2; - (*KeywordMap)["f16mat3x3"] = F16MAT3X3; - (*KeywordMap)["f16mat3x4"] = F16MAT3X4; - (*KeywordMap)["f16mat4x2"] = F16MAT4X2; - (*KeywordMap)["f16mat4x3"] = F16MAT4X3; - (*KeywordMap)["f16mat4x4"] = F16MAT4X4; - - (*KeywordMap)["float32_t"] = FLOAT32_T; - (*KeywordMap)["f32vec2"] = F32VEC2; - (*KeywordMap)["f32vec3"] = F32VEC3; - (*KeywordMap)["f32vec4"] = F32VEC4; - (*KeywordMap)["f32mat2"] = F32MAT2; - (*KeywordMap)["f32mat3"] = F32MAT3; - (*KeywordMap)["f32mat4"] = F32MAT4; - (*KeywordMap)["f32mat2x2"] = F32MAT2X2; - (*KeywordMap)["f32mat2x3"] = F32MAT2X3; - (*KeywordMap)["f32mat2x4"] = F32MAT2X4; - (*KeywordMap)["f32mat3x2"] = F32MAT3X2; - (*KeywordMap)["f32mat3x3"] = F32MAT3X3; - (*KeywordMap)["f32mat3x4"] = F32MAT3X4; - (*KeywordMap)["f32mat4x2"] = F32MAT4X2; - (*KeywordMap)["f32mat4x3"] = F32MAT4X3; - (*KeywordMap)["f32mat4x4"] = F32MAT4X4; - (*KeywordMap)["float64_t"] = FLOAT64_T; - (*KeywordMap)["f64vec2"] = F64VEC2; - (*KeywordMap)["f64vec3"] = F64VEC3; - (*KeywordMap)["f64vec4"] = F64VEC4; - (*KeywordMap)["f64mat2"] = F64MAT2; - (*KeywordMap)["f64mat3"] = F64MAT3; - (*KeywordMap)["f64mat4"] = F64MAT4; - (*KeywordMap)["f64mat2x2"] = F64MAT2X2; - (*KeywordMap)["f64mat2x3"] = F64MAT2X3; - (*KeywordMap)["f64mat2x4"] = F64MAT2X4; - (*KeywordMap)["f64mat3x2"] = F64MAT3X2; - (*KeywordMap)["f64mat3x3"] = F64MAT3X3; - (*KeywordMap)["f64mat3x4"] = F64MAT3X4; - (*KeywordMap)["f64mat4x2"] = F64MAT4X2; - (*KeywordMap)["f64mat4x3"] = F64MAT4X3; - (*KeywordMap)["f64mat4x4"] = F64MAT4X4; - - (*KeywordMap)["sampler2D"] = SAMPLER2D; - (*KeywordMap)["samplerCube"] = SAMPLERCUBE; - (*KeywordMap)["samplerCubeArray"] = SAMPLERCUBEARRAY; - (*KeywordMap)["samplerCubeArrayShadow"] = SAMPLERCUBEARRAYSHADOW; - (*KeywordMap)["isamplerCubeArray"] = ISAMPLERCUBEARRAY; - (*KeywordMap)["usamplerCubeArray"] = USAMPLERCUBEARRAY; - (*KeywordMap)["sampler1DArrayShadow"] = SAMPLER1DARRAYSHADOW; - (*KeywordMap)["isampler1DArray"] = ISAMPLER1DARRAY; - (*KeywordMap)["usampler1D"] = USAMPLER1D; - (*KeywordMap)["isampler1D"] = ISAMPLER1D; - (*KeywordMap)["usampler1DArray"] = USAMPLER1DARRAY; - (*KeywordMap)["samplerBuffer"] = SAMPLERBUFFER; - (*KeywordMap)["samplerCubeShadow"] = SAMPLERCUBESHADOW; - (*KeywordMap)["sampler2DArray"] = SAMPLER2DARRAY; - (*KeywordMap)["sampler2DArrayShadow"] = SAMPLER2DARRAYSHADOW; - (*KeywordMap)["isampler2D"] = ISAMPLER2D; - (*KeywordMap)["isampler3D"] = ISAMPLER3D; - (*KeywordMap)["isamplerCube"] = ISAMPLERCUBE; - (*KeywordMap)["isampler2DArray"] = ISAMPLER2DARRAY; - (*KeywordMap)["usampler2D"] = USAMPLER2D; - (*KeywordMap)["usampler3D"] = USAMPLER3D; - (*KeywordMap)["usamplerCube"] = USAMPLERCUBE; - (*KeywordMap)["usampler2DArray"] = USAMPLER2DARRAY; - (*KeywordMap)["isampler2DRect"] = ISAMPLER2DRECT; - (*KeywordMap)["usampler2DRect"] = USAMPLER2DRECT; - (*KeywordMap)["isamplerBuffer"] = ISAMPLERBUFFER; - (*KeywordMap)["usamplerBuffer"] = USAMPLERBUFFER; - (*KeywordMap)["sampler2DMS"] = SAMPLER2DMS; - (*KeywordMap)["isampler2DMS"] = ISAMPLER2DMS; - (*KeywordMap)["usampler2DMS"] = USAMPLER2DMS; - (*KeywordMap)["sampler2DMSArray"] = SAMPLER2DMSARRAY; - (*KeywordMap)["isampler2DMSArray"] = ISAMPLER2DMSARRAY; - (*KeywordMap)["usampler2DMSArray"] = USAMPLER2DMSARRAY; - (*KeywordMap)["sampler1D"] = SAMPLER1D; - (*KeywordMap)["sampler1DShadow"] = SAMPLER1DSHADOW; - (*KeywordMap)["sampler3D"] = SAMPLER3D; - (*KeywordMap)["sampler2DShadow"] = SAMPLER2DSHADOW; - (*KeywordMap)["sampler2DRect"] = SAMPLER2DRECT; - (*KeywordMap)["sampler2DRectShadow"] = SAMPLER2DRECTSHADOW; - (*KeywordMap)["sampler1DArray"] = SAMPLER1DARRAY; - - (*KeywordMap)["samplerExternalOES"] = SAMPLEREXTERNALOES; // GL_OES_EGL_image_external - - (*KeywordMap)["sampler"] = SAMPLER; - (*KeywordMap)["samplerShadow"] = SAMPLERSHADOW; - - (*KeywordMap)["texture2D"] = TEXTURE2D; - (*KeywordMap)["textureCube"] = TEXTURECUBE; - (*KeywordMap)["textureCubeArray"] = TEXTURECUBEARRAY; - (*KeywordMap)["itextureCubeArray"] = ITEXTURECUBEARRAY; - (*KeywordMap)["utextureCubeArray"] = UTEXTURECUBEARRAY; - (*KeywordMap)["itexture1DArray"] = ITEXTURE1DARRAY; - (*KeywordMap)["utexture1D"] = UTEXTURE1D; - (*KeywordMap)["itexture1D"] = ITEXTURE1D; - (*KeywordMap)["utexture1DArray"] = UTEXTURE1DARRAY; - (*KeywordMap)["textureBuffer"] = TEXTUREBUFFER; - (*KeywordMap)["texture2DArray"] = TEXTURE2DARRAY; - (*KeywordMap)["itexture2D"] = ITEXTURE2D; - (*KeywordMap)["itexture3D"] = ITEXTURE3D; - (*KeywordMap)["itextureCube"] = ITEXTURECUBE; - (*KeywordMap)["itexture2DArray"] = ITEXTURE2DARRAY; - (*KeywordMap)["utexture2D"] = UTEXTURE2D; - (*KeywordMap)["utexture3D"] = UTEXTURE3D; - (*KeywordMap)["utextureCube"] = UTEXTURECUBE; - (*KeywordMap)["utexture2DArray"] = UTEXTURE2DARRAY; - (*KeywordMap)["itexture2DRect"] = ITEXTURE2DRECT; - (*KeywordMap)["utexture2DRect"] = UTEXTURE2DRECT; - (*KeywordMap)["itextureBuffer"] = ITEXTUREBUFFER; - (*KeywordMap)["utextureBuffer"] = UTEXTUREBUFFER; - (*KeywordMap)["texture2DMS"] = TEXTURE2DMS; - (*KeywordMap)["itexture2DMS"] = ITEXTURE2DMS; - (*KeywordMap)["utexture2DMS"] = UTEXTURE2DMS; - (*KeywordMap)["texture2DMSArray"] = TEXTURE2DMSARRAY; - (*KeywordMap)["itexture2DMSArray"] = ITEXTURE2DMSARRAY; - (*KeywordMap)["utexture2DMSArray"] = UTEXTURE2DMSARRAY; - (*KeywordMap)["texture1D"] = TEXTURE1D; - (*KeywordMap)["texture3D"] = TEXTURE3D; - (*KeywordMap)["texture2DRect"] = TEXTURE2DRECT; - (*KeywordMap)["texture1DArray"] = TEXTURE1DARRAY; - - (*KeywordMap)["subpassInput"] = SUBPASSINPUT; - (*KeywordMap)["subpassInputMS"] = SUBPASSINPUTMS; - (*KeywordMap)["isubpassInput"] = ISUBPASSINPUT; - (*KeywordMap)["isubpassInputMS"] = ISUBPASSINPUTMS; - (*KeywordMap)["usubpassInput"] = USUBPASSINPUT; - (*KeywordMap)["usubpassInputMS"] = USUBPASSINPUTMS; - -#ifdef AMD_EXTENSIONS - (*KeywordMap)["f16sampler1D"] = F16SAMPLER1D; - (*KeywordMap)["f16sampler2D"] = F16SAMPLER2D; - (*KeywordMap)["f16sampler3D"] = F16SAMPLER3D; - (*KeywordMap)["f16sampler2DRect"] = F16SAMPLER2DRECT; - (*KeywordMap)["f16samplerCube"] = F16SAMPLERCUBE; - (*KeywordMap)["f16sampler1DArray"] = F16SAMPLER1DARRAY; - (*KeywordMap)["f16sampler2DArray"] = F16SAMPLER2DARRAY; - (*KeywordMap)["f16samplerCubeArray"] = F16SAMPLERCUBEARRAY; - (*KeywordMap)["f16samplerBuffer"] = F16SAMPLERBUFFER; - (*KeywordMap)["f16sampler2DMS"] = F16SAMPLER2DMS; - (*KeywordMap)["f16sampler2DMSArray"] = F16SAMPLER2DMSARRAY; - (*KeywordMap)["f16sampler1DShadow"] = F16SAMPLER1DSHADOW; - (*KeywordMap)["f16sampler2DShadow"] = F16SAMPLER2DSHADOW; - (*KeywordMap)["f16sampler2DRectShadow"] = F16SAMPLER2DRECTSHADOW; - (*KeywordMap)["f16samplerCubeShadow"] = F16SAMPLERCUBESHADOW; - (*KeywordMap)["f16sampler1DArrayShadow"] = F16SAMPLER1DARRAYSHADOW; - (*KeywordMap)["f16sampler2DArrayShadow"] = F16SAMPLER2DARRAYSHADOW; - (*KeywordMap)["f16samplerCubeArrayShadow"] = F16SAMPLERCUBEARRAYSHADOW; - - (*KeywordMap)["f16image1D"] = F16IMAGE1D; - (*KeywordMap)["f16image2D"] = F16IMAGE2D; - (*KeywordMap)["f16image3D"] = F16IMAGE3D; - (*KeywordMap)["f16image2DRect"] = F16IMAGE2DRECT; - (*KeywordMap)["f16imageCube"] = F16IMAGECUBE; - (*KeywordMap)["f16image1DArray"] = F16IMAGE1DARRAY; - (*KeywordMap)["f16image2DArray"] = F16IMAGE2DARRAY; - (*KeywordMap)["f16imageCubeArray"] = F16IMAGECUBEARRAY; - (*KeywordMap)["f16imageBuffer"] = F16IMAGEBUFFER; - (*KeywordMap)["f16image2DMS"] = F16IMAGE2DMS; - (*KeywordMap)["f16image2DMSArray"] = F16IMAGE2DMSARRAY; - - (*KeywordMap)["f16texture1D"] = F16TEXTURE1D; - (*KeywordMap)["f16texture2D"] = F16TEXTURE2D; - (*KeywordMap)["f16texture3D"] = F16TEXTURE3D; - (*KeywordMap)["f16texture2DRect"] = F16TEXTURE2DRECT; - (*KeywordMap)["f16textureCube"] = F16TEXTURECUBE; - (*KeywordMap)["f16texture1DArray"] = F16TEXTURE1DARRAY; - (*KeywordMap)["f16texture2DArray"] = F16TEXTURE2DARRAY; - (*KeywordMap)["f16textureCubeArray"] = F16TEXTURECUBEARRAY; - (*KeywordMap)["f16textureBuffer"] = F16TEXTUREBUFFER; - (*KeywordMap)["f16texture2DMS"] = F16TEXTURE2DMS; - (*KeywordMap)["f16texture2DMSArray"] = F16TEXTURE2DMSARRAY; - - (*KeywordMap)["f16subpassInput"] = F16SUBPASSINPUT; - (*KeywordMap)["f16subpassInputMS"] = F16SUBPASSINPUTMS; -#endif - - (*KeywordMap)["noperspective"] = NOPERSPECTIVE; - (*KeywordMap)["smooth"] = SMOOTH; - (*KeywordMap)["flat"] = FLAT; -#ifdef AMD_EXTENSIONS - (*KeywordMap)["__explicitInterpAMD"] = __EXPLICITINTERPAMD; -#endif - (*KeywordMap)["centroid"] = CENTROID; - (*KeywordMap)["precise"] = PRECISE; - (*KeywordMap)["invariant"] = INVARIANT; - (*KeywordMap)["packed"] = PACKED; - (*KeywordMap)["resource"] = RESOURCE; - (*KeywordMap)["superp"] = SUPERP; - - ReservedSet = new std::unordered_set; - - ReservedSet->insert("common"); - ReservedSet->insert("partition"); - ReservedSet->insert("active"); - ReservedSet->insert("asm"); - ReservedSet->insert("class"); - ReservedSet->insert("union"); - ReservedSet->insert("enum"); - ReservedSet->insert("typedef"); - ReservedSet->insert("template"); - ReservedSet->insert("this"); - ReservedSet->insert("goto"); - ReservedSet->insert("inline"); - ReservedSet->insert("noinline"); - ReservedSet->insert("public"); - ReservedSet->insert("static"); - ReservedSet->insert("extern"); - ReservedSet->insert("external"); - ReservedSet->insert("interface"); - ReservedSet->insert("long"); - ReservedSet->insert("short"); - ReservedSet->insert("half"); - ReservedSet->insert("fixed"); - ReservedSet->insert("unsigned"); - ReservedSet->insert("input"); - ReservedSet->insert("output"); - ReservedSet->insert("hvec2"); - ReservedSet->insert("hvec3"); - ReservedSet->insert("hvec4"); - ReservedSet->insert("fvec2"); - ReservedSet->insert("fvec3"); - ReservedSet->insert("fvec4"); - ReservedSet->insert("sampler3DRect"); - ReservedSet->insert("filter"); - ReservedSet->insert("sizeof"); - ReservedSet->insert("cast"); - ReservedSet->insert("namespace"); - ReservedSet->insert("using"); -} - -void TScanContext::deleteKeywordMap() -{ - delete KeywordMap; - KeywordMap = nullptr; - delete ReservedSet; - ReservedSet = nullptr; -} - -// Called by yylex to get the next token. -// Returning 0 implies end of input. -int TScanContext::tokenize(TPpContext* pp, TParserToken& token) -{ - do { - parserToken = &token; - TPpToken ppToken; - int token = pp->tokenize(ppToken); - if (token == EndOfInput) - return 0; - - tokenText = ppToken.name; - loc = ppToken.loc; - parserToken->sType.lex.loc = loc; - switch (token) { - case ';': afterType = false; return SEMICOLON; - case ',': afterType = false; return COMMA; - case ':': return COLON; - case '=': afterType = false; return EQUAL; - case '(': afterType = false; return LEFT_PAREN; - case ')': afterType = false; return RIGHT_PAREN; - case '.': field = true; return DOT; - case '!': return BANG; - case '-': return DASH; - case '~': return TILDE; - case '+': return PLUS; - case '*': return STAR; - case '/': return SLASH; - case '%': return PERCENT; - case '<': return LEFT_ANGLE; - case '>': return RIGHT_ANGLE; - case '|': return VERTICAL_BAR; - case '^': return CARET; - case '&': return AMPERSAND; - case '?': return QUESTION; - case '[': return LEFT_BRACKET; - case ']': return RIGHT_BRACKET; - case '{': return LEFT_BRACE; - case '}': return RIGHT_BRACE; - case '\\': - parseContext.error(loc, "illegal use of escape character", "\\", ""); - break; - - case PPAtomAddAssign: return ADD_ASSIGN; - case PPAtomSubAssign: return SUB_ASSIGN; - case PPAtomMulAssign: return MUL_ASSIGN; - case PPAtomDivAssign: return DIV_ASSIGN; - case PPAtomModAssign: return MOD_ASSIGN; - - case PpAtomRight: return RIGHT_OP; - case PpAtomLeft: return LEFT_OP; - - case PpAtomRightAssign: return RIGHT_ASSIGN; - case PpAtomLeftAssign: return LEFT_ASSIGN; - case PpAtomAndAssign: return AND_ASSIGN; - case PpAtomOrAssign: return OR_ASSIGN; - case PpAtomXorAssign: return XOR_ASSIGN; - - case PpAtomAnd: return AND_OP; - case PpAtomOr: return OR_OP; - case PpAtomXor: return XOR_OP; - - case PpAtomEQ: return EQ_OP; - case PpAtomGE: return GE_OP; - case PpAtomNE: return NE_OP; - case PpAtomLE: return LE_OP; - - case PpAtomDecrement: return DEC_OP; - case PpAtomIncrement: return INC_OP; - - case PpAtomColonColon: - parseContext.error(loc, "not supported", "::", ""); - break; - - case PpAtomConstInt: parserToken->sType.lex.i = ppToken.ival; return INTCONSTANT; - case PpAtomConstUint: parserToken->sType.lex.i = ppToken.ival; return UINTCONSTANT; - case PpAtomConstInt16: parserToken->sType.lex.i = ppToken.ival; return INT16CONSTANT; - case PpAtomConstUint16: parserToken->sType.lex.i = ppToken.ival; return UINT16CONSTANT; - case PpAtomConstInt64: parserToken->sType.lex.i64 = ppToken.i64val; return INT64CONSTANT; - case PpAtomConstUint64: parserToken->sType.lex.i64 = ppToken.i64val; return UINT64CONSTANT; - case PpAtomConstFloat: parserToken->sType.lex.d = ppToken.dval; return FLOATCONSTANT; - case PpAtomConstDouble: parserToken->sType.lex.d = ppToken.dval; return DOUBLECONSTANT; - case PpAtomConstFloat16: parserToken->sType.lex.d = ppToken.dval; return FLOAT16CONSTANT; - case PpAtomIdentifier: - { - int token = tokenizeIdentifier(); - field = false; - return token; - } - - case EndOfInput: return 0; - - default: - char buf[2]; - buf[0] = (char)token; - buf[1] = 0; - parseContext.error(loc, "unexpected token", buf, ""); - break; - } - } while (true); -} - -int TScanContext::tokenizeIdentifier() -{ - if (ReservedSet->find(tokenText) != ReservedSet->end()) - return reservedWord(); - - auto it = KeywordMap->find(tokenText); - if (it == KeywordMap->end()) { - // Should have an identifier of some sort - return identifierOrType(); - } - keyword = it->second; - - switch (keyword) { - case CONST: - case UNIFORM: - case IN: - case OUT: - case INOUT: - case STRUCT: - case BREAK: - case CONTINUE: - case DO: - case FOR: - case WHILE: - case IF: - case ELSE: - case DISCARD: - case RETURN: - case CASE: - return keyword; - - case NONUNIFORM: - if (parseContext.extensionTurnedOn(E_GL_EXT_nonuniform_qualifier)) - return keyword; - else - return identifierOrType(); - - case SWITCH: - case DEFAULT: - if ((parseContext.profile == EEsProfile && parseContext.version < 300) || - (parseContext.profile != EEsProfile && parseContext.version < 130)) - reservedWord(); - return keyword; - - case VOID: - case BOOL: - case FLOAT: - case INT: - case BVEC2: - case BVEC3: - case BVEC4: - case VEC2: - case VEC3: - case VEC4: - case IVEC2: - case IVEC3: - case IVEC4: - case MAT2: - case MAT3: - case MAT4: - case SAMPLER2D: - case SAMPLERCUBE: - afterType = true; - return keyword; - - case BOOLCONSTANT: - if (strcmp("true", tokenText) == 0) - parserToken->sType.lex.b = true; - else - parserToken->sType.lex.b = false; - return keyword; - - case ATTRIBUTE: - case VARYING: - if (parseContext.profile == EEsProfile && parseContext.version >= 300) - reservedWord(); - return keyword; - - case BUFFER: - if ((parseContext.profile == EEsProfile && parseContext.version < 310) || - (parseContext.profile != EEsProfile && parseContext.version < 430)) - return identifierOrType(); - return keyword; - - case ATOMIC_UINT: - if ((parseContext.profile == EEsProfile && parseContext.version >= 310) || - parseContext.extensionTurnedOn(E_GL_ARB_shader_atomic_counters)) - return keyword; - return es30ReservedFromGLSL(420); - - case COHERENT: - case RESTRICT: - case READONLY: - case WRITEONLY: - if (parseContext.profile == EEsProfile && parseContext.version >= 310) - return keyword; - return es30ReservedFromGLSL(parseContext.extensionTurnedOn(E_GL_ARB_shader_image_load_store) ? 130 : 420); - - case VOLATILE: - if (parseContext.profile == EEsProfile && parseContext.version >= 310) - return keyword; - if (! parseContext.symbolTable.atBuiltInLevel() && (parseContext.profile == EEsProfile || - (parseContext.version < 420 && ! parseContext.extensionTurnedOn(E_GL_ARB_shader_image_load_store)))) - reservedWord(); - return keyword; - - case LAYOUT: - { - const int numLayoutExts = 2; - const char* layoutExts[numLayoutExts] = { E_GL_ARB_shading_language_420pack, - E_GL_ARB_explicit_attrib_location }; - if ((parseContext.profile == EEsProfile && parseContext.version < 300) || - (parseContext.profile != EEsProfile && parseContext.version < 140 && - ! parseContext.extensionsTurnedOn(numLayoutExts, layoutExts))) - return identifierOrType(); - return keyword; - } - case SHARED: - if ((parseContext.profile == EEsProfile && parseContext.version < 300) || - (parseContext.profile != EEsProfile && parseContext.version < 140)) - return identifierOrType(); - return keyword; - - case PATCH: - if (parseContext.symbolTable.atBuiltInLevel() || - (parseContext.profile == EEsProfile && - (parseContext.version >= 320 || - parseContext.extensionsTurnedOn(Num_AEP_tessellation_shader, AEP_tessellation_shader))) || - (parseContext.profile != EEsProfile && parseContext.extensionTurnedOn(E_GL_ARB_tessellation_shader))) - return keyword; - - return es30ReservedFromGLSL(400); - - case SAMPLE: - if ((parseContext.profile == EEsProfile && parseContext.version >= 320) || - parseContext.extensionsTurnedOn(1, &E_GL_OES_shader_multisample_interpolation)) - return keyword; - return es30ReservedFromGLSL(400); - - case SUBROUTINE: - return es30ReservedFromGLSL(400); - - case HIGH_PRECISION: - case MEDIUM_PRECISION: - case LOW_PRECISION: - case PRECISION: - return precisionKeyword(); - - case MAT2X2: - case MAT2X3: - case MAT2X4: - case MAT3X2: - case MAT3X3: - case MAT3X4: - case MAT4X2: - case MAT4X3: - case MAT4X4: - return matNxM(); - - case DMAT2: - case DMAT3: - case DMAT4: - case DMAT2X2: - case DMAT2X3: - case DMAT2X4: - case DMAT3X2: - case DMAT3X3: - case DMAT3X4: - case DMAT4X2: - case DMAT4X3: - case DMAT4X4: - return dMat(); - - case IMAGE1D: - case IIMAGE1D: - case UIMAGE1D: - case IMAGE1DARRAY: - case IIMAGE1DARRAY: - case UIMAGE1DARRAY: - case IMAGE2DRECT: - case IIMAGE2DRECT: - case UIMAGE2DRECT: - afterType = true; - return firstGenerationImage(false); - - case IMAGEBUFFER: - case IIMAGEBUFFER: - case UIMAGEBUFFER: - afterType = true; - if ((parseContext.profile == EEsProfile && parseContext.version >= 320) || - parseContext.extensionsTurnedOn(Num_AEP_texture_buffer, AEP_texture_buffer)) - return keyword; - return firstGenerationImage(false); - - case IMAGE2D: - case IIMAGE2D: - case UIMAGE2D: - case IMAGE3D: - case IIMAGE3D: - case UIMAGE3D: - case IMAGECUBE: - case IIMAGECUBE: - case UIMAGECUBE: - case IMAGE2DARRAY: - case IIMAGE2DARRAY: - case UIMAGE2DARRAY: - afterType = true; - return firstGenerationImage(true); - - case IMAGECUBEARRAY: - case IIMAGECUBEARRAY: - case UIMAGECUBEARRAY: - afterType = true; - if ((parseContext.profile == EEsProfile && parseContext.version >= 320) || - parseContext.extensionsTurnedOn(Num_AEP_texture_cube_map_array, AEP_texture_cube_map_array)) - return keyword; - return secondGenerationImage(); - - case IMAGE2DMS: - case IIMAGE2DMS: - case UIMAGE2DMS: - case IMAGE2DMSARRAY: - case IIMAGE2DMSARRAY: - case UIMAGE2DMSARRAY: - afterType = true; - return secondGenerationImage(); - - case DOUBLE: - case DVEC2: - case DVEC3: - case DVEC4: - afterType = true; - if (parseContext.profile == EEsProfile || parseContext.version < 400) - reservedWord(); - return keyword; - - case INT64_T: - case UINT64_T: - case I64VEC2: - case I64VEC3: - case I64VEC4: - case U64VEC2: - case U64VEC3: - case U64VEC4: - afterType = true; - if (parseContext.symbolTable.atBuiltInLevel() || - (parseContext.profile != EEsProfile && parseContext.version >= 450 && - (parseContext.extensionTurnedOn(E_GL_ARB_gpu_shader_int64) || - parseContext.extensionTurnedOn(E_GL_KHX_shader_explicit_arithmetic_types) || - parseContext.extensionTurnedOn(E_GL_KHX_shader_explicit_arithmetic_types_int64)))) - return keyword; - return identifierOrType(); - - case INT8_T: - case UINT8_T: - case I8VEC2: - case I8VEC3: - case I8VEC4: - case U8VEC2: - case U8VEC3: - case U8VEC4: - afterType = true; - if (parseContext.symbolTable.atBuiltInLevel() || - ((parseContext.extensionTurnedOn(E_GL_KHX_shader_explicit_arithmetic_types) || - parseContext.extensionTurnedOn(E_GL_KHX_shader_explicit_arithmetic_types_int8)) && - parseContext.profile != EEsProfile && parseContext.version >= 450)) - return keyword; - return identifierOrType(); - - case INT16_T: - case UINT16_T: - case I16VEC2: - case I16VEC3: - case I16VEC4: - case U16VEC2: - case U16VEC3: - case U16VEC4: - afterType = true; - if (parseContext.symbolTable.atBuiltInLevel() || - (parseContext.profile != EEsProfile && parseContext.version >= 450 && - ( -#ifdef AMD_EXTENSIONS - parseContext.extensionTurnedOn(E_GL_AMD_gpu_shader_int16) || -#endif - parseContext.extensionTurnedOn(E_GL_KHX_shader_explicit_arithmetic_types) || - parseContext.extensionTurnedOn(E_GL_KHX_shader_explicit_arithmetic_types_int16)))) - return keyword; - return identifierOrType(); - case INT32_T: - case UINT32_T: - case I32VEC2: - case I32VEC3: - case I32VEC4: - case U32VEC2: - case U32VEC3: - case U32VEC4: - afterType = true; - if (parseContext.symbolTable.atBuiltInLevel() || - ((parseContext.extensionTurnedOn(E_GL_KHX_shader_explicit_arithmetic_types) || - parseContext.extensionTurnedOn(E_GL_KHX_shader_explicit_arithmetic_types_int32)) && - parseContext.profile != EEsProfile && parseContext.version >= 450)) - return keyword; - return identifierOrType(); - case FLOAT32_T: - case F32VEC2: - case F32VEC3: - case F32VEC4: - case F32MAT2: - case F32MAT3: - case F32MAT4: - case F32MAT2X2: - case F32MAT2X3: - case F32MAT2X4: - case F32MAT3X2: - case F32MAT3X3: - case F32MAT3X4: - case F32MAT4X2: - case F32MAT4X3: - case F32MAT4X4: - afterType = true; - if (parseContext.symbolTable.atBuiltInLevel() || - ((parseContext.extensionTurnedOn(E_GL_KHX_shader_explicit_arithmetic_types) || - parseContext.extensionTurnedOn(E_GL_KHX_shader_explicit_arithmetic_types_float32)) && - parseContext.profile != EEsProfile && parseContext.version >= 450)) - return keyword; - return identifierOrType(); - - case FLOAT64_T: - case F64VEC2: - case F64VEC3: - case F64VEC4: - case F64MAT2: - case F64MAT3: - case F64MAT4: - case F64MAT2X2: - case F64MAT2X3: - case F64MAT2X4: - case F64MAT3X2: - case F64MAT3X3: - case F64MAT3X4: - case F64MAT4X2: - case F64MAT4X3: - case F64MAT4X4: - afterType = true; - if (parseContext.symbolTable.atBuiltInLevel() || - ((parseContext.extensionTurnedOn(E_GL_KHX_shader_explicit_arithmetic_types) || - parseContext.extensionTurnedOn(E_GL_KHX_shader_explicit_arithmetic_types_float64)) && - parseContext.profile != EEsProfile && parseContext.version >= 450)) - return keyword; - return identifierOrType(); - - case FLOAT16_T: - case F16VEC2: - case F16VEC3: - case F16VEC4: - case F16MAT2: - case F16MAT3: - case F16MAT4: - case F16MAT2X2: - case F16MAT2X3: - case F16MAT2X4: - case F16MAT3X2: - case F16MAT3X3: - case F16MAT3X4: - case F16MAT4X2: - case F16MAT4X3: - case F16MAT4X4: - afterType = true; - if (parseContext.symbolTable.atBuiltInLevel() || - (parseContext.profile != EEsProfile && parseContext.version >= 450 && - ( -#ifdef AMD_EXTENSIONS - parseContext.extensionTurnedOn(E_GL_AMD_gpu_shader_half_float) || -#endif - parseContext.extensionTurnedOn(E_GL_KHX_shader_explicit_arithmetic_types) || - parseContext.extensionTurnedOn(E_GL_KHX_shader_explicit_arithmetic_types_float16)))) - return keyword; - - return identifierOrType(); - - case SAMPLERCUBEARRAY: - case SAMPLERCUBEARRAYSHADOW: - case ISAMPLERCUBEARRAY: - case USAMPLERCUBEARRAY: - afterType = true; - if ((parseContext.profile == EEsProfile && parseContext.version >= 320) || - parseContext.extensionsTurnedOn(Num_AEP_texture_cube_map_array, AEP_texture_cube_map_array)) - return keyword; - if (parseContext.profile == EEsProfile || (parseContext.version < 400 && ! parseContext.extensionTurnedOn(E_GL_ARB_texture_cube_map_array))) - reservedWord(); - return keyword; - - case ISAMPLER1D: - case ISAMPLER1DARRAY: - case SAMPLER1DARRAYSHADOW: - case USAMPLER1D: - case USAMPLER1DARRAY: - afterType = true; - return es30ReservedFromGLSL(130); - - case UINT: - case UVEC2: - case UVEC3: - case UVEC4: - case SAMPLERCUBESHADOW: - case SAMPLER2DARRAY: - case SAMPLER2DARRAYSHADOW: - case ISAMPLER2D: - case ISAMPLER3D: - case ISAMPLERCUBE: - case ISAMPLER2DARRAY: - case USAMPLER2D: - case USAMPLER3D: - case USAMPLERCUBE: - case USAMPLER2DARRAY: - afterType = true; - return nonreservedKeyword(300, 130); - - case ISAMPLER2DRECT: - case USAMPLER2DRECT: - afterType = true; - return es30ReservedFromGLSL(140); - - case SAMPLERBUFFER: - afterType = true; - if ((parseContext.profile == EEsProfile && parseContext.version >= 320) || - parseContext.extensionsTurnedOn(Num_AEP_texture_buffer, AEP_texture_buffer)) - return keyword; - return es30ReservedFromGLSL(130); - - case ISAMPLERBUFFER: - case USAMPLERBUFFER: - afterType = true; - if ((parseContext.profile == EEsProfile && parseContext.version >= 320) || - parseContext.extensionsTurnedOn(Num_AEP_texture_buffer, AEP_texture_buffer)) - return keyword; - return es30ReservedFromGLSL(140); - - case SAMPLER2DMS: - case ISAMPLER2DMS: - case USAMPLER2DMS: - afterType = true; - if (parseContext.profile == EEsProfile && parseContext.version >= 310) - return keyword; - return es30ReservedFromGLSL(150); - - case SAMPLER2DMSARRAY: - case ISAMPLER2DMSARRAY: - case USAMPLER2DMSARRAY: - afterType = true; - if ((parseContext.profile == EEsProfile && parseContext.version >= 320) || - parseContext.extensionsTurnedOn(1, &E_GL_OES_texture_storage_multisample_2d_array)) - return keyword; - return es30ReservedFromGLSL(150); - - case SAMPLER1D: - case SAMPLER1DSHADOW: - afterType = true; - if (parseContext.profile == EEsProfile) - reservedWord(); - return keyword; - - case SAMPLER3D: - afterType = true; - if (parseContext.profile == EEsProfile && parseContext.version < 300) { - if (!parseContext.extensionTurnedOn(E_GL_OES_texture_3D)) - reservedWord(); - } - return keyword; - - case SAMPLER2DSHADOW: - afterType = true; - if (parseContext.profile == EEsProfile && parseContext.version < 300) { - if (!parseContext.extensionTurnedOn(E_GL_EXT_shadow_samplers)) - reservedWord(); - } - return keyword; - - case SAMPLER2DRECT: - case SAMPLER2DRECTSHADOW: - afterType = true; - if (parseContext.profile == EEsProfile) - reservedWord(); - else if (parseContext.version < 140 && ! parseContext.symbolTable.atBuiltInLevel() && ! parseContext.extensionTurnedOn(E_GL_ARB_texture_rectangle)) { - if (parseContext.relaxedErrors()) - parseContext.requireExtensions(loc, 1, &E_GL_ARB_texture_rectangle, "texture-rectangle sampler keyword"); - else - reservedWord(); - } - return keyword; - - case SAMPLER1DARRAY: - afterType = true; - if (parseContext.profile == EEsProfile && parseContext.version == 300) - reservedWord(); - else if ((parseContext.profile == EEsProfile && parseContext.version < 300) || - (parseContext.profile != EEsProfile && parseContext.version < 130)) - return identifierOrType(); - return keyword; - - case SAMPLEREXTERNALOES: - afterType = true; - if (parseContext.symbolTable.atBuiltInLevel() || - parseContext.extensionTurnedOn(E_GL_OES_EGL_image_external) || - parseContext.extensionTurnedOn(E_GL_OES_EGL_image_external_essl3)) - return keyword; - return identifierOrType(); - - case TEXTURE2D: - case TEXTURECUBE: - case TEXTURECUBEARRAY: - case ITEXTURECUBEARRAY: - case UTEXTURECUBEARRAY: - case ITEXTURE1DARRAY: - case UTEXTURE1D: - case ITEXTURE1D: - case UTEXTURE1DARRAY: - case TEXTUREBUFFER: - case TEXTURE2DARRAY: - case ITEXTURE2D: - case ITEXTURE3D: - case ITEXTURECUBE: - case ITEXTURE2DARRAY: - case UTEXTURE2D: - case UTEXTURE3D: - case UTEXTURECUBE: - case UTEXTURE2DARRAY: - case ITEXTURE2DRECT: - case UTEXTURE2DRECT: - case ITEXTUREBUFFER: - case UTEXTUREBUFFER: - case TEXTURE2DMS: - case ITEXTURE2DMS: - case UTEXTURE2DMS: - case TEXTURE2DMSARRAY: - case ITEXTURE2DMSARRAY: - case UTEXTURE2DMSARRAY: - case TEXTURE1D: - case TEXTURE3D: - case TEXTURE2DRECT: - case TEXTURE1DARRAY: - case SAMPLER: - case SAMPLERSHADOW: - if (parseContext.spvVersion.vulkan > 0) - return keyword; - else - return identifierOrType(); - - case SUBPASSINPUT: - case SUBPASSINPUTMS: - case ISUBPASSINPUT: - case ISUBPASSINPUTMS: - case USUBPASSINPUT: - case USUBPASSINPUTMS: - if (parseContext.spvVersion.vulkan > 0) - return keyword; - else - return identifierOrType(); - -#ifdef AMD_EXTENSIONS - case F16SAMPLER1D: - case F16SAMPLER2D: - case F16SAMPLER3D: - case F16SAMPLER2DRECT: - case F16SAMPLERCUBE: - case F16SAMPLER1DARRAY: - case F16SAMPLER2DARRAY: - case F16SAMPLERCUBEARRAY: - case F16SAMPLERBUFFER: - case F16SAMPLER2DMS: - case F16SAMPLER2DMSARRAY: - case F16SAMPLER1DSHADOW: - case F16SAMPLER2DSHADOW: - case F16SAMPLER1DARRAYSHADOW: - case F16SAMPLER2DARRAYSHADOW: - case F16SAMPLER2DRECTSHADOW: - case F16SAMPLERCUBESHADOW: - case F16SAMPLERCUBEARRAYSHADOW: - - case F16IMAGE1D: - case F16IMAGE2D: - case F16IMAGE3D: - case F16IMAGE2DRECT: - case F16IMAGECUBE: - case F16IMAGE1DARRAY: - case F16IMAGE2DARRAY: - case F16IMAGECUBEARRAY: - case F16IMAGEBUFFER: - case F16IMAGE2DMS: - case F16IMAGE2DMSARRAY: - - case F16TEXTURE1D: - case F16TEXTURE2D: - case F16TEXTURE3D: - case F16TEXTURE2DRECT: - case F16TEXTURECUBE: - case F16TEXTURE1DARRAY: - case F16TEXTURE2DARRAY: - case F16TEXTURECUBEARRAY: - case F16TEXTUREBUFFER: - case F16TEXTURE2DMS: - case F16TEXTURE2DMSARRAY: - - case F16SUBPASSINPUT: - case F16SUBPASSINPUTMS: - afterType = true; - if (parseContext.symbolTable.atBuiltInLevel() || - (parseContext.extensionTurnedOn(E_GL_AMD_gpu_shader_half_float_fetch) && - parseContext.profile != EEsProfile && parseContext.version >= 450)) - return keyword; - return identifierOrType(); -#endif - - case NOPERSPECTIVE: -#ifdef NV_EXTENSIONS - if (parseContext.profile == EEsProfile && parseContext.version >= 300 && - parseContext.extensionTurnedOn(E_GL_NV_shader_noperspective_interpolation)) - return keyword; -#endif - return es30ReservedFromGLSL(130); - - case SMOOTH: - if ((parseContext.profile == EEsProfile && parseContext.version < 300) || - (parseContext.profile != EEsProfile && parseContext.version < 130)) - return identifierOrType(); - return keyword; - -#ifdef AMD_EXTENSIONS - case __EXPLICITINTERPAMD: - if (parseContext.profile != EEsProfile && parseContext.version >= 450 && - parseContext.extensionTurnedOn(E_GL_AMD_shader_explicit_vertex_parameter)) - return keyword; - return identifierOrType(); -#endif - - case FLAT: - if (parseContext.profile == EEsProfile && parseContext.version < 300) - reservedWord(); - else if (parseContext.profile != EEsProfile && parseContext.version < 130) - return identifierOrType(); - return keyword; - - case CENTROID: - if (parseContext.version < 120) - return identifierOrType(); - return keyword; - - case PRECISE: - if ((parseContext.profile == EEsProfile && - (parseContext.version >= 320 || parseContext.extensionsTurnedOn(Num_AEP_gpu_shader5, AEP_gpu_shader5))) || - (parseContext.profile != EEsProfile && parseContext.version >= 400)) - return keyword; - if (parseContext.profile == EEsProfile && parseContext.version == 310) { - reservedWord(); - return keyword; - } - return identifierOrType(); - - case INVARIANT: - if (parseContext.profile != EEsProfile && parseContext.version < 120) - return identifierOrType(); - return keyword; - - case PACKED: - if ((parseContext.profile == EEsProfile && parseContext.version < 300) || - (parseContext.profile != EEsProfile && parseContext.version < 330)) - return reservedWord(); - return identifierOrType(); - - case RESOURCE: - { - bool reserved = (parseContext.profile == EEsProfile && parseContext.version >= 300) || - (parseContext.profile != EEsProfile && parseContext.version >= 420); - return identifierOrReserved(reserved); - } - case SUPERP: - { - bool reserved = parseContext.profile == EEsProfile || parseContext.version >= 130; - return identifierOrReserved(reserved); - } - - default: - parseContext.infoSink.info.message(EPrefixInternalError, "Unknown glslang keyword", loc); - return 0; - } -} - -int TScanContext::identifierOrType() -{ - parserToken->sType.lex.string = NewPoolTString(tokenText); - if (field) - return IDENTIFIER; - - parserToken->sType.lex.symbol = parseContext.symbolTable.find(*parserToken->sType.lex.string); - if (afterType == false && parserToken->sType.lex.symbol) { - if (const TVariable* variable = parserToken->sType.lex.symbol->getAsVariable()) { - if (variable->isUserType()) { - afterType = true; - - return TYPE_NAME; - } - } - } - - return IDENTIFIER; -} - -// Give an error for use of a reserved symbol. -// However, allow built-in declarations to use reserved words, to allow -// extension support before the extension is enabled. -int TScanContext::reservedWord() -{ - if (! parseContext.symbolTable.atBuiltInLevel()) - parseContext.error(loc, "Reserved word.", tokenText, "", ""); - - return 0; -} - -int TScanContext::identifierOrReserved(bool reserved) -{ - if (reserved) { - reservedWord(); - - return 0; - } - - if (parseContext.forwardCompatible) - parseContext.warn(loc, "using future reserved keyword", tokenText, ""); - - return identifierOrType(); -} - -// For keywords that suddenly showed up on non-ES (not previously reserved) -// but then got reserved by ES 3.0. -int TScanContext::es30ReservedFromGLSL(int version) -{ - if (parseContext.symbolTable.atBuiltInLevel()) - return keyword; - - if ((parseContext.profile == EEsProfile && parseContext.version < 300) || - (parseContext.profile != EEsProfile && parseContext.version < version)) { - if (parseContext.forwardCompatible) - parseContext.warn(loc, "future reserved word in ES 300 and keyword in GLSL", tokenText, ""); - - return identifierOrType(); - } else if (parseContext.profile == EEsProfile && parseContext.version >= 300) - reservedWord(); - - return keyword; -} - -// For a keyword that was never reserved, until it suddenly -// showed up, both in an es version and a non-ES version. -int TScanContext::nonreservedKeyword(int esVersion, int nonEsVersion) -{ - if ((parseContext.profile == EEsProfile && parseContext.version < esVersion) || - (parseContext.profile != EEsProfile && parseContext.version < nonEsVersion)) { - if (parseContext.forwardCompatible) - parseContext.warn(loc, "using future keyword", tokenText, ""); - - return identifierOrType(); - } - - return keyword; -} - -int TScanContext::precisionKeyword() -{ - if (parseContext.profile == EEsProfile || parseContext.version >= 130) - return keyword; - - if (parseContext.forwardCompatible) - parseContext.warn(loc, "using ES precision qualifier keyword", tokenText, ""); - - return identifierOrType(); -} - -int TScanContext::matNxM() -{ - afterType = true; - - if (parseContext.version > 110) - return keyword; - - if (parseContext.forwardCompatible) - parseContext.warn(loc, "using future non-square matrix type keyword", tokenText, ""); - - return identifierOrType(); -} - -int TScanContext::dMat() -{ - afterType = true; - - if (parseContext.profile == EEsProfile && parseContext.version >= 300) { - reservedWord(); - - return keyword; - } - - if (parseContext.profile != EEsProfile && parseContext.version >= 400) - return keyword; - - if (parseContext.forwardCompatible) - parseContext.warn(loc, "using future type keyword", tokenText, ""); - - return identifierOrType(); -} - -int TScanContext::firstGenerationImage(bool inEs310) -{ - if (parseContext.symbolTable.atBuiltInLevel() || - (parseContext.profile != EEsProfile && (parseContext.version >= 420 || - parseContext.extensionTurnedOn(E_GL_ARB_shader_image_load_store))) || - (inEs310 && parseContext.profile == EEsProfile && parseContext.version >= 310)) - return keyword; - - if ((parseContext.profile == EEsProfile && parseContext.version >= 300) || - (parseContext.profile != EEsProfile && parseContext.version >= 130)) { - reservedWord(); - - return keyword; - } - - if (parseContext.forwardCompatible) - parseContext.warn(loc, "using future type keyword", tokenText, ""); - - return identifierOrType(); -} - -int TScanContext::secondGenerationImage() -{ - if (parseContext.profile == EEsProfile && parseContext.version >= 310) { - reservedWord(); - return keyword; - } - - if (parseContext.symbolTable.atBuiltInLevel() || - (parseContext.profile != EEsProfile && - (parseContext.version >= 420 || parseContext.extensionTurnedOn(E_GL_ARB_shader_image_load_store)))) - return keyword; - - if (parseContext.forwardCompatible) - parseContext.warn(loc, "using future type keyword", tokenText, ""); - - return identifierOrType(); -} - -} // end namespace glslang diff --git a/External/glslang/glslang/MachineIndependent/Scan.h b/External/glslang/glslang/MachineIndependent/Scan.h deleted file mode 100644 index 2c26c2ef..00000000 --- a/External/glslang/glslang/MachineIndependent/Scan.h +++ /dev/null @@ -1,274 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// Copyright (C) 2013 LunarG, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// -#ifndef _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]; - } - 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) - { - logicalSourceLoc.name = filename; - loc[getLastValidSourceIndex()].name = filename; - } - - void setFile(const char* filename, int i) - { - if (i == getLastValidSourceIndex()) { - logicalSourceLoc.name = filename; - } - loc[i].name = filename; - } - - 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/External/glslang/glslang/MachineIndependent/ScanContext.h b/External/glslang/glslang/MachineIndependent/ScanContext.h deleted file mode 100644 index 608ae067..00000000 --- a/External/glslang/glslang/MachineIndependent/ScanContext.h +++ /dev/null @@ -1,88 +0,0 @@ -// -// 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), field(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 field; // true if we're on a field, right after a '.' - TSourceLoc loc; - TParserToken* parserToken; - TPpToken* ppToken; - - const char* tokenText; - int keyword; -}; - -} // end namespace glslang diff --git a/External/glslang/glslang/MachineIndependent/ShaderLang.cpp b/External/glslang/glslang/MachineIndependent/ShaderLang.cpp deleted file mode 100644 index 4f39f345..00000000 --- a/External/glslang/glslang/MachineIndependent/ShaderLang.cpp +++ /dev/null @@ -1,1949 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// Copyright (C) 2013-2016 LunarG, Inc. -// Copyright (C) 2015-2017 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. -// - -// -// Implement the top-level of interface to the compiler/linker, -// as defined in ShaderLang.h -// This is the platform independent interface between an OGL driver -// and the shading language compiler/linker. -// -#include -#include -#include -#include -#include "SymbolTable.h" -#include "ParseHelper.h" -#include "Scan.h" -#include "ScanContext.h" - -#ifdef ENABLE_HLSL -#include "../../hlsl/hlslParseHelper.h" -#include "../../hlsl/hlslParseables.h" -#include "../../hlsl/hlslScanContext.h" -#endif - -#include "../Include/ShHandle.h" -#include "../../OGLCompilersDLL/InitializeDll.h" - -#include "preprocessor/PpContext.h" - -#define SH_EXPORTING -#include "../Public/ShaderLang.h" -#include "reflection.h" -#include "iomapper.h" -#include "Initialize.h" - -namespace { // anonymous namespace for file-local functions and symbols - -// Total number of successful initializers of glslang: a refcount -// Shared global; access should be protected by a global mutex/critical section. -int NumberOfClients = 0; - -using namespace glslang; - -// Create a language specific version of parseables. -TBuiltInParseables* CreateBuiltInParseables(TInfoSink& infoSink, EShSource source) -{ - switch (source) { - case EShSourceGlsl: return new TBuiltIns(); // GLSL builtIns -#ifdef ENABLE_HLSL - case EShSourceHlsl: return new TBuiltInParseablesHlsl(); // HLSL intrinsics -#endif - - default: - infoSink.info.message(EPrefixInternalError, "Unable to determine source language"); - return nullptr; - } -} - -// Create a language specific version of a parse context. -TParseContextBase* CreateParseContext(TSymbolTable& symbolTable, TIntermediate& intermediate, - int version, EProfile profile, EShSource source, - EShLanguage language, TInfoSink& infoSink, - SpvVersion spvVersion, bool forwardCompatible, EShMessages messages, - bool parsingBuiltIns, std::string sourceEntryPointName = "") -{ - switch (source) { - case EShSourceGlsl: { - if (sourceEntryPointName.size() == 0) - intermediate.setEntryPointName("main"); - TString entryPoint = sourceEntryPointName.c_str(); - return new TParseContext(symbolTable, intermediate, parsingBuiltIns, version, profile, spvVersion, - language, infoSink, forwardCompatible, messages, &entryPoint); - } -#ifdef ENABLE_HLSL - case EShSourceHlsl: - return new HlslParseContext(symbolTable, intermediate, parsingBuiltIns, version, profile, spvVersion, - language, infoSink, sourceEntryPointName.c_str(), forwardCompatible, messages); -#endif - default: - infoSink.info.message(EPrefixInternalError, "Unable to determine source language"); - return nullptr; - } -} - -// Local mapping functions for making arrays of symbol tables.... - -const int VersionCount = 17; // index range in MapVersionToIndex - -int MapVersionToIndex(int version) -{ - int index = 0; - - switch (version) { - case 100: index = 0; break; - case 110: index = 1; break; - case 120: index = 2; break; - case 130: index = 3; break; - case 140: index = 4; break; - case 150: index = 5; break; - case 300: index = 6; break; - case 330: index = 7; break; - case 400: index = 8; break; - case 410: index = 9; break; - case 420: index = 10; break; - case 430: index = 11; break; - case 440: index = 12; break; - case 310: index = 13; break; - case 450: index = 14; break; - case 500: index = 0; break; // HLSL - case 320: index = 15; break; - case 460: index = 16; break; - default: assert(0); break; - } - - assert(index < VersionCount); - - return index; -} - -const int SpvVersionCount = 3; // index range in MapSpvVersionToIndex - -int MapSpvVersionToIndex(const SpvVersion& spvVersion) -{ - int index = 0; - - if (spvVersion.openGl > 0) - index = 1; - else if (spvVersion.vulkan > 0) - index = 2; - - assert(index < SpvVersionCount); - - return index; -} - -const int ProfileCount = 4; // index range in MapProfileToIndex - -int MapProfileToIndex(EProfile profile) -{ - int index = 0; - - switch (profile) { - case ENoProfile: index = 0; break; - case ECoreProfile: index = 1; break; - case ECompatibilityProfile: index = 2; break; - case EEsProfile: index = 3; break; - default: break; - } - - assert(index < ProfileCount); - - return index; -} - -const int SourceCount = 2; - -int MapSourceToIndex(EShSource source) -{ - int index = 0; - - switch (source) { - case EShSourceGlsl: index = 0; break; - case EShSourceHlsl: index = 1; break; - default: break; - } - - assert(index < SourceCount); - - return index; -} - -// only one of these needed for non-ES; ES needs 2 for different precision defaults of built-ins -enum EPrecisionClass { - EPcGeneral, - EPcFragment, - EPcCount -}; - -// A process-global symbol table per version per profile for built-ins common -// to multiple stages (languages), and a process-global symbol table per version -// per profile per stage for built-ins unique to each stage. They will be sparsely -// populated, so they will only be generated as needed. -// -// Each has a different set of built-ins, and we want to preserve that from -// compile to compile. -// -TSymbolTable* CommonSymbolTable[VersionCount][SpvVersionCount][ProfileCount][SourceCount][EPcCount] = {}; -TSymbolTable* SharedSymbolTables[VersionCount][SpvVersionCount][ProfileCount][SourceCount][EShLangCount] = {}; - -TPoolAllocator* PerProcessGPA = nullptr; - -// -// Parse and add to the given symbol table the content of the given shader string. -// -bool InitializeSymbolTable(const TString& builtIns, int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage language, - EShSource source, TInfoSink& infoSink, TSymbolTable& symbolTable) -{ - TIntermediate intermediate(language, version, profile); - - intermediate.setSource(source); - - std::unique_ptr parseContext(CreateParseContext(symbolTable, intermediate, version, profile, source, - language, infoSink, spvVersion, true, EShMsgDefault, - true)); - - TShader::ForbidIncluder includer; - TPpContext ppContext(*parseContext, "", includer); - TScanContext scanContext(*parseContext); - parseContext->setScanContext(&scanContext); - parseContext->setPpContext(&ppContext); - - // - // Push the symbol table to give it an initial scope. This - // push should not have a corresponding pop, so that built-ins - // are preserved, and the test for an empty table fails. - // - - symbolTable.push(); - - const char* builtInShaders[2]; - size_t builtInLengths[2]; - builtInShaders[0] = builtIns.c_str(); - builtInLengths[0] = builtIns.size(); - - if (builtInLengths[0] == 0) - return true; - - TInputScanner input(1, builtInShaders, builtInLengths); - if (! parseContext->parseShaderStrings(ppContext, input) != 0) { - infoSink.info.message(EPrefixInternalError, "Unable to parse built-ins"); - printf("Unable to parse built-ins\n%s\n", infoSink.info.c_str()); - printf("%s\n", builtInShaders[0]); - - return false; - } - - return true; -} - -int CommonIndex(EProfile profile, EShLanguage language) -{ - return (profile == EEsProfile && language == EShLangFragment) ? EPcFragment : EPcGeneral; -} - -// -// To initialize per-stage shared tables, with the common table already complete. -// -void InitializeStageSymbolTable(TBuiltInParseables& builtInParseables, int version, EProfile profile, const SpvVersion& spvVersion, - EShLanguage language, EShSource source, TInfoSink& infoSink, TSymbolTable** commonTable, - TSymbolTable** symbolTables) -{ - (*symbolTables[language]).adoptLevels(*commonTable[CommonIndex(profile, language)]); - InitializeSymbolTable(builtInParseables.getStageString(language), version, profile, spvVersion, language, source, - infoSink, *symbolTables[language]); - builtInParseables.identifyBuiltIns(version, profile, spvVersion, language, *symbolTables[language]); - if (profile == EEsProfile && version >= 300) - (*symbolTables[language]).setNoBuiltInRedeclarations(); - if (version == 110) - (*symbolTables[language]).setSeparateNameSpaces(); -} - -// -// Initialize the full set of shareable symbol tables; -// The common (cross-stage) and those shareable per-stage. -// -bool InitializeSymbolTables(TInfoSink& infoSink, TSymbolTable** commonTable, TSymbolTable** symbolTables, int version, EProfile profile, const SpvVersion& spvVersion, EShSource source) -{ - std::unique_ptr builtInParseables(CreateBuiltInParseables(infoSink, source)); - - if (builtInParseables == nullptr) - return false; - - builtInParseables->initialize(version, profile, spvVersion); - - // do the common tables - InitializeSymbolTable(builtInParseables->getCommonString(), version, profile, spvVersion, EShLangVertex, source, - infoSink, *commonTable[EPcGeneral]); - if (profile == EEsProfile) - InitializeSymbolTable(builtInParseables->getCommonString(), version, profile, spvVersion, EShLangFragment, source, - infoSink, *commonTable[EPcFragment]); - - // do the per-stage tables - - // always have vertex and fragment - InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangVertex, source, - infoSink, commonTable, symbolTables); - InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangFragment, source, - infoSink, commonTable, symbolTables); - - // check for tessellation - if ((profile != EEsProfile && version >= 150) || - (profile == EEsProfile && version >= 310)) { - InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangTessControl, source, - infoSink, commonTable, symbolTables); - InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangTessEvaluation, source, - infoSink, commonTable, symbolTables); - } - - // check for geometry - if ((profile != EEsProfile && version >= 150) || - (profile == EEsProfile && version >= 310)) - InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangGeometry, source, - infoSink, commonTable, symbolTables); - - // check for compute - if ((profile != EEsProfile && version >= 420) || - (profile == EEsProfile && version >= 310)) - InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangCompute, source, - infoSink, commonTable, symbolTables); - - return true; -} - -bool AddContextSpecificSymbols(const TBuiltInResource* resources, TInfoSink& infoSink, TSymbolTable& symbolTable, int version, - EProfile profile, const SpvVersion& spvVersion, EShLanguage language, EShSource source) -{ - std::unique_ptr builtInParseables(CreateBuiltInParseables(infoSink, source)); - - if (builtInParseables == nullptr) - return false; - - builtInParseables->initialize(*resources, version, profile, spvVersion, language); - InitializeSymbolTable(builtInParseables->getCommonString(), version, profile, spvVersion, language, source, infoSink, symbolTable); - builtInParseables->identifyBuiltIns(version, profile, spvVersion, language, symbolTable, *resources); - - return true; -} - -// -// To do this on the fly, we want to leave the current state of our thread's -// pool allocator intact, so: -// - Switch to a new pool for parsing the built-ins -// - Do the parsing, which builds the symbol table, using the new pool -// - Switch to the process-global pool to save a copy of the resulting symbol table -// - Free up the new pool used to parse the built-ins -// - Switch back to the original thread's pool -// -// This only gets done the first time any thread needs a particular symbol table -// (lazy evaluation). -// -void SetupBuiltinSymbolTable(int version, EProfile profile, const SpvVersion& spvVersion, EShSource source) -{ - TInfoSink infoSink; - - // Make sure only one thread tries to do this at a time - glslang::GetGlobalLock(); - - // See if it's already been done for this version/profile combination - int versionIndex = MapVersionToIndex(version); - int spvVersionIndex = MapSpvVersionToIndex(spvVersion); - int profileIndex = MapProfileToIndex(profile); - int sourceIndex = MapSourceToIndex(source); - if (CommonSymbolTable[versionIndex][spvVersionIndex][profileIndex][sourceIndex][EPcGeneral]) { - glslang::ReleaseGlobalLock(); - - return; - } - - // Switch to a new pool - TPoolAllocator& previousAllocator = GetThreadPoolAllocator(); - TPoolAllocator* builtInPoolAllocator = new TPoolAllocator; - SetThreadPoolAllocator(builtInPoolAllocator); - - // Dynamically allocate the local symbol tables so we can control when they are deallocated WRT when the pool is popped. - TSymbolTable* commonTable[EPcCount]; - TSymbolTable* stageTables[EShLangCount]; - for (int precClass = 0; precClass < EPcCount; ++precClass) - commonTable[precClass] = new TSymbolTable; - for (int stage = 0; stage < EShLangCount; ++stage) - stageTables[stage] = new TSymbolTable; - - // Generate the local symbol tables using the new pool - InitializeSymbolTables(infoSink, commonTable, stageTables, version, profile, spvVersion, source); - - // Switch to the process-global pool - SetThreadPoolAllocator(PerProcessGPA); - - // Copy the local symbol tables from the new pool to the global tables using the process-global pool - for (int precClass = 0; precClass < EPcCount; ++precClass) { - if (! commonTable[precClass]->isEmpty()) { - CommonSymbolTable[versionIndex][spvVersionIndex][profileIndex][sourceIndex][precClass] = new TSymbolTable; - CommonSymbolTable[versionIndex][spvVersionIndex][profileIndex][sourceIndex][precClass]->copyTable(*commonTable[precClass]); - CommonSymbolTable[versionIndex][spvVersionIndex][profileIndex][sourceIndex][precClass]->readOnly(); - } - } - for (int stage = 0; stage < EShLangCount; ++stage) { - if (! stageTables[stage]->isEmpty()) { - SharedSymbolTables[versionIndex][spvVersionIndex][profileIndex][sourceIndex][stage] = new TSymbolTable; - SharedSymbolTables[versionIndex][spvVersionIndex][profileIndex][sourceIndex][stage]->adoptLevels(*CommonSymbolTable - [versionIndex][spvVersionIndex][profileIndex][sourceIndex][CommonIndex(profile, (EShLanguage)stage)]); - SharedSymbolTables[versionIndex][spvVersionIndex][profileIndex][sourceIndex][stage]->copyTable(*stageTables[stage]); - SharedSymbolTables[versionIndex][spvVersionIndex][profileIndex][sourceIndex][stage]->readOnly(); - } - } - - // Clean up the local tables before deleting the pool they used. - for (int precClass = 0; precClass < EPcCount; ++precClass) - delete commonTable[precClass]; - for (int stage = 0; stage < EShLangCount; ++stage) - delete stageTables[stage]; - - delete builtInPoolAllocator; - SetThreadPoolAllocator(&previousAllocator); - - glslang::ReleaseGlobalLock(); -} - -// Return true if the shader was correctly specified for version/profile/stage. -bool DeduceVersionProfile(TInfoSink& infoSink, EShLanguage stage, bool versionNotFirst, int defaultVersion, - EShSource source, int& version, EProfile& profile, const SpvVersion& spvVersion) -{ - const int FirstProfileVersion = 150; - bool correct = true; - - if (source == EShSourceHlsl) { - version = 500; // shader model; currently a characteristic of glslang, not the input - profile = ECoreProfile; // allow doubles in prototype parsing - return correct; - } - - // Get a version... - if (version == 0) { - version = defaultVersion; - // infoSink.info.message(EPrefixWarning, "#version: statement missing; use #version on first line of shader"); - } - - // Get a good profile... - if (profile == ENoProfile) { - if (version == 300 || version == 310 || version == 320) { - correct = false; - infoSink.info.message(EPrefixError, "#version: versions 300, 310, and 320 require specifying the 'es' profile"); - profile = EEsProfile; - } else if (version == 100) - profile = EEsProfile; - else if (version >= FirstProfileVersion) - profile = ECoreProfile; - else - profile = ENoProfile; - } else { - // a profile was provided... - if (version < 150) { - correct = false; - infoSink.info.message(EPrefixError, "#version: versions before 150 do not allow a profile token"); - if (version == 100) - profile = EEsProfile; - else - profile = ENoProfile; - } else if (version == 300 || version == 310 || version == 320) { - if (profile != EEsProfile) { - correct = false; - infoSink.info.message(EPrefixError, "#version: versions 300, 310, and 320 support only the es profile"); - } - profile = EEsProfile; - } else { - if (profile == EEsProfile) { - correct = false; - infoSink.info.message(EPrefixError, "#version: only version 300, 310, and 320 support the es profile"); - if (version >= FirstProfileVersion) - profile = ECoreProfile; - else - profile = ENoProfile; - } - // else: typical desktop case... e.g., "#version 410 core" - } - } - - // Fix version... - switch (version) { - // ES versions - case 100: break; - case 300: break; - case 310: break; - case 320: break; - - // desktop versions - case 110: break; - case 120: break; - case 130: break; - case 140: break; - case 150: break; - case 330: break; - case 400: break; - case 410: break; - case 420: break; - case 430: break; - case 440: break; - case 450: break; - case 460: break; - - // unknown version - default: - correct = false; - infoSink.info.message(EPrefixError, "version not supported"); - if (profile == EEsProfile) - version = 310; - else { - version = 450; - profile = ECoreProfile; - } - break; - } - - // Correct for stage type... - switch (stage) { - case EShLangGeometry: - if ((profile == EEsProfile && version < 310) || - (profile != EEsProfile && version < 150)) { - correct = false; - infoSink.info.message(EPrefixError, "#version: geometry shaders require es profile with version 310 or non-es profile with version 150 or above"); - version = (profile == EEsProfile) ? 310 : 150; - if (profile == EEsProfile || profile == ENoProfile) - profile = ECoreProfile; - } - break; - case EShLangTessControl: - case EShLangTessEvaluation: - if ((profile == EEsProfile && version < 310) || - (profile != EEsProfile && version < 150)) { - correct = false; - infoSink.info.message(EPrefixError, "#version: tessellation shaders require es profile with version 310 or non-es profile with version 150 or above"); - version = (profile == EEsProfile) ? 310 : 400; // 150 supports the extension, correction is to 400 which does not - if (profile == EEsProfile || profile == ENoProfile) - profile = ECoreProfile; - } - break; - case EShLangCompute: - if ((profile == EEsProfile && version < 310) || - (profile != EEsProfile && version < 420)) { - correct = false; - infoSink.info.message(EPrefixError, "#version: compute shaders require es profile with version 310 or above, or non-es profile with version 420 or above"); - version = profile == EEsProfile ? 310 : 420; - } - break; - default: - break; - } - - if (profile == EEsProfile && version >= 300 && versionNotFirst) { - correct = false; - infoSink.info.message(EPrefixError, "#version: statement must appear first in es-profile shader; before comments or newlines"); - } - - // Check for SPIR-V compatibility - if (spvVersion.spv != 0) { - switch (profile) { - case EEsProfile: - if (spvVersion.vulkan > 0 && version < 310) { - correct = false; - infoSink.info.message(EPrefixError, "#version: ES shaders for Vulkan SPIR-V require version 310 or higher"); - version = 310; - } - if (spvVersion.openGl >= 100) { - correct = false; - infoSink.info.message(EPrefixError, "#version: ES shaders for OpenGL SPIR-V are not supported"); - version = 310; - } - break; - case ECompatibilityProfile: - infoSink.info.message(EPrefixError, "#version: compilation for SPIR-V does not support the compatibility profile"); - break; - default: - if (spvVersion.vulkan > 0 && version < 140) { - correct = false; - infoSink.info.message(EPrefixError, "#version: Desktop shaders for Vulkan SPIR-V require version 140 or higher"); - version = 140; - } - if (spvVersion.openGl >= 100 && version < 330) { - correct = false; - infoSink.info.message(EPrefixError, "#version: Desktop shaders for OpenGL SPIR-V require version 330 or higher"); - version = 330; - } - break; - } - } - - return correct; -} - -// There are multiple paths in for setting environment stuff. -// TEnvironment takes precedence, for what it sets, so sort all this out. -// Ideally, the internal code could be made to use TEnvironment, but for -// now, translate it to the historically used parameters. -void TranslateEnvironment(const TEnvironment* environment, EShMessages& messages, EShSource& source, - EShLanguage& stage, SpvVersion& spvVersion) -{ - // Set up environmental defaults, first ignoring 'environment'. - if (messages & EShMsgSpvRules) - spvVersion.spv = EShTargetSpv_1_0; - if (messages & EShMsgVulkanRules) { - spvVersion.vulkan = EShTargetVulkan_1_0; - spvVersion.vulkanGlsl = 100; - } else if (spvVersion.spv != 0) - spvVersion.openGl = 100; - - // Now, override, based on any content set in 'environment'. - // 'environment' must be cleared to ESh*None settings when items - // are not being set. - if (environment != nullptr) { - // input language - if (environment->input.languageFamily != EShSourceNone) { - stage = environment->input.stage; - switch (environment->input.dialect) { - case EShClientNone: - break; - case EShClientVulkan: - spvVersion.vulkanGlsl = environment->input.dialectVersion; - break; - case EShClientOpenGL: - spvVersion.openGl = environment->input.dialectVersion; - break; - } - switch (environment->input.languageFamily) { - case EShSourceNone: - break; - case EShSourceGlsl: - source = EShSourceGlsl; - messages = static_cast(messages & ~EShMsgReadHlsl); - break; - case EShSourceHlsl: - source = EShSourceHlsl; - messages = static_cast(messages | EShMsgReadHlsl); - break; - } - } - - // client - switch (environment->client.client) { - case EShClientVulkan: - spvVersion.vulkan = environment->client.version; - break; - default: - break; - } - - // generated code - switch (environment->target.language) { - case EshTargetSpv: - spvVersion.spv = environment->target.version; - break; - default: - break; - } - } -} - -// Most processes are recorded when set in the intermediate representation, -// These are the few that are not. -void RecordProcesses(TIntermediate& intermediate, EShMessages messages, const std::string& sourceEntryPointName) -{ - if ((messages & EShMsgRelaxedErrors) != 0) - intermediate.addProcess("relaxed-errors"); - if ((messages & EShMsgSuppressWarnings) != 0) - intermediate.addProcess("suppress-warnings"); - if ((messages & EShMsgKeepUncalled) != 0) - intermediate.addProcess("keep-uncalled"); - if (sourceEntryPointName.size() > 0) { - intermediate.addProcess("source-entrypoint"); - intermediate.addProcessArgument(sourceEntryPointName); - } -} - -// This is the common setup and cleanup code for PreprocessDeferred and -// CompileDeferred. -// It takes any callable with a signature of -// bool (TParseContextBase& parseContext, TPpContext& ppContext, -// TInputScanner& input, bool versionWillBeError, -// TSymbolTable& , TIntermediate& , -// EShOptimizationLevel , EShMessages ); -// Which returns false if a failure was detected and true otherwise. -// -template -bool ProcessDeferred( - TCompiler* compiler, - const char* const shaderStrings[], - const int numStrings, - const int* inputLengths, - const char* const stringNames[], - const char* customPreamble, - const EShOptimizationLevel optLevel, - const TBuiltInResource* resources, - int defaultVersion, // use 100 for ES environment, 110 for desktop; this is the GLSL version, not SPIR-V or Vulkan - EProfile defaultProfile, - // set version/profile to defaultVersion/defaultProfile regardless of the #version - // directive in the source code - bool forceDefaultVersionAndProfile, - bool forwardCompatible, // give errors for use of deprecated features - EShMessages messages, // warnings/errors/AST; things to print out - TIntermediate& intermediate, // returned tree, etc. - ProcessingContext& processingContext, - bool requireNonempty, - TShader::Includer& includer, - const std::string sourceEntryPointName = "", - const TEnvironment* environment = nullptr) // optional way of fully setting all versions, overriding the above -{ - // This must be undone (.pop()) by the caller, after it finishes consuming the created tree. - GetThreadPoolAllocator().push(); - - if (numStrings == 0) - return true; - - // Move to length-based strings, rather than null-terminated strings. - // Also, add strings to include the preamble and to ensure the shader is not null, - // which lets the grammar accept what was a null (post preprocessing) shader. - // - // Shader will look like - // string 0: system preamble - // string 1: custom preamble - // string 2...numStrings+1: user's shader - // string numStrings+2: "int;" - const int numPre = 2; - const int numPost = requireNonempty? 1 : 0; - const int numTotal = numPre + numStrings + numPost; - std::unique_ptr lengths(new size_t[numTotal]); - std::unique_ptr strings(new const char*[numTotal]); - std::unique_ptr names(new const char*[numTotal]); - for (int s = 0; s < numStrings; ++s) { - strings[s + numPre] = shaderStrings[s]; - if (inputLengths == nullptr || inputLengths[s] < 0) - lengths[s + numPre] = strlen(shaderStrings[s]); - else - lengths[s + numPre] = inputLengths[s]; - } - if (stringNames != nullptr) { - for (int s = 0; s < numStrings; ++s) - names[s + numPre] = stringNames[s]; - } else { - for (int s = 0; s < numStrings; ++s) - names[s + numPre] = nullptr; - } - - // Get all the stages, languages, clients, and other environment - // stuff sorted out. - EShSource source = (messages & EShMsgReadHlsl) != 0 ? EShSourceHlsl : EShSourceGlsl; - SpvVersion spvVersion; - EShLanguage stage = compiler->getLanguage(); - TranslateEnvironment(environment, messages, source, stage, spvVersion); - if (environment != nullptr && environment->target.hlslFunctionality1) - intermediate.setHlslFunctionality1(); - - // First, without using the preprocessor or parser, find the #version, so we know what - // symbol tables, processing rules, etc. to set up. This does not need the extra strings - // outlined above, just the user shader, after the system and user preambles. - glslang::TInputScanner userInput(numStrings, &strings[numPre], &lengths[numPre]); - int version = 0; - EProfile profile = ENoProfile; - bool versionNotFirstToken = false; - bool versionNotFirst = (source == EShSourceHlsl) - ? true - : userInput.scanVersion(version, profile, versionNotFirstToken); - bool versionNotFound = version == 0; - if (forceDefaultVersionAndProfile && source == EShSourceGlsl) { - if (! (messages & EShMsgSuppressWarnings) && ! versionNotFound && - (version != defaultVersion || profile != defaultProfile)) { - compiler->infoSink.info << "Warning, (version, profile) forced to be (" - << defaultVersion << ", " << ProfileName(defaultProfile) - << "), while in source code it is (" - << version << ", " << ProfileName(profile) << ")\n"; - } - - if (versionNotFound) { - versionNotFirstToken = false; - versionNotFirst = false; - versionNotFound = false; - } - version = defaultVersion; - profile = defaultProfile; - } - - bool goodVersion = DeduceVersionProfile(compiler->infoSink, stage, - versionNotFirst, defaultVersion, source, version, profile, spvVersion); - bool versionWillBeError = (versionNotFound || (profile == EEsProfile && version >= 300 && versionNotFirst)); - bool warnVersionNotFirst = false; - if (! versionWillBeError && versionNotFirstToken) { - if (messages & EShMsgRelaxedErrors) - warnVersionNotFirst = true; - else - versionWillBeError = true; - } - - intermediate.setSource(source); - intermediate.setVersion(version); - intermediate.setProfile(profile); - intermediate.setSpv(spvVersion); - RecordProcesses(intermediate, messages, sourceEntryPointName); - if (spvVersion.vulkan > 0) - intermediate.setOriginUpperLeft(); - if ((messages & EShMsgHlslOffsets) || source == EShSourceHlsl) - intermediate.setHlslOffsets(); - if (messages & EShMsgDebugInfo) { - intermediate.setSourceFile(names[numPre]); - for (int s = 0; s < numStrings; ++s) - intermediate.addSourceText(strings[numPre + s]); - } - SetupBuiltinSymbolTable(version, profile, spvVersion, source); - - TSymbolTable* cachedTable = SharedSymbolTables[MapVersionToIndex(version)] - [MapSpvVersionToIndex(spvVersion)] - [MapProfileToIndex(profile)] - [MapSourceToIndex(source)] - [stage]; - - // Dynamically allocate the symbol table so we can control when it is deallocated WRT the pool. - std::unique_ptr symbolTable(new TSymbolTable); - if (cachedTable) - symbolTable->adoptLevels(*cachedTable); - - // Add built-in symbols that are potentially context dependent; - // they get popped again further down. - if (! AddContextSpecificSymbols(resources, compiler->infoSink, *symbolTable, version, profile, spvVersion, - stage, source)) { - return false; - } - - // - // Now we can process the full shader under proper symbols and rules. - // - - std::unique_ptr parseContext(CreateParseContext(*symbolTable, intermediate, version, profile, source, - stage, compiler->infoSink, - spvVersion, forwardCompatible, messages, false, sourceEntryPointName)); - TPpContext ppContext(*parseContext, names[numPre] ? names[numPre] : "", includer); - - // only GLSL (bison triggered, really) needs an externally set scan context - glslang::TScanContext scanContext(*parseContext); - if (source == EShSourceGlsl) - parseContext->setScanContext(&scanContext); - - parseContext->setPpContext(&ppContext); - parseContext->setLimits(*resources); - if (! goodVersion) - parseContext->addError(); - if (warnVersionNotFirst) { - TSourceLoc loc; - loc.init(); - parseContext->warn(loc, "Illegal to have non-comment, non-whitespace tokens before #version", "#version", ""); - } - - parseContext->initializeExtensionBehavior(); - - // Fill in the strings as outlined above. - std::string preamble; - parseContext->getPreamble(preamble); - strings[0] = preamble.c_str(); - lengths[0] = strlen(strings[0]); - names[0] = nullptr; - strings[1] = customPreamble; - lengths[1] = strlen(strings[1]); - names[1] = nullptr; - assert(2 == numPre); - if (requireNonempty) { - const int postIndex = numStrings + numPre; - strings[postIndex] = "\n int;"; - lengths[postIndex] = strlen(strings[numStrings + numPre]); - names[postIndex] = nullptr; - } - TInputScanner fullInput(numStrings + numPre + numPost, strings.get(), lengths.get(), names.get(), numPre, numPost); - - // Push a new symbol allocation scope that will get used for the shader's globals. - symbolTable->push(); - - bool success = processingContext(*parseContext, ppContext, fullInput, - versionWillBeError, *symbolTable, - intermediate, optLevel, messages); - return success; -} - -// Responsible for keeping track of the most recent source string and line in -// the preprocessor and outputting newlines appropriately if the source string -// or line changes. -class SourceLineSynchronizer { -public: - SourceLineSynchronizer(const std::function& lastSourceIndex, - std::string* output) - : getLastSourceIndex(lastSourceIndex), output(output), lastSource(-1), lastLine(0) {} -// SourceLineSynchronizer(const SourceLineSynchronizer&) = delete; -// SourceLineSynchronizer& operator=(const SourceLineSynchronizer&) = delete; - - // Sets the internally tracked source string index to that of the most - // recently read token. If we switched to a new source string, returns - // true and inserts a newline. Otherwise, returns false and outputs nothing. - bool syncToMostRecentString() { - if (getLastSourceIndex() != lastSource) { - // After switching to a new source string, we need to reset lastLine - // because line number resets every time a new source string is - // used. We also need to output a newline to separate the output - // from the previous source string (if there is one). - if (lastSource != -1 || lastLine != 0) - *output += '\n'; - lastSource = getLastSourceIndex(); - lastLine = -1; - return true; - } - return false; - } - - // Calls syncToMostRecentString() and then sets the internally tracked line - // number to tokenLine. If we switched to a new line, returns true and inserts - // newlines appropriately. Otherwise, returns false and outputs nothing. - bool syncToLine(int tokenLine) { - syncToMostRecentString(); - const bool newLineStarted = lastLine < tokenLine; - for (; lastLine < tokenLine; ++lastLine) { - if (lastLine > 0) *output += '\n'; - } - return newLineStarted; - } - - // Sets the internally tracked line number to newLineNum. - void setLineNum(int newLineNum) { lastLine = newLineNum; } - -private: - SourceLineSynchronizer& operator=(const SourceLineSynchronizer&); - - // A function for getting the index of the last valid source string we've - // read tokens from. - const std::function getLastSourceIndex; - // output string for newlines. - std::string* output; - // lastSource is the source string index (starting from 0) of the last token - // processed. It is tracked in order for newlines to be inserted when a new - // source string starts. -1 means we haven't started processing any source - // string. - int lastSource; - // lastLine is the line number (starting from 1) of the last token processed. - // It is tracked in order for newlines to be inserted when a token appears - // on a new line. 0 means we haven't started processing any line in the - // current source string. - int lastLine; -}; - -// DoPreprocessing is a valid ProcessingContext template argument, -// which only performs the preprocessing step of compilation. -// It places the result in the "string" argument to its constructor. -struct DoPreprocessing { - explicit DoPreprocessing(std::string* string): outputString(string) {} - bool operator()(TParseContextBase& parseContext, TPpContext& ppContext, - TInputScanner& input, bool versionWillBeError, - TSymbolTable&, TIntermediate&, - EShOptimizationLevel, EShMessages) - { - // This is a list of tokens that do not require a space before or after. - static const std::string unNeededSpaceTokens = ";()[]"; - static const std::string noSpaceBeforeTokens = ","; - glslang::TPpToken ppToken; - - parseContext.setScanner(&input); - ppContext.setInput(input, versionWillBeError); - - std::string outputBuffer; - SourceLineSynchronizer lineSync( - std::bind(&TInputScanner::getLastValidSourceIndex, &input), &outputBuffer); - - parseContext.setExtensionCallback([&lineSync, &outputBuffer]( - int line, const char* extension, const char* behavior) { - lineSync.syncToLine(line); - outputBuffer += "#extension "; - outputBuffer += extension; - outputBuffer += " : "; - outputBuffer += behavior; - }); - - parseContext.setLineCallback([&lineSync, &outputBuffer, &parseContext]( - int curLineNum, int newLineNum, bool hasSource, int sourceNum, const char* sourceName) { - // SourceNum is the number of the source-string that is being parsed. - lineSync.syncToLine(curLineNum); - outputBuffer += "#line "; - outputBuffer += std::to_string(newLineNum); - if (hasSource) { - outputBuffer += ' '; - if (sourceName != nullptr) { - outputBuffer += '\"'; - outputBuffer += sourceName; - outputBuffer += '\"'; - } else { - outputBuffer += std::to_string(sourceNum); - } - } - if (parseContext.lineDirectiveShouldSetNextLine()) { - // newLineNum is the new line number for the line following the #line - // directive. So the new line number for the current line is - newLineNum -= 1; - } - outputBuffer += '\n'; - // And we are at the next line of the #line directive now. - lineSync.setLineNum(newLineNum + 1); - }); - - parseContext.setVersionCallback( - [&lineSync, &outputBuffer](int line, int version, const char* str) { - lineSync.syncToLine(line); - outputBuffer += "#version "; - outputBuffer += std::to_string(version); - if (str) { - outputBuffer += ' '; - outputBuffer += str; - } - }); - - parseContext.setPragmaCallback([&lineSync, &outputBuffer]( - int line, const glslang::TVector& ops) { - lineSync.syncToLine(line); - outputBuffer += "#pragma "; - for(size_t i = 0; i < ops.size(); ++i) { - outputBuffer += ops[i].c_str(); - } - }); - - parseContext.setErrorCallback([&lineSync, &outputBuffer]( - int line, const char* errorMessage) { - lineSync.syncToLine(line); - outputBuffer += "#error "; - outputBuffer += errorMessage; - }); - - int lastToken = EndOfInput; // lastToken records the last token processed. - do { - int token = ppContext.tokenize(ppToken); - if (token == EndOfInput) - break; - - bool isNewString = lineSync.syncToMostRecentString(); - bool isNewLine = lineSync.syncToLine(ppToken.loc.line); - - if (isNewLine) { - // Don't emit whitespace onto empty lines. - // Copy any whitespace characters at the start of a line - // from the input to the output. - outputBuffer += std::string(ppToken.loc.column - 1, ' '); - } - - // Output a space in between tokens, but not at the start of a line, - // and also not around special tokens. This helps with readability - // and consistency. - if (!isNewString && !isNewLine && lastToken != EndOfInput && - (unNeededSpaceTokens.find((char)token) == std::string::npos) && - (unNeededSpaceTokens.find((char)lastToken) == std::string::npos) && - (noSpaceBeforeTokens.find((char)token) == std::string::npos)) { - outputBuffer += ' '; - } - lastToken = token; - outputBuffer += ppToken.name; - } while (true); - outputBuffer += '\n'; - *outputString = std::move(outputBuffer); - - bool success = true; - if (parseContext.getNumErrors() > 0) { - success = false; - parseContext.infoSink.info.prefix(EPrefixError); - parseContext.infoSink.info << parseContext.getNumErrors() << " compilation errors. No code generated.\n\n"; - } - return success; - } - std::string* outputString; -}; - -// DoFullParse is a valid ProcessingConext template argument for fully -// parsing the shader. It populates the "intermediate" with the AST. -struct DoFullParse{ - bool operator()(TParseContextBase& parseContext, TPpContext& ppContext, - TInputScanner& fullInput, bool versionWillBeError, - TSymbolTable&, TIntermediate& intermediate, - EShOptimizationLevel optLevel, EShMessages messages) - { - bool success = true; - // Parse the full shader. - if (! parseContext.parseShaderStrings(ppContext, fullInput, versionWillBeError)) - success = false; - - if (success && intermediate.getTreeRoot()) { - if (optLevel == EShOptNoGeneration) - parseContext.infoSink.info.message(EPrefixNone, "No errors. No code generation or linking was requested."); - else - success = intermediate.postProcess(intermediate.getTreeRoot(), parseContext.getLanguage()); - } else if (! success) { - parseContext.infoSink.info.prefix(EPrefixError); - parseContext.infoSink.info << parseContext.getNumErrors() << " compilation errors. No code generated.\n\n"; - } - - if (messages & EShMsgAST) - intermediate.output(parseContext.infoSink, true); - - return success; - } -}; - -// Take a single compilation unit, and run the preprocessor on it. -// Return: True if there were no issues found in preprocessing, -// False if during preprocessing any unknown version, pragmas or -// extensions were found. -bool PreprocessDeferred( - TCompiler* compiler, - const char* const shaderStrings[], - const int numStrings, - const int* inputLengths, - const char* const stringNames[], - const char* preamble, - const EShOptimizationLevel optLevel, - const TBuiltInResource* resources, - int defaultVersion, // use 100 for ES environment, 110 for desktop - EProfile defaultProfile, - bool forceDefaultVersionAndProfile, - bool forwardCompatible, // give errors for use of deprecated features - EShMessages messages, // warnings/errors/AST; things to print out - TShader::Includer& includer, - TIntermediate& intermediate, // returned tree, etc. - std::string* outputString) -{ - DoPreprocessing parser(outputString); - return ProcessDeferred(compiler, shaderStrings, numStrings, inputLengths, stringNames, - preamble, optLevel, resources, defaultVersion, - defaultProfile, forceDefaultVersionAndProfile, - forwardCompatible, messages, intermediate, parser, - false, includer); -} - -// -// do a partial compile on the given strings for a single compilation unit -// for a potential deferred link into a single stage (and deferred full compile of that -// stage through machine-dependent compilation). -// -// all preprocessing, parsing, semantic checks, etc. for a single compilation unit -// are done here. -// -// return: the tree and other information is filled into the intermediate argument, -// and true is returned by the function for success. -// -bool CompileDeferred( - TCompiler* compiler, - const char* const shaderStrings[], - const int numStrings, - const int* inputLengths, - const char* const stringNames[], - const char* preamble, - const EShOptimizationLevel optLevel, - const TBuiltInResource* resources, - int defaultVersion, // use 100 for ES environment, 110 for desktop - EProfile defaultProfile, - bool forceDefaultVersionAndProfile, - bool forwardCompatible, // give errors for use of deprecated features - EShMessages messages, // warnings/errors/AST; things to print out - TIntermediate& intermediate,// returned tree, etc. - TShader::Includer& includer, - const std::string sourceEntryPointName = "", - TEnvironment* environment = nullptr) -{ - DoFullParse parser; - return ProcessDeferred(compiler, shaderStrings, numStrings, inputLengths, stringNames, - preamble, optLevel, resources, defaultVersion, - defaultProfile, forceDefaultVersionAndProfile, - forwardCompatible, messages, intermediate, parser, - true, includer, sourceEntryPointName, environment); -} - -} // end anonymous namespace for local functions - -// -// ShInitialize() should be called exactly once per process, not per thread. -// -int ShInitialize() -{ - glslang::InitGlobalLock(); - - if (! InitProcess()) - return 0; - - glslang::GetGlobalLock(); - ++NumberOfClients; - glslang::ReleaseGlobalLock(); - - if (PerProcessGPA == nullptr) - PerProcessGPA = new TPoolAllocator(); - - glslang::TScanContext::fillInKeywordMap(); -#ifdef ENABLE_HLSL - glslang::HlslScanContext::fillInKeywordMap(); -#endif - - return 1; -} - -// -// Driver calls these to create and destroy compiler/linker -// objects. -// - -ShHandle ShConstructCompiler(const EShLanguage language, int debugOptions) -{ - if (!InitThread()) - return 0; - - TShHandleBase* base = static_cast(ConstructCompiler(language, debugOptions)); - - return reinterpret_cast(base); -} - -ShHandle ShConstructLinker(const EShExecutable executable, int debugOptions) -{ - if (!InitThread()) - return 0; - - TShHandleBase* base = static_cast(ConstructLinker(executable, debugOptions)); - - return reinterpret_cast(base); -} - -ShHandle ShConstructUniformMap() -{ - if (!InitThread()) - return 0; - - TShHandleBase* base = static_cast(ConstructUniformMap()); - - return reinterpret_cast(base); -} - -void ShDestruct(ShHandle handle) -{ - if (handle == 0) - return; - - TShHandleBase* base = static_cast(handle); - - if (base->getAsCompiler()) - DeleteCompiler(base->getAsCompiler()); - else if (base->getAsLinker()) - DeleteLinker(base->getAsLinker()); - else if (base->getAsUniformMap()) - DeleteUniformMap(base->getAsUniformMap()); -} - -// -// Cleanup symbol tables -// -int __fastcall ShFinalize() -{ - glslang::GetGlobalLock(); - --NumberOfClients; - assert(NumberOfClients >= 0); - bool finalize = NumberOfClients == 0; - glslang::ReleaseGlobalLock(); - if (! finalize) - return 1; - - for (int version = 0; version < VersionCount; ++version) { - for (int spvVersion = 0; spvVersion < SpvVersionCount; ++spvVersion) { - for (int p = 0; p < ProfileCount; ++p) { - for (int source = 0; source < SourceCount; ++source) { - for (int stage = 0; stage < EShLangCount; ++stage) { - delete SharedSymbolTables[version][spvVersion][p][source][stage]; - SharedSymbolTables[version][spvVersion][p][source][stage] = 0; - } - } - } - } - } - - for (int version = 0; version < VersionCount; ++version) { - for (int spvVersion = 0; spvVersion < SpvVersionCount; ++spvVersion) { - for (int p = 0; p < ProfileCount; ++p) { - for (int source = 0; source < SourceCount; ++source) { - for (int pc = 0; pc < EPcCount; ++pc) { - delete CommonSymbolTable[version][spvVersion][p][source][pc]; - CommonSymbolTable[version][spvVersion][p][source][pc] = 0; - } - } - } - } - } - - if (PerProcessGPA != nullptr) { - delete PerProcessGPA; - PerProcessGPA = nullptr; - } - - glslang::TScanContext::deleteKeywordMap(); -#ifdef ENABLE_HLSL - glslang::HlslScanContext::deleteKeywordMap(); -#endif - - return 1; -} - -// -// Do a full compile on the given strings for a single compilation unit -// forming a complete stage. The result of the machine dependent compilation -// is left in the provided compile object. -// -// Return: The return value is really boolean, indicating -// success (1) or failure (0). -// -int ShCompile( - const ShHandle handle, - const char* const shaderStrings[], - const int numStrings, - const int* inputLengths, - const EShOptimizationLevel optLevel, - const TBuiltInResource* resources, - int /*debugOptions*/, - int defaultVersion, // use 100 for ES environment, 110 for desktop - bool forwardCompatible, // give errors for use of deprecated features - EShMessages messages // warnings/errors/AST; things to print out - ) -{ - // Map the generic handle to the C++ object - if (handle == 0) - return 0; - - TShHandleBase* base = reinterpret_cast(handle); - TCompiler* compiler = base->getAsCompiler(); - if (compiler == 0) - return 0; - - SetThreadPoolAllocator(compiler->getPool()); - - compiler->infoSink.info.erase(); - compiler->infoSink.debug.erase(); - - TIntermediate intermediate(compiler->getLanguage()); - TShader::ForbidIncluder includer; - bool success = CompileDeferred(compiler, shaderStrings, numStrings, inputLengths, nullptr, - "", optLevel, resources, defaultVersion, ENoProfile, false, - forwardCompatible, messages, intermediate, includer); - - // - // Call the machine dependent compiler - // - if (success && intermediate.getTreeRoot() && optLevel != EShOptNoGeneration) - success = compiler->compile(intermediate.getTreeRoot(), intermediate.getVersion(), intermediate.getProfile()); - - intermediate.removeTree(); - - // Throw away all the temporary memory used by the compilation process. - // The push was done in the CompileDeferred() call above. - GetThreadPoolAllocator().pop(); - - return success ? 1 : 0; -} - -// -// Link the given compile objects. -// -// Return: The return value of is really boolean, indicating -// success or failure. -// -int ShLinkExt( - const ShHandle linkHandle, - const ShHandle compHandles[], - const int numHandles) -{ - if (linkHandle == 0 || numHandles == 0) - return 0; - - THandleList cObjects; - - for (int i = 0; i < numHandles; ++i) { - if (compHandles[i] == 0) - return 0; - TShHandleBase* base = reinterpret_cast(compHandles[i]); - if (base->getAsLinker()) { - cObjects.push_back(base->getAsLinker()); - } - if (base->getAsCompiler()) - cObjects.push_back(base->getAsCompiler()); - - if (cObjects[i] == 0) - return 0; - } - - TShHandleBase* base = reinterpret_cast(linkHandle); - TLinker* linker = static_cast(base->getAsLinker()); - - SetThreadPoolAllocator(linker->getPool()); - - if (linker == 0) - return 0; - - linker->infoSink.info.erase(); - - for (int i = 0; i < numHandles; ++i) { - if (cObjects[i]->getAsCompiler()) { - if (! cObjects[i]->getAsCompiler()->linkable()) { - linker->infoSink.info.message(EPrefixError, "Not all shaders have valid object code."); - return 0; - } - } - } - - bool ret = linker->link(cObjects); - - return ret ? 1 : 0; -} - -// -// ShSetEncrpytionMethod is a place-holder for specifying -// how source code is encrypted. -// -void ShSetEncryptionMethod(ShHandle handle) -{ - if (handle == 0) - return; -} - -// -// Return any compiler/linker/uniformmap log of messages for the application. -// -const char* ShGetInfoLog(const ShHandle handle) -{ - if (handle == 0) - return 0; - - TShHandleBase* base = static_cast(handle); - TInfoSink* infoSink; - - if (base->getAsCompiler()) - infoSink = &(base->getAsCompiler()->getInfoSink()); - else if (base->getAsLinker()) - infoSink = &(base->getAsLinker()->getInfoSink()); - else - return 0; - - infoSink->info << infoSink->debug.c_str(); - return infoSink->info.c_str(); -} - -// -// Return the resulting binary code from the link process. Structure -// is machine dependent. -// -const void* ShGetExecutable(const ShHandle handle) -{ - if (handle == 0) - return 0; - - TShHandleBase* base = reinterpret_cast(handle); - - TLinker* linker = static_cast(base->getAsLinker()); - if (linker == 0) - return 0; - - return linker->getObjectCode(); -} - -// -// Let the linker know where the application said it's attributes are bound. -// The linker does not use these values, they are remapped by the ICD or -// hardware. It just needs them to know what's aliased. -// -// Return: The return value of is really boolean, indicating -// success or failure. -// -int ShSetVirtualAttributeBindings(const ShHandle handle, const ShBindingTable* table) -{ - if (handle == 0) - return 0; - - TShHandleBase* base = reinterpret_cast(handle); - TLinker* linker = static_cast(base->getAsLinker()); - - if (linker == 0) - return 0; - - linker->setAppAttributeBindings(table); - - return 1; -} - -// -// Let the linker know where the predefined attributes have to live. -// -int ShSetFixedAttributeBindings(const ShHandle handle, const ShBindingTable* table) -{ - if (handle == 0) - return 0; - - TShHandleBase* base = reinterpret_cast(handle); - TLinker* linker = static_cast(base->getAsLinker()); - - if (linker == 0) - return 0; - - linker->setFixedAttributeBindings(table); - return 1; -} - -// -// Some attribute locations are off-limits to the linker... -// -int ShExcludeAttributes(const ShHandle handle, int *attributes, int count) -{ - if (handle == 0) - return 0; - - TShHandleBase* base = reinterpret_cast(handle); - TLinker* linker = static_cast(base->getAsLinker()); - if (linker == 0) - return 0; - - linker->setExcludedAttributes(attributes, count); - - return 1; -} - -// -// Return the index for OpenGL to use for knowing where a uniform lives. -// -// Return: The return value of is really boolean, indicating -// success or failure. -// -int ShGetUniformLocation(const ShHandle handle, const char* name) -{ - if (handle == 0) - return -1; - - TShHandleBase* base = reinterpret_cast(handle); - TUniformMap* uniformMap= base->getAsUniformMap(); - if (uniformMap == 0) - return -1; - - return uniformMap->getLocation(name); -} - -//////////////////////////////////////////////////////////////////////////////////////////// -// -// Deferred-Lowering C++ Interface -// ----------------------------------- -// -// Below is a new alternate C++ interface that might potentially replace the above -// opaque handle-based interface. -// -// See more detailed comment in ShaderLang.h -// - -namespace glslang { - -#include "../Include/revision.h" - -#define QUOTE(s) #s -#define STR(n) QUOTE(n) - -const char* GetEsslVersionString() -{ - return "OpenGL ES GLSL 3.20 glslang Khronos. " STR(GLSLANG_MINOR_VERSION) "." STR(GLSLANG_PATCH_LEVEL); -} - -const char* GetGlslVersionString() -{ - return "4.60 glslang Khronos. " STR(GLSLANG_MINOR_VERSION) "." STR(GLSLANG_PATCH_LEVEL); -} - -int GetKhronosToolId() -{ - return 8; -} - -bool InitializeProcess() -{ - return ShInitialize() != 0; -} - -void FinalizeProcess() -{ - ShFinalize(); -} - -class TDeferredCompiler : public TCompiler { -public: - TDeferredCompiler(EShLanguage s, TInfoSink& i) : TCompiler(s, i) { } - virtual bool compile(TIntermNode*, int = 0, EProfile = ENoProfile) { return true; } -}; - -TShader::TShader(EShLanguage s) - : stage(s), lengths(nullptr), stringNames(nullptr), preamble("") -{ - pool = new TPoolAllocator; - infoSink = new TInfoSink; - compiler = new TDeferredCompiler(stage, *infoSink); - intermediate = new TIntermediate(s); - - // clear environment (avoid constructors in them for use in a C interface) - environment.input.languageFamily = EShSourceNone; - environment.input.dialect = EShClientNone; - environment.client.client = EShClientNone; - environment.target.language = EShTargetNone; - environment.target.hlslFunctionality1 = false; -} - -TShader::~TShader() -{ - delete infoSink; - delete compiler; - delete intermediate; - delete pool; -} - -void TShader::setStrings(const char* const* s, int n) -{ - strings = s; - numStrings = n; - lengths = nullptr; -} - -void TShader::setStringsWithLengths(const char* const* s, const int* l, int n) -{ - strings = s; - numStrings = n; - lengths = l; -} - -void TShader::setStringsWithLengthsAndNames( - const char* const* s, const int* l, const char* const* names, int n) -{ - strings = s; - numStrings = n; - lengths = l; - stringNames = names; -} - -void TShader::setEntryPoint(const char* entryPoint) -{ - intermediate->setEntryPointName(entryPoint); -} - -void TShader::setSourceEntryPoint(const char* name) -{ - sourceEntryPointName = name; -} - -void TShader::addProcesses(const std::vector& p) -{ - intermediate->addProcesses(p); -} - -// Set binding base for given resource type -void TShader::setShiftBinding(TResourceType res, unsigned int base) { - intermediate->setShiftBinding(res, base); -} - -// Set binding base for given resource type for a given binding set. -void TShader::setShiftBindingForSet(TResourceType res, unsigned int base, unsigned int set) { - intermediate->setShiftBindingForSet(res, base, set); -} - -// Set binding base for sampler types -void TShader::setShiftSamplerBinding(unsigned int base) { setShiftBinding(EResSampler, base); } -// Set binding base for texture types (SRV) -void TShader::setShiftTextureBinding(unsigned int base) { setShiftBinding(EResTexture, base); } -// Set binding base for image types -void TShader::setShiftImageBinding(unsigned int base) { setShiftBinding(EResImage, base); } -// Set binding base for uniform buffer objects (CBV) -void TShader::setShiftUboBinding(unsigned int base) { setShiftBinding(EResUbo, base); } -// Synonym for setShiftUboBinding, to match HLSL language. -void TShader::setShiftCbufferBinding(unsigned int base) { setShiftBinding(EResUbo, base); } -// Set binding base for UAV (unordered access view) -void TShader::setShiftUavBinding(unsigned int base) { setShiftBinding(EResUav, base); } -// Set binding base for SSBOs -void TShader::setShiftSsboBinding(unsigned int base) { setShiftBinding(EResSsbo, base); } -// Enables binding automapping using TIoMapper -void TShader::setAutoMapBindings(bool map) { intermediate->setAutoMapBindings(map); } -// Enables position.Y output negation in vertex shader -void TShader::setInvertY(bool invert) { intermediate->setInvertY(invert); } -// Fragile: currently within one stage: simple auto-assignment of location -void TShader::setAutoMapLocations(bool map) { intermediate->setAutoMapLocations(map); } -// See comment above TDefaultHlslIoMapper in iomapper.cpp: -void TShader::setHlslIoMapping(bool hlslIoMap) { intermediate->setHlslIoMapping(hlslIoMap); } -void TShader::setFlattenUniformArrays(bool flatten) { intermediate->setFlattenUniformArrays(flatten); } -void TShader::setNoStorageFormat(bool useUnknownFormat) { intermediate->setNoStorageFormat(useUnknownFormat); } -void TShader::setResourceSetBinding(const std::vector& base) { intermediate->setResourceSetBinding(base); } -void TShader::setTextureSamplerTransformMode(EShTextureSamplerTransformMode mode) { intermediate->setTextureSamplerTransformMode(mode); } - -// -// Turn the shader strings into a parse tree in the TIntermediate. -// -// Returns true for success. -// -bool TShader::parse(const TBuiltInResource* builtInResources, int defaultVersion, EProfile defaultProfile, bool forceDefaultVersionAndProfile, - bool forwardCompatible, EShMessages messages, Includer& includer) -{ - if (! InitThread()) - return false; - SetThreadPoolAllocator(pool); - - if (! preamble) - preamble = ""; - - return CompileDeferred(compiler, strings, numStrings, lengths, stringNames, - preamble, EShOptNone, builtInResources, defaultVersion, - defaultProfile, forceDefaultVersionAndProfile, - forwardCompatible, messages, *intermediate, includer, sourceEntryPointName, - &environment); -} - -// Fill in a string with the result of preprocessing ShaderStrings -// Returns true if all extensions, pragmas and version strings were valid. -bool TShader::preprocess(const TBuiltInResource* builtInResources, - int defaultVersion, EProfile defaultProfile, - bool forceDefaultVersionAndProfile, - bool forwardCompatible, EShMessages message, - std::string* output_string, - Includer& includer) -{ - if (! InitThread()) - return false; - SetThreadPoolAllocator(pool); - - if (! preamble) - preamble = ""; - - return PreprocessDeferred(compiler, strings, numStrings, lengths, stringNames, preamble, - EShOptNone, builtInResources, defaultVersion, - defaultProfile, forceDefaultVersionAndProfile, - forwardCompatible, message, includer, *intermediate, output_string); -} - -const char* TShader::getInfoLog() -{ - return infoSink->info.c_str(); -} - -const char* TShader::getInfoDebugLog() -{ - return infoSink->debug.c_str(); -} - -TProgram::TProgram() : reflection(0), ioMapper(nullptr), linked(false) -{ - pool = new TPoolAllocator; - infoSink = new TInfoSink; - for (int s = 0; s < EShLangCount; ++s) { - intermediate[s] = 0; - newedIntermediate[s] = false; - } -} - -TProgram::~TProgram() -{ - delete ioMapper; - delete infoSink; - delete reflection; - - for (int s = 0; s < EShLangCount; ++s) - if (newedIntermediate[s]) - delete intermediate[s]; - - delete pool; -} - -// -// Merge the compilation units within each stage into a single TIntermediate. -// All starting compilation units need to be the result of calling TShader::parse(). -// -// Return true for success. -// -bool TProgram::link(EShMessages messages) -{ - if (linked) - return false; - linked = true; - - bool error = false; - - SetThreadPoolAllocator(pool); - - for (int s = 0; s < EShLangCount; ++s) { - if (! linkStage((EShLanguage)s, messages)) - error = true; - } - - // TODO: Link: cross-stage error checking - - return ! error; -} - -// -// Merge the compilation units within the given stage into a single TIntermediate. -// -// Return true for success. -// -bool TProgram::linkStage(EShLanguage stage, EShMessages messages) -{ - if (stages[stage].size() == 0) - return true; - - int numEsShaders = 0, numNonEsShaders = 0; - for (auto it = stages[stage].begin(); it != stages[stage].end(); ++it) { - if ((*it)->intermediate->getProfile() == EEsProfile) { - numEsShaders++; - } else { - numNonEsShaders++; - } - } - - if (numEsShaders > 0 && numNonEsShaders > 0) { - infoSink->info.message(EPrefixError, "Cannot mix ES profile with non-ES profile shaders"); - return false; - } else if (numEsShaders > 1) { - infoSink->info.message(EPrefixError, "Cannot attach multiple ES shaders of the same type to a single program"); - return false; - } - - // - // Be efficient for the common single compilation unit per stage case, - // reusing it's TIntermediate instead of merging into a new one. - // - TIntermediate *firstIntermediate = stages[stage].front()->intermediate; - if (stages[stage].size() == 1) - intermediate[stage] = firstIntermediate; - else { - intermediate[stage] = new TIntermediate(stage, - firstIntermediate->getVersion(), - firstIntermediate->getProfile()); - - - // The new TIntermediate must use the same origin as the original TIntermediates. - // Otherwise linking will fail due to different coordinate systems. - if (firstIntermediate->getOriginUpperLeft()) { - intermediate[stage]->setOriginUpperLeft(); - } - intermediate[stage]->setSpv(firstIntermediate->getSpv()); - - newedIntermediate[stage] = true; - } - - if (messages & EShMsgAST) - infoSink->info << "\nLinked " << StageName(stage) << " stage:\n\n"; - - if (stages[stage].size() > 1) { - std::list::const_iterator it; - for (it = stages[stage].begin(); it != stages[stage].end(); ++it) - intermediate[stage]->merge(*infoSink, *(*it)->intermediate); - } - - intermediate[stage]->finalCheck(*infoSink, (messages & EShMsgKeepUncalled) != 0); - - if (messages & EShMsgAST) - intermediate[stage]->output(*infoSink, true); - - return intermediate[stage]->getNumErrors() == 0; -} - -const char* TProgram::getInfoLog() -{ - return infoSink->info.c_str(); -} - -const char* TProgram::getInfoDebugLog() -{ - return infoSink->debug.c_str(); -} - -// -// Reflection implementation. -// - -bool TProgram::buildReflection() -{ - if (! linked || reflection) - return false; - - reflection = new TReflection; - - for (int s = 0; s < EShLangCount; ++s) { - if (intermediate[s]) { - if (! reflection->addStage((EShLanguage)s, *intermediate[s])) - return false; - } - } - - return true; -} - -int TProgram::getNumLiveUniformVariables() const { return reflection->getNumUniforms(); } -int TProgram::getNumLiveUniformBlocks() const { return reflection->getNumUniformBlocks(); } -const char* TProgram::getUniformName(int index) const { return reflection->getUniform(index).name.c_str(); } -const char* TProgram::getUniformBlockName(int index) const { return reflection->getUniformBlock(index).name.c_str(); } -int TProgram::getUniformBlockSize(int index) const { return reflection->getUniformBlock(index).size; } -int TProgram::getUniformIndex(const char* name) const { return reflection->getIndex(name); } -int TProgram::getUniformBinding(int index) const { return reflection->getUniform(index).getBinding(); } -int TProgram::getUniformBlockBinding(int index) const { return reflection->getUniformBlock(index).getBinding(); } -int TProgram::getUniformBlockIndex(int index) const { return reflection->getUniform(index).index; } -int TProgram::getUniformBlockCounterIndex(int index) const { return reflection->getUniformBlock(index).counterIndex; } -int TProgram::getUniformType(int index) const { return reflection->getUniform(index).glDefineType; } -int TProgram::getUniformBufferOffset(int index) const { return reflection->getUniform(index).offset; } -int TProgram::getUniformArraySize(int index) const { return reflection->getUniform(index).size; } -int TProgram::getNumLiveAttributes() const { return reflection->getNumAttributes(); } -const char* TProgram::getAttributeName(int index) const { return reflection->getAttribute(index).name.c_str(); } -int TProgram::getAttributeType(int index) const { return reflection->getAttribute(index).glDefineType; } -const TType* TProgram::getAttributeTType(int index) const { return reflection->getAttribute(index).getType(); } -const TType* TProgram::getUniformTType(int index) const { return reflection->getUniform(index).getType(); } -const TType* TProgram::getUniformBlockTType(int index) const { return reflection->getUniformBlock(index).getType(); } -unsigned TProgram::getLocalSize(int dim) const { return reflection->getLocalSize(dim); } - -void TProgram::dumpReflection() { reflection->dump(); } - -// -// I/O mapping implementation. -// -bool TProgram::mapIO(TIoMapResolver* resolver) -{ - if (! linked || ioMapper) - return false; - - ioMapper = new TIoMapper; - - for (int s = 0; s < EShLangCount; ++s) { - if (intermediate[s]) { - if (! ioMapper->addStage((EShLanguage)s, *intermediate[s], *infoSink, resolver)) - return false; - } - } - - return true; -} - -} // end namespace glslang diff --git a/External/glslang/glslang/MachineIndependent/SymbolTable.cpp b/External/glslang/glslang/MachineIndependent/SymbolTable.cpp deleted file mode 100644 index db46e107..00000000 --- a/External/glslang/glslang/MachineIndependent/SymbolTable.cpp +++ /dev/null @@ -1,385 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// Copyright (C) 2012-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. -// - -// -// Symbol table for parsing. Most functionality and main ideas -// are documented in the header file. -// - -#include "SymbolTable.h" - -namespace glslang { - -// -// TType helper function needs a place to live. -// - -// -// Recursively generate mangled names. -// -void TType::buildMangledName(TString& mangledName) const -{ - if (isMatrix()) - mangledName += 'm'; - else if (isVector()) - mangledName += 'v'; - - switch (basicType) { - case EbtFloat: mangledName += 'f'; break; - case EbtDouble: mangledName += 'd'; break; - case EbtFloat16: mangledName += "f16"; break; - case EbtInt: mangledName += 'i'; break; - case EbtUint: mangledName += 'u'; break; - case EbtInt8: mangledName += "i8"; break; - case EbtUint8: mangledName += "u8"; break; - case EbtInt16: mangledName += "i16"; break; - case EbtUint16: mangledName += "u16"; break; - case EbtInt64: mangledName += "i64"; break; - case EbtUint64: mangledName += "u64"; break; - case EbtBool: mangledName += 'b'; break; - case EbtAtomicUint: mangledName += "au"; break; - case EbtSampler: - switch (sampler.type) { -#ifdef AMD_EXTENSIONS - case EbtFloat16: mangledName += "f16"; break; -#endif - case EbtInt: mangledName += "i"; break; - case EbtUint: mangledName += "u"; break; - default: break; // some compilers want this - } - if (sampler.image) - mangledName += "I"; // a normal image - else if (sampler.sampler) - mangledName += "p"; // a "pure" sampler - else if (!sampler.combined) - mangledName += "t"; // a "pure" texture - else - mangledName += "s"; // traditional combined sampler - if (sampler.arrayed) - mangledName += "A"; - if (sampler.shadow) - mangledName += "S"; - if (sampler.external) - mangledName += "E"; - switch (sampler.dim) { - case Esd1D: mangledName += "1"; break; - case Esd2D: mangledName += "2"; break; - case Esd3D: mangledName += "3"; break; - case EsdCube: mangledName += "C"; break; - case EsdRect: mangledName += "R2"; break; - case EsdBuffer: mangledName += "B"; break; - case EsdSubpass: mangledName += "P"; break; - default: break; // some compilers want this - } - - if (sampler.hasReturnStruct()) { - // Name mangle for sampler return struct uses struct table index. - mangledName += "-tx-struct"; - - char text[16]; // plenty enough space for the small integers. - snprintf(text, sizeof(text), "%d-", sampler.structReturnIndex); - mangledName += text; - } else { - switch (sampler.getVectorSize()) { - case 1: mangledName += "1"; break; - case 2: mangledName += "2"; break; - case 3: mangledName += "3"; break; - case 4: break; // default to prior name mangle behavior - } - } - - if (sampler.ms) - mangledName += "M"; - break; - case EbtStruct: - case EbtBlock: - if (basicType == EbtStruct) - mangledName += "struct-"; - else - mangledName += "block-"; - if (typeName) - mangledName += *typeName; - for (unsigned int i = 0; i < structure->size(); ++i) { - mangledName += '-'; - (*structure)[i].type->buildMangledName(mangledName); - } - default: - break; - } - - if (getVectorSize() > 0) - mangledName += static_cast('0' + getVectorSize()); - else { - mangledName += static_cast('0' + getMatrixCols()); - mangledName += static_cast('0' + getMatrixRows()); - } - - if (arraySizes) { - const int maxSize = 11; - char buf[maxSize]; - for (int i = 0; i < arraySizes->getNumDims(); ++i) { - if (arraySizes->getDimNode(i)) { - if (arraySizes->getDimNode(i)->getAsSymbolNode()) - snprintf(buf, maxSize, "s%d", arraySizes->getDimNode(i)->getAsSymbolNode()->getId()); - else - snprintf(buf, maxSize, "s%p", arraySizes->getDimNode(i)); - } else - snprintf(buf, maxSize, "%d", arraySizes->getDimSize(i)); - mangledName += '['; - mangledName += buf; - mangledName += ']'; - } - } -} - -// -// Dump functions. -// - -void TVariable::dump(TInfoSink& infoSink) const -{ - infoSink.debug << getName().c_str() << ": " << type.getStorageQualifierString() << " " << type.getBasicTypeString(); - if (type.isArray()) { - infoSink.debug << "[0]"; - } - infoSink.debug << "\n"; -} - -void TFunction::dump(TInfoSink& infoSink) const -{ - infoSink.debug << getName().c_str() << ": " << returnType.getBasicTypeString() << " " << getMangledName().c_str() << "\n"; -} - -void TAnonMember::dump(TInfoSink& TInfoSink) const -{ - TInfoSink.debug << "anonymous member " << getMemberNumber() << " of " << getAnonContainer().getName().c_str() << "\n"; -} - -void TSymbolTableLevel::dump(TInfoSink &infoSink) const -{ - tLevel::const_iterator it; - for (it = level.begin(); it != level.end(); ++it) - (*it).second->dump(infoSink); -} - -void TSymbolTable::dump(TInfoSink &infoSink) const -{ - for (int level = currentLevel(); level >= 0; --level) { - infoSink.debug << "LEVEL " << level << "\n"; - table[level]->dump(infoSink); - } -} - -// -// Functions have buried pointers to delete. -// -TFunction::~TFunction() -{ - for (TParamList::iterator i = parameters.begin(); i != parameters.end(); ++i) - delete (*i).type; -} - -// -// Symbol table levels are a map of pointers to symbols that have to be deleted. -// -TSymbolTableLevel::~TSymbolTableLevel() -{ - for (tLevel::iterator it = level.begin(); it != level.end(); ++it) - delete (*it).second; - - delete [] defaultPrecision; -} - -// -// Change all function entries in the table with the non-mangled name -// to be related to the provided built-in operation. -// -void TSymbolTableLevel::relateToOperator(const char* name, TOperator op) -{ - tLevel::const_iterator candidate = level.lower_bound(name); - while (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) { - TFunction* function = (*candidate).second->getAsFunction(); - function->relateToOperator(op); - } else - break; - ++candidate; - } -} - -// Make all function overloads of the given name require an extension(s). -// Should only be used for a version/profile that actually needs the extension(s). -void TSymbolTableLevel::setFunctionExtensions(const char* name, int num, const char* const extensions[]) -{ - tLevel::const_iterator candidate = level.lower_bound(name); - while (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) { - TSymbol* symbol = candidate->second; - symbol->setExtensions(num, extensions); - } else - break; - ++candidate; - } -} - -// -// Make all symbols in this table level read only. -// -void TSymbolTableLevel::readOnly() -{ - for (tLevel::iterator it = level.begin(); it != level.end(); ++it) - (*it).second->makeReadOnly(); -} - -// -// Copy a symbol, but the copy is writable; call readOnly() afterward if that's not desired. -// -TSymbol::TSymbol(const TSymbol& copyOf) -{ - name = NewPoolTString(copyOf.name->c_str()); - uniqueId = copyOf.uniqueId; - writable = true; -} - -TVariable::TVariable(const TVariable& copyOf) : TSymbol(copyOf) -{ - type.deepCopy(copyOf.type); - userType = copyOf.userType; - numExtensions = 0; - extensions = 0; - if (copyOf.numExtensions != 0) - setExtensions(copyOf.numExtensions, copyOf.extensions); - - if (! copyOf.constArray.empty()) { - assert(! copyOf.type.isStruct()); - TConstUnionArray newArray(copyOf.constArray, 0, copyOf.constArray.size()); - constArray = newArray; - } - - // don't support specialization-constant subtrees in cloned tables - constSubtree = nullptr; -} - -TVariable* TVariable::clone() const -{ - TVariable *variable = new TVariable(*this); - - return variable; -} - -TFunction::TFunction(const TFunction& copyOf) : TSymbol(copyOf) -{ - for (unsigned int i = 0; i < copyOf.parameters.size(); ++i) { - TParameter param; - parameters.push_back(param); - parameters.back().copyParam(copyOf.parameters[i]); - } - - numExtensions = 0; - extensions = 0; - if (copyOf.extensions != 0) - setExtensions(copyOf.numExtensions, copyOf.extensions); - returnType.deepCopy(copyOf.returnType); - mangledName = copyOf.mangledName; - op = copyOf.op; - defined = copyOf.defined; - prototyped = copyOf.prototyped; - implicitThis = copyOf.implicitThis; - illegalImplicitThis = copyOf.illegalImplicitThis; - defaultParamCount = copyOf.defaultParamCount; -} - -TFunction* TFunction::clone() const -{ - TFunction *function = new TFunction(*this); - - return function; -} - -TAnonMember* TAnonMember::clone() const -{ - // Anonymous members of a given block should be cloned at a higher level, - // where they can all be assured to still end up pointing to a single - // copy of the original container. - assert(0); - - return 0; -} - -TSymbolTableLevel* TSymbolTableLevel::clone() const -{ - TSymbolTableLevel *symTableLevel = new TSymbolTableLevel(); - symTableLevel->anonId = anonId; - symTableLevel->thisLevel = thisLevel; - std::vector containerCopied(anonId, false); - tLevel::const_iterator iter; - for (iter = level.begin(); iter != level.end(); ++iter) { - const TAnonMember* anon = iter->second->getAsAnonMember(); - if (anon) { - // Insert all the anonymous members of this same container at once, - // avoid inserting the other members in the future, once this has been done, - // allowing them to all be part of the same new container. - if (! containerCopied[anon->getAnonId()]) { - TVariable* container = anon->getAnonContainer().clone(); - container->changeName(NewPoolTString("")); - // insert the whole container - symTableLevel->insert(*container, false); - containerCopied[anon->getAnonId()] = true; - } - } else - symTableLevel->insert(*iter->second->clone(), false); - } - - return symTableLevel; -} - -void TSymbolTable::copyTable(const TSymbolTable& copyOf) -{ - assert(adoptedLevels == copyOf.adoptedLevels); - - uniqueId = copyOf.uniqueId; - noBuiltInRedeclarations = copyOf.noBuiltInRedeclarations; - separateNameSpaces = copyOf.separateNameSpaces; - for (unsigned int i = copyOf.adoptedLevels; i < copyOf.table.size(); ++i) - table.push_back(copyOf.table[i]->clone()); -} - -} // end namespace glslang diff --git a/External/glslang/glslang/MachineIndependent/SymbolTable.h b/External/glslang/glslang/MachineIndependent/SymbolTable.h deleted file mode 100644 index f928b7ae..00000000 --- a/External/glslang/glslang/MachineIndependent/SymbolTable.h +++ /dev/null @@ -1,825 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// Copyright (C) 2013 LunarG, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -#ifndef _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; - -class TSymbol { -public: - POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator()) - explicit TSymbol(const TString *n) : name(n), numExtensions(0), 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 num, const char* const exts[]) - { - assert(extensions == 0); - assert(num > 0); - numExtensions = num; - extensions = NewPoolObject(exts[0], num); - for (int e = 0; e < num; ++e) - extensions[e] = exts[e]; - } - virtual int getNumExtensions() const { return numExtensions; } - virtual const char** getExtensions() const { return extensions; } - virtual void dump(TInfoSink &infoSink) const = 0; - - 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). - int numExtensions; - const char** 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), - 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 dump(TInfoSink &infoSink) const; - -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 - - // TODO: these two should be a union - // A variable could be a compile-time constant, or a specialization - // constant, or neither, but never both. - TConstUnionArray constArray; // for compile-time constant value - TIntermTyped* constSubtree; // for specialization constant computation - 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]; } - - virtual void dump(TInfoSink &infoSink) const override; - -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, const TVariable& a, int an) : TSymbol(n), anonContainer(a), memberNumber(m), anonId(an) { } - virtual TAnonMember* clone() const; - virtual ~TAnonMember() { } - - virtual const TAnonMember* getAsAnonMember() const { return this; } - virtual const TVariable& getAnonContainer() const { return anonContainer; } - virtual unsigned int getMemberNumber() const { return memberNumber; } - - virtual const TType& getType() const - { - const TTypeList& types = *anonContainer.getType().getStruct(); - return *types[memberNumber].type; - } - - virtual TType& getWritableType() - { - assert(writable); - const TTypeList& types = *anonContainer.getType().getStruct(); - return *types[memberNumber].type; - } - - virtual int getAnonId() const { return anonId; } - virtual void dump(TInfoSink &infoSink) const; - -protected: - explicit TAnonMember(const TAnonMember&); - TAnonMember& operator=(const TAnonMember&); - - const 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[]); - void dump(TInfoSink &infoSink) const; - 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 num, const char* const extensions[]) - { - TSymbol* symbol = find(TString(name)); - if (symbol) - symbol->setExtensions(num, extensions); - } - - int getMaxSymbolId() { return uniqueId; } - void dump(TInfoSink &infoSink) const; - 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/External/glslang/glslang/MachineIndependent/Versions.cpp b/External/glslang/glslang/MachineIndependent/Versions.cpp deleted file mode 100644 index 51b64308..00000000 --- a/External/glslang/glslang/MachineIndependent/Versions.cpp +++ /dev/null @@ -1,964 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// Copyright (C) 2012-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. -// - -// -// Help manage multiple profiles, versions, extensions etc. -// -// These don't return error codes, as the presumption is parsing will -// always continue as if the tested feature were enabled, and thus there -// is no error recovery needed. -// - -// -// HOW TO add a feature enabled by an extension. -// -// To add a new hypothetical "Feature F" to the front end, where an extension -// "XXX_extension_X" can be used to enable the feature, do the following. -// -// OVERVIEW: Specific features are what are error-checked for, not -// extensions: A specific Feature F might be enabled by an extension, or a -// particular version in a particular profile, or a stage, or combinations, etc. -// -// The basic mechanism is to use the following to "declare" all the things that -// enable/disable Feature F, in a code path that implements Feature F: -// -// requireProfile() -// profileRequires() -// requireStage() -// checkDeprecated() -// requireNotRemoved() -// requireExtensions() -// -// Typically, only the first two calls are needed. They go into a code path that -// implements Feature F, and will log the proper error/warning messages. Parsing -// will then always continue as if the tested feature was enabled. -// -// There is typically no if-testing or conditional parsing, just insertion of the calls above. -// However, if symbols specific to the extension are added (step 5), they will -// only be added under tests that the minimum version and profile are present. -// -// 1) Add a symbol name for the extension string at the bottom of Versions.h: -// -// const char* const XXX_extension_X = "XXX_extension_X"; -// -// 2) Add extension initialization to TParseVersions::initializeExtensionBehavior(), -// the first function below: -// -// extensionBehavior[XXX_extension_X] = EBhDisable; -// -// 3) Add any preprocessor directives etc. in the next function, TParseVersions::getPreamble(): -// -// "#define XXX_extension_X 1\n" -// -// The new-line is important, as that ends preprocess tokens. -// -// 4) Insert a profile check in the feature's path (unless all profiles support the feature, -// for some version level). That is, call requireProfile() to constrain the profiles, e.g.: -// -// // ... in a path specific to Feature F... -// requireProfile(loc, -// ECoreProfile | ECompatibilityProfile, -// "Feature F"); -// -// 5) For each profile that supports the feature, insert version/extension checks: -// -// The mostly likely scenario is that Feature F can only be used with a -// particular profile if XXX_extension_X is present or the version is -// high enough that the core specification already incorporated it. -// -// // following the requireProfile() call... -// profileRequires(loc, -// ECoreProfile | ECompatibilityProfile, -// 420, // 0 if no version incorporated the feature into the core spec. -// XXX_extension_X, // can be a list of extensions that all add the feature -// "Feature F Description"); -// -// This allows the feature if either A) one of the extensions is enabled or -// B) the version is high enough. If no version yet incorporates the feature -// into core, pass in 0. -// -// This can be called multiple times, if different profiles support the -// feature starting at different version numbers or with different -// extensions. -// -// This must be called for each profile allowed by the initial call to requireProfile(). -// -// Profiles are all masks, which can be "or"-ed together. -// -// ENoProfile -// ECoreProfile -// ECompatibilityProfile -// EEsProfile -// -// The ENoProfile profile is only for desktop, before profiles showed up in version 150; -// All other #version with no profile default to either es or core, and so have profiles. -// -// You can select all but a particular profile using ~. The following basically means "desktop": -// -// ~EEsProfile -// -// 6) If built-in symbols are added by the extension, add them in Initialize.cpp: Their use -// will be automatically error checked against the extensions enabled at that moment. -// see the comment at the top of Initialize.cpp for where to put them. Establish them at -// the earliest release that supports the extension. Then, tag them with the -// set of extensions that both enable them and are necessary, given the version of the symbol -// table. (There is a different symbol table for each version.) -// - -#include "parseVersions.h" -#include "localintermediate.h" - -namespace glslang { - -// -// Initialize all extensions, almost always to 'disable', as once their features -// are incorporated into a core version, their features are supported through allowing that -// core version, not through a pseudo-enablement of the extension. -// -void TParseVersions::initializeExtensionBehavior() -{ - extensionBehavior[E_GL_OES_texture_3D] = EBhDisable; - extensionBehavior[E_GL_OES_standard_derivatives] = EBhDisable; - extensionBehavior[E_GL_EXT_frag_depth] = EBhDisable; - extensionBehavior[E_GL_OES_EGL_image_external] = EBhDisable; - extensionBehavior[E_GL_OES_EGL_image_external_essl3] = EBhDisable; - extensionBehavior[E_GL_EXT_shader_texture_lod] = EBhDisable; - extensionBehavior[E_GL_EXT_shadow_samplers] = EBhDisable; - extensionBehavior[E_GL_ARB_texture_rectangle] = EBhDisable; - extensionBehavior[E_GL_3DL_array_objects] = EBhDisable; - extensionBehavior[E_GL_ARB_shading_language_420pack] = EBhDisable; - extensionBehavior[E_GL_ARB_texture_gather] = EBhDisable; - extensionBehavior[E_GL_ARB_gpu_shader5] = EBhDisablePartial; - extensionBehavior[E_GL_ARB_separate_shader_objects] = EBhDisable; - extensionBehavior[E_GL_ARB_compute_shader] = EBhDisable; - extensionBehavior[E_GL_ARB_tessellation_shader] = EBhDisable; - extensionBehavior[E_GL_ARB_enhanced_layouts] = EBhDisable; - extensionBehavior[E_GL_ARB_texture_cube_map_array] = EBhDisable; - extensionBehavior[E_GL_ARB_shader_texture_lod] = EBhDisable; - extensionBehavior[E_GL_ARB_explicit_attrib_location] = EBhDisable; - extensionBehavior[E_GL_ARB_shader_image_load_store] = EBhDisable; - extensionBehavior[E_GL_ARB_shader_atomic_counters] = EBhDisable; - extensionBehavior[E_GL_ARB_shader_draw_parameters] = EBhDisable; - extensionBehavior[E_GL_ARB_shader_group_vote] = EBhDisable; - extensionBehavior[E_GL_ARB_derivative_control] = EBhDisable; - extensionBehavior[E_GL_ARB_shader_texture_image_samples] = EBhDisable; - extensionBehavior[E_GL_ARB_viewport_array] = EBhDisable; - extensionBehavior[E_GL_ARB_gpu_shader_int64] = EBhDisable; - extensionBehavior[E_GL_ARB_shader_ballot] = EBhDisable; - extensionBehavior[E_GL_ARB_sparse_texture2] = EBhDisable; - extensionBehavior[E_GL_ARB_sparse_texture_clamp] = EBhDisable; - extensionBehavior[E_GL_ARB_shader_stencil_export] = EBhDisable; -// extensionBehavior[E_GL_ARB_cull_distance] = EBhDisable; // present for 4.5, but need extension control over block members - extensionBehavior[E_GL_ARB_post_depth_coverage] = EBhDisable; - extensionBehavior[E_GL_ARB_shader_viewport_layer_array] = EBhDisable; - - extensionBehavior[E_GL_KHR_shader_subgroup_basic] = EBhDisable; - extensionBehavior[E_GL_KHR_shader_subgroup_vote] = EBhDisable; - extensionBehavior[E_GL_KHR_shader_subgroup_arithmetic] = EBhDisable; - extensionBehavior[E_GL_KHR_shader_subgroup_ballot] = EBhDisable; - extensionBehavior[E_GL_KHR_shader_subgroup_shuffle] = EBhDisable; - extensionBehavior[E_GL_KHR_shader_subgroup_shuffle_relative] = EBhDisable; - extensionBehavior[E_GL_KHR_shader_subgroup_clustered] = EBhDisable; - extensionBehavior[E_GL_KHR_shader_subgroup_quad] = EBhDisable; - - extensionBehavior[E_GL_EXT_shader_non_constant_global_initializers] = EBhDisable; - extensionBehavior[E_GL_EXT_shader_image_load_formatted] = EBhDisable; - extensionBehavior[E_GL_EXT_post_depth_coverage] = EBhDisable; - extensionBehavior[E_GL_EXT_control_flow_attributes] = EBhDisable; - extensionBehavior[E_GL_EXT_nonuniform_qualifier] = EBhDisable; - - // #line and #include - extensionBehavior[E_GL_GOOGLE_cpp_style_line_directive] = EBhDisable; - extensionBehavior[E_GL_GOOGLE_include_directive] = EBhDisable; - -#ifdef AMD_EXTENSIONS - extensionBehavior[E_GL_AMD_shader_ballot] = EBhDisable; - extensionBehavior[E_GL_AMD_shader_trinary_minmax] = EBhDisable; - extensionBehavior[E_GL_AMD_shader_explicit_vertex_parameter] = EBhDisable; - extensionBehavior[E_GL_AMD_gcn_shader] = EBhDisable; - extensionBehavior[E_GL_AMD_gpu_shader_half_float] = EBhDisable; - extensionBehavior[E_GL_AMD_texture_gather_bias_lod] = EBhDisable; - extensionBehavior[E_GL_AMD_gpu_shader_int16] = EBhDisable; - extensionBehavior[E_GL_AMD_shader_image_load_store_lod] = EBhDisable; - extensionBehavior[E_GL_AMD_shader_fragment_mask] = EBhDisable; - extensionBehavior[E_GL_AMD_gpu_shader_half_float_fetch] = EBhDisable; -#endif - -#ifdef NV_EXTENSIONS - extensionBehavior[E_GL_NV_sample_mask_override_coverage] = EBhDisable; - extensionBehavior[E_SPV_NV_geometry_shader_passthrough] = EBhDisable; - extensionBehavior[E_GL_NV_viewport_array2] = EBhDisable; - extensionBehavior[E_GL_NV_stereo_view_rendering] = EBhDisable; - extensionBehavior[E_GL_NVX_multiview_per_view_attributes] = EBhDisable; - extensionBehavior[E_GL_NV_shader_atomic_int64] = EBhDisable; - extensionBehavior[E_GL_NV_conservative_raster_underestimation] = EBhDisable; - extensionBehavior[E_GL_NV_shader_noperspective_interpolation] = EBhDisable; - extensionBehavior[E_GL_NV_shader_subgroup_partitioned] = EBhDisable; -#endif - - // AEP - extensionBehavior[E_GL_ANDROID_extension_pack_es31a] = EBhDisable; - extensionBehavior[E_GL_KHR_blend_equation_advanced] = EBhDisable; - extensionBehavior[E_GL_OES_sample_variables] = EBhDisable; - extensionBehavior[E_GL_OES_shader_image_atomic] = EBhDisable; - extensionBehavior[E_GL_OES_shader_multisample_interpolation] = EBhDisable; - extensionBehavior[E_GL_OES_texture_storage_multisample_2d_array] = EBhDisable; - extensionBehavior[E_GL_EXT_geometry_shader] = EBhDisable; - extensionBehavior[E_GL_EXT_geometry_point_size] = EBhDisable; - extensionBehavior[E_GL_EXT_gpu_shader5] = EBhDisable; - extensionBehavior[E_GL_EXT_primitive_bounding_box] = EBhDisable; - extensionBehavior[E_GL_EXT_shader_io_blocks] = EBhDisable; - extensionBehavior[E_GL_EXT_tessellation_shader] = EBhDisable; - extensionBehavior[E_GL_EXT_tessellation_point_size] = EBhDisable; - extensionBehavior[E_GL_EXT_texture_buffer] = EBhDisable; - extensionBehavior[E_GL_EXT_texture_cube_map_array] = EBhDisable; - - // OES matching AEP - extensionBehavior[E_GL_OES_geometry_shader] = EBhDisable; - extensionBehavior[E_GL_OES_geometry_point_size] = EBhDisable; - extensionBehavior[E_GL_OES_gpu_shader5] = EBhDisable; - extensionBehavior[E_GL_OES_primitive_bounding_box] = EBhDisable; - extensionBehavior[E_GL_OES_shader_io_blocks] = EBhDisable; - extensionBehavior[E_GL_OES_tessellation_shader] = EBhDisable; - extensionBehavior[E_GL_OES_tessellation_point_size] = EBhDisable; - extensionBehavior[E_GL_OES_texture_buffer] = EBhDisable; - extensionBehavior[E_GL_OES_texture_cube_map_array] = EBhDisable; - - // EXT extensions - extensionBehavior[E_GL_EXT_device_group] = EBhDisable; - extensionBehavior[E_GL_EXT_multiview] = EBhDisable; - - // OVR extensions - extensionBehavior[E_GL_OVR_multiview] = EBhDisable; - extensionBehavior[E_GL_OVR_multiview2] = EBhDisable; - - // explicit types - extensionBehavior[E_GL_KHX_shader_explicit_arithmetic_types] = EBhDisable; - extensionBehavior[E_GL_KHX_shader_explicit_arithmetic_types_int8] = EBhDisable; - extensionBehavior[E_GL_KHX_shader_explicit_arithmetic_types_int16] = EBhDisable; - extensionBehavior[E_GL_KHX_shader_explicit_arithmetic_types_int32] = EBhDisable; - extensionBehavior[E_GL_KHX_shader_explicit_arithmetic_types_int64] = EBhDisable; - extensionBehavior[E_GL_KHX_shader_explicit_arithmetic_types_float16] = EBhDisable; - extensionBehavior[E_GL_KHX_shader_explicit_arithmetic_types_float32] = EBhDisable; - extensionBehavior[E_GL_KHX_shader_explicit_arithmetic_types_float64] = EBhDisable; -} - -// Get code that is not part of a shared symbol table, is specific to this shader, -// or needed by the preprocessor (which does not use a shared symbol table). -void TParseVersions::getPreamble(std::string& preamble) -{ - if (profile == EEsProfile) { - preamble = - "#define GL_ES 1\n" - "#define GL_FRAGMENT_PRECISION_HIGH 1\n" - "#define GL_OES_texture_3D 1\n" - "#define GL_OES_standard_derivatives 1\n" - "#define GL_EXT_frag_depth 1\n" - "#define GL_OES_EGL_image_external 1\n" - "#define GL_OES_EGL_image_external_essl3 1\n" - "#define GL_EXT_shader_texture_lod 1\n" - "#define GL_EXT_shadow_samplers 1\n" - - // AEP - "#define GL_ANDROID_extension_pack_es31a 1\n" - "#define GL_KHR_blend_equation_advanced 1\n" - "#define GL_OES_sample_variables 1\n" - "#define GL_OES_shader_image_atomic 1\n" - "#define GL_OES_shader_multisample_interpolation 1\n" - "#define GL_OES_texture_storage_multisample_2d_array 1\n" - "#define GL_EXT_geometry_shader 1\n" - "#define GL_EXT_geometry_point_size 1\n" - "#define GL_EXT_gpu_shader5 1\n" - "#define GL_EXT_primitive_bounding_box 1\n" - "#define GL_EXT_shader_io_blocks 1\n" - "#define GL_EXT_tessellation_shader 1\n" - "#define GL_EXT_tessellation_point_size 1\n" - "#define GL_EXT_texture_buffer 1\n" - "#define GL_EXT_texture_cube_map_array 1\n" - - // OES matching AEP - "#define GL_OES_geometry_shader 1\n" - "#define GL_OES_geometry_point_size 1\n" - "#define GL_OES_gpu_shader5 1\n" - "#define GL_OES_primitive_bounding_box 1\n" - "#define GL_OES_shader_io_blocks 1\n" - "#define GL_OES_tessellation_shader 1\n" - "#define GL_OES_tessellation_point_size 1\n" - "#define GL_OES_texture_buffer 1\n" - "#define GL_OES_texture_cube_map_array 1\n" - "#define GL_EXT_shader_non_constant_global_initializers 1\n" - ; - -#ifdef NV_EXTENSIONS - if (profile == EEsProfile && version >= 300) { - preamble += "#define GL_NV_shader_noperspective_interpolation 1\n"; - } -#endif - - } else { - preamble = - "#define GL_FRAGMENT_PRECISION_HIGH 1\n" - "#define GL_ARB_texture_rectangle 1\n" - "#define GL_ARB_shading_language_420pack 1\n" - "#define GL_ARB_texture_gather 1\n" - "#define GL_ARB_gpu_shader5 1\n" - "#define GL_ARB_separate_shader_objects 1\n" - "#define GL_ARB_compute_shader 1\n" - "#define GL_ARB_tessellation_shader 1\n" - "#define GL_ARB_enhanced_layouts 1\n" - "#define GL_ARB_texture_cube_map_array 1\n" - "#define GL_ARB_shader_texture_lod 1\n" - "#define GL_ARB_explicit_attrib_location 1\n" - "#define GL_ARB_shader_image_load_store 1\n" - "#define GL_ARB_shader_atomic_counters 1\n" - "#define GL_ARB_shader_draw_parameters 1\n" - "#define GL_ARB_shader_group_vote 1\n" - "#define GL_ARB_derivative_control 1\n" - "#define GL_ARB_shader_texture_image_samples 1\n" - "#define GL_ARB_viewport_array 1\n" - "#define GL_ARB_gpu_shader_int64 1\n" - "#define GL_ARB_shader_ballot 1\n" - "#define GL_ARB_sparse_texture2 1\n" - "#define GL_ARB_sparse_texture_clamp 1\n" - "#define GL_ARB_shader_stencil_export 1\n" -// "#define GL_ARB_cull_distance 1\n" // present for 4.5, but need extension control over block members - "#define GL_ARB_post_depth_coverage 1\n" - "#define GL_EXT_shader_non_constant_global_initializers 1\n" - "#define GL_EXT_shader_image_load_formatted 1\n" - "#define GL_EXT_post_depth_coverage 1\n" - "#define GL_EXT_control_flow_attributes 1\n" - "#define GL_EXT_nonuniform_qualifier 1\n" - - // GL_KHR_shader_subgroup - "#define GL_KHR_shader_subgroup_basic 1\n" - "#define GL_KHR_shader_subgroup_vote 1\n" - "#define GL_KHR_shader_subgroup_arithmetic 1\n" - "#define GL_KHR_shader_subgroup_ballot 1\n" - "#define GL_KHR_shader_subgroup_shuffle 1\n" - "#define GL_KHR_shader_subgroup_shuffle_relative 1\n" - "#define GL_KHR_shader_subgroup_clustered 1\n" - "#define GL_KHR_shader_subgroup_quad 1\n" - -#ifdef AMD_EXTENSIONS - "#define GL_AMD_shader_ballot 1\n" - "#define GL_AMD_shader_trinary_minmax 1\n" - "#define GL_AMD_shader_explicit_vertex_parameter 1\n" - "#define GL_AMD_gcn_shader 1\n" - "#define GL_AMD_gpu_shader_half_float 1\n" - "#define GL_AMD_texture_gather_bias_lod 1\n" - "#define GL_AMD_gpu_shader_int16 1\n" - "#define GL_AMD_shader_image_load_store_lod 1\n" - "#define GL_AMD_shader_fragment_mask 1\n" - "#define GL_AMD_gpu_shader_half_float_fetch 1\n" -#endif - -#ifdef NV_EXTENSIONS - "#define GL_NV_sample_mask_override_coverage 1\n" - "#define GL_NV_geometry_shader_passthrough 1\n" - "#define GL_NV_viewport_array2 1\n" - "#define GL_NV_shader_atomic_int64 1\n" - "#define GL_NV_conservative_raster_underestimation 1\n" - "#define GL_NV_shader_subgroup_partitioned 1\n" -#endif - "#define GL_KHX_shader_explicit_arithmetic_types 1\n" - "#define GL_KHX_shader_explicit_arithmetic_types_int8 1\n" - "#define GL_KHX_shader_explicit_arithmetic_types_int16 1\n" - "#define GL_KHX_shader_explicit_arithmetic_types_int32 1\n" - "#define GL_KHX_shader_explicit_arithmetic_types_int64 1\n" - "#define GL_KHX_shader_explicit_arithmetic_types_float16 1\n" - "#define GL_KHX_shader_explicit_arithmetic_types_float32 1\n" - "#define GL_KHX_shader_explicit_arithmetic_types_float64 1\n" - ; - - if (version >= 150) { - // define GL_core_profile and GL_compatibility_profile - preamble += "#define GL_core_profile 1\n"; - - if (profile == ECompatibilityProfile) - preamble += "#define GL_compatibility_profile 1\n"; - } - } - - if ((profile != EEsProfile && version >= 140) || - (profile == EEsProfile && version >= 310)) { - preamble += - "#define GL_EXT_device_group 1\n" - "#define GL_EXT_multiview 1\n" - ; - } - - if (version >= 300 /* both ES and non-ES */) { - preamble += - "#define GL_OVR_multiview 1\n" - "#define GL_OVR_multiview2 1\n" - ; - } - - // #line and #include - preamble += - "#define GL_GOOGLE_cpp_style_line_directive 1\n" - "#define GL_GOOGLE_include_directive 1\n" - ; - - // #define VULKAN XXXX - const int numberBufSize = 12; - char numberBuf[numberBufSize]; - if (spvVersion.vulkanGlsl > 0) { - preamble += "#define VULKAN "; - snprintf(numberBuf, numberBufSize, "%d", spvVersion.vulkanGlsl); - preamble += numberBuf; - preamble += "\n"; - } - // #define GL_SPIRV XXXX - if (spvVersion.openGl > 0) { - preamble += "#define GL_SPIRV "; - snprintf(numberBuf, numberBufSize, "%d", spvVersion.openGl); - preamble += numberBuf; - preamble += "\n"; - } - -} - -// -// When to use requireProfile(): -// -// Use if only some profiles support a feature. However, if within a profile the feature -// is version or extension specific, follow this call with calls to profileRequires(). -// -// Operation: If the current profile is not one of the profileMask, -// give an error message. -// -void TParseVersions::requireProfile(const TSourceLoc& loc, int profileMask, const char* featureDesc) -{ - if (! (profile & profileMask)) - error(loc, "not supported with this profile:", featureDesc, ProfileName(profile)); -} - -// -// Map from stage enum to externally readable text name. -// -const char* StageName(EShLanguage stage) -{ - switch(stage) { - case EShLangVertex: return "vertex"; - case EShLangTessControl: return "tessellation control"; - case EShLangTessEvaluation: return "tessellation evaluation"; - case EShLangGeometry: return "geometry"; - case EShLangFragment: return "fragment"; - case EShLangCompute: return "compute"; - default: return "unknown stage"; - } -} - -// -// When to use profileRequires(): -// -// If a set of profiles have the same requirements for what version or extensions -// are needed to support a feature. -// -// It must be called for each profile that needs protection. Use requireProfile() first -// to reduce that set of profiles. -// -// Operation: Will issue warnings/errors based on the current profile, version, and extension -// behaviors. It only checks extensions when the current profile is one of the profileMask. -// -// A minVersion of 0 means no version of the profileMask support this in core, -// the extension must be present. -// - -// entry point that takes multiple extensions -void TParseVersions::profileRequires(const TSourceLoc& loc, int profileMask, int minVersion, int numExtensions, const char* const extensions[], const char* featureDesc) -{ - if (profile & profileMask) { - bool okay = false; - if (minVersion > 0 && version >= minVersion) - okay = true; - for (int i = 0; i < numExtensions; ++i) { - switch (getExtensionBehavior(extensions[i])) { - case EBhWarn: - infoSink.info.message(EPrefixWarning, ("extension " + TString(extensions[i]) + " is being used for " + featureDesc).c_str(), loc); - // fall through - case EBhRequire: - case EBhEnable: - okay = true; - break; - default: break; // some compilers want this - } - } - - if (! okay) - error(loc, "not supported for this version or the enabled extensions", featureDesc, ""); - } -} - -// entry point for the above that takes a single extension -void TParseVersions::profileRequires(const TSourceLoc& loc, int profileMask, int minVersion, const char* extension, const char* featureDesc) -{ - profileRequires(loc, profileMask, minVersion, extension ? 1 : 0, &extension, featureDesc); -} - -// -// When to use requireStage() -// -// If only some stages support a feature. -// -// Operation: If the current stage is not present, give an error message. -// -void TParseVersions::requireStage(const TSourceLoc& loc, EShLanguageMask languageMask, const char* featureDesc) -{ - if (((1 << language) & languageMask) == 0) - error(loc, "not supported in this stage:", featureDesc, StageName(language)); -} - -// If only one stage supports a feature, this can be called. But, all supporting stages -// must be specified with one call. -void TParseVersions::requireStage(const TSourceLoc& loc, EShLanguage stage, const char* featureDesc) -{ - requireStage(loc, static_cast(1 << stage), featureDesc); -} - -// -// Within a set of profiles, see if a feature is deprecated and give an error or warning based on whether -// a future compatibility context is being use. -// -void TParseVersions::checkDeprecated(const TSourceLoc& loc, int profileMask, int depVersion, const char* featureDesc) -{ - if (profile & profileMask) { - if (version >= depVersion) { - if (forwardCompatible) - error(loc, "deprecated, may be removed in future release", featureDesc, ""); - else if (! suppressWarnings()) - infoSink.info.message(EPrefixWarning, (TString(featureDesc) + " deprecated in version " + - String(depVersion) + "; may be removed in future release").c_str(), loc); - } - } -} - -// -// Within a set of profiles, see if a feature has now been removed and if so, give an error. -// The version argument is the first version no longer having the feature. -// -void TParseVersions::requireNotRemoved(const TSourceLoc& loc, int profileMask, int removedVersion, const char* featureDesc) -{ - if (profile & profileMask) { - if (version >= removedVersion) { - const int maxSize = 60; - char buf[maxSize]; - snprintf(buf, maxSize, "%s profile; removed in version %d", ProfileName(profile), removedVersion); - error(loc, "no longer supported in", featureDesc, buf); - } - } -} - -void TParseVersions::unimplemented(const TSourceLoc& loc, const char* featureDesc) -{ - error(loc, "feature not yet implemented", featureDesc, ""); -} - -// Returns true if at least one of the extensions in the extensions parameter is requested. Otherwise, returns false. -// Warns appropriately if the requested behavior of an extension is "warn". -bool TParseVersions::checkExtensionsRequested(const TSourceLoc& loc, int numExtensions, const char* const extensions[], const char* featureDesc) -{ - // First, see if any of the extensions are enabled - for (int i = 0; i < numExtensions; ++i) { - TExtensionBehavior behavior = getExtensionBehavior(extensions[i]); - if (behavior == EBhEnable || behavior == EBhRequire) - return true; - } - - // See if any extensions want to give a warning on use; give warnings for all such extensions - bool warned = false; - for (int i = 0; i < numExtensions; ++i) { - TExtensionBehavior behavior = getExtensionBehavior(extensions[i]); - if (behavior == EBhDisable && relaxedErrors()) { - infoSink.info.message(EPrefixWarning, "The following extension must be enabled to use this feature:", loc); - behavior = EBhWarn; - } - if (behavior == EBhWarn) { - infoSink.info.message(EPrefixWarning, ("extension " + TString(extensions[i]) + " is being used for " + featureDesc).c_str(), loc); - warned = true; - } - } - if (warned) - return true; - return false; -} - -// -// Use when there are no profile/version to check, it's just an error if one of the -// extensions is not present. -// -void TParseVersions::requireExtensions(const TSourceLoc& loc, int numExtensions, const char* const extensions[], const char* featureDesc) -{ - if (checkExtensionsRequested(loc, numExtensions, extensions, featureDesc)) - return; - - // If we get this far, give errors explaining what extensions are needed - if (numExtensions == 1) - error(loc, "required extension not requested:", featureDesc, extensions[0]); - else { - error(loc, "required extension not requested:", featureDesc, "Possible extensions include:"); - for (int i = 0; i < numExtensions; ++i) - infoSink.info.message(EPrefixNone, extensions[i]); - } -} - -// -// Use by preprocessor when there are no profile/version to check, it's just an error if one of the -// extensions is not present. -// -void TParseVersions::ppRequireExtensions(const TSourceLoc& loc, int numExtensions, const char* const extensions[], const char* featureDesc) -{ - if (checkExtensionsRequested(loc, numExtensions, extensions, featureDesc)) - return; - - // If we get this far, give errors explaining what extensions are needed - if (numExtensions == 1) - ppError(loc, "required extension not requested:", featureDesc, extensions[0]); - else { - ppError(loc, "required extension not requested:", featureDesc, "Possible extensions include:"); - for (int i = 0; i < numExtensions; ++i) - infoSink.info.message(EPrefixNone, extensions[i]); - } -} - -TExtensionBehavior TParseVersions::getExtensionBehavior(const char* extension) -{ - auto iter = extensionBehavior.find(TString(extension)); - if (iter == extensionBehavior.end()) - return EBhMissing; - else - return iter->second; -} - -// Returns true if the given extension is set to enable, require, or warn. -bool TParseVersions::extensionTurnedOn(const char* const extension) -{ - switch (getExtensionBehavior(extension)) { - case EBhEnable: - case EBhRequire: - case EBhWarn: - return true; - default: - break; - } - return false; -} -// See if any of the extensions are set to enable, require, or warn. -bool TParseVersions::extensionsTurnedOn(int numExtensions, const char* const extensions[]) -{ - for (int i = 0; i < numExtensions; ++i) { - if (extensionTurnedOn(extensions[i])) - return true; - } - return false; -} - -// -// Change the current state of an extension's behavior. -// -void TParseVersions::updateExtensionBehavior(int line, const char* extension, const char* behaviorString) -{ - // Translate from text string of extension's behavior to an enum. - TExtensionBehavior behavior = EBhDisable; - if (! strcmp("require", behaviorString)) - behavior = EBhRequire; - else if (! strcmp("enable", behaviorString)) - behavior = EBhEnable; - else if (! strcmp("disable", behaviorString)) - behavior = EBhDisable; - else if (! strcmp("warn", behaviorString)) - behavior = EBhWarn; - else { - error(getCurrentLoc(), "behavior not supported:", "#extension", behaviorString); - return; - } - - // update the requested extension - updateExtensionBehavior(extension, behavior); - - // see if need to propagate to implicitly modified things - if (strcmp(extension, "GL_ANDROID_extension_pack_es31a") == 0) { - // to everything in AEP - updateExtensionBehavior(line, "GL_KHR_blend_equation_advanced", behaviorString); - updateExtensionBehavior(line, "GL_OES_sample_variables", behaviorString); - updateExtensionBehavior(line, "GL_OES_shader_image_atomic", behaviorString); - updateExtensionBehavior(line, "GL_OES_shader_multisample_interpolation", behaviorString); - updateExtensionBehavior(line, "GL_OES_texture_storage_multisample_2d_array", behaviorString); - updateExtensionBehavior(line, "GL_EXT_geometry_shader", behaviorString); - updateExtensionBehavior(line, "GL_EXT_gpu_shader5", behaviorString); - updateExtensionBehavior(line, "GL_EXT_primitive_bounding_box", behaviorString); - updateExtensionBehavior(line, "GL_EXT_shader_io_blocks", behaviorString); - updateExtensionBehavior(line, "GL_EXT_tessellation_shader", behaviorString); - updateExtensionBehavior(line, "GL_EXT_texture_buffer", behaviorString); - updateExtensionBehavior(line, "GL_EXT_texture_cube_map_array", behaviorString); - } - // geometry to io_blocks - else if (strcmp(extension, "GL_EXT_geometry_shader") == 0) - updateExtensionBehavior(line, "GL_EXT_shader_io_blocks", behaviorString); - else if (strcmp(extension, "GL_OES_geometry_shader") == 0) - updateExtensionBehavior(line, "GL_OES_shader_io_blocks", behaviorString); - // tessellation to io_blocks - else if (strcmp(extension, "GL_EXT_tessellation_shader") == 0) - updateExtensionBehavior(line, "GL_EXT_shader_io_blocks", behaviorString); - else if (strcmp(extension, "GL_OES_tessellation_shader") == 0) - updateExtensionBehavior(line, "GL_OES_shader_io_blocks", behaviorString); - else if (strcmp(extension, "GL_GOOGLE_include_directive") == 0) - updateExtensionBehavior(line, "GL_GOOGLE_cpp_style_line_directive", behaviorString); - // subgroup_* to subgroup_basic - else if (strcmp(extension, "GL_KHR_shader_subgroup_vote") == 0) - updateExtensionBehavior(line, "GL_KHR_shader_subgroup_basic", behaviorString); - else if (strcmp(extension, "GL_KHR_shader_subgroup_arithmetic") == 0) - updateExtensionBehavior(line, "GL_KHR_shader_subgroup_basic", behaviorString); - else if (strcmp(extension, "GL_KHR_shader_subgroup_ballot") == 0) - updateExtensionBehavior(line, "GL_KHR_shader_subgroup_basic", behaviorString); - else if (strcmp(extension, "GL_KHR_shader_subgroup_shuffle") == 0) - updateExtensionBehavior(line, "GL_KHR_shader_subgroup_basic", behaviorString); - else if (strcmp(extension, "GL_KHR_shader_subgroup_shuffle_relative") == 0) - updateExtensionBehavior(line, "GL_KHR_shader_subgroup_basic", behaviorString); - else if (strcmp(extension, "GL_KHR_shader_subgroup_clustered") == 0) - updateExtensionBehavior(line, "GL_KHR_shader_subgroup_basic", behaviorString); - else if (strcmp(extension, "GL_KHR_shader_subgroup_quad") == 0) - updateExtensionBehavior(line, "GL_KHR_shader_subgroup_basic", behaviorString); -#ifdef NV_EXTENSIONS - else if (strcmp(extension, "GL_NV_shader_subgroup_partitioned") == 0) - updateExtensionBehavior(line, "GL_KHR_shader_subgroup_basic", behaviorString); -#endif -} - -void TParseVersions::updateExtensionBehavior(const char* extension, TExtensionBehavior behavior) -{ - // Update the current behavior - if (strcmp(extension, "all") == 0) { - // special case for the 'all' extension; apply it to every extension present - if (behavior == EBhRequire || behavior == EBhEnable) { - error(getCurrentLoc(), "extension 'all' cannot have 'require' or 'enable' behavior", "#extension", ""); - return; - } else { - for (auto iter = extensionBehavior.begin(); iter != extensionBehavior.end(); ++iter) - iter->second = behavior; - } - } else { - // Do the update for this single extension - auto iter = extensionBehavior.find(TString(extension)); - if (iter == extensionBehavior.end()) { - switch (behavior) { - case EBhRequire: - error(getCurrentLoc(), "extension not supported:", "#extension", extension); - break; - case EBhEnable: - case EBhWarn: - case EBhDisable: - warn(getCurrentLoc(), "extension not supported:", "#extension", extension); - break; - default: - assert(0 && "unexpected behavior"); - } - - return; - } else { - if (iter->second == EBhDisablePartial) - warn(getCurrentLoc(), "extension is only partially supported:", "#extension", extension); - if (behavior == EBhEnable || behavior == EBhRequire) - intermediate.addRequestedExtension(extension); - iter->second = behavior; - } - } -} - -// Call for any operation needing full GLSL integer data-type support. -void TParseVersions::fullIntegerCheck(const TSourceLoc& loc, const char* op) -{ - profileRequires(loc, ENoProfile, 130, nullptr, op); - profileRequires(loc, EEsProfile, 300, nullptr, op); -} - -// Call for any operation needing GLSL double data-type support. -void TParseVersions::doubleCheck(const TSourceLoc& loc, const char* op) -{ - requireProfile(loc, ECoreProfile | ECompatibilityProfile, op); - profileRequires(loc, ECoreProfile, 400, nullptr, op); - profileRequires(loc, ECompatibilityProfile, 400, nullptr, op); -} - -// Call for any operation needing GLSL float16 data-type support. -void TParseVersions::float16Check(const TSourceLoc& loc, const char* op, bool builtIn) -{ - if (!builtIn) { -#if AMD_EXTENSIONS - const char* const extensions[3] = {E_GL_AMD_gpu_shader_half_float, - E_GL_KHX_shader_explicit_arithmetic_types, - E_GL_KHX_shader_explicit_arithmetic_types_float16}; - -#else - const char* const extensions[2] = {E_GL_KHX_shader_explicit_arithmetic_types, - E_GL_KHX_shader_explicit_arithmetic_types_float16}; -#endif - requireExtensions(loc, sizeof(extensions)/sizeof(extensions[0]), extensions, "explicit types"); - requireProfile(loc, ECoreProfile | ECompatibilityProfile, op); - profileRequires(loc, ECoreProfile, 450, nullptr, op); - profileRequires(loc, ECompatibilityProfile, 450, nullptr, op); - } -} - -// Call for any operation needing GLSL float32 data-type support. -void TParseVersions::explicitFloat32Check(const TSourceLoc& loc, const char* op, bool builtIn) -{ - if (!builtIn) { - const char* const extensions[2] = {E_GL_KHX_shader_explicit_arithmetic_types, - E_GL_KHX_shader_explicit_arithmetic_types_float32}; - requireExtensions(loc, 2, extensions, "explicit types"); - requireProfile(loc, ECoreProfile | ECompatibilityProfile, op); - profileRequires(loc, ECoreProfile, 450, nullptr, op); - profileRequires(loc, ECompatibilityProfile, 450, nullptr, op); - } -} - -// Call for any operation needing GLSL float64 data-type support. -void TParseVersions::explicitFloat64Check(const TSourceLoc& loc, const char* op, bool builtIn) -{ - if (!builtIn) { - const char* const extensions[2] = {E_GL_KHX_shader_explicit_arithmetic_types, - E_GL_KHX_shader_explicit_arithmetic_types_float64}; - requireExtensions(loc, 2, extensions, "explicit types"); - requireProfile(loc, ECoreProfile | ECompatibilityProfile, op); - profileRequires(loc, ECoreProfile, 450, nullptr, op); - profileRequires(loc, ECompatibilityProfile, 450, nullptr, op); - } -} - -// Call for any operation needing GLSL explicit int8 data-type support. -void TParseVersions::explicitInt8Check(const TSourceLoc& loc, const char* op, bool builtIn) -{ - if (! builtIn) { - const char* const extensions[2] = {E_GL_KHX_shader_explicit_arithmetic_types, - E_GL_KHX_shader_explicit_arithmetic_types_int8}; - requireExtensions(loc, 2, extensions, "explicit types"); - requireProfile(loc, ECoreProfile | ECompatibilityProfile, op); - profileRequires(loc, ECoreProfile, 450, nullptr, op); - profileRequires(loc, ECompatibilityProfile, 450, nullptr, op); - } -} - -#ifdef AMD_EXTENSIONS -// Call for any operation needing GLSL float16 opaque-type support -void TParseVersions::float16OpaqueCheck(const TSourceLoc& loc, const char* op, bool builtIn) -{ - if (! builtIn) { - requireExtensions(loc, 1, &E_GL_AMD_gpu_shader_half_float_fetch, op); - requireProfile(loc, ECoreProfile | ECompatibilityProfile, op); - profileRequires(loc, ECoreProfile, 450, nullptr, op); - profileRequires(loc, ECompatibilityProfile, 450, nullptr, op); - } -} -#endif - -// Call for any operation needing GLSL explicit int16 data-type support. -void TParseVersions::explicitInt16Check(const TSourceLoc& loc, const char* op, bool builtIn) -{ - if (! builtIn) { -#if AMD_EXTENSIONS - const char* const extensions[3] = {E_GL_AMD_gpu_shader_int16, - E_GL_KHX_shader_explicit_arithmetic_types, - E_GL_KHX_shader_explicit_arithmetic_types_int16}; -#else - const char* const extensions[2] = {E_GL_KHX_shader_explicit_arithmetic_types, - E_GL_KHX_shader_explicit_arithmetic_types_int16}; -#endif - requireExtensions(loc, sizeof(extensions)/sizeof(extensions[0]), extensions, "explicit types"); - requireProfile(loc, ECoreProfile | ECompatibilityProfile, op); - profileRequires(loc, ECoreProfile, 450, nullptr, op); - profileRequires(loc, ECompatibilityProfile, 450, nullptr, op); - } -} - -// Call for any operation needing GLSL explicit int32 data-type support. -void TParseVersions::explicitInt32Check(const TSourceLoc& loc, const char* op, bool builtIn) -{ - if (! builtIn) { - const char* const extensions[2] = {E_GL_KHX_shader_explicit_arithmetic_types, - E_GL_KHX_shader_explicit_arithmetic_types_int32}; - requireExtensions(loc, 2, extensions, "explicit types"); - requireProfile(loc, ECoreProfile | ECompatibilityProfile, op); - profileRequires(loc, ECoreProfile, 450, nullptr, op); - profileRequires(loc, ECompatibilityProfile, 450, nullptr, op); - } -} - -// Call for any operation needing GLSL 64-bit integer data-type support. -void TParseVersions::int64Check(const TSourceLoc& loc, const char* op, bool builtIn) -{ - if (! builtIn) { - const char* const extensions[3] = {E_GL_ARB_gpu_shader_int64, - E_GL_KHX_shader_explicit_arithmetic_types, - E_GL_KHX_shader_explicit_arithmetic_types_int64}; - requireExtensions(loc, 3, extensions, "shader int64"); - requireProfile(loc, ECoreProfile | ECompatibilityProfile, op); - profileRequires(loc, ECoreProfile, 450, nullptr, op); - profileRequires(loc, ECompatibilityProfile, 450, nullptr, op); - } -} - -// Call for any operation removed because SPIR-V is in use. -void TParseVersions::spvRemoved(const TSourceLoc& loc, const char* op) -{ - if (spvVersion.spv != 0) - error(loc, "not allowed when generating SPIR-V", op, ""); -} - -// Call for any operation removed because Vulkan SPIR-V is being generated. -void TParseVersions::vulkanRemoved(const TSourceLoc& loc, const char* op) -{ - if (spvVersion.vulkan > 0) - error(loc, "not allowed when using GLSL for Vulkan", op, ""); -} - -// Call for any operation that requires Vulkan. -void TParseVersions::requireVulkan(const TSourceLoc& loc, const char* op) -{ - if (spvVersion.vulkan == 0) - error(loc, "only allowed when using GLSL for Vulkan", op, ""); -} - -// Call for any operation that requires SPIR-V. -void TParseVersions::requireSpv(const TSourceLoc& loc, const char* op) -{ - if (spvVersion.spv == 0) - error(loc, "only allowed when generating SPIR-V", op, ""); -} - -} // end namespace glslang diff --git a/External/glslang/glslang/MachineIndependent/Versions.h b/External/glslang/glslang/MachineIndependent/Versions.h deleted file mode 100644 index b297d27b..00000000 --- a/External/glslang/glslang/MachineIndependent/Versions.h +++ /dev/null @@ -1,278 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// Copyright (C) 2012-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 _VERSIONS_INCLUDED_ -#define _VERSIONS_INCLUDED_ - -// -// 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) -} 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 -// 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_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_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_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_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_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_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"; - -// 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"; - -// 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"; - -#ifdef AMD_EXTENSIONS -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"; -#endif - -#ifdef NV_EXTENSIONS - -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"; - -// 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]); -#endif - -// 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"; - -// KHX -const char* const E_GL_KHX_shader_explicit_arithmetic_types = "GL_KHX_shader_explicit_arithmetic_types"; -const char* const E_GL_KHX_shader_explicit_arithmetic_types_int8 = "GL_KHX_shader_explicit_arithmetic_types_int8"; -const char* const E_GL_KHX_shader_explicit_arithmetic_types_int16 = "GL_KHX_shader_explicit_arithmetic_types_int16"; -const char* const E_GL_KHX_shader_explicit_arithmetic_types_int32 = "GL_KHX_shader_explicit_arithmetic_types_int32"; -const char* const E_GL_KHX_shader_explicit_arithmetic_types_int64 = "GL_KHX_shader_explicit_arithmetic_types_int64"; -const char* const E_GL_KHX_shader_explicit_arithmetic_types_float16 = "GL_KHX_shader_explicit_arithmetic_types_float16"; -const char* const E_GL_KHX_shader_explicit_arithmetic_types_float32 = "GL_KHX_shader_explicit_arithmetic_types_float32"; -const char* const E_GL_KHX_shader_explicit_arithmetic_types_float64 = "GL_KHX_shader_explicit_arithmetic_types_float64"; - -// 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/External/glslang/glslang/MachineIndependent/attribute.cpp b/External/glslang/glslang/MachineIndependent/attribute.cpp deleted file mode 100644 index 73b665d8..00000000 --- a/External/glslang/glslang/MachineIndependent/attribute.cpp +++ /dev/null @@ -1,257 +0,0 @@ -// -// 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 Google, Inc., nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -#include "attribute.h" -#include "../Include/intermediate.h" -#include "ParseHelper.h" - -namespace glslang { - -// extract integers out of attribute arguments stored in attribute aggregate -bool TAttributeArgs::getInt(int& value, int argNum) const -{ - const TConstUnion* intConst = getConstUnion(EbtInt, argNum); - - if (intConst == nullptr) - return false; - - value = intConst->getIConst(); - return true; -} - -// extract strings out of attribute arguments stored in attribute aggregate. -// convert to lower case if converToLower is true (for case-insensitive compare convenience) -bool TAttributeArgs::getString(TString& value, int argNum, bool convertToLower) const -{ - const TConstUnion* stringConst = getConstUnion(EbtString, argNum); - - if (stringConst == nullptr) - return false; - - value = *stringConst->getSConst(); - - // Convenience. - if (convertToLower) - std::transform(value.begin(), value.end(), value.begin(), ::tolower); - - return true; -} - -// How many arguments were supplied? -int TAttributeArgs::size() const -{ - return args == nullptr ? 0 : (int)args->getSequence().size(); -} - -// Helper to get attribute const union. Returns nullptr on failure. -const TConstUnion* TAttributeArgs::getConstUnion(TBasicType basicType, int argNum) const -{ - if (args == nullptr) - return nullptr; - - if (argNum >= (int)args->getSequence().size()) - return nullptr; - - const TConstUnion* constVal = &args->getSequence()[argNum]->getAsConstantUnion()->getConstArray()[0]; - if (constVal == nullptr || constVal->getType() != basicType) - return nullptr; - - return constVal; -} - -// Implementation of TParseContext parts of attributes -TAttributeType TParseContext::attributeFromName(const TString& name) const -{ - if (name == "branch" || name == "dont_flatten") - return EatBranch; - else if (name == "flatten") - return EatFlatten; - else if (name == "unroll") - return EatUnroll; - else if (name == "loop" || name == "dont_unroll") - return EatLoop; - else if (name == "dependency_infinite") - return EatDependencyInfinite; - else if (name == "dependency_length") - return EatDependencyLength; - else - return EatNone; -} - -// Make an initial leaf for the grammar from a no-argument attribute -TAttributes* TParseContext::makeAttributes(const TString& identifier) const -{ - TAttributes *attributes = nullptr; - attributes = NewPoolObject(attributes); - TAttributeArgs args = { attributeFromName(identifier), nullptr }; - attributes->push_back(args); - return attributes; -} - -// Make an initial leaf for the grammar from a one-argument attribute -TAttributes* TParseContext::makeAttributes(const TString& identifier, TIntermNode* node) const -{ - TAttributes *attributes = nullptr; - attributes = NewPoolObject(attributes); - - // for now, node is always a simple single expression, but other code expects - // a list, so make it so - TIntermAggregate* agg = intermediate.makeAggregate(node); - TAttributeArgs args = { attributeFromName(identifier), agg }; - attributes->push_back(args); - return attributes; -} - -// Merge two sets of attributes into a single set. -// The second argument is destructively consumed. -TAttributes* TParseContext::mergeAttributes(TAttributes* attr1, TAttributes* attr2) const -{ - attr1->splice(attr1->end(), *attr2); - return attr1; -} - -// -// Selection attributes -// -void TParseContext::handleSelectionAttributes(const TAttributes& attributes, TIntermNode* node) -{ - TIntermSelection* selection = node->getAsSelectionNode(); - if (selection == nullptr) - return; - - for (auto it = attributes.begin(); it != attributes.end(); ++it) { - if (it->size() > 0) { - warn(node->getLoc(), "attribute with arguments not recognized, skipping", "", ""); - continue; - } - - switch (it->name) { - case EatFlatten: - selection->setFlatten(); - break; - case EatBranch: - selection->setDontFlatten(); - break; - default: - warn(node->getLoc(), "attribute does not apply to a selection", "", ""); - break; - } - } -} - -// -// Switch attributes -// -void TParseContext::handleSwitchAttributes(const TAttributes& attributes, TIntermNode* node) -{ - TIntermSwitch* selection = node->getAsSwitchNode(); - if (selection == nullptr) - return; - - for (auto it = attributes.begin(); it != attributes.end(); ++it) { - if (it->size() > 0) { - warn(node->getLoc(), "attribute with arguments not recognized, skipping", "", ""); - continue; - } - - switch (it->name) { - case EatFlatten: - selection->setFlatten(); - break; - case EatBranch: - selection->setDontFlatten(); - break; - default: - warn(node->getLoc(), "attribute does not apply to a switch", "", ""); - break; - } - } -} - -// -// Loop attributes -// -void TParseContext::handleLoopAttributes(const TAttributes& attributes, TIntermNode* node) -{ - TIntermLoop* loop = node->getAsLoopNode(); - if (loop == nullptr) { - // the actual loop might be part of a sequence - TIntermAggregate* agg = node->getAsAggregate(); - if (agg == nullptr) - return; - for (auto it = agg->getSequence().begin(); it != agg->getSequence().end(); ++it) { - loop = (*it)->getAsLoopNode(); - if (loop != nullptr) - break; - } - if (loop == nullptr) - return; - } - - for (auto it = attributes.begin(); it != attributes.end(); ++it) { - if (it->name != EatDependencyLength && it->size() > 0) { - warn(node->getLoc(), "attribute with arguments not recognized, skipping", "", ""); - continue; - } - - int value; - switch (it->name) { - case EatUnroll: - loop->setUnroll(); - break; - case EatLoop: - loop->setDontUnroll(); - break; - case EatDependencyInfinite: - loop->setLoopDependency(TIntermLoop::dependencyInfinite); - break; - case EatDependencyLength: - if (it->size() == 1 && it->getInt(value)) { - if (value <= 0) - error(node->getLoc(), "must be positive", "dependency_length", ""); - loop->setLoopDependency(value); - } else - warn(node->getLoc(), "expected a single integer argument", "dependency_length", ""); - break; - default: - warn(node->getLoc(), "attribute does not apply to a loop", "", ""); - break; - } - } -} - - -} // end namespace glslang diff --git a/External/glslang/glslang/MachineIndependent/attribute.h b/External/glslang/glslang/MachineIndependent/attribute.h deleted file mode 100644 index 8d0c5bca..00000000 --- a/External/glslang/glslang/MachineIndependent/attribute.h +++ /dev/null @@ -1,102 +0,0 @@ -// -// 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 - }; - - 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/External/glslang/glslang/MachineIndependent/gl_types.h b/External/glslang/glslang/MachineIndependent/gl_types.h deleted file mode 100644 index c9fee9ec..00000000 --- a/External/glslang/glslang/MachineIndependent/gl_types.h +++ /dev/null @@ -1,214 +0,0 @@ -/* -** 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 - -#ifdef AMD_EXTENSIONS -// 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 -#endif - -#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 - -#ifdef AMD_EXTENSIONS -#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 -#endif - -#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/External/glslang/glslang/MachineIndependent/glslang.y b/External/glslang/glslang/MachineIndependent/glslang.y deleted file mode 100644 index e65483a8..00000000 --- a/External/glslang/glslang/MachineIndependent/glslang.y +++ /dev/null @@ -1,3614 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// Copyright (C) 2012-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. -// - -/** - * This is bison grammar and productions for parsing all versions of the - * GLSL shading languages. - */ -%{ - -/* Based on: -ANSI C Yacc grammar - -In 1985, Jeff Lee published his Yacc grammar (which is accompanied by a -matching Lex specification) for the April 30, 1985 draft version of the -ANSI C standard. Tom Stockfisch reposted it to net.sources in 1987; that -original, as mentioned in the answer to question 17.25 of the comp.lang.c -FAQ, can be ftp'ed from ftp.uu.net, file usenet/net.sources/ansi.c.grammar.Z. - -I intend to keep this version as close to the current C Standard grammar as -possible; please let me know if you discover discrepancies. - -Jutta Degener, 1995 -*/ - -#include "SymbolTable.h" -#include "ParseHelper.h" -#include "../Public/ShaderLang.h" -#include "attribute.h" - -using namespace glslang; - -%} - -%define parse.error verbose - -%union { - 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; - }; - } interm; -} - -%{ - -/* windows only pragma */ -#ifdef _MSC_VER - #pragma warning(disable : 4065) - #pragma warning(disable : 4127) - #pragma warning(disable : 4244) -#endif - -#define parseContext (*pParseContext) -#define yyerror(context, msg) context->parserError(msg) - -extern int yylex(YYSTYPE*, TParseContext&); - -%} - -%parse-param {glslang::TParseContext* pParseContext} -%lex-param {parseContext} -%pure-parser // enable thread safety -%expect 1 // One shift reduce conflict because of if | else - -%token ATTRIBUTE VARYING -%token FLOAT16_T FLOAT FLOAT32_T DOUBLE FLOAT64_T -%token CONST BOOL INT UINT INT64_T UINT64_T INT32_T UINT32_T INT16_T UINT16_T INT8_T UINT8_T -%token BREAK CONTINUE DO ELSE FOR IF DISCARD RETURN SWITCH CASE DEFAULT SUBROUTINE -%token BVEC2 BVEC3 BVEC4 -%token IVEC2 IVEC3 IVEC4 -%token UVEC2 UVEC3 UVEC4 -%token I64VEC2 I64VEC3 I64VEC4 -%token U64VEC2 U64VEC3 U64VEC4 -%token I32VEC2 I32VEC3 I32VEC4 -%token U32VEC2 U32VEC3 U32VEC4 -%token I16VEC2 I16VEC3 I16VEC4 -%token U16VEC2 U16VEC3 U16VEC4 -%token I8VEC2 I8VEC3 I8VEC4 -%token U8VEC2 U8VEC3 U8VEC4 -%token VEC2 VEC3 VEC4 -%token MAT2 MAT3 MAT4 CENTROID IN OUT INOUT -%token UNIFORM PATCH SAMPLE BUFFER SHARED NONUNIFORM -%token COHERENT VOLATILE RESTRICT READONLY WRITEONLY -%token DVEC2 DVEC3 DVEC4 DMAT2 DMAT3 DMAT4 -%token F16VEC2 F16VEC3 F16VEC4 F16MAT2 F16MAT3 F16MAT4 -%token F32VEC2 F32VEC3 F32VEC4 F32MAT2 F32MAT3 F32MAT4 -%token F64VEC2 F64VEC3 F64VEC4 F64MAT2 F64MAT3 F64MAT4 -%token NOPERSPECTIVE FLAT SMOOTH LAYOUT __EXPLICITINTERPAMD - -%token MAT2X2 MAT2X3 MAT2X4 -%token MAT3X2 MAT3X3 MAT3X4 -%token MAT4X2 MAT4X3 MAT4X4 -%token DMAT2X2 DMAT2X3 DMAT2X4 -%token DMAT3X2 DMAT3X3 DMAT3X4 -%token DMAT4X2 DMAT4X3 DMAT4X4 -%token F16MAT2X2 F16MAT2X3 F16MAT2X4 -%token F16MAT3X2 F16MAT3X3 F16MAT3X4 -%token F16MAT4X2 F16MAT4X3 F16MAT4X4 -%token F32MAT2X2 F32MAT2X3 F32MAT2X4 -%token F32MAT3X2 F32MAT3X3 F32MAT3X4 -%token F32MAT4X2 F32MAT4X3 F32MAT4X4 -%token F64MAT2X2 F64MAT2X3 F64MAT2X4 -%token F64MAT3X2 F64MAT3X3 F64MAT3X4 -%token F64MAT4X2 F64MAT4X3 F64MAT4X4 -%token ATOMIC_UINT - -// combined image/sampler -%token SAMPLER1D SAMPLER2D SAMPLER3D SAMPLERCUBE SAMPLER1DSHADOW SAMPLER2DSHADOW -%token SAMPLERCUBESHADOW SAMPLER1DARRAY SAMPLER2DARRAY SAMPLER1DARRAYSHADOW -%token SAMPLER2DARRAYSHADOW ISAMPLER1D ISAMPLER2D ISAMPLER3D ISAMPLERCUBE -%token ISAMPLER1DARRAY ISAMPLER2DARRAY USAMPLER1D USAMPLER2D USAMPLER3D -%token USAMPLERCUBE USAMPLER1DARRAY USAMPLER2DARRAY -%token SAMPLER2DRECT SAMPLER2DRECTSHADOW ISAMPLER2DRECT USAMPLER2DRECT -%token SAMPLERBUFFER ISAMPLERBUFFER USAMPLERBUFFER -%token SAMPLERCUBEARRAY SAMPLERCUBEARRAYSHADOW -%token ISAMPLERCUBEARRAY USAMPLERCUBEARRAY -%token SAMPLER2DMS ISAMPLER2DMS USAMPLER2DMS -%token SAMPLER2DMSARRAY ISAMPLER2DMSARRAY USAMPLER2DMSARRAY -%token SAMPLEREXTERNALOES - -%token F16SAMPLER1D F16SAMPLER2D F16SAMPLER3D F16SAMPLER2DRECT F16SAMPLERCUBE -%token F16SAMPLER1DARRAY F16SAMPLER2DARRAY F16SAMPLERCUBEARRAY -%token F16SAMPLERBUFFER F16SAMPLER2DMS F16SAMPLER2DMSARRAY -%token F16SAMPLER1DSHADOW F16SAMPLER2DSHADOW F16SAMPLER1DARRAYSHADOW F16SAMPLER2DARRAYSHADOW -%token F16SAMPLER2DRECTSHADOW F16SAMPLERCUBESHADOW F16SAMPLERCUBEARRAYSHADOW - -// pure sampler -%token SAMPLER SAMPLERSHADOW - -// texture without sampler -%token TEXTURE1D TEXTURE2D TEXTURE3D TEXTURECUBE -%token TEXTURE1DARRAY TEXTURE2DARRAY -%token ITEXTURE1D ITEXTURE2D ITEXTURE3D ITEXTURECUBE -%token ITEXTURE1DARRAY ITEXTURE2DARRAY UTEXTURE1D UTEXTURE2D UTEXTURE3D -%token UTEXTURECUBE UTEXTURE1DARRAY UTEXTURE2DARRAY -%token TEXTURE2DRECT ITEXTURE2DRECT UTEXTURE2DRECT -%token TEXTUREBUFFER ITEXTUREBUFFER UTEXTUREBUFFER -%token TEXTURECUBEARRAY ITEXTURECUBEARRAY UTEXTURECUBEARRAY -%token TEXTURE2DMS ITEXTURE2DMS UTEXTURE2DMS -%token TEXTURE2DMSARRAY ITEXTURE2DMSARRAY UTEXTURE2DMSARRAY - -%token F16TEXTURE1D F16TEXTURE2D F16TEXTURE3D F16TEXTURE2DRECT F16TEXTURECUBE -%token F16TEXTURE1DARRAY F16TEXTURE2DARRAY F16TEXTURECUBEARRAY -%token F16TEXTUREBUFFER F16TEXTURE2DMS F16TEXTURE2DMSARRAY - -// input attachments -%token SUBPASSINPUT SUBPASSINPUTMS ISUBPASSINPUT ISUBPASSINPUTMS USUBPASSINPUT USUBPASSINPUTMS -%token F16SUBPASSINPUT F16SUBPASSINPUTMS - -%token IMAGE1D IIMAGE1D UIMAGE1D IMAGE2D IIMAGE2D -%token UIMAGE2D IMAGE3D IIMAGE3D UIMAGE3D -%token IMAGE2DRECT IIMAGE2DRECT UIMAGE2DRECT -%token IMAGECUBE IIMAGECUBE UIMAGECUBE -%token IMAGEBUFFER IIMAGEBUFFER UIMAGEBUFFER -%token IMAGE1DARRAY IIMAGE1DARRAY UIMAGE1DARRAY -%token IMAGE2DARRAY IIMAGE2DARRAY UIMAGE2DARRAY -%token IMAGECUBEARRAY IIMAGECUBEARRAY UIMAGECUBEARRAY -%token IMAGE2DMS IIMAGE2DMS UIMAGE2DMS -%token IMAGE2DMSARRAY IIMAGE2DMSARRAY UIMAGE2DMSARRAY - -%token F16IMAGE1D F16IMAGE2D F16IMAGE3D F16IMAGE2DRECT -%token F16IMAGECUBE F16IMAGE1DARRAY F16IMAGE2DARRAY F16IMAGECUBEARRAY -%token F16IMAGEBUFFER F16IMAGE2DMS F16IMAGE2DMSARRAY - -%token STRUCT VOID WHILE - -%token IDENTIFIER TYPE_NAME -%token FLOATCONSTANT DOUBLECONSTANT INT16CONSTANT UINT16CONSTANT INT32CONSTANT UINT32CONSTANT INTCONSTANT UINTCONSTANT INT64CONSTANT UINT64CONSTANT BOOLCONSTANT FLOAT16CONSTANT -%token LEFT_OP RIGHT_OP -%token INC_OP DEC_OP LE_OP GE_OP EQ_OP NE_OP -%token AND_OP OR_OP XOR_OP MUL_ASSIGN DIV_ASSIGN ADD_ASSIGN -%token MOD_ASSIGN LEFT_ASSIGN RIGHT_ASSIGN AND_ASSIGN XOR_ASSIGN OR_ASSIGN -%token SUB_ASSIGN - -%token LEFT_PAREN RIGHT_PAREN LEFT_BRACKET RIGHT_BRACKET LEFT_BRACE RIGHT_BRACE DOT -%token COMMA COLON EQUAL SEMICOLON BANG DASH TILDE PLUS STAR SLASH PERCENT -%token LEFT_ANGLE RIGHT_ANGLE VERTICAL_BAR CARET AMPERSAND QUESTION - -%token INVARIANT PRECISE -%token HIGH_PRECISION MEDIUM_PRECISION LOW_PRECISION PRECISION - -%token PACKED RESOURCE SUPERP - -%type assignment_operator unary_operator -%type variable_identifier primary_expression postfix_expression -%type expression integer_expression assignment_expression -%type unary_expression multiplicative_expression additive_expression -%type relational_expression equality_expression -%type conditional_expression constant_expression -%type logical_or_expression logical_xor_expression logical_and_expression -%type shift_expression and_expression exclusive_or_expression inclusive_or_expression -%type function_call initializer initializer_list condition conditionopt - -%type translation_unit function_definition -%type statement simple_statement -%type statement_list switch_statement_list compound_statement -%type declaration_statement selection_statement selection_statement_nonattributed expression_statement -%type switch_statement switch_statement_nonattributed case_label -%type declaration external_declaration -%type for_init_statement compound_statement_no_new_scope -%type selection_rest_statement for_rest_statement -%type iteration_statement iteration_statement_nonattributed jump_statement statement_no_new_scope statement_scoped -%type single_declaration init_declarator_list - -%type parameter_declaration parameter_declarator parameter_type_specifier - -%type array_specifier -%type precise_qualifier invariant_qualifier interpolation_qualifier storage_qualifier precision_qualifier -%type layout_qualifier layout_qualifier_id_list layout_qualifier_id -%type non_uniform_qualifier - -%type type_qualifier fully_specified_type type_specifier -%type single_type_qualifier -%type type_specifier_nonarray -%type struct_specifier -%type struct_declarator -%type struct_declarator_list struct_declaration struct_declaration_list type_name_list -%type block_structure -%type function_header function_declarator -%type function_header_with_parameters -%type function_call_header_with_parameters function_call_header_no_parameters function_call_generic function_prototype -%type function_call_or_method function_identifier function_call_header - -%type identifier_list - -%type attribute attribute_list single_attribute - -%start translation_unit -%% - -variable_identifier - : IDENTIFIER { - $$ = parseContext.handleVariable($1.loc, $1.symbol, $1.string); - } - ; - -primary_expression - : variable_identifier { - $$ = $1; - } - | INT32CONSTANT { - parseContext.explicitInt32Check($1.loc, "32-bit signed literal"); - $$ = parseContext.intermediate.addConstantUnion($1.i, $1.loc, true); - } - | UINT32CONSTANT { - parseContext.explicitInt32Check($1.loc, "32-bit signed literal"); - $$ = parseContext.intermediate.addConstantUnion($1.u, $1.loc, true); - } - | INTCONSTANT { - $$ = parseContext.intermediate.addConstantUnion($1.i, $1.loc, true); - } - | UINTCONSTANT { - parseContext.fullIntegerCheck($1.loc, "unsigned literal"); - $$ = parseContext.intermediate.addConstantUnion($1.u, $1.loc, true); - } - | INT64CONSTANT { - parseContext.int64Check($1.loc, "64-bit integer literal"); - $$ = parseContext.intermediate.addConstantUnion($1.i64, $1.loc, true); - } - | UINT64CONSTANT { - parseContext.int64Check($1.loc, "64-bit unsigned integer literal"); - $$ = parseContext.intermediate.addConstantUnion($1.u64, $1.loc, true); - } - | INT16CONSTANT { - parseContext.explicitInt16Check($1.loc, "16-bit integer literal"); - $$ = parseContext.intermediate.addConstantUnion((short)$1.i, $1.loc, true); - } - | UINT16CONSTANT { - parseContext.explicitInt16Check($1.loc, "16-bit unsigned integer literal"); - $$ = parseContext.intermediate.addConstantUnion((unsigned short)$1.u, $1.loc, true); - } - | FLOATCONSTANT { - $$ = parseContext.intermediate.addConstantUnion($1.d, EbtFloat, $1.loc, true); - } - | DOUBLECONSTANT { - parseContext.doubleCheck($1.loc, "double literal"); - $$ = parseContext.intermediate.addConstantUnion($1.d, EbtDouble, $1.loc, true); - } - | FLOAT16CONSTANT { - parseContext.float16Check($1.loc, "half float literal"); - $$ = parseContext.intermediate.addConstantUnion($1.d, EbtFloat16, $1.loc, true); - } - | BOOLCONSTANT { - $$ = parseContext.intermediate.addConstantUnion($1.b, $1.loc, true); - } - | LEFT_PAREN expression RIGHT_PAREN { - $$ = $2; - if ($$->getAsConstantUnion()) - $$->getAsConstantUnion()->setExpression(); - } - ; - -postfix_expression - : primary_expression { - $$ = $1; - } - | postfix_expression LEFT_BRACKET integer_expression RIGHT_BRACKET { - $$ = parseContext.handleBracketDereference($2.loc, $1, $3); - } - | function_call { - $$ = $1; - } - | postfix_expression DOT IDENTIFIER { - $$ = parseContext.handleDotDereference($3.loc, $1, *$3.string); - } - | postfix_expression INC_OP { - parseContext.variableCheck($1); - parseContext.lValueErrorCheck($2.loc, "++", $1); - $$ = parseContext.handleUnaryMath($2.loc, "++", EOpPostIncrement, $1); - } - | postfix_expression DEC_OP { - parseContext.variableCheck($1); - parseContext.lValueErrorCheck($2.loc, "--", $1); - $$ = parseContext.handleUnaryMath($2.loc, "--", EOpPostDecrement, $1); - } - ; - -integer_expression - : expression { - parseContext.integerCheck($1, "[]"); - $$ = $1; - } - ; - -function_call - : function_call_or_method { - $$ = parseContext.handleFunctionCall($1.loc, $1.function, $1.intermNode); - delete $1.function; - } - ; - -function_call_or_method - : function_call_generic { - $$ = $1; - } - ; - -function_call_generic - : function_call_header_with_parameters RIGHT_PAREN { - $$ = $1; - $$.loc = $2.loc; - } - | function_call_header_no_parameters RIGHT_PAREN { - $$ = $1; - $$.loc = $2.loc; - } - ; - -function_call_header_no_parameters - : function_call_header VOID { - $$ = $1; - } - | function_call_header { - $$ = $1; - } - ; - -function_call_header_with_parameters - : function_call_header assignment_expression { - TParameter param = { 0, new TType }; - param.type->shallowCopy($2->getType()); - $1.function->addParameter(param); - $$.function = $1.function; - $$.intermNode = $2; - } - | function_call_header_with_parameters COMMA assignment_expression { - TParameter param = { 0, new TType }; - param.type->shallowCopy($3->getType()); - $1.function->addParameter(param); - $$.function = $1.function; - $$.intermNode = parseContext.intermediate.growAggregate($1.intermNode, $3, $2.loc); - } - ; - -function_call_header - : function_identifier LEFT_PAREN { - $$ = $1; - } - ; - -// Grammar Note: Constructors look like functions, but are recognized as types. - -function_identifier - : type_specifier { - // Constructor - $$.intermNode = 0; - $$.function = parseContext.handleConstructorCall($1.loc, $1); - } - | postfix_expression { - // - // Should be a method or subroutine call, but we haven't recognized the arguments yet. - // - $$.function = 0; - $$.intermNode = 0; - - TIntermMethod* method = $1->getAsMethodNode(); - if (method) { - $$.function = new TFunction(&method->getMethodName(), TType(EbtInt), EOpArrayLength); - $$.intermNode = method->getObject(); - } else { - TIntermSymbol* symbol = $1->getAsSymbolNode(); - if (symbol) { - parseContext.reservedErrorCheck(symbol->getLoc(), symbol->getName()); - TFunction *function = new TFunction(&symbol->getName(), TType(EbtVoid)); - $$.function = function; - } else - parseContext.error($1->getLoc(), "function call, method, or subroutine call expected", "", ""); - } - - if ($$.function == 0) { - // error recover - TString empty(""); - $$.function = new TFunction(&empty, TType(EbtVoid), EOpNull); - } - } - | non_uniform_qualifier { - // Constructor - $$.intermNode = 0; - $$.function = parseContext.handleConstructorCall($1.loc, $1); - } - ; - -unary_expression - : postfix_expression { - parseContext.variableCheck($1); - $$ = $1; - if (TIntermMethod* method = $1->getAsMethodNode()) - parseContext.error($1->getLoc(), "incomplete method syntax", method->getMethodName().c_str(), ""); - } - | INC_OP unary_expression { - parseContext.lValueErrorCheck($1.loc, "++", $2); - $$ = parseContext.handleUnaryMath($1.loc, "++", EOpPreIncrement, $2); - } - | DEC_OP unary_expression { - parseContext.lValueErrorCheck($1.loc, "--", $2); - $$ = parseContext.handleUnaryMath($1.loc, "--", EOpPreDecrement, $2); - } - | unary_operator unary_expression { - if ($1.op != EOpNull) { - char errorOp[2] = {0, 0}; - switch($1.op) { - case EOpNegative: errorOp[0] = '-'; break; - case EOpLogicalNot: errorOp[0] = '!'; break; - case EOpBitwiseNot: errorOp[0] = '~'; break; - default: break; // some compilers want this - } - $$ = parseContext.handleUnaryMath($1.loc, errorOp, $1.op, $2); - } else { - $$ = $2; - if ($$->getAsConstantUnion()) - $$->getAsConstantUnion()->setExpression(); - } - } - ; -// Grammar Note: No traditional style type casts. - -unary_operator - : PLUS { $$.loc = $1.loc; $$.op = EOpNull; } - | DASH { $$.loc = $1.loc; $$.op = EOpNegative; } - | BANG { $$.loc = $1.loc; $$.op = EOpLogicalNot; } - | TILDE { $$.loc = $1.loc; $$.op = EOpBitwiseNot; - parseContext.fullIntegerCheck($1.loc, "bitwise not"); } - ; -// Grammar Note: No '*' or '&' unary ops. Pointers are not supported. - -multiplicative_expression - : unary_expression { $$ = $1; } - | multiplicative_expression STAR unary_expression { - $$ = parseContext.handleBinaryMath($2.loc, "*", EOpMul, $1, $3); - if ($$ == 0) - $$ = $1; - } - | multiplicative_expression SLASH unary_expression { - $$ = parseContext.handleBinaryMath($2.loc, "/", EOpDiv, $1, $3); - if ($$ == 0) - $$ = $1; - } - | multiplicative_expression PERCENT unary_expression { - parseContext.fullIntegerCheck($2.loc, "%"); - $$ = parseContext.handleBinaryMath($2.loc, "%", EOpMod, $1, $3); - if ($$ == 0) - $$ = $1; - } - ; - -additive_expression - : multiplicative_expression { $$ = $1; } - | additive_expression PLUS multiplicative_expression { - $$ = parseContext.handleBinaryMath($2.loc, "+", EOpAdd, $1, $3); - if ($$ == 0) - $$ = $1; - } - | additive_expression DASH multiplicative_expression { - $$ = parseContext.handleBinaryMath($2.loc, "-", EOpSub, $1, $3); - if ($$ == 0) - $$ = $1; - } - ; - -shift_expression - : additive_expression { $$ = $1; } - | shift_expression LEFT_OP additive_expression { - parseContext.fullIntegerCheck($2.loc, "bit shift left"); - $$ = parseContext.handleBinaryMath($2.loc, "<<", EOpLeftShift, $1, $3); - if ($$ == 0) - $$ = $1; - } - | shift_expression RIGHT_OP additive_expression { - parseContext.fullIntegerCheck($2.loc, "bit shift right"); - $$ = parseContext.handleBinaryMath($2.loc, ">>", EOpRightShift, $1, $3); - if ($$ == 0) - $$ = $1; - } - ; - -relational_expression - : shift_expression { $$ = $1; } - | relational_expression LEFT_ANGLE shift_expression { - $$ = parseContext.handleBinaryMath($2.loc, "<", EOpLessThan, $1, $3); - if ($$ == 0) - $$ = parseContext.intermediate.addConstantUnion(false, $2.loc); - } - | relational_expression RIGHT_ANGLE shift_expression { - $$ = parseContext.handleBinaryMath($2.loc, ">", EOpGreaterThan, $1, $3); - if ($$ == 0) - $$ = parseContext.intermediate.addConstantUnion(false, $2.loc); - } - | relational_expression LE_OP shift_expression { - $$ = parseContext.handleBinaryMath($2.loc, "<=", EOpLessThanEqual, $1, $3); - if ($$ == 0) - $$ = parseContext.intermediate.addConstantUnion(false, $2.loc); - } - | relational_expression GE_OP shift_expression { - $$ = parseContext.handleBinaryMath($2.loc, ">=", EOpGreaterThanEqual, $1, $3); - if ($$ == 0) - $$ = parseContext.intermediate.addConstantUnion(false, $2.loc); - } - ; - -equality_expression - : relational_expression { $$ = $1; } - | equality_expression EQ_OP relational_expression { - parseContext.arrayObjectCheck($2.loc, $1->getType(), "array comparison"); - parseContext.opaqueCheck($2.loc, $1->getType(), "=="); - parseContext.specializationCheck($2.loc, $1->getType(), "=="); - $$ = parseContext.handleBinaryMath($2.loc, "==", EOpEqual, $1, $3); - if ($$ == 0) - $$ = parseContext.intermediate.addConstantUnion(false, $2.loc); - } - | equality_expression NE_OP relational_expression { - parseContext.arrayObjectCheck($2.loc, $1->getType(), "array comparison"); - parseContext.opaqueCheck($2.loc, $1->getType(), "!="); - parseContext.specializationCheck($2.loc, $1->getType(), "!="); - $$ = parseContext.handleBinaryMath($2.loc, "!=", EOpNotEqual, $1, $3); - if ($$ == 0) - $$ = parseContext.intermediate.addConstantUnion(false, $2.loc); - } - ; - -and_expression - : equality_expression { $$ = $1; } - | and_expression AMPERSAND equality_expression { - parseContext.fullIntegerCheck($2.loc, "bitwise and"); - $$ = parseContext.handleBinaryMath($2.loc, "&", EOpAnd, $1, $3); - if ($$ == 0) - $$ = $1; - } - ; - -exclusive_or_expression - : and_expression { $$ = $1; } - | exclusive_or_expression CARET and_expression { - parseContext.fullIntegerCheck($2.loc, "bitwise exclusive or"); - $$ = parseContext.handleBinaryMath($2.loc, "^", EOpExclusiveOr, $1, $3); - if ($$ == 0) - $$ = $1; - } - ; - -inclusive_or_expression - : exclusive_or_expression { $$ = $1; } - | inclusive_or_expression VERTICAL_BAR exclusive_or_expression { - parseContext.fullIntegerCheck($2.loc, "bitwise inclusive or"); - $$ = parseContext.handleBinaryMath($2.loc, "|", EOpInclusiveOr, $1, $3); - if ($$ == 0) - $$ = $1; - } - ; - -logical_and_expression - : inclusive_or_expression { $$ = $1; } - | logical_and_expression AND_OP inclusive_or_expression { - $$ = parseContext.handleBinaryMath($2.loc, "&&", EOpLogicalAnd, $1, $3); - if ($$ == 0) - $$ = parseContext.intermediate.addConstantUnion(false, $2.loc); - } - ; - -logical_xor_expression - : logical_and_expression { $$ = $1; } - | logical_xor_expression XOR_OP logical_and_expression { - $$ = parseContext.handleBinaryMath($2.loc, "^^", EOpLogicalXor, $1, $3); - if ($$ == 0) - $$ = parseContext.intermediate.addConstantUnion(false, $2.loc); - } - ; - -logical_or_expression - : logical_xor_expression { $$ = $1; } - | logical_or_expression OR_OP logical_xor_expression { - $$ = parseContext.handleBinaryMath($2.loc, "||", EOpLogicalOr, $1, $3); - if ($$ == 0) - $$ = parseContext.intermediate.addConstantUnion(false, $2.loc); - } - ; - -conditional_expression - : logical_or_expression { $$ = $1; } - | logical_or_expression QUESTION { - ++parseContext.controlFlowNestingLevel; - } - expression COLON assignment_expression { - --parseContext.controlFlowNestingLevel; - parseContext.boolCheck($2.loc, $1); - parseContext.rValueErrorCheck($2.loc, "?", $1); - parseContext.rValueErrorCheck($5.loc, ":", $4); - parseContext.rValueErrorCheck($5.loc, ":", $6); - $$ = parseContext.intermediate.addSelection($1, $4, $6, $2.loc); - if ($$ == 0) { - parseContext.binaryOpError($2.loc, ":", $4->getCompleteString(), $6->getCompleteString()); - $$ = $6; - } - } - ; - -assignment_expression - : conditional_expression { $$ = $1; } - | unary_expression assignment_operator assignment_expression { - parseContext.arrayObjectCheck($2.loc, $1->getType(), "array assignment"); - parseContext.opaqueCheck($2.loc, $1->getType(), "="); - parseContext.specializationCheck($2.loc, $1->getType(), "="); - parseContext.lValueErrorCheck($2.loc, "assign", $1); - parseContext.rValueErrorCheck($2.loc, "assign", $3); - $$ = parseContext.intermediate.addAssign($2.op, $1, $3, $2.loc); - if ($$ == 0) { - parseContext.assignError($2.loc, "assign", $1->getCompleteString(), $3->getCompleteString()); - $$ = $1; - } - } - ; - -assignment_operator - : EQUAL { - $$.loc = $1.loc; - $$.op = EOpAssign; - } - | MUL_ASSIGN { - $$.loc = $1.loc; - $$.op = EOpMulAssign; - } - | DIV_ASSIGN { - $$.loc = $1.loc; - $$.op = EOpDivAssign; - } - | MOD_ASSIGN { - parseContext.fullIntegerCheck($1.loc, "%="); - $$.loc = $1.loc; - $$.op = EOpModAssign; - } - | ADD_ASSIGN { - $$.loc = $1.loc; - $$.op = EOpAddAssign; - } - | SUB_ASSIGN { - $$.loc = $1.loc; - $$.op = EOpSubAssign; - } - | LEFT_ASSIGN { - parseContext.fullIntegerCheck($1.loc, "bit-shift left assign"); - $$.loc = $1.loc; $$.op = EOpLeftShiftAssign; - } - | RIGHT_ASSIGN { - parseContext.fullIntegerCheck($1.loc, "bit-shift right assign"); - $$.loc = $1.loc; $$.op = EOpRightShiftAssign; - } - | AND_ASSIGN { - parseContext.fullIntegerCheck($1.loc, "bitwise-and assign"); - $$.loc = $1.loc; $$.op = EOpAndAssign; - } - | XOR_ASSIGN { - parseContext.fullIntegerCheck($1.loc, "bitwise-xor assign"); - $$.loc = $1.loc; $$.op = EOpExclusiveOrAssign; - } - | OR_ASSIGN { - parseContext.fullIntegerCheck($1.loc, "bitwise-or assign"); - $$.loc = $1.loc; $$.op = EOpInclusiveOrAssign; - } - ; - -expression - : assignment_expression { - $$ = $1; - } - | expression COMMA assignment_expression { - parseContext.samplerConstructorLocationCheck($2.loc, ",", $3); - $$ = parseContext.intermediate.addComma($1, $3, $2.loc); - if ($$ == 0) { - parseContext.binaryOpError($2.loc, ",", $1->getCompleteString(), $3->getCompleteString()); - $$ = $3; - } - } - ; - -constant_expression - : conditional_expression { - parseContext.constantValueCheck($1, ""); - $$ = $1; - } - ; - -declaration - : function_prototype SEMICOLON { - parseContext.handleFunctionDeclarator($1.loc, *$1.function, true /* prototype */); - $$ = 0; - // TODO: 4.0 functionality: subroutines: make the identifier a user type for this signature - } - | init_declarator_list SEMICOLON { - if ($1.intermNode && $1.intermNode->getAsAggregate()) - $1.intermNode->getAsAggregate()->setOperator(EOpSequence); - $$ = $1.intermNode; - } - | PRECISION precision_qualifier type_specifier SEMICOLON { - parseContext.profileRequires($1.loc, ENoProfile, 130, 0, "precision statement"); - - // lazy setting of the previous scope's defaults, has effect only the first time it is called in a particular scope - parseContext.symbolTable.setPreviousDefaultPrecisions(&parseContext.defaultPrecision[0]); - parseContext.setDefaultPrecision($1.loc, $3, $2.qualifier.precision); - $$ = 0; - } - | block_structure SEMICOLON { - parseContext.declareBlock($1.loc, *$1.typeList); - $$ = 0; - } - | block_structure IDENTIFIER SEMICOLON { - parseContext.declareBlock($1.loc, *$1.typeList, $2.string); - $$ = 0; - } - | block_structure IDENTIFIER array_specifier SEMICOLON { - parseContext.declareBlock($1.loc, *$1.typeList, $2.string, $3.arraySizes); - $$ = 0; - } - | type_qualifier SEMICOLON { - parseContext.globalQualifierFixCheck($1.loc, $1.qualifier); - parseContext.updateStandaloneQualifierDefaults($1.loc, $1); - $$ = 0; - } - | type_qualifier IDENTIFIER SEMICOLON { - parseContext.checkNoShaderLayouts($1.loc, $1.shaderQualifiers); - parseContext.addQualifierToExisting($1.loc, $1.qualifier, *$2.string); - $$ = 0; - } - | type_qualifier IDENTIFIER identifier_list SEMICOLON { - parseContext.checkNoShaderLayouts($1.loc, $1.shaderQualifiers); - $3->push_back($2.string); - parseContext.addQualifierToExisting($1.loc, $1.qualifier, *$3); - $$ = 0; - } - ; - -block_structure - : type_qualifier IDENTIFIER LEFT_BRACE { parseContext.nestedBlockCheck($1.loc); } struct_declaration_list RIGHT_BRACE { - --parseContext.structNestingLevel; - parseContext.blockName = $2.string; - parseContext.globalQualifierFixCheck($1.loc, $1.qualifier); - parseContext.checkNoShaderLayouts($1.loc, $1.shaderQualifiers); - parseContext.currentBlockQualifier = $1.qualifier; - $$.loc = $1.loc; - $$.typeList = $5; - } - -identifier_list - : COMMA IDENTIFIER { - $$ = new TIdentifierList; - $$->push_back($2.string); - } - | identifier_list COMMA IDENTIFIER { - $$ = $1; - $$->push_back($3.string); - } - ; - -function_prototype - : function_declarator RIGHT_PAREN { - $$.function = $1; - $$.loc = $2.loc; - } - ; - -function_declarator - : function_header { - $$ = $1; - } - | function_header_with_parameters { - $$ = $1; - } - ; - - -function_header_with_parameters - : function_header parameter_declaration { - // Add the parameter - $$ = $1; - if ($2.param.type->getBasicType() != EbtVoid) - $1->addParameter($2.param); - else - delete $2.param.type; - } - | function_header_with_parameters COMMA parameter_declaration { - // - // Only first parameter of one-parameter functions can be void - // The check for named parameters not being void is done in parameter_declarator - // - if ($3.param.type->getBasicType() == EbtVoid) { - // - // This parameter > first is void - // - parseContext.error($2.loc, "cannot be an argument type except for '(void)'", "void", ""); - delete $3.param.type; - } else { - // Add the parameter - $$ = $1; - $1->addParameter($3.param); - } - } - ; - -function_header - : fully_specified_type IDENTIFIER LEFT_PAREN { - if ($1.qualifier.storage != EvqGlobal && $1.qualifier.storage != EvqTemporary) { - parseContext.error($2.loc, "no qualifiers allowed for function return", - GetStorageQualifierString($1.qualifier.storage), ""); - } - if ($1.arraySizes) - parseContext.arraySizeRequiredCheck($1.loc, *$1.arraySizes); - - // Add the function as a prototype after parsing it (we do not support recursion) - TFunction *function; - TType type($1); - - // Potentially rename shader entry point function. No-op most of the time. - parseContext.renameShaderFunction($2.string); - - // Make the function - function = new TFunction($2.string, type); - $$ = function; - } - ; - -parameter_declarator - // Type + name - : type_specifier IDENTIFIER { - if ($1.arraySizes) { - parseContext.profileRequires($1.loc, ENoProfile, 120, E_GL_3DL_array_objects, "arrayed type"); - parseContext.profileRequires($1.loc, EEsProfile, 300, 0, "arrayed type"); - parseContext.arraySizeRequiredCheck($1.loc, *$1.arraySizes); - } - if ($1.basicType == EbtVoid) { - parseContext.error($2.loc, "illegal use of type 'void'", $2.string->c_str(), ""); - } - parseContext.reservedErrorCheck($2.loc, *$2.string); - - TParameter param = {$2.string, new TType($1)}; - $$.loc = $2.loc; - $$.param = param; - } - | type_specifier IDENTIFIER array_specifier { - if ($1.arraySizes) { - parseContext.profileRequires($1.loc, ENoProfile, 120, E_GL_3DL_array_objects, "arrayed type"); - parseContext.profileRequires($1.loc, EEsProfile, 300, 0, "arrayed type"); - parseContext.arraySizeRequiredCheck($1.loc, *$1.arraySizes); - } - TType* type = new TType($1); - type->transferArraySizes($3.arraySizes); - type->copyArrayInnerSizes($1.arraySizes); - - parseContext.arrayOfArrayVersionCheck($2.loc, type->getArraySizes()); - parseContext.arraySizeRequiredCheck($3.loc, *$3.arraySizes); - parseContext.reservedErrorCheck($2.loc, *$2.string); - - TParameter param = { $2.string, type }; - - $$.loc = $2.loc; - $$.param = param; - } - ; - -parameter_declaration - // - // With name - // - : type_qualifier parameter_declarator { - $$ = $2; - if ($1.qualifier.precision != EpqNone) - $$.param.type->getQualifier().precision = $1.qualifier.precision; - parseContext.precisionQualifierCheck($$.loc, $$.param.type->getBasicType(), $$.param.type->getQualifier()); - - parseContext.checkNoShaderLayouts($1.loc, $1.shaderQualifiers); - parseContext.parameterTypeCheck($2.loc, $1.qualifier.storage, *$$.param.type); - parseContext.paramCheckFix($1.loc, $1.qualifier, *$$.param.type); - - } - | parameter_declarator { - $$ = $1; - - parseContext.parameterTypeCheck($1.loc, EvqIn, *$1.param.type); - parseContext.paramCheckFixStorage($1.loc, EvqTemporary, *$$.param.type); - parseContext.precisionQualifierCheck($$.loc, $$.param.type->getBasicType(), $$.param.type->getQualifier()); - } - // - // Without name - // - | type_qualifier parameter_type_specifier { - $$ = $2; - if ($1.qualifier.precision != EpqNone) - $$.param.type->getQualifier().precision = $1.qualifier.precision; - parseContext.precisionQualifierCheck($1.loc, $$.param.type->getBasicType(), $$.param.type->getQualifier()); - - parseContext.checkNoShaderLayouts($1.loc, $1.shaderQualifiers); - parseContext.parameterTypeCheck($2.loc, $1.qualifier.storage, *$$.param.type); - parseContext.paramCheckFix($1.loc, $1.qualifier, *$$.param.type); - } - | parameter_type_specifier { - $$ = $1; - - parseContext.parameterTypeCheck($1.loc, EvqIn, *$1.param.type); - parseContext.paramCheckFixStorage($1.loc, EvqTemporary, *$$.param.type); - parseContext.precisionQualifierCheck($$.loc, $$.param.type->getBasicType(), $$.param.type->getQualifier()); - } - ; - -parameter_type_specifier - : type_specifier { - TParameter param = { 0, new TType($1) }; - $$.param = param; - if ($1.arraySizes) - parseContext.arraySizeRequiredCheck($1.loc, *$1.arraySizes); - } - ; - -init_declarator_list - : single_declaration { - $$ = $1; - } - | init_declarator_list COMMA IDENTIFIER { - $$ = $1; - parseContext.declareVariable($3.loc, *$3.string, $1.type); - } - | init_declarator_list COMMA IDENTIFIER array_specifier { - $$ = $1; - parseContext.declareVariable($3.loc, *$3.string, $1.type, $4.arraySizes); - } - | init_declarator_list COMMA IDENTIFIER array_specifier EQUAL initializer { - $$.type = $1.type; - TIntermNode* initNode = parseContext.declareVariable($3.loc, *$3.string, $1.type, $4.arraySizes, $6); - $$.intermNode = parseContext.intermediate.growAggregate($1.intermNode, initNode, $5.loc); - } - | init_declarator_list COMMA IDENTIFIER EQUAL initializer { - $$.type = $1.type; - TIntermNode* initNode = parseContext.declareVariable($3.loc, *$3.string, $1.type, 0, $5); - $$.intermNode = parseContext.intermediate.growAggregate($1.intermNode, initNode, $4.loc); - } - ; - -single_declaration - : fully_specified_type { - $$.type = $1; - $$.intermNode = 0; - parseContext.declareTypeDefaults($$.loc, $$.type); - } - | fully_specified_type IDENTIFIER { - $$.type = $1; - $$.intermNode = 0; - parseContext.declareVariable($2.loc, *$2.string, $1); - } - | fully_specified_type IDENTIFIER array_specifier { - $$.type = $1; - $$.intermNode = 0; - parseContext.declareVariable($2.loc, *$2.string, $1, $3.arraySizes); - } - | fully_specified_type IDENTIFIER array_specifier EQUAL initializer { - $$.type = $1; - TIntermNode* initNode = parseContext.declareVariable($2.loc, *$2.string, $1, $3.arraySizes, $5); - $$.intermNode = parseContext.intermediate.growAggregate(0, initNode, $4.loc); - } - | fully_specified_type IDENTIFIER EQUAL initializer { - $$.type = $1; - TIntermNode* initNode = parseContext.declareVariable($2.loc, *$2.string, $1, 0, $4); - $$.intermNode = parseContext.intermediate.growAggregate(0, initNode, $3.loc); - } - -// Grammar Note: No 'enum', or 'typedef'. - -fully_specified_type - : type_specifier { - $$ = $1; - - parseContext.globalQualifierTypeCheck($1.loc, $1.qualifier, $$); - if ($1.arraySizes) { - parseContext.profileRequires($1.loc, ENoProfile, 120, E_GL_3DL_array_objects, "arrayed type"); - parseContext.profileRequires($1.loc, EEsProfile, 300, 0, "arrayed type"); - } - - parseContext.precisionQualifierCheck($$.loc, $$.basicType, $$.qualifier); - } - | type_qualifier type_specifier { - parseContext.globalQualifierFixCheck($1.loc, $1.qualifier); - parseContext.globalQualifierTypeCheck($1.loc, $1.qualifier, $2); - - if ($2.arraySizes) { - parseContext.profileRequires($2.loc, ENoProfile, 120, E_GL_3DL_array_objects, "arrayed type"); - parseContext.profileRequires($2.loc, EEsProfile, 300, 0, "arrayed type"); - } - - if ($2.arraySizes && parseContext.arrayQualifierError($2.loc, $1.qualifier)) - $2.arraySizes = nullptr; - - parseContext.checkNoShaderLayouts($2.loc, $1.shaderQualifiers); - $2.shaderQualifiers.merge($1.shaderQualifiers); - parseContext.mergeQualifiers($2.loc, $2.qualifier, $1.qualifier, true); - parseContext.precisionQualifierCheck($2.loc, $2.basicType, $2.qualifier); - - $$ = $2; - - if (! $$.qualifier.isInterpolation() && - ((parseContext.language == EShLangVertex && $$.qualifier.storage == EvqVaryingOut) || - (parseContext.language == EShLangFragment && $$.qualifier.storage == EvqVaryingIn))) - $$.qualifier.smooth = true; - } - ; - -invariant_qualifier - : INVARIANT { - parseContext.globalCheck($1.loc, "invariant"); - parseContext.profileRequires($$.loc, ENoProfile, 120, 0, "invariant"); - $$.init($1.loc); - $$.qualifier.invariant = true; - } - ; - -interpolation_qualifier - : SMOOTH { - parseContext.globalCheck($1.loc, "smooth"); - parseContext.profileRequires($1.loc, ENoProfile, 130, 0, "smooth"); - parseContext.profileRequires($1.loc, EEsProfile, 300, 0, "smooth"); - $$.init($1.loc); - $$.qualifier.smooth = true; - } - | FLAT { - parseContext.globalCheck($1.loc, "flat"); - parseContext.profileRequires($1.loc, ENoProfile, 130, 0, "flat"); - parseContext.profileRequires($1.loc, EEsProfile, 300, 0, "flat"); - $$.init($1.loc); - $$.qualifier.flat = true; - } - | NOPERSPECTIVE { - parseContext.globalCheck($1.loc, "noperspective"); -#ifdef NV_EXTENSIONS - parseContext.profileRequires($1.loc, EEsProfile, 0, E_GL_NV_shader_noperspective_interpolation, "noperspective"); -#else - parseContext.requireProfile($1.loc, ~EEsProfile, "noperspective"); -#endif - parseContext.profileRequires($1.loc, ENoProfile, 130, 0, "noperspective"); - $$.init($1.loc); - $$.qualifier.nopersp = true; - } - | __EXPLICITINTERPAMD { -#ifdef AMD_EXTENSIONS - parseContext.globalCheck($1.loc, "__explicitInterpAMD"); - parseContext.profileRequires($1.loc, ECoreProfile, 450, E_GL_AMD_shader_explicit_vertex_parameter, "explicit interpolation"); - parseContext.profileRequires($1.loc, ECompatibilityProfile, 450, E_GL_AMD_shader_explicit_vertex_parameter, "explicit interpolation"); - $$.init($1.loc); - $$.qualifier.explicitInterp = true; -#endif - } - ; - -layout_qualifier - : LAYOUT LEFT_PAREN layout_qualifier_id_list RIGHT_PAREN { - $$ = $3; - } - ; - -layout_qualifier_id_list - : layout_qualifier_id { - $$ = $1; - } - | layout_qualifier_id_list COMMA layout_qualifier_id { - $$ = $1; - $$.shaderQualifiers.merge($3.shaderQualifiers); - parseContext.mergeObjectLayoutQualifiers($$.qualifier, $3.qualifier, false); - } - -layout_qualifier_id - : IDENTIFIER { - $$.init($1.loc); - parseContext.setLayoutQualifier($1.loc, $$, *$1.string); - } - | IDENTIFIER EQUAL constant_expression { - $$.init($1.loc); - parseContext.setLayoutQualifier($1.loc, $$, *$1.string, $3); - } - | SHARED { // because "shared" is both an identifier and a keyword - $$.init($1.loc); - TString strShared("shared"); - parseContext.setLayoutQualifier($1.loc, $$, strShared); - } - ; - -precise_qualifier - : PRECISE { - parseContext.profileRequires($$.loc, ECoreProfile | ECompatibilityProfile, 400, E_GL_ARB_gpu_shader5, "precise"); - parseContext.profileRequires($1.loc, EEsProfile, 320, Num_AEP_gpu_shader5, AEP_gpu_shader5, "precise"); - $$.init($1.loc); - $$.qualifier.noContraction = true; - } - ; - -type_qualifier - : single_type_qualifier { - $$ = $1; - } - | type_qualifier single_type_qualifier { - $$ = $1; - if ($$.basicType == EbtVoid) - $$.basicType = $2.basicType; - - $$.shaderQualifiers.merge($2.shaderQualifiers); - parseContext.mergeQualifiers($$.loc, $$.qualifier, $2.qualifier, false); - } - ; - -single_type_qualifier - : storage_qualifier { - $$ = $1; - } - | layout_qualifier { - $$ = $1; - } - | precision_qualifier { - parseContext.checkPrecisionQualifier($1.loc, $1.qualifier.precision); - $$ = $1; - } - | interpolation_qualifier { - // allow inheritance of storage qualifier from block declaration - $$ = $1; - } - | invariant_qualifier { - // allow inheritance of storage qualifier from block declaration - $$ = $1; - } - | precise_qualifier { - // allow inheritance of storage qualifier from block declaration - $$ = $1; - } - | non_uniform_qualifier { - $$ = $1; - } - ; - -storage_qualifier - : CONST { - $$.init($1.loc); - $$.qualifier.storage = EvqConst; // will later turn into EvqConstReadOnly, if the initializer is not constant - } - | ATTRIBUTE { - parseContext.requireStage($1.loc, EShLangVertex, "attribute"); - parseContext.checkDeprecated($1.loc, ECoreProfile, 130, "attribute"); - parseContext.checkDeprecated($1.loc, ENoProfile, 130, "attribute"); - parseContext.requireNotRemoved($1.loc, ECoreProfile, 420, "attribute"); - parseContext.requireNotRemoved($1.loc, EEsProfile, 300, "attribute"); - - parseContext.globalCheck($1.loc, "attribute"); - - $$.init($1.loc); - $$.qualifier.storage = EvqVaryingIn; - } - | VARYING { - parseContext.checkDeprecated($1.loc, ENoProfile, 130, "varying"); - parseContext.checkDeprecated($1.loc, ECoreProfile, 130, "varying"); - parseContext.requireNotRemoved($1.loc, ECoreProfile, 420, "varying"); - parseContext.requireNotRemoved($1.loc, EEsProfile, 300, "varying"); - - parseContext.globalCheck($1.loc, "varying"); - - $$.init($1.loc); - if (parseContext.language == EShLangVertex) - $$.qualifier.storage = EvqVaryingOut; - else - $$.qualifier.storage = EvqVaryingIn; - } - | INOUT { - parseContext.globalCheck($1.loc, "inout"); - $$.init($1.loc); - $$.qualifier.storage = EvqInOut; - } - | IN { - parseContext.globalCheck($1.loc, "in"); - $$.init($1.loc); - // whether this is a parameter "in" or a pipeline "in" will get sorted out a bit later - $$.qualifier.storage = EvqIn; - } - | OUT { - parseContext.globalCheck($1.loc, "out"); - $$.init($1.loc); - // whether this is a parameter "out" or a pipeline "out" will get sorted out a bit later - $$.qualifier.storage = EvqOut; - } - | CENTROID { - parseContext.profileRequires($1.loc, ENoProfile, 120, 0, "centroid"); - parseContext.profileRequires($1.loc, EEsProfile, 300, 0, "centroid"); - parseContext.globalCheck($1.loc, "centroid"); - $$.init($1.loc); - $$.qualifier.centroid = true; - } - | PATCH { - parseContext.globalCheck($1.loc, "patch"); - parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangTessControlMask | EShLangTessEvaluationMask), "patch"); - $$.init($1.loc); - $$.qualifier.patch = true; - } - | SAMPLE { - parseContext.globalCheck($1.loc, "sample"); - $$.init($1.loc); - $$.qualifier.sample = true; - } - | UNIFORM { - parseContext.globalCheck($1.loc, "uniform"); - $$.init($1.loc); - $$.qualifier.storage = EvqUniform; - } - | BUFFER { - parseContext.globalCheck($1.loc, "buffer"); - $$.init($1.loc); - $$.qualifier.storage = EvqBuffer; - } - | SHARED { - parseContext.globalCheck($1.loc, "shared"); - parseContext.profileRequires($1.loc, ECoreProfile | ECompatibilityProfile, 430, E_GL_ARB_compute_shader, "shared"); - parseContext.profileRequires($1.loc, EEsProfile, 310, 0, "shared"); - parseContext.requireStage($1.loc, EShLangCompute, "shared"); - $$.init($1.loc); - $$.qualifier.storage = EvqShared; - } - | COHERENT { - $$.init($1.loc); - $$.qualifier.coherent = true; - } - | VOLATILE { - $$.init($1.loc); - $$.qualifier.volatil = true; - } - | RESTRICT { - $$.init($1.loc); - $$.qualifier.restrict = true; - } - | READONLY { - $$.init($1.loc); - $$.qualifier.readonly = true; - } - | WRITEONLY { - $$.init($1.loc); - $$.qualifier.writeonly = true; - } - | SUBROUTINE { - parseContext.spvRemoved($1.loc, "subroutine"); - parseContext.globalCheck($1.loc, "subroutine"); - parseContext.unimplemented($1.loc, "subroutine"); - $$.init($1.loc); - } - | SUBROUTINE LEFT_PAREN type_name_list RIGHT_PAREN { - parseContext.spvRemoved($1.loc, "subroutine"); - parseContext.globalCheck($1.loc, "subroutine"); - parseContext.unimplemented($1.loc, "subroutine"); - $$.init($1.loc); - } - ; - -non_uniform_qualifier - : NONUNIFORM { - $$.init($1.loc); - $$.qualifier.nonUniform = true; - } - ; - -type_name_list - : IDENTIFIER { - // TODO - } - | type_name_list COMMA IDENTIFIER { - // TODO: 4.0 semantics: subroutines - // 1) make sure each identifier is a type declared earlier with SUBROUTINE - // 2) save all of the identifiers for future comparison with the declared function - } - ; - -type_specifier - : type_specifier_nonarray { - $$ = $1; - $$.qualifier.precision = parseContext.getDefaultPrecision($$); - } - | type_specifier_nonarray array_specifier { - parseContext.arrayOfArrayVersionCheck($2.loc, $2.arraySizes); - $$ = $1; - $$.qualifier.precision = parseContext.getDefaultPrecision($$); - $$.arraySizes = $2.arraySizes; - } - ; - -array_specifier - : LEFT_BRACKET RIGHT_BRACKET { - $$.loc = $1.loc; - $$.arraySizes = new TArraySizes; - $$.arraySizes->addInnerSize(); - } - | LEFT_BRACKET conditional_expression RIGHT_BRACKET { - $$.loc = $1.loc; - $$.arraySizes = new TArraySizes; - - TArraySize size; - parseContext.arraySizeCheck($2->getLoc(), $2, size); - $$.arraySizes->addInnerSize(size); - } - | array_specifier LEFT_BRACKET RIGHT_BRACKET { - $$ = $1; - $$.arraySizes->addInnerSize(); - } - | array_specifier LEFT_BRACKET conditional_expression RIGHT_BRACKET { - $$ = $1; - - TArraySize size; - parseContext.arraySizeCheck($3->getLoc(), $3, size); - $$.arraySizes->addInnerSize(size); - } - ; - -type_specifier_nonarray - : VOID { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtVoid; - } - | FLOAT { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat; - } - | DOUBLE { - parseContext.doubleCheck($1.loc, "double"); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtDouble; - } - | FLOAT16_T { - parseContext.float16Check($1.loc, "float16_t", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat16; - } - | FLOAT32_T { - parseContext.explicitFloat32Check($1.loc, "float32_t", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat; - } - | FLOAT64_T { - parseContext.explicitFloat64Check($1.loc, "float64_t", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtDouble; - } - | INT { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtInt; - } - | UINT { - parseContext.fullIntegerCheck($1.loc, "unsigned integer"); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtUint; - } - | INT8_T { - parseContext.explicitInt8Check($1.loc, "8-bit signed integer", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtInt8; - } - | UINT8_T { - parseContext.explicitInt8Check($1.loc, "8-bit unsigned integer", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtUint8; - } - | INT16_T { - parseContext.explicitInt16Check($1.loc, "16-bit signed integer", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtInt16; - } - | UINT16_T { - parseContext.explicitInt16Check($1.loc, "16-bit unsigned integer", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtUint16; - } - | INT32_T { - parseContext.explicitInt32Check($1.loc, "32-bit signed integer", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtInt; - } - | UINT32_T { - parseContext.explicitInt32Check($1.loc, "32-bit unsigned integer", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtUint; - } - | INT64_T { - parseContext.int64Check($1.loc, "64-bit integer", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtInt64; - } - | UINT64_T { - parseContext.int64Check($1.loc, "64-bit unsigned integer", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtUint64; - } - | BOOL { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtBool; - } - | VEC2 { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat; - $$.setVector(2); - } - | VEC3 { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat; - $$.setVector(3); - } - | VEC4 { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat; - $$.setVector(4); - } - | DVEC2 { - parseContext.doubleCheck($1.loc, "double vector"); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtDouble; - $$.setVector(2); - } - | DVEC3 { - parseContext.doubleCheck($1.loc, "double vector"); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtDouble; - $$.setVector(3); - } - | DVEC4 { - parseContext.doubleCheck($1.loc, "double vector"); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtDouble; - $$.setVector(4); - } - | F16VEC2 { - parseContext.float16Check($1.loc, "half float vector", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat16; - $$.setVector(2); - } - | F16VEC3 { - parseContext.float16Check($1.loc, "half float vector", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat16; - $$.setVector(3); - } - | F16VEC4 { - parseContext.float16Check($1.loc, "half float vector", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat16; - $$.setVector(4); - } - | F32VEC2 { - parseContext.explicitFloat32Check($1.loc, "float32_t vector", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat; - $$.setVector(2); - } - | F32VEC3 { - parseContext.explicitFloat32Check($1.loc, "float32_t vector", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat; - $$.setVector(3); - } - | F32VEC4 { - parseContext.explicitFloat32Check($1.loc, "float32_t vector", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat; - $$.setVector(4); - } - | F64VEC2 { - parseContext.explicitFloat64Check($1.loc, "float64_t vector", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtDouble; - $$.setVector(2); - } - | F64VEC3 { - parseContext.explicitFloat64Check($1.loc, "float64_t vector", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtDouble; - $$.setVector(3); - } - | F64VEC4 { - parseContext.explicitFloat64Check($1.loc, "float64_t vector", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtDouble; - $$.setVector(4); - } - | BVEC2 { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtBool; - $$.setVector(2); - } - | BVEC3 { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtBool; - $$.setVector(3); - } - | BVEC4 { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtBool; - $$.setVector(4); - } - | IVEC2 { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtInt; - $$.setVector(2); - } - | IVEC3 { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtInt; - $$.setVector(3); - } - | IVEC4 { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtInt; - $$.setVector(4); - } - | I8VEC2 { - parseContext.explicitInt8Check($1.loc, "8-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtInt8; - $$.setVector(2); - } - | I8VEC3 { - parseContext.explicitInt8Check($1.loc, "8-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtInt8; - $$.setVector(3); - } - | I8VEC4 { - parseContext.explicitInt8Check($1.loc, "8-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtInt8; - $$.setVector(4); - } - | I16VEC2 { - parseContext.explicitInt16Check($1.loc, "16-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtInt16; - $$.setVector(2); - } - | I16VEC3 { - parseContext.explicitInt16Check($1.loc, "16-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtInt16; - $$.setVector(3); - } - | I16VEC4 { - parseContext.explicitInt16Check($1.loc, "16-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtInt16; - $$.setVector(4); - } - | I32VEC2 { - parseContext.explicitInt32Check($1.loc, "32-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtInt; - $$.setVector(2); - } - | I32VEC3 { - parseContext.explicitInt32Check($1.loc, "32-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtInt; - $$.setVector(3); - } - | I32VEC4 { - parseContext.explicitInt32Check($1.loc, "32-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtInt; - $$.setVector(4); - } - | I64VEC2 { - parseContext.int64Check($1.loc, "64-bit integer vector", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtInt64; - $$.setVector(2); - } - | I64VEC3 { - parseContext.int64Check($1.loc, "64-bit integer vector", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtInt64; - $$.setVector(3); - } - | I64VEC4 { - parseContext.int64Check($1.loc, "64-bit integer vector", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtInt64; - $$.setVector(4); - } - | UVEC2 { - parseContext.fullIntegerCheck($1.loc, "unsigned integer vector"); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtUint; - $$.setVector(2); - } - | UVEC3 { - parseContext.fullIntegerCheck($1.loc, "unsigned integer vector"); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtUint; - $$.setVector(3); - } - | UVEC4 { - parseContext.fullIntegerCheck($1.loc, "unsigned integer vector"); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtUint; - $$.setVector(4); - } - | U8VEC2 { - parseContext.explicitInt8Check($1.loc, "8-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtUint8; - $$.setVector(2); - } - | U8VEC3 { - parseContext.explicitInt8Check($1.loc, "8-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtInt8; - $$.setVector(3); - } - | U8VEC4 { - parseContext.explicitInt8Check($1.loc, "8-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtUint8; - $$.setVector(4); - } - | U16VEC2 { - parseContext.explicitInt16Check($1.loc, "16-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtUint16; - $$.setVector(2); - } - | U16VEC3 { - parseContext.explicitInt16Check($1.loc, "16-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtUint16; - $$.setVector(3); - } - | U16VEC4 { - parseContext.explicitInt16Check($1.loc, "16-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtUint16; - $$.setVector(4); - } - | U32VEC2 { - parseContext.explicitInt32Check($1.loc, "32-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtUint; - $$.setVector(2); - } - | U32VEC3 { - parseContext.explicitInt32Check($1.loc, "32-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtUint; - $$.setVector(3); - } - | U32VEC4 { - parseContext.explicitInt32Check($1.loc, "32-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtUint; - $$.setVector(4); - } - | U64VEC2 { - parseContext.int64Check($1.loc, "64-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtUint64; - $$.setVector(2); - } - | U64VEC3 { - parseContext.int64Check($1.loc, "64-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtUint64; - $$.setVector(3); - } - | U64VEC4 { - parseContext.int64Check($1.loc, "64-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtUint64; - $$.setVector(4); - } - | MAT2 { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat; - $$.setMatrix(2, 2); - } - | MAT3 { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat; - $$.setMatrix(3, 3); - } - | MAT4 { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat; - $$.setMatrix(4, 4); - } - | MAT2X2 { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat; - $$.setMatrix(2, 2); - } - | MAT2X3 { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat; - $$.setMatrix(2, 3); - } - | MAT2X4 { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat; - $$.setMatrix(2, 4); - } - | MAT3X2 { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat; - $$.setMatrix(3, 2); - } - | MAT3X3 { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat; - $$.setMatrix(3, 3); - } - | MAT3X4 { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat; - $$.setMatrix(3, 4); - } - | MAT4X2 { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat; - $$.setMatrix(4, 2); - } - | MAT4X3 { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat; - $$.setMatrix(4, 3); - } - | MAT4X4 { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat; - $$.setMatrix(4, 4); - } - | DMAT2 { - parseContext.doubleCheck($1.loc, "double matrix"); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtDouble; - $$.setMatrix(2, 2); - } - | DMAT3 { - parseContext.doubleCheck($1.loc, "double matrix"); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtDouble; - $$.setMatrix(3, 3); - } - | DMAT4 { - parseContext.doubleCheck($1.loc, "double matrix"); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtDouble; - $$.setMatrix(4, 4); - } - | DMAT2X2 { - parseContext.doubleCheck($1.loc, "double matrix"); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtDouble; - $$.setMatrix(2, 2); - } - | DMAT2X3 { - parseContext.doubleCheck($1.loc, "double matrix"); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtDouble; - $$.setMatrix(2, 3); - } - | DMAT2X4 { - parseContext.doubleCheck($1.loc, "double matrix"); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtDouble; - $$.setMatrix(2, 4); - } - | DMAT3X2 { - parseContext.doubleCheck($1.loc, "double matrix"); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtDouble; - $$.setMatrix(3, 2); - } - | DMAT3X3 { - parseContext.doubleCheck($1.loc, "double matrix"); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtDouble; - $$.setMatrix(3, 3); - } - | DMAT3X4 { - parseContext.doubleCheck($1.loc, "double matrix"); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtDouble; - $$.setMatrix(3, 4); - } - | DMAT4X2 { - parseContext.doubleCheck($1.loc, "double matrix"); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtDouble; - $$.setMatrix(4, 2); - } - | DMAT4X3 { - parseContext.doubleCheck($1.loc, "double matrix"); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtDouble; - $$.setMatrix(4, 3); - } - | DMAT4X4 { - parseContext.doubleCheck($1.loc, "double matrix"); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtDouble; - $$.setMatrix(4, 4); - } - | F16MAT2 { - parseContext.float16Check($1.loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat16; - $$.setMatrix(2, 2); - } - | F16MAT3 { - parseContext.float16Check($1.loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat16; - $$.setMatrix(3, 3); - } - | F16MAT4 { - parseContext.float16Check($1.loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat16; - $$.setMatrix(4, 4); - } - | F16MAT2X2 { - parseContext.float16Check($1.loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat16; - $$.setMatrix(2, 2); - } - | F16MAT2X3 { - parseContext.float16Check($1.loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat16; - $$.setMatrix(2, 3); - } - | F16MAT2X4 { - parseContext.float16Check($1.loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat16; - $$.setMatrix(2, 4); - } - | F16MAT3X2 { - parseContext.float16Check($1.loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat16; - $$.setMatrix(3, 2); - } - | F16MAT3X3 { - parseContext.float16Check($1.loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat16; - $$.setMatrix(3, 3); - } - | F16MAT3X4 { - parseContext.float16Check($1.loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat16; - $$.setMatrix(3, 4); - } - | F16MAT4X2 { - parseContext.float16Check($1.loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat16; - $$.setMatrix(4, 2); - } - | F16MAT4X3 { - parseContext.float16Check($1.loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat16; - $$.setMatrix(4, 3); - } - | F16MAT4X4 { - parseContext.float16Check($1.loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat16; - $$.setMatrix(4, 4); - } - | F32MAT2 { - parseContext.explicitFloat32Check($1.loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat; - $$.setMatrix(2, 2); - } - | F32MAT3 { - parseContext.explicitFloat32Check($1.loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat; - $$.setMatrix(3, 3); - } - | F32MAT4 { - parseContext.explicitFloat32Check($1.loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat; - $$.setMatrix(4, 4); - } - | F32MAT2X2 { - parseContext.explicitFloat32Check($1.loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat; - $$.setMatrix(2, 2); - } - | F32MAT2X3 { - parseContext.explicitFloat32Check($1.loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat; - $$.setMatrix(2, 3); - } - | F32MAT2X4 { - parseContext.explicitFloat32Check($1.loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat; - $$.setMatrix(2, 4); - } - | F32MAT3X2 { - parseContext.explicitFloat32Check($1.loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat; - $$.setMatrix(3, 2); - } - | F32MAT3X3 { - parseContext.explicitFloat32Check($1.loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat; - $$.setMatrix(3, 3); - } - | F32MAT3X4 { - parseContext.explicitFloat32Check($1.loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat; - $$.setMatrix(3, 4); - } - | F32MAT4X2 { - parseContext.explicitFloat32Check($1.loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat; - $$.setMatrix(4, 2); - } - | F32MAT4X3 { - parseContext.explicitFloat32Check($1.loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat; - $$.setMatrix(4, 3); - } - | F32MAT4X4 { - parseContext.explicitFloat32Check($1.loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat; - $$.setMatrix(4, 4); - } - | F64MAT2 { - parseContext.explicitFloat64Check($1.loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtDouble; - $$.setMatrix(2, 2); - } - | F64MAT3 { - parseContext.explicitFloat64Check($1.loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtDouble; - $$.setMatrix(3, 3); - } - | F64MAT4 { - parseContext.explicitFloat64Check($1.loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtDouble; - $$.setMatrix(4, 4); - } - | F64MAT2X2 { - parseContext.explicitFloat64Check($1.loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtDouble; - $$.setMatrix(2, 2); - } - | F64MAT2X3 { - parseContext.explicitFloat64Check($1.loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtDouble; - $$.setMatrix(2, 3); - } - | F64MAT2X4 { - parseContext.explicitFloat64Check($1.loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtDouble; - $$.setMatrix(2, 4); - } - | F64MAT3X2 { - parseContext.explicitFloat64Check($1.loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtDouble; - $$.setMatrix(3, 2); - } - | F64MAT3X3 { - parseContext.explicitFloat64Check($1.loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtDouble; - $$.setMatrix(3, 3); - } - | F64MAT3X4 { - parseContext.explicitFloat64Check($1.loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtDouble; - $$.setMatrix(3, 4); - } - | F64MAT4X2 { - parseContext.explicitFloat64Check($1.loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtDouble; - $$.setMatrix(4, 2); - } - | F64MAT4X3 { - parseContext.explicitFloat64Check($1.loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtDouble; - $$.setMatrix(4, 3); - } - | F64MAT4X4 { - parseContext.explicitFloat64Check($1.loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtDouble; - $$.setMatrix(4, 4); - } - | ATOMIC_UINT { - parseContext.vulkanRemoved($1.loc, "atomic counter types"); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtAtomicUint; - } - | SAMPLER1D { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtFloat, Esd1D); - } - | SAMPLER2D { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtFloat, Esd2D); - } - | SAMPLER3D { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtFloat, Esd3D); - } - | SAMPLERCUBE { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtFloat, EsdCube); - } - | SAMPLER1DSHADOW { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtFloat, Esd1D, false, true); - } - | SAMPLER2DSHADOW { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtFloat, Esd2D, false, true); - } - | SAMPLERCUBESHADOW { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtFloat, EsdCube, false, true); - } - | SAMPLER1DARRAY { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtFloat, Esd1D, true); - } - | SAMPLER2DARRAY { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtFloat, Esd2D, true); - } - | SAMPLER1DARRAYSHADOW { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtFloat, Esd1D, true, true); - } - | SAMPLER2DARRAYSHADOW { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtFloat, Esd2D, true, true); - } - | SAMPLERCUBEARRAY { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtFloat, EsdCube, true); - } - | SAMPLERCUBEARRAYSHADOW { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtFloat, EsdCube, true, true); - } - | F16SAMPLER1D { -#ifdef AMD_EXTENSIONS - parseContext.float16OpaqueCheck($1.loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtFloat16, Esd1D); -#endif - } - | F16SAMPLER2D { -#ifdef AMD_EXTENSIONS - parseContext.float16OpaqueCheck($1.loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtFloat16, Esd2D); -#endif - } - | F16SAMPLER3D { -#ifdef AMD_EXTENSIONS - parseContext.float16OpaqueCheck($1.loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtFloat16, Esd3D); -#endif - } - | F16SAMPLERCUBE { -#ifdef AMD_EXTENSIONS - parseContext.float16OpaqueCheck($1.loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtFloat16, EsdCube); -#endif - } - | F16SAMPLER1DSHADOW { -#ifdef AMD_EXTENSIONS - parseContext.float16OpaqueCheck($1.loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtFloat16, Esd1D, false, true); -#endif - } - | F16SAMPLER2DSHADOW { -#ifdef AMD_EXTENSIONS - parseContext.float16OpaqueCheck($1.loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtFloat16, Esd2D, false, true); -#endif - } - | F16SAMPLERCUBESHADOW { -#ifdef AMD_EXTENSIONS - parseContext.float16OpaqueCheck($1.loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtFloat16, EsdCube, false, true); -#endif - } - | F16SAMPLER1DARRAY { -#ifdef AMD_EXTENSIONS - parseContext.float16OpaqueCheck($1.loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtFloat16, Esd1D, true); -#endif - } - | F16SAMPLER2DARRAY { -#ifdef AMD_EXTENSIONS - parseContext.float16OpaqueCheck($1.loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtFloat16, Esd2D, true); -#endif - } - | F16SAMPLER1DARRAYSHADOW { -#ifdef AMD_EXTENSIONS - parseContext.float16OpaqueCheck($1.loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtFloat16, Esd1D, true, true); -#endif - } - | F16SAMPLER2DARRAYSHADOW { -#ifdef AMD_EXTENSIONS - parseContext.float16OpaqueCheck($1.loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtFloat16, Esd2D, true, true); -#endif - } - | F16SAMPLERCUBEARRAY { -#ifdef AMD_EXTENSIONS - parseContext.float16OpaqueCheck($1.loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtFloat16, EsdCube, true); -#endif - } - | F16SAMPLERCUBEARRAYSHADOW { -#ifdef AMD_EXTENSIONS - parseContext.float16OpaqueCheck($1.loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtFloat16, EsdCube, true, true); -#endif - } - | ISAMPLER1D { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtInt, Esd1D); - } - | ISAMPLER2D { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtInt, Esd2D); - } - | ISAMPLER3D { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtInt, Esd3D); - } - | ISAMPLERCUBE { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtInt, EsdCube); - } - | ISAMPLER1DARRAY { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtInt, Esd1D, true); - } - | ISAMPLER2DARRAY { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtInt, Esd2D, true); - } - | ISAMPLERCUBEARRAY { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtInt, EsdCube, true); - } - | USAMPLER1D { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtUint, Esd1D); - } - | USAMPLER2D { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtUint, Esd2D); - } - | USAMPLER3D { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtUint, Esd3D); - } - | USAMPLERCUBE { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtUint, EsdCube); - } - | USAMPLER1DARRAY { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtUint, Esd1D, true); - } - | USAMPLER2DARRAY { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtUint, Esd2D, true); - } - | USAMPLERCUBEARRAY { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtUint, EsdCube, true); - } - | SAMPLER2DRECT { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtFloat, EsdRect); - } - | SAMPLER2DRECTSHADOW { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtFloat, EsdRect, false, true); - } - | F16SAMPLER2DRECT { -#ifdef AMD_EXTENSIONS - parseContext.float16OpaqueCheck($1.loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtFloat16, EsdRect); -#endif - } - | F16SAMPLER2DRECTSHADOW { -#ifdef AMD_EXTENSIONS - parseContext.float16OpaqueCheck($1.loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtFloat16, EsdRect, false, true); -#endif - } - | ISAMPLER2DRECT { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtInt, EsdRect); - } - | USAMPLER2DRECT { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtUint, EsdRect); - } - | SAMPLERBUFFER { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtFloat, EsdBuffer); - } - | F16SAMPLERBUFFER { -#ifdef AMD_EXTENSIONS - parseContext.float16OpaqueCheck($1.loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtFloat16, EsdBuffer); -#endif - } - | ISAMPLERBUFFER { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtInt, EsdBuffer); - } - | USAMPLERBUFFER { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtUint, EsdBuffer); - } - | SAMPLER2DMS { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtFloat, Esd2D, false, false, true); - } - | F16SAMPLER2DMS { -#ifdef AMD_EXTENSIONS - parseContext.float16OpaqueCheck($1.loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtFloat16, Esd2D, false, false, true); -#endif - } - | ISAMPLER2DMS { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtInt, Esd2D, false, false, true); - } - | USAMPLER2DMS { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtUint, Esd2D, false, false, true); - } - | SAMPLER2DMSARRAY { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtFloat, Esd2D, true, false, true); - } - | F16SAMPLER2DMSARRAY { -#ifdef AMD_EXTENSIONS - parseContext.float16OpaqueCheck($1.loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtFloat16, Esd2D, true, false, true); -#endif - } - | ISAMPLER2DMSARRAY { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtInt, Esd2D, true, false, true); - } - | USAMPLER2DMSARRAY { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtUint, Esd2D, true, false, true); - } - | SAMPLER { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setPureSampler(false); - } - | SAMPLERSHADOW { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setPureSampler(true); - } - | TEXTURE1D { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setTexture(EbtFloat, Esd1D); - } - | F16TEXTURE1D { -#ifdef AMD_EXTENSIONS - parseContext.float16OpaqueCheck($1.loc, "half float texture", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setTexture(EbtFloat16, Esd1D); -#endif - } - | TEXTURE2D { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setTexture(EbtFloat, Esd2D); - } - | F16TEXTURE2D { -#ifdef AMD_EXTENSIONS - parseContext.float16OpaqueCheck($1.loc, "half float texture", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setTexture(EbtFloat16, Esd2D); -#endif - } - | TEXTURE3D { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setTexture(EbtFloat, Esd3D); - } - | F16TEXTURE3D { -#ifdef AMD_EXTENSIONS - parseContext.float16OpaqueCheck($1.loc, "half float texture", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setTexture(EbtFloat16, Esd3D); -#endif - } - | TEXTURECUBE { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setTexture(EbtFloat, EsdCube); - } - | F16TEXTURECUBE { -#ifdef AMD_EXTENSIONS - parseContext.float16OpaqueCheck($1.loc, "half float texture", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setTexture(EbtFloat16, EsdCube); -#endif - } - | TEXTURE1DARRAY { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setTexture(EbtFloat, Esd1D, true); - } - | F16TEXTURE1DARRAY { -#ifdef AMD_EXTENSIONS - parseContext.float16OpaqueCheck($1.loc, "half float texture", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setTexture(EbtFloat16, Esd1D, true); -#endif - } - | TEXTURE2DARRAY { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setTexture(EbtFloat, Esd2D, true); - } - | F16TEXTURE2DARRAY { -#ifdef AMD_EXTENSIONS - parseContext.float16OpaqueCheck($1.loc, "half float texture", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setTexture(EbtFloat16, Esd2D, true); -#endif - } - | TEXTURECUBEARRAY { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setTexture(EbtFloat, EsdCube, true); - } - | F16TEXTURECUBEARRAY { -#ifdef AMD_EXTENSIONS - parseContext.float16OpaqueCheck($1.loc, "half float texture", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setTexture(EbtFloat16, EsdCube, true); -#endif - } - | ITEXTURE1D { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setTexture(EbtInt, Esd1D); - } - | ITEXTURE2D { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setTexture(EbtInt, Esd2D); - } - | ITEXTURE3D { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setTexture(EbtInt, Esd3D); - } - | ITEXTURECUBE { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setTexture(EbtInt, EsdCube); - } - | ITEXTURE1DARRAY { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setTexture(EbtInt, Esd1D, true); - } - | ITEXTURE2DARRAY { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setTexture(EbtInt, Esd2D, true); - } - | ITEXTURECUBEARRAY { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setTexture(EbtInt, EsdCube, true); - } - | UTEXTURE1D { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setTexture(EbtUint, Esd1D); - } - | UTEXTURE2D { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setTexture(EbtUint, Esd2D); - } - | UTEXTURE3D { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setTexture(EbtUint, Esd3D); - } - | UTEXTURECUBE { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setTexture(EbtUint, EsdCube); - } - | UTEXTURE1DARRAY { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setTexture(EbtUint, Esd1D, true); - } - | UTEXTURE2DARRAY { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setTexture(EbtUint, Esd2D, true); - } - | UTEXTURECUBEARRAY { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setTexture(EbtUint, EsdCube, true); - } - | TEXTURE2DRECT { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setTexture(EbtFloat, EsdRect); - } - | F16TEXTURE2DRECT { -#ifdef AMD_EXTENSIONS - parseContext.float16OpaqueCheck($1.loc, "half float texture", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setTexture(EbtFloat16, EsdRect); -#endif - } - | ITEXTURE2DRECT { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setTexture(EbtInt, EsdRect); - } - | UTEXTURE2DRECT { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setTexture(EbtUint, EsdRect); - } - | TEXTUREBUFFER { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setTexture(EbtFloat, EsdBuffer); - } - | F16TEXTUREBUFFER { -#ifdef AMD_EXTENSIONS - parseContext.float16OpaqueCheck($1.loc, "half float texture", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setTexture(EbtFloat16, EsdBuffer); -#endif - } - | ITEXTUREBUFFER { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setTexture(EbtInt, EsdBuffer); - } - | UTEXTUREBUFFER { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setTexture(EbtUint, EsdBuffer); - } - | TEXTURE2DMS { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setTexture(EbtFloat, Esd2D, false, false, true); - } - | F16TEXTURE2DMS { -#ifdef AMD_EXTENSIONS - parseContext.float16OpaqueCheck($1.loc, "half float texture", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setTexture(EbtFloat16, Esd2D, false, false, true); -#endif - } - | ITEXTURE2DMS { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setTexture(EbtInt, Esd2D, false, false, true); - } - | UTEXTURE2DMS { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setTexture(EbtUint, Esd2D, false, false, true); - } - | TEXTURE2DMSARRAY { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setTexture(EbtFloat, Esd2D, true, false, true); - } - | F16TEXTURE2DMSARRAY { -#ifdef AMD_EXTENSIONS - parseContext.float16OpaqueCheck($1.loc, "half float texture", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setTexture(EbtFloat16, Esd2D, true, false, true); -#endif - } - | ITEXTURE2DMSARRAY { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setTexture(EbtInt, Esd2D, true, false, true); - } - | UTEXTURE2DMSARRAY { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setTexture(EbtUint, Esd2D, true, false, true); - } - | IMAGE1D { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtFloat, Esd1D); - } - | F16IMAGE1D { -#ifdef AMD_EXTENSIONS - parseContext.float16OpaqueCheck($1.loc, "half float image", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtFloat16, Esd1D); -#endif - } - | IIMAGE1D { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtInt, Esd1D); - } - | UIMAGE1D { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtUint, Esd1D); - } - | IMAGE2D { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtFloat, Esd2D); - } - | F16IMAGE2D { -#ifdef AMD_EXTENSIONS - parseContext.float16OpaqueCheck($1.loc, "half float image", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtFloat16, Esd2D); -#endif - } - | IIMAGE2D { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtInt, Esd2D); - } - | UIMAGE2D { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtUint, Esd2D); - } - | IMAGE3D { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtFloat, Esd3D); - } - | F16IMAGE3D { -#ifdef AMD_EXTENSIONS - parseContext.float16OpaqueCheck($1.loc, "half float image", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtFloat16, Esd3D); -#endif - } - | IIMAGE3D { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtInt, Esd3D); - } - | UIMAGE3D { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtUint, Esd3D); - } - | IMAGE2DRECT { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtFloat, EsdRect); - } - | F16IMAGE2DRECT { -#ifdef AMD_EXTENSIONS - parseContext.float16OpaqueCheck($1.loc, "half float image", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtFloat16, EsdRect); -#endif - } - | IIMAGE2DRECT { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtInt, EsdRect); - } - | UIMAGE2DRECT { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtUint, EsdRect); - } - | IMAGECUBE { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtFloat, EsdCube); - } - | F16IMAGECUBE { -#ifdef AMD_EXTENSIONS - parseContext.float16OpaqueCheck($1.loc, "half float image", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtFloat16, EsdCube); -#endif - } - | IIMAGECUBE { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtInt, EsdCube); - } - | UIMAGECUBE { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtUint, EsdCube); - } - | IMAGEBUFFER { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtFloat, EsdBuffer); - } - | F16IMAGEBUFFER { -#ifdef AMD_EXTENSIONS - parseContext.float16OpaqueCheck($1.loc, "half float image", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtFloat16, EsdBuffer); -#endif - } - | IIMAGEBUFFER { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtInt, EsdBuffer); - } - | UIMAGEBUFFER { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtUint, EsdBuffer); - } - | IMAGE1DARRAY { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtFloat, Esd1D, true); - } - | F16IMAGE1DARRAY { -#ifdef AMD_EXTENSIONS - parseContext.float16OpaqueCheck($1.loc, "half float image", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtFloat16, Esd1D, true); -#endif - } - | IIMAGE1DARRAY { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtInt, Esd1D, true); - } - | UIMAGE1DARRAY { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtUint, Esd1D, true); - } - | IMAGE2DARRAY { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtFloat, Esd2D, true); - } - | F16IMAGE2DARRAY { -#ifdef AMD_EXTENSIONS - parseContext.float16OpaqueCheck($1.loc, "half float image", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtFloat16, Esd2D, true); -#endif - } - | IIMAGE2DARRAY { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtInt, Esd2D, true); - } - | UIMAGE2DARRAY { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtUint, Esd2D, true); - } - | IMAGECUBEARRAY { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtFloat, EsdCube, true); - } - | F16IMAGECUBEARRAY { -#ifdef AMD_EXTENSIONS - parseContext.float16OpaqueCheck($1.loc, "half float image", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtFloat16, EsdCube, true); -#endif - } - | IIMAGECUBEARRAY { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtInt, EsdCube, true); - } - | UIMAGECUBEARRAY { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtUint, EsdCube, true); - } - | IMAGE2DMS { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtFloat, Esd2D, false, false, true); - } - | F16IMAGE2DMS { -#ifdef AMD_EXTENSIONS - parseContext.float16OpaqueCheck($1.loc, "half float image", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtFloat16, Esd2D, false, false, true); -#endif - } - | IIMAGE2DMS { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtInt, Esd2D, false, false, true); - } - | UIMAGE2DMS { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtUint, Esd2D, false, false, true); - } - | IMAGE2DMSARRAY { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtFloat, Esd2D, true, false, true); - } - | F16IMAGE2DMSARRAY { -#ifdef AMD_EXTENSIONS - parseContext.float16OpaqueCheck($1.loc, "half float image", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtFloat16, Esd2D, true, false, true); -#endif - } - | IIMAGE2DMSARRAY { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtInt, Esd2D, true, false, true); - } - | UIMAGE2DMSARRAY { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtUint, Esd2D, true, false, true); - } - | SAMPLEREXTERNALOES { // GL_OES_EGL_image_external - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtFloat, Esd2D); - $$.sampler.external = true; - } - | SUBPASSINPUT { - parseContext.requireStage($1.loc, EShLangFragment, "subpass input"); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setSubpass(EbtFloat); - } - | SUBPASSINPUTMS { - parseContext.requireStage($1.loc, EShLangFragment, "subpass input"); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setSubpass(EbtFloat, true); - } - | F16SUBPASSINPUT { -#ifdef AMD_EXTENSIONS - parseContext.float16OpaqueCheck($1.loc, "half float subpass input", parseContext.symbolTable.atBuiltInLevel()); - parseContext.requireStage($1.loc, EShLangFragment, "subpass input"); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setSubpass(EbtFloat16); -#endif - } - | F16SUBPASSINPUTMS { -#ifdef AMD_EXTENSIONS - parseContext.float16OpaqueCheck($1.loc, "half float subpass input", parseContext.symbolTable.atBuiltInLevel()); - parseContext.requireStage($1.loc, EShLangFragment, "subpass input"); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setSubpass(EbtFloat16, true); -#endif - } - | ISUBPASSINPUT { - parseContext.requireStage($1.loc, EShLangFragment, "subpass input"); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setSubpass(EbtInt); - } - | ISUBPASSINPUTMS { - parseContext.requireStage($1.loc, EShLangFragment, "subpass input"); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setSubpass(EbtInt, true); - } - | USUBPASSINPUT { - parseContext.requireStage($1.loc, EShLangFragment, "subpass input"); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setSubpass(EbtUint); - } - | USUBPASSINPUTMS { - parseContext.requireStage($1.loc, EShLangFragment, "subpass input"); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setSubpass(EbtUint, true); - } - | struct_specifier { - $$ = $1; - $$.qualifier.storage = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - parseContext.structTypeCheck($$.loc, $$); - } - | TYPE_NAME { - // - // This is for user defined type names. The lexical phase looked up the - // type. - // - if (const TVariable* variable = ($1.symbol)->getAsVariable()) { - const TType& structure = variable->getType(); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtStruct; - $$.userDef = &structure; - } else - parseContext.error($1.loc, "expected type name", $1.string->c_str(), ""); - } - ; - -precision_qualifier - : HIGH_PRECISION { - parseContext.profileRequires($1.loc, ENoProfile, 130, 0, "highp precision qualifier"); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - parseContext.handlePrecisionQualifier($1.loc, $$.qualifier, EpqHigh); - } - | MEDIUM_PRECISION { - parseContext.profileRequires($1.loc, ENoProfile, 130, 0, "mediump precision qualifier"); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - parseContext.handlePrecisionQualifier($1.loc, $$.qualifier, EpqMedium); - } - | LOW_PRECISION { - parseContext.profileRequires($1.loc, ENoProfile, 130, 0, "lowp precision qualifier"); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - parseContext.handlePrecisionQualifier($1.loc, $$.qualifier, EpqLow); - } - ; - -struct_specifier - : STRUCT IDENTIFIER LEFT_BRACE { parseContext.nestedStructCheck($1.loc); } struct_declaration_list RIGHT_BRACE { - TType* structure = new TType($5, *$2.string); - parseContext.structArrayCheck($2.loc, *structure); - TVariable* userTypeDef = new TVariable($2.string, *structure, true); - if (! parseContext.symbolTable.insert(*userTypeDef)) - parseContext.error($2.loc, "redefinition", $2.string->c_str(), "struct"); - $$.init($1.loc); - $$.basicType = EbtStruct; - $$.userDef = structure; - --parseContext.structNestingLevel; - } - | STRUCT LEFT_BRACE { parseContext.nestedStructCheck($1.loc); } struct_declaration_list RIGHT_BRACE { - TType* structure = new TType($4, TString("")); - $$.init($1.loc); - $$.basicType = EbtStruct; - $$.userDef = structure; - --parseContext.structNestingLevel; - } - ; - -struct_declaration_list - : struct_declaration { - $$ = $1; - } - | struct_declaration_list struct_declaration { - $$ = $1; - for (unsigned int i = 0; i < $2->size(); ++i) { - for (unsigned int j = 0; j < $$->size(); ++j) { - if ((*$$)[j].type->getFieldName() == (*$2)[i].type->getFieldName()) - parseContext.error((*$2)[i].loc, "duplicate member name:", "", (*$2)[i].type->getFieldName().c_str()); - } - $$->push_back((*$2)[i]); - } - } - ; - -struct_declaration - : type_specifier struct_declarator_list SEMICOLON { - if ($1.arraySizes) { - parseContext.profileRequires($1.loc, ENoProfile, 120, E_GL_3DL_array_objects, "arrayed type"); - parseContext.profileRequires($1.loc, EEsProfile, 300, 0, "arrayed type"); - if (parseContext.profile == EEsProfile) - parseContext.arraySizeRequiredCheck($1.loc, *$1.arraySizes); - } - - $$ = $2; - - parseContext.voidErrorCheck($1.loc, (*$2)[0].type->getFieldName(), $1.basicType); - parseContext.precisionQualifierCheck($1.loc, $1.basicType, $1.qualifier); - - for (unsigned int i = 0; i < $$->size(); ++i) { - TType type($1); - type.setFieldName((*$$)[i].type->getFieldName()); - type.transferArraySizes((*$$)[i].type->getArraySizes()); - type.copyArrayInnerSizes($1.arraySizes); - parseContext.arrayOfArrayVersionCheck((*$$)[i].loc, type.getArraySizes()); - (*$$)[i].type->shallowCopy(type); - } - } - | type_qualifier type_specifier struct_declarator_list SEMICOLON { - if ($2.arraySizes) { - parseContext.profileRequires($2.loc, ENoProfile, 120, E_GL_3DL_array_objects, "arrayed type"); - parseContext.profileRequires($2.loc, EEsProfile, 300, 0, "arrayed type"); - if (parseContext.profile == EEsProfile) - parseContext.arraySizeRequiredCheck($2.loc, *$2.arraySizes); - } - - $$ = $3; - - parseContext.memberQualifierCheck($1); - parseContext.voidErrorCheck($2.loc, (*$3)[0].type->getFieldName(), $2.basicType); - parseContext.mergeQualifiers($2.loc, $2.qualifier, $1.qualifier, true); - parseContext.precisionQualifierCheck($2.loc, $2.basicType, $2.qualifier); - - for (unsigned int i = 0; i < $$->size(); ++i) { - TType type($2); - type.setFieldName((*$$)[i].type->getFieldName()); - type.transferArraySizes((*$$)[i].type->getArraySizes()); - type.copyArrayInnerSizes($2.arraySizes); - parseContext.arrayOfArrayVersionCheck((*$$)[i].loc, type.getArraySizes()); - (*$$)[i].type->shallowCopy(type); - } - } - ; - -struct_declarator_list - : struct_declarator { - $$ = new TTypeList; - $$->push_back($1); - } - | struct_declarator_list COMMA struct_declarator { - $$->push_back($3); - } - ; - -struct_declarator - : IDENTIFIER { - $$.type = new TType(EbtVoid); - $$.loc = $1.loc; - $$.type->setFieldName(*$1.string); - } - | IDENTIFIER array_specifier { - parseContext.arrayOfArrayVersionCheck($1.loc, $2.arraySizes); - - $$.type = new TType(EbtVoid); - $$.loc = $1.loc; - $$.type->setFieldName(*$1.string); - $$.type->transferArraySizes($2.arraySizes); - } - ; - -initializer - : assignment_expression { - $$ = $1; - } - | LEFT_BRACE initializer_list RIGHT_BRACE { - const char* initFeature = "{ } style initializers"; - parseContext.requireProfile($1.loc, ~EEsProfile, initFeature); - parseContext.profileRequires($1.loc, ~EEsProfile, 420, E_GL_ARB_shading_language_420pack, initFeature); - $$ = $2; - } - | LEFT_BRACE initializer_list COMMA RIGHT_BRACE { - const char* initFeature = "{ } style initializers"; - parseContext.requireProfile($1.loc, ~EEsProfile, initFeature); - parseContext.profileRequires($1.loc, ~EEsProfile, 420, E_GL_ARB_shading_language_420pack, initFeature); - $$ = $2; - } - ; - -initializer_list - : initializer { - $$ = parseContext.intermediate.growAggregate(0, $1, $1->getLoc()); - } - | initializer_list COMMA initializer { - $$ = parseContext.intermediate.growAggregate($1, $3); - } - ; - -declaration_statement - : declaration { $$ = $1; } - ; - -statement - : compound_statement { $$ = $1; } - | simple_statement { $$ = $1; } - ; - -// Grammar Note: labeled statements for switch statements only; 'goto' is not supported. - -simple_statement - : declaration_statement { $$ = $1; } - | expression_statement { $$ = $1; } - | selection_statement { $$ = $1; } - | switch_statement { $$ = $1; } - | case_label { $$ = $1; } - | iteration_statement { $$ = $1; } - | jump_statement { $$ = $1; } - ; - -compound_statement - : LEFT_BRACE RIGHT_BRACE { $$ = 0; } - | LEFT_BRACE { - parseContext.symbolTable.push(); - ++parseContext.statementNestingLevel; - } - statement_list { - parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]); - --parseContext.statementNestingLevel; - } - RIGHT_BRACE { - if ($3 && $3->getAsAggregate()) - $3->getAsAggregate()->setOperator(EOpSequence); - $$ = $3; - } - ; - -statement_no_new_scope - : compound_statement_no_new_scope { $$ = $1; } - | simple_statement { $$ = $1; } - ; - -statement_scoped - : { - ++parseContext.controlFlowNestingLevel; - } - compound_statement { - --parseContext.controlFlowNestingLevel; - $$ = $2; - } - | { - parseContext.symbolTable.push(); - ++parseContext.statementNestingLevel; - ++parseContext.controlFlowNestingLevel; - } - simple_statement { - parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]); - --parseContext.statementNestingLevel; - --parseContext.controlFlowNestingLevel; - $$ = $2; - } - -compound_statement_no_new_scope - // Statement that doesn't create a new scope, for selection_statement, iteration_statement - : LEFT_BRACE RIGHT_BRACE { - $$ = 0; - } - | LEFT_BRACE statement_list RIGHT_BRACE { - if ($2 && $2->getAsAggregate()) - $2->getAsAggregate()->setOperator(EOpSequence); - $$ = $2; - } - ; - -statement_list - : statement { - $$ = parseContext.intermediate.makeAggregate($1); - if ($1 && $1->getAsBranchNode() && ($1->getAsBranchNode()->getFlowOp() == EOpCase || - $1->getAsBranchNode()->getFlowOp() == EOpDefault)) { - parseContext.wrapupSwitchSubsequence(0, $1); - $$ = 0; // start a fresh subsequence for what's after this case - } - } - | statement_list statement { - if ($2 && $2->getAsBranchNode() && ($2->getAsBranchNode()->getFlowOp() == EOpCase || - $2->getAsBranchNode()->getFlowOp() == EOpDefault)) { - parseContext.wrapupSwitchSubsequence($1 ? $1->getAsAggregate() : 0, $2); - $$ = 0; // start a fresh subsequence for what's after this case - } else - $$ = parseContext.intermediate.growAggregate($1, $2); - } - ; - -expression_statement - : SEMICOLON { $$ = 0; } - | expression SEMICOLON { $$ = static_cast($1); } - ; - -selection_statement - : selection_statement_nonattributed { - $$ = $1; - } - | attribute selection_statement_nonattributed { - parseContext.handleSelectionAttributes(*$1, $2); - $$ = $2; - } - -selection_statement_nonattributed - : IF LEFT_PAREN expression RIGHT_PAREN selection_rest_statement { - parseContext.boolCheck($1.loc, $3); - $$ = parseContext.intermediate.addSelection($3, $5, $1.loc); - } - ; - -selection_rest_statement - : statement_scoped ELSE statement_scoped { - $$.node1 = $1; - $$.node2 = $3; - } - | statement_scoped { - $$.node1 = $1; - $$.node2 = 0; - } - ; - -condition - // In 1996 c++ draft, conditions can include single declarations - : expression { - $$ = $1; - parseContext.boolCheck($1->getLoc(), $1); - } - | fully_specified_type IDENTIFIER EQUAL initializer { - parseContext.boolCheck($2.loc, $1); - - TType type($1); - TIntermNode* initNode = parseContext.declareVariable($2.loc, *$2.string, $1, 0, $4); - if (initNode) - $$ = initNode->getAsTyped(); - else - $$ = 0; - } - ; - -switch_statement - : switch_statement_nonattributed { - $$ = $1; - } - | attribute switch_statement_nonattributed { - parseContext.handleSwitchAttributes(*$1, $2); - $$ = $2; - } - -switch_statement_nonattributed - : SWITCH LEFT_PAREN expression RIGHT_PAREN { - // start new switch sequence on the switch stack - ++parseContext.controlFlowNestingLevel; - ++parseContext.statementNestingLevel; - parseContext.switchSequenceStack.push_back(new TIntermSequence); - parseContext.switchLevel.push_back(parseContext.statementNestingLevel); - parseContext.symbolTable.push(); - } - LEFT_BRACE switch_statement_list RIGHT_BRACE { - $$ = parseContext.addSwitch($1.loc, $3, $7 ? $7->getAsAggregate() : 0); - delete parseContext.switchSequenceStack.back(); - parseContext.switchSequenceStack.pop_back(); - parseContext.switchLevel.pop_back(); - parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]); - --parseContext.statementNestingLevel; - --parseContext.controlFlowNestingLevel; - } - ; - -switch_statement_list - : /* nothing */ { - $$ = 0; - } - | statement_list { - $$ = $1; - } - ; - -case_label - : CASE expression COLON { - $$ = 0; - if (parseContext.switchLevel.size() == 0) - parseContext.error($1.loc, "cannot appear outside switch statement", "case", ""); - else if (parseContext.switchLevel.back() != parseContext.statementNestingLevel) - parseContext.error($1.loc, "cannot be nested inside control flow", "case", ""); - else { - parseContext.constantValueCheck($2, "case"); - parseContext.integerCheck($2, "case"); - $$ = parseContext.intermediate.addBranch(EOpCase, $2, $1.loc); - } - } - | DEFAULT COLON { - $$ = 0; - if (parseContext.switchLevel.size() == 0) - parseContext.error($1.loc, "cannot appear outside switch statement", "default", ""); - else if (parseContext.switchLevel.back() != parseContext.statementNestingLevel) - parseContext.error($1.loc, "cannot be nested inside control flow", "default", ""); - else - $$ = parseContext.intermediate.addBranch(EOpDefault, $1.loc); - } - ; - -iteration_statement - : iteration_statement_nonattributed { - $$ = $1; - } - | attribute iteration_statement_nonattributed { - parseContext.handleLoopAttributes(*$1, $2); - $$ = $2; - } - -iteration_statement_nonattributed - : WHILE LEFT_PAREN { - if (! parseContext.limits.whileLoops) - parseContext.error($1.loc, "while loops not available", "limitation", ""); - parseContext.symbolTable.push(); - ++parseContext.loopNestingLevel; - ++parseContext.statementNestingLevel; - ++parseContext.controlFlowNestingLevel; - } - condition RIGHT_PAREN statement_no_new_scope { - parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]); - $$ = parseContext.intermediate.addLoop($6, $4, 0, true, $1.loc); - --parseContext.loopNestingLevel; - --parseContext.statementNestingLevel; - --parseContext.controlFlowNestingLevel; - } - | DO { - ++parseContext.loopNestingLevel; - ++parseContext.statementNestingLevel; - ++parseContext.controlFlowNestingLevel; - } - statement WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON { - if (! parseContext.limits.whileLoops) - parseContext.error($1.loc, "do-while loops not available", "limitation", ""); - - parseContext.boolCheck($8.loc, $6); - - $$ = parseContext.intermediate.addLoop($3, $6, 0, false, $4.loc); - --parseContext.loopNestingLevel; - --parseContext.statementNestingLevel; - --parseContext.controlFlowNestingLevel; - } - | FOR LEFT_PAREN { - parseContext.symbolTable.push(); - ++parseContext.loopNestingLevel; - ++parseContext.statementNestingLevel; - ++parseContext.controlFlowNestingLevel; - } - for_init_statement for_rest_statement RIGHT_PAREN statement_no_new_scope { - parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]); - $$ = parseContext.intermediate.makeAggregate($4, $2.loc); - TIntermLoop* forLoop = parseContext.intermediate.addLoop($7, reinterpret_cast($5.node1), reinterpret_cast($5.node2), true, $1.loc); - if (! parseContext.limits.nonInductiveForLoops) - parseContext.inductiveLoopCheck($1.loc, $4, forLoop); - $$ = parseContext.intermediate.growAggregate($$, forLoop, $1.loc); - $$->getAsAggregate()->setOperator(EOpSequence); - --parseContext.loopNestingLevel; - --parseContext.statementNestingLevel; - --parseContext.controlFlowNestingLevel; - } - ; - -for_init_statement - : expression_statement { - $$ = $1; - } - | declaration_statement { - $$ = $1; - } - ; - -conditionopt - : condition { - $$ = $1; - } - | /* May be null */ { - $$ = 0; - } - ; - -for_rest_statement - : conditionopt SEMICOLON { - $$.node1 = $1; - $$.node2 = 0; - } - | conditionopt SEMICOLON expression { - $$.node1 = $1; - $$.node2 = $3; - } - ; - -jump_statement - : CONTINUE SEMICOLON { - if (parseContext.loopNestingLevel <= 0) - parseContext.error($1.loc, "continue statement only allowed in loops", "", ""); - $$ = parseContext.intermediate.addBranch(EOpContinue, $1.loc); - } - | BREAK SEMICOLON { - if (parseContext.loopNestingLevel + parseContext.switchSequenceStack.size() <= 0) - parseContext.error($1.loc, "break statement only allowed in switch and loops", "", ""); - $$ = parseContext.intermediate.addBranch(EOpBreak, $1.loc); - } - | RETURN SEMICOLON { - $$ = parseContext.intermediate.addBranch(EOpReturn, $1.loc); - if (parseContext.currentFunctionType->getBasicType() != EbtVoid) - parseContext.error($1.loc, "non-void function must return a value", "return", ""); - if (parseContext.inMain) - parseContext.postEntryPointReturn = true; - } - | RETURN expression SEMICOLON { - $$ = parseContext.handleReturnValue($1.loc, $2); - } - | DISCARD SEMICOLON { - parseContext.requireStage($1.loc, EShLangFragment, "discard"); - $$ = parseContext.intermediate.addBranch(EOpKill, $1.loc); - } - ; - -// Grammar Note: No 'goto'. Gotos are not supported. - -translation_unit - : external_declaration { - $$ = $1; - parseContext.intermediate.setTreeRoot($$); - } - | translation_unit external_declaration { - if ($2 != nullptr) { - $$ = parseContext.intermediate.growAggregate($1, $2); - parseContext.intermediate.setTreeRoot($$); - } - } - ; - -external_declaration - : function_definition { - $$ = $1; - } - | declaration { - $$ = $1; - } - | SEMICOLON { - parseContext.requireProfile($1.loc, ~EEsProfile, "extraneous semicolon"); - parseContext.profileRequires($1.loc, ~EEsProfile, 460, nullptr, "extraneous semicolon"); - $$ = nullptr; - } - ; - -function_definition - : function_prototype { - $1.function = parseContext.handleFunctionDeclarator($1.loc, *$1.function, false /* not prototype */); - $1.intermNode = parseContext.handleFunctionDefinition($1.loc, *$1.function); - } - compound_statement_no_new_scope { - // May be best done as post process phase on intermediate code - if (parseContext.currentFunctionType->getBasicType() != EbtVoid && ! parseContext.functionReturnsValue) - parseContext.error($1.loc, "function does not return a value:", "", $1.function->getName().c_str()); - parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]); - $$ = parseContext.intermediate.growAggregate($1.intermNode, $3); - parseContext.intermediate.setAggregateOperator($$, EOpFunction, $1.function->getType(), $1.loc); - $$->getAsAggregate()->setName($1.function->getMangledName().c_str()); - - // store the pragma information for debug and optimize and other vendor specific - // information. This information can be queried from the parse tree - $$->getAsAggregate()->setOptimize(parseContext.contextPragma.optimize); - $$->getAsAggregate()->setDebug(parseContext.contextPragma.debug); - $$->getAsAggregate()->setPragmaTable(parseContext.contextPragma.pragmaTable); - } - ; - -attribute - : LEFT_BRACKET LEFT_BRACKET attribute_list RIGHT_BRACKET RIGHT_BRACKET { - $$ = $3; - parseContext.requireExtensions($1.loc, 1, &E_GL_EXT_control_flow_attributes, "attribute"); - } - -attribute_list - : single_attribute { - $$ = $1; - } - | attribute_list COMMA single_attribute { - $$ = parseContext.mergeAttributes($1, $3); - } - -single_attribute - : IDENTIFIER { - $$ = parseContext.makeAttributes(*$1.string); - } - | IDENTIFIER LEFT_PAREN constant_expression RIGHT_PAREN { - $$ = parseContext.makeAttributes(*$1.string, $3); - } - -%% diff --git a/External/glslang/glslang/MachineIndependent/glslang_tab.cpp b/External/glslang/glslang/MachineIndependent/glslang_tab.cpp deleted file mode 100644 index 38672d67..00000000 --- a/External/glslang/glslang/MachineIndependent/glslang_tab.cpp +++ /dev/null @@ -1,10051 +0,0 @@ -/* A Bison parser, made by GNU Bison 3.0. */ - -/* Bison implementation for Yacc-like parsers in C - - Copyright (C) 1984, 1989-1990, 2000-2013 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. */ - -/* C LALR(1) parser skeleton written by Richard Stallman, by - simplifying the original so-called "semantic" parser. */ - -/* All symbols defined below should begin with yy or YY, to avoid - infringing on user name space. This should be done even for local - variables, as they might otherwise be expanded by user macros. - There are some unavoidable exceptions within include files to - define necessary library symbols; they are noted "INFRINGES ON - USER NAME SPACE" below. */ - -/* Identify Bison output. */ -#define YYBISON 1 - -/* Bison version. */ -#define YYBISON_VERSION "3.0" - -/* Skeleton name. */ -#define YYSKELETON_NAME "yacc.c" - -/* Pure parsers. */ -#define YYPURE 1 - -/* Push parsers. */ -#define YYPUSH 0 - -/* Pull parsers. */ -#define YYPULL 1 - - - - -/* Copy the first part of user declarations. */ -#line 42 "MachineIndependent/glslang.y" /* yacc.c:339 */ - - -/* Based on: -ANSI C Yacc grammar - -In 1985, Jeff Lee published his Yacc grammar (which is accompanied by a -matching Lex specification) for the April 30, 1985 draft version of the -ANSI C standard. Tom Stockfisch reposted it to net.sources in 1987; that -original, as mentioned in the answer to question 17.25 of the comp.lang.c -FAQ, can be ftp'ed from ftp.uu.net, file usenet/net.sources/ansi.c.grammar.Z. - -I intend to keep this version as close to the current C Standard grammar as -possible; please let me know if you discover discrepancies. - -Jutta Degener, 1995 -*/ - -#include "SymbolTable.h" -#include "ParseHelper.h" -#include "../Public/ShaderLang.h" -#include "attribute.h" - -using namespace glslang; - - -#line 92 "MachineIndependent/glslang_tab.cpp" /* yacc.c:339 */ - -# ifndef YY_NULL -# if defined __cplusplus && 201103L <= __cplusplus -# define YY_NULL nullptr -# else -# define YY_NULL 0 -# endif -# endif - -/* Enabling verbose error messages. */ -#ifdef YYERROR_VERBOSE -# undef YYERROR_VERBOSE -# define YYERROR_VERBOSE 1 -#else -# define YYERROR_VERBOSE 1 -#endif - -/* In a future release of Bison, this section will be replaced - by #include "glslang_tab.cpp.h". */ -#ifndef YY_YY_MACHINEINDEPENDENT_GLSLANG_TAB_CPP_H_INCLUDED -# define YY_YY_MACHINEINDEPENDENT_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 - { - ATTRIBUTE = 258, - VARYING = 259, - FLOAT16_T = 260, - FLOAT = 261, - FLOAT32_T = 262, - DOUBLE = 263, - FLOAT64_T = 264, - CONST = 265, - BOOL = 266, - INT = 267, - UINT = 268, - INT64_T = 269, - UINT64_T = 270, - INT32_T = 271, - UINT32_T = 272, - INT16_T = 273, - UINT16_T = 274, - INT8_T = 275, - UINT8_T = 276, - BREAK = 277, - CONTINUE = 278, - DO = 279, - ELSE = 280, - FOR = 281, - IF = 282, - DISCARD = 283, - RETURN = 284, - SWITCH = 285, - CASE = 286, - DEFAULT = 287, - SUBROUTINE = 288, - BVEC2 = 289, - BVEC3 = 290, - BVEC4 = 291, - IVEC2 = 292, - IVEC3 = 293, - IVEC4 = 294, - UVEC2 = 295, - UVEC3 = 296, - UVEC4 = 297, - I64VEC2 = 298, - I64VEC3 = 299, - I64VEC4 = 300, - U64VEC2 = 301, - U64VEC3 = 302, - U64VEC4 = 303, - I32VEC2 = 304, - I32VEC3 = 305, - I32VEC4 = 306, - U32VEC2 = 307, - U32VEC3 = 308, - U32VEC4 = 309, - I16VEC2 = 310, - I16VEC3 = 311, - I16VEC4 = 312, - U16VEC2 = 313, - U16VEC3 = 314, - U16VEC4 = 315, - I8VEC2 = 316, - I8VEC3 = 317, - I8VEC4 = 318, - U8VEC2 = 319, - U8VEC3 = 320, - U8VEC4 = 321, - VEC2 = 322, - VEC3 = 323, - VEC4 = 324, - MAT2 = 325, - MAT3 = 326, - MAT4 = 327, - CENTROID = 328, - IN = 329, - OUT = 330, - INOUT = 331, - UNIFORM = 332, - PATCH = 333, - SAMPLE = 334, - BUFFER = 335, - SHARED = 336, - NONUNIFORM = 337, - COHERENT = 338, - VOLATILE = 339, - RESTRICT = 340, - READONLY = 341, - WRITEONLY = 342, - DVEC2 = 343, - DVEC3 = 344, - DVEC4 = 345, - DMAT2 = 346, - DMAT3 = 347, - DMAT4 = 348, - F16VEC2 = 349, - F16VEC3 = 350, - F16VEC4 = 351, - F16MAT2 = 352, - F16MAT3 = 353, - F16MAT4 = 354, - F32VEC2 = 355, - F32VEC3 = 356, - F32VEC4 = 357, - F32MAT2 = 358, - F32MAT3 = 359, - F32MAT4 = 360, - F64VEC2 = 361, - F64VEC3 = 362, - F64VEC4 = 363, - F64MAT2 = 364, - F64MAT3 = 365, - F64MAT4 = 366, - NOPERSPECTIVE = 367, - FLAT = 368, - SMOOTH = 369, - LAYOUT = 370, - __EXPLICITINTERPAMD = 371, - MAT2X2 = 372, - MAT2X3 = 373, - MAT2X4 = 374, - MAT3X2 = 375, - MAT3X3 = 376, - MAT3X4 = 377, - MAT4X2 = 378, - MAT4X3 = 379, - MAT4X4 = 380, - DMAT2X2 = 381, - DMAT2X3 = 382, - DMAT2X4 = 383, - DMAT3X2 = 384, - DMAT3X3 = 385, - DMAT3X4 = 386, - DMAT4X2 = 387, - DMAT4X3 = 388, - DMAT4X4 = 389, - F16MAT2X2 = 390, - F16MAT2X3 = 391, - F16MAT2X4 = 392, - F16MAT3X2 = 393, - F16MAT3X3 = 394, - F16MAT3X4 = 395, - F16MAT4X2 = 396, - F16MAT4X3 = 397, - F16MAT4X4 = 398, - F32MAT2X2 = 399, - F32MAT2X3 = 400, - F32MAT2X4 = 401, - F32MAT3X2 = 402, - F32MAT3X3 = 403, - F32MAT3X4 = 404, - F32MAT4X2 = 405, - F32MAT4X3 = 406, - F32MAT4X4 = 407, - F64MAT2X2 = 408, - F64MAT2X3 = 409, - F64MAT2X4 = 410, - F64MAT3X2 = 411, - F64MAT3X3 = 412, - F64MAT3X4 = 413, - F64MAT4X2 = 414, - F64MAT4X3 = 415, - F64MAT4X4 = 416, - ATOMIC_UINT = 417, - SAMPLER1D = 418, - SAMPLER2D = 419, - SAMPLER3D = 420, - SAMPLERCUBE = 421, - SAMPLER1DSHADOW = 422, - SAMPLER2DSHADOW = 423, - SAMPLERCUBESHADOW = 424, - SAMPLER1DARRAY = 425, - SAMPLER2DARRAY = 426, - SAMPLER1DARRAYSHADOW = 427, - SAMPLER2DARRAYSHADOW = 428, - ISAMPLER1D = 429, - ISAMPLER2D = 430, - ISAMPLER3D = 431, - ISAMPLERCUBE = 432, - ISAMPLER1DARRAY = 433, - ISAMPLER2DARRAY = 434, - USAMPLER1D = 435, - USAMPLER2D = 436, - USAMPLER3D = 437, - USAMPLERCUBE = 438, - USAMPLER1DARRAY = 439, - USAMPLER2DARRAY = 440, - SAMPLER2DRECT = 441, - SAMPLER2DRECTSHADOW = 442, - ISAMPLER2DRECT = 443, - USAMPLER2DRECT = 444, - SAMPLERBUFFER = 445, - ISAMPLERBUFFER = 446, - USAMPLERBUFFER = 447, - SAMPLERCUBEARRAY = 448, - SAMPLERCUBEARRAYSHADOW = 449, - ISAMPLERCUBEARRAY = 450, - USAMPLERCUBEARRAY = 451, - SAMPLER2DMS = 452, - ISAMPLER2DMS = 453, - USAMPLER2DMS = 454, - SAMPLER2DMSARRAY = 455, - ISAMPLER2DMSARRAY = 456, - USAMPLER2DMSARRAY = 457, - SAMPLEREXTERNALOES = 458, - F16SAMPLER1D = 459, - F16SAMPLER2D = 460, - F16SAMPLER3D = 461, - F16SAMPLER2DRECT = 462, - F16SAMPLERCUBE = 463, - F16SAMPLER1DARRAY = 464, - F16SAMPLER2DARRAY = 465, - F16SAMPLERCUBEARRAY = 466, - F16SAMPLERBUFFER = 467, - F16SAMPLER2DMS = 468, - F16SAMPLER2DMSARRAY = 469, - F16SAMPLER1DSHADOW = 470, - F16SAMPLER2DSHADOW = 471, - F16SAMPLER1DARRAYSHADOW = 472, - F16SAMPLER2DARRAYSHADOW = 473, - F16SAMPLER2DRECTSHADOW = 474, - F16SAMPLERCUBESHADOW = 475, - F16SAMPLERCUBEARRAYSHADOW = 476, - SAMPLER = 477, - SAMPLERSHADOW = 478, - TEXTURE1D = 479, - TEXTURE2D = 480, - TEXTURE3D = 481, - TEXTURECUBE = 482, - TEXTURE1DARRAY = 483, - TEXTURE2DARRAY = 484, - ITEXTURE1D = 485, - ITEXTURE2D = 486, - ITEXTURE3D = 487, - ITEXTURECUBE = 488, - ITEXTURE1DARRAY = 489, - ITEXTURE2DARRAY = 490, - UTEXTURE1D = 491, - UTEXTURE2D = 492, - UTEXTURE3D = 493, - UTEXTURECUBE = 494, - UTEXTURE1DARRAY = 495, - UTEXTURE2DARRAY = 496, - TEXTURE2DRECT = 497, - ITEXTURE2DRECT = 498, - UTEXTURE2DRECT = 499, - TEXTUREBUFFER = 500, - ITEXTUREBUFFER = 501, - UTEXTUREBUFFER = 502, - TEXTURECUBEARRAY = 503, - ITEXTURECUBEARRAY = 504, - UTEXTURECUBEARRAY = 505, - TEXTURE2DMS = 506, - ITEXTURE2DMS = 507, - UTEXTURE2DMS = 508, - TEXTURE2DMSARRAY = 509, - ITEXTURE2DMSARRAY = 510, - UTEXTURE2DMSARRAY = 511, - F16TEXTURE1D = 512, - F16TEXTURE2D = 513, - F16TEXTURE3D = 514, - F16TEXTURE2DRECT = 515, - F16TEXTURECUBE = 516, - F16TEXTURE1DARRAY = 517, - F16TEXTURE2DARRAY = 518, - F16TEXTURECUBEARRAY = 519, - F16TEXTUREBUFFER = 520, - F16TEXTURE2DMS = 521, - F16TEXTURE2DMSARRAY = 522, - SUBPASSINPUT = 523, - SUBPASSINPUTMS = 524, - ISUBPASSINPUT = 525, - ISUBPASSINPUTMS = 526, - USUBPASSINPUT = 527, - USUBPASSINPUTMS = 528, - F16SUBPASSINPUT = 529, - F16SUBPASSINPUTMS = 530, - IMAGE1D = 531, - IIMAGE1D = 532, - UIMAGE1D = 533, - IMAGE2D = 534, - IIMAGE2D = 535, - UIMAGE2D = 536, - IMAGE3D = 537, - IIMAGE3D = 538, - UIMAGE3D = 539, - IMAGE2DRECT = 540, - IIMAGE2DRECT = 541, - UIMAGE2DRECT = 542, - IMAGECUBE = 543, - IIMAGECUBE = 544, - UIMAGECUBE = 545, - IMAGEBUFFER = 546, - IIMAGEBUFFER = 547, - UIMAGEBUFFER = 548, - IMAGE1DARRAY = 549, - IIMAGE1DARRAY = 550, - UIMAGE1DARRAY = 551, - IMAGE2DARRAY = 552, - IIMAGE2DARRAY = 553, - UIMAGE2DARRAY = 554, - IMAGECUBEARRAY = 555, - IIMAGECUBEARRAY = 556, - UIMAGECUBEARRAY = 557, - IMAGE2DMS = 558, - IIMAGE2DMS = 559, - UIMAGE2DMS = 560, - IMAGE2DMSARRAY = 561, - IIMAGE2DMSARRAY = 562, - UIMAGE2DMSARRAY = 563, - F16IMAGE1D = 564, - F16IMAGE2D = 565, - F16IMAGE3D = 566, - F16IMAGE2DRECT = 567, - F16IMAGECUBE = 568, - F16IMAGE1DARRAY = 569, - F16IMAGE2DARRAY = 570, - F16IMAGECUBEARRAY = 571, - F16IMAGEBUFFER = 572, - F16IMAGE2DMS = 573, - F16IMAGE2DMSARRAY = 574, - STRUCT = 575, - VOID = 576, - WHILE = 577, - IDENTIFIER = 578, - TYPE_NAME = 579, - FLOATCONSTANT = 580, - DOUBLECONSTANT = 581, - INT16CONSTANT = 582, - UINT16CONSTANT = 583, - INT32CONSTANT = 584, - UINT32CONSTANT = 585, - INTCONSTANT = 586, - UINTCONSTANT = 587, - INT64CONSTANT = 588, - UINT64CONSTANT = 589, - BOOLCONSTANT = 590, - FLOAT16CONSTANT = 591, - LEFT_OP = 592, - RIGHT_OP = 593, - INC_OP = 594, - DEC_OP = 595, - LE_OP = 596, - GE_OP = 597, - EQ_OP = 598, - NE_OP = 599, - AND_OP = 600, - OR_OP = 601, - XOR_OP = 602, - MUL_ASSIGN = 603, - DIV_ASSIGN = 604, - ADD_ASSIGN = 605, - MOD_ASSIGN = 606, - LEFT_ASSIGN = 607, - RIGHT_ASSIGN = 608, - AND_ASSIGN = 609, - XOR_ASSIGN = 610, - OR_ASSIGN = 611, - SUB_ASSIGN = 612, - LEFT_PAREN = 613, - RIGHT_PAREN = 614, - LEFT_BRACKET = 615, - RIGHT_BRACKET = 616, - LEFT_BRACE = 617, - RIGHT_BRACE = 618, - DOT = 619, - COMMA = 620, - COLON = 621, - EQUAL = 622, - SEMICOLON = 623, - BANG = 624, - DASH = 625, - TILDE = 626, - PLUS = 627, - STAR = 628, - SLASH = 629, - PERCENT = 630, - LEFT_ANGLE = 631, - RIGHT_ANGLE = 632, - VERTICAL_BAR = 633, - CARET = 634, - AMPERSAND = 635, - QUESTION = 636, - INVARIANT = 637, - PRECISE = 638, - HIGH_PRECISION = 639, - MEDIUM_PRECISION = 640, - LOW_PRECISION = 641, - PRECISION = 642, - PACKED = 643, - RESOURCE = 644, - SUPERP = 645 - }; -#endif - -/* Value type. */ -#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED -typedef union YYSTYPE YYSTYPE; -union YYSTYPE -{ -#line 70 "MachineIndependent/glslang.y" /* yacc.c:355 */ - - 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; - }; - } interm; - -#line 558 "MachineIndependent/glslang_tab.cpp" /* yacc.c:355 */ -}; -# define YYSTYPE_IS_TRIVIAL 1 -# define YYSTYPE_IS_DECLARED 1 -#endif - - - -int yyparse (glslang::TParseContext* pParseContext); - -#endif /* !YY_YY_MACHINEINDEPENDENT_GLSLANG_TAB_CPP_H_INCLUDED */ - -/* Copy the second part of user declarations. */ -#line 105 "MachineIndependent/glslang.y" /* yacc.c:358 */ - - -/* windows only pragma */ -#ifdef _MSC_VER - #pragma warning(disable : 4065) - #pragma warning(disable : 4127) - #pragma warning(disable : 4244) -#endif - -#define parseContext (*pParseContext) -#define yyerror(context, msg) context->parserError(msg) - -extern int yylex(YYSTYPE*, TParseContext&); - - -#line 587 "MachineIndependent/glslang_tab.cpp" /* yacc.c:358 */ - -#ifdef short -# undef short -#endif - -#ifdef YYTYPE_UINT8 -typedef YYTYPE_UINT8 yytype_uint8; -#else -typedef unsigned char yytype_uint8; -#endif - -#ifdef YYTYPE_INT8 -typedef YYTYPE_INT8 yytype_int8; -#else -typedef signed char yytype_int8; -#endif - -#ifdef YYTYPE_UINT16 -typedef YYTYPE_UINT16 yytype_uint16; -#else -typedef unsigned short int yytype_uint16; -#endif - -#ifdef YYTYPE_INT16 -typedef YYTYPE_INT16 yytype_int16; -#else -typedef short int yytype_int16; -#endif - -#ifndef YYSIZE_T -# ifdef __SIZE_TYPE__ -# define YYSIZE_T __SIZE_TYPE__ -# elif defined size_t -# define YYSIZE_T size_t -# elif ! defined YYSIZE_T -# include /* INFRINGES ON USER NAME SPACE */ -# define YYSIZE_T size_t -# else -# define YYSIZE_T unsigned int -# endif -#endif - -#define YYSIZE_MAXIMUM ((YYSIZE_T) -1) - -#ifndef YY_ -# if defined YYENABLE_NLS && YYENABLE_NLS -# if ENABLE_NLS -# include /* INFRINGES ON USER NAME SPACE */ -# define YY_(Msgid) dgettext ("bison-runtime", Msgid) -# endif -# endif -# ifndef YY_ -# define YY_(Msgid) Msgid -# endif -#endif - -#ifndef __attribute__ -/* This feature is available in gcc versions 2.5 and later. */ -# if (! defined __GNUC__ || __GNUC__ < 2 \ - || (__GNUC__ == 2 && __GNUC_MINOR__ < 5)) -# define __attribute__(Spec) /* empty */ -# endif -#endif - -/* Suppress unused-variable warnings by "using" E. */ -#if ! defined lint || defined __GNUC__ -# define YYUSE(E) ((void) (E)) -#else -# define YYUSE(E) /* empty */ -#endif - -#if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__ -/* Suppress an incorrect diagnostic about yylval being uninitialized. */ -# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ - _Pragma ("GCC diagnostic push") \ - _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")\ - _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"") -# define YY_IGNORE_MAYBE_UNINITIALIZED_END \ - _Pragma ("GCC diagnostic pop") -#else -# define YY_INITIAL_VALUE(Value) Value -#endif -#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN -# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN -# define YY_IGNORE_MAYBE_UNINITIALIZED_END -#endif -#ifndef YY_INITIAL_VALUE -# define YY_INITIAL_VALUE(Value) /* Nothing. */ -#endif - - -#if ! defined yyoverflow || YYERROR_VERBOSE - -/* The parser invokes alloca or malloc; define the necessary symbols. */ - -# ifdef YYSTACK_USE_ALLOCA -# if YYSTACK_USE_ALLOCA -# ifdef __GNUC__ -# define YYSTACK_ALLOC __builtin_alloca -# elif defined __BUILTIN_VA_ARG_INCR -# include /* INFRINGES ON USER NAME SPACE */ -# elif defined _AIX -# define YYSTACK_ALLOC __alloca -# elif defined _MSC_VER -# include /* INFRINGES ON USER NAME SPACE */ -# define alloca _alloca -# else -# define YYSTACK_ALLOC alloca -# if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS -# include /* INFRINGES ON USER NAME SPACE */ - /* Use EXIT_SUCCESS as a witness for stdlib.h. */ -# ifndef EXIT_SUCCESS -# define EXIT_SUCCESS 0 -# endif -# endif -# endif -# endif -# endif - -# ifdef YYSTACK_ALLOC - /* Pacify GCC's 'empty if-body' warning. */ -# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0) -# ifndef YYSTACK_ALLOC_MAXIMUM - /* The OS might guarantee only one guard page at the bottom of the stack, - and a page size can be as small as 4096 bytes. So we cannot safely - invoke alloca (N) if N exceeds 4096. Use a slightly smaller number - to allow for a few compiler-allocated temporary stack slots. */ -# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */ -# endif -# else -# define YYSTACK_ALLOC YYMALLOC -# define YYSTACK_FREE YYFREE -# ifndef YYSTACK_ALLOC_MAXIMUM -# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM -# endif -# if (defined __cplusplus && ! defined EXIT_SUCCESS \ - && ! ((defined YYMALLOC || defined malloc) \ - && (defined YYFREE || defined free))) -# include /* INFRINGES ON USER NAME SPACE */ -# ifndef EXIT_SUCCESS -# define EXIT_SUCCESS 0 -# endif -# endif -# ifndef YYMALLOC -# define YYMALLOC malloc -# if ! defined malloc && ! defined EXIT_SUCCESS -void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ -# endif -# endif -# ifndef YYFREE -# define YYFREE free -# if ! defined free && ! defined EXIT_SUCCESS -void free (void *); /* INFRINGES ON USER NAME SPACE */ -# endif -# endif -# endif -#endif /* ! defined yyoverflow || YYERROR_VERBOSE */ - - -#if (! defined yyoverflow \ - && (! defined __cplusplus \ - || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) - -/* A type that is properly aligned for any stack member. */ -union yyalloc -{ - yytype_int16 yyss_alloc; - YYSTYPE yyvs_alloc; -}; - -/* The size of the maximum gap between one aligned stack and the next. */ -# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) - -/* The size of an array large to enough to hold all stacks, each with - N elements. */ -# define YYSTACK_BYTES(N) \ - ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \ - + YYSTACK_GAP_MAXIMUM) - -# define YYCOPY_NEEDED 1 - -/* Relocate STACK from its old location to the new one. The - local variables YYSIZE and YYSTACKSIZE give the old and new number of - elements in the stack, and YYPTR gives the new location of the - stack. Advance YYPTR to a properly aligned location for the next - stack. */ -# define YYSTACK_RELOCATE(Stack_alloc, Stack) \ - do \ - { \ - YYSIZE_T yynewbytes; \ - YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \ - Stack = &yyptr->Stack_alloc; \ - yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ - yyptr += yynewbytes / sizeof (*yyptr); \ - } \ - while (0) - -#endif - -#if defined YYCOPY_NEEDED && YYCOPY_NEEDED -/* Copy COUNT objects from SRC to DST. The source and destination do - not overlap. */ -# ifndef YYCOPY -# if defined __GNUC__ && 1 < __GNUC__ -# define YYCOPY(Dst, Src, Count) \ - __builtin_memcpy (Dst, Src, (Count) * sizeof (*(Src))) -# else -# define YYCOPY(Dst, Src, Count) \ - do \ - { \ - YYSIZE_T yyi; \ - for (yyi = 0; yyi < (Count); yyi++) \ - (Dst)[yyi] = (Src)[yyi]; \ - } \ - while (0) -# endif -# endif -#endif /* !YYCOPY_NEEDED */ - -/* YYFINAL -- State number of the termination state. */ -#define YYFINAL 366 -/* YYLAST -- Last index in YYTABLE. */ -#define YYLAST 8949 - -/* YYNTOKENS -- Number of terminals. */ -#define YYNTOKENS 391 -/* YYNNTS -- Number of nonterminals. */ -#define YYNNTS 107 -/* YYNRULES -- Number of rules. */ -#define YYNRULES 556 -/* YYNSTATES -- Number of states. */ -#define YYNSTATES 697 - -/* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned - by yylex, with out-of-bounds checking. */ -#define YYUNDEFTOK 2 -#define YYMAXUTOK 645 - -#define YYTRANSLATE(YYX) \ - ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) - -/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM - as returned by yylex, without out-of-bounds checking. */ -static const yytype_uint16 yytranslate[] = -{ - 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, - 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, - 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, - 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, - 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, - 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, - 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, - 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, - 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, - 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, - 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, - 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, - 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, - 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, - 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, - 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, - 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, - 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, - 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, - 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, - 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, - 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, - 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, - 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, - 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, - 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, - 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, - 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, - 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, - 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, - 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, - 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, - 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, - 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, - 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, - 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, - 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, - 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, - 385, 386, 387, 388, 389, 390 -}; - -#if YYDEBUG - /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ -static const yytype_uint16 yyrline[] = -{ - 0, 293, 293, 299, 302, 306, 310, 313, 317, 321, - 325, 329, 333, 336, 340, 344, 347, 355, 358, 361, - 364, 367, 372, 380, 387, 394, 400, 404, 411, 414, - 420, 427, 437, 445, 450, 477, 485, 491, 495, 499, - 519, 520, 521, 522, 528, 529, 534, 539, 548, 549, - 554, 562, 563, 569, 578, 579, 584, 589, 594, 602, - 603, 611, 622, 623, 632, 633, 642, 643, 652, 653, - 661, 662, 670, 671, 679, 680, 680, 698, 699, 714, - 718, 722, 726, 731, 735, 739, 743, 747, 751, 755, - 762, 765, 776, 783, 788, 793, 801, 805, 809, 813, - 818, 823, 832, 832, 843, 847, 854, 861, 864, 871, - 879, 899, 922, 937, 962, 973, 983, 993, 1003, 1012, - 1015, 1019, 1023, 1028, 1036, 1041, 1046, 1051, 1056, 1065, - 1076, 1103, 1112, 1119, 1126, 1137, 1149, 1155, 1158, 1165, - 1169, 1173, 1181, 1190, 1193, 1204, 1207, 1210, 1214, 1218, - 1222, 1226, 1232, 1236, 1248, 1262, 1267, 1273, 1279, 1286, - 1292, 1297, 1302, 1307, 1315, 1319, 1323, 1327, 1331, 1335, - 1341, 1350, 1357, 1360, 1368, 1372, 1381, 1386, 1394, 1398, - 1408, 1412, 1416, 1421, 1426, 1431, 1436, 1440, 1445, 1450, - 1455, 1460, 1465, 1470, 1475, 1480, 1485, 1489, 1494, 1499, - 1504, 1510, 1516, 1522, 1528, 1534, 1540, 1546, 1552, 1558, - 1564, 1570, 1576, 1581, 1586, 1591, 1596, 1601, 1606, 1612, - 1618, 1624, 1630, 1636, 1642, 1648, 1654, 1660, 1666, 1672, - 1678, 1684, 1690, 1696, 1702, 1708, 1714, 1720, 1726, 1732, - 1738, 1744, 1750, 1756, 1762, 1768, 1773, 1778, 1783, 1788, - 1793, 1798, 1803, 1808, 1813, 1818, 1823, 1828, 1834, 1840, - 1846, 1852, 1858, 1864, 1870, 1876, 1882, 1888, 1894, 1900, - 1906, 1912, 1918, 1924, 1930, 1936, 1942, 1948, 1954, 1960, - 1966, 1972, 1978, 1984, 1990, 1996, 2002, 2008, 2014, 2020, - 2026, 2032, 2038, 2044, 2050, 2056, 2062, 2068, 2074, 2080, - 2086, 2092, 2098, 2104, 2110, 2116, 2121, 2126, 2131, 2136, - 2141, 2146, 2151, 2156, 2161, 2166, 2171, 2176, 2181, 2186, - 2194, 2202, 2210, 2218, 2226, 2234, 2242, 2250, 2258, 2266, - 2274, 2282, 2290, 2295, 2300, 2305, 2310, 2315, 2320, 2325, - 2330, 2335, 2340, 2345, 2350, 2355, 2360, 2365, 2370, 2378, - 2386, 2391, 2396, 2401, 2409, 2414, 2419, 2424, 2432, 2437, - 2442, 2447, 2455, 2460, 2465, 2470, 2475, 2480, 2488, 2493, - 2501, 2506, 2514, 2519, 2527, 2532, 2540, 2545, 2553, 2558, - 2566, 2571, 2576, 2581, 2586, 2591, 2596, 2601, 2606, 2611, - 2616, 2621, 2626, 2631, 2636, 2641, 2649, 2654, 2659, 2664, - 2672, 2677, 2682, 2687, 2695, 2700, 2705, 2710, 2718, 2723, - 2728, 2733, 2741, 2746, 2751, 2756, 2764, 2769, 2774, 2779, - 2787, 2792, 2797, 2802, 2810, 2815, 2820, 2825, 2833, 2838, - 2843, 2848, 2856, 2861, 2866, 2871, 2879, 2884, 2889, 2894, - 2902, 2907, 2912, 2917, 2925, 2930, 2935, 2940, 2948, 2953, - 2958, 2963, 2971, 2976, 2981, 2987, 2993, 2999, 3008, 3017, - 3023, 3029, 3035, 3041, 3046, 3062, 3067, 3072, 3080, 3080, - 3091, 3091, 3101, 3104, 3117, 3139, 3166, 3170, 3176, 3181, - 3192, 3195, 3201, 3210, 3213, 3219, 3223, 3224, 3230, 3231, - 3232, 3233, 3234, 3235, 3236, 3240, 3241, 3245, 3241, 3257, - 3258, 3262, 3262, 3269, 3269, 3283, 3286, 3294, 3302, 3313, - 3314, 3318, 3321, 3327, 3334, 3338, 3346, 3350, 3363, 3366, - 3372, 3372, 3392, 3395, 3401, 3413, 3425, 3428, 3434, 3434, - 3449, 3449, 3465, 3465, 3486, 3489, 3495, 3498, 3504, 3508, - 3515, 3520, 3525, 3532, 3535, 3544, 3548, 3557, 3560, 3563, - 3571, 3571, 3593, 3599, 3602, 3607, 3610 -}; -#endif - -#if YYDEBUG || YYERROR_VERBOSE || 1 -/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. - First, the terminals, then, starting at YYNTOKENS, nonterminals. */ -static const char *const yytname[] = -{ - "$end", "error", "$undefined", "ATTRIBUTE", "VARYING", "FLOAT16_T", - "FLOAT", "FLOAT32_T", "DOUBLE", "FLOAT64_T", "CONST", "BOOL", "INT", - "UINT", "INT64_T", "UINT64_T", "INT32_T", "UINT32_T", "INT16_T", - "UINT16_T", "INT8_T", "UINT8_T", "BREAK", "CONTINUE", "DO", "ELSE", - "FOR", "IF", "DISCARD", "RETURN", "SWITCH", "CASE", "DEFAULT", - "SUBROUTINE", "BVEC2", "BVEC3", "BVEC4", "IVEC2", "IVEC3", "IVEC4", - "UVEC2", "UVEC3", "UVEC4", "I64VEC2", "I64VEC3", "I64VEC4", "U64VEC2", - "U64VEC3", "U64VEC4", "I32VEC2", "I32VEC3", "I32VEC4", "U32VEC2", - "U32VEC3", "U32VEC4", "I16VEC2", "I16VEC3", "I16VEC4", "U16VEC2", - "U16VEC3", "U16VEC4", "I8VEC2", "I8VEC3", "I8VEC4", "U8VEC2", "U8VEC3", - "U8VEC4", "VEC2", "VEC3", "VEC4", "MAT2", "MAT3", "MAT4", "CENTROID", - "IN", "OUT", "INOUT", "UNIFORM", "PATCH", "SAMPLE", "BUFFER", "SHARED", - "NONUNIFORM", "COHERENT", "VOLATILE", "RESTRICT", "READONLY", - "WRITEONLY", "DVEC2", "DVEC3", "DVEC4", "DMAT2", "DMAT3", "DMAT4", - "F16VEC2", "F16VEC3", "F16VEC4", "F16MAT2", "F16MAT3", "F16MAT4", - "F32VEC2", "F32VEC3", "F32VEC4", "F32MAT2", "F32MAT3", "F32MAT4", - "F64VEC2", "F64VEC3", "F64VEC4", "F64MAT2", "F64MAT3", "F64MAT4", - "NOPERSPECTIVE", "FLAT", "SMOOTH", "LAYOUT", "__EXPLICITINTERPAMD", - "MAT2X2", "MAT2X3", "MAT2X4", "MAT3X2", "MAT3X3", "MAT3X4", "MAT4X2", - "MAT4X3", "MAT4X4", "DMAT2X2", "DMAT2X3", "DMAT2X4", "DMAT3X2", - "DMAT3X3", "DMAT3X4", "DMAT4X2", "DMAT4X3", "DMAT4X4", "F16MAT2X2", - "F16MAT2X3", "F16MAT2X4", "F16MAT3X2", "F16MAT3X3", "F16MAT3X4", - "F16MAT4X2", "F16MAT4X3", "F16MAT4X4", "F32MAT2X2", "F32MAT2X3", - "F32MAT2X4", "F32MAT3X2", "F32MAT3X3", "F32MAT3X4", "F32MAT4X2", - "F32MAT4X3", "F32MAT4X4", "F64MAT2X2", "F64MAT2X3", "F64MAT2X4", - "F64MAT3X2", "F64MAT3X3", "F64MAT3X4", "F64MAT4X2", "F64MAT4X3", - "F64MAT4X4", "ATOMIC_UINT", "SAMPLER1D", "SAMPLER2D", "SAMPLER3D", - "SAMPLERCUBE", "SAMPLER1DSHADOW", "SAMPLER2DSHADOW", "SAMPLERCUBESHADOW", - "SAMPLER1DARRAY", "SAMPLER2DARRAY", "SAMPLER1DARRAYSHADOW", - "SAMPLER2DARRAYSHADOW", "ISAMPLER1D", "ISAMPLER2D", "ISAMPLER3D", - "ISAMPLERCUBE", "ISAMPLER1DARRAY", "ISAMPLER2DARRAY", "USAMPLER1D", - "USAMPLER2D", "USAMPLER3D", "USAMPLERCUBE", "USAMPLER1DARRAY", - "USAMPLER2DARRAY", "SAMPLER2DRECT", "SAMPLER2DRECTSHADOW", - "ISAMPLER2DRECT", "USAMPLER2DRECT", "SAMPLERBUFFER", "ISAMPLERBUFFER", - "USAMPLERBUFFER", "SAMPLERCUBEARRAY", "SAMPLERCUBEARRAYSHADOW", - "ISAMPLERCUBEARRAY", "USAMPLERCUBEARRAY", "SAMPLER2DMS", "ISAMPLER2DMS", - "USAMPLER2DMS", "SAMPLER2DMSARRAY", "ISAMPLER2DMSARRAY", - "USAMPLER2DMSARRAY", "SAMPLEREXTERNALOES", "F16SAMPLER1D", - "F16SAMPLER2D", "F16SAMPLER3D", "F16SAMPLER2DRECT", "F16SAMPLERCUBE", - "F16SAMPLER1DARRAY", "F16SAMPLER2DARRAY", "F16SAMPLERCUBEARRAY", - "F16SAMPLERBUFFER", "F16SAMPLER2DMS", "F16SAMPLER2DMSARRAY", - "F16SAMPLER1DSHADOW", "F16SAMPLER2DSHADOW", "F16SAMPLER1DARRAYSHADOW", - "F16SAMPLER2DARRAYSHADOW", "F16SAMPLER2DRECTSHADOW", - "F16SAMPLERCUBESHADOW", "F16SAMPLERCUBEARRAYSHADOW", "SAMPLER", - "SAMPLERSHADOW", "TEXTURE1D", "TEXTURE2D", "TEXTURE3D", "TEXTURECUBE", - "TEXTURE1DARRAY", "TEXTURE2DARRAY", "ITEXTURE1D", "ITEXTURE2D", - "ITEXTURE3D", "ITEXTURECUBE", "ITEXTURE1DARRAY", "ITEXTURE2DARRAY", - "UTEXTURE1D", "UTEXTURE2D", "UTEXTURE3D", "UTEXTURECUBE", - "UTEXTURE1DARRAY", "UTEXTURE2DARRAY", "TEXTURE2DRECT", "ITEXTURE2DRECT", - "UTEXTURE2DRECT", "TEXTUREBUFFER", "ITEXTUREBUFFER", "UTEXTUREBUFFER", - "TEXTURECUBEARRAY", "ITEXTURECUBEARRAY", "UTEXTURECUBEARRAY", - "TEXTURE2DMS", "ITEXTURE2DMS", "UTEXTURE2DMS", "TEXTURE2DMSARRAY", - "ITEXTURE2DMSARRAY", "UTEXTURE2DMSARRAY", "F16TEXTURE1D", "F16TEXTURE2D", - "F16TEXTURE3D", "F16TEXTURE2DRECT", "F16TEXTURECUBE", - "F16TEXTURE1DARRAY", "F16TEXTURE2DARRAY", "F16TEXTURECUBEARRAY", - "F16TEXTUREBUFFER", "F16TEXTURE2DMS", "F16TEXTURE2DMSARRAY", - "SUBPASSINPUT", "SUBPASSINPUTMS", "ISUBPASSINPUT", "ISUBPASSINPUTMS", - "USUBPASSINPUT", "USUBPASSINPUTMS", "F16SUBPASSINPUT", - "F16SUBPASSINPUTMS", "IMAGE1D", "IIMAGE1D", "UIMAGE1D", "IMAGE2D", - "IIMAGE2D", "UIMAGE2D", "IMAGE3D", "IIMAGE3D", "UIMAGE3D", "IMAGE2DRECT", - "IIMAGE2DRECT", "UIMAGE2DRECT", "IMAGECUBE", "IIMAGECUBE", "UIMAGECUBE", - "IMAGEBUFFER", "IIMAGEBUFFER", "UIMAGEBUFFER", "IMAGE1DARRAY", - "IIMAGE1DARRAY", "UIMAGE1DARRAY", "IMAGE2DARRAY", "IIMAGE2DARRAY", - "UIMAGE2DARRAY", "IMAGECUBEARRAY", "IIMAGECUBEARRAY", "UIMAGECUBEARRAY", - "IMAGE2DMS", "IIMAGE2DMS", "UIMAGE2DMS", "IMAGE2DMSARRAY", - "IIMAGE2DMSARRAY", "UIMAGE2DMSARRAY", "F16IMAGE1D", "F16IMAGE2D", - "F16IMAGE3D", "F16IMAGE2DRECT", "F16IMAGECUBE", "F16IMAGE1DARRAY", - "F16IMAGE2DARRAY", "F16IMAGECUBEARRAY", "F16IMAGEBUFFER", "F16IMAGE2DMS", - "F16IMAGE2DMSARRAY", "STRUCT", "VOID", "WHILE", "IDENTIFIER", - "TYPE_NAME", "FLOATCONSTANT", "DOUBLECONSTANT", "INT16CONSTANT", - "UINT16CONSTANT", "INT32CONSTANT", "UINT32CONSTANT", "INTCONSTANT", - "UINTCONSTANT", "INT64CONSTANT", "UINT64CONSTANT", "BOOLCONSTANT", - "FLOAT16CONSTANT", "LEFT_OP", "RIGHT_OP", "INC_OP", "DEC_OP", "LE_OP", - "GE_OP", "EQ_OP", "NE_OP", "AND_OP", "OR_OP", "XOR_OP", "MUL_ASSIGN", - "DIV_ASSIGN", "ADD_ASSIGN", "MOD_ASSIGN", "LEFT_ASSIGN", "RIGHT_ASSIGN", - "AND_ASSIGN", "XOR_ASSIGN", "OR_ASSIGN", "SUB_ASSIGN", "LEFT_PAREN", - "RIGHT_PAREN", "LEFT_BRACKET", "RIGHT_BRACKET", "LEFT_BRACE", - "RIGHT_BRACE", "DOT", "COMMA", "COLON", "EQUAL", "SEMICOLON", "BANG", - "DASH", "TILDE", "PLUS", "STAR", "SLASH", "PERCENT", "LEFT_ANGLE", - "RIGHT_ANGLE", "VERTICAL_BAR", "CARET", "AMPERSAND", "QUESTION", - "INVARIANT", "PRECISE", "HIGH_PRECISION", "MEDIUM_PRECISION", - "LOW_PRECISION", "PRECISION", "PACKED", "RESOURCE", "SUPERP", "$accept", - "variable_identifier", "primary_expression", "postfix_expression", - "integer_expression", "function_call", "function_call_or_method", - "function_call_generic", "function_call_header_no_parameters", - "function_call_header_with_parameters", "function_call_header", - "function_identifier", "unary_expression", "unary_operator", - "multiplicative_expression", "additive_expression", "shift_expression", - "relational_expression", "equality_expression", "and_expression", - "exclusive_or_expression", "inclusive_or_expression", - "logical_and_expression", "logical_xor_expression", - "logical_or_expression", "conditional_expression", "$@1", - "assignment_expression", "assignment_operator", "expression", - "constant_expression", "declaration", "block_structure", "$@2", - "identifier_list", "function_prototype", "function_declarator", - "function_header_with_parameters", "function_header", - "parameter_declarator", "parameter_declaration", - "parameter_type_specifier", "init_declarator_list", "single_declaration", - "fully_specified_type", "invariant_qualifier", "interpolation_qualifier", - "layout_qualifier", "layout_qualifier_id_list", "layout_qualifier_id", - "precise_qualifier", "type_qualifier", "single_type_qualifier", - "storage_qualifier", "non_uniform_qualifier", "type_name_list", - "type_specifier", "array_specifier", "type_specifier_nonarray", - "precision_qualifier", "struct_specifier", "$@3", "$@4", - "struct_declaration_list", "struct_declaration", - "struct_declarator_list", "struct_declarator", "initializer", - "initializer_list", "declaration_statement", "statement", - "simple_statement", "compound_statement", "$@5", "$@6", - "statement_no_new_scope", "statement_scoped", "$@7", "$@8", - "compound_statement_no_new_scope", "statement_list", - "expression_statement", "selection_statement", - "selection_statement_nonattributed", "selection_rest_statement", - "condition", "switch_statement", "switch_statement_nonattributed", "$@9", - "switch_statement_list", "case_label", "iteration_statement", - "iteration_statement_nonattributed", "$@10", "$@11", "$@12", - "for_init_statement", "conditionopt", "for_rest_statement", - "jump_statement", "translation_unit", "external_declaration", - "function_definition", "$@13", "attribute", "attribute_list", - "single_attribute", YY_NULL -}; -#endif - -# ifdef YYPRINT -/* YYTOKNUM[NUM] -- (External) token number corresponding to the - (internal) symbol number NUM (which must be that of a token). */ -static const yytype_uint16 yytoknum[] = -{ - 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, - 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, - 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, - 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, - 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, - 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, - 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, - 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, - 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, - 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, - 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, - 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, - 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, - 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, - 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, - 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, - 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, - 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, - 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, - 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, - 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, - 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, - 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, - 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, - 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, - 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, - 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, - 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, - 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, - 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, - 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, - 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, - 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, - 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, - 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, - 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, - 615, 616, 617, 618, 619, 620, 621, 622, 623, 624, - 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, - 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, - 645 -}; -# endif - -#define YYPACT_NINF -634 - -#define yypact_value_is_default(Yystate) \ - (!!((Yystate) == (-634))) - -#define YYTABLE_NINF -502 - -#define yytable_value_is_error(Yytable_value) \ - 0 - - /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing - STATE-NUM. */ -static const yytype_int16 yypact[] = -{ - 3391, -634, -634, -634, -634, -634, -634, -634, -634, -634, - -634, -634, -634, -634, -634, -634, -634, -634, -634, -634, - -311, -634, -634, -634, -634, -634, -634, -634, -634, -634, - -634, -634, -634, -634, -634, -634, -634, -634, -634, -634, - -634, -634, -634, -634, -634, -634, -634, -634, -634, -634, - -634, -634, -634, -634, -634, -634, -634, -634, -634, -634, - -634, -634, -634, -634, -634, -634, -634, -634, -634, -634, - -634, -634, -634, -634, -634, -634, -634, -634, -634, -634, - -634, -634, -634, -634, -634, -634, -634, -634, -634, -634, - -634, -634, -634, -634, -634, -634, -634, -634, -634, -634, - -634, -634, -295, -634, -634, -634, -634, -634, -634, -634, - -634, -634, -634, -634, -634, -634, -634, -634, -634, -634, - -634, -634, -634, -634, -634, -634, -634, -634, -634, -634, - -634, -634, -634, -634, -634, -634, -634, -634, -634, -634, - -634, -634, -634, -634, -634, -634, -634, -634, -634, -634, - -634, -634, -634, -634, -634, -634, -634, -634, -634, -634, - -634, -634, -634, -634, -634, -634, -634, -634, -634, -634, - -634, -634, -634, -634, -634, -634, -634, -634, -634, -634, - -634, -634, -634, -634, -634, -634, -634, -634, -634, -634, - -634, -634, -634, -634, -634, -634, -634, -634, -634, -634, - -634, -634, -634, -634, -634, -634, -634, -634, -634, -634, - -634, -634, -634, -634, -634, -634, -634, -634, -634, -634, - -634, -634, -634, -634, -634, -634, -634, -634, -634, -634, - -634, -634, -634, -634, -634, -634, -634, -634, -634, -634, - -634, -634, -634, -634, -634, -634, -634, -634, -634, -634, - -634, -634, -634, -634, -634, -634, -634, -634, -634, -634, - -634, -634, -634, -634, -634, -634, -634, -634, -634, -634, - -634, -634, -634, -634, -634, -634, -634, -634, -634, -634, - -634, -634, -634, -634, -634, -634, -634, -634, -634, -634, - -634, -634, -634, -634, -634, -634, -634, -634, -634, -634, - -634, -634, -634, -634, -634, -634, -634, -301, -634, -634, - -634, -634, -634, -634, -634, -634, -241, -634, -302, -342, - -290, -254, 5696, -300, -634, -210, -634, -634, -634, -634, - 4160, -634, -634, -634, -634, -219, -634, -634, 696, -634, - -634, -189, -69, -207, -634, 8625, -320, -634, -634, -203, - -634, 5696, -634, -634, -634, 5696, -155, -154, -634, -324, - -288, -634, -634, -634, 6417, -190, -634, -634, -634, -292, - -634, -196, -287, -634, -634, 5696, -195, -634, -306, 1081, - -634, -634, -634, -634, -219, -325, -634, 6785, -310, -634, - -151, -634, -277, -634, -634, -634, -634, -634, -634, -634, - -634, -634, -634, -634, -634, -634, 7889, 7889, 7889, -634, - -634, -634, -634, -634, -634, -634, -309, -634, -634, -634, - -185, -283, 8257, -183, -634, 7889, -227, -263, -299, -318, - -194, -204, -202, -200, -165, -166, -321, -179, -634, -634, - 7153, -634, -140, 7889, -634, -69, 5696, 5696, -139, 4544, - -634, -634, -634, -182, -180, -634, -173, -169, -178, 7521, - -164, 7889, -174, -163, -167, -162, -634, -634, -252, -634, - -634, -237, -634, -342, -161, -158, -634, -634, -634, -634, - 1466, -634, -634, -634, -634, -634, -634, -634, -634, -634, - -19, -190, 6785, -296, 6785, -634, -634, 6785, 5696, -634, - -127, -634, -634, -634, -278, -634, -634, 7889, -121, -634, - -634, 7889, -156, -634, -634, -634, 7889, 7889, 7889, 7889, - 7889, 7889, 7889, 7889, 7889, 7889, 7889, 7889, 7889, 7889, - 7889, 7889, 7889, 7889, 7889, -634, -634, -634, -157, -634, - -634, -634, -634, 4928, -139, -219, -236, -634, -634, -634, - -634, -634, 1851, -634, 7889, -634, -634, -230, 7889, -213, - -634, -634, -118, -634, 1851, -634, -634, -634, -634, -634, - -634, -634, -634, -634, -634, -634, 7889, 7889, -634, -634, - -634, -634, -634, -634, -634, 6785, -634, -270, -634, 5312, - -634, -634, -153, -150, -634, -634, -634, -634, -634, -227, - -227, -263, -263, -299, -299, -299, -299, -318, -318, -194, - -204, -202, -200, -165, -166, 7889, -634, -634, -226, -190, - -139, -634, -113, 3006, -275, -634, -253, -634, 3776, -148, - -282, -634, 1851, -634, -634, -634, -634, 6049, -634, -634, - -208, -634, -634, -147, -634, -634, 3776, -146, -634, -150, - -111, 5696, -145, 7889, -144, -118, -143, -634, -634, 7889, - 7889, -634, -149, -141, 196, -136, 2621, -634, -116, -120, - 2236, -137, -634, -634, -634, -634, -239, 7889, 2236, -146, - -634, -634, 1851, 6785, -634, -634, -634, -634, -119, -150, - -634, -634, 1851, -112, -634, -634, -634 -}; - - /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM. - Performed when YYTABLE does not specify something else to do. Zero - means the default is an error. */ -static const yytype_uint16 yydefact[] = -{ - 0, 153, 154, 183, 181, 184, 182, 185, 152, 196, - 186, 187, 194, 195, 192, 193, 190, 191, 188, 189, - 169, 212, 213, 214, 215, 216, 217, 230, 231, 232, - 227, 228, 229, 242, 243, 244, 224, 225, 226, 239, - 240, 241, 221, 222, 223, 236, 237, 238, 218, 219, - 220, 233, 234, 235, 197, 198, 199, 245, 246, 247, - 158, 156, 157, 155, 161, 159, 160, 162, 163, 171, - 164, 165, 166, 167, 168, 200, 201, 202, 257, 258, - 259, 203, 204, 205, 269, 270, 271, 206, 207, 208, - 281, 282, 283, 209, 210, 211, 293, 294, 295, 134, - 133, 132, 0, 135, 248, 249, 250, 251, 252, 253, - 254, 255, 256, 260, 261, 262, 263, 264, 265, 266, - 267, 268, 272, 273, 274, 275, 276, 277, 278, 279, - 280, 284, 285, 286, 287, 288, 289, 290, 291, 292, - 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, - 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, - 316, 332, 333, 334, 335, 336, 337, 339, 340, 341, - 342, 343, 344, 346, 347, 350, 351, 352, 354, 355, - 317, 318, 338, 345, 356, 358, 359, 360, 362, 363, - 454, 319, 320, 321, 348, 322, 326, 327, 330, 353, - 357, 361, 323, 324, 328, 329, 349, 325, 331, 364, - 365, 366, 368, 370, 372, 374, 376, 380, 381, 382, - 383, 384, 385, 387, 388, 389, 390, 391, 392, 394, - 396, 397, 398, 400, 401, 378, 386, 393, 402, 404, - 405, 406, 408, 409, 367, 369, 371, 395, 373, 375, - 377, 379, 399, 403, 407, 455, 456, 459, 460, 461, - 462, 457, 458, 410, 412, 413, 414, 416, 417, 418, - 420, 421, 422, 424, 425, 426, 428, 429, 430, 432, - 433, 434, 436, 437, 438, 440, 441, 442, 444, 445, - 446, 448, 449, 450, 452, 453, 411, 415, 419, 423, - 427, 435, 439, 443, 431, 447, 451, 0, 180, 464, - 549, 131, 142, 465, 466, 467, 0, 548, 0, 550, - 0, 108, 107, 0, 119, 124, 149, 148, 146, 150, - 0, 143, 145, 151, 129, 174, 147, 463, 0, 545, - 547, 0, 0, 0, 470, 0, 0, 96, 93, 0, - 106, 0, 115, 109, 117, 0, 118, 0, 94, 125, - 0, 99, 144, 130, 0, 175, 1, 546, 172, 0, - 141, 139, 0, 137, 468, 0, 0, 97, 0, 0, - 551, 110, 114, 116, 112, 120, 111, 0, 126, 102, - 0, 100, 0, 2, 12, 13, 10, 11, 4, 5, - 6, 7, 8, 9, 15, 14, 0, 0, 0, 176, - 42, 41, 43, 40, 3, 17, 36, 19, 24, 25, - 0, 0, 29, 0, 44, 0, 48, 51, 54, 59, - 62, 64, 66, 68, 70, 72, 74, 0, 35, 33, - 0, 170, 0, 0, 136, 0, 0, 0, 0, 0, - 472, 95, 98, 0, 0, 530, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 496, 505, 509, 44, 77, - 90, 0, 485, 0, 151, 129, 488, 507, 487, 486, - 0, 489, 490, 511, 491, 518, 492, 493, 526, 494, - 0, 113, 0, 121, 0, 480, 128, 0, 0, 104, - 0, 101, 37, 38, 0, 21, 22, 0, 0, 27, - 26, 0, 180, 30, 32, 39, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 75, 177, 178, 0, 173, - 92, 140, 138, 0, 0, 478, 0, 476, 471, 473, - 541, 540, 0, 532, 0, 544, 542, 0, 0, 0, - 525, 528, 0, 495, 0, 80, 81, 83, 82, 85, - 86, 87, 88, 89, 84, 79, 0, 0, 510, 506, - 508, 512, 519, 527, 123, 0, 483, 0, 127, 0, - 105, 16, 0, 23, 20, 31, 45, 46, 47, 50, - 49, 52, 53, 57, 58, 55, 56, 60, 61, 63, - 65, 67, 69, 71, 73, 0, 179, 469, 0, 479, - 0, 474, 0, 0, 0, 543, 0, 524, 0, 555, - 0, 553, 497, 78, 91, 122, 481, 0, 103, 18, - 0, 475, 477, 0, 535, 534, 537, 503, 520, 516, - 0, 0, 0, 0, 0, 0, 0, 482, 484, 0, - 0, 536, 0, 0, 515, 0, 0, 513, 0, 0, - 0, 0, 552, 554, 498, 76, 0, 538, 0, 503, - 502, 504, 522, 0, 500, 529, 499, 556, 0, 539, - 533, 514, 523, 0, 517, 531, 521 -}; - - /* YYPGOTO[NTERM-NUM]. */ -static const yytype_int16 yypgoto[] = -{ - -634, -634, -634, -634, -634, -634, -634, -634, -634, -634, - -634, -634, -289, -634, -358, -355, -401, -364, -279, -307, - -276, -280, -273, -281, -634, -354, -634, -378, -634, -367, - -397, 1, -634, -634, -634, 2, -634, -634, -634, -98, - -93, -92, -634, -634, -600, -634, -634, -634, -634, -181, - -634, -319, -326, -634, 6, -634, 0, -332, -634, -54, - -634, -634, -634, -428, -433, -272, -353, -477, -634, -357, - -467, -633, -400, -634, -634, -410, -408, -634, -634, -80, - -545, -350, -634, -216, -634, -371, -634, -214, -634, -634, - -634, -634, -212, -634, -634, -634, -634, -634, -634, -634, - -634, -61, -634, -634, -634, -634, -375 -}; - - /* YYDEFGOTO[NTERM-NUM]. */ -static const yytype_int16 yydefgoto[] = -{ - -1, 414, 415, 416, 592, 417, 418, 419, 420, 421, - 422, 423, 468, 425, 426, 427, 428, 429, 430, 431, - 432, 433, 434, 435, 436, 469, 615, 470, 576, 471, - 541, 472, 318, 498, 392, 473, 320, 321, 322, 352, - 353, 354, 323, 324, 325, 326, 327, 328, 372, 373, - 329, 330, 331, 332, 438, 369, 439, 365, 335, 336, - 337, 446, 375, 449, 450, 546, 547, 496, 587, 476, - 477, 478, 479, 564, 656, 685, 664, 665, 666, 686, - 480, 481, 482, 483, 667, 652, 484, 485, 668, 693, - 486, 487, 488, 628, 552, 623, 646, 662, 663, 489, - 338, 339, 340, 349, 490, 630, 631 -}; - - /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If - positive, shift that token. If negative, reduce the rule whose - number is the opposite. If YYTABLE_NINF, syntax error. */ -static const yytype_int16 yytable[] = -{ - 334, 317, 319, 355, 362, 455, 333, 456, 457, 495, - 437, 460, 370, 580, 378, 584, 549, 586, 543, 632, - 588, 346, 343, 523, 524, 534, 348, 388, 650, 362, - 505, 506, 355, 681, 386, 364, 364, 684, 521, 522, - 364, 504, 492, 387, 513, 684, 650, 341, 377, -34, - 440, 507, 491, 493, 440, 508, 447, 497, 525, 526, - 535, 344, 452, 342, 440, 357, 347, 441, 358, 350, - 589, 585, 444, 442, 389, 424, 510, 390, 445, 654, - 391, 591, 511, 655, 647, 622, 538, 577, 500, 540, - 577, 501, 557, 636, 559, 637, 565, 566, 567, 568, - 569, 570, 571, 572, 573, 574, 648, 519, 635, 520, - 549, 351, 577, 359, 495, 575, 495, 502, 503, 495, - 688, 362, 603, 604, 605, 606, 577, 447, 577, 620, - 447, 578, 621, 595, 368, 577, 515, 692, 625, 620, - 593, 364, 641, 313, 314, 315, 516, 517, 518, 527, - 528, 424, 577, 627, 424, 374, 549, 577, 659, 379, - 658, 599, 600, 607, 608, 580, 601, 602, 384, 385, - 440, 443, 499, 451, 509, 514, 529, 530, 531, 447, - 532, 533, 536, 539, 545, 553, 550, 624, 551, 554, - 555, 626, 560, 562, 558, 561, 590, -35, 633, 634, - -33, 563, 594, -28, 616, 629, 694, 495, 639, 643, - 653, 660, 669, 619, 670, 577, -501, 672, 678, 677, - 674, 679, 687, 610, 447, 580, 465, 596, 597, 598, - 424, 424, 424, 424, 424, 424, 424, 424, 424, 424, - 424, 424, 424, 424, 424, 424, 682, 683, 640, 695, - 609, 696, 612, 614, 371, 611, 671, 382, 381, 495, - 613, 649, 345, 383, 542, 680, 644, 642, 690, 380, - 447, 691, 618, 645, 581, 661, 582, 367, 583, 649, - 673, 675, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 676, 0, 0, 0, 0, 0, 540, - 0, 0, 0, 463, 0, 495, 0, 0, 0, 651, - 689, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 356, 0, 0, 362, 0, 651, 333, 0, - 363, 0, 0, 0, 0, 0, 333, 0, 334, 317, - 319, 0, 0, 0, 333, 376, 0, 0, 0, 0, - 0, 356, 0, 0, 0, 356, 0, 333, 0, 0, - 0, 333, 0, 0, 424, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 448, 0, 0, 0, 475, - 0, 333, 0, 0, 0, 474, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 448, 544, 0, 448, - 0, 0, 333, 333, 0, 333, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 475, 0, 0, 0, 0, 0, 474, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 448, 0, - 0, 0, 0, 0, 333, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 448, 0, 0, 0, 0, 0, 333, - 0, 0, 475, 0, 0, 0, 0, 0, 474, 0, - 0, 0, 0, 0, 475, 0, 0, 0, 0, 0, - 474, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 448, - 0, 0, 0, 0, 0, 333, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 475, 0, 0, 0, 0, 475, 474, - 0, 0, 475, 0, 474, 0, 0, 0, 474, 0, - 0, 0, 0, 0, 0, 0, 475, 0, 0, 0, - 0, 363, 474, 0, 0, 0, 0, 333, 0, 0, - 0, 0, 0, 0, 0, 0, 475, 0, 0, 0, - 475, 0, 474, 0, 0, 0, 474, 0, 475, 0, - 0, 0, 475, 0, 474, 0, 0, 0, 474, 0, - 0, 0, 475, 0, 0, 0, 366, 0, 474, 1, - 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, - 12, 13, 14, 15, 16, 17, 18, 19, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, - 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, - 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, - 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, - 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, - 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, - 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, - 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, - 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, - 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, - 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, - 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, - 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, - 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, - 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, - 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, - 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, - 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, - 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, - 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, - 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, - 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, - 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, - 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, - 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, - 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, - 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, - 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, - 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, - 301, 302, 303, 304, 305, 306, 307, 308, 0, 0, - 309, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 310, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 311, 312, - 313, 314, 315, 316, 1, 2, 3, 4, 5, 6, - 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, - 17, 18, 19, 453, 454, 455, 0, 456, 457, 458, - 459, 460, 461, 462, 20, 21, 22, 23, 24, 25, - 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, - 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, - 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, - 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, - 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, - 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, - 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, - 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, - 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, - 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, - 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, - 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, - 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, - 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, - 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, - 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, - 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, - 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, - 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, - 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, - 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, - 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, - 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, - 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, - 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, - 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, - 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, - 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, - 306, 307, 308, 463, 393, 309, 394, 395, 396, 397, - 398, 399, 400, 401, 402, 403, 404, 405, 0, 0, - 406, 407, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 408, - 0, 464, 0, 465, 466, 0, 0, 0, 0, 467, - 410, 411, 412, 413, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 311, 312, 313, 314, 315, 316, 1, - 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, - 12, 13, 14, 15, 16, 17, 18, 19, 453, 454, - 455, 0, 456, 457, 458, 459, 460, 461, 462, 20, - 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, - 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, - 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, - 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, - 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, - 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, - 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, - 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, - 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, - 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, - 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, - 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, - 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, - 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, - 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, - 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, - 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, - 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, - 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, - 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, - 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, - 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, - 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, - 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, - 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, - 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, - 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, - 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, - 301, 302, 303, 304, 305, 306, 307, 308, 463, 393, - 309, 394, 395, 396, 397, 398, 399, 400, 401, 402, - 403, 404, 405, 0, 0, 406, 407, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 408, 0, 464, 0, 465, 579, - 0, 0, 0, 0, 467, 410, 411, 412, 413, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 311, 312, - 313, 314, 315, 316, 1, 2, 3, 4, 5, 6, - 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, - 17, 18, 19, 453, 454, 455, 0, 456, 457, 458, - 459, 460, 461, 462, 20, 21, 22, 23, 24, 25, - 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, - 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, - 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, - 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, - 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, - 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, - 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, - 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, - 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, - 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, - 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, - 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, - 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, - 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, - 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, - 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, - 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, - 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, - 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, - 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, - 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, - 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, - 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, - 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, - 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, - 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, - 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, - 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, - 306, 307, 308, 463, 393, 309, 394, 395, 396, 397, - 398, 399, 400, 401, 402, 403, 404, 405, 0, 0, - 406, 407, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 408, - 0, 464, 0, 465, 0, 0, 0, 0, 0, 467, - 410, 411, 412, 413, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 311, 312, 313, 314, 315, 316, 1, - 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, - 12, 13, 14, 15, 16, 17, 18, 19, 453, 454, - 455, 0, 456, 457, 458, 459, 460, 461, 462, 20, - 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, - 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, - 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, - 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, - 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, - 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, - 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, - 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, - 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, - 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, - 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, - 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, - 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, - 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, - 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, - 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, - 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, - 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, - 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, - 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, - 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, - 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, - 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, - 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, - 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, - 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, - 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, - 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, - 301, 302, 303, 304, 305, 306, 307, 308, 463, 393, - 309, 394, 395, 396, 397, 398, 399, 400, 401, 402, - 403, 404, 405, 0, 0, 406, 407, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 408, 0, 464, 0, 379, 0, - 0, 0, 0, 0, 467, 410, 411, 412, 413, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 311, 312, - 313, 314, 315, 316, 1, 2, 3, 4, 5, 6, - 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, - 17, 18, 19, 453, 454, 455, 0, 456, 457, 458, - 459, 460, 461, 462, 20, 21, 22, 23, 24, 25, - 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, - 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, - 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, - 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, - 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, - 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, - 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, - 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, - 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, - 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, - 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, - 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, - 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, - 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, - 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, - 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, - 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, - 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, - 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, - 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, - 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, - 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, - 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, - 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, - 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, - 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, - 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, - 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, - 306, 307, 308, 463, 393, 309, 394, 395, 396, 397, - 398, 399, 400, 401, 402, 403, 404, 405, 0, 0, - 406, 407, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 408, - 0, 464, 0, 0, 0, 0, 0, 0, 0, 467, - 410, 411, 412, 413, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 311, 312, 313, 314, 315, 316, 1, - 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, - 12, 13, 14, 15, 16, 17, 18, 19, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, - 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, - 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, - 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, - 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, - 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, - 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, - 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, - 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, - 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, - 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, - 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, - 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, - 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, - 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, - 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, - 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, - 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, - 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, - 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, - 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, - 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, - 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, - 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, - 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, - 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, - 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, - 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, - 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, - 301, 302, 303, 304, 305, 306, 307, 308, 0, 393, - 309, 394, 395, 396, 397, 398, 399, 400, 401, 402, - 403, 404, 405, 0, 0, 406, 407, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 408, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 467, 410, 411, 412, 413, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 311, 312, - 313, 314, 315, 316, 1, 2, 3, 4, 5, 6, - 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, - 17, 18, 19, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 20, 21, 22, 23, 24, 25, - 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, - 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, - 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, - 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, - 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, - 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, - 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, - 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, - 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, - 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, - 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, - 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, - 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, - 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, - 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, - 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, - 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, - 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, - 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, - 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, - 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, - 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, - 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, - 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, - 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, - 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, - 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, - 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, - 306, 307, 308, 0, 0, 309, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 310, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 311, 312, 313, 314, 315, 316, 1, - 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, - 12, 13, 14, 15, 16, 17, 18, 19, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, - 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, - 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, - 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, - 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, - 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, - 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, - 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, - 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, - 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, - 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, - 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, - 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, - 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, - 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, - 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, - 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, - 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, - 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, - 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, - 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, - 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, - 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, - 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, - 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, - 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, - 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, - 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, - 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, - 301, 302, 303, 304, 305, 306, 307, 308, 0, 393, - 309, 394, 395, 396, 397, 398, 399, 400, 401, 402, - 403, 404, 405, 0, 0, 406, 407, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 408, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 410, 411, 412, 413, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 311, 312, - 313, 314, 315, 1, 2, 3, 4, 5, 6, 7, - 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, - 18, 19, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 20, 21, 22, 23, 24, 25, 26, - 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, - 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, - 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, - 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, - 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, - 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, - 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, - 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, - 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, - 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, - 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, - 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, - 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, - 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, - 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, - 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, - 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, - 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, - 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, - 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, - 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, - 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, - 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, - 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, - 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, - 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, - 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, - 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, - 307, 308, 0, 360, 309, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 361, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 311, 312, 313, 314, 315, 1, 2, 3, - 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, - 14, 15, 16, 17, 18, 19, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 20, 21, 22, - 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, - 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, - 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, - 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, - 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, - 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, - 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, - 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, - 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, - 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, - 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, - 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, - 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, - 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, - 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, - 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, - 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, - 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, - 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, - 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, - 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, - 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, - 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, - 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, - 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, - 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, - 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, - 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, - 303, 304, 305, 306, 307, 308, 0, 0, 309, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 548, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 311, 312, 313, 314, - 315, 1, 2, 3, 4, 5, 6, 7, 8, 9, - 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 20, 21, 22, 23, 24, 25, 26, 27, 28, - 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, - 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, - 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, - 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, - 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, - 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, - 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, - 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, - 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, - 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, - 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, - 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, - 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, - 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, - 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, - 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, - 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, - 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, - 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, - 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, - 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, - 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, - 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, - 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, - 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, - 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, - 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, - 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, - 0, 0, 309, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 617, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 311, 312, 313, 314, 315, 1, 2, 3, 4, 5, - 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 20, 21, 22, 23, 24, - 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, - 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, - 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, - 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, - 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, - 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, - 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, - 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, - 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, - 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, - 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, - 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, - 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, - 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, - 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, - 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, - 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, - 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, - 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, - 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, - 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, - 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, - 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, - 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, - 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, - 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, - 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, - 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, - 305, 306, 307, 308, 0, 0, 309, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 638, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 311, 312, 313, 314, 315, 1, - 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, - 12, 13, 14, 15, 16, 17, 18, 19, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, - 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, - 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, - 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, - 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, - 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, - 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, - 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, - 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, - 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, - 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, - 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, - 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, - 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, - 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, - 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, - 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, - 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, - 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, - 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, - 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, - 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, - 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, - 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, - 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, - 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, - 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, - 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, - 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, - 301, 302, 303, 304, 305, 306, 307, 308, 0, 0, - 309, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 3, 4, 5, 6, 7, 0, - 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, - 19, 0, 0, 0, 0, 0, 0, 0, 311, 312, - 313, 314, 315, 21, 22, 23, 24, 25, 26, 27, - 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, - 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, - 58, 59, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 69, 0, 0, 0, 0, 0, 75, 76, 77, - 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, - 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, - 98, 0, 0, 0, 0, 0, 104, 105, 106, 107, - 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, - 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, - 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, - 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, - 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, - 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, - 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, - 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, - 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, - 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, - 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, - 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, - 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, - 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, - 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, - 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, - 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, - 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, - 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, - 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, - 308, 0, 393, 309, 394, 395, 396, 397, 398, 399, - 400, 401, 402, 403, 404, 405, 0, 0, 406, 407, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 408, 0, 0, - 0, 494, 657, 0, 0, 0, 0, 0, 410, 411, - 412, 413, 3, 4, 5, 6, 7, 0, 9, 10, - 11, 12, 13, 14, 15, 16, 17, 18, 19, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 21, 22, 23, 24, 25, 26, 27, 28, 29, - 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, - 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, - 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, - 0, 0, 0, 0, 0, 75, 76, 77, 78, 79, - 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, - 90, 91, 92, 93, 94, 95, 96, 97, 98, 0, - 0, 0, 0, 0, 104, 105, 106, 107, 108, 109, - 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, - 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, - 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, - 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, - 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, - 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, - 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, - 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, - 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, - 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, - 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, - 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, - 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, - 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, - 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, - 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, - 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, - 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, - 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, - 300, 301, 302, 303, 304, 305, 306, 307, 308, 0, - 393, 309, 394, 395, 396, 397, 398, 399, 400, 401, - 402, 403, 404, 405, 0, 0, 406, 407, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 408, 0, 0, 409, 0, - 0, 0, 0, 0, 0, 0, 410, 411, 412, 413, - 3, 4, 5, 6, 7, 0, 9, 10, 11, 12, - 13, 14, 15, 16, 17, 18, 19, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, - 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, - 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, - 52, 53, 54, 55, 56, 57, 58, 59, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 69, 0, 0, - 0, 0, 0, 75, 76, 77, 78, 79, 80, 81, - 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, - 92, 93, 94, 95, 96, 97, 98, 0, 0, 0, - 0, 0, 104, 105, 106, 107, 108, 109, 110, 111, - 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, - 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, - 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, - 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, - 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, - 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, - 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, - 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, - 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, - 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, - 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, - 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, - 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, - 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, - 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, - 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, - 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, - 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, - 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, - 302, 303, 304, 305, 306, 307, 308, 0, 393, 309, - 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, - 404, 405, 0, 0, 406, 407, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 408, 0, 0, 0, 494, 0, 0, - 0, 0, 0, 0, 410, 411, 412, 413, 3, 4, - 5, 6, 7, 0, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 21, 22, 23, - 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, - 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, - 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, - 54, 55, 56, 57, 58, 59, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 69, 0, 0, 0, 0, - 0, 75, 76, 77, 78, 79, 80, 81, 82, 83, - 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, - 94, 95, 96, 97, 98, 0, 0, 0, 0, 0, - 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, - 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, - 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, - 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, - 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, - 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, - 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, - 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, - 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, - 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, - 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, - 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, - 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, - 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, - 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, - 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, - 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, - 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, - 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, - 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, - 304, 305, 306, 307, 308, 0, 393, 309, 394, 395, - 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, - 0, 0, 406, 407, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 408, 0, 0, 537, 0, 0, 0, 0, 0, - 0, 0, 410, 411, 412, 413, 3, 4, 5, 6, - 7, 0, 9, 10, 11, 12, 13, 14, 15, 16, - 17, 18, 19, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 21, 22, 23, 24, 25, - 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, - 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, - 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, - 56, 57, 58, 59, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 69, 0, 0, 0, 0, 0, 75, - 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, - 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, - 96, 97, 98, 0, 0, 0, 0, 0, 104, 105, - 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, - 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, - 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, - 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, - 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, - 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, - 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, - 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, - 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, - 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, - 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, - 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, - 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, - 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, - 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, - 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, - 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, - 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, - 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, - 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, - 306, 307, 308, 0, 393, 309, 394, 395, 396, 397, - 398, 399, 400, 401, 402, 403, 404, 405, 0, 0, - 406, 407, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 408, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 556, - 410, 411, 412, 413, 3, 4, 5, 6, 7, 0, - 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, - 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 21, 22, 23, 24, 25, 26, 27, - 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, - 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, - 58, 59, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 69, 0, 0, 0, 0, 0, 75, 76, 77, - 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, - 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, - 98, 0, 0, 0, 0, 0, 104, 105, 106, 107, - 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, - 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, - 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, - 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, - 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, - 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, - 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, - 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, - 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, - 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, - 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, - 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, - 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, - 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, - 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, - 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, - 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, - 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, - 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, - 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, - 308, 0, 393, 309, 394, 395, 396, 397, 398, 399, - 400, 401, 402, 403, 404, 405, 0, 0, 406, 407, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 408, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 410, 411, - 412, 413, 3, 4, 5, 6, 7, 0, 9, 10, - 11, 12, 13, 14, 15, 16, 17, 18, 19, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 21, 22, 23, 24, 25, 26, 27, 28, 29, - 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, - 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, - 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, - 0, 0, 0, 0, 0, 75, 76, 77, 78, 79, - 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, - 90, 91, 92, 93, 94, 95, 96, 97, 98, 0, - 0, 0, 0, 0, 104, 105, 106, 107, 108, 109, - 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, - 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, - 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, - 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, - 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, - 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, - 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, - 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, - 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, - 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, - 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, - 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, - 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, - 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, - 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, - 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, - 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, - 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, - 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, - 300, 301, 302, 303, 304, 305, 306, 307, 512, 0, - 393, 309, 394, 395, 396, 397, 398, 399, 400, 401, - 402, 403, 404, 405, 0, 0, 406, 407, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 408, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 410, 411, 412, 413, - 3, 4, 5, 6, 7, 0, 9, 10, 11, 12, - 13, 14, 15, 16, 17, 18, 19, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, - 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, - 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, - 52, 53, 54, 55, 56, 57, 58, 59, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 75, 76, 77, 78, 79, 80, 81, - 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, - 92, 93, 94, 95, 96, 97, 98, 0, 0, 0, - 0, 0, 104, 105, 106, 107, 108, 109, 110, 111, - 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, - 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, - 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, - 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, - 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, - 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, - 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, - 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, - 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, - 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, - 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, - 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, - 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, - 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, - 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, - 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, - 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, - 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, - 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, - 302, 303, 304, 305, 306, 307, 308, 0, 0, 309 -}; - -static const yytype_int16 yycheck[] = -{ - 0, 0, 0, 322, 330, 24, 0, 26, 27, 387, - 364, 30, 81, 480, 346, 492, 449, 494, 446, 564, - 497, 323, 323, 341, 342, 346, 368, 359, 628, 355, - 339, 340, 351, 666, 358, 360, 360, 670, 337, 338, - 360, 408, 367, 367, 422, 678, 646, 358, 368, 358, - 360, 360, 384, 385, 360, 364, 375, 367, 376, 377, - 381, 362, 368, 358, 360, 365, 368, 359, 368, 359, - 498, 367, 359, 365, 362, 364, 359, 365, 365, 361, - 368, 359, 365, 365, 359, 552, 440, 365, 365, 443, - 365, 368, 459, 363, 461, 365, 348, 349, 350, 351, - 352, 353, 354, 355, 356, 357, 359, 370, 585, 372, - 543, 365, 365, 323, 492, 367, 494, 406, 407, 497, - 359, 447, 523, 524, 525, 526, 365, 446, 365, 365, - 449, 368, 368, 511, 323, 365, 425, 682, 368, 365, - 507, 360, 368, 384, 385, 386, 373, 374, 375, 343, - 344, 440, 365, 366, 443, 362, 589, 365, 366, 362, - 637, 519, 520, 527, 528, 632, 521, 522, 323, 323, - 360, 367, 323, 368, 359, 358, 380, 379, 378, 498, - 345, 347, 361, 323, 323, 358, 368, 554, 368, 358, - 368, 558, 366, 360, 358, 358, 323, 358, 576, 577, - 358, 363, 323, 359, 361, 323, 683, 585, 361, 322, - 358, 358, 323, 545, 359, 365, 362, 361, 359, 368, - 363, 25, 359, 530, 543, 692, 362, 516, 517, 518, - 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, - 529, 530, 531, 532, 533, 534, 362, 367, 615, 368, - 529, 363, 532, 534, 323, 531, 653, 355, 351, 637, - 533, 628, 316, 355, 445, 665, 623, 620, 678, 349, - 589, 679, 544, 623, 490, 646, 490, 338, 490, 646, - 655, 659, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 660, -1, -1, -1, -1, -1, 653, - -1, -1, -1, 322, -1, 683, -1, -1, -1, 628, - 677, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 322, -1, -1, 651, -1, 646, 322, -1, - 330, -1, -1, -1, -1, -1, 330, -1, 338, 338, - 338, -1, -1, -1, 338, 345, -1, -1, -1, -1, - -1, 351, -1, -1, -1, 355, -1, 351, -1, -1, - -1, 355, -1, -1, 653, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 375, -1, -1, -1, 379, - -1, 375, -1, -1, -1, 379, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 446, 447, -1, 449, - -1, -1, 446, 447, -1, 449, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 480, -1, -1, -1, -1, -1, 480, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 498, -1, - -1, -1, -1, -1, 498, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 543, -1, -1, -1, -1, -1, 543, - -1, -1, 552, -1, -1, -1, -1, -1, 552, -1, - -1, -1, -1, -1, 564, -1, -1, -1, -1, -1, - 564, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 589, - -1, -1, -1, -1, -1, 589, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 623, -1, -1, -1, -1, 628, 623, - -1, -1, 632, -1, 628, -1, -1, -1, 632, -1, - -1, -1, -1, -1, -1, -1, 646, -1, -1, -1, - -1, 651, 646, -1, -1, -1, -1, 651, -1, -1, - -1, -1, -1, -1, -1, -1, 666, -1, -1, -1, - 670, -1, 666, -1, -1, -1, 670, -1, 678, -1, - -1, -1, 682, -1, 678, -1, -1, -1, 682, -1, - -1, -1, 692, -1, -1, -1, 0, -1, 692, 3, - 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, - 14, 15, 16, 17, 18, 19, 20, 21, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 33, - 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, - 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, - 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, - 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, - 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, - 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, - 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, - 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, - 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, - 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, - 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, - 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, - 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, - 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, - 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, - 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, - 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, - 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, - 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, - 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, - 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, - 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, - 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, - 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, - 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, - 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, - 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, - 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, - 314, 315, 316, 317, 318, 319, 320, 321, -1, -1, - 324, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 368, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 382, 383, - 384, 385, 386, 387, 3, 4, 5, 6, 7, 8, - 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, - 19, 20, 21, 22, 23, 24, -1, 26, 27, 28, - 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, - 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, - 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, - 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, - 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, - 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, - 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, - 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, - 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, - 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, - 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, - 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, - 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, - 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, - 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, - 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, - 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, - 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, - 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, - 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, - 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, - 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, - 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, - 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, - 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, - 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, - 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, - 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, - 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, - 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, - 329, 330, 331, 332, 333, 334, 335, 336, -1, -1, - 339, 340, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 358, - -1, 360, -1, 362, 363, -1, -1, -1, -1, 368, - 369, 370, 371, 372, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 382, 383, 384, 385, 386, 387, 3, - 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, - 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, - 24, -1, 26, 27, 28, 29, 30, 31, 32, 33, - 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, - 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, - 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, - 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, - 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, - 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, - 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, - 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, - 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, - 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, - 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, - 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, - 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, - 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, - 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, - 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, - 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, - 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, - 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, - 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, - 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, - 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, - 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, - 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, - 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, - 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, - 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, - 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, - 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, - 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, - 334, 335, 336, -1, -1, 339, 340, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 358, -1, 360, -1, 362, 363, - -1, -1, -1, -1, 368, 369, 370, 371, 372, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 382, 383, - 384, 385, 386, 387, 3, 4, 5, 6, 7, 8, - 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, - 19, 20, 21, 22, 23, 24, -1, 26, 27, 28, - 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, - 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, - 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, - 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, - 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, - 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, - 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, - 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, - 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, - 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, - 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, - 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, - 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, - 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, - 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, - 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, - 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, - 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, - 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, - 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, - 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, - 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, - 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, - 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, - 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, - 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, - 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, - 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, - 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, - 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, - 329, 330, 331, 332, 333, 334, 335, 336, -1, -1, - 339, 340, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 358, - -1, 360, -1, 362, -1, -1, -1, -1, -1, 368, - 369, 370, 371, 372, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 382, 383, 384, 385, 386, 387, 3, - 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, - 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, - 24, -1, 26, 27, 28, 29, 30, 31, 32, 33, - 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, - 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, - 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, - 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, - 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, - 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, - 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, - 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, - 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, - 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, - 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, - 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, - 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, - 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, - 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, - 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, - 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, - 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, - 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, - 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, - 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, - 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, - 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, - 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, - 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, - 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, - 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, - 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, - 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, - 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, - 334, 335, 336, -1, -1, 339, 340, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 358, -1, 360, -1, 362, -1, - -1, -1, -1, -1, 368, 369, 370, 371, 372, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 382, 383, - 384, 385, 386, 387, 3, 4, 5, 6, 7, 8, - 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, - 19, 20, 21, 22, 23, 24, -1, 26, 27, 28, - 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, - 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, - 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, - 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, - 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, - 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, - 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, - 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, - 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, - 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, - 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, - 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, - 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, - 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, - 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, - 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, - 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, - 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, - 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, - 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, - 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, - 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, - 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, - 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, - 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, - 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, - 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, - 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, - 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, - 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, - 329, 330, 331, 332, 333, 334, 335, 336, -1, -1, - 339, 340, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 358, - -1, 360, -1, -1, -1, -1, -1, -1, -1, 368, - 369, 370, 371, 372, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 382, 383, 384, 385, 386, 387, 3, - 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, - 14, 15, 16, 17, 18, 19, 20, 21, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 33, - 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, - 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, - 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, - 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, - 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, - 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, - 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, - 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, - 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, - 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, - 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, - 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, - 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, - 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, - 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, - 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, - 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, - 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, - 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, - 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, - 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, - 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, - 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, - 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, - 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, - 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, - 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, - 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, - 314, 315, 316, 317, 318, 319, 320, 321, -1, 323, - 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, - 334, 335, 336, -1, -1, 339, 340, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 358, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 368, 369, 370, 371, 372, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 382, 383, - 384, 385, 386, 387, 3, 4, 5, 6, 7, 8, - 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, - 19, 20, 21, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 33, 34, 35, 36, 37, 38, - 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, - 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, - 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, - 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, - 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, - 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, - 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, - 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, - 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, - 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, - 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, - 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, - 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, - 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, - 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, - 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, - 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, - 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, - 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, - 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, - 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, - 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, - 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, - 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, - 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, - 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, - 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, - 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, - 319, 320, 321, -1, -1, 324, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 368, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 382, 383, 384, 385, 386, 387, 3, - 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, - 14, 15, 16, 17, 18, 19, 20, 21, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 33, - 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, - 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, - 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, - 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, - 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, - 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, - 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, - 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, - 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, - 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, - 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, - 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, - 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, - 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, - 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, - 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, - 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, - 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, - 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, - 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, - 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, - 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, - 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, - 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, - 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, - 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, - 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, - 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, - 314, 315, 316, 317, 318, 319, 320, 321, -1, 323, - 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, - 334, 335, 336, -1, -1, 339, 340, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 358, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 369, 370, 371, 372, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 382, 383, - 384, 385, 386, 3, 4, 5, 6, 7, 8, 9, - 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, - 20, 21, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 33, 34, 35, 36, 37, 38, 39, - 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, - 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, - 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, - 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, - 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, - 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, - 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, - 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, - 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, - 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, - 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, - 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, - 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, - 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, - 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, - 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, - 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, - 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, - 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, - 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, - 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, - 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, - 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, - 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, - 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, - 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, - 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, - 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, - 320, 321, -1, 323, 324, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 368, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 382, 383, 384, 385, 386, 3, 4, 5, - 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 33, 34, 35, - 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, - 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, - 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, - 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, - 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, - 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, - 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, - 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, - 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, - 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, - 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, - 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, - 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, - 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, - 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, - 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, - 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, - 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, - 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, - 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, - 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, - 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, - 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, - 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, - 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, - 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, - 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, - 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, - 316, 317, 318, 319, 320, 321, -1, -1, 324, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 363, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 382, 383, 384, 385, - 386, 3, 4, 5, 6, 7, 8, 9, 10, 11, - 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 33, 34, 35, 36, 37, 38, 39, 40, 41, - 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, - 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, - 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, - 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, - 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, - 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, - 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, - 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, - 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, - 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, - 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, - 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, - 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, - 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, - 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, - 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, - 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, - 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, - 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, - 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, - 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, - 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, - 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, - 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, - 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, - 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, - 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, - 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, - -1, -1, 324, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 363, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 382, 383, 384, 385, 386, 3, 4, 5, 6, 7, - 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, - 18, 19, 20, 21, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 33, 34, 35, 36, 37, - 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, - 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, - 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, - 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, - 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, - 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, - 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, - 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, - 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, - 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, - 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, - 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, - 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, - 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, - 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, - 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, - 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, - 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, - 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, - 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, - 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, - 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, - 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, - 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, - 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, - 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, - 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, - 318, 319, 320, 321, -1, -1, 324, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 363, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 382, 383, 384, 385, 386, 3, - 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, - 14, 15, 16, 17, 18, 19, 20, 21, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 33, - 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, - 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, - 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, - 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, - 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, - 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, - 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, - 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, - 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, - 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, - 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, - 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, - 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, - 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, - 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, - 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, - 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, - 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, - 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, - 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, - 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, - 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, - 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, - 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, - 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, - 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, - 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, - 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, - 314, 315, 316, 317, 318, 319, 320, 321, -1, -1, - 324, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 5, 6, 7, 8, 9, -1, - 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, - 21, -1, -1, -1, -1, -1, -1, -1, 382, 383, - 384, 385, 386, 34, 35, 36, 37, 38, 39, 40, - 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, - 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, - 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, - 71, 72, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 82, -1, -1, -1, -1, -1, 88, 89, 90, - 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, - 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, - 111, -1, -1, -1, -1, -1, 117, 118, 119, 120, - 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, - 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, - 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, - 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, - 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, - 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, - 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, - 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, - 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, - 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, - 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, - 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, - 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, - 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, - 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, - 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, - 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, - 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, - 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, - 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, - 321, -1, 323, 324, 325, 326, 327, 328, 329, 330, - 331, 332, 333, 334, 335, 336, -1, -1, 339, 340, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 358, -1, -1, - -1, 362, 363, -1, -1, -1, -1, -1, 369, 370, - 371, 372, 5, 6, 7, 8, 9, -1, 11, 12, - 13, 14, 15, 16, 17, 18, 19, 20, 21, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 34, 35, 36, 37, 38, 39, 40, 41, 42, - 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, - 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, - 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 82, - -1, -1, -1, -1, -1, 88, 89, 90, 91, 92, - 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, - 103, 104, 105, 106, 107, 108, 109, 110, 111, -1, - -1, -1, -1, -1, 117, 118, 119, 120, 121, 122, - 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, - 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, - 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, - 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, - 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, - 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, - 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, - 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, - 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, - 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, - 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, - 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, - 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, - 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, - 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, - 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, - 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, - 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, - 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, - 313, 314, 315, 316, 317, 318, 319, 320, 321, -1, - 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, - 333, 334, 335, 336, -1, -1, 339, 340, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 358, -1, -1, 361, -1, - -1, -1, -1, -1, -1, -1, 369, 370, 371, 372, - 5, 6, 7, 8, 9, -1, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 34, - 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, - 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, - 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, - 65, 66, 67, 68, 69, 70, 71, 72, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 82, -1, -1, - -1, -1, -1, 88, 89, 90, 91, 92, 93, 94, - 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, - 105, 106, 107, 108, 109, 110, 111, -1, -1, -1, - -1, -1, 117, 118, 119, 120, 121, 122, 123, 124, - 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, - 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, - 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, - 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, - 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, - 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, - 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, - 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, - 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, - 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, - 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, - 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, - 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, - 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, - 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, - 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, - 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, - 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, - 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, - 315, 316, 317, 318, 319, 320, 321, -1, 323, 324, - 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, - 335, 336, -1, -1, 339, 340, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 358, -1, -1, -1, 362, -1, -1, - -1, -1, -1, -1, 369, 370, 371, 372, 5, 6, - 7, 8, 9, -1, 11, 12, 13, 14, 15, 16, - 17, 18, 19, 20, 21, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 34, 35, 36, - 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, - 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, - 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, - 67, 68, 69, 70, 71, 72, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 82, -1, -1, -1, -1, - -1, 88, 89, 90, 91, 92, 93, 94, 95, 96, - 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, - 107, 108, 109, 110, 111, -1, -1, -1, -1, -1, - 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, - 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, - 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, - 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, - 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, - 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, - 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, - 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, - 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, - 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, - 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, - 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, - 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, - 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, - 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, - 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, - 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, - 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, - 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, - 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, - 317, 318, 319, 320, 321, -1, 323, 324, 325, 326, - 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, - -1, -1, 339, 340, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 358, -1, -1, 361, -1, -1, -1, -1, -1, - -1, -1, 369, 370, 371, 372, 5, 6, 7, 8, - 9, -1, 11, 12, 13, 14, 15, 16, 17, 18, - 19, 20, 21, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 34, 35, 36, 37, 38, - 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, - 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, - 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, - 69, 70, 71, 72, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 82, -1, -1, -1, -1, -1, 88, - 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, - 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, - 109, 110, 111, -1, -1, -1, -1, -1, 117, 118, - 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, - 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, - 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, - 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, - 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, - 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, - 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, - 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, - 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, - 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, - 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, - 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, - 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, - 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, - 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, - 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, - 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, - 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, - 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, - 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, - 319, 320, 321, -1, 323, 324, 325, 326, 327, 328, - 329, 330, 331, 332, 333, 334, 335, 336, -1, -1, - 339, 340, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 358, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 368, - 369, 370, 371, 372, 5, 6, 7, 8, 9, -1, - 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, - 21, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 34, 35, 36, 37, 38, 39, 40, - 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, - 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, - 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, - 71, 72, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 82, -1, -1, -1, -1, -1, 88, 89, 90, - 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, - 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, - 111, -1, -1, -1, -1, -1, 117, 118, 119, 120, - 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, - 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, - 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, - 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, - 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, - 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, - 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, - 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, - 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, - 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, - 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, - 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, - 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, - 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, - 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, - 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, - 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, - 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, - 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, - 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, - 321, -1, 323, 324, 325, 326, 327, 328, 329, 330, - 331, 332, 333, 334, 335, 336, -1, -1, 339, 340, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 358, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 369, 370, - 371, 372, 5, 6, 7, 8, 9, -1, 11, 12, - 13, 14, 15, 16, 17, 18, 19, 20, 21, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 34, 35, 36, 37, 38, 39, 40, 41, 42, - 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, - 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, - 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 82, - -1, -1, -1, -1, -1, 88, 89, 90, 91, 92, - 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, - 103, 104, 105, 106, 107, 108, 109, 110, 111, -1, - -1, -1, -1, -1, 117, 118, 119, 120, 121, 122, - 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, - 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, - 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, - 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, - 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, - 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, - 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, - 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, - 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, - 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, - 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, - 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, - 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, - 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, - 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, - 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, - 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, - 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, - 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, - 313, 314, 315, 316, 317, 318, 319, 320, 321, -1, - 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, - 333, 334, 335, 336, -1, -1, 339, 340, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 358, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 369, 370, 371, 372, - 5, 6, 7, 8, 9, -1, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 34, - 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, - 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, - 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, - 65, 66, 67, 68, 69, 70, 71, 72, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 88, 89, 90, 91, 92, 93, 94, - 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, - 105, 106, 107, 108, 109, 110, 111, -1, -1, -1, - -1, -1, 117, 118, 119, 120, 121, 122, 123, 124, - 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, - 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, - 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, - 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, - 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, - 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, - 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, - 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, - 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, - 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, - 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, - 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, - 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, - 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, - 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, - 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, - 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, - 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, - 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, - 315, 316, 317, 318, 319, 320, 321, -1, -1, 324 -}; - - /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing - symbol of state STATE-NUM. */ -static const yytype_uint16 yystos[] = -{ - 0, 3, 4, 5, 6, 7, 8, 9, 10, 11, - 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, - 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, - 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, - 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, - 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, - 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, - 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, - 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, - 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, - 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, - 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, - 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, - 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, - 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, - 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, - 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, - 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, - 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, - 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, - 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, - 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, - 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, - 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, - 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, - 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, - 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, - 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, - 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, - 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, - 313, 314, 315, 316, 317, 318, 319, 320, 321, 324, - 368, 382, 383, 384, 385, 386, 387, 422, 423, 426, - 427, 428, 429, 433, 434, 435, 436, 437, 438, 441, - 442, 443, 444, 445, 447, 449, 450, 451, 491, 492, - 493, 358, 358, 323, 362, 450, 323, 368, 368, 494, - 359, 365, 430, 431, 432, 442, 447, 365, 368, 323, - 323, 368, 443, 447, 360, 448, 0, 492, 323, 446, - 81, 323, 439, 440, 362, 453, 447, 368, 448, 362, - 470, 431, 430, 432, 323, 323, 358, 367, 448, 362, - 365, 368, 425, 323, 325, 326, 327, 328, 329, 330, - 331, 332, 333, 334, 335, 336, 339, 340, 358, 361, - 369, 370, 371, 372, 392, 393, 394, 396, 397, 398, - 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, - 409, 410, 411, 412, 413, 414, 415, 416, 445, 447, - 360, 359, 365, 367, 359, 365, 452, 442, 447, 454, - 455, 368, 368, 22, 23, 24, 26, 27, 28, 29, - 30, 31, 32, 322, 360, 362, 363, 368, 403, 416, - 418, 420, 422, 426, 445, 447, 460, 461, 462, 463, - 471, 472, 473, 474, 477, 478, 481, 482, 483, 490, - 495, 448, 367, 448, 362, 418, 458, 367, 424, 323, - 365, 368, 403, 403, 420, 339, 340, 360, 364, 359, - 359, 365, 321, 418, 358, 403, 373, 374, 375, 370, - 372, 337, 338, 341, 342, 376, 377, 343, 344, 380, - 379, 378, 345, 347, 346, 381, 361, 361, 416, 323, - 416, 421, 440, 454, 447, 323, 456, 457, 363, 455, - 368, 368, 485, 358, 358, 368, 368, 420, 358, 420, - 366, 358, 360, 363, 464, 348, 349, 350, 351, 352, - 353, 354, 355, 356, 357, 367, 419, 365, 368, 363, - 461, 474, 478, 483, 458, 367, 458, 459, 458, 454, - 323, 359, 395, 420, 323, 418, 403, 403, 403, 405, - 405, 406, 406, 407, 407, 407, 407, 408, 408, 409, - 410, 411, 412, 413, 414, 417, 361, 363, 456, 448, - 365, 368, 461, 486, 420, 368, 420, 366, 484, 323, - 496, 497, 471, 418, 418, 458, 363, 365, 363, 361, - 420, 368, 457, 322, 460, 472, 487, 359, 359, 420, - 435, 442, 476, 358, 361, 365, 465, 363, 458, 366, - 358, 476, 488, 489, 467, 468, 469, 475, 479, 323, - 359, 421, 361, 497, 363, 418, 420, 368, 359, 25, - 463, 462, 362, 367, 462, 466, 470, 359, 359, 420, - 466, 467, 471, 480, 458, 368, 363 -}; - - /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ -static const yytype_uint16 yyr1[] = -{ - 0, 391, 392, 393, 393, 393, 393, 393, 393, 393, - 393, 393, 393, 393, 393, 393, 393, 394, 394, 394, - 394, 394, 394, 395, 396, 397, 398, 398, 399, 399, - 400, 400, 401, 402, 402, 402, 403, 403, 403, 403, - 404, 404, 404, 404, 405, 405, 405, 405, 406, 406, - 406, 407, 407, 407, 408, 408, 408, 408, 408, 409, - 409, 409, 410, 410, 411, 411, 412, 412, 413, 413, - 414, 414, 415, 415, 416, 417, 416, 418, 418, 419, - 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, - 420, 420, 421, 422, 422, 422, 422, 422, 422, 422, - 422, 422, 424, 423, 425, 425, 426, 427, 427, 428, - 428, 429, 430, 430, 431, 431, 431, 431, 432, 433, - 433, 433, 433, 433, 434, 434, 434, 434, 434, 435, - 435, 436, 437, 437, 437, 437, 438, 439, 439, 440, - 440, 440, 441, 442, 442, 443, 443, 443, 443, 443, - 443, 443, 444, 444, 444, 444, 444, 444, 444, 444, - 444, 444, 444, 444, 444, 444, 444, 444, 444, 444, - 444, 445, 446, 446, 447, 447, 448, 448, 448, 448, - 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, - 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, - 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, - 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, - 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, - 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, - 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, - 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, - 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, - 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, - 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, - 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, - 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, - 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, - 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, - 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, - 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, - 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, - 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, - 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, - 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, - 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, - 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, - 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, - 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, - 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, - 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, - 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, - 449, 449, 449, 449, 449, 450, 450, 450, 452, 451, - 453, 451, 454, 454, 455, 455, 456, 456, 457, 457, - 458, 458, 458, 459, 459, 460, 461, 461, 462, 462, - 462, 462, 462, 462, 462, 463, 464, 465, 463, 466, - 466, 468, 467, 469, 467, 470, 470, 471, 471, 472, - 472, 473, 473, 474, 475, 475, 476, 476, 477, 477, - 479, 478, 480, 480, 481, 481, 482, 482, 484, 483, - 485, 483, 486, 483, 487, 487, 488, 488, 489, 489, - 490, 490, 490, 490, 490, 491, 491, 492, 492, 492, - 494, 493, 495, 496, 496, 497, 497 -}; - - /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN. */ -static const yytype_uint8 yyr2[] = -{ - 0, 2, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 3, 1, 4, 1, - 3, 2, 2, 1, 1, 1, 2, 2, 2, 1, - 2, 3, 2, 1, 1, 1, 1, 2, 2, 2, - 1, 1, 1, 1, 1, 3, 3, 3, 1, 3, - 3, 1, 3, 3, 1, 3, 3, 3, 3, 1, - 3, 3, 1, 3, 1, 3, 1, 3, 1, 3, - 1, 3, 1, 3, 1, 0, 6, 1, 3, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 3, 1, 2, 2, 4, 2, 3, 4, 2, - 3, 4, 0, 6, 2, 3, 2, 1, 1, 2, - 3, 3, 2, 3, 2, 1, 2, 1, 1, 1, - 3, 4, 6, 5, 1, 2, 3, 5, 4, 1, - 2, 1, 1, 1, 1, 1, 4, 1, 3, 1, - 3, 1, 1, 1, 2, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 4, 1, 1, 3, 1, 2, 2, 3, 3, 4, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 0, 6, - 0, 5, 1, 2, 3, 4, 1, 3, 1, 2, - 1, 3, 4, 1, 3, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 2, 0, 0, 5, 1, - 1, 0, 2, 0, 2, 2, 3, 1, 2, 1, - 2, 1, 2, 5, 3, 1, 1, 4, 1, 2, - 0, 8, 0, 1, 3, 2, 1, 2, 0, 6, - 0, 8, 0, 7, 1, 1, 1, 0, 2, 3, - 2, 2, 2, 3, 2, 1, 2, 1, 1, 1, - 0, 3, 5, 1, 3, 1, 4 -}; - - -#define yyerrok (yyerrstatus = 0) -#define yyclearin (yychar = YYEMPTY) -#define YYEMPTY (-2) -#define YYEOF 0 - -#define YYACCEPT goto yyacceptlab -#define YYABORT goto yyabortlab -#define YYERROR goto yyerrorlab - - -#define YYRECOVERING() (!!yyerrstatus) - -#define YYBACKUP(Token, Value) \ -do \ - if (yychar == YYEMPTY) \ - { \ - yychar = (Token); \ - yylval = (Value); \ - YYPOPSTACK (yylen); \ - yystate = *yyssp; \ - goto yybackup; \ - } \ - else \ - { \ - yyerror (pParseContext, YY_("syntax error: cannot back up")); \ - YYERROR; \ - } \ -while (0) - -/* Error token number */ -#define YYTERROR 1 -#define YYERRCODE 256 - - - -/* Enable debugging if requested. */ -#if YYDEBUG - -# ifndef YYFPRINTF -# include /* INFRINGES ON USER NAME SPACE */ -# define YYFPRINTF fprintf -# endif - -# define YYDPRINTF(Args) \ -do { \ - if (yydebug) \ - YYFPRINTF Args; \ -} while (0) - -/* This macro is provided for backward compatibility. */ -#ifndef YY_LOCATION_PRINT -# define YY_LOCATION_PRINT(File, Loc) ((void) 0) -#endif - - -# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ -do { \ - if (yydebug) \ - { \ - YYFPRINTF (stderr, "%s ", Title); \ - yy_symbol_print (stderr, \ - Type, Value, pParseContext); \ - YYFPRINTF (stderr, "\n"); \ - } \ -} while (0) - - -/*----------------------------------------. -| Print this symbol's value on YYOUTPUT. | -`----------------------------------------*/ - -static void -yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, glslang::TParseContext* pParseContext) -{ - FILE *yyo = yyoutput; - YYUSE (yyo); - YYUSE (pParseContext); - if (!yyvaluep) - return; -# ifdef YYPRINT - if (yytype < YYNTOKENS) - YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); -# endif - YYUSE (yytype); -} - - -/*--------------------------------. -| Print this symbol on YYOUTPUT. | -`--------------------------------*/ - -static void -yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, glslang::TParseContext* pParseContext) -{ - YYFPRINTF (yyoutput, "%s %s (", - yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]); - - yy_symbol_value_print (yyoutput, yytype, yyvaluep, pParseContext); - YYFPRINTF (yyoutput, ")"); -} - -/*------------------------------------------------------------------. -| yy_stack_print -- Print the state stack from its BOTTOM up to its | -| TOP (included). | -`------------------------------------------------------------------*/ - -static void -yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop) -{ - YYFPRINTF (stderr, "Stack now"); - for (; yybottom <= yytop; yybottom++) - { - int yybot = *yybottom; - YYFPRINTF (stderr, " %d", yybot); - } - YYFPRINTF (stderr, "\n"); -} - -# define YY_STACK_PRINT(Bottom, Top) \ -do { \ - if (yydebug) \ - yy_stack_print ((Bottom), (Top)); \ -} while (0) - - -/*------------------------------------------------. -| Report that the YYRULE is going to be reduced. | -`------------------------------------------------*/ - -static void -yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, int yyrule, glslang::TParseContext* pParseContext) -{ - unsigned long int yylno = yyrline[yyrule]; - int yynrhs = yyr2[yyrule]; - int yyi; - YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n", - yyrule - 1, yylno); - /* The symbols being reduced. */ - for (yyi = 0; yyi < yynrhs; yyi++) - { - YYFPRINTF (stderr, " $%d = ", yyi + 1); - yy_symbol_print (stderr, - yystos[yyssp[yyi + 1 - yynrhs]], - &(yyvsp[(yyi + 1) - (yynrhs)]) - , pParseContext); - YYFPRINTF (stderr, "\n"); - } -} - -# define YY_REDUCE_PRINT(Rule) \ -do { \ - if (yydebug) \ - yy_reduce_print (yyssp, yyvsp, Rule, pParseContext); \ -} while (0) - -/* Nonzero means print parse trace. It is left uninitialized so that - multiple parsers can coexist. */ -int yydebug; -#else /* !YYDEBUG */ -# define YYDPRINTF(Args) -# define YY_SYMBOL_PRINT(Title, Type, Value, Location) -# define YY_STACK_PRINT(Bottom, Top) -# define YY_REDUCE_PRINT(Rule) -#endif /* !YYDEBUG */ - - -/* YYINITDEPTH -- initial size of the parser's stacks. */ -#ifndef YYINITDEPTH -# define YYINITDEPTH 200 -#endif - -/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only - if the built-in stack extension method is used). - - Do not make this value too large; the results are undefined if - YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH) - evaluated with infinite-precision integer arithmetic. */ - -#ifndef YYMAXDEPTH -# define YYMAXDEPTH 10000 -#endif - - -#if YYERROR_VERBOSE - -# ifndef yystrlen -# if defined __GLIBC__ && defined _STRING_H -# define yystrlen strlen -# else -/* Return the length of YYSTR. */ -static YYSIZE_T -yystrlen (const char *yystr) -{ - YYSIZE_T yylen; - for (yylen = 0; yystr[yylen]; yylen++) - continue; - return yylen; -} -# endif -# endif - -# ifndef yystpcpy -# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE -# define yystpcpy stpcpy -# else -/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in - YYDEST. */ -static char * -yystpcpy (char *yydest, const char *yysrc) -{ - char *yyd = yydest; - const char *yys = yysrc; - - while ((*yyd++ = *yys++) != '\0') - continue; - - return yyd - 1; -} -# endif -# endif - -# ifndef yytnamerr -/* Copy to YYRES the contents of YYSTR after stripping away unnecessary - quotes and backslashes, so that it's suitable for yyerror. The - heuristic is that double-quoting is unnecessary unless the string - contains an apostrophe, a comma, or backslash (other than - backslash-backslash). YYSTR is taken from yytname. If YYRES is - null, do not copy; instead, return the length of what the result - would have been. */ -static YYSIZE_T -yytnamerr (char *yyres, const char *yystr) -{ - if (*yystr == '"') - { - YYSIZE_T yyn = 0; - char const *yyp = yystr; - - for (;;) - switch (*++yyp) - { - case '\'': - case ',': - goto do_not_strip_quotes; - - case '\\': - if (*++yyp != '\\') - goto do_not_strip_quotes; - /* Fall through. */ - default: - if (yyres) - yyres[yyn] = *yyp; - yyn++; - break; - - case '"': - if (yyres) - yyres[yyn] = '\0'; - return yyn; - } - do_not_strip_quotes: ; - } - - if (! yyres) - return yystrlen (yystr); - - return yystpcpy (yyres, yystr) - yyres; -} -# endif - -/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message - about the unexpected token YYTOKEN for the state stack whose top is - YYSSP. - - Return 0 if *YYMSG was successfully written. Return 1 if *YYMSG is - not large enough to hold the message. In that case, also set - *YYMSG_ALLOC to the required number of bytes. Return 2 if the - required number of bytes is too large to store. */ -static int -yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, - yytype_int16 *yyssp, int yytoken) -{ - YYSIZE_T yysize0 = yytnamerr (YY_NULL, yytname[yytoken]); - YYSIZE_T yysize = yysize0; - enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; - /* Internationalized format string. */ - const char *yyformat = YY_NULL; - /* Arguments of yyformat. */ - char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; - /* Number of reported tokens (one for the "unexpected", one per - "expected"). */ - int yycount = 0; - - /* There are many possibilities here to consider: - - If this state is a consistent state with a default action, then - the only way this function was invoked is if the default action - is an error action. In that case, don't check for expected - tokens because there are none. - - The only way there can be no lookahead present (in yychar) is if - this state is a consistent state with a default action. Thus, - detecting the absence of a lookahead is sufficient to determine - that there is no unexpected or expected token to report. In that - case, just report a simple "syntax error". - - Don't assume there isn't a lookahead just because this state is a - consistent state with a default action. There might have been a - previous inconsistent state, consistent state with a non-default - action, or user semantic action that manipulated yychar. - - Of course, the expected token list depends on states to have - correct lookahead information, and it depends on the parser not - to perform extra reductions after fetching a lookahead from the - scanner and before detecting a syntax error. Thus, state merging - (from LALR or IELR) and default reductions corrupt the expected - token list. However, the list is correct for canonical LR with - one exception: it will still contain any token that will not be - accepted due to an error action in a later state. - */ - if (yytoken != YYEMPTY) - { - int yyn = yypact[*yyssp]; - yyarg[yycount++] = yytname[yytoken]; - if (!yypact_value_is_default (yyn)) - { - /* Start YYX at -YYN if negative to avoid negative indexes in - YYCHECK. In other words, skip the first -YYN actions for - this state because they are default actions. */ - int yyxbegin = yyn < 0 ? -yyn : 0; - /* Stay within bounds of both yycheck and yytname. */ - int yychecklim = YYLAST - yyn + 1; - int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; - int yyx; - - for (yyx = yyxbegin; yyx < yyxend; ++yyx) - if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR - && !yytable_value_is_error (yytable[yyx + yyn])) - { - if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) - { - yycount = 1; - yysize = yysize0; - break; - } - yyarg[yycount++] = yytname[yyx]; - { - YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULL, yytname[yyx]); - if (! (yysize <= yysize1 - && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) - return 2; - yysize = yysize1; - } - } - } - } - - switch (yycount) - { -# define YYCASE_(N, S) \ - case N: \ - yyformat = S; \ - break - YYCASE_(0, YY_("syntax error")); - YYCASE_(1, YY_("syntax error, unexpected %s")); - YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s")); - YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s")); - YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s")); - YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s")); -# undef YYCASE_ - } - - { - YYSIZE_T yysize1 = yysize + yystrlen (yyformat); - if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) - return 2; - yysize = yysize1; - } - - if (*yymsg_alloc < yysize) - { - *yymsg_alloc = 2 * yysize; - if (! (yysize <= *yymsg_alloc - && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM)) - *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM; - return 1; - } - - /* Avoid sprintf, as that infringes on the user's name space. - Don't have undefined behavior even if the translation - produced a string with the wrong number of "%s"s. */ - { - char *yyp = *yymsg; - int yyi = 0; - while ((*yyp = *yyformat) != '\0') - if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount) - { - yyp += yytnamerr (yyp, yyarg[yyi++]); - yyformat += 2; - } - else - { - yyp++; - yyformat++; - } - } - return 0; -} -#endif /* YYERROR_VERBOSE */ - -/*-----------------------------------------------. -| Release the memory associated to this symbol. | -`-----------------------------------------------*/ - -static void -yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, glslang::TParseContext* pParseContext) -{ - YYUSE (yyvaluep); - YYUSE (pParseContext); - if (!yymsg) - yymsg = "Deleting"; - YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); - - YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN - YYUSE (yytype); - YY_IGNORE_MAYBE_UNINITIALIZED_END -} - - - - -/*----------. -| yyparse. | -`----------*/ - -int -yyparse (glslang::TParseContext* pParseContext) -{ -/* The lookahead symbol. */ -int yychar; - - -/* The semantic value of the lookahead symbol. */ -/* Default value used for initialization, for pacifying older GCCs - or non-GCC compilers. */ -YY_INITIAL_VALUE (static YYSTYPE yyval_default;) -YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); - - /* Number of syntax errors so far. */ - int yynerrs; - - int yystate; - /* Number of tokens to shift before error messages enabled. */ - int yyerrstatus; - - /* The stacks and their tools: - 'yyss': related to states. - 'yyvs': related to semantic values. - - Refer to the stacks through separate pointers, to allow yyoverflow - to reallocate them elsewhere. */ - - /* The state stack. */ - yytype_int16 yyssa[YYINITDEPTH]; - yytype_int16 *yyss; - yytype_int16 *yyssp; - - /* The semantic value stack. */ - YYSTYPE yyvsa[YYINITDEPTH]; - YYSTYPE *yyvs; - YYSTYPE *yyvsp; - - YYSIZE_T yystacksize; - - int yyn; - int yyresult; - /* Lookahead token as an internal (translated) token number. */ - int yytoken = 0; - /* The variables used to return semantic value and location from the - action routines. */ - YYSTYPE yyval; - -#if YYERROR_VERBOSE - /* Buffer for error messages, and its allocated size. */ - char yymsgbuf[128]; - char *yymsg = yymsgbuf; - YYSIZE_T yymsg_alloc = sizeof yymsgbuf; -#endif - -#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N)) - - /* The number of symbols on the RHS of the reduced rule. - Keep to zero when no symbol should be popped. */ - int yylen = 0; - - yyssp = yyss = yyssa; - yyvsp = yyvs = yyvsa; - yystacksize = YYINITDEPTH; - - YYDPRINTF ((stderr, "Starting parse\n")); - - yystate = 0; - yyerrstatus = 0; - yynerrs = 0; - yychar = YYEMPTY; /* Cause a token to be read. */ - goto yysetstate; - -/*------------------------------------------------------------. -| yynewstate -- Push a new state, which is found in yystate. | -`------------------------------------------------------------*/ - yynewstate: - /* In all cases, when you get here, the value and location stacks - have just been pushed. So pushing a state here evens the stacks. */ - yyssp++; - - yysetstate: - *yyssp = yystate; - - if (yyss + yystacksize - 1 <= yyssp) - { - /* Get the current used size of the three stacks, in elements. */ - YYSIZE_T yysize = yyssp - yyss + 1; - -#ifdef yyoverflow - { - /* Give user a chance to reallocate the stack. Use copies of - these so that the &'s don't force the real ones into - memory. */ - YYSTYPE *yyvs1 = yyvs; - yytype_int16 *yyss1 = yyss; - - /* Each stack pointer address is followed by the size of the - data in use in that stack, in bytes. This used to be a - conditional around just the two extra args, but that might - be undefined if yyoverflow is a macro. */ - yyoverflow (YY_("memory exhausted"), - &yyss1, yysize * sizeof (*yyssp), - &yyvs1, yysize * sizeof (*yyvsp), - &yystacksize); - - yyss = yyss1; - yyvs = yyvs1; - } -#else /* no yyoverflow */ -# ifndef YYSTACK_RELOCATE - goto yyexhaustedlab; -# else - /* Extend the stack our own way. */ - if (YYMAXDEPTH <= yystacksize) - goto yyexhaustedlab; - yystacksize *= 2; - if (YYMAXDEPTH < yystacksize) - yystacksize = YYMAXDEPTH; - - { - yytype_int16 *yyss1 = yyss; - union yyalloc *yyptr = - (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); - if (! yyptr) - goto yyexhaustedlab; - YYSTACK_RELOCATE (yyss_alloc, yyss); - YYSTACK_RELOCATE (yyvs_alloc, yyvs); -# undef YYSTACK_RELOCATE - if (yyss1 != yyssa) - YYSTACK_FREE (yyss1); - } -# endif -#endif /* no yyoverflow */ - - yyssp = yyss + yysize - 1; - yyvsp = yyvs + yysize - 1; - - YYDPRINTF ((stderr, "Stack size increased to %lu\n", - (unsigned long int) yystacksize)); - - if (yyss + yystacksize - 1 <= yyssp) - YYABORT; - } - - YYDPRINTF ((stderr, "Entering state %d\n", yystate)); - - if (yystate == YYFINAL) - YYACCEPT; - - goto yybackup; - -/*-----------. -| yybackup. | -`-----------*/ -yybackup: - - /* Do appropriate processing given the current state. Read a - lookahead token if we need one and don't already have one. */ - - /* First try to decide what to do without reference to lookahead token. */ - yyn = yypact[yystate]; - if (yypact_value_is_default (yyn)) - goto yydefault; - - /* Not known => get a lookahead token if don't already have one. */ - - /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */ - if (yychar == YYEMPTY) - { - YYDPRINTF ((stderr, "Reading a token: ")); - yychar = yylex (&yylval, parseContext); - } - - if (yychar <= YYEOF) - { - yychar = yytoken = YYEOF; - YYDPRINTF ((stderr, "Now at end of input.\n")); - } - else - { - yytoken = YYTRANSLATE (yychar); - YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); - } - - /* If the proper action on seeing token YYTOKEN is to reduce or to - detect an error, take that action. */ - yyn += yytoken; - if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) - goto yydefault; - yyn = yytable[yyn]; - if (yyn <= 0) - { - if (yytable_value_is_error (yyn)) - goto yyerrlab; - yyn = -yyn; - goto yyreduce; - } - - /* Count tokens shifted since error; after three, turn off error - status. */ - if (yyerrstatus) - yyerrstatus--; - - /* Shift the lookahead token. */ - YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); - - /* Discard the shifted token. */ - yychar = YYEMPTY; - - yystate = yyn; - YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN - *++yyvsp = yylval; - YY_IGNORE_MAYBE_UNINITIALIZED_END - - goto yynewstate; - - -/*-----------------------------------------------------------. -| yydefault -- do the default action for the current state. | -`-----------------------------------------------------------*/ -yydefault: - yyn = yydefact[yystate]; - if (yyn == 0) - goto yyerrlab; - goto yyreduce; - - -/*-----------------------------. -| yyreduce -- Do a reduction. | -`-----------------------------*/ -yyreduce: - /* yyn is the number of a rule to reduce with. */ - yylen = yyr2[yyn]; - - /* If YYLEN is nonzero, implement the default value of the action: - '$$ = $1'. - - Otherwise, the following line sets YYVAL to garbage. - This behavior is undocumented and Bison - users should not rely upon it. Assigning to YYVAL - unconditionally makes the parser a bit smaller, and it avoids a - GCC warning that YYVAL may be used uninitialized. */ - yyval = yyvsp[1-yylen]; - - - YY_REDUCE_PRINT (yyn); - switch (yyn) - { - case 2: -#line 293 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.intermTypedNode) = parseContext.handleVariable((yyvsp[0].lex).loc, (yyvsp[0].lex).symbol, (yyvsp[0].lex).string); - } -#line 4016 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 3: -#line 299 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); - } -#line 4024 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 4: -#line 302 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitInt32Check((yyvsp[0].lex).loc, "32-bit signed literal"); - (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).i, (yyvsp[0].lex).loc, true); - } -#line 4033 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 5: -#line 306 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitInt32Check((yyvsp[0].lex).loc, "32-bit signed literal"); - (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).u, (yyvsp[0].lex).loc, true); - } -#line 4042 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 6: -#line 310 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).i, (yyvsp[0].lex).loc, true); - } -#line 4050 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 7: -#line 313 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "unsigned literal"); - (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).u, (yyvsp[0].lex).loc, true); - } -#line 4059 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 8: -#line 317 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.int64Check((yyvsp[0].lex).loc, "64-bit integer literal"); - (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).i64, (yyvsp[0].lex).loc, true); - } -#line 4068 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 9: -#line 321 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.int64Check((yyvsp[0].lex).loc, "64-bit unsigned integer literal"); - (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).u64, (yyvsp[0].lex).loc, true); - } -#line 4077 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 10: -#line 325 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitInt16Check((yyvsp[0].lex).loc, "16-bit integer literal"); - (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((short)(yyvsp[0].lex).i, (yyvsp[0].lex).loc, true); - } -#line 4086 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 11: -#line 329 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitInt16Check((yyvsp[0].lex).loc, "16-bit unsigned integer literal"); - (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((unsigned short)(yyvsp[0].lex).u, (yyvsp[0].lex).loc, true); - } -#line 4095 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 12: -#line 333 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).d, EbtFloat, (yyvsp[0].lex).loc, true); - } -#line 4103 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 13: -#line 336 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.doubleCheck((yyvsp[0].lex).loc, "double literal"); - (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).d, EbtDouble, (yyvsp[0].lex).loc, true); - } -#line 4112 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 14: -#line 340 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.float16Check((yyvsp[0].lex).loc, "half float literal"); - (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).d, EbtFloat16, (yyvsp[0].lex).loc, true); - } -#line 4121 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 15: -#line 344 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).b, (yyvsp[0].lex).loc, true); - } -#line 4129 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 16: -#line 347 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.intermTypedNode) = (yyvsp[-1].interm.intermTypedNode); - if ((yyval.interm.intermTypedNode)->getAsConstantUnion()) - (yyval.interm.intermTypedNode)->getAsConstantUnion()->setExpression(); - } -#line 4139 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 17: -#line 355 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); - } -#line 4147 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 18: -#line 358 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.intermTypedNode) = parseContext.handleBracketDereference((yyvsp[-2].lex).loc, (yyvsp[-3].interm.intermTypedNode), (yyvsp[-1].interm.intermTypedNode)); - } -#line 4155 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 19: -#line 361 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); - } -#line 4163 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 20: -#line 364 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.intermTypedNode) = parseContext.handleDotDereference((yyvsp[0].lex).loc, (yyvsp[-2].interm.intermTypedNode), *(yyvsp[0].lex).string); - } -#line 4171 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 21: -#line 367 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.variableCheck((yyvsp[-1].interm.intermTypedNode)); - parseContext.lValueErrorCheck((yyvsp[0].lex).loc, "++", (yyvsp[-1].interm.intermTypedNode)); - (yyval.interm.intermTypedNode) = parseContext.handleUnaryMath((yyvsp[0].lex).loc, "++", EOpPostIncrement, (yyvsp[-1].interm.intermTypedNode)); - } -#line 4181 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 22: -#line 372 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.variableCheck((yyvsp[-1].interm.intermTypedNode)); - parseContext.lValueErrorCheck((yyvsp[0].lex).loc, "--", (yyvsp[-1].interm.intermTypedNode)); - (yyval.interm.intermTypedNode) = parseContext.handleUnaryMath((yyvsp[0].lex).loc, "--", EOpPostDecrement, (yyvsp[-1].interm.intermTypedNode)); - } -#line 4191 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 23: -#line 380 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.integerCheck((yyvsp[0].interm.intermTypedNode), "[]"); - (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); - } -#line 4200 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 24: -#line 387 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.intermTypedNode) = parseContext.handleFunctionCall((yyvsp[0].interm).loc, (yyvsp[0].interm).function, (yyvsp[0].interm).intermNode); - delete (yyvsp[0].interm).function; - } -#line 4209 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 25: -#line 394 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm) = (yyvsp[0].interm); - } -#line 4217 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 26: -#line 400 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm) = (yyvsp[-1].interm); - (yyval.interm).loc = (yyvsp[0].lex).loc; - } -#line 4226 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 27: -#line 404 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm) = (yyvsp[-1].interm); - (yyval.interm).loc = (yyvsp[0].lex).loc; - } -#line 4235 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 28: -#line 411 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm) = (yyvsp[-1].interm); - } -#line 4243 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 29: -#line 414 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm) = (yyvsp[0].interm); - } -#line 4251 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 30: -#line 420 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - TParameter param = { 0, new TType }; - param.type->shallowCopy((yyvsp[0].interm.intermTypedNode)->getType()); - (yyvsp[-1].interm).function->addParameter(param); - (yyval.interm).function = (yyvsp[-1].interm).function; - (yyval.interm).intermNode = (yyvsp[0].interm.intermTypedNode); - } -#line 4263 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 31: -#line 427 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - TParameter param = { 0, new TType }; - param.type->shallowCopy((yyvsp[0].interm.intermTypedNode)->getType()); - (yyvsp[-2].interm).function->addParameter(param); - (yyval.interm).function = (yyvsp[-2].interm).function; - (yyval.interm).intermNode = parseContext.intermediate.growAggregate((yyvsp[-2].interm).intermNode, (yyvsp[0].interm.intermTypedNode), (yyvsp[-1].lex).loc); - } -#line 4275 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 32: -#line 437 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm) = (yyvsp[-1].interm); - } -#line 4283 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 33: -#line 445 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - // Constructor - (yyval.interm).intermNode = 0; - (yyval.interm).function = parseContext.handleConstructorCall((yyvsp[0].interm.type).loc, (yyvsp[0].interm.type)); - } -#line 4293 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 34: -#line 450 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - // - // Should be a method or subroutine call, but we haven't recognized the arguments yet. - // - (yyval.interm).function = 0; - (yyval.interm).intermNode = 0; - - TIntermMethod* method = (yyvsp[0].interm.intermTypedNode)->getAsMethodNode(); - if (method) { - (yyval.interm).function = new TFunction(&method->getMethodName(), TType(EbtInt), EOpArrayLength); - (yyval.interm).intermNode = method->getObject(); - } else { - TIntermSymbol* symbol = (yyvsp[0].interm.intermTypedNode)->getAsSymbolNode(); - if (symbol) { - parseContext.reservedErrorCheck(symbol->getLoc(), symbol->getName()); - TFunction *function = new TFunction(&symbol->getName(), TType(EbtVoid)); - (yyval.interm).function = function; - } else - parseContext.error((yyvsp[0].interm.intermTypedNode)->getLoc(), "function call, method, or subroutine call expected", "", ""); - } - - if ((yyval.interm).function == 0) { - // error recover - TString empty(""); - (yyval.interm).function = new TFunction(&empty, TType(EbtVoid), EOpNull); - } - } -#line 4325 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 35: -#line 477 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - // Constructor - (yyval.interm).intermNode = 0; - (yyval.interm).function = parseContext.handleConstructorCall((yyvsp[0].interm.type).loc, (yyvsp[0].interm.type)); - } -#line 4335 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 36: -#line 485 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.variableCheck((yyvsp[0].interm.intermTypedNode)); - (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); - if (TIntermMethod* method = (yyvsp[0].interm.intermTypedNode)->getAsMethodNode()) - parseContext.error((yyvsp[0].interm.intermTypedNode)->getLoc(), "incomplete method syntax", method->getMethodName().c_str(), ""); - } -#line 4346 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 37: -#line 491 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.lValueErrorCheck((yyvsp[-1].lex).loc, "++", (yyvsp[0].interm.intermTypedNode)); - (yyval.interm.intermTypedNode) = parseContext.handleUnaryMath((yyvsp[-1].lex).loc, "++", EOpPreIncrement, (yyvsp[0].interm.intermTypedNode)); - } -#line 4355 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 38: -#line 495 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.lValueErrorCheck((yyvsp[-1].lex).loc, "--", (yyvsp[0].interm.intermTypedNode)); - (yyval.interm.intermTypedNode) = parseContext.handleUnaryMath((yyvsp[-1].lex).loc, "--", EOpPreDecrement, (yyvsp[0].interm.intermTypedNode)); - } -#line 4364 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 39: -#line 499 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - if ((yyvsp[-1].interm).op != EOpNull) { - char errorOp[2] = {0, 0}; - switch((yyvsp[-1].interm).op) { - case EOpNegative: errorOp[0] = '-'; break; - case EOpLogicalNot: errorOp[0] = '!'; break; - case EOpBitwiseNot: errorOp[0] = '~'; break; - default: break; // some compilers want this - } - (yyval.interm.intermTypedNode) = parseContext.handleUnaryMath((yyvsp[-1].interm).loc, errorOp, (yyvsp[-1].interm).op, (yyvsp[0].interm.intermTypedNode)); - } else { - (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); - if ((yyval.interm.intermTypedNode)->getAsConstantUnion()) - (yyval.interm.intermTypedNode)->getAsConstantUnion()->setExpression(); - } - } -#line 4385 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 40: -#line 519 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).op = EOpNull; } -#line 4391 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 41: -#line 520 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).op = EOpNegative; } -#line 4397 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 42: -#line 521 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).op = EOpLogicalNot; } -#line 4403 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 43: -#line 522 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).op = EOpBitwiseNot; - parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "bitwise not"); } -#line 4410 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 44: -#line 528 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } -#line 4416 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 45: -#line 529 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "*", EOpMul, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); - if ((yyval.interm.intermTypedNode) == 0) - (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode); - } -#line 4426 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 46: -#line 534 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "/", EOpDiv, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); - if ((yyval.interm.intermTypedNode) == 0) - (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode); - } -#line 4436 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 47: -#line 539 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.fullIntegerCheck((yyvsp[-1].lex).loc, "%"); - (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "%", EOpMod, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); - if ((yyval.interm.intermTypedNode) == 0) - (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode); - } -#line 4447 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 48: -#line 548 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } -#line 4453 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 49: -#line 549 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "+", EOpAdd, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); - if ((yyval.interm.intermTypedNode) == 0) - (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode); - } -#line 4463 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 50: -#line 554 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "-", EOpSub, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); - if ((yyval.interm.intermTypedNode) == 0) - (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode); - } -#line 4473 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 51: -#line 562 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } -#line 4479 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 52: -#line 563 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.fullIntegerCheck((yyvsp[-1].lex).loc, "bit shift left"); - (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "<<", EOpLeftShift, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); - if ((yyval.interm.intermTypedNode) == 0) - (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode); - } -#line 4490 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 53: -#line 569 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.fullIntegerCheck((yyvsp[-1].lex).loc, "bit shift right"); - (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, ">>", EOpRightShift, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); - if ((yyval.interm.intermTypedNode) == 0) - (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode); - } -#line 4501 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 54: -#line 578 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } -#line 4507 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 55: -#line 579 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "<", EOpLessThan, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); - if ((yyval.interm.intermTypedNode) == 0) - (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion(false, (yyvsp[-1].lex).loc); - } -#line 4517 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 56: -#line 584 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, ">", EOpGreaterThan, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); - if ((yyval.interm.intermTypedNode) == 0) - (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion(false, (yyvsp[-1].lex).loc); - } -#line 4527 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 57: -#line 589 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "<=", EOpLessThanEqual, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); - if ((yyval.interm.intermTypedNode) == 0) - (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion(false, (yyvsp[-1].lex).loc); - } -#line 4537 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 58: -#line 594 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, ">=", EOpGreaterThanEqual, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); - if ((yyval.interm.intermTypedNode) == 0) - (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion(false, (yyvsp[-1].lex).loc); - } -#line 4547 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 59: -#line 602 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } -#line 4553 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 60: -#line 603 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.arrayObjectCheck((yyvsp[-1].lex).loc, (yyvsp[-2].interm.intermTypedNode)->getType(), "array comparison"); - parseContext.opaqueCheck((yyvsp[-1].lex).loc, (yyvsp[-2].interm.intermTypedNode)->getType(), "=="); - parseContext.specializationCheck((yyvsp[-1].lex).loc, (yyvsp[-2].interm.intermTypedNode)->getType(), "=="); - (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "==", EOpEqual, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); - if ((yyval.interm.intermTypedNode) == 0) - (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion(false, (yyvsp[-1].lex).loc); - } -#line 4566 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 61: -#line 611 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.arrayObjectCheck((yyvsp[-1].lex).loc, (yyvsp[-2].interm.intermTypedNode)->getType(), "array comparison"); - parseContext.opaqueCheck((yyvsp[-1].lex).loc, (yyvsp[-2].interm.intermTypedNode)->getType(), "!="); - parseContext.specializationCheck((yyvsp[-1].lex).loc, (yyvsp[-2].interm.intermTypedNode)->getType(), "!="); - (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "!=", EOpNotEqual, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); - if ((yyval.interm.intermTypedNode) == 0) - (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion(false, (yyvsp[-1].lex).loc); - } -#line 4579 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 62: -#line 622 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } -#line 4585 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 63: -#line 623 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.fullIntegerCheck((yyvsp[-1].lex).loc, "bitwise and"); - (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "&", EOpAnd, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); - if ((yyval.interm.intermTypedNode) == 0) - (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode); - } -#line 4596 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 64: -#line 632 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } -#line 4602 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 65: -#line 633 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.fullIntegerCheck((yyvsp[-1].lex).loc, "bitwise exclusive or"); - (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "^", EOpExclusiveOr, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); - if ((yyval.interm.intermTypedNode) == 0) - (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode); - } -#line 4613 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 66: -#line 642 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } -#line 4619 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 67: -#line 643 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.fullIntegerCheck((yyvsp[-1].lex).loc, "bitwise inclusive or"); - (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "|", EOpInclusiveOr, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); - if ((yyval.interm.intermTypedNode) == 0) - (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode); - } -#line 4630 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 68: -#line 652 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } -#line 4636 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 69: -#line 653 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "&&", EOpLogicalAnd, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); - if ((yyval.interm.intermTypedNode) == 0) - (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion(false, (yyvsp[-1].lex).loc); - } -#line 4646 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 70: -#line 661 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } -#line 4652 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 71: -#line 662 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "^^", EOpLogicalXor, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); - if ((yyval.interm.intermTypedNode) == 0) - (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion(false, (yyvsp[-1].lex).loc); - } -#line 4662 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 72: -#line 670 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } -#line 4668 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 73: -#line 671 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "||", EOpLogicalOr, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); - if ((yyval.interm.intermTypedNode) == 0) - (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion(false, (yyvsp[-1].lex).loc); - } -#line 4678 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 74: -#line 679 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } -#line 4684 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 75: -#line 680 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - ++parseContext.controlFlowNestingLevel; - } -#line 4692 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 76: -#line 683 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - --parseContext.controlFlowNestingLevel; - parseContext.boolCheck((yyvsp[-4].lex).loc, (yyvsp[-5].interm.intermTypedNode)); - parseContext.rValueErrorCheck((yyvsp[-4].lex).loc, "?", (yyvsp[-5].interm.intermTypedNode)); - parseContext.rValueErrorCheck((yyvsp[-1].lex).loc, ":", (yyvsp[-2].interm.intermTypedNode)); - parseContext.rValueErrorCheck((yyvsp[-1].lex).loc, ":", (yyvsp[0].interm.intermTypedNode)); - (yyval.interm.intermTypedNode) = parseContext.intermediate.addSelection((yyvsp[-5].interm.intermTypedNode), (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode), (yyvsp[-4].lex).loc); - if ((yyval.interm.intermTypedNode) == 0) { - parseContext.binaryOpError((yyvsp[-4].lex).loc, ":", (yyvsp[-2].interm.intermTypedNode)->getCompleteString(), (yyvsp[0].interm.intermTypedNode)->getCompleteString()); - (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); - } - } -#line 4709 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 77: -#line 698 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } -#line 4715 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 78: -#line 699 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.arrayObjectCheck((yyvsp[-1].interm).loc, (yyvsp[-2].interm.intermTypedNode)->getType(), "array assignment"); - parseContext.opaqueCheck((yyvsp[-1].interm).loc, (yyvsp[-2].interm.intermTypedNode)->getType(), "="); - parseContext.specializationCheck((yyvsp[-1].interm).loc, (yyvsp[-2].interm.intermTypedNode)->getType(), "="); - parseContext.lValueErrorCheck((yyvsp[-1].interm).loc, "assign", (yyvsp[-2].interm.intermTypedNode)); - parseContext.rValueErrorCheck((yyvsp[-1].interm).loc, "assign", (yyvsp[0].interm.intermTypedNode)); - (yyval.interm.intermTypedNode) = parseContext.intermediate.addAssign((yyvsp[-1].interm).op, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode), (yyvsp[-1].interm).loc); - if ((yyval.interm.intermTypedNode) == 0) { - parseContext.assignError((yyvsp[-1].interm).loc, "assign", (yyvsp[-2].interm.intermTypedNode)->getCompleteString(), (yyvsp[0].interm.intermTypedNode)->getCompleteString()); - (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode); - } - } -#line 4732 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 79: -#line 714 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm).loc = (yyvsp[0].lex).loc; - (yyval.interm).op = EOpAssign; - } -#line 4741 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 80: -#line 718 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm).loc = (yyvsp[0].lex).loc; - (yyval.interm).op = EOpMulAssign; - } -#line 4750 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 81: -#line 722 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm).loc = (yyvsp[0].lex).loc; - (yyval.interm).op = EOpDivAssign; - } -#line 4759 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 82: -#line 726 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "%="); - (yyval.interm).loc = (yyvsp[0].lex).loc; - (yyval.interm).op = EOpModAssign; - } -#line 4769 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 83: -#line 731 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm).loc = (yyvsp[0].lex).loc; - (yyval.interm).op = EOpAddAssign; - } -#line 4778 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 84: -#line 735 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm).loc = (yyvsp[0].lex).loc; - (yyval.interm).op = EOpSubAssign; - } -#line 4787 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 85: -#line 739 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "bit-shift left assign"); - (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).op = EOpLeftShiftAssign; - } -#line 4796 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 86: -#line 743 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "bit-shift right assign"); - (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).op = EOpRightShiftAssign; - } -#line 4805 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 87: -#line 747 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "bitwise-and assign"); - (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).op = EOpAndAssign; - } -#line 4814 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 88: -#line 751 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "bitwise-xor assign"); - (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).op = EOpExclusiveOrAssign; - } -#line 4823 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 89: -#line 755 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "bitwise-or assign"); - (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).op = EOpInclusiveOrAssign; - } -#line 4832 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 90: -#line 762 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); - } -#line 4840 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 91: -#line 765 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.samplerConstructorLocationCheck((yyvsp[-1].lex).loc, ",", (yyvsp[0].interm.intermTypedNode)); - (yyval.interm.intermTypedNode) = parseContext.intermediate.addComma((yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode), (yyvsp[-1].lex).loc); - if ((yyval.interm.intermTypedNode) == 0) { - parseContext.binaryOpError((yyvsp[-1].lex).loc, ",", (yyvsp[-2].interm.intermTypedNode)->getCompleteString(), (yyvsp[0].interm.intermTypedNode)->getCompleteString()); - (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); - } - } -#line 4853 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 92: -#line 776 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.constantValueCheck((yyvsp[0].interm.intermTypedNode), ""); - (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); - } -#line 4862 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 93: -#line 783 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.handleFunctionDeclarator((yyvsp[-1].interm).loc, *(yyvsp[-1].interm).function, true /* prototype */); - (yyval.interm.intermNode) = 0; - // TODO: 4.0 functionality: subroutines: make the identifier a user type for this signature - } -#line 4872 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 94: -#line 788 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - if ((yyvsp[-1].interm).intermNode && (yyvsp[-1].interm).intermNode->getAsAggregate()) - (yyvsp[-1].interm).intermNode->getAsAggregate()->setOperator(EOpSequence); - (yyval.interm.intermNode) = (yyvsp[-1].interm).intermNode; - } -#line 4882 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 95: -#line 793 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.profileRequires((yyvsp[-3].lex).loc, ENoProfile, 130, 0, "precision statement"); - - // lazy setting of the previous scope's defaults, has effect only the first time it is called in a particular scope - parseContext.symbolTable.setPreviousDefaultPrecisions(&parseContext.defaultPrecision[0]); - parseContext.setDefaultPrecision((yyvsp[-3].lex).loc, (yyvsp[-1].interm.type), (yyvsp[-2].interm.type).qualifier.precision); - (yyval.interm.intermNode) = 0; - } -#line 4895 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 96: -#line 801 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.declareBlock((yyvsp[-1].interm).loc, *(yyvsp[-1].interm).typeList); - (yyval.interm.intermNode) = 0; - } -#line 4904 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 97: -#line 805 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.declareBlock((yyvsp[-2].interm).loc, *(yyvsp[-2].interm).typeList, (yyvsp[-1].lex).string); - (yyval.interm.intermNode) = 0; - } -#line 4913 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 98: -#line 809 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.declareBlock((yyvsp[-3].interm).loc, *(yyvsp[-3].interm).typeList, (yyvsp[-2].lex).string, (yyvsp[-1].interm).arraySizes); - (yyval.interm.intermNode) = 0; - } -#line 4922 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 99: -#line 813 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.globalQualifierFixCheck((yyvsp[-1].interm.type).loc, (yyvsp[-1].interm.type).qualifier); - parseContext.updateStandaloneQualifierDefaults((yyvsp[-1].interm.type).loc, (yyvsp[-1].interm.type)); - (yyval.interm.intermNode) = 0; - } -#line 4932 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 100: -#line 818 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.checkNoShaderLayouts((yyvsp[-2].interm.type).loc, (yyvsp[-2].interm.type).shaderQualifiers); - parseContext.addQualifierToExisting((yyvsp[-2].interm.type).loc, (yyvsp[-2].interm.type).qualifier, *(yyvsp[-1].lex).string); - (yyval.interm.intermNode) = 0; - } -#line 4942 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 101: -#line 823 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.checkNoShaderLayouts((yyvsp[-3].interm.type).loc, (yyvsp[-3].interm.type).shaderQualifiers); - (yyvsp[-1].interm.identifierList)->push_back((yyvsp[-2].lex).string); - parseContext.addQualifierToExisting((yyvsp[-3].interm.type).loc, (yyvsp[-3].interm.type).qualifier, *(yyvsp[-1].interm.identifierList)); - (yyval.interm.intermNode) = 0; - } -#line 4953 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 102: -#line 832 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { parseContext.nestedBlockCheck((yyvsp[-2].interm.type).loc); } -#line 4959 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 103: -#line 832 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - --parseContext.structNestingLevel; - parseContext.blockName = (yyvsp[-4].lex).string; - parseContext.globalQualifierFixCheck((yyvsp[-5].interm.type).loc, (yyvsp[-5].interm.type).qualifier); - parseContext.checkNoShaderLayouts((yyvsp[-5].interm.type).loc, (yyvsp[-5].interm.type).shaderQualifiers); - parseContext.currentBlockQualifier = (yyvsp[-5].interm.type).qualifier; - (yyval.interm).loc = (yyvsp[-5].interm.type).loc; - (yyval.interm).typeList = (yyvsp[-1].interm.typeList); - } -#line 4973 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 104: -#line 843 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.identifierList) = new TIdentifierList; - (yyval.interm.identifierList)->push_back((yyvsp[0].lex).string); - } -#line 4982 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 105: -#line 847 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.identifierList) = (yyvsp[-2].interm.identifierList); - (yyval.interm.identifierList)->push_back((yyvsp[0].lex).string); - } -#line 4991 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 106: -#line 854 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm).function = (yyvsp[-1].interm.function); - (yyval.interm).loc = (yyvsp[0].lex).loc; - } -#line 5000 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 107: -#line 861 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.function) = (yyvsp[0].interm.function); - } -#line 5008 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 108: -#line 864 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.function) = (yyvsp[0].interm.function); - } -#line 5016 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 109: -#line 871 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - // Add the parameter - (yyval.interm.function) = (yyvsp[-1].interm.function); - if ((yyvsp[0].interm).param.type->getBasicType() != EbtVoid) - (yyvsp[-1].interm.function)->addParameter((yyvsp[0].interm).param); - else - delete (yyvsp[0].interm).param.type; - } -#line 5029 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 110: -#line 879 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - // - // Only first parameter of one-parameter functions can be void - // The check for named parameters not being void is done in parameter_declarator - // - if ((yyvsp[0].interm).param.type->getBasicType() == EbtVoid) { - // - // This parameter > first is void - // - parseContext.error((yyvsp[-1].lex).loc, "cannot be an argument type except for '(void)'", "void", ""); - delete (yyvsp[0].interm).param.type; - } else { - // Add the parameter - (yyval.interm.function) = (yyvsp[-2].interm.function); - (yyvsp[-2].interm.function)->addParameter((yyvsp[0].interm).param); - } - } -#line 5051 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 111: -#line 899 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - if ((yyvsp[-2].interm.type).qualifier.storage != EvqGlobal && (yyvsp[-2].interm.type).qualifier.storage != EvqTemporary) { - parseContext.error((yyvsp[-1].lex).loc, "no qualifiers allowed for function return", - GetStorageQualifierString((yyvsp[-2].interm.type).qualifier.storage), ""); - } - if ((yyvsp[-2].interm.type).arraySizes) - parseContext.arraySizeRequiredCheck((yyvsp[-2].interm.type).loc, *(yyvsp[-2].interm.type).arraySizes); - - // Add the function as a prototype after parsing it (we do not support recursion) - TFunction *function; - TType type((yyvsp[-2].interm.type)); - - // Potentially rename shader entry point function. No-op most of the time. - parseContext.renameShaderFunction((yyvsp[-1].lex).string); - - // Make the function - function = new TFunction((yyvsp[-1].lex).string, type); - (yyval.interm.function) = function; - } -#line 5075 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 112: -#line 922 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - if ((yyvsp[-1].interm.type).arraySizes) { - parseContext.profileRequires((yyvsp[-1].interm.type).loc, ENoProfile, 120, E_GL_3DL_array_objects, "arrayed type"); - parseContext.profileRequires((yyvsp[-1].interm.type).loc, EEsProfile, 300, 0, "arrayed type"); - parseContext.arraySizeRequiredCheck((yyvsp[-1].interm.type).loc, *(yyvsp[-1].interm.type).arraySizes); - } - if ((yyvsp[-1].interm.type).basicType == EbtVoid) { - parseContext.error((yyvsp[0].lex).loc, "illegal use of type 'void'", (yyvsp[0].lex).string->c_str(), ""); - } - parseContext.reservedErrorCheck((yyvsp[0].lex).loc, *(yyvsp[0].lex).string); - - TParameter param = {(yyvsp[0].lex).string, new TType((yyvsp[-1].interm.type))}; - (yyval.interm).loc = (yyvsp[0].lex).loc; - (yyval.interm).param = param; - } -#line 5095 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 113: -#line 937 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - if ((yyvsp[-2].interm.type).arraySizes) { - parseContext.profileRequires((yyvsp[-2].interm.type).loc, ENoProfile, 120, E_GL_3DL_array_objects, "arrayed type"); - parseContext.profileRequires((yyvsp[-2].interm.type).loc, EEsProfile, 300, 0, "arrayed type"); - parseContext.arraySizeRequiredCheck((yyvsp[-2].interm.type).loc, *(yyvsp[-2].interm.type).arraySizes); - } - TType* type = new TType((yyvsp[-2].interm.type)); - type->transferArraySizes((yyvsp[0].interm).arraySizes); - type->copyArrayInnerSizes((yyvsp[-2].interm.type).arraySizes); - - parseContext.arrayOfArrayVersionCheck((yyvsp[-1].lex).loc, type->getArraySizes()); - parseContext.arraySizeRequiredCheck((yyvsp[0].interm).loc, *(yyvsp[0].interm).arraySizes); - parseContext.reservedErrorCheck((yyvsp[-1].lex).loc, *(yyvsp[-1].lex).string); - - TParameter param = { (yyvsp[-1].lex).string, type }; - - (yyval.interm).loc = (yyvsp[-1].lex).loc; - (yyval.interm).param = param; - } -#line 5119 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 114: -#line 962 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm) = (yyvsp[0].interm); - if ((yyvsp[-1].interm.type).qualifier.precision != EpqNone) - (yyval.interm).param.type->getQualifier().precision = (yyvsp[-1].interm.type).qualifier.precision; - parseContext.precisionQualifierCheck((yyval.interm).loc, (yyval.interm).param.type->getBasicType(), (yyval.interm).param.type->getQualifier()); - - parseContext.checkNoShaderLayouts((yyvsp[-1].interm.type).loc, (yyvsp[-1].interm.type).shaderQualifiers); - parseContext.parameterTypeCheck((yyvsp[0].interm).loc, (yyvsp[-1].interm.type).qualifier.storage, *(yyval.interm).param.type); - parseContext.paramCheckFix((yyvsp[-1].interm.type).loc, (yyvsp[-1].interm.type).qualifier, *(yyval.interm).param.type); - - } -#line 5135 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 115: -#line 973 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm) = (yyvsp[0].interm); - - parseContext.parameterTypeCheck((yyvsp[0].interm).loc, EvqIn, *(yyvsp[0].interm).param.type); - parseContext.paramCheckFixStorage((yyvsp[0].interm).loc, EvqTemporary, *(yyval.interm).param.type); - parseContext.precisionQualifierCheck((yyval.interm).loc, (yyval.interm).param.type->getBasicType(), (yyval.interm).param.type->getQualifier()); - } -#line 5147 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 116: -#line 983 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm) = (yyvsp[0].interm); - if ((yyvsp[-1].interm.type).qualifier.precision != EpqNone) - (yyval.interm).param.type->getQualifier().precision = (yyvsp[-1].interm.type).qualifier.precision; - parseContext.precisionQualifierCheck((yyvsp[-1].interm.type).loc, (yyval.interm).param.type->getBasicType(), (yyval.interm).param.type->getQualifier()); - - parseContext.checkNoShaderLayouts((yyvsp[-1].interm.type).loc, (yyvsp[-1].interm.type).shaderQualifiers); - parseContext.parameterTypeCheck((yyvsp[0].interm).loc, (yyvsp[-1].interm.type).qualifier.storage, *(yyval.interm).param.type); - parseContext.paramCheckFix((yyvsp[-1].interm.type).loc, (yyvsp[-1].interm.type).qualifier, *(yyval.interm).param.type); - } -#line 5162 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 117: -#line 993 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm) = (yyvsp[0].interm); - - parseContext.parameterTypeCheck((yyvsp[0].interm).loc, EvqIn, *(yyvsp[0].interm).param.type); - parseContext.paramCheckFixStorage((yyvsp[0].interm).loc, EvqTemporary, *(yyval.interm).param.type); - parseContext.precisionQualifierCheck((yyval.interm).loc, (yyval.interm).param.type->getBasicType(), (yyval.interm).param.type->getQualifier()); - } -#line 5174 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 118: -#line 1003 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - TParameter param = { 0, new TType((yyvsp[0].interm.type)) }; - (yyval.interm).param = param; - if ((yyvsp[0].interm.type).arraySizes) - parseContext.arraySizeRequiredCheck((yyvsp[0].interm.type).loc, *(yyvsp[0].interm.type).arraySizes); - } -#line 5185 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 119: -#line 1012 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm) = (yyvsp[0].interm); - } -#line 5193 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 120: -#line 1015 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm) = (yyvsp[-2].interm); - parseContext.declareVariable((yyvsp[0].lex).loc, *(yyvsp[0].lex).string, (yyvsp[-2].interm).type); - } -#line 5202 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 121: -#line 1019 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm) = (yyvsp[-3].interm); - parseContext.declareVariable((yyvsp[-1].lex).loc, *(yyvsp[-1].lex).string, (yyvsp[-3].interm).type, (yyvsp[0].interm).arraySizes); - } -#line 5211 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 122: -#line 1023 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm).type = (yyvsp[-5].interm).type; - TIntermNode* initNode = parseContext.declareVariable((yyvsp[-3].lex).loc, *(yyvsp[-3].lex).string, (yyvsp[-5].interm).type, (yyvsp[-2].interm).arraySizes, (yyvsp[0].interm.intermTypedNode)); - (yyval.interm).intermNode = parseContext.intermediate.growAggregate((yyvsp[-5].interm).intermNode, initNode, (yyvsp[-1].lex).loc); - } -#line 5221 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 123: -#line 1028 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm).type = (yyvsp[-4].interm).type; - TIntermNode* initNode = parseContext.declareVariable((yyvsp[-2].lex).loc, *(yyvsp[-2].lex).string, (yyvsp[-4].interm).type, 0, (yyvsp[0].interm.intermTypedNode)); - (yyval.interm).intermNode = parseContext.intermediate.growAggregate((yyvsp[-4].interm).intermNode, initNode, (yyvsp[-1].lex).loc); - } -#line 5231 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 124: -#line 1036 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm).type = (yyvsp[0].interm.type); - (yyval.interm).intermNode = 0; - parseContext.declareTypeDefaults((yyval.interm).loc, (yyval.interm).type); - } -#line 5241 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 125: -#line 1041 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm).type = (yyvsp[-1].interm.type); - (yyval.interm).intermNode = 0; - parseContext.declareVariable((yyvsp[0].lex).loc, *(yyvsp[0].lex).string, (yyvsp[-1].interm.type)); - } -#line 5251 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 126: -#line 1046 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm).type = (yyvsp[-2].interm.type); - (yyval.interm).intermNode = 0; - parseContext.declareVariable((yyvsp[-1].lex).loc, *(yyvsp[-1].lex).string, (yyvsp[-2].interm.type), (yyvsp[0].interm).arraySizes); - } -#line 5261 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 127: -#line 1051 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm).type = (yyvsp[-4].interm.type); - TIntermNode* initNode = parseContext.declareVariable((yyvsp[-3].lex).loc, *(yyvsp[-3].lex).string, (yyvsp[-4].interm.type), (yyvsp[-2].interm).arraySizes, (yyvsp[0].interm.intermTypedNode)); - (yyval.interm).intermNode = parseContext.intermediate.growAggregate(0, initNode, (yyvsp[-1].lex).loc); - } -#line 5271 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 128: -#line 1056 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm).type = (yyvsp[-3].interm.type); - TIntermNode* initNode = parseContext.declareVariable((yyvsp[-2].lex).loc, *(yyvsp[-2].lex).string, (yyvsp[-3].interm.type), 0, (yyvsp[0].interm.intermTypedNode)); - (yyval.interm).intermNode = parseContext.intermediate.growAggregate(0, initNode, (yyvsp[-1].lex).loc); - } -#line 5281 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 129: -#line 1065 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type) = (yyvsp[0].interm.type); - - parseContext.globalQualifierTypeCheck((yyvsp[0].interm.type).loc, (yyvsp[0].interm.type).qualifier, (yyval.interm.type)); - if ((yyvsp[0].interm.type).arraySizes) { - parseContext.profileRequires((yyvsp[0].interm.type).loc, ENoProfile, 120, E_GL_3DL_array_objects, "arrayed type"); - parseContext.profileRequires((yyvsp[0].interm.type).loc, EEsProfile, 300, 0, "arrayed type"); - } - - parseContext.precisionQualifierCheck((yyval.interm.type).loc, (yyval.interm.type).basicType, (yyval.interm.type).qualifier); - } -#line 5297 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 130: -#line 1076 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.globalQualifierFixCheck((yyvsp[-1].interm.type).loc, (yyvsp[-1].interm.type).qualifier); - parseContext.globalQualifierTypeCheck((yyvsp[-1].interm.type).loc, (yyvsp[-1].interm.type).qualifier, (yyvsp[0].interm.type)); - - if ((yyvsp[0].interm.type).arraySizes) { - parseContext.profileRequires((yyvsp[0].interm.type).loc, ENoProfile, 120, E_GL_3DL_array_objects, "arrayed type"); - parseContext.profileRequires((yyvsp[0].interm.type).loc, EEsProfile, 300, 0, "arrayed type"); - } - - if ((yyvsp[0].interm.type).arraySizes && parseContext.arrayQualifierError((yyvsp[0].interm.type).loc, (yyvsp[-1].interm.type).qualifier)) - (yyvsp[0].interm.type).arraySizes = nullptr; - - parseContext.checkNoShaderLayouts((yyvsp[0].interm.type).loc, (yyvsp[-1].interm.type).shaderQualifiers); - (yyvsp[0].interm.type).shaderQualifiers.merge((yyvsp[-1].interm.type).shaderQualifiers); - parseContext.mergeQualifiers((yyvsp[0].interm.type).loc, (yyvsp[0].interm.type).qualifier, (yyvsp[-1].interm.type).qualifier, true); - parseContext.precisionQualifierCheck((yyvsp[0].interm.type).loc, (yyvsp[0].interm.type).basicType, (yyvsp[0].interm.type).qualifier); - - (yyval.interm.type) = (yyvsp[0].interm.type); - - if (! (yyval.interm.type).qualifier.isInterpolation() && - ((parseContext.language == EShLangVertex && (yyval.interm.type).qualifier.storage == EvqVaryingOut) || - (parseContext.language == EShLangFragment && (yyval.interm.type).qualifier.storage == EvqVaryingIn))) - (yyval.interm.type).qualifier.smooth = true; - } -#line 5326 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 131: -#line 1103 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.globalCheck((yyvsp[0].lex).loc, "invariant"); - parseContext.profileRequires((yyval.interm.type).loc, ENoProfile, 120, 0, "invariant"); - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.invariant = true; - } -#line 5337 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 132: -#line 1112 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.globalCheck((yyvsp[0].lex).loc, "smooth"); - parseContext.profileRequires((yyvsp[0].lex).loc, ENoProfile, 130, 0, "smooth"); - parseContext.profileRequires((yyvsp[0].lex).loc, EEsProfile, 300, 0, "smooth"); - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.smooth = true; - } -#line 5349 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 133: -#line 1119 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.globalCheck((yyvsp[0].lex).loc, "flat"); - parseContext.profileRequires((yyvsp[0].lex).loc, ENoProfile, 130, 0, "flat"); - parseContext.profileRequires((yyvsp[0].lex).loc, EEsProfile, 300, 0, "flat"); - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.flat = true; - } -#line 5361 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 134: -#line 1126 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.globalCheck((yyvsp[0].lex).loc, "noperspective"); -#ifdef NV_EXTENSIONS - parseContext.profileRequires((yyvsp[0].lex).loc, EEsProfile, 0, E_GL_NV_shader_noperspective_interpolation, "noperspective"); -#else - parseContext.requireProfile((yyvsp[0].lex).loc, ~EEsProfile, "noperspective"); -#endif - parseContext.profileRequires((yyvsp[0].lex).loc, ENoProfile, 130, 0, "noperspective"); - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.nopersp = true; - } -#line 5377 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 135: -#line 1137 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { -#ifdef AMD_EXTENSIONS - parseContext.globalCheck((yyvsp[0].lex).loc, "__explicitInterpAMD"); - parseContext.profileRequires((yyvsp[0].lex).loc, ECoreProfile, 450, E_GL_AMD_shader_explicit_vertex_parameter, "explicit interpolation"); - parseContext.profileRequires((yyvsp[0].lex).loc, ECompatibilityProfile, 450, E_GL_AMD_shader_explicit_vertex_parameter, "explicit interpolation"); - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.explicitInterp = true; -#endif - } -#line 5391 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 136: -#line 1149 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type) = (yyvsp[-1].interm.type); - } -#line 5399 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 137: -#line 1155 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type) = (yyvsp[0].interm.type); - } -#line 5407 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 138: -#line 1158 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type) = (yyvsp[-2].interm.type); - (yyval.interm.type).shaderQualifiers.merge((yyvsp[0].interm.type).shaderQualifiers); - parseContext.mergeObjectLayoutQualifiers((yyval.interm.type).qualifier, (yyvsp[0].interm.type).qualifier, false); - } -#line 5417 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 139: -#line 1165 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc); - parseContext.setLayoutQualifier((yyvsp[0].lex).loc, (yyval.interm.type), *(yyvsp[0].lex).string); - } -#line 5426 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 140: -#line 1169 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[-2].lex).loc); - parseContext.setLayoutQualifier((yyvsp[-2].lex).loc, (yyval.interm.type), *(yyvsp[-2].lex).string, (yyvsp[0].interm.intermTypedNode)); - } -#line 5435 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 141: -#line 1173 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { // because "shared" is both an identifier and a keyword - (yyval.interm.type).init((yyvsp[0].lex).loc); - TString strShared("shared"); - parseContext.setLayoutQualifier((yyvsp[0].lex).loc, (yyval.interm.type), strShared); - } -#line 5445 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 142: -#line 1181 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.profileRequires((yyval.interm.type).loc, ECoreProfile | ECompatibilityProfile, 400, E_GL_ARB_gpu_shader5, "precise"); - parseContext.profileRequires((yyvsp[0].lex).loc, EEsProfile, 320, Num_AEP_gpu_shader5, AEP_gpu_shader5, "precise"); - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.noContraction = true; - } -#line 5456 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 143: -#line 1190 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type) = (yyvsp[0].interm.type); - } -#line 5464 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 144: -#line 1193 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type) = (yyvsp[-1].interm.type); - if ((yyval.interm.type).basicType == EbtVoid) - (yyval.interm.type).basicType = (yyvsp[0].interm.type).basicType; - - (yyval.interm.type).shaderQualifiers.merge((yyvsp[0].interm.type).shaderQualifiers); - parseContext.mergeQualifiers((yyval.interm.type).loc, (yyval.interm.type).qualifier, (yyvsp[0].interm.type).qualifier, false); - } -#line 5477 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 145: -#line 1204 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type) = (yyvsp[0].interm.type); - } -#line 5485 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 146: -#line 1207 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type) = (yyvsp[0].interm.type); - } -#line 5493 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 147: -#line 1210 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.checkPrecisionQualifier((yyvsp[0].interm.type).loc, (yyvsp[0].interm.type).qualifier.precision); - (yyval.interm.type) = (yyvsp[0].interm.type); - } -#line 5502 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 148: -#line 1214 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - // allow inheritance of storage qualifier from block declaration - (yyval.interm.type) = (yyvsp[0].interm.type); - } -#line 5511 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 149: -#line 1218 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - // allow inheritance of storage qualifier from block declaration - (yyval.interm.type) = (yyvsp[0].interm.type); - } -#line 5520 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 150: -#line 1222 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - // allow inheritance of storage qualifier from block declaration - (yyval.interm.type) = (yyvsp[0].interm.type); - } -#line 5529 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 151: -#line 1226 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type) = (yyvsp[0].interm.type); - } -#line 5537 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 152: -#line 1232 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.storage = EvqConst; // will later turn into EvqConstReadOnly, if the initializer is not constant - } -#line 5546 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 153: -#line 1236 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.requireStage((yyvsp[0].lex).loc, EShLangVertex, "attribute"); - parseContext.checkDeprecated((yyvsp[0].lex).loc, ECoreProfile, 130, "attribute"); - parseContext.checkDeprecated((yyvsp[0].lex).loc, ENoProfile, 130, "attribute"); - parseContext.requireNotRemoved((yyvsp[0].lex).loc, ECoreProfile, 420, "attribute"); - parseContext.requireNotRemoved((yyvsp[0].lex).loc, EEsProfile, 300, "attribute"); - - parseContext.globalCheck((yyvsp[0].lex).loc, "attribute"); - - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.storage = EvqVaryingIn; - } -#line 5563 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 154: -#line 1248 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.checkDeprecated((yyvsp[0].lex).loc, ENoProfile, 130, "varying"); - parseContext.checkDeprecated((yyvsp[0].lex).loc, ECoreProfile, 130, "varying"); - parseContext.requireNotRemoved((yyvsp[0].lex).loc, ECoreProfile, 420, "varying"); - parseContext.requireNotRemoved((yyvsp[0].lex).loc, EEsProfile, 300, "varying"); - - parseContext.globalCheck((yyvsp[0].lex).loc, "varying"); - - (yyval.interm.type).init((yyvsp[0].lex).loc); - if (parseContext.language == EShLangVertex) - (yyval.interm.type).qualifier.storage = EvqVaryingOut; - else - (yyval.interm.type).qualifier.storage = EvqVaryingIn; - } -#line 5582 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 155: -#line 1262 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.globalCheck((yyvsp[0].lex).loc, "inout"); - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.storage = EvqInOut; - } -#line 5592 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 156: -#line 1267 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.globalCheck((yyvsp[0].lex).loc, "in"); - (yyval.interm.type).init((yyvsp[0].lex).loc); - // whether this is a parameter "in" or a pipeline "in" will get sorted out a bit later - (yyval.interm.type).qualifier.storage = EvqIn; - } -#line 5603 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 157: -#line 1273 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.globalCheck((yyvsp[0].lex).loc, "out"); - (yyval.interm.type).init((yyvsp[0].lex).loc); - // whether this is a parameter "out" or a pipeline "out" will get sorted out a bit later - (yyval.interm.type).qualifier.storage = EvqOut; - } -#line 5614 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 158: -#line 1279 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.profileRequires((yyvsp[0].lex).loc, ENoProfile, 120, 0, "centroid"); - parseContext.profileRequires((yyvsp[0].lex).loc, EEsProfile, 300, 0, "centroid"); - parseContext.globalCheck((yyvsp[0].lex).loc, "centroid"); - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.centroid = true; - } -#line 5626 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 159: -#line 1286 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.globalCheck((yyvsp[0].lex).loc, "patch"); - parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangTessControlMask | EShLangTessEvaluationMask), "patch"); - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.patch = true; - } -#line 5637 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 160: -#line 1292 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.globalCheck((yyvsp[0].lex).loc, "sample"); - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.sample = true; - } -#line 5647 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 161: -#line 1297 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.globalCheck((yyvsp[0].lex).loc, "uniform"); - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.storage = EvqUniform; - } -#line 5657 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 162: -#line 1302 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.globalCheck((yyvsp[0].lex).loc, "buffer"); - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.storage = EvqBuffer; - } -#line 5667 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 163: -#line 1307 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.globalCheck((yyvsp[0].lex).loc, "shared"); - parseContext.profileRequires((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, 430, E_GL_ARB_compute_shader, "shared"); - parseContext.profileRequires((yyvsp[0].lex).loc, EEsProfile, 310, 0, "shared"); - parseContext.requireStage((yyvsp[0].lex).loc, EShLangCompute, "shared"); - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.storage = EvqShared; - } -#line 5680 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 164: -#line 1315 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.coherent = true; - } -#line 5689 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 165: -#line 1319 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.volatil = true; - } -#line 5698 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 166: -#line 1323 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.restrict = true; - } -#line 5707 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 167: -#line 1327 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.readonly = true; - } -#line 5716 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 168: -#line 1331 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.writeonly = true; - } -#line 5725 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 169: -#line 1335 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.spvRemoved((yyvsp[0].lex).loc, "subroutine"); - parseContext.globalCheck((yyvsp[0].lex).loc, "subroutine"); - parseContext.unimplemented((yyvsp[0].lex).loc, "subroutine"); - (yyval.interm.type).init((yyvsp[0].lex).loc); - } -#line 5736 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 170: -#line 1341 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.spvRemoved((yyvsp[-3].lex).loc, "subroutine"); - parseContext.globalCheck((yyvsp[-3].lex).loc, "subroutine"); - parseContext.unimplemented((yyvsp[-3].lex).loc, "subroutine"); - (yyval.interm.type).init((yyvsp[-3].lex).loc); - } -#line 5747 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 171: -#line 1350 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.nonUniform = true; - } -#line 5756 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 172: -#line 1357 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - // TODO - } -#line 5764 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 173: -#line 1360 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - // TODO: 4.0 semantics: subroutines - // 1) make sure each identifier is a type declared earlier with SUBROUTINE - // 2) save all of the identifiers for future comparison with the declared function - } -#line 5774 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 174: -#line 1368 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type) = (yyvsp[0].interm.type); - (yyval.interm.type).qualifier.precision = parseContext.getDefaultPrecision((yyval.interm.type)); - } -#line 5783 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 175: -#line 1372 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.arrayOfArrayVersionCheck((yyvsp[0].interm).loc, (yyvsp[0].interm).arraySizes); - (yyval.interm.type) = (yyvsp[-1].interm.type); - (yyval.interm.type).qualifier.precision = parseContext.getDefaultPrecision((yyval.interm.type)); - (yyval.interm.type).arraySizes = (yyvsp[0].interm).arraySizes; - } -#line 5794 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 176: -#line 1381 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm).loc = (yyvsp[-1].lex).loc; - (yyval.interm).arraySizes = new TArraySizes; - (yyval.interm).arraySizes->addInnerSize(); - } -#line 5804 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 177: -#line 1386 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm).loc = (yyvsp[-2].lex).loc; - (yyval.interm).arraySizes = new TArraySizes; - - TArraySize size; - parseContext.arraySizeCheck((yyvsp[-1].interm.intermTypedNode)->getLoc(), (yyvsp[-1].interm.intermTypedNode), size); - (yyval.interm).arraySizes->addInnerSize(size); - } -#line 5817 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 178: -#line 1394 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm) = (yyvsp[-2].interm); - (yyval.interm).arraySizes->addInnerSize(); - } -#line 5826 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 179: -#line 1398 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm) = (yyvsp[-3].interm); - - TArraySize size; - parseContext.arraySizeCheck((yyvsp[-1].interm.intermTypedNode)->getLoc(), (yyvsp[-1].interm.intermTypedNode), size); - (yyval.interm).arraySizes->addInnerSize(size); - } -#line 5838 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 180: -#line 1408 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtVoid; - } -#line 5847 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 181: -#line 1412 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - } -#line 5856 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 182: -#line 1416 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.doubleCheck((yyvsp[0].lex).loc, "double"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - } -#line 5866 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 183: -#line 1421 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.float16Check((yyvsp[0].lex).loc, "float16_t", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat16; - } -#line 5876 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 184: -#line 1426 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - } -#line 5886 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 185: -#line 1431 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - } -#line 5896 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 186: -#line 1436 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtInt; - } -#line 5905 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 187: -#line 1440 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "unsigned integer"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtUint; - } -#line 5915 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 188: -#line 1445 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitInt8Check((yyvsp[0].lex).loc, "8-bit signed integer", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtInt8; - } -#line 5925 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 189: -#line 1450 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitInt8Check((yyvsp[0].lex).loc, "8-bit unsigned integer", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtUint8; - } -#line 5935 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 190: -#line 1455 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitInt16Check((yyvsp[0].lex).loc, "16-bit signed integer", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtInt16; - } -#line 5945 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 191: -#line 1460 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitInt16Check((yyvsp[0].lex).loc, "16-bit unsigned integer", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtUint16; - } -#line 5955 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 192: -#line 1465 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitInt32Check((yyvsp[0].lex).loc, "32-bit signed integer", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtInt; - } -#line 5965 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 193: -#line 1470 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitInt32Check((yyvsp[0].lex).loc, "32-bit unsigned integer", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtUint; - } -#line 5975 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 194: -#line 1475 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.int64Check((yyvsp[0].lex).loc, "64-bit integer", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtInt64; - } -#line 5985 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 195: -#line 1480 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.int64Check((yyvsp[0].lex).loc, "64-bit unsigned integer", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtUint64; - } -#line 5995 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 196: -#line 1485 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtBool; - } -#line 6004 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 197: -#line 1489 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - (yyval.interm.type).setVector(2); - } -#line 6014 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 198: -#line 1494 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - (yyval.interm.type).setVector(3); - } -#line 6024 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 199: -#line 1499 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - (yyval.interm.type).setVector(4); - } -#line 6034 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 200: -#line 1504 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.doubleCheck((yyvsp[0].lex).loc, "double vector"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - (yyval.interm.type).setVector(2); - } -#line 6045 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 201: -#line 1510 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.doubleCheck((yyvsp[0].lex).loc, "double vector"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - (yyval.interm.type).setVector(3); - } -#line 6056 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 202: -#line 1516 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.doubleCheck((yyvsp[0].lex).loc, "double vector"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - (yyval.interm.type).setVector(4); - } -#line 6067 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 203: -#line 1522 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.float16Check((yyvsp[0].lex).loc, "half float vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat16; - (yyval.interm.type).setVector(2); - } -#line 6078 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 204: -#line 1528 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.float16Check((yyvsp[0].lex).loc, "half float vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat16; - (yyval.interm.type).setVector(3); - } -#line 6089 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 205: -#line 1534 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.float16Check((yyvsp[0].lex).loc, "half float vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat16; - (yyval.interm.type).setVector(4); - } -#line 6100 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 206: -#line 1540 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - (yyval.interm.type).setVector(2); - } -#line 6111 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 207: -#line 1546 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - (yyval.interm.type).setVector(3); - } -#line 6122 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 208: -#line 1552 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - (yyval.interm.type).setVector(4); - } -#line 6133 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 209: -#line 1558 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - (yyval.interm.type).setVector(2); - } -#line 6144 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 210: -#line 1564 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - (yyval.interm.type).setVector(3); - } -#line 6155 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 211: -#line 1570 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - (yyval.interm.type).setVector(4); - } -#line 6166 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 212: -#line 1576 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtBool; - (yyval.interm.type).setVector(2); - } -#line 6176 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 213: -#line 1581 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtBool; - (yyval.interm.type).setVector(3); - } -#line 6186 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 214: -#line 1586 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtBool; - (yyval.interm.type).setVector(4); - } -#line 6196 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 215: -#line 1591 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtInt; - (yyval.interm.type).setVector(2); - } -#line 6206 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 216: -#line 1596 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtInt; - (yyval.interm.type).setVector(3); - } -#line 6216 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 217: -#line 1601 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtInt; - (yyval.interm.type).setVector(4); - } -#line 6226 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 218: -#line 1606 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitInt8Check((yyvsp[0].lex).loc, "8-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtInt8; - (yyval.interm.type).setVector(2); - } -#line 6237 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 219: -#line 1612 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitInt8Check((yyvsp[0].lex).loc, "8-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtInt8; - (yyval.interm.type).setVector(3); - } -#line 6248 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 220: -#line 1618 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitInt8Check((yyvsp[0].lex).loc, "8-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtInt8; - (yyval.interm.type).setVector(4); - } -#line 6259 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 221: -#line 1624 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitInt16Check((yyvsp[0].lex).loc, "16-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtInt16; - (yyval.interm.type).setVector(2); - } -#line 6270 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 222: -#line 1630 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitInt16Check((yyvsp[0].lex).loc, "16-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtInt16; - (yyval.interm.type).setVector(3); - } -#line 6281 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 223: -#line 1636 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitInt16Check((yyvsp[0].lex).loc, "16-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtInt16; - (yyval.interm.type).setVector(4); - } -#line 6292 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 224: -#line 1642 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitInt32Check((yyvsp[0].lex).loc, "32-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtInt; - (yyval.interm.type).setVector(2); - } -#line 6303 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 225: -#line 1648 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitInt32Check((yyvsp[0].lex).loc, "32-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtInt; - (yyval.interm.type).setVector(3); - } -#line 6314 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 226: -#line 1654 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitInt32Check((yyvsp[0].lex).loc, "32-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtInt; - (yyval.interm.type).setVector(4); - } -#line 6325 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 227: -#line 1660 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.int64Check((yyvsp[0].lex).loc, "64-bit integer vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtInt64; - (yyval.interm.type).setVector(2); - } -#line 6336 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 228: -#line 1666 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.int64Check((yyvsp[0].lex).loc, "64-bit integer vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtInt64; - (yyval.interm.type).setVector(3); - } -#line 6347 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 229: -#line 1672 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.int64Check((yyvsp[0].lex).loc, "64-bit integer vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtInt64; - (yyval.interm.type).setVector(4); - } -#line 6358 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 230: -#line 1678 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "unsigned integer vector"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtUint; - (yyval.interm.type).setVector(2); - } -#line 6369 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 231: -#line 1684 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "unsigned integer vector"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtUint; - (yyval.interm.type).setVector(3); - } -#line 6380 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 232: -#line 1690 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "unsigned integer vector"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtUint; - (yyval.interm.type).setVector(4); - } -#line 6391 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 233: -#line 1696 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitInt8Check((yyvsp[0].lex).loc, "8-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtUint8; - (yyval.interm.type).setVector(2); - } -#line 6402 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 234: -#line 1702 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitInt8Check((yyvsp[0].lex).loc, "8-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtInt8; - (yyval.interm.type).setVector(3); - } -#line 6413 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 235: -#line 1708 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitInt8Check((yyvsp[0].lex).loc, "8-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtUint8; - (yyval.interm.type).setVector(4); - } -#line 6424 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 236: -#line 1714 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitInt16Check((yyvsp[0].lex).loc, "16-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtUint16; - (yyval.interm.type).setVector(2); - } -#line 6435 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 237: -#line 1720 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitInt16Check((yyvsp[0].lex).loc, "16-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtUint16; - (yyval.interm.type).setVector(3); - } -#line 6446 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 238: -#line 1726 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitInt16Check((yyvsp[0].lex).loc, "16-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtUint16; - (yyval.interm.type).setVector(4); - } -#line 6457 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 239: -#line 1732 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitInt32Check((yyvsp[0].lex).loc, "32-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtUint; - (yyval.interm.type).setVector(2); - } -#line 6468 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 240: -#line 1738 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitInt32Check((yyvsp[0].lex).loc, "32-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtUint; - (yyval.interm.type).setVector(3); - } -#line 6479 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 241: -#line 1744 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitInt32Check((yyvsp[0].lex).loc, "32-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtUint; - (yyval.interm.type).setVector(4); - } -#line 6490 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 242: -#line 1750 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.int64Check((yyvsp[0].lex).loc, "64-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtUint64; - (yyval.interm.type).setVector(2); - } -#line 6501 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 243: -#line 1756 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.int64Check((yyvsp[0].lex).loc, "64-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtUint64; - (yyval.interm.type).setVector(3); - } -#line 6512 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 244: -#line 1762 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.int64Check((yyvsp[0].lex).loc, "64-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtUint64; - (yyval.interm.type).setVector(4); - } -#line 6523 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 245: -#line 1768 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - (yyval.interm.type).setMatrix(2, 2); - } -#line 6533 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 246: -#line 1773 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - (yyval.interm.type).setMatrix(3, 3); - } -#line 6543 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 247: -#line 1778 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - (yyval.interm.type).setMatrix(4, 4); - } -#line 6553 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 248: -#line 1783 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - (yyval.interm.type).setMatrix(2, 2); - } -#line 6563 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 249: -#line 1788 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - (yyval.interm.type).setMatrix(2, 3); - } -#line 6573 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 250: -#line 1793 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - (yyval.interm.type).setMatrix(2, 4); - } -#line 6583 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 251: -#line 1798 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - (yyval.interm.type).setMatrix(3, 2); - } -#line 6593 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 252: -#line 1803 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - (yyval.interm.type).setMatrix(3, 3); - } -#line 6603 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 253: -#line 1808 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - (yyval.interm.type).setMatrix(3, 4); - } -#line 6613 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 254: -#line 1813 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - (yyval.interm.type).setMatrix(4, 2); - } -#line 6623 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 255: -#line 1818 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - (yyval.interm.type).setMatrix(4, 3); - } -#line 6633 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 256: -#line 1823 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - (yyval.interm.type).setMatrix(4, 4); - } -#line 6643 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 257: -#line 1828 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - (yyval.interm.type).setMatrix(2, 2); - } -#line 6654 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 258: -#line 1834 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - (yyval.interm.type).setMatrix(3, 3); - } -#line 6665 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 259: -#line 1840 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - (yyval.interm.type).setMatrix(4, 4); - } -#line 6676 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 260: -#line 1846 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - (yyval.interm.type).setMatrix(2, 2); - } -#line 6687 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 261: -#line 1852 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - (yyval.interm.type).setMatrix(2, 3); - } -#line 6698 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 262: -#line 1858 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - (yyval.interm.type).setMatrix(2, 4); - } -#line 6709 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 263: -#line 1864 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - (yyval.interm.type).setMatrix(3, 2); - } -#line 6720 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 264: -#line 1870 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - (yyval.interm.type).setMatrix(3, 3); - } -#line 6731 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 265: -#line 1876 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - (yyval.interm.type).setMatrix(3, 4); - } -#line 6742 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 266: -#line 1882 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - (yyval.interm.type).setMatrix(4, 2); - } -#line 6753 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 267: -#line 1888 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - (yyval.interm.type).setMatrix(4, 3); - } -#line 6764 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 268: -#line 1894 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - (yyval.interm.type).setMatrix(4, 4); - } -#line 6775 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 269: -#line 1900 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat16; - (yyval.interm.type).setMatrix(2, 2); - } -#line 6786 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 270: -#line 1906 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat16; - (yyval.interm.type).setMatrix(3, 3); - } -#line 6797 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 271: -#line 1912 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat16; - (yyval.interm.type).setMatrix(4, 4); - } -#line 6808 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 272: -#line 1918 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat16; - (yyval.interm.type).setMatrix(2, 2); - } -#line 6819 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 273: -#line 1924 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat16; - (yyval.interm.type).setMatrix(2, 3); - } -#line 6830 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 274: -#line 1930 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat16; - (yyval.interm.type).setMatrix(2, 4); - } -#line 6841 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 275: -#line 1936 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat16; - (yyval.interm.type).setMatrix(3, 2); - } -#line 6852 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 276: -#line 1942 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat16; - (yyval.interm.type).setMatrix(3, 3); - } -#line 6863 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 277: -#line 1948 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat16; - (yyval.interm.type).setMatrix(3, 4); - } -#line 6874 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 278: -#line 1954 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat16; - (yyval.interm.type).setMatrix(4, 2); - } -#line 6885 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 279: -#line 1960 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat16; - (yyval.interm.type).setMatrix(4, 3); - } -#line 6896 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 280: -#line 1966 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat16; - (yyval.interm.type).setMatrix(4, 4); - } -#line 6907 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 281: -#line 1972 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - (yyval.interm.type).setMatrix(2, 2); - } -#line 6918 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 282: -#line 1978 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - (yyval.interm.type).setMatrix(3, 3); - } -#line 6929 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 283: -#line 1984 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - (yyval.interm.type).setMatrix(4, 4); - } -#line 6940 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 284: -#line 1990 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - (yyval.interm.type).setMatrix(2, 2); - } -#line 6951 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 285: -#line 1996 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - (yyval.interm.type).setMatrix(2, 3); - } -#line 6962 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 286: -#line 2002 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - (yyval.interm.type).setMatrix(2, 4); - } -#line 6973 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 287: -#line 2008 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - (yyval.interm.type).setMatrix(3, 2); - } -#line 6984 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 288: -#line 2014 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - (yyval.interm.type).setMatrix(3, 3); - } -#line 6995 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 289: -#line 2020 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - (yyval.interm.type).setMatrix(3, 4); - } -#line 7006 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 290: -#line 2026 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - (yyval.interm.type).setMatrix(4, 2); - } -#line 7017 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 291: -#line 2032 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - (yyval.interm.type).setMatrix(4, 3); - } -#line 7028 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 292: -#line 2038 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - (yyval.interm.type).setMatrix(4, 4); - } -#line 7039 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 293: -#line 2044 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - (yyval.interm.type).setMatrix(2, 2); - } -#line 7050 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 294: -#line 2050 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - (yyval.interm.type).setMatrix(3, 3); - } -#line 7061 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 295: -#line 2056 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - (yyval.interm.type).setMatrix(4, 4); - } -#line 7072 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 296: -#line 2062 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - (yyval.interm.type).setMatrix(2, 2); - } -#line 7083 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 297: -#line 2068 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - (yyval.interm.type).setMatrix(2, 3); - } -#line 7094 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 298: -#line 2074 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - (yyval.interm.type).setMatrix(2, 4); - } -#line 7105 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 299: -#line 2080 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - (yyval.interm.type).setMatrix(3, 2); - } -#line 7116 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 300: -#line 2086 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - (yyval.interm.type).setMatrix(3, 3); - } -#line 7127 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 301: -#line 2092 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - (yyval.interm.type).setMatrix(3, 4); - } -#line 7138 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 302: -#line 2098 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - (yyval.interm.type).setMatrix(4, 2); - } -#line 7149 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 303: -#line 2104 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - (yyval.interm.type).setMatrix(4, 3); - } -#line 7160 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 304: -#line 2110 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - (yyval.interm.type).setMatrix(4, 4); - } -#line 7171 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 305: -#line 2116 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.vulkanRemoved((yyvsp[0].lex).loc, "atomic counter types"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtAtomicUint; - } -#line 7181 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 306: -#line 2121 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat, Esd1D); - } -#line 7191 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 307: -#line 2126 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat, Esd2D); - } -#line 7201 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 308: -#line 2131 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat, Esd3D); - } -#line 7211 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 309: -#line 2136 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat, EsdCube); - } -#line 7221 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 310: -#line 2141 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat, Esd1D, false, true); - } -#line 7231 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 311: -#line 2146 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat, Esd2D, false, true); - } -#line 7241 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 312: -#line 2151 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat, EsdCube, false, true); - } -#line 7251 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 313: -#line 2156 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat, Esd1D, true); - } -#line 7261 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 314: -#line 2161 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat, Esd2D, true); - } -#line 7271 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 315: -#line 2166 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat, Esd1D, true, true); - } -#line 7281 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 316: -#line 2171 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat, Esd2D, true, true); - } -#line 7291 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 317: -#line 2176 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat, EsdCube, true); - } -#line 7301 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 318: -#line 2181 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat, EsdCube, true, true); - } -#line 7311 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 319: -#line 2186 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { -#ifdef AMD_EXTENSIONS - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat16, Esd1D); -#endif - } -#line 7324 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 320: -#line 2194 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { -#ifdef AMD_EXTENSIONS - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat16, Esd2D); -#endif - } -#line 7337 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 321: -#line 2202 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { -#ifdef AMD_EXTENSIONS - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat16, Esd3D); -#endif - } -#line 7350 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 322: -#line 2210 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { -#ifdef AMD_EXTENSIONS - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat16, EsdCube); -#endif - } -#line 7363 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 323: -#line 2218 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { -#ifdef AMD_EXTENSIONS - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat16, Esd1D, false, true); -#endif - } -#line 7376 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 324: -#line 2226 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { -#ifdef AMD_EXTENSIONS - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat16, Esd2D, false, true); -#endif - } -#line 7389 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 325: -#line 2234 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { -#ifdef AMD_EXTENSIONS - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat16, EsdCube, false, true); -#endif - } -#line 7402 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 326: -#line 2242 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { -#ifdef AMD_EXTENSIONS - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat16, Esd1D, true); -#endif - } -#line 7415 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 327: -#line 2250 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { -#ifdef AMD_EXTENSIONS - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat16, Esd2D, true); -#endif - } -#line 7428 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 328: -#line 2258 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { -#ifdef AMD_EXTENSIONS - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat16, Esd1D, true, true); -#endif - } -#line 7441 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 329: -#line 2266 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { -#ifdef AMD_EXTENSIONS - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat16, Esd2D, true, true); -#endif - } -#line 7454 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 330: -#line 2274 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { -#ifdef AMD_EXTENSIONS - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat16, EsdCube, true); -#endif - } -#line 7467 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 331: -#line 2282 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { -#ifdef AMD_EXTENSIONS - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat16, EsdCube, true, true); -#endif - } -#line 7480 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 332: -#line 2290 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtInt, Esd1D); - } -#line 7490 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 333: -#line 2295 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtInt, Esd2D); - } -#line 7500 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 334: -#line 2300 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtInt, Esd3D); - } -#line 7510 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 335: -#line 2305 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtInt, EsdCube); - } -#line 7520 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 336: -#line 2310 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtInt, Esd1D, true); - } -#line 7530 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 337: -#line 2315 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtInt, Esd2D, true); - } -#line 7540 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 338: -#line 2320 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtInt, EsdCube, true); - } -#line 7550 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 339: -#line 2325 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtUint, Esd1D); - } -#line 7560 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 340: -#line 2330 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtUint, Esd2D); - } -#line 7570 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 341: -#line 2335 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtUint, Esd3D); - } -#line 7580 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 342: -#line 2340 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtUint, EsdCube); - } -#line 7590 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 343: -#line 2345 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtUint, Esd1D, true); - } -#line 7600 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 344: -#line 2350 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtUint, Esd2D, true); - } -#line 7610 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 345: -#line 2355 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtUint, EsdCube, true); - } -#line 7620 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 346: -#line 2360 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat, EsdRect); - } -#line 7630 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 347: -#line 2365 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat, EsdRect, false, true); - } -#line 7640 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 348: -#line 2370 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { -#ifdef AMD_EXTENSIONS - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat16, EsdRect); -#endif - } -#line 7653 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 349: -#line 2378 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { -#ifdef AMD_EXTENSIONS - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat16, EsdRect, false, true); -#endif - } -#line 7666 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 350: -#line 2386 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtInt, EsdRect); - } -#line 7676 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 351: -#line 2391 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtUint, EsdRect); - } -#line 7686 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 352: -#line 2396 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat, EsdBuffer); - } -#line 7696 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 353: -#line 2401 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { -#ifdef AMD_EXTENSIONS - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat16, EsdBuffer); -#endif - } -#line 7709 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 354: -#line 2409 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtInt, EsdBuffer); - } -#line 7719 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 355: -#line 2414 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtUint, EsdBuffer); - } -#line 7729 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 356: -#line 2419 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat, Esd2D, false, false, true); - } -#line 7739 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 357: -#line 2424 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { -#ifdef AMD_EXTENSIONS - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat16, Esd2D, false, false, true); -#endif - } -#line 7752 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 358: -#line 2432 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtInt, Esd2D, false, false, true); - } -#line 7762 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 359: -#line 2437 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtUint, Esd2D, false, false, true); - } -#line 7772 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 360: -#line 2442 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat, Esd2D, true, false, true); - } -#line 7782 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 361: -#line 2447 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { -#ifdef AMD_EXTENSIONS - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat16, Esd2D, true, false, true); -#endif - } -#line 7795 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 362: -#line 2455 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtInt, Esd2D, true, false, true); - } -#line 7805 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 363: -#line 2460 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtUint, Esd2D, true, false, true); - } -#line 7815 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 364: -#line 2465 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setPureSampler(false); - } -#line 7825 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 365: -#line 2470 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setPureSampler(true); - } -#line 7835 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 366: -#line 2475 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtFloat, Esd1D); - } -#line 7845 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 367: -#line 2480 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { -#ifdef AMD_EXTENSIONS - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float texture", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtFloat16, Esd1D); -#endif - } -#line 7858 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 368: -#line 2488 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtFloat, Esd2D); - } -#line 7868 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 369: -#line 2493 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { -#ifdef AMD_EXTENSIONS - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float texture", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtFloat16, Esd2D); -#endif - } -#line 7881 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 370: -#line 2501 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtFloat, Esd3D); - } -#line 7891 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 371: -#line 2506 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { -#ifdef AMD_EXTENSIONS - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float texture", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtFloat16, Esd3D); -#endif - } -#line 7904 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 372: -#line 2514 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtFloat, EsdCube); - } -#line 7914 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 373: -#line 2519 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { -#ifdef AMD_EXTENSIONS - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float texture", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtFloat16, EsdCube); -#endif - } -#line 7927 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 374: -#line 2527 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtFloat, Esd1D, true); - } -#line 7937 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 375: -#line 2532 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { -#ifdef AMD_EXTENSIONS - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float texture", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtFloat16, Esd1D, true); -#endif - } -#line 7950 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 376: -#line 2540 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtFloat, Esd2D, true); - } -#line 7960 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 377: -#line 2545 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { -#ifdef AMD_EXTENSIONS - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float texture", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtFloat16, Esd2D, true); -#endif - } -#line 7973 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 378: -#line 2553 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtFloat, EsdCube, true); - } -#line 7983 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 379: -#line 2558 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { -#ifdef AMD_EXTENSIONS - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float texture", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtFloat16, EsdCube, true); -#endif - } -#line 7996 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 380: -#line 2566 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtInt, Esd1D); - } -#line 8006 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 381: -#line 2571 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtInt, Esd2D); - } -#line 8016 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 382: -#line 2576 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtInt, Esd3D); - } -#line 8026 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 383: -#line 2581 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtInt, EsdCube); - } -#line 8036 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 384: -#line 2586 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtInt, Esd1D, true); - } -#line 8046 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 385: -#line 2591 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtInt, Esd2D, true); - } -#line 8056 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 386: -#line 2596 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtInt, EsdCube, true); - } -#line 8066 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 387: -#line 2601 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtUint, Esd1D); - } -#line 8076 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 388: -#line 2606 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtUint, Esd2D); - } -#line 8086 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 389: -#line 2611 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtUint, Esd3D); - } -#line 8096 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 390: -#line 2616 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtUint, EsdCube); - } -#line 8106 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 391: -#line 2621 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtUint, Esd1D, true); - } -#line 8116 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 392: -#line 2626 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtUint, Esd2D, true); - } -#line 8126 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 393: -#line 2631 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtUint, EsdCube, true); - } -#line 8136 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 394: -#line 2636 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtFloat, EsdRect); - } -#line 8146 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 395: -#line 2641 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { -#ifdef AMD_EXTENSIONS - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float texture", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtFloat16, EsdRect); -#endif - } -#line 8159 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 396: -#line 2649 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtInt, EsdRect); - } -#line 8169 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 397: -#line 2654 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtUint, EsdRect); - } -#line 8179 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 398: -#line 2659 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtFloat, EsdBuffer); - } -#line 8189 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 399: -#line 2664 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { -#ifdef AMD_EXTENSIONS - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float texture", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtFloat16, EsdBuffer); -#endif - } -#line 8202 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 400: -#line 2672 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtInt, EsdBuffer); - } -#line 8212 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 401: -#line 2677 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtUint, EsdBuffer); - } -#line 8222 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 402: -#line 2682 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtFloat, Esd2D, false, false, true); - } -#line 8232 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 403: -#line 2687 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { -#ifdef AMD_EXTENSIONS - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float texture", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtFloat16, Esd2D, false, false, true); -#endif - } -#line 8245 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 404: -#line 2695 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtInt, Esd2D, false, false, true); - } -#line 8255 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 405: -#line 2700 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtUint, Esd2D, false, false, true); - } -#line 8265 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 406: -#line 2705 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtFloat, Esd2D, true, false, true); - } -#line 8275 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 407: -#line 2710 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { -#ifdef AMD_EXTENSIONS - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float texture", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtFloat16, Esd2D, true, false, true); -#endif - } -#line 8288 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 408: -#line 2718 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtInt, Esd2D, true, false, true); - } -#line 8298 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 409: -#line 2723 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtUint, Esd2D, true, false, true); - } -#line 8308 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 410: -#line 2728 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtFloat, Esd1D); - } -#line 8318 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 411: -#line 2733 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { -#ifdef AMD_EXTENSIONS - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float image", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtFloat16, Esd1D); -#endif - } -#line 8331 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 412: -#line 2741 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtInt, Esd1D); - } -#line 8341 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 413: -#line 2746 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtUint, Esd1D); - } -#line 8351 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 414: -#line 2751 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtFloat, Esd2D); - } -#line 8361 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 415: -#line 2756 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { -#ifdef AMD_EXTENSIONS - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float image", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtFloat16, Esd2D); -#endif - } -#line 8374 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 416: -#line 2764 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtInt, Esd2D); - } -#line 8384 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 417: -#line 2769 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtUint, Esd2D); - } -#line 8394 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 418: -#line 2774 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtFloat, Esd3D); - } -#line 8404 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 419: -#line 2779 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { -#ifdef AMD_EXTENSIONS - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float image", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtFloat16, Esd3D); -#endif - } -#line 8417 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 420: -#line 2787 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtInt, Esd3D); - } -#line 8427 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 421: -#line 2792 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtUint, Esd3D); - } -#line 8437 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 422: -#line 2797 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtFloat, EsdRect); - } -#line 8447 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 423: -#line 2802 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { -#ifdef AMD_EXTENSIONS - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float image", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtFloat16, EsdRect); -#endif - } -#line 8460 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 424: -#line 2810 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtInt, EsdRect); - } -#line 8470 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 425: -#line 2815 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtUint, EsdRect); - } -#line 8480 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 426: -#line 2820 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtFloat, EsdCube); - } -#line 8490 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 427: -#line 2825 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { -#ifdef AMD_EXTENSIONS - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float image", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtFloat16, EsdCube); -#endif - } -#line 8503 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 428: -#line 2833 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtInt, EsdCube); - } -#line 8513 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 429: -#line 2838 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtUint, EsdCube); - } -#line 8523 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 430: -#line 2843 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtFloat, EsdBuffer); - } -#line 8533 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 431: -#line 2848 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { -#ifdef AMD_EXTENSIONS - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float image", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtFloat16, EsdBuffer); -#endif - } -#line 8546 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 432: -#line 2856 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtInt, EsdBuffer); - } -#line 8556 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 433: -#line 2861 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtUint, EsdBuffer); - } -#line 8566 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 434: -#line 2866 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtFloat, Esd1D, true); - } -#line 8576 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 435: -#line 2871 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { -#ifdef AMD_EXTENSIONS - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float image", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtFloat16, Esd1D, true); -#endif - } -#line 8589 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 436: -#line 2879 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtInt, Esd1D, true); - } -#line 8599 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 437: -#line 2884 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtUint, Esd1D, true); - } -#line 8609 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 438: -#line 2889 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtFloat, Esd2D, true); - } -#line 8619 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 439: -#line 2894 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { -#ifdef AMD_EXTENSIONS - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float image", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtFloat16, Esd2D, true); -#endif - } -#line 8632 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 440: -#line 2902 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtInt, Esd2D, true); - } -#line 8642 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 441: -#line 2907 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtUint, Esd2D, true); - } -#line 8652 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 442: -#line 2912 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtFloat, EsdCube, true); - } -#line 8662 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 443: -#line 2917 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { -#ifdef AMD_EXTENSIONS - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float image", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtFloat16, EsdCube, true); -#endif - } -#line 8675 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 444: -#line 2925 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtInt, EsdCube, true); - } -#line 8685 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 445: -#line 2930 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtUint, EsdCube, true); - } -#line 8695 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 446: -#line 2935 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtFloat, Esd2D, false, false, true); - } -#line 8705 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 447: -#line 2940 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { -#ifdef AMD_EXTENSIONS - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float image", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtFloat16, Esd2D, false, false, true); -#endif - } -#line 8718 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 448: -#line 2948 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtInt, Esd2D, false, false, true); - } -#line 8728 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 449: -#line 2953 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtUint, Esd2D, false, false, true); - } -#line 8738 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 450: -#line 2958 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtFloat, Esd2D, true, false, true); - } -#line 8748 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 451: -#line 2963 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { -#ifdef AMD_EXTENSIONS - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float image", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtFloat16, Esd2D, true, false, true); -#endif - } -#line 8761 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 452: -#line 2971 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtInt, Esd2D, true, false, true); - } -#line 8771 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 453: -#line 2976 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtUint, Esd2D, true, false, true); - } -#line 8781 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 454: -#line 2981 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { // GL_OES_EGL_image_external - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat, Esd2D); - (yyval.interm.type).sampler.external = true; - } -#line 8792 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 455: -#line 2987 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.requireStage((yyvsp[0].lex).loc, EShLangFragment, "subpass input"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setSubpass(EbtFloat); - } -#line 8803 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 456: -#line 2993 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.requireStage((yyvsp[0].lex).loc, EShLangFragment, "subpass input"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setSubpass(EbtFloat, true); - } -#line 8814 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 457: -#line 2999 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { -#ifdef AMD_EXTENSIONS - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float subpass input", parseContext.symbolTable.atBuiltInLevel()); - parseContext.requireStage((yyvsp[0].lex).loc, EShLangFragment, "subpass input"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setSubpass(EbtFloat16); -#endif - } -#line 8828 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 458: -#line 3008 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { -#ifdef AMD_EXTENSIONS - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float subpass input", parseContext.symbolTable.atBuiltInLevel()); - parseContext.requireStage((yyvsp[0].lex).loc, EShLangFragment, "subpass input"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setSubpass(EbtFloat16, true); -#endif - } -#line 8842 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 459: -#line 3017 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.requireStage((yyvsp[0].lex).loc, EShLangFragment, "subpass input"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setSubpass(EbtInt); - } -#line 8853 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 460: -#line 3023 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.requireStage((yyvsp[0].lex).loc, EShLangFragment, "subpass input"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setSubpass(EbtInt, true); - } -#line 8864 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 461: -#line 3029 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.requireStage((yyvsp[0].lex).loc, EShLangFragment, "subpass input"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setSubpass(EbtUint); - } -#line 8875 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 462: -#line 3035 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.requireStage((yyvsp[0].lex).loc, EShLangFragment, "subpass input"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setSubpass(EbtUint, true); - } -#line 8886 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 463: -#line 3041 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type) = (yyvsp[0].interm.type); - (yyval.interm.type).qualifier.storage = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - parseContext.structTypeCheck((yyval.interm.type).loc, (yyval.interm.type)); - } -#line 8896 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 464: -#line 3046 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - // - // This is for user defined type names. The lexical phase looked up the - // type. - // - if (const TVariable* variable = ((yyvsp[0].lex).symbol)->getAsVariable()) { - const TType& structure = variable->getType(); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtStruct; - (yyval.interm.type).userDef = &structure; - } else - parseContext.error((yyvsp[0].lex).loc, "expected type name", (yyvsp[0].lex).string->c_str(), ""); - } -#line 8914 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 465: -#line 3062 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.profileRequires((yyvsp[0].lex).loc, ENoProfile, 130, 0, "highp precision qualifier"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - parseContext.handlePrecisionQualifier((yyvsp[0].lex).loc, (yyval.interm.type).qualifier, EpqHigh); - } -#line 8924 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 466: -#line 3067 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.profileRequires((yyvsp[0].lex).loc, ENoProfile, 130, 0, "mediump precision qualifier"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - parseContext.handlePrecisionQualifier((yyvsp[0].lex).loc, (yyval.interm.type).qualifier, EpqMedium); - } -#line 8934 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 467: -#line 3072 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.profileRequires((yyvsp[0].lex).loc, ENoProfile, 130, 0, "lowp precision qualifier"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - parseContext.handlePrecisionQualifier((yyvsp[0].lex).loc, (yyval.interm.type).qualifier, EpqLow); - } -#line 8944 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 468: -#line 3080 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { parseContext.nestedStructCheck((yyvsp[-2].lex).loc); } -#line 8950 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 469: -#line 3080 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - TType* structure = new TType((yyvsp[-1].interm.typeList), *(yyvsp[-4].lex).string); - parseContext.structArrayCheck((yyvsp[-4].lex).loc, *structure); - TVariable* userTypeDef = new TVariable((yyvsp[-4].lex).string, *structure, true); - if (! parseContext.symbolTable.insert(*userTypeDef)) - parseContext.error((yyvsp[-4].lex).loc, "redefinition", (yyvsp[-4].lex).string->c_str(), "struct"); - (yyval.interm.type).init((yyvsp[-5].lex).loc); - (yyval.interm.type).basicType = EbtStruct; - (yyval.interm.type).userDef = structure; - --parseContext.structNestingLevel; - } -#line 8966 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 470: -#line 3091 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { parseContext.nestedStructCheck((yyvsp[-1].lex).loc); } -#line 8972 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 471: -#line 3091 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - TType* structure = new TType((yyvsp[-1].interm.typeList), TString("")); - (yyval.interm.type).init((yyvsp[-4].lex).loc); - (yyval.interm.type).basicType = EbtStruct; - (yyval.interm.type).userDef = structure; - --parseContext.structNestingLevel; - } -#line 8984 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 472: -#line 3101 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.typeList) = (yyvsp[0].interm.typeList); - } -#line 8992 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 473: -#line 3104 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.typeList) = (yyvsp[-1].interm.typeList); - for (unsigned int i = 0; i < (yyvsp[0].interm.typeList)->size(); ++i) { - for (unsigned int j = 0; j < (yyval.interm.typeList)->size(); ++j) { - if ((*(yyval.interm.typeList))[j].type->getFieldName() == (*(yyvsp[0].interm.typeList))[i].type->getFieldName()) - parseContext.error((*(yyvsp[0].interm.typeList))[i].loc, "duplicate member name:", "", (*(yyvsp[0].interm.typeList))[i].type->getFieldName().c_str()); - } - (yyval.interm.typeList)->push_back((*(yyvsp[0].interm.typeList))[i]); - } - } -#line 9007 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 474: -#line 3117 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - if ((yyvsp[-2].interm.type).arraySizes) { - parseContext.profileRequires((yyvsp[-2].interm.type).loc, ENoProfile, 120, E_GL_3DL_array_objects, "arrayed type"); - parseContext.profileRequires((yyvsp[-2].interm.type).loc, EEsProfile, 300, 0, "arrayed type"); - if (parseContext.profile == EEsProfile) - parseContext.arraySizeRequiredCheck((yyvsp[-2].interm.type).loc, *(yyvsp[-2].interm.type).arraySizes); - } - - (yyval.interm.typeList) = (yyvsp[-1].interm.typeList); - - parseContext.voidErrorCheck((yyvsp[-2].interm.type).loc, (*(yyvsp[-1].interm.typeList))[0].type->getFieldName(), (yyvsp[-2].interm.type).basicType); - parseContext.precisionQualifierCheck((yyvsp[-2].interm.type).loc, (yyvsp[-2].interm.type).basicType, (yyvsp[-2].interm.type).qualifier); - - for (unsigned int i = 0; i < (yyval.interm.typeList)->size(); ++i) { - TType type((yyvsp[-2].interm.type)); - type.setFieldName((*(yyval.interm.typeList))[i].type->getFieldName()); - type.transferArraySizes((*(yyval.interm.typeList))[i].type->getArraySizes()); - type.copyArrayInnerSizes((yyvsp[-2].interm.type).arraySizes); - parseContext.arrayOfArrayVersionCheck((*(yyval.interm.typeList))[i].loc, type.getArraySizes()); - (*(yyval.interm.typeList))[i].type->shallowCopy(type); - } - } -#line 9034 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 475: -#line 3139 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - if ((yyvsp[-2].interm.type).arraySizes) { - parseContext.profileRequires((yyvsp[-2].interm.type).loc, ENoProfile, 120, E_GL_3DL_array_objects, "arrayed type"); - parseContext.profileRequires((yyvsp[-2].interm.type).loc, EEsProfile, 300, 0, "arrayed type"); - if (parseContext.profile == EEsProfile) - parseContext.arraySizeRequiredCheck((yyvsp[-2].interm.type).loc, *(yyvsp[-2].interm.type).arraySizes); - } - - (yyval.interm.typeList) = (yyvsp[-1].interm.typeList); - - parseContext.memberQualifierCheck((yyvsp[-3].interm.type)); - parseContext.voidErrorCheck((yyvsp[-2].interm.type).loc, (*(yyvsp[-1].interm.typeList))[0].type->getFieldName(), (yyvsp[-2].interm.type).basicType); - parseContext.mergeQualifiers((yyvsp[-2].interm.type).loc, (yyvsp[-2].interm.type).qualifier, (yyvsp[-3].interm.type).qualifier, true); - parseContext.precisionQualifierCheck((yyvsp[-2].interm.type).loc, (yyvsp[-2].interm.type).basicType, (yyvsp[-2].interm.type).qualifier); - - for (unsigned int i = 0; i < (yyval.interm.typeList)->size(); ++i) { - TType type((yyvsp[-2].interm.type)); - type.setFieldName((*(yyval.interm.typeList))[i].type->getFieldName()); - type.transferArraySizes((*(yyval.interm.typeList))[i].type->getArraySizes()); - type.copyArrayInnerSizes((yyvsp[-2].interm.type).arraySizes); - parseContext.arrayOfArrayVersionCheck((*(yyval.interm.typeList))[i].loc, type.getArraySizes()); - (*(yyval.interm.typeList))[i].type->shallowCopy(type); - } - } -#line 9063 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 476: -#line 3166 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.typeList) = new TTypeList; - (yyval.interm.typeList)->push_back((yyvsp[0].interm.typeLine)); - } -#line 9072 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 477: -#line 3170 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.typeList)->push_back((yyvsp[0].interm.typeLine)); - } -#line 9080 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 478: -#line 3176 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.typeLine).type = new TType(EbtVoid); - (yyval.interm.typeLine).loc = (yyvsp[0].lex).loc; - (yyval.interm.typeLine).type->setFieldName(*(yyvsp[0].lex).string); - } -#line 9090 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 479: -#line 3181 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.arrayOfArrayVersionCheck((yyvsp[-1].lex).loc, (yyvsp[0].interm).arraySizes); - - (yyval.interm.typeLine).type = new TType(EbtVoid); - (yyval.interm.typeLine).loc = (yyvsp[-1].lex).loc; - (yyval.interm.typeLine).type->setFieldName(*(yyvsp[-1].lex).string); - (yyval.interm.typeLine).type->transferArraySizes((yyvsp[0].interm).arraySizes); - } -#line 9103 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 480: -#line 3192 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); - } -#line 9111 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 481: -#line 3195 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - const char* initFeature = "{ } style initializers"; - parseContext.requireProfile((yyvsp[-2].lex).loc, ~EEsProfile, initFeature); - parseContext.profileRequires((yyvsp[-2].lex).loc, ~EEsProfile, 420, E_GL_ARB_shading_language_420pack, initFeature); - (yyval.interm.intermTypedNode) = (yyvsp[-1].interm.intermTypedNode); - } -#line 9122 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 482: -#line 3201 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - const char* initFeature = "{ } style initializers"; - parseContext.requireProfile((yyvsp[-3].lex).loc, ~EEsProfile, initFeature); - parseContext.profileRequires((yyvsp[-3].lex).loc, ~EEsProfile, 420, E_GL_ARB_shading_language_420pack, initFeature); - (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode); - } -#line 9133 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 483: -#line 3210 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.intermTypedNode) = parseContext.intermediate.growAggregate(0, (yyvsp[0].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)->getLoc()); - } -#line 9141 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 484: -#line 3213 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.intermTypedNode) = parseContext.intermediate.growAggregate((yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); - } -#line 9149 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 485: -#line 3219 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } -#line 9155 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 486: -#line 3223 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } -#line 9161 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 487: -#line 3224 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } -#line 9167 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 488: -#line 3230 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } -#line 9173 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 489: -#line 3231 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } -#line 9179 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 490: -#line 3232 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } -#line 9185 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 491: -#line 3233 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } -#line 9191 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 492: -#line 3234 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } -#line 9197 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 493: -#line 3235 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } -#line 9203 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 494: -#line 3236 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } -#line 9209 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 495: -#line 3240 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { (yyval.interm.intermNode) = 0; } -#line 9215 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 496: -#line 3241 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.symbolTable.push(); - ++parseContext.statementNestingLevel; - } -#line 9224 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 497: -#line 3245 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]); - --parseContext.statementNestingLevel; - } -#line 9233 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 498: -#line 3249 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - if ((yyvsp[-2].interm.intermNode) && (yyvsp[-2].interm.intermNode)->getAsAggregate()) - (yyvsp[-2].interm.intermNode)->getAsAggregate()->setOperator(EOpSequence); - (yyval.interm.intermNode) = (yyvsp[-2].interm.intermNode); - } -#line 9243 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 499: -#line 3257 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } -#line 9249 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 500: -#line 3258 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } -#line 9255 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 501: -#line 3262 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - ++parseContext.controlFlowNestingLevel; - } -#line 9263 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 502: -#line 3265 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - --parseContext.controlFlowNestingLevel; - (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); - } -#line 9272 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 503: -#line 3269 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.symbolTable.push(); - ++parseContext.statementNestingLevel; - ++parseContext.controlFlowNestingLevel; - } -#line 9282 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 504: -#line 3274 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]); - --parseContext.statementNestingLevel; - --parseContext.controlFlowNestingLevel; - (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); - } -#line 9293 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 505: -#line 3283 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.intermNode) = 0; - } -#line 9301 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 506: -#line 3286 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - if ((yyvsp[-1].interm.intermNode) && (yyvsp[-1].interm.intermNode)->getAsAggregate()) - (yyvsp[-1].interm.intermNode)->getAsAggregate()->setOperator(EOpSequence); - (yyval.interm.intermNode) = (yyvsp[-1].interm.intermNode); - } -#line 9311 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 507: -#line 3294 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.intermNode) = parseContext.intermediate.makeAggregate((yyvsp[0].interm.intermNode)); - if ((yyvsp[0].interm.intermNode) && (yyvsp[0].interm.intermNode)->getAsBranchNode() && ((yyvsp[0].interm.intermNode)->getAsBranchNode()->getFlowOp() == EOpCase || - (yyvsp[0].interm.intermNode)->getAsBranchNode()->getFlowOp() == EOpDefault)) { - parseContext.wrapupSwitchSubsequence(0, (yyvsp[0].interm.intermNode)); - (yyval.interm.intermNode) = 0; // start a fresh subsequence for what's after this case - } - } -#line 9324 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 508: -#line 3302 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - if ((yyvsp[0].interm.intermNode) && (yyvsp[0].interm.intermNode)->getAsBranchNode() && ((yyvsp[0].interm.intermNode)->getAsBranchNode()->getFlowOp() == EOpCase || - (yyvsp[0].interm.intermNode)->getAsBranchNode()->getFlowOp() == EOpDefault)) { - parseContext.wrapupSwitchSubsequence((yyvsp[-1].interm.intermNode) ? (yyvsp[-1].interm.intermNode)->getAsAggregate() : 0, (yyvsp[0].interm.intermNode)); - (yyval.interm.intermNode) = 0; // start a fresh subsequence for what's after this case - } else - (yyval.interm.intermNode) = parseContext.intermediate.growAggregate((yyvsp[-1].interm.intermNode), (yyvsp[0].interm.intermNode)); - } -#line 9337 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 509: -#line 3313 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { (yyval.interm.intermNode) = 0; } -#line 9343 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 510: -#line 3314 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { (yyval.interm.intermNode) = static_cast((yyvsp[-1].interm.intermTypedNode)); } -#line 9349 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 511: -#line 3318 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); - } -#line 9357 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 512: -#line 3321 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.handleSelectionAttributes(*(yyvsp[-1].interm.attributes), (yyvsp[0].interm.intermNode)); - (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); - } -#line 9366 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 513: -#line 3327 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.boolCheck((yyvsp[-4].lex).loc, (yyvsp[-2].interm.intermTypedNode)); - (yyval.interm.intermNode) = parseContext.intermediate.addSelection((yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.nodePair), (yyvsp[-4].lex).loc); - } -#line 9375 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 514: -#line 3334 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.nodePair).node1 = (yyvsp[-2].interm.intermNode); - (yyval.interm.nodePair).node2 = (yyvsp[0].interm.intermNode); - } -#line 9384 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 515: -#line 3338 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.nodePair).node1 = (yyvsp[0].interm.intermNode); - (yyval.interm.nodePair).node2 = 0; - } -#line 9393 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 516: -#line 3346 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); - parseContext.boolCheck((yyvsp[0].interm.intermTypedNode)->getLoc(), (yyvsp[0].interm.intermTypedNode)); - } -#line 9402 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 517: -#line 3350 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.boolCheck((yyvsp[-2].lex).loc, (yyvsp[-3].interm.type)); - - TType type((yyvsp[-3].interm.type)); - TIntermNode* initNode = parseContext.declareVariable((yyvsp[-2].lex).loc, *(yyvsp[-2].lex).string, (yyvsp[-3].interm.type), 0, (yyvsp[0].interm.intermTypedNode)); - if (initNode) - (yyval.interm.intermTypedNode) = initNode->getAsTyped(); - else - (yyval.interm.intermTypedNode) = 0; - } -#line 9417 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 518: -#line 3363 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); - } -#line 9425 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 519: -#line 3366 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.handleSwitchAttributes(*(yyvsp[-1].interm.attributes), (yyvsp[0].interm.intermNode)); - (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); - } -#line 9434 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 520: -#line 3372 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - // start new switch sequence on the switch stack - ++parseContext.controlFlowNestingLevel; - ++parseContext.statementNestingLevel; - parseContext.switchSequenceStack.push_back(new TIntermSequence); - parseContext.switchLevel.push_back(parseContext.statementNestingLevel); - parseContext.symbolTable.push(); - } -#line 9447 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 521: -#line 3380 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.intermNode) = parseContext.addSwitch((yyvsp[-7].lex).loc, (yyvsp[-5].interm.intermTypedNode), (yyvsp[-1].interm.intermNode) ? (yyvsp[-1].interm.intermNode)->getAsAggregate() : 0); - delete parseContext.switchSequenceStack.back(); - parseContext.switchSequenceStack.pop_back(); - parseContext.switchLevel.pop_back(); - parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]); - --parseContext.statementNestingLevel; - --parseContext.controlFlowNestingLevel; - } -#line 9461 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 522: -#line 3392 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.intermNode) = 0; - } -#line 9469 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 523: -#line 3395 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); - } -#line 9477 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 524: -#line 3401 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.intermNode) = 0; - if (parseContext.switchLevel.size() == 0) - parseContext.error((yyvsp[-2].lex).loc, "cannot appear outside switch statement", "case", ""); - else if (parseContext.switchLevel.back() != parseContext.statementNestingLevel) - parseContext.error((yyvsp[-2].lex).loc, "cannot be nested inside control flow", "case", ""); - else { - parseContext.constantValueCheck((yyvsp[-1].interm.intermTypedNode), "case"); - parseContext.integerCheck((yyvsp[-1].interm.intermTypedNode), "case"); - (yyval.interm.intermNode) = parseContext.intermediate.addBranch(EOpCase, (yyvsp[-1].interm.intermTypedNode), (yyvsp[-2].lex).loc); - } - } -#line 9494 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 525: -#line 3413 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.intermNode) = 0; - if (parseContext.switchLevel.size() == 0) - parseContext.error((yyvsp[-1].lex).loc, "cannot appear outside switch statement", "default", ""); - else if (parseContext.switchLevel.back() != parseContext.statementNestingLevel) - parseContext.error((yyvsp[-1].lex).loc, "cannot be nested inside control flow", "default", ""); - else - (yyval.interm.intermNode) = parseContext.intermediate.addBranch(EOpDefault, (yyvsp[-1].lex).loc); - } -#line 9508 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 526: -#line 3425 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); - } -#line 9516 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 527: -#line 3428 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.handleLoopAttributes(*(yyvsp[-1].interm.attributes), (yyvsp[0].interm.intermNode)); - (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); - } -#line 9525 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 528: -#line 3434 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - if (! parseContext.limits.whileLoops) - parseContext.error((yyvsp[-1].lex).loc, "while loops not available", "limitation", ""); - parseContext.symbolTable.push(); - ++parseContext.loopNestingLevel; - ++parseContext.statementNestingLevel; - ++parseContext.controlFlowNestingLevel; - } -#line 9538 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 529: -#line 3442 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]); - (yyval.interm.intermNode) = parseContext.intermediate.addLoop((yyvsp[0].interm.intermNode), (yyvsp[-2].interm.intermTypedNode), 0, true, (yyvsp[-5].lex).loc); - --parseContext.loopNestingLevel; - --parseContext.statementNestingLevel; - --parseContext.controlFlowNestingLevel; - } -#line 9550 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 530: -#line 3449 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - ++parseContext.loopNestingLevel; - ++parseContext.statementNestingLevel; - ++parseContext.controlFlowNestingLevel; - } -#line 9560 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 531: -#line 3454 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - if (! parseContext.limits.whileLoops) - parseContext.error((yyvsp[-7].lex).loc, "do-while loops not available", "limitation", ""); - - parseContext.boolCheck((yyvsp[0].lex).loc, (yyvsp[-2].interm.intermTypedNode)); - - (yyval.interm.intermNode) = parseContext.intermediate.addLoop((yyvsp[-5].interm.intermNode), (yyvsp[-2].interm.intermTypedNode), 0, false, (yyvsp[-4].lex).loc); - --parseContext.loopNestingLevel; - --parseContext.statementNestingLevel; - --parseContext.controlFlowNestingLevel; - } -#line 9576 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 532: -#line 3465 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.symbolTable.push(); - ++parseContext.loopNestingLevel; - ++parseContext.statementNestingLevel; - ++parseContext.controlFlowNestingLevel; - } -#line 9587 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 533: -#line 3471 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]); - (yyval.interm.intermNode) = parseContext.intermediate.makeAggregate((yyvsp[-3].interm.intermNode), (yyvsp[-5].lex).loc); - TIntermLoop* forLoop = parseContext.intermediate.addLoop((yyvsp[0].interm.intermNode), reinterpret_cast((yyvsp[-2].interm.nodePair).node1), reinterpret_cast((yyvsp[-2].interm.nodePair).node2), true, (yyvsp[-6].lex).loc); - if (! parseContext.limits.nonInductiveForLoops) - parseContext.inductiveLoopCheck((yyvsp[-6].lex).loc, (yyvsp[-3].interm.intermNode), forLoop); - (yyval.interm.intermNode) = parseContext.intermediate.growAggregate((yyval.interm.intermNode), forLoop, (yyvsp[-6].lex).loc); - (yyval.interm.intermNode)->getAsAggregate()->setOperator(EOpSequence); - --parseContext.loopNestingLevel; - --parseContext.statementNestingLevel; - --parseContext.controlFlowNestingLevel; - } -#line 9604 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 534: -#line 3486 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); - } -#line 9612 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 535: -#line 3489 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); - } -#line 9620 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 536: -#line 3495 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); - } -#line 9628 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 537: -#line 3498 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.intermTypedNode) = 0; - } -#line 9636 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 538: -#line 3504 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.nodePair).node1 = (yyvsp[-1].interm.intermTypedNode); - (yyval.interm.nodePair).node2 = 0; - } -#line 9645 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 539: -#line 3508 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.nodePair).node1 = (yyvsp[-2].interm.intermTypedNode); - (yyval.interm.nodePair).node2 = (yyvsp[0].interm.intermTypedNode); - } -#line 9654 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 540: -#line 3515 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - if (parseContext.loopNestingLevel <= 0) - parseContext.error((yyvsp[-1].lex).loc, "continue statement only allowed in loops", "", ""); - (yyval.interm.intermNode) = parseContext.intermediate.addBranch(EOpContinue, (yyvsp[-1].lex).loc); - } -#line 9664 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 541: -#line 3520 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - if (parseContext.loopNestingLevel + parseContext.switchSequenceStack.size() <= 0) - parseContext.error((yyvsp[-1].lex).loc, "break statement only allowed in switch and loops", "", ""); - (yyval.interm.intermNode) = parseContext.intermediate.addBranch(EOpBreak, (yyvsp[-1].lex).loc); - } -#line 9674 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 542: -#line 3525 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.intermNode) = parseContext.intermediate.addBranch(EOpReturn, (yyvsp[-1].lex).loc); - if (parseContext.currentFunctionType->getBasicType() != EbtVoid) - parseContext.error((yyvsp[-1].lex).loc, "non-void function must return a value", "return", ""); - if (parseContext.inMain) - parseContext.postEntryPointReturn = true; - } -#line 9686 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 543: -#line 3532 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.intermNode) = parseContext.handleReturnValue((yyvsp[-2].lex).loc, (yyvsp[-1].interm.intermTypedNode)); - } -#line 9694 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 544: -#line 3535 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.requireStage((yyvsp[-1].lex).loc, EShLangFragment, "discard"); - (yyval.interm.intermNode) = parseContext.intermediate.addBranch(EOpKill, (yyvsp[-1].lex).loc); - } -#line 9703 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 545: -#line 3544 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); - parseContext.intermediate.setTreeRoot((yyval.interm.intermNode)); - } -#line 9712 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 546: -#line 3548 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - if ((yyvsp[0].interm.intermNode) != nullptr) { - (yyval.interm.intermNode) = parseContext.intermediate.growAggregate((yyvsp[-1].interm.intermNode), (yyvsp[0].interm.intermNode)); - parseContext.intermediate.setTreeRoot((yyval.interm.intermNode)); - } - } -#line 9723 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 547: -#line 3557 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); - } -#line 9731 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 548: -#line 3560 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); - } -#line 9739 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 549: -#line 3563 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.requireProfile((yyvsp[0].lex).loc, ~EEsProfile, "extraneous semicolon"); - parseContext.profileRequires((yyvsp[0].lex).loc, ~EEsProfile, 460, nullptr, "extraneous semicolon"); - (yyval.interm.intermNode) = nullptr; - } -#line 9749 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 550: -#line 3571 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyvsp[0].interm).function = parseContext.handleFunctionDeclarator((yyvsp[0].interm).loc, *(yyvsp[0].interm).function, false /* not prototype */); - (yyvsp[0].interm).intermNode = parseContext.handleFunctionDefinition((yyvsp[0].interm).loc, *(yyvsp[0].interm).function); - } -#line 9758 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 551: -#line 3575 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - // May be best done as post process phase on intermediate code - if (parseContext.currentFunctionType->getBasicType() != EbtVoid && ! parseContext.functionReturnsValue) - parseContext.error((yyvsp[-2].interm).loc, "function does not return a value:", "", (yyvsp[-2].interm).function->getName().c_str()); - parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]); - (yyval.interm.intermNode) = parseContext.intermediate.growAggregate((yyvsp[-2].interm).intermNode, (yyvsp[0].interm.intermNode)); - parseContext.intermediate.setAggregateOperator((yyval.interm.intermNode), EOpFunction, (yyvsp[-2].interm).function->getType(), (yyvsp[-2].interm).loc); - (yyval.interm.intermNode)->getAsAggregate()->setName((yyvsp[-2].interm).function->getMangledName().c_str()); - - // store the pragma information for debug and optimize and other vendor specific - // information. This information can be queried from the parse tree - (yyval.interm.intermNode)->getAsAggregate()->setOptimize(parseContext.contextPragma.optimize); - (yyval.interm.intermNode)->getAsAggregate()->setDebug(parseContext.contextPragma.debug); - (yyval.interm.intermNode)->getAsAggregate()->setPragmaTable(parseContext.contextPragma.pragmaTable); - } -#line 9778 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 552: -#line 3593 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.attributes) = (yyvsp[-2].interm.attributes); - parseContext.requireExtensions((yyvsp[-4].lex).loc, 1, &E_GL_EXT_control_flow_attributes, "attribute"); - } -#line 9787 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 553: -#line 3599 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.attributes) = (yyvsp[0].interm.attributes); - } -#line 9795 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 554: -#line 3602 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.attributes) = parseContext.mergeAttributes((yyvsp[-2].interm.attributes), (yyvsp[0].interm.attributes)); - } -#line 9803 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 555: -#line 3607 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.attributes) = parseContext.makeAttributes(*(yyvsp[0].lex).string); - } -#line 9811 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 556: -#line 3610 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.attributes) = parseContext.makeAttributes(*(yyvsp[-3].lex).string, (yyvsp[-1].interm.intermTypedNode)); - } -#line 9819 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - -#line 9823 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - default: break; - } - /* User semantic actions sometimes alter yychar, and that requires - that yytoken be updated with the new translation. We take the - approach of translating immediately before every use of yytoken. - One alternative is translating here after every semantic action, - but that translation would be missed if the semantic action invokes - YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or - if it invokes YYBACKUP. In the case of YYABORT or YYACCEPT, an - incorrect destructor might then be invoked immediately. In the - case of YYERROR or YYBACKUP, subsequent parser actions might lead - to an incorrect destructor call or verbose syntax error message - before the lookahead is translated. */ - YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); - - YYPOPSTACK (yylen); - yylen = 0; - YY_STACK_PRINT (yyss, yyssp); - - *++yyvsp = yyval; - - /* Now 'shift' the result of the reduction. Determine what state - that goes to, based on the state we popped back to and the rule - number reduced by. */ - - yyn = yyr1[yyn]; - - yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; - if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) - yystate = yytable[yystate]; - else - yystate = yydefgoto[yyn - YYNTOKENS]; - - goto yynewstate; - - -/*--------------------------------------. -| yyerrlab -- here on detecting error. | -`--------------------------------------*/ -yyerrlab: - /* Make sure we have latest lookahead translation. See comments at - user semantic actions for why this is necessary. */ - yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar); - - /* If not already recovering from an error, report this error. */ - if (!yyerrstatus) - { - ++yynerrs; -#if ! YYERROR_VERBOSE - yyerror (pParseContext, YY_("syntax error")); -#else -# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \ - yyssp, yytoken) - { - char const *yymsgp = YY_("syntax error"); - int yysyntax_error_status; - yysyntax_error_status = YYSYNTAX_ERROR; - if (yysyntax_error_status == 0) - yymsgp = yymsg; - else if (yysyntax_error_status == 1) - { - if (yymsg != yymsgbuf) - YYSTACK_FREE (yymsg); - yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc); - if (!yymsg) - { - yymsg = yymsgbuf; - yymsg_alloc = sizeof yymsgbuf; - yysyntax_error_status = 2; - } - else - { - yysyntax_error_status = YYSYNTAX_ERROR; - yymsgp = yymsg; - } - } - yyerror (pParseContext, yymsgp); - if (yysyntax_error_status == 2) - goto yyexhaustedlab; - } -# undef YYSYNTAX_ERROR -#endif - } - - - - if (yyerrstatus == 3) - { - /* If just tried and failed to reuse lookahead token after an - error, discard it. */ - - if (yychar <= YYEOF) - { - /* Return failure if at end of input. */ - if (yychar == YYEOF) - YYABORT; - } - else - { - yydestruct ("Error: discarding", - yytoken, &yylval, pParseContext); - yychar = YYEMPTY; - } - } - - /* Else will try to reuse lookahead token after shifting the error - token. */ - goto yyerrlab1; - - -/*---------------------------------------------------. -| yyerrorlab -- error raised explicitly by YYERROR. | -`---------------------------------------------------*/ -yyerrorlab: - - /* Pacify compilers like GCC when the user code never invokes - YYERROR and the label yyerrorlab therefore never appears in user - code. */ - if (/*CONSTCOND*/ 0) - goto yyerrorlab; - - /* Do not reclaim the symbols of the rule whose action triggered - this YYERROR. */ - YYPOPSTACK (yylen); - yylen = 0; - YY_STACK_PRINT (yyss, yyssp); - yystate = *yyssp; - goto yyerrlab1; - - -/*-------------------------------------------------------------. -| yyerrlab1 -- common code for both syntax error and YYERROR. | -`-------------------------------------------------------------*/ -yyerrlab1: - yyerrstatus = 3; /* Each real token shifted decrements this. */ - - for (;;) - { - yyn = yypact[yystate]; - if (!yypact_value_is_default (yyn)) - { - yyn += YYTERROR; - if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) - { - yyn = yytable[yyn]; - if (0 < yyn) - break; - } - } - - /* Pop the current state because it cannot handle the error token. */ - if (yyssp == yyss) - YYABORT; - - - yydestruct ("Error: popping", - yystos[yystate], yyvsp, pParseContext); - YYPOPSTACK (1); - yystate = *yyssp; - YY_STACK_PRINT (yyss, yyssp); - } - - YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN - *++yyvsp = yylval; - YY_IGNORE_MAYBE_UNINITIALIZED_END - - - /* Shift the error token. */ - YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp); - - yystate = yyn; - goto yynewstate; - - -/*-------------------------------------. -| yyacceptlab -- YYACCEPT comes here. | -`-------------------------------------*/ -yyacceptlab: - yyresult = 0; - goto yyreturn; - -/*-----------------------------------. -| yyabortlab -- YYABORT comes here. | -`-----------------------------------*/ -yyabortlab: - yyresult = 1; - goto yyreturn; - -#if !defined yyoverflow || YYERROR_VERBOSE -/*-------------------------------------------------. -| yyexhaustedlab -- memory exhaustion comes here. | -`-------------------------------------------------*/ -yyexhaustedlab: - yyerror (pParseContext, YY_("memory exhausted")); - yyresult = 2; - /* Fall through. */ -#endif - -yyreturn: - if (yychar != YYEMPTY) - { - /* Make sure we have latest lookahead translation. See comments at - user semantic actions for why this is necessary. */ - yytoken = YYTRANSLATE (yychar); - yydestruct ("Cleanup: discarding lookahead", - yytoken, &yylval, pParseContext); - } - /* Do not reclaim the symbols of the rule whose action triggered - this YYABORT or YYACCEPT. */ - YYPOPSTACK (yylen); - YY_STACK_PRINT (yyss, yyssp); - while (yyssp != yyss) - { - yydestruct ("Cleanup: popping", - yystos[*yyssp], yyvsp, pParseContext); - YYPOPSTACK (1); - } -#ifndef yyoverflow - if (yyss != yyssa) - YYSTACK_FREE (yyss); -#endif -#if YYERROR_VERBOSE - if (yymsg != yymsgbuf) - YYSTACK_FREE (yymsg); -#endif - return yyresult; -} -#line 3614 "MachineIndependent/glslang.y" /* yacc.c:1906 */ - diff --git a/External/glslang/glslang/MachineIndependent/glslang_tab.cpp.h b/External/glslang/glslang/MachineIndependent/glslang_tab.cpp.h deleted file mode 100644 index 7cfb7976..00000000 --- a/External/glslang/glslang/MachineIndependent/glslang_tab.cpp.h +++ /dev/null @@ -1,489 +0,0 @@ -/* A Bison parser, made by GNU Bison 3.0. */ - -/* Bison interface for Yacc-like parsers in C - - Copyright (C) 1984, 1989-1990, 2000-2013 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_MACHINEINDEPENDENT_GLSLANG_TAB_CPP_H_INCLUDED -# define YY_YY_MACHINEINDEPENDENT_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 - { - ATTRIBUTE = 258, - VARYING = 259, - FLOAT16_T = 260, - FLOAT = 261, - FLOAT32_T = 262, - DOUBLE = 263, - FLOAT64_T = 264, - CONST = 265, - BOOL = 266, - INT = 267, - UINT = 268, - INT64_T = 269, - UINT64_T = 270, - INT32_T = 271, - UINT32_T = 272, - INT16_T = 273, - UINT16_T = 274, - INT8_T = 275, - UINT8_T = 276, - BREAK = 277, - CONTINUE = 278, - DO = 279, - ELSE = 280, - FOR = 281, - IF = 282, - DISCARD = 283, - RETURN = 284, - SWITCH = 285, - CASE = 286, - DEFAULT = 287, - SUBROUTINE = 288, - BVEC2 = 289, - BVEC3 = 290, - BVEC4 = 291, - IVEC2 = 292, - IVEC3 = 293, - IVEC4 = 294, - UVEC2 = 295, - UVEC3 = 296, - UVEC4 = 297, - I64VEC2 = 298, - I64VEC3 = 299, - I64VEC4 = 300, - U64VEC2 = 301, - U64VEC3 = 302, - U64VEC4 = 303, - I32VEC2 = 304, - I32VEC3 = 305, - I32VEC4 = 306, - U32VEC2 = 307, - U32VEC3 = 308, - U32VEC4 = 309, - I16VEC2 = 310, - I16VEC3 = 311, - I16VEC4 = 312, - U16VEC2 = 313, - U16VEC3 = 314, - U16VEC4 = 315, - I8VEC2 = 316, - I8VEC3 = 317, - I8VEC4 = 318, - U8VEC2 = 319, - U8VEC3 = 320, - U8VEC4 = 321, - VEC2 = 322, - VEC3 = 323, - VEC4 = 324, - MAT2 = 325, - MAT3 = 326, - MAT4 = 327, - CENTROID = 328, - IN = 329, - OUT = 330, - INOUT = 331, - UNIFORM = 332, - PATCH = 333, - SAMPLE = 334, - BUFFER = 335, - SHARED = 336, - NONUNIFORM = 337, - COHERENT = 338, - VOLATILE = 339, - RESTRICT = 340, - READONLY = 341, - WRITEONLY = 342, - DVEC2 = 343, - DVEC3 = 344, - DVEC4 = 345, - DMAT2 = 346, - DMAT3 = 347, - DMAT4 = 348, - F16VEC2 = 349, - F16VEC3 = 350, - F16VEC4 = 351, - F16MAT2 = 352, - F16MAT3 = 353, - F16MAT4 = 354, - F32VEC2 = 355, - F32VEC3 = 356, - F32VEC4 = 357, - F32MAT2 = 358, - F32MAT3 = 359, - F32MAT4 = 360, - F64VEC2 = 361, - F64VEC3 = 362, - F64VEC4 = 363, - F64MAT2 = 364, - F64MAT3 = 365, - F64MAT4 = 366, - NOPERSPECTIVE = 367, - FLAT = 368, - SMOOTH = 369, - LAYOUT = 370, - __EXPLICITINTERPAMD = 371, - MAT2X2 = 372, - MAT2X3 = 373, - MAT2X4 = 374, - MAT3X2 = 375, - MAT3X3 = 376, - MAT3X4 = 377, - MAT4X2 = 378, - MAT4X3 = 379, - MAT4X4 = 380, - DMAT2X2 = 381, - DMAT2X3 = 382, - DMAT2X4 = 383, - DMAT3X2 = 384, - DMAT3X3 = 385, - DMAT3X4 = 386, - DMAT4X2 = 387, - DMAT4X3 = 388, - DMAT4X4 = 389, - F16MAT2X2 = 390, - F16MAT2X3 = 391, - F16MAT2X4 = 392, - F16MAT3X2 = 393, - F16MAT3X3 = 394, - F16MAT3X4 = 395, - F16MAT4X2 = 396, - F16MAT4X3 = 397, - F16MAT4X4 = 398, - F32MAT2X2 = 399, - F32MAT2X3 = 400, - F32MAT2X4 = 401, - F32MAT3X2 = 402, - F32MAT3X3 = 403, - F32MAT3X4 = 404, - F32MAT4X2 = 405, - F32MAT4X3 = 406, - F32MAT4X4 = 407, - F64MAT2X2 = 408, - F64MAT2X3 = 409, - F64MAT2X4 = 410, - F64MAT3X2 = 411, - F64MAT3X3 = 412, - F64MAT3X4 = 413, - F64MAT4X2 = 414, - F64MAT4X3 = 415, - F64MAT4X4 = 416, - ATOMIC_UINT = 417, - SAMPLER1D = 418, - SAMPLER2D = 419, - SAMPLER3D = 420, - SAMPLERCUBE = 421, - SAMPLER1DSHADOW = 422, - SAMPLER2DSHADOW = 423, - SAMPLERCUBESHADOW = 424, - SAMPLER1DARRAY = 425, - SAMPLER2DARRAY = 426, - SAMPLER1DARRAYSHADOW = 427, - SAMPLER2DARRAYSHADOW = 428, - ISAMPLER1D = 429, - ISAMPLER2D = 430, - ISAMPLER3D = 431, - ISAMPLERCUBE = 432, - ISAMPLER1DARRAY = 433, - ISAMPLER2DARRAY = 434, - USAMPLER1D = 435, - USAMPLER2D = 436, - USAMPLER3D = 437, - USAMPLERCUBE = 438, - USAMPLER1DARRAY = 439, - USAMPLER2DARRAY = 440, - SAMPLER2DRECT = 441, - SAMPLER2DRECTSHADOW = 442, - ISAMPLER2DRECT = 443, - USAMPLER2DRECT = 444, - SAMPLERBUFFER = 445, - ISAMPLERBUFFER = 446, - USAMPLERBUFFER = 447, - SAMPLERCUBEARRAY = 448, - SAMPLERCUBEARRAYSHADOW = 449, - ISAMPLERCUBEARRAY = 450, - USAMPLERCUBEARRAY = 451, - SAMPLER2DMS = 452, - ISAMPLER2DMS = 453, - USAMPLER2DMS = 454, - SAMPLER2DMSARRAY = 455, - ISAMPLER2DMSARRAY = 456, - USAMPLER2DMSARRAY = 457, - SAMPLEREXTERNALOES = 458, - F16SAMPLER1D = 459, - F16SAMPLER2D = 460, - F16SAMPLER3D = 461, - F16SAMPLER2DRECT = 462, - F16SAMPLERCUBE = 463, - F16SAMPLER1DARRAY = 464, - F16SAMPLER2DARRAY = 465, - F16SAMPLERCUBEARRAY = 466, - F16SAMPLERBUFFER = 467, - F16SAMPLER2DMS = 468, - F16SAMPLER2DMSARRAY = 469, - F16SAMPLER1DSHADOW = 470, - F16SAMPLER2DSHADOW = 471, - F16SAMPLER1DARRAYSHADOW = 472, - F16SAMPLER2DARRAYSHADOW = 473, - F16SAMPLER2DRECTSHADOW = 474, - F16SAMPLERCUBESHADOW = 475, - F16SAMPLERCUBEARRAYSHADOW = 476, - SAMPLER = 477, - SAMPLERSHADOW = 478, - TEXTURE1D = 479, - TEXTURE2D = 480, - TEXTURE3D = 481, - TEXTURECUBE = 482, - TEXTURE1DARRAY = 483, - TEXTURE2DARRAY = 484, - ITEXTURE1D = 485, - ITEXTURE2D = 486, - ITEXTURE3D = 487, - ITEXTURECUBE = 488, - ITEXTURE1DARRAY = 489, - ITEXTURE2DARRAY = 490, - UTEXTURE1D = 491, - UTEXTURE2D = 492, - UTEXTURE3D = 493, - UTEXTURECUBE = 494, - UTEXTURE1DARRAY = 495, - UTEXTURE2DARRAY = 496, - TEXTURE2DRECT = 497, - ITEXTURE2DRECT = 498, - UTEXTURE2DRECT = 499, - TEXTUREBUFFER = 500, - ITEXTUREBUFFER = 501, - UTEXTUREBUFFER = 502, - TEXTURECUBEARRAY = 503, - ITEXTURECUBEARRAY = 504, - UTEXTURECUBEARRAY = 505, - TEXTURE2DMS = 506, - ITEXTURE2DMS = 507, - UTEXTURE2DMS = 508, - TEXTURE2DMSARRAY = 509, - ITEXTURE2DMSARRAY = 510, - UTEXTURE2DMSARRAY = 511, - F16TEXTURE1D = 512, - F16TEXTURE2D = 513, - F16TEXTURE3D = 514, - F16TEXTURE2DRECT = 515, - F16TEXTURECUBE = 516, - F16TEXTURE1DARRAY = 517, - F16TEXTURE2DARRAY = 518, - F16TEXTURECUBEARRAY = 519, - F16TEXTUREBUFFER = 520, - F16TEXTURE2DMS = 521, - F16TEXTURE2DMSARRAY = 522, - SUBPASSINPUT = 523, - SUBPASSINPUTMS = 524, - ISUBPASSINPUT = 525, - ISUBPASSINPUTMS = 526, - USUBPASSINPUT = 527, - USUBPASSINPUTMS = 528, - F16SUBPASSINPUT = 529, - F16SUBPASSINPUTMS = 530, - IMAGE1D = 531, - IIMAGE1D = 532, - UIMAGE1D = 533, - IMAGE2D = 534, - IIMAGE2D = 535, - UIMAGE2D = 536, - IMAGE3D = 537, - IIMAGE3D = 538, - UIMAGE3D = 539, - IMAGE2DRECT = 540, - IIMAGE2DRECT = 541, - UIMAGE2DRECT = 542, - IMAGECUBE = 543, - IIMAGECUBE = 544, - UIMAGECUBE = 545, - IMAGEBUFFER = 546, - IIMAGEBUFFER = 547, - UIMAGEBUFFER = 548, - IMAGE1DARRAY = 549, - IIMAGE1DARRAY = 550, - UIMAGE1DARRAY = 551, - IMAGE2DARRAY = 552, - IIMAGE2DARRAY = 553, - UIMAGE2DARRAY = 554, - IMAGECUBEARRAY = 555, - IIMAGECUBEARRAY = 556, - UIMAGECUBEARRAY = 557, - IMAGE2DMS = 558, - IIMAGE2DMS = 559, - UIMAGE2DMS = 560, - IMAGE2DMSARRAY = 561, - IIMAGE2DMSARRAY = 562, - UIMAGE2DMSARRAY = 563, - F16IMAGE1D = 564, - F16IMAGE2D = 565, - F16IMAGE3D = 566, - F16IMAGE2DRECT = 567, - F16IMAGECUBE = 568, - F16IMAGE1DARRAY = 569, - F16IMAGE2DARRAY = 570, - F16IMAGECUBEARRAY = 571, - F16IMAGEBUFFER = 572, - F16IMAGE2DMS = 573, - F16IMAGE2DMSARRAY = 574, - STRUCT = 575, - VOID = 576, - WHILE = 577, - IDENTIFIER = 578, - TYPE_NAME = 579, - FLOATCONSTANT = 580, - DOUBLECONSTANT = 581, - INT16CONSTANT = 582, - UINT16CONSTANT = 583, - INT32CONSTANT = 584, - UINT32CONSTANT = 585, - INTCONSTANT = 586, - UINTCONSTANT = 587, - INT64CONSTANT = 588, - UINT64CONSTANT = 589, - BOOLCONSTANT = 590, - FLOAT16CONSTANT = 591, - LEFT_OP = 592, - RIGHT_OP = 593, - INC_OP = 594, - DEC_OP = 595, - LE_OP = 596, - GE_OP = 597, - EQ_OP = 598, - NE_OP = 599, - AND_OP = 600, - OR_OP = 601, - XOR_OP = 602, - MUL_ASSIGN = 603, - DIV_ASSIGN = 604, - ADD_ASSIGN = 605, - MOD_ASSIGN = 606, - LEFT_ASSIGN = 607, - RIGHT_ASSIGN = 608, - AND_ASSIGN = 609, - XOR_ASSIGN = 610, - OR_ASSIGN = 611, - SUB_ASSIGN = 612, - LEFT_PAREN = 613, - RIGHT_PAREN = 614, - LEFT_BRACKET = 615, - RIGHT_BRACKET = 616, - LEFT_BRACE = 617, - RIGHT_BRACE = 618, - DOT = 619, - COMMA = 620, - COLON = 621, - EQUAL = 622, - SEMICOLON = 623, - BANG = 624, - DASH = 625, - TILDE = 626, - PLUS = 627, - STAR = 628, - SLASH = 629, - PERCENT = 630, - LEFT_ANGLE = 631, - RIGHT_ANGLE = 632, - VERTICAL_BAR = 633, - CARET = 634, - AMPERSAND = 635, - QUESTION = 636, - INVARIANT = 637, - PRECISE = 638, - HIGH_PRECISION = 639, - MEDIUM_PRECISION = 640, - LOW_PRECISION = 641, - PRECISION = 642, - PACKED = 643, - RESOURCE = 644, - SUPERP = 645 - }; -#endif - -/* Value type. */ -#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED -typedef union YYSTYPE YYSTYPE; -union YYSTYPE -{ -#line 70 "MachineIndependent/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; - }; - } interm; - -#line 480 "MachineIndependent/glslang_tab.cpp.h" /* yacc.c:1909 */ -}; -# define YYSTYPE_IS_TRIVIAL 1 -# define YYSTYPE_IS_DECLARED 1 -#endif - - - -int yyparse (glslang::TParseContext* pParseContext); - -#endif /* !YY_YY_MACHINEINDEPENDENT_GLSLANG_TAB_CPP_H_INCLUDED */ diff --git a/External/glslang/glslang/MachineIndependent/intermOut.cpp b/External/glslang/glslang/MachineIndependent/intermOut.cpp deleted file mode 100644 index 4d6ad040..00000000 --- a/External/glslang/glslang/MachineIndependent/intermOut.cpp +++ /dev/null @@ -1,1424 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// Copyright (C) 2012-2016 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. -// - -#include "localintermediate.h" -#include "../Include/InfoSink.h" - -#ifdef _MSC_VER -#include -#else -#include -#endif - -namespace { - -bool IsInfinity(double x) { -#ifdef _MSC_VER - switch (_fpclass(x)) { - case _FPCLASS_NINF: - case _FPCLASS_PINF: - return true; - default: - return false; - } -#else - return std::isinf(x); -#endif -} - -bool IsNan(double x) { -#ifdef _MSC_VER - switch (_fpclass(x)) { - case _FPCLASS_SNAN: - case _FPCLASS_QNAN: - return true; - default: - return false; - } -#else - return std::isnan(x); -#endif -} - -} - -namespace glslang { - -// -// Two purposes: -// 1. Show an example of how to iterate tree. Functions can -// also directly call Traverse() on children themselves to -// have finer grained control over the process than shown here. -// See the last function for how to get started. -// 2. Print out a text based description of the tree. -// - -// -// Use this class to carry along data from node to node in -// the traversal -// -class TOutputTraverser : public TIntermTraverser { -public: - TOutputTraverser(TInfoSink& i) : infoSink(i) { } - - virtual bool visitBinary(TVisit, TIntermBinary* node); - virtual bool visitUnary(TVisit, TIntermUnary* node); - virtual bool visitAggregate(TVisit, TIntermAggregate* node); - virtual bool visitSelection(TVisit, TIntermSelection* node); - virtual void visitConstantUnion(TIntermConstantUnion* node); - virtual void visitSymbol(TIntermSymbol* node); - virtual bool visitLoop(TVisit, TIntermLoop* node); - virtual bool visitBranch(TVisit, TIntermBranch* node); - virtual bool visitSwitch(TVisit, TIntermSwitch* node); - - TInfoSink& infoSink; -protected: - TOutputTraverser(TOutputTraverser&); - TOutputTraverser& operator=(TOutputTraverser&); -}; - -// -// Helper functions for printing, not part of traversing. -// - -static void OutputTreeText(TInfoSink& infoSink, const TIntermNode* node, const int depth) -{ - int i; - - infoSink.debug << node->getLoc().string << ":"; - if (node->getLoc().line) - infoSink.debug << node->getLoc().line; - else - infoSink.debug << "? "; - - for (i = 0; i < depth; ++i) - infoSink.debug << " "; -} - -// -// The rest of the file are the traversal functions. The last one -// is the one that starts the traversal. -// -// Return true from interior nodes to have the external traversal -// continue on to children. If you process children yourself, -// return false. -// - -bool TOutputTraverser::visitBinary(TVisit /* visit */, TIntermBinary* node) -{ - TInfoSink& out = infoSink; - - OutputTreeText(out, node, depth); - - switch (node->getOp()) { - case EOpAssign: out.debug << "move second child to first child"; break; - case EOpAddAssign: out.debug << "add second child into first child"; break; - case EOpSubAssign: out.debug << "subtract second child into first child"; break; - case EOpMulAssign: out.debug << "multiply second child into first child"; break; - case EOpVectorTimesMatrixAssign: out.debug << "matrix mult second child into first child"; break; - case EOpVectorTimesScalarAssign: out.debug << "vector scale second child into first child"; break; - case EOpMatrixTimesScalarAssign: out.debug << "matrix scale second child into first child"; break; - case EOpMatrixTimesMatrixAssign: out.debug << "matrix mult second child into first child"; break; - case EOpDivAssign: out.debug << "divide second child into first child"; break; - case EOpModAssign: out.debug << "mod second child into first child"; break; - case EOpAndAssign: out.debug << "and second child into first child"; break; - case EOpInclusiveOrAssign: out.debug << "or second child into first child"; break; - case EOpExclusiveOrAssign: out.debug << "exclusive or second child into first child"; break; - case EOpLeftShiftAssign: out.debug << "left shift second child into first child"; break; - case EOpRightShiftAssign: out.debug << "right shift second child into first child"; break; - - case EOpIndexDirect: out.debug << "direct index"; break; - case EOpIndexIndirect: out.debug << "indirect index"; break; - case EOpIndexDirectStruct: - out.debug << (*node->getLeft()->getType().getStruct())[node->getRight()->getAsConstantUnion()->getConstArray()[0].getIConst()].type->getFieldName(); - out.debug << ": direct index for structure"; break; - case EOpVectorSwizzle: out.debug << "vector swizzle"; break; - case EOpMatrixSwizzle: out.debug << "matrix swizzle"; break; - - case EOpAdd: out.debug << "add"; break; - case EOpSub: out.debug << "subtract"; break; - case EOpMul: out.debug << "component-wise multiply"; break; - case EOpDiv: out.debug << "divide"; break; - case EOpMod: out.debug << "mod"; break; - case EOpRightShift: out.debug << "right-shift"; break; - case EOpLeftShift: out.debug << "left-shift"; break; - case EOpAnd: out.debug << "bitwise and"; break; - case EOpInclusiveOr: out.debug << "inclusive-or"; break; - case EOpExclusiveOr: out.debug << "exclusive-or"; break; - case EOpEqual: out.debug << "Compare Equal"; break; - case EOpNotEqual: out.debug << "Compare Not Equal"; break; - case EOpLessThan: out.debug << "Compare Less Than"; break; - case EOpGreaterThan: out.debug << "Compare Greater Than"; break; - case EOpLessThanEqual: out.debug << "Compare Less Than or Equal"; break; - case EOpGreaterThanEqual: out.debug << "Compare Greater Than or Equal"; break; - case EOpVectorEqual: out.debug << "Equal"; break; - case EOpVectorNotEqual: out.debug << "NotEqual"; break; - - case EOpVectorTimesScalar: out.debug << "vector-scale"; break; - case EOpVectorTimesMatrix: out.debug << "vector-times-matrix"; break; - case EOpMatrixTimesVector: out.debug << "matrix-times-vector"; break; - case EOpMatrixTimesScalar: out.debug << "matrix-scale"; break; - case EOpMatrixTimesMatrix: out.debug << "matrix-multiply"; break; - - case EOpLogicalOr: out.debug << "logical-or"; break; - case EOpLogicalXor: out.debug << "logical-xor"; break; - case EOpLogicalAnd: out.debug << "logical-and"; break; - - default: out.debug << ""; - } - - out.debug << " (" << node->getCompleteString() << ")"; - - out.debug << "\n"; - - return true; -} - -bool TOutputTraverser::visitUnary(TVisit /* visit */, TIntermUnary* node) -{ - TInfoSink& out = infoSink; - - OutputTreeText(out, node, depth); - - switch (node->getOp()) { - case EOpNegative: out.debug << "Negate value"; break; - case EOpVectorLogicalNot: - case EOpLogicalNot: out.debug << "Negate conditional"; break; - case EOpBitwiseNot: out.debug << "Bitwise not"; break; - - case EOpPostIncrement: out.debug << "Post-Increment"; break; - case EOpPostDecrement: out.debug << "Post-Decrement"; break; - case EOpPreIncrement: out.debug << "Pre-Increment"; break; - case EOpPreDecrement: out.debug << "Pre-Decrement"; break; - - // * -> bool - case EOpConvInt8ToBool: out.debug << "Convert int8_t to bool"; break; - case EOpConvUint8ToBool: out.debug << "Convert uint8_t to bool"; break; - case EOpConvInt16ToBool: out.debug << "Convert int16_t to bool"; break; - case EOpConvUint16ToBool: out.debug << "Convert uint16_t to bool";break; - case EOpConvIntToBool: out.debug << "Convert int to bool"; break; - case EOpConvUintToBool: out.debug << "Convert uint to bool"; break; - case EOpConvInt64ToBool: out.debug << "Convert int64 to bool"; break; - case EOpConvUint64ToBool: out.debug << "Convert uint64 to bool"; break; - case EOpConvFloat16ToBool: out.debug << "Convert float16_t to bool"; break; - case EOpConvFloatToBool: out.debug << "Convert float to bool"; break; - case EOpConvDoubleToBool: out.debug << "Convert double to bool"; break; - - // bool -> * - case EOpConvBoolToInt8: out.debug << "Convert bool to int8_t"; break; - case EOpConvBoolToUint8: out.debug << "Convert bool to uint8_t"; break; - case EOpConvBoolToInt16: out.debug << "Convert bool to in16t_t"; break; - case EOpConvBoolToUint16: out.debug << "Convert bool to uint16_t";break; - case EOpConvBoolToInt: out.debug << "Convert bool to int" ; break; - case EOpConvBoolToUint: out.debug << "Convert bool to uint"; break; - case EOpConvBoolToInt64: out.debug << "Convert bool to int64"; break; - case EOpConvBoolToUint64: out.debug << "Convert bool to uint64";break; - case EOpConvBoolToFloat16: out.debug << "Convert bool to float16_t"; break; - case EOpConvBoolToFloat: out.debug << "Convert bool to float"; break; - case EOpConvBoolToDouble: out.debug << "Convert bool to double"; break; - - // int8_t -> (u)int* - case EOpConvInt8ToInt16: out.debug << "Convert int8_t to int16_t";break; - case EOpConvInt8ToInt: out.debug << "Convert int8_t to int"; break; - case EOpConvInt8ToInt64: out.debug << "Convert int8_t to int64"; break; - case EOpConvInt8ToUint8: out.debug << "Convert int8_t to uint8_t";break; - case EOpConvInt8ToUint16: out.debug << "Convert int8_t to uint16_t";break; - case EOpConvInt8ToUint: out.debug << "Convert int8_t to uint"; break; - case EOpConvInt8ToUint64: out.debug << "Convert int8_t to uint64"; break; - - // uint8_t -> (u)int* - case EOpConvUint8ToInt8: out.debug << "Convert uint8_t to int8_t";break; - case EOpConvUint8ToInt16: out.debug << "Convert uint8_t to int16_t";break; - case EOpConvUint8ToInt: out.debug << "Convert uint8_t to int"; break; - case EOpConvUint8ToInt64: out.debug << "Convert uint8_t to int64"; break; - case EOpConvUint8ToUint16: out.debug << "Convert uint8_t to uint16_t";break; - case EOpConvUint8ToUint: out.debug << "Convert uint8_t to uint"; break; - case EOpConvUint8ToUint64: out.debug << "Convert uint8_t to uint64"; break; - - // int8_t -> float* - case EOpConvInt8ToFloat16: out.debug << "Convert int8_t to float16_t";break; - case EOpConvInt8ToFloat: out.debug << "Convert int8_t to float"; break; - case EOpConvInt8ToDouble: out.debug << "Convert int8_t to double"; break; - - // uint8_t -> float* - case EOpConvUint8ToFloat16: out.debug << "Convert uint8_t to float16_t";break; - case EOpConvUint8ToFloat: out.debug << "Convert uint8_t to float"; break; - case EOpConvUint8ToDouble: out.debug << "Convert uint8_t to double"; break; - - // int16_t -> (u)int* - case EOpConvInt16ToInt8: out.debug << "Convert int16_t to int8_t";break; - case EOpConvInt16ToInt: out.debug << "Convert int16_t to int"; break; - case EOpConvInt16ToInt64: out.debug << "Convert int16_t to int64"; break; - case EOpConvInt16ToUint8: out.debug << "Convert int16_t to uint8_t";break; - case EOpConvInt16ToUint16: out.debug << "Convert int16_t to uint16_t";break; - case EOpConvInt16ToUint: out.debug << "Convert int16_t to uint"; break; - case EOpConvInt16ToUint64: out.debug << "Convert int16_t to uint64"; break; - - // int16_t -> float* - case EOpConvInt16ToFloat16: out.debug << "Convert int16_t to float16_t";break; - case EOpConvInt16ToFloat: out.debug << "Convert int16_t to float"; break; - case EOpConvInt16ToDouble: out.debug << "Convert int16_t to double"; break; - - // uint16_t -> (u)int* - case EOpConvUint16ToInt8: out.debug << "Convert uint16_t to int8_t";break; - case EOpConvUint16ToInt16: out.debug << "Convert uint16_t to int16_t";break; - case EOpConvUint16ToInt: out.debug << "Convert uint16_t to int"; break; - case EOpConvUint16ToInt64: out.debug << "Convert uint16_t to int64"; break; - case EOpConvUint16ToUint8: out.debug << "Convert uint16_t to uint8_t";break; - case EOpConvUint16ToUint: out.debug << "Convert uint16_t to uint"; break; - case EOpConvUint16ToUint64: out.debug << "Convert uint16_t to uint64"; break; - - // uint16_t -> float* - case EOpConvUint16ToFloat16: out.debug << "Convert uint16_t to float16_t";break; - case EOpConvUint16ToFloat: out.debug << "Convert uint16_t to float"; break; - case EOpConvUint16ToDouble: out.debug << "Convert uint16_t to double"; break; - - // int32_t -> (u)int* - case EOpConvIntToInt8: out.debug << "Convert int to int8_t";break; - case EOpConvIntToInt16: out.debug << "Convert int to int16_t";break; - case EOpConvIntToInt64: out.debug << "Convert int to int64"; break; - case EOpConvIntToUint8: out.debug << "Convert int to uint8_t";break; - case EOpConvIntToUint16: out.debug << "Convert int to uint16_t";break; - case EOpConvIntToUint: out.debug << "Convert int to uint"; break; - case EOpConvIntToUint64: out.debug << "Convert int to uint64"; break; - - // int32_t -> float* - case EOpConvIntToFloat16: out.debug << "Convert int to float16_t";break; - case EOpConvIntToFloat: out.debug << "Convert int to float"; break; - case EOpConvIntToDouble: out.debug << "Convert int to double"; break; - - // uint32_t -> (u)int* - case EOpConvUintToInt8: out.debug << "Convert uint to int8_t";break; - case EOpConvUintToInt16: out.debug << "Convert uint to int16_t";break; - case EOpConvUintToInt: out.debug << "Convert uint to int";break; - case EOpConvUintToInt64: out.debug << "Convert uint to int64"; break; - case EOpConvUintToUint8: out.debug << "Convert uint to uint8_t";break; - case EOpConvUintToUint16: out.debug << "Convert uint to uint16_t";break; - case EOpConvUintToUint64: out.debug << "Convert uint to uint64"; break; - - // uint32_t -> float* - case EOpConvUintToFloat16: out.debug << "Convert uint to float16_t";break; - case EOpConvUintToFloat: out.debug << "Convert uint to float"; break; - case EOpConvUintToDouble: out.debug << "Convert uint to double"; break; - - // int64 -> (u)int* - case EOpConvInt64ToInt8: out.debug << "Convert int64 to int8_t"; break; - case EOpConvInt64ToInt16: out.debug << "Convert int64 to int16_t"; break; - case EOpConvInt64ToInt: out.debug << "Convert int64 to int"; break; - case EOpConvInt64ToUint8: out.debug << "Convert int64 to uint8_t";break; - case EOpConvInt64ToUint16: out.debug << "Convert int64 to uint16_t";break; - case EOpConvInt64ToUint: out.debug << "Convert int64 to uint"; break; - case EOpConvInt64ToUint64: out.debug << "Convert int64 to uint64"; break; - - // int64 -> float* - case EOpConvInt64ToFloat16: out.debug << "Convert int64 to float16_t";break; - case EOpConvInt64ToFloat: out.debug << "Convert int64 to float"; break; - case EOpConvInt64ToDouble: out.debug << "Convert int64 to double"; break; - - // uint64 -> (u)int* - case EOpConvUint64ToInt8: out.debug << "Convert uint64 to int8_t";break; - case EOpConvUint64ToInt16: out.debug << "Convert uint64 to int16_t";break; - case EOpConvUint64ToInt: out.debug << "Convert uint64 to int"; break; - case EOpConvUint64ToInt64: out.debug << "Convert uint64 to int64"; break; - case EOpConvUint64ToUint8: out.debug << "Convert uint64 to uint8_t";break; - case EOpConvUint64ToUint16: out.debug << "Convert uint64 to uint16"; break; - case EOpConvUint64ToUint: out.debug << "Convert uint64 to uint"; break; - - // uint64 -> float* - case EOpConvUint64ToFloat16: out.debug << "Convert uint64 to float16_t";break; - case EOpConvUint64ToFloat: out.debug << "Convert uint64 to float"; break; - case EOpConvUint64ToDouble: out.debug << "Convert uint64 to double"; break; - - // float16_t -> int* - case EOpConvFloat16ToInt8: out.debug << "Convert float16_t to int8_t"; break; - case EOpConvFloat16ToInt16: out.debug << "Convert float16_t to int16_t"; break; - case EOpConvFloat16ToInt: out.debug << "Convert float16_t to int"; break; - case EOpConvFloat16ToInt64: out.debug << "Convert float16_t to int64"; break; - - // float16_t -> uint* - case EOpConvFloat16ToUint8: out.debug << "Convert float16_t to uint8_t"; break; - case EOpConvFloat16ToUint16: out.debug << "Convert float16_t to uint16_t"; break; - case EOpConvFloat16ToUint: out.debug << "Convert float16_t to uint"; break; - case EOpConvFloat16ToUint64: out.debug << "Convert float16_t to uint64"; break; - - // float16_t -> float* - case EOpConvFloat16ToFloat: out.debug << "Convert float16_t to float"; break; - case EOpConvFloat16ToDouble: out.debug << "Convert float16_t to double"; break; - - // float32 -> float* - case EOpConvFloatToFloat16: out.debug << "Convert float to float16_t"; break; - case EOpConvFloatToDouble: out.debug << "Convert float to double"; break; - - // float32_t -> int* - case EOpConvFloatToInt8: out.debug << "Convert float to int8_t"; break; - case EOpConvFloatToInt16: out.debug << "Convert float to int16_t"; break; - case EOpConvFloatToInt: out.debug << "Convert float to int"; break; - case EOpConvFloatToInt64: out.debug << "Convert float to int64"; break; - - // float32_t -> uint* - case EOpConvFloatToUint8: out.debug << "Convert float to uint8_t"; break; - case EOpConvFloatToUint16: out.debug << "Convert float to uint16_t"; break; - case EOpConvFloatToUint: out.debug << "Convert float to uint"; break; - case EOpConvFloatToUint64: out.debug << "Convert float to uint64"; break; - - // double -> float* - case EOpConvDoubleToFloat16: out.debug << "Convert double to float16_t"; break; - case EOpConvDoubleToFloat: out.debug << "Convert double to float"; break; - - // double -> int* - case EOpConvDoubleToInt8: out.debug << "Convert double to int8_t"; break; - case EOpConvDoubleToInt16: out.debug << "Convert double to int16_t"; break; - case EOpConvDoubleToInt: out.debug << "Convert double to int"; break; - case EOpConvDoubleToInt64: out.debug << "Convert double to int64"; break; - - // float32_t -> uint* - case EOpConvDoubleToUint8: out.debug << "Convert double to uint8_t"; break; - case EOpConvDoubleToUint16: out.debug << "Convert double to uint16_t"; break; - case EOpConvDoubleToUint: out.debug << "Convert double to uint"; break; - case EOpConvDoubleToUint64: out.debug << "Convert double to uint64"; break; - - - case EOpRadians: out.debug << "radians"; break; - case EOpDegrees: out.debug << "degrees"; break; - case EOpSin: out.debug << "sine"; break; - case EOpCos: out.debug << "cosine"; break; - case EOpTan: out.debug << "tangent"; break; - case EOpAsin: out.debug << "arc sine"; break; - case EOpAcos: out.debug << "arc cosine"; break; - case EOpAtan: out.debug << "arc tangent"; break; - case EOpSinh: out.debug << "hyp. sine"; break; - case EOpCosh: out.debug << "hyp. cosine"; break; - case EOpTanh: out.debug << "hyp. tangent"; break; - case EOpAsinh: out.debug << "arc hyp. sine"; break; - case EOpAcosh: out.debug << "arc hyp. cosine"; break; - case EOpAtanh: out.debug << "arc hyp. tangent"; break; - - case EOpExp: out.debug << "exp"; break; - case EOpLog: out.debug << "log"; break; - case EOpExp2: out.debug << "exp2"; break; - case EOpLog2: out.debug << "log2"; break; - case EOpSqrt: out.debug << "sqrt"; break; - case EOpInverseSqrt: out.debug << "inverse sqrt"; break; - - case EOpAbs: out.debug << "Absolute value"; break; - case EOpSign: out.debug << "Sign"; break; - case EOpFloor: out.debug << "Floor"; break; - case EOpTrunc: out.debug << "trunc"; break; - case EOpRound: out.debug << "round"; break; - case EOpRoundEven: out.debug << "roundEven"; break; - case EOpCeil: out.debug << "Ceiling"; break; - case EOpFract: out.debug << "Fraction"; break; - - case EOpIsNan: out.debug << "isnan"; break; - case EOpIsInf: out.debug << "isinf"; break; - - case EOpFloatBitsToInt: out.debug << "floatBitsToInt"; break; - case EOpFloatBitsToUint:out.debug << "floatBitsToUint"; break; - case EOpIntBitsToFloat: out.debug << "intBitsToFloat"; break; - case EOpUintBitsToFloat:out.debug << "uintBitsToFloat"; break; - case EOpDoubleBitsToInt64: out.debug << "doubleBitsToInt64"; break; - case EOpDoubleBitsToUint64: out.debug << "doubleBitsToUint64"; break; - case EOpInt64BitsToDouble: out.debug << "int64BitsToDouble"; break; - case EOpUint64BitsToDouble: out.debug << "uint64BitsToDouble"; break; - case EOpFloat16BitsToInt16: out.debug << "float16BitsToInt16"; break; - case EOpFloat16BitsToUint16: out.debug << "float16BitsToUint16"; break; - case EOpInt16BitsToFloat16: out.debug << "int16BitsToFloat16"; break; - case EOpUint16BitsToFloat16: out.debug << "uint16BitsToFloat16"; break; - - case EOpPackSnorm2x16: out.debug << "packSnorm2x16"; break; - case EOpUnpackSnorm2x16:out.debug << "unpackSnorm2x16"; break; - case EOpPackUnorm2x16: out.debug << "packUnorm2x16"; break; - case EOpUnpackUnorm2x16:out.debug << "unpackUnorm2x16"; break; - case EOpPackHalf2x16: out.debug << "packHalf2x16"; break; - case EOpUnpackHalf2x16: out.debug << "unpackHalf2x16"; break; - case EOpPack16: out.debug << "pack16"; break; - case EOpPack32: out.debug << "pack32"; break; - case EOpPack64: out.debug << "pack64"; break; - case EOpUnpack32: out.debug << "unpack32"; break; - case EOpUnpack16: out.debug << "unpack16"; break; - case EOpUnpack8: out.debug << "unpack8"; break; - - case EOpPackSnorm4x8: out.debug << "PackSnorm4x8"; break; - case EOpUnpackSnorm4x8: out.debug << "UnpackSnorm4x8"; break; - case EOpPackUnorm4x8: out.debug << "PackUnorm4x8"; break; - case EOpUnpackUnorm4x8: out.debug << "UnpackUnorm4x8"; break; - case EOpPackDouble2x32: out.debug << "PackDouble2x32"; break; - case EOpUnpackDouble2x32: out.debug << "UnpackDouble2x32"; break; - - case EOpPackInt2x32: out.debug << "packInt2x32"; break; - case EOpUnpackInt2x32: out.debug << "unpackInt2x32"; break; - case EOpPackUint2x32: out.debug << "packUint2x32"; break; - case EOpUnpackUint2x32: out.debug << "unpackUint2x32"; break; - - case EOpPackInt2x16: out.debug << "packInt2x16"; break; - case EOpUnpackInt2x16: out.debug << "unpackInt2x16"; break; - case EOpPackUint2x16: out.debug << "packUint2x16"; break; - case EOpUnpackUint2x16: out.debug << "unpackUint2x16"; break; - - case EOpPackInt4x16: out.debug << "packInt4x16"; break; - case EOpUnpackInt4x16: out.debug << "unpackInt4x16"; break; - case EOpPackUint4x16: out.debug << "packUint4x16"; break; - case EOpUnpackUint4x16: out.debug << "unpackUint4x16"; break; - case EOpPackFloat2x16: out.debug << "packFloat2x16"; break; - case EOpUnpackFloat2x16: out.debug << "unpackFloat2x16"; break; - - case EOpLength: out.debug << "length"; break; - case EOpNormalize: out.debug << "normalize"; break; - case EOpDPdx: out.debug << "dPdx"; break; - case EOpDPdy: out.debug << "dPdy"; break; - case EOpFwidth: out.debug << "fwidth"; break; - case EOpDPdxFine: out.debug << "dPdxFine"; break; - case EOpDPdyFine: out.debug << "dPdyFine"; break; - case EOpFwidthFine: out.debug << "fwidthFine"; break; - case EOpDPdxCoarse: out.debug << "dPdxCoarse"; break; - case EOpDPdyCoarse: out.debug << "dPdyCoarse"; break; - case EOpFwidthCoarse: out.debug << "fwidthCoarse"; break; - - case EOpInterpolateAtCentroid: out.debug << "interpolateAtCentroid"; break; - - case EOpDeterminant: out.debug << "determinant"; break; - case EOpMatrixInverse: out.debug << "inverse"; break; - case EOpTranspose: out.debug << "transpose"; break; - - case EOpAny: out.debug << "any"; break; - case EOpAll: out.debug << "all"; break; - - case EOpArrayLength: out.debug << "array length"; break; - - case EOpEmitStreamVertex: out.debug << "EmitStreamVertex"; break; - case EOpEndStreamPrimitive: out.debug << "EndStreamPrimitive"; break; - - case EOpAtomicCounterIncrement: out.debug << "AtomicCounterIncrement";break; - case EOpAtomicCounterDecrement: out.debug << "AtomicCounterDecrement";break; - case EOpAtomicCounter: out.debug << "AtomicCounter"; break; - - case EOpTextureQuerySize: out.debug << "textureSize"; break; - case EOpTextureQueryLod: out.debug << "textureQueryLod"; break; - case EOpTextureQueryLevels: out.debug << "textureQueryLevels"; break; - case EOpTextureQuerySamples: out.debug << "textureSamples"; break; - case EOpImageQuerySize: out.debug << "imageQuerySize"; break; - case EOpImageQuerySamples: out.debug << "imageQuerySamples"; break; - case EOpImageLoad: out.debug << "imageLoad"; break; - - case EOpBitFieldReverse: out.debug << "bitFieldReverse"; break; - case EOpBitCount: out.debug << "bitCount"; break; - case EOpFindLSB: out.debug << "findLSB"; break; - case EOpFindMSB: out.debug << "findMSB"; break; - - case EOpNoise: out.debug << "noise"; break; - - case EOpBallot: out.debug << "ballot"; break; - case EOpReadFirstInvocation: out.debug << "readFirstInvocation"; break; - - case EOpAnyInvocation: out.debug << "anyInvocation"; break; - case EOpAllInvocations: out.debug << "allInvocations"; break; - case EOpAllInvocationsEqual: out.debug << "allInvocationsEqual"; break; - - case EOpSubgroupElect: out.debug << "subgroupElect"; break; - case EOpSubgroupAll: out.debug << "subgroupAll"; break; - case EOpSubgroupAny: out.debug << "subgroupAny"; break; - case EOpSubgroupAllEqual: out.debug << "subgroupAllEqual"; break; - case EOpSubgroupBroadcast: out.debug << "subgroupBroadcast"; break; - case EOpSubgroupBroadcastFirst: out.debug << "subgroupBroadcastFirst"; break; - case EOpSubgroupBallot: out.debug << "subgroupBallot"; break; - case EOpSubgroupInverseBallot: out.debug << "subgroupInverseBallot"; break; - case EOpSubgroupBallotBitExtract: out.debug << "subgroupBallotBitExtract"; break; - case EOpSubgroupBallotBitCount: out.debug << "subgroupBallotBitCount"; break; - case EOpSubgroupBallotInclusiveBitCount: out.debug << "subgroupBallotInclusiveBitCount"; break; - case EOpSubgroupBallotExclusiveBitCount: out.debug << "subgroupBallotExclusiveBitCount"; break; - case EOpSubgroupBallotFindLSB: out.debug << "subgroupBallotFindLSB"; break; - case EOpSubgroupBallotFindMSB: out.debug << "subgroupBallotFindMSB"; break; - case EOpSubgroupShuffle: out.debug << "subgroupShuffle"; break; - case EOpSubgroupShuffleXor: out.debug << "subgroupShuffleXor"; break; - case EOpSubgroupShuffleUp: out.debug << "subgroupShuffleUp"; break; - case EOpSubgroupShuffleDown: out.debug << "subgroupShuffleDown"; break; - case EOpSubgroupAdd: out.debug << "subgroupAdd"; break; - case EOpSubgroupMul: out.debug << "subgroupMul"; break; - case EOpSubgroupMin: out.debug << "subgroupMin"; break; - case EOpSubgroupMax: out.debug << "subgroupMax"; break; - case EOpSubgroupAnd: out.debug << "subgroupAnd"; break; - case EOpSubgroupOr: out.debug << "subgroupOr"; break; - case EOpSubgroupXor: out.debug << "subgroupXor"; break; - case EOpSubgroupInclusiveAdd: out.debug << "subgroupInclusiveAdd"; break; - case EOpSubgroupInclusiveMul: out.debug << "subgroupInclusiveMul"; break; - case EOpSubgroupInclusiveMin: out.debug << "subgroupInclusiveMin"; break; - case EOpSubgroupInclusiveMax: out.debug << "subgroupInclusiveMax"; break; - case EOpSubgroupInclusiveAnd: out.debug << "subgroupInclusiveAnd"; break; - case EOpSubgroupInclusiveOr: out.debug << "subgroupInclusiveOr"; break; - case EOpSubgroupInclusiveXor: out.debug << "subgroupInclusiveXor"; break; - case EOpSubgroupExclusiveAdd: out.debug << "subgroupExclusiveAdd"; break; - case EOpSubgroupExclusiveMul: out.debug << "subgroupExclusiveMul"; break; - case EOpSubgroupExclusiveMin: out.debug << "subgroupExclusiveMin"; break; - case EOpSubgroupExclusiveMax: out.debug << "subgroupExclusiveMax"; break; - case EOpSubgroupExclusiveAnd: out.debug << "subgroupExclusiveAnd"; break; - case EOpSubgroupExclusiveOr: out.debug << "subgroupExclusiveOr"; break; - case EOpSubgroupExclusiveXor: out.debug << "subgroupExclusiveXor"; break; - case EOpSubgroupClusteredAdd: out.debug << "subgroupClusteredAdd"; break; - case EOpSubgroupClusteredMul: out.debug << "subgroupClusteredMul"; break; - case EOpSubgroupClusteredMin: out.debug << "subgroupClusteredMin"; break; - case EOpSubgroupClusteredMax: out.debug << "subgroupClusteredMax"; break; - case EOpSubgroupClusteredAnd: out.debug << "subgroupClusteredAnd"; break; - case EOpSubgroupClusteredOr: out.debug << "subgroupClusteredOr"; break; - case EOpSubgroupClusteredXor: out.debug << "subgroupClusteredXor"; break; - case EOpSubgroupQuadBroadcast: out.debug << "subgroupQuadBroadcast"; break; - case EOpSubgroupQuadSwapHorizontal: out.debug << "subgroupQuadSwapHorizontal"; break; - case EOpSubgroupQuadSwapVertical: out.debug << "subgroupQuadSwapVertical"; break; - case EOpSubgroupQuadSwapDiagonal: out.debug << "subgroupQuadSwapDiagonal"; break; - -#ifdef NV_EXTENSIONS - case EOpSubgroupPartition: out.debug << "subgroupPartitionNV"; break; - case EOpSubgroupPartitionedAdd: out.debug << "subgroupPartitionedAddNV"; break; - case EOpSubgroupPartitionedMul: out.debug << "subgroupPartitionedMulNV"; break; - case EOpSubgroupPartitionedMin: out.debug << "subgroupPartitionedMinNV"; break; - case EOpSubgroupPartitionedMax: out.debug << "subgroupPartitionedMaxNV"; break; - case EOpSubgroupPartitionedAnd: out.debug << "subgroupPartitionedAndNV"; break; - case EOpSubgroupPartitionedOr: out.debug << "subgroupPartitionedOrNV"; break; - case EOpSubgroupPartitionedXor: out.debug << "subgroupPartitionedXorNV"; break; - case EOpSubgroupPartitionedInclusiveAdd: out.debug << "subgroupPartitionedInclusiveAddNV"; break; - case EOpSubgroupPartitionedInclusiveMul: out.debug << "subgroupPartitionedInclusiveMulNV"; break; - case EOpSubgroupPartitionedInclusiveMin: out.debug << "subgroupPartitionedInclusiveMinNV"; break; - case EOpSubgroupPartitionedInclusiveMax: out.debug << "subgroupPartitionedInclusiveMaxNV"; break; - case EOpSubgroupPartitionedInclusiveAnd: out.debug << "subgroupPartitionedInclusiveAndNV"; break; - case EOpSubgroupPartitionedInclusiveOr: out.debug << "subgroupPartitionedInclusiveOrNV"; break; - case EOpSubgroupPartitionedInclusiveXor: out.debug << "subgroupPartitionedInclusiveXorNV"; break; - case EOpSubgroupPartitionedExclusiveAdd: out.debug << "subgroupPartitionedExclusiveAddNV"; break; - case EOpSubgroupPartitionedExclusiveMul: out.debug << "subgroupPartitionedExclusiveMulNV"; break; - case EOpSubgroupPartitionedExclusiveMin: out.debug << "subgroupPartitionedExclusiveMinNV"; break; - case EOpSubgroupPartitionedExclusiveMax: out.debug << "subgroupPartitionedExclusiveMaxNV"; break; - case EOpSubgroupPartitionedExclusiveAnd: out.debug << "subgroupPartitionedExclusiveAndNV"; break; - case EOpSubgroupPartitionedExclusiveOr: out.debug << "subgroupPartitionedExclusiveOrNV"; break; - case EOpSubgroupPartitionedExclusiveXor: out.debug << "subgroupPartitionedExclusiveXorNV"; break; -#endif - - case EOpClip: out.debug << "clip"; break; - case EOpIsFinite: out.debug << "isfinite"; break; - case EOpLog10: out.debug << "log10"; break; - case EOpRcp: out.debug << "rcp"; break; - case EOpSaturate: out.debug << "saturate"; break; - - case EOpSparseTexelsResident: out.debug << "sparseTexelsResident"; break; - -#ifdef AMD_EXTENSIONS - case EOpMinInvocations: out.debug << "minInvocations"; break; - case EOpMaxInvocations: out.debug << "maxInvocations"; break; - case EOpAddInvocations: out.debug << "addInvocations"; break; - case EOpMinInvocationsNonUniform: out.debug << "minInvocationsNonUniform"; break; - case EOpMaxInvocationsNonUniform: out.debug << "maxInvocationsNonUniform"; break; - case EOpAddInvocationsNonUniform: out.debug << "addInvocationsNonUniform"; break; - - case EOpMinInvocationsInclusiveScan: out.debug << "minInvocationsInclusiveScan"; break; - case EOpMaxInvocationsInclusiveScan: out.debug << "maxInvocationsInclusiveScan"; break; - case EOpAddInvocationsInclusiveScan: out.debug << "addInvocationsInclusiveScan"; break; - case EOpMinInvocationsInclusiveScanNonUniform: out.debug << "minInvocationsInclusiveScanNonUniform"; break; - case EOpMaxInvocationsInclusiveScanNonUniform: out.debug << "maxInvocationsInclusiveScanNonUniform"; break; - case EOpAddInvocationsInclusiveScanNonUniform: out.debug << "addInvocationsInclusiveScanNonUniform"; break; - - case EOpMinInvocationsExclusiveScan: out.debug << "minInvocationsExclusiveScan"; break; - case EOpMaxInvocationsExclusiveScan: out.debug << "maxInvocationsExclusiveScan"; break; - case EOpAddInvocationsExclusiveScan: out.debug << "addInvocationsExclusiveScan"; break; - case EOpMinInvocationsExclusiveScanNonUniform: out.debug << "minInvocationsExclusiveScanNonUniform"; break; - case EOpMaxInvocationsExclusiveScanNonUniform: out.debug << "maxInvocationsExclusiveScanNonUniform"; break; - case EOpAddInvocationsExclusiveScanNonUniform: out.debug << "addInvocationsExclusiveScanNonUniform"; break; - - case EOpMbcnt: out.debug << "mbcnt"; break; - - case EOpFragmentMaskFetch: out.debug << "fragmentMaskFetchAMD"; break; - case EOpFragmentFetch: out.debug << "fragmentFetchAMD"; break; - - case EOpCubeFaceIndex: out.debug << "cubeFaceIndex"; break; - case EOpCubeFaceCoord: out.debug << "cubeFaceCoord"; break; -#endif - - case EOpSubpassLoad: out.debug << "subpassLoad"; break; - case EOpSubpassLoadMS: out.debug << "subpassLoadMS"; break; - - default: out.debug.message(EPrefixError, "Bad unary op"); - } - - out.debug << " (" << node->getCompleteString() << ")"; - - out.debug << "\n"; - - return true; -} - -bool TOutputTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node) -{ - TInfoSink& out = infoSink; - - if (node->getOp() == EOpNull) { - out.debug.message(EPrefixError, "node is still EOpNull!"); - return true; - } - - OutputTreeText(out, node, depth); - - switch (node->getOp()) { - case EOpSequence: out.debug << "Sequence\n"; return true; - case EOpLinkerObjects: out.debug << "Linker Objects\n"; return true; - case EOpComma: out.debug << "Comma"; break; - case EOpFunction: out.debug << "Function Definition: " << node->getName(); break; - case EOpFunctionCall: out.debug << "Function Call: " << node->getName(); break; - case EOpParameters: out.debug << "Function Parameters: "; break; - - case EOpConstructFloat: out.debug << "Construct float"; break; - case EOpConstructDouble:out.debug << "Construct double"; break; - - case EOpConstructVec2: out.debug << "Construct vec2"; break; - case EOpConstructVec3: out.debug << "Construct vec3"; break; - case EOpConstructVec4: out.debug << "Construct vec4"; break; - case EOpConstructDVec2: out.debug << "Construct dvec2"; break; - case EOpConstructDVec3: out.debug << "Construct dvec3"; break; - case EOpConstructDVec4: out.debug << "Construct dvec4"; break; - case EOpConstructBool: out.debug << "Construct bool"; break; - case EOpConstructBVec2: out.debug << "Construct bvec2"; break; - case EOpConstructBVec3: out.debug << "Construct bvec3"; break; - case EOpConstructBVec4: out.debug << "Construct bvec4"; break; - case EOpConstructInt8: out.debug << "Construct int8_t"; break; - case EOpConstructI8Vec2: out.debug << "Construct i8vec2"; break; - case EOpConstructI8Vec3: out.debug << "Construct i8vec3"; break; - case EOpConstructI8Vec4: out.debug << "Construct i8vec4"; break; - case EOpConstructInt: out.debug << "Construct int"; break; - case EOpConstructIVec2: out.debug << "Construct ivec2"; break; - case EOpConstructIVec3: out.debug << "Construct ivec3"; break; - case EOpConstructIVec4: out.debug << "Construct ivec4"; break; - case EOpConstructUint8: out.debug << "Construct uint8_t"; break; - case EOpConstructU8Vec2: out.debug << "Construct u8vec2"; break; - case EOpConstructU8Vec3: out.debug << "Construct u8vec3"; break; - case EOpConstructU8Vec4: out.debug << "Construct u8vec4"; break; - case EOpConstructUint: out.debug << "Construct uint"; break; - case EOpConstructUVec2: out.debug << "Construct uvec2"; break; - case EOpConstructUVec3: out.debug << "Construct uvec3"; break; - case EOpConstructUVec4: out.debug << "Construct uvec4"; break; - case EOpConstructInt64: out.debug << "Construct int64"; break; - case EOpConstructI64Vec2: out.debug << "Construct i64vec2"; break; - case EOpConstructI64Vec3: out.debug << "Construct i64vec3"; break; - case EOpConstructI64Vec4: out.debug << "Construct i64vec4"; break; - case EOpConstructUint64: out.debug << "Construct uint64"; break; - case EOpConstructU64Vec2: out.debug << "Construct u64vec2"; break; - case EOpConstructU64Vec3: out.debug << "Construct u64vec3"; break; - case EOpConstructU64Vec4: out.debug << "Construct u64vec4"; break; - case EOpConstructInt16: out.debug << "Construct int16_t"; break; - case EOpConstructI16Vec2: out.debug << "Construct i16vec2"; break; - case EOpConstructI16Vec3: out.debug << "Construct i16vec3"; break; - case EOpConstructI16Vec4: out.debug << "Construct i16vec4"; break; - case EOpConstructUint16: out.debug << "Construct uint16_t"; break; - case EOpConstructU16Vec2: out.debug << "Construct u16vec2"; break; - case EOpConstructU16Vec3: out.debug << "Construct u16vec3"; break; - case EOpConstructU16Vec4: out.debug << "Construct u16vec4"; break; - case EOpConstructMat2x2: out.debug << "Construct mat2"; break; - case EOpConstructMat2x3: out.debug << "Construct mat2x3"; break; - case EOpConstructMat2x4: out.debug << "Construct mat2x4"; break; - case EOpConstructMat3x2: out.debug << "Construct mat3x2"; break; - case EOpConstructMat3x3: out.debug << "Construct mat3"; break; - case EOpConstructMat3x4: out.debug << "Construct mat3x4"; break; - case EOpConstructMat4x2: out.debug << "Construct mat4x2"; break; - case EOpConstructMat4x3: out.debug << "Construct mat4x3"; break; - case EOpConstructMat4x4: out.debug << "Construct mat4"; break; - case EOpConstructDMat2x2: out.debug << "Construct dmat2"; break; - case EOpConstructDMat2x3: out.debug << "Construct dmat2x3"; break; - case EOpConstructDMat2x4: out.debug << "Construct dmat2x4"; break; - case EOpConstructDMat3x2: out.debug << "Construct dmat3x2"; break; - case EOpConstructDMat3x3: out.debug << "Construct dmat3"; break; - case EOpConstructDMat3x4: out.debug << "Construct dmat3x4"; break; - case EOpConstructDMat4x2: out.debug << "Construct dmat4x2"; break; - case EOpConstructDMat4x3: out.debug << "Construct dmat4x3"; break; - case EOpConstructDMat4x4: out.debug << "Construct dmat4"; break; - case EOpConstructIMat2x2: out.debug << "Construct imat2"; break; - case EOpConstructIMat2x3: out.debug << "Construct imat2x3"; break; - case EOpConstructIMat2x4: out.debug << "Construct imat2x4"; break; - case EOpConstructIMat3x2: out.debug << "Construct imat3x2"; break; - case EOpConstructIMat3x3: out.debug << "Construct imat3"; break; - case EOpConstructIMat3x4: out.debug << "Construct imat3x4"; break; - case EOpConstructIMat4x2: out.debug << "Construct imat4x2"; break; - case EOpConstructIMat4x3: out.debug << "Construct imat4x3"; break; - case EOpConstructIMat4x4: out.debug << "Construct imat4"; break; - case EOpConstructUMat2x2: out.debug << "Construct umat2"; break; - case EOpConstructUMat2x3: out.debug << "Construct umat2x3"; break; - case EOpConstructUMat2x4: out.debug << "Construct umat2x4"; break; - case EOpConstructUMat3x2: out.debug << "Construct umat3x2"; break; - case EOpConstructUMat3x3: out.debug << "Construct umat3"; break; - case EOpConstructUMat3x4: out.debug << "Construct umat3x4"; break; - case EOpConstructUMat4x2: out.debug << "Construct umat4x2"; break; - case EOpConstructUMat4x3: out.debug << "Construct umat4x3"; break; - case EOpConstructUMat4x4: out.debug << "Construct umat4"; break; - case EOpConstructBMat2x2: out.debug << "Construct bmat2"; break; - case EOpConstructBMat2x3: out.debug << "Construct bmat2x3"; break; - case EOpConstructBMat2x4: out.debug << "Construct bmat2x4"; break; - case EOpConstructBMat3x2: out.debug << "Construct bmat3x2"; break; - case EOpConstructBMat3x3: out.debug << "Construct bmat3"; break; - case EOpConstructBMat3x4: out.debug << "Construct bmat3x4"; break; - case EOpConstructBMat4x2: out.debug << "Construct bmat4x2"; break; - case EOpConstructBMat4x3: out.debug << "Construct bmat4x3"; break; - case EOpConstructBMat4x4: out.debug << "Construct bmat4"; break; - case EOpConstructFloat16: out.debug << "Construct float16_t"; break; - case EOpConstructF16Vec2: out.debug << "Construct f16vec2"; break; - case EOpConstructF16Vec3: out.debug << "Construct f16vec3"; break; - case EOpConstructF16Vec4: out.debug << "Construct f16vec4"; break; - case EOpConstructF16Mat2x2: out.debug << "Construct f16mat2"; break; - case EOpConstructF16Mat2x3: out.debug << "Construct f16mat2x3"; break; - case EOpConstructF16Mat2x4: out.debug << "Construct f16mat2x4"; break; - case EOpConstructF16Mat3x2: out.debug << "Construct f16mat3x2"; break; - case EOpConstructF16Mat3x3: out.debug << "Construct f16mat3"; break; - case EOpConstructF16Mat3x4: out.debug << "Construct f16mat3x4"; break; - case EOpConstructF16Mat4x2: out.debug << "Construct f16mat4x2"; break; - case EOpConstructF16Mat4x3: out.debug << "Construct f16mat4x3"; break; - case EOpConstructF16Mat4x4: out.debug << "Construct f16mat4"; break; - case EOpConstructStruct: out.debug << "Construct structure"; break; - case EOpConstructTextureSampler: out.debug << "Construct combined texture-sampler"; break; - - case EOpLessThan: out.debug << "Compare Less Than"; break; - case EOpGreaterThan: out.debug << "Compare Greater Than"; break; - case EOpLessThanEqual: out.debug << "Compare Less Than or Equal"; break; - case EOpGreaterThanEqual: out.debug << "Compare Greater Than or Equal"; break; - case EOpVectorEqual: out.debug << "Equal"; break; - case EOpVectorNotEqual: out.debug << "NotEqual"; break; - - case EOpMod: out.debug << "mod"; break; - case EOpModf: out.debug << "modf"; break; - case EOpPow: out.debug << "pow"; break; - - case EOpAtan: out.debug << "arc tangent"; break; - - case EOpMin: out.debug << "min"; break; - case EOpMax: out.debug << "max"; break; - case EOpClamp: out.debug << "clamp"; break; - case EOpMix: out.debug << "mix"; break; - case EOpStep: out.debug << "step"; break; - case EOpSmoothStep: out.debug << "smoothstep"; break; - - case EOpDistance: out.debug << "distance"; break; - case EOpDot: out.debug << "dot-product"; break; - case EOpCross: out.debug << "cross-product"; break; - case EOpFaceForward: out.debug << "face-forward"; break; - case EOpReflect: out.debug << "reflect"; break; - case EOpRefract: out.debug << "refract"; break; - case EOpMul: out.debug << "component-wise multiply"; break; - case EOpOuterProduct: out.debug << "outer product"; break; - - case EOpEmitVertex: out.debug << "EmitVertex"; break; - case EOpEndPrimitive: out.debug << "EndPrimitive"; break; - - case EOpBarrier: out.debug << "Barrier"; break; - case EOpMemoryBarrier: out.debug << "MemoryBarrier"; break; - case EOpMemoryBarrierAtomicCounter: out.debug << "MemoryBarrierAtomicCounter"; break; - case EOpMemoryBarrierBuffer: out.debug << "MemoryBarrierBuffer"; break; - case EOpMemoryBarrierImage: out.debug << "MemoryBarrierImage"; break; - case EOpMemoryBarrierShared: out.debug << "MemoryBarrierShared"; break; - case EOpGroupMemoryBarrier: out.debug << "GroupMemoryBarrier"; break; - - case EOpReadInvocation: out.debug << "readInvocation"; break; - -#ifdef AMD_EXTENSIONS - case EOpSwizzleInvocations: out.debug << "swizzleInvocations"; break; - case EOpSwizzleInvocationsMasked: out.debug << "swizzleInvocationsMasked"; break; - case EOpWriteInvocation: out.debug << "writeInvocation"; break; - - case EOpMin3: out.debug << "min3"; break; - case EOpMax3: out.debug << "max3"; break; - case EOpMid3: out.debug << "mid3"; break; - - case EOpTime: out.debug << "time"; break; -#endif - - case EOpAtomicAdd: out.debug << "AtomicAdd"; break; - case EOpAtomicMin: out.debug << "AtomicMin"; break; - case EOpAtomicMax: out.debug << "AtomicMax"; break; - case EOpAtomicAnd: out.debug << "AtomicAnd"; break; - case EOpAtomicOr: out.debug << "AtomicOr"; break; - case EOpAtomicXor: out.debug << "AtomicXor"; break; - case EOpAtomicExchange: out.debug << "AtomicExchange"; break; - case EOpAtomicCompSwap: out.debug << "AtomicCompSwap"; break; - - case EOpAtomicCounterAdd: out.debug << "AtomicCounterAdd"; break; - case EOpAtomicCounterSubtract: out.debug << "AtomicCounterSubtract"; break; - case EOpAtomicCounterMin: out.debug << "AtomicCounterMin"; break; - case EOpAtomicCounterMax: out.debug << "AtomicCounterMax"; break; - case EOpAtomicCounterAnd: out.debug << "AtomicCounterAnd"; break; - case EOpAtomicCounterOr: out.debug << "AtomicCounterOr"; break; - case EOpAtomicCounterXor: out.debug << "AtomicCounterXor"; break; - case EOpAtomicCounterExchange: out.debug << "AtomicCounterExchange"; break; - case EOpAtomicCounterCompSwap: out.debug << "AtomicCounterCompSwap"; break; - - case EOpImageQuerySize: out.debug << "imageQuerySize"; break; - case EOpImageQuerySamples: out.debug << "imageQuerySamples"; break; - case EOpImageLoad: out.debug << "imageLoad"; break; - case EOpImageStore: out.debug << "imageStore"; break; - case EOpImageAtomicAdd: out.debug << "imageAtomicAdd"; break; - case EOpImageAtomicMin: out.debug << "imageAtomicMin"; break; - case EOpImageAtomicMax: out.debug << "imageAtomicMax"; break; - case EOpImageAtomicAnd: out.debug << "imageAtomicAnd"; break; - case EOpImageAtomicOr: out.debug << "imageAtomicOr"; break; - case EOpImageAtomicXor: out.debug << "imageAtomicXor"; break; - case EOpImageAtomicExchange: out.debug << "imageAtomicExchange"; break; - case EOpImageAtomicCompSwap: out.debug << "imageAtomicCompSwap"; break; -#ifdef AMD_EXTENSIONS - case EOpImageLoadLod: out.debug << "imageLoadLod"; break; - case EOpImageStoreLod: out.debug << "imageStoreLod"; break; -#endif - - case EOpTextureQuerySize: out.debug << "textureSize"; break; - case EOpTextureQueryLod: out.debug << "textureQueryLod"; break; - case EOpTextureQueryLevels: out.debug << "textureQueryLevels"; break; - case EOpTextureQuerySamples: out.debug << "textureSamples"; break; - case EOpTexture: out.debug << "texture"; break; - case EOpTextureProj: out.debug << "textureProj"; break; - case EOpTextureLod: out.debug << "textureLod"; break; - case EOpTextureOffset: out.debug << "textureOffset"; break; - case EOpTextureFetch: out.debug << "textureFetch"; break; - case EOpTextureFetchOffset: out.debug << "textureFetchOffset"; break; - case EOpTextureProjOffset: out.debug << "textureProjOffset"; break; - case EOpTextureLodOffset: out.debug << "textureLodOffset"; break; - case EOpTextureProjLod: out.debug << "textureProjLod"; break; - case EOpTextureProjLodOffset: out.debug << "textureProjLodOffset"; break; - case EOpTextureGrad: out.debug << "textureGrad"; break; - case EOpTextureGradOffset: out.debug << "textureGradOffset"; break; - case EOpTextureProjGrad: out.debug << "textureProjGrad"; break; - case EOpTextureProjGradOffset: out.debug << "textureProjGradOffset"; break; - case EOpTextureGather: out.debug << "textureGather"; break; - case EOpTextureGatherOffset: out.debug << "textureGatherOffset"; break; - case EOpTextureGatherOffsets: out.debug << "textureGatherOffsets"; break; - case EOpTextureClamp: out.debug << "textureClamp"; break; - case EOpTextureOffsetClamp: out.debug << "textureOffsetClamp"; break; - case EOpTextureGradClamp: out.debug << "textureGradClamp"; break; - case EOpTextureGradOffsetClamp: out.debug << "textureGradOffsetClamp"; break; -#ifdef AMD_EXTENSIONS - case EOpTextureGatherLod: out.debug << "textureGatherLod"; break; - case EOpTextureGatherLodOffset: out.debug << "textureGatherLodOffset"; break; - case EOpTextureGatherLodOffsets: out.debug << "textureGatherLodOffsets"; break; -#endif - - case EOpSparseTexture: out.debug << "sparseTexture"; break; - case EOpSparseTextureOffset: out.debug << "sparseTextureOffset"; break; - case EOpSparseTextureLod: out.debug << "sparseTextureLod"; break; - case EOpSparseTextureLodOffset: out.debug << "sparseTextureLodOffset"; break; - case EOpSparseTextureFetch: out.debug << "sparseTexelFetch"; break; - case EOpSparseTextureFetchOffset: out.debug << "sparseTexelFetchOffset"; break; - case EOpSparseTextureGrad: out.debug << "sparseTextureGrad"; break; - case EOpSparseTextureGradOffset: out.debug << "sparseTextureGradOffset"; break; - case EOpSparseTextureGather: out.debug << "sparseTextureGather"; break; - case EOpSparseTextureGatherOffset: out.debug << "sparseTextureGatherOffset"; break; - case EOpSparseTextureGatherOffsets: out.debug << "sparseTextureGatherOffsets"; break; - case EOpSparseImageLoad: out.debug << "sparseImageLoad"; break; - case EOpSparseTextureClamp: out.debug << "sparseTextureClamp"; break; - case EOpSparseTextureOffsetClamp: out.debug << "sparseTextureOffsetClamp"; break; - case EOpSparseTextureGradClamp: out.debug << "sparseTextureGradClamp"; break; - case EOpSparseTextureGradOffsetClamp: out.debug << "sparseTextureGradOffsetClam"; break; -#ifdef AMD_EXTENSIONS - case EOpSparseTextureGatherLod: out.debug << "sparseTextureGatherLod"; break; - case EOpSparseTextureGatherLodOffset: out.debug << "sparseTextureGatherLodOffset"; break; - case EOpSparseTextureGatherLodOffsets: out.debug << "sparseTextureGatherLodOffsets"; break; - case EOpSparseImageLoadLod: out.debug << "sparseImageLoadLod"; break; -#endif - - case EOpAddCarry: out.debug << "addCarry"; break; - case EOpSubBorrow: out.debug << "subBorrow"; break; - case EOpUMulExtended: out.debug << "uMulExtended"; break; - case EOpIMulExtended: out.debug << "iMulExtended"; break; - case EOpBitfieldExtract: out.debug << "bitfieldExtract"; break; - case EOpBitfieldInsert: out.debug << "bitfieldInsert"; break; - - case EOpFma: out.debug << "fma"; break; - case EOpFrexp: out.debug << "frexp"; break; - case EOpLdexp: out.debug << "ldexp"; break; - - case EOpInterpolateAtSample: out.debug << "interpolateAtSample"; break; - case EOpInterpolateAtOffset: out.debug << "interpolateAtOffset"; break; -#ifdef AMD_EXTENSIONS - case EOpInterpolateAtVertex: out.debug << "interpolateAtVertex"; break; -#endif - - case EOpSinCos: out.debug << "sincos"; break; - case EOpGenMul: out.debug << "mul"; break; - - case EOpAllMemoryBarrierWithGroupSync: out.debug << "AllMemoryBarrierWithGroupSync"; break; - case EOpDeviceMemoryBarrier: out.debug << "DeviceMemoryBarrier"; break; - case EOpDeviceMemoryBarrierWithGroupSync: out.debug << "DeviceMemoryBarrierWithGroupSync"; break; - case EOpWorkgroupMemoryBarrier: out.debug << "WorkgroupMemoryBarrier"; break; - case EOpWorkgroupMemoryBarrierWithGroupSync: out.debug << "WorkgroupMemoryBarrierWithGroupSync"; break; - - case EOpSubgroupBarrier: out.debug << "subgroupBarrier"; break; - case EOpSubgroupMemoryBarrier: out.debug << "subgroupMemoryBarrier"; break; - case EOpSubgroupMemoryBarrierBuffer: out.debug << "subgroupMemoryBarrierBuffer"; break; - case EOpSubgroupMemoryBarrierImage: out.debug << "subgroupMemoryBarrierImage"; break; - case EOpSubgroupMemoryBarrierShared: out.debug << "subgroupMemoryBarrierShared"; break; - case EOpSubgroupElect: out.debug << "subgroupElect"; break; - case EOpSubgroupAll: out.debug << "subgroupAll"; break; - case EOpSubgroupAny: out.debug << "subgroupAny"; break; - case EOpSubgroupAllEqual: out.debug << "subgroupAllEqual"; break; - case EOpSubgroupBroadcast: out.debug << "subgroupBroadcast"; break; - case EOpSubgroupBroadcastFirst: out.debug << "subgroupBroadcastFirst"; break; - case EOpSubgroupBallot: out.debug << "subgroupBallot"; break; - case EOpSubgroupInverseBallot: out.debug << "subgroupInverseBallot"; break; - case EOpSubgroupBallotBitExtract: out.debug << "subgroupBallotBitExtract"; break; - case EOpSubgroupBallotBitCount: out.debug << "subgroupBallotBitCount"; break; - case EOpSubgroupBallotInclusiveBitCount: out.debug << "subgroupBallotInclusiveBitCount"; break; - case EOpSubgroupBallotExclusiveBitCount: out.debug << "subgroupBallotExclusiveBitCount"; break; - case EOpSubgroupBallotFindLSB: out.debug << "subgroupBallotFindLSB"; break; - case EOpSubgroupBallotFindMSB: out.debug << "subgroupBallotFindMSB"; break; - case EOpSubgroupShuffle: out.debug << "subgroupShuffle"; break; - case EOpSubgroupShuffleXor: out.debug << "subgroupShuffleXor"; break; - case EOpSubgroupShuffleUp: out.debug << "subgroupShuffleUp"; break; - case EOpSubgroupShuffleDown: out.debug << "subgroupShuffleDown"; break; - case EOpSubgroupAdd: out.debug << "subgroupAdd"; break; - case EOpSubgroupMul: out.debug << "subgroupMul"; break; - case EOpSubgroupMin: out.debug << "subgroupMin"; break; - case EOpSubgroupMax: out.debug << "subgroupMax"; break; - case EOpSubgroupAnd: out.debug << "subgroupAnd"; break; - case EOpSubgroupOr: out.debug << "subgroupOr"; break; - case EOpSubgroupXor: out.debug << "subgroupXor"; break; - case EOpSubgroupInclusiveAdd: out.debug << "subgroupInclusiveAdd"; break; - case EOpSubgroupInclusiveMul: out.debug << "subgroupInclusiveMul"; break; - case EOpSubgroupInclusiveMin: out.debug << "subgroupInclusiveMin"; break; - case EOpSubgroupInclusiveMax: out.debug << "subgroupInclusiveMax"; break; - case EOpSubgroupInclusiveAnd: out.debug << "subgroupInclusiveAnd"; break; - case EOpSubgroupInclusiveOr: out.debug << "subgroupInclusiveOr"; break; - case EOpSubgroupInclusiveXor: out.debug << "subgroupInclusiveXor"; break; - case EOpSubgroupExclusiveAdd: out.debug << "subgroupExclusiveAdd"; break; - case EOpSubgroupExclusiveMul: out.debug << "subgroupExclusiveMul"; break; - case EOpSubgroupExclusiveMin: out.debug << "subgroupExclusiveMin"; break; - case EOpSubgroupExclusiveMax: out.debug << "subgroupExclusiveMax"; break; - case EOpSubgroupExclusiveAnd: out.debug << "subgroupExclusiveAnd"; break; - case EOpSubgroupExclusiveOr: out.debug << "subgroupExclusiveOr"; break; - case EOpSubgroupExclusiveXor: out.debug << "subgroupExclusiveXor"; break; - case EOpSubgroupClusteredAdd: out.debug << "subgroupClusteredAdd"; break; - case EOpSubgroupClusteredMul: out.debug << "subgroupClusteredMul"; break; - case EOpSubgroupClusteredMin: out.debug << "subgroupClusteredMin"; break; - case EOpSubgroupClusteredMax: out.debug << "subgroupClusteredMax"; break; - case EOpSubgroupClusteredAnd: out.debug << "subgroupClusteredAnd"; break; - case EOpSubgroupClusteredOr: out.debug << "subgroupClusteredOr"; break; - case EOpSubgroupClusteredXor: out.debug << "subgroupClusteredXor"; break; - case EOpSubgroupQuadBroadcast: out.debug << "subgroupQuadBroadcast"; break; - case EOpSubgroupQuadSwapHorizontal: out.debug << "subgroupQuadSwapHorizontal"; break; - case EOpSubgroupQuadSwapVertical: out.debug << "subgroupQuadSwapVertical"; break; - case EOpSubgroupQuadSwapDiagonal: out.debug << "subgroupQuadSwapDiagonal"; break; - - case EOpSubpassLoad: out.debug << "subpassLoad"; break; - case EOpSubpassLoadMS: out.debug << "subpassLoadMS"; break; - - default: out.debug.message(EPrefixError, "Bad aggregation op"); - } - - if (node->getOp() != EOpSequence && node->getOp() != EOpParameters) - out.debug << " (" << node->getCompleteString() << ")"; - - out.debug << "\n"; - - return true; -} - -bool TOutputTraverser::visitSelection(TVisit /* visit */, TIntermSelection* node) -{ - TInfoSink& out = infoSink; - - OutputTreeText(out, node, depth); - - out.debug << "Test condition and select"; - out.debug << " (" << node->getCompleteString() << ")"; - - if (node->getShortCircuit() == false) - out.debug << ": no shortcircuit"; - if (node->getFlatten()) - out.debug << ": Flatten"; - if (node->getDontFlatten()) - out.debug << ": DontFlatten"; - out.debug << "\n"; - - ++depth; - - OutputTreeText(out, node, depth); - out.debug << "Condition\n"; - node->getCondition()->traverse(this); - - OutputTreeText(out, node, depth); - if (node->getTrueBlock()) { - out.debug << "true case\n"; - node->getTrueBlock()->traverse(this); - } else - out.debug << "true case is null\n"; - - if (node->getFalseBlock()) { - OutputTreeText(out, node, depth); - out.debug << "false case\n"; - node->getFalseBlock()->traverse(this); - } - - --depth; - - return false; -} - -static void OutputConstantUnion(TInfoSink& out, const TIntermTyped* node, const TConstUnionArray& constUnion, int depth) -{ - int size = node->getType().computeNumComponents(); - - for (int i = 0; i < size; i++) { - OutputTreeText(out, node, depth); - switch (constUnion[i].getType()) { - case EbtBool: - if (constUnion[i].getBConst()) - out.debug << "true"; - else - out.debug << "false"; - - out.debug << " (" << "const bool" << ")"; - - out.debug << "\n"; - break; - case EbtFloat: - case EbtDouble: - case EbtFloat16: - { - const double value = constUnion[i].getDConst(); - // Print infinities and NaNs in a portable way. - if (IsInfinity(value)) { - if (value < 0) - out.debug << "-1.#INF\n"; - else - out.debug << "+1.#INF\n"; - } else if (IsNan(value)) - out.debug << "1.#IND\n"; - else { - const int maxSize = 300; - char buf[maxSize]; - snprintf(buf, maxSize, "%f", value); - - out.debug << buf << "\n"; - } - } - break; - case EbtInt8: - { - const int maxSize = 300; - char buf[maxSize]; - snprintf(buf, maxSize, "%d (%s)", constUnion[i].getI8Const(), "const int8_t"); - - out.debug << buf << "\n"; - } - break; - case EbtUint8: - { - const int maxSize = 300; - char buf[maxSize]; - snprintf(buf, maxSize, "%u (%s)", constUnion[i].getU8Const(), "const uint8_t"); - - out.debug << buf << "\n"; - } - break; - case EbtInt16: - { - const int maxSize = 300; - char buf[maxSize]; - snprintf(buf, maxSize, "%d (%s)", constUnion[i].getI16Const(), "const int16_t"); - - out.debug << buf << "\n"; - } - break; - case EbtUint16: - { - const int maxSize = 300; - char buf[maxSize]; - snprintf(buf, maxSize, "%u (%s)", constUnion[i].getU16Const(), "const uint16_t"); - - out.debug << buf << "\n"; - } - break; - case EbtInt: - { - const int maxSize = 300; - char buf[maxSize]; - snprintf(buf, maxSize, "%d (%s)", constUnion[i].getIConst(), "const int"); - - out.debug << buf << "\n"; - } - break; - case EbtUint: - { - const int maxSize = 300; - char buf[maxSize]; - snprintf(buf, maxSize, "%u (%s)", constUnion[i].getUConst(), "const uint"); - - out.debug << buf << "\n"; - } - break; - case EbtInt64: - { - const int maxSize = 300; - char buf[maxSize]; - snprintf(buf, maxSize, "%lld (%s)", constUnion[i].getI64Const(), "const int64_t"); - - out.debug << buf << "\n"; - } - break; - case EbtUint64: - { - const int maxSize = 300; - char buf[maxSize]; - snprintf(buf, maxSize, "%llu (%s)", constUnion[i].getU64Const(), "const uint64_t"); - - out.debug << buf << "\n"; - } - break; - default: - out.info.message(EPrefixInternalError, "Unknown constant", node->getLoc()); - break; - } - } -} - -void TOutputTraverser::visitConstantUnion(TIntermConstantUnion* node) -{ - OutputTreeText(infoSink, node, depth); - infoSink.debug << "Constant:\n"; - - OutputConstantUnion(infoSink, node, node->getConstArray(), depth + 1); -} - -void TOutputTraverser::visitSymbol(TIntermSymbol* node) -{ - OutputTreeText(infoSink, node, depth); - - infoSink.debug << "'" << node->getName() << "' (" << node->getCompleteString() << ")\n"; - - if (! node->getConstArray().empty()) - OutputConstantUnion(infoSink, node, node->getConstArray(), depth + 1); - else if (node->getConstSubtree()) { - incrementDepth(node); - node->getConstSubtree()->traverse(this); - decrementDepth(); - } -} - -bool TOutputTraverser::visitLoop(TVisit /* visit */, TIntermLoop* node) -{ - TInfoSink& out = infoSink; - - OutputTreeText(out, node, depth); - - out.debug << "Loop with condition "; - if (! node->testFirst()) - out.debug << "not "; - out.debug << "tested first"; - - if (node->getUnroll()) - out.debug << ": Unroll"; - if (node->getDontUnroll()) - out.debug << ": DontUnroll"; - if (node->getLoopDependency()) { - out.debug << ": Dependency "; - out.debug << node->getLoopDependency(); - } - out.debug << "\n"; - - ++depth; - - OutputTreeText(infoSink, node, depth); - if (node->getTest()) { - out.debug << "Loop Condition\n"; - node->getTest()->traverse(this); - } else - out.debug << "No loop condition\n"; - - OutputTreeText(infoSink, node, depth); - if (node->getBody()) { - out.debug << "Loop Body\n"; - node->getBody()->traverse(this); - } else - out.debug << "No loop body\n"; - - if (node->getTerminal()) { - OutputTreeText(infoSink, node, depth); - out.debug << "Loop Terminal Expression\n"; - node->getTerminal()->traverse(this); - } - - --depth; - - return false; -} - -bool TOutputTraverser::visitBranch(TVisit /* visit*/, TIntermBranch* node) -{ - TInfoSink& out = infoSink; - - OutputTreeText(out, node, depth); - - switch (node->getFlowOp()) { - case EOpKill: out.debug << "Branch: Kill"; break; - case EOpBreak: out.debug << "Branch: Break"; break; - case EOpContinue: out.debug << "Branch: Continue"; break; - case EOpReturn: out.debug << "Branch: Return"; break; - case EOpCase: out.debug << "case: "; break; - case EOpDefault: out.debug << "default: "; break; - default: out.debug << "Branch: Unknown Branch"; break; - } - - if (node->getExpression()) { - out.debug << " with expression\n"; - ++depth; - node->getExpression()->traverse(this); - --depth; - } else - out.debug << "\n"; - - return false; -} - -bool TOutputTraverser::visitSwitch(TVisit /* visit */, TIntermSwitch* node) -{ - TInfoSink& out = infoSink; - - OutputTreeText(out, node, depth); - out.debug << "switch"; - - if (node->getFlatten()) - out.debug << ": Flatten"; - if (node->getDontFlatten()) - out.debug << ": DontFlatten"; - out.debug << "\n"; - - OutputTreeText(out, node, depth); - out.debug << "condition\n"; - ++depth; - node->getCondition()->traverse(this); - - --depth; - OutputTreeText(out, node, depth); - out.debug << "body\n"; - ++depth; - node->getBody()->traverse(this); - - --depth; - - return false; -} - -// -// This function is the one to call externally to start the traversal. -// Individual functions can be initialized to 0 to skip processing of that -// type of node. It's children will still be processed. -// -void TIntermediate::output(TInfoSink& infoSink, bool tree) -{ - infoSink.debug << "Shader version: " << version << "\n"; - if (requestedExtensions.size() > 0) { - for (auto extIt = requestedExtensions.begin(); extIt != requestedExtensions.end(); ++extIt) - infoSink.debug << "Requested " << *extIt << "\n"; - } - - if (xfbMode) - infoSink.debug << "in xfb mode\n"; - - switch (language) { - case EShLangVertex: - break; - - case EShLangTessControl: - infoSink.debug << "vertices = " << vertices << "\n"; - - if (inputPrimitive != ElgNone) - infoSink.debug << "input primitive = " << TQualifier::getGeometryString(inputPrimitive) << "\n"; - if (vertexSpacing != EvsNone) - infoSink.debug << "vertex spacing = " << TQualifier::getVertexSpacingString(vertexSpacing) << "\n"; - if (vertexOrder != EvoNone) - infoSink.debug << "triangle order = " << TQualifier::getVertexOrderString(vertexOrder) << "\n"; - break; - - case EShLangTessEvaluation: - infoSink.debug << "input primitive = " << TQualifier::getGeometryString(inputPrimitive) << "\n"; - infoSink.debug << "vertex spacing = " << TQualifier::getVertexSpacingString(vertexSpacing) << "\n"; - infoSink.debug << "triangle order = " << TQualifier::getVertexOrderString(vertexOrder) << "\n"; - if (pointMode) - infoSink.debug << "using point mode\n"; - break; - - case EShLangGeometry: - infoSink.debug << "invocations = " << invocations << "\n"; - infoSink.debug << "max_vertices = " << vertices << "\n"; - infoSink.debug << "input primitive = " << TQualifier::getGeometryString(inputPrimitive) << "\n"; - infoSink.debug << "output primitive = " << TQualifier::getGeometryString(outputPrimitive) << "\n"; - break; - - case EShLangFragment: - if (pixelCenterInteger) - infoSink.debug << "gl_FragCoord pixel center is integer\n"; - if (originUpperLeft) - infoSink.debug << "gl_FragCoord origin is upper left\n"; - if (earlyFragmentTests) - infoSink.debug << "using early_fragment_tests\n"; - if (postDepthCoverage) - infoSink.debug << "using post_depth_coverage\n"; - if (depthLayout != EldNone) - infoSink.debug << "using " << TQualifier::getLayoutDepthString(depthLayout) << "\n"; - if (blendEquations != 0) { - infoSink.debug << "using"; - // blendEquations is a mask, decode it - for (TBlendEquationShift be = (TBlendEquationShift)0; be < EBlendCount; be = (TBlendEquationShift)(be + 1)) { - if (blendEquations & (1 << be)) - infoSink.debug << " " << TQualifier::getBlendEquationString(be); - } - infoSink.debug << "\n"; - } - break; - - case EShLangCompute: - infoSink.debug << "local_size = (" << localSize[0] << ", " << localSize[1] << ", " << localSize[2] << ")\n"; - { - if (localSizeSpecId[0] != TQualifier::layoutNotSet || - localSizeSpecId[1] != TQualifier::layoutNotSet || - localSizeSpecId[2] != TQualifier::layoutNotSet) { - infoSink.debug << "local_size ids = (" << - localSizeSpecId[0] << ", " << - localSizeSpecId[1] << ", " << - localSizeSpecId[2] << ")\n"; - } - } - break; - - default: - break; - } - - if (treeRoot == 0 || ! tree) - return; - - TOutputTraverser it(infoSink); - - treeRoot->traverse(&it); -} - -} // end namespace glslang diff --git a/External/glslang/glslang/MachineIndependent/iomapper.cpp b/External/glslang/glslang/MachineIndependent/iomapper.cpp deleted file mode 100644 index ad22353b..00000000 --- a/External/glslang/glslang/MachineIndependent/iomapper.cpp +++ /dev/null @@ -1,789 +0,0 @@ -// -// Copyright (C) 2016-2017 LunarG, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -#include "../Include/Common.h" -#include "../Include/InfoSink.h" -#include "iomapper.h" -#include "LiveTraverser.h" -#include "localintermediate.h" - -#include "gl_types.h" - -#include -#include - -// -// Map IO bindings. -// -// High-level algorithm for one stage: -// -// 1. Traverse all code (live+dead) to find the explicitly provided bindings. -// -// 2. Traverse (just) the live code to determine which non-provided bindings -// require auto-numbering. We do not auto-number dead ones. -// -// 3. Traverse all the code to apply the bindings: -// a. explicitly given bindings are offset according to their type -// b. implicit live bindings are auto-numbered into the holes, using -// any open binding slot. -// c. implicit dead bindings are left un-bound. -// - - -namespace glslang { - -struct TVarEntryInfo -{ - int id; - TIntermSymbol* symbol; - bool live; - int newBinding; - int newSet; - int newLocation; - int newComponent; - int newIndex; - - 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; - } - }; -}; - - - -typedef std::vector TVarLiveMap; - -class TVarGatherTraverser : public TLiveTraverser -{ -public: - TVarGatherTraverser(const TIntermediate& i, bool traverseDeadCode, TVarLiveMap& inList, TVarLiveMap& outList, TVarLiveMap& uniformList) - : TLiveTraverser(i, traverseDeadCode, true, true, false) - , inputList(inList) - , outputList(outList) - , uniformList(uniformList) - { - } - - - virtual void visitSymbol(TIntermSymbol* base) - { - TVarLiveMap* target = nullptr; - if (base->getQualifier().storage == EvqVaryingIn) - target = &inputList; - else if (base->getQualifier().storage == EvqVaryingOut) - target = &outputList; - else if (base->getQualifier().isUniformOrBuffer()) - target = &uniformList; - - if (target) { - TVarEntryInfo ent = { base->getId(), base, !traverseAll }; - TVarLiveMap::iterator at = std::lower_bound(target->begin(), target->end(), ent, TVarEntryInfo::TOrderById()); - if (at != target->end() && at->id == ent.id) - at->live = at->live || !traverseAll; // update live state - else - target->insert(at, ent); - } - } - -private: - TVarLiveMap& inputList; - TVarLiveMap& outputList; - TVarLiveMap& uniformList; -}; - -class TVarSetTraverser : public TLiveTraverser -{ -public: - TVarSetTraverser(const TIntermediate& i, const TVarLiveMap& inList, const TVarLiveMap& outList, const TVarLiveMap& uniformList) - : TLiveTraverser(i, true, true, true, false) - , inputList(inList) - , outputList(outList) - , uniformList(uniformList) - { - } - - - virtual void visitSymbol(TIntermSymbol* base) - { - const TVarLiveMap* source; - if (base->getQualifier().storage == EvqVaryingIn) - source = &inputList; - else if (base->getQualifier().storage == EvqVaryingOut) - source = &outputList; - else if (base->getQualifier().isUniformOrBuffer()) - source = &uniformList; - else - return; - - TVarEntryInfo ent = { base->getId() }; - TVarLiveMap::const_iterator at = std::lower_bound(source->begin(), source->end(), ent, TVarEntryInfo::TOrderById()); - if (at == source->end()) - return; - - if (at->id != ent.id) - return; - - if (at->newBinding != -1) - base->getWritableType().getQualifier().layoutBinding = at->newBinding; - if (at->newSet != -1) - base->getWritableType().getQualifier().layoutSet = at->newSet; - if (at->newLocation != -1) - base->getWritableType().getQualifier().layoutLocation = at->newLocation; - if (at->newComponent != -1) - base->getWritableType().getQualifier().layoutComponent = at->newComponent; - if (at->newIndex != -1) - base->getWritableType().getQualifier().layoutIndex = at->newIndex; - } - - private: - const TVarLiveMap& inputList; - const TVarLiveMap& outputList; - const TVarLiveMap& uniformList; -}; - -struct TNotifyUniformAdaptor -{ - EShLanguage stage; - TIoMapResolver& resolver; - inline TNotifyUniformAdaptor(EShLanguage s, TIoMapResolver& r) - : stage(s) - , resolver(r) - { - } - inline void operator()(TVarEntryInfo& ent) - { - resolver.notifyBinding(stage, ent.symbol->getName().c_str(), ent.symbol->getType(), ent.live); - } -private: - TNotifyUniformAdaptor& operator=(TNotifyUniformAdaptor&); -}; - -struct TNotifyInOutAdaptor -{ - EShLanguage stage; - TIoMapResolver& resolver; - inline TNotifyInOutAdaptor(EShLanguage s, TIoMapResolver& r) - : stage(s) - , resolver(r) - { - } - inline void operator()(TVarEntryInfo& ent) - { - resolver.notifyInOut(stage, ent.symbol->getName().c_str(), ent.symbol->getType(), ent.live); - } -private: - TNotifyInOutAdaptor& operator=(TNotifyInOutAdaptor&); -}; - -struct TResolverUniformAdaptor -{ - TResolverUniformAdaptor(EShLanguage s, TIoMapResolver& r, TInfoSink& i, bool& e, TIntermediate& interm) - : stage(s) - , resolver(r) - , infoSink(i) - , error(e) - , intermediate(interm) - { - } - - inline void operator()(TVarEntryInfo& ent) - { - ent.newLocation = -1; - ent.newComponent = -1; - ent.newBinding = -1; - ent.newSet = -1; - ent.newIndex = -1; - const bool isValid = resolver.validateBinding(stage, ent.symbol->getName().c_str(), ent.symbol->getType(), - ent.live); - if (isValid) { - ent.newBinding = resolver.resolveBinding(stage, ent.symbol->getName().c_str(), ent.symbol->getType(), - ent.live); - ent.newSet = resolver.resolveSet(stage, ent.symbol->getName().c_str(), ent.symbol->getType(), ent.live); - ent.newLocation = resolver.resolveUniformLocation(stage, ent.symbol->getName().c_str(), - ent.symbol->getType(), ent.live); - - if (ent.newBinding != -1) { - if (ent.newBinding >= int(TQualifier::layoutBindingEnd)) { - TString err = "mapped binding out of range: " + ent.symbol->getName(); - - infoSink.info.message(EPrefixInternalError, err.c_str()); - error = true; - } - } - if (ent.newSet != -1) { - if (ent.newSet >= int(TQualifier::layoutSetEnd)) { - TString err = "mapped set out of range: " + ent.symbol->getName(); - - infoSink.info.message(EPrefixInternalError, err.c_str()); - error = true; - } - } - } else { - TString errorMsg = "Invalid binding: " + ent.symbol->getName(); - infoSink.info.message(EPrefixInternalError, errorMsg.c_str()); - error = true; - } - } - - EShLanguage stage; - TIoMapResolver& resolver; - TInfoSink& infoSink; - bool& error; - TIntermediate& intermediate; - -private: - TResolverUniformAdaptor& operator=(TResolverUniformAdaptor&); -}; - -struct TResolverInOutAdaptor -{ - TResolverInOutAdaptor(EShLanguage s, TIoMapResolver& r, TInfoSink& i, bool& e, TIntermediate& interm) - : stage(s) - , resolver(r) - , infoSink(i) - , error(e) - , intermediate(interm) - { - } - - inline void operator()(TVarEntryInfo& ent) - { - ent.newLocation = -1; - ent.newComponent = -1; - ent.newBinding = -1; - ent.newSet = -1; - ent.newIndex = -1; - const bool isValid = resolver.validateInOut(stage, - ent.symbol->getName().c_str(), - ent.symbol->getType(), - ent.live); - if (isValid) { - ent.newLocation = resolver.resolveInOutLocation(stage, - ent.symbol->getName().c_str(), - ent.symbol->getType(), - ent.live); - ent.newComponent = resolver.resolveInOutComponent(stage, - ent.symbol->getName().c_str(), - ent.symbol->getType(), - ent.live); - ent.newIndex = resolver.resolveInOutIndex(stage, - ent.symbol->getName().c_str(), - ent.symbol->getType(), - ent.live); - } else { - TString errorMsg = "Invalid shader In/Out variable semantic: "; - errorMsg += ent.symbol->getType().getQualifier().semanticName; - infoSink.info.message(EPrefixInternalError, errorMsg.c_str()); - error = true; - } - } - - EShLanguage stage; - TIoMapResolver& resolver; - TInfoSink& infoSink; - bool& error; - TIntermediate& intermediate; - -private: - TResolverInOutAdaptor& operator=(TResolverInOutAdaptor&); -}; - -// Base class for shared TIoMapResolver services, used by several derivations. -struct TDefaultIoResolverBase : public glslang::TIoMapResolver -{ - TDefaultIoResolverBase(const TIntermediate &intermediate) : - intermediate(intermediate), - nextUniformLocation(0), - nextInputLocation(0), - nextOutputLocation(0) - { } - - int getBaseBinding(TResourceType res, unsigned int set) const { - return selectBaseBinding(intermediate.getShiftBinding(res), - intermediate.getShiftBindingForSet(res, set)); - } - - const std::vector& getResourceSetBinding() const { return intermediate.getResourceSetBinding(); } - - bool doAutoBindingMapping() const { return intermediate.getAutoMapBindings(); } - bool doAutoLocationMapping() const { return intermediate.getAutoMapLocations(); } - - typedef std::vector TSlotSet; - typedef std::unordered_map TSlotSetMap; - TSlotSetMap slots; - - TSlotSet::iterator findSlot(int set, int slot) - { - return std::lower_bound(slots[set].begin(), slots[set].end(), slot); - } - - bool checkEmpty(int set, int slot) - { - TSlotSet::iterator at = findSlot(set, slot); - return !(at != slots[set].end() && *at == slot); - } - - int reserveSlot(int set, int slot) - { - TSlotSet::iterator at = findSlot(set, slot); - - // tolerate aliasing, by not double-recording aliases - // (policy about appropriateness of the alias is higher up) - if (at == slots[set].end() || *at != slot) - slots[set].insert(at, slot); - - return slot; - } - - int getFreeSlot(int set, int base) - { - TSlotSet::iterator at = findSlot(set, base); - if (at == slots[set].end()) - return reserveSlot(set, base); - - // look in locksteps, if they not match, then there is a free slot - for (; at != slots[set].end(); ++at, ++base) - if (*at != base) - break; - return reserveSlot(set, base); - } - - virtual bool validateBinding(EShLanguage /*stage*/, const char* /*name*/, const glslang::TType& type, bool /*is_live*/) override = 0; - - virtual int resolveBinding(EShLanguage /*stage*/, const char* /*name*/, const glslang::TType& type, bool is_live) override = 0; - - int resolveSet(EShLanguage /*stage*/, const char* /*name*/, const glslang::TType& type, bool /*is_live*/) override - { - if (type.getQualifier().hasSet()) - return type.getQualifier().layoutSet; - - // If a command line or API option requested a single descriptor set, use that (if not overrided by spaceN) - if (getResourceSetBinding().size() == 1) - return atoi(getResourceSetBinding()[0].c_str()); - - return 0; - } - int resolveUniformLocation(EShLanguage /*stage*/, const char* /*name*/, const glslang::TType& type, bool /*is_live*/) override - { - // kick out of not doing this - if (!doAutoLocationMapping()) - return -1; - - // no locations added if already present, a built-in variable, a block, or an opaque - if (type.getQualifier().hasLocation() || type.isBuiltIn() || - type.getBasicType() == EbtBlock || - type.getBasicType() == EbtAtomicUint || - (type.containsOpaque() && intermediate.getSpv().openGl == 0)) - return -1; - - // no locations on blocks of built-in variables - if (type.isStruct()) { - if (type.getStruct()->size() < 1) - return -1; - if ((*type.getStruct())[0].type->isBuiltIn()) - return -1; - } - - int location = nextUniformLocation; - - nextUniformLocation += TIntermediate::computeTypeUniformLocationSize(type); - - return location; - } - bool validateInOut(EShLanguage /*stage*/, const char* /*name*/, const TType& /*type*/, bool /*is_live*/) override - { - return true; - } - int resolveInOutLocation(EShLanguage stage, const char* /*name*/, const TType& type, bool /*is_live*/) override - { - // kick out of not doing this - if (!doAutoLocationMapping()) - return -1; - - // no locations added if already present, or a built-in variable - if (type.getQualifier().hasLocation() || type.isBuiltIn()) - return -1; - - // no locations on blocks of built-in variables - if (type.isStruct()) { - if (type.getStruct()->size() < 1) - return -1; - if ((*type.getStruct())[0].type->isBuiltIn()) - return -1; - } - - // point to the right input or output location counter - int& nextLocation = type.getQualifier().isPipeInput() ? nextInputLocation : nextOutputLocation; - - // Placeholder. This does not do proper cross-stage lining up, nor - // work with mixed location/no-location declarations. - int location = nextLocation; - nextLocation += TIntermediate::computeTypeLocationSize(type, stage); - - return location; - } - int resolveInOutComponent(EShLanguage /*stage*/, const char* /*name*/, const TType& /*type*/, bool /*is_live*/) override - { - return -1; - } - int resolveInOutIndex(EShLanguage /*stage*/, const char* /*name*/, const TType& /*type*/, bool /*is_live*/) override - { - return -1; - } - - void notifyBinding(EShLanguage, const char* /*name*/, const TType&, bool /*is_live*/) override {} - void notifyInOut(EShLanguage, const char* /*name*/, const TType&, bool /*is_live*/) override {} - void endNotifications(EShLanguage) override {} - void beginNotifications(EShLanguage) override {} - void beginResolve(EShLanguage) override {} - void endResolve(EShLanguage) override {} - -protected: - const TIntermediate &intermediate; - int nextUniformLocation; - int nextInputLocation; - int nextOutputLocation; - - // 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; - } -}; - -/* - * Basic implementation of glslang::TIoMapResolver that replaces the - * previous offset behavior. - * It does the same, uses the offsets for the corresponding uniform - * types. Also respects the EOptionAutoMapBindings flag and binds - * them if needed. - */ -/* - * Default resolver - */ -struct TDefaultIoResolver : public TDefaultIoResolverBase -{ - TDefaultIoResolver(const TIntermediate &intermediate) : TDefaultIoResolverBase(intermediate) { } - - bool validateBinding(EShLanguage /*stage*/, const char* /*name*/, const glslang::TType& /*type*/, bool /*is_live*/) override - { - return true; - } - - int resolveBinding(EShLanguage /*stage*/, const char* /*name*/, const glslang::TType& type, bool is_live) override - { - const int set = getLayoutSet(type); - - if (type.getQualifier().hasBinding()) { - if (isImageType(type)) - return reserveSlot(set, getBaseBinding(EResImage, set) + type.getQualifier().layoutBinding); - - if (isTextureType(type)) - return reserveSlot(set, getBaseBinding(EResTexture, set) + type.getQualifier().layoutBinding); - - if (isSsboType(type)) - return reserveSlot(set, getBaseBinding(EResSsbo, set) + type.getQualifier().layoutBinding); - - if (isSamplerType(type)) - return reserveSlot(set, getBaseBinding(EResSampler, set) + type.getQualifier().layoutBinding); - - if (isUboType(type)) - return reserveSlot(set, getBaseBinding(EResUbo, set) + type.getQualifier().layoutBinding); - } else if (is_live && doAutoBindingMapping()) { - // find free slot, the caller did make sure it passes all vars with binding - // first and now all are passed that do not have a binding and needs one - - if (isImageType(type)) - return getFreeSlot(set, getBaseBinding(EResImage, set)); - - if (isTextureType(type)) - return getFreeSlot(set, getBaseBinding(EResTexture, set)); - - if (isSsboType(type)) - return getFreeSlot(set, getBaseBinding(EResSsbo, set)); - - if (isSamplerType(type)) - return getFreeSlot(set, getBaseBinding(EResSampler, set)); - - if (isUboType(type)) - return getFreeSlot(set, getBaseBinding(EResUbo, set)); - } - - return -1; - } - -protected: - 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; - } -}; - -/******************************************************************************** -The following IO resolver maps types in HLSL register space, as follows: - -t - for shader resource views (SRV) - TEXTURE1D - TEXTURE1DARRAY - TEXTURE2D - TEXTURE2DARRAY - TEXTURE3D - TEXTURECUBE - TEXTURECUBEARRAY - TEXTURE2DMS - TEXTURE2DMSARRAY - STRUCTUREDBUFFER - BYTEADDRESSBUFFER - BUFFER - TBUFFER - -s - for samplers - SAMPLER - SAMPLER1D - SAMPLER2D - SAMPLER3D - SAMPLERCUBE - SAMPLERSTATE - SAMPLERCOMPARISONSTATE - -u - for unordered access views (UAV) - RWBYTEADDRESSBUFFER - RWSTRUCTUREDBUFFER - APPENDSTRUCTUREDBUFFER - CONSUMESTRUCTUREDBUFFER - RWBUFFER - RWTEXTURE1D - RWTEXTURE1DARRAY - RWTEXTURE2D - RWTEXTURE2DARRAY - RWTEXTURE3D - -b - for constant buffer views (CBV) - CBUFFER - CONSTANTBUFFER - ********************************************************************************/ -struct TDefaultHlslIoResolver : public TDefaultIoResolverBase -{ - TDefaultHlslIoResolver(const TIntermediate &intermediate) : TDefaultIoResolverBase(intermediate) { } - - bool validateBinding(EShLanguage /*stage*/, const char* /*name*/, const glslang::TType& /*type*/, bool /*is_live*/) override - { - return true; - } - - int resolveBinding(EShLanguage /*stage*/, const char* /*name*/, const glslang::TType& type, bool is_live) override - { - const int set = getLayoutSet(type); - - if (type.getQualifier().hasBinding()) { - if (isUavType(type)) - return reserveSlot(set, getBaseBinding(EResUav, set) + type.getQualifier().layoutBinding); - - if (isSrvType(type)) - return reserveSlot(set, getBaseBinding(EResTexture, set) + type.getQualifier().layoutBinding); - - if (isSamplerType(type)) - return reserveSlot(set, getBaseBinding(EResSampler, set) + type.getQualifier().layoutBinding); - - if (isUboType(type)) - return reserveSlot(set, getBaseBinding(EResUbo, set) + type.getQualifier().layoutBinding); - } else if (is_live && doAutoBindingMapping()) { - // find free slot, the caller did make sure it passes all vars with binding - // first and now all are passed that do not have a binding and needs one - - if (isUavType(type)) - return getFreeSlot(set, getBaseBinding(EResUav, set)); - - if (isSrvType(type)) - return getFreeSlot(set, getBaseBinding(EResTexture, set)); - - if (isSamplerType(type)) - return getFreeSlot(set, getBaseBinding(EResSampler, set)); - - if (isUboType(type)) - return getFreeSlot(set, getBaseBinding(EResUbo, set)); - } - - return -1; - } - -protected: - // 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().readonly) - return false; - - return (type.getBasicType() == glslang::EbtSampler && type.getSampler().isImage()) || - (type.getQualifier().storage == EvqBuffer); - } -}; - - -// Map I/O variables to provided offsets, and make bindings for -// unbound but live variables. -// -// Returns false if the input is too malformed to do this. -bool TIoMapper::addStage(EShLanguage stage, TIntermediate &intermediate, TInfoSink &infoSink, TIoMapResolver *resolver) -{ - bool somethingToDo = !intermediate.getResourceSetBinding().empty() || - intermediate.getAutoMapBindings() || - intermediate.getAutoMapLocations(); - - for (int res = 0; res < EResCount; ++res) { - somethingToDo = somethingToDo || - (intermediate.getShiftBinding(TResourceType(res)) != 0) || - intermediate.hasShiftBindingForSet(TResourceType(res)); - } - - if (!somethingToDo && resolver == nullptr) - return true; - - if (intermediate.getNumEntryPoints() != 1 || intermediate.isRecursive()) - return false; - - TIntermNode* root = intermediate.getTreeRoot(); - if (root == nullptr) - return false; - - // if no resolver is provided, use the default resolver with the given shifts and auto map settings - TDefaultIoResolver defaultResolver(intermediate); - TDefaultHlslIoResolver defaultHlslResolver(intermediate); - - if (resolver == nullptr) { - // TODO: use a passed in IO mapper for this - if (intermediate.usingHlslIoMapping()) - resolver = &defaultHlslResolver; - else - resolver = &defaultResolver; - } - - TVarLiveMap inVarMap, outVarMap, uniformVarMap; - TVarGatherTraverser iter_binding_all(intermediate, true, inVarMap, outVarMap, uniformVarMap); - TVarGatherTraverser iter_binding_live(intermediate, false, inVarMap, outVarMap, uniformVarMap); - - root->traverse(&iter_binding_all); - iter_binding_live.pushFunction(intermediate.getEntryPointMangledName().c_str()); - - while (!iter_binding_live.functions.empty()) { - TIntermNode* function = iter_binding_live.functions.back(); - iter_binding_live.functions.pop_back(); - function->traverse(&iter_binding_live); - } - - // sort entries by priority. see TVarEntryInfo::TOrderByPriority for info. - std::sort(uniformVarMap.begin(), uniformVarMap.end(), TVarEntryInfo::TOrderByPriority()); - - bool hadError = false; - TNotifyInOutAdaptor inOutNotify(stage, *resolver); - TNotifyUniformAdaptor uniformNotify(stage, *resolver); - TResolverUniformAdaptor uniformResolve(stage, *resolver, infoSink, hadError, intermediate); - TResolverInOutAdaptor inOutResolve(stage, *resolver, infoSink, hadError, intermediate); - resolver->beginNotifications(stage); - std::for_each(inVarMap.begin(), inVarMap.end(), inOutNotify); - std::for_each(outVarMap.begin(), outVarMap.end(), inOutNotify); - std::for_each(uniformVarMap.begin(), uniformVarMap.end(), uniformNotify); - resolver->endNotifications(stage); - resolver->beginResolve(stage); - std::for_each(inVarMap.begin(), inVarMap.end(), inOutResolve); - std::for_each(outVarMap.begin(), outVarMap.end(), inOutResolve); - std::for_each(uniformVarMap.begin(), uniformVarMap.end(), uniformResolve); - resolver->endResolve(stage); - - if (!hadError) { - // sort by id again, so we can use lower bound to find entries - std::sort(uniformVarMap.begin(), uniformVarMap.end(), TVarEntryInfo::TOrderById()); - TVarSetTraverser iter_iomap(intermediate, inVarMap, outVarMap, uniformVarMap); - root->traverse(&iter_iomap); - } - - return !hadError; -} - -} // end namespace glslang diff --git a/External/glslang/glslang/MachineIndependent/iomapper.h b/External/glslang/glslang/MachineIndependent/iomapper.h deleted file mode 100644 index 5e0d4391..00000000 --- a/External/glslang/glslang/MachineIndependent/iomapper.h +++ /dev/null @@ -1,63 +0,0 @@ -// -// 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 _IOMAPPER_INCLUDED -#define _IOMAPPER_INCLUDED - -#include "../Public/ShaderLang.h" - -// -// A reflection database and its interface, consistent with the OpenGL API reflection queries. -// - -class TInfoSink; - -namespace glslang { - -class TIntermediate; - -// I/O mapper -class TIoMapper { -public: - TIoMapper() {} - virtual ~TIoMapper() {} - - // grow the reflection stage by stage - bool addStage(EShLanguage, TIntermediate&, TInfoSink&, TIoMapResolver*); -}; - -} // end namespace glslang - -#endif // _IOMAPPER_INCLUDED diff --git a/External/glslang/glslang/MachineIndependent/limits.cpp b/External/glslang/glslang/MachineIndependent/limits.cpp deleted file mode 100644 index 64d191b4..00000000 --- a/External/glslang/glslang/MachineIndependent/limits.cpp +++ /dev/null @@ -1,198 +0,0 @@ -// -// 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. -// - -// -// Do sub tree walks for -// 1) inductive loop bodies to see if the inductive variable is modified -// 2) array-index expressions to see if they are "constant-index-expression" -// -// These are per Appendix A of ES 2.0: -// -// "Within the body of the loop, the loop index is not statically assigned to nor is it used as the -// argument to a function out or inout parameter." -// -// "The following are constant-index-expressions: -// - Constant expressions -// - Loop indices as defined in section 4 -// - Expressions composed of both of the above" -// -// N.B.: assuming the last rule excludes function calls -// - -#include "ParseHelper.h" - -namespace glslang { - -// -// The inductive loop-body traverser. -// -// Just look at things that might modify the loop index. -// - -class TInductiveTraverser : public TIntermTraverser { -public: - TInductiveTraverser(int id, TSymbolTable& st) - : loopId(id), symbolTable(st), bad(false) { } - - virtual bool visitBinary(TVisit, TIntermBinary* node); - virtual bool visitUnary(TVisit, TIntermUnary* node); - virtual bool visitAggregate(TVisit, TIntermAggregate* node); - - int loopId; // unique ID of the symbol that's the loop inductive variable - TSymbolTable& symbolTable; - bool bad; - TSourceLoc badLoc; - -protected: - TInductiveTraverser(TInductiveTraverser&); - TInductiveTraverser& operator=(TInductiveTraverser&); -}; - -// check binary operations for those modifying the loop index -bool TInductiveTraverser::visitBinary(TVisit /* visit */, TIntermBinary* node) -{ - if (node->modifiesState() && node->getLeft()->getAsSymbolNode() && - node->getLeft()->getAsSymbolNode()->getId() == loopId) { - bad = true; - badLoc = node->getLoc(); - } - - return true; -} - -// check unary operations for those modifying the loop index -bool TInductiveTraverser::visitUnary(TVisit /* visit */, TIntermUnary* node) -{ - if (node->modifiesState() && node->getOperand()->getAsSymbolNode() && - node->getOperand()->getAsSymbolNode()->getId() == loopId) { - bad = true; - badLoc = node->getLoc(); - } - - return true; -} - -// check function calls for arguments modifying the loop index -bool TInductiveTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node) -{ - if (node->getOp() == EOpFunctionCall) { - // see if an out or inout argument is the loop index - const TIntermSequence& args = node->getSequence(); - for (int i = 0; i < (int)args.size(); ++i) { - if (args[i]->getAsSymbolNode() && args[i]->getAsSymbolNode()->getId() == loopId) { - TSymbol* function = symbolTable.find(node->getName()); - const TType* type = (*function->getAsFunction())[i].type; - if (type->getQualifier().storage == EvqOut || - type->getQualifier().storage == EvqInOut) { - bad = true; - badLoc = node->getLoc(); - } - } - } - } - - return true; -} - -// -// External function to call for loop check. -// -void TParseContext::inductiveLoopBodyCheck(TIntermNode* body, int loopId, TSymbolTable& symbolTable) -{ - TInductiveTraverser it(loopId, symbolTable); - - if (body == nullptr) - return; - - body->traverse(&it); - - if (it.bad) - error(it.badLoc, "inductive loop index modified", "limitations", ""); -} - -// -// The "constant-index-expression" tranverser. -// -// Just look at things that can form an index. -// - -class TIndexTraverser : public TIntermTraverser { -public: - TIndexTraverser(const TIdSetType& ids) : inductiveLoopIds(ids), bad(false) { } - virtual void visitSymbol(TIntermSymbol* symbol); - virtual bool visitAggregate(TVisit, TIntermAggregate* node); - const TIdSetType& inductiveLoopIds; - bool bad; - TSourceLoc badLoc; - -protected: - TIndexTraverser(TIndexTraverser&); - TIndexTraverser& operator=(TIndexTraverser&); -}; - -// make sure symbols are inductive-loop indexes -void TIndexTraverser::visitSymbol(TIntermSymbol* symbol) -{ - if (inductiveLoopIds.find(symbol->getId()) == inductiveLoopIds.end()) { - bad = true; - badLoc = symbol->getLoc(); - } -} - -// check for function calls, assuming they are bad; spec. doesn't really say -bool TIndexTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node) -{ - if (node->getOp() == EOpFunctionCall) { - bad = true; - badLoc = node->getLoc(); - } - - return true; -} - -// -// External function to call for loop check. -// -void TParseContext::constantIndexExpressionCheck(TIntermNode* index) -{ - TIndexTraverser it(inductiveLoopIds); - - index->traverse(&it); - - if (it.bad) - error(it.badLoc, "Non-constant-index-expression", "limitations", ""); -} - -} // end namespace glslang diff --git a/External/glslang/glslang/MachineIndependent/linkValidate.cpp b/External/glslang/glslang/MachineIndependent/linkValidate.cpp deleted file mode 100644 index c540ae64..00000000 --- a/External/glslang/glslang/MachineIndependent/linkValidate.cpp +++ /dev/null @@ -1,1286 +0,0 @@ -// -// 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. -// - -// -// Do link-time merging and validation of intermediate representations. -// -// Basic model is that during compilation, each compilation unit (shader) is -// compiled into one TIntermediate instance. Then, at link time, multiple -// units for the same stage can be merged together, which can generate errors. -// Then, after all merging, a single instance of TIntermediate represents -// the whole stage. A final error check can be done on the resulting stage, -// even if no merging was done (i.e., the stage was only one compilation unit). -// - -#include "localintermediate.h" -#include "../Include/InfoSink.h" - -namespace glslang { - -// -// Link-time error emitter. -// -void TIntermediate::error(TInfoSink& infoSink, const char* message) -{ - infoSink.info.prefix(EPrefixError); - infoSink.info << "Linking " << StageName(language) << " stage: " << message << "\n"; - - ++numErrors; -} - -// Link-time warning. -void TIntermediate::warn(TInfoSink& infoSink, const char* message) -{ - infoSink.info.prefix(EPrefixWarning); - infoSink.info << "Linking " << StageName(language) << " stage: " << message << "\n"; -} - -// TODO: 4.4 offset/align: "Two blocks linked together in the same program with the same block -// name must have the exact same set of members qualified with offset and their integral-constant -// expression values must be the same, or a link-time error results." - -// -// Merge the information from 'unit' into 'this' -// -void TIntermediate::merge(TInfoSink& infoSink, TIntermediate& unit) -{ - if (source == EShSourceNone) - source = unit.source; - - if (source != unit.source) - error(infoSink, "can't link compilation units from different source languages"); - - if (unit.getNumEntryPoints() > 0) { - if (getNumEntryPoints() > 0) - error(infoSink, "can't handle multiple entry points per stage"); - else { - entryPointName = unit.getEntryPointName(); - entryPointMangledName = unit.getEntryPointMangledName(); - } - } - numEntryPoints += unit.getNumEntryPoints(); - numErrors += unit.getNumErrors(); - numPushConstants += unit.numPushConstants; - callGraph.insert(callGraph.end(), unit.callGraph.begin(), unit.callGraph.end()); - - if (originUpperLeft != unit.originUpperLeft || pixelCenterInteger != unit.pixelCenterInteger) - error(infoSink, "gl_FragCoord redeclarations must match across shaders"); - - if (! earlyFragmentTests) - earlyFragmentTests = unit.earlyFragmentTests; - - if (!postDepthCoverage) - postDepthCoverage = unit.postDepthCoverage; - - if (depthLayout == EldNone) - depthLayout = unit.depthLayout; - else if (depthLayout != unit.depthLayout) - error(infoSink, "Contradictory depth layouts"); - - blendEquations |= unit.blendEquations; - - if (inputPrimitive == ElgNone) - inputPrimitive = unit.inputPrimitive; - else if (inputPrimitive != unit.inputPrimitive) - error(infoSink, "Contradictory input layout primitives"); - - if (outputPrimitive == ElgNone) - outputPrimitive = unit.outputPrimitive; - else if (outputPrimitive != unit.outputPrimitive) - error(infoSink, "Contradictory output layout primitives"); - - if (vertices == TQualifier::layoutNotSet) - vertices = unit.vertices; - else if (vertices != unit.vertices) { - if (language == EShLangGeometry) - error(infoSink, "Contradictory layout max_vertices values"); - else if (language == EShLangTessControl) - error(infoSink, "Contradictory layout vertices values"); - else - assert(0); - } - - if (vertexSpacing == EvsNone) - vertexSpacing = unit.vertexSpacing; - else if (vertexSpacing != unit.vertexSpacing) - error(infoSink, "Contradictory input vertex spacing"); - - if (vertexOrder == EvoNone) - vertexOrder = unit.vertexOrder; - else if (vertexOrder != unit.vertexOrder) - error(infoSink, "Contradictory triangle ordering"); - - if (unit.pointMode) - pointMode = true; - - for (int i = 0; i < 3; ++i) { - if (localSize[i] > 1) - localSize[i] = unit.localSize[i]; - else if (localSize[i] != unit.localSize[i]) - error(infoSink, "Contradictory local size"); - - if (localSizeSpecId[i] != TQualifier::layoutNotSet) - localSizeSpecId[i] = unit.localSizeSpecId[i]; - else if (localSizeSpecId[i] != unit.localSizeSpecId[i]) - error(infoSink, "Contradictory local size specialization ids"); - } - - if (unit.xfbMode) - xfbMode = true; - for (size_t b = 0; b < xfbBuffers.size(); ++b) { - if (xfbBuffers[b].stride == TQualifier::layoutXfbStrideEnd) - xfbBuffers[b].stride = unit.xfbBuffers[b].stride; - else if (xfbBuffers[b].stride != unit.xfbBuffers[b].stride) - error(infoSink, "Contradictory xfb_stride"); - xfbBuffers[b].implicitStride = std::max(xfbBuffers[b].implicitStride, unit.xfbBuffers[b].implicitStride); - if (unit.xfbBuffers[b].containsDouble) - xfbBuffers[b].containsDouble = true; - // TODO: 4.4 link: enhanced layouts: compare ranges - } - - if (unit.treeRoot == 0) - return; - - if (treeRoot == 0) { - treeRoot = unit.treeRoot; - version = unit.version; - requestedExtensions = unit.requestedExtensions; - return; - } - - // Getting this far means we have two existing trees to merge... - - version = std::max(version, unit.version); - requestedExtensions.insert(unit.requestedExtensions.begin(), unit.requestedExtensions.end()); - - // Get the top-level globals of each unit - TIntermSequence& globals = treeRoot->getAsAggregate()->getSequence(); - TIntermSequence& unitGlobals = unit.treeRoot->getAsAggregate()->getSequence(); - - // Get the linker-object lists - TIntermSequence& linkerObjects = findLinkerObjects(); - TIntermSequence& unitLinkerObjects = unit.findLinkerObjects(); - - mergeBodies(infoSink, globals, unitGlobals); - mergeLinkerObjects(infoSink, linkerObjects, unitLinkerObjects); - - ioAccessed.insert(unit.ioAccessed.begin(), unit.ioAccessed.end()); -} - -// -// Merge the function bodies and global-level initializers from unitGlobals into globals. -// Will error check duplication of function bodies for the same signature. -// -void TIntermediate::mergeBodies(TInfoSink& infoSink, TIntermSequence& globals, const TIntermSequence& unitGlobals) -{ - // TODO: link-time performance: Processing in alphabetical order will be faster - - // Error check the global objects, not including the linker objects - for (unsigned int child = 0; child < globals.size() - 1; ++child) { - for (unsigned int unitChild = 0; unitChild < unitGlobals.size() - 1; ++unitChild) { - TIntermAggregate* body = globals[child]->getAsAggregate(); - TIntermAggregate* unitBody = unitGlobals[unitChild]->getAsAggregate(); - if (body && unitBody && body->getOp() == EOpFunction && unitBody->getOp() == EOpFunction && body->getName() == unitBody->getName()) { - error(infoSink, "Multiple function bodies in multiple compilation units for the same signature in the same stage:"); - infoSink.info << " " << globals[child]->getAsAggregate()->getName() << "\n"; - } - } - } - - // Merge the global objects, just in front of the linker objects - globals.insert(globals.end() - 1, unitGlobals.begin(), unitGlobals.end() - 1); -} - -// -// Merge the linker objects from unitLinkerObjects into linkerObjects. -// Duplication is expected and filtered out, but contradictions are an error. -// -void TIntermediate::mergeLinkerObjects(TInfoSink& infoSink, TIntermSequence& linkerObjects, const TIntermSequence& unitLinkerObjects) -{ - // Error check and merge the linker objects (duplicates should not be created) - std::size_t initialNumLinkerObjects = linkerObjects.size(); - for (unsigned int unitLinkObj = 0; unitLinkObj < unitLinkerObjects.size(); ++unitLinkObj) { - bool merge = true; - for (std::size_t linkObj = 0; linkObj < initialNumLinkerObjects; ++linkObj) { - TIntermSymbol* symbol = linkerObjects[linkObj]->getAsSymbolNode(); - TIntermSymbol* unitSymbol = unitLinkerObjects[unitLinkObj]->getAsSymbolNode(); - assert(symbol && unitSymbol); - if (symbol->getName() == unitSymbol->getName()) { - // filter out copy - merge = false; - - // but if one has an initializer and the other does not, update - // the initializer - if (symbol->getConstArray().empty() && ! unitSymbol->getConstArray().empty()) - symbol->setConstArray(unitSymbol->getConstArray()); - - // Similarly for binding - if (! symbol->getQualifier().hasBinding() && unitSymbol->getQualifier().hasBinding()) - symbol->getQualifier().layoutBinding = unitSymbol->getQualifier().layoutBinding; - - // Update implicit array sizes - mergeImplicitArraySizes(symbol->getWritableType(), unitSymbol->getType()); - - // Check for consistent types/qualification/initializers etc. - mergeErrorCheck(infoSink, *symbol, *unitSymbol, false); - } - } - if (merge) - linkerObjects.push_back(unitLinkerObjects[unitLinkObj]); - } -} - -// TODO 4.5 link functionality: cull distance array size checking - -// Recursively merge the implicit array sizes through the objects' respective type trees. -void TIntermediate::mergeImplicitArraySizes(TType& type, const TType& unitType) -{ - if (type.isUnsizedArray()) { - if (unitType.isUnsizedArray()) { - type.updateImplicitArraySize(unitType.getImplicitArraySize()); - if (unitType.isArrayVariablyIndexed()) - type.setArrayVariablyIndexed(); - } else if (unitType.isSizedArray()) - type.changeOuterArraySize(unitType.getOuterArraySize()); - } - - // Type mismatches are caught and reported after this, just be careful for now. - if (! type.isStruct() || ! unitType.isStruct() || type.getStruct()->size() != unitType.getStruct()->size()) - return; - - for (int i = 0; i < (int)type.getStruct()->size(); ++i) - mergeImplicitArraySizes(*(*type.getStruct())[i].type, *(*unitType.getStruct())[i].type); -} - -// -// Compare two global objects from two compilation units and see if they match -// well enough. Rules can be different for intra- vs. cross-stage matching. -// -// This function only does one of intra- or cross-stage matching per call. -// -void TIntermediate::mergeErrorCheck(TInfoSink& infoSink, const TIntermSymbol& symbol, const TIntermSymbol& unitSymbol, bool crossStage) -{ - bool writeTypeComparison = false; - - // Types have to match - if (symbol.getType() != unitSymbol.getType()) { - // but, we make an exception if one is an implicit array and the other is sized - if (! (symbol.getType().isArray() && unitSymbol.getType().isArray() && - symbol.getType().sameElementType(unitSymbol.getType()) && - (symbol.getType().isUnsizedArray() || unitSymbol.getType().isUnsizedArray()))) { - error(infoSink, "Types must match:"); - writeTypeComparison = true; - } - } - - // Qualifiers have to (almost) match - - // Storage... - if (symbol.getQualifier().storage != unitSymbol.getQualifier().storage) { - error(infoSink, "Storage qualifiers must match:"); - writeTypeComparison = true; - } - - // Precision... - if (symbol.getQualifier().precision != unitSymbol.getQualifier().precision) { - error(infoSink, "Precision qualifiers must match:"); - writeTypeComparison = true; - } - - // Invariance... - if (! crossStage && symbol.getQualifier().invariant != unitSymbol.getQualifier().invariant) { - error(infoSink, "Presence of invariant qualifier must match:"); - writeTypeComparison = true; - } - - // Precise... - if (! crossStage && symbol.getQualifier().noContraction != unitSymbol.getQualifier().noContraction) { - error(infoSink, "Presence of precise qualifier must match:"); - writeTypeComparison = true; - } - - // Auxiliary and interpolation... - if (symbol.getQualifier().centroid != unitSymbol.getQualifier().centroid || - symbol.getQualifier().smooth != unitSymbol.getQualifier().smooth || - symbol.getQualifier().flat != unitSymbol.getQualifier().flat || - symbol.getQualifier().sample != unitSymbol.getQualifier().sample || - symbol.getQualifier().patch != unitSymbol.getQualifier().patch || - symbol.getQualifier().nopersp != unitSymbol.getQualifier().nopersp) { - error(infoSink, "Interpolation and auxiliary storage qualifiers must match:"); - writeTypeComparison = true; - } - - // Memory... - if (symbol.getQualifier().coherent != unitSymbol.getQualifier().coherent || - symbol.getQualifier().volatil != unitSymbol.getQualifier().volatil || - symbol.getQualifier().restrict != unitSymbol.getQualifier().restrict || - symbol.getQualifier().readonly != unitSymbol.getQualifier().readonly || - symbol.getQualifier().writeonly != unitSymbol.getQualifier().writeonly) { - error(infoSink, "Memory qualifiers must match:"); - writeTypeComparison = true; - } - - // Layouts... - // TODO: 4.4 enhanced layouts: Generalize to include offset/align: current spec - // requires separate user-supplied offset from actual computed offset, but - // current implementation only has one offset. - if (symbol.getQualifier().layoutMatrix != unitSymbol.getQualifier().layoutMatrix || - symbol.getQualifier().layoutPacking != unitSymbol.getQualifier().layoutPacking || - symbol.getQualifier().layoutLocation != unitSymbol.getQualifier().layoutLocation || - symbol.getQualifier().layoutComponent != unitSymbol.getQualifier().layoutComponent || - symbol.getQualifier().layoutIndex != unitSymbol.getQualifier().layoutIndex || - symbol.getQualifier().layoutBinding != unitSymbol.getQualifier().layoutBinding || - (symbol.getQualifier().hasBinding() && (symbol.getQualifier().layoutOffset != unitSymbol.getQualifier().layoutOffset))) { - error(infoSink, "Layout qualification must match:"); - writeTypeComparison = true; - } - - // Initializers have to match, if both are present, and if we don't already know the types don't match - if (! writeTypeComparison) { - if (! symbol.getConstArray().empty() && ! unitSymbol.getConstArray().empty()) { - if (symbol.getConstArray() != unitSymbol.getConstArray()) { - error(infoSink, "Initializers must match:"); - infoSink.info << " " << symbol.getName() << "\n"; - } - } - } - - if (writeTypeComparison) - infoSink.info << " " << symbol.getName() << ": \"" << symbol.getType().getCompleteString() << "\" versus \"" << - unitSymbol.getType().getCompleteString() << "\"\n"; -} - -// -// Do final link-time error checking of a complete (merged) intermediate representation. -// (Much error checking was done during merging). -// -// Also, lock in defaults of things not set, including array sizes. -// -void TIntermediate::finalCheck(TInfoSink& infoSink, bool keepUncalled) -{ - if (getTreeRoot() == nullptr) - return; - - if (numEntryPoints < 1) { - if (source == EShSourceGlsl) - error(infoSink, "Missing entry point: Each stage requires one entry point"); - else - warn(infoSink, "Entry point not found"); - } - - if (numPushConstants > 1) - error(infoSink, "Only one push_constant block is allowed per stage"); - - // recursion and missing body checking - checkCallGraphCycles(infoSink); - checkCallGraphBodies(infoSink, keepUncalled); - - // overlap/alias/missing I/O, etc. - inOutLocationCheck(infoSink); - - // invocations - if (invocations == TQualifier::layoutNotSet) - invocations = 1; - - if (inIoAccessed("gl_ClipDistance") && inIoAccessed("gl_ClipVertex")) - error(infoSink, "Can only use one of gl_ClipDistance or gl_ClipVertex (gl_ClipDistance is preferred)"); - if (inIoAccessed("gl_CullDistance") && inIoAccessed("gl_ClipVertex")) - error(infoSink, "Can only use one of gl_CullDistance or gl_ClipVertex (gl_ClipDistance is preferred)"); - - if (userOutputUsed() && (inIoAccessed("gl_FragColor") || inIoAccessed("gl_FragData"))) - error(infoSink, "Cannot use gl_FragColor or gl_FragData when using user-defined outputs"); - if (inIoAccessed("gl_FragColor") && inIoAccessed("gl_FragData")) - error(infoSink, "Cannot use both gl_FragColor and gl_FragData"); - - for (size_t b = 0; b < xfbBuffers.size(); ++b) { - if (xfbBuffers[b].containsDouble) - RoundToPow2(xfbBuffers[b].implicitStride, 8); - - // "It is a compile-time or link-time error to have - // any xfb_offset that overflows xfb_stride, whether stated on declarations before or after the xfb_stride, or - // in different compilation units. While xfb_stride can be declared multiple times for the same buffer, it is a - // compile-time or link-time error to have different values specified for the stride for the same buffer." - if (xfbBuffers[b].stride != TQualifier::layoutXfbStrideEnd && xfbBuffers[b].implicitStride > xfbBuffers[b].stride) { - error(infoSink, "xfb_stride is too small to hold all buffer entries:"); - infoSink.info.prefix(EPrefixError); - infoSink.info << " xfb_buffer " << (unsigned int)b << ", xfb_stride " << xfbBuffers[b].stride << ", minimum stride needed: " << xfbBuffers[b].implicitStride << "\n"; - } - if (xfbBuffers[b].stride == TQualifier::layoutXfbStrideEnd) - xfbBuffers[b].stride = xfbBuffers[b].implicitStride; - - // "If the buffer is capturing any - // outputs with double-precision components, the stride must be a multiple of 8, otherwise it must be a - // multiple of 4, or a compile-time or link-time error results." - if (xfbBuffers[b].containsDouble && ! IsMultipleOfPow2(xfbBuffers[b].stride, 8)) { - error(infoSink, "xfb_stride must be multiple of 8 for buffer holding a double:"); - infoSink.info.prefix(EPrefixError); - infoSink.info << " xfb_buffer " << (unsigned int)b << ", xfb_stride " << xfbBuffers[b].stride << "\n"; - } else if (! IsMultipleOfPow2(xfbBuffers[b].stride, 4)) { - error(infoSink, "xfb_stride must be multiple of 4:"); - infoSink.info.prefix(EPrefixError); - infoSink.info << " xfb_buffer " << (unsigned int)b << ", xfb_stride " << xfbBuffers[b].stride << "\n"; - } - - // "The resulting stride (implicit or explicit), when divided by 4, must be less than or equal to the - // implementation-dependent constant gl_MaxTransformFeedbackInterleavedComponents." - if (xfbBuffers[b].stride > (unsigned int)(4 * resources.maxTransformFeedbackInterleavedComponents)) { - error(infoSink, "xfb_stride is too large:"); - infoSink.info.prefix(EPrefixError); - infoSink.info << " xfb_buffer " << (unsigned int)b << ", components (1/4 stride) needed are " << xfbBuffers[b].stride/4 << ", gl_MaxTransformFeedbackInterleavedComponents is " << resources.maxTransformFeedbackInterleavedComponents << "\n"; - } - } - - switch (language) { - case EShLangVertex: - break; - case EShLangTessControl: - if (vertices == TQualifier::layoutNotSet) - error(infoSink, "At least one shader must specify an output layout(vertices=...)"); - break; - case EShLangTessEvaluation: - if (source == EShSourceGlsl) { - if (inputPrimitive == ElgNone) - error(infoSink, "At least one shader must specify an input layout primitive"); - if (vertexSpacing == EvsNone) - vertexSpacing = EvsEqual; - if (vertexOrder == EvoNone) - vertexOrder = EvoCcw; - } - break; - case EShLangGeometry: - if (inputPrimitive == ElgNone) - error(infoSink, "At least one shader must specify an input layout primitive"); - if (outputPrimitive == ElgNone -#ifdef NV_EXTENSIONS - && !getGeoPassthroughEXT() -#endif - ) - error(infoSink, "At least one shader must specify an output layout primitive"); - if (vertices == TQualifier::layoutNotSet -#ifdef NV_EXTENSIONS - && !getGeoPassthroughEXT() -#endif - ) - error(infoSink, "At least one shader must specify a layout(max_vertices = value)"); - break; - case EShLangFragment: - // for GL_ARB_post_depth_coverage, EarlyFragmentTest is set automatically in - // ParseHelper.cpp. So if we reach here, this must be GL_EXT_post_depth_coverage - // requiring explicit early_fragment_tests - if (getPostDepthCoverage() && !getEarlyFragmentTests()) - error(infoSink, "post_depth_coverage requires early_fragment_tests"); - break; - case EShLangCompute: - break; - default: - error(infoSink, "Unknown Stage."); - break; - } - - // Process the tree for any node-specific work. - class TFinalLinkTraverser : public TIntermTraverser { - public: - TFinalLinkTraverser() { } - virtual ~TFinalLinkTraverser() { } - - virtual void visitSymbol(TIntermSymbol* symbol) - { - // Implicitly size arrays. - // If an unsized array is left as unsized, it effectively - // becomes run-time sized. - symbol->getWritableType().adoptImplicitArraySizes(false); - } - } finalLinkTraverser; - - treeRoot->traverse(&finalLinkTraverser); -} - -// -// See if the call graph contains any static recursion, which is disallowed -// by the specification. -// -void TIntermediate::checkCallGraphCycles(TInfoSink& infoSink) -{ - // Clear fields we'll use for this. - for (TGraph::iterator call = callGraph.begin(); call != callGraph.end(); ++call) { - call->visited = false; - call->currentPath = false; - call->errorGiven = false; - } - - // - // Loop, looking for a new connected subgraph. One subgraph is handled per loop iteration. - // - - TCall* newRoot; - do { - // See if we have unvisited parts of the graph. - newRoot = 0; - for (TGraph::iterator call = callGraph.begin(); call != callGraph.end(); ++call) { - if (! call->visited) { - newRoot = &(*call); - break; - } - } - - // If not, we are done. - if (! newRoot) - break; - - // Otherwise, we found a new subgraph, process it: - // See what all can be reached by this new root, and if any of - // that is recursive. This is done by depth-first traversals, seeing - // if a new call is found that was already in the currentPath (a back edge), - // thereby detecting recursion. - std::list stack; - newRoot->currentPath = true; // currentPath will be true iff it is on the stack - stack.push_back(newRoot); - while (! stack.empty()) { - // get a caller - TCall* call = stack.back(); - - // Add to the stack just one callee. - // This algorithm always terminates, because only !visited and !currentPath causes a push - // and all pushes change currentPath to true, and all pops change visited to true. - TGraph::iterator child = callGraph.begin(); - for (; child != callGraph.end(); ++child) { - - // If we already visited this node, its whole subgraph has already been processed, so skip it. - if (child->visited) - continue; - - if (call->callee == child->caller) { - if (child->currentPath) { - // Then, we found a back edge - if (! child->errorGiven) { - error(infoSink, "Recursion detected:"); - infoSink.info << " " << call->callee << " calling " << child->callee << "\n"; - child->errorGiven = true; - recursive = true; - } - } else { - child->currentPath = true; - stack.push_back(&(*child)); - break; - } - } - } - if (child == callGraph.end()) { - // no more callees, we bottomed out, never look at this node again - stack.back()->currentPath = false; - stack.back()->visited = true; - stack.pop_back(); - } - } // end while, meaning nothing left to process in this subtree - - } while (newRoot); // redundant loop check; should always exit via the 'break' above -} - -// -// See which functions are reachable from the entry point and which have bodies. -// Reachable ones with missing bodies are errors. -// Unreachable bodies are dead code. -// -void TIntermediate::checkCallGraphBodies(TInfoSink& infoSink, bool keepUncalled) -{ - // Clear fields we'll use for this. - for (TGraph::iterator call = callGraph.begin(); call != callGraph.end(); ++call) { - call->visited = false; - call->calleeBodyPosition = -1; - } - - // The top level of the AST includes function definitions (bodies). - // Compare these to function calls in the call graph. - // We'll end up knowing which have bodies, and if so, - // how to map the call-graph node to the location in the AST. - TIntermSequence &functionSequence = getTreeRoot()->getAsAggregate()->getSequence(); - std::vector reachable(functionSequence.size(), true); // so that non-functions are reachable - for (int f = 0; f < (int)functionSequence.size(); ++f) { - glslang::TIntermAggregate* node = functionSequence[f]->getAsAggregate(); - if (node && (node->getOp() == glslang::EOpFunction)) { - if (node->getName().compare(getEntryPointMangledName().c_str()) != 0) - reachable[f] = false; // so that function bodies are unreachable, until proven otherwise - for (TGraph::iterator call = callGraph.begin(); call != callGraph.end(); ++call) { - if (call->callee == node->getName()) - call->calleeBodyPosition = f; - } - } - } - - // Start call-graph traversal by visiting the entry point nodes. - for (TGraph::iterator call = callGraph.begin(); call != callGraph.end(); ++call) { - if (call->caller.compare(getEntryPointMangledName().c_str()) == 0) - call->visited = true; - } - - // Propagate 'visited' through the call-graph to every part of the graph it - // can reach (seeded with the entry-point setting above). - bool changed; - do { - changed = false; - for (auto call1 = callGraph.begin(); call1 != callGraph.end(); ++call1) { - if (call1->visited) { - for (TGraph::iterator call2 = callGraph.begin(); call2 != callGraph.end(); ++call2) { - if (! call2->visited) { - if (call1->callee == call2->caller) { - changed = true; - call2->visited = true; - } - } - } - } - } - } while (changed); - - // Any call-graph node set to visited but without a callee body is an error. - for (TGraph::iterator call = callGraph.begin(); call != callGraph.end(); ++call) { - if (call->visited) { - if (call->calleeBodyPosition == -1) { - error(infoSink, "No function definition (body) found: "); - infoSink.info << " " << call->callee << "\n"; - } else - reachable[call->calleeBodyPosition] = true; - } - } - - // Bodies in the AST not reached by the call graph are dead; - // clear them out, since they can't be reached and also can't - // be translated further due to possibility of being ill defined. - if (! keepUncalled) { - for (int f = 0; f < (int)functionSequence.size(); ++f) { - if (! reachable[f]) - functionSequence[f] = nullptr; - } - functionSequence.erase(std::remove(functionSequence.begin(), functionSequence.end(), nullptr), functionSequence.end()); - } -} - -// -// Satisfy rules for location qualifiers on inputs and outputs -// -void TIntermediate::inOutLocationCheck(TInfoSink& infoSink) -{ - // ES 3.0 requires all outputs to have location qualifiers if there is more than one output - bool fragOutWithNoLocation = false; - int numFragOut = 0; - - // TODO: linker functionality: location collision checking - - TIntermSequence& linkObjects = findLinkerObjects(); - for (size_t i = 0; i < linkObjects.size(); ++i) { - const TType& type = linkObjects[i]->getAsTyped()->getType(); - const TQualifier& qualifier = type.getQualifier(); - if (language == EShLangFragment) { - if (qualifier.storage == EvqVaryingOut && qualifier.builtIn == EbvNone) { - ++numFragOut; - if (!qualifier.hasAnyLocation()) - fragOutWithNoLocation = true; - } - } - } - - if (profile == EEsProfile) { - if (numFragOut > 1 && fragOutWithNoLocation) - error(infoSink, "when more than one fragment shader output, all must have location qualifiers"); - } -} - -TIntermSequence& TIntermediate::findLinkerObjects() const -{ - // Get the top-level globals - TIntermSequence& globals = treeRoot->getAsAggregate()->getSequence(); - - // Get the last member of the sequences, expected to be the linker-object lists - assert(globals.back()->getAsAggregate()->getOp() == EOpLinkerObjects); - - return globals.back()->getAsAggregate()->getSequence(); -} - -// See if a variable was both a user-declared output and used. -// Note: the spec discusses writing to one, but this looks at read or write, which -// is more useful, and perhaps the spec should be changed to reflect that. -bool TIntermediate::userOutputUsed() const -{ - const TIntermSequence& linkerObjects = findLinkerObjects(); - - bool found = false; - for (size_t i = 0; i < linkerObjects.size(); ++i) { - const TIntermSymbol& symbolNode = *linkerObjects[i]->getAsSymbolNode(); - if (symbolNode.getQualifier().storage == EvqVaryingOut && - symbolNode.getName().compare(0, 3, "gl_") != 0 && - inIoAccessed(symbolNode.getName())) { - found = true; - break; - } - } - - return found; -} - -// Accumulate locations used for inputs, outputs, and uniforms, and check for collisions -// as the accumulation is done. -// -// Returns < 0 if no collision, >= 0 if collision and the value returned is a colliding value. -// -// typeCollision is set to true if there is no direct collision, but the types in the same location -// are different. -// -int TIntermediate::addUsedLocation(const TQualifier& qualifier, const TType& type, bool& typeCollision) -{ - typeCollision = false; - - int set; - if (qualifier.isPipeInput()) - set = 0; - else if (qualifier.isPipeOutput()) - set = 1; - else if (qualifier.storage == EvqUniform) - set = 2; - else if (qualifier.storage == EvqBuffer) - set = 3; - else - return -1; - - int size; - if (qualifier.isUniformOrBuffer()) { - if (type.isSizedArray()) - size = type.getCumulativeArraySize(); - else - size = 1; - } else { - // Strip off the outer array dimension for those having an extra one. - if (type.isArray() && qualifier.isArrayedIo(language)) { - TType elementType(type, 0); - size = computeTypeLocationSize(elementType, language); - } else - size = computeTypeLocationSize(type, language); - } - - // Locations, and components within locations. - // - // Almost always, dealing with components means a single location is involved. - // The exception is a dvec3. From the spec: - // - // "A dvec3 will consume all four components of the first location and components 0 and 1 of - // the second location. This leaves components 2 and 3 available for other component-qualified - // declarations." - // - // That means, without ever mentioning a component, a component range - // for a different location gets specified, if it's not a vertex shader input. (!) - // (A vertex shader input will show using only one location, even for a dvec3/4.) - // - // So, for the case of dvec3, we need two independent ioRanges. - - int collision = -1; // no collision - if (size == 2 && type.getBasicType() == EbtDouble && type.getVectorSize() == 3 && - (qualifier.isPipeInput() || qualifier.isPipeOutput())) { - // Dealing with dvec3 in/out split across two locations. - // Need two io-ranges. - // The case where the dvec3 doesn't start at component 0 was previously caught as overflow. - - // First range: - TRange locationRange(qualifier.layoutLocation, qualifier.layoutLocation); - TRange componentRange(0, 3); - TIoRange range(locationRange, componentRange, type.getBasicType(), 0); - - // check for collisions - collision = checkLocationRange(set, range, type, typeCollision); - if (collision < 0) { - usedIo[set].push_back(range); - - // Second range: - TRange locationRange2(qualifier.layoutLocation + 1, qualifier.layoutLocation + 1); - TRange componentRange2(0, 1); - TIoRange range2(locationRange2, componentRange2, type.getBasicType(), 0); - - // check for collisions - collision = checkLocationRange(set, range2, type, typeCollision); - if (collision < 0) - usedIo[set].push_back(range2); - } - } else { - // Not a dvec3 in/out split across two locations, generic path. - // Need a single IO-range block. - - TRange locationRange(qualifier.layoutLocation, qualifier.layoutLocation + size - 1); - TRange componentRange(0, 3); - if (qualifier.hasComponent() || type.getVectorSize() > 0) { - int consumedComponents = type.getVectorSize() * (type.getBasicType() == EbtDouble ? 2 : 1); - if (qualifier.hasComponent()) - componentRange.start = qualifier.layoutComponent; - componentRange.last = componentRange.start + consumedComponents - 1; - } - - // combine location and component ranges - TIoRange range(locationRange, componentRange, type.getBasicType(), qualifier.hasIndex() ? qualifier.layoutIndex : 0); - - // check for collisions, except for vertex inputs on desktop targeting OpenGL - if (! (profile != EEsProfile && language == EShLangVertex && qualifier.isPipeInput()) || spvVersion.vulkan > 0) - collision = checkLocationRange(set, range, type, typeCollision); - - if (collision < 0) - usedIo[set].push_back(range); - } - - return collision; -} - -// Compare a new (the passed in) 'range' against the existing set, and see -// if there are any collisions. -// -// Returns < 0 if no collision, >= 0 if collision and the value returned is a colliding value. -// -int TIntermediate::checkLocationRange(int set, const TIoRange& range, const TType& type, bool& typeCollision) -{ - for (size_t r = 0; r < usedIo[set].size(); ++r) { - if (range.overlap(usedIo[set][r])) { - // there is a collision; pick one - return std::max(range.location.start, usedIo[set][r].location.start); - } else if (range.location.overlap(usedIo[set][r].location) && type.getBasicType() != usedIo[set][r].basicType) { - // aliased-type mismatch - typeCollision = true; - return std::max(range.location.start, usedIo[set][r].location.start); - } - } - - return -1; // no collision -} - -// Accumulate bindings and offsets, and check for collisions -// as the accumulation is done. -// -// Returns < 0 if no collision, >= 0 if collision and the value returned is a colliding value. -// -int TIntermediate::addUsedOffsets(int binding, int offset, int numOffsets) -{ - TRange bindingRange(binding, binding); - TRange offsetRange(offset, offset + numOffsets - 1); - TOffsetRange range(bindingRange, offsetRange); - - // check for collisions, except for vertex inputs on desktop - for (size_t r = 0; r < usedAtomics.size(); ++r) { - if (range.overlap(usedAtomics[r])) { - // there is a collision; pick one - return std::max(offset, usedAtomics[r].offset.start); - } - } - - usedAtomics.push_back(range); - - return -1; // no collision -} - -// Accumulate used constant_id values. -// -// Return false is one was already used. -bool TIntermediate::addUsedConstantId(int id) -{ - if (usedConstantId.find(id) != usedConstantId.end()) - return false; - - usedConstantId.insert(id); - - return true; -} - -// Recursively figure out how many locations are used up by an input or output type. -// Return the size of type, as measured by "locations". -int TIntermediate::computeTypeLocationSize(const TType& type, EShLanguage stage) -{ - // "If the declared input is an array of size n and each element takes m locations, it will be assigned m * n - // consecutive locations..." - if (type.isArray()) { - // TODO: perf: this can be flattened by using getCumulativeArraySize(), and a deref that discards all arrayness - // TODO: are there valid cases of having an unsized array with a location? If so, running this code too early. - TType elementType(type, 0); - if (type.isSizedArray()) - return type.getOuterArraySize() * computeTypeLocationSize(elementType, stage); - else - return computeTypeLocationSize(elementType, stage); - } - - // "The locations consumed by block and structure members are determined by applying the rules above - // recursively..." - if (type.isStruct()) { - int size = 0; - for (int member = 0; member < (int)type.getStruct()->size(); ++member) { - TType memberType(type, member); - size += computeTypeLocationSize(memberType, stage); - } - return size; - } - - // ES: "If a shader input is any scalar or vector type, it will consume a single location." - - // Desktop: "If a vertex shader input is any scalar or vector type, it will consume a single location. If a non-vertex - // shader input is a scalar or vector type other than dvec3 or dvec4, it will consume a single location, while - // types dvec3 or dvec4 will consume two consecutive locations. Inputs of type double and dvec2 will - // consume only a single location, in all stages." - if (type.isScalar()) - return 1; - if (type.isVector()) { - if (stage == EShLangVertex && type.getQualifier().isPipeInput()) - return 1; - if (type.getBasicType() == EbtDouble && type.getVectorSize() > 2) - return 2; - else - return 1; - } - - // "If the declared input is an n x m single- or double-precision matrix, ... - // The number of locations assigned for each matrix will be the same as - // for an n-element array of m-component vectors..." - if (type.isMatrix()) { - TType columnType(type, 0); - return type.getMatrixCols() * computeTypeLocationSize(columnType, stage); - } - - assert(0); - return 1; -} - -// Same as computeTypeLocationSize but for uniforms -int TIntermediate::computeTypeUniformLocationSize(const TType& type) -{ - // "Individual elements of a uniform array are assigned - // consecutive locations with the first element taking location - // location." - if (type.isArray()) { - // TODO: perf: this can be flattened by using getCumulativeArraySize(), and a deref that discards all arrayness - TType elementType(type, 0); - if (type.isSizedArray()) { - return type.getOuterArraySize() * computeTypeUniformLocationSize(elementType); - } else { - // TODO: are there valid cases of having an implicitly-sized array with a location? If so, running this code too early. - return computeTypeUniformLocationSize(elementType); - } - } - - // "Each subsequent inner-most member or element gets incremental - // locations for the entire structure or array." - if (type.isStruct()) { - int size = 0; - for (int member = 0; member < (int)type.getStruct()->size(); ++member) { - TType memberType(type, member); - size += computeTypeUniformLocationSize(memberType); - } - return size; - } - - return 1; -} - -// Accumulate xfb buffer ranges and check for collisions as the accumulation is done. -// -// Returns < 0 if no collision, >= 0 if collision and the value returned is a colliding value. -// -int TIntermediate::addXfbBufferOffset(const TType& type) -{ - const TQualifier& qualifier = type.getQualifier(); - - assert(qualifier.hasXfbOffset() && qualifier.hasXfbBuffer()); - TXfbBuffer& buffer = xfbBuffers[qualifier.layoutXfbBuffer]; - - // compute the range - unsigned int size = computeTypeXfbSize(type, buffer.containsDouble); - buffer.implicitStride = std::max(buffer.implicitStride, qualifier.layoutXfbOffset + size); - TRange range(qualifier.layoutXfbOffset, qualifier.layoutXfbOffset + size - 1); - - // check for collisions - for (size_t r = 0; r < buffer.ranges.size(); ++r) { - if (range.overlap(buffer.ranges[r])) { - // there is a collision; pick an example to return - return std::max(range.start, buffer.ranges[r].start); - } - } - - buffer.ranges.push_back(range); - - return -1; // no collision -} - -// Recursively figure out how many bytes of xfb buffer are used by the given type. -// Return the size of type, in bytes. -// Sets containsDouble to true if the type contains a double. -// N.B. Caller must set containsDouble to false before calling. -unsigned int TIntermediate::computeTypeXfbSize(const TType& type, bool& containsDouble) const -{ - // "...if applied to an aggregate containing a double, the offset must also be a multiple of 8, - // and the space taken in the buffer will be a multiple of 8. - // ...within the qualified entity, subsequent components are each - // assigned, in order, to the next available offset aligned to a multiple of - // that component's size. Aggregate types are flattened down to the component - // level to get this sequence of components." - - if (type.isArray()) { - // TODO: perf: this can be flattened by using getCumulativeArraySize(), and a deref that discards all arrayness - assert(type.isSizedArray()); - TType elementType(type, 0); - return type.getOuterArraySize() * computeTypeXfbSize(elementType, containsDouble); - } - - if (type.isStruct()) { - unsigned int size = 0; - bool structContainsDouble = false; - for (int member = 0; member < (int)type.getStruct()->size(); ++member) { - TType memberType(type, member); - // "... if applied to - // an aggregate containing a double, the offset must also be a multiple of 8, - // and the space taken in the buffer will be a multiple of 8." - bool memberContainsDouble = false; - int memberSize = computeTypeXfbSize(memberType, memberContainsDouble); - if (memberContainsDouble) { - structContainsDouble = true; - RoundToPow2(size, 8); - } - size += memberSize; - } - - if (structContainsDouble) { - containsDouble = true; - RoundToPow2(size, 8); - } - return size; - } - - int numComponents; - if (type.isScalar()) - numComponents = 1; - else if (type.isVector()) - numComponents = type.getVectorSize(); - else if (type.isMatrix()) - numComponents = type.getMatrixCols() * type.getMatrixRows(); - else { - assert(0); - numComponents = 1; - } - - if (type.getBasicType() == EbtDouble) { - containsDouble = true; - return 8 * numComponents; - } else - return 4 * numComponents; -} - -const int baseAlignmentVec4Std140 = 16; - -// Return the size and alignment of a component of the given type. -// The size is returned in the 'size' parameter -// Return value is the alignment.. -int TIntermediate::getBaseAlignmentScalar(const TType& type, int& size) -{ - switch (type.getBasicType()) { - case EbtInt64: - case EbtUint64: - case EbtDouble: size = 8; return 8; - case EbtFloat16: size = 2; return 2; - case EbtInt8: - case EbtUint8: size = 1; return 1; - case EbtInt16: - case EbtUint16: size = 2; return 2; - default: size = 4; return 4; - } -} - -// Implement base-alignment and size rules from section 7.6.2.2 Standard Uniform Block Layout -// Operates recursively. -// -// If std140 is true, it does the rounding up to vec4 size required by std140, -// otherwise it does not, yielding std430 rules. -// -// The size is returned in the 'size' parameter -// -// The stride is only non-0 for arrays or matrices, and is the stride of the -// top-level object nested within the type. E.g., for an array of matrices, -// it is the distances needed between matrices, despite the rules saying the -// stride comes from the flattening down to vectors. -// -// Return value is the alignment of the type. -int TIntermediate::getBaseAlignment(const TType& type, int& size, int& stride, bool std140, bool rowMajor) -{ - int alignment; - - // When using the std140 storage layout, structures will be laid out in buffer - // storage with its members stored in monotonically increasing order based on their - // location in the declaration. A structure and each structure member have a base - // offset and a base alignment, from which an aligned offset is computed by rounding - // the base offset up to a multiple of the base alignment. The base offset of the first - // member of a structure is taken from the aligned offset of the structure itself. The - // base offset of all other structure members is derived by taking the offset of the - // last basic machine unit consumed by the previous member and adding one. Each - // structure member is stored in memory at its aligned offset. The members of a top- - // level uniform block are laid out in buffer storage by treating the uniform block as - // a structure with a base offset of zero. - // - // 1. If the member is a scalar consuming N basic machine units, the base alignment is N. - // - // 2. If the member is a two- or four-component vector with components consuming N basic - // machine units, the base alignment is 2N or 4N, respectively. - // - // 3. If the member is a three-component vector with components consuming N - // basic machine units, the base alignment is 4N. - // - // 4. If the member is an array of scalars or vectors, the base alignment and array - // stride are set to match the base alignment of a single array element, according - // to rules (1), (2), and (3), and rounded up to the base alignment of a vec4. The - // array may have padding at the end; the base offset of the member following - // the array is rounded up to the next multiple of the base alignment. - // - // 5. If the member is a column-major matrix with C columns and R rows, the - // matrix is stored identically to an array of C column vectors with R - // components each, according to rule (4). - // - // 6. If the member is an array of S column-major matrices with C columns and - // R rows, the matrix is stored identically to a row of S X C column vectors - // with R components each, according to rule (4). - // - // 7. If the member is a row-major matrix with C columns and R rows, the matrix - // is stored identically to an array of R row vectors with C components each, - // according to rule (4). - // - // 8. If the member is an array of S row-major matrices with C columns and R - // rows, the matrix is stored identically to a row of S X R row vectors with C - // components each, according to rule (4). - // - // 9. If the member is a structure, the base alignment of the structure is N , where - // N is the largest base alignment value of any of its members, and rounded - // up to the base alignment of a vec4. The individual members of this substructure - // are then assigned offsets by applying this set of rules recursively, - // where the base offset of the first member of the sub-structure is equal to the - // aligned offset of the structure. The structure may have padding at the end; - // the base offset of the member following the sub-structure is rounded up to - // the next multiple of the base alignment of the structure. - // - // 10. If the member is an array of S structures, the S elements of the array are laid - // out in order, according to rule (9). - // - // Assuming, for rule 10: The stride is the same as the size of an element. - - stride = 0; - int dummyStride; - - // rules 4, 6, 8, and 10 - if (type.isArray()) { - // TODO: perf: this might be flattened by using getCumulativeArraySize(), and a deref that discards all arrayness - TType derefType(type, 0); - alignment = getBaseAlignment(derefType, size, dummyStride, std140, rowMajor); - if (std140) - alignment = std::max(baseAlignmentVec4Std140, alignment); - RoundToPow2(size, alignment); - stride = size; // uses full matrix size for stride of an array of matrices (not quite what rule 6/8, but what's expected) - // uses the assumption for rule 10 in the comment above - size = stride * type.getOuterArraySize(); - return alignment; - } - - // rule 9 - if (type.getBasicType() == EbtStruct) { - const TTypeList& memberList = *type.getStruct(); - - size = 0; - int maxAlignment = std140 ? baseAlignmentVec4Std140 : 0; - for (size_t m = 0; m < memberList.size(); ++m) { - int memberSize; - // modify just the children's view of matrix layout, if there is one for this member - TLayoutMatrix subMatrixLayout = memberList[m].type->getQualifier().layoutMatrix; - int memberAlignment = getBaseAlignment(*memberList[m].type, memberSize, dummyStride, std140, - (subMatrixLayout != ElmNone) ? (subMatrixLayout == ElmRowMajor) : rowMajor); - maxAlignment = std::max(maxAlignment, memberAlignment); - RoundToPow2(size, memberAlignment); - size += memberSize; - } - - // The structure may have padding at the end; the base offset of - // the member following the sub-structure is rounded up to the next - // multiple of the base alignment of the structure. - RoundToPow2(size, maxAlignment); - - return maxAlignment; - } - - // rule 1 - if (type.isScalar()) - return getBaseAlignmentScalar(type, size); - - // rules 2 and 3 - if (type.isVector()) { - int scalarAlign = getBaseAlignmentScalar(type, size); - switch (type.getVectorSize()) { - case 1: // HLSL has this, GLSL does not - return scalarAlign; - case 2: - size *= 2; - return 2 * scalarAlign; - default: - size *= type.getVectorSize(); - return 4 * scalarAlign; - } - } - - // rules 5 and 7 - if (type.isMatrix()) { - // rule 5: deref to row, not to column, meaning the size of vector is num columns instead of num rows - TType derefType(type, 0, rowMajor); - - alignment = getBaseAlignment(derefType, size, dummyStride, std140, rowMajor); - if (std140) - alignment = std::max(baseAlignmentVec4Std140, alignment); - RoundToPow2(size, alignment); - stride = size; // use intra-matrix stride for stride of a just a matrix - if (rowMajor) - size = stride * type.getMatrixRows(); - else - size = stride * type.getMatrixCols(); - - return alignment; - } - - assert(0); // all cases should be covered above - size = baseAlignmentVec4Std140; - return baseAlignmentVec4Std140; -} - -// To aid the basic HLSL rule about crossing vec4 boundaries. -bool TIntermediate::improperStraddle(const TType& type, int size, int offset) -{ - if (! type.isVector() || type.isArray()) - return false; - - return size <= 16 ? offset / 16 != (offset + size - 1) / 16 - : offset % 16 != 0; -} - -} // end namespace glslang diff --git a/External/glslang/glslang/MachineIndependent/localintermediate.h b/External/glslang/glslang/MachineIndependent/localintermediate.h deleted file mode 100644 index 17e07651..00000000 --- a/External/glslang/glslang/MachineIndependent/localintermediate.h +++ /dev/null @@ -1,752 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// Copyright (C) 2016 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 _LOCAL_INTERMEDIATE_INCLUDED_ -#define _LOCAL_INTERMEDIATE_INCLUDED_ - -#include "../Include/intermediate.h" -#include "../Public/ShaderLang.h" -#include "Versions.h" - -#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; -}; - -// Things that need to be tracked per xfb buffer. -struct TXfbBuffer { - TXfbBuffer() : stride(TQualifier::layoutXfbStrideEnd), implicitStride(0), containsDouble(false) { } - std::vector ranges; // byte offsets that have already been assigned - unsigned int stride; - unsigned int implicitStride; - bool containsDouble; -}; - -// Track a set of strings describing how the module was processed. -// Using 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; - -// -// Set of helper functions to help parse and build the tree. -// -class TIntermediate { -public: - explicit TIntermediate(EShLanguage l, int v = 0, EProfile p = ENoProfile) : - implicitThisName("@this"), implicitCounterName("@count"), - language(l), source(EShSourceNone), profile(p), version(v), treeRoot(0), - numEntryPoints(0), numErrors(0), numPushConstants(0), recursive(false), - invocations(TQualifier::layoutNotSet), vertices(TQualifier::layoutNotSet), - inputPrimitive(ElgNone), outputPrimitive(ElgNone), - pixelCenterInteger(false), originUpperLeft(false), - vertexSpacing(EvsNone), vertexOrder(EvoNone), pointMode(false), earlyFragmentTests(false), - postDepthCoverage(false), depthLayout(EldNone), depthReplacing(false), - hlslFunctionality1(false), - blendEquations(0), xfbMode(false), multiStream(false), -#ifdef NV_EXTENSIONS - layoutOverrideCoverage(false), - geoPassthroughEXT(false), -#endif - autoMapBindings(false), - autoMapLocations(false), - invertY(false), - flattenUniformArrays(false), - useUnknownFormat(false), - hlslOffsets(false), - useStorageBuffer(false), - hlslIoMapping(false), - textureSamplerTransformMode(EShTexSampTransKeep), - needToLegalize(false) - { - localSize[0] = 1; - localSize[1] = 1; - localSize[2] = 1; - localSizeSpecId[0] = TQualifier::layoutNotSet; - localSizeSpecId[1] = TQualifier::layoutNotSet; - localSizeSpecId[2] = TQualifier::layoutNotSet; - xfbBuffers.resize(TQualifier::layoutXfbBufferEnd); - - shiftBinding.fill(0); - } - void setLimits(const TBuiltInResource& r) { resources = r; } - - bool postProcess(TIntermNode*, EShLanguage); - void output(TInfoSink&, bool tree); - void removeTree(); - - void setSource(EShSource s) { source = s; } - EShSource getSource() const { return source; } - 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 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; } - void setInvertY(bool invert) - { - invertY = invert; - if (invertY) - processes.addProcess("invert-y"); - } - bool getInvertY() const { return invertY; } - - void setFlattenUniformArrays(bool flatten) - { - flattenUniformArrays = flatten; - if (flattenUniformArrays) - processes.addProcess("flatten-uniform-arrays"); - } - bool getFlattenUniformArrays() const { return flattenUniformArrays; } - void setNoStorageFormat(bool b) - { - useUnknownFormat = b; - if (useUnknownFormat) - processes.addProcess("no-storage-format"); - } - bool getNoStorageFormat() const { return useUnknownFormat; } - void setHlslOffsets() - { - hlslOffsets = true; - if (hlslOffsets) - processes.addProcess("hlsl-offsets"); - } - bool usingHlslOFfsets() const { return hlslOffsets; } - void setUseStorageBuffer() - { - useStorageBuffer = true; - processes.addProcess("use-storage-buffer"); - } - bool usingStorageBuffer() const { return useStorageBuffer; } - void setHlslIoMapping(bool b) - { - hlslIoMapping = b; - if (hlslIoMapping) - processes.addProcess("hlsl-iomap"); - } - bool usingHlslIoMapping() { return hlslIoMapping; } - - 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; - } - - void setTextureSamplerTransformMode(EShTextureSamplerTransformMode mode) { textureSamplerTransformMode = mode; } - - 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-environment processes - if (spvVersion.vulkan > 0) - processes.addProcess("target-env vulkan1.0"); - else if (spvVersion.vulkan > 0) - processes.addProcess("target-env vulkanUnknown"); - 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; } - 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*) const; - std::tuple addConversion(TOperator op, TIntermTyped* node0, TIntermTyped* node1) const; - TIntermTyped* addUniShapeConversion(TOperator, const TType&, TIntermTyped*); - 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&); - - 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 setLocalSize(int dim, int size) - { - if (localSize[dim] > 1) - return size == localSize[dim]; - 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]; } - - 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 setOriginUpperLeft() { originUpperLeft = true; } - bool getOriginUpperLeft() const { return originUpperLeft; } - void setPixelCenterInteger() { pixelCenterInteger = true; } - bool getPixelCenterInteger() const { return pixelCenterInteger; } - void setEarlyFragmentTests() { earlyFragmentTests = true; } - bool getEarlyFragmentTests() const { return earlyFragmentTests; } - void setPostDepthCoverage() { postDepthCoverage = true; } - bool getPostDepthCoverage() const { return postDepthCoverage; } - bool setDepth(TLayoutDepth d) - { - if (depthLayout != EldNone) - return depthLayout == d; - depthLayout = d; - return true; - } - TLayoutDepth getDepth() const { return depthLayout; } - void setDepthReplacing() { depthReplacing = true; } - bool isDepthReplacing() const { return depthReplacing; } - - void setHlslFunctionality1() { hlslFunctionality1 = true; } - bool getHlslFunctionality1() const { return hlslFunctionality1; } - - void addBlendEquation(TBlendEquationShift b) { blendEquations |= (1 << b); } - unsigned int getBlendEquations() const { return blendEquations; } - - void addToCallGraph(TInfoSink&, const TString& caller, const TString& callee); - void merge(TInfoSink&, TIntermediate&); - void finalCheck(TInfoSink&, bool keepUncalled); - - 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&); - - 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& containsDouble) const; - static int getBaseAlignmentScalar(const TType&, int& size); - static int getBaseAlignment(const TType&, int& size, int& stride, bool std140, bool rowMajor); - static bool improperStraddle(const TType& type, int size, int offset); - bool promote(TIntermOperator*); - -#ifdef NV_EXTENSIONS - void setLayoutOverrideCoverage() { layoutOverrideCoverage = true; } - bool getLayoutOverrideCoverage() const { return layoutOverrideCoverage; } - void setGeoPassthroughEXT() { geoPassthroughEXT = true; } - bool getGeoPassthroughEXT() const { return geoPassthroughEXT; } -#endif - - const char* addSemanticName(const TString& name) - { - return semanticNameSet.insert(name).first->c_str(); - } - - void setSourceFile(const char* file) { if (file != nullptr) sourceFile = file; } - const std::string& getSourceFile() const { return sourceFile; } - void addSourceText(const char* text) { sourceText = sourceText + text; } - const std::string& getSourceText() const { return sourceText; } - 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(); } - - void setNeedsLegalization() { needToLegalize = true; } - bool needsLegalization() const { return needToLegalize; } - - const char* const implicitThisName; - const char* const implicitCounterName; - -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 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&); - TIntermSequence& 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; - TIntermUnary* createConversion(TBasicType convertTo, TIntermTyped* node) const; - std::tuple getConversionDestinatonType(TBasicType type0, TBasicType type1, TOperator op) const; - bool extensionRequested(const char *extension) const {return requestedExtensions.find(extension) != requestedExtensions.end();} - static const char* getResourceName(TResourceType); - - const EShLanguage language; // stage, known at construction time - EShSource source; // source language, known a bit later - std::string entryPointName; - std::string entryPointMangledName; - - 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; - int invocations; - int vertices; - TLayoutGeometry inputPrimitive; - TLayoutGeometry outputPrimitive; - bool pixelCenterInteger; - bool originUpperLeft; - TVertexSpacing vertexSpacing; - TVertexOrder vertexOrder; - bool pointMode; - int localSize[3]; - int localSizeSpecId[3]; - bool earlyFragmentTests; - bool postDepthCoverage; - TLayoutDepth depthLayout; - bool depthReplacing; - bool hlslFunctionality1; - int blendEquations; // an 'or'ing of masks of shifts of TBlendEquationShift - bool xfbMode; - bool multiStream; - -#ifdef NV_EXTENSIONS - bool layoutOverrideCoverage; - bool geoPassthroughEXT; -#endif - - // Base shift values - std::array shiftBinding; - - // Per-descriptor-set shift values - std::array, EResCount> shiftBindingForSet; - - std::vector resourceSetBinding; - bool autoMapBindings; - bool autoMapLocations; - bool invertY; - bool flattenUniformArrays; - bool useUnknownFormat; - bool hlslOffsets; - bool useStorageBuffer; - bool hlslIoMapping; - - typedef std::list TGraph; - TGraph callGraph; - - std::set ioAccessed; // set of names of statically read/written I/O that might need extra checking - std::vector usedIo[4]; // sets of used locations, one for each of in, out, uniform, and buffers - std::vector usedAtomics; // sets of bindings used by atomic counters - std::vector xfbBuffers; // all the data we need to track per xfb buffer - std::unordered_set usedConstantId; // specialization constant ids used - std::set semanticNameSet; - - EShTextureSamplerTransformMode textureSamplerTransformMode; - - // source code of shader, useful as part of debug information - std::string sourceFile; - std::string sourceText; - - // for OpModuleProcessed, or equivalent - TProcesses processes; - - bool needToLegalize; - -private: - void operator=(TIntermediate&); // prevent assignments -}; - -} // end namespace glslang - -#endif // _LOCAL_INTERMEDIATE_INCLUDED_ diff --git a/External/glslang/glslang/MachineIndependent/parseConst.cpp b/External/glslang/glslang/MachineIndependent/parseConst.cpp deleted file mode 100644 index 1a8e6d99..00000000 --- a/External/glslang/glslang/MachineIndependent/parseConst.cpp +++ /dev/null @@ -1,204 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -// -// Traverse a tree of constants to create a single folded constant. -// It should only be used when the whole tree is known to be constant. -// - -#include "ParseHelper.h" - -namespace glslang { - -class TConstTraverser : public TIntermTraverser { -public: - TConstTraverser(const TConstUnionArray& cUnion, bool singleConstParam, TOperator constructType, const TType& t) - : unionArray(cUnion), type(t), - constructorType(constructType), singleConstantParam(singleConstParam), error(false), isMatrix(false), - matrixCols(0), matrixRows(0) { index = 0; tOp = EOpNull; } - - virtual void visitConstantUnion(TIntermConstantUnion* node); - virtual bool visitAggregate(TVisit, TIntermAggregate* node); - - int index; - TConstUnionArray unionArray; - TOperator tOp; - const TType& type; - TOperator constructorType; - bool singleConstantParam; - bool error; - int size; // size of the constructor ( 4 for vec4) - bool isMatrix; - int matrixCols; - int matrixRows; - -protected: - TConstTraverser(TConstTraverser&); - TConstTraverser& operator=(TConstTraverser&); -}; - -bool TConstTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node) -{ - if (! node->isConstructor() && node->getOp() != EOpComma) { - error = true; - - return false; - } - - bool flag = node->getSequence().size() == 1 && node->getSequence()[0]->getAsTyped()->getAsConstantUnion(); - if (flag) { - singleConstantParam = true; - constructorType = node->getOp(); - size = node->getType().computeNumComponents(); - - if (node->getType().isMatrix()) { - isMatrix = true; - matrixCols = node->getType().getMatrixCols(); - matrixRows = node->getType().getMatrixRows(); - } - } - - for (TIntermSequence::iterator p = node->getSequence().begin(); - p != node->getSequence().end(); p++) { - - if (node->getOp() == EOpComma) - index = 0; - - (*p)->traverse(this); - } - if (flag) - { - singleConstantParam = false; - constructorType = EOpNull; - size = 0; - isMatrix = false; - matrixCols = 0; - matrixRows = 0; - } - - return false; -} - -void TConstTraverser::visitConstantUnion(TIntermConstantUnion* node) -{ - TConstUnionArray leftUnionArray(unionArray); - int instanceSize = type.computeNumComponents(); - - if (index >= instanceSize) - return; - - if (! singleConstantParam) { - int rightUnionSize = node->getType().computeNumComponents(); - - const TConstUnionArray& rightUnionArray = node->getConstArray(); - for (int i = 0; i < rightUnionSize; i++) { - if (index >= instanceSize) - return; - leftUnionArray[index] = rightUnionArray[i]; - - index++; - } - } else { - int endIndex = index + size; - const TConstUnionArray& rightUnionArray = node->getConstArray(); - if (! isMatrix) { - int count = 0; - int nodeComps = node->getType().computeNumComponents(); - for (int i = index; i < endIndex; i++) { - if (i >= instanceSize) - return; - - leftUnionArray[i] = rightUnionArray[count]; - - (index)++; - - if (nodeComps > 1) - count++; - } - } else { - // constructing a matrix, but from what? - if (node->isMatrix()) { - // Matrix from a matrix; this has the outer matrix, node is the argument matrix. - // Traverse the outer, potentially bigger matrix, fill in missing pieces with the - // identity matrix. - for (int c = 0; c < matrixCols; ++c) { - for (int r = 0; r < matrixRows; ++r) { - int targetOffset = index + c * matrixRows + r; - if (r < node->getType().getMatrixRows() && c < node->getType().getMatrixCols()) { - int srcOffset = c * node->getType().getMatrixRows() + r; - leftUnionArray[targetOffset] = rightUnionArray[srcOffset]; - } else if (r == c) - leftUnionArray[targetOffset].setDConst(1.0); - else - leftUnionArray[targetOffset].setDConst(0.0); - } - } - } else { - // matrix from vector - int count = 0; - const int startIndex = index; - int nodeComps = node->getType().computeNumComponents(); - for (int i = startIndex; i < endIndex; i++) { - if (i >= instanceSize) - return; - if (i == startIndex || (i - startIndex) % (matrixRows + 1) == 0 ) - leftUnionArray[i] = rightUnionArray[count]; - else - leftUnionArray[i].setDConst(0.0); - - index++; - - if (nodeComps > 1) - count++; - } - } - } - } -} - -bool TIntermediate::parseConstTree(TIntermNode* root, TConstUnionArray unionArray, TOperator constructorType, const TType& t, bool singleConstantParam) -{ - if (root == 0) - return false; - - TConstTraverser it(unionArray, singleConstantParam, constructorType, t); - - root->traverse(&it); - if (it.error) - return true; - else - return false; -} - -} // end namespace glslang diff --git a/External/glslang/glslang/MachineIndependent/parseVersions.h b/External/glslang/glslang/MachineIndependent/parseVersions.h deleted file mode 100644 index b2aaa399..00000000 --- a/External/glslang/glslang/MachineIndependent/parseVersions.h +++ /dev/null @@ -1,147 +0,0 @@ -// -// Copyright (C) 2016 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) - : infoSink(infoSink), version(version), profile(profile), language(language), - spvVersion(spvVersion), forwardCompatible(forwardCompatible), - intermediate(interm), messages(messages), numErrors(0), currentScanner(0) { } - virtual ~TParseVersions() { } - virtual void initializeExtensionBehavior(); - virtual void requireProfile(const TSourceLoc&, int queryProfiles, const char* featureDesc); - virtual void profileRequires(const TSourceLoc&, int queryProfiles, int minVersion, int numExtensions, const char* const extensions[], const char* featureDesc); - virtual void profileRequires(const TSourceLoc&, int queryProfiles, int minVersion, const char* const extension, const char* featureDesc); - virtual void requireStage(const TSourceLoc&, EShLanguageMask, const char* featureDesc); - virtual void requireStage(const TSourceLoc&, EShLanguage, const char* featureDesc); - 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 unimplemented(const TSourceLoc&, 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 fullIntegerCheck(const TSourceLoc&, const char* op); - virtual void doubleCheck(const TSourceLoc&, const char* op); - virtual void float16Check(const TSourceLoc&, const char* op, bool builtIn = false); -#ifdef AMD_EXTENSIONS - virtual void float16OpaqueCheck(const TSourceLoc&, const char* op, bool builtIn = false); -#endif - 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 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); - virtual bool checkExtensionsRequested(const TSourceLoc&, int numExtensions, const char* const extensions[], const char* featureDesc); - virtual void updateExtensionBehavior(const char* const extension, TExtensionBehavior); - - 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; - - 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&); - bool relaxedErrors() const { return (messages & EShMsgRelaxedErrors) != 0; } - bool suppressWarnings() const { return (messages & EShMsgSuppressWarnings) != 0; } - bool isReadingHLSL() const { return (messages & EShMsgReadHlsl) == EShMsgReadHlsl; } - bool hlslEnable16BitTypes() const { return (messages & EShMsgHlslEnable16BitTypes) != 0; } - - TInfoSink& infoSink; - - // compilation mode - int version; // version, updated by #version in the shader - EProfile profile; // the declared profile in the shader (core by default) - EShLanguage language; // really the stage - SpvVersion spvVersion; - bool forwardCompatible; // true if errors are to be given for use of deprecated features - 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/External/glslang/glslang/MachineIndependent/preprocessor/Pp.cpp b/External/glslang/glslang/MachineIndependent/preprocessor/Pp.cpp deleted file mode 100644 index 8048fa51..00000000 --- a/External/glslang/glslang/MachineIndependent/preprocessor/Pp.cpp +++ /dev/null @@ -1,1270 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// Copyright (C) 2013 LunarG, Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// -/****************************************************************************\ -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 _CRT_SECURE_NO_WARNINGS -#define _CRT_SECURE_NO_WARNINGS -#endif - -#include -#include -#include -#include -#include - -#include "PpContext.h" -#include "PpTokens.h" - -namespace glslang { - -// Handle #define -int TPpContext::CPPdefine(TPpToken* ppToken) -{ - MacroSymbol mac; - - // get the macro name - int token = scanToken(ppToken); - if (token != PpAtomIdentifier) { - parseContext.ppError(ppToken->loc, "must be followed by macro name", "#define", ""); - return token; - } - if (ppToken->loc.string >= 0) { - // We are in user code; check for reserved name use: - parseContext.reservedPpErrorCheck(ppToken->loc, ppToken->name, "#define"); - } - - // save the macro name - const int defAtom = atomStrings.getAddAtom(ppToken->name); - - // gather parameters to the macro, between (...) - token = scanToken(ppToken); - if (token == '(' && ! ppToken->space) { - mac.emptyArgs = 1; - do { - token = scanToken(ppToken); - if (mac.args.size() == 0 && token == ')') - break; - if (token != PpAtomIdentifier) { - parseContext.ppError(ppToken->loc, "bad argument", "#define", ""); - - return token; - } - mac.emptyArgs = 0; - const int argAtom = atomStrings.getAddAtom(ppToken->name); - - // check for duplication of parameter name - bool duplicate = false; - for (size_t a = 0; a < mac.args.size(); ++a) { - if (mac.args[a] == argAtom) { - parseContext.ppError(ppToken->loc, "duplicate macro parameter", "#define", ""); - duplicate = true; - break; - } - } - if (! duplicate) - mac.args.push_back(argAtom); - token = scanToken(ppToken); - } while (token == ','); - if (token != ')') { - parseContext.ppError(ppToken->loc, "missing parenthesis", "#define", ""); - - return token; - } - - token = scanToken(ppToken); - } - - // record the definition of the macro - TSourceLoc defineLoc = ppToken->loc; // because ppToken is going to go to the next line before we report errors - while (token != '\n' && token != EndOfInput) { - mac.body.putToken(token, ppToken); - token = scanToken(ppToken); - if (token != '\n' && ppToken->space) - mac.body.putToken(' ', ppToken); - } - - // check for duplicate definition - MacroSymbol* existing = lookupMacroDef(defAtom); - if (existing != nullptr) { - if (! existing->undef) { - // Already defined -- need to make sure they are identical: - // "Two replacement lists are identical if and only if the preprocessing tokens in both have the same number, - // ordering, spelling, and white-space separation, where all white-space separations are considered identical." - if (existing->args.size() != mac.args.size() || existing->emptyArgs != mac.emptyArgs) - parseContext.ppError(defineLoc, "Macro redefined; different number of arguments:", "#define", atomStrings.getString(defAtom)); - else { - if (existing->args != mac.args) - parseContext.ppError(defineLoc, "Macro redefined; different argument names:", "#define", atomStrings.getString(defAtom)); - existing->body.reset(); - mac.body.reset(); - int newToken; - do { - int oldToken; - TPpToken oldPpToken; - TPpToken newPpToken; - oldToken = existing->body.getToken(parseContext, &oldPpToken); - newToken = mac.body.getToken(parseContext, &newPpToken); - if (oldToken != newToken || oldPpToken != newPpToken) { - parseContext.ppError(defineLoc, "Macro redefined; different substitutions:", "#define", atomStrings.getString(defAtom)); - break; - } - } while (newToken > 0); - } - } - *existing = mac; - } else - addMacroDef(defAtom, mac); - - return '\n'; -} - -// Handle #undef -int TPpContext::CPPundef(TPpToken* ppToken) -{ - int token = scanToken(ppToken); - if (token != PpAtomIdentifier) { - parseContext.ppError(ppToken->loc, "must be followed by macro name", "#undef", ""); - - return token; - } - - parseContext.reservedPpErrorCheck(ppToken->loc, ppToken->name, "#undef"); - - MacroSymbol* macro = lookupMacroDef(atomStrings.getAtom(ppToken->name)); - if (macro != nullptr) - macro->undef = 1; - token = scanToken(ppToken); - if (token != '\n') - parseContext.ppError(ppToken->loc, "can only be followed by a single macro name", "#undef", ""); - - return token; -} - -// Handle #else -/* Skip forward to appropriate spot. This is used both -** to skip to a #endif after seeing an #else, AND to skip to a #else, -** #elif, or #endif after a #if/#ifdef/#ifndef/#elif test was false. -*/ -int TPpContext::CPPelse(int matchelse, TPpToken* ppToken) -{ - int depth = 0; - int token = scanToken(ppToken); - - while (token != EndOfInput) { - if (token != '#') { - while (token != '\n' && token != EndOfInput) - token = scanToken(ppToken); - - if (token == EndOfInput) - return token; - - token = scanToken(ppToken); - continue; - } - - if ((token = scanToken(ppToken)) != PpAtomIdentifier) - continue; - - int nextAtom = atomStrings.getAtom(ppToken->name); - if (nextAtom == PpAtomIf || nextAtom == PpAtomIfdef || nextAtom == PpAtomIfndef) { - depth++; - if (ifdepth >= maxIfNesting || elsetracker >= maxIfNesting) { - parseContext.ppError(ppToken->loc, "maximum nesting depth exceeded", "#if/#ifdef/#ifndef", ""); - return EndOfInput; - } else { - ifdepth++; - elsetracker++; - } - } else if (nextAtom == PpAtomEndif) { - token = extraTokenCheck(nextAtom, ppToken, scanToken(ppToken)); - elseSeen[elsetracker] = false; - --elsetracker; - if (depth == 0) { - // found the #endif we are looking for - if (ifdepth > 0) - --ifdepth; - break; - } - --depth; - --ifdepth; - } else if (matchelse && depth == 0) { - if (nextAtom == PpAtomElse) { - elseSeen[elsetracker] = true; - token = extraTokenCheck(nextAtom, ppToken, scanToken(ppToken)); - // found the #else we are looking for - break; - } else if (nextAtom == PpAtomElif) { - if (elseSeen[elsetracker]) - parseContext.ppError(ppToken->loc, "#elif after #else", "#elif", ""); - /* we decrement ifdepth here, because CPPif will increment - * it and we really want to leave it alone */ - if (ifdepth > 0) { - --ifdepth; - elseSeen[elsetracker] = false; - --elsetracker; - } - - return CPPif(ppToken); - } - } else if (nextAtom == PpAtomElse) { - if (elseSeen[elsetracker]) - parseContext.ppError(ppToken->loc, "#else after #else", "#else", ""); - else - elseSeen[elsetracker] = true; - token = extraTokenCheck(nextAtom, ppToken, scanToken(ppToken)); - } else if (nextAtom == PpAtomElif) { - if (elseSeen[elsetracker]) - parseContext.ppError(ppToken->loc, "#elif after #else", "#elif", ""); - } - } - - return token; -} - -// Call when there should be no more tokens left on a line. -int TPpContext::extraTokenCheck(int contextAtom, TPpToken* ppToken, int token) -{ - if (token != '\n' && token != EndOfInput) { - static const char* message = "unexpected tokens following directive"; - - const char* label; - if (contextAtom == PpAtomElse) - label = "#else"; - else if (contextAtom == PpAtomElif) - label = "#elif"; - else if (contextAtom == PpAtomEndif) - label = "#endif"; - else if (contextAtom == PpAtomIf) - label = "#if"; - else if (contextAtom == PpAtomLine) - label = "#line"; - else - label = ""; - - if (parseContext.relaxedErrors()) - parseContext.ppWarn(ppToken->loc, message, label, ""); - else - parseContext.ppError(ppToken->loc, message, label, ""); - - while (token != '\n' && token != EndOfInput) - token = scanToken(ppToken); - } - - return token; -} - -enum eval_prec { - MIN_PRECEDENCE, - COND, LOGOR, LOGAND, OR, XOR, AND, EQUAL, RELATION, SHIFT, ADD, MUL, UNARY, - MAX_PRECEDENCE -}; - -namespace { - - int op_logor(int a, int b) { return a || b; } - int op_logand(int a, int b) { return a && b; } - int op_or(int a, int b) { return a | b; } - int op_xor(int a, int b) { return a ^ b; } - int op_and(int a, int b) { return a & b; } - int op_eq(int a, int b) { return a == b; } - int op_ne(int a, int b) { return a != b; } - int op_ge(int a, int b) { return a >= b; } - int op_le(int a, int b) { return a <= b; } - int op_gt(int a, int b) { return a > b; } - int op_lt(int a, int b) { return a < b; } - int op_shl(int a, int b) { return a << b; } - int op_shr(int a, int b) { return a >> b; } - int op_add(int a, int b) { return a + b; } - int op_sub(int a, int b) { return a - b; } - int op_mul(int a, int b) { return a * b; } - int op_div(int a, int b) { return a == INT_MIN && b == -1 ? 0 : a / b; } - int op_mod(int a, int b) { return a == INT_MIN && b == -1 ? 0 : a % b; } - int op_pos(int a) { return a; } - int op_neg(int a) { return -a; } - int op_cmpl(int a) { return ~a; } - int op_not(int a) { return !a; } - -}; - -struct TBinop { - int token, precedence, (*op)(int, int); -} binop[] = { - { PpAtomOr, LOGOR, op_logor }, - { PpAtomAnd, LOGAND, op_logand }, - { '|', OR, op_or }, - { '^', XOR, op_xor }, - { '&', AND, op_and }, - { PpAtomEQ, EQUAL, op_eq }, - { PpAtomNE, EQUAL, op_ne }, - { '>', RELATION, op_gt }, - { PpAtomGE, RELATION, op_ge }, - { '<', RELATION, op_lt }, - { PpAtomLE, RELATION, op_le }, - { PpAtomLeft, SHIFT, op_shl }, - { PpAtomRight, SHIFT, op_shr }, - { '+', ADD, op_add }, - { '-', ADD, op_sub }, - { '*', MUL, op_mul }, - { '/', MUL, op_div }, - { '%', MUL, op_mod }, -}; - -struct TUnop { - int token, (*op)(int); -} unop[] = { - { '+', op_pos }, - { '-', op_neg }, - { '~', op_cmpl }, - { '!', op_not }, -}; - -#define NUM_ELEMENTS(A) (sizeof(A) / sizeof(A[0])) - -int TPpContext::eval(int token, int precedence, bool shortCircuit, int& res, bool& err, TPpToken* ppToken) -{ - TSourceLoc loc = ppToken->loc; // because we sometimes read the newline before reporting the error - if (token == PpAtomIdentifier) { - if (strcmp("defined", ppToken->name) == 0) { - if (! parseContext.isReadingHLSL() && isMacroInput()) { - if (parseContext.relaxedErrors()) - parseContext.ppWarn(ppToken->loc, "nonportable when expanded from macros for preprocessor expression", - "defined", ""); - else - parseContext.ppError(ppToken->loc, "cannot use in preprocessor expression when expanded from macros", - "defined", ""); - } - bool needclose = 0; - token = scanToken(ppToken); - if (token == '(') { - needclose = true; - token = scanToken(ppToken); - } - if (token != PpAtomIdentifier) { - parseContext.ppError(loc, "incorrect directive, expected identifier", "preprocessor evaluation", ""); - err = true; - res = 0; - - return token; - } - - MacroSymbol* macro = lookupMacroDef(atomStrings.getAtom(ppToken->name)); - res = macro != nullptr ? !macro->undef : 0; - token = scanToken(ppToken); - if (needclose) { - if (token != ')') { - parseContext.ppError(loc, "expected ')'", "preprocessor evaluation", ""); - err = true; - res = 0; - - return token; - } - token = scanToken(ppToken); - } - } else { - token = evalToToken(token, shortCircuit, res, err, ppToken); - return eval(token, precedence, shortCircuit, res, err, ppToken); - } - } else if (token == PpAtomConstInt) { - res = ppToken->ival; - token = scanToken(ppToken); - } else if (token == '(') { - token = scanToken(ppToken); - token = eval(token, MIN_PRECEDENCE, shortCircuit, res, err, ppToken); - if (! err) { - if (token != ')') { - parseContext.ppError(loc, "expected ')'", "preprocessor evaluation", ""); - err = true; - res = 0; - - return token; - } - token = scanToken(ppToken); - } - } else { - int op = NUM_ELEMENTS(unop) - 1; - for (; op >= 0; op--) { - if (unop[op].token == token) - break; - } - if (op >= 0) { - token = scanToken(ppToken); - token = eval(token, UNARY, shortCircuit, res, err, ppToken); - res = unop[op].op(res); - } else { - parseContext.ppError(loc, "bad expression", "preprocessor evaluation", ""); - err = true; - res = 0; - - return token; - } - } - - token = evalToToken(token, shortCircuit, res, err, ppToken); - - // Perform evaluation of binary operation, if there is one, otherwise we are done. - while (! err) { - if (token == ')' || token == '\n') - break; - int op; - for (op = NUM_ELEMENTS(binop) - 1; op >= 0; op--) { - if (binop[op].token == token) - break; - } - if (op < 0 || binop[op].precedence <= precedence) - break; - int leftSide = res; - - // Setup short-circuiting, needed for ES, unless already in a short circuit. - // (Once in a short-circuit, can't turn off again, until that whole subexpression is done. - if (! shortCircuit) { - if ((token == PpAtomOr && leftSide == 1) || - (token == PpAtomAnd && leftSide == 0)) - shortCircuit = true; - } - - token = scanToken(ppToken); - token = eval(token, binop[op].precedence, shortCircuit, res, err, ppToken); - - if (binop[op].op == op_div || binop[op].op == op_mod) { - if (res == 0) { - parseContext.ppError(loc, "division by 0", "preprocessor evaluation", ""); - res = 1; - } - } - res = binop[op].op(leftSide, res); - } - - return token; -} - -// Expand macros, skipping empty expansions, to get to the first real token in those expansions. -int TPpContext::evalToToken(int token, bool shortCircuit, int& res, bool& err, TPpToken* ppToken) -{ - while (token == PpAtomIdentifier && strcmp("defined", ppToken->name) != 0) { - int macroReturn = MacroExpand(ppToken, true, false); - if (macroReturn == 0) { - parseContext.ppError(ppToken->loc, "can't evaluate expression", "preprocessor evaluation", ""); - err = true; - res = 0; - token = scanToken(ppToken); - break; - } - if (macroReturn == -1) { - if (! shortCircuit && parseContext.profile == EEsProfile) { - const char* message = "undefined macro in expression not allowed in es profile"; - if (parseContext.relaxedErrors()) - parseContext.ppWarn(ppToken->loc, message, "preprocessor evaluation", ppToken->name); - else - parseContext.ppError(ppToken->loc, message, "preprocessor evaluation", ppToken->name); - } - } - token = scanToken(ppToken); - } - - return token; -} - -// Handle #if -int TPpContext::CPPif(TPpToken* ppToken) -{ - int token = scanToken(ppToken); - if (ifdepth >= maxIfNesting || elsetracker >= maxIfNesting) { - parseContext.ppError(ppToken->loc, "maximum nesting depth exceeded", "#if", ""); - return EndOfInput; - } else { - elsetracker++; - ifdepth++; - } - int res = 0; - bool err = false; - token = eval(token, MIN_PRECEDENCE, false, res, err, ppToken); - token = extraTokenCheck(PpAtomIf, ppToken, token); - if (!res && !err) - token = CPPelse(1, ppToken); - - return token; -} - -// Handle #ifdef -int TPpContext::CPPifdef(int defined, TPpToken* ppToken) -{ - int token = scanToken(ppToken); - if (ifdepth > maxIfNesting || elsetracker > maxIfNesting) { - parseContext.ppError(ppToken->loc, "maximum nesting depth exceeded", "#ifdef", ""); - return EndOfInput; - } else { - elsetracker++; - ifdepth++; - } - - if (token != PpAtomIdentifier) { - if (defined) - parseContext.ppError(ppToken->loc, "must be followed by macro name", "#ifdef", ""); - else - parseContext.ppError(ppToken->loc, "must be followed by macro name", "#ifndef", ""); - } else { - MacroSymbol* macro = lookupMacroDef(atomStrings.getAtom(ppToken->name)); - token = scanToken(ppToken); - if (token != '\n') { - parseContext.ppError(ppToken->loc, "unexpected tokens following #ifdef directive - expected a newline", "#ifdef", ""); - while (token != '\n' && token != EndOfInput) - token = scanToken(ppToken); - } - if (((macro != nullptr && !macro->undef) ? 1 : 0) != defined) - token = CPPelse(1, ppToken); - } - - return token; -} - -// Handle #include ... -// TODO: Handle macro expansions for the header name -int TPpContext::CPPinclude(TPpToken* ppToken) -{ - const TSourceLoc directiveLoc = ppToken->loc; - bool startWithLocalSearch = true; // to additionally include the extra "" paths - int token = scanToken(ppToken); - - // handle -style #include - if (token == '<') { - startWithLocalSearch = false; - token = scanHeaderName(ppToken, '>'); - } - // otherwise ppToken already has the header name and it was "header-name" style - - if (token != PpAtomConstString) { - parseContext.ppError(directiveLoc, "must be followed by a header name", "#include", ""); - return token; - } - - // Make a copy of the name because it will be overwritten by the next token scan. - const std::string filename = ppToken->name; - - // See if the directive was well formed - token = scanToken(ppToken); - if (token != '\n') { - if (token == EndOfInput) - parseContext.ppError(ppToken->loc, "expected newline after header name:", "#include", "%s", filename.c_str()); - else - parseContext.ppError(ppToken->loc, "extra content after header name:", "#include", "%s", filename.c_str()); - return token; - } - - // Process well-formed directive - - // Find the inclusion, first look in "Local" ("") paths, if requested, - // otherwise, only search the "System" (<>) paths. - TShader::Includer::IncludeResult* res = nullptr; - if (startWithLocalSearch) - res = includer.includeLocal(filename.c_str(), currentSourceFile.c_str(), includeStack.size() + 1); - if (res == nullptr || res->headerName.empty()) { - includer.releaseInclude(res); - res = includer.includeSystem(filename.c_str(), currentSourceFile.c_str(), includeStack.size() + 1); - } - - // Process the results - if (res != nullptr && !res->headerName.empty()) { - if (res->headerData != nullptr && res->headerLength > 0) { - // path for processing one or more tokens from an included header, hand off 'res' - const bool forNextLine = parseContext.lineDirectiveShouldSetNextLine(); - std::ostringstream prologue; - std::ostringstream epilogue; - prologue << "#line " << forNextLine << " " << "\"" << res->headerName << "\"\n"; - epilogue << (res->headerData[res->headerLength - 1] == '\n'? "" : "\n") << - "#line " << directiveLoc.line + forNextLine << " " << directiveLoc.getStringNameOrNum() << "\n"; - pushInput(new TokenizableIncludeFile(directiveLoc, prologue.str(), res, epilogue.str(), this)); - // There's no "current" location anymore. - parseContext.setCurrentColumn(0); - } else { - // things are okay, but there is nothing to process - includer.releaseInclude(res); - } - } else { - // error path, clean up - std::string message = - res != nullptr ? std::string(res->headerData, res->headerLength) - : std::string("Could not process include directive"); - parseContext.ppError(directiveLoc, message.c_str(), "#include", "for header name: %s", filename.c_str()); - includer.releaseInclude(res); - } - - return token; -} - -// Handle #line -int TPpContext::CPPline(TPpToken* ppToken) -{ - // "#line must have, after macro substitution, one of the following forms: - // "#line line - // "#line line source-string-number" - - int token = scanToken(ppToken); - const TSourceLoc directiveLoc = ppToken->loc; - if (token == '\n') { - parseContext.ppError(ppToken->loc, "must by followed by an integral literal", "#line", ""); - return token; - } - - int lineRes = 0; // Line number after macro expansion. - int lineToken = 0; - bool hasFile = false; - int fileRes = 0; // Source file number after macro expansion. - const char* sourceName = nullptr; // Optional source file name. - bool lineErr = false; - bool fileErr = false; - token = eval(token, MIN_PRECEDENCE, false, lineRes, lineErr, ppToken); - if (! lineErr) { - lineToken = lineRes; - if (token == '\n') - ++lineRes; - - if (parseContext.lineDirectiveShouldSetNextLine()) - --lineRes; - parseContext.setCurrentLine(lineRes); - - if (token != '\n') { - if (token == PpAtomConstString) { - parseContext.ppRequireExtensions(directiveLoc, 1, &E_GL_GOOGLE_cpp_style_line_directive, "filename-based #line"); - // We need to save a copy of the string instead of pointing - // to the name field of the token since the name field - // will likely be overwritten by the next token scan. - sourceName = atomStrings.getString(atomStrings.getAddAtom(ppToken->name)); - parseContext.setCurrentSourceName(sourceName); - hasFile = true; - token = scanToken(ppToken); - } else { - token = eval(token, MIN_PRECEDENCE, false, fileRes, fileErr, ppToken); - if (! fileErr) { - parseContext.setCurrentString(fileRes); - hasFile = true; - } - } - } - } - if (!fileErr && !lineErr) { - parseContext.notifyLineDirective(directiveLoc.line, lineToken, hasFile, fileRes, sourceName); - } - token = extraTokenCheck(PpAtomLine, ppToken, token); - - return token; -} - -// Handle #error -int TPpContext::CPPerror(TPpToken* ppToken) -{ - int token = scanToken(ppToken); - std::string message; - TSourceLoc loc = ppToken->loc; - - while (token != '\n' && token != EndOfInput) { - if (token == PpAtomConstInt16 || token == PpAtomConstUint16 || - token == PpAtomConstInt || token == PpAtomConstUint || - token == PpAtomConstInt64 || token == PpAtomConstUint64 || - token == PpAtomConstFloat16 || - token == PpAtomConstFloat || token == PpAtomConstDouble) { - message.append(ppToken->name); - } else if (token == PpAtomIdentifier || token == PpAtomConstString) { - message.append(ppToken->name); - } else { - message.append(atomStrings.getString(token)); - } - message.append(" "); - token = scanToken(ppToken); - } - parseContext.notifyErrorDirective(loc.line, message.c_str()); - // store this msg into the shader's information log..set the Compile Error flag!!!! - parseContext.ppError(loc, message.c_str(), "#error", ""); - - return '\n'; -} - -// Handle #pragma -int TPpContext::CPPpragma(TPpToken* ppToken) -{ - char SrcStrName[2]; - TVector tokens; - - TSourceLoc loc = ppToken->loc; // because we go to the next line before processing - int token = scanToken(ppToken); - while (token != '\n' && token != EndOfInput) { - switch (token) { - case PpAtomIdentifier: - case PpAtomConstInt: - case PpAtomConstUint: - case PpAtomConstInt64: - case PpAtomConstUint64: -#ifdef AMD_EXTENSIONS - case PpAtomConstInt16: - case PpAtomConstUint16: -#endif - case PpAtomConstFloat: - case PpAtomConstDouble: - case PpAtomConstFloat16: - tokens.push_back(ppToken->name); - break; - default: - SrcStrName[0] = (char)token; - SrcStrName[1] = '\0'; - tokens.push_back(SrcStrName); - } - token = scanToken(ppToken); - } - - if (token == EndOfInput) - parseContext.ppError(loc, "directive must end with a newline", "#pragma", ""); - else - parseContext.handlePragma(loc, tokens); - - return token; -} - -// #version: This is just for error checking: the version and profile are decided before preprocessing starts -int TPpContext::CPPversion(TPpToken* ppToken) -{ - int token = scanToken(ppToken); - - if (errorOnVersion || versionSeen) { - if (parseContext.isReadingHLSL()) - parseContext.ppError(ppToken->loc, "invalid preprocessor command", "#version", ""); - else - parseContext.ppError(ppToken->loc, "must occur first in shader", "#version", ""); - } - versionSeen = true; - - if (token == '\n') { - parseContext.ppError(ppToken->loc, "must be followed by version number", "#version", ""); - - return token; - } - - if (token != PpAtomConstInt) - parseContext.ppError(ppToken->loc, "must be followed by version number", "#version", ""); - - ppToken->ival = atoi(ppToken->name); - int versionNumber = ppToken->ival; - int line = ppToken->loc.line; - token = scanToken(ppToken); - - if (token == '\n') { - parseContext.notifyVersion(line, versionNumber, nullptr); - return token; - } else { - int profileAtom = atomStrings.getAtom(ppToken->name); - if (profileAtom != PpAtomCore && - profileAtom != PpAtomCompatibility && - profileAtom != PpAtomEs) - parseContext.ppError(ppToken->loc, "bad profile name; use es, core, or compatibility", "#version", ""); - parseContext.notifyVersion(line, versionNumber, ppToken->name); - token = scanToken(ppToken); - - if (token == '\n') - return token; - else - parseContext.ppError(ppToken->loc, "bad tokens following profile -- expected newline", "#version", ""); - } - - return token; -} - -// Handle #extension -int TPpContext::CPPextension(TPpToken* ppToken) -{ - int line = ppToken->loc.line; - int token = scanToken(ppToken); - char extensionName[MaxTokenLength + 1]; - - if (token=='\n') { - parseContext.ppError(ppToken->loc, "extension name not specified", "#extension", ""); - return token; - } - - if (token != PpAtomIdentifier) - parseContext.ppError(ppToken->loc, "extension name expected", "#extension", ""); - - assert(strlen(ppToken->name) <= MaxTokenLength); - strcpy(extensionName, ppToken->name); - - token = scanToken(ppToken); - if (token != ':') { - parseContext.ppError(ppToken->loc, "':' missing after extension name", "#extension", ""); - return token; - } - - token = scanToken(ppToken); - if (token != PpAtomIdentifier) { - parseContext.ppError(ppToken->loc, "behavior for extension not specified", "#extension", ""); - return token; - } - - parseContext.updateExtensionBehavior(line, extensionName, ppToken->name); - parseContext.notifyExtensionDirective(line, extensionName, ppToken->name); - - token = scanToken(ppToken); - if (token == '\n') - return token; - else - parseContext.ppError(ppToken->loc, "extra tokens -- expected newline", "#extension",""); - - return token; -} - -int TPpContext::readCPPline(TPpToken* ppToken) -{ - int token = scanToken(ppToken); - - if (token == PpAtomIdentifier) { - switch (atomStrings.getAtom(ppToken->name)) { - case PpAtomDefine: - token = CPPdefine(ppToken); - break; - case PpAtomElse: - if (elseSeen[elsetracker]) - parseContext.ppError(ppToken->loc, "#else after #else", "#else", ""); - elseSeen[elsetracker] = true; - if (ifdepth == 0) - parseContext.ppError(ppToken->loc, "mismatched statements", "#else", ""); - token = extraTokenCheck(PpAtomElse, ppToken, scanToken(ppToken)); - token = CPPelse(0, ppToken); - break; - case PpAtomElif: - if (ifdepth == 0) - parseContext.ppError(ppToken->loc, "mismatched statements", "#elif", ""); - if (elseSeen[elsetracker]) - parseContext.ppError(ppToken->loc, "#elif after #else", "#elif", ""); - // this token is really a dont care, but we still need to eat the tokens - token = scanToken(ppToken); - while (token != '\n' && token != EndOfInput) - token = scanToken(ppToken); - token = CPPelse(0, ppToken); - break; - case PpAtomEndif: - if (ifdepth == 0) - parseContext.ppError(ppToken->loc, "mismatched statements", "#endif", ""); - else { - elseSeen[elsetracker] = false; - --elsetracker; - --ifdepth; - } - token = extraTokenCheck(PpAtomEndif, ppToken, scanToken(ppToken)); - break; - case PpAtomIf: - token = CPPif(ppToken); - break; - case PpAtomIfdef: - token = CPPifdef(1, ppToken); - break; - case PpAtomIfndef: - token = CPPifdef(0, ppToken); - break; - case PpAtomInclude: - if(!parseContext.isReadingHLSL()) { - parseContext.ppRequireExtensions(ppToken->loc, 1, &E_GL_GOOGLE_include_directive, "#include"); - } - token = CPPinclude(ppToken); - break; - case PpAtomLine: - token = CPPline(ppToken); - break; - case PpAtomPragma: - token = CPPpragma(ppToken); - break; - case PpAtomUndef: - token = CPPundef(ppToken); - break; - case PpAtomError: - token = CPPerror(ppToken); - break; - case PpAtomVersion: - token = CPPversion(ppToken); - break; - case PpAtomExtension: - token = CPPextension(ppToken); - break; - default: - parseContext.ppError(ppToken->loc, "invalid directive:", "#", ppToken->name); - break; - } - } else if (token != '\n' && token != EndOfInput) - parseContext.ppError(ppToken->loc, "invalid directive", "#", ""); - - while (token != '\n' && token != EndOfInput) - token = scanToken(ppToken); - - return token; -} - -// Context-dependent parsing of a #include . -// Assumes no macro expansions etc. are being done; the name is just on the current input. -// Always creates a name and returns PpAtomicConstString, unless we run out of input. -int TPpContext::scanHeaderName(TPpToken* ppToken, char delimit) -{ - bool tooLong = false; - - if (inputStack.empty()) - return EndOfInput; - - int len = 0; - ppToken->name[0] = '\0'; - do { - int ch = inputStack.back()->getch(); - - // done yet? - if (ch == delimit) { - ppToken->name[len] = '\0'; - if (tooLong) - parseContext.ppError(ppToken->loc, "header name too long", "", ""); - return PpAtomConstString; - } else if (ch == EndOfInput) - return EndOfInput; - - // found a character to expand the name with - if (len < MaxTokenLength) - ppToken->name[len++] = (char)ch; - else - tooLong = true; - } while (true); -} - -// Macro-expand a macro argument 'arg' to create 'expandedArg'. -// Does not replace 'arg'. -// Returns nullptr if no expanded argument is created. -TPpContext::TokenStream* TPpContext::PrescanMacroArg(TokenStream& arg, TPpToken* ppToken, bool newLineOkay) -{ - // expand the argument - TokenStream* expandedArg = new TokenStream; - pushInput(new tMarkerInput(this)); - pushTokenStreamInput(arg); - int token; - while ((token = scanToken(ppToken)) != tMarkerInput::marker && token != EndOfInput) { - token = tokenPaste(token, *ppToken); - if (token == tMarkerInput::marker || token == EndOfInput) - break; - if (token == PpAtomIdentifier && MacroExpand(ppToken, false, newLineOkay) != 0) - continue; - expandedArg->putToken(token, ppToken); - } - - if (token == EndOfInput) { - // MacroExpand ate the marker, so had bad input, recover - delete expandedArg; - expandedArg = nullptr; - } else { - // remove the marker - popInput(); - } - - return expandedArg; -} - -// -// Return the next token for a macro expansion, handling macro arguments, -// whose semantics are dependent on being adjacent to ##. -// -int TPpContext::tMacroInput::scan(TPpToken* ppToken) -{ - int token; - do { - token = mac->body.getToken(pp->parseContext, ppToken); - } while (token == ' '); // handle white space in macro - - // Hash operators basically turn off a round of macro substitution - // (the round done on the argument before the round done on the RHS of the - // macro definition): - // - // "A parameter in the replacement list, unless preceded by a # or ## - // preprocessing token or followed by a ## preprocessing token (see below), - // is replaced by the corresponding argument after all macros contained - // therein have been expanded." - // - // "If, in the replacement list, a parameter is immediately preceded or - // followed by a ## preprocessing token, the parameter is replaced by the - // corresponding argument's preprocessing token sequence." - - bool pasting = false; - if (postpaste) { - // don't expand next token - pasting = true; - postpaste = false; - } - - if (prepaste) { - // already know we should be on a ##, verify - assert(token == PpAtomPaste); - prepaste = false; - postpaste = true; - } - - // see if are preceding a ## - if (mac->body.peekUntokenizedPasting()) { - prepaste = true; - pasting = true; - } - - // HLSL does expand macros before concatenation - if (pasting && pp->parseContext.isReadingHLSL()) - pasting = false; - - // TODO: preprocessor: properly handle whitespace (or lack of it) between tokens when expanding - if (token == PpAtomIdentifier) { - int i; - for (i = (int)mac->args.size() - 1; i >= 0; i--) - if (strcmp(pp->atomStrings.getString(mac->args[i]), ppToken->name) == 0) - break; - if (i >= 0) { - TokenStream* arg = expandedArgs[i]; - if (arg == nullptr || pasting) - arg = args[i]; - pp->pushTokenStreamInput(*arg, prepaste); - - return pp->scanToken(ppToken); - } - } - - if (token == EndOfInput) - mac->busy = 0; - - return token; -} - -// return a textual zero, for scanning a macro that was never defined -int TPpContext::tZeroInput::scan(TPpToken* ppToken) -{ - if (done) - return EndOfInput; - - strcpy(ppToken->name, "0"); - ppToken->ival = 0; - ppToken->space = false; - done = true; - - return PpAtomConstInt; -} - -// -// Check a token to see if it is a macro that should be expanded. -// If it is, and defined, push a tInput that will produce the appropriate expansion -// and return 1. -// If it is, but undefined, and expandUndef is requested, push a tInput that will -// expand to 0 and return -1. -// Otherwise, return 0 to indicate no expansion, which is not necessarily an error. -// -int TPpContext::MacroExpand(TPpToken* ppToken, bool expandUndef, bool newLineOkay) -{ - ppToken->space = false; - int macroAtom = atomStrings.getAtom(ppToken->name); - switch (macroAtom) { - case PpAtomLineMacro: - ppToken->ival = parseContext.getCurrentLoc().line; - snprintf(ppToken->name, sizeof(ppToken->name), "%d", ppToken->ival); - UngetToken(PpAtomConstInt, ppToken); - return 1; - - case PpAtomFileMacro: { - if (parseContext.getCurrentLoc().name) - parseContext.ppRequireExtensions(ppToken->loc, 1, &E_GL_GOOGLE_cpp_style_line_directive, "filename-based __FILE__"); - ppToken->ival = parseContext.getCurrentLoc().string; - snprintf(ppToken->name, sizeof(ppToken->name), "%s", ppToken->loc.getStringNameOrNum().c_str()); - UngetToken(PpAtomConstInt, ppToken); - return 1; - } - - case PpAtomVersionMacro: - ppToken->ival = parseContext.version; - snprintf(ppToken->name, sizeof(ppToken->name), "%d", ppToken->ival); - UngetToken(PpAtomConstInt, ppToken); - return 1; - - default: - break; - } - - MacroSymbol* macro = macroAtom == 0 ? nullptr : lookupMacroDef(macroAtom); - int depth = 0; - - // no recursive expansions - if (macro != nullptr && macro->busy) - return 0; - - // not expanding undefined macros - if ((macro == nullptr || macro->undef) && ! expandUndef) - return 0; - - // 0 is the value of an undefined macro - if ((macro == nullptr || macro->undef) && expandUndef) { - pushInput(new tZeroInput(this)); - return -1; - } - - tMacroInput *in = new tMacroInput(this); - - TSourceLoc loc = ppToken->loc; // in case we go to the next line before discovering the error - in->mac = macro; - if (macro->args.size() > 0 || macro->emptyArgs) { - int token = scanToken(ppToken); - if (newLineOkay) { - while (token == '\n') - token = scanToken(ppToken); - } - if (token != '(') { - UngetToken(token, ppToken); - delete in; - return 0; - } - in->args.resize(in->mac->args.size()); - for (size_t i = 0; i < in->mac->args.size(); i++) - in->args[i] = new TokenStream; - in->expandedArgs.resize(in->mac->args.size()); - for (size_t i = 0; i < in->mac->args.size(); i++) - in->expandedArgs[i] = nullptr; - size_t arg = 0; - bool tokenRecorded = false; - do { - depth = 0; - while (1) { - token = scanToken(ppToken); - if (token == EndOfInput || token == tMarkerInput::marker) { - parseContext.ppError(loc, "End of input in macro", "macro expansion", atomStrings.getString(macroAtom)); - delete in; - return 0; - } - if (token == '\n') { - if (! newLineOkay) { - parseContext.ppError(loc, "End of line in macro substitution:", "macro expansion", atomStrings.getString(macroAtom)); - delete in; - return 0; - } - continue; - } - if (token == '#') { - parseContext.ppError(ppToken->loc, "unexpected '#'", "macro expansion", atomStrings.getString(macroAtom)); - delete in; - return 0; - } - if (in->mac->args.size() == 0 && token != ')') - break; - if (depth == 0 && (token == ',' || token == ')')) - break; - if (token == '(') - depth++; - if (token == ')') - depth--; - in->args[arg]->putToken(token, ppToken); - tokenRecorded = true; - } - if (token == ')') { - if (in->mac->args.size() == 1 && tokenRecorded == 0) - break; - arg++; - break; - } - arg++; - } while (arg < in->mac->args.size()); - - if (arg < in->mac->args.size()) - parseContext.ppError(loc, "Too few args in Macro", "macro expansion", atomStrings.getString(macroAtom)); - else if (token != ')') { - depth=0; - while (token != EndOfInput && (depth > 0 || token != ')')) { - if (token == ')') - depth--; - token = scanToken(ppToken); - if (token == '(') - depth++; - } - - if (token == EndOfInput) { - parseContext.ppError(loc, "End of input in macro", "macro expansion", atomStrings.getString(macroAtom)); - delete in; - return 0; - } - parseContext.ppError(loc, "Too many args in macro", "macro expansion", atomStrings.getString(macroAtom)); - } - - // We need both expanded and non-expanded forms of the argument, for whether or - // not token pasting will be applied later when the argument is consumed next to ##. - for (size_t i = 0; i < in->mac->args.size(); i++) - in->expandedArgs[i] = PrescanMacroArg(*in->args[i], ppToken, newLineOkay); - } - - pushInput(in); - macro->busy = 1; - macro->body.reset(); - - return 1; -} - -} // end namespace glslang diff --git a/External/glslang/glslang/MachineIndependent/preprocessor/PpAtom.cpp b/External/glslang/glslang/MachineIndependent/preprocessor/PpAtom.cpp deleted file mode 100644 index 06c2333e..00000000 --- a/External/glslang/glslang/MachineIndependent/preprocessor/PpAtom.cpp +++ /dev/null @@ -1,181 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// Copyright (C) 2013 LunarG, Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// -/****************************************************************************\ -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 _CRT_SECURE_NO_WARNINGS -#define _CRT_SECURE_NO_WARNINGS -#endif - -#include -#include -#include - -#include "PpContext.h" -#include "PpTokens.h" - -namespace { - -using namespace glslang; - -const struct { - int val; - const char* str; -} tokens[] = { - - { PPAtomAddAssign, "+=" }, - { PPAtomSubAssign, "-=" }, - { PPAtomMulAssign, "*=" }, - { PPAtomDivAssign, "/=" }, - { PPAtomModAssign, "%=" }, - - { PpAtomRight, ">>" }, - { PpAtomLeft, "<<" }, - { PpAtomAnd, "&&" }, - { PpAtomOr, "||" }, - { PpAtomXor, "^^" }, - - { PpAtomRightAssign, ">>=" }, - { PpAtomLeftAssign, "<<=" }, - { PpAtomAndAssign, "&=" }, - { PpAtomOrAssign, "|=" }, - { PpAtomXorAssign, "^=" }, - - { PpAtomEQ, "==" }, - { PpAtomNE, "!=" }, - { PpAtomGE, ">=" }, - { PpAtomLE, "<=" }, - - { PpAtomDecrement, "--" }, - { PpAtomIncrement, "++" }, - - { PpAtomColonColon, "::" }, - - { PpAtomDefine, "define" }, - { PpAtomUndef, "undef" }, - { PpAtomIf, "if" }, - { PpAtomElif, "elif" }, - { PpAtomElse, "else" }, - { PpAtomEndif, "endif" }, - { PpAtomIfdef, "ifdef" }, - { PpAtomIfndef, "ifndef" }, - { PpAtomLine, "line" }, - { PpAtomPragma, "pragma" }, - { PpAtomError, "error" }, - - { PpAtomVersion, "version" }, - { PpAtomCore, "core" }, - { PpAtomCompatibility, "compatibility" }, - { PpAtomEs, "es" }, - { PpAtomExtension, "extension" }, - - { PpAtomLineMacro, "__LINE__" }, - { PpAtomFileMacro, "__FILE__" }, - { PpAtomVersionMacro, "__VERSION__" }, - - { PpAtomInclude, "include" }, -}; - -} // end anonymous namespace - -namespace glslang { - -// -// Initialize the atom table. -// -TStringAtomMap::TStringAtomMap() -{ - badToken.assign(""); - - // Add single character tokens to the atom table: - const char* s = "~!%^&*()-+=|,.<>/?;:[]{}#\\"; - char t[2]; - - t[1] = '\0'; - while (*s) { - t[0] = *s; - addAtomFixed(t, s[0]); - s++; - } - - // Add multiple character scanner tokens : - for (size_t ii = 0; ii < sizeof(tokens)/sizeof(tokens[0]); ii++) - addAtomFixed(tokens[ii].str, tokens[ii].val); - - nextAtom = PpAtomLast; -} - -} // end namespace glslang diff --git a/External/glslang/glslang/MachineIndependent/preprocessor/PpContext.cpp b/External/glslang/glslang/MachineIndependent/preprocessor/PpContext.cpp deleted file mode 100644 index 6a2e05fe..00000000 --- a/External/glslang/glslang/MachineIndependent/preprocessor/PpContext.cpp +++ /dev/null @@ -1,115 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// Copyright (C) 2013 LunarG, Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// -/****************************************************************************\ -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. -\****************************************************************************/ - -#include - -#include "PpContext.h" - -namespace glslang { - -TPpContext::TPpContext(TParseContextBase& pc, const std::string& rootFileName, TShader::Includer& inclr) : - preamble(0), strings(0), previous_token('\n'), parseContext(pc), includer(inclr), inComment(false), - rootFileName(rootFileName), - currentSourceFile(rootFileName) -{ - ifdepth = 0; - for (elsetracker = 0; elsetracker < maxIfNesting; elsetracker++) - elseSeen[elsetracker] = false; - elsetracker = 0; -} - -TPpContext::~TPpContext() -{ - delete [] preamble; - - // free up the inputStack - while (! inputStack.empty()) - popInput(); -} - -void TPpContext::setInput(TInputScanner& input, bool versionWillBeError) -{ - assert(inputStack.size() == 0); - - pushInput(new tStringInput(this, input)); - - errorOnVersion = versionWillBeError; - versionSeen = false; -} - -} // end namespace glslang diff --git a/External/glslang/glslang/MachineIndependent/preprocessor/PpContext.h b/External/glslang/glslang/MachineIndependent/preprocessor/PpContext.h deleted file mode 100644 index 854bbbad..00000000 --- a/External/glslang/glslang/MachineIndependent/preprocessor/PpContext.h +++ /dev/null @@ -1,622 +0,0 @@ -// -// 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. -// -/****************************************************************************\ -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 "../ParseHelper.h" - -/* windows only pragma */ -#ifdef _MSC_VER - #pragma warning(disable : 4127) -#endif - -namespace glslang { - -class TPpToken { -public: - TPpToken() : space(false), i64val(0) - { - loc.init(); - name[0] = 0; - } - - // This is used for comparing macro definitions, so checks what is relevant for that. - bool operator==(const TPpToken& right) - { - return space == right.space && - ival == right.ival && dval == right.dval && i64val == right.i64val && - strncmp(name, right.name, MaxTokenLength) == 0; - } - bool operator!=(const TPpToken& right) { return ! operator==(right); } - - TSourceLoc loc; - bool space; // true if a space (for white space or a removed comment) should also be recognized, in front of the token returned - - union { - int ival; - double dval; - long long i64val; - }; - - 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; - -// 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 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 - // - - class TokenStream { - public: - TokenStream() : current(0) { } - - void putToken(int token, TPpToken* ppToken); - int getToken(TParseContextBase&, TPpToken*); - bool atEnd() { return current >= data.size(); } - bool peekTokenizedPasting(bool lastTokenPastes); - bool peekUntokenizedPasting(); - void reset() { current = 0; } - - protected: - void putSubtoken(char); - int getSubtoken(); - void ungetSubtoken(); - - TVector data; - size_t current; - }; - - // - // From Pp.cpp - // - - struct MacroSymbol { - MacroSymbol() : emptyArgs(0), busy(0), undef(0) { } - TVector args; - TokenStream body; - unsigned emptyArgs : 1; - 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 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 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); - int 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); } - 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, names, 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.name, 0); - scanner.setFile(startLoc.name, 1); - scanner.setFile(startLoc.name, 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]; - // String names - const char* names[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; -}; - -} // end namespace glslang - -#endif // PPCONTEXT_H diff --git a/External/glslang/glslang/MachineIndependent/preprocessor/PpScanner.cpp b/External/glslang/glslang/MachineIndependent/preprocessor/PpScanner.cpp deleted file mode 100644 index f4eaf57d..00000000 --- a/External/glslang/glslang/MachineIndependent/preprocessor/PpScanner.cpp +++ /dev/null @@ -1,1100 +0,0 @@ -// -// 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. -// -/****************************************************************************\ -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 _CRT_SECURE_NO_WARNINGS -#define _CRT_SECURE_NO_WARNINGS -#endif - -#include -#include - -#include "PpContext.h" -#include "PpTokens.h" -#include "../Scan.h" - -namespace glslang { - -/////////////////////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////// Floating point constants: ///////////////////////////////// -/////////////////////////////////////////////////////////////////////////////////////////////// - -/* -* lFloatConst() - Scan a single- or double-precision floating point constant. Assumes that the scanner -* has seen at least one digit, followed by either a decimal '.' or the -* letter 'e', or a precision ending (e.g., F or LF). -*/ - -int TPpContext::lFloatConst(int len, int ch, TPpToken* ppToken) -{ - bool HasDecimalOrExponent = false; - int isDouble = 0; - - const auto saveName = [&](int ch) { - if (len <= MaxTokenLength) - ppToken->name[len++] = static_cast(ch); - }; - - // Decimal: - - if (ch == '.') { - HasDecimalOrExponent = true; - saveName(ch); - ch = getChar(); - - // 1.#INF or -1.#INF - if (ch == '#' && (ifdepth > 0 || parseContext.intermediate.getSource() == EShSourceHlsl)) { - if ((len < 2) || - (len == 2 && ppToken->name[0] != '1') || - (len == 3 && ppToken->name[1] != '1' && !(ppToken->name[0] == '-' || ppToken->name[0] == '+')) || - (len > 3)) - parseContext.ppError(ppToken->loc, "unexpected use of", "#", ""); - else { - // we have 1.# or -1.# or +1.#, check for 'INF' - if ((ch = getChar()) != 'I' || - (ch = getChar()) != 'N' || - (ch = getChar()) != 'F') - parseContext.ppError(ppToken->loc, "expected 'INF'", "#", ""); - else { - // we have [+-].#INF, and we are targeting IEEE 754, so wrap it up: - saveName('I'); - saveName('N'); - saveName('F'); - ppToken->name[len] = '\0'; - if (ppToken->name[0] == '-') - ppToken->i64val = 0xfff0000000000000; // -Infinity - else - ppToken->i64val = 0x7ff0000000000000; // +Infinity - return PpAtomConstFloat; - } - } - } - - while (ch >= '0' && ch <= '9') { - saveName(ch); - ch = getChar(); - } - } - - // Exponent: - - if (ch == 'e' || ch == 'E') { - HasDecimalOrExponent = true; - saveName(ch); - ch = getChar(); - if (ch == '+' || ch == '-') { - saveName(ch); - ch = getChar(); - } - if (ch >= '0' && ch <= '9') { - while (ch >= '0' && ch <= '9') { - saveName(ch); - ch = getChar(); - } - } else { - parseContext.ppError(ppToken->loc, "bad character in float exponent", "", ""); - } - } - - // Suffix: - bool isFloat16 = false; - if (ch == 'l' || ch == 'L') { - if (ifdepth == 0 && parseContext.intermediate.getSource() == EShSourceGlsl) - parseContext.doubleCheck(ppToken->loc, "double floating-point suffix"); - if (ifdepth == 0 && !HasDecimalOrExponent) - parseContext.ppError(ppToken->loc, "float literal needs a decimal point or exponent", "", ""); - if (parseContext.intermediate.getSource() == EShSourceGlsl) { - int ch2 = getChar(); - if (ch2 != 'f' && ch2 != 'F') { - ungetChar(); - ungetChar(); - } else { - saveName(ch); - saveName(ch2); - isDouble = 1; - } - } else if (parseContext.intermediate.getSource() == EShSourceHlsl) { - saveName(ch); - isDouble = 1; - } - } else if (ch == 'h' || ch == 'H') { - if (ifdepth == 0 && parseContext.intermediate.getSource() == EShSourceGlsl) - parseContext.float16Check(ppToken->loc, "half floating-point suffix"); - if (ifdepth == 0 && !HasDecimalOrExponent) - parseContext.ppError(ppToken->loc, "float literal needs a decimal point or exponent", "", ""); - if (parseContext.intermediate.getSource() == EShSourceGlsl) { - int ch2 = getChar(); - if (ch2 != 'f' && ch2 != 'F') { - ungetChar(); - ungetChar(); - } else { - saveName(ch); - saveName(ch2); - isFloat16 = true; - } - } else if (parseContext.intermediate.getSource() == EShSourceHlsl) { - saveName(ch); - isFloat16 = true; - } - } else if (ch == 'f' || ch == 'F') { - if (ifdepth == 0) - parseContext.profileRequires(ppToken->loc, EEsProfile, 300, nullptr, "floating-point suffix"); - if (ifdepth == 0 && !parseContext.relaxedErrors()) - parseContext.profileRequires(ppToken->loc, ~EEsProfile, 120, nullptr, "floating-point suffix"); - if (ifdepth == 0 && !HasDecimalOrExponent) - parseContext.ppError(ppToken->loc, "float literal needs a decimal point or exponent", "", ""); - saveName(ch); - } else - ungetChar(); - - // Patch up the name, length, etc. - - if (len > MaxTokenLength) { - len = MaxTokenLength; - parseContext.ppError(ppToken->loc, "float literal too long", "", ""); - } - ppToken->name[len] = '\0'; - - // Get the numerical value - ppToken->dval = strtod(ppToken->name, nullptr); - - // Return the right token type - if (isDouble) - return PpAtomConstDouble; - else if (isFloat16) - return PpAtomConstFloat16; - else - return PpAtomConstFloat; -} - -// Recognize a character literal. -// -// The first ' has already been accepted, read the rest, through the closing '. -// -// Always returns PpAtomConstInt. -// -int TPpContext::characterLiteral(TPpToken* ppToken) -{ - ppToken->name[0] = 0; - ppToken->ival = 0; - - if (parseContext.intermediate.getSource() != EShSourceHlsl) { - // illegal, except in macro definition, for which case we report the character - return '\''; - } - - int ch = getChar(); - switch (ch) { - case '\'': - // As empty sequence: '' - parseContext.ppError(ppToken->loc, "unexpected", "\'", ""); - return PpAtomConstInt; - case '\\': - // As escape sequence: '\XXX' - switch (ch = getChar()) { - case 'a': - ppToken->ival = 7; - break; - case 'b': - ppToken->ival = 8; - break; - case 't': - ppToken->ival = 9; - break; - case 'n': - ppToken->ival = 10; - break; - case 'v': - ppToken->ival = 11; - break; - case 'f': - ppToken->ival = 12; - break; - case 'r': - ppToken->ival = 13; - break; - case 'x': - case '0': - parseContext.ppError(ppToken->loc, "octal and hex sequences not supported", "\\", ""); - break; - default: - // This catches '\'', '\"', '\?', etc. - // Also, things like '\C' mean the same thing as 'C' - // (after the above cases are filtered out). - ppToken->ival = ch; - break; - } - break; - default: - ppToken->ival = ch; - break; - } - ppToken->name[0] = (char)ppToken->ival; - ppToken->name[1] = '\0'; - ch = getChar(); - if (ch != '\'') { - parseContext.ppError(ppToken->loc, "expected", "\'", ""); - // Look ahead for a closing ' - do { - ch = getChar(); - } while (ch != '\'' && ch != EndOfInput && ch != '\n'); - } - - return PpAtomConstInt; -} - -// -// Scanner used to tokenize source stream. -// -int TPpContext::tStringInput::scan(TPpToken* ppToken) -{ - int AlreadyComplained = 0; - int len = 0; - int ch = 0; - int ii = 0; - unsigned long long ival = 0; - const auto floatingPointChar = [&](int ch) { return ch == '.' || ch == 'e' || ch == 'E' || - ch == 'f' || ch == 'F' || - ch == 'h' || ch == 'H'; }; - - static const char* const Int64_Extensions[] = { - E_GL_ARB_gpu_shader_int64, - E_GL_KHX_shader_explicit_arithmetic_types, - E_GL_KHX_shader_explicit_arithmetic_types_int64 }; - static const int Num_Int64_Extensions = sizeof(Int64_Extensions) / sizeof(Int64_Extensions[0]); - - static const char* const Int16_Extensions[] = { -#ifdef AMD_EXTENSIONS - E_GL_AMD_gpu_shader_int16, -#endif - E_GL_KHX_shader_explicit_arithmetic_types, - E_GL_KHX_shader_explicit_arithmetic_types_int16 }; - static const int Num_Int16_Extensions = sizeof(Int16_Extensions) / sizeof(Int16_Extensions[0]); - - ppToken->ival = 0; - ppToken->i64val = 0; - ppToken->space = false; - ch = getch(); - for (;;) { - while (ch == ' ' || ch == '\t') { - ppToken->space = true; - ch = getch(); - } - - ppToken->loc = pp->parseContext.getCurrentLoc(); - len = 0; - switch (ch) { - default: - // Single character token, including EndOfInput, '#' and '\' (escaped newlines are handled at a lower level, so this is just a '\' token) - if (ch > PpAtomMaxSingle) - ch = PpAtomBadToken; - return ch; - - case 'A': case 'B': case 'C': case 'D': case 'E': - case 'F': case 'G': case 'H': case 'I': case 'J': - case 'K': case 'L': case 'M': case 'N': case 'O': - case 'P': case 'Q': case 'R': case 'S': case 'T': - case 'U': case 'V': case 'W': case 'X': case 'Y': - case 'Z': case '_': - case 'a': case 'b': case 'c': case 'd': case 'e': - case 'f': case 'g': case 'h': case 'i': case 'j': - case 'k': case 'l': case 'm': case 'n': case 'o': - case 'p': case 'q': case 'r': case 's': case 't': - case 'u': case 'v': case 'w': case 'x': case 'y': - case 'z': - do { - if (len < MaxTokenLength) { - ppToken->name[len++] = (char)ch; - ch = getch(); - } else { - if (! AlreadyComplained) { - pp->parseContext.ppError(ppToken->loc, "name too long", "", ""); - AlreadyComplained = 1; - } - ch = getch(); - } - } while ((ch >= 'a' && ch <= 'z') || - (ch >= 'A' && ch <= 'Z') || - (ch >= '0' && ch <= '9') || - ch == '_'); - - // line continuation with no token before or after makes len == 0, and need to start over skipping white space, etc. - if (len == 0) - continue; - - ppToken->name[len] = '\0'; - ungetch(); - return PpAtomIdentifier; - case '0': - ppToken->name[len++] = (char)ch; - ch = getch(); - if (ch == 'x' || ch == 'X') { - // must be hexadecimal - - bool isUnsigned = false; - bool isInt64 = false; - bool isInt16 = false; - ppToken->name[len++] = (char)ch; - ch = getch(); - if ((ch >= '0' && ch <= '9') || - (ch >= 'A' && ch <= 'F') || - (ch >= 'a' && ch <= 'f')) { - - ival = 0; - do { - if (len < MaxTokenLength && ival <= 0x0fffffffffffffffull) { - ppToken->name[len++] = (char)ch; - if (ch >= '0' && ch <= '9') { - ii = ch - '0'; - } else if (ch >= 'A' && ch <= 'F') { - ii = ch - 'A' + 10; - } else if (ch >= 'a' && ch <= 'f') { - ii = ch - 'a' + 10; - } else - pp->parseContext.ppError(ppToken->loc, "bad digit in hexadecimal literal", "", ""); - ival = (ival << 4) | ii; - } else { - if (! AlreadyComplained) { - if(len < MaxTokenLength) - pp->parseContext.ppError(ppToken->loc, "hexadecimal literal too big", "", ""); - else - pp->parseContext.ppError(ppToken->loc, "hexadecimal literal too long", "", ""); - AlreadyComplained = 1; - } - ival = 0xffffffffffffffffull; - } - ch = getch(); - } while ((ch >= '0' && ch <= '9') || - (ch >= 'A' && ch <= 'F') || - (ch >= 'a' && ch <= 'f')); - } else { - pp->parseContext.ppError(ppToken->loc, "bad digit in hexadecimal literal", "", ""); - } - if (ch == 'u' || ch == 'U') { - if (len < MaxTokenLength) - ppToken->name[len++] = (char)ch; - isUnsigned = true; - - int nextCh = getch(); - if (nextCh == 'l' || nextCh == 'L') { - if (len < MaxTokenLength) - ppToken->name[len++] = (char)nextCh; - isInt64 = true; - } else - ungetch(); - -#ifdef AMD_EXTENSIONS - nextCh = getch(); - if ((nextCh == 's' || nextCh == 'S') && - pp->parseContext.intermediate.getSource() == EShSourceGlsl) { - if (len < MaxTokenLength) - ppToken->name[len++] = (char)nextCh; - isInt16 = true; - } else - ungetch(); -#endif - } else if (ch == 'l' || ch == 'L') { - if (len < MaxTokenLength) - ppToken->name[len++] = (char)ch; - isInt64 = true; -#ifdef AMD_EXTENSIONS - } else if ((ch == 's' || ch == 'S') && - pp->parseContext.intermediate.getSource() == EShSourceGlsl) { - if (len < MaxTokenLength) - ppToken->name[len++] = (char)ch; - isInt16 = true; -#endif - } else - ungetch(); - ppToken->name[len] = '\0'; - - if (isInt64 && pp->parseContext.intermediate.getSource() == EShSourceGlsl) { - if (pp->ifdepth == 0) { - pp->parseContext.requireProfile(ppToken->loc, ~EEsProfile, - "64-bit hexadecimal literal"); - pp->parseContext.profileRequires(ppToken->loc, ~EEsProfile, 0, - Num_Int64_Extensions, Int64_Extensions, "64-bit hexadecimal literal"); - } - ppToken->i64val = ival; - return isUnsigned ? PpAtomConstUint64 : PpAtomConstInt64; - } else if (isInt16) { - if (pp->ifdepth == 0) { - if (pp->parseContext.intermediate.getSource() == EShSourceGlsl) { - pp->parseContext.requireProfile(ppToken->loc, ~EEsProfile, - "16-bit hexadecimal literal"); - pp->parseContext.profileRequires(ppToken->loc, ~EEsProfile, 0, - Num_Int16_Extensions, Int16_Extensions, "16-bit hexadecimal literal"); - } - } - ppToken->ival = (int)ival; - return isUnsigned ? PpAtomConstUint16 : PpAtomConstInt16; - } else { - if (ival > 0xffffffffu && !AlreadyComplained) - pp->parseContext.ppError(ppToken->loc, "hexadecimal literal too big", "", ""); - ppToken->ival = (int)ival; - return isUnsigned ? PpAtomConstUint : PpAtomConstInt; - } - } else { - // could be octal integer or floating point, speculative pursue octal until it must be floating point - - bool isUnsigned = false; - bool isInt64 = false; - bool isInt16 = false; - bool octalOverflow = false; - bool nonOctal = false; - ival = 0; - - // see how much octal-like stuff we can read - while (ch >= '0' && ch <= '7') { - if (len < MaxTokenLength) - ppToken->name[len++] = (char)ch; - else if (! AlreadyComplained) { - pp->parseContext.ppError(ppToken->loc, "numeric literal too long", "", ""); - AlreadyComplained = 1; - } - if (ival <= 0x1fffffffffffffffull) { - ii = ch - '0'; - ival = (ival << 3) | ii; - } else - octalOverflow = true; - ch = getch(); - } - - // could be part of a float... - if (ch == '8' || ch == '9') { - nonOctal = true; - do { - if (len < MaxTokenLength) - ppToken->name[len++] = (char)ch; - else if (! AlreadyComplained) { - pp->parseContext.ppError(ppToken->loc, "numeric literal too long", "", ""); - AlreadyComplained = 1; - } - ch = getch(); - } while (ch >= '0' && ch <= '9'); - } - if (floatingPointChar(ch)) - return pp->lFloatConst(len, ch, ppToken); - - // wasn't a float, so must be octal... - if (nonOctal) - pp->parseContext.ppError(ppToken->loc, "octal literal digit too large", "", ""); - - if (ch == 'u' || ch == 'U') { - if (len < MaxTokenLength) - ppToken->name[len++] = (char)ch; - isUnsigned = true; - - int nextCh = getch(); - if (nextCh == 'l' || nextCh == 'L') { - if (len < MaxTokenLength) - ppToken->name[len++] = (char)nextCh; - isInt64 = true; - } else - ungetch(); - -#ifdef AMD_EXTENSIONS - nextCh = getch(); - if ((nextCh == 's' || nextCh == 'S') && - pp->parseContext.intermediate.getSource() == EShSourceGlsl) { - if (len < MaxTokenLength) - ppToken->name[len++] = (char)nextCh; - isInt16 = true; - } else - ungetch(); -#endif - } else if (ch == 'l' || ch == 'L') { - if (len < MaxTokenLength) - ppToken->name[len++] = (char)ch; - isInt64 = true; -#ifdef AMD_EXTENSIONS - } else if ((ch == 's' || ch == 'S') && - pp->parseContext.intermediate.getSource() == EShSourceGlsl) { - if (len < MaxTokenLength) - ppToken->name[len++] = (char)ch; - isInt16 = true; -#endif - } else - ungetch(); - ppToken->name[len] = '\0'; - - if (!isInt64 && ival > 0xffffffffu) - octalOverflow = true; - - if (octalOverflow) - pp->parseContext.ppError(ppToken->loc, "octal literal too big", "", ""); - - if (isInt64 && pp->parseContext.intermediate.getSource() == EShSourceGlsl) { - if (pp->ifdepth == 0) { - pp->parseContext.requireProfile(ppToken->loc, ~EEsProfile, - "64-bit octal literal"); - pp->parseContext.profileRequires(ppToken->loc, ~EEsProfile, 0, - Num_Int64_Extensions, Int64_Extensions, "64-bit octal literal"); - } - ppToken->i64val = ival; - return isUnsigned ? PpAtomConstUint64 : PpAtomConstInt64; - } else if (isInt16) { - if (pp->ifdepth == 0) { - if (pp->parseContext.intermediate.getSource() == EShSourceGlsl) { - pp->parseContext.requireProfile(ppToken->loc, ~EEsProfile, - "16-bit octal literal"); - pp->parseContext.profileRequires(ppToken->loc, ~EEsProfile, 0, - Num_Int16_Extensions, Int16_Extensions, "16-bit octal literal"); - } - } - ppToken->ival = (int)ival; - return isUnsigned ? PpAtomConstUint16 : PpAtomConstInt16; - } else { - ppToken->ival = (int)ival; - return isUnsigned ? PpAtomConstUint : PpAtomConstInt; - } - } - break; - case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - // can't be hexadecimal or octal, is either decimal or floating point - - do { - if (len < MaxTokenLength) - ppToken->name[len++] = (char)ch; - else if (! AlreadyComplained) { - pp->parseContext.ppError(ppToken->loc, "numeric literal too long", "", ""); - AlreadyComplained = 1; - } - ch = getch(); - } while (ch >= '0' && ch <= '9'); - if (floatingPointChar(ch)) - return pp->lFloatConst(len, ch, ppToken); - else { - // Finish handling signed and unsigned integers - int numericLen = len; - bool isUnsigned = false; - bool isInt64 = false; - bool isInt16 = false; - if (ch == 'u' || ch == 'U') { - if (len < MaxTokenLength) - ppToken->name[len++] = (char)ch; - isUnsigned = true; - - int nextCh = getch(); - if (nextCh == 'l' || nextCh == 'L') { - if (len < MaxTokenLength) - ppToken->name[len++] = (char)nextCh; - isInt64 = true; - } else - ungetch(); - -#ifdef AMD_EXTENSIONS - nextCh = getch(); - if ((nextCh == 's' || nextCh == 'S') && - pp->parseContext.intermediate.getSource() == EShSourceGlsl) { - if (len < MaxTokenLength) - ppToken->name[len++] = (char)nextCh; - isInt16 = true; - } else - ungetch(); -#endif - } else if (ch == 'l' || ch == 'L') { - if (len < MaxTokenLength) - ppToken->name[len++] = (char)ch; - isInt64 = true; -#ifdef AMD_EXTENSIONS - } else if ((ch == 's' || ch == 'S') && - pp->parseContext.intermediate.getSource() == EShSourceGlsl) { - if (len < MaxTokenLength) - ppToken->name[len++] = (char)ch; - isInt16 = true; -#endif - } else - ungetch(); - - ppToken->name[len] = '\0'; - ival = 0; - const unsigned oneTenthMaxInt = 0xFFFFFFFFu / 10; - const unsigned remainderMaxInt = 0xFFFFFFFFu - 10 * oneTenthMaxInt; - const unsigned long long oneTenthMaxInt64 = 0xFFFFFFFFFFFFFFFFull / 10; - const unsigned long long remainderMaxInt64 = 0xFFFFFFFFFFFFFFFFull - 10 * oneTenthMaxInt64; - const unsigned short oneTenthMaxInt16 = 0xFFFFu / 10; - const unsigned short remainderMaxInt16 = 0xFFFFu - 10 * oneTenthMaxInt16; - for (int i = 0; i < numericLen; i++) { - ch = ppToken->name[i] - '0'; - bool overflow = false; - if (isInt64) - overflow = (ival > oneTenthMaxInt64 || (ival == oneTenthMaxInt64 && (unsigned long long)ch > remainderMaxInt64)); - else if (isInt16) - overflow = (ival > oneTenthMaxInt16 || (ival == oneTenthMaxInt16 && (unsigned short)ch > remainderMaxInt16)); - else - overflow = (ival > oneTenthMaxInt || (ival == oneTenthMaxInt && (unsigned)ch > remainderMaxInt)); - if (overflow) { - pp->parseContext.ppError(ppToken->loc, "numeric literal too big", "", ""); - ival = 0xFFFFFFFFFFFFFFFFull; - break; - } else - ival = ival * 10 + ch; - } - - if (isInt64 && pp->parseContext.intermediate.getSource() == EShSourceGlsl) { - if (pp->ifdepth == 0) { - pp->parseContext.requireProfile(ppToken->loc, ~EEsProfile, - "64-bit literal"); - pp->parseContext.profileRequires(ppToken->loc, ~EEsProfile, 0, - Num_Int64_Extensions, Int64_Extensions, "64-bit literal"); - } - ppToken->i64val = ival; - return isUnsigned ? PpAtomConstUint64 : PpAtomConstInt64; - } else if (isInt16) { - if (pp->ifdepth == 0 && pp->parseContext.intermediate.getSource() == EShSourceGlsl) { - pp->parseContext.requireProfile(ppToken->loc, ~EEsProfile, - "16-bit literal"); - pp->parseContext.profileRequires(ppToken->loc, ~EEsProfile, 0, - Num_Int16_Extensions, Int16_Extensions, "16-bit literal"); - } - ppToken->ival = (int)ival; - return isUnsigned ? PpAtomConstUint16 : PpAtomConstInt16; - } else { - ppToken->ival = (int)ival; - return isUnsigned ? PpAtomConstUint : PpAtomConstInt; - } - } - break; - case '-': - ch = getch(); - if (ch == '-') { - return PpAtomDecrement; - } else if (ch == '=') { - return PPAtomSubAssign; - } else { - ungetch(); - return '-'; - } - case '+': - ch = getch(); - if (ch == '+') { - return PpAtomIncrement; - } else if (ch == '=') { - return PPAtomAddAssign; - } else { - ungetch(); - return '+'; - } - case '*': - ch = getch(); - if (ch == '=') { - return PPAtomMulAssign; - } else { - ungetch(); - return '*'; - } - case '%': - ch = getch(); - if (ch == '=') { - return PPAtomModAssign; - } else { - ungetch(); - return '%'; - } - case '^': - ch = getch(); - if (ch == '^') { - return PpAtomXor; - } else { - if (ch == '=') - return PpAtomXorAssign; - else{ - ungetch(); - return '^'; - } - } - - case '=': - ch = getch(); - if (ch == '=') { - return PpAtomEQ; - } else { - ungetch(); - return '='; - } - case '!': - ch = getch(); - if (ch == '=') { - return PpAtomNE; - } else { - ungetch(); - return '!'; - } - case '|': - ch = getch(); - if (ch == '|') { - return PpAtomOr; - } else if (ch == '=') { - return PpAtomOrAssign; - } else { - ungetch(); - return '|'; - } - case '&': - ch = getch(); - if (ch == '&') { - return PpAtomAnd; - } else if (ch == '=') { - return PpAtomAndAssign; - } else { - ungetch(); - return '&'; - } - case '<': - ch = getch(); - if (ch == '<') { - ch = getch(); - if (ch == '=') - return PpAtomLeftAssign; - else { - ungetch(); - return PpAtomLeft; - } - } else if (ch == '=') { - return PpAtomLE; - } else { - ungetch(); - return '<'; - } - case '>': - ch = getch(); - if (ch == '>') { - ch = getch(); - if (ch == '=') - return PpAtomRightAssign; - else { - ungetch(); - return PpAtomRight; - } - } else if (ch == '=') { - return PpAtomGE; - } else { - ungetch(); - return '>'; - } - case '.': - ch = getch(); - if (ch >= '0' && ch <= '9') { - ungetch(); - return pp->lFloatConst(0, '.', ppToken); - } else { - ungetch(); - return '.'; - } - case '/': - ch = getch(); - if (ch == '/') { - pp->inComment = true; - do { - ch = getch(); - } while (ch != '\n' && ch != EndOfInput); - ppToken->space = true; - pp->inComment = false; - - return ch; - } else if (ch == '*') { - ch = getch(); - do { - while (ch != '*') { - if (ch == EndOfInput) { - pp->parseContext.ppError(ppToken->loc, "End of input in comment", "comment", ""); - return ch; - } - ch = getch(); - } - ch = getch(); - if (ch == EndOfInput) { - pp->parseContext.ppError(ppToken->loc, "End of input in comment", "comment", ""); - return ch; - } - } while (ch != '/'); - ppToken->space = true; - // loop again to get the next token... - break; - } else if (ch == '=') { - return PPAtomDivAssign; - } else { - ungetch(); - return '/'; - } - break; - case '\'': - return pp->characterLiteral(ppToken); - case '"': - // TODO: If this gets enhanced to handle escape sequences, or - // anything that is different than what #include needs, then - // #include needs to use scanHeaderName() for this. - ch = getch(); - while (ch != '"' && ch != '\n' && ch != EndOfInput) { - if (len < MaxTokenLength) { - ppToken->name[len] = (char)ch; - len++; - ch = getch(); - } else - break; - }; - ppToken->name[len] = '\0'; - if (ch != '"') { - ungetch(); - pp->parseContext.ppError(ppToken->loc, "End of line in string", "string", ""); - } - return PpAtomConstString; - case ':': - ch = getch(); - if (ch == ':') - return PpAtomColonColon; - ungetch(); - return ':'; - } - - ch = getch(); - } -} - -// -// The main functional entry point into the preprocessor, which will -// scan the source strings to figure out and return the next processing token. -// -// Return the token, or EndOfInput when no more tokens. -// -int TPpContext::tokenize(TPpToken& ppToken) -{ - for(;;) { - int token = scanToken(&ppToken); - - // Handle token-pasting logic - token = tokenPaste(token, ppToken); - - if (token == EndOfInput) { - missingEndifCheck(); - return EndOfInput; - } - if (token == '#') { - if (previous_token == '\n') { - token = readCPPline(&ppToken); - if (token == EndOfInput) { - missingEndifCheck(); - return EndOfInput; - } - continue; - } else { - parseContext.ppError(ppToken.loc, "preprocessor directive cannot be preceded by another token", "#", ""); - return EndOfInput; - } - } - previous_token = token; - - if (token == '\n') - continue; - - // expand macros - if (token == PpAtomIdentifier && MacroExpand(&ppToken, false, true) != 0) - continue; - - switch (token) { - case PpAtomIdentifier: - case PpAtomConstInt: - case PpAtomConstUint: - case PpAtomConstFloat: - case PpAtomConstInt64: - case PpAtomConstUint64: - case PpAtomConstInt16: - case PpAtomConstUint16: - case PpAtomConstDouble: - case PpAtomConstFloat16: - if (ppToken.name[0] == '\0') - continue; - break; - case PpAtomConstString: - if (ifdepth == 0 && parseContext.intermediate.getSource() != EShSourceHlsl) { - // HLSL allows string literals. - parseContext.ppError(ppToken.loc, "string literals not supported", "\"\"", ""); - continue; - } - break; - case '\'': - parseContext.ppError(ppToken.loc, "character literals not supported", "\'", ""); - continue; - default: - strcpy(ppToken.name, atomStrings.getString(token)); - break; - } - - return token; - } -} - -// -// Do all token-pasting related combining of two pasted tokens when getting a -// stream of tokens from a replacement list. Degenerates to no processing if a -// replacement list is not the source of the token stream. -// -int TPpContext::tokenPaste(int token, TPpToken& ppToken) -{ - // starting with ## is illegal, skip to next token - if (token == PpAtomPaste) { - parseContext.ppError(ppToken.loc, "unexpected location", "##", ""); - return scanToken(&ppToken); - } - - int resultToken = token; // "foo" pasted with "35" is an identifier, not a number - - // ## can be chained, process all in the chain at once - while (peekPasting()) { - TPpToken pastedPpToken; - - // next token has to be ## - token = scanToken(&pastedPpToken); - assert(token == PpAtomPaste); - - // This covers end of macro expansion - if (endOfReplacementList()) { - parseContext.ppError(ppToken.loc, "unexpected location; end of replacement list", "##", ""); - break; - } - - // get the token after the ## - token = scanToken(&pastedPpToken); - - // This covers end of argument expansion - if (token == tMarkerInput::marker) { - parseContext.ppError(ppToken.loc, "unexpected location; end of argument", "##", ""); - break; - } - - // get the token text - switch (resultToken) { - case PpAtomIdentifier: - // already have the correct text in token.names - break; - case '=': - case '!': - case '-': - case '~': - case '+': - case '*': - case '/': - case '%': - case '<': - case '>': - case '|': - case '^': - case '&': - case PpAtomRight: - case PpAtomLeft: - case PpAtomAnd: - case PpAtomOr: - case PpAtomXor: - strcpy(ppToken.name, atomStrings.getString(resultToken)); - strcpy(pastedPpToken.name, atomStrings.getString(token)); - break; - default: - parseContext.ppError(ppToken.loc, "not supported for these tokens", "##", ""); - return resultToken; - } - - // combine the tokens - if (strlen(ppToken.name) + strlen(pastedPpToken.name) > MaxTokenLength) { - parseContext.ppError(ppToken.loc, "combined tokens are too long", "##", ""); - return resultToken; - } - strncat(ppToken.name, pastedPpToken.name, MaxTokenLength - strlen(ppToken.name)); - - // correct the kind of token we are making, if needed (identifiers stay identifiers) - if (resultToken != PpAtomIdentifier) { - int newToken = atomStrings.getAtom(ppToken.name); - if (newToken > 0) - resultToken = newToken; - else - parseContext.ppError(ppToken.loc, "combined token is invalid", "##", ""); - } - } - - return resultToken; -} - -// Checks if we've seen balanced #if...#endif -void TPpContext::missingEndifCheck() -{ - if (ifdepth > 0) - parseContext.ppError(parseContext.getCurrentLoc(), "missing #endif", "", ""); -} - -} // end namespace glslang diff --git a/External/glslang/glslang/MachineIndependent/preprocessor/PpTokens.cpp b/External/glslang/glslang/MachineIndependent/preprocessor/PpTokens.cpp deleted file mode 100644 index 31e0d1f9..00000000 --- a/External/glslang/glslang/MachineIndependent/preprocessor/PpTokens.cpp +++ /dev/null @@ -1,359 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// Copyright (C) 2013 LunarG, Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// -/****************************************************************************\ -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. -\****************************************************************************/ - -// -// For recording and playing back the stream of tokens in a macro definition. -// - -#ifndef _CRT_SECURE_NO_WARNINGS -#define _CRT_SECURE_NO_WARNINGS -#endif -#if (defined(_MSC_VER) && _MSC_VER < 1900 /*vs2015*/) -#define snprintf sprintf_s -#endif - -#include -#include -#include -#include - -#include "PpContext.h" -#include "PpTokens.h" - -namespace glslang { - -// push onto back of stream -void TPpContext::TokenStream::putSubtoken(char subtoken) -{ - data.push_back(static_cast(subtoken)); -} - -// get the next token in stream -int TPpContext::TokenStream::getSubtoken() -{ - if (current < data.size()) - return data[current++]; - else - return EndOfInput; -} - -// back up one position in the stream -void TPpContext::TokenStream::ungetSubtoken() -{ - if (current > 0) - --current; -} - -// Add a complete token (including backing string) to the end of a list -// for later playback. -void TPpContext::TokenStream::putToken(int token, TPpToken* ppToken) -{ - const char* s; - char* str = NULL; - - assert((token & ~0xff) == 0); - putSubtoken(static_cast(token)); - - switch (token) { - case PpAtomIdentifier: - case PpAtomConstString: - s = ppToken->name; - while (*s) - putSubtoken(*s++); - putSubtoken(0); - break; - case PpAtomConstInt: - case PpAtomConstUint: - case PpAtomConstInt64: - case PpAtomConstUint64: -#ifdef AMD_EXTENSIONS - case PpAtomConstInt16: - case PpAtomConstUint16: -#endif - case PpAtomConstFloat: - case PpAtomConstDouble: - case PpAtomConstFloat16: - str = ppToken->name; - while (*str) { - putSubtoken(*str); - str++; - } - putSubtoken(0); - break; - default: - break; - } -} - -// Read the next token from a token stream. -// (Not the source stream, but a stream used to hold a tokenized macro). -int TPpContext::TokenStream::getToken(TParseContextBase& parseContext, TPpToken *ppToken) -{ - int len; - int ch; - - int subtoken = getSubtoken(); - ppToken->loc = parseContext.getCurrentLoc(); - switch (subtoken) { - case '#': - // Check for ##, unless the current # is the last character - if (current < data.size()) { - if (getSubtoken() == '#') { - parseContext.requireProfile(ppToken->loc, ~EEsProfile, "token pasting (##)"); - parseContext.profileRequires(ppToken->loc, ~EEsProfile, 130, 0, "token pasting (##)"); - subtoken = PpAtomPaste; - } else - ungetSubtoken(); - } - break; - case PpAtomConstString: - case PpAtomIdentifier: - case PpAtomConstFloat: - case PpAtomConstDouble: - case PpAtomConstFloat16: - case PpAtomConstInt: - case PpAtomConstUint: - case PpAtomConstInt64: - case PpAtomConstUint64: -#ifdef AMD_EXTENSIONS - case PpAtomConstInt16: - case PpAtomConstUint16: -#endif - len = 0; - ch = getSubtoken(); - while (ch != 0 && ch != EndOfInput) { - if (len < MaxTokenLength) { - ppToken->name[len] = (char)ch; - len++; - ch = getSubtoken(); - } else { - parseContext.error(ppToken->loc, "token too long", "", ""); - break; - } - } - ppToken->name[len] = 0; - - switch (subtoken) { - case PpAtomIdentifier: - break; - case PpAtomConstString: - break; - case PpAtomConstFloat: - case PpAtomConstDouble: - case PpAtomConstFloat16: - ppToken->dval = atof(ppToken->name); - break; - case PpAtomConstInt: -#ifdef AMD_EXTENSIONS - case PpAtomConstInt16: -#endif - if (len > 0 && ppToken->name[0] == '0') { - if (len > 1 && (ppToken->name[1] == 'x' || ppToken->name[1] == 'X')) - ppToken->ival = (int)strtol(ppToken->name, 0, 16); - else - ppToken->ival = (int)strtol(ppToken->name, 0, 8); - } else - ppToken->ival = atoi(ppToken->name); - break; - case PpAtomConstUint: -#ifdef AMD_EXTENSIONS - case PpAtomConstUint16: -#endif - if (len > 0 && ppToken->name[0] == '0') { - if (len > 1 && (ppToken->name[1] == 'x' || ppToken->name[1] == 'X')) - ppToken->ival = (int)strtoul(ppToken->name, 0, 16); - else - ppToken->ival = (int)strtoul(ppToken->name, 0, 8); - } else - ppToken->ival = (int)strtoul(ppToken->name, 0, 10); - break; - case PpAtomConstInt64: - if (len > 0 && ppToken->name[0] == '0') { - if (len > 1 && (ppToken->name[1] == 'x' || ppToken->name[1] == 'X')) - ppToken->i64val = strtoll(ppToken->name, nullptr, 16); - else - ppToken->i64val = strtoll(ppToken->name, nullptr, 8); - } else - ppToken->i64val = atoll(ppToken->name); - break; - case PpAtomConstUint64: - if (len > 0 && ppToken->name[0] == '0') { - if (len > 1 && (ppToken->name[1] == 'x' || ppToken->name[1] == 'X')) - ppToken->i64val = (long long)strtoull(ppToken->name, nullptr, 16); - else - ppToken->i64val = (long long)strtoull(ppToken->name, nullptr, 8); - } else - ppToken->i64val = (long long)strtoull(ppToken->name, 0, 10); - break; - } - } - - return subtoken; -} - -// We are pasting if -// 1. we are preceding a pasting operator within this stream -// or -// 2. the entire macro is preceding a pasting operator (lastTokenPastes) -// and we are also on the last token -bool TPpContext::TokenStream::peekTokenizedPasting(bool lastTokenPastes) -{ - // 1. preceding ##? - - size_t savePos = current; - int subtoken; - // skip white space - do { - subtoken = getSubtoken(); - } while (subtoken == ' '); - current = savePos; - if (subtoken == PpAtomPaste) - return true; - - // 2. last token and we've been told after this there will be a ## - - if (! lastTokenPastes) - return false; - // Getting here means the last token will be pasted, after this - - // Are we at the last non-whitespace token? - savePos = current; - bool moreTokens = false; - do { - subtoken = getSubtoken(); - if (subtoken == EndOfInput) - break; - if (subtoken != ' ') { - moreTokens = true; - break; - } - } while (true); - current = savePos; - - return !moreTokens; -} - -// See if the next non-white-space tokens are two consecutive # -bool TPpContext::TokenStream::peekUntokenizedPasting() -{ - // don't return early, have to restore this - size_t savePos = current; - - // skip white-space - int subtoken; - do { - subtoken = getSubtoken(); - } while (subtoken == ' '); - - // check for ## - bool pasting = false; - if (subtoken == '#') { - subtoken = getSubtoken(); - if (subtoken == '#') - pasting = true; - } - - current = savePos; - - return pasting; -} - -void TPpContext::pushTokenStreamInput(TokenStream& ts, bool prepasting) -{ - pushInput(new tTokenInput(this, &ts, prepasting)); - ts.reset(); -} - -int TPpContext::tUngotTokenInput::scan(TPpToken* ppToken) -{ - if (done) - return EndOfInput; - - int ret = token; - *ppToken = lval; - done = true; - - return ret; -} - -void TPpContext::UngetToken(int token, TPpToken* ppToken) -{ - pushInput(new tUngotTokenInput(this, token, ppToken)); -} - -} // end namespace glslang diff --git a/External/glslang/glslang/MachineIndependent/preprocessor/PpTokens.h b/External/glslang/glslang/MachineIndependent/preprocessor/PpTokens.h deleted file mode 100644 index 7b0f8155..00000000 --- a/External/glslang/glslang/MachineIndependent/preprocessor/PpTokens.h +++ /dev/null @@ -1,179 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// -/****************************************************************************\ -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/External/glslang/glslang/MachineIndependent/propagateNoContraction.cpp b/External/glslang/glslang/MachineIndependent/propagateNoContraction.cpp deleted file mode 100644 index ae95688a..00000000 --- a/External/glslang/glslang/MachineIndependent/propagateNoContraction.cpp +++ /dev/null @@ -1,866 +0,0 @@ -// -// 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 the 'noContraction' qualifier. -// - -#include "propagateNoContraction.h" - -#include -#include -#include -#include -#include - -#include "localintermediate.h" -namespace { - -// Use a string to hold the access chain information, as in most cases the -// access chain is short and may contain only one element, which is the symbol -// ID. -// Example: struct {float a; float b;} s; -// Object s.a will be represented with: /0 -// Object s.b will be represented with: /1 -// Object s will be represented with: -// For members of vector, matrix and arrays, they will be represented with the -// same symbol ID of their container symbol objects. This is because their -// preciseness is always the same as their container symbol objects. -typedef std::string ObjectAccessChain; - -// The delimiter used in the ObjectAccessChain string to separate symbol ID and -// different level of struct indices. -const char ObjectAccesschainDelimiter = '/'; - -// Mapping from Symbol IDs of symbol nodes, to their defining operation -// nodes. -typedef std::unordered_multimap NodeMapping; -// Mapping from object nodes to their access chain info string. -typedef std::unordered_map AccessChainMapping; - -// Set of object IDs. -typedef std::unordered_set ObjectAccesschainSet; -// Set of return branch nodes. -typedef std::unordered_set ReturnBranchNodeSet; - -// A helper function to tell whether a node is 'noContraction'. Returns true if -// the node has 'noContraction' qualifier, otherwise false. -bool isPreciseObjectNode(glslang::TIntermTyped* node) -{ - return node->getType().getQualifier().noContraction; -} - -// Returns true if the opcode is a dereferencing one. -bool isDereferenceOperation(glslang::TOperator op) -{ - switch (op) { - case glslang::EOpIndexDirect: - case glslang::EOpIndexDirectStruct: - case glslang::EOpIndexIndirect: - case glslang::EOpVectorSwizzle: - case glslang::EOpMatrixSwizzle: - return true; - default: - return false; - } -} - -// Returns true if the opcode leads to an assignment operation. -bool isAssignOperation(glslang::TOperator op) -{ - switch (op) { - case glslang::EOpAssign: - case glslang::EOpAddAssign: - case glslang::EOpSubAssign: - case glslang::EOpMulAssign: - case glslang::EOpVectorTimesMatrixAssign: - case glslang::EOpVectorTimesScalarAssign: - case glslang::EOpMatrixTimesScalarAssign: - case glslang::EOpMatrixTimesMatrixAssign: - case glslang::EOpDivAssign: - case glslang::EOpModAssign: - case glslang::EOpAndAssign: - case glslang::EOpLeftShiftAssign: - case glslang::EOpRightShiftAssign: - case glslang::EOpInclusiveOrAssign: - case glslang::EOpExclusiveOrAssign: - - case glslang::EOpPostIncrement: - case glslang::EOpPostDecrement: - case glslang::EOpPreIncrement: - case glslang::EOpPreDecrement: - return true; - default: - return false; - } -} - -// A helper function to get the unsigned int from a given constant union node. -// Note the node should only hold a uint scalar. -unsigned getStructIndexFromConstantUnion(glslang::TIntermTyped* node) -{ - assert(node->getAsConstantUnion() && node->getAsConstantUnion()->isScalar()); - unsigned struct_dereference_index = node->getAsConstantUnion()->getConstArray()[0].getUConst(); - return struct_dereference_index; -} - -// A helper function to generate symbol_label. -ObjectAccessChain generateSymbolLabel(glslang::TIntermSymbol* node) -{ - ObjectAccessChain symbol_id = - std::to_string(node->getId()) + "(" + node->getName().c_str() + ")"; - return symbol_id; -} - -// Returns true if the operation is an arithmetic operation and valid for -// the 'NoContraction' decoration. -bool isArithmeticOperation(glslang::TOperator op) -{ - switch (op) { - case glslang::EOpAddAssign: - case glslang::EOpSubAssign: - case glslang::EOpMulAssign: - case glslang::EOpVectorTimesMatrixAssign: - case glslang::EOpVectorTimesScalarAssign: - case glslang::EOpMatrixTimesScalarAssign: - case glslang::EOpMatrixTimesMatrixAssign: - case glslang::EOpDivAssign: - case glslang::EOpModAssign: - - case glslang::EOpNegative: - - case glslang::EOpAdd: - case glslang::EOpSub: - case glslang::EOpMul: - case glslang::EOpDiv: - case glslang::EOpMod: - - case glslang::EOpVectorTimesScalar: - case glslang::EOpVectorTimesMatrix: - case glslang::EOpMatrixTimesVector: - case glslang::EOpMatrixTimesScalar: - case glslang::EOpMatrixTimesMatrix: - - case glslang::EOpDot: - - case glslang::EOpPostIncrement: - case glslang::EOpPostDecrement: - case glslang::EOpPreIncrement: - case glslang::EOpPreDecrement: - return true; - default: - return false; - } -} - -// A helper class to help manage the populating_initial_no_contraction_ flag. -template class StateSettingGuard { -public: - StateSettingGuard(T* state_ptr, T new_state_value) - : state_ptr_(state_ptr), previous_state_(*state_ptr) - { - *state_ptr = new_state_value; - } - StateSettingGuard(T* state_ptr) : state_ptr_(state_ptr), previous_state_(*state_ptr) {} - void setState(T new_state_value) { *state_ptr_ = new_state_value; } - ~StateSettingGuard() { *state_ptr_ = previous_state_; } - -private: - T* state_ptr_; - T previous_state_; -}; - -// A helper function to get the front element from a given ObjectAccessChain -ObjectAccessChain getFrontElement(const ObjectAccessChain& chain) -{ - size_t pos_delimiter = chain.find(ObjectAccesschainDelimiter); - return pos_delimiter == std::string::npos ? chain : chain.substr(0, pos_delimiter); -} - -// A helper function to get the access chain starting from the second element. -ObjectAccessChain subAccessChainFromSecondElement(const ObjectAccessChain& chain) -{ - size_t pos_delimiter = chain.find(ObjectAccesschainDelimiter); - return pos_delimiter == std::string::npos ? "" : chain.substr(pos_delimiter + 1); -} - -// A helper function to get the access chain after removing a given prefix. -ObjectAccessChain getSubAccessChainAfterPrefix(const ObjectAccessChain& chain, - const ObjectAccessChain& prefix) -{ - size_t pos = chain.find(prefix); - if (pos != 0) - return chain; - return chain.substr(prefix.length() + sizeof(ObjectAccesschainDelimiter)); -} - -// -// A traverser which traverses the whole AST and populates: -// 1) A mapping from symbol nodes' IDs to their defining operation nodes. -// 2) A set of access chains of the initial precise object nodes. -// -class TSymbolDefinitionCollectingTraverser : public glslang::TIntermTraverser { -public: - TSymbolDefinitionCollectingTraverser(NodeMapping* symbol_definition_mapping, - AccessChainMapping* accesschain_mapping, - ObjectAccesschainSet* precise_objects, - ReturnBranchNodeSet* precise_return_nodes); - - bool visitUnary(glslang::TVisit, glslang::TIntermUnary*) override; - bool visitBinary(glslang::TVisit, glslang::TIntermBinary*) override; - void visitSymbol(glslang::TIntermSymbol*) override; - bool visitAggregate(glslang::TVisit, glslang::TIntermAggregate*) override; - bool visitBranch(glslang::TVisit, glslang::TIntermBranch*) override; - -protected: - TSymbolDefinitionCollectingTraverser& operator=(const TSymbolDefinitionCollectingTraverser&); - - // The mapping from symbol node IDs to their defining nodes. This should be - // populated along traversing the AST. - NodeMapping& symbol_definition_mapping_; - // The set of symbol node IDs for precise symbol nodes, the ones marked as - // 'noContraction'. - ObjectAccesschainSet& precise_objects_; - // The set of precise return nodes. - ReturnBranchNodeSet& precise_return_nodes_; - // A temporary cache of the symbol node whose defining node is to be found - // currently along traversing the AST. - ObjectAccessChain current_object_; - // A map from object node to its access chain. This traverser stores - // the built access chains into this map for each object node it has - // visited. - AccessChainMapping& accesschain_mapping_; - // The pointer to the Function Definition node, so we can get the - // preciseness of the return expression from it when we traverse the - // return branch node. - glslang::TIntermAggregate* current_function_definition_node_; -}; - -TSymbolDefinitionCollectingTraverser::TSymbolDefinitionCollectingTraverser( - NodeMapping* symbol_definition_mapping, AccessChainMapping* accesschain_mapping, - ObjectAccesschainSet* precise_objects, - std::unordered_set* precise_return_nodes) - : TIntermTraverser(true, false, false), symbol_definition_mapping_(*symbol_definition_mapping), - precise_objects_(*precise_objects), precise_return_nodes_(*precise_return_nodes), - current_object_(), accesschain_mapping_(*accesschain_mapping), - current_function_definition_node_(nullptr) {} - -// Visits a symbol node, set the current_object_ to the -// current node symbol ID, and record a mapping from this node to the current -// current_object_, which is the just obtained symbol -// ID. -void TSymbolDefinitionCollectingTraverser::visitSymbol(glslang::TIntermSymbol* node) -{ - current_object_ = generateSymbolLabel(node); - accesschain_mapping_[node] = current_object_; -} - -// Visits an aggregate node, traverses all of its children. -bool TSymbolDefinitionCollectingTraverser::visitAggregate(glslang::TVisit, - glslang::TIntermAggregate* node) -{ - // This aggregate node might be a function definition node, in which case we need to - // cache this node, so we can get the preciseness information of the return value - // of this function later. - StateSettingGuard current_function_definition_node_setting_guard( - ¤t_function_definition_node_); - if (node->getOp() == glslang::EOpFunction) { - // This is function definition node, we need to cache this node so that we can - // get the preciseness of the return value later. - current_function_definition_node_setting_guard.setState(node); - } - // Traverse the items in the sequence. - glslang::TIntermSequence& seq = node->getSequence(); - for (int i = 0; i < (int)seq.size(); ++i) { - current_object_.clear(); - seq[i]->traverse(this); - } - return false; -} - -bool TSymbolDefinitionCollectingTraverser::visitBranch(glslang::TVisit, - glslang::TIntermBranch* node) -{ - if (node->getFlowOp() == glslang::EOpReturn && node->getExpression() && - current_function_definition_node_ && - current_function_definition_node_->getType().getQualifier().noContraction) { - // This node is a return node with an expression, and its function has a - // precise return value. We need to find the involved objects in its - // expression and add them to the set of initial precise objects. - precise_return_nodes_.insert(node); - node->getExpression()->traverse(this); - } - return false; -} - -// Visits a unary node. This might be an implicit assignment like i++, i--. etc. -bool TSymbolDefinitionCollectingTraverser::visitUnary(glslang::TVisit /* visit */, - glslang::TIntermUnary* node) -{ - current_object_.clear(); - node->getOperand()->traverse(this); - if (isAssignOperation(node->getOp())) { - // We should always be able to get an access chain of the operand node. - assert(!current_object_.empty()); - - // If the operand node object is 'precise', we collect its access chain - // for the initial set of 'precise' objects. - if (isPreciseObjectNode(node->getOperand())) { - // The operand node is an 'precise' object node, add its - // access chain to the set of 'precise' objects. This is to collect - // the initial set of 'precise' objects. - precise_objects_.insert(current_object_); - } - // Gets the symbol ID from the object's access chain. - ObjectAccessChain id_symbol = getFrontElement(current_object_); - // Add a mapping from the symbol ID to this assignment operation node. - symbol_definition_mapping_.insert(std::make_pair(id_symbol, node)); - } - // A unary node is not a dereference node, so we clear the access chain which - // is under construction. - current_object_.clear(); - return false; -} - -// Visits a binary node and updates the mapping from symbol IDs to the definition -// nodes. Also collects the access chains for the initial precise objects. -bool TSymbolDefinitionCollectingTraverser::visitBinary(glslang::TVisit /* visit */, - glslang::TIntermBinary* node) -{ - // Traverses the left node to build the access chain info for the object. - current_object_.clear(); - node->getLeft()->traverse(this); - - if (isAssignOperation(node->getOp())) { - // We should always be able to get an access chain for the left node. - assert(!current_object_.empty()); - - // If the left node object is 'precise', it is an initial precise object - // specified in the shader source. Adds it to the initial work list to - // process later. - if (isPreciseObjectNode(node->getLeft())) { - // The left node is an 'precise' object node, add its access chain to - // the set of 'precise' objects. This is to collect the initial set - // of 'precise' objects. - precise_objects_.insert(current_object_); - } - // Gets the symbol ID from the object access chain, which should be the - // first element recorded in the access chain. - ObjectAccessChain id_symbol = getFrontElement(current_object_); - // Adds a mapping from the symbol ID to this assignment operation node. - symbol_definition_mapping_.insert(std::make_pair(id_symbol, node)); - - // Traverses the right node, there may be other 'assignment' - // operations in the right. - current_object_.clear(); - node->getRight()->traverse(this); - - } else if (isDereferenceOperation(node->getOp())) { - // The left node (parent node) is a struct type object. We need to - // record the access chain information of the current node into its - // object id. - if (node->getOp() == glslang::EOpIndexDirectStruct) { - unsigned struct_dereference_index = getStructIndexFromConstantUnion(node->getRight()); - current_object_.push_back(ObjectAccesschainDelimiter); - current_object_.append(std::to_string(struct_dereference_index)); - } - accesschain_mapping_[node] = current_object_; - - // For a dereference node, there is no need to traverse the right child - // node as the right node should always be an integer type object. - - } else { - // For other binary nodes, still traverse the right node. - current_object_.clear(); - node->getRight()->traverse(this); - } - return false; -} - -// Traverses the AST and returns a tuple of four members: -// 1) a mapping from symbol IDs to the definition nodes (aka. assignment nodes) of these symbols. -// 2) a mapping from object nodes in the AST to the access chains of these objects. -// 3) a set of access chains of precise objects. -// 4) a set of return nodes with precise expressions. -std::tuple -getSymbolToDefinitionMappingAndPreciseSymbolIDs(const glslang::TIntermediate& intermediate) -{ - auto result_tuple = std::make_tuple(NodeMapping(), AccessChainMapping(), ObjectAccesschainSet(), - ReturnBranchNodeSet()); - - TIntermNode* root = intermediate.getTreeRoot(); - if (root == 0) - return result_tuple; - - NodeMapping& symbol_definition_mapping = std::get<0>(result_tuple); - AccessChainMapping& accesschain_mapping = std::get<1>(result_tuple); - ObjectAccesschainSet& precise_objects = std::get<2>(result_tuple); - ReturnBranchNodeSet& precise_return_nodes = std::get<3>(result_tuple); - - // Traverses the AST and populate the results. - TSymbolDefinitionCollectingTraverser collector(&symbol_definition_mapping, &accesschain_mapping, - &precise_objects, &precise_return_nodes); - root->traverse(&collector); - - return result_tuple; -} - -// -// A traverser that determine whether the left node (or operand node for unary -// node) of an assignment node is 'precise', containing 'precise' or not, -// according to the access chain a given precise object which share the same -// symbol as the left node. -// -// Post-orderly traverses the left node subtree of an binary assignment node and: -// -// 1) Propagates the 'precise' from the left object nodes to this object node. -// -// 2) Builds object access chain along the traversal, and also compares with -// the access chain of the given 'precise' object along with the traversal to -// tell if the node to be defined is 'precise' or not. -// -class TNoContractionAssigneeCheckingTraverser : public glslang::TIntermTraverser { - - enum DecisionStatus { - // The object node to be assigned to may contain 'precise' objects and also not 'precise' objects. - Mixed = 0, - // The object node to be assigned to is either a 'precise' object or a struct objects whose members are all 'precise'. - Precise = 1, - // The object node to be assigned to is not a 'precise' object. - NotPreicse = 2, - }; - -public: - TNoContractionAssigneeCheckingTraverser(const AccessChainMapping& accesschain_mapping) - : TIntermTraverser(true, false, false), accesschain_mapping_(accesschain_mapping), - precise_object_(nullptr) {} - - // Checks the preciseness of a given assignment node with a precise object - // represented as access chain. The precise object shares the same symbol - // with the assignee of the given assignment node. Return a tuple of two: - // - // 1) The preciseness of the assignee node of this assignment node. True - // if the assignee contains 'precise' objects or is 'precise', false if - // the assignee is not 'precise' according to the access chain of the given - // precise object. - // - // 2) The incremental access chain from the assignee node to its nested - // 'precise' object, according to the access chain of the given precise - // object. This incremental access chain can be empty, which means the - // assignee is 'precise'. Otherwise it shows the path to the nested - // precise object. - std::tuple - getPrecisenessAndRemainedAccessChain(glslang::TIntermOperator* node, - const ObjectAccessChain& precise_object) - { - assert(isAssignOperation(node->getOp())); - precise_object_ = &precise_object; - ObjectAccessChain assignee_object; - if (glslang::TIntermBinary* BN = node->getAsBinaryNode()) { - // This is a binary assignment node, we need to check the - // preciseness of the left node. - assert(accesschain_mapping_.count(BN->getLeft())); - // The left node (assignee node) is an object node, traverse the - // node to let the 'precise' of nesting objects being transfered to - // nested objects. - BN->getLeft()->traverse(this); - // After traversing the left node, if the left node is 'precise', - // we can conclude this assignment should propagate 'precise'. - if (isPreciseObjectNode(BN->getLeft())) { - return make_tuple(true, ObjectAccessChain()); - } - // If the preciseness of the left node (assignee node) can not - // be determined by now, we need to compare the access chain string - // of the assignee object with the given precise object. - assignee_object = accesschain_mapping_.at(BN->getLeft()); - - } else if (glslang::TIntermUnary* UN = node->getAsUnaryNode()) { - // This is a unary assignment node, we need to check the - // preciseness of the operand node. For unary assignment node, the - // operand node should always be an object node. - assert(accesschain_mapping_.count(UN->getOperand())); - // Traverse the operand node to let the 'precise' being propagated - // from lower nodes to upper nodes. - UN->getOperand()->traverse(this); - // After traversing the operand node, if the operand node is - // 'precise', this assignment should propagate 'precise'. - if (isPreciseObjectNode(UN->getOperand())) { - return make_tuple(true, ObjectAccessChain()); - } - // If the preciseness of the operand node (assignee node) can not - // be determined by now, we need to compare the access chain string - // of the assignee object with the given precise object. - assignee_object = accesschain_mapping_.at(UN->getOperand()); - } else { - // Not a binary or unary node, should not happen. - assert(false); - } - - // Compare the access chain string of the assignee node with the given - // precise object to determine if this assignment should propagate - // 'precise'. - if (assignee_object.find(precise_object) == 0) { - // The access chain string of the given precise object is a prefix - // of assignee's access chain string. The assignee should be - // 'precise'. - return make_tuple(true, ObjectAccessChain()); - } else if (precise_object.find(assignee_object) == 0) { - // The assignee's access chain string is a prefix of the given - // precise object, the assignee object contains 'precise' object, - // and we need to pass the remained access chain to the object nodes - // in the right. - return make_tuple(true, getSubAccessChainAfterPrefix(precise_object, assignee_object)); - } else { - // The access chain strings do not match, the assignee object can - // not be labeled as 'precise' according to the given precise - // object. - return make_tuple(false, ObjectAccessChain()); - } - } - -protected: - TNoContractionAssigneeCheckingTraverser& operator=(const TNoContractionAssigneeCheckingTraverser&); - - bool visitBinary(glslang::TVisit, glslang::TIntermBinary* node) override; - void visitSymbol(glslang::TIntermSymbol* node) override; - - // A map from object nodes to their access chain string (used as object ID). - const AccessChainMapping& accesschain_mapping_; - // A given precise object, represented in it access chain string. This - // precise object is used to be compared with the assignee node to tell if - // the assignee node is 'precise', contains 'precise' object or not - // 'precise'. - const ObjectAccessChain* precise_object_; -}; - -// Visits a binary node. If the node is an object node, it must be a dereference -// node. In such cases, if the left node is 'precise', this node should also be -// 'precise'. -bool TNoContractionAssigneeCheckingTraverser::visitBinary(glslang::TVisit, - glslang::TIntermBinary* node) -{ - // Traverses the left so that we transfer the 'precise' from nesting object - // to its nested object. - node->getLeft()->traverse(this); - // If this binary node is an object node, we should have it in the - // accesschain_mapping_. - if (accesschain_mapping_.count(node)) { - // A binary object node must be a dereference node. - assert(isDereferenceOperation(node->getOp())); - // If the left node is 'precise', this node should also be precise, - // otherwise, compare with the given precise_object_. If the - // access chain of this node matches with the given precise_object_, - // this node should be marked as 'precise'. - if (isPreciseObjectNode(node->getLeft())) { - node->getWritableType().getQualifier().noContraction = true; - } else if (accesschain_mapping_.at(node) == *precise_object_) { - node->getWritableType().getQualifier().noContraction = true; - } - } - return false; -} - -// Visits a symbol node, if the symbol node ID (its access chain string) matches -// with the given precise object, this node should be 'precise'. -void TNoContractionAssigneeCheckingTraverser::visitSymbol(glslang::TIntermSymbol* node) -{ - // A symbol node should always be an object node, and should have been added - // to the map from object nodes to their access chain strings. - assert(accesschain_mapping_.count(node)); - if (accesschain_mapping_.at(node) == *precise_object_) { - node->getWritableType().getQualifier().noContraction = true; - } -} - -// -// A traverser that only traverses the right side of binary assignment nodes -// and the operand node of unary assignment nodes. -// -// 1) Marks arithmetic operations as 'NoContraction'. -// -// 2) Find the object which should be marked as 'precise' in the right and -// update the 'precise' object work list. -// -class TNoContractionPropagator : public glslang::TIntermTraverser { -public: - TNoContractionPropagator(ObjectAccesschainSet* precise_objects, - const AccessChainMapping& accesschain_mapping) - : TIntermTraverser(true, false, false), - precise_objects_(*precise_objects), added_precise_object_ids_(), - remained_accesschain_(), accesschain_mapping_(accesschain_mapping) {} - - // Propagates 'precise' in the right nodes of a given assignment node with - // access chain record from the assignee node to a 'precise' object it - // contains. - void - propagateNoContractionInOneExpression(glslang::TIntermTyped* defining_node, - const ObjectAccessChain& assignee_remained_accesschain) - { - remained_accesschain_ = assignee_remained_accesschain; - if (glslang::TIntermBinary* BN = defining_node->getAsBinaryNode()) { - assert(isAssignOperation(BN->getOp())); - BN->getRight()->traverse(this); - if (isArithmeticOperation(BN->getOp())) { - BN->getWritableType().getQualifier().noContraction = true; - } - } else if (glslang::TIntermUnary* UN = defining_node->getAsUnaryNode()) { - assert(isAssignOperation(UN->getOp())); - UN->getOperand()->traverse(this); - if (isArithmeticOperation(UN->getOp())) { - UN->getWritableType().getQualifier().noContraction = true; - } - } - } - - // Propagates 'precise' in a given precise return node. - void propagateNoContractionInReturnNode(glslang::TIntermBranch* return_node) - { - remained_accesschain_ = ""; - assert(return_node->getFlowOp() == glslang::EOpReturn && return_node->getExpression()); - return_node->getExpression()->traverse(this); - } - -protected: - TNoContractionPropagator& operator=(const TNoContractionPropagator&); - - // Visits an aggregate node. The node can be a initializer list, in which - // case we need to find the 'precise' or 'precise' containing object node - // with the access chain record. In other cases, just need to traverse all - // the children nodes. - bool visitAggregate(glslang::TVisit, glslang::TIntermAggregate* node) override - { - if (!remained_accesschain_.empty() && node->getOp() == glslang::EOpConstructStruct) { - // This is a struct initializer node, and the remained - // access chain is not empty, we need to refer to the - // assignee_remained_access_chain_ to find the nested - // 'precise' object. And we don't need to visit other nodes in this - // aggregate node. - - // Gets the struct dereference index that leads to 'precise' object. - ObjectAccessChain precise_accesschain_index_str = - getFrontElement(remained_accesschain_); - unsigned precise_accesschain_index = (unsigned)strtoul(precise_accesschain_index_str.c_str(), nullptr, 10); - // Gets the node pointed by the access chain index extracted before. - glslang::TIntermTyped* potential_precise_node = - node->getSequence()[precise_accesschain_index]->getAsTyped(); - assert(potential_precise_node); - // Pop the front access chain index from the path, and visit the nested node. - { - ObjectAccessChain next_level_accesschain = - subAccessChainFromSecondElement(remained_accesschain_); - StateSettingGuard setup_remained_accesschain_for_next_level( - &remained_accesschain_, next_level_accesschain); - potential_precise_node->traverse(this); - } - return false; - } - return true; - } - - // Visits a binary node. A binary node can be an object node, e.g. a dereference node. - // As only the top object nodes in the right side of an assignment needs to be visited - // and added to 'precise' work list, this traverser won't visit the children nodes of - // an object node. If the binary node does not represent an object node, it should - // go on to traverse its children nodes and if it is an arithmetic operation node, this - // operation should be marked as 'noContraction'. - bool visitBinary(glslang::TVisit, glslang::TIntermBinary* node) override - { - if (isDereferenceOperation(node->getOp())) { - // This binary node is an object node. Need to update the precise - // object set with the access chain of this node + remained - // access chain . - ObjectAccessChain new_precise_accesschain = accesschain_mapping_.at(node); - if (remained_accesschain_.empty()) { - node->getWritableType().getQualifier().noContraction = true; - } else { - new_precise_accesschain += ObjectAccesschainDelimiter + remained_accesschain_; - } - // Cache the access chain as added precise object, so we won't add the - // same object to the work list again. - if (!added_precise_object_ids_.count(new_precise_accesschain)) { - precise_objects_.insert(new_precise_accesschain); - added_precise_object_ids_.insert(new_precise_accesschain); - } - // Only the upper-most object nodes should be visited, so do not - // visit children of this object node. - return false; - } - // If this is an arithmetic operation, marks this node as 'noContraction'. - if (isArithmeticOperation(node->getOp()) && node->getBasicType() != glslang::EbtInt) { - node->getWritableType().getQualifier().noContraction = true; - } - // As this node is not an object node, need to traverse the children nodes. - return true; - } - - // Visits a unary node. A unary node can not be an object node. If the operation - // is an arithmetic operation, need to mark this node as 'noContraction'. - bool visitUnary(glslang::TVisit /* visit */, glslang::TIntermUnary* node) override - { - // If this is an arithmetic operation, marks this with 'noContraction' - if (isArithmeticOperation(node->getOp())) { - node->getWritableType().getQualifier().noContraction = true; - } - return true; - } - - // Visits a symbol node. A symbol node is always an object node. So we - // should always be able to find its in our collected mapping from object - // nodes to access chains. As an object node, a symbol node can be either - // 'precise' or containing 'precise' objects according to unused - // access chain information we have when we visit this node. - void visitSymbol(glslang::TIntermSymbol* node) override - { - // Symbol nodes are object nodes and should always have an - // access chain collected before matches with it. - assert(accesschain_mapping_.count(node)); - ObjectAccessChain new_precise_accesschain = accesschain_mapping_.at(node); - // If the unused access chain is empty, this symbol node should be - // marked as 'precise'. Otherwise, the unused access chain should be - // appended to the symbol ID to build a new access chain which points to - // the nested 'precise' object in this symbol object. - if (remained_accesschain_.empty()) { - node->getWritableType().getQualifier().noContraction = true; - } else { - new_precise_accesschain += ObjectAccesschainDelimiter + remained_accesschain_; - } - // Add the new 'precise' access chain to the work list and make sure we - // don't visit it again. - if (!added_precise_object_ids_.count(new_precise_accesschain)) { - precise_objects_.insert(new_precise_accesschain); - added_precise_object_ids_.insert(new_precise_accesschain); - } - } - - // A set of precise objects, represented as access chains. - ObjectAccesschainSet& precise_objects_; - // Visited symbol nodes, should not revisit these nodes. - ObjectAccesschainSet added_precise_object_ids_; - // The left node of an assignment operation might be an parent of 'precise' objects. - // This means the left node might not be an 'precise' object node, but it may contains - // 'precise' qualifier which should be propagated to the corresponding child node in - // the right. So we need the path from the left node to its nested 'precise' node to - // tell us how to find the corresponding 'precise' node in the right. - ObjectAccessChain remained_accesschain_; - // A map from node pointers to their access chains. - const AccessChainMapping& accesschain_mapping_; -}; -} - -namespace glslang { - -void PropagateNoContraction(const glslang::TIntermediate& intermediate) -{ - // First, traverses the AST, records symbols with their defining operations - // and collects the initial set of precise symbols (symbol nodes that marked - // as 'noContraction') and precise return nodes. - auto mappings_and_precise_objects = - getSymbolToDefinitionMappingAndPreciseSymbolIDs(intermediate); - - // The mapping of symbol node IDs to their defining nodes. This enables us - // to get the defining node directly from a given symbol ID without - // traversing the tree again. - NodeMapping& symbol_definition_mapping = std::get<0>(mappings_and_precise_objects); - - // The mapping of object nodes to their access chains recorded. - AccessChainMapping& accesschain_mapping = std::get<1>(mappings_and_precise_objects); - - // The initial set of 'precise' objects which are represented as the - // access chain toward them. - ObjectAccesschainSet& precise_object_accesschains = std::get<2>(mappings_and_precise_objects); - - // The set of 'precise' return nodes. - ReturnBranchNodeSet& precise_return_nodes = std::get<3>(mappings_and_precise_objects); - - // Second, uses the initial set of precise objects as a work list, pops an - // access chain, extract the symbol ID from it. Then: - // 1) Check the assignee object, see if it is 'precise' object node or - // contains 'precise' object. Obtain the incremental access chain from the - // assignee node to its nested 'precise' node (if any). - // 2) If the assignee object node is 'precise' or it contains 'precise' - // objects, traverses the right side of the assignment operation - // expression to mark arithmetic operations as 'noContration' and update - // 'precise' access chain work list with new found object nodes. - // Repeat above steps until the work list is empty. - TNoContractionAssigneeCheckingTraverser checker(accesschain_mapping); - TNoContractionPropagator propagator(&precise_object_accesschains, accesschain_mapping); - - // We have two initial precise work lists to handle: - // 1) precise return nodes - // 2) precise object access chains - // We should process the precise return nodes first and the involved - // objects in the return expression should be added to the precise object - // access chain set. - while (!precise_return_nodes.empty()) { - glslang::TIntermBranch* precise_return_node = *precise_return_nodes.begin(); - propagator.propagateNoContractionInReturnNode(precise_return_node); - precise_return_nodes.erase(precise_return_node); - } - - while (!precise_object_accesschains.empty()) { - // Get the access chain of a precise object from the work list. - ObjectAccessChain precise_object_accesschain = *precise_object_accesschains.begin(); - // Get the symbol id from the access chain. - ObjectAccessChain symbol_id = getFrontElement(precise_object_accesschain); - // Get all the defining nodes of that symbol ID. - std::pair range = - symbol_definition_mapping.equal_range(symbol_id); - // Visits all the assignment nodes of that symbol ID and - // 1) Check if the assignee node is 'precise' or contains 'precise' - // objects. - // 2) Propagate the 'precise' to the top layer object nodes - // in the right side of the assignment operation, update the 'precise' - // work list with new access chains representing the new 'precise' - // objects, and mark arithmetic operations as 'noContraction'. - for (NodeMapping::iterator defining_node_iter = range.first; - defining_node_iter != range.second; defining_node_iter++) { - TIntermOperator* defining_node = defining_node_iter->second; - // Check the assignee node. - auto checker_result = checker.getPrecisenessAndRemainedAccessChain( - defining_node, precise_object_accesschain); - bool& contain_precise = std::get<0>(checker_result); - ObjectAccessChain& remained_accesschain = std::get<1>(checker_result); - // If the assignee node is 'precise' or contains 'precise', propagate the - // 'precise' to the right. Otherwise just skip this assignment node. - if (contain_precise) { - propagator.propagateNoContractionInOneExpression(defining_node, - remained_accesschain); - } - } - // Remove the last processed 'precise' object from the work list. - precise_object_accesschains.erase(precise_object_accesschain); - } -} -}; diff --git a/External/glslang/glslang/MachineIndependent/propagateNoContraction.h b/External/glslang/glslang/MachineIndependent/propagateNoContraction.h deleted file mode 100644 index 8521ad7d..00000000 --- a/External/glslang/glslang/MachineIndependent/propagateNoContraction.h +++ /dev/null @@ -1,55 +0,0 @@ -// -// 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/External/glslang/glslang/MachineIndependent/reflection.cpp b/External/glslang/glslang/MachineIndependent/reflection.cpp deleted file mode 100644 index 4818b108..00000000 --- a/External/glslang/glslang/MachineIndependent/reflection.cpp +++ /dev/null @@ -1,843 +0,0 @@ -// -// 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. -// - -#include "../Include/Common.h" -#include "reflection.h" -#include "LiveTraverser.h" -#include "localintermediate.h" - -#include "gl_types.h" - -// -// Grow the reflection database through a friend traverser class of TReflection and a -// collection of functions to do a liveness traversal that note what uniforms are used -// in semantically non-dead code. -// -// Can be used multiple times, once per stage, to grow a program reflection. -// -// High-level algorithm for one stage: -// -// 1. Put the entry point on the list of live functions. -// -// 2. Traverse any live function, while skipping if-tests with a compile-time constant -// condition of false, and while adding any encountered function calls to the live -// function list. -// -// Repeat until the live function list is empty. -// -// 3. Add any encountered uniform variables and blocks to the reflection database. -// -// Can be attempted with a failed link, but will return false if recursion had been detected, or -// there wasn't exactly one entry point. -// - -namespace glslang { - -// -// The traverser: mostly pass through, except -// - processing binary nodes to see if they are dereferences of an aggregates to track -// - processing symbol nodes to see if they are non-aggregate objects to track -// -// This ignores semantically dead code by using TLiveTraverser. -// -// This is in the glslang namespace directly so it can be a friend of TReflection. -// - -class TReflectionTraverser : public TLiveTraverser { -public: - TReflectionTraverser(const TIntermediate& i, TReflection& r) : - TLiveTraverser(i), reflection(r) { } - - virtual bool visitBinary(TVisit, TIntermBinary* node); - virtual void visitSymbol(TIntermSymbol* base); - - // Add a simple reference to a uniform variable to the uniform database, no dereference involved. - // However, no dereference doesn't mean simple... it could be a complex aggregate. - void addUniform(const TIntermSymbol& base) - { - if (processedDerefs.find(&base) == processedDerefs.end()) { - processedDerefs.insert(&base); - - // Use a degenerate (empty) set of dereferences to immediately put as at the end of - // the dereference change expected by blowUpActiveAggregate. - TList derefs; - blowUpActiveAggregate(base.getType(), base.getName(), derefs, derefs.end(), -1, -1, 0); - } - } - - void addAttribute(const TIntermSymbol& base) - { - if (processedDerefs.find(&base) == processedDerefs.end()) { - processedDerefs.insert(&base); - - const TString &name = base.getName(); - const TType &type = base.getType(); - - TReflection::TNameToIndex::const_iterator it = reflection.nameToIndex.find(name); - if (it == reflection.nameToIndex.end()) { - reflection.nameToIndex[name] = (int)reflection.indexToAttribute.size(); - reflection.indexToAttribute.push_back(TObjectReflection(name, type, 0, mapToGlType(type), 0, 0)); - } - } - } - - // Lookup or calculate the offset of a block member, using the recursively - // defined block offset rules. - int getOffset(const TType& type, int index) - { - const TTypeList& memberList = *type.getStruct(); - - // Don't calculate offset if one is present, it could be user supplied - // and different than what would be calculated. That is, this is faster, - // but not just an optimization. - if (memberList[index].type->getQualifier().hasOffset()) - return memberList[index].type->getQualifier().layoutOffset; - - int memberSize; - int dummyStride; - int offset = 0; - for (int m = 0; m <= index; ++m) { - // modify just the children's view of matrix layout, if there is one for this member - TLayoutMatrix subMatrixLayout = memberList[m].type->getQualifier().layoutMatrix; - int memberAlignment = intermediate.getBaseAlignment(*memberList[m].type, memberSize, dummyStride, - type.getQualifier().layoutPacking == ElpStd140, - subMatrixLayout != ElmNone - ? subMatrixLayout == ElmRowMajor - : type.getQualifier().layoutMatrix == ElmRowMajor); - RoundToPow2(offset, memberAlignment); - if (m < index) - offset += memberSize; - } - - return offset; - } - - // Calculate the block data size. - // Block arrayness is not taken into account, each element is backed by a separate buffer. - int getBlockSize(const TType& blockType) - { - const TTypeList& memberList = *blockType.getStruct(); - int lastIndex = (int)memberList.size() - 1; - int lastOffset = getOffset(blockType, lastIndex); - - int lastMemberSize; - int dummyStride; - intermediate.getBaseAlignment(*memberList[lastIndex].type, lastMemberSize, dummyStride, - blockType.getQualifier().layoutPacking == ElpStd140, - blockType.getQualifier().layoutMatrix == ElmRowMajor); - - return lastOffset + lastMemberSize; - } - - // Traverse the provided deref chain, including the base, and - // - build a full reflection-granularity name, array size, etc. entry out of it, if it goes down to that granularity - // - recursively expand any variable array index in the middle of that traversal - // - recursively expand what's left at the end if the deref chain did not reach down to reflection granularity - // - // arraySize tracks, just for the final dereference in the chain, if there was a specific known size. - // A value of 0 for arraySize will mean to use the full array's size. - void blowUpActiveAggregate(const TType& baseType, const TString& baseName, const TList& derefs, - TList::const_iterator deref, int offset, int blockIndex, int arraySize) - { - // process the part of the dereference chain that was explicit in the shader - TString name = baseName; - const TType* terminalType = &baseType; - for (; deref != derefs.end(); ++deref) { - TIntermBinary* visitNode = *deref; - terminalType = &visitNode->getType(); - int index; - switch (visitNode->getOp()) { - case EOpIndexIndirect: - // Visit all the indices of this array, and for each one add on the remaining dereferencing - for (int i = 0; i < std::max(visitNode->getLeft()->getType().getOuterArraySize(), 1); ++i) { - TString newBaseName = name; - if (baseType.getBasicType() != EbtBlock) - newBaseName.append(TString("[") + String(i) + "]"); - TList::const_iterator nextDeref = deref; - ++nextDeref; - TType derefType(*terminalType, 0); - blowUpActiveAggregate(derefType, newBaseName, derefs, nextDeref, offset, blockIndex, arraySize); - } - - // it was all completed in the recursive calls above - return; - case EOpIndexDirect: - index = visitNode->getRight()->getAsConstantUnion()->getConstArray()[0].getIConst(); - if (baseType.getBasicType() != EbtBlock) - name.append(TString("[") + String(index) + "]"); - break; - case EOpIndexDirectStruct: - index = visitNode->getRight()->getAsConstantUnion()->getConstArray()[0].getIConst(); - if (offset >= 0) - offset += getOffset(visitNode->getLeft()->getType(), index); - if (name.size() > 0) - name.append("."); - name.append((*visitNode->getLeft()->getType().getStruct())[index].type->getFieldName()); - break; - default: - break; - } - } - - // if the terminalType is still too coarse a granularity, this is still an aggregate to expand, expand it... - if (! isReflectionGranularity(*terminalType)) { - if (terminalType->isArray()) { - // Visit all the indices of this array, and for each one, - // fully explode the remaining aggregate to dereference - for (int i = 0; i < std::max(terminalType->getOuterArraySize(), 1); ++i) { - TString newBaseName = name; - newBaseName.append(TString("[") + String(i) + "]"); - TType derefType(*terminalType, 0); - blowUpActiveAggregate(derefType, newBaseName, derefs, derefs.end(), offset, blockIndex, 0); - } - } else { - // Visit all members of this aggregate, and for each one, - // fully explode the remaining aggregate to dereference - const TTypeList& typeList = *terminalType->getStruct(); - for (int i = 0; i < (int)typeList.size(); ++i) { - TString newBaseName = name; - newBaseName.append(TString(".") + typeList[i].type->getFieldName()); - TType derefType(*terminalType, i); - blowUpActiveAggregate(derefType, newBaseName, derefs, derefs.end(), offset, blockIndex, 0); - } - } - - // it was all completed in the recursive calls above - return; - } - - // Finally, add a full string to the reflection database, and update the array size if necessary. - // If the dereferenced entity to record is an array, compute the size and update the maximum size. - - // there might not be a final array dereference, it could have been copied as an array object - if (arraySize == 0) - arraySize = mapToGlArraySize(*terminalType); - - TReflection::TNameToIndex::const_iterator it = reflection.nameToIndex.find(name); - if (it == reflection.nameToIndex.end()) { - reflection.nameToIndex[name] = (int)reflection.indexToUniform.size(); - reflection.indexToUniform.push_back(TObjectReflection(name, *terminalType, offset, - mapToGlType(*terminalType), - arraySize, blockIndex)); - } else if (arraySize > 1) { - int& reflectedArraySize = reflection.indexToUniform[it->second].size; - reflectedArraySize = std::max(arraySize, reflectedArraySize); - } - } - - // Add a uniform dereference where blocks/struct/arrays are involved in the access. - // Handles the situation where the left node is at the correct or too coarse a - // granularity for reflection. (That is, further dereferences up the tree will be - // skipped.) Earlier dereferences, down the tree, will be handled - // at the same time, and logged to prevent reprocessing as the tree is traversed. - // - // Note: Other things like the following must be caught elsewhere: - // - a simple non-array, non-struct variable (no dereference even conceivable) - // - an aggregrate consumed en masse, without a dereference - // - // So, this code is for cases like - // - a struct/block dereferencing a member (whether the member is array or not) - // - an array of struct - // - structs/arrays containing the above - // - void addDereferencedUniform(TIntermBinary* topNode) - { - // See if too fine-grained to process (wait to get further down the tree) - const TType& leftType = topNode->getLeft()->getType(); - if ((leftType.isVector() || leftType.isMatrix()) && ! leftType.isArray()) - return; - - // We have an array or structure or block dereference, see if it's a uniform - // based dereference (if not, skip it). - TIntermSymbol* base = findBase(topNode); - if (! base || ! base->getQualifier().isUniformOrBuffer()) - return; - - // See if we've already processed this (e.g., in the middle of something - // we did earlier), and if so skip it - if (processedDerefs.find(topNode) != processedDerefs.end()) - return; - - // Process this uniform dereference - - int offset = -1; - int blockIndex = -1; - bool anonymous = false; - - // See if we need to record the block itself - bool block = base->getBasicType() == EbtBlock; - if (block) { - offset = 0; - anonymous = IsAnonymous(base->getName()); - - const TString& blockName = base->getType().getTypeName(); - - if (base->getType().isArray()) { - TType derefType(base->getType(), 0); - - assert(! anonymous); - for (int e = 0; e < base->getType().getCumulativeArraySize(); ++e) - blockIndex = addBlockName(blockName + "[" + String(e) + "]", derefType, - getBlockSize(base->getType())); - } else - blockIndex = addBlockName(blockName, base->getType(), getBlockSize(base->getType())); - } - - // Process the dereference chain, backward, accumulating the pieces for later forward traversal. - // If the topNode is a reflection-granularity-array dereference, don't include that last dereference. - TList derefs; - for (TIntermBinary* visitNode = topNode; visitNode; visitNode = visitNode->getLeft()->getAsBinaryNode()) { - if (isReflectionGranularity(visitNode->getLeft()->getType())) - continue; - - derefs.push_front(visitNode); - processedDerefs.insert(visitNode); - } - processedDerefs.insert(base); - - // See if we have a specific array size to stick to while enumerating the explosion of the aggregate - int arraySize = 0; - if (isReflectionGranularity(topNode->getLeft()->getType()) && topNode->getLeft()->isArray()) { - if (topNode->getOp() == EOpIndexDirect) - arraySize = topNode->getRight()->getAsConstantUnion()->getConstArray()[0].getIConst() + 1; - } - - // Put the dereference chain together, forward - TString baseName; - if (! anonymous) { - if (block) - baseName = base->getType().getTypeName(); - else - baseName = base->getName(); - } - blowUpActiveAggregate(base->getType(), baseName, derefs, derefs.begin(), offset, blockIndex, arraySize); - } - - int addBlockName(const TString& name, const TType& type, int size) - { - int blockIndex; - TReflection::TNameToIndex::const_iterator it = reflection.nameToIndex.find(name); - if (reflection.nameToIndex.find(name) == reflection.nameToIndex.end()) { - blockIndex = (int)reflection.indexToUniformBlock.size(); - reflection.nameToIndex[name] = blockIndex; - reflection.indexToUniformBlock.push_back(TObjectReflection(name, type, -1, -1, size, -1)); - } else - blockIndex = it->second; - - return blockIndex; - } - - // Are we at a level in a dereference chain at which individual active uniform queries are made? - bool isReflectionGranularity(const TType& type) - { - return type.getBasicType() != EbtBlock && type.getBasicType() != EbtStruct; - } - - // For a binary operation indexing into an aggregate, chase down the base of the aggregate. - // Return 0 if the topology does not fit this situation. - TIntermSymbol* findBase(const TIntermBinary* node) - { - TIntermSymbol *base = node->getLeft()->getAsSymbolNode(); - if (base) - return base; - TIntermBinary* left = node->getLeft()->getAsBinaryNode(); - if (! left) - return nullptr; - - return findBase(left); - } - - // - // Translate a glslang sampler type into the GL API #define number. - // - int mapSamplerToGlType(TSampler sampler) - { - if (! sampler.image) { - // a sampler... - switch (sampler.type) { - case EbtFloat: - switch ((int)sampler.dim) { - case Esd1D: - switch ((int)sampler.shadow) { - case false: return sampler.arrayed ? GL_SAMPLER_1D_ARRAY : GL_SAMPLER_1D; - case true: return sampler.arrayed ? GL_SAMPLER_1D_ARRAY_SHADOW : GL_SAMPLER_1D_SHADOW; - } - case Esd2D: - switch ((int)sampler.ms) { - case false: - switch ((int)sampler.shadow) { - case false: return sampler.arrayed ? GL_SAMPLER_2D_ARRAY : GL_SAMPLER_2D; - case true: return sampler.arrayed ? GL_SAMPLER_2D_ARRAY_SHADOW : GL_SAMPLER_2D_SHADOW; - } - case true: return sampler.arrayed ? GL_SAMPLER_2D_MULTISAMPLE_ARRAY : GL_SAMPLER_2D_MULTISAMPLE; - } - case Esd3D: - return GL_SAMPLER_3D; - case EsdCube: - switch ((int)sampler.shadow) { - case false: return sampler.arrayed ? GL_SAMPLER_CUBE_MAP_ARRAY : GL_SAMPLER_CUBE; - case true: return sampler.arrayed ? GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW : GL_SAMPLER_CUBE_SHADOW; - } - case EsdRect: - return sampler.shadow ? GL_SAMPLER_2D_RECT_SHADOW : GL_SAMPLER_2D_RECT; - case EsdBuffer: - return GL_SAMPLER_BUFFER; - } -#ifdef AMD_EXTENSIONS - case EbtFloat16: - switch ((int)sampler.dim) { - case Esd1D: - switch ((int)sampler.shadow) { - case false: return sampler.arrayed ? GL_FLOAT16_SAMPLER_1D_ARRAY_AMD : GL_FLOAT16_SAMPLER_1D_AMD; - case true: return sampler.arrayed ? GL_FLOAT16_SAMPLER_1D_ARRAY_SHADOW_AMD : GL_FLOAT16_SAMPLER_1D_SHADOW_AMD; - } - case Esd2D: - switch ((int)sampler.ms) { - case false: - switch ((int)sampler.shadow) { - case false: return sampler.arrayed ? GL_FLOAT16_SAMPLER_2D_ARRAY_AMD : GL_FLOAT16_SAMPLER_2D_AMD; - case true: return sampler.arrayed ? GL_FLOAT16_SAMPLER_2D_ARRAY_SHADOW_AMD : GL_FLOAT16_SAMPLER_2D_SHADOW_AMD; - } - case true: return sampler.arrayed ? GL_FLOAT16_SAMPLER_2D_MULTISAMPLE_ARRAY_AMD : GL_FLOAT16_SAMPLER_2D_MULTISAMPLE_AMD; - } - case Esd3D: - return GL_FLOAT16_SAMPLER_3D_AMD; - case EsdCube: - switch ((int)sampler.shadow) { - case false: return sampler.arrayed ? GL_FLOAT16_SAMPLER_CUBE_MAP_ARRAY_AMD : GL_FLOAT16_SAMPLER_CUBE_AMD; - case true: return sampler.arrayed ? GL_FLOAT16_SAMPLER_CUBE_MAP_ARRAY_SHADOW_AMD : GL_FLOAT16_SAMPLER_CUBE_SHADOW_AMD; - } - case EsdRect: - return sampler.shadow ? GL_FLOAT16_SAMPLER_2D_RECT_SHADOW_AMD : GL_FLOAT16_SAMPLER_2D_RECT_AMD; - case EsdBuffer: - return GL_FLOAT16_SAMPLER_BUFFER_AMD; - } -#endif - case EbtInt: - switch ((int)sampler.dim) { - case Esd1D: - return sampler.arrayed ? GL_INT_SAMPLER_1D_ARRAY : GL_INT_SAMPLER_1D; - case Esd2D: - switch ((int)sampler.ms) { - case false: return sampler.arrayed ? GL_INT_SAMPLER_2D_ARRAY : GL_INT_SAMPLER_2D; - case true: return sampler.arrayed ? GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY - : GL_INT_SAMPLER_2D_MULTISAMPLE; - } - case Esd3D: - return GL_INT_SAMPLER_3D; - case EsdCube: - return sampler.arrayed ? GL_INT_SAMPLER_CUBE_MAP_ARRAY : GL_INT_SAMPLER_CUBE; - case EsdRect: - return GL_INT_SAMPLER_2D_RECT; - case EsdBuffer: - return GL_INT_SAMPLER_BUFFER; - } - case EbtUint: - switch ((int)sampler.dim) { - case Esd1D: - return sampler.arrayed ? GL_UNSIGNED_INT_SAMPLER_1D_ARRAY : GL_UNSIGNED_INT_SAMPLER_1D; - case Esd2D: - switch ((int)sampler.ms) { - case false: return sampler.arrayed ? GL_UNSIGNED_INT_SAMPLER_2D_ARRAY : GL_UNSIGNED_INT_SAMPLER_2D; - case true: return sampler.arrayed ? GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY - : GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE; - } - case Esd3D: - return GL_UNSIGNED_INT_SAMPLER_3D; - case EsdCube: - return sampler.arrayed ? GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY : GL_UNSIGNED_INT_SAMPLER_CUBE; - case EsdRect: - return GL_UNSIGNED_INT_SAMPLER_2D_RECT; - case EsdBuffer: - return GL_UNSIGNED_INT_SAMPLER_BUFFER; - } - default: - return 0; - } - } else { - // an image... - switch (sampler.type) { - case EbtFloat: - switch ((int)sampler.dim) { - case Esd1D: - return sampler.arrayed ? GL_IMAGE_1D_ARRAY : GL_IMAGE_1D; - case Esd2D: - switch ((int)sampler.ms) { - case false: return sampler.arrayed ? GL_IMAGE_2D_ARRAY : GL_IMAGE_2D; - case true: return sampler.arrayed ? GL_IMAGE_2D_MULTISAMPLE_ARRAY : GL_IMAGE_2D_MULTISAMPLE; - } - case Esd3D: - return GL_IMAGE_3D; - case EsdCube: - return sampler.arrayed ? GL_IMAGE_CUBE_MAP_ARRAY : GL_IMAGE_CUBE; - case EsdRect: - return GL_IMAGE_2D_RECT; - case EsdBuffer: - return GL_IMAGE_BUFFER; - } -#ifdef AMD_EXTENSIONS - case EbtFloat16: - switch ((int)sampler.dim) { - case Esd1D: - return sampler.arrayed ? GL_FLOAT16_IMAGE_1D_ARRAY_AMD : GL_FLOAT16_IMAGE_1D_AMD; - case Esd2D: - switch ((int)sampler.ms) { - case false: return sampler.arrayed ? GL_FLOAT16_IMAGE_2D_ARRAY_AMD : GL_FLOAT16_IMAGE_2D_AMD; - case true: return sampler.arrayed ? GL_FLOAT16_IMAGE_2D_MULTISAMPLE_ARRAY_AMD : GL_FLOAT16_IMAGE_2D_MULTISAMPLE_AMD; - } - case Esd3D: - return GL_FLOAT16_IMAGE_3D_AMD; - case EsdCube: - return sampler.arrayed ? GL_FLOAT16_IMAGE_CUBE_MAP_ARRAY_AMD : GL_FLOAT16_IMAGE_CUBE_AMD; - case EsdRect: - return GL_FLOAT16_IMAGE_2D_RECT_AMD; - case EsdBuffer: - return GL_FLOAT16_IMAGE_BUFFER_AMD; - } -#endif - case EbtInt: - switch ((int)sampler.dim) { - case Esd1D: - return sampler.arrayed ? GL_INT_IMAGE_1D_ARRAY : GL_INT_IMAGE_1D; - case Esd2D: - switch ((int)sampler.ms) { - case false: return sampler.arrayed ? GL_INT_IMAGE_2D_ARRAY : GL_INT_IMAGE_2D; - case true: return sampler.arrayed ? GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY : GL_INT_IMAGE_2D_MULTISAMPLE; - } - case Esd3D: - return GL_INT_IMAGE_3D; - case EsdCube: - return sampler.arrayed ? GL_INT_IMAGE_CUBE_MAP_ARRAY : GL_INT_IMAGE_CUBE; - case EsdRect: - return GL_INT_IMAGE_2D_RECT; - case EsdBuffer: - return GL_INT_IMAGE_BUFFER; - } - case EbtUint: - switch ((int)sampler.dim) { - case Esd1D: - return sampler.arrayed ? GL_UNSIGNED_INT_IMAGE_1D_ARRAY : GL_UNSIGNED_INT_IMAGE_1D; - case Esd2D: - switch ((int)sampler.ms) { - case false: return sampler.arrayed ? GL_UNSIGNED_INT_IMAGE_2D_ARRAY : GL_UNSIGNED_INT_IMAGE_2D; - case true: return sampler.arrayed ? GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY - : GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE; - } - case Esd3D: - return GL_UNSIGNED_INT_IMAGE_3D; - case EsdCube: - return sampler.arrayed ? GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY : GL_UNSIGNED_INT_IMAGE_CUBE; - case EsdRect: - return GL_UNSIGNED_INT_IMAGE_2D_RECT; - case EsdBuffer: - return GL_UNSIGNED_INT_IMAGE_BUFFER; - } - default: - return 0; - } - } - } - - // - // Translate a glslang type into the GL API #define number. - // Ignores arrayness. - // - int mapToGlType(const TType& type) - { - switch (type.getBasicType()) { - case EbtSampler: - return mapSamplerToGlType(type.getSampler()); - case EbtStruct: - case EbtBlock: - case EbtVoid: - return 0; - default: - break; - } - - if (type.isVector()) { - int offset = type.getVectorSize() - 2; - switch (type.getBasicType()) { - case EbtFloat: return GL_FLOAT_VEC2 + offset; - case EbtDouble: return GL_DOUBLE_VEC2 + offset; -#ifdef AMD_EXTENSIONS - case EbtFloat16: return GL_FLOAT16_VEC2_NV + offset; -#endif - case EbtInt: return GL_INT_VEC2 + offset; - case EbtUint: return GL_UNSIGNED_INT_VEC2 + offset; - case EbtInt64: return GL_INT64_ARB + offset; - case EbtUint64: return GL_UNSIGNED_INT64_ARB + offset; - case EbtBool: return GL_BOOL_VEC2 + offset; - case EbtAtomicUint: return GL_UNSIGNED_INT_ATOMIC_COUNTER + offset; - default: return 0; - } - } - if (type.isMatrix()) { - switch (type.getBasicType()) { - case EbtFloat: - switch (type.getMatrixCols()) { - case 2: - switch (type.getMatrixRows()) { - case 2: return GL_FLOAT_MAT2; - case 3: return GL_FLOAT_MAT2x3; - case 4: return GL_FLOAT_MAT2x4; - default: return 0; - } - case 3: - switch (type.getMatrixRows()) { - case 2: return GL_FLOAT_MAT3x2; - case 3: return GL_FLOAT_MAT3; - case 4: return GL_FLOAT_MAT3x4; - default: return 0; - } - case 4: - switch (type.getMatrixRows()) { - case 2: return GL_FLOAT_MAT4x2; - case 3: return GL_FLOAT_MAT4x3; - case 4: return GL_FLOAT_MAT4; - default: return 0; - } - } - case EbtDouble: - switch (type.getMatrixCols()) { - case 2: - switch (type.getMatrixRows()) { - case 2: return GL_DOUBLE_MAT2; - case 3: return GL_DOUBLE_MAT2x3; - case 4: return GL_DOUBLE_MAT2x4; - default: return 0; - } - case 3: - switch (type.getMatrixRows()) { - case 2: return GL_DOUBLE_MAT3x2; - case 3: return GL_DOUBLE_MAT3; - case 4: return GL_DOUBLE_MAT3x4; - default: return 0; - } - case 4: - switch (type.getMatrixRows()) { - case 2: return GL_DOUBLE_MAT4x2; - case 3: return GL_DOUBLE_MAT4x3; - case 4: return GL_DOUBLE_MAT4; - default: return 0; - } - } -#ifdef AMD_EXTENSIONS - case EbtFloat16: - switch (type.getMatrixCols()) { - case 2: - switch (type.getMatrixRows()) { - case 2: return GL_FLOAT16_MAT2_AMD; - case 3: return GL_FLOAT16_MAT2x3_AMD; - case 4: return GL_FLOAT16_MAT2x4_AMD; - default: return 0; - } - case 3: - switch (type.getMatrixRows()) { - case 2: return GL_FLOAT16_MAT3x2_AMD; - case 3: return GL_FLOAT16_MAT3_AMD; - case 4: return GL_FLOAT16_MAT3x4_AMD; - default: return 0; - } - case 4: - switch (type.getMatrixRows()) { - case 2: return GL_FLOAT16_MAT4x2_AMD; - case 3: return GL_FLOAT16_MAT4x3_AMD; - case 4: return GL_FLOAT16_MAT4_AMD; - default: return 0; - } - } -#endif - default: - return 0; - } - } - if (type.getVectorSize() == 1) { - switch (type.getBasicType()) { - case EbtFloat: return GL_FLOAT; - case EbtDouble: return GL_DOUBLE; -#ifdef AMD_EXTENSIONS - case EbtFloat16: return GL_FLOAT16_NV; -#endif - case EbtInt: return GL_INT; - case EbtUint: return GL_UNSIGNED_INT; - case EbtInt64: return GL_INT64_ARB; - case EbtUint64: return GL_UNSIGNED_INT64_ARB; - case EbtBool: return GL_BOOL; - case EbtAtomicUint: return GL_UNSIGNED_INT_ATOMIC_COUNTER; - default: return 0; - } - } - - return 0; - } - - int mapToGlArraySize(const TType& type) - { - return type.isArray() ? type.getOuterArraySize() : 1; - } - - TReflection& reflection; - std::set processedDerefs; - -protected: - TReflectionTraverser(TReflectionTraverser&); - TReflectionTraverser& operator=(TReflectionTraverser&); -}; - -// -// Implement the traversal functions of interest. -// - -// To catch dereferenced aggregates that must be reflected. -// This catches them at the highest level possible in the tree. -bool TReflectionTraverser::visitBinary(TVisit /* visit */, TIntermBinary* node) -{ - switch (node->getOp()) { - case EOpIndexDirect: - case EOpIndexIndirect: - case EOpIndexDirectStruct: - addDereferencedUniform(node); - break; - default: - break; - } - - // still need to visit everything below, which could contain sub-expressions - // containing different uniforms - return true; -} - -// To reflect non-dereferenced objects. -void TReflectionTraverser::visitSymbol(TIntermSymbol* base) -{ - if (base->getQualifier().storage == EvqUniform) - addUniform(*base); - - if (intermediate.getStage() == EShLangVertex && base->getQualifier().isPipeInput()) - addAttribute(*base); -} - -// -// Implement TReflection methods. -// - -// Track any required attribute reflection, such as compute shader numthreads. -// -void TReflection::buildAttributeReflection(EShLanguage stage, const TIntermediate& intermediate) -{ - if (stage == EShLangCompute) { - // Remember thread dimensions - for (int dim=0; dim<3; ++dim) - localSize[dim] = intermediate.getLocalSize(dim); - } -} - -// build counter block index associations for buffers -void TReflection::buildCounterIndices(const TIntermediate& intermediate) -{ - // search for ones that have counters - for (int i = 0; i < int(indexToUniformBlock.size()); ++i) { - const TString counterName(intermediate.addCounterBufferName(indexToUniformBlock[i].name)); - const int index = getIndex(counterName); - - if (index >= 0) - indexToUniformBlock[i].counterIndex = index; - } -} - -// Merge live symbols from 'intermediate' into the existing reflection database. -// -// Returns false if the input is too malformed to do this. -bool TReflection::addStage(EShLanguage stage, const TIntermediate& intermediate) -{ - if (intermediate.getTreeRoot() == nullptr || - intermediate.getNumEntryPoints() != 1 || - intermediate.isRecursive()) - return false; - - buildAttributeReflection(stage, intermediate); - - TReflectionTraverser it(intermediate, *this); - - // put the entry point on the list of functions to process - it.pushFunction(intermediate.getEntryPointMangledName().c_str()); - - // process all the functions - while (! it.functions.empty()) { - TIntermNode* function = it.functions.back(); - it.functions.pop_back(); - function->traverse(&it); - } - - buildCounterIndices(intermediate); - - return true; -} - -void TReflection::dump() -{ - printf("Uniform reflection:\n"); - for (size_t i = 0; i < indexToUniform.size(); ++i) - indexToUniform[i].dump(); - printf("\n"); - - printf("Uniform block reflection:\n"); - for (size_t i = 0; i < indexToUniformBlock.size(); ++i) - indexToUniformBlock[i].dump(); - printf("\n"); - - printf("Vertex attribute reflection:\n"); - for (size_t i = 0; i < indexToAttribute.size(); ++i) - indexToAttribute[i].dump(); - printf("\n"); - - if (getLocalSize(0) > 1) { - static const char* axis[] = { "X", "Y", "Z" }; - - for (int dim=0; dim<3; ++dim) - if (getLocalSize(dim) > 1) - printf("Local size %s: %d\n", axis[dim], getLocalSize(dim)); - - printf("\n"); - } - - // printf("Live names\n"); - // for (TNameToIndex::const_iterator it = nameToIndex.begin(); it != nameToIndex.end(); ++it) - // printf("%s: %d\n", it->first.c_str(), it->second); - // printf("\n"); -} - -} // end namespace glslang diff --git a/External/glslang/glslang/MachineIndependent/reflection.h b/External/glslang/glslang/MachineIndependent/reflection.h deleted file mode 100644 index bf233e33..00000000 --- a/External/glslang/glslang/MachineIndependent/reflection.h +++ /dev/null @@ -1,177 +0,0 @@ -// -// 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 _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; - -// Data needed for just a single object at the granularity exchanged by the reflection API -class TObjectReflection { -public: - TObjectReflection(const TString& pName, const TType& pType, int pOffset, int pGLDefineType, int pSize, int pIndex) : - name(pName), offset(pOffset), - glDefineType(pGLDefineType), size(pSize), index(pIndex), counterIndex(-1), type(pType.clone()) { } - - const TType* const getType() const { return type; } - int getBinding() const - { - if (type == nullptr || !type->getQualifier().hasBinding()) - return -1; - return type->getQualifier().layoutBinding; - } - void dump() const - { - printf("%s: offset %d, type %x, size %d, index %d, binding %d", - name.c_str(), offset, glDefineType, size, index, getBinding() ); - - if (counterIndex != -1) - printf(", counter %d", counterIndex); - - printf("\n"); - } - static TObjectReflection badReflection() { return TObjectReflection(); } - - TString 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; - -protected: - TObjectReflection() : offset(-1), glDefineType(-1), size(-1), index(-1), type(nullptr) { } - - const TType* type; -}; - -// The full reflection database -class TReflection { -public: - TReflection() : 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 attribute index to the attribute's description - int getNumAttributes() { return (int)indexToAttribute.size(); } - const TObjectReflection& getAttribute(int i) const - { - if (i >= 0 && i < (int)indexToAttribute.size()) - return indexToAttribute[i]; - else - return badReflection; - } - - // for mapping any name to its index (block names, uniform names and attribute 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()); } - - // 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 buildAttributeReflection(EShLanguage, const TIntermediate&); - - // Need a TString hash: typedef std::unordered_map TNameToIndex; - typedef std::map TNameToIndex; - typedef std::vector TMapIndexToReflection; - - 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 - TMapIndexToReflection indexToUniform; - TMapIndexToReflection indexToUniformBlock; - TMapIndexToReflection indexToAttribute; - - unsigned int localSize[3]; -}; - -} // end namespace glslang - -#endif // _REFLECTION_INCLUDED diff --git a/External/glslang/glslang/OSDependent/Unix/CMakeLists.txt b/External/glslang/glslang/OSDependent/Unix/CMakeLists.txt deleted file mode 100644 index 1bf49e12..00000000 --- a/External/glslang/glslang/OSDependent/Unix/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -add_library(OSDependent STATIC ossource.cpp ../osinclude.h) -set_property(TARGET OSDependent PROPERTY FOLDER glslang) -set_property(TARGET OSDependent PROPERTY POSITION_INDEPENDENT_CODE ON) - -if(ENABLE_GLSLANG_INSTALL) - install(TARGETS OSDependent - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) -endif(ENABLE_GLSLANG_INSTALL) diff --git a/External/glslang/glslang/OSDependent/Unix/ossource.cpp b/External/glslang/glslang/OSDependent/Unix/ossource.cpp deleted file mode 100644 index f59bbceb..00000000 --- a/External/glslang/glslang/OSDependent/Unix/ossource.cpp +++ /dev/null @@ -1,204 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -// -// This file contains the Linux-specific functions -// -#include "../osinclude.h" -#include "../../../OGLCompilersDLL/InitializeDll.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace glslang { - -// -// Thread cleanup -// - -// -// Wrapper for Linux call to DetachThread. This is required as pthread_cleanup_push() expects -// the cleanup routine to return void. -// -static void DetachThreadLinux(void *) -{ - DetachThread(); -} - -// -// Registers cleanup handler, sets cancel type and state, and executes the thread specific -// cleanup handler. This function will be called in the Standalone.cpp for regression -// testing. When OpenGL applications are run with the driver code, Linux OS does the -// thread cleanup. -// -void OS_CleanupThreadData(void) -{ -#ifdef __ANDROID__ - DetachThreadLinux(NULL); -#else - int old_cancel_state, old_cancel_type; - void *cleanupArg = NULL; - - // - // Set thread cancel state and push cleanup handler. - // - pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &old_cancel_state); - pthread_cleanup_push(DetachThreadLinux, (void *) cleanupArg); - - // - // Put the thread in deferred cancellation mode. - // - pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &old_cancel_type); - - // - // Pop cleanup handler and execute it prior to unregistering the cleanup handler. - // - pthread_cleanup_pop(1); - - // - // Restore the thread's previous cancellation mode. - // - pthread_setcanceltype(old_cancel_state, NULL); -#endif -} - -// -// Thread Local Storage Operations -// -inline OS_TLSIndex PthreadKeyToTLSIndex(pthread_key_t key) -{ - return (OS_TLSIndex)((uintptr_t)key + 1); -} - -inline pthread_key_t TLSIndexToPthreadKey(OS_TLSIndex nIndex) -{ - return (pthread_key_t)((uintptr_t)nIndex - 1); -} - -OS_TLSIndex OS_AllocTLSIndex() -{ - pthread_key_t pPoolIndex; - - // - // Create global pool key. - // - if ((pthread_key_create(&pPoolIndex, NULL)) != 0) { - assert(0 && "OS_AllocTLSIndex(): Unable to allocate Thread Local Storage"); - return OS_INVALID_TLS_INDEX; - } - else - return PthreadKeyToTLSIndex(pPoolIndex); -} - -bool OS_SetTLSValue(OS_TLSIndex nIndex, void *lpvValue) -{ - if (nIndex == OS_INVALID_TLS_INDEX) { - assert(0 && "OS_SetTLSValue(): Invalid TLS Index"); - return false; - } - - if (pthread_setspecific(TLSIndexToPthreadKey(nIndex), lpvValue) == 0) - return true; - else - return false; -} - -void* OS_GetTLSValue(OS_TLSIndex nIndex) -{ - // - // This function should return 0 if nIndex is invalid. - // - assert(nIndex != OS_INVALID_TLS_INDEX); - return pthread_getspecific(TLSIndexToPthreadKey(nIndex)); -} - -bool OS_FreeTLSIndex(OS_TLSIndex nIndex) -{ - if (nIndex == OS_INVALID_TLS_INDEX) { - assert(0 && "OS_SetTLSValue(): Invalid TLS Index"); - return false; - } - - // - // Delete the global pool key. - // - if (pthread_key_delete(TLSIndexToPthreadKey(nIndex)) == 0) - return true; - else - return false; -} - -namespace { - pthread_mutex_t gMutex; -} - -void InitGlobalLock() -{ - pthread_mutexattr_t mutexattr; - pthread_mutexattr_init(&mutexattr); - pthread_mutexattr_settype(&mutexattr, PTHREAD_MUTEX_RECURSIVE); - pthread_mutex_init(&gMutex, &mutexattr); -} - -void GetGlobalLock() -{ - pthread_mutex_lock(&gMutex); -} - -void ReleaseGlobalLock() -{ - pthread_mutex_unlock(&gMutex); -} - -// #define DUMP_COUNTERS - -void OS_DumpMemoryCounters() -{ -#ifdef DUMP_COUNTERS - struct rusage usage; - - if (getrusage(RUSAGE_SELF, &usage) == 0) - printf("Working set size: %ld\n", usage.ru_maxrss * 1024); -#else - printf("Recompile with DUMP_COUNTERS defined to see counters.\n"); -#endif -} - -} // end namespace glslang diff --git a/External/glslang/glslang/OSDependent/Windows/CMakeLists.txt b/External/glslang/glslang/OSDependent/Windows/CMakeLists.txt deleted file mode 100644 index f257418a..00000000 --- a/External/glslang/glslang/OSDependent/Windows/CMakeLists.txt +++ /dev/null @@ -1,20 +0,0 @@ -set(SOURCES ossource.cpp ../osinclude.h) - -add_library(OSDependent STATIC ${SOURCES}) -set_property(TARGET OSDependent PROPERTY FOLDER glslang) -set_property(TARGET OSDependent PROPERTY POSITION_INDEPENDENT_CODE ON) - -# MinGW GCC complains about function pointer casts to void*. -# Turn that off with -fpermissive. -if(${CMAKE_CXX_COMPILER_ID} MATCHES "GNU") - target_compile_options(OSDependent PRIVATE -fpermissive) -endif() - -if(WIN32) - source_group("Source" FILES ${SOURCES}) -endif(WIN32) - -if(ENABLE_GLSLANG_INSTALL) - install(TARGETS OSDependent - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) -endif(ENABLE_GLSLANG_INSTALL) diff --git a/External/glslang/glslang/OSDependent/Windows/main.cpp b/External/glslang/glslang/OSDependent/Windows/main.cpp deleted file mode 100644 index 0bcde7b6..00000000 --- a/External/glslang/glslang/OSDependent/Windows/main.cpp +++ /dev/null @@ -1,74 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -#include "InitializeDll.h" - -#define STRICT -#define VC_EXTRALEAN 1 -#include -#include - -BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) -{ - switch (fdwReason) - { - case DLL_PROCESS_ATTACH: - - if (! glslang::InitProcess()) - return FALSE; - break; - case DLL_THREAD_ATTACH: - - if (! glslang::InitThread()) - return FALSE; - break; - - case DLL_THREAD_DETACH: - - if (! glslang::DetachThread()) - return FALSE; - break; - - case DLL_PROCESS_DETACH: - - glslang::DetachProcess(); - break; - - default: - assert(0 && "DllMain(): Reason for calling DLL Main is unknown"); - return FALSE; - } - - return TRUE; -} diff --git a/External/glslang/glslang/OSDependent/Windows/ossource.cpp b/External/glslang/glslang/OSDependent/Windows/ossource.cpp deleted file mode 100644 index 870840c5..00000000 --- a/External/glslang/glslang/OSDependent/Windows/ossource.cpp +++ /dev/null @@ -1,147 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -#include "../osinclude.h" - -#define STRICT -#define VC_EXTRALEAN 1 -#include -#include -#include -#include -#include -#include - -// -// This file contains the Window-OS-specific functions -// - -#if !(defined(_WIN32) || defined(_WIN64)) -#error Trying to build a windows specific file in a non windows build. -#endif - -namespace glslang { - -inline OS_TLSIndex ToGenericTLSIndex (DWORD handle) -{ - return (OS_TLSIndex)((uintptr_t)handle + 1); -} - -inline DWORD ToNativeTLSIndex (OS_TLSIndex nIndex) -{ - return (DWORD)((uintptr_t)nIndex - 1); -} - -// -// Thread Local Storage Operations -// -OS_TLSIndex OS_AllocTLSIndex() -{ - DWORD dwIndex = TlsAlloc(); - if (dwIndex == TLS_OUT_OF_INDEXES) { - assert(0 && "OS_AllocTLSIndex(): Unable to allocate Thread Local Storage"); - return OS_INVALID_TLS_INDEX; - } - - return ToGenericTLSIndex(dwIndex); -} - -bool OS_SetTLSValue(OS_TLSIndex nIndex, void *lpvValue) -{ - if (nIndex == OS_INVALID_TLS_INDEX) { - assert(0 && "OS_SetTLSValue(): Invalid TLS Index"); - return false; - } - - if (TlsSetValue(ToNativeTLSIndex(nIndex), lpvValue)) - return true; - else - return false; -} - -void* OS_GetTLSValue(OS_TLSIndex nIndex) -{ - assert(nIndex != OS_INVALID_TLS_INDEX); - return TlsGetValue(ToNativeTLSIndex(nIndex)); -} - -bool OS_FreeTLSIndex(OS_TLSIndex nIndex) -{ - if (nIndex == OS_INVALID_TLS_INDEX) { - assert(0 && "OS_SetTLSValue(): Invalid TLS Index"); - return false; - } - - if (TlsFree(ToNativeTLSIndex(nIndex))) - return true; - else - return false; -} - -HANDLE GlobalLock; - -void InitGlobalLock() -{ - GlobalLock = CreateMutex(0, false, 0); -} - -void GetGlobalLock() -{ - WaitForSingleObject(GlobalLock, INFINITE); -} - -void ReleaseGlobalLock() -{ - ReleaseMutex(GlobalLock); -} - -unsigned int __stdcall EnterGenericThread (void* entry) -{ - return ((TThreadEntrypoint)entry)(0); -} - -//#define DUMP_COUNTERS - -void OS_DumpMemoryCounters() -{ -#ifdef DUMP_COUNTERS - PROCESS_MEMORY_COUNTERS counters; - GetProcessMemoryInfo(GetCurrentProcess(), &counters, sizeof(counters)); - printf("Working set size: %d\n", counters.WorkingSetSize); -#else - printf("Recompile with DUMP_COUNTERS defined to see counters.\n"); -#endif -} - -} // namespace glslang diff --git a/External/glslang/glslang/OSDependent/osinclude.h b/External/glslang/glslang/OSDependent/osinclude.h deleted file mode 100644 index 218abe4f..00000000 --- a/External/glslang/glslang/OSDependent/osinclude.h +++ /dev/null @@ -1,63 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -#ifndef __OSINCLUDE_H -#define __OSINCLUDE_H - -namespace glslang { - -// -// Thread Local Storage Operations -// -typedef void* OS_TLSIndex; -#define OS_INVALID_TLS_INDEX ((void*)0) - -OS_TLSIndex OS_AllocTLSIndex(); -bool OS_SetTLSValue(OS_TLSIndex nIndex, void *lpvValue); -bool OS_FreeTLSIndex(OS_TLSIndex nIndex); -void* OS_GetTLSValue(OS_TLSIndex nIndex); - -void InitGlobalLock(); -void GetGlobalLock(); -void ReleaseGlobalLock(); - -typedef unsigned int (*TThreadEntrypoint)(void*); - -void OS_CleanupThreadData(void); - -void OS_DumpMemoryCounters(); - -} // end namespace glslang - -#endif // __OSINCLUDE_H diff --git a/External/glslang/glslang/Public/ShaderLang.h b/External/glslang/glslang/Public/ShaderLang.h deleted file mode 100644 index 911fc310..00000000 --- a/External/glslang/glslang/Public/ShaderLang.h +++ /dev/null @@ -1,714 +0,0 @@ -// -// 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 _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 -#ifndef __fastcall -#define __fastcall -#endif -#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 6 - -// -// 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 __fastcall ShFinalize(); - -// -// Types of languages the compiler can consume. -// -typedef enum { - EShLangVertex, - EShLangTessControl, - EShLangTessEvaluation, - EShLangGeometry, - EShLangFragment, - EShLangCompute, - 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), -} EShLanguageMask; - -namespace glslang { - -class TType; - -typedef enum { - EShSourceNone, - EShSourceGlsl, - EShSourceHlsl, -} EShSource; // if EShLanguage were EShStage, this could be EShLanguage instead - -typedef enum { - EShClientNone, - EShClientVulkan, - EShClientOpenGL, -} EShClient; - -typedef enum { - EShTargetNone, - EShTargetSpv, // preferred spelling - EshTargetSpv = EShTargetSpv, // legacy spelling -} EShTargetLanguage; - -typedef enum { - EShTargetVulkan_1_0 = (1 << 22), - EShTargetVulkan_1_1 = (1 << 22) | (1 << 12), - EShTargetOpenGL_450 = 450, -} EShTargetClientVersion; - -typedef EShTargetClientVersion EshTargetClientVersion; - -typedef enum { - EShTargetSpv_1_0 = (1 << 16), - EShTargetSpv_1_3 = (1 << 16) | (3 << 8), -} 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 -} 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 -} 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 -}; - -// -// 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 -// - 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 setInvertY(bool invert); - void setHlslIoMapping(bool hlslIoMap); - void setFlattenUniformArrays(bool flatten); - void setNoStorageFormat(bool useUnknownFormat); - 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. - 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 setEnvTargetHlslFunctionality1() { environment.target.hlslFunctionality1 = true; } - bool getEnvTargetHlslFunctionality1() const { return environment.target.hlslFunctionality1; } - - // 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); - } - - 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; - const int* lengths; - const char* const* stringNames; - const char* preamble; - int numStrings; - - // 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&); -}; - -class TReflection; -class TIoMapper; - -// 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, const char* name, const TType& type, bool is_live) = 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, const char* name, const TType& type, bool is_live) = 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, const char* name, const TType& type, bool is_live) = 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, const char* name, const TType& type, bool is_live) = 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, const char* name, const TType& type, bool is_live) = 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, const char* name, const TType& type, bool is_live) = 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, const char* name, const TType& type, bool is_live) = 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, const char* name, const TType& type, bool is_live) = 0; - // Notification of a uniform variable - virtual void notifyBinding(EShLanguage stage, const char* name, const TType& type, bool is_live) = 0; - // Notification of a in or out variable - virtual void notifyInOut(EShLanguage stage, const char* name, const TType& type, bool is_live) = 0; - // Called by mapIO when it has finished the notify pass - virtual void endNotifications(EShLanguage stage) = 0; - // Called by mapIO when it starts its notify pass for the given stage - virtual void beginNotifications(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; -}; - -// 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); } - - // Link Validation interface - bool link(EShMessages); - const char* getInfoLog(); - const char* getInfoDebugLog(); - - TIntermediate* getIntermediate(EShLanguage stage) const { return intermediate[stage]; } - - // Reflection Interface - bool buildReflection(); // call first, to do liveness analysis, index mapping, etc.; returns false on failure - int getNumLiveUniformVariables() const; // can be used for glGetProgramiv(GL_ACTIVE_UNIFORMS) - int getNumLiveUniformBlocks() const; // can be used for glGetProgramiv(GL_ACTIVE_UNIFORM_BLOCKS) - const char* getUniformName(int index) const; // can be used for "name" part of glGetActiveUniform() - const char* getUniformBlockName(int blockIndex) const; // can be used for glGetActiveUniformBlockName() - int getUniformBlockSize(int blockIndex) const; // can be used for glGetActiveUniformBlockiv(UNIFORM_BLOCK_DATA_SIZE) - int getUniformIndex(const char* name) const; // can be used for glGetUniformIndices() - int getUniformBinding(int index) const; // returns the binding number - int getUniformBlockBinding(int index) const; // returns the block binding number - int getUniformBlockIndex(int index) const; // can be used for glGetActiveUniformsiv(GL_UNIFORM_BLOCK_INDEX) - int getUniformBlockCounterIndex(int index) const; // returns block index of associated counter. - int getUniformType(int index) const; // can be used for glGetActiveUniformsiv(GL_UNIFORM_TYPE) - int getUniformBufferOffset(int index) const; // can be used for glGetActiveUniformsiv(GL_UNIFORM_OFFSET) - int getUniformArraySize(int index) const; // can be used for glGetActiveUniformsiv(GL_UNIFORM_SIZE) - int getNumLiveAttributes() const; // can be used for glGetProgramiv(GL_ACTIVE_ATTRIBUTES) - unsigned getLocalSize(int dim) const; // return dim'th local size - const char *getAttributeName(int index) const; // can be used for glGetActiveAttrib() - int getAttributeType(int index) const; // can be used for glGetActiveAttrib() - const TType* getUniformTType(int index) const; // returns a TType* - const TType* getUniformBlockTType(int index) const; // returns a TType* - const TType* getAttributeTType(int index) const; // returns a TType* - - 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* resolver = NULL); - -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; - TReflection* reflection; - TIoMapper* ioMapper; - bool linked; - -private: - TProgram(TProgram&); - TProgram& operator=(TProgram&); -}; - -} // end namespace glslang - -#endif // _COMPILER_INTERFACE_INCLUDED_ diff --git a/External/glslang/glslang/updateGrammar b/External/glslang/glslang/updateGrammar deleted file mode 100644 index f8fa81da..00000000 --- a/External/glslang/glslang/updateGrammar +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env bash - -bison --defines=MachineIndependent/glslang_tab.cpp.h -t MachineIndependent/glslang.y -o MachineIndependent/glslang_tab.cpp diff --git a/External/glslang/gtests/AST.FromFile.cpp b/External/glslang/gtests/AST.FromFile.cpp deleted file mode 100644 index 701db463..00000000 --- a/External/glslang/gtests/AST.FromFile.cpp +++ /dev/null @@ -1,249 +0,0 @@ -// -// Copyright (C) 2016 Google, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -#include - -#include "TestFixture.h" - -namespace glslangtest { -namespace { - -using CompileToAstTest = GlslangTest<::testing::TestWithParam>; - -#ifdef NV_EXTENSIONS -using CompileToAstTestNV = GlslangTest<::testing::TestWithParam>; -#endif - -TEST_P(CompileToAstTest, FromFile) -{ - loadFileCompileAndCheck(GlobalTestSettings.testRoot, GetParam(), - Source::GLSL, Semantics::OpenGL, glslang::EShTargetVulkan_1_0, - Target::AST); -} - -#ifdef NV_EXTENSIONS -// Compiling GLSL to SPIR-V under OpenGL semantics (NV extensions enabled). -TEST_P(CompileToAstTestNV, FromFile) -{ - loadFileCompileAndCheck(GlobalTestSettings.testRoot, GetParam(), - Source::GLSL, Semantics::OpenGL, glslang::EShTargetVulkan_1_0, - Target::AST); -} -#endif - -// clang-format off -INSTANTIATE_TEST_CASE_P( - Glsl, CompileToAstTest, - ::testing::ValuesIn(std::vector({ - "sample.frag", - "sample.vert", - "decls.frag", - "specExamples.frag", - "specExamples.vert", - "versionsClean.frag", - "versionsClean.vert", - "versionsErrors.frag", - "versionsErrors.vert", - "100.frag", - "100samplerExternal.frag", - "120.vert", - "120.frag", - "130.vert", - "130.frag", - "140.vert", - "140.frag", - "150.vert", - "150.geom", - "150.frag", - "precision.frag", - "precision.vert", - "nonSquare.vert", - "matrixError.vert", - "cppSimple.vert", - "cppIndent.vert", - "cppIntMinOverNegativeOne.frag", - "cppNest.vert", - "cppBad.vert", - "cppBad2.vert", - "cppComplexExpr.vert", - "cppDeepNest.frag", - "cppPassMacroName.frag", - "cppRelaxSkipTokensErrors.vert", - "badChars.frag", - "pointCoord.frag", - "array.frag", - "array100.frag", - "comment.frag", - "300.vert", - "300.frag", - "300BuiltIns.frag", - "300layout.vert", - "300layout.frag", - "300operations.frag", - "300block.frag", - "300samplerExternal.frag", - "310.comp", - "310.vert", - "310.geom", - "310.frag", - "310.tesc", - "310.tese", - "310implicitSizeArrayError.vert", - "310AofA.vert", - "310runtimeArray.vert", - "320.comp", - "320.vert", - "320.geom", - "320.frag", - "320.tesc", - "320.tese", - "330.frag", - "330comp.frag", - "constErrors.frag", - "constFold.frag", - "constFoldIntMin.frag", - "errors.frag", - "forwardRef.frag", - "uint.frag", - "switch.frag", - "tokenLength.vert", - "100Limits.vert", - "100scope.vert", - "110scope.vert", - "300scope.vert", - "400.frag", - "400.vert", - "410.vert", - "420.comp", - "420.frag", - "420.vert", - "420.geom", - "420_size_gl_in.geom", - "430scope.vert", - "lineContinuation100.vert", - "lineContinuation.vert", - "numeral.frag", - "400.geom", - "400.tesc", - "400.tese", - "410.tesc", - "420.tesc", - "420.tese", - "410.geom", - "430.vert", - "430.comp", - "430AofA.frag", - "435.vert", - "440.vert", - "440.frag", - "450.vert", - "450.geom", - "450.tesc", - "450.tese", - "450.frag", - "450.comp", - "460.frag", - "460.vert", - "dce.frag", - "atomic_uint.frag", - "implicitInnerAtomicUint.frag", - "aggOps.frag", - "always-discard.frag", - "always-discard2.frag", - "conditionalDiscard.frag", - "conversion.frag", - "dataOut.frag", - "dataOutIndirect.frag", - "deepRvalue.frag", - "depthOut.frag", - "discard-dce.frag", - "doWhileLoop.frag", - "earlyReturnDiscard.frag", - "flowControl.frag", - "forLoop.frag", - "functionCall.frag", - "functionSemantics.frag", - "length.frag", - "localAggregates.frag", - "loops.frag", - "loopsArtificial.frag", - "matrix.frag", - "matrix2.frag", - "mixedArrayDecls.frag", - "nonuniform.frag", - "newTexture.frag", - "Operations.frag", - "overlongLiteral.frag", - "prepost.frag", - "runtimeArray.vert", - "simpleFunctionCall.frag", - "structAssignment.frag", - "structDeref.frag", - "structure.frag", - "swizzle.frag", - "invalidSwizzle.vert", - "syntaxError.frag", - "test.frag", - "texture.frag", - "tokenPaste.vert", - "types.frag", - "uniformArray.frag", - "variableArrayIndex.frag", - "varyingArray.frag", - "varyingArrayIndirect.frag", - "voidFunction.frag", - "whileLoop.frag", - "nonVulkan.frag", - "negativeArraySize.comp", - "precise.tesc", - "precise_struct_block.vert", - "maxClipDistances.vert", - "findFunction.frag", - })), - FileNameAsCustomTestSuffix -); - -#ifdef NV_EXTENSIONS -INSTANTIATE_TEST_CASE_P( - Glsl, CompileToAstTestNV, - ::testing::ValuesIn(std::vector({ - "nvShaderNoperspectiveInterpolation.frag", - })), - FileNameAsCustomTestSuffix -); -#endif -// clang-format on - -} // anonymous namespace -} // namespace glslangtest diff --git a/External/glslang/gtests/BuiltInResource.FromFile.cpp b/External/glslang/gtests/BuiltInResource.FromFile.cpp deleted file mode 100644 index da81fe98..00000000 --- a/External/glslang/gtests/BuiltInResource.FromFile.cpp +++ /dev/null @@ -1,57 +0,0 @@ -// -// Copyright (C) 2016 Google, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -#include - -#include - -#include "StandAlone/ResourceLimits.h" -#include "TestFixture.h" - -namespace glslangtest { -namespace { - -using DefaultResourceTest = GlslangTest<::testing::Test>; - -TEST_F(DefaultResourceTest, FromFile) -{ - const std::string path = GlobalTestSettings.testRoot + "/baseResults/test.conf"; - std::string expectedConfig; - tryLoadFile(path, "expected resource limit", &expectedConfig); - const std::string realConfig = glslang::GetDefaultTBuiltInResourceString(); - ASSERT_EQ(expectedConfig, realConfig); -} - -} // anonymous namespace -} // namespace glslangtest diff --git a/External/glslang/gtests/CMakeLists.txt b/External/glslang/gtests/CMakeLists.txt deleted file mode 100644 index 15b73f4b..00000000 --- a/External/glslang/gtests/CMakeLists.txt +++ /dev/null @@ -1,59 +0,0 @@ -if(BUILD_TESTING) - if(TARGET gmock) - message(STATUS "Google Mock found - building tests") - - set(TEST_SOURCES - # Framework related source files - ${CMAKE_CURRENT_SOURCE_DIR}/Initializer.h - ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/Settings.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/Settings.h - ${CMAKE_CURRENT_SOURCE_DIR}/TestFixture.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/TestFixture.h - - # Test related source files - ${CMAKE_CURRENT_SOURCE_DIR}/AST.FromFile.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/BuiltInResource.FromFile.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/Config.FromFile.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/HexFloat.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/Hlsl.FromFile.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/Link.FromFile.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/Link.FromFile.Vk.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/Pp.FromFile.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/Spv.FromFile.cpp - - # -- Remapper tests - ${CMAKE_CURRENT_SOURCE_DIR}/Remap.FromFile.cpp) - - add_executable(glslangtests ${TEST_SOURCES}) - set_property(TARGET glslangtests PROPERTY FOLDER tests) - glslang_set_link_args(glslangtests) - if(ENABLE_GLSLANG_INSTALL) - install(TARGETS glslangtests - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) - endif(ENABLE_GLSLANG_INSTALL) - - set(GLSLANG_TEST_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/../Test") - # Supply a default test root directory, so that manual testing - # doesn't have to specify the --test-root option in the normal - # case that you want to use the tests from the same source tree. - target_compile_definitions(glslangtests - PRIVATE GLSLANG_TEST_DIRECTORY="${GLSLANG_TEST_DIRECTORY}") - target_include_directories(glslangtests PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR} - ${PROJECT_SOURCE_DIR} - ${gmock_SOURCE_DIR}/include - ${gtest_SOURCE_DIR}/include) - - set(LIBRARIES - SPVRemapper glslang OSDependent OGLCompiler glslang - SPIRV glslang-default-resource-limits) - if(ENABLE_HLSL) - set(LIBRARIES ${LIBRARIES} HLSL) - endif(ENABLE_HLSL) - target_link_libraries(glslangtests PRIVATE ${LIBRARIES} gmock) - - add_test(NAME glslang-gtests - COMMAND glslangtests --test-root "${GLSLANG_TEST_DIRECTORY}") - endif() -endif() diff --git a/External/glslang/gtests/Config.FromFile.cpp b/External/glslang/gtests/Config.FromFile.cpp deleted file mode 100644 index f3a27724..00000000 --- a/External/glslang/gtests/Config.FromFile.cpp +++ /dev/null @@ -1,107 +0,0 @@ -// -// Copyright (C) 2016 Google, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -#include "StandAlone/ResourceLimits.h" -#include "TestFixture.h" - -namespace glslangtest { -namespace { - -struct TestCaseSpec { - std::string input; - std::string config; - std::string output; - EShMessages controls; -}; - -using ConfigTest = GlslangTest<::testing::TestWithParam>; - -TEST_P(ConfigTest, FromFile) -{ - TestCaseSpec testCase = GetParam(); - GlslangResult result; - - // Get the contents for input shader and limit configurations. - std::string shaderContents, configContents; - tryLoadFile(GlobalTestSettings.testRoot + "/" + testCase.input, "input", &shaderContents); - tryLoadFile(GlobalTestSettings.testRoot + "/" + testCase.config, "limits config", &configContents); - - // Decode limit configurations. - TBuiltInResource resources = {}; - { - const size_t len = configContents.size(); - char* configChars = new char[len + 1]; - memcpy(configChars, configContents.data(), len); - configChars[len] = 0; - glslang::DecodeResourceLimits(&resources, configChars); - delete[] configChars; - } - - // Compile the shader. - glslang::TShader shader(GetShaderStage(GetSuffix(testCase.input))); - compile(&shader, shaderContents, "", testCase.controls, &resources); - result.shaderResults.push_back( - {testCase.input, shader.getInfoLog(), shader.getInfoDebugLog()}); - - // Link the shader. - glslang::TProgram program; - program.addShader(&shader); - program.link(testCase.controls); - result.linkingOutput = program.getInfoLog(); - result.linkingError = program.getInfoDebugLog(); - - std::ostringstream stream; - outputResultToStream(&stream, result, testCase.controls); - - // Check with expected results. - const std::string expectedOutputFname = - GlobalTestSettings.testRoot + "/baseResults/" + testCase.output; - std::string expectedOutput; - tryLoadFile(expectedOutputFname, "expected output", &expectedOutput); - - checkEqAndUpdateIfRequested(expectedOutput, stream.str(), expectedOutputFname); -} - -// clang-format off -INSTANTIATE_TEST_CASE_P( - Glsl, ConfigTest, - ::testing::ValuesIn(std::vector({ - {"specExamples.vert", "baseResults/test.conf", "specExamplesConf.vert.out", (EShMessages)(EShMsgAST | EShMsgCascadingErrors)}, - {"100Limits.vert", "100.conf", "100LimitsConf.vert.out", EShMsgCascadingErrors}, - })), -); -// clang-format on - -} // anonymous namespace -} // namespace glslangtest diff --git a/External/glslang/gtests/HexFloat.cpp b/External/glslang/gtests/HexFloat.cpp deleted file mode 100644 index ddbee1f4..00000000 --- a/External/glslang/gtests/HexFloat.cpp +++ /dev/null @@ -1,1231 +0,0 @@ -// Copyright (c) 2015-2016 The Khronos Group Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include -#include -#include -#include -#include -#include - -#include -#include "SPIRV/hex_float.h" - -namespace { -using ::testing::Eq; -using spvutils::BitwiseCast; -using spvutils::Float16; -using spvutils::FloatProxy; -using spvutils::HexFloat; -using spvutils::ParseNormalFloat; - -// In this file "encode" means converting a number into a string, -// and "decode" means converting a string into a number. - -using HexFloatTest = - ::testing::TestWithParam, std::string>>; -using DecodeHexFloatTest = - ::testing::TestWithParam>>; -using HexDoubleTest = - ::testing::TestWithParam, std::string>>; -using DecodeHexDoubleTest = - ::testing::TestWithParam>>; - -// Hex-encodes a float value. -template -std::string EncodeViaHexFloat(const T& value) { - std::stringstream ss; - ss << spvutils::HexFloat(value); - return ss.str(); -} - -// The following two tests can't be DRY because they take different parameter -// types. - -TEST_P(HexFloatTest, EncodeCorrectly) { - EXPECT_THAT(EncodeViaHexFloat(GetParam().first), Eq(GetParam().second)); -} - -TEST_P(HexDoubleTest, EncodeCorrectly) { - EXPECT_THAT(EncodeViaHexFloat(GetParam().first), Eq(GetParam().second)); -} - -// Decodes a hex-float string. -template -FloatProxy Decode(const std::string& str) { - spvutils::HexFloat> decoded(0.f); - EXPECT_TRUE((std::stringstream(str) >> decoded).eof()); - return decoded.value(); -} - -TEST_P(HexFloatTest, DecodeCorrectly) { - EXPECT_THAT(Decode(GetParam().second), Eq(GetParam().first)); -} - -TEST_P(HexDoubleTest, DecodeCorrectly) { - EXPECT_THAT(Decode(GetParam().second), Eq(GetParam().first)); -} - -INSTANTIATE_TEST_CASE_P( - Float32Tests, HexFloatTest, - ::testing::ValuesIn(std::vector, std::string>>({ - {0.f, "0x0p+0"}, - {1.f, "0x1p+0"}, - {2.f, "0x1p+1"}, - {3.f, "0x1.8p+1"}, - {0.5f, "0x1p-1"}, - {0.25f, "0x1p-2"}, - {0.75f, "0x1.8p-1"}, - {-0.f, "-0x0p+0"}, - {-1.f, "-0x1p+0"}, - {-0.5f, "-0x1p-1"}, - {-0.25f, "-0x1p-2"}, - {-0.75f, "-0x1.8p-1"}, - - // Larger numbers - {512.f, "0x1p+9"}, - {-512.f, "-0x1p+9"}, - {1024.f, "0x1p+10"}, - {-1024.f, "-0x1p+10"}, - {1024.f + 8.f, "0x1.02p+10"}, - {-1024.f - 8.f, "-0x1.02p+10"}, - - // Small numbers - {1.0f / 512.f, "0x1p-9"}, - {1.0f / -512.f, "-0x1p-9"}, - {1.0f / 1024.f, "0x1p-10"}, - {1.0f / -1024.f, "-0x1p-10"}, - {1.0f / 1024.f + 1.0f / 8.f, "0x1.02p-3"}, - {1.0f / -1024.f - 1.0f / 8.f, "-0x1.02p-3"}, - - // lowest non-denorm - {float(ldexp(1.0f, -126)), "0x1p-126"}, - {float(ldexp(-1.0f, -126)), "-0x1p-126"}, - - // Denormalized values - {float(ldexp(1.0f, -127)), "0x1p-127"}, - {float(ldexp(1.0f, -127) / 2.0f), "0x1p-128"}, - {float(ldexp(1.0f, -127) / 4.0f), "0x1p-129"}, - {float(ldexp(1.0f, -127) / 8.0f), "0x1p-130"}, - {float(ldexp(-1.0f, -127)), "-0x1p-127"}, - {float(ldexp(-1.0f, -127) / 2.0f), "-0x1p-128"}, - {float(ldexp(-1.0f, -127) / 4.0f), "-0x1p-129"}, - {float(ldexp(-1.0f, -127) / 8.0f), "-0x1p-130"}, - - {float(ldexp(1.0, -127) + (ldexp(1.0, -127) / 2.0f)), "0x1.8p-127"}, - {float(ldexp(1.0, -127) / 2.0 + (ldexp(1.0, -127) / 4.0f)), - "0x1.8p-128"}, - - })),); - -INSTANTIATE_TEST_CASE_P( - Float32NanTests, HexFloatTest, - ::testing::ValuesIn(std::vector, std::string>>({ - // Various NAN and INF cases - {uint32_t(0xFF800000), "-0x1p+128"}, // -inf - {uint32_t(0x7F800000), "0x1p+128"}, // inf - {uint32_t(0xFFC00000), "-0x1.8p+128"}, // -nan - {uint32_t(0xFF800100), "-0x1.0002p+128"}, // -nan - {uint32_t(0xFF800c00), "-0x1.0018p+128"}, // -nan - {uint32_t(0xFF80F000), "-0x1.01ep+128"}, // -nan - {uint32_t(0xFFFFFFFF), "-0x1.fffffep+128"}, // -nan - {uint32_t(0x7FC00000), "0x1.8p+128"}, // +nan - {uint32_t(0x7F800100), "0x1.0002p+128"}, // +nan - {uint32_t(0x7f800c00), "0x1.0018p+128"}, // +nan - {uint32_t(0x7F80F000), "0x1.01ep+128"}, // +nan - {uint32_t(0x7FFFFFFF), "0x1.fffffep+128"}, // +nan - })),); - -INSTANTIATE_TEST_CASE_P( - Float64Tests, HexDoubleTest, - ::testing::ValuesIn( - std::vector, std::string>>({ - {0., "0x0p+0"}, - {1., "0x1p+0"}, - {2., "0x1p+1"}, - {3., "0x1.8p+1"}, - {0.5, "0x1p-1"}, - {0.25, "0x1p-2"}, - {0.75, "0x1.8p-1"}, - {-0., "-0x0p+0"}, - {-1., "-0x1p+0"}, - {-0.5, "-0x1p-1"}, - {-0.25, "-0x1p-2"}, - {-0.75, "-0x1.8p-1"}, - - // Larger numbers - {512., "0x1p+9"}, - {-512., "-0x1p+9"}, - {1024., "0x1p+10"}, - {-1024., "-0x1p+10"}, - {1024. + 8., "0x1.02p+10"}, - {-1024. - 8., "-0x1.02p+10"}, - - // Large outside the range of normal floats - {ldexp(1.0, 128), "0x1p+128"}, - {ldexp(1.0, 129), "0x1p+129"}, - {ldexp(-1.0, 128), "-0x1p+128"}, - {ldexp(-1.0, 129), "-0x1p+129"}, - {ldexp(1.0, 128) + ldexp(1.0, 90), "0x1.0000000004p+128"}, - {ldexp(1.0, 129) + ldexp(1.0, 120), "0x1.008p+129"}, - {ldexp(-1.0, 128) + ldexp(1.0, 90), "-0x1.fffffffff8p+127"}, - {ldexp(-1.0, 129) + ldexp(1.0, 120), "-0x1.ffp+128"}, - - // Small numbers - {1.0 / 512., "0x1p-9"}, - {1.0 / -512., "-0x1p-9"}, - {1.0 / 1024., "0x1p-10"}, - {1.0 / -1024., "-0x1p-10"}, - {1.0 / 1024. + 1.0 / 8., "0x1.02p-3"}, - {1.0 / -1024. - 1.0 / 8., "-0x1.02p-3"}, - - // Small outside the range of normal floats - {ldexp(1.0, -128), "0x1p-128"}, - {ldexp(1.0, -129), "0x1p-129"}, - {ldexp(-1.0, -128), "-0x1p-128"}, - {ldexp(-1.0, -129), "-0x1p-129"}, - {ldexp(1.0, -128) + ldexp(1.0, -90), "0x1.0000000004p-90"}, - {ldexp(1.0, -129) + ldexp(1.0, -120), "0x1.008p-120"}, - {ldexp(-1.0, -128) + ldexp(1.0, -90), "0x1.fffffffff8p-91"}, - {ldexp(-1.0, -129) + ldexp(1.0, -120), "0x1.ffp-121"}, - - // lowest non-denorm - {ldexp(1.0, -1022), "0x1p-1022"}, - {ldexp(-1.0, -1022), "-0x1p-1022"}, - - // Denormalized values - {ldexp(1.0, -1023), "0x1p-1023"}, - {ldexp(1.0, -1023) / 2.0, "0x1p-1024"}, - {ldexp(1.0, -1023) / 4.0, "0x1p-1025"}, - {ldexp(1.0, -1023) / 8.0, "0x1p-1026"}, - {ldexp(-1.0, -1024), "-0x1p-1024"}, - {ldexp(-1.0, -1024) / 2.0, "-0x1p-1025"}, - {ldexp(-1.0, -1024) / 4.0, "-0x1p-1026"}, - {ldexp(-1.0, -1024) / 8.0, "-0x1p-1027"}, - - {ldexp(1.0, -1023) + (ldexp(1.0, -1023) / 2.0), "0x1.8p-1023"}, - {ldexp(1.0, -1023) / 2.0 + (ldexp(1.0, -1023) / 4.0), - "0x1.8p-1024"}, - - })),); - -INSTANTIATE_TEST_CASE_P( - Float64NanTests, HexDoubleTest, - ::testing::ValuesIn(std::vector< - std::pair, std::string>>({ - // Various NAN and INF cases - {uint64_t(0xFFF0000000000000LL), "-0x1p+1024"}, //-inf - {uint64_t(0x7FF0000000000000LL), "0x1p+1024"}, //+inf - {uint64_t(0xFFF8000000000000LL), "-0x1.8p+1024"}, // -nan - {uint64_t(0xFFF0F00000000000LL), "-0x1.0fp+1024"}, // -nan - {uint64_t(0xFFF0000000000001LL), "-0x1.0000000000001p+1024"}, // -nan - {uint64_t(0xFFF0000300000000LL), "-0x1.00003p+1024"}, // -nan - {uint64_t(0xFFFFFFFFFFFFFFFFLL), "-0x1.fffffffffffffp+1024"}, // -nan - {uint64_t(0x7FF8000000000000LL), "0x1.8p+1024"}, // +nan - {uint64_t(0x7FF0F00000000000LL), "0x1.0fp+1024"}, // +nan - {uint64_t(0x7FF0000000000001LL), "0x1.0000000000001p+1024"}, // -nan - {uint64_t(0x7FF0000300000000LL), "0x1.00003p+1024"}, // -nan - {uint64_t(0x7FFFFFFFFFFFFFFFLL), "0x1.fffffffffffffp+1024"}, // -nan - })),); - -TEST(HexFloatStreamTest, OperatorLeftShiftPreservesFloatAndFill) { - std::stringstream s; - s << std::setw(4) << std::oct << std::setfill('x') << 8 << " " - << FloatProxy(uint32_t(0xFF800100)) << " " << std::setw(4) << 9; - EXPECT_THAT(s.str(), Eq(std::string("xx10 -0x1.0002p+128 xx11"))); -} - -TEST(HexDoubleStreamTest, OperatorLeftShiftPreservesFloatAndFill) { - std::stringstream s; - s << std::setw(4) << std::oct << std::setfill('x') << 8 << " " - << FloatProxy(uint64_t(0x7FF0F00000000000LL)) << " " << std::setw(4) - << 9; - EXPECT_THAT(s.str(), Eq(std::string("xx10 0x1.0fp+1024 xx11"))); -} - -TEST_P(DecodeHexFloatTest, DecodeCorrectly) { - EXPECT_THAT(Decode(GetParam().first), Eq(GetParam().second)); -} - -TEST_P(DecodeHexDoubleTest, DecodeCorrectly) { - EXPECT_THAT(Decode(GetParam().first), Eq(GetParam().second)); -} - -INSTANTIATE_TEST_CASE_P( - Float32DecodeTests, DecodeHexFloatTest, - ::testing::ValuesIn(std::vector>>({ - {"0x0p+000", 0.f}, - {"0x0p0", 0.f}, - {"0x0p-0", 0.f}, - - // flush to zero cases - {"0x1p-500", 0.f}, // Exponent underflows. - {"-0x1p-500", -0.f}, - {"0x0.00000000001p-126", 0.f}, // Fraction causes underflow. - {"-0x0.0000000001p-127", -0.f}, - {"-0x0.01p-142", -0.f}, // Fraction causes additional underflow. - {"0x0.01p-142", 0.f}, - - // Some floats that do not encode the same way as they decode. - {"0x2p+0", 2.f}, - {"0xFFp+0", 255.f}, - {"0x0.8p+0", 0.5f}, - {"0x0.4p+0", 0.25f}, - })),); - -INSTANTIATE_TEST_CASE_P( - Float32DecodeInfTests, DecodeHexFloatTest, - ::testing::ValuesIn(std::vector>>({ - // inf cases - {"-0x1p+128", uint32_t(0xFF800000)}, // -inf - {"0x32p+127", uint32_t(0x7F800000)}, // inf - {"0x32p+500", uint32_t(0x7F800000)}, // inf - {"-0x32p+127", uint32_t(0xFF800000)}, // -inf - })),); - -INSTANTIATE_TEST_CASE_P( - Float64DecodeTests, DecodeHexDoubleTest, - ::testing::ValuesIn( - std::vector>>({ - {"0x0p+000", 0.}, - {"0x0p0", 0.}, - {"0x0p-0", 0.}, - - // flush to zero cases - {"0x1p-5000", 0.}, // Exponent underflows. - {"-0x1p-5000", -0.}, - {"0x0.0000000000000001p-1023", 0.}, // Fraction causes underflow. - {"-0x0.000000000000001p-1024", -0.}, - {"-0x0.01p-1090", -0.f}, // Fraction causes additional underflow. - {"0x0.01p-1090", 0.}, - - // Some floats that do not encode the same way as they decode. - {"0x2p+0", 2.}, - {"0xFFp+0", 255.}, - {"0x0.8p+0", 0.5}, - {"0x0.4p+0", 0.25}, - })),); - -INSTANTIATE_TEST_CASE_P( - Float64DecodeInfTests, DecodeHexDoubleTest, - ::testing::ValuesIn( - std::vector>>({ - // inf cases - {"-0x1p+1024", uint64_t(0xFFF0000000000000)}, // -inf - {"0x32p+1023", uint64_t(0x7FF0000000000000)}, // inf - {"0x32p+5000", uint64_t(0x7FF0000000000000)}, // inf - {"-0x32p+1023", uint64_t(0xFFF0000000000000)}, // -inf - })),); - -TEST(FloatProxy, ValidConversion) { - EXPECT_THAT(FloatProxy(1.f).getAsFloat(), Eq(1.0f)); - EXPECT_THAT(FloatProxy(32.f).getAsFloat(), Eq(32.0f)); - EXPECT_THAT(FloatProxy(-1.f).getAsFloat(), Eq(-1.0f)); - EXPECT_THAT(FloatProxy(0.f).getAsFloat(), Eq(0.0f)); - EXPECT_THAT(FloatProxy(-0.f).getAsFloat(), Eq(-0.0f)); - EXPECT_THAT(FloatProxy(1.2e32f).getAsFloat(), Eq(1.2e32f)); - - EXPECT_TRUE(std::isinf(FloatProxy(uint32_t(0xFF800000)).getAsFloat())); - EXPECT_TRUE(std::isinf(FloatProxy(uint32_t(0x7F800000)).getAsFloat())); - EXPECT_TRUE(std::isnan(FloatProxy(uint32_t(0xFFC00000)).getAsFloat())); - EXPECT_TRUE(std::isnan(FloatProxy(uint32_t(0xFF800100)).getAsFloat())); - EXPECT_TRUE(std::isnan(FloatProxy(uint32_t(0xFF800c00)).getAsFloat())); - EXPECT_TRUE(std::isnan(FloatProxy(uint32_t(0xFF80F000)).getAsFloat())); - EXPECT_TRUE(std::isnan(FloatProxy(uint32_t(0xFFFFFFFF)).getAsFloat())); - EXPECT_TRUE(std::isnan(FloatProxy(uint32_t(0x7FC00000)).getAsFloat())); - EXPECT_TRUE(std::isnan(FloatProxy(uint32_t(0x7F800100)).getAsFloat())); - EXPECT_TRUE(std::isnan(FloatProxy(uint32_t(0x7f800c00)).getAsFloat())); - EXPECT_TRUE(std::isnan(FloatProxy(uint32_t(0x7F80F000)).getAsFloat())); - EXPECT_TRUE(std::isnan(FloatProxy(uint32_t(0x7FFFFFFF)).getAsFloat())); - - EXPECT_THAT(FloatProxy(uint32_t(0xFF800000)).data(), Eq(0xFF800000u)); - EXPECT_THAT(FloatProxy(uint32_t(0x7F800000)).data(), Eq(0x7F800000u)); - EXPECT_THAT(FloatProxy(uint32_t(0xFFC00000)).data(), Eq(0xFFC00000u)); - EXPECT_THAT(FloatProxy(uint32_t(0xFF800100)).data(), Eq(0xFF800100u)); - EXPECT_THAT(FloatProxy(uint32_t(0xFF800c00)).data(), Eq(0xFF800c00u)); - EXPECT_THAT(FloatProxy(uint32_t(0xFF80F000)).data(), Eq(0xFF80F000u)); - EXPECT_THAT(FloatProxy(uint32_t(0xFFFFFFFF)).data(), Eq(0xFFFFFFFFu)); - EXPECT_THAT(FloatProxy(uint32_t(0x7FC00000)).data(), Eq(0x7FC00000u)); - EXPECT_THAT(FloatProxy(uint32_t(0x7F800100)).data(), Eq(0x7F800100u)); - EXPECT_THAT(FloatProxy(uint32_t(0x7f800c00)).data(), Eq(0x7f800c00u)); - EXPECT_THAT(FloatProxy(uint32_t(0x7F80F000)).data(), Eq(0x7F80F000u)); - EXPECT_THAT(FloatProxy(uint32_t(0x7FFFFFFF)).data(), Eq(0x7FFFFFFFu)); -} - -TEST(FloatProxy, Nan) { - EXPECT_TRUE(FloatProxy(uint32_t(0xFFC00000)).isNan()); - EXPECT_TRUE(FloatProxy(uint32_t(0xFF800100)).isNan()); - EXPECT_TRUE(FloatProxy(uint32_t(0xFF800c00)).isNan()); - EXPECT_TRUE(FloatProxy(uint32_t(0xFF80F000)).isNan()); - EXPECT_TRUE(FloatProxy(uint32_t(0xFFFFFFFF)).isNan()); - EXPECT_TRUE(FloatProxy(uint32_t(0x7FC00000)).isNan()); - EXPECT_TRUE(FloatProxy(uint32_t(0x7F800100)).isNan()); - EXPECT_TRUE(FloatProxy(uint32_t(0x7f800c00)).isNan()); - EXPECT_TRUE(FloatProxy(uint32_t(0x7F80F000)).isNan()); - EXPECT_TRUE(FloatProxy(uint32_t(0x7FFFFFFF)).isNan()); -} - -TEST(FloatProxy, Negation) { - EXPECT_THAT((-FloatProxy(1.f)).getAsFloat(), Eq(-1.0f)); - EXPECT_THAT((-FloatProxy(0.f)).getAsFloat(), Eq(-0.0f)); - - EXPECT_THAT((-FloatProxy(-1.f)).getAsFloat(), Eq(1.0f)); - EXPECT_THAT((-FloatProxy(-0.f)).getAsFloat(), Eq(0.0f)); - - EXPECT_THAT((-FloatProxy(32.f)).getAsFloat(), Eq(-32.0f)); - EXPECT_THAT((-FloatProxy(-32.f)).getAsFloat(), Eq(32.0f)); - - EXPECT_THAT((-FloatProxy(1.2e32f)).getAsFloat(), Eq(-1.2e32f)); - EXPECT_THAT((-FloatProxy(-1.2e32f)).getAsFloat(), Eq(1.2e32f)); - - EXPECT_THAT( - (-FloatProxy(std::numeric_limits::infinity())).getAsFloat(), - Eq(-std::numeric_limits::infinity())); - EXPECT_THAT((-FloatProxy(-std::numeric_limits::infinity())) - .getAsFloat(), - Eq(std::numeric_limits::infinity())); -} - -// Test conversion of FloatProxy values to strings. -// -// In previous cases, we always wrapped the FloatProxy value in a HexFloat -// before conversion to a string. In the following cases, the FloatProxy -// decides for itself whether to print as a regular number or as a hex float. - -using FloatProxyFloatTest = - ::testing::TestWithParam, std::string>>; -using FloatProxyDoubleTest = - ::testing::TestWithParam, std::string>>; - -// Converts a float value to a string via a FloatProxy. -template -std::string EncodeViaFloatProxy(const T& value) { - std::stringstream ss; - ss << value; - return ss.str(); -} - -// Converts a floating point string so that the exponent prefix -// is 'e', and the exponent value does not have leading zeros. -// The Microsoft runtime library likes to write things like "2.5E+010". -// Convert that to "2.5e+10". -// We don't care what happens to strings that are not floating point -// strings. -std::string NormalizeExponentInFloatString(std::string in) { - std::string result; - // Reserve one spot for the terminating null, even when the sscanf fails. - std::vector prefix(in.size() + 1); - char e; - char plus_or_minus; - int exponent; // in base 10 - if ((4 == std::sscanf(in.c_str(), "%[-+.0123456789]%c%c%d", prefix.data(), &e, - &plus_or_minus, &exponent)) && - (e == 'e' || e == 'E') && - (plus_or_minus == '-' || plus_or_minus == '+')) { - // It looks like a floating point value with exponent. - std::stringstream out; - out << prefix.data() << 'e' << plus_or_minus << exponent; - result = out.str(); - } else { - result = in; - } - return result; -} - -TEST(NormalizeFloat, Sample) { - EXPECT_THAT(NormalizeExponentInFloatString(""), Eq("")); - EXPECT_THAT(NormalizeExponentInFloatString("1e-12"), Eq("1e-12")); - EXPECT_THAT(NormalizeExponentInFloatString("1E+14"), Eq("1e+14")); - EXPECT_THAT(NormalizeExponentInFloatString("1e-0012"), Eq("1e-12")); - EXPECT_THAT(NormalizeExponentInFloatString("1.263E+014"), Eq("1.263e+14")); -} - -// The following two tests can't be DRY because they take different parameter -// types. -TEST_P(FloatProxyFloatTest, EncodeCorrectly) { - EXPECT_THAT( - NormalizeExponentInFloatString(EncodeViaFloatProxy(GetParam().first)), - Eq(GetParam().second)); -} - -TEST_P(FloatProxyDoubleTest, EncodeCorrectly) { - EXPECT_THAT( - NormalizeExponentInFloatString(EncodeViaFloatProxy(GetParam().first)), - Eq(GetParam().second)); -} - -INSTANTIATE_TEST_CASE_P( - Float32Tests, FloatProxyFloatTest, - ::testing::ValuesIn(std::vector, std::string>>({ - // Zero - {0.f, "0"}, - // Normal numbers - {1.f, "1"}, - {-0.25f, "-0.25"}, - {1000.0f, "1000"}, - - // Still normal numbers, but with large magnitude exponents. - {float(ldexp(1.f, 126)), "8.50706e+37"}, - {float(ldexp(-1.f, -126)), "-1.17549e-38"}, - - // denormalized values are printed as hex floats. - {float(ldexp(1.0f, -127)), "0x1p-127"}, - {float(ldexp(1.5f, -128)), "0x1.8p-128"}, - {float(ldexp(1.25, -129)), "0x1.4p-129"}, - {float(ldexp(1.125, -130)), "0x1.2p-130"}, - {float(ldexp(-1.0f, -127)), "-0x1p-127"}, - {float(ldexp(-1.0f, -128)), "-0x1p-128"}, - {float(ldexp(-1.0f, -129)), "-0x1p-129"}, - {float(ldexp(-1.5f, -130)), "-0x1.8p-130"}, - - // NaNs - {FloatProxy(uint32_t(0xFFC00000)), "-0x1.8p+128"}, - {FloatProxy(uint32_t(0xFF800100)), "-0x1.0002p+128"}, - - {std::numeric_limits::infinity(), "0x1p+128"}, - {-std::numeric_limits::infinity(), "-0x1p+128"}, - })),); - -INSTANTIATE_TEST_CASE_P( - Float64Tests, FloatProxyDoubleTest, - ::testing::ValuesIn( - std::vector, std::string>>({ - {0., "0"}, - {1., "1"}, - {-0.25, "-0.25"}, - {1000.0, "1000"}, - - // Large outside the range of normal floats - {ldexp(1.0, 128), "3.40282366920938e+38"}, - {ldexp(1.5, 129), "1.02084710076282e+39"}, - {ldexp(-1.0, 128), "-3.40282366920938e+38"}, - {ldexp(-1.5, 129), "-1.02084710076282e+39"}, - - // Small outside the range of normal floats - {ldexp(1.5, -129), "2.20405190779179e-39"}, - {ldexp(-1.5, -129), "-2.20405190779179e-39"}, - - // lowest non-denorm - {ldexp(1.0, -1022), "2.2250738585072e-308"}, - {ldexp(-1.0, -1022), "-2.2250738585072e-308"}, - - // Denormalized values - {ldexp(1.125, -1023), "0x1.2p-1023"}, - {ldexp(-1.375, -1024), "-0x1.6p-1024"}, - - // NaNs - {uint64_t(0x7FF8000000000000LL), "0x1.8p+1024"}, - {uint64_t(0xFFF0F00000000000LL), "-0x1.0fp+1024"}, - - // Infinity - {std::numeric_limits::infinity(), "0x1p+1024"}, - {-std::numeric_limits::infinity(), "-0x1p+1024"}, - - })),); - -// double is used so that unbiased_exponent can be used with the output -// of ldexp directly. -int32_t unbiased_exponent(double f) { - return spvutils::HexFloat>( - static_cast(f)).getUnbiasedNormalizedExponent(); -} - -int16_t unbiased_half_exponent(uint16_t f) { - return spvutils::HexFloat>(f) - .getUnbiasedNormalizedExponent(); -} - -TEST(HexFloatOperationTest, UnbiasedExponent) { - // Float cases - EXPECT_EQ(0, unbiased_exponent(ldexp(1.0f, 0))); - EXPECT_EQ(-32, unbiased_exponent(ldexp(1.0f, -32))); - EXPECT_EQ(42, unbiased_exponent(ldexp(1.0f, 42))); - EXPECT_EQ(125, unbiased_exponent(ldexp(1.0f, 125))); - // Saturates to 128 - EXPECT_EQ(128, unbiased_exponent(ldexp(1.0f, 256))); - - EXPECT_EQ(-100, unbiased_exponent(ldexp(1.0f, -100))); - EXPECT_EQ(-127, unbiased_exponent(ldexp(1.0f, -127))); // First denorm - EXPECT_EQ(-128, unbiased_exponent(ldexp(1.0f, -128))); - EXPECT_EQ(-129, unbiased_exponent(ldexp(1.0f, -129))); - EXPECT_EQ(-140, unbiased_exponent(ldexp(1.0f, -140))); - // Smallest representable number - EXPECT_EQ(-126 - 23, unbiased_exponent(ldexp(1.0f, -126 - 23))); - // Should get rounded to 0 first. - EXPECT_EQ(0, unbiased_exponent(ldexp(1.0f, -127 - 23))); - - // Float16 cases - // The exponent is represented in the bits 0x7C00 - // The offset is -15 - EXPECT_EQ(0, unbiased_half_exponent(0x3C00)); - EXPECT_EQ(3, unbiased_half_exponent(0x4800)); - EXPECT_EQ(-1, unbiased_half_exponent(0x3800)); - EXPECT_EQ(-14, unbiased_half_exponent(0x0400)); - EXPECT_EQ(16, unbiased_half_exponent(0x7C00)); - EXPECT_EQ(10, unbiased_half_exponent(0x6400)); - - // Smallest representable number - EXPECT_EQ(-24, unbiased_half_exponent(0x0001)); -} - -// Creates a float that is the sum of 1/(2 ^ fractions[i]) for i in factions -float float_fractions(const std::vector& fractions) { - float f = 0; - for(int32_t i: fractions) { - f += std::ldexp(1.0f, -i); - } - return f; -} - -// Returns the normalized significand of a HexFloat> -// that was created by calling float_fractions with the input fractions, -// raised to the power of exp. -uint32_t normalized_significand(const std::vector& fractions, uint32_t exp) { - return spvutils::HexFloat>( - static_cast(ldexp(float_fractions(fractions), exp))) - .getNormalizedSignificand(); -} - -// Sets the bits from MSB to LSB of the significand part of a float. -// For example 0 would set the bit 23 (counting from LSB to MSB), -// and 1 would set the 22nd bit. -uint32_t bits_set(const std::vector& bits) { - const uint32_t top_bit = 1u << 22u; - uint32_t val= 0; - for(uint32_t i: bits) { - val |= top_bit >> i; - } - return val; -} - -// The same as bits_set but for a Float16 value instead of 32-bit floating -// point. -uint16_t half_bits_set(const std::vector& bits) { - const uint32_t top_bit = 1u << 9u; - uint32_t val= 0; - for(uint32_t i: bits) { - val |= top_bit >> i; - } - return static_cast(val); -} - -TEST(HexFloatOperationTest, NormalizedSignificand) { - // For normalized numbers (the following) it should be a simple matter - // of getting rid of the top implicit bit - EXPECT_EQ(bits_set({}), normalized_significand({0}, 0)); - EXPECT_EQ(bits_set({0}), normalized_significand({0, 1}, 0)); - EXPECT_EQ(bits_set({0, 1}), normalized_significand({0, 1, 2}, 0)); - EXPECT_EQ(bits_set({1}), normalized_significand({0, 2}, 0)); - EXPECT_EQ(bits_set({1}), normalized_significand({0, 2}, 32)); - EXPECT_EQ(bits_set({1}), normalized_significand({0, 2}, 126)); - - // For denormalized numbers we expect the normalized significand to - // shift as if it were normalized. This means, in practice that the - // top_most set bit will be cut off. Looks very similar to above (on purpose) - EXPECT_EQ(bits_set({}), normalized_significand({0}, -127)); - EXPECT_EQ(bits_set({3}), normalized_significand({0, 4}, -128)); - EXPECT_EQ(bits_set({3}), normalized_significand({0, 4}, -127)); - EXPECT_EQ(bits_set({}), normalized_significand({22}, -127)); - EXPECT_EQ(bits_set({0}), normalized_significand({21, 22}, -127)); -} - -// Returns the 32-bit floating point value created by -// calling setFromSignUnbiasedExponentAndNormalizedSignificand -// on a HexFloat> -float set_from_sign(bool negative, int32_t unbiased_exponent, - uint32_t significand, bool round_denorm_up) { - spvutils::HexFloat> f(0.f); - f.setFromSignUnbiasedExponentAndNormalizedSignificand( - negative, unbiased_exponent, significand, round_denorm_up); - return f.value().getAsFloat(); -} - -TEST(HexFloatOperationTests, - SetFromSignUnbiasedExponentAndNormalizedSignificand) { - - EXPECT_EQ(1.f, set_from_sign(false, 0, 0, false)); - - // Tests insertion of various denormalized numbers with and without round up. - EXPECT_EQ(static_cast(ldexp(1.f, -149)), set_from_sign(false, -149, 0, false)); - EXPECT_EQ(static_cast(ldexp(1.f, -149)), set_from_sign(false, -149, 0, true)); - EXPECT_EQ(0.f, set_from_sign(false, -150, 1, false)); - EXPECT_EQ(static_cast(ldexp(1.f, -149)), set_from_sign(false, -150, 1, true)); - - EXPECT_EQ(ldexp(1.0f, -127), set_from_sign(false, -127, 0, false)); - EXPECT_EQ(ldexp(1.0f, -128), set_from_sign(false, -128, 0, false)); - EXPECT_EQ(float_fractions({0, 1, 2, 5}), - set_from_sign(false, 0, bits_set({0, 1, 4}), false)); - EXPECT_EQ(ldexp(float_fractions({0, 1, 2, 5}), -32), - set_from_sign(false, -32, bits_set({0, 1, 4}), false)); - EXPECT_EQ(ldexp(float_fractions({0, 1, 2, 5}), -128), - set_from_sign(false, -128, bits_set({0, 1, 4}), false)); - - // The negative cases from above. - EXPECT_EQ(-1.f, set_from_sign(true, 0, 0, false)); - EXPECT_EQ(-ldexp(1.0, -127), set_from_sign(true, -127, 0, false)); - EXPECT_EQ(-ldexp(1.0, -128), set_from_sign(true, -128, 0, false)); - EXPECT_EQ(-float_fractions({0, 1, 2, 5}), - set_from_sign(true, 0, bits_set({0, 1, 4}), false)); - EXPECT_EQ(-ldexp(float_fractions({0, 1, 2, 5}), -32), - set_from_sign(true, -32, bits_set({0, 1, 4}), false)); - EXPECT_EQ(-ldexp(float_fractions({0, 1, 2, 5}), -128), - set_from_sign(true, -128, bits_set({0, 1, 4}), false)); -} - -TEST(HexFloatOperationTests, NonRounding) { - // Rounding from 32-bit hex-float to 32-bit hex-float should be trivial, - // except in the denorm case which is a bit more complex. - using HF = spvutils::HexFloat>; - bool carry_bit = false; - - spvutils::round_direction rounding[] = { - spvutils::kRoundToZero, - spvutils::kRoundToNearestEven, - spvutils::kRoundToPositiveInfinity, - spvutils::kRoundToNegativeInfinity}; - - // Everything fits, so this should be straight-forward - for (spvutils::round_direction round : rounding) { - EXPECT_EQ(bits_set({}), HF(0.f).getRoundedNormalizedSignificand( - round, &carry_bit)); - EXPECT_FALSE(carry_bit); - - EXPECT_EQ(bits_set({0}), - HF(float_fractions({0, 1})) - .getRoundedNormalizedSignificand(round, &carry_bit)); - EXPECT_FALSE(carry_bit); - - EXPECT_EQ(bits_set({1, 3}), - HF(float_fractions({0, 2, 4})) - .getRoundedNormalizedSignificand(round, &carry_bit)); - EXPECT_FALSE(carry_bit); - - EXPECT_EQ( - bits_set({0, 1, 4}), - HF(static_cast(-ldexp(float_fractions({0, 1, 2, 5}), -128))) - .getRoundedNormalizedSignificand(round, &carry_bit)); - EXPECT_FALSE(carry_bit); - - EXPECT_EQ( - bits_set({0, 1, 4, 22}), - HF(static_cast(float_fractions({0, 1, 2, 5, 23}))) - .getRoundedNormalizedSignificand(round, &carry_bit)); - EXPECT_FALSE(carry_bit); - } -} - -struct RoundSignificandCase { - float source_float; - std::pair expected_results; - spvutils::round_direction round; -}; - -using HexFloatRoundTest = - ::testing::TestWithParam; - -TEST_P(HexFloatRoundTest, RoundDownToFP16) { - using HF = spvutils::HexFloat>; - using HF16 = spvutils::HexFloat>; - - HF input_value(GetParam().source_float); - bool carry_bit = false; - EXPECT_EQ(GetParam().expected_results.first, - input_value.getRoundedNormalizedSignificand( - GetParam().round, &carry_bit)); - EXPECT_EQ(carry_bit, GetParam().expected_results.second); -} - -// clang-format off -INSTANTIATE_TEST_CASE_P(F32ToF16, HexFloatRoundTest, - ::testing::ValuesIn(std::vector( - { - {float_fractions({0}), std::make_pair(half_bits_set({}), false), spvutils::kRoundToZero}, - {float_fractions({0}), std::make_pair(half_bits_set({}), false), spvutils::kRoundToNearestEven}, - {float_fractions({0}), std::make_pair(half_bits_set({}), false), spvutils::kRoundToPositiveInfinity}, - {float_fractions({0}), std::make_pair(half_bits_set({}), false), spvutils::kRoundToNegativeInfinity}, - {float_fractions({0, 1}), std::make_pair(half_bits_set({0}), false), spvutils::kRoundToZero}, - - {float_fractions({0, 1, 11}), std::make_pair(half_bits_set({0}), false), spvutils::kRoundToZero}, - {float_fractions({0, 1, 11}), std::make_pair(half_bits_set({0, 9}), false), spvutils::kRoundToPositiveInfinity}, - {float_fractions({0, 1, 11}), std::make_pair(half_bits_set({0}), false), spvutils::kRoundToNegativeInfinity}, - {float_fractions({0, 1, 11}), std::make_pair(half_bits_set({0}), false), spvutils::kRoundToNearestEven}, - - {float_fractions({0, 1, 10, 11}), std::make_pair(half_bits_set({0, 9}), false), spvutils::kRoundToZero}, - {float_fractions({0, 1, 10, 11}), std::make_pair(half_bits_set({0, 8}), false), spvutils::kRoundToPositiveInfinity}, - {float_fractions({0, 1, 10, 11}), std::make_pair(half_bits_set({0, 9}), false), spvutils::kRoundToNegativeInfinity}, - {float_fractions({0, 1, 10, 11}), std::make_pair(half_bits_set({0, 8}), false), spvutils::kRoundToNearestEven}, - - {float_fractions({0, 1, 11, 12}), std::make_pair(half_bits_set({0}), false), spvutils::kRoundToZero}, - {float_fractions({0, 1, 11, 12}), std::make_pair(half_bits_set({0, 9}), false), spvutils::kRoundToPositiveInfinity}, - {float_fractions({0, 1, 11, 12}), std::make_pair(half_bits_set({0}), false), spvutils::kRoundToNegativeInfinity}, - {float_fractions({0, 1, 11, 12}), std::make_pair(half_bits_set({0, 9}), false), spvutils::kRoundToNearestEven}, - - {-float_fractions({0, 1, 11, 12}), std::make_pair(half_bits_set({0}), false), spvutils::kRoundToZero}, - {-float_fractions({0, 1, 11, 12}), std::make_pair(half_bits_set({0}), false), spvutils::kRoundToPositiveInfinity}, - {-float_fractions({0, 1, 11, 12}), std::make_pair(half_bits_set({0, 9}), false), spvutils::kRoundToNegativeInfinity}, - {-float_fractions({0, 1, 11, 12}), std::make_pair(half_bits_set({0, 9}), false), spvutils::kRoundToNearestEven}, - - {float_fractions({0, 1, 11, 22}), std::make_pair(half_bits_set({0}), false), spvutils::kRoundToZero}, - {float_fractions({0, 1, 11, 22}), std::make_pair(half_bits_set({0, 9}), false), spvutils::kRoundToPositiveInfinity}, - {float_fractions({0, 1, 11, 22}), std::make_pair(half_bits_set({0}), false), spvutils::kRoundToNegativeInfinity}, - {float_fractions({0, 1, 11, 22}), std::make_pair(half_bits_set({0, 9}), false), spvutils::kRoundToNearestEven}, - - // Carries - {float_fractions({0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}), std::make_pair(half_bits_set({0, 1, 2, 3, 4, 5, 6, 7, 8, 9}), false), spvutils::kRoundToZero}, - {float_fractions({0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}), std::make_pair(half_bits_set({}), true), spvutils::kRoundToPositiveInfinity}, - {float_fractions({0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}), std::make_pair(half_bits_set({0, 1, 2, 3, 4, 5, 6, 7, 8, 9}), false), spvutils::kRoundToNegativeInfinity}, - {float_fractions({0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}), std::make_pair(half_bits_set({}), true), spvutils::kRoundToNearestEven}, - - // Cases where original number was denorm. Note: this should have no effect - // the number is pre-normalized. - {static_cast(ldexp(float_fractions({0, 1, 11, 13}), -128)), std::make_pair(half_bits_set({0}), false), spvutils::kRoundToZero}, - {static_cast(ldexp(float_fractions({0, 1, 11, 13}), -129)), std::make_pair(half_bits_set({0, 9}), false), spvutils::kRoundToPositiveInfinity}, - {static_cast(ldexp(float_fractions({0, 1, 11, 13}), -131)), std::make_pair(half_bits_set({0}), false), spvutils::kRoundToNegativeInfinity}, - {static_cast(ldexp(float_fractions({0, 1, 11, 13}), -130)), std::make_pair(half_bits_set({0, 9}), false), spvutils::kRoundToNearestEven}, - })),); -// clang-format on - -struct UpCastSignificandCase { - uint16_t source_half; - uint32_t expected_result; -}; - -using HexFloatRoundUpSignificandTest = - ::testing::TestWithParam; -TEST_P(HexFloatRoundUpSignificandTest, Widening) { - using HF = spvutils::HexFloat>; - using HF16 = spvutils::HexFloat>; - bool carry_bit = false; - - spvutils::round_direction rounding[] = { - spvutils::kRoundToZero, - spvutils::kRoundToNearestEven, - spvutils::kRoundToPositiveInfinity, - spvutils::kRoundToNegativeInfinity}; - - // Everything fits, so everything should just be bit-shifts. - for (spvutils::round_direction round : rounding) { - carry_bit = false; - HF16 input_value(GetParam().source_half); - EXPECT_EQ( - GetParam().expected_result, - input_value.getRoundedNormalizedSignificand(round, &carry_bit)) - << std::hex << "0x" - << input_value.getRoundedNormalizedSignificand(round, &carry_bit) - << " 0x" << GetParam().expected_result; - EXPECT_FALSE(carry_bit); - } -} - -INSTANTIATE_TEST_CASE_P(F16toF32, HexFloatRoundUpSignificandTest, - // 0xFC00 of the source 16-bit hex value cover the sign and the exponent. - // They are ignored for this test. - ::testing::ValuesIn(std::vector( - { - {0x3F00, 0x600000}, - {0x0F00, 0x600000}, - {0x0F01, 0x602000}, - {0x0FFF, 0x7FE000}, - })),); - -struct DownCastTest { - float source_float; - uint16_t expected_half; - std::vector directions; -}; - -std::string get_round_text(spvutils::round_direction direction) { -#define CASE(round_direction) \ - case round_direction: \ - return #round_direction - - switch (direction) { - CASE(spvutils::kRoundToZero); - CASE(spvutils::kRoundToPositiveInfinity); - CASE(spvutils::kRoundToNegativeInfinity); - CASE(spvutils::kRoundToNearestEven); - } -#undef CASE - return ""; -} - -using HexFloatFP32To16Tests = ::testing::TestWithParam; - -TEST_P(HexFloatFP32To16Tests, NarrowingCasts) { - using HF = spvutils::HexFloat>; - using HF16 = spvutils::HexFloat>; - HF f(GetParam().source_float); - for (auto round : GetParam().directions) { - HF16 half(0); - f.castTo(half, round); - EXPECT_EQ(GetParam().expected_half, half.value().getAsFloat().get_value()) - << get_round_text(round) << " " << std::hex - << spvutils::BitwiseCast(GetParam().source_float) - << " cast to: " << half.value().getAsFloat().get_value(); - } -} - -const uint16_t positive_infinity = 0x7C00; -const uint16_t negative_infinity = 0xFC00; - -INSTANTIATE_TEST_CASE_P(F32ToF16, HexFloatFP32To16Tests, - ::testing::ValuesIn(std::vector( - { - // Exactly representable as half. - {0.f, 0x0, {spvutils::kRoundToZero, spvutils::kRoundToPositiveInfinity, spvutils::kRoundToNegativeInfinity, spvutils::kRoundToNearestEven}}, - {-0.f, 0x8000, {spvutils::kRoundToZero, spvutils::kRoundToPositiveInfinity, spvutils::kRoundToNegativeInfinity, spvutils::kRoundToNearestEven}}, - {1.0f, 0x3C00, {spvutils::kRoundToZero, spvutils::kRoundToPositiveInfinity, spvutils::kRoundToNegativeInfinity, spvutils::kRoundToNearestEven}}, - {-1.0f, 0xBC00, {spvutils::kRoundToZero, spvutils::kRoundToPositiveInfinity, spvutils::kRoundToNegativeInfinity, spvutils::kRoundToNearestEven}}, - - {float_fractions({0, 1, 10}) , 0x3E01, {spvutils::kRoundToZero, spvutils::kRoundToPositiveInfinity, spvutils::kRoundToNegativeInfinity, spvutils::kRoundToNearestEven}}, - {-float_fractions({0, 1, 10}) , 0xBE01, {spvutils::kRoundToZero, spvutils::kRoundToPositiveInfinity, spvutils::kRoundToNegativeInfinity, spvutils::kRoundToNearestEven}}, - {static_cast(ldexp(float_fractions({0, 1, 10}), 3)), 0x4A01, {spvutils::kRoundToZero, spvutils::kRoundToPositiveInfinity, spvutils::kRoundToNegativeInfinity, spvutils::kRoundToNearestEven}}, - {static_cast(-ldexp(float_fractions({0, 1, 10}), 3)), 0xCA01, {spvutils::kRoundToZero, spvutils::kRoundToPositiveInfinity, spvutils::kRoundToNegativeInfinity, spvutils::kRoundToNearestEven}}, - - - // Underflow - {static_cast(ldexp(1.0f, -25)), 0x0, {spvutils::kRoundToZero, spvutils::kRoundToNegativeInfinity, spvutils::kRoundToNearestEven}}, - {static_cast(ldexp(1.0f, -25)), 0x1, {spvutils::kRoundToPositiveInfinity}}, - {static_cast(-ldexp(1.0f, -25)), 0x8000, {spvutils::kRoundToZero, spvutils::kRoundToPositiveInfinity, spvutils::kRoundToNearestEven}}, - {static_cast(-ldexp(1.0f, -25)), 0x8001, {spvutils::kRoundToNegativeInfinity}}, - {static_cast(ldexp(1.0f, -24)), 0x1, {spvutils::kRoundToZero, spvutils::kRoundToPositiveInfinity, spvutils::kRoundToNegativeInfinity, spvutils::kRoundToNearestEven}}, - - // Overflow - {static_cast(ldexp(1.0f, 16)), positive_infinity, {spvutils::kRoundToZero, spvutils::kRoundToPositiveInfinity, spvutils::kRoundToNegativeInfinity, spvutils::kRoundToNearestEven}}, - {static_cast(ldexp(1.0f, 18)), positive_infinity, {spvutils::kRoundToZero, spvutils::kRoundToPositiveInfinity, spvutils::kRoundToNegativeInfinity, spvutils::kRoundToNearestEven}}, - {static_cast(ldexp(1.3f, 16)), positive_infinity, {spvutils::kRoundToZero, spvutils::kRoundToPositiveInfinity, spvutils::kRoundToNegativeInfinity, spvutils::kRoundToNearestEven}}, - {static_cast(-ldexp(1.0f, 16)), negative_infinity, {spvutils::kRoundToZero, spvutils::kRoundToPositiveInfinity, spvutils::kRoundToNegativeInfinity, spvutils::kRoundToNearestEven}}, - {static_cast(-ldexp(1.0f, 18)), negative_infinity, {spvutils::kRoundToZero, spvutils::kRoundToPositiveInfinity, spvutils::kRoundToNegativeInfinity, spvutils::kRoundToNearestEven}}, - {static_cast(-ldexp(1.3f, 16)), negative_infinity, {spvutils::kRoundToZero, spvutils::kRoundToPositiveInfinity, spvutils::kRoundToNegativeInfinity, spvutils::kRoundToNearestEven}}, - - // Transfer of Infinities - {std::numeric_limits::infinity(), positive_infinity, {spvutils::kRoundToZero, spvutils::kRoundToPositiveInfinity, spvutils::kRoundToNegativeInfinity, spvutils::kRoundToNearestEven}}, - {-std::numeric_limits::infinity(), negative_infinity, {spvutils::kRoundToZero, spvutils::kRoundToPositiveInfinity, spvutils::kRoundToNegativeInfinity, spvutils::kRoundToNearestEven}}, - - // Nans are below because we cannot test for equality. - })),); - -struct UpCastCase{ - uint16_t source_half; - float expected_float; -}; - -using HexFloatFP16To32Tests = ::testing::TestWithParam; -TEST_P(HexFloatFP16To32Tests, WideningCasts) { - using HF = spvutils::HexFloat>; - using HF16 = spvutils::HexFloat>; - HF16 f(GetParam().source_half); - - spvutils::round_direction rounding[] = { - spvutils::kRoundToZero, - spvutils::kRoundToNearestEven, - spvutils::kRoundToPositiveInfinity, - spvutils::kRoundToNegativeInfinity}; - - // Everything fits, so everything should just be bit-shifts. - for (spvutils::round_direction round : rounding) { - HF flt(0.f); - f.castTo(flt, round); - EXPECT_EQ(GetParam().expected_float, flt.value().getAsFloat()) - << get_round_text(round) << " " << std::hex - << spvutils::BitwiseCast(GetParam().source_half) - << " cast to: " << flt.value().getAsFloat(); - } -} - -INSTANTIATE_TEST_CASE_P(F16ToF32, HexFloatFP16To32Tests, - ::testing::ValuesIn(std::vector( - { - {0x0000, 0.f}, - {0x8000, -0.f}, - {0x3C00, 1.0f}, - {0xBC00, -1.0f}, - {0x3F00, float_fractions({0, 1, 2})}, - {0xBF00, -float_fractions({0, 1, 2})}, - {0x3F01, float_fractions({0, 1, 2, 10})}, - {0xBF01, -float_fractions({0, 1, 2, 10})}, - - // denorm - {0x0001, static_cast(ldexp(1.0, -24))}, - {0x0002, static_cast(ldexp(1.0, -23))}, - {0x8001, static_cast(-ldexp(1.0, -24))}, - {0x8011, static_cast(-ldexp(1.0, -20) + -ldexp(1.0, -24))}, - - // inf - {0x7C00, std::numeric_limits::infinity()}, - {0xFC00, -std::numeric_limits::infinity()}, - })),); - -TEST(HexFloatOperationTests, NanTests) { - using HF = spvutils::HexFloat>; - using HF16 = spvutils::HexFloat>; - spvutils::round_direction rounding[] = { - spvutils::kRoundToZero, - spvutils::kRoundToNearestEven, - spvutils::kRoundToPositiveInfinity, - spvutils::kRoundToNegativeInfinity}; - - // Everything fits, so everything should just be bit-shifts. - for (spvutils::round_direction round : rounding) { - HF16 f16(0); - HF f(0.f); - HF(std::numeric_limits::quiet_NaN()).castTo(f16, round); - EXPECT_TRUE(f16.value().isNan()); - HF(std::numeric_limits::signaling_NaN()).castTo(f16, round); - EXPECT_TRUE(f16.value().isNan()); - - HF16(0x7C01).castTo(f, round); - EXPECT_TRUE(f.value().isNan()); - HF16(0x7C11).castTo(f, round); - EXPECT_TRUE(f.value().isNan()); - HF16(0xFC01).castTo(f, round); - EXPECT_TRUE(f.value().isNan()); - HF16(0x7C10).castTo(f, round); - EXPECT_TRUE(f.value().isNan()); - HF16(0xFF00).castTo(f, round); - EXPECT_TRUE(f.value().isNan()); - } -} - -// A test case for parsing good and bad HexFloat> literals. -template -struct FloatParseCase { - std::string literal; - bool negate_value; - bool expect_success; - HexFloat> expected_value; -}; - -using ParseNormalFloatTest = ::testing::TestWithParam>; - -TEST_P(ParseNormalFloatTest, Samples) { - std::stringstream input(GetParam().literal); - HexFloat> parsed_value(0.0f); - ParseNormalFloat(input, GetParam().negate_value, parsed_value); - EXPECT_NE(GetParam().expect_success, input.fail()) - << " literal: " << GetParam().literal - << " negate: " << GetParam().negate_value; - if (GetParam().expect_success) { - EXPECT_THAT(parsed_value.value(), Eq(GetParam().expected_value.value())) - << " literal: " << GetParam().literal - << " negate: " << GetParam().negate_value; - } -} - -// Returns a FloatParseCase with expected failure. -template -FloatParseCase BadFloatParseCase(std::string literal, bool negate_value, - T expected_value) { - HexFloat> proxy_expected_value(expected_value); - return FloatParseCase{literal, negate_value, false, proxy_expected_value}; -} - -// Returns a FloatParseCase that should successfully parse to a given value. -template -FloatParseCase GoodFloatParseCase(std::string literal, bool negate_value, - T expected_value) { - HexFloat> proxy_expected_value(expected_value); - return FloatParseCase{literal, negate_value, true, proxy_expected_value}; -} - -INSTANTIATE_TEST_CASE_P( - FloatParse, ParseNormalFloatTest, - ::testing::ValuesIn(std::vector>{ - // Failing cases due to trivially incorrect syntax. - BadFloatParseCase("abc", false, 0.0f), - BadFloatParseCase("abc", true, 0.0f), - - // Valid cases. - GoodFloatParseCase("0", false, 0.0f), - GoodFloatParseCase("0.0", false, 0.0f), - GoodFloatParseCase("-0.0", false, -0.0f), - GoodFloatParseCase("2.0", false, 2.0f), - GoodFloatParseCase("-2.0", false, -2.0f), - GoodFloatParseCase("+2.0", false, 2.0f), - // Cases with negate_value being true. - GoodFloatParseCase("0.0", true, -0.0f), - GoodFloatParseCase("2.0", true, -2.0f), - - // When negate_value is true, we should not accept a - // leading minus or plus. - BadFloatParseCase("-0.0", true, 0.0f), - BadFloatParseCase("-2.0", true, 0.0f), - BadFloatParseCase("+0.0", true, 0.0f), - BadFloatParseCase("+2.0", true, 0.0f), - - // Overflow is an error for 32-bit float parsing. - BadFloatParseCase("1e40", false, FLT_MAX), - BadFloatParseCase("1e40", true, -FLT_MAX), - BadFloatParseCase("-1e40", false, -FLT_MAX), - // We can't have -1e40 and negate_value == true since - // that represents an original case of "--1e40" which - // is invalid. - }),); - -using ParseNormalFloat16Test = - ::testing::TestWithParam>; - -TEST_P(ParseNormalFloat16Test, Samples) { - std::stringstream input(GetParam().literal); - HexFloat> parsed_value(0); - ParseNormalFloat(input, GetParam().negate_value, parsed_value); - EXPECT_NE(GetParam().expect_success, input.fail()) - << " literal: " << GetParam().literal - << " negate: " << GetParam().negate_value; - if (GetParam().expect_success) { - EXPECT_THAT(parsed_value.value(), Eq(GetParam().expected_value.value())) - << " literal: " << GetParam().literal - << " negate: " << GetParam().negate_value; - } -} - -INSTANTIATE_TEST_CASE_P( - Float16Parse, ParseNormalFloat16Test, - ::testing::ValuesIn(std::vector>{ - // Failing cases due to trivially incorrect syntax. - BadFloatParseCase("abc", false, uint16_t{0}), - BadFloatParseCase("abc", true, uint16_t{0}), - - // Valid cases. - GoodFloatParseCase("0", false, uint16_t{0}), - GoodFloatParseCase("0.0", false, uint16_t{0}), - GoodFloatParseCase("-0.0", false, uint16_t{0x8000}), - GoodFloatParseCase("2.0", false, uint16_t{0x4000}), - GoodFloatParseCase("-2.0", false, uint16_t{0xc000}), - GoodFloatParseCase("+2.0", false, uint16_t{0x4000}), - // Cases with negate_value being true. - GoodFloatParseCase("0.0", true, uint16_t{0x8000}), - GoodFloatParseCase("2.0", true, uint16_t{0xc000}), - - // When negate_value is true, we should not accept a leading minus or - // plus. - BadFloatParseCase("-0.0", true, uint16_t{0}), - BadFloatParseCase("-2.0", true, uint16_t{0}), - BadFloatParseCase("+0.0", true, uint16_t{0}), - BadFloatParseCase("+2.0", true, uint16_t{0}), - }),); - -// A test case for detecting infinities. -template -struct OverflowParseCase { - std::string input; - bool expect_success; - T expected_value; -}; - -using FloatProxyParseOverflowFloatTest = - ::testing::TestWithParam>; - -TEST_P(FloatProxyParseOverflowFloatTest, Sample) { - std::istringstream input(GetParam().input); - HexFloat> value(0.0f); - input >> value; - EXPECT_NE(GetParam().expect_success, input.fail()); - if (GetParam().expect_success) { - EXPECT_THAT(value.value().getAsFloat(), GetParam().expected_value); - } -} - -INSTANTIATE_TEST_CASE_P( - FloatOverflow, FloatProxyParseOverflowFloatTest, - ::testing::ValuesIn(std::vector>({ - {"0", true, 0.0f}, - {"0.0", true, 0.0f}, - {"1.0", true, 1.0f}, - {"1e38", true, 1e38f}, - {"-1e38", true, -1e38f}, - {"1e40", false, FLT_MAX}, - {"-1e40", false, -FLT_MAX}, - {"1e400", false, FLT_MAX}, - {"-1e400", false, -FLT_MAX}, - })),); - -using FloatProxyParseOverflowDoubleTest = - ::testing::TestWithParam>; - -TEST_P(FloatProxyParseOverflowDoubleTest, Sample) { - std::istringstream input(GetParam().input); - HexFloat> value(0.0); - input >> value; - EXPECT_NE(GetParam().expect_success, input.fail()); - if (GetParam().expect_success) { - EXPECT_THAT(value.value().getAsFloat(), Eq(GetParam().expected_value)); - } -} - -INSTANTIATE_TEST_CASE_P( - DoubleOverflow, FloatProxyParseOverflowDoubleTest, - ::testing::ValuesIn(std::vector>({ - {"0", true, 0.0}, - {"0.0", true, 0.0}, - {"1.0", true, 1.0}, - {"1e38", true, 1e38}, - {"-1e38", true, -1e38}, - {"1e40", true, 1e40}, - {"-1e40", true, -1e40}, - {"1e400", false, DBL_MAX}, - {"-1e400", false, -DBL_MAX}, - })),); - -using FloatProxyParseOverflowFloat16Test = - ::testing::TestWithParam>; - -TEST_P(FloatProxyParseOverflowFloat16Test, Sample) { - std::istringstream input(GetParam().input); - HexFloat> value(0); - input >> value; - EXPECT_NE(GetParam().expect_success, input.fail()) << " literal: " - << GetParam().input; - if (GetParam().expect_success) { - EXPECT_THAT(value.value().data(), Eq(GetParam().expected_value)) - << " literal: " << GetParam().input; - } -} - -INSTANTIATE_TEST_CASE_P( - Float16Overflow, FloatProxyParseOverflowFloat16Test, - ::testing::ValuesIn(std::vector>({ - {"0", true, uint16_t{0}}, - {"0.0", true, uint16_t{0}}, - {"1.0", true, uint16_t{0x3c00}}, - // Overflow for 16-bit float is an error, and returns max or - // lowest value. - {"1e38", false, uint16_t{0x7bff}}, - {"1e40", false, uint16_t{0x7bff}}, - {"1e400", false, uint16_t{0x7bff}}, - {"-1e38", false, uint16_t{0xfbff}}, - {"-1e40", false, uint16_t{0xfbff}}, - {"-1e400", false, uint16_t{0xfbff}}, - })),); - -TEST(FloatProxy, Max) { - EXPECT_THAT(FloatProxy::max().getAsFloat().get_value(), - Eq(uint16_t{0x7bff})); - EXPECT_THAT(FloatProxy::max().getAsFloat(), - Eq(std::numeric_limits::max())); - EXPECT_THAT(FloatProxy::max().getAsFloat(), - Eq(std::numeric_limits::max())); -} - -TEST(FloatProxy, Lowest) { - EXPECT_THAT(FloatProxy::lowest().getAsFloat().get_value(), - Eq(uint16_t{0xfbff})); - EXPECT_THAT(FloatProxy::lowest().getAsFloat(), - Eq(std::numeric_limits::lowest())); - EXPECT_THAT(FloatProxy::lowest().getAsFloat(), - Eq(std::numeric_limits::lowest())); -} - -// TODO(awoloszyn): Add fp16 tests and HexFloatTraits. -} // anonymous namespace diff --git a/External/glslang/gtests/Hlsl.FromFile.cpp b/External/glslang/gtests/Hlsl.FromFile.cpp deleted file mode 100644 index 79e9592c..00000000 --- a/External/glslang/gtests/Hlsl.FromFile.cpp +++ /dev/null @@ -1,433 +0,0 @@ -// -// Copyright (C) 2016 Google, Inc. -// 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 Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -#include - -#include "TestFixture.h" - -namespace glslangtest { -namespace { - -struct FileNameEntryPointPair { - const char* fileName; - const char* entryPoint; -}; - -// We are using FileNameEntryPointPair objects as parameters for instantiating -// the template, so the global FileNameAsCustomTestSuffix() won't work since -// it assumes std::string as parameters. Thus, an overriding one here. -std::string FileNameAsCustomTestSuffix( - const ::testing::TestParamInfo& info) { - std::string name = info.param.fileName; - // A valid test case suffix cannot have '.' and '-' inside. - std::replace(name.begin(), name.end(), '.', '_'); - std::replace(name.begin(), name.end(), '-', '_'); - return name; -} - -using HlslCompileTest = GlslangTest<::testing::TestWithParam>; -using HlslVulkan1_1CompileTest = GlslangTest<::testing::TestWithParam>; -using HlslCompileAndFlattenTest = GlslangTest<::testing::TestWithParam>; -using HlslLegalizeTest = GlslangTest<::testing::TestWithParam>; - -// Compiling HLSL to pre-legalized SPIR-V under Vulkan semantics. Expected -// to successfully generate both AST and SPIR-V. -TEST_P(HlslCompileTest, FromFile) -{ - loadFileCompileAndCheck(GlobalTestSettings.testRoot, GetParam().fileName, - Source::HLSL, Semantics::Vulkan, glslang::EShTargetVulkan_1_0, - Target::BothASTAndSpv, true, GetParam().entryPoint); -} - -TEST_P(HlslVulkan1_1CompileTest, FromFile) -{ - loadFileCompileAndCheck(GlobalTestSettings.testRoot, GetParam().fileName, - Source::HLSL, Semantics::Vulkan, glslang::EShTargetVulkan_1_1, - Target::BothASTAndSpv, true, GetParam().entryPoint); -} - -TEST_P(HlslCompileAndFlattenTest, FromFile) -{ - loadFileCompileFlattenUniformsAndCheck(GlobalTestSettings.testRoot, GetParam().fileName, - Source::HLSL, Semantics::Vulkan, - Target::BothASTAndSpv, GetParam().entryPoint); -} - -// Compiling HLSL to legal SPIR-V under Vulkan semantics. Expected to -// successfully generate SPIR-V. -TEST_P(HlslLegalizeTest, FromFile) -{ - loadFileCompileAndCheck(GlobalTestSettings.testRoot, GetParam().fileName, - Source::HLSL, Semantics::Vulkan, glslang::EShTargetVulkan_1_0, - Target::Spv, true, GetParam().entryPoint, - "/baseLegalResults/", true); -} - -// clang-format off -INSTANTIATE_TEST_CASE_P( - ToSpirv, HlslCompileTest, - ::testing::ValuesIn(std::vector{ - {"hlsl.amend.frag", "f1"}, - {"hlsl.aliasOpaque.frag", "main"}, - {"hlsl.array.frag", "PixelShaderFunction"}, - {"hlsl.array.implicit-size.frag", "PixelShaderFunction"}, - {"hlsl.array.multidim.frag", "main"}, - {"hlsl.assoc.frag", "PixelShaderFunction"}, - {"hlsl.attribute.frag", "PixelShaderFunction"}, - {"hlsl.attribute.expression.comp", "main"}, - {"hlsl.attributeC11.frag", "main"}, - {"hlsl.attributeGlobalBuffer.frag", "main"}, - {"hlsl.basic.comp", "main"}, - {"hlsl.basic.geom", "main"}, - {"hlsl.boolConv.vert", "main"}, - {"hlsl.buffer.frag", "PixelShaderFunction"}, - {"hlsl.calculatelod.dx10.frag", "main"}, - {"hlsl.calculatelodunclamped.dx10.frag", "main"}, - {"hlsl.cast.frag", "PixelShaderFunction"}, - {"hlsl.cbuffer-identifier.vert", "main"}, - {"hlsl.charLit.vert", "main"}, - {"hlsl.clip.frag", "main"}, - {"hlsl.clipdistance-1.frag", "main"}, - {"hlsl.clipdistance-1.geom", "main"}, - {"hlsl.clipdistance-1.vert", "main"}, - {"hlsl.clipdistance-2.frag", "main"}, - {"hlsl.clipdistance-2.geom", "main"}, - {"hlsl.clipdistance-2.vert", "main"}, - {"hlsl.clipdistance-3.frag", "main"}, - {"hlsl.clipdistance-3.geom", "main"}, - {"hlsl.clipdistance-3.vert", "main"}, - {"hlsl.clipdistance-4.frag", "main"}, - {"hlsl.clipdistance-4.geom", "main"}, - {"hlsl.clipdistance-4.vert", "main"}, - {"hlsl.clipdistance-5.frag", "main"}, - {"hlsl.clipdistance-5.vert", "main"}, - {"hlsl.clipdistance-6.frag", "main"}, - {"hlsl.clipdistance-6.vert", "main"}, - {"hlsl.clipdistance-7.frag", "main"}, - {"hlsl.clipdistance-7.vert", "main"}, - {"hlsl.clipdistance-8.frag", "main"}, - {"hlsl.clipdistance-8.vert", "main"}, - {"hlsl.clipdistance-9.frag", "main"}, - {"hlsl.clipdistance-9.vert", "main"}, - {"hlsl.color.hull.tesc", "main"}, - {"hlsl.comparison.vec.frag", "main"}, - {"hlsl.conditional.frag", "PixelShaderFunction"}, - {"hlsl.constantbuffer.frag", "main"}, - {"hlsl.constructArray.vert", "main"}, - {"hlsl.constructexpr.frag", "main"}, - {"hlsl.constructimat.frag", "main"}, - {"hlsl.depthGreater.frag", "PixelShaderFunction"}, - {"hlsl.depthLess.frag", "PixelShaderFunction"}, - {"hlsl.discard.frag", "PixelShaderFunction"}, - {"hlsl.doLoop.frag", "PixelShaderFunction"}, - {"hlsl.emptystructreturn.frag", "main"}, - {"hlsl.emptystructreturn.vert", "main"}, - {"hlsl.emptystruct.init.vert", "main"}, - {"hlsl.entry-in.frag", "PixelShaderFunction"}, - {"hlsl.entry-out.frag", "PixelShaderFunction"}, - {"hlsl.fraggeom.frag", "main"}, - {"hlsl.float1.frag", "PixelShaderFunction"}, - {"hlsl.float4.frag", "PixelShaderFunction"}, - {"hlsl.flatten.return.frag", "main"}, - {"hlsl.flattenOpaque.frag", "main"}, - {"hlsl.flattenOpaqueInit.vert", "main"}, - {"hlsl.flattenOpaqueInitMix.vert", "main"}, - {"hlsl.flattenSubset.frag", "main"}, - {"hlsl.flattenSubset2.frag", "main"}, - {"hlsl.forLoop.frag", "PixelShaderFunction"}, - {"hlsl.gather.array.dx10.frag", "main"}, - {"hlsl.gather.basic.dx10.frag", "main"}, - {"hlsl.gather.basic.dx10.vert", "main"}, - {"hlsl.gather.offset.dx10.frag", "main"}, - {"hlsl.gather.offsetarray.dx10.frag", "main"}, - {"hlsl.gathercmpRGBA.offset.dx10.frag", "main"}, - {"hlsl.gatherRGBA.array.dx10.frag", "main"}, - {"hlsl.gatherRGBA.basic.dx10.frag", "main"}, - {"hlsl.gatherRGBA.offset.dx10.frag", "main"}, - {"hlsl.gatherRGBA.offsetarray.dx10.frag", "main"}, - {"hlsl.getdimensions.dx10.frag", "main"}, - {"hlsl.getdimensions.rw.dx10.frag", "main"}, - {"hlsl.getdimensions.dx10.vert", "main"}, - {"hlsl.getsampleposition.dx10.frag", "main"}, - {"hlsl.global-const-init.frag", "main"}, - {"hlsl.gs-hs-mix.tesc", "HSMain"}, - {"hlsl.domain.1.tese", "main"}, - {"hlsl.domain.2.tese", "main"}, - {"hlsl.domain.3.tese", "main"}, - {"hlsl.function.frag", "main"}, - {"hlsl.hull.1.tesc", "main"}, - {"hlsl.hull.2.tesc", "main"}, - {"hlsl.hull.3.tesc", "main"}, - {"hlsl.hull.4.tesc", "main"}, - {"hlsl.hull.5.tesc", "main"}, - {"hlsl.hull.void.tesc", "main"}, - {"hlsl.hull.ctrlpt-1.tesc", "main"}, - {"hlsl.hull.ctrlpt-2.tesc", "main"}, - {"hlsl.identifier.sample.frag", "main"}, - {"hlsl.if.frag", "PixelShaderFunction"}, - {"hlsl.imagefetch-subvec4.comp", "main"}, - {"hlsl.implicitBool.frag", "main"}, - {"hlsl.inf.vert", "main"}, - {"hlsl.inoutquals.frag", "main"}, - {"hlsl.init.frag", "ShaderFunction"}, - {"hlsl.init2.frag", "main"}, - {"hlsl.isfinite.frag", "main"}, - {"hlsl.intrinsics.barriers.comp", "ComputeShaderFunction"}, - {"hlsl.intrinsics.comp", "ComputeShaderFunction"}, - {"hlsl.intrinsics.evalfns.frag", "main"}, - {"hlsl.intrinsics.d3dcolortoubyte4.frag", "main"}, - {"hlsl.intrinsics.double.frag", "PixelShaderFunction"}, - {"hlsl.intrinsics.f1632.frag", "main"}, - {"hlsl.intrinsics.f3216.frag", "main"}, - {"hlsl.intrinsics.frag", "main"}, - {"hlsl.intrinsic.frexp.frag", "main"}, - {"hlsl.intrinsics.lit.frag", "PixelShaderFunction"}, - {"hlsl.intrinsics.negative.comp", "ComputeShaderFunction"}, - {"hlsl.intrinsics.negative.frag", "PixelShaderFunction"}, - {"hlsl.intrinsics.negative.vert", "VertexShaderFunction"}, - {"hlsl.intrinsics.promote.frag", "main"}, - {"hlsl.intrinsics.promote.down.frag", "main"}, - {"hlsl.intrinsics.promote.outputs.frag", "main"}, - {"hlsl.layout.frag", "main"}, - {"hlsl.layoutOverride.vert", "main"}, - {"hlsl.load.2dms.dx10.frag", "main"}, - {"hlsl.load.array.dx10.frag", "main"}, - {"hlsl.load.basic.dx10.frag", "main"}, - {"hlsl.load.basic.dx10.vert", "main"}, - {"hlsl.load.buffer.dx10.frag", "main"}, - {"hlsl.load.buffer.float.dx10.frag", "main"}, - {"hlsl.load.rwbuffer.dx10.frag", "main"}, - {"hlsl.load.rwtexture.dx10.frag", "main"}, - {"hlsl.load.rwtexture.array.dx10.frag", "main"}, - {"hlsl.load.offset.dx10.frag", "main"}, - {"hlsl.load.offsetarray.dx10.frag", "main"}, - {"hlsl.localStructuredBuffer.comp", "main"}, - {"hlsl.logical.binary.frag", "main"}, - {"hlsl.logical.binary.vec.frag", "main"}, - {"hlsl.logicalConvert.frag", "main"}, - {"hlsl.logical.unary.frag", "main"}, - {"hlsl.loopattr.frag", "main"}, - {"hlsl.matpack-pragma.frag", "main"}, - {"hlsl.mip.operator.frag", "main"}, - {"hlsl.mip.negative.frag", "main"}, - {"hlsl.mip.negative2.frag", "main"}, - {"hlsl.namespace.frag", "main"}, - {"hlsl.nonint-index.frag", "main"}, - {"hlsl.matNx1.frag", "main"}, - {"hlsl.matpack-1.frag", "main"}, - {"hlsl.matrixSwizzle.vert", "ShaderFunction"}, - {"hlsl.memberFunCall.frag", "main"}, - {"hlsl.mintypes.frag", "main"}, - {"hlsl.mul-truncate.frag", "main"}, - {"hlsl.multiEntry.vert", "RealEntrypoint"}, - {"hlsl.multiReturn.frag", "main"}, - {"hlsl.matrixindex.frag", "main"}, - {"hlsl.nonstaticMemberFunction.frag", "main"}, - {"hlsl.numericsuffixes.frag", "main"}, - {"hlsl.numthreads.comp", "main_aux2"}, - {"hlsl.overload.frag", "PixelShaderFunction"}, - {"hlsl.opaque-type-bug.frag", "main"}, - {"hlsl.params.default.frag", "main"}, - {"hlsl.params.default.negative.frag", "main"}, - {"hlsl.partialInit.frag", "PixelShaderFunction"}, - {"hlsl.partialFlattenLocal.vert", "main"}, - {"hlsl.PointSize.geom", "main"}, - {"hlsl.PointSize.vert", "main"}, - {"hlsl.pp.vert", "main"}, - {"hlsl.pp.line.frag", "main"}, - {"hlsl.precise.frag", "main"}, - {"hlsl.promote.atomic.frag", "main"}, - {"hlsl.promote.binary.frag", "main"}, - {"hlsl.promote.vec1.frag", "main"}, - {"hlsl.promotions.frag", "main"}, - {"hlsl.rw.atomics.frag", "main"}, - {"hlsl.rw.bracket.frag", "main"}, - {"hlsl.rw.register.frag", "main"}, - {"hlsl.rw.scalar.bracket.frag", "main"}, - {"hlsl.rw.swizzle.frag", "main"}, - {"hlsl.rw.vec2.bracket.frag", "main"}, - {"hlsl.sample.array.dx10.frag", "main"}, - {"hlsl.sample.basic.dx10.frag", "main"}, - {"hlsl.sample.offset.dx10.frag", "main"}, - {"hlsl.sample.offsetarray.dx10.frag", "main"}, - {"hlsl.samplebias.array.dx10.frag", "main"}, - {"hlsl.samplebias.basic.dx10.frag", "main"}, - {"hlsl.samplebias.offset.dx10.frag", "main"}, - {"hlsl.samplebias.offsetarray.dx10.frag", "main"}, - {"hlsl.samplecmp.array.dx10.frag", "main"}, - {"hlsl.samplecmp.basic.dx10.frag", "main"}, - {"hlsl.samplecmp.dualmode.frag", "main"}, - {"hlsl.samplecmp.offset.dx10.frag", "main"}, - {"hlsl.samplecmp.offsetarray.dx10.frag", "main"}, - {"hlsl.samplecmp.negative.frag", "main"}, - {"hlsl.samplecmp.negative2.frag", "main"}, - {"hlsl.samplecmplevelzero.array.dx10.frag", "main"}, - {"hlsl.samplecmplevelzero.basic.dx10.frag", "main"}, - {"hlsl.samplecmplevelzero.offset.dx10.frag", "main"}, - {"hlsl.samplecmplevelzero.offsetarray.dx10.frag", "main"}, - {"hlsl.samplegrad.array.dx10.frag", "main"}, - {"hlsl.samplegrad.basic.dx10.frag", "main"}, - {"hlsl.samplegrad.basic.dx10.vert", "main"}, - {"hlsl.samplegrad.offset.dx10.frag", "main"}, - {"hlsl.samplegrad.offsetarray.dx10.frag", "main"}, - {"hlsl.samplelevel.array.dx10.frag", "main"}, - {"hlsl.samplelevel.basic.dx10.frag", "main"}, - {"hlsl.samplelevel.basic.dx10.vert", "main"}, - {"hlsl.samplelevel.offset.dx10.frag", "main"}, - {"hlsl.samplelevel.offsetarray.dx10.frag", "main"}, - {"hlsl.sample.sub-vec4.dx10.frag", "main"}, - {"hlsl.scalar-length.frag", "main"}, - {"hlsl.scalarCast.vert", "main"}, - {"hlsl.semicolons.frag", "main"}, - {"hlsl.shapeConv.frag", "main"}, - {"hlsl.shapeConvRet.frag", "main"}, - {"hlsl.snorm.uav.comp", "main"}, - {"hlsl.staticMemberFunction.frag", "main"}, - {"hlsl.store.rwbyteaddressbuffer.type.comp", "main"}, - {"hlsl.stringtoken.frag", "main"}, - {"hlsl.string.frag", "main"}, - {"hlsl.struct.split-1.vert", "main"}, - {"hlsl.struct.split.array.geom", "main"}, - {"hlsl.struct.split.assign.frag", "main"}, - {"hlsl.struct.split.call.vert", "main"}, - {"hlsl.struct.split.nested.geom", "main"}, - {"hlsl.struct.split.trivial.geom", "main"}, - {"hlsl.struct.split.trivial.vert", "main"}, - {"hlsl.structarray.flatten.frag", "main"}, - {"hlsl.structarray.flatten.geom", "main"}, - {"hlsl.structbuffer.frag", "main"}, - {"hlsl.structbuffer.append.frag", "main"}, - {"hlsl.structbuffer.append.fn.frag", "main"}, - {"hlsl.structbuffer.atomics.frag", "main"}, - {"hlsl.structbuffer.byte.frag", "main"}, - {"hlsl.structbuffer.coherent.frag", "main"}, - {"hlsl.structbuffer.floatidx.comp", "main"}, - {"hlsl.structbuffer.incdec.frag", "main"}, - {"hlsl.structbuffer.fn.frag", "main"}, - {"hlsl.structbuffer.fn2.comp", "main"}, - {"hlsl.structbuffer.rw.frag", "main"}, - {"hlsl.structbuffer.rwbyte.frag", "main"}, - {"hlsl.structin.vert", "main"}, - {"hlsl.structIoFourWay.frag", "main"}, - {"hlsl.structStructName.frag", "main"}, - {"hlsl.subpass.frag", "main"}, - {"hlsl.synthesizeInput.frag", "main"}, - {"hlsl.texturebuffer.frag", "main"}, - {"hlsl.texture.struct.frag", "main"}, - {"hlsl.texture.subvec4.frag", "main"}, - {"hlsl.this.frag", "main"}, - {"hlsl.intrinsics.vert", "VertexShaderFunction"}, - {"hlsl.intrinsic.frexp.vert", "VertexShaderFunction"}, - {"hlsl.matType.frag", "PixelShaderFunction"}, - {"hlsl.matType.bool.frag", "main"}, - {"hlsl.matType.int.frag", "main"}, - {"hlsl.max.frag", "PixelShaderFunction"}, - {"hlsl.preprocessor.frag", "main"}, - {"hlsl.precedence.frag", "PixelShaderFunction"}, - {"hlsl.precedence2.frag", "PixelShaderFunction"}, - {"hlsl.scalar2matrix.frag", "main"}, - {"hlsl.semantic.geom", "main"}, - {"hlsl.semantic.vert", "main"}, - {"hlsl.semantic-1.vert", "main"}, - {"hlsl.scope.frag", "PixelShaderFunction"}, - {"hlsl.sin.frag", "PixelShaderFunction"}, - {"hlsl.struct.frag", "PixelShaderFunction"}, - {"hlsl.switch.frag", "PixelShaderFunction"}, - {"hlsl.swizzle.frag", "PixelShaderFunction"}, - {"hlsl.target.frag", "main"}, - {"hlsl.targetStruct1.frag", "main"}, - {"hlsl.targetStruct2.frag", "main"}, - {"hlsl.templatetypes.frag", "PixelShaderFunction"}, - {"hlsl.tx.bracket.frag", "main"}, - {"hlsl.tx.overload.frag", "main"}, - {"hlsl.type.half.frag", "main"}, - {"hlsl.type.identifier.frag", "main"}, - {"hlsl.typeGraphCopy.vert", "main"}, - {"hlsl.typedef.frag", "PixelShaderFunction"}, - {"hlsl.whileLoop.frag", "PixelShaderFunction"}, - {"hlsl.void.frag", "PixelShaderFunction"} - }), - FileNameAsCustomTestSuffix -); -// clang-format on - -// clang-format off -INSTANTIATE_TEST_CASE_P( - ToSpirv, HlslVulkan1_1CompileTest, - ::testing::ValuesIn(std::vector{ - {"hlsl.wavebroadcast.comp", "CSMain"}, - {"hlsl.waveprefix.comp", "CSMain"}, - {"hlsl.wavequad.comp", "CSMain"}, - {"hlsl.wavequery.comp", "CSMain"}, - {"hlsl.wavequery.frag", "PixelShaderFunction"}, - {"hlsl.wavereduction.comp", "CSMain"}, - {"hlsl.wavevote.comp", "CSMain"}, - }), - FileNameAsCustomTestSuffix -); -// clang-format on - -// clang-format off -INSTANTIATE_TEST_CASE_P( - ToSpirv, HlslCompileAndFlattenTest, - ::testing::ValuesIn(std::vector{ - {"hlsl.array.flatten.frag", "main"}, - {"hlsl.partialFlattenMixed.vert", "main"}, - }), - FileNameAsCustomTestSuffix -); -// clang-format on - -#if ENABLE_OPT -// clang-format off -INSTANTIATE_TEST_CASE_P( - ToSpirv, HlslLegalizeTest, - ::testing::ValuesIn(std::vector{ - {"hlsl.aliasOpaque.frag", "main"}, - {"hlsl.flattenOpaque.frag", "main"}, - {"hlsl.flattenOpaqueInit.vert", "main"}, - {"hlsl.flattenOpaqueInitMix.vert", "main"}, - {"hlsl.flattenSubset.frag", "main"}, - {"hlsl.flattenSubset2.frag", "main"}, - {"hlsl.partialFlattenLocal.vert", "main"}, - {"hlsl.partialFlattenMixed.vert", "main"} - }), - FileNameAsCustomTestSuffix -); -// clang-format on -#endif - -} // anonymous namespace -} // namespace glslangtest diff --git a/External/glslang/gtests/Initializer.h b/External/glslang/gtests/Initializer.h deleted file mode 100644 index b46b3f55..00000000 --- a/External/glslang/gtests/Initializer.h +++ /dev/null @@ -1,55 +0,0 @@ -// -// Copyright (C) 2016 Google, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -#ifndef GLSLANG_GTESTS_INITIALIZER_H -#define GLSLANG_GTESTS_INITIALIZER_H - -#include "glslang/Public/ShaderLang.h" - -namespace glslangtest { - -// Initializes glslang on creation, and destroys it on completion. -// This object is expected to be a singleton, so that internal glslang state -// can be correctly handled. -// -class GlslangInitializer { -public: - GlslangInitializer() { glslang::InitializeProcess(); } - - ~GlslangInitializer() { glslang::FinalizeProcess(); } -}; - -} // namespace glslangtest - -#endif // GLSLANG_GTESTS_INITIALIZER_H diff --git a/External/glslang/gtests/Link.FromFile.Vk.cpp b/External/glslang/gtests/Link.FromFile.Vk.cpp deleted file mode 100644 index 0a616d82..00000000 --- a/External/glslang/gtests/Link.FromFile.Vk.cpp +++ /dev/null @@ -1,114 +0,0 @@ -// -// Copyright (C) 2016-2017 Google, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -#include - -#include - -#include "TestFixture.h" - -namespace glslangtest { -namespace { - -using LinkTestVulkan = GlslangTest< - ::testing::TestWithParam>>; - -TEST_P(LinkTestVulkan, FromFile) -{ - const auto& fileNames = GetParam(); - const size_t fileCount = fileNames.size(); - const EShMessages controls = DeriveOptions(Source::GLSL, Semantics::Vulkan, Target::AST); - GlslangResult result; - - // Compile each input shader file. - bool success = true; - std::vector> shaders; - for (size_t i = 0; i < fileCount; ++i) { - std::string contents; - tryLoadFile(GlobalTestSettings.testRoot + "/" + fileNames[i], - "input", &contents); - shaders.emplace_back( - new glslang::TShader(GetShaderStage(GetSuffix(fileNames[i])))); - auto* shader = shaders.back().get(); - shader->setAutoMapLocations(true); - success &= compile(shader, contents, "", controls); - result.shaderResults.push_back( - {fileNames[i], shader->getInfoLog(), shader->getInfoDebugLog()}); - } - - // Link all of them. - glslang::TProgram program; - for (const auto& shader : shaders) program.addShader(shader.get()); - success &= program.link(controls); - result.linkingOutput = program.getInfoLog(); - result.linkingError = program.getInfoDebugLog(); - - if (success && (controls & EShMsgSpvRules)) { - spv::SpvBuildLogger logger; - std::vector spirv_binary; - glslang::SpvOptions options; - options.disableOptimizer = true; - glslang::GlslangToSpv(*program.getIntermediate(shaders.front()->getStage()), - spirv_binary, &logger, &options); - - std::ostringstream disassembly_stream; - spv::Parameterize(); - spv::Disassemble(disassembly_stream, spirv_binary); - result.spirvWarningsErrors = logger.getAllMessages(); - result.spirv = disassembly_stream.str(); - } - - std::ostringstream stream; - outputResultToStream(&stream, result, controls); - - // Check with expected results. - const std::string expectedOutputFname = - GlobalTestSettings.testRoot + "/baseResults/" + fileNames.front() + ".out"; - std::string expectedOutput; - tryLoadFile(expectedOutputFname, "expected output", &expectedOutput); - - checkEqAndUpdateIfRequested(expectedOutput, stream.str(), expectedOutputFname); -} - -// clang-format off -INSTANTIATE_TEST_CASE_P( - Glsl, LinkTestVulkan, - ::testing::ValuesIn(std::vector>({ - {"link1.vk.frag", "link2.vk.frag"}, - })), -); -// clang-format on - -} // anonymous namespace -} // namespace glslangtest diff --git a/External/glslang/gtests/Link.FromFile.cpp b/External/glslang/gtests/Link.FromFile.cpp deleted file mode 100644 index ab845bf5..00000000 --- a/External/glslang/gtests/Link.FromFile.cpp +++ /dev/null @@ -1,108 +0,0 @@ -// -// Copyright (C) 2016 Google, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -#include - -#include - -#include "TestFixture.h" - -namespace glslangtest { -namespace { - -using LinkTest = GlslangTest< - ::testing::TestWithParam>>; - -TEST_P(LinkTest, FromFile) -{ - const auto& fileNames = GetParam(); - const size_t fileCount = fileNames.size(); - const EShMessages controls = DeriveOptions(Source::GLSL, Semantics::OpenGL, Target::AST); - GlslangResult result; - - // Compile each input shader file. - std::vector> shaders; - for (size_t i = 0; i < fileCount; ++i) { - std::string contents; - tryLoadFile(GlobalTestSettings.testRoot + "/" + fileNames[i], - "input", &contents); - shaders.emplace_back( - new glslang::TShader(GetShaderStage(GetSuffix(fileNames[i])))); - auto* shader = shaders.back().get(); - compile(shader, contents, "", controls); - result.shaderResults.push_back( - {fileNames[i], shader->getInfoLog(), shader->getInfoDebugLog()}); - } - - // Link all of them. - glslang::TProgram program; - for (const auto& shader : shaders) program.addShader(shader.get()); - program.link(controls); - result.linkingOutput = program.getInfoLog(); - result.linkingError = program.getInfoDebugLog(); - - std::ostringstream stream; - outputResultToStream(&stream, result, controls); - - // Check with expected results. - const std::string expectedOutputFname = - GlobalTestSettings.testRoot + "/baseResults/" + fileNames.front() + ".out"; - std::string expectedOutput; - tryLoadFile(expectedOutputFname, "expected output", &expectedOutput); - - checkEqAndUpdateIfRequested(expectedOutput, stream.str(), expectedOutputFname); -} - -// clang-format off -INSTANTIATE_TEST_CASE_P( - Glsl, LinkTest, - ::testing::ValuesIn(std::vector>({ - {"mains1.frag", "mains2.frag", "noMain1.geom", "noMain2.geom"}, - {"noMain.vert", "mains.frag"}, - {"link1.frag", "link2.frag", "link3.frag"}, - {"recurse1.vert", "recurse1.frag", "recurse2.frag"}, - {"300link.frag"}, - {"300link2.frag"}, - {"300link3.frag"}, - {"empty.frag", "empty2.frag", "empty3.frag"}, - {"150.tesc", "150.tese", "400.tesc", "400.tese", "410.tesc", "420.tesc", "420.tese"}, - {"max_vertices_0.geom"}, - {"es-link1.frag", "es-link2.frag"}, - {"missingBodies.vert"} - })), -); -// clang-format on - -} // anonymous namespace -} // namespace glslangtest diff --git a/External/glslang/gtests/Pp.FromFile.cpp b/External/glslang/gtests/Pp.FromFile.cpp deleted file mode 100644 index 13daac0d..00000000 --- a/External/glslang/gtests/Pp.FromFile.cpp +++ /dev/null @@ -1,75 +0,0 @@ -// -// Copyright (C) 2016 Google, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -#include - -#include "TestFixture.h" - -namespace glslangtest { -namespace { - -using PreprocessingTest = GlslangTest<::testing::TestWithParam>; - -TEST_P(PreprocessingTest, FromFile) -{ - loadFilePreprocessAndCheck(GlobalTestSettings.testRoot, GetParam()); -} - -// clang-format off -INSTANTIATE_TEST_CASE_P( - Glsl, PreprocessingTest, - ::testing::ValuesIn(std::vector({ - "preprocessor.cpp_style_line_directive.vert", - "preprocessor.cpp_style___FILE__.vert", - "preprocessor.edge_cases.vert", - "preprocessor.errors.vert", - "preprocessor.extensions.vert", - "preprocessor.function_macro.vert", - "preprocessor.include.enabled.vert", - "preprocessor.include.disabled.vert", - "preprocessor.line.vert", - "preprocessor.line.frag", - "preprocessor.pragma.vert", - "preprocessor.simple.vert", - "preprocessor.success_if_parse_would_fail.vert", - "preprocessor.defined.vert", - "preprocessor.many.endif.vert", - "preprocessor.eof_missing.vert", - })), - FileNameAsCustomTestSuffix -); -// clang-format on - -} // anonymous namespace -} // namespace glslangtest diff --git a/External/glslang/gtests/README.md b/External/glslang/gtests/README.md deleted file mode 100644 index c8261cc4..00000000 --- a/External/glslang/gtests/README.md +++ /dev/null @@ -1,26 +0,0 @@ -Glslang Tests based on the Google Test Framework -================================================ - -This directory contains [Google Test][gtest] based test fixture and test -cases for glslang. - -Apart from typical unit tests, necessary utility methods are added into -the [`GlslangTests`](TestFixture.h) fixture to provide the ability to do -file-based integration tests. Various `*.FromFile.cpp` files lists names -of files containing input shader code in the `Test/` directory. Utility -methods will load the input shader source, compile them, and compare with -the corresponding expected output in the `Test/baseResults/` directory. - -How to run the tests --------------------- - -Please make sure you have a copy of [Google Test][gtest] checked out under -the `External` directory before building. After building, just run the -`ctest` command or the `gtests/glslangtests` binary in your build directory. - -The `gtests/glslangtests` binary also provides an `--update-mode` command -line option, which, if supplied, will overwrite the golden files under -the `Test/baseResults/` directory with real output from that invocation. -This serves as an easy way to update golden files. - -[gtest]: https://github.com/google/googletest diff --git a/External/glslang/gtests/Remap.FromFile.cpp b/External/glslang/gtests/Remap.FromFile.cpp deleted file mode 100644 index 50bce8e3..00000000 --- a/External/glslang/gtests/Remap.FromFile.cpp +++ /dev/null @@ -1,118 +0,0 @@ -// -// 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 Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -#include - -#include "TestFixture.h" - -namespace glslangtest { -namespace { - -struct RemapTestArgs { - const char* fileName; - const char* entryPoint; - Source sourceLanguage; - unsigned int remapOpts; -}; - -// We are using FileNameEntryPointPair objects as parameters for instantiating -// the template, so the global FileNameAsCustomTestSuffix() won't work since -// it assumes std::string as parameters. Thus, an overriding one here. -std::string FileNameAsCustomTestSuffix( - const ::testing::TestParamInfo& info) { - std::string name = info.param.fileName; - // A valid test case suffix cannot have '.' and '-' inside. - std::replace(name.begin(), name.end(), '.', '_'); - std::replace(name.begin(), name.end(), '-', '_'); - return name; -} - -using RemapTest = GlslangTest<::testing::TestWithParam>; - -// Remapping SPIR-V modules. -TEST_P(RemapTest, FromFile) -{ - if (GetSuffix(GetParam().fileName) == "spv") { - loadFileRemapAndCheck(GlobalTestSettings.testRoot, GetParam().fileName, - GetParam().sourceLanguage, - Semantics::Vulkan, - Target::Spv, - GetParam().remapOpts); - } else { - loadFileCompileRemapAndCheck(GlobalTestSettings.testRoot, GetParam().fileName, - GetParam().sourceLanguage, - Semantics::Vulkan, - Target::Spv, - GetParam().entryPoint, - GetParam().remapOpts); - } -} - -// clang-format off -INSTANTIATE_TEST_CASE_P( - ToSpirv, RemapTest, - ::testing::ValuesIn(std::vector{ - // GLSL remapper tests - // testname entry language remapper_options - { "remap.basic.none.frag", "main", Source::GLSL, spv::spirvbin_t::NONE }, - { "remap.basic.everything.frag", "main", Source::GLSL, spv::spirvbin_t::DO_EVERYTHING }, - { "remap.basic.dcefunc.frag", "main", Source::GLSL, spv::spirvbin_t::DCE_FUNCS }, - { "remap.basic.strip.frag", "main", Source::GLSL, spv::spirvbin_t::STRIP }, - { "remap.specconst.comp", "main", Source::GLSL, spv::spirvbin_t::DO_EVERYTHING }, - { "remap.switch.none.frag", "main", Source::GLSL, spv::spirvbin_t::NONE }, - { "remap.switch.everything.frag", "main", Source::GLSL, spv::spirvbin_t::DO_EVERYTHING }, - { "remap.literal64.none.spv", "main", Source::GLSL, spv::spirvbin_t::NONE }, - { "remap.literal64.everything.spv", "main", Source::GLSL, spv::spirvbin_t::DO_EVERYTHING }, - { "remap.if.none.frag", "main", Source::GLSL, spv::spirvbin_t::NONE }, - { "remap.if.everything.frag", "main", Source::GLSL, spv::spirvbin_t::DO_EVERYTHING }, - { "remap.similar_1a.none.frag", "main", Source::GLSL, spv::spirvbin_t::NONE }, - { "remap.similar_1b.none.frag", "main", Source::GLSL, spv::spirvbin_t::NONE }, - { "remap.similar_1a.everything.frag", "main", Source::GLSL, spv::spirvbin_t::DO_EVERYTHING }, - { "remap.similar_1b.everything.frag", "main", Source::GLSL, spv::spirvbin_t::DO_EVERYTHING }, - { "remap.uniformarray.none.frag", "main", Source::GLSL, spv::spirvbin_t::NONE }, - { "remap.uniformarray.everything.frag", "main", Source::GLSL, spv::spirvbin_t::DO_EVERYTHING }, - - // HLSL remapper tests - { "remap.hlsl.sample.basic.strip.frag", "main", Source::HLSL, spv::spirvbin_t::STRIP }, - { "remap.hlsl.sample.basic.everything.frag", "main", Source::HLSL, spv::spirvbin_t::DO_EVERYTHING }, - { "remap.hlsl.sample.basic.none.frag", "main", Source::HLSL, spv::spirvbin_t::NONE }, - { "remap.hlsl.templatetypes.none.frag", "main", Source::HLSL, spv::spirvbin_t::NONE }, - { "remap.hlsl.templatetypes.everything.frag", "main", Source::HLSL, spv::spirvbin_t::DO_EVERYTHING }, - }), - FileNameAsCustomTestSuffix -); -// clang-format on - -} // anonymous namespace -} // namespace glslangtest diff --git a/External/glslang/gtests/Settings.cpp b/External/glslang/gtests/Settings.cpp deleted file mode 100644 index 0ac58449..00000000 --- a/External/glslang/gtests/Settings.cpp +++ /dev/null @@ -1,51 +0,0 @@ -// -// Copyright (C) 2016 Google, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -#include "Settings.h" - -namespace glslangtest { - -// We need CMake to provide us the absolute path to the directory containing -// test files, so we are certain to find those files no matter where the test -// harness binary is generated. This provides out-of-source build capability. -// This will be used as the default test root, but can be overridden with -// the --test-root argument. -#ifndef GLSLANG_TEST_DIRECTORY -#error \ - "GLSLANG_TEST_DIRECTORY needs to be defined for gtest to locate test files." -#endif - -GTestSettings GlobalTestSettings = {nullptr, false, GLSLANG_TEST_DIRECTORY}; - -} // namespace glslangtest diff --git a/External/glslang/gtests/Settings.h b/External/glslang/gtests/Settings.h deleted file mode 100644 index c38474cc..00000000 --- a/External/glslang/gtests/Settings.h +++ /dev/null @@ -1,58 +0,0 @@ -// -// Copyright (C) 2016 Google, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -#ifndef GLSLANG_GTESTS_SETTINGS_H -#define GLSLANG_GTESTS_SETTINGS_H - -#include - -namespace glslangtest { - -class GlslangInitializer; - -struct GTestSettings { - // A handle to GlslangInitializer instance. - GlslangInitializer* initializer; - // An indicator of whether GTest should write real output to the file for - // the expected output. - bool updateMode; - // The root directory for test files. - std::string testRoot; -}; - -extern GTestSettings GlobalTestSettings; - -} // namespace glslangtest - -#endif // GLSLANG_GTESTS_SETTINGS_H diff --git a/External/glslang/gtests/Spv.FromFile.cpp b/External/glslang/gtests/Spv.FromFile.cpp deleted file mode 100644 index 4b1ff462..00000000 --- a/External/glslang/gtests/Spv.FromFile.cpp +++ /dev/null @@ -1,505 +0,0 @@ - // -// Copyright (C) 2016 Google, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -#include - -#include - -#include "TestFixture.h" - -namespace glslangtest { -namespace { - -struct IoMapData { - const char* fileName; - const char* entryPoint; - int baseSamplerBinding; - int baseTextureBinding; - int baseImageBinding; - int baseUboBinding; - int baseSsboBinding; - bool autoMapBindings; - bool flattenUniforms; -}; - -std::string FileNameAsCustomTestSuffixIoMap( - const ::testing::TestParamInfo& info) { - std::string name = info.param.fileName; - // A valid test case suffix cannot have '.' and '-' inside. - std::replace(name.begin(), name.end(), '.', '_'); - std::replace(name.begin(), name.end(), '-', '_'); - return name; -} - -using CompileVulkanToSpirvTest = GlslangTest<::testing::TestWithParam>; -using CompileVulkan1_1ToSpirvTest = GlslangTest<::testing::TestWithParam>; -using CompileOpenGLToSpirvTest = GlslangTest<::testing::TestWithParam>; -using VulkanSemantics = GlslangTest<::testing::TestWithParam>; -using OpenGLSemantics = GlslangTest<::testing::TestWithParam>; -using VulkanAstSemantics = GlslangTest<::testing::TestWithParam>; -using HlslIoMap = GlslangTest<::testing::TestWithParam>; -using GlslIoMap = GlslangTest<::testing::TestWithParam>; -#ifdef AMD_EXTENSIONS -using CompileVulkanToSpirvTestAMD = GlslangTest<::testing::TestWithParam>; -#endif -#ifdef NV_EXTENSIONS -using CompileVulkanToSpirvTestNV = GlslangTest<::testing::TestWithParam>; -#endif -using CompileUpgradeTextureToSampledTextureAndDropSamplersTest = GlslangTest<::testing::TestWithParam>; - -// Compiling GLSL to SPIR-V under Vulkan semantics. Expected to successfully -// generate SPIR-V. -TEST_P(CompileVulkanToSpirvTest, FromFile) -{ - loadFileCompileAndCheck(GlobalTestSettings.testRoot, GetParam(), - Source::GLSL, Semantics::Vulkan, glslang::EShTargetVulkan_1_0, - Target::Spv); -} - -TEST_P(CompileVulkan1_1ToSpirvTest, FromFile) -{ - loadFileCompileAndCheck(GlobalTestSettings.testRoot, GetParam(), - Source::GLSL, Semantics::Vulkan, glslang::EShTargetVulkan_1_1, - Target::Spv); -} - -// Compiling GLSL to SPIR-V under OpenGL semantics. Expected to successfully -// generate SPIR-V. -TEST_P(CompileOpenGLToSpirvTest, FromFile) -{ - loadFileCompileAndCheck(GlobalTestSettings.testRoot, GetParam(), - Source::GLSL, Semantics::OpenGL, glslang::EShTargetVulkan_1_0, - Target::Spv); -} - -// GLSL-level Vulkan semantics test. Expected to error out before generating -// SPIR-V. -TEST_P(VulkanSemantics, FromFile) -{ - loadFileCompileAndCheck(GlobalTestSettings.testRoot, GetParam(), - Source::GLSL, Semantics::Vulkan, glslang::EShTargetVulkan_1_0, - Target::Spv, false); -} - -// GLSL-level Vulkan semantics test. Expected to error out before generating -// SPIR-V. -TEST_P(OpenGLSemantics, FromFile) -{ - loadFileCompileAndCheck(GlobalTestSettings.testRoot, GetParam(), - Source::GLSL, Semantics::OpenGL, glslang::EShTargetVulkan_1_0, - Target::Spv, false); -} - -// GLSL-level Vulkan semantics test that need to see the AST for validation. -TEST_P(VulkanAstSemantics, FromFile) -{ - loadFileCompileAndCheck(GlobalTestSettings.testRoot, GetParam(), - Source::GLSL, Semantics::Vulkan, glslang::EShTargetVulkan_1_0, - Target::AST); -} - -// HLSL-level Vulkan semantics tests. -TEST_P(HlslIoMap, FromFile) -{ - loadFileCompileIoMapAndCheck(GlobalTestSettings.testRoot, GetParam().fileName, - Source::HLSL, Semantics::Vulkan, - Target::Spv, GetParam().entryPoint, - GetParam().baseSamplerBinding, - GetParam().baseTextureBinding, - GetParam().baseImageBinding, - GetParam().baseUboBinding, - GetParam().baseSsboBinding, - GetParam().autoMapBindings, - GetParam().flattenUniforms); -} - -// GLSL-level Vulkan semantics tests. -TEST_P(GlslIoMap, FromFile) -{ - loadFileCompileIoMapAndCheck(GlobalTestSettings.testRoot, GetParam().fileName, - Source::GLSL, Semantics::Vulkan, - Target::Spv, GetParam().entryPoint, - GetParam().baseSamplerBinding, - GetParam().baseTextureBinding, - GetParam().baseImageBinding, - GetParam().baseUboBinding, - GetParam().baseSsboBinding, - GetParam().autoMapBindings, - GetParam().flattenUniforms); -} - -#ifdef AMD_EXTENSIONS -// Compiling GLSL to SPIR-V under Vulkan semantics (AMD extensions enabled). -// Expected to successfully generate SPIR-V. -TEST_P(CompileVulkanToSpirvTestAMD, FromFile) -{ - loadFileCompileAndCheck(GlobalTestSettings.testRoot, GetParam(), - Source::GLSL, Semantics::Vulkan, glslang::EShTargetVulkan_1_0, - Target::Spv); -} -#endif - -#ifdef NV_EXTENSIONS -// Compiling GLSL to SPIR-V under Vulkan semantics (NV extensions enabled). -// Expected to successfully generate SPIR-V. -TEST_P(CompileVulkanToSpirvTestNV, FromFile) -{ - loadFileCompileAndCheck(GlobalTestSettings.testRoot, GetParam(), - Source::GLSL, Semantics::Vulkan, glslang::EShTargetVulkan_1_0, - Target::Spv); -} -#endif - -TEST_P(CompileUpgradeTextureToSampledTextureAndDropSamplersTest, FromFile) -{ - loadCompileUpgradeTextureToSampledTextureAndDropSamplersAndCheck(GlobalTestSettings.testRoot, - GetParam(), - Source::GLSL, - Semantics::Vulkan, - Target::Spv); -} - -// clang-format off -INSTANTIATE_TEST_CASE_P( - Glsl, CompileVulkanToSpirvTest, - ::testing::ValuesIn(std::vector({ - // Test looping constructs. - // No tests yet for making sure break and continue from a nested loop - // goes to the innermost target. - "spv.barrier.vert", - "spv.do-simple.vert", - "spv.do-while-continue-break.vert", - "spv.for-complex-condition.vert", - "spv.for-continue-break.vert", - "spv.for-simple.vert", - "spv.for-notest.vert", - "spv.for-nobody.vert", - "spv.while-continue-break.vert", - "spv.while-simple.vert", - // vulkan-specific tests - "spv.set.vert", - "spv.double.comp", - "spv.100ops.frag", - "spv.130.frag", - "spv.140.frag", - "spv.150.geom", - "spv.150.vert", - "spv.300BuiltIns.vert", - "spv.300layout.frag", - "spv.300layout.vert", - "spv.300layoutp.vert", - "spv.310.comp", - "spv.310.bitcast.frag", - "spv.330.geom", - "spv.400.frag", - "spv.400.tesc", - "spv.400.tese", - "spv.420.geom", - "spv.430.frag", - "spv.430.vert", - "spv.450.tesc", - "spv.450.geom", - "spv.450.noRedecl.tesc", - "spv.accessChain.frag", - "spv.aggOps.frag", - "spv.always-discard.frag", - "spv.always-discard2.frag", - "spv.arbPostDepthCoverage.frag", - "spv.arbPostDepthCoverage_Error.frag", - "spv.bitCast.frag", - "spv.bool.vert", - "spv.boolInBlock.frag", - "spv.branch-return.vert", - "spv.builtInXFB.vert", - "spv.conditionalDiscard.frag", - "spv.constStruct.vert", - "spv.controlFlowAttributes.frag", - "spv.conversion.frag", - "spv.dataOut.frag", - "spv.dataOutIndirect.frag", - "spv.dataOutIndirect.vert", - "spv.deepRvalue.frag", - "spv.depthOut.frag", - "spv.discard-dce.frag", - "spv.doWhileLoop.frag", - "spv.earlyReturnDiscard.frag", - "spv.extPostDepthCoverage.frag", - "spv.extPostDepthCoverage_Error.frag", - "spv.flowControl.frag", - "spv.forLoop.frag", - "spv.forwardFun.frag", - "spv.fullyCovered.frag", - "spv.functionCall.frag", - "spv.functionNestedOpaque.vert", - "spv.functionSemantics.frag", - "spv.GeometryShaderPassthrough.geom", - "spv.interpOps.frag", - "spv.int64.frag", - "spv.intOps.vert", - "spv.layoutNested.vert", - "spv.length.frag", - "spv.localAggregates.frag", - "spv.loops.frag", - "spv.loopsArtificial.frag", - "spv.matFun.vert", - "spv.matrix.frag", - "spv.matrix2.frag", - "spv.memoryQualifier.frag", - "spv.merge-unreachable.frag", - "spv.multiStruct.comp", - "spv.multiStructFuncall.frag", - "spv.newTexture.frag", - "spv.noDeadDecorations.vert", - "spv.nonSquare.vert", - "spv.nonuniform.frag", - "spv.noWorkgroup.comp", - "spv.offsets.frag", - "spv.Operations.frag", - "spv.paramMemory.frag", - "spv.precision.frag", - "spv.precisionNonESSamp.frag", - "spv.prepost.frag", - "spv.qualifiers.vert", - "spv.sample.frag", - "spv.sampleId.frag", - "spv.samplePosition.frag", - "spv.sampleMaskOverrideCoverage.frag", - "spv.shaderBallot.comp", - "spv.shaderDrawParams.vert", - "spv.shaderGroupVote.comp", - "spv.shaderStencilExport.frag", - "spv.shiftOps.frag", - "spv.simpleFunctionCall.frag", - "spv.simpleMat.vert", - "spv.sparseTexture.frag", - "spv.sparseTextureClamp.frag", - "spv.structAssignment.frag", - "spv.structDeref.frag", - "spv.structure.frag", - "spv.switch.frag", - "spv.swizzle.frag", - "spv.swizzleInversion.frag", - "spv.test.frag", - "spv.test.vert", - "spv.texture.frag", - "spv.texture.vert", - "spv.textureBuffer.vert", - "spv.image.frag", - "spv.types.frag", - "spv.uint.frag", - "spv.uniformArray.frag", - "spv.variableArrayIndex.frag", - "spv.varyingArray.frag", - "spv.varyingArrayIndirect.frag", - "spv.vecMatConstruct.frag", - "spv.voidFunction.frag", - "spv.whileLoop.frag", - "spv.AofA.frag", - "spv.queryL.frag", - "spv.separate.frag", - "spv.shortCircuit.frag", - "spv.pushConstant.vert", - "spv.pushConstantAnon.vert", - "spv.subpass.frag", - "spv.specConstant.vert", - "spv.specConstant.comp", - "spv.specConstantComposite.vert", - "spv.specConstantOperations.vert", - "spv.storageBuffer.vert", - "spv.precise.tese", - "spv.precise.tesc", - "spv.vulkan100.subgroupArithmetic.comp", - "spv.vulkan100.subgroupPartitioned.comp", - "spv.xfb.vert", - "spv.xfb2.vert", - "spv.xfb3.vert", - })), - FileNameAsCustomTestSuffix -); - -// clang-format off -INSTANTIATE_TEST_CASE_P( - Glsl, CompileVulkan1_1ToSpirvTest, - ::testing::ValuesIn(std::vector({ - "spv.deviceGroup.frag", - "spv.drawParams.vert", - "spv.int8.frag", - "spv.vulkan110.int16.frag", - "spv.int32.frag", - "spv.explicittypes.frag", - "spv.float32.frag", - "spv.float64.frag", - "spv.multiView.frag", - "spv.subgroup.frag", - "spv.subgroup.geom", - "spv.subgroup.tesc", - "spv.subgroup.tese", - "spv.subgroup.vert", - "spv.subgroupArithmetic.comp", - "spv.subgroupBasic.comp", - "spv.subgroupBallot.comp", - "spv.subgroupClustered.comp", - "spv.subgroupClusteredNeg.comp", - "spv.subgroupPartitioned.comp", - "spv.subgroupShuffle.comp", - "spv.subgroupShuffleRelative.comp", - "spv.subgroupQuad.comp", - "spv.subgroupVote.comp", - "spv.vulkan110.storageBuffer.vert", - })), - FileNameAsCustomTestSuffix -); - -// clang-format off -INSTANTIATE_TEST_CASE_P( - Hlsl, HlslIoMap, - ::testing::ValuesIn(std::vector{ - { "spv.register.autoassign.frag", "main_ep", 5, 10, 0, 20, 30, true, false }, - { "spv.register.noautoassign.frag", "main_ep", 5, 10, 0, 15, 30, false, false }, - { "spv.register.autoassign-2.frag", "main", 5, 10, 0, 15, 30, true, true }, - { "spv.register.subpass.frag", "main", 0, 20, 0, 0, 0, true, true }, - { "spv.buffer.autoassign.frag", "main", 5, 10, 0, 15, 30, true, true }, - { "spv.ssbo.autoassign.frag", "main", 5, 10, 0, 15, 30, true, true }, - { "spv.ssboAlias.frag", "main", 0, 0, 0, 0, 83, true, false }, - { "spv.rw.autoassign.frag", "main", 5, 10, 20, 15, 30, true, true }, - { "spv.register.autoassign.rangetest.frag", "main", - glslang::TQualifier::layoutBindingEnd-2, - glslang::TQualifier::layoutBindingEnd+5, - 20, 30, true, false }, - }), - FileNameAsCustomTestSuffixIoMap -); - -// clang-format off -INSTANTIATE_TEST_CASE_P( - Hlsl, GlslIoMap, - ::testing::ValuesIn(std::vector{ - { "spv.glsl.register.autoassign.frag", "main", 5, 10, 0, 20, 30, true, false }, - { "spv.glsl.register.noautoassign.frag", "main", 5, 10, 0, 15, 30, false, false }, - }), - FileNameAsCustomTestSuffixIoMap -); - -// clang-format off -INSTANTIATE_TEST_CASE_P( - Glsl, CompileOpenGLToSpirvTest, - ::testing::ValuesIn(std::vector({ - "spv.460.frag", - "spv.460.vert", - "spv.460.comp", - "spv.atomic.comp", - "spv.glFragColor.frag", - "spv.rankShift.comp", - "spv.specConst.vert", - "spv.OVR_multiview.vert", - })), - FileNameAsCustomTestSuffix -); - -INSTANTIATE_TEST_CASE_P( - Glsl, VulkanSemantics, - ::testing::ValuesIn(std::vector({ - "vulkan.frag", - "vulkan.vert", - "vulkan.comp", - })), - FileNameAsCustomTestSuffix -); - -INSTANTIATE_TEST_CASE_P( - Glsl, OpenGLSemantics, - ::testing::ValuesIn(std::vector({ - "glspv.esversion.vert", - "glspv.version.frag", - "glspv.version.vert", - "glspv.frag", - "glspv.vert", - })), - FileNameAsCustomTestSuffix -); - -INSTANTIATE_TEST_CASE_P( - Glsl, VulkanAstSemantics, - ::testing::ValuesIn(std::vector({ - "vulkan.ast.vert", - })), - FileNameAsCustomTestSuffix -); - -#ifdef AMD_EXTENSIONS -INSTANTIATE_TEST_CASE_P( - Glsl, CompileVulkanToSpirvTestAMD, - ::testing::ValuesIn(std::vector({ - "spv.float16.frag", - "spv.float16Fetch.frag", - "spv.imageLoadStoreLod.frag", - "spv.int16.frag", - "spv.int16.amd.frag", - "spv.shaderBallotAMD.comp", - "spv.shaderFragMaskAMD.frag", - "spv.textureGatherBiasLod.frag", - })), - FileNameAsCustomTestSuffix -); -#endif - -#ifdef NV_EXTENSIONS -INSTANTIATE_TEST_CASE_P( - Glsl, CompileVulkanToSpirvTestNV, - ::testing::ValuesIn(std::vector({ - "spv.sampleMaskOverrideCoverage.frag", - "spv.GeometryShaderPassthrough.geom", - "spv.viewportArray2.vert", - "spv.viewportArray2.tesc", - "spv.stereoViewRendering.vert", - "spv.stereoViewRendering.tesc", - "spv.multiviewPerViewAttributes.vert", - "spv.multiviewPerViewAttributes.tesc", - "spv.atomicInt64.comp", -})), -FileNameAsCustomTestSuffix -); -#endif - -INSTANTIATE_TEST_CASE_P( - Glsl, CompileUpgradeTextureToSampledTextureAndDropSamplersTest, - ::testing::ValuesIn(std::vector({ - "spv.texture.sampler.transform.frag", - })), - FileNameAsCustomTestSuffix -); -// clang-format on - -} // anonymous namespace -} // namespace glslangtest diff --git a/External/glslang/gtests/TestFixture.cpp b/External/glslang/gtests/TestFixture.cpp deleted file mode 100644 index 77bada5f..00000000 --- a/External/glslang/gtests/TestFixture.cpp +++ /dev/null @@ -1,164 +0,0 @@ -// -// Copyright (C) 2016 Google, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -#include "TestFixture.h" - -namespace glslangtest { - -std::string FileNameAsCustomTestSuffix( - const ::testing::TestParamInfo& info) -{ - std::string name = info.param; - // A valid test case suffix cannot have '.' and '-' inside. - std::replace(name.begin(), name.end(), '.', '_'); - std::replace(name.begin(), name.end(), '-', '_'); - return name; -} - -EShLanguage GetShaderStage(const std::string& stage) -{ - if (stage == "vert") { - return EShLangVertex; - } else if (stage == "tesc") { - return EShLangTessControl; - } else if (stage == "tese") { - return EShLangTessEvaluation; - } else if (stage == "geom") { - return EShLangGeometry; - } else if (stage == "frag") { - return EShLangFragment; - } else if (stage == "comp") { - return EShLangCompute; - } else { - assert(0 && "Unknown shader stage"); - return EShLangCount; - } -} - -EShMessages DeriveOptions(Source source, Semantics semantics, Target target) -{ - EShMessages result = EShMsgCascadingErrors; - - switch (source) { - case Source::GLSL: - break; - case Source::HLSL: - result = static_cast(result | EShMsgReadHlsl); - break; - } - - switch (target) { - case Target::AST: - result = static_cast(result | EShMsgAST); - break; - case Target::Spv: - result = static_cast(result | EShMsgSpvRules); - result = static_cast(result | EShMsgKeepUncalled); - break; - case Target::BothASTAndSpv: - result = static_cast(result | EShMsgSpvRules | EShMsgAST); - result = static_cast(result | EShMsgKeepUncalled); - break; - }; - - switch (semantics) { - case Semantics::OpenGL: - break; - case Semantics::Vulkan: - result = static_cast(result | EShMsgVulkanRules | EShMsgSpvRules); - break; - } - - result = static_cast(result | EShMsgHlslLegalization); - - return result; -} - -std::pair ReadFile(const std::string& path) -{ - std::ifstream fstream(path, std::ios::in); - if (fstream) { - std::string contents; - fstream.seekg(0, std::ios::end); - contents.reserve((std::string::size_type)fstream.tellg()); - fstream.seekg(0, std::ios::beg); - contents.assign((std::istreambuf_iterator(fstream)), - std::istreambuf_iterator()); - return std::make_pair(true, contents); - } - return std::make_pair(false, ""); -} - -std::pair > ReadSpvBinaryFile(const std::string& path) -{ - std::ifstream fstream(path, std::fstream::in | std::fstream::binary); - - if (!fstream) - return std::make_pair(false, std::vector()); - - std::vector contents; - - // Reserve space (for efficiency, not for correctness) - fstream.seekg(0, fstream.end); - contents.reserve(size_t(fstream.tellg()) / sizeof(std::uint32_t)); - fstream.seekg(0, fstream.beg); - - // There is no istream iterator traversing by uint32_t, so we must loop. - while (!fstream.eof()) { - std::uint32_t inWord; - fstream.read((char *)&inWord, sizeof(inWord)); - - if (!fstream.eof()) - contents.push_back(inWord); - } - - return std::make_pair(true, contents); // hopefully, c++11 move semantics optimizes the copy away. -} - -bool WriteFile(const std::string& path, const std::string& contents) -{ - std::ofstream fstream(path, std::ios::out); - if (!fstream) return false; - fstream << contents; - fstream.flush(); - return true; -} - -std::string GetSuffix(const std::string& name) -{ - const size_t pos = name.rfind('.'); - return (pos == std::string::npos) ? "" : name.substr(name.rfind('.') + 1); -} - -} // namespace glslangtest diff --git a/External/glslang/gtests/TestFixture.h b/External/glslang/gtests/TestFixture.h deleted file mode 100644 index a58978d3..00000000 --- a/External/glslang/gtests/TestFixture.h +++ /dev/null @@ -1,646 +0,0 @@ -// -// Copyright (C) 2016 Google, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -#ifndef GLSLANG_GTESTS_TEST_FIXTURE_H -#define GLSLANG_GTESTS_TEST_FIXTURE_H - -#include -#include -#include -#include -#include -#include - -#include - -#include "SPIRV/GlslangToSpv.h" -#include "SPIRV/disassemble.h" -#include "SPIRV/doc.h" -#include "SPIRV/SPVRemapper.h" -#include "StandAlone/ResourceLimits.h" -#include "glslang/Public/ShaderLang.h" - -#include "Initializer.h" -#include "Settings.h" - -namespace glslangtest { - -// This function is used to provide custom test name suffixes based on the -// shader source file names. Otherwise, the test name suffixes will just be -// numbers, which are not quite obvious. -std::string FileNameAsCustomTestSuffix( - const ::testing::TestParamInfo& info); - -enum class Source { - GLSL, - HLSL, -}; - -// Enum for shader compilation semantics. -enum class Semantics { - OpenGL, - Vulkan -}; - -// Enum for compilation target. -enum class Target { - AST, - Spv, - BothASTAndSpv, -}; - -EShLanguage GetShaderStage(const std::string& stage); - -EShMessages DeriveOptions(Source, Semantics, Target); - -// Reads the content of the file at the given |path|. On success, returns true -// and the contents; otherwise, returns false and an empty string. -std::pair ReadFile(const std::string& path); -std::pair > ReadSpvBinaryFile(const std::string& path); - -// Writes the given |contents| into the file at the given |path|. Returns true -// on successful output. -bool WriteFile(const std::string& path, const std::string& contents); - -// Returns the suffix of the given |name|. -std::string GetSuffix(const std::string& name); - -// Base class for glslang integration tests. It contains many handy utility-like -// methods such as reading shader source files, compiling into AST/SPIR-V, and -// comparing with expected outputs. -// -// To write value-Parameterized tests: -// using ValueParamTest = GlslangTest<::testing::TestWithParam>; -// To use as normal fixture: -// using FixtureTest = GlslangTest<::testing::Test>; -template -class GlslangTest : public GT { -public: - GlslangTest() - : defaultVersion(100), - defaultProfile(ENoProfile), - forceVersionProfile(false), - isForwardCompatible(false) {} - - // Tries to load the contents from the file at the given |path|. On success, - // writes the contents into |contents|. On failure, errors out. - void tryLoadFile(const std::string& path, const std::string& tag, - std::string* contents) - { - bool fileReadOk; - std::tie(fileReadOk, *contents) = ReadFile(path); - ASSERT_TRUE(fileReadOk) << "Cannot open " << tag << " file: " << path; - } - - // Tries to load the contents from the file at the given |path|. On success, - // writes the contents into |contents|. On failure, errors out. - void tryLoadSpvFile(const std::string& path, const std::string& tag, - std::vector& contents) - { - bool fileReadOk; - std::tie(fileReadOk, contents) = ReadSpvBinaryFile(path); - ASSERT_TRUE(fileReadOk) << "Cannot open " << tag << " file: " << path; - } - - // Checks the equality of |expected| and |real|. If they are not equal, - // write |real| to the given file named as |fname| if update mode is on. - void checkEqAndUpdateIfRequested(const std::string& expected, - const std::string& real, - const std::string& fname) - { - // In order to output the message we want under proper circumstances, - // we need the following operator<< stuff. - EXPECT_EQ(expected, real) - << (GlobalTestSettings.updateMode - ? ("Mismatch found and update mode turned on - " - "flushing expected result output.") - : ""); - - // Update the expected output file if requested. - // It looks weird to duplicate the comparison between expected_output - // and stream.str(). However, if creating a variable for the comparison - // result, we cannot have pretty print of the string diff in the above. - if (GlobalTestSettings.updateMode && expected != real) { - EXPECT_TRUE(WriteFile(fname, real)) << "Flushing failed"; - } - } - - struct ShaderResult { - std::string shaderName; - std::string output; - std::string error; - }; - - // A struct for holding all the information returned by glslang compilation - // and linking. - struct GlslangResult { - std::vector shaderResults; - std::string linkingOutput; - std::string linkingError; - std::string spirvWarningsErrors; - std::string spirv; // Optional SPIR-V disassembly text. - }; - - // Compiles and the given source |code| of the given shader |stage| into - // the target under the semantics conveyed via |controls|. Returns true - // and modifies |shader| on success. - bool compile(glslang::TShader* shader, const std::string& code, - const std::string& entryPointName, EShMessages controls, - const TBuiltInResource* resources=nullptr) - { - const char* shaderStrings = code.data(); - const int shaderLengths = static_cast(code.size()); - - shader->setStringsWithLengths(&shaderStrings, &shaderLengths, 1); - if (!entryPointName.empty()) shader->setEntryPoint(entryPointName.c_str()); - return shader->parse( - (resources ? resources : &glslang::DefaultTBuiltInResource), - defaultVersion, isForwardCompatible, controls); - } - - // Compiles and links the given source |code| of the given shader - // |stage| into the target under the semantics specified via |controls|. - // Returns a GlslangResult instance containing all the information generated - // during the process. If the target includes SPIR-V, also disassembles - // the result and returns disassembly text. - GlslangResult compileAndLink( - const std::string shaderName, const std::string& code, - const std::string& entryPointName, EShMessages controls, - glslang::EShTargetClientVersion clientTargetVersion, - bool flattenUniformArrays = false, - EShTextureSamplerTransformMode texSampTransMode = EShTexSampTransKeep, - bool enableOptimizer = false, - bool automap = true) - { - const EShLanguage stage = GetShaderStage(GetSuffix(shaderName)); - - glslang::TShader shader(stage); - if (automap) { - shader.setAutoMapLocations(true); - shader.setAutoMapBindings(true); - } - shader.setTextureSamplerTransformMode(texSampTransMode); - shader.setFlattenUniformArrays(flattenUniformArrays); - - if (controls & EShMsgSpvRules) { - if (controls & EShMsgVulkanRules) { - shader.setEnvInput((controls & EShMsgReadHlsl) ? glslang::EShSourceHlsl - : glslang::EShSourceGlsl, - stage, glslang::EShClientVulkan, 100); - shader.setEnvClient(glslang::EShClientVulkan, clientTargetVersion); - shader.setEnvTarget(glslang::EShTargetSpv, - clientTargetVersion == glslang::EShTargetVulkan_1_1 ? glslang::EShTargetSpv_1_3 - : glslang::EShTargetSpv_1_0); - } else { - shader.setEnvInput((controls & EShMsgReadHlsl) ? glslang::EShSourceHlsl - : glslang::EShSourceGlsl, - stage, glslang::EShClientOpenGL, 100); - shader.setEnvClient(glslang::EShClientOpenGL, clientTargetVersion); - shader.setEnvTarget(glslang::EshTargetSpv, glslang::EShTargetSpv_1_0); - } - } - - bool success = compile(&shader, code, entryPointName, controls); - - glslang::TProgram program; - program.addShader(&shader); - success &= program.link(controls); - - spv::SpvBuildLogger logger; - - if (success && (controls & EShMsgSpvRules)) { - std::vector spirv_binary; - glslang::SpvOptions options; - options.disableOptimizer = !enableOptimizer; - glslang::GlslangToSpv(*program.getIntermediate(stage), - spirv_binary, &logger, &options); - - std::ostringstream disassembly_stream; - spv::Parameterize(); - spv::Disassemble(disassembly_stream, spirv_binary); - return {{{shaderName, shader.getInfoLog(), shader.getInfoDebugLog()},}, - program.getInfoLog(), program.getInfoDebugLog(), - logger.getAllMessages(), disassembly_stream.str()}; - } else { - return {{{shaderName, shader.getInfoLog(), shader.getInfoDebugLog()},}, - program.getInfoLog(), program.getInfoDebugLog(), "", ""}; - } - } - - // Compiles and links the given source |code| of the given shader - // |stage| into the target under the semantics specified via |controls|. - // Returns a GlslangResult instance containing all the information generated - // during the process. If the target includes SPIR-V, also disassembles - // the result and returns disassembly text. - GlslangResult compileLinkIoMap( - const std::string shaderName, const std::string& code, - const std::string& entryPointName, EShMessages controls, - int baseSamplerBinding, - int baseTextureBinding, - int baseImageBinding, - int baseUboBinding, - int baseSsboBinding, - bool autoMapBindings, - bool flattenUniformArrays) - { - const EShLanguage stage = GetShaderStage(GetSuffix(shaderName)); - - glslang::TShader shader(stage); - shader.setShiftSamplerBinding(baseSamplerBinding); - shader.setShiftTextureBinding(baseTextureBinding); - shader.setShiftImageBinding(baseImageBinding); - shader.setShiftUboBinding(baseUboBinding); - shader.setShiftSsboBinding(baseSsboBinding); - shader.setAutoMapBindings(autoMapBindings); - shader.setAutoMapLocations(true); - shader.setFlattenUniformArrays(flattenUniformArrays); - - bool success = compile(&shader, code, entryPointName, controls); - - glslang::TProgram program; - program.addShader(&shader); - - success &= program.link(controls); - success &= program.mapIO(); - - spv::SpvBuildLogger logger; - - if (success && (controls & EShMsgSpvRules)) { - std::vector spirv_binary; - glslang::GlslangToSpv(*program.getIntermediate(stage), - spirv_binary, &logger); - - std::ostringstream disassembly_stream; - spv::Parameterize(); - spv::Disassemble(disassembly_stream, spirv_binary); - return {{{shaderName, shader.getInfoLog(), shader.getInfoDebugLog()},}, - program.getInfoLog(), program.getInfoDebugLog(), - logger.getAllMessages(), disassembly_stream.str()}; - } else { - return {{{shaderName, shader.getInfoLog(), shader.getInfoDebugLog()},}, - program.getInfoLog(), program.getInfoDebugLog(), "", ""}; - } - } - - // This is like compileAndLink but with remapping of the SPV binary - // through spirvbin_t::remap(). While technically this could be merged - // with compileAndLink() above (with the remap step optionally being a no-op) - // it is given separately here for ease of future extraction. - GlslangResult compileLinkRemap( - const std::string shaderName, const std::string& code, - const std::string& entryPointName, EShMessages controls, - const unsigned int remapOptions = spv::spirvbin_t::NONE) - { - const EShLanguage stage = GetShaderStage(GetSuffix(shaderName)); - - glslang::TShader shader(stage); - shader.setAutoMapBindings(true); - shader.setAutoMapLocations(true); - - bool success = compile(&shader, code, entryPointName, controls); - - glslang::TProgram program; - program.addShader(&shader); - success &= program.link(controls); - - spv::SpvBuildLogger logger; - - if (success && (controls & EShMsgSpvRules)) { - std::vector spirv_binary; - glslang::GlslangToSpv(*program.getIntermediate(stage), - spirv_binary, &logger); - - spv::spirvbin_t(0 /*verbosity*/).remap(spirv_binary, remapOptions); - - std::ostringstream disassembly_stream; - spv::Parameterize(); - spv::Disassemble(disassembly_stream, spirv_binary); - return {{{shaderName, shader.getInfoLog(), shader.getInfoDebugLog()},}, - program.getInfoLog(), program.getInfoDebugLog(), - logger.getAllMessages(), disassembly_stream.str()}; - } else { - return {{{shaderName, shader.getInfoLog(), shader.getInfoDebugLog()},}, - program.getInfoLog(), program.getInfoDebugLog(), "", ""}; - } - } - - // remap the binary in 'code' with the options in remapOptions - GlslangResult remap( - const std::string shaderName, const std::vector& code, - EShMessages controls, - const unsigned int remapOptions = spv::spirvbin_t::NONE) - { - if ((controls & EShMsgSpvRules)) { - std::vector spirv_binary(code); // scratch copy - - spv::spirvbin_t(0 /*verbosity*/).remap(spirv_binary, remapOptions); - - std::ostringstream disassembly_stream; - spv::Parameterize(); - spv::Disassemble(disassembly_stream, spirv_binary); - - return {{{shaderName, "", ""},}, - "", "", - "", disassembly_stream.str()}; - } else { - return {{{shaderName, "", ""},}, "", "", "", ""}; - } - } - - void outputResultToStream(std::ostringstream* stream, - const GlslangResult& result, - EShMessages controls) - { - const auto outputIfNotEmpty = [&stream](const std::string& str) { - if (!str.empty()) *stream << str << "\n"; - }; - - for (const auto& shaderResult : result.shaderResults) { - *stream << shaderResult.shaderName << "\n"; - outputIfNotEmpty(shaderResult.output); - outputIfNotEmpty(shaderResult.error); - } - outputIfNotEmpty(result.linkingOutput); - outputIfNotEmpty(result.linkingError); - *stream << result.spirvWarningsErrors; - - if (controls & EShMsgSpvRules) { - *stream - << (result.spirv.empty() - ? "SPIR-V is not generated for failed compile or link\n" - : result.spirv); - } - } - - void loadFileCompileAndCheck(const std::string& testDir, - const std::string& testName, - Source source, - Semantics semantics, - glslang::EShTargetClientVersion clientTargetVersion, - Target target, - bool automap = true, - const std::string& entryPointName="", - const std::string& baseDir="/baseResults/", - const bool enableOptimizer = false) - { - const std::string inputFname = testDir + "/" + testName; - const std::string expectedOutputFname = - testDir + baseDir + testName + ".out"; - std::string input, expectedOutput; - - tryLoadFile(inputFname, "input", &input); - tryLoadFile(expectedOutputFname, "expected output", &expectedOutput); - - EShMessages controls = DeriveOptions(source, semantics, target); - if (enableOptimizer) - controls = static_cast(controls & ~EShMsgHlslLegalization); - GlslangResult result = compileAndLink(testName, input, entryPointName, controls, clientTargetVersion, false, - EShTexSampTransKeep, enableOptimizer, automap); - - // Generate the hybrid output in the way of glslangValidator. - std::ostringstream stream; - outputResultToStream(&stream, result, controls); - - checkEqAndUpdateIfRequested(expectedOutput, stream.str(), - expectedOutputFname); - } - - void loadFileCompileFlattenUniformsAndCheck(const std::string& testDir, - const std::string& testName, - Source source, - Semantics semantics, - Target target, - const std::string& entryPointName="") - { - const std::string inputFname = testDir + "/" + testName; - const std::string expectedOutputFname = - testDir + "/baseResults/" + testName + ".out"; - std::string input, expectedOutput; - - tryLoadFile(inputFname, "input", &input); - tryLoadFile(expectedOutputFname, "expected output", &expectedOutput); - - const EShMessages controls = DeriveOptions(source, semantics, target); - GlslangResult result = compileAndLink(testName, input, entryPointName, controls, - glslang::EShTargetVulkan_1_0, true); - - // Generate the hybrid output in the way of glslangValidator. - std::ostringstream stream; - outputResultToStream(&stream, result, controls); - - checkEqAndUpdateIfRequested(expectedOutput, stream.str(), - expectedOutputFname); - } - - void loadFileCompileIoMapAndCheck(const std::string& testDir, - const std::string& testName, - Source source, - Semantics semantics, - Target target, - const std::string& entryPointName, - int baseSamplerBinding, - int baseTextureBinding, - int baseImageBinding, - int baseUboBinding, - int baseSsboBinding, - bool autoMapBindings, - bool flattenUniformArrays) - { - const std::string inputFname = testDir + "/" + testName; - const std::string expectedOutputFname = - testDir + "/baseResults/" + testName + ".out"; - std::string input, expectedOutput; - - tryLoadFile(inputFname, "input", &input); - tryLoadFile(expectedOutputFname, "expected output", &expectedOutput); - - const EShMessages controls = DeriveOptions(source, semantics, target); - GlslangResult result = compileLinkIoMap(testName, input, entryPointName, controls, - baseSamplerBinding, baseTextureBinding, baseImageBinding, - baseUboBinding, baseSsboBinding, - autoMapBindings, - flattenUniformArrays); - - // Generate the hybrid output in the way of glslangValidator. - std::ostringstream stream; - outputResultToStream(&stream, result, controls); - - checkEqAndUpdateIfRequested(expectedOutput, stream.str(), - expectedOutputFname); - } - - void loadFileCompileRemapAndCheck(const std::string& testDir, - const std::string& testName, - Source source, - Semantics semantics, - Target target, - const std::string& entryPointName="", - const unsigned int remapOptions = spv::spirvbin_t::NONE) - { - const std::string inputFname = testDir + "/" + testName; - const std::string expectedOutputFname = - testDir + "/baseResults/" + testName + ".out"; - std::string input, expectedOutput; - - tryLoadFile(inputFname, "input", &input); - tryLoadFile(expectedOutputFname, "expected output", &expectedOutput); - - const EShMessages controls = DeriveOptions(source, semantics, target); - GlslangResult result = compileLinkRemap(testName, input, entryPointName, controls, remapOptions); - - // Generate the hybrid output in the way of glslangValidator. - std::ostringstream stream; - outputResultToStream(&stream, result, controls); - - checkEqAndUpdateIfRequested(expectedOutput, stream.str(), - expectedOutputFname); - } - - void loadFileRemapAndCheck(const std::string& testDir, - const std::string& testName, - Source source, - Semantics semantics, - Target target, - const unsigned int remapOptions = spv::spirvbin_t::NONE) - { - const std::string inputFname = testDir + "/" + testName; - const std::string expectedOutputFname = - testDir + "/baseResults/" + testName + ".out"; - std::vector input; - std::string expectedOutput; - - tryLoadSpvFile(inputFname, "input", input); - tryLoadFile(expectedOutputFname, "expected output", &expectedOutput); - - const EShMessages controls = DeriveOptions(source, semantics, target); - GlslangResult result = remap(testName, input, controls, remapOptions); - - // Generate the hybrid output in the way of glslangValidator. - std::ostringstream stream; - outputResultToStream(&stream, result, controls); - - checkEqAndUpdateIfRequested(expectedOutput, stream.str(), - expectedOutputFname); - } - - // Preprocesses the given |source| code. On success, returns true, the - // preprocessed shader, and warning messages. Otherwise, returns false, an - // empty string, and error messages. - std::tuple preprocess( - const std::string& source) - { - const char* shaderStrings = source.data(); - const int shaderLengths = static_cast(source.size()); - - glslang::TShader shader(EShLangVertex); - shader.setStringsWithLengths(&shaderStrings, &shaderLengths, 1); - std::string ppShader; - glslang::TShader::ForbidIncluder includer; - const bool success = shader.preprocess( - &glslang::DefaultTBuiltInResource, defaultVersion, defaultProfile, - forceVersionProfile, isForwardCompatible, (EShMessages)(EShMsgOnlyPreprocessor | EShMsgCascadingErrors), - &ppShader, includer); - - std::string log = shader.getInfoLog(); - log += shader.getInfoDebugLog(); - if (success) { - return std::make_tuple(true, ppShader, log); - } else { - return std::make_tuple(false, "", log); - } - } - - void loadFilePreprocessAndCheck(const std::string& testDir, - const std::string& testName) - { - const std::string inputFname = testDir + "/" + testName; - const std::string expectedOutputFname = - testDir + "/baseResults/" + testName + ".out"; - const std::string expectedErrorFname = - testDir + "/baseResults/" + testName + ".err"; - std::string input, expectedOutput, expectedError; - - tryLoadFile(inputFname, "input", &input); - tryLoadFile(expectedOutputFname, "expected output", &expectedOutput); - tryLoadFile(expectedErrorFname, "expected error", &expectedError); - - bool ppOk; - std::string output, error; - std::tie(ppOk, output, error) = preprocess(input); - if (!output.empty()) output += '\n'; - if (!error.empty()) error += '\n'; - - checkEqAndUpdateIfRequested(expectedOutput, output, - expectedOutputFname); - checkEqAndUpdateIfRequested(expectedError, error, - expectedErrorFname); - } - - void loadCompileUpgradeTextureToSampledTextureAndDropSamplersAndCheck(const std::string& testDir, - const std::string& testName, - Source source, - Semantics semantics, - Target target, - const std::string& entryPointName = "") - { - const std::string inputFname = testDir + "/" + testName; - const std::string expectedOutputFname = testDir + "/baseResults/" + testName + ".out"; - std::string input, expectedOutput; - - tryLoadFile(inputFname, "input", &input); - tryLoadFile(expectedOutputFname, "expected output", &expectedOutput); - - const EShMessages controls = DeriveOptions(source, semantics, target); - GlslangResult result = compileAndLink(testName, input, entryPointName, controls, - glslang::EShTargetVulkan_1_0, false, - EShTexSampTransUpgradeTextureRemoveSampler); - - // Generate the hybrid output in the way of glslangValidator. - std::ostringstream stream; - outputResultToStream(&stream, result, controls); - - checkEqAndUpdateIfRequested(expectedOutput, stream.str(), - expectedOutputFname); - } - -private: - const int defaultVersion; - const EProfile defaultProfile; - const bool forceVersionProfile; - const bool isForwardCompatible; -}; - -} // namespace glslangtest - -#endif // GLSLANG_GTESTS_TEST_FIXTURE_H diff --git a/External/glslang/gtests/main.cpp b/External/glslang/gtests/main.cpp deleted file mode 100644 index 9cd06d1d..00000000 --- a/External/glslang/gtests/main.cpp +++ /dev/null @@ -1,79 +0,0 @@ -// -// Copyright (C) 2016 Google, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -#include -#include - -#include - -#include "Initializer.h" -#include "Settings.h" - -int main(int argc, char** argv) -{ - ::testing::InitGoogleTest(&argc, argv); - - std::unique_ptr initializer( - new glslangtest::GlslangInitializer); - - glslangtest::GlobalTestSettings.initializer = initializer.get(); - - for (int i = 1; i < argc; ++i) { - if (std::string("--update-mode") == argv[i]) { - glslangtest::GlobalTestSettings.updateMode = true; - } - if (std::string("--test-root") == argv[i]) { - // Allow the user set the test root directory. This is useful - // for testing with files from another source tree. - if (i + 1 < argc) { - glslangtest::GlobalTestSettings.testRoot = argv[i + 1]; - i++; - } else { - printf("error: --test-root requires an argument\n"); - return 1; - } - } - if (std::string("--help") == argv[i]) { - printf("\nExtra options:\n\n"); - printf(" --update-mode\n Update the golden results for the tests.\n"); - printf(" --test-root \n Specify the test root directory (useful for testing with\n files from another source tree).\n"); - } - } - - const int result = RUN_ALL_TESTS(); - - glslangtest::GlobalTestSettings.initializer = nullptr; - - return result; -} diff --git a/External/glslang/hlsl/CMakeLists.txt b/External/glslang/hlsl/CMakeLists.txt deleted file mode 100644 index a3b643f0..00000000 --- a/External/glslang/hlsl/CMakeLists.txt +++ /dev/null @@ -1,35 +0,0 @@ -set(SOURCES - hlslAttributes.cpp - hlslParseHelper.cpp - hlslScanContext.cpp - hlslOpMap.cpp - hlslTokenStream.cpp - hlslGrammar.cpp - hlslParseables.cpp) - -set(HEADERS - hlslAttributes.h - hlslParseHelper.h - hlslTokens.h - hlslScanContext.h - hlslOpMap.h - hlslTokenStream.h - hlslGrammar.h - hlslParseables.h) - -add_library(HLSL ${LIB_TYPE} ${SOURCES} ${HEADERS}) -set_property(TARGET HLSL PROPERTY FOLDER hlsl) -set_property(TARGET HLSL PROPERTY POSITION_INDEPENDENT_CODE ON) - -if(WIN32 AND BUILD_SHARED_LIBS) - set_target_properties(HLSL PROPERTIES PREFIX "") -endif() - -if(WIN32) - source_group("Source" FILES ${SOURCES} ${HEADERS}) -endif(WIN32) - -if(ENABLE_GLSLANG_INSTALL) - install(TARGETS HLSL - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) -endif(ENABLE_GLSLANG_INSTALL) diff --git a/External/glslang/hlsl/hlslAttributes.cpp b/External/glslang/hlsl/hlslAttributes.cpp deleted file mode 100644 index 261cec34..00000000 --- a/External/glslang/hlsl/hlslAttributes.cpp +++ /dev/null @@ -1,106 +0,0 @@ -// -// 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 Google, Inc., nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -#include "hlslAttributes.h" -#include "hlslParseHelper.h" - -namespace glslang { - // Map the given string to an attribute enum from TAttributeType, - // or EatNone if invalid. - TAttributeType HlslParseContext::attributeFromName(const TString& nameSpace, const TString& name) const - { - // handle names within a namespace - - if (nameSpace == "vk") { - if (name == "input_attachment_index") - return EatInputAttachment; - else if (name == "location") - return EatLocation; - else if (name == "binding") - return EatBinding; - else if (name == "global_cbuffer_binding") - return EatGlobalBinding; - else if (name == "builtin") - return EatBuiltIn; - else if (name == "constant_id") - return EatConstantId; - else if (name == "push_constant") - return EatPushConstant; - } else if (nameSpace.size() > 0) - return EatNone; - - // handle names with no namespace - - if (name == "allow_uav_condition") - return EatAllow_uav_condition; - else if (name == "branch") - return EatBranch; - else if (name == "call") - return EatCall; - else if (name == "domain") - return EatDomain; - else if (name == "earlydepthstencil") - return EatEarlyDepthStencil; - else if (name == "fastopt") - return EatFastOpt; - else if (name == "flatten") - return EatFlatten; - else if (name == "forcecase") - return EatForceCase; - else if (name == "instance") - return EatInstance; - else if (name == "maxtessfactor") - return EatMaxTessFactor; - else if (name == "maxvertexcount") - return EatMaxVertexCount; - else if (name == "numthreads") - return EatNumThreads; - else if (name == "outputcontrolpoints") - return EatOutputControlPoints; - else if (name == "outputtopology") - return EatOutputTopology; - else if (name == "partitioning") - return EatPartitioning; - else if (name == "patchconstantfunc") - return EatPatchConstantFunc; - else if (name == "unroll") - return EatUnroll; - else if (name == "loop") - return EatLoop; - else - return EatNone; - } - -} // end namespace glslang diff --git a/External/glslang/hlsl/hlslAttributes.h b/External/glslang/hlsl/hlslAttributes.h deleted file mode 100644 index b1cc0372..00000000 --- a/External/glslang/hlsl/hlslAttributes.h +++ /dev/null @@ -1,59 +0,0 @@ -// -// 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 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 HLSLATTRIBUTES_H_ -#define HLSLATTRIBUTES_H_ - -#include -#include - -#include "../glslang/MachineIndependent/attribute.h" -#include "../glslang/MachineIndependent/SymbolTable.h" -#include "hlslScanContext.h" - -namespace glslang { - - class TFunctionDeclarator { - public: - TFunctionDeclarator() : function(nullptr), body(nullptr) { } - TSourceLoc loc; - TFunction* function; - TAttributes attributes; - TVector* body; - }; - -} // end namespace glslang - -#endif // HLSLATTRIBUTES_H_ diff --git a/External/glslang/hlsl/hlslGrammar.cpp b/External/glslang/hlsl/hlslGrammar.cpp deleted file mode 100644 index cb058779..00000000 --- a/External/glslang/hlsl/hlslGrammar.cpp +++ /dev/null @@ -1,4120 +0,0 @@ -// -// Copyright (C) 2016 Google, Inc. -// 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 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. -// - -// -// This is a set of mutually recursive methods implementing the HLSL grammar. -// Generally, each returns -// - through an argument: a type specifically appropriate to which rule it -// recognized -// - through the return value: true/false to indicate whether or not it -// recognized its rule -// -// As much as possible, only grammar recognition should happen in this file, -// with all other work being farmed out to hlslParseHelper.cpp, which in turn -// will build the AST. -// -// The next token, yet to be "accepted" is always sitting in 'token'. -// When a method says it accepts a rule, that means all tokens involved -// in the rule will have been consumed, and none left in 'token'. -// - -#include "hlslTokens.h" -#include "hlslGrammar.h" -#include "hlslAttributes.h" - -namespace glslang { - -// Root entry point to this recursive decent parser. -// Return true if compilation unit was successfully accepted. -bool HlslGrammar::parse() -{ - advanceToken(); - return acceptCompilationUnit(); -} - -void HlslGrammar::expected(const char* syntax) -{ - parseContext.error(token.loc, "Expected", syntax, ""); -} - -void HlslGrammar::unimplemented(const char* error) -{ - parseContext.error(token.loc, "Unimplemented", error, ""); -} - -// IDENTIFIER -// THIS -// type that can be used as IDENTIFIER -// -// Only process the next token if it is an identifier. -// Return true if it was an identifier. -bool HlslGrammar::acceptIdentifier(HlslToken& idToken) -{ - // IDENTIFIER - if (peekTokenClass(EHTokIdentifier)) { - idToken = token; - advanceToken(); - return true; - } - - // THIS - // -> maps to the IDENTIFIER spelled with the internal special name for 'this' - if (peekTokenClass(EHTokThis)) { - idToken = token; - advanceToken(); - idToken.tokenClass = EHTokIdentifier; - idToken.string = NewPoolTString(intermediate.implicitThisName); - return true; - } - - // type that can be used as IDENTIFIER - - // Even though "sample", "bool", "float", etc keywords (for types, interpolation modifiers), - // they ARE still accepted as identifiers. This is not a dense space: e.g, "void" is not a - // valid identifier, nor is "linear". This code special cases the known instances of this, so - // e.g, "int sample;" or "float float;" is accepted. Other cases can be added here if needed. - - const char* idString = getTypeString(peek()); - if (idString == nullptr) - return false; - - token.string = NewPoolTString(idString); - token.tokenClass = EHTokIdentifier; - idToken = token; - typeIdentifiers = true; - - advanceToken(); - - return true; -} - -// compilationUnit -// : declaration_list EOF -// -bool HlslGrammar::acceptCompilationUnit() -{ - TIntermNode* unitNode = nullptr; - - if (! acceptDeclarationList(unitNode)) - return false; - - if (! peekTokenClass(EHTokNone)) - return false; - - // set root of AST - if (unitNode && !unitNode->getAsAggregate()) - unitNode = intermediate.growAggregate(nullptr, unitNode); - intermediate.setTreeRoot(unitNode); - - return true; -} - -// Recognize the following, but with the extra condition that it can be -// successfully terminated by EOF or '}'. -// -// declaration_list -// : list of declaration_or_semicolon followed by EOF or RIGHT_BRACE -// -// declaration_or_semicolon -// : declaration -// : SEMICOLON -// -bool HlslGrammar::acceptDeclarationList(TIntermNode*& nodeList) -{ - do { - // HLSL allows extra semicolons between global declarations - do { } while (acceptTokenClass(EHTokSemicolon)); - - // EOF or RIGHT_BRACE - if (peekTokenClass(EHTokNone) || peekTokenClass(EHTokRightBrace)) - return true; - - // declaration - if (! acceptDeclaration(nodeList)) - return false; - } while (true); - - return true; -} - -// sampler_state -// : LEFT_BRACE [sampler_state_assignment ... ] RIGHT_BRACE -// -// sampler_state_assignment -// : sampler_state_identifier EQUAL value SEMICOLON -// -// sampler_state_identifier -// : ADDRESSU -// | ADDRESSV -// | ADDRESSW -// | BORDERCOLOR -// | FILTER -// | MAXANISOTROPY -// | MAXLOD -// | MINLOD -// | MIPLODBIAS -// -bool HlslGrammar::acceptSamplerState() -{ - // TODO: this should be genericized to accept a list of valid tokens and - // return token/value pairs. Presently it is specific to texture values. - - if (! acceptTokenClass(EHTokLeftBrace)) - return true; - - parseContext.warn(token.loc, "unimplemented", "immediate sampler state", ""); - - do { - // read state name - HlslToken state; - if (! acceptIdentifier(state)) - break; // end of list - - // FXC accepts any case - TString stateName = *state.string; - std::transform(stateName.begin(), stateName.end(), stateName.begin(), ::tolower); - - if (! acceptTokenClass(EHTokAssign)) { - expected("assign"); - return false; - } - - if (stateName == "minlod" || stateName == "maxlod") { - if (! peekTokenClass(EHTokIntConstant)) { - expected("integer"); - return false; - } - - TIntermTyped* lod = nullptr; - if (! acceptLiteral(lod)) // should never fail, since we just looked for an integer - return false; - } else if (stateName == "maxanisotropy") { - if (! peekTokenClass(EHTokIntConstant)) { - expected("integer"); - return false; - } - - TIntermTyped* maxAnisotropy = nullptr; - if (! acceptLiteral(maxAnisotropy)) // should never fail, since we just looked for an integer - return false; - } else if (stateName == "filter") { - HlslToken filterMode; - if (! acceptIdentifier(filterMode)) { - expected("filter mode"); - return false; - } - } else if (stateName == "addressu" || stateName == "addressv" || stateName == "addressw") { - HlslToken addrMode; - if (! acceptIdentifier(addrMode)) { - expected("texture address mode"); - return false; - } - } else if (stateName == "miplodbias") { - TIntermTyped* lodBias = nullptr; - if (! acceptLiteral(lodBias)) { - expected("lod bias"); - return false; - } - } else if (stateName == "bordercolor") { - return false; - } else { - expected("texture state"); - return false; - } - - // SEMICOLON - if (! acceptTokenClass(EHTokSemicolon)) { - expected("semicolon"); - return false; - } - } while (true); - - if (! acceptTokenClass(EHTokRightBrace)) - return false; - - return true; -} - -// sampler_declaration_dx9 -// : SAMPLER identifier EQUAL sampler_type sampler_state -// -bool HlslGrammar::acceptSamplerDeclarationDX9(TType& /*type*/) -{ - if (! acceptTokenClass(EHTokSampler)) - return false; - - // TODO: remove this when DX9 style declarations are implemented. - unimplemented("Direct3D 9 sampler declaration"); - - // read sampler name - HlslToken name; - if (! acceptIdentifier(name)) { - expected("sampler name"); - return false; - } - - if (! acceptTokenClass(EHTokAssign)) { - expected("="); - return false; - } - - return false; -} - -// declaration -// : attributes attributed_declaration -// | NAMESPACE IDENTIFIER LEFT_BRACE declaration_list RIGHT_BRACE -// -// attributed_declaration -// : sampler_declaration_dx9 post_decls SEMICOLON -// | fully_specified_type // for cbuffer/tbuffer -// | fully_specified_type declarator_list SEMICOLON // for non cbuffer/tbuffer -// | fully_specified_type identifier function_parameters post_decls compound_statement // function definition -// | fully_specified_type identifier sampler_state post_decls compound_statement // sampler definition -// | typedef declaration -// -// declarator_list -// : declarator COMMA declarator COMMA declarator... // zero or more declarators -// -// declarator -// : identifier array_specifier post_decls -// | identifier array_specifier post_decls EQUAL assignment_expression -// | identifier function_parameters post_decls // function prototype -// -// Parsing has to go pretty far in to know whether it's a variable, prototype, or -// function definition, so the implementation below doesn't perfectly divide up the grammar -// as above. (The 'identifier' in the first item in init_declarator list is the -// same as 'identifier' for function declarations.) -// -// This can generate more than one subtree, one per initializer or a function body. -// All initializer subtrees are put in their own aggregate node, making one top-level -// node for all the initializers. Each function created is a top-level node to grow -// into the passed-in nodeList. -// -// If 'nodeList' is passed in as non-null, it must an aggregate to extend for -// each top-level node the declaration creates. Otherwise, if only one top-level -// node in generated here, that is want is returned in nodeList. -// -bool HlslGrammar::acceptDeclaration(TIntermNode*& nodeList) -{ - // NAMESPACE IDENTIFIER LEFT_BRACE declaration_list RIGHT_BRACE - if (acceptTokenClass(EHTokNamespace)) { - HlslToken namespaceToken; - if (!acceptIdentifier(namespaceToken)) { - expected("namespace name"); - return false; - } - parseContext.pushNamespace(*namespaceToken.string); - if (!acceptTokenClass(EHTokLeftBrace)) { - expected("{"); - return false; - } - if (!acceptDeclarationList(nodeList)) { - expected("declaration list"); - return false; - } - if (!acceptTokenClass(EHTokRightBrace)) { - expected("}"); - return false; - } - parseContext.popNamespace(); - return true; - } - - bool declarator_list = false; // true when processing comma separation - - // attributes - TFunctionDeclarator declarator; - acceptAttributes(declarator.attributes); - - // typedef - bool typedefDecl = acceptTokenClass(EHTokTypedef); - - TType declaredType; - - // DX9 sampler declaration use a different syntax - // DX9 shaders need to run through HLSL compiler (fxc) via a back compat mode, it isn't going to - // be possible to simultaneously compile D3D10+ style shaders and DX9 shaders. If we want to compile DX9 - // HLSL shaders, this will have to be a master level switch - // As such, the sampler keyword in D3D10+ turns into an automatic sampler type, and is commonly used - // For that reason, this line is commented out - // if (acceptSamplerDeclarationDX9(declaredType)) - // return true; - - bool forbidDeclarators = (peekTokenClass(EHTokCBuffer) || peekTokenClass(EHTokTBuffer)); - // fully_specified_type - if (! acceptFullySpecifiedType(declaredType, nodeList, declarator.attributes, forbidDeclarators)) - return false; - - // cbuffer and tbuffer end with the closing '}'. - // No semicolon is included. - if (forbidDeclarators) - return true; - - // declarator_list - // : declarator - // : identifier - HlslToken idToken; - TIntermAggregate* initializers = nullptr; - while (acceptIdentifier(idToken)) { - TString *fullName = idToken.string; - if (parseContext.symbolTable.atGlobalLevel()) - parseContext.getFullNamespaceName(fullName); - if (peekTokenClass(EHTokLeftParen)) { - // looks like function parameters - - // merge in the attributes into the return type - parseContext.transferTypeAttributes(token.loc, declarator.attributes, declaredType, true); - - // Potentially rename shader entry point function. No-op most of the time. - parseContext.renameShaderFunction(fullName); - - // function_parameters - declarator.function = new TFunction(fullName, declaredType); - if (!acceptFunctionParameters(*declarator.function)) { - expected("function parameter list"); - return false; - } - - // post_decls - acceptPostDecls(declarator.function->getWritableType().getQualifier()); - - // compound_statement (function body definition) or just a prototype? - declarator.loc = token.loc; - if (peekTokenClass(EHTokLeftBrace)) { - if (declarator_list) - parseContext.error(idToken.loc, "function body can't be in a declarator list", "{", ""); - if (typedefDecl) - parseContext.error(idToken.loc, "function body can't be in a typedef", "{", ""); - return acceptFunctionDefinition(declarator, nodeList, nullptr); - } else { - if (typedefDecl) - parseContext.error(idToken.loc, "function typedefs not implemented", "{", ""); - parseContext.handleFunctionDeclarator(declarator.loc, *declarator.function, true); - } - } else { - // A variable declaration. - - // merge in the attributes, the first time around, into the shared type - if (! declarator_list) - parseContext.transferTypeAttributes(token.loc, declarator.attributes, declaredType); - - // Fix the storage qualifier if it's a global. - if (declaredType.getQualifier().storage == EvqTemporary && parseContext.symbolTable.atGlobalLevel()) - declaredType.getQualifier().storage = EvqUniform; - - // recognize array_specifier - TArraySizes* arraySizes = nullptr; - acceptArraySpecifier(arraySizes); - - // We can handle multiple variables per type declaration, so - // the number of types can expand when arrayness is different. - TType variableType; - variableType.shallowCopy(declaredType); - - // In the most general case, arrayness is potentially coming both from the - // declared type and from the variable: "int[] a[];" or just one or the other. - // Merge it all to the variableType, so all arrayness is part of the variableType. - variableType.transferArraySizes(arraySizes); - variableType.copyArrayInnerSizes(declaredType.getArraySizes()); - - // samplers accept immediate sampler state - if (variableType.getBasicType() == EbtSampler) { - if (! acceptSamplerState()) - return false; - } - - // post_decls - acceptPostDecls(variableType.getQualifier()); - - // EQUAL assignment_expression - TIntermTyped* expressionNode = nullptr; - if (acceptTokenClass(EHTokAssign)) { - if (typedefDecl) - parseContext.error(idToken.loc, "can't have an initializer", "typedef", ""); - if (! acceptAssignmentExpression(expressionNode)) { - expected("initializer"); - return false; - } - } - - // TODO: things scoped within an annotation need their own name space; - // TODO: strings are not yet handled. - if (variableType.getBasicType() != EbtString && parseContext.getAnnotationNestingLevel() == 0) { - if (typedefDecl) - parseContext.declareTypedef(idToken.loc, *fullName, variableType); - else if (variableType.getBasicType() == EbtBlock) { - if (expressionNode) - parseContext.error(idToken.loc, "buffer aliasing not yet supported", "block initializer", ""); - parseContext.declareBlock(idToken.loc, variableType, fullName); - parseContext.declareStructBufferCounter(idToken.loc, variableType, *fullName); - } else { - if (variableType.getQualifier().storage == EvqUniform && ! variableType.containsOpaque()) { - // this isn't really an individual variable, but a member of the $Global buffer - parseContext.growGlobalUniformBlock(idToken.loc, variableType, *fullName); - } else { - // Declare the variable and add any initializer code to the AST. - // The top-level node is always made into an aggregate, as that's - // historically how the AST has been. - initializers = intermediate.growAggregate(initializers, - parseContext.declareVariable(idToken.loc, *fullName, variableType, expressionNode), - idToken.loc); - } - } - } - } - - // COMMA - if (acceptTokenClass(EHTokComma)) - declarator_list = true; - } - - // The top-level initializer node is a sequence. - if (initializers != nullptr) - initializers->setOperator(EOpSequence); - - // Add the initializers' aggregate to the nodeList we were handed. - if (nodeList) - nodeList = intermediate.growAggregate(nodeList, initializers); - else - nodeList = initializers; - - // SEMICOLON - if (! acceptTokenClass(EHTokSemicolon)) { - // This may have been a false detection of what appeared to be a declaration, but - // was actually an assignment such as "float = 4", where "float" is an identifier. - // We put the token back to let further parsing happen for cases where that may - // happen. This errors on the side of caution, and mostly triggers the error. - if (peek() == EHTokAssign || peek() == EHTokLeftBracket || peek() == EHTokDot || peek() == EHTokComma) { - recedeToken(); - return false; - } else { - expected(";"); - return false; - } - } - - return true; -} - -// control_declaration -// : fully_specified_type identifier EQUAL expression -// -bool HlslGrammar::acceptControlDeclaration(TIntermNode*& node) -{ - node = nullptr; - TAttributes attributes; - - // fully_specified_type - TType type; - if (! acceptFullySpecifiedType(type, attributes)) - return false; - - if (attributes.size() > 0) - parseContext.warn(token.loc, "attributes don't apply to control declaration", "", ""); - - // filter out type casts - if (peekTokenClass(EHTokLeftParen)) { - recedeToken(); - return false; - } - - // identifier - HlslToken idToken; - if (! acceptIdentifier(idToken)) { - expected("identifier"); - return false; - } - - // EQUAL - TIntermTyped* expressionNode = nullptr; - if (! acceptTokenClass(EHTokAssign)) { - expected("="); - return false; - } - - // expression - if (! acceptExpression(expressionNode)) { - expected("initializer"); - return false; - } - - node = parseContext.declareVariable(idToken.loc, *idToken.string, type, expressionNode); - - return true; -} - -// fully_specified_type -// : type_specifier -// | type_qualifier type_specifier -// -bool HlslGrammar::acceptFullySpecifiedType(TType& type, const TAttributes& attributes) -{ - TIntermNode* nodeList = nullptr; - return acceptFullySpecifiedType(type, nodeList, attributes); -} -bool HlslGrammar::acceptFullySpecifiedType(TType& type, TIntermNode*& nodeList, const TAttributes& attributes, bool forbidDeclarators) -{ - // type_qualifier - TQualifier qualifier; - qualifier.clear(); - if (! acceptQualifier(qualifier)) - return false; - TSourceLoc loc = token.loc; - - // type_specifier - if (! acceptType(type, nodeList)) { - // If this is not a type, we may have inadvertently gone down a wrong path - // by parsing "sample", which can be treated like either an identifier or a - // qualifier. Back it out, if we did. - if (qualifier.sample) - recedeToken(); - - return false; - } - - if (type.getBasicType() == EbtBlock) { - // the type was a block, which set some parts of the qualifier - parseContext.mergeQualifiers(type.getQualifier(), qualifier); - - // merge in the attributes - parseContext.transferTypeAttributes(token.loc, attributes, type); - - // further, it can create an anonymous instance of the block - // (cbuffer and tbuffer don't consume the next identifier, and - // should set forbidDeclarators) - if (forbidDeclarators || peek() != EHTokIdentifier) - parseContext.declareBlock(loc, type); - } else { - // Some qualifiers are set when parsing the type. Merge those with - // whatever comes from acceptQualifier. - assert(qualifier.layoutFormat == ElfNone); - - qualifier.layoutFormat = type.getQualifier().layoutFormat; - qualifier.precision = type.getQualifier().precision; - - if (type.getQualifier().storage == EvqOut || - type.getQualifier().storage == EvqBuffer) { - qualifier.storage = type.getQualifier().storage; - qualifier.readonly = type.getQualifier().readonly; - } - - if (type.isBuiltIn()) - qualifier.builtIn = type.getQualifier().builtIn; - - type.getQualifier() = qualifier; - } - - return true; -} - -// type_qualifier -// : qualifier qualifier ... -// -// Zero or more of these, so this can't return false. -// -bool HlslGrammar::acceptQualifier(TQualifier& qualifier) -{ - do { - switch (peek()) { - case EHTokStatic: - qualifier.storage = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - break; - case EHTokExtern: - // TODO: no meaning in glslang? - break; - case EHTokShared: - // TODO: hint - break; - case EHTokGroupShared: - qualifier.storage = EvqShared; - break; - case EHTokUniform: - qualifier.storage = EvqUniform; - break; - case EHTokConst: - qualifier.storage = EvqConst; - break; - case EHTokVolatile: - qualifier.volatil = true; - break; - case EHTokLinear: - qualifier.smooth = true; - break; - case EHTokCentroid: - qualifier.centroid = true; - break; - case EHTokNointerpolation: - qualifier.flat = true; - break; - case EHTokNoperspective: - qualifier.nopersp = true; - break; - case EHTokSample: - qualifier.sample = true; - break; - case EHTokRowMajor: - qualifier.layoutMatrix = ElmColumnMajor; - break; - case EHTokColumnMajor: - qualifier.layoutMatrix = ElmRowMajor; - break; - case EHTokPrecise: - qualifier.noContraction = true; - break; - case EHTokIn: - qualifier.storage = (qualifier.storage == EvqOut) ? EvqInOut : EvqIn; - break; - case EHTokOut: - qualifier.storage = (qualifier.storage == EvqIn) ? EvqInOut : EvqOut; - break; - case EHTokInOut: - qualifier.storage = EvqInOut; - break; - case EHTokLayout: - if (! acceptLayoutQualifierList(qualifier)) - return false; - continue; - case EHTokGloballyCoherent: - qualifier.coherent = true; - break; - case EHTokInline: - // TODO: map this to SPIR-V function control - break; - - // GS geometries: these are specified on stage input variables, and are an error (not verified here) - // for output variables. - case EHTokPoint: - qualifier.storage = EvqIn; - if (!parseContext.handleInputGeometry(token.loc, ElgPoints)) - return false; - break; - case EHTokLine: - qualifier.storage = EvqIn; - if (!parseContext.handleInputGeometry(token.loc, ElgLines)) - return false; - break; - case EHTokTriangle: - qualifier.storage = EvqIn; - if (!parseContext.handleInputGeometry(token.loc, ElgTriangles)) - return false; - break; - case EHTokLineAdj: - qualifier.storage = EvqIn; - if (!parseContext.handleInputGeometry(token.loc, ElgLinesAdjacency)) - return false; - break; - case EHTokTriangleAdj: - qualifier.storage = EvqIn; - if (!parseContext.handleInputGeometry(token.loc, ElgTrianglesAdjacency)) - return false; - break; - - default: - return true; - } - advanceToken(); - } while (true); -} - -// layout_qualifier_list -// : LAYOUT LEFT_PAREN layout_qualifier COMMA layout_qualifier ... RIGHT_PAREN -// -// layout_qualifier -// : identifier -// | identifier EQUAL expression -// -// Zero or more of these, so this can't return false. -// -bool HlslGrammar::acceptLayoutQualifierList(TQualifier& qualifier) -{ - if (! acceptTokenClass(EHTokLayout)) - return false; - - // LEFT_PAREN - if (! acceptTokenClass(EHTokLeftParen)) - return false; - - do { - // identifier - HlslToken idToken; - if (! acceptIdentifier(idToken)) - break; - - // EQUAL expression - if (acceptTokenClass(EHTokAssign)) { - TIntermTyped* expr; - if (! acceptConditionalExpression(expr)) { - expected("expression"); - return false; - } - parseContext.setLayoutQualifier(idToken.loc, qualifier, *idToken.string, expr); - } else - parseContext.setLayoutQualifier(idToken.loc, qualifier, *idToken.string); - - // COMMA - if (! acceptTokenClass(EHTokComma)) - break; - } while (true); - - // RIGHT_PAREN - if (! acceptTokenClass(EHTokRightParen)) { - expected(")"); - return false; - } - - return true; -} - -// template_type -// : FLOAT -// | DOUBLE -// | INT -// | DWORD -// | UINT -// | BOOL -// -bool HlslGrammar::acceptTemplateVecMatBasicType(TBasicType& basicType) -{ - switch (peek()) { - case EHTokFloat: - basicType = EbtFloat; - break; - case EHTokDouble: - basicType = EbtDouble; - break; - case EHTokInt: - case EHTokDword: - basicType = EbtInt; - break; - case EHTokUint: - basicType = EbtUint; - break; - case EHTokBool: - basicType = EbtBool; - break; - default: - return false; - } - - advanceToken(); - - return true; -} - -// vector_template_type -// : VECTOR -// | VECTOR LEFT_ANGLE template_type COMMA integer_literal RIGHT_ANGLE -// -bool HlslGrammar::acceptVectorTemplateType(TType& type) -{ - if (! acceptTokenClass(EHTokVector)) - return false; - - if (! acceptTokenClass(EHTokLeftAngle)) { - // in HLSL, 'vector' alone means float4. - new(&type) TType(EbtFloat, EvqTemporary, 4); - return true; - } - - TBasicType basicType; - if (! acceptTemplateVecMatBasicType(basicType)) { - expected("scalar type"); - return false; - } - - // COMMA - if (! acceptTokenClass(EHTokComma)) { - expected(","); - return false; - } - - // integer - if (! peekTokenClass(EHTokIntConstant)) { - expected("literal integer"); - return false; - } - - TIntermTyped* vecSize; - if (! acceptLiteral(vecSize)) - return false; - - const int vecSizeI = vecSize->getAsConstantUnion()->getConstArray()[0].getIConst(); - - new(&type) TType(basicType, EvqTemporary, vecSizeI); - - if (vecSizeI == 1) - type.makeVector(); - - if (!acceptTokenClass(EHTokRightAngle)) { - expected("right angle bracket"); - return false; - } - - return true; -} - -// matrix_template_type -// : MATRIX -// | MATRIX LEFT_ANGLE template_type COMMA integer_literal COMMA integer_literal RIGHT_ANGLE -// -bool HlslGrammar::acceptMatrixTemplateType(TType& type) -{ - if (! acceptTokenClass(EHTokMatrix)) - return false; - - if (! acceptTokenClass(EHTokLeftAngle)) { - // in HLSL, 'matrix' alone means float4x4. - new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 4); - return true; - } - - TBasicType basicType; - if (! acceptTemplateVecMatBasicType(basicType)) { - expected("scalar type"); - return false; - } - - // COMMA - if (! acceptTokenClass(EHTokComma)) { - expected(","); - return false; - } - - // integer rows - if (! peekTokenClass(EHTokIntConstant)) { - expected("literal integer"); - return false; - } - - TIntermTyped* rows; - if (! acceptLiteral(rows)) - return false; - - // COMMA - if (! acceptTokenClass(EHTokComma)) { - expected(","); - return false; - } - - // integer cols - if (! peekTokenClass(EHTokIntConstant)) { - expected("literal integer"); - return false; - } - - TIntermTyped* cols; - if (! acceptLiteral(cols)) - return false; - - new(&type) TType(basicType, EvqTemporary, 0, - rows->getAsConstantUnion()->getConstArray()[0].getIConst(), - cols->getAsConstantUnion()->getConstArray()[0].getIConst()); - - if (!acceptTokenClass(EHTokRightAngle)) { - expected("right angle bracket"); - return false; - } - - return true; -} - -// layout_geometry -// : LINESTREAM -// | POINTSTREAM -// | TRIANGLESTREAM -// -bool HlslGrammar::acceptOutputPrimitiveGeometry(TLayoutGeometry& geometry) -{ - // read geometry type - const EHlslTokenClass geometryType = peek(); - - switch (geometryType) { - case EHTokPointStream: geometry = ElgPoints; break; - case EHTokLineStream: geometry = ElgLineStrip; break; - case EHTokTriangleStream: geometry = ElgTriangleStrip; break; - default: - return false; // not a layout geometry - } - - advanceToken(); // consume the layout keyword - return true; -} - -// tessellation_decl_type -// : INPUTPATCH -// | OUTPUTPATCH -// -bool HlslGrammar::acceptTessellationDeclType(TBuiltInVariable& patchType) -{ - // read geometry type - const EHlslTokenClass tessType = peek(); - - switch (tessType) { - case EHTokInputPatch: patchType = EbvInputPatch; break; - case EHTokOutputPatch: patchType = EbvOutputPatch; break; - default: - return false; // not a tessellation decl - } - - advanceToken(); // consume the keyword - return true; -} - -// tessellation_patch_template_type -// : tessellation_decl_type LEFT_ANGLE type comma integer_literal RIGHT_ANGLE -// -bool HlslGrammar::acceptTessellationPatchTemplateType(TType& type) -{ - TBuiltInVariable patchType; - - if (! acceptTessellationDeclType(patchType)) - return false; - - if (! acceptTokenClass(EHTokLeftAngle)) - return false; - - if (! acceptType(type)) { - expected("tessellation patch type"); - return false; - } - - if (! acceptTokenClass(EHTokComma)) - return false; - - // integer size - if (! peekTokenClass(EHTokIntConstant)) { - expected("literal integer"); - return false; - } - - TIntermTyped* size; - if (! acceptLiteral(size)) - return false; - - TArraySizes* arraySizes = new TArraySizes; - arraySizes->addInnerSize(size->getAsConstantUnion()->getConstArray()[0].getIConst()); - type.transferArraySizes(arraySizes); - type.getQualifier().builtIn = patchType; - - if (! acceptTokenClass(EHTokRightAngle)) { - expected("right angle bracket"); - return false; - } - - return true; -} - -// stream_out_template_type -// : output_primitive_geometry_type LEFT_ANGLE type RIGHT_ANGLE -// -bool HlslGrammar::acceptStreamOutTemplateType(TType& type, TLayoutGeometry& geometry) -{ - geometry = ElgNone; - - if (! acceptOutputPrimitiveGeometry(geometry)) - return false; - - if (! acceptTokenClass(EHTokLeftAngle)) - return false; - - if (! acceptType(type)) { - expected("stream output type"); - return false; - } - - type.getQualifier().storage = EvqOut; - type.getQualifier().builtIn = EbvGsOutputStream; - - if (! acceptTokenClass(EHTokRightAngle)) { - expected("right angle bracket"); - return false; - } - - return true; -} - -// annotations -// : LEFT_ANGLE declaration SEMI_COLON ... declaration SEMICOLON RIGHT_ANGLE -// -bool HlslGrammar::acceptAnnotations(TQualifier&) -{ - if (! acceptTokenClass(EHTokLeftAngle)) - return false; - - // note that we are nesting a name space - parseContext.nestAnnotations(); - - // declaration SEMI_COLON ... declaration SEMICOLON RIGHT_ANGLE - do { - // eat any extra SEMI_COLON; don't know if the grammar calls for this or not - while (acceptTokenClass(EHTokSemicolon)) - ; - - if (acceptTokenClass(EHTokRightAngle)) - break; - - // declaration - TIntermNode* node = nullptr; - if (! acceptDeclaration(node)) { - expected("declaration in annotation"); - return false; - } - } while (true); - - parseContext.unnestAnnotations(); - return true; -} - -// subpass input type -// : SUBPASSINPUT -// | SUBPASSINPUT VECTOR LEFT_ANGLE template_type RIGHT_ANGLE -// | SUBPASSINPUTMS -// | SUBPASSINPUTMS VECTOR LEFT_ANGLE template_type RIGHT_ANGLE -bool HlslGrammar::acceptSubpassInputType(TType& type) -{ - // read subpass type - const EHlslTokenClass subpassInputType = peek(); - - bool multisample; - - switch (subpassInputType) { - case EHTokSubpassInput: multisample = false; break; - case EHTokSubpassInputMS: multisample = true; break; - default: - return false; // not a subpass input declaration - } - - advanceToken(); // consume the sampler type keyword - - TType subpassType(EbtFloat, EvqUniform, 4); // default type is float4 - - if (acceptTokenClass(EHTokLeftAngle)) { - if (! acceptType(subpassType)) { - expected("scalar or vector type"); - return false; - } - - const TBasicType basicRetType = subpassType.getBasicType() ; - - switch (basicRetType) { - case EbtFloat: - case EbtUint: - case EbtInt: - case EbtStruct: - break; - default: - unimplemented("basic type in subpass input"); - return false; - } - - if (! acceptTokenClass(EHTokRightAngle)) { - expected("right angle bracket"); - return false; - } - } - - const TBasicType subpassBasicType = subpassType.isStruct() ? (*subpassType.getStruct())[0].type->getBasicType() - : subpassType.getBasicType(); - - TSampler sampler; - sampler.setSubpass(subpassBasicType, multisample); - - // Remember the declared return type. Function returns false on error. - if (!parseContext.setTextureReturnType(sampler, subpassType, token.loc)) - return false; - - type.shallowCopy(TType(sampler, EvqUniform)); - - return true; -} - -// sampler_type -// : SAMPLER -// | SAMPLER1D -// | SAMPLER2D -// | SAMPLER3D -// | SAMPLERCUBE -// | SAMPLERSTATE -// | SAMPLERCOMPARISONSTATE -bool HlslGrammar::acceptSamplerType(TType& type) -{ - // read sampler type - const EHlslTokenClass samplerType = peek(); - - // TODO: for DX9 - // TSamplerDim dim = EsdNone; - - bool isShadow = false; - - switch (samplerType) { - case EHTokSampler: break; - case EHTokSampler1d: /*dim = Esd1D*/; break; - case EHTokSampler2d: /*dim = Esd2D*/; break; - case EHTokSampler3d: /*dim = Esd3D*/; break; - case EHTokSamplerCube: /*dim = EsdCube*/; break; - case EHTokSamplerState: break; - case EHTokSamplerComparisonState: isShadow = true; break; - default: - return false; // not a sampler declaration - } - - advanceToken(); // consume the sampler type keyword - - TArraySizes* arraySizes = nullptr; // TODO: array - - TSampler sampler; - sampler.setPureSampler(isShadow); - - type.shallowCopy(TType(sampler, EvqUniform, arraySizes)); - - return true; -} - -// texture_type -// | BUFFER -// | TEXTURE1D -// | TEXTURE1DARRAY -// | TEXTURE2D -// | TEXTURE2DARRAY -// | TEXTURE3D -// | TEXTURECUBE -// | TEXTURECUBEARRAY -// | TEXTURE2DMS -// | TEXTURE2DMSARRAY -// | RWBUFFER -// | RWTEXTURE1D -// | RWTEXTURE1DARRAY -// | RWTEXTURE2D -// | RWTEXTURE2DARRAY -// | RWTEXTURE3D - -bool HlslGrammar::acceptTextureType(TType& type) -{ - const EHlslTokenClass textureType = peek(); - - TSamplerDim dim = EsdNone; - bool array = false; - bool ms = false; - bool image = false; - bool combined = true; - - switch (textureType) { - case EHTokBuffer: dim = EsdBuffer; combined = false; break; - case EHTokTexture1d: dim = Esd1D; break; - case EHTokTexture1darray: dim = Esd1D; array = true; break; - case EHTokTexture2d: dim = Esd2D; break; - case EHTokTexture2darray: dim = Esd2D; array = true; break; - case EHTokTexture3d: dim = Esd3D; break; - case EHTokTextureCube: dim = EsdCube; break; - case EHTokTextureCubearray: dim = EsdCube; array = true; break; - case EHTokTexture2DMS: dim = Esd2D; ms = true; break; - case EHTokTexture2DMSarray: dim = Esd2D; array = true; ms = true; break; - case EHTokRWBuffer: dim = EsdBuffer; image=true; break; - case EHTokRWTexture1d: dim = Esd1D; array=false; image=true; break; - case EHTokRWTexture1darray: dim = Esd1D; array=true; image=true; break; - case EHTokRWTexture2d: dim = Esd2D; array=false; image=true; break; - case EHTokRWTexture2darray: dim = Esd2D; array=true; image=true; break; - case EHTokRWTexture3d: dim = Esd3D; array=false; image=true; break; - default: - return false; // not a texture declaration - } - - advanceToken(); // consume the texture object keyword - - TType txType(EbtFloat, EvqUniform, 4); // default type is float4 - - TIntermTyped* msCount = nullptr; - - // texture type: required for multisample types and RWBuffer/RWTextures! - if (acceptTokenClass(EHTokLeftAngle)) { - if (! acceptType(txType)) { - expected("scalar or vector type"); - return false; - } - - const TBasicType basicRetType = txType.getBasicType() ; - - switch (basicRetType) { - case EbtFloat: - case EbtUint: - case EbtInt: - case EbtStruct: - break; - default: - unimplemented("basic type in texture"); - return false; - } - - // Buffers can handle small mats if they fit in 4 components - if (dim == EsdBuffer && txType.isMatrix()) { - if ((txType.getMatrixCols() * txType.getMatrixRows()) > 4) { - expected("components < 4 in matrix buffer type"); - return false; - } - - // TODO: except we don't handle it yet... - unimplemented("matrix type in buffer"); - return false; - } - - if (!txType.isScalar() && !txType.isVector() && !txType.isStruct()) { - expected("scalar, vector, or struct type"); - return false; - } - - if (ms && acceptTokenClass(EHTokComma)) { - // read sample count for multisample types, if given - if (! peekTokenClass(EHTokIntConstant)) { - expected("multisample count"); - return false; - } - - if (! acceptLiteral(msCount)) // should never fail, since we just found an integer - return false; - } - - if (! acceptTokenClass(EHTokRightAngle)) { - expected("right angle bracket"); - return false; - } - } else if (ms) { - expected("texture type for multisample"); - return false; - } else if (image) { - expected("type for RWTexture/RWBuffer"); - return false; - } - - TArraySizes* arraySizes = nullptr; - const bool shadow = false; // declared on the sampler - - TSampler sampler; - TLayoutFormat format = ElfNone; - - // Buffer, RWBuffer and RWTexture (images) require a TLayoutFormat. We handle only a limit set. - if (image || dim == EsdBuffer) - format = parseContext.getLayoutFromTxType(token.loc, txType); - - const TBasicType txBasicType = txType.isStruct() ? (*txType.getStruct())[0].type->getBasicType() - : txType.getBasicType(); - - // Non-image Buffers are combined - if (dim == EsdBuffer && !image) { - sampler.set(txType.getBasicType(), dim, array); - } else { - // DX10 textures are separated. TODO: DX9. - if (image) { - sampler.setImage(txBasicType, dim, array, shadow, ms); - } else { - sampler.setTexture(txBasicType, dim, array, shadow, ms); - } - } - - // Remember the declared return type. Function returns false on error. - if (!parseContext.setTextureReturnType(sampler, txType, token.loc)) - return false; - - // Force uncombined, if necessary - if (!combined) - sampler.combined = false; - - type.shallowCopy(TType(sampler, EvqUniform, arraySizes)); - type.getQualifier().layoutFormat = format; - - return true; -} - -// If token is for a type, update 'type' with the type information, -// and return true and advance. -// Otherwise, return false, and don't advance -bool HlslGrammar::acceptType(TType& type) -{ - TIntermNode* nodeList = nullptr; - return acceptType(type, nodeList); -} -bool HlslGrammar::acceptType(TType& type, TIntermNode*& nodeList) -{ - // Basic types for min* types, use native halfs if the option allows them. - bool enable16BitTypes = parseContext.hlslEnable16BitTypes(); - - const TBasicType min16float_bt = enable16BitTypes ? EbtFloat16 : EbtFloat; - const TBasicType min10float_bt = enable16BitTypes ? EbtFloat16 : EbtFloat; - const TBasicType half_bt = enable16BitTypes ? EbtFloat16 : EbtFloat; - const TBasicType min16int_bt = enable16BitTypes ? EbtInt16 : EbtInt; - const TBasicType min12int_bt = enable16BitTypes ? EbtInt16 : EbtInt; - const TBasicType min16uint_bt = enable16BitTypes ? EbtUint16 : EbtUint; - - // Some types might have turned into identifiers. Take the hit for checking - // when this has happened. - if (typeIdentifiers) { - const char* identifierString = getTypeString(peek()); - if (identifierString != nullptr) { - TString name = identifierString; - // if it's an identifier, it's not a type - if (parseContext.symbolTable.find(name) != nullptr) - return false; - } - } - - bool isUnorm = false; - bool isSnorm = false; - - // Accept snorm and unorm. Presently, this is ignored, save for an error check below. - switch (peek()) { - case EHTokUnorm: - isUnorm = true; - advanceToken(); // eat the token - break; - case EHTokSNorm: - isSnorm = true; - advanceToken(); // eat the token - break; - default: - break; - } - - switch (peek()) { - case EHTokVector: - return acceptVectorTemplateType(type); - break; - - case EHTokMatrix: - return acceptMatrixTemplateType(type); - break; - - case EHTokPointStream: // fall through - case EHTokLineStream: // ... - case EHTokTriangleStream: // ... - { - TLayoutGeometry geometry; - if (! acceptStreamOutTemplateType(type, geometry)) - return false; - - if (! parseContext.handleOutputGeometry(token.loc, geometry)) - return false; - - return true; - } - - case EHTokInputPatch: // fall through - case EHTokOutputPatch: // ... - { - if (! acceptTessellationPatchTemplateType(type)) - return false; - - return true; - } - - case EHTokSampler: // fall through - case EHTokSampler1d: // ... - case EHTokSampler2d: // ... - case EHTokSampler3d: // ... - case EHTokSamplerCube: // ... - case EHTokSamplerState: // ... - case EHTokSamplerComparisonState: // ... - return acceptSamplerType(type); - break; - - case EHTokSubpassInput: // fall through - case EHTokSubpassInputMS: // ... - return acceptSubpassInputType(type); - break; - - case EHTokBuffer: // fall through - case EHTokTexture1d: // ... - case EHTokTexture1darray: // ... - case EHTokTexture2d: // ... - case EHTokTexture2darray: // ... - case EHTokTexture3d: // ... - case EHTokTextureCube: // ... - case EHTokTextureCubearray: // ... - case EHTokTexture2DMS: // ... - case EHTokTexture2DMSarray: // ... - case EHTokRWTexture1d: // ... - case EHTokRWTexture1darray: // ... - case EHTokRWTexture2d: // ... - case EHTokRWTexture2darray: // ... - case EHTokRWTexture3d: // ... - case EHTokRWBuffer: // ... - return acceptTextureType(type); - break; - - case EHTokAppendStructuredBuffer: - case EHTokByteAddressBuffer: - case EHTokConsumeStructuredBuffer: - case EHTokRWByteAddressBuffer: - case EHTokRWStructuredBuffer: - case EHTokStructuredBuffer: - return acceptStructBufferType(type); - break; - - case EHTokTextureBuffer: - return acceptTextureBufferType(type); - break; - - case EHTokConstantBuffer: - return acceptConstantBufferType(type); - - case EHTokClass: - case EHTokStruct: - case EHTokCBuffer: - case EHTokTBuffer: - return acceptStruct(type, nodeList); - - case EHTokIdentifier: - // An identifier could be for a user-defined type. - // Note we cache the symbol table lookup, to save for a later rule - // when this is not a type. - if (parseContext.lookupUserType(*token.string, type) != nullptr) { - advanceToken(); - return true; - } else - return false; - - case EHTokVoid: - new(&type) TType(EbtVoid); - break; - - case EHTokString: - new(&type) TType(EbtString); - break; - - case EHTokFloat: - new(&type) TType(EbtFloat); - break; - case EHTokFloat1: - new(&type) TType(EbtFloat); - type.makeVector(); - break; - case EHTokFloat2: - new(&type) TType(EbtFloat, EvqTemporary, 2); - break; - case EHTokFloat3: - new(&type) TType(EbtFloat, EvqTemporary, 3); - break; - case EHTokFloat4: - new(&type) TType(EbtFloat, EvqTemporary, 4); - break; - - case EHTokDouble: - new(&type) TType(EbtDouble); - break; - case EHTokDouble1: - new(&type) TType(EbtDouble); - type.makeVector(); - break; - case EHTokDouble2: - new(&type) TType(EbtDouble, EvqTemporary, 2); - break; - case EHTokDouble3: - new(&type) TType(EbtDouble, EvqTemporary, 3); - break; - case EHTokDouble4: - new(&type) TType(EbtDouble, EvqTemporary, 4); - break; - - case EHTokInt: - case EHTokDword: - new(&type) TType(EbtInt); - break; - case EHTokInt1: - new(&type) TType(EbtInt); - type.makeVector(); - break; - case EHTokInt2: - new(&type) TType(EbtInt, EvqTemporary, 2); - break; - case EHTokInt3: - new(&type) TType(EbtInt, EvqTemporary, 3); - break; - case EHTokInt4: - new(&type) TType(EbtInt, EvqTemporary, 4); - break; - - case EHTokUint: - new(&type) TType(EbtUint); - break; - case EHTokUint1: - new(&type) TType(EbtUint); - type.makeVector(); - break; - case EHTokUint2: - new(&type) TType(EbtUint, EvqTemporary, 2); - break; - case EHTokUint3: - new(&type) TType(EbtUint, EvqTemporary, 3); - break; - case EHTokUint4: - new(&type) TType(EbtUint, EvqTemporary, 4); - break; - - case EHTokUint64: - new(&type) TType(EbtUint64); - break; - - case EHTokBool: - new(&type) TType(EbtBool); - break; - case EHTokBool1: - new(&type) TType(EbtBool); - type.makeVector(); - break; - case EHTokBool2: - new(&type) TType(EbtBool, EvqTemporary, 2); - break; - case EHTokBool3: - new(&type) TType(EbtBool, EvqTemporary, 3); - break; - case EHTokBool4: - new(&type) TType(EbtBool, EvqTemporary, 4); - break; - - case EHTokHalf: - new(&type) TType(half_bt, EvqTemporary); - break; - case EHTokHalf1: - new(&type) TType(half_bt, EvqTemporary); - type.makeVector(); - break; - case EHTokHalf2: - new(&type) TType(half_bt, EvqTemporary, 2); - break; - case EHTokHalf3: - new(&type) TType(half_bt, EvqTemporary, 3); - break; - case EHTokHalf4: - new(&type) TType(half_bt, EvqTemporary, 4); - break; - - case EHTokMin16float: - new(&type) TType(min16float_bt, EvqTemporary, EpqMedium); - break; - case EHTokMin16float1: - new(&type) TType(min16float_bt, EvqTemporary, EpqMedium); - type.makeVector(); - break; - case EHTokMin16float2: - new(&type) TType(min16float_bt, EvqTemporary, EpqMedium, 2); - break; - case EHTokMin16float3: - new(&type) TType(min16float_bt, EvqTemporary, EpqMedium, 3); - break; - case EHTokMin16float4: - new(&type) TType(min16float_bt, EvqTemporary, EpqMedium, 4); - break; - - case EHTokMin10float: - new(&type) TType(min10float_bt, EvqTemporary, EpqMedium); - break; - case EHTokMin10float1: - new(&type) TType(min10float_bt, EvqTemporary, EpqMedium); - type.makeVector(); - break; - case EHTokMin10float2: - new(&type) TType(min10float_bt, EvqTemporary, EpqMedium, 2); - break; - case EHTokMin10float3: - new(&type) TType(min10float_bt, EvqTemporary, EpqMedium, 3); - break; - case EHTokMin10float4: - new(&type) TType(min10float_bt, EvqTemporary, EpqMedium, 4); - break; - - case EHTokMin16int: - new(&type) TType(min16int_bt, EvqTemporary, EpqMedium); - break; - case EHTokMin16int1: - new(&type) TType(min16int_bt, EvqTemporary, EpqMedium); - type.makeVector(); - break; - case EHTokMin16int2: - new(&type) TType(min16int_bt, EvqTemporary, EpqMedium, 2); - break; - case EHTokMin16int3: - new(&type) TType(min16int_bt, EvqTemporary, EpqMedium, 3); - break; - case EHTokMin16int4: - new(&type) TType(min16int_bt, EvqTemporary, EpqMedium, 4); - break; - - case EHTokMin12int: - new(&type) TType(min12int_bt, EvqTemporary, EpqMedium); - break; - case EHTokMin12int1: - new(&type) TType(min12int_bt, EvqTemporary, EpqMedium); - type.makeVector(); - break; - case EHTokMin12int2: - new(&type) TType(min12int_bt, EvqTemporary, EpqMedium, 2); - break; - case EHTokMin12int3: - new(&type) TType(min12int_bt, EvqTemporary, EpqMedium, 3); - break; - case EHTokMin12int4: - new(&type) TType(min12int_bt, EvqTemporary, EpqMedium, 4); - break; - - case EHTokMin16uint: - new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium); - break; - case EHTokMin16uint1: - new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium); - type.makeVector(); - break; - case EHTokMin16uint2: - new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium, 2); - break; - case EHTokMin16uint3: - new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium, 3); - break; - case EHTokMin16uint4: - new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium, 4); - break; - - case EHTokInt1x1: - new(&type) TType(EbtInt, EvqTemporary, 0, 1, 1); - break; - case EHTokInt1x2: - new(&type) TType(EbtInt, EvqTemporary, 0, 1, 2); - break; - case EHTokInt1x3: - new(&type) TType(EbtInt, EvqTemporary, 0, 1, 3); - break; - case EHTokInt1x4: - new(&type) TType(EbtInt, EvqTemporary, 0, 1, 4); - break; - case EHTokInt2x1: - new(&type) TType(EbtInt, EvqTemporary, 0, 2, 1); - break; - case EHTokInt2x2: - new(&type) TType(EbtInt, EvqTemporary, 0, 2, 2); - break; - case EHTokInt2x3: - new(&type) TType(EbtInt, EvqTemporary, 0, 2, 3); - break; - case EHTokInt2x4: - new(&type) TType(EbtInt, EvqTemporary, 0, 2, 4); - break; - case EHTokInt3x1: - new(&type) TType(EbtInt, EvqTemporary, 0, 3, 1); - break; - case EHTokInt3x2: - new(&type) TType(EbtInt, EvqTemporary, 0, 3, 2); - break; - case EHTokInt3x3: - new(&type) TType(EbtInt, EvqTemporary, 0, 3, 3); - break; - case EHTokInt3x4: - new(&type) TType(EbtInt, EvqTemporary, 0, 3, 4); - break; - case EHTokInt4x1: - new(&type) TType(EbtInt, EvqTemporary, 0, 4, 1); - break; - case EHTokInt4x2: - new(&type) TType(EbtInt, EvqTemporary, 0, 4, 2); - break; - case EHTokInt4x3: - new(&type) TType(EbtInt, EvqTemporary, 0, 4, 3); - break; - case EHTokInt4x4: - new(&type) TType(EbtInt, EvqTemporary, 0, 4, 4); - break; - - case EHTokUint1x1: - new(&type) TType(EbtUint, EvqTemporary, 0, 1, 1); - break; - case EHTokUint1x2: - new(&type) TType(EbtUint, EvqTemporary, 0, 1, 2); - break; - case EHTokUint1x3: - new(&type) TType(EbtUint, EvqTemporary, 0, 1, 3); - break; - case EHTokUint1x4: - new(&type) TType(EbtUint, EvqTemporary, 0, 1, 4); - break; - case EHTokUint2x1: - new(&type) TType(EbtUint, EvqTemporary, 0, 2, 1); - break; - case EHTokUint2x2: - new(&type) TType(EbtUint, EvqTemporary, 0, 2, 2); - break; - case EHTokUint2x3: - new(&type) TType(EbtUint, EvqTemporary, 0, 2, 3); - break; - case EHTokUint2x4: - new(&type) TType(EbtUint, EvqTemporary, 0, 2, 4); - break; - case EHTokUint3x1: - new(&type) TType(EbtUint, EvqTemporary, 0, 3, 1); - break; - case EHTokUint3x2: - new(&type) TType(EbtUint, EvqTemporary, 0, 3, 2); - break; - case EHTokUint3x3: - new(&type) TType(EbtUint, EvqTemporary, 0, 3, 3); - break; - case EHTokUint3x4: - new(&type) TType(EbtUint, EvqTemporary, 0, 3, 4); - break; - case EHTokUint4x1: - new(&type) TType(EbtUint, EvqTemporary, 0, 4, 1); - break; - case EHTokUint4x2: - new(&type) TType(EbtUint, EvqTemporary, 0, 4, 2); - break; - case EHTokUint4x3: - new(&type) TType(EbtUint, EvqTemporary, 0, 4, 3); - break; - case EHTokUint4x4: - new(&type) TType(EbtUint, EvqTemporary, 0, 4, 4); - break; - - case EHTokBool1x1: - new(&type) TType(EbtBool, EvqTemporary, 0, 1, 1); - break; - case EHTokBool1x2: - new(&type) TType(EbtBool, EvqTemporary, 0, 1, 2); - break; - case EHTokBool1x3: - new(&type) TType(EbtBool, EvqTemporary, 0, 1, 3); - break; - case EHTokBool1x4: - new(&type) TType(EbtBool, EvqTemporary, 0, 1, 4); - break; - case EHTokBool2x1: - new(&type) TType(EbtBool, EvqTemporary, 0, 2, 1); - break; - case EHTokBool2x2: - new(&type) TType(EbtBool, EvqTemporary, 0, 2, 2); - break; - case EHTokBool2x3: - new(&type) TType(EbtBool, EvqTemporary, 0, 2, 3); - break; - case EHTokBool2x4: - new(&type) TType(EbtBool, EvqTemporary, 0, 2, 4); - break; - case EHTokBool3x1: - new(&type) TType(EbtBool, EvqTemporary, 0, 3, 1); - break; - case EHTokBool3x2: - new(&type) TType(EbtBool, EvqTemporary, 0, 3, 2); - break; - case EHTokBool3x3: - new(&type) TType(EbtBool, EvqTemporary, 0, 3, 3); - break; - case EHTokBool3x4: - new(&type) TType(EbtBool, EvqTemporary, 0, 3, 4); - break; - case EHTokBool4x1: - new(&type) TType(EbtBool, EvqTemporary, 0, 4, 1); - break; - case EHTokBool4x2: - new(&type) TType(EbtBool, EvqTemporary, 0, 4, 2); - break; - case EHTokBool4x3: - new(&type) TType(EbtBool, EvqTemporary, 0, 4, 3); - break; - case EHTokBool4x4: - new(&type) TType(EbtBool, EvqTemporary, 0, 4, 4); - break; - - case EHTokFloat1x1: - new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 1); - break; - case EHTokFloat1x2: - new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 2); - break; - case EHTokFloat1x3: - new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 3); - break; - case EHTokFloat1x4: - new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 4); - break; - case EHTokFloat2x1: - new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 1); - break; - case EHTokFloat2x2: - new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 2); - break; - case EHTokFloat2x3: - new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 3); - break; - case EHTokFloat2x4: - new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 4); - break; - case EHTokFloat3x1: - new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 1); - break; - case EHTokFloat3x2: - new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 2); - break; - case EHTokFloat3x3: - new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 3); - break; - case EHTokFloat3x4: - new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 4); - break; - case EHTokFloat4x1: - new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 1); - break; - case EHTokFloat4x2: - new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 2); - break; - case EHTokFloat4x3: - new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 3); - break; - case EHTokFloat4x4: - new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 4); - break; - - case EHTokHalf1x1: - new(&type) TType(half_bt, EvqTemporary, 0, 1, 1); - break; - case EHTokHalf1x2: - new(&type) TType(half_bt, EvqTemporary, 0, 1, 2); - break; - case EHTokHalf1x3: - new(&type) TType(half_bt, EvqTemporary, 0, 1, 3); - break; - case EHTokHalf1x4: - new(&type) TType(half_bt, EvqTemporary, 0, 1, 4); - break; - case EHTokHalf2x1: - new(&type) TType(half_bt, EvqTemporary, 0, 2, 1); - break; - case EHTokHalf2x2: - new(&type) TType(half_bt, EvqTemporary, 0, 2, 2); - break; - case EHTokHalf2x3: - new(&type) TType(half_bt, EvqTemporary, 0, 2, 3); - break; - case EHTokHalf2x4: - new(&type) TType(half_bt, EvqTemporary, 0, 2, 4); - break; - case EHTokHalf3x1: - new(&type) TType(half_bt, EvqTemporary, 0, 3, 1); - break; - case EHTokHalf3x2: - new(&type) TType(half_bt, EvqTemporary, 0, 3, 2); - break; - case EHTokHalf3x3: - new(&type) TType(half_bt, EvqTemporary, 0, 3, 3); - break; - case EHTokHalf3x4: - new(&type) TType(half_bt, EvqTemporary, 0, 3, 4); - break; - case EHTokHalf4x1: - new(&type) TType(half_bt, EvqTemporary, 0, 4, 1); - break; - case EHTokHalf4x2: - new(&type) TType(half_bt, EvqTemporary, 0, 4, 2); - break; - case EHTokHalf4x3: - new(&type) TType(half_bt, EvqTemporary, 0, 4, 3); - break; - case EHTokHalf4x4: - new(&type) TType(half_bt, EvqTemporary, 0, 4, 4); - break; - - case EHTokDouble1x1: - new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 1); - break; - case EHTokDouble1x2: - new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 2); - break; - case EHTokDouble1x3: - new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 3); - break; - case EHTokDouble1x4: - new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 4); - break; - case EHTokDouble2x1: - new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 1); - break; - case EHTokDouble2x2: - new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 2); - break; - case EHTokDouble2x3: - new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 3); - break; - case EHTokDouble2x4: - new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 4); - break; - case EHTokDouble3x1: - new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 1); - break; - case EHTokDouble3x2: - new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 2); - break; - case EHTokDouble3x3: - new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 3); - break; - case EHTokDouble3x4: - new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 4); - break; - case EHTokDouble4x1: - new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 1); - break; - case EHTokDouble4x2: - new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 2); - break; - case EHTokDouble4x3: - new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 3); - break; - case EHTokDouble4x4: - new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 4); - break; - - default: - return false; - } - - advanceToken(); - - if ((isUnorm || isSnorm) && !type.isFloatingDomain()) { - parseContext.error(token.loc, "unorm and snorm only valid in floating point domain", "", ""); - return false; - } - - return true; -} - -// struct -// : struct_type IDENTIFIER post_decls LEFT_BRACE struct_declaration_list RIGHT_BRACE -// | struct_type post_decls LEFT_BRACE struct_declaration_list RIGHT_BRACE -// | struct_type IDENTIFIER // use of previously declared struct type -// -// struct_type -// : STRUCT -// | CLASS -// | CBUFFER -// | TBUFFER -// -bool HlslGrammar::acceptStruct(TType& type, TIntermNode*& nodeList) -{ - // This storage qualifier will tell us whether it's an AST - // block type or just a generic structure type. - TStorageQualifier storageQualifier = EvqTemporary; - bool readonly = false; - - if (acceptTokenClass(EHTokCBuffer)) { - // CBUFFER - storageQualifier = EvqUniform; - } else if (acceptTokenClass(EHTokTBuffer)) { - // TBUFFER - storageQualifier = EvqBuffer; - readonly = true; - } else if (! acceptTokenClass(EHTokClass) && ! acceptTokenClass(EHTokStruct)) { - // Neither CLASS nor STRUCT - return false; - } - - // Now known to be one of CBUFFER, TBUFFER, CLASS, or STRUCT - - - // IDENTIFIER. It might also be a keyword which can double as an identifier. - // For example: 'cbuffer ConstantBuffer' or 'struct ConstantBuffer' is legal. - // 'cbuffer int' is also legal, and 'struct int' appears rejected only because - // it attempts to redefine the 'int' type. - const char* idString = getTypeString(peek()); - TString structName = ""; - if (peekTokenClass(EHTokIdentifier) || idString != nullptr) { - if (idString != nullptr) - structName = *idString; - else - structName = *token.string; - advanceToken(); - } - - // post_decls - TQualifier postDeclQualifier; - postDeclQualifier.clear(); - bool postDeclsFound = acceptPostDecls(postDeclQualifier); - - // LEFT_BRACE, or - // struct_type IDENTIFIER - if (! acceptTokenClass(EHTokLeftBrace)) { - if (structName.size() > 0 && !postDeclsFound && parseContext.lookupUserType(structName, type) != nullptr) { - // struct_type IDENTIFIER - return true; - } else { - expected("{"); - return false; - } - } - - - // struct_declaration_list - TTypeList* typeList; - // Save each member function so they can be processed after we have a fully formed 'this'. - TVector functionDeclarators; - - parseContext.pushNamespace(structName); - bool acceptedList = acceptStructDeclarationList(typeList, nodeList, functionDeclarators); - parseContext.popNamespace(); - - if (! acceptedList) { - expected("struct member declarations"); - return false; - } - - // RIGHT_BRACE - if (! acceptTokenClass(EHTokRightBrace)) { - expected("}"); - return false; - } - - // create the user-defined type - if (storageQualifier == EvqTemporary) - new(&type) TType(typeList, structName); - else { - postDeclQualifier.storage = storageQualifier; - postDeclQualifier.readonly = readonly; - new(&type) TType(typeList, structName, postDeclQualifier); // sets EbtBlock - } - - parseContext.declareStruct(token.loc, structName, type); - - // For member functions: now that we know the type of 'this', go back and - // - add their implicit argument with 'this' (not to the mangling, just the argument list) - // - parse the functions, their tokens were saved for deferred parsing (now) - for (int b = 0; b < (int)functionDeclarators.size(); ++b) { - // update signature - if (functionDeclarators[b].function->hasImplicitThis()) - functionDeclarators[b].function->addThisParameter(type, intermediate.implicitThisName); - } - - // All member functions get parsed inside the class/struct namespace and with the - // class/struct members in a symbol-table level. - parseContext.pushNamespace(structName); - parseContext.pushThisScope(type, functionDeclarators); - bool deferredSuccess = true; - for (int b = 0; b < (int)functionDeclarators.size() && deferredSuccess; ++b) { - // parse body - pushTokenStream(functionDeclarators[b].body); - if (! acceptFunctionBody(functionDeclarators[b], nodeList)) - deferredSuccess = false; - popTokenStream(); - } - parseContext.popThisScope(); - parseContext.popNamespace(); - - return deferredSuccess; -} - -// constantbuffer -// : CONSTANTBUFFER LEFT_ANGLE type RIGHT_ANGLE -bool HlslGrammar::acceptConstantBufferType(TType& type) -{ - if (! acceptTokenClass(EHTokConstantBuffer)) - return false; - - if (! acceptTokenClass(EHTokLeftAngle)) { - expected("left angle bracket"); - return false; - } - - TType templateType; - if (! acceptType(templateType)) { - expected("type"); - return false; - } - - if (! acceptTokenClass(EHTokRightAngle)) { - expected("right angle bracket"); - return false; - } - - TQualifier postDeclQualifier; - postDeclQualifier.clear(); - postDeclQualifier.storage = EvqUniform; - - if (templateType.isStruct()) { - // Make a block from the type parsed as the template argument - TTypeList* typeList = templateType.getWritableStruct(); - new(&type) TType(typeList, "", postDeclQualifier); // sets EbtBlock - - type.getQualifier().storage = EvqUniform; - - return true; - } else { - parseContext.error(token.loc, "non-structure type in ConstantBuffer", "", ""); - return false; - } -} - -// texture_buffer -// : TEXTUREBUFFER LEFT_ANGLE type RIGHT_ANGLE -bool HlslGrammar::acceptTextureBufferType(TType& type) -{ - if (! acceptTokenClass(EHTokTextureBuffer)) - return false; - - if (! acceptTokenClass(EHTokLeftAngle)) { - expected("left angle bracket"); - return false; - } - - TType templateType; - if (! acceptType(templateType)) { - expected("type"); - return false; - } - - if (! acceptTokenClass(EHTokRightAngle)) { - expected("right angle bracket"); - return false; - } - - templateType.getQualifier().storage = EvqBuffer; - templateType.getQualifier().readonly = true; - - TType blockType(templateType.getWritableStruct(), "", templateType.getQualifier()); - - blockType.getQualifier().storage = EvqBuffer; - blockType.getQualifier().readonly = true; - - type.shallowCopy(blockType); - - return true; -} - - -// struct_buffer -// : APPENDSTRUCTUREDBUFFER -// | BYTEADDRESSBUFFER -// | CONSUMESTRUCTUREDBUFFER -// | RWBYTEADDRESSBUFFER -// | RWSTRUCTUREDBUFFER -// | STRUCTUREDBUFFER -bool HlslGrammar::acceptStructBufferType(TType& type) -{ - const EHlslTokenClass structBuffType = peek(); - - // TODO: globallycoherent - bool hasTemplateType = true; - bool readonly = false; - - TStorageQualifier storage = EvqBuffer; - TBuiltInVariable builtinType = EbvNone; - - switch (structBuffType) { - case EHTokAppendStructuredBuffer: - builtinType = EbvAppendConsume; - break; - case EHTokByteAddressBuffer: - hasTemplateType = false; - readonly = true; - builtinType = EbvByteAddressBuffer; - break; - case EHTokConsumeStructuredBuffer: - builtinType = EbvAppendConsume; - break; - case EHTokRWByteAddressBuffer: - hasTemplateType = false; - builtinType = EbvRWByteAddressBuffer; - break; - case EHTokRWStructuredBuffer: - builtinType = EbvRWStructuredBuffer; - break; - case EHTokStructuredBuffer: - builtinType = EbvStructuredBuffer; - readonly = true; - break; - default: - return false; // not a structure buffer type - } - - advanceToken(); // consume the structure keyword - - // type on which this StructedBuffer is templatized. E.g, StructedBuffer ==> MyStruct - TType* templateType = new TType; - - if (hasTemplateType) { - if (! acceptTokenClass(EHTokLeftAngle)) { - expected("left angle bracket"); - return false; - } - - if (! acceptType(*templateType)) { - expected("type"); - return false; - } - if (! acceptTokenClass(EHTokRightAngle)) { - expected("right angle bracket"); - return false; - } - } else { - // byte address buffers have no explicit type. - TType uintType(EbtUint, storage); - templateType->shallowCopy(uintType); - } - - // Create an unsized array out of that type. - // TODO: does this work if it's already an array type? - TArraySizes* unsizedArray = new TArraySizes; - unsizedArray->addInnerSize(UnsizedArraySize); - templateType->transferArraySizes(unsizedArray); - templateType->getQualifier().storage = storage; - - // field name is canonical for all structbuffers - templateType->setFieldName("@data"); - - TTypeList* blockStruct = new TTypeList; - TTypeLoc member = { templateType, token.loc }; - blockStruct->push_back(member); - - // This is the type of the buffer block (SSBO) - TType blockType(blockStruct, "", templateType->getQualifier()); - - blockType.getQualifier().storage = storage; - blockType.getQualifier().readonly = readonly; - blockType.getQualifier().builtIn = builtinType; - - // We may have created an equivalent type before, in which case we should use its - // deep structure. - parseContext.shareStructBufferType(blockType); - - type.shallowCopy(blockType); - - return true; -} - -// struct_declaration_list -// : struct_declaration SEMI_COLON struct_declaration SEMI_COLON ... -// -// struct_declaration -// : attributes fully_specified_type struct_declarator COMMA struct_declarator ... -// | attributes fully_specified_type IDENTIFIER function_parameters post_decls compound_statement // member-function definition -// -// struct_declarator -// : IDENTIFIER post_decls -// | IDENTIFIER array_specifier post_decls -// | IDENTIFIER function_parameters post_decls // member-function prototype -// -bool HlslGrammar::acceptStructDeclarationList(TTypeList*& typeList, TIntermNode*& nodeList, - TVector& declarators) -{ - typeList = new TTypeList(); - HlslToken idToken; - - do { - // success on seeing the RIGHT_BRACE coming up - if (peekTokenClass(EHTokRightBrace)) - break; - - // struct_declaration - - // attributes - TAttributes attributes; - acceptAttributes(attributes); - - bool declarator_list = false; - - // fully_specified_type - TType memberType; - if (! acceptFullySpecifiedType(memberType, nodeList, attributes)) { - expected("member type"); - return false; - } - - // merge in the attributes - parseContext.transferTypeAttributes(token.loc, attributes, memberType); - - // struct_declarator COMMA struct_declarator ... - bool functionDefinitionAccepted = false; - do { - if (! acceptIdentifier(idToken)) { - expected("member name"); - return false; - } - - if (peekTokenClass(EHTokLeftParen)) { - // function_parameters - if (!declarator_list) { - declarators.resize(declarators.size() + 1); - // request a token stream for deferred processing - functionDefinitionAccepted = acceptMemberFunctionDefinition(nodeList, memberType, *idToken.string, - declarators.back()); - if (functionDefinitionAccepted) - break; - } - expected("member-function definition"); - return false; - } else { - // add it to the list of members - TTypeLoc member = { new TType(EbtVoid), token.loc }; - member.type->shallowCopy(memberType); - member.type->setFieldName(*idToken.string); - typeList->push_back(member); - - // array_specifier - TArraySizes* arraySizes = nullptr; - acceptArraySpecifier(arraySizes); - if (arraySizes) - typeList->back().type->transferArraySizes(arraySizes); - - acceptPostDecls(member.type->getQualifier()); - - // EQUAL assignment_expression - if (acceptTokenClass(EHTokAssign)) { - parseContext.warn(idToken.loc, "struct-member initializers ignored", "typedef", ""); - TIntermTyped* expressionNode = nullptr; - if (! acceptAssignmentExpression(expressionNode)) { - expected("initializer"); - return false; - } - } - } - // success on seeing the SEMICOLON coming up - if (peekTokenClass(EHTokSemicolon)) - break; - - // COMMA - if (acceptTokenClass(EHTokComma)) - declarator_list = true; - else { - expected(","); - return false; - } - - } while (true); - - // SEMI_COLON - if (! functionDefinitionAccepted && ! acceptTokenClass(EHTokSemicolon)) { - expected(";"); - return false; - } - - } while (true); - - return true; -} - -// member_function_definition -// | function_parameters post_decls compound_statement -// -// Expects type to have EvqGlobal for a static member and -// EvqTemporary for non-static member. -bool HlslGrammar::acceptMemberFunctionDefinition(TIntermNode*& nodeList, const TType& type, TString& memberName, - TFunctionDeclarator& declarator) -{ - bool accepted = false; - - TString* functionName = &memberName; - parseContext.getFullNamespaceName(functionName); - declarator.function = new TFunction(functionName, type); - if (type.getQualifier().storage == EvqTemporary) - declarator.function->setImplicitThis(); - else - declarator.function->setIllegalImplicitThis(); - - // function_parameters - if (acceptFunctionParameters(*declarator.function)) { - // post_decls - acceptPostDecls(declarator.function->getWritableType().getQualifier()); - - // compound_statement (function body definition) - if (peekTokenClass(EHTokLeftBrace)) { - declarator.loc = token.loc; - declarator.body = new TVector; - accepted = acceptFunctionDefinition(declarator, nodeList, declarator.body); - } - } else - expected("function parameter list"); - - return accepted; -} - -// function_parameters -// : LEFT_PAREN parameter_declaration COMMA parameter_declaration ... RIGHT_PAREN -// | LEFT_PAREN VOID RIGHT_PAREN -// -bool HlslGrammar::acceptFunctionParameters(TFunction& function) -{ - // LEFT_PAREN - if (! acceptTokenClass(EHTokLeftParen)) - return false; - - // VOID RIGHT_PAREN - if (! acceptTokenClass(EHTokVoid)) { - do { - // parameter_declaration - if (! acceptParameterDeclaration(function)) - break; - - // COMMA - if (! acceptTokenClass(EHTokComma)) - break; - } while (true); - } - - // RIGHT_PAREN - if (! acceptTokenClass(EHTokRightParen)) { - expected(")"); - return false; - } - - return true; -} - -// default_parameter_declaration -// : EQUAL conditional_expression -// : EQUAL initializer -bool HlslGrammar::acceptDefaultParameterDeclaration(const TType& type, TIntermTyped*& node) -{ - node = nullptr; - - // Valid not to have a default_parameter_declaration - if (!acceptTokenClass(EHTokAssign)) - return true; - - if (!acceptConditionalExpression(node)) { - if (!acceptInitializer(node)) - return false; - - // For initializer lists, we have to const-fold into a constructor for the type, so build - // that. - TFunction* constructor = parseContext.makeConstructorCall(token.loc, type); - if (constructor == nullptr) // cannot construct - return false; - - TIntermTyped* arguments = nullptr; - for (int i = 0; i < int(node->getAsAggregate()->getSequence().size()); i++) - parseContext.handleFunctionArgument(constructor, arguments, node->getAsAggregate()->getSequence()[i]->getAsTyped()); - - node = parseContext.handleFunctionCall(token.loc, constructor, node); - } - - if (node == nullptr) - return false; - - // If this is simply a constant, we can use it directly. - if (node->getAsConstantUnion()) - return true; - - // Otherwise, it has to be const-foldable. - TIntermTyped* origNode = node; - - node = intermediate.fold(node->getAsAggregate()); - - if (node != nullptr && origNode != node) - return true; - - parseContext.error(token.loc, "invalid default parameter value", "", ""); - - return false; -} - -// parameter_declaration -// : attributes attributed_declaration -// -// attributed_declaration -// : fully_specified_type post_decls [ = default_parameter_declaration ] -// | fully_specified_type identifier array_specifier post_decls [ = default_parameter_declaration ] -// -bool HlslGrammar::acceptParameterDeclaration(TFunction& function) -{ - // attributes - TAttributes attributes; - acceptAttributes(attributes); - - // fully_specified_type - TType* type = new TType; - if (! acceptFullySpecifiedType(*type, attributes)) - return false; - - // merge in the attributes - parseContext.transferTypeAttributes(token.loc, attributes, *type); - - // identifier - HlslToken idToken; - acceptIdentifier(idToken); - - // array_specifier - TArraySizes* arraySizes = nullptr; - acceptArraySpecifier(arraySizes); - if (arraySizes) { - if (arraySizes->hasUnsized()) { - parseContext.error(token.loc, "function parameter requires array size", "[]", ""); - return false; - } - - type->transferArraySizes(arraySizes); - } - - // post_decls - acceptPostDecls(type->getQualifier()); - - TIntermTyped* defaultValue; - if (!acceptDefaultParameterDeclaration(*type, defaultValue)) - return false; - - parseContext.paramFix(*type); - - // If any prior parameters have default values, all the parameters after that must as well. - if (defaultValue == nullptr && function.getDefaultParamCount() > 0) { - parseContext.error(idToken.loc, "invalid parameter after default value parameters", idToken.string->c_str(), ""); - return false; - } - - TParameter param = { idToken.string, type, defaultValue }; - function.addParameter(param); - - return true; -} - -// Do the work to create the function definition in addition to -// parsing the body (compound_statement). -// -// If 'deferredTokens' are passed in, just get the token stream, -// don't process. -// -bool HlslGrammar::acceptFunctionDefinition(TFunctionDeclarator& declarator, TIntermNode*& nodeList, - TVector* deferredTokens) -{ - parseContext.handleFunctionDeclarator(declarator.loc, *declarator.function, false /* not prototype */); - - if (deferredTokens) - return captureBlockTokens(*deferredTokens); - else - return acceptFunctionBody(declarator, nodeList); -} - -bool HlslGrammar::acceptFunctionBody(TFunctionDeclarator& declarator, TIntermNode*& nodeList) -{ - // we might get back an entry-point - TIntermNode* entryPointNode = nullptr; - - // This does a pushScope() - TIntermNode* functionNode = parseContext.handleFunctionDefinition(declarator.loc, *declarator.function, - declarator.attributes, entryPointNode); - - // compound_statement - TIntermNode* functionBody = nullptr; - if (! acceptCompoundStatement(functionBody)) - return false; - - // this does a popScope() - parseContext.handleFunctionBody(declarator.loc, *declarator.function, functionBody, functionNode); - - // Hook up the 1 or 2 function definitions. - nodeList = intermediate.growAggregate(nodeList, functionNode); - nodeList = intermediate.growAggregate(nodeList, entryPointNode); - - return true; -} - -// Accept an expression with parenthesis around it, where -// the parenthesis ARE NOT expression parenthesis, but the -// syntactically required ones like in "if ( expression )". -// -// Also accepts a declaration expression; "if (int a = expression)". -// -// Note this one is not set up to be speculative; as it gives -// errors if not found. -// -bool HlslGrammar::acceptParenExpression(TIntermTyped*& expression) -{ - expression = nullptr; - - // LEFT_PAREN - if (! acceptTokenClass(EHTokLeftParen)) - expected("("); - - bool decl = false; - TIntermNode* declNode = nullptr; - decl = acceptControlDeclaration(declNode); - if (decl) { - if (declNode == nullptr || declNode->getAsTyped() == nullptr) { - expected("initialized declaration"); - return false; - } else - expression = declNode->getAsTyped(); - } else { - // no declaration - if (! acceptExpression(expression)) { - expected("expression"); - return false; - } - } - - // RIGHT_PAREN - if (! acceptTokenClass(EHTokRightParen)) - expected(")"); - - return true; -} - -// The top-level full expression recognizer. -// -// expression -// : assignment_expression COMMA assignment_expression COMMA assignment_expression ... -// -bool HlslGrammar::acceptExpression(TIntermTyped*& node) -{ - node = nullptr; - - // assignment_expression - if (! acceptAssignmentExpression(node)) - return false; - - if (! peekTokenClass(EHTokComma)) - return true; - - do { - // ... COMMA - TSourceLoc loc = token.loc; - advanceToken(); - - // ... assignment_expression - TIntermTyped* rightNode = nullptr; - if (! acceptAssignmentExpression(rightNode)) { - expected("assignment expression"); - return false; - } - - node = intermediate.addComma(node, rightNode, loc); - - if (! peekTokenClass(EHTokComma)) - return true; - } while (true); -} - -// initializer -// : LEFT_BRACE RIGHT_BRACE -// | LEFT_BRACE initializer_list RIGHT_BRACE -// -// initializer_list -// : assignment_expression COMMA assignment_expression COMMA ... -// -bool HlslGrammar::acceptInitializer(TIntermTyped*& node) -{ - // LEFT_BRACE - if (! acceptTokenClass(EHTokLeftBrace)) - return false; - - // RIGHT_BRACE - TSourceLoc loc = token.loc; - if (acceptTokenClass(EHTokRightBrace)) { - // a zero-length initializer list - node = intermediate.makeAggregate(loc); - return true; - } - - // initializer_list - node = nullptr; - do { - // assignment_expression - TIntermTyped* expr; - if (! acceptAssignmentExpression(expr)) { - expected("assignment expression in initializer list"); - return false; - } - - const bool firstNode = (node == nullptr); - - node = intermediate.growAggregate(node, expr, loc); - - // If every sub-node in the list has qualifier EvqConst, the returned node becomes - // EvqConst. Otherwise, it becomes EvqTemporary. That doesn't happen with e.g. - // EvqIn or EvqPosition, since the collection isn't EvqPosition if all the members are. - if (firstNode && expr->getQualifier().storage == EvqConst) - node->getQualifier().storage = EvqConst; - else if (expr->getQualifier().storage != EvqConst) - node->getQualifier().storage = EvqTemporary; - - // COMMA - if (acceptTokenClass(EHTokComma)) { - if (acceptTokenClass(EHTokRightBrace)) // allow trailing comma - return true; - continue; - } - - // RIGHT_BRACE - if (acceptTokenClass(EHTokRightBrace)) - return true; - - expected(", or }"); - return false; - } while (true); -} - -// Accept an assignment expression, where assignment operations -// associate right-to-left. That is, it is implicit, for example -// -// a op (b op (c op d)) -// -// assigment_expression -// : initializer -// | conditional_expression -// | conditional_expression assign_op conditional_expression assign_op conditional_expression ... -// -bool HlslGrammar::acceptAssignmentExpression(TIntermTyped*& node) -{ - // initializer - if (peekTokenClass(EHTokLeftBrace)) { - if (acceptInitializer(node)) - return true; - - expected("initializer"); - return false; - } - - // conditional_expression - if (! acceptConditionalExpression(node)) - return false; - - // assignment operation? - TOperator assignOp = HlslOpMap::assignment(peek()); - if (assignOp == EOpNull) - return true; - - // assign_op - TSourceLoc loc = token.loc; - advanceToken(); - - // conditional_expression assign_op conditional_expression ... - // Done by recursing this function, which automatically - // gets the right-to-left associativity. - TIntermTyped* rightNode = nullptr; - if (! acceptAssignmentExpression(rightNode)) { - expected("assignment expression"); - return false; - } - - node = parseContext.handleAssign(loc, assignOp, node, rightNode); - node = parseContext.handleLvalue(loc, "assign", node); - - if (node == nullptr) { - parseContext.error(loc, "could not create assignment", "", ""); - return false; - } - - if (! peekTokenClass(EHTokComma)) - return true; - - return true; -} - -// Accept a conditional expression, which associates right-to-left, -// accomplished by the "true" expression calling down to lower -// precedence levels than this level. -// -// conditional_expression -// : binary_expression -// | binary_expression QUESTION expression COLON assignment_expression -// -bool HlslGrammar::acceptConditionalExpression(TIntermTyped*& node) -{ - // binary_expression - if (! acceptBinaryExpression(node, PlLogicalOr)) - return false; - - if (! acceptTokenClass(EHTokQuestion)) - return true; - - node = parseContext.convertConditionalExpression(token.loc, node, false); - if (node == nullptr) - return false; - - ++parseContext.controlFlowNestingLevel; // this only needs to work right if no errors - - TIntermTyped* trueNode = nullptr; - if (! acceptExpression(trueNode)) { - expected("expression after ?"); - return false; - } - TSourceLoc loc = token.loc; - - if (! acceptTokenClass(EHTokColon)) { - expected(":"); - return false; - } - - TIntermTyped* falseNode = nullptr; - if (! acceptAssignmentExpression(falseNode)) { - expected("expression after :"); - return false; - } - - --parseContext.controlFlowNestingLevel; - - node = intermediate.addSelection(node, trueNode, falseNode, loc); - - return true; -} - -// Accept a binary expression, for binary operations that -// associate left-to-right. This is, it is implicit, for example -// -// ((a op b) op c) op d -// -// binary_expression -// : expression op expression op expression ... -// -// where 'expression' is the next higher level in precedence. -// -bool HlslGrammar::acceptBinaryExpression(TIntermTyped*& node, PrecedenceLevel precedenceLevel) -{ - if (precedenceLevel > PlMul) - return acceptUnaryExpression(node); - - // assignment_expression - if (! acceptBinaryExpression(node, (PrecedenceLevel)(precedenceLevel + 1))) - return false; - - do { - TOperator op = HlslOpMap::binary(peek()); - PrecedenceLevel tokenLevel = HlslOpMap::precedenceLevel(op); - if (tokenLevel < precedenceLevel) - return true; - - // ... op - TSourceLoc loc = token.loc; - advanceToken(); - - // ... expression - TIntermTyped* rightNode = nullptr; - if (! acceptBinaryExpression(rightNode, (PrecedenceLevel)(precedenceLevel + 1))) { - expected("expression"); - return false; - } - - node = intermediate.addBinaryMath(op, node, rightNode, loc); - if (node == nullptr) { - parseContext.error(loc, "Could not perform requested binary operation", "", ""); - return false; - } - } while (true); -} - -// unary_expression -// : (type) unary_expression -// | + unary_expression -// | - unary_expression -// | ! unary_expression -// | ~ unary_expression -// | ++ unary_expression -// | -- unary_expression -// | postfix_expression -// -bool HlslGrammar::acceptUnaryExpression(TIntermTyped*& node) -{ - // (type) unary_expression - // Have to look two steps ahead, because this could be, e.g., a - // postfix_expression instead, since that also starts with at "(". - if (acceptTokenClass(EHTokLeftParen)) { - TType castType; - if (acceptType(castType)) { - // recognize any array_specifier as part of the type - TArraySizes* arraySizes = nullptr; - acceptArraySpecifier(arraySizes); - if (arraySizes != nullptr) - castType.transferArraySizes(arraySizes); - TSourceLoc loc = token.loc; - if (acceptTokenClass(EHTokRightParen)) { - // We've matched "(type)" now, get the expression to cast - if (! acceptUnaryExpression(node)) - return false; - - // Hook it up like a constructor - TFunction* constructorFunction = parseContext.makeConstructorCall(loc, castType); - if (constructorFunction == nullptr) { - expected("type that can be constructed"); - return false; - } - TIntermTyped* arguments = nullptr; - parseContext.handleFunctionArgument(constructorFunction, arguments, node); - node = parseContext.handleFunctionCall(loc, constructorFunction, arguments); - - return node != nullptr; - } else { - // This could be a parenthesized constructor, ala (int(3)), and we just accepted - // the '(int' part. We must back up twice. - recedeToken(); - recedeToken(); - - // Note, there are no array constructors like - // (float[2](...)) - if (arraySizes != nullptr) - parseContext.error(loc, "parenthesized array constructor not allowed", "([]())", "", ""); - } - } else { - // This isn't a type cast, but it still started "(", so if it is a - // unary expression, it can only be a postfix_expression, so try that. - // Back it up first. - recedeToken(); - return acceptPostfixExpression(node); - } - } - - // peek for "op unary_expression" - TOperator unaryOp = HlslOpMap::preUnary(peek()); - - // postfix_expression (if no unary operator) - if (unaryOp == EOpNull) - return acceptPostfixExpression(node); - - // op unary_expression - TSourceLoc loc = token.loc; - advanceToken(); - if (! acceptUnaryExpression(node)) - return false; - - // + is a no-op - if (unaryOp == EOpAdd) - return true; - - node = intermediate.addUnaryMath(unaryOp, node, loc); - - // These unary ops require lvalues - if (unaryOp == EOpPreIncrement || unaryOp == EOpPreDecrement) - node = parseContext.handleLvalue(loc, "unary operator", node); - - return node != nullptr; -} - -// postfix_expression -// : LEFT_PAREN expression RIGHT_PAREN -// | literal -// | constructor -// | IDENTIFIER [ COLONCOLON IDENTIFIER [ COLONCOLON IDENTIFIER ... ] ] -// | function_call -// | postfix_expression LEFT_BRACKET integer_expression RIGHT_BRACKET -// | postfix_expression DOT IDENTIFIER -// | postfix_expression DOT IDENTIFIER arguments -// | postfix_expression arguments -// | postfix_expression INC_OP -// | postfix_expression DEC_OP -// -bool HlslGrammar::acceptPostfixExpression(TIntermTyped*& node) -{ - // Not implemented as self-recursive: - // The logical "right recursion" is done with a loop at the end - - // idToken will pick up either a variable or a function name in a function call - HlslToken idToken; - - // Find something before the postfix operations, as they can't operate - // on nothing. So, no "return true", they fall through, only "return false". - if (acceptTokenClass(EHTokLeftParen)) { - // LEFT_PAREN expression RIGHT_PAREN - if (! acceptExpression(node)) { - expected("expression"); - return false; - } - if (! acceptTokenClass(EHTokRightParen)) { - expected(")"); - return false; - } - } else if (acceptLiteral(node)) { - // literal (nothing else to do yet) - } else if (acceptConstructor(node)) { - // constructor (nothing else to do yet) - } else if (acceptIdentifier(idToken)) { - // user-type, namespace name, variable, or function name - TString* fullName = idToken.string; - while (acceptTokenClass(EHTokColonColon)) { - // user-type or namespace name - fullName = NewPoolTString(fullName->c_str()); - fullName->append(parseContext.scopeMangler); - if (acceptIdentifier(idToken)) - fullName->append(*idToken.string); - else { - expected("identifier after ::"); - return false; - } - } - if (! peekTokenClass(EHTokLeftParen)) { - node = parseContext.handleVariable(idToken.loc, fullName); - if (node == nullptr) - return false; - } else if (acceptFunctionCall(idToken.loc, *fullName, node, nullptr)) { - // function_call (nothing else to do yet) - } else { - expected("function call arguments"); - return false; - } - } else { - // nothing found, can't post operate - return false; - } - - // Something was found, chain as many postfix operations as exist. - do { - TSourceLoc loc = token.loc; - TOperator postOp = HlslOpMap::postUnary(peek()); - - // Consume only a valid post-unary operator, otherwise we are done. - switch (postOp) { - case EOpIndexDirectStruct: - case EOpIndexIndirect: - case EOpPostIncrement: - case EOpPostDecrement: - case EOpScoping: - advanceToken(); - break; - default: - return true; - } - - // We have a valid post-unary operator, process it. - switch (postOp) { - case EOpScoping: - case EOpIndexDirectStruct: - { - // DOT IDENTIFIER - // includes swizzles, member variables, and member functions - HlslToken field; - if (! acceptIdentifier(field)) { - expected("swizzle or member"); - return false; - } - - if (peekTokenClass(EHTokLeftParen)) { - // member function - TIntermTyped* thisNode = node; - - // arguments - if (! acceptFunctionCall(field.loc, *field.string, node, thisNode)) { - expected("function parameters"); - return false; - } - } else - node = parseContext.handleDotDereference(field.loc, node, *field.string); - - break; - } - case EOpIndexIndirect: - { - // LEFT_BRACKET integer_expression RIGHT_BRACKET - TIntermTyped* indexNode = nullptr; - if (! acceptExpression(indexNode) || - ! peekTokenClass(EHTokRightBracket)) { - expected("expression followed by ']'"); - return false; - } - advanceToken(); - node = parseContext.handleBracketDereference(indexNode->getLoc(), node, indexNode); - if (node == nullptr) - return false; - break; - } - case EOpPostIncrement: - // INC_OP - // fall through - case EOpPostDecrement: - // DEC_OP - node = intermediate.addUnaryMath(postOp, node, loc); - node = parseContext.handleLvalue(loc, "unary operator", node); - break; - default: - assert(0); - break; - } - } while (true); -} - -// constructor -// : type argument_list -// -bool HlslGrammar::acceptConstructor(TIntermTyped*& node) -{ - // type - TType type; - if (acceptType(type)) { - TFunction* constructorFunction = parseContext.makeConstructorCall(token.loc, type); - if (constructorFunction == nullptr) - return false; - - // arguments - TIntermTyped* arguments = nullptr; - if (! acceptArguments(constructorFunction, arguments)) { - // It's possible this is a type keyword used as an identifier. Put the token back - // for later use. - recedeToken(); - return false; - } - - // hook it up - node = parseContext.handleFunctionCall(arguments->getLoc(), constructorFunction, arguments); - - return node != nullptr; - } - - return false; -} - -// The function_call identifier was already recognized, and passed in as idToken. -// -// function_call -// : [idToken] arguments -// -bool HlslGrammar::acceptFunctionCall(const TSourceLoc& loc, TString& name, TIntermTyped*& node, TIntermTyped* baseObject) -{ - // name - TString* functionName = nullptr; - if (baseObject == nullptr) { - functionName = &name; - } else if (parseContext.isBuiltInMethod(loc, baseObject, name)) { - // Built-in methods are not in the symbol table as methods, but as global functions - // taking an explicit 'this' as the first argument. - functionName = NewPoolTString(BUILTIN_PREFIX); - functionName->append(name); - } else { - if (! baseObject->getType().isStruct()) { - expected("structure"); - return false; - } - functionName = NewPoolTString(""); - functionName->append(baseObject->getType().getTypeName()); - parseContext.addScopeMangler(*functionName); - functionName->append(name); - } - - // function - TFunction* function = new TFunction(functionName, TType(EbtVoid)); - - // arguments - TIntermTyped* arguments = nullptr; - if (baseObject != nullptr) { - // Non-static member functions have an implicit first argument of the base object. - parseContext.handleFunctionArgument(function, arguments, baseObject); - } - if (! acceptArguments(function, arguments)) - return false; - - // call - node = parseContext.handleFunctionCall(loc, function, arguments); - - return node != nullptr; -} - -// arguments -// : LEFT_PAREN expression COMMA expression COMMA ... RIGHT_PAREN -// -// The arguments are pushed onto the 'function' argument list and -// onto the 'arguments' aggregate. -// -bool HlslGrammar::acceptArguments(TFunction* function, TIntermTyped*& arguments) -{ - // LEFT_PAREN - if (! acceptTokenClass(EHTokLeftParen)) - return false; - - // RIGHT_PAREN - if (acceptTokenClass(EHTokRightParen)) - return true; - - // must now be at least one expression... - do { - // expression - TIntermTyped* arg; - if (! acceptAssignmentExpression(arg)) - return false; - - // hook it up - parseContext.handleFunctionArgument(function, arguments, arg); - - // COMMA - if (! acceptTokenClass(EHTokComma)) - break; - } while (true); - - // RIGHT_PAREN - if (! acceptTokenClass(EHTokRightParen)) { - expected(")"); - return false; - } - - return true; -} - -bool HlslGrammar::acceptLiteral(TIntermTyped*& node) -{ - switch (token.tokenClass) { - case EHTokIntConstant: - node = intermediate.addConstantUnion(token.i, token.loc, true); - break; - case EHTokUintConstant: - node = intermediate.addConstantUnion(token.u, token.loc, true); - break; - case EHTokFloat16Constant: - node = intermediate.addConstantUnion(token.d, EbtFloat16, token.loc, true); - break; - case EHTokFloatConstant: - node = intermediate.addConstantUnion(token.d, EbtFloat, token.loc, true); - break; - case EHTokDoubleConstant: - node = intermediate.addConstantUnion(token.d, EbtDouble, token.loc, true); - break; - case EHTokBoolConstant: - node = intermediate.addConstantUnion(token.b, token.loc, true); - break; - case EHTokStringConstant: - node = intermediate.addConstantUnion(token.string, token.loc, true); - break; - - default: - return false; - } - - advanceToken(); - - return true; -} - -// simple_statement -// : SEMICOLON -// | declaration_statement -// | expression SEMICOLON -// -bool HlslGrammar::acceptSimpleStatement(TIntermNode*& statement) -{ - // SEMICOLON - if (acceptTokenClass(EHTokSemicolon)) - return true; - - // declaration - if (acceptDeclaration(statement)) - return true; - - // expression - TIntermTyped* node; - if (acceptExpression(node)) - statement = node; - else - return false; - - // SEMICOLON (following an expression) - if (acceptTokenClass(EHTokSemicolon)) - return true; - else { - expected(";"); - return false; - } -} - -// compound_statement -// : LEFT_CURLY statement statement ... RIGHT_CURLY -// -bool HlslGrammar::acceptCompoundStatement(TIntermNode*& retStatement) -{ - TIntermAggregate* compoundStatement = nullptr; - - // LEFT_CURLY - if (! acceptTokenClass(EHTokLeftBrace)) - return false; - - // statement statement ... - TIntermNode* statement = nullptr; - while (acceptStatement(statement)) { - TIntermBranch* branch = statement ? statement->getAsBranchNode() : nullptr; - if (branch != nullptr && (branch->getFlowOp() == EOpCase || - branch->getFlowOp() == EOpDefault)) { - // hook up individual subsequences within a switch statement - parseContext.wrapupSwitchSubsequence(compoundStatement, statement); - compoundStatement = nullptr; - } else { - // hook it up to the growing compound statement - compoundStatement = intermediate.growAggregate(compoundStatement, statement); - } - } - if (compoundStatement) - compoundStatement->setOperator(EOpSequence); - - retStatement = compoundStatement; - - // RIGHT_CURLY - return acceptTokenClass(EHTokRightBrace); -} - -bool HlslGrammar::acceptScopedStatement(TIntermNode*& statement) -{ - parseContext.pushScope(); - bool result = acceptStatement(statement); - parseContext.popScope(); - - return result; -} - -bool HlslGrammar::acceptScopedCompoundStatement(TIntermNode*& statement) -{ - parseContext.pushScope(); - bool result = acceptCompoundStatement(statement); - parseContext.popScope(); - - return result; -} - -// statement -// : attributes attributed_statement -// -// attributed_statement -// : compound_statement -// | simple_statement -// | selection_statement -// | switch_statement -// | case_label -// | default_label -// | iteration_statement -// | jump_statement -// -bool HlslGrammar::acceptStatement(TIntermNode*& statement) -{ - statement = nullptr; - - // attributes - TAttributes attributes; - acceptAttributes(attributes); - - // attributed_statement - switch (peek()) { - case EHTokLeftBrace: - return acceptScopedCompoundStatement(statement); - - case EHTokIf: - return acceptSelectionStatement(statement, attributes); - - case EHTokSwitch: - return acceptSwitchStatement(statement, attributes); - - case EHTokFor: - case EHTokDo: - case EHTokWhile: - return acceptIterationStatement(statement, attributes); - - case EHTokContinue: - case EHTokBreak: - case EHTokDiscard: - case EHTokReturn: - return acceptJumpStatement(statement); - - case EHTokCase: - return acceptCaseLabel(statement); - case EHTokDefault: - return acceptDefaultLabel(statement); - - case EHTokRightBrace: - // Performance: not strictly necessary, but stops a bunch of hunting early, - // and is how sequences of statements end. - return false; - - default: - return acceptSimpleStatement(statement); - } - - return true; -} - -// attributes -// : [zero or more:] bracketed-attribute -// -// bracketed-attribute: -// : LEFT_BRACKET scoped-attribute RIGHT_BRACKET -// : LEFT_BRACKET LEFT_BRACKET scoped-attribute RIGHT_BRACKET RIGHT_BRACKET -// -// scoped-attribute: -// : attribute -// | namespace COLON COLON attribute -// -// attribute: -// : UNROLL -// | UNROLL LEFT_PAREN literal RIGHT_PAREN -// | FASTOPT -// | ALLOW_UAV_CONDITION -// | BRANCH -// | FLATTEN -// | FORCECASE -// | CALL -// | DOMAIN -// | EARLYDEPTHSTENCIL -// | INSTANCE -// | MAXTESSFACTOR -// | OUTPUTCONTROLPOINTS -// | OUTPUTTOPOLOGY -// | PARTITIONING -// | PATCHCONSTANTFUNC -// | NUMTHREADS LEFT_PAREN x_size, y_size,z z_size RIGHT_PAREN -// -void HlslGrammar::acceptAttributes(TAttributes& attributes) -{ - // For now, accept the [ XXX(X) ] syntax, but drop all but - // numthreads, which is used to set the CS local size. - // TODO: subset to correct set? Pass on? - do { - HlslToken attributeToken; - - // LEFT_BRACKET? - if (! acceptTokenClass(EHTokLeftBracket)) - return; - // another LEFT_BRACKET? - bool doubleBrackets = false; - if (acceptTokenClass(EHTokLeftBracket)) - doubleBrackets = true; - - // attribute? (could be namespace; will adjust later) - if (!acceptIdentifier(attributeToken)) { - if (!peekTokenClass(EHTokRightBracket)) { - expected("namespace or attribute identifier"); - advanceToken(); - } - } - - TString nameSpace; - if (acceptTokenClass(EHTokColonColon)) { - // namespace COLON COLON - nameSpace = *attributeToken.string; - // attribute - if (!acceptIdentifier(attributeToken)) { - expected("attribute identifier"); - return; - } - } - - TIntermAggregate* expressions = nullptr; - - // (x, ...) - if (acceptTokenClass(EHTokLeftParen)) { - expressions = new TIntermAggregate; - - TIntermTyped* node; - bool expectingExpression = false; - - while (acceptAssignmentExpression(node)) { - expectingExpression = false; - expressions->getSequence().push_back(node); - if (acceptTokenClass(EHTokComma)) - expectingExpression = true; - } - - // 'expressions' is an aggregate with the expressions in it - if (! acceptTokenClass(EHTokRightParen)) - expected(")"); - - // Error for partial or missing expression - if (expectingExpression || expressions->getSequence().empty()) - expected("expression"); - } - - // RIGHT_BRACKET - if (!acceptTokenClass(EHTokRightBracket)) { - expected("]"); - return; - } - // another RIGHT_BRACKET? - if (doubleBrackets && !acceptTokenClass(EHTokRightBracket)) { - expected("]]"); - return; - } - - // Add any values we found into the attribute map. - if (attributeToken.string != nullptr) { - TAttributeType attributeType = parseContext.attributeFromName(nameSpace, *attributeToken.string); - if (attributeType == EatNone) - parseContext.warn(attributeToken.loc, "unrecognized attribute", attributeToken.string->c_str(), ""); - else { - TAttributeArgs attributeArgs = { attributeType, expressions }; - attributes.push_back(attributeArgs); - } - } - } while (true); -} - -// selection_statement -// : IF LEFT_PAREN expression RIGHT_PAREN statement -// : IF LEFT_PAREN expression RIGHT_PAREN statement ELSE statement -// -bool HlslGrammar::acceptSelectionStatement(TIntermNode*& statement, const TAttributes& attributes) -{ - TSourceLoc loc = token.loc; - - // IF - if (! acceptTokenClass(EHTokIf)) - return false; - - // so that something declared in the condition is scoped to the lifetimes - // of the then-else statements - parseContext.pushScope(); - - // LEFT_PAREN expression RIGHT_PAREN - TIntermTyped* condition; - if (! acceptParenExpression(condition)) - return false; - condition = parseContext.convertConditionalExpression(loc, condition); - if (condition == nullptr) - return false; - - // create the child statements - TIntermNodePair thenElse = { nullptr, nullptr }; - - ++parseContext.controlFlowNestingLevel; // this only needs to work right if no errors - - // then statement - if (! acceptScopedStatement(thenElse.node1)) { - expected("then statement"); - return false; - } - - // ELSE - if (acceptTokenClass(EHTokElse)) { - // else statement - if (! acceptScopedStatement(thenElse.node2)) { - expected("else statement"); - return false; - } - } - - // Put the pieces together - statement = intermediate.addSelection(condition, thenElse, loc); - parseContext.handleSelectionAttributes(loc, statement->getAsSelectionNode(), attributes); - - parseContext.popScope(); - --parseContext.controlFlowNestingLevel; - - return true; -} - -// switch_statement -// : SWITCH LEFT_PAREN expression RIGHT_PAREN compound_statement -// -bool HlslGrammar::acceptSwitchStatement(TIntermNode*& statement, const TAttributes& attributes) -{ - // SWITCH - TSourceLoc loc = token.loc; - - if (! acceptTokenClass(EHTokSwitch)) - return false; - - // LEFT_PAREN expression RIGHT_PAREN - parseContext.pushScope(); - TIntermTyped* switchExpression; - if (! acceptParenExpression(switchExpression)) { - parseContext.popScope(); - return false; - } - - // compound_statement - parseContext.pushSwitchSequence(new TIntermSequence); - - ++parseContext.controlFlowNestingLevel; - bool statementOkay = acceptCompoundStatement(statement); - --parseContext.controlFlowNestingLevel; - - if (statementOkay) - statement = parseContext.addSwitch(loc, switchExpression, statement ? statement->getAsAggregate() : nullptr, - attributes); - - parseContext.popSwitchSequence(); - parseContext.popScope(); - - return statementOkay; -} - -// iteration_statement -// : WHILE LEFT_PAREN condition RIGHT_PAREN statement -// | DO LEFT_BRACE statement RIGHT_BRACE WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON -// | FOR LEFT_PAREN for_init_statement for_rest_statement RIGHT_PAREN statement -// -// Non-speculative, only call if it needs to be found; WHILE or DO or FOR already seen. -bool HlslGrammar::acceptIterationStatement(TIntermNode*& statement, const TAttributes& attributes) -{ - TSourceLoc loc = token.loc; - TIntermTyped* condition = nullptr; - - EHlslTokenClass loop = peek(); - assert(loop == EHTokDo || loop == EHTokFor || loop == EHTokWhile); - - // WHILE or DO or FOR - advanceToken(); - - TIntermLoop* loopNode = nullptr; - switch (loop) { - case EHTokWhile: - // so that something declared in the condition is scoped to the lifetime - // of the while sub-statement - parseContext.pushScope(); // this only needs to work right if no errors - parseContext.nestLooping(); - ++parseContext.controlFlowNestingLevel; - - // LEFT_PAREN condition RIGHT_PAREN - if (! acceptParenExpression(condition)) - return false; - condition = parseContext.convertConditionalExpression(loc, condition); - if (condition == nullptr) - return false; - - // statement - if (! acceptScopedStatement(statement)) { - expected("while sub-statement"); - return false; - } - - parseContext.unnestLooping(); - parseContext.popScope(); - --parseContext.controlFlowNestingLevel; - - loopNode = intermediate.addLoop(statement, condition, nullptr, true, loc); - statement = loopNode; - break; - - case EHTokDo: - parseContext.nestLooping(); // this only needs to work right if no errors - ++parseContext.controlFlowNestingLevel; - - // statement - if (! acceptScopedStatement(statement)) { - expected("do sub-statement"); - return false; - } - - // WHILE - if (! acceptTokenClass(EHTokWhile)) { - expected("while"); - return false; - } - - // LEFT_PAREN condition RIGHT_PAREN - if (! acceptParenExpression(condition)) - return false; - condition = parseContext.convertConditionalExpression(loc, condition); - if (condition == nullptr) - return false; - - if (! acceptTokenClass(EHTokSemicolon)) - expected(";"); - - parseContext.unnestLooping(); - --parseContext.controlFlowNestingLevel; - - loopNode = intermediate.addLoop(statement, condition, 0, false, loc); - statement = loopNode; - break; - - case EHTokFor: - { - // LEFT_PAREN - if (! acceptTokenClass(EHTokLeftParen)) - expected("("); - - // so that something declared in the condition is scoped to the lifetime - // of the for sub-statement - parseContext.pushScope(); - - // initializer - TIntermNode* initNode = nullptr; - if (! acceptSimpleStatement(initNode)) - expected("for-loop initializer statement"); - - parseContext.nestLooping(); // this only needs to work right if no errors - ++parseContext.controlFlowNestingLevel; - - // condition SEMI_COLON - acceptExpression(condition); - if (! acceptTokenClass(EHTokSemicolon)) - expected(";"); - if (condition != nullptr) { - condition = parseContext.convertConditionalExpression(loc, condition); - if (condition == nullptr) - return false; - } - - // iterator SEMI_COLON - TIntermTyped* iterator = nullptr; - acceptExpression(iterator); - if (! acceptTokenClass(EHTokRightParen)) - expected(")"); - - // statement - if (! acceptScopedStatement(statement)) { - expected("for sub-statement"); - return false; - } - - statement = intermediate.addForLoop(statement, initNode, condition, iterator, true, loc, loopNode); - - parseContext.popScope(); - parseContext.unnestLooping(); - --parseContext.controlFlowNestingLevel; - - break; - } - - default: - return false; - } - - parseContext.handleLoopAttributes(loc, loopNode, attributes); - return true; -} - -// jump_statement -// : CONTINUE SEMICOLON -// | BREAK SEMICOLON -// | DISCARD SEMICOLON -// | RETURN SEMICOLON -// | RETURN expression SEMICOLON -// -bool HlslGrammar::acceptJumpStatement(TIntermNode*& statement) -{ - EHlslTokenClass jump = peek(); - switch (jump) { - case EHTokContinue: - case EHTokBreak: - case EHTokDiscard: - case EHTokReturn: - advanceToken(); - break; - default: - // not something we handle in this function - return false; - } - - switch (jump) { - case EHTokContinue: - statement = intermediate.addBranch(EOpContinue, token.loc); - if (parseContext.loopNestingLevel == 0) { - expected("loop"); - return false; - } - break; - case EHTokBreak: - statement = intermediate.addBranch(EOpBreak, token.loc); - if (parseContext.loopNestingLevel == 0 && parseContext.switchSequenceStack.size() == 0) { - expected("loop or switch"); - return false; - } - break; - case EHTokDiscard: - statement = intermediate.addBranch(EOpKill, token.loc); - break; - - case EHTokReturn: - { - // expression - TIntermTyped* node; - if (acceptExpression(node)) { - // hook it up - statement = parseContext.handleReturnValue(token.loc, node); - } else - statement = intermediate.addBranch(EOpReturn, token.loc); - break; - } - - default: - assert(0); - return false; - } - - // SEMICOLON - if (! acceptTokenClass(EHTokSemicolon)) - expected(";"); - - return true; -} - -// case_label -// : CASE expression COLON -// -bool HlslGrammar::acceptCaseLabel(TIntermNode*& statement) -{ - TSourceLoc loc = token.loc; - if (! acceptTokenClass(EHTokCase)) - return false; - - TIntermTyped* expression; - if (! acceptExpression(expression)) { - expected("case expression"); - return false; - } - - if (! acceptTokenClass(EHTokColon)) { - expected(":"); - return false; - } - - statement = parseContext.intermediate.addBranch(EOpCase, expression, loc); - - return true; -} - -// default_label -// : DEFAULT COLON -// -bool HlslGrammar::acceptDefaultLabel(TIntermNode*& statement) -{ - TSourceLoc loc = token.loc; - if (! acceptTokenClass(EHTokDefault)) - return false; - - if (! acceptTokenClass(EHTokColon)) { - expected(":"); - return false; - } - - statement = parseContext.intermediate.addBranch(EOpDefault, loc); - - return true; -} - -// array_specifier -// : LEFT_BRACKET integer_expression RGHT_BRACKET ... // optional -// : LEFT_BRACKET RGHT_BRACKET // optional -// -void HlslGrammar::acceptArraySpecifier(TArraySizes*& arraySizes) -{ - arraySizes = nullptr; - - // Early-out if there aren't any array dimensions - if (!peekTokenClass(EHTokLeftBracket)) - return; - - // If we get here, we have at least one array dimension. This will track the sizes we find. - arraySizes = new TArraySizes; - - // Collect each array dimension. - while (acceptTokenClass(EHTokLeftBracket)) { - TSourceLoc loc = token.loc; - TIntermTyped* sizeExpr = nullptr; - - // Array sizing expression is optional. If omitted, array will be later sized by initializer list. - const bool hasArraySize = acceptAssignmentExpression(sizeExpr); - - if (! acceptTokenClass(EHTokRightBracket)) { - expected("]"); - return; - } - - if (hasArraySize) { - TArraySize arraySize; - parseContext.arraySizeCheck(loc, sizeExpr, arraySize); - arraySizes->addInnerSize(arraySize); - } else { - arraySizes->addInnerSize(0); // sized by initializers. - } - } -} - -// post_decls -// : COLON semantic // optional -// COLON PACKOFFSET LEFT_PAREN c[Subcomponent][.component] RIGHT_PAREN // optional -// COLON REGISTER LEFT_PAREN [shader_profile,] Type#[subcomp]opt (COMMA SPACEN)opt RIGHT_PAREN // optional -// COLON LAYOUT layout_qualifier_list -// annotations // optional -// -// Return true if any tokens were accepted. That is, -// false can be returned on successfully recognizing nothing, -// not necessarily meaning bad syntax. -// -bool HlslGrammar::acceptPostDecls(TQualifier& qualifier) -{ - bool found = false; - - do { - // COLON - if (acceptTokenClass(EHTokColon)) { - found = true; - HlslToken idToken; - if (peekTokenClass(EHTokLayout)) - acceptLayoutQualifierList(qualifier); - else if (acceptTokenClass(EHTokPackOffset)) { - // PACKOFFSET LEFT_PAREN c[Subcomponent][.component] RIGHT_PAREN - if (! acceptTokenClass(EHTokLeftParen)) { - expected("("); - return false; - } - HlslToken locationToken; - if (! acceptIdentifier(locationToken)) { - expected("c[subcomponent][.component]"); - return false; - } - HlslToken componentToken; - if (acceptTokenClass(EHTokDot)) { - if (! acceptIdentifier(componentToken)) { - expected("component"); - return false; - } - } - if (! acceptTokenClass(EHTokRightParen)) { - expected(")"); - break; - } - parseContext.handlePackOffset(locationToken.loc, qualifier, *locationToken.string, componentToken.string); - } else if (! acceptIdentifier(idToken)) { - expected("layout, semantic, packoffset, or register"); - return false; - } else if (*idToken.string == "register") { - // REGISTER LEFT_PAREN [shader_profile,] Type#[subcomp]opt (COMMA SPACEN)opt RIGHT_PAREN - // LEFT_PAREN - if (! acceptTokenClass(EHTokLeftParen)) { - expected("("); - return false; - } - HlslToken registerDesc; // for Type# - HlslToken profile; - if (! acceptIdentifier(registerDesc)) { - expected("register number description"); - return false; - } - if (registerDesc.string->size() > 1 && !isdigit((*registerDesc.string)[1]) && - acceptTokenClass(EHTokComma)) { - // Then we didn't really see the registerDesc yet, it was - // actually the profile. Adjust... - profile = registerDesc; - if (! acceptIdentifier(registerDesc)) { - expected("register number description"); - return false; - } - } - int subComponent = 0; - if (acceptTokenClass(EHTokLeftBracket)) { - // LEFT_BRACKET subcomponent RIGHT_BRACKET - if (! peekTokenClass(EHTokIntConstant)) { - expected("literal integer"); - return false; - } - subComponent = token.i; - advanceToken(); - if (! acceptTokenClass(EHTokRightBracket)) { - expected("]"); - break; - } - } - // (COMMA SPACEN)opt - HlslToken spaceDesc; - if (acceptTokenClass(EHTokComma)) { - if (! acceptIdentifier(spaceDesc)) { - expected ("space identifier"); - return false; - } - } - // RIGHT_PAREN - if (! acceptTokenClass(EHTokRightParen)) { - expected(")"); - break; - } - parseContext.handleRegister(registerDesc.loc, qualifier, profile.string, *registerDesc.string, subComponent, spaceDesc.string); - } else { - // semantic, in idToken.string - TString semanticUpperCase = *idToken.string; - std::transform(semanticUpperCase.begin(), semanticUpperCase.end(), semanticUpperCase.begin(), ::toupper); - parseContext.handleSemantic(idToken.loc, qualifier, mapSemantic(semanticUpperCase.c_str()), semanticUpperCase); - } - } else if (peekTokenClass(EHTokLeftAngle)) { - found = true; - acceptAnnotations(qualifier); - } else - break; - - } while (true); - - return found; -} - -// -// Get the stream of tokens from the scanner, but skip all syntactic/semantic -// processing. -// -bool HlslGrammar::captureBlockTokens(TVector& tokens) -{ - if (! peekTokenClass(EHTokLeftBrace)) - return false; - - int braceCount = 0; - - do { - switch (peek()) { - case EHTokLeftBrace: - ++braceCount; - break; - case EHTokRightBrace: - --braceCount; - break; - case EHTokNone: - // End of input before balance { } is bad... - return false; - default: - break; - } - - tokens.push_back(token); - advanceToken(); - } while (braceCount > 0); - - return true; -} - -// Return a string for just the types that can also be declared as an identifier. -const char* HlslGrammar::getTypeString(EHlslTokenClass tokenClass) const -{ - switch (tokenClass) { - case EHTokSample: return "sample"; - case EHTokHalf: return "half"; - case EHTokHalf1x1: return "half1x1"; - case EHTokHalf1x2: return "half1x2"; - case EHTokHalf1x3: return "half1x3"; - case EHTokHalf1x4: return "half1x4"; - case EHTokHalf2x1: return "half2x1"; - case EHTokHalf2x2: return "half2x2"; - case EHTokHalf2x3: return "half2x3"; - case EHTokHalf2x4: return "half2x4"; - case EHTokHalf3x1: return "half3x1"; - case EHTokHalf3x2: return "half3x2"; - case EHTokHalf3x3: return "half3x3"; - case EHTokHalf3x4: return "half3x4"; - case EHTokHalf4x1: return "half4x1"; - case EHTokHalf4x2: return "half4x2"; - case EHTokHalf4x3: return "half4x3"; - case EHTokHalf4x4: return "half4x4"; - case EHTokBool: return "bool"; - case EHTokFloat: return "float"; - case EHTokDouble: return "double"; - case EHTokInt: return "int"; - case EHTokUint: return "uint"; - case EHTokMin16float: return "min16float"; - case EHTokMin10float: return "min10float"; - case EHTokMin16int: return "min16int"; - case EHTokMin12int: return "min12int"; - case EHTokConstantBuffer: return "ConstantBuffer"; - case EHTokLayout: return "layout"; - default: - return nullptr; - } -} - -} // end namespace glslang diff --git a/External/glslang/hlsl/hlslGrammar.h b/External/glslang/hlsl/hlslGrammar.h deleted file mode 100644 index 046f7957..00000000 --- a/External/glslang/hlsl/hlslGrammar.h +++ /dev/null @@ -1,140 +0,0 @@ -// -// Copyright (C) 2016 Google, Inc. -// 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 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 HLSLGRAMMAR_H_ -#define HLSLGRAMMAR_H_ - -#include "hlslParseHelper.h" -#include "hlslOpMap.h" -#include "hlslTokenStream.h" - -namespace glslang { - - class TFunctionDeclarator; - - // Should just be the grammar aspect of HLSL. - // Described in more detail in hlslGrammar.cpp. - - class HlslGrammar : public HlslTokenStream { - public: - HlslGrammar(HlslScanContext& scanner, HlslParseContext& parseContext) - : HlslTokenStream(scanner), parseContext(parseContext), intermediate(parseContext.intermediate), - typeIdentifiers(false) { } - virtual ~HlslGrammar() { } - - bool parse(); - - protected: - HlslGrammar(); - HlslGrammar& operator=(const HlslGrammar&); - - void expected(const char*); - void unimplemented(const char*); - bool acceptIdentifier(HlslToken&); - bool acceptCompilationUnit(); - bool acceptDeclarationList(TIntermNode*&); - bool acceptDeclaration(TIntermNode*&); - bool acceptControlDeclaration(TIntermNode*& node); - bool acceptSamplerDeclarationDX9(TType&); - bool acceptSamplerState(); - bool acceptFullySpecifiedType(TType&, const TAttributes&); - bool acceptFullySpecifiedType(TType&, TIntermNode*& nodeList, const TAttributes&, bool forbidDeclarators = false); - bool acceptQualifier(TQualifier&); - bool acceptLayoutQualifierList(TQualifier&); - bool acceptType(TType&); - bool acceptType(TType&, TIntermNode*& nodeList); - bool acceptTemplateVecMatBasicType(TBasicType&); - bool acceptVectorTemplateType(TType&); - bool acceptMatrixTemplateType(TType&); - bool acceptTessellationDeclType(TBuiltInVariable&); - bool acceptTessellationPatchTemplateType(TType&); - bool acceptStreamOutTemplateType(TType&, TLayoutGeometry&); - bool acceptOutputPrimitiveGeometry(TLayoutGeometry&); - bool acceptAnnotations(TQualifier&); - bool acceptSamplerType(TType&); - bool acceptTextureType(TType&); - bool acceptSubpassInputType(TType&); - bool acceptStructBufferType(TType&); - bool acceptTextureBufferType(TType&); - bool acceptConstantBufferType(TType&); - bool acceptStruct(TType&, TIntermNode*& nodeList); - bool acceptStructDeclarationList(TTypeList*&, TIntermNode*& nodeList, TVector&); - bool acceptMemberFunctionDefinition(TIntermNode*& nodeList, const TType&, TString& memberName, - TFunctionDeclarator&); - bool acceptFunctionParameters(TFunction&); - bool acceptParameterDeclaration(TFunction&); - bool acceptFunctionDefinition(TFunctionDeclarator&, TIntermNode*& nodeList, TVector* deferredTokens); - bool acceptFunctionBody(TFunctionDeclarator& declarator, TIntermNode*& nodeList); - bool acceptParenExpression(TIntermTyped*&); - bool acceptExpression(TIntermTyped*&); - bool acceptInitializer(TIntermTyped*&); - bool acceptAssignmentExpression(TIntermTyped*&); - bool acceptConditionalExpression(TIntermTyped*&); - bool acceptBinaryExpression(TIntermTyped*&, PrecedenceLevel); - bool acceptUnaryExpression(TIntermTyped*&); - bool acceptPostfixExpression(TIntermTyped*&); - bool acceptConstructor(TIntermTyped*&); - bool acceptFunctionCall(const TSourceLoc&, TString& name, TIntermTyped*&, TIntermTyped* objectBase); - bool acceptArguments(TFunction*, TIntermTyped*&); - bool acceptLiteral(TIntermTyped*&); - bool acceptSimpleStatement(TIntermNode*&); - bool acceptCompoundStatement(TIntermNode*&); - bool acceptScopedStatement(TIntermNode*&); - bool acceptScopedCompoundStatement(TIntermNode*&); - bool acceptStatement(TIntermNode*&); - bool acceptNestedStatement(TIntermNode*&); - void acceptAttributes(TAttributes&); - bool acceptSelectionStatement(TIntermNode*&, const TAttributes&); - bool acceptSwitchStatement(TIntermNode*&, const TAttributes&); - bool acceptIterationStatement(TIntermNode*&, const TAttributes&); - bool acceptJumpStatement(TIntermNode*&); - bool acceptCaseLabel(TIntermNode*&); - bool acceptDefaultLabel(TIntermNode*&); - void acceptArraySpecifier(TArraySizes*&); - bool acceptPostDecls(TQualifier&); - bool acceptDefaultParameterDeclaration(const TType&, TIntermTyped*&); - - bool captureBlockTokens(TVector& tokens); - const char* getTypeString(EHlslTokenClass tokenClass) const; - - HlslParseContext& parseContext; // state of parsing and helper functions for building the intermediate - TIntermediate& intermediate; // the final product, the intermediate representation, includes the AST - bool typeIdentifiers; // shader uses some types as identifiers - }; - -} // end namespace glslang - -#endif // HLSLGRAMMAR_H_ diff --git a/External/glslang/hlsl/hlslOpMap.cpp b/External/glslang/hlsl/hlslOpMap.cpp deleted file mode 100644 index ebe6fbd9..00000000 --- a/External/glslang/hlsl/hlslOpMap.cpp +++ /dev/null @@ -1,173 +0,0 @@ -// -// Copyright (C) 2016 Google, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of Google, Inc., nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -// Map from physical token form (e.g. '-') to logical operator -// form (e.g., binary subtract or unary negate). - -#include "hlslOpMap.h" - -namespace glslang { - -// Map parsing tokens that could be assignments into assignment operators. -TOperator HlslOpMap::assignment(EHlslTokenClass op) -{ - switch (op) { - case EHTokAssign: return EOpAssign; - case EHTokMulAssign: return EOpMulAssign; - case EHTokDivAssign: return EOpDivAssign; - case EHTokAddAssign: return EOpAddAssign; - case EHTokModAssign: return EOpModAssign; - case EHTokLeftAssign: return EOpLeftShiftAssign; - case EHTokRightAssign: return EOpRightShiftAssign; - case EHTokAndAssign: return EOpAndAssign; - case EHTokXorAssign: return EOpExclusiveOrAssign; - case EHTokOrAssign: return EOpInclusiveOrAssign; - case EHTokSubAssign: return EOpSubAssign; - - default: - return EOpNull; - } -} - -// Map parsing tokens that could be binary operations into binary operators. -TOperator HlslOpMap::binary(EHlslTokenClass op) -{ - switch (op) { - case EHTokPlus: return EOpAdd; - case EHTokDash: return EOpSub; - case EHTokStar: return EOpMul; - case EHTokSlash: return EOpDiv; - case EHTokPercent: return EOpMod; - case EHTokRightOp: return EOpRightShift; - case EHTokLeftOp: return EOpLeftShift; - case EHTokAmpersand: return EOpAnd; - case EHTokVerticalBar: return EOpInclusiveOr; - case EHTokCaret: return EOpExclusiveOr; - case EHTokEqOp: return EOpEqual; - case EHTokNeOp: return EOpNotEqual; - case EHTokLeftAngle: return EOpLessThan; - case EHTokRightAngle: return EOpGreaterThan; - case EHTokLeOp: return EOpLessThanEqual; - case EHTokGeOp: return EOpGreaterThanEqual; - case EHTokOrOp: return EOpLogicalOr; - case EHTokXorOp: return EOpLogicalXor; - case EHTokAndOp: return EOpLogicalAnd; - - default: - return EOpNull; - } -} - -// Map parsing tokens that could be unary operations into unary operators. -// These are just the ones that can appear in front of its operand. -TOperator HlslOpMap::preUnary(EHlslTokenClass op) -{ - switch (op) { - case EHTokPlus: return EOpAdd; // means no-op, but still a unary op was present - case EHTokDash: return EOpNegative; - case EHTokBang: return EOpLogicalNot; - case EHTokTilde: return EOpBitwiseNot; - - case EHTokIncOp: return EOpPreIncrement; - case EHTokDecOp: return EOpPreDecrement; - - default: return EOpNull; // means not a pre-unary op - } -} - -// Map parsing tokens that could be unary operations into unary operators. -// These are just the ones that can appear behind its operand. -TOperator HlslOpMap::postUnary(EHlslTokenClass op) -{ - switch (op) { - case EHTokDot: return EOpIndexDirectStruct; - case EHTokLeftBracket: return EOpIndexIndirect; - - case EHTokIncOp: return EOpPostIncrement; - case EHTokDecOp: return EOpPostDecrement; - - case EHTokColonColon: return EOpScoping; - - default: return EOpNull; // means not a post-unary op - } -} - -// Map operators into their level of precedence. -PrecedenceLevel HlslOpMap::precedenceLevel(TOperator op) -{ - switch (op) { - case EOpLogicalOr: - return PlLogicalOr; - case EOpLogicalXor: - return PlLogicalXor; - case EOpLogicalAnd: - return PlLogicalAnd; - - case EOpInclusiveOr: - return PlBitwiseOr; - case EOpExclusiveOr: - return PlBitwiseXor; - case EOpAnd: - return PlBitwiseAnd; - - case EOpEqual: - case EOpNotEqual: - return PlEquality; - - case EOpLessThan: - case EOpGreaterThan: - case EOpLessThanEqual: - case EOpGreaterThanEqual: - return PlRelational; - - case EOpRightShift: - case EOpLeftShift: - return PlShift; - - case EOpAdd: - case EOpSub: - return PlAdd; - - case EOpMul: - case EOpDiv: - case EOpMod: - return PlMul; - - default: - return PlBad; - } -} - -} // end namespace glslang diff --git a/External/glslang/hlsl/hlslOpMap.h b/External/glslang/hlsl/hlslOpMap.h deleted file mode 100644 index 4e783f3f..00000000 --- a/External/glslang/hlsl/hlslOpMap.h +++ /dev/null @@ -1,69 +0,0 @@ -// -// Copyright (C) 2016 Google, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of Google, Inc., nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -#ifndef HLSLOPMAP_H_ -#define HLSLOPMAP_H_ - -#include "hlslScanContext.h" - -namespace glslang { - - enum PrecedenceLevel { - PlBad, - PlLogicalOr, - PlLogicalXor, - PlLogicalAnd, - PlBitwiseOr, - PlBitwiseXor, - PlBitwiseAnd, - PlEquality, - PlRelational, - PlShift, - PlAdd, - PlMul - }; - - class HlslOpMap { - public: - static TOperator assignment(EHlslTokenClass op); - static TOperator binary(EHlslTokenClass op); - static TOperator preUnary(EHlslTokenClass op); - static TOperator postUnary(EHlslTokenClass op); - static PrecedenceLevel precedenceLevel(TOperator); - }; - -} // end namespace glslang - -#endif // HLSLOPMAP_H_ diff --git a/External/glslang/hlsl/hlslParseHelper.cpp b/External/glslang/hlsl/hlslParseHelper.cpp deleted file mode 100644 index ef45da10..00000000 --- a/External/glslang/hlsl/hlslParseHelper.cpp +++ /dev/null @@ -1,9943 +0,0 @@ -// -// Copyright (C) 2017 Google, Inc. -// Copyright (C) 2017 LunarG, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -#include "hlslParseHelper.h" -#include "hlslScanContext.h" -#include "hlslGrammar.h" -#include "hlslAttributes.h" - -#include "../glslang/MachineIndependent/Scan.h" -#include "../glslang/MachineIndependent/preprocessor/PpContext.h" - -#include "../glslang/OSDependent/osinclude.h" - -#include -#include -#include -#include -#include - -namespace glslang { - -HlslParseContext::HlslParseContext(TSymbolTable& symbolTable, TIntermediate& interm, bool parsingBuiltins, - int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage language, - TInfoSink& infoSink, - const TString sourceEntryPointName, - bool forwardCompatible, EShMessages messages) : - TParseContextBase(symbolTable, interm, parsingBuiltins, version, profile, spvVersion, language, infoSink, - forwardCompatible, messages, &sourceEntryPointName), - annotationNestingLevel(0), - inputPatch(nullptr), - nextInLocation(0), nextOutLocation(0), - entryPointFunction(nullptr), - entryPointFunctionBody(nullptr), - gsStreamOutput(nullptr), - clipDistanceOutput(nullptr), - cullDistanceOutput(nullptr), - clipDistanceInput(nullptr), - cullDistanceInput(nullptr) -{ - globalUniformDefaults.clear(); - globalUniformDefaults.layoutMatrix = ElmRowMajor; - globalUniformDefaults.layoutPacking = ElpStd140; - - globalBufferDefaults.clear(); - globalBufferDefaults.layoutMatrix = ElmRowMajor; - globalBufferDefaults.layoutPacking = ElpStd430; - - globalInputDefaults.clear(); - globalOutputDefaults.clear(); - - clipSemanticNSizeIn.fill(0); - cullSemanticNSizeIn.fill(0); - clipSemanticNSizeOut.fill(0); - cullSemanticNSizeOut.fill(0); - - // "Shaders in the transform - // feedback capturing mode have an initial global default of - // layout(xfb_buffer = 0) out;" - if (language == EShLangVertex || - language == EShLangTessControl || - language == EShLangTessEvaluation || - language == EShLangGeometry) - globalOutputDefaults.layoutXfbBuffer = 0; - - if (language == EShLangGeometry) - globalOutputDefaults.layoutStream = 0; - - if (spvVersion.spv == 0 || spvVersion.vulkan == 0) - infoSink.info << "ERROR: HLSL currently only supported when requesting SPIR-V for Vulkan.\n"; -} - -HlslParseContext::~HlslParseContext() -{ -} - -void HlslParseContext::initializeExtensionBehavior() -{ - TParseContextBase::initializeExtensionBehavior(); - - // HLSL allows #line by default. - extensionBehavior[E_GL_GOOGLE_cpp_style_line_directive] = EBhEnable; -} - -void HlslParseContext::setLimits(const TBuiltInResource& r) -{ - resources = r; - intermediate.setLimits(resources); -} - -// -// Parse an array of strings using the parser in HlslRules. -// -// Returns true for successful acceptance of the shader, false if any errors. -// -bool HlslParseContext::parseShaderStrings(TPpContext& ppContext, TInputScanner& input, bool versionWillBeError) -{ - currentScanner = &input; - ppContext.setInput(input, versionWillBeError); - - HlslScanContext scanContext(*this, ppContext); - HlslGrammar grammar(scanContext, *this); - if (!grammar.parse()) { - // Print a message formated such that if you click on the message it will take you right to - // the line through most UIs. - const glslang::TSourceLoc& sourceLoc = input.getSourceLoc(); - infoSink.info << sourceLoc.name << "(" << sourceLoc.line << "): error at column " << sourceLoc.column - << ", HLSL parsing failed.\n"; - ++numErrors; - return false; - } - - finish(); - - return numErrors == 0; -} - -// -// Return true if this l-value node should be converted in some manner. -// For instance: turning a load aggregate into a store in an l-value. -// -bool HlslParseContext::shouldConvertLValue(const TIntermNode* node) const -{ - if (node == nullptr || node->getAsTyped() == nullptr) - return false; - - const TIntermAggregate* lhsAsAggregate = node->getAsAggregate(); - const TIntermBinary* lhsAsBinary = node->getAsBinaryNode(); - - // If it's a swizzled/indexed aggregate, look at the left node instead. - if (lhsAsBinary != nullptr && - (lhsAsBinary->getOp() == EOpVectorSwizzle || lhsAsBinary->getOp() == EOpIndexDirect)) - lhsAsAggregate = lhsAsBinary->getLeft()->getAsAggregate(); - if (lhsAsAggregate != nullptr && lhsAsAggregate->getOp() == EOpImageLoad) - return true; - - return false; -} - -void HlslParseContext::growGlobalUniformBlock(const TSourceLoc& loc, TType& memberType, const TString& memberName, - TTypeList* newTypeList) -{ - newTypeList = nullptr; - correctUniform(memberType.getQualifier()); - if (memberType.isStruct()) { - auto it = ioTypeMap.find(memberType.getStruct()); - if (it != ioTypeMap.end() && it->second.uniform) - newTypeList = it->second.uniform; - } - TParseContextBase::growGlobalUniformBlock(loc, memberType, memberName, newTypeList); -} - -// -// Return a TLayoutFormat corresponding to the given texture type. -// -TLayoutFormat HlslParseContext::getLayoutFromTxType(const TSourceLoc& loc, const TType& txType) -{ - if (txType.isStruct()) { - // TODO: implement. - error(loc, "unimplemented: structure type in image or buffer", "", ""); - return ElfNone; - } - - const int components = txType.getVectorSize(); - const TBasicType txBasicType = txType.getBasicType(); - - const auto selectFormat = [this,&components](TLayoutFormat v1, TLayoutFormat v2, TLayoutFormat v4) -> TLayoutFormat { - if (intermediate.getNoStorageFormat()) - return ElfNone; - - return components == 1 ? v1 : - components == 2 ? v2 : v4; - }; - - switch (txBasicType) { - case EbtFloat: return selectFormat(ElfR32f, ElfRg32f, ElfRgba32f); - case EbtInt: return selectFormat(ElfR32i, ElfRg32i, ElfRgba32i); - case EbtUint: return selectFormat(ElfR32ui, ElfRg32ui, ElfRgba32ui); - default: - error(loc, "unknown basic type in image format", "", ""); - return ElfNone; - } -} - -// -// Both test and if necessary, spit out an error, to see if the node is really -// an l-value that can be operated on this way. -// -// Returns true if there was an error. -// -bool HlslParseContext::lValueErrorCheck(const TSourceLoc& loc, const char* op, TIntermTyped* node) -{ - if (shouldConvertLValue(node)) { - // if we're writing to a texture, it must be an RW form. - - TIntermAggregate* lhsAsAggregate = node->getAsAggregate(); - TIntermTyped* object = lhsAsAggregate->getSequence()[0]->getAsTyped(); - - if (!object->getType().getSampler().isImage()) { - error(loc, "operator[] on a non-RW texture must be an r-value", "", ""); - return true; - } - } - - // We tolerate samplers as l-values, even though they are nominally - // illegal, because we expect a later optimization to eliminate them. - if (node->getType().getBasicType() == EbtSampler) { - intermediate.setNeedsLegalization(); - return false; - } - - // Let the base class check errors - return TParseContextBase::lValueErrorCheck(loc, op, node); -} - -// -// This function handles l-value conversions and verifications. It uses, but is not synonymous -// with lValueErrorCheck. That function accepts an l-value directly, while this one must be -// given the surrounding tree - e.g, with an assignment, so we can convert the assign into a -// series of other image operations. -// -// Most things are passed through unmodified, except for error checking. -// -TIntermTyped* HlslParseContext::handleLvalue(const TSourceLoc& loc, const char* op, TIntermTyped*& node) -{ - if (node == nullptr) - return nullptr; - - TIntermBinary* nodeAsBinary = node->getAsBinaryNode(); - TIntermUnary* nodeAsUnary = node->getAsUnaryNode(); - TIntermAggregate* sequence = nullptr; - - TIntermTyped* lhs = nodeAsUnary ? nodeAsUnary->getOperand() : - nodeAsBinary ? nodeAsBinary->getLeft() : - nullptr; - - // Early bail out if there is no conversion to apply - if (!shouldConvertLValue(lhs)) { - if (lhs != nullptr) - if (lValueErrorCheck(loc, op, lhs)) - return nullptr; - return node; - } - - // *** If we get here, we're going to apply some conversion to an l-value. - - // Helper to create a load. - const auto makeLoad = [&](TIntermSymbol* rhsTmp, TIntermTyped* object, TIntermTyped* coord, const TType& derefType) { - TIntermAggregate* loadOp = new TIntermAggregate(EOpImageLoad); - loadOp->setLoc(loc); - loadOp->getSequence().push_back(object); - loadOp->getSequence().push_back(intermediate.addSymbol(*coord->getAsSymbolNode())); - loadOp->setType(derefType); - - sequence = intermediate.growAggregate(sequence, - intermediate.addAssign(EOpAssign, rhsTmp, loadOp, loc), - loc); - }; - - // Helper to create a store. - const auto makeStore = [&](TIntermTyped* object, TIntermTyped* coord, TIntermSymbol* rhsTmp) { - TIntermAggregate* storeOp = new TIntermAggregate(EOpImageStore); - storeOp->getSequence().push_back(object); - storeOp->getSequence().push_back(coord); - storeOp->getSequence().push_back(intermediate.addSymbol(*rhsTmp)); - storeOp->setLoc(loc); - storeOp->setType(TType(EbtVoid)); - - sequence = intermediate.growAggregate(sequence, storeOp); - }; - - // Helper to create an assign. - const auto makeBinary = [&](TOperator op, TIntermTyped* lhs, TIntermTyped* rhs) { - sequence = intermediate.growAggregate(sequence, - intermediate.addBinaryNode(op, lhs, rhs, loc, lhs->getType()), - loc); - }; - - // Helper to complete sequence by adding trailing variable, so we evaluate to the right value. - const auto finishSequence = [&](TIntermSymbol* rhsTmp, const TType& derefType) -> TIntermAggregate* { - // Add a trailing use of the temp, so the sequence returns the proper value. - sequence = intermediate.growAggregate(sequence, intermediate.addSymbol(*rhsTmp)); - sequence->setOperator(EOpSequence); - sequence->setLoc(loc); - sequence->setType(derefType); - - return sequence; - }; - - // Helper to add unary op - const auto makeUnary = [&](TOperator op, TIntermSymbol* rhsTmp) { - sequence = intermediate.growAggregate(sequence, - intermediate.addUnaryNode(op, intermediate.addSymbol(*rhsTmp), loc, - rhsTmp->getType()), - loc); - }; - - // Return true if swizzle or index writes all components of the given variable. - const auto writesAllComponents = [&](TIntermSymbol* var, TIntermBinary* swizzle) -> bool { - if (swizzle == nullptr) // not a swizzle or index - return true; - - // Track which components are being set. - std::array compIsSet; - compIsSet.fill(false); - - const TIntermConstantUnion* asConst = swizzle->getRight()->getAsConstantUnion(); - const TIntermAggregate* asAggregate = swizzle->getRight()->getAsAggregate(); - - // This could be either a direct index, or a swizzle. - if (asConst) { - compIsSet[asConst->getConstArray()[0].getIConst()] = true; - } else if (asAggregate) { - const TIntermSequence& seq = asAggregate->getSequence(); - for (int comp=0; compgetAsConstantUnion()->getConstArray()[0].getIConst()] = true; - } else { - assert(0); - } - - // Return true if all components are being set by the index or swizzle - return std::all_of(compIsSet.begin(), compIsSet.begin() + var->getType().getVectorSize(), - [](bool isSet) { return isSet; } ); - }; - - // Create swizzle matching input swizzle - const auto addSwizzle = [&](TIntermSymbol* var, TIntermBinary* swizzle) -> TIntermTyped* { - if (swizzle) - return intermediate.addBinaryNode(swizzle->getOp(), var, swizzle->getRight(), loc, swizzle->getType()); - else - return var; - }; - - TIntermBinary* lhsAsBinary = lhs->getAsBinaryNode(); - TIntermAggregate* lhsAsAggregate = lhs->getAsAggregate(); - bool lhsIsSwizzle = false; - - // If it's a swizzled L-value, remember the swizzle, and use the LHS. - if (lhsAsBinary != nullptr && (lhsAsBinary->getOp() == EOpVectorSwizzle || lhsAsBinary->getOp() == EOpIndexDirect)) { - lhsAsAggregate = lhsAsBinary->getLeft()->getAsAggregate(); - lhsIsSwizzle = true; - } - - TIntermTyped* object = lhsAsAggregate->getSequence()[0]->getAsTyped(); - TIntermTyped* coord = lhsAsAggregate->getSequence()[1]->getAsTyped(); - - const TSampler& texSampler = object->getType().getSampler(); - - TType objDerefType; - getTextureReturnType(texSampler, objDerefType); - - if (nodeAsBinary) { - TIntermTyped* rhs = nodeAsBinary->getRight(); - const TOperator assignOp = nodeAsBinary->getOp(); - - bool isModifyOp = false; - - switch (assignOp) { - case EOpAddAssign: - case EOpSubAssign: - case EOpMulAssign: - case EOpVectorTimesMatrixAssign: - case EOpVectorTimesScalarAssign: - case EOpMatrixTimesScalarAssign: - case EOpMatrixTimesMatrixAssign: - case EOpDivAssign: - case EOpModAssign: - case EOpAndAssign: - case EOpInclusiveOrAssign: - case EOpExclusiveOrAssign: - case EOpLeftShiftAssign: - case EOpRightShiftAssign: - isModifyOp = true; - // fall through... - case EOpAssign: - { - // Since this is an lvalue, we'll convert an image load to a sequence like this - // (to still provide the value): - // OpSequence - // OpImageStore(object, lhs, rhs) - // rhs - // But if it's not a simple symbol RHS (say, a fn call), we don't want to duplicate the RHS, - // so we'll convert instead to this: - // OpSequence - // rhsTmp = rhs - // OpImageStore(object, coord, rhsTmp) - // rhsTmp - // If this is a read-modify-write op, like +=, we issue: - // OpSequence - // coordtmp = load's param1 - // rhsTmp = OpImageLoad(object, coordTmp) - // rhsTmp op= rhs - // OpImageStore(object, coordTmp, rhsTmp) - // rhsTmp - // - // If the lvalue is swizzled, we apply that when writing the temp variable, like so: - // ... - // rhsTmp.some_swizzle = ... - // For partial writes, an error is generated. - - TIntermSymbol* rhsTmp = rhs->getAsSymbolNode(); - TIntermTyped* coordTmp = coord; - - if (rhsTmp == nullptr || isModifyOp || lhsIsSwizzle) { - rhsTmp = makeInternalVariableNode(loc, "storeTemp", objDerefType); - - // Partial updates not yet supported - if (!writesAllComponents(rhsTmp, lhsAsBinary)) { - error(loc, "unimplemented: partial image updates", "", ""); - } - - // Assign storeTemp = rhs - if (isModifyOp) { - // We have to make a temp var for the coordinate, to avoid evaluating it twice. - coordTmp = makeInternalVariableNode(loc, "coordTemp", coord->getType()); - makeBinary(EOpAssign, coordTmp, coord); // coordtmp = load[param1] - makeLoad(rhsTmp, object, coordTmp, objDerefType); // rhsTmp = OpImageLoad(object, coordTmp) - } - - // rhsTmp op= rhs. - makeBinary(assignOp, addSwizzle(intermediate.addSymbol(*rhsTmp), lhsAsBinary), rhs); - } - - makeStore(object, coordTmp, rhsTmp); // add a store - return finishSequence(rhsTmp, objDerefType); // return rhsTmp from sequence - } - - default: - break; - } - } - - if (nodeAsUnary) { - const TOperator assignOp = nodeAsUnary->getOp(); - - switch (assignOp) { - case EOpPreIncrement: - case EOpPreDecrement: - { - // We turn this into: - // OpSequence - // coordtmp = load's param1 - // rhsTmp = OpImageLoad(object, coordTmp) - // rhsTmp op - // OpImageStore(object, coordTmp, rhsTmp) - // rhsTmp - - TIntermSymbol* rhsTmp = makeInternalVariableNode(loc, "storeTemp", objDerefType); - TIntermTyped* coordTmp = makeInternalVariableNode(loc, "coordTemp", coord->getType()); - - makeBinary(EOpAssign, coordTmp, coord); // coordtmp = load[param1] - makeLoad(rhsTmp, object, coordTmp, objDerefType); // rhsTmp = OpImageLoad(object, coordTmp) - makeUnary(assignOp, rhsTmp); // op rhsTmp - makeStore(object, coordTmp, rhsTmp); // OpImageStore(object, coordTmp, rhsTmp) - return finishSequence(rhsTmp, objDerefType); // return rhsTmp from sequence - } - - case EOpPostIncrement: - case EOpPostDecrement: - { - // We turn this into: - // OpSequence - // coordtmp = load's param1 - // rhsTmp1 = OpImageLoad(object, coordTmp) - // rhsTmp2 = rhsTmp1 - // rhsTmp2 op - // OpImageStore(object, coordTmp, rhsTmp2) - // rhsTmp1 (pre-op value) - TIntermSymbol* rhsTmp1 = makeInternalVariableNode(loc, "storeTempPre", objDerefType); - TIntermSymbol* rhsTmp2 = makeInternalVariableNode(loc, "storeTempPost", objDerefType); - TIntermTyped* coordTmp = makeInternalVariableNode(loc, "coordTemp", coord->getType()); - - makeBinary(EOpAssign, coordTmp, coord); // coordtmp = load[param1] - makeLoad(rhsTmp1, object, coordTmp, objDerefType); // rhsTmp1 = OpImageLoad(object, coordTmp) - makeBinary(EOpAssign, rhsTmp2, rhsTmp1); // rhsTmp2 = rhsTmp1 - makeUnary(assignOp, rhsTmp2); // rhsTmp op - makeStore(object, coordTmp, rhsTmp2); // OpImageStore(object, coordTmp, rhsTmp2) - return finishSequence(rhsTmp1, objDerefType); // return rhsTmp from sequence - } - - default: - break; - } - } - - if (lhs) - if (lValueErrorCheck(loc, op, lhs)) - return nullptr; - - return node; -} - -void HlslParseContext::handlePragma(const TSourceLoc& loc, const TVector& tokens) -{ - if (pragmaCallback) - pragmaCallback(loc.line, tokens); - - if (tokens.size() == 0) - return; - - // These pragmas are case insensitive in HLSL, so we'll compare in lower case. - TVector lowerTokens = tokens; - - for (auto it = lowerTokens.begin(); it != lowerTokens.end(); ++it) - std::transform(it->begin(), it->end(), it->begin(), ::tolower); - - // Handle pack_matrix - if (tokens.size() == 4 && lowerTokens[0] == "pack_matrix" && tokens[1] == "(" && tokens[3] == ")") { - // Note that HLSL semantic order is Mrc, not Mcr like SPIR-V, so we reverse the sense. - // Row major becomes column major and vice versa. - - if (lowerTokens[2] == "row_major") { - globalUniformDefaults.layoutMatrix = globalBufferDefaults.layoutMatrix = ElmColumnMajor; - } else if (lowerTokens[2] == "column_major") { - globalUniformDefaults.layoutMatrix = globalBufferDefaults.layoutMatrix = ElmRowMajor; - } else { - // unknown majorness strings are treated as (HLSL column major)==(SPIR-V row major) - warn(loc, "unknown pack_matrix pragma value", tokens[2].c_str(), ""); - globalUniformDefaults.layoutMatrix = globalBufferDefaults.layoutMatrix = ElmRowMajor; - } - return; - } - - // Handle once - if (lowerTokens[0] == "once") { - warn(loc, "not implemented", "#pragma once", ""); - return; - } -} - -// -// Look at a '.' matrix selector string and change it into components -// for a matrix. There are two types: -// -// _21 second row, first column (one based) -// _m21 third row, second column (zero based) -// -// Returns true if there is no error. -// -bool HlslParseContext::parseMatrixSwizzleSelector(const TSourceLoc& loc, const TString& fields, int cols, int rows, - TSwizzleSelectors& components) -{ - int startPos[MaxSwizzleSelectors]; - int numComps = 0; - TString compString = fields; - - // Find where each component starts, - // recording the first character position after the '_'. - for (size_t c = 0; c < compString.size(); ++c) { - if (compString[c] == '_') { - if (numComps >= MaxSwizzleSelectors) { - error(loc, "matrix component swizzle has too many components", compString.c_str(), ""); - return false; - } - if (c > compString.size() - 3 || - ((compString[c+1] == 'm' || compString[c+1] == 'M') && c > compString.size() - 4)) { - error(loc, "matrix component swizzle missing", compString.c_str(), ""); - return false; - } - startPos[numComps++] = (int)c + 1; - } - } - - // Process each component - for (int i = 0; i < numComps; ++i) { - int pos = startPos[i]; - int bias = -1; - if (compString[pos] == 'm' || compString[pos] == 'M') { - bias = 0; - ++pos; - } - TMatrixSelector comp; - comp.coord1 = compString[pos+0] - '0' + bias; - comp.coord2 = compString[pos+1] - '0' + bias; - if (comp.coord1 < 0 || comp.coord1 >= cols) { - error(loc, "matrix row component out of range", compString.c_str(), ""); - return false; - } - if (comp.coord2 < 0 || comp.coord2 >= rows) { - error(loc, "matrix column component out of range", compString.c_str(), ""); - return false; - } - components.push_back(comp); - } - - return true; -} - -// If the 'comps' express a column of a matrix, -// return the column. Column means the first coords all match. -// -// Otherwise, return -1. -// -int HlslParseContext::getMatrixComponentsColumn(int rows, const TSwizzleSelectors& selector) -{ - int col = -1; - - // right number of comps? - if (selector.size() != rows) - return -1; - - // all comps in the same column? - // rows in order? - col = selector[0].coord1; - for (int i = 0; i < rows; ++i) { - if (col != selector[i].coord1) - return -1; - if (i != selector[i].coord2) - return -1; - } - - return col; -} - -// -// Handle seeing a variable identifier in the grammar. -// -TIntermTyped* HlslParseContext::handleVariable(const TSourceLoc& loc, const TString* string) -{ - int thisDepth; - TSymbol* symbol = symbolTable.find(*string, thisDepth); - if (symbol && symbol->getAsVariable() && symbol->getAsVariable()->isUserType()) { - error(loc, "expected symbol, not user-defined type", string->c_str(), ""); - return nullptr; - } - - // Error check for requiring specific extensions present. - if (symbol && symbol->getNumExtensions()) - requireExtensions(loc, symbol->getNumExtensions(), symbol->getExtensions(), symbol->getName().c_str()); - - const TVariable* variable = nullptr; - const TAnonMember* anon = symbol ? symbol->getAsAnonMember() : nullptr; - TIntermTyped* node = nullptr; - if (anon) { - // It was a member of an anonymous container, which could be a 'this' structure. - - // Create a subtree for its dereference. - if (thisDepth > 0) { - variable = getImplicitThis(thisDepth); - if (variable == nullptr) - error(loc, "cannot access member variables (static member function?)", "this", ""); - } - if (variable == nullptr) - variable = anon->getAnonContainer().getAsVariable(); - - TIntermTyped* container = intermediate.addSymbol(*variable, loc); - TIntermTyped* constNode = intermediate.addConstantUnion(anon->getMemberNumber(), loc); - node = intermediate.addIndex(EOpIndexDirectStruct, container, constNode, loc); - - node->setType(*(*variable->getType().getStruct())[anon->getMemberNumber()].type); - if (node->getType().hiddenMember()) - error(loc, "member of nameless block was not redeclared", string->c_str(), ""); - } else { - // Not a member of an anonymous container. - - // The symbol table search was done in the lexical phase. - // See if it was a variable. - variable = symbol ? symbol->getAsVariable() : nullptr; - if (variable) { - if ((variable->getType().getBasicType() == EbtBlock || - variable->getType().getBasicType() == EbtStruct) && variable->getType().getStruct() == nullptr) { - error(loc, "cannot be used (maybe an instance name is needed)", string->c_str(), ""); - variable = nullptr; - } - } else { - if (symbol) - error(loc, "variable name expected", string->c_str(), ""); - } - - // Recovery, if it wasn't found or was not a variable. - if (variable == nullptr) { - error(loc, "unknown variable", string->c_str(), ""); - variable = new TVariable(string, TType(EbtVoid)); - } - - if (variable->getType().getQualifier().isFrontEndConstant()) - node = intermediate.addConstantUnion(variable->getConstArray(), variable->getType(), loc); - else - node = intermediate.addSymbol(*variable, loc); - } - - if (variable->getType().getQualifier().isIo()) - intermediate.addIoAccessed(*string); - - return node; -} - -// -// Handle operator[] on any objects it applies to. Currently: -// Textures -// Buffers -// -TIntermTyped* HlslParseContext::handleBracketOperator(const TSourceLoc& loc, TIntermTyped* base, TIntermTyped* index) -{ - // handle r-value operator[] on textures and images. l-values will be processed later. - if (base->getType().getBasicType() == EbtSampler && !base->isArray()) { - const TSampler& sampler = base->getType().getSampler(); - if (sampler.isImage() || sampler.isTexture()) { - if (! mipsOperatorMipArg.empty() && mipsOperatorMipArg.back().mipLevel == nullptr) { - // The first operator[] to a .mips[] sequence is the mip level. We'll remember it. - mipsOperatorMipArg.back().mipLevel = index; - return base; // next [] index is to the same base. - } else { - TIntermAggregate* load = new TIntermAggregate(sampler.isImage() ? EOpImageLoad : EOpTextureFetch); - - TType sampReturnType; - getTextureReturnType(sampler, sampReturnType); - - load->setType(sampReturnType); - load->setLoc(loc); - load->getSequence().push_back(base); - load->getSequence().push_back(index); - - // Textures need a MIP. If we saw one go by, use it. Otherwise, use zero. - if (sampler.isTexture()) { - if (! mipsOperatorMipArg.empty()) { - load->getSequence().push_back(mipsOperatorMipArg.back().mipLevel); - mipsOperatorMipArg.pop_back(); - } else { - load->getSequence().push_back(intermediate.addConstantUnion(0, loc, true)); - } - } - - return load; - } - } - } - - // Handle operator[] on structured buffers: this indexes into the array element of the buffer. - // indexStructBufferContent returns nullptr if it isn't a structuredbuffer (SSBO). - TIntermTyped* sbArray = indexStructBufferContent(loc, base); - if (sbArray != nullptr) { - if (sbArray == nullptr) - return nullptr; - - // Now we'll apply the [] index to that array - const TOperator idxOp = (index->getQualifier().storage == EvqConst) ? EOpIndexDirect : EOpIndexIndirect; - - TIntermTyped* element = intermediate.addIndex(idxOp, sbArray, index, loc); - const TType derefType(sbArray->getType(), 0); - element->setType(derefType); - return element; - } - - return nullptr; -} - -// -// Cast index value to a uint if it isn't already (for operator[], load indexes, etc) -TIntermTyped* HlslParseContext::makeIntegerIndex(TIntermTyped* index) -{ - const TBasicType indexBasicType = index->getType().getBasicType(); - const int vecSize = index->getType().getVectorSize(); - - // We can use int types directly as the index - if (indexBasicType == EbtInt || indexBasicType == EbtUint || - indexBasicType == EbtInt64 || indexBasicType == EbtUint64) - return index; - - // Cast index to unsigned integer if it isn't one. - return intermediate.addConversion(EOpConstructUint, TType(EbtUint, EvqTemporary, vecSize), index); -} - -// -// Handle seeing a base[index] dereference in the grammar. -// -TIntermTyped* HlslParseContext::handleBracketDereference(const TSourceLoc& loc, TIntermTyped* base, TIntermTyped* index) -{ - index = makeIntegerIndex(index); - - if (index == nullptr) { - error(loc, " unknown index type ", "", ""); - return nullptr; - } - - TIntermTyped* result = handleBracketOperator(loc, base, index); - - if (result != nullptr) - return result; // it was handled as an operator[] - - bool flattened = false; - int indexValue = 0; - if (index->getQualifier().isFrontEndConstant()) - indexValue = index->getAsConstantUnion()->getConstArray()[0].getIConst(); - - variableCheck(base); - if (! base->isArray() && ! base->isMatrix() && ! base->isVector()) { - if (base->getAsSymbolNode()) - error(loc, " left of '[' is not of type array, matrix, or vector ", - base->getAsSymbolNode()->getName().c_str(), ""); - else - error(loc, " left of '[' is not of type array, matrix, or vector ", "expression", ""); - } else if (base->getType().getQualifier().storage == EvqConst && index->getQualifier().storage == EvqConst) { - // both base and index are front-end constants - checkIndex(loc, base->getType(), indexValue); - return intermediate.foldDereference(base, indexValue, loc); - } else { - // at least one of base and index is variable... - - if (index->getQualifier().isFrontEndConstant()) - checkIndex(loc, base->getType(), indexValue); - - if (base->getType().isScalarOrVec1()) - result = base; - else if (base->getAsSymbolNode() && wasFlattened(base)) { - if (index->getQualifier().storage != EvqConst) - error(loc, "Invalid variable index to flattened array", base->getAsSymbolNode()->getName().c_str(), ""); - - result = flattenAccess(base, indexValue); - flattened = (result != base); - } else { - if (index->getQualifier().isFrontEndConstant()) { - if (base->getType().isUnsizedArray()) - base->getWritableType().updateImplicitArraySize(indexValue + 1); - else - checkIndex(loc, base->getType(), indexValue); - result = intermediate.addIndex(EOpIndexDirect, base, index, loc); - } else - result = intermediate.addIndex(EOpIndexIndirect, base, index, loc); - } - } - - if (result == nullptr) { - // Insert dummy error-recovery result - result = intermediate.addConstantUnion(0.0, EbtFloat, loc); - } else { - // If the array reference was flattened, it has the correct type. E.g, if it was - // a uniform array, it was flattened INTO a set of scalar uniforms, not scalar temps. - // In that case, we preserve the qualifiers. - if (!flattened) { - // Insert valid dereferenced result - TType newType(base->getType(), 0); // dereferenced type - if (base->getType().getQualifier().storage == EvqConst && index->getQualifier().storage == EvqConst) - newType.getQualifier().storage = EvqConst; - else - newType.getQualifier().storage = EvqTemporary; - result->setType(newType); - } - } - - return result; -} - -// Handle seeing a binary node with a math operation. -TIntermTyped* HlslParseContext::handleBinaryMath(const TSourceLoc& loc, const char* str, TOperator op, - TIntermTyped* left, TIntermTyped* right) -{ - TIntermTyped* result = intermediate.addBinaryMath(op, left, right, loc); - if (result == nullptr) - binaryOpError(loc, str, left->getCompleteString(), right->getCompleteString()); - - return result; -} - -// Handle seeing a unary node with a math operation. -TIntermTyped* HlslParseContext::handleUnaryMath(const TSourceLoc& loc, const char* str, TOperator op, - TIntermTyped* childNode) -{ - TIntermTyped* result = intermediate.addUnaryMath(op, childNode, loc); - - if (result) - return result; - else - unaryOpError(loc, str, childNode->getCompleteString()); - - return childNode; -} -// -// Return true if the name is a struct buffer method -// -bool HlslParseContext::isStructBufferMethod(const TString& name) const -{ - return - name == "GetDimensions" || - name == "Load" || - name == "Load2" || - name == "Load3" || - name == "Load4" || - name == "Store" || - name == "Store2" || - name == "Store3" || - name == "Store4" || - name == "InterlockedAdd" || - name == "InterlockedAnd" || - name == "InterlockedCompareExchange" || - name == "InterlockedCompareStore" || - name == "InterlockedExchange" || - name == "InterlockedMax" || - name == "InterlockedMin" || - name == "InterlockedOr" || - name == "InterlockedXor" || - name == "IncrementCounter" || - name == "DecrementCounter" || - name == "Append" || - name == "Consume"; -} - -// -// Handle seeing a base.field dereference in the grammar, where 'field' is a -// swizzle or member variable. -// -TIntermTyped* HlslParseContext::handleDotDereference(const TSourceLoc& loc, TIntermTyped* base, const TString& field) -{ - variableCheck(base); - - if (base->isArray()) { - error(loc, "cannot apply to an array:", ".", field.c_str()); - return base; - } - - TIntermTyped* result = base; - - if (base->getType().getBasicType() == EbtSampler) { - // Handle .mips[mipid][pos] operation on textures - const TSampler& sampler = base->getType().getSampler(); - if (sampler.isTexture() && field == "mips") { - // Push a null to signify that we expect a mip level under operator[] next. - mipsOperatorMipArg.push_back(tMipsOperatorData(loc, nullptr)); - // Keep 'result' pointing to 'base', since we expect an operator[] to go by next. - } else { - if (field == "mips") - error(loc, "unexpected texture type for .mips[][] operator:", - base->getType().getCompleteString().c_str(), ""); - else - error(loc, "unexpected operator on texture type:", field.c_str(), - base->getType().getCompleteString().c_str()); - } - } else if (base->isVector() || base->isScalar()) { - TSwizzleSelectors selectors; - parseSwizzleSelector(loc, field, base->getVectorSize(), selectors); - - if (base->isScalar()) { - if (selectors.size() == 1) - return result; - else { - TType type(base->getBasicType(), EvqTemporary, selectors.size()); - return addConstructor(loc, base, type); - } - } - if (base->getVectorSize() == 1) { - TType scalarType(base->getBasicType(), EvqTemporary, 1); - if (selectors.size() == 1) - return addConstructor(loc, base, scalarType); - else { - TType vectorType(base->getBasicType(), EvqTemporary, selectors.size()); - return addConstructor(loc, addConstructor(loc, base, scalarType), vectorType); - } - } - - if (base->getType().getQualifier().isFrontEndConstant()) - result = intermediate.foldSwizzle(base, selectors, loc); - else { - if (selectors.size() == 1) { - TIntermTyped* index = intermediate.addConstantUnion(selectors[0], loc); - result = intermediate.addIndex(EOpIndexDirect, base, index, loc); - result->setType(TType(base->getBasicType(), EvqTemporary)); - } else { - TIntermTyped* index = intermediate.addSwizzle(selectors, loc); - result = intermediate.addIndex(EOpVectorSwizzle, base, index, loc); - result->setType(TType(base->getBasicType(), EvqTemporary, base->getType().getQualifier().precision, - selectors.size())); - } - } - } else if (base->isMatrix()) { - TSwizzleSelectors selectors; - if (! parseMatrixSwizzleSelector(loc, field, base->getMatrixCols(), base->getMatrixRows(), selectors)) - return result; - - if (selectors.size() == 1) { - // Representable by m[c][r] - if (base->getType().getQualifier().isFrontEndConstant()) { - result = intermediate.foldDereference(base, selectors[0].coord1, loc); - result = intermediate.foldDereference(result, selectors[0].coord2, loc); - } else { - result = intermediate.addIndex(EOpIndexDirect, base, - intermediate.addConstantUnion(selectors[0].coord1, loc), - loc); - TType dereferencedCol(base->getType(), 0); - result->setType(dereferencedCol); - result = intermediate.addIndex(EOpIndexDirect, result, - intermediate.addConstantUnion(selectors[0].coord2, loc), - loc); - TType dereferenced(dereferencedCol, 0); - result->setType(dereferenced); - } - } else { - int column = getMatrixComponentsColumn(base->getMatrixRows(), selectors); - if (column >= 0) { - // Representable by m[c] - if (base->getType().getQualifier().isFrontEndConstant()) - result = intermediate.foldDereference(base, column, loc); - else { - result = intermediate.addIndex(EOpIndexDirect, base, intermediate.addConstantUnion(column, loc), - loc); - TType dereferenced(base->getType(), 0); - result->setType(dereferenced); - } - } else { - // general case, not a column, not a single component - TIntermTyped* index = intermediate.addSwizzle(selectors, loc); - result = intermediate.addIndex(EOpMatrixSwizzle, base, index, loc); - result->setType(TType(base->getBasicType(), EvqTemporary, base->getType().getQualifier().precision, - selectors.size())); - } - } - } else if (base->getBasicType() == EbtStruct || base->getBasicType() == EbtBlock) { - const TTypeList* fields = base->getType().getStruct(); - bool fieldFound = false; - int member; - for (member = 0; member < (int)fields->size(); ++member) { - if ((*fields)[member].type->getFieldName() == field) { - fieldFound = true; - break; - } - } - if (fieldFound) { - if (base->getAsSymbolNode() && wasFlattened(base)) { - result = flattenAccess(base, member); - } else { - if (base->getType().getQualifier().storage == EvqConst) - result = intermediate.foldDereference(base, member, loc); - else { - TIntermTyped* index = intermediate.addConstantUnion(member, loc); - result = intermediate.addIndex(EOpIndexDirectStruct, base, index, loc); - result->setType(*(*fields)[member].type); - } - } - } else - error(loc, "no such field in structure", field.c_str(), ""); - } else - error(loc, "does not apply to this type:", field.c_str(), base->getType().getCompleteString().c_str()); - - return result; -} - -// -// Return true if the field should be treated as a built-in method. -// Return false otherwise. -// -bool HlslParseContext::isBuiltInMethod(const TSourceLoc&, TIntermTyped* base, const TString& field) -{ - if (base == nullptr) - return false; - - variableCheck(base); - - if (base->getType().getBasicType() == EbtSampler) { - return true; - } else if (isStructBufferType(base->getType()) && isStructBufferMethod(field)) { - return true; - } else if (field == "Append" || - field == "RestartStrip") { - // We cannot check the type here: it may be sanitized if we're not compiling a geometry shader, but - // the code is around in the shader source. - return true; - } else - return false; -} - -// Independently establish a built-in that is a member of a structure. -// 'arraySizes' are what's desired for the independent built-in, whatever -// the higher-level source/expression of them was. -void HlslParseContext::splitBuiltIn(const TString& baseName, const TType& memberType, const TArraySizes* arraySizes, - const TQualifier& outerQualifier) -{ - // Because of arrays of structs, we might be asked more than once, - // but the arraySizes passed in should have captured the whole thing - // the first time. - // However, clip/cull rely on multiple updates. - if (!isClipOrCullDistance(memberType)) - if (splitBuiltIns.find(tInterstageIoData(memberType.getQualifier().builtIn, outerQualifier.storage)) != - splitBuiltIns.end()) - return; - - TVariable* ioVar = makeInternalVariable(baseName + "." + memberType.getFieldName(), memberType); - - if (arraySizes != nullptr && !memberType.isArray()) - ioVar->getWritableType().copyArraySizes(*arraySizes); - - splitBuiltIns[tInterstageIoData(memberType.getQualifier().builtIn, outerQualifier.storage)] = ioVar; - if (!isClipOrCullDistance(ioVar->getType())) - trackLinkage(*ioVar); - - // Merge qualifier from the user structure - mergeQualifiers(ioVar->getWritableType().getQualifier(), outerQualifier); - - // Fix the builtin type if needed (e.g, some types require fixed array sizes, no matter how the - // shader declared them). This is done after mergeQualifiers(), in case fixBuiltInIoType looks - // at the qualifier to determine e.g, in or out qualifications. - fixBuiltInIoType(ioVar->getWritableType()); - - // But, not location, we're losing that - ioVar->getWritableType().getQualifier().layoutLocation = TQualifier::layoutLocationEnd; -} - -// Split a type into -// 1. a struct of non-I/O members -// 2. a collection of independent I/O variables -void HlslParseContext::split(const TVariable& variable) -{ - // Create a new variable: - const TType& clonedType = *variable.getType().clone(); - const TType& splitType = split(clonedType, variable.getName(), clonedType.getQualifier()); - splitNonIoVars[variable.getUniqueId()] = makeInternalVariable(variable.getName(), splitType); -} - -// Recursive implementation of split(). -// Returns reference to the modified type. -const TType& HlslParseContext::split(const TType& type, const TString& name, const TQualifier& outerQualifier) -{ - if (type.isStruct()) { - TTypeList* userStructure = type.getWritableStruct(); - for (auto ioType = userStructure->begin(); ioType != userStructure->end(); ) { - if (ioType->type->isBuiltIn()) { - // move out the built-in - splitBuiltIn(name, *ioType->type, type.getArraySizes(), outerQualifier); - ioType = userStructure->erase(ioType); - } else { - split(*ioType->type, name + "." + ioType->type->getFieldName(), outerQualifier); - ++ioType; - } - } - } - - return type; -} - -// Is this an aggregate that should be flattened? -// Can be applied to intermediate levels of type in a hierarchy. -// Some things like flattening uniform arrays are only about the top level -// of the aggregate, triggered on 'topLevel'. -bool HlslParseContext::shouldFlatten(const TType& type, TStorageQualifier qualifier, bool topLevel) const -{ - switch (qualifier) { - case EvqVaryingIn: - case EvqVaryingOut: - return type.isStruct() || type.isArray(); - case EvqUniform: - return (type.isArray() && intermediate.getFlattenUniformArrays() && topLevel) || - (type.isStruct() && type.containsOpaque()); - default: - return false; - }; -} - -// Top level variable flattening: construct data -void HlslParseContext::flatten(const TVariable& variable, bool linkage) -{ - const TType& type = variable.getType(); - - // If it's a standalone built-in, there is nothing to flatten - if (type.isBuiltIn() && !type.isStruct()) - return; - - auto entry = flattenMap.insert(std::make_pair(variable.getUniqueId(), - TFlattenData(type.getQualifier().layoutBinding, - type.getQualifier().layoutLocation))); - - // the item is a map pair, so first->second is the TFlattenData itself. - flatten(variable, type, entry.first->second, variable.getName(), linkage, type.getQualifier(), nullptr); -} - -// Recursively flatten the given variable at the provided type, building the flattenData as we go. -// -// This is mutually recursive with flattenStruct and flattenArray. -// We are going to flatten an arbitrarily nested composite structure into a linear sequence of -// members, and later on, we want to turn a path through the tree structure into a final -// location in this linear sequence. -// -// If the tree was N-ary, that can be directly calculated. However, we are dealing with -// arbitrary numbers - perhaps a struct of 7 members containing an array of 3. Thus, we must -// build a data structure to allow the sequence of bracket and dot operators on arrays and -// structs to arrive at the proper member. -// -// To avoid storing a tree with pointers, we are going to flatten the tree into a vector of integers. -// The leaves are the indexes into the flattened member array. -// Each level will have the next location for the Nth item stored sequentially, so for instance: -// -// struct { float2 a[2]; int b; float4 c[3] }; -// -// This will produce the following flattened tree: -// Pos: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 -// (3, 7, 8, 5, 6, 0, 1, 2, 11, 12, 13, 3, 4, 5} -// -// Given a reference to mystruct.c[1], the access chain is (2,1), so we traverse: -// (0+2) = 8 --> (8+1) = 12 --> 12 = 4 -// -// so the 4th flattened member in traversal order is ours. -// -int HlslParseContext::flatten(const TVariable& variable, const TType& type, - TFlattenData& flattenData, TString name, bool linkage, - const TQualifier& outerQualifier, - const TArraySizes* builtInArraySizes) -{ - // If something is an arrayed struct, the array flattener will recursively call flatten() - // to then flatten the struct, so this is an "if else": we don't do both. - if (type.isArray()) - return flattenArray(variable, type, flattenData, name, linkage, outerQualifier); - else if (type.isStruct()) - return flattenStruct(variable, type, flattenData, name, linkage, outerQualifier, builtInArraySizes); - else { - assert(0); // should never happen - return -1; - } -} - -// Add a single flattened member to the flattened data being tracked for the composite -// Returns true for the final flattening level. -int HlslParseContext::addFlattenedMember(const TVariable& variable, const TType& type, TFlattenData& flattenData, - const TString& memberName, bool linkage, - const TQualifier& outerQualifier, - const TArraySizes* builtInArraySizes) -{ - if (!shouldFlatten(type, outerQualifier.storage, false)) { - // This is as far as we flatten. Insert the variable. - TVariable* memberVariable = makeInternalVariable(memberName, type); - mergeQualifiers(memberVariable->getWritableType().getQualifier(), variable.getType().getQualifier()); - - if (flattenData.nextBinding != TQualifier::layoutBindingEnd) - memberVariable->getWritableType().getQualifier().layoutBinding = flattenData.nextBinding++; - - if (memberVariable->getType().isBuiltIn()) { - // inherited locations are nonsensical for built-ins (TODO: what if semantic had a number) - memberVariable->getWritableType().getQualifier().layoutLocation = TQualifier::layoutLocationEnd; - } else { - // inherited locations must be auto bumped, not replicated - if (flattenData.nextLocation != TQualifier::layoutLocationEnd) { - memberVariable->getWritableType().getQualifier().layoutLocation = flattenData.nextLocation; - flattenData.nextLocation += intermediate.computeTypeLocationSize(memberVariable->getType(), language); - nextOutLocation = std::max(nextOutLocation, flattenData.nextLocation); - } - } - - flattenData.offsets.push_back(static_cast(flattenData.members.size())); - flattenData.members.push_back(memberVariable); - - if (linkage) - trackLinkage(*memberVariable); - - return static_cast(flattenData.offsets.size()) - 1; // location of the member reference - } else { - // Further recursion required - return flatten(variable, type, flattenData, memberName, linkage, outerQualifier, builtInArraySizes); - } -} - -// Figure out the mapping between an aggregate's top members and an -// equivalent set of individual variables. -// -// Assumes shouldFlatten() or equivalent was called first. -int HlslParseContext::flattenStruct(const TVariable& variable, const TType& type, - TFlattenData& flattenData, TString name, bool linkage, - const TQualifier& outerQualifier, - const TArraySizes* builtInArraySizes) -{ - assert(type.isStruct()); - - auto members = *type.getStruct(); - - // Reserve space for this tree level. - int start = static_cast(flattenData.offsets.size()); - int pos = start; - flattenData.offsets.resize(int(pos + members.size()), -1); - - for (int member = 0; member < (int)members.size(); ++member) { - TType& dereferencedType = *members[member].type; - if (dereferencedType.isBuiltIn()) - splitBuiltIn(variable.getName(), dereferencedType, builtInArraySizes, outerQualifier); - else { - const int mpos = addFlattenedMember(variable, dereferencedType, flattenData, - name + "." + dereferencedType.getFieldName(), - linkage, outerQualifier, - builtInArraySizes == nullptr && dereferencedType.isArray() - ? dereferencedType.getArraySizes() - : builtInArraySizes); - flattenData.offsets[pos++] = mpos; - } - } - - return start; -} - -// Figure out mapping between an array's members and an -// equivalent set of individual variables. -// -// Assumes shouldFlatten() or equivalent was called first. -int HlslParseContext::flattenArray(const TVariable& variable, const TType& type, - TFlattenData& flattenData, TString name, bool linkage, - const TQualifier& outerQualifier) -{ - assert(type.isSizedArray()); - - const int size = type.getOuterArraySize(); - const TType dereferencedType(type, 0); - - if (name.empty()) - name = variable.getName(); - - // Reserve space for this tree level. - int start = static_cast(flattenData.offsets.size()); - int pos = start; - flattenData.offsets.resize(int(pos + size), -1); - - for (int element=0; element < size; ++element) { - char elementNumBuf[20]; // sufficient for MAXINT - snprintf(elementNumBuf, sizeof(elementNumBuf)-1, "[%d]", element); - const int mpos = addFlattenedMember(variable, dereferencedType, flattenData, - name + elementNumBuf, linkage, outerQualifier, - type.getArraySizes()); - - flattenData.offsets[pos++] = mpos; - } - - return start; -} - -// Return true if we have flattened this node. -bool HlslParseContext::wasFlattened(const TIntermTyped* node) const -{ - return node != nullptr && node->getAsSymbolNode() != nullptr && - wasFlattened(node->getAsSymbolNode()->getId()); -} - -// Return true if we have split this structure -bool HlslParseContext::wasSplit(const TIntermTyped* node) const -{ - return node != nullptr && node->getAsSymbolNode() != nullptr && - wasSplit(node->getAsSymbolNode()->getId()); -} - -// Turn an access into an aggregate that was flattened to instead be -// an access to the individual variable the member was flattened to. -// Assumes wasFlattened() or equivalent was called first. -TIntermTyped* HlslParseContext::flattenAccess(TIntermTyped* base, int member) -{ - const TType dereferencedType(base->getType(), member); // dereferenced type - const TIntermSymbol& symbolNode = *base->getAsSymbolNode(); - TIntermTyped* flattened = flattenAccess(symbolNode.getId(), member, base->getQualifier().storage, - dereferencedType, symbolNode.getFlattenSubset()); - - return flattened ? flattened : base; -} -TIntermTyped* HlslParseContext::flattenAccess(int uniqueId, int member, TStorageQualifier outerStorage, - const TType& dereferencedType, int subset) -{ - const auto flattenData = flattenMap.find(uniqueId); - - if (flattenData == flattenMap.end()) - return nullptr; - - // Calculate new cumulative offset from the packed tree - int newSubset = flattenData->second.offsets[subset >= 0 ? subset + member : member]; - - TIntermSymbol* subsetSymbol; - if (!shouldFlatten(dereferencedType, outerStorage, false)) { - // Finished flattening: create symbol for variable - member = flattenData->second.offsets[newSubset]; - const TVariable* memberVariable = flattenData->second.members[member]; - subsetSymbol = intermediate.addSymbol(*memberVariable); - subsetSymbol->setFlattenSubset(-1); - } else { - - // If this is not the final flattening, accumulate the position and return - // an object of the partially dereferenced type. - subsetSymbol = new TIntermSymbol(uniqueId, "flattenShadow", dereferencedType); - subsetSymbol->setFlattenSubset(newSubset); - } - - return subsetSymbol; -} - -// For finding where the first leaf is in a subtree of a multi-level aggregate -// that is just getting a subset assigned. Follows the same logic as flattenAccess, -// but logically going down the "left-most" tree branch each step of the way. -// -// Returns the offset into the first leaf of the subset. -int HlslParseContext::findSubtreeOffset(const TIntermNode& node) const -{ - const TIntermSymbol* sym = node.getAsSymbolNode(); - if (sym == nullptr) - return 0; - if (!sym->isArray() && !sym->isStruct()) - return 0; - int subset = sym->getFlattenSubset(); - if (subset == -1) - return 0; - - // Getting this far means a partial aggregate is identified by the flatten subset. - // Find the first leaf of the subset. - - const auto flattenData = flattenMap.find(sym->getId()); - if (flattenData == flattenMap.end()) - return 0; - - return findSubtreeOffset(sym->getType(), subset, flattenData->second.offsets); - - do { - subset = flattenData->second.offsets[subset]; - } while (true); -} -// Recursively do the desent -int HlslParseContext::findSubtreeOffset(const TType& type, int subset, const TVector& offsets) const -{ - if (!type.isArray() && !type.isStruct()) - return offsets[subset]; - TType derefType(type, 0); - return findSubtreeOffset(derefType, offsets[subset], offsets); -}; - -// Find and return the split IO TVariable for id, or nullptr if none. -TVariable* HlslParseContext::getSplitNonIoVar(int id) const -{ - const auto splitNonIoVar = splitNonIoVars.find(id); - if (splitNonIoVar == splitNonIoVars.end()) - return nullptr; - - return splitNonIoVar->second; -} - -// Pass through to base class after remembering built-in mappings. -void HlslParseContext::trackLinkage(TSymbol& symbol) -{ - TBuiltInVariable biType = symbol.getType().getQualifier().builtIn; - - if (biType != EbvNone) - builtInTessLinkageSymbols[biType] = symbol.clone(); - - TParseContextBase::trackLinkage(symbol); -} - - -// Returns true if the built-in is a clip or cull distance variable. -bool HlslParseContext::isClipOrCullDistance(TBuiltInVariable builtIn) -{ - return builtIn == EbvClipDistance || builtIn == EbvCullDistance; -} - -// Some types require fixed array sizes in SPIR-V, but can be scalars or -// arrays of sizes SPIR-V doesn't allow. For example, tessellation factors. -// This creates the right size. A conversion is performed when the internal -// type is copied to or from the external type. This corrects the externally -// facing input or output type to abide downstream semantics. -void HlslParseContext::fixBuiltInIoType(TType& type) -{ - int requiredArraySize = 0; - - switch (type.getQualifier().builtIn) { - case EbvTessLevelOuter: requiredArraySize = 4; break; - case EbvTessLevelInner: requiredArraySize = 2; break; - - case EbvTessCoord: - { - // tesscoord is always a vec3 for the IO variable, no matter the shader's - // declared vector size. - TType tessCoordType(type.getBasicType(), type.getQualifier().storage, 3); - - tessCoordType.getQualifier() = type.getQualifier(); - type.shallowCopy(tessCoordType); - - break; - } - default: - if (isClipOrCullDistance(type)) { - const int loc = type.getQualifier().layoutLocation; - - if (type.getQualifier().builtIn == EbvClipDistance) { - if (type.getQualifier().storage == EvqVaryingIn) - clipSemanticNSizeIn[loc] = type.getVectorSize(); - else - clipSemanticNSizeOut[loc] = type.getVectorSize(); - } else { - if (type.getQualifier().storage == EvqVaryingIn) - cullSemanticNSizeIn[loc] = type.getVectorSize(); - else - cullSemanticNSizeOut[loc] = type.getVectorSize(); - } - } - - return; - } - - // Alter or set array size as needed. - if (requiredArraySize > 0) { - if (!type.isArray() || type.getOuterArraySize() != requiredArraySize) { - TArraySizes* arraySizes = new TArraySizes; - arraySizes->addInnerSize(requiredArraySize); - type.transferArraySizes(arraySizes); - } - } -} - -// Variables that correspond to the user-interface in and out of a stage -// (not the built-in interface) are -// - assigned locations -// - registered as a linkage node (part of the stage's external interface). -// Assumes it is called in the order in which locations should be assigned. -void HlslParseContext::assignToInterface(TVariable& variable) -{ - const auto assignLocation = [&](TVariable& variable) { - TType& type = variable.getWritableType(); - if (!type.isStruct() || type.getStruct()->size() > 0) { - TQualifier& qualifier = type.getQualifier(); - if (qualifier.storage == EvqVaryingIn || qualifier.storage == EvqVaryingOut) { - if (qualifier.builtIn == EbvNone && !qualifier.hasLocation()) { - // Strip off the outer array dimension for those having an extra one. - int size; - if (type.isArray() && qualifier.isArrayedIo(language)) { - TType elementType(type, 0); - size = intermediate.computeTypeLocationSize(elementType, language); - } else - size = intermediate.computeTypeLocationSize(type, language); - - if (qualifier.storage == EvqVaryingIn) { - variable.getWritableType().getQualifier().layoutLocation = nextInLocation; - nextInLocation += size; - } else { - variable.getWritableType().getQualifier().layoutLocation = nextOutLocation; - nextOutLocation += size; - } - } - trackLinkage(variable); - } - } - }; - - if (wasFlattened(variable.getUniqueId())) { - auto& memberList = flattenMap[variable.getUniqueId()].members; - for (auto member = memberList.begin(); member != memberList.end(); ++member) - assignLocation(**member); - } else if (wasSplit(variable.getUniqueId())) { - TVariable* splitIoVar = getSplitNonIoVar(variable.getUniqueId()); - assignLocation(*splitIoVar); - } else { - assignLocation(variable); - } -} - -// -// Handle seeing a function declarator in the grammar. This is the precursor -// to recognizing a function prototype or function definition. -// -void HlslParseContext::handleFunctionDeclarator(const TSourceLoc& loc, TFunction& function, bool prototype) -{ - // - // Multiple declarations of the same function name are allowed. - // - // If this is a definition, the definition production code will check for redefinitions - // (we don't know at this point if it's a definition or not). - // - bool builtIn; - TSymbol* symbol = symbolTable.find(function.getMangledName(), &builtIn); - const TFunction* prevDec = symbol ? symbol->getAsFunction() : 0; - - if (prototype) { - // All built-in functions are defined, even though they don't have a body. - // Count their prototype as a definition instead. - if (symbolTable.atBuiltInLevel()) - function.setDefined(); - else { - if (prevDec && ! builtIn) - symbol->getAsFunction()->setPrototyped(); // need a writable one, but like having prevDec as a const - function.setPrototyped(); - } - } - - // This insert won't actually insert it if it's a duplicate signature, but it will still check for - // other forms of name collisions. - if (! symbolTable.insert(function)) - error(loc, "function name is redeclaration of existing name", function.getName().c_str(), ""); -} - -// For struct buffers with counters, we must pass the counter buffer as hidden parameter. -// This adds the hidden parameter to the parameter list in 'paramNodes' if needed. -// Otherwise, it's a no-op -void HlslParseContext::addStructBufferHiddenCounterParam(const TSourceLoc& loc, TParameter& param, - TIntermAggregate*& paramNodes) -{ - if (! hasStructBuffCounter(*param.type)) - return; - - const TString counterBlockName(intermediate.addCounterBufferName(*param.name)); - - TType counterType; - counterBufferType(loc, counterType); - TVariable *variable = makeInternalVariable(counterBlockName, counterType); - - if (! symbolTable.insert(*variable)) - error(loc, "redefinition", variable->getName().c_str(), ""); - - paramNodes = intermediate.growAggregate(paramNodes, - intermediate.addSymbol(*variable, loc), - loc); -} - -// -// Handle seeing the function prototype in front of a function definition in the grammar. -// The body is handled after this function returns. -// -// Returns an aggregate of parameter-symbol nodes. -// -TIntermAggregate* HlslParseContext::handleFunctionDefinition(const TSourceLoc& loc, TFunction& function, - const TAttributes& attributes, - TIntermNode*& entryPointTree) -{ - currentCaller = function.getMangledName(); - TSymbol* symbol = symbolTable.find(function.getMangledName()); - TFunction* prevDec = symbol ? symbol->getAsFunction() : nullptr; - - if (prevDec == nullptr) - error(loc, "can't find function", function.getName().c_str(), ""); - // Note: 'prevDec' could be 'function' if this is the first time we've seen function - // as it would have just been put in the symbol table. Otherwise, we're looking up - // an earlier occurrence. - - if (prevDec && prevDec->isDefined()) { - // Then this function already has a body. - error(loc, "function already has a body", function.getName().c_str(), ""); - } - if (prevDec && ! prevDec->isDefined()) { - prevDec->setDefined(); - - // Remember the return type for later checking for RETURN statements. - currentFunctionType = &(prevDec->getType()); - } else - currentFunctionType = new TType(EbtVoid); - functionReturnsValue = false; - - // Entry points need different I/O and other handling, transform it so the - // rest of this function doesn't care. - entryPointTree = transformEntryPoint(loc, function, attributes); - - // - // New symbol table scope for body of function plus its arguments - // - pushScope(); - - // - // Insert parameters into the symbol table. - // If the parameter has no name, it's not an error, just don't insert it - // (could be used for unused args). - // - // Also, accumulate the list of parameters into the AST, so lower level code - // knows where to find parameters. - // - TIntermAggregate* paramNodes = new TIntermAggregate; - for (int i = 0; i < function.getParamCount(); i++) { - TParameter& param = function[i]; - if (param.name != nullptr) { - TVariable *variable = new TVariable(param.name, *param.type); - - if (i == 0 && function.hasImplicitThis()) { - // Anonymous 'this' members are already in a symbol-table level, - // and we need to know what function parameter to map them to. - symbolTable.makeInternalVariable(*variable); - pushImplicitThis(variable); - } - - // Insert the parameters with name in the symbol table. - if (! symbolTable.insert(*variable)) - error(loc, "redefinition", variable->getName().c_str(), ""); - - // Add parameters to the AST list. - if (shouldFlatten(variable->getType(), variable->getType().getQualifier().storage, true)) { - // Expand the AST parameter nodes (but not the name mangling or symbol table view) - // for structures that need to be flattened. - flatten(*variable, false); - const TTypeList* structure = variable->getType().getStruct(); - for (int mem = 0; mem < (int)structure->size(); ++mem) { - paramNodes = intermediate.growAggregate(paramNodes, - flattenAccess(variable->getUniqueId(), mem, - variable->getType().getQualifier().storage, - *(*structure)[mem].type), - loc); - } - } else { - // Add the parameter to the AST - paramNodes = intermediate.growAggregate(paramNodes, - intermediate.addSymbol(*variable, loc), - loc); - } - - // Add hidden AST parameter for struct buffer counters, if needed. - addStructBufferHiddenCounterParam(loc, param, paramNodes); - } else - paramNodes = intermediate.growAggregate(paramNodes, intermediate.addSymbol(*param.type, loc), loc); - } - if (function.hasIllegalImplicitThis()) - pushImplicitThis(nullptr); - - intermediate.setAggregateOperator(paramNodes, EOpParameters, TType(EbtVoid), loc); - loopNestingLevel = 0; - controlFlowNestingLevel = 0; - postEntryPointReturn = false; - - return paramNodes; -} - -// Handle all [attrib] attribute for the shader entry point -void HlslParseContext::handleEntryPointAttributes(const TSourceLoc& loc, const TAttributes& attributes) -{ - for (auto it = attributes.begin(); it != attributes.end(); ++it) { - switch (it->name) { - case EatNumThreads: - { - const TIntermSequence& sequence = it->args->getSequence(); - for (int lid = 0; lid < int(sequence.size()); ++lid) - intermediate.setLocalSize(lid, sequence[lid]->getAsConstantUnion()->getConstArray()[0].getIConst()); - break; - } - case EatMaxVertexCount: - { - int maxVertexCount; - - if (! it->getInt(maxVertexCount)) { - error(loc, "invalid maxvertexcount", "", ""); - } else { - if (! intermediate.setVertices(maxVertexCount)) - error(loc, "cannot change previously set maxvertexcount attribute", "", ""); - } - break; - } - case EatPatchConstantFunc: - { - TString pcfName; - if (! it->getString(pcfName, 0, false)) { - error(loc, "invalid patch constant function", "", ""); - } else { - patchConstantFunctionName = pcfName; - } - break; - } - case EatDomain: - { - // Handle [domain("...")] - TString domainStr; - if (! it->getString(domainStr)) { - error(loc, "invalid domain", "", ""); - } else { - TLayoutGeometry domain = ElgNone; - - if (domainStr == "tri") { - domain = ElgTriangles; - } else if (domainStr == "quad") { - domain = ElgQuads; - } else if (domainStr == "isoline") { - domain = ElgIsolines; - } else { - error(loc, "unsupported domain type", domainStr.c_str(), ""); - } - - if (language == EShLangTessEvaluation) { - if (! intermediate.setInputPrimitive(domain)) - error(loc, "cannot change previously set domain", TQualifier::getGeometryString(domain), ""); - } else { - if (! intermediate.setOutputPrimitive(domain)) - error(loc, "cannot change previously set domain", TQualifier::getGeometryString(domain), ""); - } - } - break; - } - case EatOutputTopology: - { - // Handle [outputtopology("...")] - TString topologyStr; - if (! it->getString(topologyStr)) { - error(loc, "invalid outputtopology", "", ""); - } else { - TVertexOrder vertexOrder = EvoNone; - TLayoutGeometry primitive = ElgNone; - - if (topologyStr == "point") { - intermediate.setPointMode(); - } else if (topologyStr == "line") { - primitive = ElgIsolines; - } else if (topologyStr == "triangle_cw") { - vertexOrder = EvoCw; - primitive = ElgTriangles; - } else if (topologyStr == "triangle_ccw") { - vertexOrder = EvoCcw; - primitive = ElgTriangles; - } else { - error(loc, "unsupported outputtopology type", topologyStr.c_str(), ""); - } - - if (vertexOrder != EvoNone) { - if (! intermediate.setVertexOrder(vertexOrder)) { - error(loc, "cannot change previously set outputtopology", - TQualifier::getVertexOrderString(vertexOrder), ""); - } - } - if (primitive != ElgNone) - intermediate.setOutputPrimitive(primitive); - } - break; - } - case EatPartitioning: - { - // Handle [partitioning("...")] - TString partitionStr; - if (! it->getString(partitionStr)) { - error(loc, "invalid partitioning", "", ""); - } else { - TVertexSpacing partitioning = EvsNone; - - if (partitionStr == "integer") { - partitioning = EvsEqual; - } else if (partitionStr == "fractional_even") { - partitioning = EvsFractionalEven; - } else if (partitionStr == "fractional_odd") { - partitioning = EvsFractionalOdd; - //} else if (partition == "pow2") { // TODO: currently nothing to map this to. - } else { - error(loc, "unsupported partitioning type", partitionStr.c_str(), ""); - } - - if (! intermediate.setVertexSpacing(partitioning)) - error(loc, "cannot change previously set partitioning", - TQualifier::getVertexSpacingString(partitioning), ""); - } - break; - } - case EatOutputControlPoints: - { - // Handle [outputcontrolpoints("...")] - int ctrlPoints; - if (! it->getInt(ctrlPoints)) { - error(loc, "invalid outputcontrolpoints", "", ""); - } else { - if (! intermediate.setVertices(ctrlPoints)) { - error(loc, "cannot change previously set outputcontrolpoints attribute", "", ""); - } - } - break; - } - case EatBuiltIn: - case EatLocation: - // tolerate these because of dual use of entrypoint and type attributes - break; - default: - warn(loc, "attribute does not apply to entry point", "", ""); - break; - } - } -} - -// Update the given type with any type-like attribute information in the -// attributes. -void HlslParseContext::transferTypeAttributes(const TSourceLoc& loc, const TAttributes& attributes, TType& type, - bool allowEntry) -{ - if (attributes.size() == 0) - return; - - int value; - TString builtInString; - for (auto it = attributes.begin(); it != attributes.end(); ++it) { - switch (it->name) { - case EatLocation: - // location - if (it->getInt(value)) - type.getQualifier().layoutLocation = value; - break; - case EatBinding: - // binding - if (it->getInt(value)) { - type.getQualifier().layoutBinding = value; - type.getQualifier().layoutSet = 0; - } - // set - if (it->getInt(value, 1)) - type.getQualifier().layoutSet = value; - break; - case EatGlobalBinding: - // global cbuffer binding - if (it->getInt(value)) - globalUniformBinding = value; - // global cbuffer binding - if (it->getInt(value, 1)) - globalUniformSet = value; - break; - case EatInputAttachment: - // input attachment - if (it->getInt(value)) - type.getQualifier().layoutAttachment = value; - break; - case EatBuiltIn: - // PointSize built-in - if (it->getString(builtInString, 0, false)) { - if (builtInString == "PointSize") - type.getQualifier().builtIn = EbvPointSize; - } - break; - case EatPushConstant: - // push_constant - type.getQualifier().layoutPushConstant = true; - break; - case EatConstantId: - // specialization constant - if (it->getInt(value)) { - TSourceLoc loc; - loc.init(); - setSpecConstantId(loc, type.getQualifier(), value); - } - break; - default: - if (! allowEntry) - warn(loc, "attribute does not apply to a type", "", ""); - break; - } - } -} - -// -// Do all special handling for the entry point, including wrapping -// the shader's entry point with the official entry point that will call it. -// -// The following: -// -// retType shaderEntryPoint(args...) // shader declared entry point -// { body } -// -// Becomes -// -// out retType ret; -// in iargs...; -// out oargs ...; -// -// void shaderEntryPoint() // synthesized, but official, entry point -// { -// args = iargs...; -// ret = @shaderEntryPoint(args...); -// oargs = args...; -// } -// retType @shaderEntryPoint(args...) -// { body } -// -// The symbol table will still map the original entry point name to the -// the modified function and its new name: -// -// symbol table: shaderEntryPoint -> @shaderEntryPoint -// -// Returns nullptr if no entry-point tree was built, otherwise, returns -// a subtree that creates the entry point. -// -TIntermNode* HlslParseContext::transformEntryPoint(const TSourceLoc& loc, TFunction& userFunction, - const TAttributes& attributes) -{ - // Return true if this is a tessellation patch constant function input to a domain shader. - const auto isDsPcfInput = [this](const TType& type) { - return language == EShLangTessEvaluation && - type.contains([](const TType* t) { - return t->getQualifier().builtIn == EbvTessLevelOuter || - t->getQualifier().builtIn == EbvTessLevelInner; - }); - }; - - // if we aren't in the entry point, fix the IO as such and exit - if (userFunction.getName().compare(intermediate.getEntryPointName().c_str()) != 0) { - remapNonEntryPointIO(userFunction); - return nullptr; - } - - entryPointFunction = &userFunction; // needed in finish() - - // Handle entry point attributes - handleEntryPointAttributes(loc, attributes); - - // entry point logic... - - // Move parameters and return value to shader in/out - TVariable* entryPointOutput; // gets created in remapEntryPointIO - TVector inputs; - TVector outputs; - remapEntryPointIO(userFunction, entryPointOutput, inputs, outputs); - - // Further this return/in/out transform by flattening, splitting, and assigning locations - const auto makeVariableInOut = [&](TVariable& variable) { - if (variable.getType().isStruct()) { - if (variable.getType().getQualifier().isArrayedIo(language)) { - if (variable.getType().containsBuiltIn()) - split(variable); - } else if (shouldFlatten(variable.getType(), EvqVaryingIn /* not assigned yet, but close enough */, true)) - flatten(variable, false /* don't track linkage here, it will be tracked in assignToInterface() */); - } - // TODO: flatten arrays too - // TODO: flatten everything in I/O - // TODO: replace all split with flatten, make all paths can create flattened I/O, then split code can be removed - - // For clip and cull distance, multiple output variables potentially get merged - // into one in assignClipCullDistance. That code in assignClipCullDistance - // handles the interface logic, so we avoid it here in that case. - if (!isClipOrCullDistance(variable.getType())) - assignToInterface(variable); - }; - if (entryPointOutput != nullptr) - makeVariableInOut(*entryPointOutput); - for (auto it = inputs.begin(); it != inputs.end(); ++it) - if (!isDsPcfInput((*it)->getType())) // wait until the end for PCF input (see comment below) - makeVariableInOut(*(*it)); - for (auto it = outputs.begin(); it != outputs.end(); ++it) - makeVariableInOut(*(*it)); - - // In the domain shader, PCF input must be at the end of the linkage. That's because in the - // hull shader there is no ordering: the output comes from the separate PCF, which does not - // participate in the argument list. That is always put at the end of the HS linkage, so the - // input side of the DS must match. The argument may be in any position in the DS argument list - // however, so this ensures the linkage is built in the correct order regardless of argument order. - if (language == EShLangTessEvaluation) { - for (auto it = inputs.begin(); it != inputs.end(); ++it) - if (isDsPcfInput((*it)->getType())) - makeVariableInOut(*(*it)); - } - - // Synthesize the call - - pushScope(); // matches the one in handleFunctionBody() - - // new signature - TType voidType(EbtVoid); - TFunction synthEntryPoint(&userFunction.getName(), voidType); - TIntermAggregate* synthParams = new TIntermAggregate(); - intermediate.setAggregateOperator(synthParams, EOpParameters, voidType, loc); - intermediate.setEntryPointMangledName(synthEntryPoint.getMangledName().c_str()); - intermediate.incrementEntryPointCount(); - TFunction callee(&userFunction.getName(), voidType); // call based on old name, which is still in the symbol table - - // change original name - userFunction.addPrefix("@"); // change the name in the function, but not in the symbol table - - // Copy inputs (shader-in -> calling arg), while building up the call node - TVector argVars; - TIntermAggregate* synthBody = new TIntermAggregate(); - auto inputIt = inputs.begin(); - TIntermTyped* callingArgs = nullptr; - - for (int i = 0; i < userFunction.getParamCount(); i++) { - TParameter& param = userFunction[i]; - argVars.push_back(makeInternalVariable(*param.name, *param.type)); - argVars.back()->getWritableType().getQualifier().makeTemporary(); - - // Track the input patch, which is the only non-builtin supported by hull shader PCF. - if (param.getDeclaredBuiltIn() == EbvInputPatch) - inputPatch = argVars.back(); - - TIntermSymbol* arg = intermediate.addSymbol(*argVars.back()); - handleFunctionArgument(&callee, callingArgs, arg); - if (param.type->getQualifier().isParamInput()) { - intermediate.growAggregate(synthBody, handleAssign(loc, EOpAssign, arg, - intermediate.addSymbol(**inputIt))); - inputIt++; - } - } - - // Call - currentCaller = synthEntryPoint.getMangledName(); - TIntermTyped* callReturn = handleFunctionCall(loc, &callee, callingArgs); - currentCaller = userFunction.getMangledName(); - - // Return value - if (entryPointOutput) { - TIntermTyped* returnAssign; - - // For hull shaders, the wrapped entry point return value is written to - // an array element as indexed by invocation ID, which we might have to make up. - // This is required to match SPIR-V semantics. - if (language == EShLangTessControl) { - TIntermSymbol* invocationIdSym = findTessLinkageSymbol(EbvInvocationId); - - // If there is no user declared invocation ID, we must make one. - if (invocationIdSym == nullptr) { - TType invocationIdType(EbtUint, EvqIn, 1); - TString* invocationIdName = NewPoolTString("InvocationId"); - invocationIdType.getQualifier().builtIn = EbvInvocationId; - - TVariable* variable = makeInternalVariable(*invocationIdName, invocationIdType); - - globalQualifierFix(loc, variable->getWritableType().getQualifier()); - trackLinkage(*variable); - - invocationIdSym = intermediate.addSymbol(*variable); - } - - TIntermTyped* element = intermediate.addIndex(EOpIndexIndirect, intermediate.addSymbol(*entryPointOutput), - invocationIdSym, loc); - - // Set the type of the array element being dereferenced - const TType derefElementType(entryPointOutput->getType(), 0); - element->setType(derefElementType); - - returnAssign = handleAssign(loc, EOpAssign, element, callReturn); - } else { - returnAssign = handleAssign(loc, EOpAssign, intermediate.addSymbol(*entryPointOutput), callReturn); - } - intermediate.growAggregate(synthBody, returnAssign); - } else - intermediate.growAggregate(synthBody, callReturn); - - // Output copies - auto outputIt = outputs.begin(); - for (int i = 0; i < userFunction.getParamCount(); i++) { - TParameter& param = userFunction[i]; - - // GS outputs are via emit, so we do not copy them here. - if (param.type->getQualifier().isParamOutput()) { - if (param.getDeclaredBuiltIn() == EbvGsOutputStream) { - // GS output stream does not assign outputs here: it's the Append() method - // which writes to the output, probably multiple times separated by Emit. - // We merely remember the output to use, here. - gsStreamOutput = *outputIt; - } else { - intermediate.growAggregate(synthBody, handleAssign(loc, EOpAssign, - intermediate.addSymbol(**outputIt), - intermediate.addSymbol(*argVars[i]))); - } - - outputIt++; - } - } - - // Put the pieces together to form a full function subtree - // for the synthesized entry point. - synthBody->setOperator(EOpSequence); - TIntermNode* synthFunctionDef = synthParams; - handleFunctionBody(loc, synthEntryPoint, synthBody, synthFunctionDef); - - entryPointFunctionBody = synthBody; - - return synthFunctionDef; -} - -void HlslParseContext::handleFunctionBody(const TSourceLoc& loc, TFunction& function, TIntermNode* functionBody, - TIntermNode*& node) -{ - node = intermediate.growAggregate(node, functionBody); - intermediate.setAggregateOperator(node, EOpFunction, function.getType(), loc); - node->getAsAggregate()->setName(function.getMangledName().c_str()); - - popScope(); - if (function.hasImplicitThis()) - popImplicitThis(); - - if (function.getType().getBasicType() != EbtVoid && ! functionReturnsValue) - error(loc, "function does not return a value:", "", function.getName().c_str()); -} - -// AST I/O is done through shader globals declared in the 'in' or 'out' -// storage class. An HLSL entry point has a return value, input parameters -// and output parameters. These need to get remapped to the AST I/O. -void HlslParseContext::remapEntryPointIO(TFunction& function, TVariable*& returnValue, - TVector& inputs, TVector& outputs) -{ - // We might have in input structure type with no decorations that caused it - // to look like an input type, yet it has (e.g.) interpolation types that - // must be modified that turn it into an input type. - // Hence, a missing ioTypeMap for 'input' might need to be synthesized. - const auto synthesizeEditedInput = [this](TType& type) { - // True if a type needs to be 'flat' - const auto needsFlat = [](const TType& type) { - return type.containsBasicType(EbtInt) || - type.containsBasicType(EbtUint) || - type.containsBasicType(EbtInt64) || - type.containsBasicType(EbtUint64) || - type.containsBasicType(EbtBool) || - type.containsBasicType(EbtDouble); - }; - - if (language == EShLangFragment && needsFlat(type)) { - if (type.isStruct()) { - TTypeList* finalList = nullptr; - auto it = ioTypeMap.find(type.getStruct()); - if (it == ioTypeMap.end() || it->second.input == nullptr) { - // Getting here means we have no input struct, but we need one. - auto list = new TTypeList; - for (auto member = type.getStruct()->begin(); member != type.getStruct()->end(); ++member) { - TType* newType = new TType; - newType->shallowCopy(*member->type); - TTypeLoc typeLoc = { newType, member->loc }; - list->push_back(typeLoc); - } - // install the new input type - if (it == ioTypeMap.end()) { - tIoKinds newLists = { list, nullptr, nullptr }; - ioTypeMap[type.getStruct()] = newLists; - } else - it->second.input = list; - finalList = list; - } else - finalList = it->second.input; - // edit for 'flat' - for (auto member = finalList->begin(); member != finalList->end(); ++member) { - if (needsFlat(*member->type)) { - member->type->getQualifier().clearInterpolation(); - member->type->getQualifier().flat = true; - } - } - } else { - type.getQualifier().clearInterpolation(); - type.getQualifier().flat = true; - } - } - }; - - // Do the actual work to make a type be a shader input or output variable, - // and clear the original to be non-IO (for use as a normal function parameter/return). - const auto makeIoVariable = [this](const char* name, TType& type, TStorageQualifier storage) -> TVariable* { - TVariable* ioVariable = makeInternalVariable(name, type); - clearUniformInputOutput(type.getQualifier()); - if (type.isStruct()) { - auto newLists = ioTypeMap.find(ioVariable->getType().getStruct()); - if (newLists != ioTypeMap.end()) { - if (storage == EvqVaryingIn && newLists->second.input) - ioVariable->getWritableType().setStruct(newLists->second.input); - else if (storage == EvqVaryingOut && newLists->second.output) - ioVariable->getWritableType().setStruct(newLists->second.output); - } - } - if (storage == EvqVaryingIn) { - correctInput(ioVariable->getWritableType().getQualifier()); - if (language == EShLangTessEvaluation) - if (!ioVariable->getType().isArray()) - ioVariable->getWritableType().getQualifier().patch = true; - } else { - correctOutput(ioVariable->getWritableType().getQualifier()); - } - ioVariable->getWritableType().getQualifier().storage = storage; - - fixBuiltInIoType(ioVariable->getWritableType()); - - return ioVariable; - }; - - // return value is actually a shader-scoped output (out) - if (function.getType().getBasicType() == EbtVoid) { - returnValue = nullptr; - } else { - if (language == EShLangTessControl) { - // tessellation evaluation in HLSL writes a per-ctrl-pt value, but it needs to be an - // array in SPIR-V semantics. We'll write to it indexed by invocation ID. - - returnValue = makeIoVariable("@entryPointOutput", function.getWritableType(), EvqVaryingOut); - - TType outputType; - outputType.shallowCopy(function.getType()); - - // vertices has necessarily already been set when handling entry point attributes. - TArraySizes* arraySizes = new TArraySizes; - arraySizes->addInnerSize(intermediate.getVertices()); - outputType.transferArraySizes(arraySizes); - - clearUniformInputOutput(function.getWritableType().getQualifier()); - returnValue = makeIoVariable("@entryPointOutput", outputType, EvqVaryingOut); - } else { - returnValue = makeIoVariable("@entryPointOutput", function.getWritableType(), EvqVaryingOut); - } - } - - // parameters are actually shader-scoped inputs and outputs (in or out) - for (int i = 0; i < function.getParamCount(); i++) { - TType& paramType = *function[i].type; - if (paramType.getQualifier().isParamInput()) { - synthesizeEditedInput(paramType); - TVariable* argAsGlobal = makeIoVariable(function[i].name->c_str(), paramType, EvqVaryingIn); - inputs.push_back(argAsGlobal); - } - if (paramType.getQualifier().isParamOutput()) { - TVariable* argAsGlobal = makeIoVariable(function[i].name->c_str(), paramType, EvqVaryingOut); - outputs.push_back(argAsGlobal); - } - } -} - -// An HLSL function that looks like an entry point, but is not, -// declares entry point IO built-ins, but these have to be undone. -void HlslParseContext::remapNonEntryPointIO(TFunction& function) -{ - // return value - if (function.getType().getBasicType() != EbtVoid) - clearUniformInputOutput(function.getWritableType().getQualifier()); - - // parameters. - // References to structuredbuffer types are left unmodified - for (int i = 0; i < function.getParamCount(); i++) - if (!isReference(*function[i].type)) - clearUniformInputOutput(function[i].type->getQualifier()); -} - -// Handle function returns, including type conversions to the function return type -// if necessary. -TIntermNode* HlslParseContext::handleReturnValue(const TSourceLoc& loc, TIntermTyped* value) -{ - functionReturnsValue = true; - - if (currentFunctionType->getBasicType() == EbtVoid) { - error(loc, "void function cannot return a value", "return", ""); - return intermediate.addBranch(EOpReturn, loc); - } else if (*currentFunctionType != value->getType()) { - value = intermediate.addConversion(EOpReturn, *currentFunctionType, value); - if (value && *currentFunctionType != value->getType()) - value = intermediate.addUniShapeConversion(EOpReturn, *currentFunctionType, value); - if (value == nullptr || *currentFunctionType != value->getType()) { - error(loc, "type does not match, or is not convertible to, the function's return type", "return", ""); - return value; - } - } - - return intermediate.addBranch(EOpReturn, value, loc); -} - -void HlslParseContext::handleFunctionArgument(TFunction* function, - TIntermTyped*& arguments, TIntermTyped* newArg) -{ - TParameter param = { 0, new TType, nullptr }; - param.type->shallowCopy(newArg->getType()); - - function->addParameter(param); - if (arguments) - arguments = intermediate.growAggregate(arguments, newArg); - else - arguments = newArg; -} - -// Position may require special handling: we can optionally invert Y. -// See: https://github.com/KhronosGroup/glslang/issues/1173 -// https://github.com/KhronosGroup/glslang/issues/494 -TIntermTyped* HlslParseContext::assignPosition(const TSourceLoc& loc, TOperator op, - TIntermTyped* left, TIntermTyped* right) -{ - // If we are not asked for Y inversion, use a plain old assign. - if (!intermediate.getInvertY()) - return intermediate.addAssign(op, left, right, loc); - - // If we get here, we should invert Y. - TIntermAggregate* assignList = nullptr; - - // If this is a complex rvalue, we don't want to dereference it many times. Create a temporary. - TVariable* rhsTempVar = nullptr; - rhsTempVar = makeInternalVariable("@position", right->getType()); - rhsTempVar->getWritableType().getQualifier().makeTemporary(); - - { - TIntermTyped* rhsTempSym = intermediate.addSymbol(*rhsTempVar, loc); - assignList = intermediate.growAggregate(assignList, - intermediate.addAssign(EOpAssign, rhsTempSym, right, loc), loc); - } - - // pos.y = -pos.y - { - const int Y = 1; - - TIntermTyped* tempSymL = intermediate.addSymbol(*rhsTempVar, loc); - TIntermTyped* tempSymR = intermediate.addSymbol(*rhsTempVar, loc); - TIntermTyped* index = intermediate.addConstantUnion(Y, loc); - - TIntermTyped* lhsElement = intermediate.addIndex(EOpIndexDirect, tempSymL, index, loc); - TIntermTyped* rhsElement = intermediate.addIndex(EOpIndexDirect, tempSymR, index, loc); - - const TType derefType(right->getType(), 0); - - lhsElement->setType(derefType); - rhsElement->setType(derefType); - - TIntermTyped* yNeg = intermediate.addUnaryMath(EOpNegative, rhsElement, loc); - - assignList = intermediate.growAggregate(assignList, intermediate.addAssign(EOpAssign, lhsElement, yNeg, loc)); - } - - // Assign the rhs temp (now with Y inversion) to the final output - { - TIntermTyped* rhsTempSym = intermediate.addSymbol(*rhsTempVar, loc); - assignList = intermediate.growAggregate(assignList, intermediate.addAssign(op, left, rhsTempSym, loc)); - } - - assert(assignList != nullptr); - assignList->setOperator(EOpSequence); - - return assignList; -} - -// Clip and cull distance require special handling due to a semantic mismatch. In HLSL, -// these can be float scalar, float vector, or arrays of float scalar or float vector. -// In SPIR-V, they are arrays of scalar floats in all cases. We must copy individual components -// (e.g, both x and y components of a float2) out into the destination float array. -// -// The values are assigned to sequential members of the output array. The inner dimension -// is vector components. The outer dimension is array elements. -TIntermAggregate* HlslParseContext::assignClipCullDistance(const TSourceLoc& loc, TOperator op, int semanticId, - TIntermTyped* left, TIntermTyped* right) -{ - switch (language) { - case EShLangFragment: - case EShLangVertex: - case EShLangGeometry: - break; - default: - error(loc, "unimplemented: clip/cull not currently implemented for this stage", "", ""); - return nullptr; - } - - TVariable** clipCullVar = nullptr; - - // Figure out if we are assigning to, or from, clip or cull distance. - const bool isOutput = isClipOrCullDistance(left->getType()); - - // This is the rvalue or lvalue holding the clip or cull distance. - TIntermTyped* clipCullNode = isOutput ? left : right; - // This is the value going into or out of the clip or cull distance. - TIntermTyped* internalNode = isOutput ? right : left; - - const TBuiltInVariable builtInType = clipCullNode->getQualifier().builtIn; - - decltype(clipSemanticNSizeIn)* semanticNSize = nullptr; - - // Refer to either the clip or the cull distance, depending on semantic. - switch (builtInType) { - case EbvClipDistance: - clipCullVar = isOutput ? &clipDistanceOutput : &clipDistanceInput; - semanticNSize = isOutput ? &clipSemanticNSizeOut : &clipSemanticNSizeIn; - break; - case EbvCullDistance: - clipCullVar = isOutput ? &cullDistanceOutput : &cullDistanceInput; - semanticNSize = isOutput ? &cullSemanticNSizeOut : &cullSemanticNSizeIn; - break; - - // called invalidly: we expected a clip or a cull distance. - // static compile time problem: should not happen. - default: assert(0); return nullptr; - } - - // This is the offset in the destination array of a given semantic's data - std::array semanticOffset; - - // Calculate offset of variable of semantic N in destination array - int arrayLoc = 0; - int vecItems = 0; - - for (int x = 0; x < maxClipCullRegs; ++x) { - // See if we overflowed the vec4 packing - if ((vecItems + (*semanticNSize)[x]) > 4) { - arrayLoc = (arrayLoc + 3) & (~0x3); // round up to next multiple of 4 - vecItems = 0; - } - - semanticOffset[x] = arrayLoc; - vecItems += (*semanticNSize)[x]; - arrayLoc += (*semanticNSize)[x]; - } - - - // It can have up to 2 array dimensions (in the case of geometry shader inputs) - const TArraySizes* const internalArraySizes = internalNode->getType().getArraySizes(); - const int internalArrayDims = internalNode->getType().isArray() ? internalArraySizes->getNumDims() : 0; - // vector sizes: - const int internalVectorSize = internalNode->getType().getVectorSize(); - // array sizes, or 1 if it's not an array: - const int internalInnerArraySize = (internalArrayDims > 0 ? internalArraySizes->getDimSize(internalArrayDims-1) : 1); - const int internalOuterArraySize = (internalArrayDims > 1 ? internalArraySizes->getDimSize(0) : 1); - - // The created type may be an array of arrays, e.g, for geometry shader inputs. - const bool isImplicitlyArrayed = (language == EShLangGeometry && !isOutput); - - // If we haven't created the output already, create it now. - if (*clipCullVar == nullptr) { - // ClipDistance and CullDistance are handled specially in the entry point input/output copy - // algorithm, because they may need to be unpacked from components of vectors (or a scalar) - // into a float array, or vice versa. Here, we make the array the right size and type, - // which depends on the incoming data, which has several potential dimensions: - // * Semantic ID - // * vector size - // * array size - // Of those, semantic ID and array size cannot appear simultaneously. - // - // Also to note: for implicitly arrayed forms (e.g, geometry shader inputs), we need to create two - // array dimensions. The shader's declaration may have one or two array dimensions. One is always - // the geometry's dimension. - - const bool useInnerSize = internalArrayDims > 1 || !isImplicitlyArrayed; - - const int requiredInnerArraySize = arrayLoc * (useInnerSize ? internalInnerArraySize : 1); - const int requiredOuterArraySize = (internalArrayDims > 0) ? internalArraySizes->getDimSize(0) : 1; - - TType clipCullType(EbtFloat, clipCullNode->getType().getQualifier().storage, 1); - clipCullType.getQualifier() = clipCullNode->getType().getQualifier(); - - // Create required array dimension - TArraySizes* arraySizes = new TArraySizes; - if (isImplicitlyArrayed) - arraySizes->addInnerSize(requiredOuterArraySize); - arraySizes->addInnerSize(requiredInnerArraySize); - clipCullType.transferArraySizes(arraySizes); - - // Obtain symbol name: we'll use that for the symbol we introduce. - TIntermSymbol* sym = clipCullNode->getAsSymbolNode(); - assert(sym != nullptr); - - // We are moving the semantic ID from the layout location, so it is no longer needed or - // desired there. - clipCullType.getQualifier().layoutLocation = TQualifier::layoutLocationEnd; - - // Create variable and track its linkage - *clipCullVar = makeInternalVariable(sym->getName().c_str(), clipCullType); - - trackLinkage(**clipCullVar); - } - - // Create symbol for the clip or cull variable. - TIntermSymbol* clipCullSym = intermediate.addSymbol(**clipCullVar); - - // vector sizes: - const int clipCullVectorSize = clipCullSym->getType().getVectorSize(); - - // array sizes, or 1 if it's not an array: - const TArraySizes* const clipCullArraySizes = clipCullSym->getType().getArraySizes(); - const int clipCullOuterArraySize = isImplicitlyArrayed ? clipCullArraySizes->getDimSize(0) : 1; - const int clipCullInnerArraySize = clipCullArraySizes->getDimSize(isImplicitlyArrayed ? 1 : 0); - - // clipCullSym has got to be an array of scalar floats, per SPIR-V semantics. - // fixBuiltInIoType() should have handled that upstream. - assert(clipCullSym->getType().isArray()); - assert(clipCullSym->getType().getVectorSize() == 1); - assert(clipCullSym->getType().getBasicType() == EbtFloat); - - // We may be creating multiple sub-assignments. This is an aggregate to hold them. - // TODO: it would be possible to be clever sometimes and avoid the sequence node if not needed. - TIntermAggregate* assignList = nullptr; - - // Holds individual component assignments as we make them. - TIntermTyped* clipCullAssign = nullptr; - - // If the types are homomorphic, use a simple assign. No need to mess about with - // individual components. - if (clipCullSym->getType().isArray() == internalNode->getType().isArray() && - clipCullInnerArraySize == internalInnerArraySize && - clipCullOuterArraySize == internalOuterArraySize && - clipCullVectorSize == internalVectorSize) { - - if (isOutput) - clipCullAssign = intermediate.addAssign(op, clipCullSym, internalNode, loc); - else - clipCullAssign = intermediate.addAssign(op, internalNode, clipCullSym, loc); - - assignList = intermediate.growAggregate(assignList, clipCullAssign); - assignList->setOperator(EOpSequence); - - return assignList; - } - - // We are going to copy each component of the internal (per array element if indicated) to sequential - // array elements of the clipCullSym. This tracks the lhs element we're writing to as we go along. - // We may be starting in the middle - e.g, for a non-zero semantic ID calculated above. - int clipCullInnerArrayPos = semanticOffset[semanticId]; - int clipCullOuterArrayPos = 0; - - // Lambda to add an index to a node, set the type of the result, and return the new node. - const auto addIndex = [this, &loc](TIntermTyped* node, int pos) -> TIntermTyped* { - const TType derefType(node->getType(), 0); - node = intermediate.addIndex(EOpIndexDirect, node, intermediate.addConstantUnion(pos, loc), loc); - node->setType(derefType); - return node; - }; - - // Loop through every component of every element of the internal, and copy to or from the matching external. - for (int internalOuterArrayPos = 0; internalOuterArrayPos < internalOuterArraySize; ++internalOuterArrayPos) { - for (int internalInnerArrayPos = 0; internalInnerArrayPos < internalInnerArraySize; ++internalInnerArrayPos) { - for (int internalComponent = 0; internalComponent < internalVectorSize; ++internalComponent) { - // clip/cull array member to read from / write to: - TIntermTyped* clipCullMember = clipCullSym; - - // If implicitly arrayed, there is an outer array dimension involved - if (isImplicitlyArrayed) - clipCullMember = addIndex(clipCullMember, clipCullOuterArrayPos); - - // Index into proper array position for clip cull member - clipCullMember = addIndex(clipCullMember, clipCullInnerArrayPos++); - - // if needed, start over with next outer array slice. - if (isImplicitlyArrayed && clipCullInnerArrayPos >= clipCullInnerArraySize) { - clipCullInnerArrayPos = semanticOffset[semanticId]; - ++clipCullOuterArrayPos; - } - - // internal member to read from / write to: - TIntermTyped* internalMember = internalNode; - - // If internal node has outer array dimension, index appropriately. - if (internalArrayDims > 1) - internalMember = addIndex(internalMember, internalOuterArrayPos); - - // If internal node has inner array dimension, index appropriately. - if (internalArrayDims > 0) - internalMember = addIndex(internalMember, internalInnerArrayPos); - - // If internal node is a vector, extract the component of interest. - if (internalNode->getType().isVector()) - internalMember = addIndex(internalMember, internalComponent); - - // Create an assignment: output from internal to clip cull, or input from clip cull to internal. - if (isOutput) - clipCullAssign = intermediate.addAssign(op, clipCullMember, internalMember, loc); - else - clipCullAssign = intermediate.addAssign(op, internalMember, clipCullMember, loc); - - // Track assignment in the sequence. - assignList = intermediate.growAggregate(assignList, clipCullAssign); - } - } - } - - assert(assignList != nullptr); - assignList->setOperator(EOpSequence); - - return assignList; -} - -// Some simple source assignments need to be flattened to a sequence -// of AST assignments. Catch these and flatten, otherwise, pass through -// to intermediate.addAssign(). -// -// Also, assignment to matrix swizzles requires multiple component assignments, -// intercept those as well. -TIntermTyped* HlslParseContext::handleAssign(const TSourceLoc& loc, TOperator op, TIntermTyped* left, - TIntermTyped* right) -{ - if (left == nullptr || right == nullptr) - return nullptr; - - // writing to opaques will require fixing transforms - if (left->getType().containsOpaque()) - intermediate.setNeedsLegalization(); - - if (left->getAsOperator() && left->getAsOperator()->getOp() == EOpMatrixSwizzle) - return handleAssignToMatrixSwizzle(loc, op, left, right); - - // Return true if the given node is an index operation into a split variable. - const auto indexesSplit = [this](const TIntermTyped* node) -> bool { - const TIntermBinary* binaryNode = node->getAsBinaryNode(); - - if (binaryNode == nullptr) - return false; - - return (binaryNode->getOp() == EOpIndexDirect || binaryNode->getOp() == EOpIndexIndirect) && - wasSplit(binaryNode->getLeft()); - }; - - // Return true if this stage assigns clip position with potentially inverted Y - const auto assignsClipPos = [this](const TIntermTyped* node) -> bool { - return node->getType().getQualifier().builtIn == EbvPosition && - (language == EShLangVertex || language == EShLangGeometry || language == EShLangTessEvaluation); - }; - - const bool isSplitLeft = wasSplit(left) || indexesSplit(left); - const bool isSplitRight = wasSplit(right) || indexesSplit(right); - - const bool isFlattenLeft = wasFlattened(left); - const bool isFlattenRight = wasFlattened(right); - - // OK to do a single assign if neither side is split or flattened. Otherwise, - // fall through to a member-wise copy. - if (!isFlattenLeft && !isFlattenRight && !isSplitLeft && !isSplitRight) { - // Clip and cull distance requires more processing. See comment above assignClipCullDistance. - if (isClipOrCullDistance(left->getType()) || isClipOrCullDistance(right->getType())) { - const bool isOutput = isClipOrCullDistance(left->getType()); - - const int semanticId = (isOutput ? left : right)->getType().getQualifier().layoutLocation; - return assignClipCullDistance(loc, op, semanticId, left, right); - } else if (assignsClipPos(left)) { - // Position can require special handling: see comment above assignPosition - return assignPosition(loc, op, left, right); - } - - return intermediate.addAssign(op, left, right, loc); - } - - TIntermAggregate* assignList = nullptr; - const TVector* leftVariables = nullptr; - const TVector* rightVariables = nullptr; - - // A temporary to store the right node's value, so we don't keep indirecting into it - // if it's not a simple symbol. - TVariable* rhsTempVar = nullptr; - - // If the RHS is a simple symbol node, we'll copy it for each member. - TIntermSymbol* cloneSymNode = nullptr; - - int memberCount = 0; - - // Track how many items there are to copy. - if (left->getType().isStruct()) - memberCount = (int)left->getType().getStruct()->size(); - if (left->getType().isArray()) - memberCount = left->getType().getCumulativeArraySize(); - - if (isFlattenLeft) - leftVariables = &flattenMap.find(left->getAsSymbolNode()->getId())->second.members; - - if (isFlattenRight) { - rightVariables = &flattenMap.find(right->getAsSymbolNode()->getId())->second.members; - } else { - // The RHS is not flattened. There are several cases: - // 1. 1 item to copy: Use the RHS directly. - // 2. >1 item, simple symbol RHS: we'll create a new TIntermSymbol node for each, but no assign to temp. - // 3. >1 item, complex RHS: assign it to a new temp variable, and create a TIntermSymbol for each member. - - if (memberCount <= 1) { - // case 1: we'll use the symbol directly below. Nothing to do. - } else { - if (right->getAsSymbolNode() != nullptr) { - // case 2: we'll copy the symbol per iteration below. - cloneSymNode = right->getAsSymbolNode(); - } else { - // case 3: assign to a temp, and indirect into that. - rhsTempVar = makeInternalVariable("flattenTemp", right->getType()); - rhsTempVar->getWritableType().getQualifier().makeTemporary(); - TIntermTyped* noFlattenRHS = intermediate.addSymbol(*rhsTempVar, loc); - - // Add this to the aggregate being built. - assignList = intermediate.growAggregate(assignList, - intermediate.addAssign(op, noFlattenRHS, right, loc), loc); - } - } - } - - // When dealing with split arrayed structures of built-ins, the arrayness is moved to the extracted built-in - // variables, which is awkward when copying between split and unsplit structures. This variable tracks - // array indirections so they can be percolated from outer structs to inner variables. - std::vector arrayElement; - - TStorageQualifier leftStorage = left->getType().getQualifier().storage; - TStorageQualifier rightStorage = right->getType().getQualifier().storage; - - int leftOffset = findSubtreeOffset(*left); - int rightOffset = findSubtreeOffset(*right); - - const auto getMember = [&](bool isLeft, const TType& type, int member, TIntermTyped* splitNode, int splitMember, - bool flattened) - -> TIntermTyped * { - const bool split = isLeft ? isSplitLeft : isSplitRight; - - TIntermTyped* subTree; - const TType derefType(type, member); - const TVariable* builtInVar = nullptr; - if ((flattened || split) && derefType.isBuiltIn()) { - auto splitPair = splitBuiltIns.find(HlslParseContext::tInterstageIoData( - derefType.getQualifier().builtIn, - isLeft ? leftStorage : rightStorage)); - if (splitPair != splitBuiltIns.end()) - builtInVar = splitPair->second; - } - if (builtInVar != nullptr) { - // copy from interstage IO built-in if needed - subTree = intermediate.addSymbol(*builtInVar); - - if (subTree->getType().isArray()) { - // Arrayness of builtIn symbols isn't handled by the normal recursion: - // it's been extracted and moved to the built-in. - if (!arrayElement.empty()) { - const TType splitDerefType(subTree->getType(), arrayElement.back()); - subTree = intermediate.addIndex(EOpIndexDirect, subTree, - intermediate.addConstantUnion(arrayElement.back(), loc), loc); - subTree->setType(splitDerefType); - } else if (splitNode->getAsOperator() != nullptr && (splitNode->getAsOperator()->getOp() == EOpIndexIndirect)) { - // This might also be a stage with arrayed outputs, in which case there's an index - // operation we should transfer to the output builtin. - - const TType splitDerefType(subTree->getType(), 0); - subTree = intermediate.addIndex(splitNode->getAsOperator()->getOp(), subTree, - splitNode->getAsBinaryNode()->getRight(), loc); - subTree->setType(splitDerefType); - } - } - } else if (flattened && !shouldFlatten(derefType, isLeft ? leftStorage : rightStorage, false)) { - if (isLeft) - subTree = intermediate.addSymbol(*(*leftVariables)[leftOffset++]); - else - subTree = intermediate.addSymbol(*(*rightVariables)[rightOffset++]); - } else { - // Index operator if it's an aggregate, else EOpNull - const TOperator accessOp = type.isArray() ? EOpIndexDirect - : type.isStruct() ? EOpIndexDirectStruct - : EOpNull; - if (accessOp == EOpNull) { - subTree = splitNode; - } else { - subTree = intermediate.addIndex(accessOp, splitNode, intermediate.addConstantUnion(splitMember, loc), - loc); - const TType splitDerefType(splitNode->getType(), splitMember); - subTree->setType(splitDerefType); - } - } - - return subTree; - }; - - // Use the proper RHS node: a new symbol from a TVariable, copy - // of an TIntermSymbol node, or sometimes the right node directly. - right = rhsTempVar != nullptr ? intermediate.addSymbol(*rhsTempVar, loc) : - cloneSymNode != nullptr ? intermediate.addSymbol(*cloneSymNode) : - right; - - // Cannot use auto here, because this is recursive, and auto can't work out the type without seeing the - // whole thing. So, we'll resort to an explicit type via std::function. - const std::function - traverse = [&](TIntermTyped* left, TIntermTyped* right, TIntermTyped* splitLeft, TIntermTyped* splitRight, - bool topLevel) -> void { - // If we get here, we are assigning to or from a whole array or struct that must be - // flattened, so have to do member-by-member assignment: - - bool shouldFlattenSubsetLeft = isFlattenLeft && shouldFlatten(left->getType(), leftStorage, topLevel); - bool shouldFlattenSubsetRight = isFlattenRight && shouldFlatten(right->getType(), rightStorage, topLevel); - - if ((left->getType().isArray() || right->getType().isArray()) && - (shouldFlattenSubsetLeft || isSplitLeft || - shouldFlattenSubsetRight || isSplitRight)) { - const int elementsL = left->getType().isArray() ? left->getType().getOuterArraySize() : 1; - const int elementsR = right->getType().isArray() ? right->getType().getOuterArraySize() : 1; - - // The arrays might not be the same size, - // e.g., if the size has been forced for EbvTessLevelInner/Outer. - const int elementsToCopy = std::min(elementsL, elementsR); - - // array case - for (int element = 0; element < elementsToCopy; ++element) { - arrayElement.push_back(element); - - // Add a new AST symbol node if we have a temp variable holding a complex RHS. - TIntermTyped* subLeft = getMember(true, left->getType(), element, left, element, - shouldFlattenSubsetLeft); - TIntermTyped* subRight = getMember(false, right->getType(), element, right, element, - shouldFlattenSubsetRight); - - TIntermTyped* subSplitLeft = isSplitLeft ? getMember(true, left->getType(), element, splitLeft, - element, shouldFlattenSubsetLeft) - : subLeft; - TIntermTyped* subSplitRight = isSplitRight ? getMember(false, right->getType(), element, splitRight, - element, shouldFlattenSubsetRight) - : subRight; - - traverse(subLeft, subRight, subSplitLeft, subSplitRight, false); - - arrayElement.pop_back(); - } - } else if (left->getType().isStruct() && (shouldFlattenSubsetLeft || isSplitLeft || - shouldFlattenSubsetRight || isSplitRight)) { - // struct case - const auto& membersL = *left->getType().getStruct(); - const auto& membersR = *right->getType().getStruct(); - - // These track the members in the split structures corresponding to the same in the unsplit structures, - // which we traverse in parallel. - int memberL = 0; - int memberR = 0; - - // Handle empty structure assignment - if (int(membersL.size()) == 0 && int(membersR.size()) == 0) - assignList = intermediate.growAggregate(assignList, intermediate.addAssign(op, left, right, loc), loc); - - for (int member = 0; member < int(membersL.size()); ++member) { - const TType& typeL = *membersL[member].type; - const TType& typeR = *membersR[member].type; - - TIntermTyped* subLeft = getMember(true, left->getType(), member, left, member, - shouldFlattenSubsetLeft); - TIntermTyped* subRight = getMember(false, right->getType(), member, right, member, - shouldFlattenSubsetRight); - - // If there is no splitting, use the same values to avoid inefficiency. - TIntermTyped* subSplitLeft = isSplitLeft ? getMember(true, left->getType(), member, splitLeft, - memberL, shouldFlattenSubsetLeft) - : subLeft; - TIntermTyped* subSplitRight = isSplitRight ? getMember(false, right->getType(), member, splitRight, - memberR, shouldFlattenSubsetRight) - : subRight; - - if (isClipOrCullDistance(subSplitLeft->getType()) || isClipOrCullDistance(subSplitRight->getType())) { - // Clip and cull distance built-in assignment is complex in its own right, and is handled in - // a separate function dedicated to that task. See comment above assignClipCullDistance; - - const bool isOutput = isClipOrCullDistance(subSplitLeft->getType()); - - // Since all clip/cull semantics boil down to the same built-in type, we need to get the - // semantic ID from the dereferenced type's layout location, to avoid an N-1 mapping. - const TType derefType((isOutput ? left : right)->getType(), member); - const int semanticId = derefType.getQualifier().layoutLocation; - - TIntermAggregate* clipCullAssign = assignClipCullDistance(loc, op, semanticId, - subSplitLeft, subSplitRight); - - assignList = intermediate.growAggregate(assignList, clipCullAssign, loc); - } else if (assignsClipPos(subSplitLeft)) { - // Position can require special handling: see comment above assignPosition - TIntermTyped* positionAssign = assignPosition(loc, op, subSplitLeft, subSplitRight); - assignList = intermediate.growAggregate(assignList, positionAssign, loc); - } else if (!shouldFlattenSubsetLeft && !shouldFlattenSubsetRight && - !typeL.containsBuiltIn() && !typeR.containsBuiltIn()) { - // If this is the final flattening (no nested types below to flatten) - // we'll copy the member, else recurse into the type hierarchy. - // However, if splitting the struct, that means we can copy a whole - // subtree here IFF it does not itself contain any interstage built-in - // IO variables, so we only have to recurse into it if there's something - // for splitting to do. That can save a lot of AST verbosity for - // a bunch of memberwise copies. - - assignList = intermediate.growAggregate(assignList, - intermediate.addAssign(op, subSplitLeft, subSplitRight, loc), - loc); - } else { - traverse(subLeft, subRight, subSplitLeft, subSplitRight, false); - } - - memberL += (typeL.isBuiltIn() ? 0 : 1); - memberR += (typeR.isBuiltIn() ? 0 : 1); - } - } else { - // Member copy - assignList = intermediate.growAggregate(assignList, intermediate.addAssign(op, left, right, loc), loc); - } - - }; - - TIntermTyped* splitLeft = left; - TIntermTyped* splitRight = right; - - // If either left or right was a split structure, we must read or write it, but still have to - // parallel-recurse through the unsplit structure to identify the built-in IO vars. - // The left can be either a symbol, or an index into a symbol (e.g, array reference) - if (isSplitLeft) { - if (indexesSplit(left)) { - // Index case: Refer to the indexed symbol, if the left is an index operator. - const TIntermSymbol* symNode = left->getAsBinaryNode()->getLeft()->getAsSymbolNode(); - - TIntermTyped* splitLeftNonIo = intermediate.addSymbol(*getSplitNonIoVar(symNode->getId()), loc); - - splitLeft = intermediate.addIndex(left->getAsBinaryNode()->getOp(), splitLeftNonIo, - left->getAsBinaryNode()->getRight(), loc); - - const TType derefType(splitLeftNonIo->getType(), 0); - splitLeft->setType(derefType); - } else { - // Symbol case: otherwise, if not indexed, we have the symbol directly. - const TIntermSymbol* symNode = left->getAsSymbolNode(); - splitLeft = intermediate.addSymbol(*getSplitNonIoVar(symNode->getId()), loc); - } - } - - if (isSplitRight) - splitRight = intermediate.addSymbol(*getSplitNonIoVar(right->getAsSymbolNode()->getId()), loc); - - // This makes the whole assignment, recursing through subtypes as needed. - traverse(left, right, splitLeft, splitRight, true); - - assert(assignList != nullptr); - assignList->setOperator(EOpSequence); - - return assignList; -} - -// An assignment to matrix swizzle must be decomposed into individual assignments. -// These must be selected component-wise from the RHS and stored component-wise -// into the LHS. -TIntermTyped* HlslParseContext::handleAssignToMatrixSwizzle(const TSourceLoc& loc, TOperator op, TIntermTyped* left, - TIntermTyped* right) -{ - assert(left->getAsOperator() && left->getAsOperator()->getOp() == EOpMatrixSwizzle); - - if (op != EOpAssign) - error(loc, "only simple assignment to non-simple matrix swizzle is supported", "assign", ""); - - // isolate the matrix and swizzle nodes - TIntermTyped* matrix = left->getAsBinaryNode()->getLeft()->getAsTyped(); - const TIntermSequence& swizzle = left->getAsBinaryNode()->getRight()->getAsAggregate()->getSequence(); - - // if the RHS isn't already a simple vector, let's store into one - TIntermSymbol* vector = right->getAsSymbolNode(); - TIntermTyped* vectorAssign = nullptr; - if (vector == nullptr) { - // create a new intermediate vector variable to assign to - TType vectorType(matrix->getBasicType(), EvqTemporary, matrix->getQualifier().precision, (int)swizzle.size()/2); - vector = intermediate.addSymbol(*makeInternalVariable("intermVec", vectorType), loc); - - // assign the right to the new vector - vectorAssign = handleAssign(loc, op, vector, right); - } - - // Assign the vector components to the matrix components. - // Store this as a sequence, so a single aggregate node represents this - // entire operation. - TIntermAggregate* result = intermediate.makeAggregate(vectorAssign); - TType columnType(matrix->getType(), 0); - TType componentType(columnType, 0); - TType indexType(EbtInt); - for (int i = 0; i < (int)swizzle.size(); i += 2) { - // the right component, single index into the RHS vector - TIntermTyped* rightComp = intermediate.addIndex(EOpIndexDirect, vector, - intermediate.addConstantUnion(i/2, loc), loc); - - // the left component, double index into the LHS matrix - TIntermTyped* leftComp = intermediate.addIndex(EOpIndexDirect, matrix, - intermediate.addConstantUnion(swizzle[i]->getAsConstantUnion()->getConstArray(), - indexType, loc), - loc); - leftComp->setType(columnType); - leftComp = intermediate.addIndex(EOpIndexDirect, leftComp, - intermediate.addConstantUnion(swizzle[i+1]->getAsConstantUnion()->getConstArray(), - indexType, loc), - loc); - leftComp->setType(componentType); - - // Add the assignment to the aggregate - result = intermediate.growAggregate(result, intermediate.addAssign(op, leftComp, rightComp, loc)); - } - - result->setOp(EOpSequence); - - return result; -} - -// -// HLSL atomic operations have slightly different arguments than -// GLSL/AST/SPIRV. The semantics are converted below in decomposeIntrinsic. -// This provides the post-decomposition equivalent opcode. -// -TOperator HlslParseContext::mapAtomicOp(const TSourceLoc& loc, TOperator op, bool isImage) -{ - switch (op) { - case EOpInterlockedAdd: return isImage ? EOpImageAtomicAdd : EOpAtomicAdd; - case EOpInterlockedAnd: return isImage ? EOpImageAtomicAnd : EOpAtomicAnd; - case EOpInterlockedCompareExchange: return isImage ? EOpImageAtomicCompSwap : EOpAtomicCompSwap; - case EOpInterlockedMax: return isImage ? EOpImageAtomicMax : EOpAtomicMax; - case EOpInterlockedMin: return isImage ? EOpImageAtomicMin : EOpAtomicMin; - case EOpInterlockedOr: return isImage ? EOpImageAtomicOr : EOpAtomicOr; - case EOpInterlockedXor: return isImage ? EOpImageAtomicXor : EOpAtomicXor; - case EOpInterlockedExchange: return isImage ? EOpImageAtomicExchange : EOpAtomicExchange; - case EOpInterlockedCompareStore: // TODO: ... - default: - error(loc, "unknown atomic operation", "unknown op", ""); - return EOpNull; - } -} - -// -// Create a combined sampler/texture from separate sampler and texture. -// -TIntermAggregate* HlslParseContext::handleSamplerTextureCombine(const TSourceLoc& loc, TIntermTyped* argTex, - TIntermTyped* argSampler) -{ - TIntermAggregate* txcombine = new TIntermAggregate(EOpConstructTextureSampler); - - txcombine->getSequence().push_back(argTex); - txcombine->getSequence().push_back(argSampler); - - TSampler samplerType = argTex->getType().getSampler(); - samplerType.combined = true; - - // TODO: - // This block exists until the spec no longer requires shadow modes on texture objects. - // It can be deleted after that, along with the shadowTextureVariant member. - { - const bool shadowMode = argSampler->getType().getSampler().shadow; - - TIntermSymbol* texSymbol = argTex->getAsSymbolNode(); - - if (texSymbol == nullptr) - texSymbol = argTex->getAsBinaryNode()->getLeft()->getAsSymbolNode(); - - if (texSymbol == nullptr) { - error(loc, "unable to find texture symbol", "", ""); - return nullptr; - } - - // This forces the texture's shadow state to be the sampler's - // shadow state. This depends on downstream optimization to - // DCE one variant in [shadow, nonshadow] if both are present, - // or the SPIR-V module would be invalid. - int newId = texSymbol->getId(); - - // Check to see if this texture has been given a shadow mode already. - // If so, look up the one we already have. - const auto textureShadowEntry = textureShadowVariant.find(texSymbol->getId()); - - if (textureShadowEntry != textureShadowVariant.end()) - newId = textureShadowEntry->second->get(shadowMode); - else - textureShadowVariant[texSymbol->getId()] = new tShadowTextureSymbols; - - // Sometimes we have to create another symbol (if this texture has been seen before, - // and we haven't created the form for this shadow mode). - if (newId == -1) { - TType texType; - texType.shallowCopy(argTex->getType()); - texType.getSampler().shadow = shadowMode; // set appropriate shadow mode. - globalQualifierFix(loc, texType.getQualifier()); - - TVariable* newTexture = makeInternalVariable(texSymbol->getName(), texType); - - trackLinkage(*newTexture); - - newId = newTexture->getUniqueId(); - } - - assert(newId != -1); - - if (textureShadowVariant.find(newId) == textureShadowVariant.end()) - textureShadowVariant[newId] = textureShadowVariant[texSymbol->getId()]; - - textureShadowVariant[newId]->set(shadowMode, newId); - - // Remember this shadow mode in the texture and the merged type. - argTex->getWritableType().getSampler().shadow = shadowMode; - samplerType.shadow = shadowMode; - - texSymbol->switchId(newId); - } - - txcombine->setType(TType(samplerType, EvqTemporary)); - txcombine->setLoc(loc); - - return txcombine; -} - -// Return true if this a buffer type that has an associated counter buffer. -bool HlslParseContext::hasStructBuffCounter(const TType& type) const -{ - switch (type.getQualifier().declaredBuiltIn) { - case EbvAppendConsume: // fall through... - case EbvRWStructuredBuffer: // ... - return true; - default: - return false; // the other structuredbuffer types do not have a counter. - } -} - -void HlslParseContext::counterBufferType(const TSourceLoc& loc, TType& type) -{ - // Counter type - TType* counterType = new TType(EbtUint, EvqBuffer); - counterType->setFieldName(intermediate.implicitCounterName); - - TTypeList* blockStruct = new TTypeList; - TTypeLoc member = { counterType, loc }; - blockStruct->push_back(member); - - TType blockType(blockStruct, "", counterType->getQualifier()); - blockType.getQualifier().storage = EvqBuffer; - - type.shallowCopy(blockType); - shareStructBufferType(type); -} - -// declare counter for a structured buffer type -void HlslParseContext::declareStructBufferCounter(const TSourceLoc& loc, const TType& bufferType, const TString& name) -{ - // Bail out if not a struct buffer - if (! isStructBufferType(bufferType)) - return; - - if (! hasStructBuffCounter(bufferType)) - return; - - TType blockType; - counterBufferType(loc, blockType); - - TString* blockName = new TString(intermediate.addCounterBufferName(name)); - - // Counter buffer is not yet in use - structBufferCounter[*blockName] = false; - - shareStructBufferType(blockType); - declareBlock(loc, blockType, blockName); -} - -// return the counter that goes with a given structuredbuffer -TIntermTyped* HlslParseContext::getStructBufferCounter(const TSourceLoc& loc, TIntermTyped* buffer) -{ - // Bail out if not a struct buffer - if (buffer == nullptr || ! isStructBufferType(buffer->getType())) - return nullptr; - - const TString counterBlockName(intermediate.addCounterBufferName(buffer->getAsSymbolNode()->getName())); - - // Mark the counter as being used - structBufferCounter[counterBlockName] = true; - - TIntermTyped* counterVar = handleVariable(loc, &counterBlockName); // find the block structure - TIntermTyped* index = intermediate.addConstantUnion(0, loc); // index to counter inside block struct - - TIntermTyped* counterMember = intermediate.addIndex(EOpIndexDirectStruct, counterVar, index, loc); - counterMember->setType(TType(EbtUint)); - return counterMember; -} - -// -// Decompose structure buffer methods into AST -// -void HlslParseContext::decomposeStructBufferMethods(const TSourceLoc& loc, TIntermTyped*& node, TIntermNode* arguments) -{ - if (node == nullptr || node->getAsOperator() == nullptr || arguments == nullptr) - return; - - const TOperator op = node->getAsOperator()->getOp(); - TIntermAggregate* argAggregate = arguments->getAsAggregate(); - - // Buffer is the object upon which method is called, so always arg 0 - TIntermTyped* bufferObj = nullptr; - - // The parameters can be an aggregate, or just a the object as a symbol if there are no fn params. - if (argAggregate) { - if (argAggregate->getSequence().empty()) - return; - bufferObj = argAggregate->getSequence()[0]->getAsTyped(); - } else { - bufferObj = arguments->getAsSymbolNode(); - } - - if (bufferObj == nullptr || bufferObj->getAsSymbolNode() == nullptr) - return; - - // Some methods require a hidden internal counter, obtained via getStructBufferCounter(). - // This lambda adds something to it and returns the old value. - const auto incDecCounter = [&](int incval) -> TIntermTyped* { - TIntermTyped* incrementValue = intermediate.addConstantUnion(static_cast(incval), loc, true); - TIntermTyped* counter = getStructBufferCounter(loc, bufferObj); // obtain the counter member - - if (counter == nullptr) - return nullptr; - - TIntermAggregate* counterIncrement = new TIntermAggregate(EOpAtomicAdd); - counterIncrement->setType(TType(EbtUint, EvqTemporary)); - counterIncrement->setLoc(loc); - counterIncrement->getSequence().push_back(counter); - counterIncrement->getSequence().push_back(incrementValue); - - return counterIncrement; - }; - - // Index to obtain the runtime sized array out of the buffer. - TIntermTyped* argArray = indexStructBufferContent(loc, bufferObj); - if (argArray == nullptr) - return; // It might not be a struct buffer method. - - switch (op) { - case EOpMethodLoad: - { - TIntermTyped* argIndex = makeIntegerIndex(argAggregate->getSequence()[1]->getAsTyped()); // index - - const TType& bufferType = bufferObj->getType(); - - const TBuiltInVariable builtInType = bufferType.getQualifier().declaredBuiltIn; - - // Byte address buffers index in bytes (only multiples of 4 permitted... not so much a byte address - // buffer then, but that's what it calls itself. - const bool isByteAddressBuffer = (builtInType == EbvByteAddressBuffer || - builtInType == EbvRWByteAddressBuffer); - - - if (isByteAddressBuffer) - argIndex = intermediate.addBinaryNode(EOpRightShift, argIndex, - intermediate.addConstantUnion(2, loc, true), - loc, TType(EbtInt)); - - // Index into the array to find the item being loaded. - const TOperator idxOp = (argIndex->getQualifier().storage == EvqConst) ? EOpIndexDirect : EOpIndexIndirect; - - node = intermediate.addIndex(idxOp, argArray, argIndex, loc); - - const TType derefType(argArray->getType(), 0); - node->setType(derefType); - } - - break; - - case EOpMethodLoad2: - case EOpMethodLoad3: - case EOpMethodLoad4: - { - TIntermTyped* argIndex = makeIntegerIndex(argAggregate->getSequence()[1]->getAsTyped()); // index - - TOperator constructOp = EOpNull; - int size = 0; - - switch (op) { - case EOpMethodLoad2: size = 2; constructOp = EOpConstructVec2; break; - case EOpMethodLoad3: size = 3; constructOp = EOpConstructVec3; break; - case EOpMethodLoad4: size = 4; constructOp = EOpConstructVec4; break; - default: assert(0); - } - - TIntermTyped* body = nullptr; - - // First, we'll store the address in a variable to avoid multiple shifts - // (we must convert the byte address to an item address) - TIntermTyped* byteAddrIdx = intermediate.addBinaryNode(EOpRightShift, argIndex, - intermediate.addConstantUnion(2, loc, true), - loc, TType(EbtInt)); - - TVariable* byteAddrSym = makeInternalVariable("byteAddrTemp", TType(EbtInt, EvqTemporary)); - TIntermTyped* byteAddrIdxVar = intermediate.addSymbol(*byteAddrSym, loc); - - body = intermediate.growAggregate(body, intermediate.addAssign(EOpAssign, byteAddrIdxVar, byteAddrIdx, loc)); - - TIntermTyped* vec = nullptr; - - // These are only valid on (rw)byteaddressbuffers, so we can always perform the >>2 - // address conversion. - for (int idx=0; idxgetQualifier().storage == EvqConst) ? EOpIndexDirect - : EOpIndexIndirect; - - TIntermTyped* indexVal = intermediate.addIndex(idxOp, argArray, offsetIdx, loc); - - TType derefType(argArray->getType(), 0); - derefType.getQualifier().makeTemporary(); - indexVal->setType(derefType); - - vec = intermediate.growAggregate(vec, indexVal); - } - - vec->setType(TType(argArray->getBasicType(), EvqTemporary, size)); - vec->getAsAggregate()->setOperator(constructOp); - - body = intermediate.growAggregate(body, vec); - body->setType(vec->getType()); - body->getAsAggregate()->setOperator(EOpSequence); - - node = body; - } - - break; - - case EOpMethodStore: - case EOpMethodStore2: - case EOpMethodStore3: - case EOpMethodStore4: - { - TIntermTyped* argIndex = makeIntegerIndex(argAggregate->getSequence()[1]->getAsTyped()); // index - TIntermTyped* argValue = argAggregate->getSequence()[2]->getAsTyped(); // value - - // Index into the array to find the item being loaded. - // Byte address buffers index in bytes (only multiples of 4 permitted... not so much a byte address - // buffer then, but that's what it calls itself). - - int size = 0; - - switch (op) { - case EOpMethodStore: size = 1; break; - case EOpMethodStore2: size = 2; break; - case EOpMethodStore3: size = 3; break; - case EOpMethodStore4: size = 4; break; - default: assert(0); - } - - TIntermAggregate* body = nullptr; - - // First, we'll store the address in a variable to avoid multiple shifts - // (we must convert the byte address to an item address) - TIntermTyped* byteAddrIdx = intermediate.addBinaryNode(EOpRightShift, argIndex, - intermediate.addConstantUnion(2, loc, true), loc, TType(EbtInt)); - - TVariable* byteAddrSym = makeInternalVariable("byteAddrTemp", TType(EbtInt, EvqTemporary)); - TIntermTyped* byteAddrIdxVar = intermediate.addSymbol(*byteAddrSym, loc); - - body = intermediate.growAggregate(body, intermediate.addAssign(EOpAssign, byteAddrIdxVar, byteAddrIdx, loc)); - - for (int idx=0; idxgetQualifier().storage == EvqConst) ? EOpIndexDirect - : EOpIndexIndirect; - - TIntermTyped* lValue = intermediate.addIndex(idxOp, argArray, offsetIdx, loc); - const TType derefType(argArray->getType(), 0); - lValue->setType(derefType); - - TIntermTyped* rValue; - if (size == 1) { - rValue = argValue; - } else { - rValue = intermediate.addIndex(EOpIndexDirect, argValue, idxConst, loc); - const TType indexType(argValue->getType(), 0); - rValue->setType(indexType); - } - - TIntermTyped* assign = intermediate.addAssign(EOpAssign, lValue, rValue, loc); - - body = intermediate.growAggregate(body, assign); - } - - body->setOperator(EOpSequence); - node = body; - } - - break; - - case EOpMethodGetDimensions: - { - const int numArgs = (int)argAggregate->getSequence().size(); - TIntermTyped* argNumItems = argAggregate->getSequence()[1]->getAsTyped(); // out num items - TIntermTyped* argStride = numArgs > 2 ? argAggregate->getSequence()[2]->getAsTyped() : nullptr; // out stride - - TIntermAggregate* body = nullptr; - - // Length output: - if (argArray->getType().isSizedArray()) { - const int length = argArray->getType().getOuterArraySize(); - TIntermTyped* assign = intermediate.addAssign(EOpAssign, argNumItems, - intermediate.addConstantUnion(length, loc, true), loc); - body = intermediate.growAggregate(body, assign, loc); - } else { - TIntermTyped* lengthCall = intermediate.addBuiltInFunctionCall(loc, EOpArrayLength, true, argArray, - argNumItems->getType()); - TIntermTyped* assign = intermediate.addAssign(EOpAssign, argNumItems, lengthCall, loc); - body = intermediate.growAggregate(body, assign, loc); - } - - // Stride output: - if (argStride != nullptr) { - int size; - int stride; - intermediate.getBaseAlignment(argArray->getType(), size, stride, false, - argArray->getType().getQualifier().layoutMatrix == ElmRowMajor); - - TIntermTyped* assign = intermediate.addAssign(EOpAssign, argStride, - intermediate.addConstantUnion(stride, loc, true), loc); - - body = intermediate.growAggregate(body, assign); - } - - body->setOperator(EOpSequence); - node = body; - } - - break; - - case EOpInterlockedAdd: - case EOpInterlockedAnd: - case EOpInterlockedExchange: - case EOpInterlockedMax: - case EOpInterlockedMin: - case EOpInterlockedOr: - case EOpInterlockedXor: - case EOpInterlockedCompareExchange: - case EOpInterlockedCompareStore: - { - // We'll replace the first argument with the block dereference, and let - // downstream decomposition handle the rest. - - TIntermSequence& sequence = argAggregate->getSequence(); - - TIntermTyped* argIndex = makeIntegerIndex(sequence[1]->getAsTyped()); // index - argIndex = intermediate.addBinaryNode(EOpRightShift, argIndex, intermediate.addConstantUnion(2, loc, true), - loc, TType(EbtInt)); - - const TOperator idxOp = (argIndex->getQualifier().storage == EvqConst) ? EOpIndexDirect : EOpIndexIndirect; - TIntermTyped* element = intermediate.addIndex(idxOp, argArray, argIndex, loc); - - const TType derefType(argArray->getType(), 0); - element->setType(derefType); - - // Replace the numeric byte offset parameter with array reference. - sequence[1] = element; - sequence.erase(sequence.begin(), sequence.begin()+1); - } - break; - - case EOpMethodIncrementCounter: - { - node = incDecCounter(1); - break; - } - - case EOpMethodDecrementCounter: - { - TIntermTyped* preIncValue = incDecCounter(-1); // result is original value - node = intermediate.addBinaryNode(EOpAdd, preIncValue, intermediate.addConstantUnion(-1, loc, true), loc, - preIncValue->getType()); - break; - } - - case EOpMethodAppend: - { - TIntermTyped* oldCounter = incDecCounter(1); - - TIntermTyped* lValue = intermediate.addIndex(EOpIndexIndirect, argArray, oldCounter, loc); - TIntermTyped* rValue = argAggregate->getSequence()[1]->getAsTyped(); - - const TType derefType(argArray->getType(), 0); - lValue->setType(derefType); - - node = intermediate.addAssign(EOpAssign, lValue, rValue, loc); - - break; - } - - case EOpMethodConsume: - { - TIntermTyped* oldCounter = incDecCounter(-1); - - TIntermTyped* newCounter = intermediate.addBinaryNode(EOpAdd, oldCounter, - intermediate.addConstantUnion(-1, loc, true), loc, - oldCounter->getType()); - - node = intermediate.addIndex(EOpIndexIndirect, argArray, newCounter, loc); - - const TType derefType(argArray->getType(), 0); - node->setType(derefType); - - break; - } - - default: - break; // most pass through unchanged - } -} - -// Create array of standard sample positions for given sample count. -// TODO: remove when a real method to query sample pos exists in SPIR-V. -TIntermConstantUnion* HlslParseContext::getSamplePosArray(int count) -{ - struct tSamplePos { float x, y; }; - - static const tSamplePos pos1[] = { - { 0.0/16.0, 0.0/16.0 }, - }; - - // standard sample positions for 2, 4, 8, and 16 samples. - static const tSamplePos pos2[] = { - { 4.0/16.0, 4.0/16.0 }, {-4.0/16.0, -4.0/16.0 }, - }; - - static const tSamplePos pos4[] = { - {-2.0/16.0, -6.0/16.0 }, { 6.0/16.0, -2.0/16.0 }, {-6.0/16.0, 2.0/16.0 }, { 2.0/16.0, 6.0/16.0 }, - }; - - static const tSamplePos pos8[] = { - { 1.0/16.0, -3.0/16.0 }, {-1.0/16.0, 3.0/16.0 }, { 5.0/16.0, 1.0/16.0 }, {-3.0/16.0, -5.0/16.0 }, - {-5.0/16.0, 5.0/16.0 }, {-7.0/16.0, -1.0/16.0 }, { 3.0/16.0, 7.0/16.0 }, { 7.0/16.0, -7.0/16.0 }, - }; - - static const tSamplePos pos16[] = { - { 1.0/16.0, 1.0/16.0 }, {-1.0/16.0, -3.0/16.0 }, {-3.0/16.0, 2.0/16.0 }, { 4.0/16.0, -1.0/16.0 }, - {-5.0/16.0, -2.0/16.0 }, { 2.0/16.0, 5.0/16.0 }, { 5.0/16.0, 3.0/16.0 }, { 3.0/16.0, -5.0/16.0 }, - {-2.0/16.0, 6.0/16.0 }, { 0.0/16.0, -7.0/16.0 }, {-4.0/16.0, -6.0/16.0 }, {-6.0/16.0, 4.0/16.0 }, - {-8.0/16.0, 0.0/16.0 }, { 7.0/16.0, -4.0/16.0 }, { 6.0/16.0, 7.0/16.0 }, {-7.0/16.0, -8.0/16.0 }, - }; - - const tSamplePos* sampleLoc = nullptr; - int numSamples = count; - - switch (count) { - case 2: sampleLoc = pos2; break; - case 4: sampleLoc = pos4; break; - case 8: sampleLoc = pos8; break; - case 16: sampleLoc = pos16; break; - default: - sampleLoc = pos1; - numSamples = 1; - } - - TConstUnionArray* values = new TConstUnionArray(numSamples*2); - - for (int pos=0; posaddInnerSize(numSamples); - retType.transferArraySizes(arraySizes); - } - - return new TIntermConstantUnion(*values, retType); -} - -// -// Decompose DX9 and DX10 sample intrinsics & object methods into AST -// -void HlslParseContext::decomposeSampleMethods(const TSourceLoc& loc, TIntermTyped*& node, TIntermNode* arguments) -{ - if (node == nullptr || !node->getAsOperator()) - return; - - // Sampler return must always be a vec4, but we can construct a shorter vector or a structure from it. - const auto convertReturn = [&loc, &node, this](TIntermTyped* result, const TSampler& sampler) -> TIntermTyped* { - result->setType(TType(node->getType().getBasicType(), EvqTemporary, node->getVectorSize())); - - TIntermTyped* convertedResult = nullptr; - - TType retType; - getTextureReturnType(sampler, retType); - - if (retType.isStruct()) { - // For type convenience, conversionAggregate points to the convertedResult (we know it's an aggregate here) - TIntermAggregate* conversionAggregate = new TIntermAggregate; - convertedResult = conversionAggregate; - - // Convert vector output to return structure. We will need a temp symbol to copy the results to. - TVariable* structVar = makeInternalVariable("@sampleStructTemp", retType); - - // We also need a temp symbol to hold the result of the texture. We don't want to re-fetch the - // sample each time we'll index into the result, so we'll copy to this, and index into the copy. - TVariable* sampleShadow = makeInternalVariable("@sampleResultShadow", result->getType()); - - // Initial copy from texture to our sample result shadow. - TIntermTyped* shadowCopy = intermediate.addAssign(EOpAssign, intermediate.addSymbol(*sampleShadow, loc), - result, loc); - - conversionAggregate->getSequence().push_back(shadowCopy); - - unsigned vec4Pos = 0; - - for (unsigned m = 0; m < unsigned(retType.getStruct()->size()); ++m) { - const TType memberType(retType, m); // dereferenced type of the member we're about to assign. - - // Check for bad struct members. This should have been caught upstream. Complain, because - // wwe don't know what to do with it. This algorithm could be generalized to handle - // other things, e.g, sub-structures, but HLSL doesn't allow them. - if (!memberType.isVector() && !memberType.isScalar()) { - error(loc, "expected: scalar or vector type in texture structure", "", ""); - return nullptr; - } - - // Index into the struct variable to find the member to assign. - TIntermTyped* structMember = intermediate.addIndex(EOpIndexDirectStruct, - intermediate.addSymbol(*structVar, loc), - intermediate.addConstantUnion(m, loc), loc); - - structMember->setType(memberType); - - // Assign each component of (possible) vector in struct member. - for (int component = 0; component < memberType.getVectorSize(); ++component) { - TIntermTyped* vec4Member = intermediate.addIndex(EOpIndexDirect, - intermediate.addSymbol(*sampleShadow, loc), - intermediate.addConstantUnion(vec4Pos++, loc), loc); - vec4Member->setType(TType(memberType.getBasicType(), EvqTemporary, 1)); - - TIntermTyped* memberAssign = nullptr; - - if (memberType.isVector()) { - // Vector member: we need to create an access chain to the vector component. - - TIntermTyped* structVecComponent = intermediate.addIndex(EOpIndexDirect, structMember, - intermediate.addConstantUnion(component, loc), loc); - - memberAssign = intermediate.addAssign(EOpAssign, structVecComponent, vec4Member, loc); - } else { - // Scalar member: we can assign to it directly. - memberAssign = intermediate.addAssign(EOpAssign, structMember, vec4Member, loc); - } - - - conversionAggregate->getSequence().push_back(memberAssign); - } - } - - // Add completed variable so the expression results in the whole struct value we just built. - conversionAggregate->getSequence().push_back(intermediate.addSymbol(*structVar, loc)); - - // Make it a sequence. - intermediate.setAggregateOperator(conversionAggregate, EOpSequence, retType, loc); - } else { - // vector clamp the output if template vector type is smaller than sample result. - if (retType.getVectorSize() < node->getVectorSize()) { - // Too many components. Construct shorter vector from it. - const TOperator op = intermediate.mapTypeToConstructorOp(retType); - - convertedResult = constructBuiltIn(retType, op, result, loc, false); - } else { - // Enough components. Use directly. - convertedResult = result; - } - } - - convertedResult->setLoc(loc); - return convertedResult; - }; - - const TOperator op = node->getAsOperator()->getOp(); - const TIntermAggregate* argAggregate = arguments ? arguments->getAsAggregate() : nullptr; - - // Bail out if not a sampler method. - // Note though this is odd to do before checking the op, because the op - // could be something that takes the arguments, and the function in question - // takes the result of the op. So, this is not the final word. - if (arguments != nullptr) { - if (argAggregate == nullptr) { - if (arguments->getAsTyped()->getBasicType() != EbtSampler) - return; - } else { - if (argAggregate->getSequence().size() == 0 || - argAggregate->getSequence()[0]->getAsTyped()->getBasicType() != EbtSampler) - return; - } - } - - switch (op) { - // **** DX9 intrinsics: **** - case EOpTexture: - { - // Texture with ddx & ddy is really gradient form in HLSL - if (argAggregate->getSequence().size() == 4) - node->getAsAggregate()->setOperator(EOpTextureGrad); - - break; - } - - case EOpTextureBias: - { - TIntermTyped* arg0 = argAggregate->getSequence()[0]->getAsTyped(); // sampler - TIntermTyped* arg1 = argAggregate->getSequence()[1]->getAsTyped(); // coord - - // HLSL puts bias in W component of coordinate. We extract it and add it to - // the argument list, instead - TIntermTyped* w = intermediate.addConstantUnion(3, loc, true); - TIntermTyped* bias = intermediate.addIndex(EOpIndexDirect, arg1, w, loc); - - TOperator constructOp = EOpNull; - const TSampler& sampler = arg0->getType().getSampler(); - - switch (sampler.dim) { - case Esd1D: constructOp = EOpConstructFloat; break; // 1D - case Esd2D: constructOp = EOpConstructVec2; break; // 2D - case Esd3D: constructOp = EOpConstructVec3; break; // 3D - case EsdCube: constructOp = EOpConstructVec3; break; // also 3D - default: break; - } - - TIntermAggregate* constructCoord = new TIntermAggregate(constructOp); - constructCoord->getSequence().push_back(arg1); - constructCoord->setLoc(loc); - - // The input vector should never be less than 2, since there's always a bias. - // The max is for safety, and should be a no-op. - constructCoord->setType(TType(arg1->getBasicType(), EvqTemporary, std::max(arg1->getVectorSize() - 1, 0))); - - TIntermAggregate* tex = new TIntermAggregate(EOpTexture); - tex->getSequence().push_back(arg0); // sampler - tex->getSequence().push_back(constructCoord); // coordinate - tex->getSequence().push_back(bias); // bias - - node = convertReturn(tex, sampler); - - break; - } - - // **** DX10 methods: **** - case EOpMethodSample: // fall through - case EOpMethodSampleBias: // ... - { - TIntermTyped* argTex = argAggregate->getSequence()[0]->getAsTyped(); - TIntermTyped* argSamp = argAggregate->getSequence()[1]->getAsTyped(); - TIntermTyped* argCoord = argAggregate->getSequence()[2]->getAsTyped(); - TIntermTyped* argBias = nullptr; - TIntermTyped* argOffset = nullptr; - const TSampler& sampler = argTex->getType().getSampler(); - - int nextArg = 3; - - if (op == EOpMethodSampleBias) // SampleBias has a bias arg - argBias = argAggregate->getSequence()[nextArg++]->getAsTyped(); - - TOperator textureOp = EOpTexture; - - if ((int)argAggregate->getSequence().size() == (nextArg+1)) { // last parameter is offset form - textureOp = EOpTextureOffset; - argOffset = argAggregate->getSequence()[nextArg++]->getAsTyped(); - } - - TIntermAggregate* txcombine = handleSamplerTextureCombine(loc, argTex, argSamp); - - TIntermAggregate* txsample = new TIntermAggregate(textureOp); - txsample->getSequence().push_back(txcombine); - txsample->getSequence().push_back(argCoord); - - if (argBias != nullptr) - txsample->getSequence().push_back(argBias); - - if (argOffset != nullptr) - txsample->getSequence().push_back(argOffset); - - node = convertReturn(txsample, sampler); - - break; - } - - case EOpMethodSampleGrad: // ... - { - TIntermTyped* argTex = argAggregate->getSequence()[0]->getAsTyped(); - TIntermTyped* argSamp = argAggregate->getSequence()[1]->getAsTyped(); - TIntermTyped* argCoord = argAggregate->getSequence()[2]->getAsTyped(); - TIntermTyped* argDDX = argAggregate->getSequence()[3]->getAsTyped(); - TIntermTyped* argDDY = argAggregate->getSequence()[4]->getAsTyped(); - TIntermTyped* argOffset = nullptr; - const TSampler& sampler = argTex->getType().getSampler(); - - TOperator textureOp = EOpTextureGrad; - - if (argAggregate->getSequence().size() == 6) { // last parameter is offset form - textureOp = EOpTextureGradOffset; - argOffset = argAggregate->getSequence()[5]->getAsTyped(); - } - - TIntermAggregate* txcombine = handleSamplerTextureCombine(loc, argTex, argSamp); - - TIntermAggregate* txsample = new TIntermAggregate(textureOp); - txsample->getSequence().push_back(txcombine); - txsample->getSequence().push_back(argCoord); - txsample->getSequence().push_back(argDDX); - txsample->getSequence().push_back(argDDY); - - if (argOffset != nullptr) - txsample->getSequence().push_back(argOffset); - - node = convertReturn(txsample, sampler); - - break; - } - - case EOpMethodGetDimensions: - { - // AST returns a vector of results, which we break apart component-wise into - // separate values to assign to the HLSL method's outputs, ala: - // tx . GetDimensions(width, height); - // float2 sizeQueryTemp = EOpTextureQuerySize - // width = sizeQueryTemp.X; - // height = sizeQueryTemp.Y; - - TIntermTyped* argTex = argAggregate->getSequence()[0]->getAsTyped(); - const TType& texType = argTex->getType(); - - assert(texType.getBasicType() == EbtSampler); - - const TSampler& sampler = texType.getSampler(); - const TSamplerDim dim = sampler.dim; - const bool isImage = sampler.isImage(); - const bool isMs = sampler.isMultiSample(); - const int numArgs = (int)argAggregate->getSequence().size(); - - int numDims = 0; - - switch (dim) { - case Esd1D: numDims = 1; break; // W - case Esd2D: numDims = 2; break; // W, H - case Esd3D: numDims = 3; break; // W, H, D - case EsdCube: numDims = 2; break; // W, H (cube) - case EsdBuffer: numDims = 1; break; // W (buffers) - case EsdRect: numDims = 2; break; // W, H (rect) - default: - assert(0 && "unhandled texture dimension"); - } - - // Arrayed adds another dimension for the number of array elements - if (sampler.isArrayed()) - ++numDims; - - // Establish whether the method itself is querying mip levels. This can be false even - // if the underlying query requires a MIP level, due to the available HLSL method overloads. - const bool mipQuery = (numArgs > (numDims + 1 + (isMs ? 1 : 0))); - - // Establish whether we must use the LOD form of query (even if the method did not supply a mip level to query). - // True if: - // 1. 1D/2D/3D/Cube AND multisample==0 AND NOT image (those can be sent to the non-LOD query) - // or, - // 2. There is a LOD (because the non-LOD query cannot be used in that case, per spec) - const bool mipRequired = - ((dim == Esd1D || dim == Esd2D || dim == Esd3D || dim == EsdCube) && !isMs && !isImage) || // 1... - mipQuery; // 2... - - // AST assumes integer return. Will be converted to float if required. - TIntermAggregate* sizeQuery = new TIntermAggregate(isImage ? EOpImageQuerySize : EOpTextureQuerySize); - sizeQuery->getSequence().push_back(argTex); - - // If we're building an LOD query, add the LOD. - if (mipRequired) { - // If the base HLSL query had no MIP level given, use level 0. - TIntermTyped* queryLod = mipQuery ? argAggregate->getSequence()[1]->getAsTyped() : - intermediate.addConstantUnion(0, loc, true); - sizeQuery->getSequence().push_back(queryLod); - } - - sizeQuery->setType(TType(EbtUint, EvqTemporary, numDims)); - sizeQuery->setLoc(loc); - - // Return value from size query - TVariable* tempArg = makeInternalVariable("sizeQueryTemp", sizeQuery->getType()); - tempArg->getWritableType().getQualifier().makeTemporary(); - TIntermTyped* sizeQueryAssign = intermediate.addAssign(EOpAssign, - intermediate.addSymbol(*tempArg, loc), - sizeQuery, loc); - - // Compound statement for assigning outputs - TIntermAggregate* compoundStatement = intermediate.makeAggregate(sizeQueryAssign, loc); - // Index of first output parameter - const int outParamBase = mipQuery ? 2 : 1; - - for (int compNum = 0; compNum < numDims; ++compNum) { - TIntermTyped* indexedOut = nullptr; - TIntermSymbol* sizeQueryReturn = intermediate.addSymbol(*tempArg, loc); - - if (numDims > 1) { - TIntermTyped* component = intermediate.addConstantUnion(compNum, loc, true); - indexedOut = intermediate.addIndex(EOpIndexDirect, sizeQueryReturn, component, loc); - indexedOut->setType(TType(EbtUint, EvqTemporary, 1)); - indexedOut->setLoc(loc); - } else { - indexedOut = sizeQueryReturn; - } - - TIntermTyped* outParam = argAggregate->getSequence()[outParamBase + compNum]->getAsTyped(); - TIntermTyped* compAssign = intermediate.addAssign(EOpAssign, outParam, indexedOut, loc); - - compoundStatement = intermediate.growAggregate(compoundStatement, compAssign); - } - - // handle mip level parameter - if (mipQuery) { - TIntermTyped* outParam = argAggregate->getSequence()[outParamBase + numDims]->getAsTyped(); - - TIntermAggregate* levelsQuery = new TIntermAggregate(EOpTextureQueryLevels); - levelsQuery->getSequence().push_back(argTex); - levelsQuery->setType(TType(EbtUint, EvqTemporary, 1)); - levelsQuery->setLoc(loc); - - TIntermTyped* compAssign = intermediate.addAssign(EOpAssign, outParam, levelsQuery, loc); - compoundStatement = intermediate.growAggregate(compoundStatement, compAssign); - } - - // 2DMS formats query # samples, which needs a different query op - if (sampler.isMultiSample()) { - TIntermTyped* outParam = argAggregate->getSequence()[outParamBase + numDims]->getAsTyped(); - - TIntermAggregate* samplesQuery = new TIntermAggregate(EOpImageQuerySamples); - samplesQuery->getSequence().push_back(argTex); - samplesQuery->setType(TType(EbtUint, EvqTemporary, 1)); - samplesQuery->setLoc(loc); - - TIntermTyped* compAssign = intermediate.addAssign(EOpAssign, outParam, samplesQuery, loc); - compoundStatement = intermediate.growAggregate(compoundStatement, compAssign); - } - - compoundStatement->setOperator(EOpSequence); - compoundStatement->setLoc(loc); - compoundStatement->setType(TType(EbtVoid)); - - node = compoundStatement; - - break; - } - - case EOpMethodSampleCmp: // fall through... - case EOpMethodSampleCmpLevelZero: - { - TIntermTyped* argTex = argAggregate->getSequence()[0]->getAsTyped(); - TIntermTyped* argSamp = argAggregate->getSequence()[1]->getAsTyped(); - TIntermTyped* argCoord = argAggregate->getSequence()[2]->getAsTyped(); - TIntermTyped* argCmpVal = argAggregate->getSequence()[3]->getAsTyped(); - TIntermTyped* argOffset = nullptr; - - // Sampler argument should be a sampler. - if (argSamp->getType().getBasicType() != EbtSampler) { - error(loc, "expected: sampler type", "", ""); - return; - } - - // Sampler should be a SamplerComparisonState - if (! argSamp->getType().getSampler().isShadow()) { - error(loc, "expected: SamplerComparisonState", "", ""); - return; - } - - // optional offset value - if (argAggregate->getSequence().size() > 4) - argOffset = argAggregate->getSequence()[4]->getAsTyped(); - - const int coordDimWithCmpVal = argCoord->getType().getVectorSize() + 1; // +1 for cmp - - // AST wants comparison value as one of the texture coordinates - TOperator constructOp = EOpNull; - switch (coordDimWithCmpVal) { - // 1D can't happen: there's always at least 1 coordinate dimension + 1 cmp val - case 2: constructOp = EOpConstructVec2; break; - case 3: constructOp = EOpConstructVec3; break; - case 4: constructOp = EOpConstructVec4; break; - case 5: constructOp = EOpConstructVec4; break; // cubeArrayShadow, cmp value is separate arg. - default: assert(0); break; - } - - TIntermAggregate* coordWithCmp = new TIntermAggregate(constructOp); - coordWithCmp->getSequence().push_back(argCoord); - if (coordDimWithCmpVal != 5) // cube array shadow is special. - coordWithCmp->getSequence().push_back(argCmpVal); - coordWithCmp->setLoc(loc); - coordWithCmp->setType(TType(argCoord->getBasicType(), EvqTemporary, std::min(coordDimWithCmpVal, 4))); - - TOperator textureOp = (op == EOpMethodSampleCmpLevelZero ? EOpTextureLod : EOpTexture); - if (argOffset != nullptr) - textureOp = (op == EOpMethodSampleCmpLevelZero ? EOpTextureLodOffset : EOpTextureOffset); - - // Create combined sampler & texture op - TIntermAggregate* txcombine = handleSamplerTextureCombine(loc, argTex, argSamp); - TIntermAggregate* txsample = new TIntermAggregate(textureOp); - txsample->getSequence().push_back(txcombine); - txsample->getSequence().push_back(coordWithCmp); - - if (coordDimWithCmpVal == 5) // cube array shadow is special: cmp val follows coord. - txsample->getSequence().push_back(argCmpVal); - - // the LevelZero form uses 0 as an explicit LOD - if (op == EOpMethodSampleCmpLevelZero) - txsample->getSequence().push_back(intermediate.addConstantUnion(0.0, EbtFloat, loc, true)); - - // Add offset if present - if (argOffset != nullptr) - txsample->getSequence().push_back(argOffset); - - txsample->setType(node->getType()); - txsample->setLoc(loc); - node = txsample; - - break; - } - - case EOpMethodLoad: - { - TIntermTyped* argTex = argAggregate->getSequence()[0]->getAsTyped(); - TIntermTyped* argCoord = argAggregate->getSequence()[1]->getAsTyped(); - TIntermTyped* argOffset = nullptr; - TIntermTyped* lodComponent = nullptr; - TIntermTyped* coordSwizzle = nullptr; - - const TSampler& sampler = argTex->getType().getSampler(); - const bool isMS = sampler.isMultiSample(); - const bool isBuffer = sampler.dim == EsdBuffer; - const bool isImage = sampler.isImage(); - const TBasicType coordBaseType = argCoord->getType().getBasicType(); - - // Last component of coordinate is the mip level, for non-MS. we separate them here: - if (isMS || isBuffer || isImage) { - // MS, Buffer, and Image have no LOD - coordSwizzle = argCoord; - } else { - // Extract coordinate - int swizzleSize = argCoord->getType().getVectorSize() - (isMS ? 0 : 1); - TSwizzleSelectors coordFields; - for (int i = 0; i < swizzleSize; ++i) - coordFields.push_back(i); - TIntermTyped* coordIdx = intermediate.addSwizzle(coordFields, loc); - coordSwizzle = intermediate.addIndex(EOpVectorSwizzle, argCoord, coordIdx, loc); - coordSwizzle->setType(TType(coordBaseType, EvqTemporary, coordFields.size())); - - // Extract LOD - TIntermTyped* lodIdx = intermediate.addConstantUnion(coordFields.size(), loc, true); - lodComponent = intermediate.addIndex(EOpIndexDirect, argCoord, lodIdx, loc); - lodComponent->setType(TType(coordBaseType, EvqTemporary, 1)); - } - - const int numArgs = (int)argAggregate->getSequence().size(); - const bool hasOffset = ((!isMS && numArgs == 3) || (isMS && numArgs == 4)); - - // Create texel fetch - const TOperator fetchOp = (isImage ? EOpImageLoad : - hasOffset ? EOpTextureFetchOffset : - EOpTextureFetch); - TIntermAggregate* txfetch = new TIntermAggregate(fetchOp); - - // Build up the fetch - txfetch->getSequence().push_back(argTex); - txfetch->getSequence().push_back(coordSwizzle); - - if (isMS) { - // add 2DMS sample index - TIntermTyped* argSampleIdx = argAggregate->getSequence()[2]->getAsTyped(); - txfetch->getSequence().push_back(argSampleIdx); - } else if (isBuffer) { - // Nothing else to do for buffers. - } else if (isImage) { - // Nothing else to do for images. - } else { - // 2DMS and buffer have no LOD, but everything else does. - txfetch->getSequence().push_back(lodComponent); - } - - // Obtain offset arg, if there is one. - if (hasOffset) { - const int offsetPos = (isMS ? 3 : 2); - argOffset = argAggregate->getSequence()[offsetPos]->getAsTyped(); - txfetch->getSequence().push_back(argOffset); - } - - node = convertReturn(txfetch, sampler); - - break; - } - - case EOpMethodSampleLevel: - { - TIntermTyped* argTex = argAggregate->getSequence()[0]->getAsTyped(); - TIntermTyped* argSamp = argAggregate->getSequence()[1]->getAsTyped(); - TIntermTyped* argCoord = argAggregate->getSequence()[2]->getAsTyped(); - TIntermTyped* argLod = argAggregate->getSequence()[3]->getAsTyped(); - TIntermTyped* argOffset = nullptr; - const TSampler& sampler = argTex->getType().getSampler(); - - const int numArgs = (int)argAggregate->getSequence().size(); - - if (numArgs == 5) // offset, if present - argOffset = argAggregate->getSequence()[4]->getAsTyped(); - - const TOperator textureOp = (argOffset == nullptr ? EOpTextureLod : EOpTextureLodOffset); - TIntermAggregate* txsample = new TIntermAggregate(textureOp); - - TIntermAggregate* txcombine = handleSamplerTextureCombine(loc, argTex, argSamp); - - txsample->getSequence().push_back(txcombine); - txsample->getSequence().push_back(argCoord); - txsample->getSequence().push_back(argLod); - - if (argOffset != nullptr) - txsample->getSequence().push_back(argOffset); - - node = convertReturn(txsample, sampler); - - break; - } - - case EOpMethodGather: - { - TIntermTyped* argTex = argAggregate->getSequence()[0]->getAsTyped(); - TIntermTyped* argSamp = argAggregate->getSequence()[1]->getAsTyped(); - TIntermTyped* argCoord = argAggregate->getSequence()[2]->getAsTyped(); - TIntermTyped* argOffset = nullptr; - - // Offset is optional - if (argAggregate->getSequence().size() > 3) - argOffset = argAggregate->getSequence()[3]->getAsTyped(); - - const TOperator textureOp = (argOffset == nullptr ? EOpTextureGather : EOpTextureGatherOffset); - TIntermAggregate* txgather = new TIntermAggregate(textureOp); - - TIntermAggregate* txcombine = handleSamplerTextureCombine(loc, argTex, argSamp); - - txgather->getSequence().push_back(txcombine); - txgather->getSequence().push_back(argCoord); - // Offset if not given is implicitly channel 0 (red) - - if (argOffset != nullptr) - txgather->getSequence().push_back(argOffset); - - txgather->setType(node->getType()); - txgather->setLoc(loc); - node = txgather; - - break; - } - - case EOpMethodGatherRed: // fall through... - case EOpMethodGatherGreen: // ... - case EOpMethodGatherBlue: // ... - case EOpMethodGatherAlpha: // ... - case EOpMethodGatherCmpRed: // ... - case EOpMethodGatherCmpGreen: // ... - case EOpMethodGatherCmpBlue: // ... - case EOpMethodGatherCmpAlpha: // ... - { - int channel = 0; // the channel we are gathering - int cmpValues = 0; // 1 if there is a compare value (handier than a bool below) - - switch (op) { - case EOpMethodGatherCmpRed: cmpValues = 1; // fall through - case EOpMethodGatherRed: channel = 0; break; - case EOpMethodGatherCmpGreen: cmpValues = 1; // fall through - case EOpMethodGatherGreen: channel = 1; break; - case EOpMethodGatherCmpBlue: cmpValues = 1; // fall through - case EOpMethodGatherBlue: channel = 2; break; - case EOpMethodGatherCmpAlpha: cmpValues = 1; // fall through - case EOpMethodGatherAlpha: channel = 3; break; - default: assert(0); break; - } - - // For now, we have nothing to map the component-wise comparison forms - // to, because neither GLSL nor SPIR-V has such an opcode. Issue an - // unimplemented error instead. Most of the machinery is here if that - // should ever become available. However, red can be passed through - // to OpImageDrefGather. G/B/A cannot, because that opcode does not - // accept a component. - if (cmpValues != 0 && op != EOpMethodGatherCmpRed) { - error(loc, "unimplemented: component-level gather compare", "", ""); - return; - } - - int arg = 0; - - TIntermTyped* argTex = argAggregate->getSequence()[arg++]->getAsTyped(); - TIntermTyped* argSamp = argAggregate->getSequence()[arg++]->getAsTyped(); - TIntermTyped* argCoord = argAggregate->getSequence()[arg++]->getAsTyped(); - TIntermTyped* argOffset = nullptr; - TIntermTyped* argOffsets[4] = { nullptr, nullptr, nullptr, nullptr }; - // TIntermTyped* argStatus = nullptr; // TODO: residency - TIntermTyped* argCmp = nullptr; - - const TSamplerDim dim = argTex->getType().getSampler().dim; - - const int argSize = (int)argAggregate->getSequence().size(); - bool hasStatus = (argSize == (5+cmpValues) || argSize == (8+cmpValues)); - bool hasOffset1 = false; - bool hasOffset4 = false; - - // Sampler argument should be a sampler. - if (argSamp->getType().getBasicType() != EbtSampler) { - error(loc, "expected: sampler type", "", ""); - return; - } - - // Cmp forms require SamplerComparisonState - if (cmpValues > 0 && ! argSamp->getType().getSampler().isShadow()) { - error(loc, "expected: SamplerComparisonState", "", ""); - return; - } - - // Only 2D forms can have offsets. Discover if we have 0, 1 or 4 offsets. - if (dim == Esd2D) { - hasOffset1 = (argSize == (4+cmpValues) || argSize == (5+cmpValues)); - hasOffset4 = (argSize == (7+cmpValues) || argSize == (8+cmpValues)); - } - - assert(!(hasOffset1 && hasOffset4)); - - TOperator textureOp = EOpTextureGather; - - // Compare forms have compare value - if (cmpValues != 0) - argCmp = argOffset = argAggregate->getSequence()[arg++]->getAsTyped(); - - // Some forms have single offset - if (hasOffset1) { - textureOp = EOpTextureGatherOffset; // single offset form - argOffset = argAggregate->getSequence()[arg++]->getAsTyped(); - } - - // Some forms have 4 gather offsets - if (hasOffset4) { - textureOp = EOpTextureGatherOffsets; // note plural, for 4 offset form - for (int offsetNum = 0; offsetNum < 4; ++offsetNum) - argOffsets[offsetNum] = argAggregate->getSequence()[arg++]->getAsTyped(); - } - - // Residency status - if (hasStatus) { - // argStatus = argAggregate->getSequence()[arg++]->getAsTyped(); - error(loc, "unimplemented: residency status", "", ""); - return; - } - - TIntermAggregate* txgather = new TIntermAggregate(textureOp); - TIntermAggregate* txcombine = handleSamplerTextureCombine(loc, argTex, argSamp); - - TIntermTyped* argChannel = intermediate.addConstantUnion(channel, loc, true); - - txgather->getSequence().push_back(txcombine); - txgather->getSequence().push_back(argCoord); - - // AST wants an array of 4 offsets, where HLSL has separate args. Here - // we construct an array from the separate args. - if (hasOffset4) { - TType arrayType(EbtInt, EvqTemporary, 2); - TArraySizes* arraySizes = new TArraySizes; - arraySizes->addInnerSize(4); - arrayType.transferArraySizes(arraySizes); - - TIntermAggregate* initList = new TIntermAggregate(EOpNull); - - for (int offsetNum = 0; offsetNum < 4; ++offsetNum) - initList->getSequence().push_back(argOffsets[offsetNum]); - - argOffset = addConstructor(loc, initList, arrayType); - } - - // Add comparison value if we have one - if (argCmp != nullptr) - txgather->getSequence().push_back(argCmp); - - // Add offset (either 1, or an array of 4) if we have one - if (argOffset != nullptr) - txgather->getSequence().push_back(argOffset); - - // Add channel value if the sampler is not shadow - if (! argSamp->getType().getSampler().isShadow()) - txgather->getSequence().push_back(argChannel); - - txgather->setType(node->getType()); - txgather->setLoc(loc); - node = txgather; - - break; - } - - case EOpMethodCalculateLevelOfDetail: - case EOpMethodCalculateLevelOfDetailUnclamped: - { - TIntermTyped* argTex = argAggregate->getSequence()[0]->getAsTyped(); - TIntermTyped* argSamp = argAggregate->getSequence()[1]->getAsTyped(); - TIntermTyped* argCoord = argAggregate->getSequence()[2]->getAsTyped(); - - TIntermAggregate* txquerylod = new TIntermAggregate(EOpTextureQueryLod); - - TIntermAggregate* txcombine = handleSamplerTextureCombine(loc, argTex, argSamp); - txquerylod->getSequence().push_back(txcombine); - txquerylod->getSequence().push_back(argCoord); - - TIntermTyped* lodComponent = intermediate.addConstantUnion(0, loc, true); - TIntermTyped* lodComponentIdx = intermediate.addIndex(EOpIndexDirect, txquerylod, lodComponent, loc); - lodComponentIdx->setType(TType(EbtFloat, EvqTemporary, 1)); - - node = lodComponentIdx; - - // We cannot currently obtain the unclamped LOD - if (op == EOpMethodCalculateLevelOfDetailUnclamped) - error(loc, "unimplemented: CalculateLevelOfDetailUnclamped", "", ""); - - break; - } - - case EOpMethodGetSamplePosition: - { - // TODO: this entire decomposition exists because there is not yet a way to query - // the sample position directly through SPIR-V. Instead, we return fixed sample - // positions for common cases. *** If the sample positions are set differently, - // this will be wrong. *** - - TIntermTyped* argTex = argAggregate->getSequence()[0]->getAsTyped(); - TIntermTyped* argSampIdx = argAggregate->getSequence()[1]->getAsTyped(); - - TIntermAggregate* samplesQuery = new TIntermAggregate(EOpImageQuerySamples); - samplesQuery->getSequence().push_back(argTex); - samplesQuery->setType(TType(EbtUint, EvqTemporary, 1)); - samplesQuery->setLoc(loc); - - TIntermAggregate* compoundStatement = nullptr; - - TVariable* outSampleCount = makeInternalVariable("@sampleCount", TType(EbtUint)); - outSampleCount->getWritableType().getQualifier().makeTemporary(); - TIntermTyped* compAssign = intermediate.addAssign(EOpAssign, intermediate.addSymbol(*outSampleCount, loc), - samplesQuery, loc); - compoundStatement = intermediate.growAggregate(compoundStatement, compAssign); - - TIntermTyped* idxtest[4]; - - // Create tests against 2, 4, 8, and 16 sample values - int count = 0; - for (int val = 2; val <= 16; val *= 2) - idxtest[count++] = - intermediate.addBinaryNode(EOpEqual, - intermediate.addSymbol(*outSampleCount, loc), - intermediate.addConstantUnion(val, loc), - loc, TType(EbtBool)); - - const TOperator idxOp = (argSampIdx->getQualifier().storage == EvqConst) ? EOpIndexDirect : EOpIndexIndirect; - - // Create index ops into position arrays given sample index. - // TODO: should it be clamped? - TIntermTyped* index[4]; - count = 0; - for (int val = 2; val <= 16; val *= 2) { - index[count] = intermediate.addIndex(idxOp, getSamplePosArray(val), argSampIdx, loc); - index[count++]->setType(TType(EbtFloat, EvqTemporary, 2)); - } - - // Create expression as: - // (sampleCount == 2) ? pos2[idx] : - // (sampleCount == 4) ? pos4[idx] : - // (sampleCount == 8) ? pos8[idx] : - // (sampleCount == 16) ? pos16[idx] : float2(0,0); - TIntermTyped* test = - intermediate.addSelection(idxtest[0], index[0], - intermediate.addSelection(idxtest[1], index[1], - intermediate.addSelection(idxtest[2], index[2], - intermediate.addSelection(idxtest[3], index[3], - getSamplePosArray(1), loc), loc), loc), loc); - - compoundStatement = intermediate.growAggregate(compoundStatement, test); - compoundStatement->setOperator(EOpSequence); - compoundStatement->setLoc(loc); - compoundStatement->setType(TType(EbtFloat, EvqTemporary, 2)); - - node = compoundStatement; - - break; - } - - case EOpSubpassLoad: - { - const TIntermTyped* argSubpass = - argAggregate ? argAggregate->getSequence()[0]->getAsTyped() : - arguments->getAsTyped(); - - const TSampler& sampler = argSubpass->getType().getSampler(); - - // subpass load: the multisample form is overloaded. Here, we convert that to - // the EOpSubpassLoadMS opcode. - if (argAggregate != nullptr && argAggregate->getSequence().size() > 1) - node->getAsOperator()->setOp(EOpSubpassLoadMS); - - node = convertReturn(node, sampler); - - break; - } - - - default: - break; // most pass through unchanged - } -} - -// -// Decompose geometry shader methods -// -void HlslParseContext::decomposeGeometryMethods(const TSourceLoc& loc, TIntermTyped*& node, TIntermNode* arguments) -{ - if (node == nullptr || !node->getAsOperator()) - return; - - const TOperator op = node->getAsOperator()->getOp(); - const TIntermAggregate* argAggregate = arguments ? arguments->getAsAggregate() : nullptr; - - switch (op) { - case EOpMethodAppend: - if (argAggregate) { - // Don't emit these for non-GS stage, since we won't have the gsStreamOutput symbol. - if (language != EShLangGeometry) { - node = nullptr; - return; - } - - TIntermAggregate* sequence = nullptr; - TIntermAggregate* emit = new TIntermAggregate(EOpEmitVertex); - - emit->setLoc(loc); - emit->setType(TType(EbtVoid)); - - // find the matching output - if (gsStreamOutput == nullptr) { - error(loc, "unable to find output symbol for Append()", "", ""); - return; - } - - sequence = intermediate.growAggregate(sequence, - handleAssign(loc, EOpAssign, - intermediate.addSymbol(*gsStreamOutput, loc), - argAggregate->getSequence()[1]->getAsTyped()), - loc); - - sequence = intermediate.growAggregate(sequence, emit); - - sequence->setOperator(EOpSequence); - sequence->setLoc(loc); - sequence->setType(TType(EbtVoid)); - node = sequence; - } - break; - - case EOpMethodRestartStrip: - { - // Don't emit these for non-GS stage, since we won't have the gsStreamOutput symbol. - if (language != EShLangGeometry) { - node = nullptr; - return; - } - - TIntermAggregate* cut = new TIntermAggregate(EOpEndPrimitive); - cut->setLoc(loc); - cut->setType(TType(EbtVoid)); - node = cut; - } - break; - - default: - break; // most pass through unchanged - } -} - -// -// Optionally decompose intrinsics to AST opcodes. -// -void HlslParseContext::decomposeIntrinsic(const TSourceLoc& loc, TIntermTyped*& node, TIntermNode* arguments) -{ - // Helper to find image data for image atomics: - // OpImageLoad(image[idx]) - // We take the image load apart and add its params to the atomic op aggregate node - const auto imageAtomicParams = [this, &loc, &node](TIntermAggregate* atomic, TIntermTyped* load) { - TIntermAggregate* loadOp = load->getAsAggregate(); - if (loadOp == nullptr) { - error(loc, "unknown image type in atomic operation", "", ""); - node = nullptr; - return; - } - - atomic->getSequence().push_back(loadOp->getSequence()[0]); - atomic->getSequence().push_back(loadOp->getSequence()[1]); - }; - - // Return true if this is an imageLoad, which we will change to an image atomic. - const auto isImageParam = [](TIntermTyped* image) -> bool { - TIntermAggregate* imageAggregate = image->getAsAggregate(); - return imageAggregate != nullptr && imageAggregate->getOp() == EOpImageLoad; - }; - - const auto lookupBuiltinVariable = [&](const char* name, TBuiltInVariable builtin, TType& type) -> TIntermTyped* { - TSymbol* symbol = symbolTable.find(name); - if (nullptr == symbol) { - type.getQualifier().builtIn = builtin; - - TVariable* variable = new TVariable(new TString(name), type); - - symbolTable.insert(*variable); - - symbol = symbolTable.find(name); - assert(symbol && "Inserted symbol could not be found!"); - } - - return intermediate.addSymbol(*(symbol->getAsVariable()), loc); - }; - - // HLSL intrinsics can be pass through to native AST opcodes, or decomposed here to existing AST - // opcodes for compatibility with existing software stacks. - static const bool decomposeHlslIntrinsics = true; - - if (!decomposeHlslIntrinsics || !node || !node->getAsOperator()) - return; - - const TIntermAggregate* argAggregate = arguments ? arguments->getAsAggregate() : nullptr; - TIntermUnary* fnUnary = node->getAsUnaryNode(); - const TOperator op = node->getAsOperator()->getOp(); - - switch (op) { - case EOpGenMul: - { - // mul(a,b) -> MatrixTimesMatrix, MatrixTimesVector, MatrixTimesScalar, VectorTimesScalar, Dot, Mul - // Since we are treating HLSL rows like GLSL columns (the first matrix indirection), - // we must reverse the operand order here. Hence, arg0 gets sequence[1], etc. - TIntermTyped* arg0 = argAggregate->getSequence()[1]->getAsTyped(); - TIntermTyped* arg1 = argAggregate->getSequence()[0]->getAsTyped(); - - if (arg0->isVector() && arg1->isVector()) { // vec * vec - node->getAsAggregate()->setOperator(EOpDot); - } else { - node = handleBinaryMath(loc, "mul", EOpMul, arg0, arg1); - } - - break; - } - - case EOpRcp: - { - // rcp(a) -> 1 / a - TIntermTyped* arg0 = fnUnary->getOperand(); - TBasicType type0 = arg0->getBasicType(); - TIntermTyped* one = intermediate.addConstantUnion(1, type0, loc, true); - node = handleBinaryMath(loc, "rcp", EOpDiv, one, arg0); - - break; - } - - case EOpAny: // fall through - case EOpAll: - { - TIntermTyped* typedArg = arguments->getAsTyped(); - - // HLSL allows float/etc types here, and the SPIR-V opcode requires a bool. - // We'll convert here. Note that for efficiency, we could add a smarter - // decomposition for some type cases, e.g, maybe by decomposing a dot product. - if (typedArg->getType().getBasicType() != EbtBool) { - const TType boolType(EbtBool, EvqTemporary, - typedArg->getVectorSize(), - typedArg->getMatrixCols(), - typedArg->getMatrixRows(), - typedArg->isVector()); - - typedArg = intermediate.addConversion(EOpConstructBool, boolType, typedArg); - node->getAsUnaryNode()->setOperand(typedArg); - } - - break; - } - - case EOpSaturate: - { - // saturate(a) -> clamp(a,0,1) - TIntermTyped* arg0 = fnUnary->getOperand(); - TBasicType type0 = arg0->getBasicType(); - TIntermAggregate* clamp = new TIntermAggregate(EOpClamp); - - clamp->getSequence().push_back(arg0); - clamp->getSequence().push_back(intermediate.addConstantUnion(0, type0, loc, true)); - clamp->getSequence().push_back(intermediate.addConstantUnion(1, type0, loc, true)); - clamp->setLoc(loc); - clamp->setType(node->getType()); - clamp->getWritableType().getQualifier().makeTemporary(); - node = clamp; - - break; - } - - case EOpSinCos: - { - // sincos(a,b,c) -> b = sin(a), c = cos(a) - TIntermTyped* arg0 = argAggregate->getSequence()[0]->getAsTyped(); - TIntermTyped* arg1 = argAggregate->getSequence()[1]->getAsTyped(); - TIntermTyped* arg2 = argAggregate->getSequence()[2]->getAsTyped(); - - TIntermTyped* sinStatement = handleUnaryMath(loc, "sin", EOpSin, arg0); - TIntermTyped* cosStatement = handleUnaryMath(loc, "cos", EOpCos, arg0); - TIntermTyped* sinAssign = intermediate.addAssign(EOpAssign, arg1, sinStatement, loc); - TIntermTyped* cosAssign = intermediate.addAssign(EOpAssign, arg2, cosStatement, loc); - - TIntermAggregate* compoundStatement = intermediate.makeAggregate(sinAssign, loc); - compoundStatement = intermediate.growAggregate(compoundStatement, cosAssign); - compoundStatement->setOperator(EOpSequence); - compoundStatement->setLoc(loc); - compoundStatement->setType(TType(EbtVoid)); - - node = compoundStatement; - - break; - } - - case EOpClip: - { - // clip(a) -> if (any(a<0)) discard; - TIntermTyped* arg0 = fnUnary->getOperand(); - TBasicType type0 = arg0->getBasicType(); - TIntermTyped* compareNode = nullptr; - - // For non-scalars: per experiment with FXC compiler, discard if any component < 0. - if (!arg0->isScalar()) { - // component-wise compare: a < 0 - TIntermAggregate* less = new TIntermAggregate(EOpLessThan); - less->getSequence().push_back(arg0); - less->setLoc(loc); - - // make vec or mat of bool matching dimensions of input - less->setType(TType(EbtBool, EvqTemporary, - arg0->getType().getVectorSize(), - arg0->getType().getMatrixCols(), - arg0->getType().getMatrixRows(), - arg0->getType().isVector())); - - // calculate # of components for comparison const - const int constComponentCount = - std::max(arg0->getType().getVectorSize(), 1) * - std::max(arg0->getType().getMatrixCols(), 1) * - std::max(arg0->getType().getMatrixRows(), 1); - - TConstUnion zero; - if (arg0->getType().isIntegerDomain()) - zero.setDConst(0); - else - zero.setDConst(0.0); - TConstUnionArray zeros(constComponentCount, zero); - - less->getSequence().push_back(intermediate.addConstantUnion(zeros, arg0->getType(), loc, true)); - - compareNode = intermediate.addBuiltInFunctionCall(loc, EOpAny, true, less, TType(EbtBool)); - } else { - TIntermTyped* zero; - if (arg0->getType().isIntegerDomain()) - zero = intermediate.addConstantUnion(0, loc, true); - else - zero = intermediate.addConstantUnion(0.0, type0, loc, true); - compareNode = handleBinaryMath(loc, "clip", EOpLessThan, arg0, zero); - } - - TIntermBranch* killNode = intermediate.addBranch(EOpKill, loc); - - node = new TIntermSelection(compareNode, killNode, nullptr); - node->setLoc(loc); - - break; - } - - case EOpLog10: - { - // log10(a) -> log2(a) * 0.301029995663981 (== 1/log2(10)) - TIntermTyped* arg0 = fnUnary->getOperand(); - TIntermTyped* log2 = handleUnaryMath(loc, "log2", EOpLog2, arg0); - TIntermTyped* base = intermediate.addConstantUnion(0.301029995663981f, EbtFloat, loc, true); - - node = handleBinaryMath(loc, "mul", EOpMul, log2, base); - - break; - } - - case EOpDst: - { - // dest.x = 1; - // dest.y = src0.y * src1.y; - // dest.z = src0.z; - // dest.w = src1.w; - - TIntermTyped* arg0 = argAggregate->getSequence()[0]->getAsTyped(); - TIntermTyped* arg1 = argAggregate->getSequence()[1]->getAsTyped(); - - TIntermTyped* y = intermediate.addConstantUnion(1, loc, true); - TIntermTyped* z = intermediate.addConstantUnion(2, loc, true); - TIntermTyped* w = intermediate.addConstantUnion(3, loc, true); - - TIntermTyped* src0y = intermediate.addIndex(EOpIndexDirect, arg0, y, loc); - TIntermTyped* src1y = intermediate.addIndex(EOpIndexDirect, arg1, y, loc); - TIntermTyped* src0z = intermediate.addIndex(EOpIndexDirect, arg0, z, loc); - TIntermTyped* src1w = intermediate.addIndex(EOpIndexDirect, arg1, w, loc); - - TIntermAggregate* dst = new TIntermAggregate(EOpConstructVec4); - - dst->getSequence().push_back(intermediate.addConstantUnion(1.0, EbtFloat, loc, true)); - dst->getSequence().push_back(handleBinaryMath(loc, "mul", EOpMul, src0y, src1y)); - dst->getSequence().push_back(src0z); - dst->getSequence().push_back(src1w); - dst->setType(TType(EbtFloat, EvqTemporary, 4)); - dst->setLoc(loc); - node = dst; - - break; - } - - case EOpInterlockedAdd: // optional last argument (if present) is assigned from return value - case EOpInterlockedMin: // ... - case EOpInterlockedMax: // ... - case EOpInterlockedAnd: // ... - case EOpInterlockedOr: // ... - case EOpInterlockedXor: // ... - case EOpInterlockedExchange: // always has output arg - { - TIntermTyped* arg0 = argAggregate->getSequence()[0]->getAsTyped(); // dest - TIntermTyped* arg1 = argAggregate->getSequence()[1]->getAsTyped(); // value - TIntermTyped* arg2 = nullptr; - - if (argAggregate->getSequence().size() > 2) - arg2 = argAggregate->getSequence()[2]->getAsTyped(); - - const bool isImage = isImageParam(arg0); - const TOperator atomicOp = mapAtomicOp(loc, op, isImage); - TIntermAggregate* atomic = new TIntermAggregate(atomicOp); - atomic->setType(arg0->getType()); - atomic->getWritableType().getQualifier().makeTemporary(); - atomic->setLoc(loc); - - if (isImage) { - // orig_value = imageAtomicOp(image, loc, data) - imageAtomicParams(atomic, arg0); - atomic->getSequence().push_back(arg1); - - if (argAggregate->getSequence().size() > 2) { - node = intermediate.addAssign(EOpAssign, arg2, atomic, loc); - } else { - node = atomic; // no assignment needed, as there was no out var. - } - } else { - // Normal memory variable: - // arg0 = mem, arg1 = data, arg2(optional,out) = orig_value - if (argAggregate->getSequence().size() > 2) { - // optional output param is present. return value goes to arg2. - atomic->getSequence().push_back(arg0); - atomic->getSequence().push_back(arg1); - - node = intermediate.addAssign(EOpAssign, arg2, atomic, loc); - } else { - // Set the matching operator. Since output is absent, this is all we need to do. - node->getAsAggregate()->setOperator(atomicOp); - node->setType(atomic->getType()); - } - } - - break; - } - - case EOpInterlockedCompareExchange: - { - TIntermTyped* arg0 = argAggregate->getSequence()[0]->getAsTyped(); // dest - TIntermTyped* arg1 = argAggregate->getSequence()[1]->getAsTyped(); // cmp - TIntermTyped* arg2 = argAggregate->getSequence()[2]->getAsTyped(); // value - TIntermTyped* arg3 = argAggregate->getSequence()[3]->getAsTyped(); // orig - - const bool isImage = isImageParam(arg0); - TIntermAggregate* atomic = new TIntermAggregate(mapAtomicOp(loc, op, isImage)); - atomic->setLoc(loc); - atomic->setType(arg2->getType()); - atomic->getWritableType().getQualifier().makeTemporary(); - - if (isImage) { - imageAtomicParams(atomic, arg0); - } else { - atomic->getSequence().push_back(arg0); - } - - atomic->getSequence().push_back(arg1); - atomic->getSequence().push_back(arg2); - node = intermediate.addAssign(EOpAssign, arg3, atomic, loc); - - break; - } - - case EOpEvaluateAttributeSnapped: - { - // SPIR-V InterpolateAtOffset uses float vec2 offset in pixels - // HLSL uses int2 offset on a 16x16 grid in [-8..7] on x & y: - // iU = (iU<<28)>>28 - // fU = ((float)iU)/16 - // Targets might handle this natively, in which case they can disable - // decompositions. - - TIntermTyped* arg0 = argAggregate->getSequence()[0]->getAsTyped(); // value - TIntermTyped* arg1 = argAggregate->getSequence()[1]->getAsTyped(); // offset - - TIntermTyped* i28 = intermediate.addConstantUnion(28, loc, true); - TIntermTyped* iU = handleBinaryMath(loc, ">>", EOpRightShift, - handleBinaryMath(loc, "<<", EOpLeftShift, arg1, i28), - i28); - - TIntermTyped* recip16 = intermediate.addConstantUnion((1.0/16.0), EbtFloat, loc, true); - TIntermTyped* floatOffset = handleBinaryMath(loc, "mul", EOpMul, - intermediate.addConversion(EOpConstructFloat, - TType(EbtFloat, EvqTemporary, 2), iU), - recip16); - - TIntermAggregate* interp = new TIntermAggregate(EOpInterpolateAtOffset); - interp->getSequence().push_back(arg0); - interp->getSequence().push_back(floatOffset); - interp->setLoc(loc); - interp->setType(arg0->getType()); - interp->getWritableType().getQualifier().makeTemporary(); - - node = interp; - - break; - } - - case EOpLit: - { - TIntermTyped* n_dot_l = argAggregate->getSequence()[0]->getAsTyped(); - TIntermTyped* n_dot_h = argAggregate->getSequence()[1]->getAsTyped(); - TIntermTyped* m = argAggregate->getSequence()[2]->getAsTyped(); - - TIntermAggregate* dst = new TIntermAggregate(EOpConstructVec4); - - // Ambient - dst->getSequence().push_back(intermediate.addConstantUnion(1.0, EbtFloat, loc, true)); - - // Diffuse: - TIntermTyped* zero = intermediate.addConstantUnion(0.0, EbtFloat, loc, true); - TIntermAggregate* diffuse = new TIntermAggregate(EOpMax); - diffuse->getSequence().push_back(n_dot_l); - diffuse->getSequence().push_back(zero); - diffuse->setLoc(loc); - diffuse->setType(TType(EbtFloat)); - dst->getSequence().push_back(diffuse); - - // Specular: - TIntermAggregate* min_ndot = new TIntermAggregate(EOpMin); - min_ndot->getSequence().push_back(n_dot_l); - min_ndot->getSequence().push_back(n_dot_h); - min_ndot->setLoc(loc); - min_ndot->setType(TType(EbtFloat)); - - TIntermTyped* compare = handleBinaryMath(loc, "<", EOpLessThan, min_ndot, zero); - TIntermTyped* n_dot_h_m = handleBinaryMath(loc, "mul", EOpMul, n_dot_h, m); // n_dot_h * m - - dst->getSequence().push_back(intermediate.addSelection(compare, zero, n_dot_h_m, loc)); - - // One: - dst->getSequence().push_back(intermediate.addConstantUnion(1.0, EbtFloat, loc, true)); - - dst->setLoc(loc); - dst->setType(TType(EbtFloat, EvqTemporary, 4)); - node = dst; - break; - } - - case EOpAsDouble: - { - // asdouble accepts two 32 bit ints. we can use EOpUint64BitsToDouble, but must - // first construct a uint64. - TIntermTyped* arg0 = argAggregate->getSequence()[0]->getAsTyped(); - TIntermTyped* arg1 = argAggregate->getSequence()[1]->getAsTyped(); - - if (arg0->getType().isVector()) { // TODO: ... - error(loc, "double2 conversion not implemented", "asdouble", ""); - break; - } - - TIntermAggregate* uint64 = new TIntermAggregate(EOpConstructUVec2); - - uint64->getSequence().push_back(arg0); - uint64->getSequence().push_back(arg1); - uint64->setType(TType(EbtUint, EvqTemporary, 2)); // convert 2 uints to a uint2 - uint64->setLoc(loc); - - // bitcast uint2 to a double - TIntermTyped* convert = new TIntermUnary(EOpUint64BitsToDouble); - convert->getAsUnaryNode()->setOperand(uint64); - convert->setLoc(loc); - convert->setType(TType(EbtDouble, EvqTemporary)); - node = convert; - - break; - } - - case EOpF16tof32: - { - // input uvecN with low 16 bits of each component holding a float16. convert to float32. - TIntermTyped* argValue = node->getAsUnaryNode()->getOperand(); - TIntermTyped* zero = intermediate.addConstantUnion(0, loc, true); - const int vecSize = argValue->getType().getVectorSize(); - - TOperator constructOp = EOpNull; - switch (vecSize) { - case 1: constructOp = EOpNull; break; // direct use, no construct needed - case 2: constructOp = EOpConstructVec2; break; - case 3: constructOp = EOpConstructVec3; break; - case 4: constructOp = EOpConstructVec4; break; - default: assert(0); break; - } - - // For scalar case, we don't need to construct another type. - TIntermAggregate* result = (vecSize > 1) ? new TIntermAggregate(constructOp) : nullptr; - - if (result) { - result->setType(TType(EbtFloat, EvqTemporary, vecSize)); - result->setLoc(loc); - } - - for (int idx = 0; idx < vecSize; ++idx) { - TIntermTyped* idxConst = intermediate.addConstantUnion(idx, loc, true); - TIntermTyped* component = argValue->getType().isVector() ? - intermediate.addIndex(EOpIndexDirect, argValue, idxConst, loc) : argValue; - - if (component != argValue) - component->setType(TType(argValue->getBasicType(), EvqTemporary)); - - TIntermTyped* unpackOp = new TIntermUnary(EOpUnpackHalf2x16); - unpackOp->setType(TType(EbtFloat, EvqTemporary, 2)); - unpackOp->getAsUnaryNode()->setOperand(component); - unpackOp->setLoc(loc); - - TIntermTyped* lowOrder = intermediate.addIndex(EOpIndexDirect, unpackOp, zero, loc); - - if (result != nullptr) { - result->getSequence().push_back(lowOrder); - node = result; - } else { - node = lowOrder; - } - } - - break; - } - - case EOpF32tof16: - { - // input floatN converted to 16 bit float in low order bits of each component of uintN - TIntermTyped* argValue = node->getAsUnaryNode()->getOperand(); - - TIntermTyped* zero = intermediate.addConstantUnion(0.0, EbtFloat, loc, true); - const int vecSize = argValue->getType().getVectorSize(); - - TOperator constructOp = EOpNull; - switch (vecSize) { - case 1: constructOp = EOpNull; break; // direct use, no construct needed - case 2: constructOp = EOpConstructUVec2; break; - case 3: constructOp = EOpConstructUVec3; break; - case 4: constructOp = EOpConstructUVec4; break; - default: assert(0); break; - } - - // For scalar case, we don't need to construct another type. - TIntermAggregate* result = (vecSize > 1) ? new TIntermAggregate(constructOp) : nullptr; - - if (result) { - result->setType(TType(EbtUint, EvqTemporary, vecSize)); - result->setLoc(loc); - } - - for (int idx = 0; idx < vecSize; ++idx) { - TIntermTyped* idxConst = intermediate.addConstantUnion(idx, loc, true); - TIntermTyped* component = argValue->getType().isVector() ? - intermediate.addIndex(EOpIndexDirect, argValue, idxConst, loc) : argValue; - - if (component != argValue) - component->setType(TType(argValue->getBasicType(), EvqTemporary)); - - TIntermAggregate* vec2ComponentAndZero = new TIntermAggregate(EOpConstructVec2); - vec2ComponentAndZero->getSequence().push_back(component); - vec2ComponentAndZero->getSequence().push_back(zero); - vec2ComponentAndZero->setType(TType(EbtFloat, EvqTemporary, 2)); - vec2ComponentAndZero->setLoc(loc); - - TIntermTyped* packOp = new TIntermUnary(EOpPackHalf2x16); - packOp->getAsUnaryNode()->setOperand(vec2ComponentAndZero); - packOp->setLoc(loc); - packOp->setType(TType(EbtUint, EvqTemporary)); - - if (result != nullptr) { - result->getSequence().push_back(packOp); - node = result; - } else { - node = packOp; - } - } - - break; - } - - case EOpD3DCOLORtoUBYTE4: - { - // ivec4 ( x.zyxw * 255.001953 ); - TIntermTyped* arg0 = node->getAsUnaryNode()->getOperand(); - TSwizzleSelectors selectors; - selectors.push_back(2); - selectors.push_back(1); - selectors.push_back(0); - selectors.push_back(3); - TIntermTyped* swizzleIdx = intermediate.addSwizzle(selectors, loc); - TIntermTyped* swizzled = intermediate.addIndex(EOpVectorSwizzle, arg0, swizzleIdx, loc); - swizzled->setType(arg0->getType()); - swizzled->getWritableType().getQualifier().makeTemporary(); - - TIntermTyped* conversion = intermediate.addConstantUnion(255.001953f, EbtFloat, loc, true); - TIntermTyped* rangeConverted = handleBinaryMath(loc, "mul", EOpMul, conversion, swizzled); - rangeConverted->setType(arg0->getType()); - rangeConverted->getWritableType().getQualifier().makeTemporary(); - - node = intermediate.addConversion(EOpConstructInt, TType(EbtInt, EvqTemporary, 4), rangeConverted); - node->setLoc(loc); - node->setType(TType(EbtInt, EvqTemporary, 4)); - break; - } - - case EOpIsFinite: - { - // Since OPIsFinite in SPIR-V is only supported with the Kernel capability, we translate - // it to !isnan && !isinf - - TIntermTyped* arg0 = node->getAsUnaryNode()->getOperand(); - - // We'll make a temporary in case the RHS is cmoplex - TVariable* tempArg = makeInternalVariable("@finitetmp", arg0->getType()); - tempArg->getWritableType().getQualifier().makeTemporary(); - - TIntermTyped* tmpArgAssign = intermediate.addAssign(EOpAssign, - intermediate.addSymbol(*tempArg, loc), - arg0, loc); - - TIntermAggregate* compoundStatement = intermediate.makeAggregate(tmpArgAssign, loc); - - const TType boolType(EbtBool, EvqTemporary, arg0->getVectorSize(), arg0->getMatrixCols(), - arg0->getMatrixRows()); - - TIntermTyped* isnan = handleUnaryMath(loc, "isnan", EOpIsNan, intermediate.addSymbol(*tempArg, loc)); - isnan->setType(boolType); - - TIntermTyped* notnan = handleUnaryMath(loc, "!", EOpLogicalNot, isnan); - notnan->setType(boolType); - - TIntermTyped* isinf = handleUnaryMath(loc, "isinf", EOpIsInf, intermediate.addSymbol(*tempArg, loc)); - isinf->setType(boolType); - - TIntermTyped* notinf = handleUnaryMath(loc, "!", EOpLogicalNot, isinf); - notinf->setType(boolType); - - TIntermTyped* andNode = handleBinaryMath(loc, "and", EOpLogicalAnd, notnan, notinf); - andNode->setType(boolType); - - compoundStatement = intermediate.growAggregate(compoundStatement, andNode); - compoundStatement->setOperator(EOpSequence); - compoundStatement->setLoc(loc); - compoundStatement->setType(boolType); - - node = compoundStatement; - - break; - } - case EOpWaveGetLaneCount: - { - // Mapped to gl_SubgroupSize builtin (We preprend @ to the symbol - // so that it inhabits the symbol table, but has a user-invalid name - // in-case some source HLSL defined the symbol also). - TType type(EbtUint, EvqVaryingIn); - node = lookupBuiltinVariable("@gl_SubgroupSize", EbvSubgroupSize2, type); - break; - } - case EOpWaveGetLaneIndex: - { - // Mapped to gl_SubgroupInvocationID builtin (We preprend @ to the - // symbol so that it inhabits the symbol table, but has a - // user-invalid name in-case some source HLSL defined the symbol - // also). - TType type(EbtUint, EvqVaryingIn); - node = lookupBuiltinVariable("@gl_SubgroupInvocationID", EbvSubgroupInvocation2, type); - break; - } - case EOpWaveActiveCountBits: - { - // Mapped to subgroupBallotBitCount(subgroupBallot()) builtin - - // uvec4 type. - TType uvec4Type(EbtUint, EvqTemporary, 4); - - // Get the uvec4 return from subgroupBallot(). - TIntermTyped* res = intermediate.addBuiltInFunctionCall(loc, - EOpSubgroupBallot, true, arguments, uvec4Type); - - // uint type. - TType uintType(EbtUint, EvqTemporary); - - node = intermediate.addBuiltInFunctionCall(loc, - EOpSubgroupBallotBitCount, true, res, uintType); - - break; - } - case EOpWavePrefixCountBits: - { - // Mapped to subgroupBallotInclusiveBitCount(subgroupBallot()) - // builtin - - // uvec4 type. - TType uvec4Type(EbtUint, EvqTemporary, 4); - - // Get the uvec4 return from subgroupBallot(). - TIntermTyped* res = intermediate.addBuiltInFunctionCall(loc, - EOpSubgroupBallot, true, arguments, uvec4Type); - - // uint type. - TType uintType(EbtUint, EvqTemporary); - - node = intermediate.addBuiltInFunctionCall(loc, - EOpSubgroupBallotInclusiveBitCount, true, res, uintType); - - break; - } - - default: - break; // most pass through unchanged - } -} - -// -// Handle seeing function call syntax in the grammar, which could be any of -// - .length() method -// - constructor -// - a call to a built-in function mapped to an operator -// - a call to a built-in function that will remain a function call (e.g., texturing) -// - user function -// - subroutine call (not implemented yet) -// -TIntermTyped* HlslParseContext::handleFunctionCall(const TSourceLoc& loc, TFunction* function, TIntermTyped* arguments) -{ - TIntermTyped* result = nullptr; - - TOperator op = function->getBuiltInOp(); - if (op != EOpNull) { - // - // Then this should be a constructor. - // Don't go through the symbol table for constructors. - // Their parameters will be verified algorithmically. - // - TType type(EbtVoid); // use this to get the type back - if (! constructorError(loc, arguments, *function, op, type)) { - // - // It's a constructor, of type 'type'. - // - result = handleConstructor(loc, arguments, type); - if (result == nullptr) { - error(loc, "cannot construct with these arguments", type.getCompleteString().c_str(), ""); - return nullptr; - } - } - } else { - // - // Find it in the symbol table. - // - const TFunction* fnCandidate = nullptr; - bool builtIn = false; - int thisDepth = 0; - - // For mat mul, the situation is unusual: we have to compare vector sizes to mat row or col sizes, - // and clamp the opposite arg. Since that's complex, we farm it off to a separate method. - // It doesn't naturally fall out of processing an argument at a time in isolation. - if (function->getName() == "mul") - addGenMulArgumentConversion(loc, *function, arguments); - - TIntermAggregate* aggregate = arguments ? arguments->getAsAggregate() : nullptr; - - // TODO: this needs improvement: there's no way at present to look up a signature in - // the symbol table for an arbitrary type. This is a temporary hack until that ability exists. - // It will have false positives, since it doesn't check arg counts or types. - if (arguments) { - // Check if first argument is struct buffer type. It may be an aggregate or a symbol, so we - // look for either case. - - TIntermTyped* arg0 = nullptr; - - if (aggregate && aggregate->getSequence().size() > 0) - arg0 = aggregate->getSequence()[0]->getAsTyped(); - else if (arguments->getAsSymbolNode()) - arg0 = arguments->getAsSymbolNode(); - - if (arg0 != nullptr && isStructBufferType(arg0->getType())) { - static const int methodPrefixSize = sizeof(BUILTIN_PREFIX)-1; - - if (function->getName().length() > methodPrefixSize && - isStructBufferMethod(function->getName().substr(methodPrefixSize))) { - const TString mangle = function->getName() + "("; - TSymbol* symbol = symbolTable.find(mangle, &builtIn); - - if (symbol) - fnCandidate = symbol->getAsFunction(); - } - } - } - - if (fnCandidate == nullptr) - fnCandidate = findFunction(loc, *function, builtIn, thisDepth, arguments); - - if (fnCandidate) { - // This is a declared function that might map to - // - a built-in operator, - // - a built-in function not mapped to an operator, or - // - a user function. - - // Error check for a function requiring specific extensions present. - if (builtIn && fnCandidate->getNumExtensions()) - requireExtensions(loc, fnCandidate->getNumExtensions(), fnCandidate->getExtensions(), - fnCandidate->getName().c_str()); - - // turn an implicit member-function resolution into an explicit call - TString callerName; - if (thisDepth == 0) - callerName = fnCandidate->getMangledName(); - else { - // get the explicit (full) name of the function - callerName = currentTypePrefix[currentTypePrefix.size() - thisDepth]; - callerName += fnCandidate->getMangledName(); - // insert the implicit calling argument - pushFrontArguments(intermediate.addSymbol(*getImplicitThis(thisDepth)), arguments); - } - - // Convert 'in' arguments, so that types match. - // However, skip those that need expansion, that is covered next. - if (arguments) - addInputArgumentConversions(*fnCandidate, arguments); - - // Expand arguments. Some arguments must physically expand to a different set - // than what the shader declared and passes. - if (arguments && !builtIn) - expandArguments(loc, *fnCandidate, arguments); - - // Expansion may have changed the form of arguments - aggregate = arguments ? arguments->getAsAggregate() : nullptr; - - op = fnCandidate->getBuiltInOp(); - if (builtIn && op != EOpNull) { - // A function call mapped to a built-in operation. - result = intermediate.addBuiltInFunctionCall(loc, op, fnCandidate->getParamCount() == 1, arguments, - fnCandidate->getType()); - if (result == nullptr) { - error(arguments->getLoc(), " wrong operand type", "Internal Error", - "built in unary operator function. Type: %s", - static_cast(arguments)->getCompleteString().c_str()); - } else if (result->getAsOperator()) { - builtInOpCheck(loc, *fnCandidate, *result->getAsOperator()); - } - } else { - // This is a function call not mapped to built-in operator. - // It could still be a built-in function, but only if PureOperatorBuiltins == false. - result = intermediate.setAggregateOperator(arguments, EOpFunctionCall, fnCandidate->getType(), loc); - TIntermAggregate* call = result->getAsAggregate(); - call->setName(callerName); - - // this is how we know whether the given function is a built-in function or a user-defined function - // if builtIn == false, it's a userDefined -> could be an overloaded built-in function also - // if builtIn == true, it's definitely a built-in function with EOpNull - if (! builtIn) { - call->setUserDefined(); - intermediate.addToCallGraph(infoSink, currentCaller, callerName); - } - } - - // for decompositions, since we want to operate on the function node, not the aggregate holding - // output conversions. - const TIntermTyped* fnNode = result; - - decomposeStructBufferMethods(loc, result, arguments); // HLSL->AST struct buffer method decompositions - decomposeIntrinsic(loc, result, arguments); // HLSL->AST intrinsic decompositions - decomposeSampleMethods(loc, result, arguments); // HLSL->AST sample method decompositions - decomposeGeometryMethods(loc, result, arguments); // HLSL->AST geometry method decompositions - - // Create the qualifier list, carried in the AST for the call. - // Because some arguments expand to multiple arguments, the qualifier list will - // be longer than the formal parameter list. - if (result == fnNode && result->getAsAggregate()) { - TQualifierList& qualifierList = result->getAsAggregate()->getQualifierList(); - for (int i = 0; i < fnCandidate->getParamCount(); ++i) { - TStorageQualifier qual = (*fnCandidate)[i].type->getQualifier().storage; - if (hasStructBuffCounter(*(*fnCandidate)[i].type)) { - // add buffer and counter buffer argument qualifier - qualifierList.push_back(qual); - qualifierList.push_back(qual); - } else if (shouldFlatten(*(*fnCandidate)[i].type, (*fnCandidate)[i].type->getQualifier().storage, - true)) { - // add structure member expansion - for (int memb = 0; memb < (int)(*fnCandidate)[i].type->getStruct()->size(); ++memb) - qualifierList.push_back(qual); - } else { - // Normal 1:1 case - qualifierList.push_back(qual); - } - } - } - - // Convert 'out' arguments. If it was a constant folded built-in, it won't be an aggregate anymore. - // Built-ins with a single argument aren't called with an aggregate, but they also don't have an output. - // Also, build the qualifier list for user function calls, which are always called with an aggregate. - // We don't do this is if there has been a decomposition, which will have added its own conversions - // for output parameters. - if (result == fnNode && result->getAsAggregate()) - result = addOutputArgumentConversions(*fnCandidate, *result->getAsOperator()); - } - } - - // generic error recovery - // TODO: simplification: localize all the error recoveries that look like this, and taking type into account to - // reduce cascades - if (result == nullptr) - result = intermediate.addConstantUnion(0.0, EbtFloat, loc); - - return result; -} - -// An initial argument list is difficult: it can be null, or a single node, -// or an aggregate if more than one argument. Add one to the front, maintaining -// this lack of uniformity. -void HlslParseContext::pushFrontArguments(TIntermTyped* front, TIntermTyped*& arguments) -{ - if (arguments == nullptr) - arguments = front; - else if (arguments->getAsAggregate() != nullptr) - arguments->getAsAggregate()->getSequence().insert(arguments->getAsAggregate()->getSequence().begin(), front); - else - arguments = intermediate.growAggregate(front, arguments); -} - -// -// HLSL allows mismatched dimensions on vec*mat, mat*vec, vec*vec, and mat*mat. This is a -// situation not well suited to resolution in intrinsic selection, but we can do so here, since we -// can look at both arguments insert explicit shape changes if required. -// -void HlslParseContext::addGenMulArgumentConversion(const TSourceLoc& loc, TFunction& call, TIntermTyped*& args) -{ - TIntermAggregate* argAggregate = args ? args->getAsAggregate() : nullptr; - - if (argAggregate == nullptr || argAggregate->getSequence().size() != 2) { - // It really ought to have two arguments. - error(loc, "expected: mul arguments", "", ""); - return; - } - - TIntermTyped* arg0 = argAggregate->getSequence()[0]->getAsTyped(); - TIntermTyped* arg1 = argAggregate->getSequence()[1]->getAsTyped(); - - if (arg0->isVector() && arg1->isVector()) { - // For: - // vec * vec: it's handled during intrinsic selection, so while we could do it here, - // we can also ignore it, which is easier. - } else if (arg0->isVector() && arg1->isMatrix()) { - // vec * mat: we clamp the vec if the mat col is smaller, else clamp the mat col. - if (arg0->getVectorSize() < arg1->getMatrixCols()) { - // vec is smaller, so truncate larger mat dimension - const TType truncType(arg1->getBasicType(), arg1->getQualifier().storage, arg1->getQualifier().precision, - 0, arg0->getVectorSize(), arg1->getMatrixRows()); - arg1 = addConstructor(loc, arg1, truncType); - } else if (arg0->getVectorSize() > arg1->getMatrixCols()) { - // vec is larger, so truncate vec to mat size - const TType truncType(arg0->getBasicType(), arg0->getQualifier().storage, arg0->getQualifier().precision, - arg1->getMatrixCols()); - arg0 = addConstructor(loc, arg0, truncType); - } - } else if (arg0->isMatrix() && arg1->isVector()) { - // mat * vec: we clamp the vec if the mat col is smaller, else clamp the mat col. - if (arg1->getVectorSize() < arg0->getMatrixRows()) { - // vec is smaller, so truncate larger mat dimension - const TType truncType(arg0->getBasicType(), arg0->getQualifier().storage, arg0->getQualifier().precision, - 0, arg0->getMatrixCols(), arg1->getVectorSize()); - arg0 = addConstructor(loc, arg0, truncType); - } else if (arg1->getVectorSize() > arg0->getMatrixRows()) { - // vec is larger, so truncate vec to mat size - const TType truncType(arg1->getBasicType(), arg1->getQualifier().storage, arg1->getQualifier().precision, - arg0->getMatrixRows()); - arg1 = addConstructor(loc, arg1, truncType); - } - } else if (arg0->isMatrix() && arg1->isMatrix()) { - // mat * mat: we clamp the smaller inner dimension to match the other matrix size. - // Remember, HLSL Mrc = GLSL/SPIRV Mcr. - if (arg0->getMatrixRows() > arg1->getMatrixCols()) { - const TType truncType(arg0->getBasicType(), arg0->getQualifier().storage, arg0->getQualifier().precision, - 0, arg0->getMatrixCols(), arg1->getMatrixCols()); - arg0 = addConstructor(loc, arg0, truncType); - } else if (arg0->getMatrixRows() < arg1->getMatrixCols()) { - const TType truncType(arg1->getBasicType(), arg1->getQualifier().storage, arg1->getQualifier().precision, - 0, arg0->getMatrixRows(), arg1->getMatrixRows()); - arg1 = addConstructor(loc, arg1, truncType); - } - } else { - // It's something with scalars: we'll just leave it alone. Function selection will handle it - // downstream. - } - - // Warn if we altered one of the arguments - if (arg0 != argAggregate->getSequence()[0] || arg1 != argAggregate->getSequence()[1]) - warn(loc, "mul() matrix size mismatch", "", ""); - - // Put arguments back. (They might be unchanged, in which case this is harmless). - argAggregate->getSequence()[0] = arg0; - argAggregate->getSequence()[1] = arg1; - - call[0].type = &arg0->getWritableType(); - call[1].type = &arg1->getWritableType(); -} - -// -// Add any needed implicit conversions for function-call arguments to input parameters. -// -void HlslParseContext::addInputArgumentConversions(const TFunction& function, TIntermTyped*& arguments) -{ - TIntermAggregate* aggregate = arguments->getAsAggregate(); - - // Replace a single argument with a single argument. - const auto setArg = [&](int paramNum, TIntermTyped* arg) { - if (function.getParamCount() == 1) - arguments = arg; - else { - if (aggregate == nullptr) - arguments = arg; - else - aggregate->getSequence()[paramNum] = arg; - } - }; - - // Process each argument's conversion - for (int param = 0; param < function.getParamCount(); ++param) { - if (! function[param].type->getQualifier().isParamInput()) - continue; - - // At this early point there is a slight ambiguity between whether an aggregate 'arguments' - // is the single argument itself or its children are the arguments. Only one argument - // means take 'arguments' itself as the one argument. - TIntermTyped* arg = function.getParamCount() == 1 - ? arguments->getAsTyped() - : (aggregate ? - aggregate->getSequence()[param]->getAsTyped() : - arguments->getAsTyped()); - if (*function[param].type != arg->getType()) { - // In-qualified arguments just need an extra node added above the argument to - // convert to the correct type. - TIntermTyped* convArg = intermediate.addConversion(EOpFunctionCall, *function[param].type, arg); - if (convArg != nullptr) - convArg = intermediate.addUniShapeConversion(EOpFunctionCall, *function[param].type, convArg); - if (convArg != nullptr) - setArg(param, convArg); - else - error(arg->getLoc(), "cannot convert input argument, argument", "", "%d", param); - } else { - if (wasFlattened(arg)) { - // If both formal and calling arg are to be flattened, leave that to argument - // expansion, not conversion. - if (!shouldFlatten(*function[param].type, function[param].type->getQualifier().storage, true)) { - // Will make a two-level subtree. - // The deepest will copy member-by-member to build the structure to pass. - // The level above that will be a two-operand EOpComma sequence that follows the copy by the - // object itself. - TVariable* internalAggregate = makeInternalVariable("aggShadow", *function[param].type); - internalAggregate->getWritableType().getQualifier().makeTemporary(); - TIntermSymbol* internalSymbolNode = new TIntermSymbol(internalAggregate->getUniqueId(), - internalAggregate->getName(), - internalAggregate->getType()); - internalSymbolNode->setLoc(arg->getLoc()); - // This makes the deepest level, the member-wise copy - TIntermAggregate* assignAgg = handleAssign(arg->getLoc(), EOpAssign, - internalSymbolNode, arg)->getAsAggregate(); - - // Now, pair that with the resulting aggregate. - assignAgg = intermediate.growAggregate(assignAgg, internalSymbolNode, arg->getLoc()); - assignAgg->setOperator(EOpComma); - assignAgg->setType(internalAggregate->getType()); - setArg(param, assignAgg); - } - } - } - } -} - -// -// Add any needed implicit expansion of calling arguments from what the shader listed to what's -// internally needed for the AST (given the constraints downstream). -// -void HlslParseContext::expandArguments(const TSourceLoc& loc, const TFunction& function, TIntermTyped*& arguments) -{ - TIntermAggregate* aggregate = arguments->getAsAggregate(); - int functionParamNumberOffset = 0; - - // Replace a single argument with a single argument. - const auto setArg = [&](int paramNum, TIntermTyped* arg) { - if (function.getParamCount() + functionParamNumberOffset == 1) - arguments = arg; - else { - if (aggregate == nullptr) - arguments = arg; - else - aggregate->getSequence()[paramNum] = arg; - } - }; - - // Replace a single argument with a list of arguments - const auto setArgList = [&](int paramNum, const TVector& args) { - if (args.size() == 1) - setArg(paramNum, args.front()); - else if (args.size() > 1) { - if (function.getParamCount() + functionParamNumberOffset == 1) { - arguments = intermediate.makeAggregate(args.front()); - std::for_each(args.begin() + 1, args.end(), - [&](TIntermTyped* arg) { - arguments = intermediate.growAggregate(arguments, arg); - }); - } else { - auto it = aggregate->getSequence().erase(aggregate->getSequence().begin() + paramNum); - aggregate->getSequence().insert(it, args.begin(), args.end()); - } - functionParamNumberOffset += (int)(args.size() - 1); - } - }; - - // Process each argument's conversion - for (int param = 0; param < function.getParamCount(); ++param) { - // At this early point there is a slight ambiguity between whether an aggregate 'arguments' - // is the single argument itself or its children are the arguments. Only one argument - // means take 'arguments' itself as the one argument. - TIntermTyped* arg = function.getParamCount() == 1 - ? arguments->getAsTyped() - : (aggregate ? - aggregate->getSequence()[param + functionParamNumberOffset]->getAsTyped() : - arguments->getAsTyped()); - - if (wasFlattened(arg) && shouldFlatten(*function[param].type, function[param].type->getQualifier().storage, true)) { - // Need to pass the structure members instead of the structure. - TVector memberArgs; - for (int memb = 0; memb < (int)arg->getType().getStruct()->size(); ++memb) - memberArgs.push_back(flattenAccess(arg, memb)); - setArgList(param + functionParamNumberOffset, memberArgs); - } - } - - // TODO: if we need both hidden counter args (below) and struct expansion (above) - // the two algorithms need to be merged: Each assumes the list starts out 1:1 between - // parameters and arguments. - - // If any argument is a pass-by-reference struct buffer with an associated counter - // buffer, we have to add another hidden parameter for that counter. - if (aggregate) - addStructBuffArguments(loc, aggregate); -} - -// -// Add any needed implicit output conversions for function-call arguments. This -// can require a new tree topology, complicated further by whether the function -// has a return value. -// -// Returns a node of a subtree that evaluates to the return value of the function. -// -TIntermTyped* HlslParseContext::addOutputArgumentConversions(const TFunction& function, TIntermOperator& intermNode) -{ - assert (intermNode.getAsAggregate() != nullptr || intermNode.getAsUnaryNode() != nullptr); - - const TSourceLoc& loc = intermNode.getLoc(); - - TIntermSequence argSequence; // temp sequence for unary node args - - if (intermNode.getAsUnaryNode()) - argSequence.push_back(intermNode.getAsUnaryNode()->getOperand()); - - TIntermSequence& arguments = argSequence.empty() ? intermNode.getAsAggregate()->getSequence() : argSequence; - - const auto needsConversion = [&](int argNum) { - return function[argNum].type->getQualifier().isParamOutput() && - (*function[argNum].type != arguments[argNum]->getAsTyped()->getType() || - shouldConvertLValue(arguments[argNum]) || - wasFlattened(arguments[argNum]->getAsTyped())); - }; - - // Will there be any output conversions? - bool outputConversions = false; - for (int i = 0; i < function.getParamCount(); ++i) { - if (needsConversion(i)) { - outputConversions = true; - break; - } - } - - if (! outputConversions) - return &intermNode; - - // Setup for the new tree, if needed: - // - // Output conversions need a different tree topology. - // Out-qualified arguments need a temporary of the correct type, with the call - // followed by an assignment of the temporary to the original argument: - // void: function(arg, ...) -> ( function(tempArg, ...), arg = tempArg, ...) - // ret = function(arg, ...) -> ret = (tempRet = function(tempArg, ...), arg = tempArg, ..., tempRet) - // Where the "tempArg" type needs no conversion as an argument, but will convert on assignment. - TIntermTyped* conversionTree = nullptr; - TVariable* tempRet = nullptr; - if (intermNode.getBasicType() != EbtVoid) { - // do the "tempRet = function(...), " bit from above - tempRet = makeInternalVariable("tempReturn", intermNode.getType()); - TIntermSymbol* tempRetNode = intermediate.addSymbol(*tempRet, loc); - conversionTree = intermediate.addAssign(EOpAssign, tempRetNode, &intermNode, loc); - } else - conversionTree = &intermNode; - - conversionTree = intermediate.makeAggregate(conversionTree); - - // Process each argument's conversion - for (int i = 0; i < function.getParamCount(); ++i) { - if (needsConversion(i)) { - // Out-qualified arguments needing conversion need to use the topology setup above. - // Do the " ...(tempArg, ...), arg = tempArg" bit from above. - - // Make a temporary for what the function expects the argument to look like. - TVariable* tempArg = makeInternalVariable("tempArg", *function[i].type); - tempArg->getWritableType().getQualifier().makeTemporary(); - TIntermSymbol* tempArgNode = intermediate.addSymbol(*tempArg, loc); - - // This makes the deepest level, the member-wise copy - TIntermTyped* tempAssign = handleAssign(arguments[i]->getLoc(), EOpAssign, arguments[i]->getAsTyped(), - tempArgNode); - tempAssign = handleLvalue(arguments[i]->getLoc(), "assign", tempAssign); - conversionTree = intermediate.growAggregate(conversionTree, tempAssign, arguments[i]->getLoc()); - - // replace the argument with another node for the same tempArg variable - arguments[i] = intermediate.addSymbol(*tempArg, loc); - } - } - - // Finalize the tree topology (see bigger comment above). - if (tempRet) { - // do the "..., tempRet" bit from above - TIntermSymbol* tempRetNode = intermediate.addSymbol(*tempRet, loc); - conversionTree = intermediate.growAggregate(conversionTree, tempRetNode, loc); - } - - conversionTree = intermediate.setAggregateOperator(conversionTree, EOpComma, intermNode.getType(), loc); - - return conversionTree; -} - -// -// Add any needed "hidden" counter buffer arguments for function calls. -// -// Modifies the 'aggregate' argument if needed. Otherwise, is no-op. -// -void HlslParseContext::addStructBuffArguments(const TSourceLoc& loc, TIntermAggregate*& aggregate) -{ - // See if there are any SB types with counters. - const bool hasStructBuffArg = - std::any_of(aggregate->getSequence().begin(), - aggregate->getSequence().end(), - [this](const TIntermNode* node) { - return (node->getAsTyped() != nullptr) && hasStructBuffCounter(node->getAsTyped()->getType()); - }); - - // Nothing to do, if we didn't find one. - if (! hasStructBuffArg) - return; - - TIntermSequence argsWithCounterBuffers; - - for (int param = 0; param < int(aggregate->getSequence().size()); ++param) { - argsWithCounterBuffers.push_back(aggregate->getSequence()[param]); - - if (hasStructBuffCounter(aggregate->getSequence()[param]->getAsTyped()->getType())) { - const TIntermSymbol* blockSym = aggregate->getSequence()[param]->getAsSymbolNode(); - if (blockSym != nullptr) { - TType counterType; - counterBufferType(loc, counterType); - - const TString counterBlockName(intermediate.addCounterBufferName(blockSym->getName())); - - TVariable* variable = makeInternalVariable(counterBlockName, counterType); - - // Mark this buffer's counter block as being in use - structBufferCounter[counterBlockName] = true; - - TIntermSymbol* sym = intermediate.addSymbol(*variable, loc); - argsWithCounterBuffers.push_back(sym); - } - } - } - - // Swap with the temp list we've built up. - aggregate->getSequence().swap(argsWithCounterBuffers); -} - - -// -// Do additional checking of built-in function calls that is not caught -// by normal semantic checks on argument type, extension tagging, etc. -// -// Assumes there has been a semantically correct match to a built-in function prototype. -// -void HlslParseContext::builtInOpCheck(const TSourceLoc& loc, const TFunction& fnCandidate, TIntermOperator& callNode) -{ - // Set up convenience accessors to the argument(s). There is almost always - // multiple arguments for the cases below, but when there might be one, - // check the unaryArg first. - const TIntermSequence* argp = nullptr; // confusing to use [] syntax on a pointer, so this is to help get a reference - const TIntermTyped* unaryArg = nullptr; - const TIntermTyped* arg0 = nullptr; - if (callNode.getAsAggregate()) { - argp = &callNode.getAsAggregate()->getSequence(); - if (argp->size() > 0) - arg0 = (*argp)[0]->getAsTyped(); - } else { - assert(callNode.getAsUnaryNode()); - unaryArg = callNode.getAsUnaryNode()->getOperand(); - arg0 = unaryArg; - } - const TIntermSequence& aggArgs = *argp; // only valid when unaryArg is nullptr - - switch (callNode.getOp()) { - case EOpTextureGather: - case EOpTextureGatherOffset: - case EOpTextureGatherOffsets: - { - // Figure out which variants are allowed by what extensions, - // and what arguments must be constant for which situations. - - TString featureString = fnCandidate.getName() + "(...)"; - const char* feature = featureString.c_str(); - int compArg = -1; // track which argument, if any, is the constant component argument - switch (callNode.getOp()) { - case EOpTextureGather: - // More than two arguments needs gpu_shader5, and rectangular or shadow needs gpu_shader5, - // otherwise, need GL_ARB_texture_gather. - if (fnCandidate.getParamCount() > 2 || fnCandidate[0].type->getSampler().dim == EsdRect || - fnCandidate[0].type->getSampler().shadow) { - if (! fnCandidate[0].type->getSampler().shadow) - compArg = 2; - } - break; - case EOpTextureGatherOffset: - // GL_ARB_texture_gather is good enough for 2D non-shadow textures with no component argument - if (! fnCandidate[0].type->getSampler().shadow) - compArg = 3; - break; - case EOpTextureGatherOffsets: - if (! fnCandidate[0].type->getSampler().shadow) - compArg = 3; - break; - default: - break; - } - - if (compArg > 0 && compArg < fnCandidate.getParamCount()) { - if (aggArgs[compArg]->getAsConstantUnion()) { - int value = aggArgs[compArg]->getAsConstantUnion()->getConstArray()[0].getIConst(); - if (value < 0 || value > 3) - error(loc, "must be 0, 1, 2, or 3:", feature, "component argument"); - } else - error(loc, "must be a compile-time constant:", feature, "component argument"); - } - - break; - } - - case EOpTextureOffset: - case EOpTextureFetchOffset: - case EOpTextureProjOffset: - case EOpTextureLodOffset: - case EOpTextureProjLodOffset: - case EOpTextureGradOffset: - case EOpTextureProjGradOffset: - { - // Handle texture-offset limits checking - // Pick which argument has to hold constant offsets - int arg = -1; - switch (callNode.getOp()) { - case EOpTextureOffset: arg = 2; break; - case EOpTextureFetchOffset: arg = (arg0->getType().getSampler().dim != EsdRect) ? 3 : 2; break; - case EOpTextureProjOffset: arg = 2; break; - case EOpTextureLodOffset: arg = 3; break; - case EOpTextureProjLodOffset: arg = 3; break; - case EOpTextureGradOffset: arg = 4; break; - case EOpTextureProjGradOffset: arg = 4; break; - default: - assert(0); - break; - } - - if (arg > 0) { - if (aggArgs[arg]->getAsConstantUnion() == nullptr) - error(loc, "argument must be compile-time constant", "texel offset", ""); - else { - const TType& type = aggArgs[arg]->getAsTyped()->getType(); - for (int c = 0; c < type.getVectorSize(); ++c) { - int offset = aggArgs[arg]->getAsConstantUnion()->getConstArray()[c].getIConst(); - if (offset > resources.maxProgramTexelOffset || offset < resources.minProgramTexelOffset) - error(loc, "value is out of range:", "texel offset", - "[gl_MinProgramTexelOffset, gl_MaxProgramTexelOffset]"); - } - } - } - - break; - } - - case EOpTextureQuerySamples: - case EOpImageQuerySamples: - break; - - case EOpImageAtomicAdd: - case EOpImageAtomicMin: - case EOpImageAtomicMax: - case EOpImageAtomicAnd: - case EOpImageAtomicOr: - case EOpImageAtomicXor: - case EOpImageAtomicExchange: - case EOpImageAtomicCompSwap: - break; - - case EOpInterpolateAtCentroid: - case EOpInterpolateAtSample: - case EOpInterpolateAtOffset: - // Make sure the first argument is an interpolant, or an array element of an interpolant - if (arg0->getType().getQualifier().storage != EvqVaryingIn) { - // It might still be an array element. - // - // We could check more, but the semantics of the first argument are already met; the - // only way to turn an array into a float/vec* is array dereference and swizzle. - // - // ES and desktop 4.3 and earlier: swizzles may not be used - // desktop 4.4 and later: swizzles may be used - const TIntermTyped* base = TIntermediate::findLValueBase(arg0, true); - if (base == nullptr || base->getType().getQualifier().storage != EvqVaryingIn) - error(loc, "first argument must be an interpolant, or interpolant-array element", - fnCandidate.getName().c_str(), ""); - } - break; - - default: - break; - } -} - -// -// Handle seeing something in a grammar production that can be done by calling -// a constructor. -// -// The constructor still must be "handled" by handleFunctionCall(), which will -// then call handleConstructor(). -// -TFunction* HlslParseContext::makeConstructorCall(const TSourceLoc& loc, const TType& type) -{ - TOperator op = intermediate.mapTypeToConstructorOp(type); - - if (op == EOpNull) { - error(loc, "cannot construct this type", type.getBasicString(), ""); - return nullptr; - } - - TString empty(""); - - return new TFunction(&empty, type, op); -} - -// -// Handle seeing a "COLON semantic" at the end of a type declaration, -// by updating the type according to the semantic. -// -void HlslParseContext::handleSemantic(TSourceLoc loc, TQualifier& qualifier, TBuiltInVariable builtIn, - const TString& upperCase) -{ - // Parse and return semantic number. If limit is 0, it will be ignored. Otherwise, if the parsed - // semantic number is >= limit, errorMsg is issued and 0 is returned. - // TODO: it would be nicer if limit and errorMsg had default parameters, but some compilers don't yet - // accept those in lambda functions. - const auto getSemanticNumber = [this, loc](const TString& semantic, unsigned int limit, const char* errorMsg) -> unsigned int { - size_t pos = semantic.find_last_not_of("0123456789"); - if (pos == std::string::npos) - return 0u; - - unsigned int semanticNum = (unsigned int)atoi(semantic.c_str() + pos + 1); - - if (limit != 0 && semanticNum >= limit) { - error(loc, errorMsg, semantic.c_str(), ""); - return 0u; - } - - return semanticNum; - }; - - switch(builtIn) { - case EbvNone: - // Get location numbers from fragment outputs, instead of - // auto-assigning them. - if (language == EShLangFragment && upperCase.compare(0, 9, "SV_TARGET") == 0) { - qualifier.layoutLocation = getSemanticNumber(upperCase, 0, nullptr); - nextOutLocation = std::max(nextOutLocation, qualifier.layoutLocation + 1u); - } else if (upperCase.compare(0, 15, "SV_CLIPDISTANCE") == 0) { - builtIn = EbvClipDistance; - qualifier.layoutLocation = getSemanticNumber(upperCase, maxClipCullRegs, "invalid clip semantic"); - } else if (upperCase.compare(0, 15, "SV_CULLDISTANCE") == 0) { - builtIn = EbvCullDistance; - qualifier.layoutLocation = getSemanticNumber(upperCase, maxClipCullRegs, "invalid cull semantic"); - } - break; - case EbvPosition: - // adjust for stage in/out - if (language == EShLangFragment) - builtIn = EbvFragCoord; - break; - case EbvFragStencilRef: - error(loc, "unimplemented; need ARB_shader_stencil_export", "SV_STENCILREF", ""); - break; - case EbvTessLevelInner: - case EbvTessLevelOuter: - qualifier.patch = true; - break; - default: - break; - } - - if (qualifier.builtIn == EbvNone) - qualifier.builtIn = builtIn; - qualifier.semanticName = intermediate.addSemanticName(upperCase); -} - -// -// Handle seeing something like "PACKOFFSET LEFT_PAREN c[Subcomponent][.component] RIGHT_PAREN" -// -// 'location' has the "c[Subcomponent]" part. -// 'component' points to the "component" part, or nullptr if not present. -// -void HlslParseContext::handlePackOffset(const TSourceLoc& loc, TQualifier& qualifier, const glslang::TString& location, - const glslang::TString* component) -{ - if (location.size() == 0 || location[0] != 'c') { - error(loc, "expected 'c'", "packoffset", ""); - return; - } - if (location.size() == 1) - return; - if (! isdigit(location[1])) { - error(loc, "expected number after 'c'", "packoffset", ""); - return; - } - - qualifier.layoutOffset = 16 * atoi(location.substr(1, location.size()).c_str()); - if (component != nullptr) { - int componentOffset = 0; - switch ((*component)[0]) { - case 'x': componentOffset = 0; break; - case 'y': componentOffset = 4; break; - case 'z': componentOffset = 8; break; - case 'w': componentOffset = 12; break; - default: - componentOffset = -1; - break; - } - if (componentOffset < 0 || component->size() > 1) { - error(loc, "expected {x, y, z, w} for component", "packoffset", ""); - return; - } - qualifier.layoutOffset += componentOffset; - } -} - -// -// Handle seeing something like "REGISTER LEFT_PAREN [shader_profile,] Type# RIGHT_PAREN" -// -// 'profile' points to the shader_profile part, or nullptr if not present. -// 'desc' is the type# part. -// -void HlslParseContext::handleRegister(const TSourceLoc& loc, TQualifier& qualifier, const glslang::TString* profile, - const glslang::TString& desc, int subComponent, const glslang::TString* spaceDesc) -{ - if (profile != nullptr) - warn(loc, "ignoring shader_profile", "register", ""); - - if (desc.size() < 1) { - error(loc, "expected register type", "register", ""); - return; - } - - int regNumber = 0; - if (desc.size() > 1) { - if (isdigit(desc[1])) - regNumber = atoi(desc.substr(1, desc.size()).c_str()); - else { - error(loc, "expected register number after register type", "register", ""); - return; - } - } - - // TODO: learn what all these really mean and how they interact with regNumber and subComponent - const std::vector& resourceInfo = intermediate.getResourceSetBinding(); - switch (std::tolower(desc[0])) { - case 'b': - case 't': - case 'c': - case 's': - case 'u': - // if nothing else has set the binding, do so now - // (other mechanisms override this one) - if (!qualifier.hasBinding()) - qualifier.layoutBinding = regNumber + subComponent; - - // This handles per-register layout sets numbers. For the global mode which sets - // every symbol to the same value, see setLinkageLayoutSets(). - if ((resourceInfo.size() % 3) == 0) { - // Apply per-symbol resource set and binding. - for (auto it = resourceInfo.cbegin(); it != resourceInfo.cend(); it = it + 3) { - if (strcmp(desc.c_str(), it[0].c_str()) == 0) { - qualifier.layoutSet = atoi(it[1].c_str()); - qualifier.layoutBinding = atoi(it[2].c_str()) + subComponent; - break; - } - } - } - break; - default: - warn(loc, "ignoring unrecognized register type", "register", "%c", desc[0]); - break; - } - - // space - unsigned int setNumber; - const auto crackSpace = [&]() -> bool { - const int spaceLen = 5; - if (spaceDesc->size() < spaceLen + 1) - return false; - if (spaceDesc->compare(0, spaceLen, "space") != 0) - return false; - if (! isdigit((*spaceDesc)[spaceLen])) - return false; - setNumber = atoi(spaceDesc->substr(spaceLen, spaceDesc->size()).c_str()); - return true; - }; - - // if nothing else has set the set, do so now - // (other mechanisms override this one) - if (spaceDesc && !qualifier.hasSet()) { - if (! crackSpace()) { - error(loc, "expected spaceN", "register", ""); - return; - } - qualifier.layoutSet = setNumber; - } -} - -// Convert to a scalar boolean, or if not allowed by HLSL semantics, -// report an error and return nullptr. -TIntermTyped* HlslParseContext::convertConditionalExpression(const TSourceLoc& loc, TIntermTyped* condition, - bool mustBeScalar) -{ - if (mustBeScalar && !condition->getType().isScalarOrVec1()) { - error(loc, "requires a scalar", "conditional expression", ""); - return nullptr; - } - - return intermediate.addConversion(EOpConstructBool, TType(EbtBool, EvqTemporary, condition->getVectorSize()), - condition); -} - -// -// Same error message for all places assignments don't work. -// -void HlslParseContext::assignError(const TSourceLoc& loc, const char* op, TString left, TString right) -{ - error(loc, "", op, "cannot convert from '%s' to '%s'", - right.c_str(), left.c_str()); -} - -// -// Same error message for all places unary operations don't work. -// -void HlslParseContext::unaryOpError(const TSourceLoc& loc, const char* op, TString operand) -{ - error(loc, " wrong operand type", op, - "no operation '%s' exists that takes an operand of type %s (or there is no acceptable conversion)", - op, operand.c_str()); -} - -// -// Same error message for all binary operations don't work. -// -void HlslParseContext::binaryOpError(const TSourceLoc& loc, const char* op, TString left, TString right) -{ - error(loc, " wrong operand types:", op, - "no operation '%s' exists that takes a left-hand operand of type '%s' and " - "a right operand of type '%s' (or there is no acceptable conversion)", - op, left.c_str(), right.c_str()); -} - -// -// A basic type of EbtVoid is a key that the name string was seen in the source, but -// it was not found as a variable in the symbol table. If so, give the error -// message and insert a dummy variable in the symbol table to prevent future errors. -// -void HlslParseContext::variableCheck(TIntermTyped*& nodePtr) -{ - TIntermSymbol* symbol = nodePtr->getAsSymbolNode(); - if (! symbol) - return; - - if (symbol->getType().getBasicType() == EbtVoid) { - error(symbol->getLoc(), "undeclared identifier", symbol->getName().c_str(), ""); - - // Add to symbol table to prevent future error messages on the same name - if (symbol->getName().size() > 0) { - TVariable* fakeVariable = new TVariable(&symbol->getName(), TType(EbtFloat)); - symbolTable.insert(*fakeVariable); - - // substitute a symbol node for this new variable - nodePtr = intermediate.addSymbol(*fakeVariable, symbol->getLoc()); - } - } -} - -// -// Both test, and if necessary spit out an error, to see if the node is really -// a constant. -// -void HlslParseContext::constantValueCheck(TIntermTyped* node, const char* token) -{ - if (node->getQualifier().storage != EvqConst) - error(node->getLoc(), "constant expression required", token, ""); -} - -// -// Both test, and if necessary spit out an error, to see if the node is really -// an integer. -// -void HlslParseContext::integerCheck(const TIntermTyped* node, const char* token) -{ - if ((node->getBasicType() == EbtInt || node->getBasicType() == EbtUint) && node->isScalar()) - return; - - error(node->getLoc(), "scalar integer expression required", token, ""); -} - -// -// Both test, and if necessary spit out an error, to see if we are currently -// globally scoped. -// -void HlslParseContext::globalCheck(const TSourceLoc& loc, const char* token) -{ - if (! symbolTable.atGlobalLevel()) - error(loc, "not allowed in nested scope", token, ""); -} - -bool HlslParseContext::builtInName(const TString& /*identifier*/) -{ - return false; -} - -// -// Make sure there is enough data and not too many arguments provided to the -// constructor to build something of the type of the constructor. Also returns -// the type of the constructor. -// -// Returns true if there was an error in construction. -// -bool HlslParseContext::constructorError(const TSourceLoc& loc, TIntermNode* node, TFunction& function, - TOperator op, TType& type) -{ - type.shallowCopy(function.getType()); - - bool constructingMatrix = false; - switch (op) { - case EOpConstructTextureSampler: - return constructorTextureSamplerError(loc, function); - case EOpConstructMat2x2: - case EOpConstructMat2x3: - case EOpConstructMat2x4: - case EOpConstructMat3x2: - case EOpConstructMat3x3: - case EOpConstructMat3x4: - case EOpConstructMat4x2: - case EOpConstructMat4x3: - case EOpConstructMat4x4: - case EOpConstructDMat2x2: - case EOpConstructDMat2x3: - case EOpConstructDMat2x4: - case EOpConstructDMat3x2: - case EOpConstructDMat3x3: - case EOpConstructDMat3x4: - case EOpConstructDMat4x2: - case EOpConstructDMat4x3: - case EOpConstructDMat4x4: - case EOpConstructIMat2x2: - case EOpConstructIMat2x3: - case EOpConstructIMat2x4: - case EOpConstructIMat3x2: - case EOpConstructIMat3x3: - case EOpConstructIMat3x4: - case EOpConstructIMat4x2: - case EOpConstructIMat4x3: - case EOpConstructIMat4x4: - case EOpConstructUMat2x2: - case EOpConstructUMat2x3: - case EOpConstructUMat2x4: - case EOpConstructUMat3x2: - case EOpConstructUMat3x3: - case EOpConstructUMat3x4: - case EOpConstructUMat4x2: - case EOpConstructUMat4x3: - case EOpConstructUMat4x4: - case EOpConstructBMat2x2: - case EOpConstructBMat2x3: - case EOpConstructBMat2x4: - case EOpConstructBMat3x2: - case EOpConstructBMat3x3: - case EOpConstructBMat3x4: - case EOpConstructBMat4x2: - case EOpConstructBMat4x3: - case EOpConstructBMat4x4: - constructingMatrix = true; - break; - default: - break; - } - - // - // Walk the arguments for first-pass checks and collection of information. - // - - int size = 0; - bool constType = true; - bool full = false; - bool overFull = false; - bool matrixInMatrix = false; - bool arrayArg = false; - for (int arg = 0; arg < function.getParamCount(); ++arg) { - if (function[arg].type->isArray()) { - if (function[arg].type->isUnsizedArray()) { - // Can't construct from an unsized array. - error(loc, "array argument must be sized", "constructor", ""); - return true; - } - arrayArg = true; - } - if (constructingMatrix && function[arg].type->isMatrix()) - matrixInMatrix = true; - - // 'full' will go to true when enough args have been seen. If we loop - // again, there is an extra argument. - if (full) { - // For vectors and matrices, it's okay to have too many components - // available, but not okay to have unused arguments. - overFull = true; - } - - size += function[arg].type->computeNumComponents(); - if (op != EOpConstructStruct && ! type.isArray() && size >= type.computeNumComponents()) - full = true; - - if (function[arg].type->getQualifier().storage != EvqConst) - constType = false; - } - - if (constType) - type.getQualifier().storage = EvqConst; - - if (type.isArray()) { - if (function.getParamCount() == 0) { - error(loc, "array constructor must have at least one argument", "constructor", ""); - return true; - } - - if (type.isUnsizedArray()) { - // auto adapt the constructor type to the number of arguments - type.changeOuterArraySize(function.getParamCount()); - } else if (type.getOuterArraySize() != function.getParamCount() && type.computeNumComponents() > size) { - error(loc, "array constructor needs one argument per array element", "constructor", ""); - return true; - } - - if (type.isArrayOfArrays()) { - // Types have to match, but we're still making the type. - // Finish making the type, and the comparison is done later - // when checking for conversion. - TArraySizes& arraySizes = *type.getArraySizes(); - - // At least the dimensionalities have to match. - if (! function[0].type->isArray() || - arraySizes.getNumDims() != function[0].type->getArraySizes()->getNumDims() + 1) { - error(loc, "array constructor argument not correct type to construct array element", "constructor", ""); - return true; - } - - if (arraySizes.isInnerUnsized()) { - // "Arrays of arrays ..., and the size for any dimension is optional" - // That means we need to adopt (from the first argument) the other array sizes into the type. - for (int d = 1; d < arraySizes.getNumDims(); ++d) { - if (arraySizes.getDimSize(d) == UnsizedArraySize) { - arraySizes.setDimSize(d, function[0].type->getArraySizes()->getDimSize(d - 1)); - } - } - } - } - } - - // Some array -> array type casts are okay - if (arrayArg && function.getParamCount() == 1 && op != EOpConstructStruct && type.isArray() && - !type.isArrayOfArrays() && !function[0].type->isArrayOfArrays() && - type.getVectorSize() >= 1 && function[0].type->getVectorSize() >= 1) - return false; - - if (arrayArg && op != EOpConstructStruct && ! type.isArrayOfArrays()) { - error(loc, "constructing non-array constituent from array argument", "constructor", ""); - return true; - } - - if (matrixInMatrix && ! type.isArray()) { - return false; - } - - if (overFull) { - error(loc, "too many arguments", "constructor", ""); - return true; - } - - if (op == EOpConstructStruct && ! type.isArray() && isScalarConstructor(node)) - return false; - - if (op == EOpConstructStruct && ! type.isArray() && (int)type.getStruct()->size() != function.getParamCount()) { - error(loc, "Number of constructor parameters does not match the number of structure fields", "constructor", ""); - return true; - } - - if ((op != EOpConstructStruct && size != 1 && size < type.computeNumComponents()) || - (op == EOpConstructStruct && size < type.computeNumComponents())) { - error(loc, "not enough data provided for construction", "constructor", ""); - return true; - } - - return false; -} - -// See if 'node', in the context of constructing aggregates, is a scalar argument -// to a constructor. -// -bool HlslParseContext::isScalarConstructor(const TIntermNode* node) -{ - // Obviously, it must be a scalar, but an aggregate node might not be fully - // completed yet: holding a sequence of initializers under an aggregate - // would not yet be typed, so don't check it's type. This corresponds to - // the aggregate operator also not being set yet. (An aggregate operation - // that legitimately yields a scalar will have a getOp() of that operator, - // not EOpNull.) - - return node->getAsTyped() != nullptr && - node->getAsTyped()->isScalar() && - (node->getAsAggregate() == nullptr || node->getAsAggregate()->getOp() != EOpNull); -} - -// Verify all the correct semantics for constructing a combined texture/sampler. -// Return true if the semantics are incorrect. -bool HlslParseContext::constructorTextureSamplerError(const TSourceLoc& loc, const TFunction& function) -{ - TString constructorName = function.getType().getBasicTypeString(); // TODO: performance: should not be making copy; interface needs to change - const char* token = constructorName.c_str(); - - // exactly two arguments needed - if (function.getParamCount() != 2) { - error(loc, "sampler-constructor requires two arguments", token, ""); - return true; - } - - // For now, not allowing arrayed constructors, the rest of this function - // is set up to allow them, if this test is removed: - if (function.getType().isArray()) { - error(loc, "sampler-constructor cannot make an array of samplers", token, ""); - return true; - } - - // first argument - // * the constructor's first argument must be a texture type - // * the dimensionality (1D, 2D, 3D, Cube, Rect, Buffer, MS, and Array) - // of the texture type must match that of the constructed sampler type - // (that is, the suffixes of the type of the first argument and the - // type of the constructor will be spelled the same way) - if (function[0].type->getBasicType() != EbtSampler || - ! function[0].type->getSampler().isTexture() || - function[0].type->isArray()) { - error(loc, "sampler-constructor first argument must be a scalar textureXXX type", token, ""); - return true; - } - // simulate the first argument's impact on the result type, so it can be compared with the encapsulated operator!=() - TSampler texture = function.getType().getSampler(); - texture.combined = false; - texture.shadow = false; - if (texture != function[0].type->getSampler()) { - error(loc, "sampler-constructor first argument must match type and dimensionality of constructor type", token, ""); - return true; - } - - // second argument - // * the constructor's second argument must be a scalar of type - // *sampler* or *samplerShadow* - // * the presence or absence of depth comparison (Shadow) must match - // between the constructed sampler type and the type of the second argument - if (function[1].type->getBasicType() != EbtSampler || - ! function[1].type->getSampler().isPureSampler() || - function[1].type->isArray()) { - error(loc, "sampler-constructor second argument must be a scalar type 'sampler'", token, ""); - return true; - } - if (function.getType().getSampler().shadow != function[1].type->getSampler().shadow) { - error(loc, "sampler-constructor second argument presence of shadow must match constructor presence of shadow", - token, ""); - return true; - } - - return false; -} - -// Checks to see if a void variable has been declared and raise an error message for such a case -// -// returns true in case of an error -// -bool HlslParseContext::voidErrorCheck(const TSourceLoc& loc, const TString& identifier, const TBasicType basicType) -{ - if (basicType == EbtVoid) { - error(loc, "illegal use of type 'void'", identifier.c_str(), ""); - return true; - } - - return false; -} - -// -// Fix just a full qualifier (no variables or types yet, but qualifier is complete) at global level. -// -void HlslParseContext::globalQualifierFix(const TSourceLoc&, TQualifier& qualifier) -{ - // move from parameter/unknown qualifiers to pipeline in/out qualifiers - switch (qualifier.storage) { - case EvqIn: - qualifier.storage = EvqVaryingIn; - break; - case EvqOut: - qualifier.storage = EvqVaryingOut; - break; - default: - break; - } -} - -// -// Merge characteristics of the 'src' qualifier into the 'dst'. -// If there is duplication, issue error messages, unless 'force' -// is specified, which means to just override default settings. -// -// Also, when force is false, it will be assumed that 'src' follows -// 'dst', for the purpose of error checking order for versions -// that require specific orderings of qualifiers. -// -void HlslParseContext::mergeQualifiers(TQualifier& dst, const TQualifier& src) -{ - // Storage qualification - if (dst.storage == EvqTemporary || dst.storage == EvqGlobal) - dst.storage = src.storage; - else if ((dst.storage == EvqIn && src.storage == EvqOut) || - (dst.storage == EvqOut && src.storage == EvqIn)) - dst.storage = EvqInOut; - else if ((dst.storage == EvqIn && src.storage == EvqConst) || - (dst.storage == EvqConst && src.storage == EvqIn)) - dst.storage = EvqConstReadOnly; - - // Layout qualifiers - mergeObjectLayoutQualifiers(dst, src, false); - - // individual qualifiers - bool repeated = false; -#define MERGE_SINGLETON(field) repeated |= dst.field && src.field; dst.field |= src.field; - MERGE_SINGLETON(invariant); - MERGE_SINGLETON(noContraction); - MERGE_SINGLETON(centroid); - MERGE_SINGLETON(smooth); - MERGE_SINGLETON(flat); - MERGE_SINGLETON(nopersp); - MERGE_SINGLETON(patch); - MERGE_SINGLETON(sample); - MERGE_SINGLETON(coherent); - MERGE_SINGLETON(volatil); - MERGE_SINGLETON(restrict); - MERGE_SINGLETON(readonly); - MERGE_SINGLETON(writeonly); - MERGE_SINGLETON(specConstant); - MERGE_SINGLETON(nonUniform); -} - -// used to flatten the sampler type space into a single dimension -// correlates with the declaration of defaultSamplerPrecision[] -int HlslParseContext::computeSamplerTypeIndex(TSampler& sampler) -{ - int arrayIndex = sampler.arrayed ? 1 : 0; - int shadowIndex = sampler.shadow ? 1 : 0; - int externalIndex = sampler.external ? 1 : 0; - - return EsdNumDims * - (EbtNumTypes * (2 * (2 * arrayIndex + shadowIndex) + externalIndex) + sampler.type) + sampler.dim; -} - -// -// Do size checking for an array type's size. -// -void HlslParseContext::arraySizeCheck(const TSourceLoc& loc, TIntermTyped* expr, TArraySize& sizePair) -{ - bool isConst = false; - sizePair.size = 1; - sizePair.node = nullptr; - - TIntermConstantUnion* constant = expr->getAsConstantUnion(); - if (constant) { - // handle true (non-specialization) constant - sizePair.size = constant->getConstArray()[0].getIConst(); - isConst = true; - } else { - // see if it's a specialization constant instead - if (expr->getQualifier().isSpecConstant()) { - isConst = true; - sizePair.node = expr; - TIntermSymbol* symbol = expr->getAsSymbolNode(); - if (symbol && symbol->getConstArray().size() > 0) - sizePair.size = symbol->getConstArray()[0].getIConst(); - } - } - - if (! isConst || (expr->getBasicType() != EbtInt && expr->getBasicType() != EbtUint)) { - error(loc, "array size must be a constant integer expression", "", ""); - return; - } - - if (sizePair.size <= 0) { - error(loc, "array size must be a positive integer", "", ""); - return; - } -} - -// -// Require array to be completely sized -// -void HlslParseContext::arraySizeRequiredCheck(const TSourceLoc& loc, const TArraySizes& arraySizes) -{ - if (arraySizes.hasUnsized()) - error(loc, "array size required", "", ""); -} - -void HlslParseContext::structArrayCheck(const TSourceLoc& /*loc*/, const TType& type) -{ - const TTypeList& structure = *type.getStruct(); - for (int m = 0; m < (int)structure.size(); ++m) { - const TType& member = *structure[m].type; - if (member.isArray()) - arraySizeRequiredCheck(structure[m].loc, *member.getArraySizes()); - } -} - -// -// Do all the semantic checking for declaring or redeclaring an array, with and -// without a size, and make the right changes to the symbol table. -// -void HlslParseContext::declareArray(const TSourceLoc& loc, const TString& identifier, const TType& type, - TSymbol*& symbol, bool track) -{ - if (symbol == nullptr) { - bool currentScope; - symbol = symbolTable.find(identifier, nullptr, ¤tScope); - - if (symbol && builtInName(identifier) && ! symbolTable.atBuiltInLevel()) { - // bad shader (errors already reported) trying to redeclare a built-in name as an array - return; - } - if (symbol == nullptr || ! currentScope) { - // - // Successfully process a new definition. - // (Redeclarations have to take place at the same scope; otherwise they are hiding declarations) - // - symbol = new TVariable(&identifier, type); - symbolTable.insert(*symbol); - if (track && symbolTable.atGlobalLevel()) - trackLinkage(*symbol); - - return; - } - if (symbol->getAsAnonMember()) { - error(loc, "cannot redeclare a user-block member array", identifier.c_str(), ""); - symbol = nullptr; - return; - } - } - - // - // Process a redeclaration. - // - - if (symbol == nullptr) { - error(loc, "array variable name expected", identifier.c_str(), ""); - return; - } - - // redeclareBuiltinVariable() should have already done the copyUp() - TType& existingType = symbol->getWritableType(); - - if (existingType.isSizedArray()) { - // be more lenient for input arrays to geometry shaders and tessellation control outputs, - // where the redeclaration is the same size - return; - } - - existingType.updateArraySizes(type); -} - -// -// Enforce non-initializer type/qualifier rules. -// -void HlslParseContext::fixConstInit(const TSourceLoc& loc, const TString& identifier, TType& type, - TIntermTyped*& initializer) -{ - // - // Make the qualifier make sense, given that there is an initializer. - // - if (initializer == nullptr) { - if (type.getQualifier().storage == EvqConst || - type.getQualifier().storage == EvqConstReadOnly) { - initializer = intermediate.makeAggregate(loc); - warn(loc, "variable with qualifier 'const' not initialized; zero initializing", identifier.c_str(), ""); - } - } -} - -// -// See if the identifier is a built-in symbol that can be redeclared, and if so, -// copy the symbol table's read-only built-in variable to the current -// global level, where it can be modified based on the passed in type. -// -// Returns nullptr if no redeclaration took place; meaning a normal declaration still -// needs to occur for it, not necessarily an error. -// -// Returns a redeclared and type-modified variable if a redeclared occurred. -// -TSymbol* HlslParseContext::redeclareBuiltinVariable(const TSourceLoc& /*loc*/, const TString& identifier, - const TQualifier& /*qualifier*/, - const TShaderQualifiers& /*publicType*/) -{ - if (! builtInName(identifier) || symbolTable.atBuiltInLevel() || ! symbolTable.atGlobalLevel()) - return nullptr; - - return nullptr; -} - -// -// Generate index to the array element in a structure buffer (SSBO) -// -TIntermTyped* HlslParseContext::indexStructBufferContent(const TSourceLoc& loc, TIntermTyped* buffer) const -{ - // Bail out if not a struct buffer - if (buffer == nullptr || ! isStructBufferType(buffer->getType())) - return nullptr; - - // Runtime sized array is always the last element. - const TTypeList* bufferStruct = buffer->getType().getStruct(); - TIntermTyped* arrayPosition = intermediate.addConstantUnion(unsigned(bufferStruct->size()-1), loc); - - TIntermTyped* argArray = intermediate.addIndex(EOpIndexDirectStruct, buffer, arrayPosition, loc); - argArray->setType(*(*bufferStruct)[bufferStruct->size()-1].type); - - return argArray; -} - -// -// IFF type is a structuredbuffer/byteaddressbuffer type, return the content -// (template) type. E.g, StructuredBuffer -> MyType. Else return nullptr. -// -TType* HlslParseContext::getStructBufferContentType(const TType& type) const -{ - if (type.getBasicType() != EbtBlock || type.getQualifier().storage != EvqBuffer) - return nullptr; - - const int memberCount = (int)type.getStruct()->size(); - assert(memberCount > 0); - - TType* contentType = (*type.getStruct())[memberCount-1].type; - - return contentType->isUnsizedArray() ? contentType : nullptr; -} - -// -// If an existing struct buffer has a sharable type, then share it. -// -void HlslParseContext::shareStructBufferType(TType& type) -{ - // PackOffset must be equivalent to share types on a per-member basis. - // Note: cannot use auto type due to recursion. Thus, this is a std::function. - const std::function - compareQualifiers = [&](TType& lhs, TType& rhs) -> bool { - if (lhs.getQualifier().layoutOffset != rhs.getQualifier().layoutOffset) - return false; - - if (lhs.isStruct() != rhs.isStruct()) - return false; - - if (lhs.isStruct() && rhs.isStruct()) { - if (lhs.getStruct()->size() != rhs.getStruct()->size()) - return false; - - for (int i = 0; i < int(lhs.getStruct()->size()); ++i) - if (!compareQualifiers(*(*lhs.getStruct())[i].type, *(*rhs.getStruct())[i].type)) - return false; - } - - return true; - }; - - // We need to compare certain qualifiers in addition to the type. - const auto typeEqual = [compareQualifiers](TType& lhs, TType& rhs) -> bool { - if (lhs.getQualifier().readonly != rhs.getQualifier().readonly) - return false; - - // If both are structures, recursively look for packOffset equality - // as well as type equality. - return compareQualifiers(lhs, rhs) && lhs == rhs; - }; - - // This is an exhaustive O(N) search, but real world shaders have - // only a small number of these. - for (int idx = 0; idx < int(structBufferTypes.size()); ++idx) { - // If the deep structure matches, modulo qualifiers, use it - if (typeEqual(*structBufferTypes[idx], type)) { - type.shallowCopy(*structBufferTypes[idx]); - return; - } - } - - // Otherwise, remember it: - TType* typeCopy = new TType; - typeCopy->shallowCopy(type); - structBufferTypes.push_back(typeCopy); -} - -void HlslParseContext::paramFix(TType& type) -{ - switch (type.getQualifier().storage) { - case EvqConst: - type.getQualifier().storage = EvqConstReadOnly; - break; - case EvqGlobal: - case EvqUniform: - case EvqTemporary: - type.getQualifier().storage = EvqIn; - break; - case EvqBuffer: - { - // SSBO parameter. These do not go through the declareBlock path since they are fn parameters. - correctUniform(type.getQualifier()); - TQualifier bufferQualifier = globalBufferDefaults; - mergeObjectLayoutQualifiers(bufferQualifier, type.getQualifier(), true); - bufferQualifier.storage = type.getQualifier().storage; - bufferQualifier.readonly = type.getQualifier().readonly; - bufferQualifier.coherent = type.getQualifier().coherent; - bufferQualifier.declaredBuiltIn = type.getQualifier().declaredBuiltIn; - type.getQualifier() = bufferQualifier; - break; - } - default: - break; - } -} - -void HlslParseContext::specializationCheck(const TSourceLoc& loc, const TType& type, const char* op) -{ - if (type.containsSpecializationSize()) - error(loc, "can't use with types containing arrays sized with a specialization constant", op, ""); -} - -// -// Layout qualifier stuff. -// - -// Put the id's layout qualification into the public type, for qualifiers not having a number set. -// This is before we know any type information for error checking. -void HlslParseContext::setLayoutQualifier(const TSourceLoc& loc, TQualifier& qualifier, TString& id) -{ - std::transform(id.begin(), id.end(), id.begin(), ::tolower); - - if (id == TQualifier::getLayoutMatrixString(ElmColumnMajor)) { - qualifier.layoutMatrix = ElmRowMajor; - return; - } - if (id == TQualifier::getLayoutMatrixString(ElmRowMajor)) { - qualifier.layoutMatrix = ElmColumnMajor; - return; - } - if (id == "push_constant") { - requireVulkan(loc, "push_constant"); - qualifier.layoutPushConstant = true; - return; - } - if (language == EShLangGeometry || language == EShLangTessEvaluation) { - if (id == TQualifier::getGeometryString(ElgTriangles)) { - // publicType.shaderQualifiers.geometry = ElgTriangles; - warn(loc, "ignored", id.c_str(), ""); - return; - } - if (language == EShLangGeometry) { - if (id == TQualifier::getGeometryString(ElgPoints)) { - // publicType.shaderQualifiers.geometry = ElgPoints; - warn(loc, "ignored", id.c_str(), ""); - return; - } - if (id == TQualifier::getGeometryString(ElgLineStrip)) { - // publicType.shaderQualifiers.geometry = ElgLineStrip; - warn(loc, "ignored", id.c_str(), ""); - return; - } - if (id == TQualifier::getGeometryString(ElgLines)) { - // publicType.shaderQualifiers.geometry = ElgLines; - warn(loc, "ignored", id.c_str(), ""); - return; - } - if (id == TQualifier::getGeometryString(ElgLinesAdjacency)) { - // publicType.shaderQualifiers.geometry = ElgLinesAdjacency; - warn(loc, "ignored", id.c_str(), ""); - return; - } - if (id == TQualifier::getGeometryString(ElgTrianglesAdjacency)) { - // publicType.shaderQualifiers.geometry = ElgTrianglesAdjacency; - warn(loc, "ignored", id.c_str(), ""); - return; - } - if (id == TQualifier::getGeometryString(ElgTriangleStrip)) { - // publicType.shaderQualifiers.geometry = ElgTriangleStrip; - warn(loc, "ignored", id.c_str(), ""); - return; - } - } else { - assert(language == EShLangTessEvaluation); - - // input primitive - if (id == TQualifier::getGeometryString(ElgTriangles)) { - // publicType.shaderQualifiers.geometry = ElgTriangles; - warn(loc, "ignored", id.c_str(), ""); - return; - } - if (id == TQualifier::getGeometryString(ElgQuads)) { - // publicType.shaderQualifiers.geometry = ElgQuads; - warn(loc, "ignored", id.c_str(), ""); - return; - } - if (id == TQualifier::getGeometryString(ElgIsolines)) { - // publicType.shaderQualifiers.geometry = ElgIsolines; - warn(loc, "ignored", id.c_str(), ""); - return; - } - - // vertex spacing - if (id == TQualifier::getVertexSpacingString(EvsEqual)) { - // publicType.shaderQualifiers.spacing = EvsEqual; - warn(loc, "ignored", id.c_str(), ""); - return; - } - if (id == TQualifier::getVertexSpacingString(EvsFractionalEven)) { - // publicType.shaderQualifiers.spacing = EvsFractionalEven; - warn(loc, "ignored", id.c_str(), ""); - return; - } - if (id == TQualifier::getVertexSpacingString(EvsFractionalOdd)) { - // publicType.shaderQualifiers.spacing = EvsFractionalOdd; - warn(loc, "ignored", id.c_str(), ""); - return; - } - - // triangle order - if (id == TQualifier::getVertexOrderString(EvoCw)) { - // publicType.shaderQualifiers.order = EvoCw; - warn(loc, "ignored", id.c_str(), ""); - return; - } - if (id == TQualifier::getVertexOrderString(EvoCcw)) { - // publicType.shaderQualifiers.order = EvoCcw; - warn(loc, "ignored", id.c_str(), ""); - return; - } - - // point mode - if (id == "point_mode") { - // publicType.shaderQualifiers.pointMode = true; - warn(loc, "ignored", id.c_str(), ""); - return; - } - } - } - if (language == EShLangFragment) { - if (id == "origin_upper_left") { - // publicType.shaderQualifiers.originUpperLeft = true; - warn(loc, "ignored", id.c_str(), ""); - return; - } - if (id == "pixel_center_integer") { - // publicType.shaderQualifiers.pixelCenterInteger = true; - warn(loc, "ignored", id.c_str(), ""); - return; - } - if (id == "early_fragment_tests") { - // publicType.shaderQualifiers.earlyFragmentTests = true; - warn(loc, "ignored", id.c_str(), ""); - return; - } - for (TLayoutDepth depth = (TLayoutDepth)(EldNone + 1); depth < EldCount; depth = (TLayoutDepth)(depth + 1)) { - if (id == TQualifier::getLayoutDepthString(depth)) { - // publicType.shaderQualifiers.layoutDepth = depth; - warn(loc, "ignored", id.c_str(), ""); - return; - } - } - if (id.compare(0, 13, "blend_support") == 0) { - bool found = false; - for (TBlendEquationShift be = (TBlendEquationShift)0; be < EBlendCount; be = (TBlendEquationShift)(be + 1)) { - if (id == TQualifier::getBlendEquationString(be)) { - requireExtensions(loc, 1, &E_GL_KHR_blend_equation_advanced, "blend equation"); - intermediate.addBlendEquation(be); - // publicType.shaderQualifiers.blendEquation = true; - warn(loc, "ignored", id.c_str(), ""); - found = true; - break; - } - } - if (! found) - error(loc, "unknown blend equation", "blend_support", ""); - return; - } - } - error(loc, "unrecognized layout identifier, or qualifier requires assignment (e.g., binding = 4)", id.c_str(), ""); -} - -// Put the id's layout qualifier value into the public type, for qualifiers having a number set. -// This is before we know any type information for error checking. -void HlslParseContext::setLayoutQualifier(const TSourceLoc& loc, TQualifier& qualifier, TString& id, - const TIntermTyped* node) -{ - const char* feature = "layout-id value"; - // const char* nonLiteralFeature = "non-literal layout-id value"; - - integerCheck(node, feature); - const TIntermConstantUnion* constUnion = node->getAsConstantUnion(); - int value = 0; - if (constUnion) { - value = constUnion->getConstArray()[0].getIConst(); - } - - std::transform(id.begin(), id.end(), id.begin(), ::tolower); - - if (id == "offset") { - qualifier.layoutOffset = value; - return; - } else if (id == "align") { - // "The specified alignment must be a power of 2, or a compile-time error results." - if (! IsPow2(value)) - error(loc, "must be a power of 2", "align", ""); - else - qualifier.layoutAlign = value; - return; - } else if (id == "location") { - if ((unsigned int)value >= TQualifier::layoutLocationEnd) - error(loc, "location is too large", id.c_str(), ""); - else - qualifier.layoutLocation = value; - return; - } else if (id == "set") { - if ((unsigned int)value >= TQualifier::layoutSetEnd) - error(loc, "set is too large", id.c_str(), ""); - else - qualifier.layoutSet = value; - return; - } else if (id == "binding") { - if ((unsigned int)value >= TQualifier::layoutBindingEnd) - error(loc, "binding is too large", id.c_str(), ""); - else - qualifier.layoutBinding = value; - return; - } else if (id == "component") { - if ((unsigned)value >= TQualifier::layoutComponentEnd) - error(loc, "component is too large", id.c_str(), ""); - else - qualifier.layoutComponent = value; - return; - } else if (id.compare(0, 4, "xfb_") == 0) { - // "Any shader making any static use (after preprocessing) of any of these - // *xfb_* qualifiers will cause the shader to be in a transform feedback - // capturing mode and hence responsible for describing the transform feedback - // setup." - intermediate.setXfbMode(); - if (id == "xfb_buffer") { - // "It is a compile-time error to specify an *xfb_buffer* that is greater than - // the implementation-dependent constant gl_MaxTransformFeedbackBuffers." - if (value >= resources.maxTransformFeedbackBuffers) - error(loc, "buffer is too large:", id.c_str(), "gl_MaxTransformFeedbackBuffers is %d", - resources.maxTransformFeedbackBuffers); - if (value >= (int)TQualifier::layoutXfbBufferEnd) - error(loc, "buffer is too large:", id.c_str(), "internal max is %d", TQualifier::layoutXfbBufferEnd - 1); - else - qualifier.layoutXfbBuffer = value; - return; - } else if (id == "xfb_offset") { - if (value >= (int)TQualifier::layoutXfbOffsetEnd) - error(loc, "offset is too large:", id.c_str(), "internal max is %d", TQualifier::layoutXfbOffsetEnd - 1); - else - qualifier.layoutXfbOffset = value; - return; - } else if (id == "xfb_stride") { - // "The resulting stride (implicit or explicit), when divided by 4, must be less than or equal to the - // implementation-dependent constant gl_MaxTransformFeedbackInterleavedComponents." - if (value > 4 * resources.maxTransformFeedbackInterleavedComponents) - error(loc, "1/4 stride is too large:", id.c_str(), "gl_MaxTransformFeedbackInterleavedComponents is %d", - resources.maxTransformFeedbackInterleavedComponents); - else if (value >= (int)TQualifier::layoutXfbStrideEnd) - error(loc, "stride is too large:", id.c_str(), "internal max is %d", TQualifier::layoutXfbStrideEnd - 1); - if (value < (int)TQualifier::layoutXfbStrideEnd) - qualifier.layoutXfbStride = value; - return; - } - } - - if (id == "input_attachment_index") { - requireVulkan(loc, "input_attachment_index"); - if (value >= (int)TQualifier::layoutAttachmentEnd) - error(loc, "attachment index is too large", id.c_str(), ""); - else - qualifier.layoutAttachment = value; - return; - } - if (id == "constant_id") { - setSpecConstantId(loc, qualifier, value); - return; - } - - switch (language) { - case EShLangVertex: - break; - - case EShLangTessControl: - if (id == "vertices") { - if (value == 0) - error(loc, "must be greater than 0", "vertices", ""); - else - // publicType.shaderQualifiers.vertices = value; - warn(loc, "ignored", id.c_str(), ""); - return; - } - break; - - case EShLangTessEvaluation: - break; - - case EShLangGeometry: - if (id == "invocations") { - if (value == 0) - error(loc, "must be at least 1", "invocations", ""); - else - // publicType.shaderQualifiers.invocations = value; - warn(loc, "ignored", id.c_str(), ""); - return; - } - if (id == "max_vertices") { - // publicType.shaderQualifiers.vertices = value; - warn(loc, "ignored", id.c_str(), ""); - if (value > resources.maxGeometryOutputVertices) - error(loc, "too large, must be less than gl_MaxGeometryOutputVertices", "max_vertices", ""); - return; - } - if (id == "stream") { - qualifier.layoutStream = value; - return; - } - break; - - case EShLangFragment: - if (id == "index") { - qualifier.layoutIndex = value; - return; - } - break; - - case EShLangCompute: - if (id.compare(0, 11, "local_size_") == 0) { - if (id == "local_size_x") { - // publicType.shaderQualifiers.localSize[0] = value; - warn(loc, "ignored", id.c_str(), ""); - return; - } - if (id == "local_size_y") { - // publicType.shaderQualifiers.localSize[1] = value; - warn(loc, "ignored", id.c_str(), ""); - return; - } - if (id == "local_size_z") { - // publicType.shaderQualifiers.localSize[2] = value; - warn(loc, "ignored", id.c_str(), ""); - return; - } - if (spvVersion.spv != 0) { - if (id == "local_size_x_id") { - // publicType.shaderQualifiers.localSizeSpecId[0] = value; - warn(loc, "ignored", id.c_str(), ""); - return; - } - if (id == "local_size_y_id") { - // publicType.shaderQualifiers.localSizeSpecId[1] = value; - warn(loc, "ignored", id.c_str(), ""); - return; - } - if (id == "local_size_z_id") { - // publicType.shaderQualifiers.localSizeSpecId[2] = value; - warn(loc, "ignored", id.c_str(), ""); - return; - } - } - } - break; - - default: - break; - } - - error(loc, "there is no such layout identifier for this stage taking an assigned value", id.c_str(), ""); -} - -void HlslParseContext::setSpecConstantId(const TSourceLoc& loc, TQualifier& qualifier, int value) -{ - if (value >= (int)TQualifier::layoutSpecConstantIdEnd) { - error(loc, "specialization-constant id is too large", "constant_id", ""); - } else { - qualifier.layoutSpecConstantId = value; - qualifier.specConstant = true; - if (! intermediate.addUsedConstantId(value)) - error(loc, "specialization-constant id already used", "constant_id", ""); - } - return; -} - -// Merge any layout qualifier information from src into dst, leaving everything else in dst alone -// -// "More than one layout qualifier may appear in a single declaration. -// Additionally, the same layout-qualifier-name can occur multiple times -// within a layout qualifier or across multiple layout qualifiers in the -// same declaration. When the same layout-qualifier-name occurs -// multiple times, in a single declaration, the last occurrence overrides -// the former occurrence(s). Further, if such a layout-qualifier-name -// will effect subsequent declarations or other observable behavior, it -// is only the last occurrence that will have any effect, behaving as if -// the earlier occurrence(s) within the declaration are not present. -// This is also true for overriding layout-qualifier-names, where one -// overrides the other (e.g., row_major vs. column_major); only the last -// occurrence has any effect." -// -void HlslParseContext::mergeObjectLayoutQualifiers(TQualifier& dst, const TQualifier& src, bool inheritOnly) -{ - if (src.hasMatrix()) - dst.layoutMatrix = src.layoutMatrix; - if (src.hasPacking()) - dst.layoutPacking = src.layoutPacking; - - if (src.hasStream()) - dst.layoutStream = src.layoutStream; - - if (src.hasFormat()) - dst.layoutFormat = src.layoutFormat; - - if (src.hasXfbBuffer()) - dst.layoutXfbBuffer = src.layoutXfbBuffer; - - if (src.hasAlign()) - dst.layoutAlign = src.layoutAlign; - - if (! inheritOnly) { - if (src.hasLocation()) - dst.layoutLocation = src.layoutLocation; - if (src.hasComponent()) - dst.layoutComponent = src.layoutComponent; - if (src.hasIndex()) - dst.layoutIndex = src.layoutIndex; - - if (src.hasOffset()) - dst.layoutOffset = src.layoutOffset; - - if (src.hasSet()) - dst.layoutSet = src.layoutSet; - if (src.layoutBinding != TQualifier::layoutBindingEnd) - dst.layoutBinding = src.layoutBinding; - - if (src.hasXfbStride()) - dst.layoutXfbStride = src.layoutXfbStride; - if (src.hasXfbOffset()) - dst.layoutXfbOffset = src.layoutXfbOffset; - if (src.hasAttachment()) - dst.layoutAttachment = src.layoutAttachment; - if (src.hasSpecConstantId()) - dst.layoutSpecConstantId = src.layoutSpecConstantId; - - if (src.layoutPushConstant) - dst.layoutPushConstant = true; - } -} - - -// -// Look up a function name in the symbol table, and make sure it is a function. -// -// First, look for an exact match. If there is none, use the generic selector -// TParseContextBase::selectFunction() to find one, parameterized by the -// convertible() and better() predicates defined below. -// -// Return the function symbol if found, otherwise nullptr. -// -const TFunction* HlslParseContext::findFunction(const TSourceLoc& loc, TFunction& call, bool& builtIn, int& thisDepth, - TIntermTyped*& args) -{ - if (symbolTable.isFunctionNameVariable(call.getName())) { - error(loc, "can't use function syntax on variable", call.getName().c_str(), ""); - return nullptr; - } - - // first, look for an exact match - bool dummyScope; - TSymbol* symbol = symbolTable.find(call.getMangledName(), &builtIn, &dummyScope, &thisDepth); - if (symbol) - return symbol->getAsFunction(); - - // no exact match, use the generic selector, parameterized by the GLSL rules - - // create list of candidates to send - TVector candidateList; - symbolTable.findFunctionNameList(call.getMangledName(), candidateList, builtIn); - - // These built-in ops can accept any type, so we bypass the argument selection - if (candidateList.size() == 1 && builtIn && - (candidateList[0]->getBuiltInOp() == EOpMethodAppend || - candidateList[0]->getBuiltInOp() == EOpMethodRestartStrip || - candidateList[0]->getBuiltInOp() == EOpMethodIncrementCounter || - candidateList[0]->getBuiltInOp() == EOpMethodDecrementCounter || - candidateList[0]->getBuiltInOp() == EOpMethodAppend || - candidateList[0]->getBuiltInOp() == EOpMethodConsume)) { - return candidateList[0]; - } - - bool allowOnlyUpConversions = true; - - // can 'from' convert to 'to'? - const auto convertible = [&](const TType& from, const TType& to, TOperator op, int arg) -> bool { - if (from == to) - return true; - - // no aggregate conversions - if (from.isArray() || to.isArray() || - from.isStruct() || to.isStruct()) - return false; - - switch (op) { - case EOpInterlockedAdd: - case EOpInterlockedAnd: - case EOpInterlockedCompareExchange: - case EOpInterlockedCompareStore: - case EOpInterlockedExchange: - case EOpInterlockedMax: - case EOpInterlockedMin: - case EOpInterlockedOr: - case EOpInterlockedXor: - // We do not promote the texture or image type for these ocodes. Normally that would not - // be an issue because it's a buffer, but we haven't decomposed the opcode yet, and at this - // stage it's merely e.g, a basic integer type. - // - // Instead, we want to promote other arguments, but stay within the same family. In other - // words, InterlockedAdd(RWBuffer, ...) will always use the int flavor, never the uint flavor, - // but it is allowed to promote its other arguments. - if (arg == 0) - return false; - break; - case EOpMethodSample: - case EOpMethodSampleBias: - case EOpMethodSampleCmp: - case EOpMethodSampleCmpLevelZero: - case EOpMethodSampleGrad: - case EOpMethodSampleLevel: - case EOpMethodLoad: - case EOpMethodGetDimensions: - case EOpMethodGetSamplePosition: - case EOpMethodGather: - case EOpMethodCalculateLevelOfDetail: - case EOpMethodCalculateLevelOfDetailUnclamped: - case EOpMethodGatherRed: - case EOpMethodGatherGreen: - case EOpMethodGatherBlue: - case EOpMethodGatherAlpha: - case EOpMethodGatherCmp: - case EOpMethodGatherCmpRed: - case EOpMethodGatherCmpGreen: - case EOpMethodGatherCmpBlue: - case EOpMethodGatherCmpAlpha: - case EOpMethodAppend: - case EOpMethodRestartStrip: - // those are method calls, the object type can not be changed - // they are equal if the dim and type match (is dim sufficient?) - if (arg == 0) - return from.getSampler().type == to.getSampler().type && - from.getSampler().arrayed == to.getSampler().arrayed && - from.getSampler().shadow == to.getSampler().shadow && - from.getSampler().ms == to.getSampler().ms && - from.getSampler().dim == to.getSampler().dim; - break; - default: - break; - } - - // basic types have to be convertible - if (allowOnlyUpConversions) - if (! intermediate.canImplicitlyPromote(from.getBasicType(), to.getBasicType(), EOpFunctionCall)) - return false; - - // shapes have to be convertible - if ((from.isScalarOrVec1() && to.isScalarOrVec1()) || - (from.isScalarOrVec1() && to.isVector()) || - (from.isScalarOrVec1() && to.isMatrix()) || - (from.isVector() && to.isVector() && from.getVectorSize() >= to.getVectorSize())) - return true; - - // TODO: what are the matrix rules? they go here - - return false; - }; - - // Is 'to2' a better conversion than 'to1'? - // Ties should not be considered as better. - // Assumes 'convertible' already said true. - const auto better = [](const TType& from, const TType& to1, const TType& to2) -> bool { - // exact match is always better than mismatch - if (from == to2) - return from != to1; - if (from == to1) - return false; - - // shape changes are always worse - if (from.isScalar() || from.isVector()) { - if (from.getVectorSize() == to2.getVectorSize() && - from.getVectorSize() != to1.getVectorSize()) - return true; - if (from.getVectorSize() == to1.getVectorSize() && - from.getVectorSize() != to2.getVectorSize()) - return false; - } - - // Handle sampler betterness: An exact sampler match beats a non-exact match. - // (If we just looked at basic type, all EbtSamplers would look the same). - // If any type is not a sampler, just use the linearize function below. - if (from.getBasicType() == EbtSampler && to1.getBasicType() == EbtSampler && to2.getBasicType() == EbtSampler) { - // We can ignore the vector size in the comparison. - TSampler to1Sampler = to1.getSampler(); - TSampler to2Sampler = to2.getSampler(); - - to1Sampler.vectorSize = to2Sampler.vectorSize = from.getSampler().vectorSize; - - if (from.getSampler() == to2Sampler) - return from.getSampler() != to1Sampler; - if (from.getSampler() == to1Sampler) - return false; - } - - // Might or might not be changing shape, which means basic type might - // or might not match, so within that, the question is how big a - // basic-type conversion is being done. - // - // Use a hierarchy of domains, translated to order of magnitude - // in a linearized view: - // - floating-point vs. integer - // - 32 vs. 64 bit (or width in general) - // - bool vs. non bool - // - signed vs. not signed - const auto linearize = [](const TBasicType& basicType) -> int { - switch (basicType) { - case EbtBool: return 1; - case EbtInt: return 10; - case EbtUint: return 11; - case EbtInt64: return 20; - case EbtUint64: return 21; - case EbtFloat: return 100; - case EbtDouble: return 110; - default: return 0; - } - }; - - return abs(linearize(to2.getBasicType()) - linearize(from.getBasicType())) < - abs(linearize(to1.getBasicType()) - linearize(from.getBasicType())); - }; - - // for ambiguity reporting - bool tie = false; - - // send to the generic selector - const TFunction* bestMatch = selectFunction(candidateList, call, convertible, better, tie); - - if (bestMatch == nullptr) { - // If there is nothing selected by allowing only up-conversions (to a larger linearize() value), - // we instead try down-conversions, which are valid in HLSL, but not preferred if there are any - // upconversions possible. - allowOnlyUpConversions = false; - bestMatch = selectFunction(candidateList, call, convertible, better, tie); - } - - if (bestMatch == nullptr) { - error(loc, "no matching overloaded function found", call.getName().c_str(), ""); - return nullptr; - } - - // For built-ins, we can convert across the arguments. This will happen in several steps: - // Step 1: If there's an exact match, use it. - // Step 2a: Otherwise, get the operator from the best match and promote arguments: - // Step 2b: reconstruct the TFunction based on the new arg types - // Step 3: Re-select after type promotion is applied, to find proper candidate. - if (builtIn) { - // Step 1: If there's an exact match, use it. - if (call.getMangledName() == bestMatch->getMangledName()) - return bestMatch; - - // Step 2a: Otherwise, get the operator from the best match and promote arguments as if we - // are that kind of operator. - if (args != nullptr) { - // The arg list can be a unary node, or an aggregate. We have to handle both. - // We will use the normal promote() facilities, which require an interm node. - TIntermOperator* promote = nullptr; - - if (call.getParamCount() == 1) { - promote = new TIntermUnary(bestMatch->getBuiltInOp()); - promote->getAsUnaryNode()->setOperand(args->getAsTyped()); - } else { - promote = new TIntermAggregate(bestMatch->getBuiltInOp()); - promote->getAsAggregate()->getSequence().swap(args->getAsAggregate()->getSequence()); - } - - if (! intermediate.promote(promote)) - return nullptr; - - // Obtain the promoted arg list. - if (call.getParamCount() == 1) { - args = promote->getAsUnaryNode()->getOperand(); - } else { - promote->getAsAggregate()->getSequence().swap(args->getAsAggregate()->getSequence()); - } - } - - // Step 2b: reconstruct the TFunction based on the new arg types - TFunction convertedCall(&call.getName(), call.getType(), call.getBuiltInOp()); - - if (args->getAsAggregate()) { - // Handle aggregates: put all args into the new function call - for (int arg=0; arggetAsAggregate()->getSequence().size()); ++arg) { - // TODO: But for constness, we could avoid the new & shallowCopy, and use the pointer directly. - TParameter param = { 0, new TType, nullptr }; - param.type->shallowCopy(args->getAsAggregate()->getSequence()[arg]->getAsTyped()->getType()); - convertedCall.addParameter(param); - } - } else if (args->getAsUnaryNode()) { - // Handle unaries: put all args into the new function call - TParameter param = { 0, new TType, nullptr }; - param.type->shallowCopy(args->getAsUnaryNode()->getOperand()->getAsTyped()->getType()); - convertedCall.addParameter(param); - } else if (args->getAsTyped()) { - // Handle bare e.g, floats, not in an aggregate. - TParameter param = { 0, new TType, nullptr }; - param.type->shallowCopy(args->getAsTyped()->getType()); - convertedCall.addParameter(param); - } else { - assert(0); // unknown argument list. - return nullptr; - } - - // Step 3: Re-select after type promotion, to find proper candidate - // send to the generic selector - bestMatch = selectFunction(candidateList, convertedCall, convertible, better, tie); - - // At this point, there should be no tie. - } - - if (tie) - error(loc, "ambiguous best function under implicit type conversion", call.getName().c_str(), ""); - - // Append default parameter values if needed - if (!tie && bestMatch != nullptr) { - for (int defParam = call.getParamCount(); defParam < bestMatch->getParamCount(); ++defParam) { - handleFunctionArgument(&call, args, (*bestMatch)[defParam].defaultValue); - } - } - - return bestMatch; -} - -// -// Do everything necessary to handle a typedef declaration, for a single symbol. -// -// 'parseType' is the type part of the declaration (to the left) -// 'arraySizes' is the arrayness tagged on the identifier (to the right) -// -void HlslParseContext::declareTypedef(const TSourceLoc& loc, const TString& identifier, const TType& parseType) -{ - TVariable* typeSymbol = new TVariable(&identifier, parseType, true); - if (! symbolTable.insert(*typeSymbol)) - error(loc, "name already defined", "typedef", identifier.c_str()); -} - -// Do everything necessary to handle a struct declaration, including -// making IO aliases because HLSL allows mixed IO in a struct that specializes -// based on the usage (input, output, uniform, none). -void HlslParseContext::declareStruct(const TSourceLoc& loc, TString& structName, TType& type) -{ - // If it was named, which means the type can be reused later, add - // it to the symbol table. (Unless it's a block, in which - // case the name is not a type.) - if (type.getBasicType() == EbtBlock || structName.size() == 0) - return; - - TVariable* userTypeDef = new TVariable(&structName, type, true); - if (! symbolTable.insert(*userTypeDef)) { - error(loc, "redefinition", structName.c_str(), "struct"); - return; - } - - // See if we need IO aliases for the structure typeList - - const auto condAlloc = [](bool pred, TTypeList*& list) { - if (pred && list == nullptr) - list = new TTypeList; - }; - - tIoKinds newLists = { nullptr, nullptr, nullptr }; // allocate for each kind found - for (auto member = type.getStruct()->begin(); member != type.getStruct()->end(); ++member) { - condAlloc(hasUniform(member->type->getQualifier()), newLists.uniform); - condAlloc( hasInput(member->type->getQualifier()), newLists.input); - condAlloc( hasOutput(member->type->getQualifier()), newLists.output); - - if (member->type->isStruct()) { - auto it = ioTypeMap.find(member->type->getStruct()); - if (it != ioTypeMap.end()) { - condAlloc(it->second.uniform != nullptr, newLists.uniform); - condAlloc(it->second.input != nullptr, newLists.input); - condAlloc(it->second.output != nullptr, newLists.output); - } - } - } - if (newLists.uniform == nullptr && - newLists.input == nullptr && - newLists.output == nullptr) { - // Won't do any IO caching, clear up the type and get out now. - for (auto member = type.getStruct()->begin(); member != type.getStruct()->end(); ++member) - clearUniformInputOutput(member->type->getQualifier()); - return; - } - - // We have IO involved. - - // Make a pure typeList for the symbol table, and cache side copies of IO versions. - for (auto member = type.getStruct()->begin(); member != type.getStruct()->end(); ++member) { - const auto inheritStruct = [&](TTypeList* s, TTypeLoc& ioMember) { - if (s != nullptr) { - ioMember.type = new TType; - ioMember.type->shallowCopy(*member->type); - ioMember.type->setStruct(s); - } - }; - const auto newMember = [&](TTypeLoc& m) { - if (m.type == nullptr) { - m.type = new TType; - m.type->shallowCopy(*member->type); - } - }; - - TTypeLoc newUniformMember = { nullptr, member->loc }; - TTypeLoc newInputMember = { nullptr, member->loc }; - TTypeLoc newOutputMember = { nullptr, member->loc }; - if (member->type->isStruct()) { - // swap in an IO child if there is one - auto it = ioTypeMap.find(member->type->getStruct()); - if (it != ioTypeMap.end()) { - inheritStruct(it->second.uniform, newUniformMember); - inheritStruct(it->second.input, newInputMember); - inheritStruct(it->second.output, newOutputMember); - } - } - if (newLists.uniform) { - newMember(newUniformMember); - - // inherit default matrix layout (changeable via #pragma pack_matrix), if none given. - if (member->type->isMatrix() && member->type->getQualifier().layoutMatrix == ElmNone) - newUniformMember.type->getQualifier().layoutMatrix = globalUniformDefaults.layoutMatrix; - - correctUniform(newUniformMember.type->getQualifier()); - newLists.uniform->push_back(newUniformMember); - } - if (newLists.input) { - newMember(newInputMember); - correctInput(newInputMember.type->getQualifier()); - newLists.input->push_back(newInputMember); - } - if (newLists.output) { - newMember(newOutputMember); - correctOutput(newOutputMember.type->getQualifier()); - newLists.output->push_back(newOutputMember); - } - - // make original pure - clearUniformInputOutput(member->type->getQualifier()); - } - ioTypeMap[type.getStruct()] = newLists; -} - -// Lookup a user-type by name. -// If found, fill in the type and return the defining symbol. -// If not found, return nullptr. -TSymbol* HlslParseContext::lookupUserType(const TString& typeName, TType& type) -{ - TSymbol* symbol = symbolTable.find(typeName); - if (symbol && symbol->getAsVariable() && symbol->getAsVariable()->isUserType()) { - type.shallowCopy(symbol->getType()); - return symbol; - } else - return nullptr; -} - -// -// Do everything necessary to handle a variable (non-block) declaration. -// Either redeclaring a variable, or making a new one, updating the symbol -// table, and all error checking. -// -// Returns a subtree node that computes an initializer, if needed. -// Returns nullptr if there is no code to execute for initialization. -// -// 'parseType' is the type part of the declaration (to the left) -// 'arraySizes' is the arrayness tagged on the identifier (to the right) -// -TIntermNode* HlslParseContext::declareVariable(const TSourceLoc& loc, const TString& identifier, TType& type, - TIntermTyped* initializer) -{ - if (voidErrorCheck(loc, identifier, type.getBasicType())) - return nullptr; - - // Global consts with initializers that are non-const act like EvqGlobal in HLSL. - // This test is implicitly recursive, because initializers propagate constness - // up the aggregate node tree during creation. E.g, for: - // { { 1, 2 }, { 3, 4 } } - // the initializer list is marked EvqConst at the top node, and remains so here. However: - // { 1, { myvar, 2 }, 3 } - // is not a const intializer, and still becomes EvqGlobal here. - - const bool nonConstInitializer = (initializer != nullptr && initializer->getQualifier().storage != EvqConst); - - if (type.getQualifier().storage == EvqConst && symbolTable.atGlobalLevel() && nonConstInitializer) { - // Force to global - type.getQualifier().storage = EvqGlobal; - } - - // make const and initialization consistent - fixConstInit(loc, identifier, type, initializer); - - // Check for redeclaration of built-ins and/or attempting to declare a reserved name - TSymbol* symbol = nullptr; - - inheritGlobalDefaults(type.getQualifier()); - - const bool flattenVar = shouldFlatten(type, type.getQualifier().storage, true); - - // correct IO in the type - switch (type.getQualifier().storage) { - case EvqGlobal: - case EvqTemporary: - clearUniformInputOutput(type.getQualifier()); - break; - case EvqUniform: - case EvqBuffer: - correctUniform(type.getQualifier()); - if (type.isStruct()) { - auto it = ioTypeMap.find(type.getStruct()); - if (it != ioTypeMap.end()) - type.setStruct(it->second.uniform); - } - - break; - default: - break; - } - - // Declare the variable - if (type.isArray()) { - // array case - declareArray(loc, identifier, type, symbol, !flattenVar); - } else { - // non-array case - if (symbol == nullptr) - symbol = declareNonArray(loc, identifier, type, !flattenVar); - else if (type != symbol->getType()) - error(loc, "cannot change the type of", "redeclaration", symbol->getName().c_str()); - } - - if (symbol == nullptr) - return nullptr; - - if (flattenVar) - flatten(*symbol->getAsVariable(), symbolTable.atGlobalLevel()); - - if (initializer == nullptr) - return nullptr; - - // Deal with initializer - TVariable* variable = symbol->getAsVariable(); - if (variable == nullptr) { - error(loc, "initializer requires a variable, not a member", identifier.c_str(), ""); - return nullptr; - } - return executeInitializer(loc, initializer, variable); -} - -// Pick up global defaults from the provide global defaults into dst. -void HlslParseContext::inheritGlobalDefaults(TQualifier& dst) const -{ - if (dst.storage == EvqVaryingOut) { - if (! dst.hasStream() && language == EShLangGeometry) - dst.layoutStream = globalOutputDefaults.layoutStream; - if (! dst.hasXfbBuffer()) - dst.layoutXfbBuffer = globalOutputDefaults.layoutXfbBuffer; - } -} - -// -// Make an internal-only variable whose name is for debug purposes only -// and won't be searched for. Callers will only use the return value to use -// the variable, not the name to look it up. It is okay if the name -// is the same as other names; there won't be any conflict. -// -TVariable* HlslParseContext::makeInternalVariable(const char* name, const TType& type) const -{ - TString* nameString = NewPoolTString(name); - TVariable* variable = new TVariable(nameString, type); - symbolTable.makeInternalVariable(*variable); - - return variable; -} - -// Make a symbol node holding a new internal temporary variable. -TIntermSymbol* HlslParseContext::makeInternalVariableNode(const TSourceLoc& loc, const char* name, - const TType& type) const -{ - TVariable* tmpVar = makeInternalVariable(name, type); - tmpVar->getWritableType().getQualifier().makeTemporary(); - - return intermediate.addSymbol(*tmpVar, loc); -} - -// -// Declare a non-array variable, the main point being there is no redeclaration -// for resizing allowed. -// -// Return the successfully declared variable. -// -TVariable* HlslParseContext::declareNonArray(const TSourceLoc& loc, const TString& identifier, const TType& type, - bool track) -{ - // make a new variable - TVariable* variable = new TVariable(&identifier, type); - - // add variable to symbol table - if (symbolTable.insert(*variable)) { - if (track && symbolTable.atGlobalLevel()) - trackLinkage(*variable); - return variable; - } - - error(loc, "redefinition", variable->getName().c_str(), ""); - return nullptr; -} - -// -// Handle all types of initializers from the grammar. -// -// Returning nullptr just means there is no code to execute to handle the -// initializer, which will, for example, be the case for constant initializers. -// -TIntermNode* HlslParseContext::executeInitializer(const TSourceLoc& loc, TIntermTyped* initializer, TVariable* variable) -{ - // - // Identifier must be of type constant, a global, or a temporary, and - // starting at version 120, desktop allows uniforms to have initializers. - // - TStorageQualifier qualifier = variable->getType().getQualifier().storage; - - // - // If the initializer was from braces { ... }, we convert the whole subtree to a - // constructor-style subtree, allowing the rest of the code to operate - // identically for both kinds of initializers. - // - // - // Type can't be deduced from the initializer list, so a skeletal type to - // follow has to be passed in. Constness and specialization-constness - // should be deduced bottom up, not dictated by the skeletal type. - // - TType skeletalType; - skeletalType.shallowCopy(variable->getType()); - skeletalType.getQualifier().makeTemporary(); - if (initializer->getAsAggregate() && initializer->getAsAggregate()->getOp() == EOpNull) - initializer = convertInitializerList(loc, skeletalType, initializer, nullptr); - if (initializer == nullptr) { - // error recovery; don't leave const without constant values - if (qualifier == EvqConst) - variable->getWritableType().getQualifier().storage = EvqTemporary; - return nullptr; - } - - // Fix outer arrayness if variable is unsized, getting size from the initializer - if (initializer->getType().isSizedArray() && variable->getType().isUnsizedArray()) - variable->getWritableType().changeOuterArraySize(initializer->getType().getOuterArraySize()); - - // Inner arrayness can also get set by an initializer - if (initializer->getType().isArrayOfArrays() && variable->getType().isArrayOfArrays() && - initializer->getType().getArraySizes()->getNumDims() == - variable->getType().getArraySizes()->getNumDims()) { - // adopt unsized sizes from the initializer's sizes - for (int d = 1; d < variable->getType().getArraySizes()->getNumDims(); ++d) { - if (variable->getType().getArraySizes()->getDimSize(d) == UnsizedArraySize) { - variable->getWritableType().getArraySizes()->setDimSize(d, - initializer->getType().getArraySizes()->getDimSize(d)); - } - } - } - - // Uniform and global consts require a constant initializer - if (qualifier == EvqUniform && initializer->getType().getQualifier().storage != EvqConst) { - error(loc, "uniform initializers must be constant", "=", "'%s'", variable->getType().getCompleteString().c_str()); - variable->getWritableType().getQualifier().storage = EvqTemporary; - return nullptr; - } - - // Const variables require a constant initializer - if (qualifier == EvqConst) { - if (initializer->getType().getQualifier().storage != EvqConst) { - variable->getWritableType().getQualifier().storage = EvqConstReadOnly; - qualifier = EvqConstReadOnly; - } - } - - if (qualifier == EvqConst || qualifier == EvqUniform) { - // Compile-time tagging of the variable with its constant value... - - initializer = intermediate.addConversion(EOpAssign, variable->getType(), initializer); - if (initializer != nullptr && variable->getType() != initializer->getType()) - initializer = intermediate.addUniShapeConversion(EOpAssign, variable->getType(), initializer); - if (initializer == nullptr || !initializer->getAsConstantUnion() || - variable->getType() != initializer->getType()) { - error(loc, "non-matching or non-convertible constant type for const initializer", - variable->getType().getStorageQualifierString(), ""); - variable->getWritableType().getQualifier().storage = EvqTemporary; - return nullptr; - } - - variable->setConstArray(initializer->getAsConstantUnion()->getConstArray()); - } else { - // normal assigning of a value to a variable... - specializationCheck(loc, initializer->getType(), "initializer"); - TIntermSymbol* intermSymbol = intermediate.addSymbol(*variable, loc); - TIntermNode* initNode = handleAssign(loc, EOpAssign, intermSymbol, initializer); - if (initNode == nullptr) - assignError(loc, "=", intermSymbol->getCompleteString(), initializer->getCompleteString()); - return initNode; - } - - return nullptr; -} - -// -// Reprocess any initializer-list { ... } parts of the initializer. -// Need to hierarchically assign correct types and implicit -// conversions. Will do this mimicking the same process used for -// creating a constructor-style initializer, ensuring we get the -// same form. -// -// Returns a node representing an expression for the initializer list expressed -// as the correct type. -// -// Returns nullptr if there is an error. -// -TIntermTyped* HlslParseContext::convertInitializerList(const TSourceLoc& loc, const TType& type, - TIntermTyped* initializer, TIntermTyped* scalarInit) -{ - // Will operate recursively. Once a subtree is found that is constructor style, - // everything below it is already good: Only the "top part" of the initializer - // can be an initializer list, where "top part" can extend for several (or all) levels. - - // see if we have bottomed out in the tree within the initializer-list part - TIntermAggregate* initList = initializer->getAsAggregate(); - if (initList == nullptr || initList->getOp() != EOpNull) { - // We don't have a list, but if it's a scalar and the 'type' is a - // composite, we need to lengthen below to make it useful. - // Otherwise, this is an already formed object to initialize with. - if (type.isScalar() || !initializer->getType().isScalar()) - return initializer; - else - initList = intermediate.makeAggregate(initializer); - } - - // Of the initializer-list set of nodes, need to process bottom up, - // so recurse deep, then process on the way up. - - // Go down the tree here... - if (type.isArray()) { - // The type's array might be unsized, which could be okay, so base sizes on the size of the aggregate. - // Later on, initializer execution code will deal with array size logic. - TType arrayType; - arrayType.shallowCopy(type); // sharing struct stuff is fine - arrayType.copyArraySizes(*type.getArraySizes()); // but get a fresh copy of the array information, to edit below - - // edit array sizes to fill in unsized dimensions - if (type.isUnsizedArray()) - arrayType.changeOuterArraySize((int)initList->getSequence().size()); - - // set unsized array dimensions that can be derived from the initializer's first element - if (arrayType.isArrayOfArrays() && initList->getSequence().size() > 0) { - TIntermTyped* firstInit = initList->getSequence()[0]->getAsTyped(); - if (firstInit->getType().isArray() && - arrayType.getArraySizes()->getNumDims() == firstInit->getType().getArraySizes()->getNumDims() + 1) { - for (int d = 1; d < arrayType.getArraySizes()->getNumDims(); ++d) { - if (arrayType.getArraySizes()->getDimSize(d) == UnsizedArraySize) - arrayType.getArraySizes()->setDimSize(d, firstInit->getType().getArraySizes()->getDimSize(d - 1)); - } - } - } - - // lengthen list to be long enough - lengthenList(loc, initList->getSequence(), arrayType.getOuterArraySize(), scalarInit); - - // recursively process each element - TType elementType(arrayType, 0); // dereferenced type - for (int i = 0; i < arrayType.getOuterArraySize(); ++i) { - initList->getSequence()[i] = convertInitializerList(loc, elementType, - initList->getSequence()[i]->getAsTyped(), scalarInit); - if (initList->getSequence()[i] == nullptr) - return nullptr; - } - - return addConstructor(loc, initList, arrayType); - } else if (type.isStruct()) { - // do we have implicit assignments to opaques? - for (size_t i = initList->getSequence().size(); i < type.getStruct()->size(); ++i) { - if ((*type.getStruct())[i].type->containsOpaque()) { - error(loc, "cannot implicitly initialize opaque members", "initializer list", ""); - return nullptr; - } - } - - // lengthen list to be long enough - lengthenList(loc, initList->getSequence(), static_cast(type.getStruct()->size()), scalarInit); - - if (type.getStruct()->size() != initList->getSequence().size()) { - error(loc, "wrong number of structure members", "initializer list", ""); - return nullptr; - } - for (size_t i = 0; i < type.getStruct()->size(); ++i) { - initList->getSequence()[i] = convertInitializerList(loc, *(*type.getStruct())[i].type, - initList->getSequence()[i]->getAsTyped(), scalarInit); - if (initList->getSequence()[i] == nullptr) - return nullptr; - } - } else if (type.isMatrix()) { - if (type.computeNumComponents() == (int)initList->getSequence().size()) { - // This means the matrix is initialized component-wise, rather than as - // a series of rows and columns. We can just use the list directly as - // a constructor; no further processing needed. - } else { - // lengthen list to be long enough - lengthenList(loc, initList->getSequence(), type.getMatrixCols(), scalarInit); - - if (type.getMatrixCols() != (int)initList->getSequence().size()) { - error(loc, "wrong number of matrix columns:", "initializer list", type.getCompleteString().c_str()); - return nullptr; - } - TType vectorType(type, 0); // dereferenced type - for (int i = 0; i < type.getMatrixCols(); ++i) { - initList->getSequence()[i] = convertInitializerList(loc, vectorType, - initList->getSequence()[i]->getAsTyped(), scalarInit); - if (initList->getSequence()[i] == nullptr) - return nullptr; - } - } - } else if (type.isVector()) { - // lengthen list to be long enough - lengthenList(loc, initList->getSequence(), type.getVectorSize(), scalarInit); - - // error check; we're at bottom, so work is finished below - if (type.getVectorSize() != (int)initList->getSequence().size()) { - error(loc, "wrong vector size (or rows in a matrix column):", "initializer list", - type.getCompleteString().c_str()); - return nullptr; - } - } else if (type.isScalar()) { - // lengthen list to be long enough - lengthenList(loc, initList->getSequence(), 1, scalarInit); - - if ((int)initList->getSequence().size() != 1) { - error(loc, "scalar expected one element:", "initializer list", type.getCompleteString().c_str()); - return nullptr; - } - } else { - error(loc, "unexpected initializer-list type:", "initializer list", type.getCompleteString().c_str()); - return nullptr; - } - - // Now that the subtree is processed, process this node as if the - // initializer list is a set of arguments to a constructor. - TIntermTyped* emulatedConstructorArguments; - if (initList->getSequence().size() == 1) - emulatedConstructorArguments = initList->getSequence()[0]->getAsTyped(); - else - emulatedConstructorArguments = initList; - - return addConstructor(loc, emulatedConstructorArguments, type); -} - -// Lengthen list to be long enough to cover any gap from the current list size -// to 'size'. If the list is longer, do nothing. -// The value to lengthen with is the default for short lists. -// -// By default, lists that are too short due to lack of initializers initialize to zero. -// Alternatively, it could be a scalar initializer for a structure. Both cases are handled, -// based on whether something is passed in as 'scalarInit'. -// -// 'scalarInit' must be safe to use each time this is called (no side effects replication). -// -void HlslParseContext::lengthenList(const TSourceLoc& loc, TIntermSequence& list, int size, TIntermTyped* scalarInit) -{ - for (int c = (int)list.size(); c < size; ++c) { - if (scalarInit == nullptr) - list.push_back(intermediate.addConstantUnion(0, loc)); - else - list.push_back(scalarInit); - } -} - -// -// Test for the correctness of the parameters passed to various constructor functions -// and also convert them to the right data type, if allowed and required. -// -// Returns nullptr for an error or the constructed node (aggregate or typed) for no error. -// -TIntermTyped* HlslParseContext::handleConstructor(const TSourceLoc& loc, TIntermTyped* node, const TType& type) -{ - if (node == nullptr) - return nullptr; - - // Handle the idiom "(struct type)" - if (type.isStruct() && isScalarConstructor(node)) { - // 'node' will almost always get used multiple times, so should not be used directly, - // it would create a DAG instead of a tree, which might be okay (would - // like to formalize that for constants and symbols), but if it has - // side effects, they would get executed multiple times, which is not okay. - if (node->getAsConstantUnion() == nullptr && node->getAsSymbolNode() == nullptr) { - TIntermAggregate* seq = intermediate.makeAggregate(loc); - TIntermSymbol* copy = makeInternalVariableNode(loc, "scalarCopy", node->getType()); - seq = intermediate.growAggregate(seq, intermediate.addBinaryNode(EOpAssign, copy, node, loc)); - seq = intermediate.growAggregate(seq, convertInitializerList(loc, type, intermediate.makeAggregate(loc), copy)); - seq->setOp(EOpComma); - seq->setType(type); - return seq; - } else - return convertInitializerList(loc, type, intermediate.makeAggregate(loc), node); - } - - return addConstructor(loc, node, type); -} - -// Add a constructor, either from the grammar, or other programmatic reasons. -// -// 'node' is what to construct from. -// 'type' is what type to construct. -// -// Returns the constructed object. -// Return nullptr if it can't be done. -// -TIntermTyped* HlslParseContext::addConstructor(const TSourceLoc& loc, TIntermTyped* node, const TType& type) -{ - TIntermAggregate* aggrNode = node->getAsAggregate(); - TOperator op = intermediate.mapTypeToConstructorOp(type); - - // Combined texture-sampler constructors are completely semantic checked - // in constructorTextureSamplerError() - if (op == EOpConstructTextureSampler) - return intermediate.setAggregateOperator(aggrNode, op, type, loc); - - TTypeList::const_iterator memberTypes; - if (op == EOpConstructStruct) - memberTypes = type.getStruct()->begin(); - - TType elementType; - if (type.isArray()) { - TType dereferenced(type, 0); - elementType.shallowCopy(dereferenced); - } else - elementType.shallowCopy(type); - - bool singleArg; - if (aggrNode != nullptr) { - if (aggrNode->getOp() != EOpNull) - singleArg = true; - else - singleArg = false; - } else - singleArg = true; - - TIntermTyped *newNode; - if (singleArg) { - // Handle array -> array conversion - // Constructing an array of one type from an array of another type is allowed, - // assuming there are enough components available (semantic-checked earlier). - if (type.isArray() && node->isArray()) - newNode = convertArray(node, type); - - // If structure constructor or array constructor is being called - // for only one parameter inside the aggregate, we need to call constructAggregate function once. - else if (type.isArray()) - newNode = constructAggregate(node, elementType, 1, node->getLoc()); - else if (op == EOpConstructStruct) - newNode = constructAggregate(node, *(*memberTypes).type, 1, node->getLoc()); - else { - // shape conversion for matrix constructor from scalar. HLSL semantics are: scalar - // is replicated into every element of the matrix (not just the diagnonal), so - // that is handled specially here. - if (type.isMatrix() && node->getType().isScalarOrVec1()) - node = intermediate.addShapeConversion(type, node); - - newNode = constructBuiltIn(type, op, node, node->getLoc(), false); - } - - if (newNode && (type.isArray() || op == EOpConstructStruct)) - newNode = intermediate.setAggregateOperator(newNode, EOpConstructStruct, type, loc); - - return newNode; - } - - // - // Handle list of arguments. - // - TIntermSequence& sequenceVector = aggrNode->getSequence(); // Stores the information about the parameter to the constructor - // if the structure constructor contains more than one parameter, then construct - // each parameter - - int paramCount = 0; // keeps a track of the constructor parameter number being checked - - // for each parameter to the constructor call, check to see if the right type is passed or convert them - // to the right type if possible (and allowed). - // for structure constructors, just check if the right type is passed, no conversion is allowed. - - for (TIntermSequence::iterator p = sequenceVector.begin(); - p != sequenceVector.end(); p++, paramCount++) { - if (type.isArray()) - newNode = constructAggregate(*p, elementType, paramCount + 1, node->getLoc()); - else if (op == EOpConstructStruct) - newNode = constructAggregate(*p, *(memberTypes[paramCount]).type, paramCount + 1, node->getLoc()); - else - newNode = constructBuiltIn(type, op, (*p)->getAsTyped(), node->getLoc(), true); - - if (newNode) - *p = newNode; - else - return nullptr; - } - - TIntermTyped* constructor = intermediate.setAggregateOperator(aggrNode, op, type, loc); - - return constructor; -} - -// Function for constructor implementation. Calls addUnaryMath with appropriate EOp value -// for the parameter to the constructor (passed to this function). Essentially, it converts -// the parameter types correctly. If a constructor expects an int (like ivec2) and is passed a -// float, then float is converted to int. -// -// Returns nullptr for an error or the constructed node. -// -TIntermTyped* HlslParseContext::constructBuiltIn(const TType& type, TOperator op, TIntermTyped* node, - const TSourceLoc& loc, bool subset) -{ - TIntermTyped* newNode; - TOperator basicOp; - - // - // First, convert types as needed. - // - switch (op) { - case EOpConstructF16Vec2: - case EOpConstructF16Vec3: - case EOpConstructF16Vec4: - case EOpConstructF16Mat2x2: - case EOpConstructF16Mat2x3: - case EOpConstructF16Mat2x4: - case EOpConstructF16Mat3x2: - case EOpConstructF16Mat3x3: - case EOpConstructF16Mat3x4: - case EOpConstructF16Mat4x2: - case EOpConstructF16Mat4x3: - case EOpConstructF16Mat4x4: - case EOpConstructFloat16: - basicOp = EOpConstructFloat16; - break; - - case EOpConstructVec2: - case EOpConstructVec3: - case EOpConstructVec4: - case EOpConstructMat2x2: - case EOpConstructMat2x3: - case EOpConstructMat2x4: - case EOpConstructMat3x2: - case EOpConstructMat3x3: - case EOpConstructMat3x4: - case EOpConstructMat4x2: - case EOpConstructMat4x3: - case EOpConstructMat4x4: - case EOpConstructFloat: - basicOp = EOpConstructFloat; - break; - - case EOpConstructDVec2: - case EOpConstructDVec3: - case EOpConstructDVec4: - case EOpConstructDMat2x2: - case EOpConstructDMat2x3: - case EOpConstructDMat2x4: - case EOpConstructDMat3x2: - case EOpConstructDMat3x3: - case EOpConstructDMat3x4: - case EOpConstructDMat4x2: - case EOpConstructDMat4x3: - case EOpConstructDMat4x4: - case EOpConstructDouble: - basicOp = EOpConstructDouble; - break; - - case EOpConstructI16Vec2: - case EOpConstructI16Vec3: - case EOpConstructI16Vec4: - case EOpConstructInt16: - basicOp = EOpConstructInt16; - break; - - case EOpConstructIVec2: - case EOpConstructIVec3: - case EOpConstructIVec4: - case EOpConstructIMat2x2: - case EOpConstructIMat2x3: - case EOpConstructIMat2x4: - case EOpConstructIMat3x2: - case EOpConstructIMat3x3: - case EOpConstructIMat3x4: - case EOpConstructIMat4x2: - case EOpConstructIMat4x3: - case EOpConstructIMat4x4: - case EOpConstructInt: - basicOp = EOpConstructInt; - break; - - case EOpConstructU16Vec2: - case EOpConstructU16Vec3: - case EOpConstructU16Vec4: - case EOpConstructUint16: - basicOp = EOpConstructUint16; - break; - - case EOpConstructUVec2: - case EOpConstructUVec3: - case EOpConstructUVec4: - case EOpConstructUMat2x2: - case EOpConstructUMat2x3: - case EOpConstructUMat2x4: - case EOpConstructUMat3x2: - case EOpConstructUMat3x3: - case EOpConstructUMat3x4: - case EOpConstructUMat4x2: - case EOpConstructUMat4x3: - case EOpConstructUMat4x4: - case EOpConstructUint: - basicOp = EOpConstructUint; - break; - - case EOpConstructBVec2: - case EOpConstructBVec3: - case EOpConstructBVec4: - case EOpConstructBMat2x2: - case EOpConstructBMat2x3: - case EOpConstructBMat2x4: - case EOpConstructBMat3x2: - case EOpConstructBMat3x3: - case EOpConstructBMat3x4: - case EOpConstructBMat4x2: - case EOpConstructBMat4x3: - case EOpConstructBMat4x4: - case EOpConstructBool: - basicOp = EOpConstructBool; - break; - - default: - error(loc, "unsupported construction", "", ""); - - return nullptr; - } - newNode = intermediate.addUnaryMath(basicOp, node, node->getLoc()); - if (newNode == nullptr) { - error(loc, "can't convert", "constructor", ""); - return nullptr; - } - - // - // Now, if there still isn't an operation to do the construction, and we need one, add one. - // - - // Otherwise, skip out early. - if (subset || (newNode != node && newNode->getType() == type)) - return newNode; - - // setAggregateOperator will insert a new node for the constructor, as needed. - return intermediate.setAggregateOperator(newNode, op, type, loc); -} - -// Convert the array in node to the requested type, which is also an array. -// Returns nullptr on failure, otherwise returns aggregate holding the list of -// elements needed to construct the array. -TIntermTyped* HlslParseContext::convertArray(TIntermTyped* node, const TType& type) -{ - assert(node->isArray() && type.isArray()); - if (node->getType().computeNumComponents() < type.computeNumComponents()) - return nullptr; - - // TODO: write an argument replicator, for the case the argument should not be - // executed multiple times, yet multiple copies are needed. - - TIntermTyped* constructee = node->getAsTyped(); - // track where we are in consuming the argument - int constructeeElement = 0; - int constructeeComponent = 0; - - // bump up to the next component to consume - const auto getNextComponent = [&]() { - TIntermTyped* component; - component = handleBracketDereference(node->getLoc(), constructee, - intermediate.addConstantUnion(constructeeElement, node->getLoc())); - if (component->isVector()) - component = handleBracketDereference(node->getLoc(), component, - intermediate.addConstantUnion(constructeeComponent, node->getLoc())); - // bump component pointer up - ++constructeeComponent; - if (constructeeComponent == constructee->getVectorSize()) { - constructeeComponent = 0; - ++constructeeElement; - } - return component; - }; - - // make one subnode per constructed array element - TIntermAggregate* constructor = nullptr; - TType derefType(type, 0); - TType speculativeComponentType(derefType, 0); - TType* componentType = derefType.isVector() ? &speculativeComponentType : &derefType; - TOperator componentOp = intermediate.mapTypeToConstructorOp(*componentType); - TType crossType(node->getBasicType(), EvqTemporary, type.getVectorSize()); - for (int e = 0; e < type.getOuterArraySize(); ++e) { - // construct an element - TIntermTyped* elementArg; - if (type.getVectorSize() == constructee->getVectorSize()) { - // same element shape - elementArg = handleBracketDereference(node->getLoc(), constructee, - intermediate.addConstantUnion(e, node->getLoc())); - } else { - // mismatched element shapes - if (type.getVectorSize() == 1) - elementArg = getNextComponent(); - else { - // make a vector - TIntermAggregate* elementConstructee = nullptr; - for (int c = 0; c < type.getVectorSize(); ++c) - elementConstructee = intermediate.growAggregate(elementConstructee, getNextComponent()); - elementArg = addConstructor(node->getLoc(), elementConstructee, crossType); - } - } - // convert basic types - elementArg = intermediate.addConversion(componentOp, derefType, elementArg); - if (elementArg == nullptr) - return nullptr; - // combine with top-level constructor - constructor = intermediate.growAggregate(constructor, elementArg); - } - - return constructor; -} - -// This function tests for the type of the parameters to the structure or array constructor. Raises -// an error message if the expected type does not match the parameter passed to the constructor. -// -// Returns nullptr for an error or the input node itself if the expected and the given parameter types match. -// -TIntermTyped* HlslParseContext::constructAggregate(TIntermNode* node, const TType& type, int paramCount, - const TSourceLoc& loc) -{ - // Handle cases that map more 1:1 between constructor arguments and constructed. - TIntermTyped* converted = intermediate.addConversion(EOpConstructStruct, type, node->getAsTyped()); - if (converted == nullptr || converted->getType() != type) { - error(loc, "", "constructor", "cannot convert parameter %d from '%s' to '%s'", paramCount, - node->getAsTyped()->getType().getCompleteString().c_str(), type.getCompleteString().c_str()); - - return nullptr; - } - - return converted; -} - -// -// Do everything needed to add an interface block. -// -void HlslParseContext::declareBlock(const TSourceLoc& loc, TType& type, const TString* instanceName) -{ - assert(type.getWritableStruct() != nullptr); - - // Clean up top-level decorations that don't belong. - switch (type.getQualifier().storage) { - case EvqUniform: - case EvqBuffer: - correctUniform(type.getQualifier()); - break; - case EvqVaryingIn: - correctInput(type.getQualifier()); - break; - case EvqVaryingOut: - correctOutput(type.getQualifier()); - break; - default: - break; - } - - TTypeList& typeList = *type.getWritableStruct(); - // fix and check for member storage qualifiers and types that don't belong within a block - for (unsigned int member = 0; member < typeList.size(); ++member) { - TType& memberType = *typeList[member].type; - TQualifier& memberQualifier = memberType.getQualifier(); - const TSourceLoc& memberLoc = typeList[member].loc; - globalQualifierFix(memberLoc, memberQualifier); - memberQualifier.storage = type.getQualifier().storage; - - if (memberType.isStruct()) { - // clean up and pick up the right set of decorations - auto it = ioTypeMap.find(memberType.getStruct()); - switch (type.getQualifier().storage) { - case EvqUniform: - case EvqBuffer: - correctUniform(type.getQualifier()); - if (it != ioTypeMap.end() && it->second.uniform) - memberType.setStruct(it->second.uniform); - break; - case EvqVaryingIn: - correctInput(type.getQualifier()); - if (it != ioTypeMap.end() && it->second.input) - memberType.setStruct(it->second.input); - break; - case EvqVaryingOut: - correctOutput(type.getQualifier()); - if (it != ioTypeMap.end() && it->second.output) - memberType.setStruct(it->second.output); - break; - default: - break; - } - } - } - - // Make default block qualification, and adjust the member qualifications - - TQualifier defaultQualification; - switch (type.getQualifier().storage) { - case EvqUniform: defaultQualification = globalUniformDefaults; break; - case EvqBuffer: defaultQualification = globalBufferDefaults; break; - case EvqVaryingIn: defaultQualification = globalInputDefaults; break; - case EvqVaryingOut: defaultQualification = globalOutputDefaults; break; - default: defaultQualification.clear(); break; - } - - // Special case for "push_constant uniform", which has a default of std430, - // contrary to normal uniform defaults, and can't have a default tracked for it. - if (type.getQualifier().layoutPushConstant && ! type.getQualifier().hasPacking()) - type.getQualifier().layoutPacking = ElpStd430; - - // fix and check for member layout qualifiers - - mergeObjectLayoutQualifiers(defaultQualification, type.getQualifier(), true); - - bool memberWithLocation = false; - bool memberWithoutLocation = false; - for (unsigned int member = 0; member < typeList.size(); ++member) { - TQualifier& memberQualifier = typeList[member].type->getQualifier(); - const TSourceLoc& memberLoc = typeList[member].loc; - if (memberQualifier.hasStream()) { - if (defaultQualification.layoutStream != memberQualifier.layoutStream) - error(memberLoc, "member cannot contradict block", "stream", ""); - } - - // "This includes a block's inheritance of the - // current global default buffer, a block member's inheritance of the block's - // buffer, and the requirement that any *xfb_buffer* declared on a block - // member must match the buffer inherited from the block." - if (memberQualifier.hasXfbBuffer()) { - if (defaultQualification.layoutXfbBuffer != memberQualifier.layoutXfbBuffer) - error(memberLoc, "member cannot contradict block (or what block inherited from global)", "xfb_buffer", ""); - } - - if (memberQualifier.hasLocation()) { - switch (type.getQualifier().storage) { - case EvqVaryingIn: - case EvqVaryingOut: - memberWithLocation = true; - break; - default: - break; - } - } else - memberWithoutLocation = true; - - TQualifier newMemberQualification = defaultQualification; - mergeQualifiers(newMemberQualification, memberQualifier); - memberQualifier = newMemberQualification; - } - - // Process the members - fixBlockLocations(loc, type.getQualifier(), typeList, memberWithLocation, memberWithoutLocation); - fixBlockXfbOffsets(type.getQualifier(), typeList); - fixBlockUniformOffsets(type.getQualifier(), typeList); - - // reverse merge, so that currentBlockQualifier now has all layout information - // (can't use defaultQualification directly, it's missing other non-layout-default-class qualifiers) - mergeObjectLayoutQualifiers(type.getQualifier(), defaultQualification, true); - - // - // Build and add the interface block as a new type named 'blockName' - // - - // Use the instance name as the interface name if one exists, else the block name. - const TString& interfaceName = (instanceName && !instanceName->empty()) ? *instanceName : type.getTypeName(); - - TType blockType(&typeList, interfaceName, type.getQualifier()); - if (type.isArray()) - blockType.transferArraySizes(type.getArraySizes()); - - // Add the variable, as anonymous or named instanceName. - // Make an anonymous variable if no name was provided. - if (instanceName == nullptr) - instanceName = NewPoolTString(""); - - TVariable& variable = *new TVariable(instanceName, blockType); - if (! symbolTable.insert(variable)) { - if (*instanceName == "") - error(loc, "nameless block contains a member that already has a name at global scope", - "" /* blockName->c_str() */, ""); - else - error(loc, "block instance name redefinition", variable.getName().c_str(), ""); - - return; - } - - // Save it in the AST for linker use. - if (symbolTable.atGlobalLevel()) - trackLinkage(variable); -} - -// -// "For a block, this process applies to the entire block, or until the first member -// is reached that has a location layout qualifier. When a block member is declared with a location -// qualifier, its location comes from that qualifier: The member's location qualifier overrides the block-level -// declaration. Subsequent members are again assigned consecutive locations, based on the newest location, -// until the next member declared with a location qualifier. The values used for locations do not have to be -// declared in increasing order." -void HlslParseContext::fixBlockLocations(const TSourceLoc& loc, TQualifier& qualifier, TTypeList& typeList, bool memberWithLocation, bool memberWithoutLocation) -{ - // "If a block has no block-level location layout qualifier, it is required that either all or none of its members - // have a location layout qualifier, or a compile-time error results." - if (! qualifier.hasLocation() && memberWithLocation && memberWithoutLocation) - error(loc, "either the block needs a location, or all members need a location, or no members have a location", "location", ""); - else { - if (memberWithLocation) { - // remove any block-level location and make it per *every* member - int nextLocation = 0; // by the rule above, initial value is not relevant - if (qualifier.hasAnyLocation()) { - nextLocation = qualifier.layoutLocation; - qualifier.layoutLocation = TQualifier::layoutLocationEnd; - if (qualifier.hasComponent()) { - // "It is a compile-time error to apply the *component* qualifier to a ... block" - error(loc, "cannot apply to a block", "component", ""); - } - if (qualifier.hasIndex()) { - error(loc, "cannot apply to a block", "index", ""); - } - } - for (unsigned int member = 0; member < typeList.size(); ++member) { - TQualifier& memberQualifier = typeList[member].type->getQualifier(); - const TSourceLoc& memberLoc = typeList[member].loc; - if (! memberQualifier.hasLocation()) { - if (nextLocation >= (int)TQualifier::layoutLocationEnd) - error(memberLoc, "location is too large", "location", ""); - memberQualifier.layoutLocation = nextLocation; - memberQualifier.layoutComponent = 0; - } - nextLocation = memberQualifier.layoutLocation + - intermediate.computeTypeLocationSize(*typeList[member].type, language); - } - } - } -} - -void HlslParseContext::fixBlockXfbOffsets(TQualifier& qualifier, TTypeList& typeList) -{ - // "If a block is qualified with xfb_offset, all its - // members are assigned transform feedback buffer offsets. If a block is not qualified with xfb_offset, any - // members of that block not qualified with an xfb_offset will not be assigned transform feedback buffer - // offsets." - - if (! qualifier.hasXfbBuffer() || ! qualifier.hasXfbOffset()) - return; - - int nextOffset = qualifier.layoutXfbOffset; - for (unsigned int member = 0; member < typeList.size(); ++member) { - TQualifier& memberQualifier = typeList[member].type->getQualifier(); - bool containsDouble = false; - int memberSize = intermediate.computeTypeXfbSize(*typeList[member].type, containsDouble); - // see if we need to auto-assign an offset to this member - if (! memberQualifier.hasXfbOffset()) { - // "if applied to an aggregate containing a double, the offset must also be a multiple of 8" - if (containsDouble) - RoundToPow2(nextOffset, 8); - memberQualifier.layoutXfbOffset = nextOffset; - } else - nextOffset = memberQualifier.layoutXfbOffset; - nextOffset += memberSize; - } - - // The above gave all block members an offset, so we can take it off the block now, - // which will avoid double counting the offset usage. - qualifier.layoutXfbOffset = TQualifier::layoutXfbOffsetEnd; -} - -// Calculate and save the offset of each block member, using the recursively -// defined block offset rules and the user-provided offset and align. -// -// Also, compute and save the total size of the block. For the block's size, arrayness -// is not taken into account, as each element is backed by a separate buffer. -// -void HlslParseContext::fixBlockUniformOffsets(const TQualifier& qualifier, TTypeList& typeList) -{ - if (! qualifier.isUniformOrBuffer()) - return; - if (qualifier.layoutPacking != ElpStd140 && qualifier.layoutPacking != ElpStd430) - return; - - int offset = 0; - int memberSize; - for (unsigned int member = 0; member < typeList.size(); ++member) { - TQualifier& memberQualifier = typeList[member].type->getQualifier(); - const TSourceLoc& memberLoc = typeList[member].loc; - - // "When align is applied to an array, it effects only the start of the array, not the array's internal stride." - - // modify just the children's view of matrix layout, if there is one for this member - TLayoutMatrix subMatrixLayout = typeList[member].type->getQualifier().layoutMatrix; - int dummyStride; - int memberAlignment = intermediate.getBaseAlignment(*typeList[member].type, memberSize, dummyStride, - qualifier.layoutPacking == ElpStd140, - subMatrixLayout != ElmNone - ? subMatrixLayout == ElmRowMajor - : qualifier.layoutMatrix == ElmRowMajor); - if (memberQualifier.hasOffset()) { - // "The specified offset must be a multiple - // of the base alignment of the type of the block member it qualifies, or a compile-time error results." - if (! IsMultipleOfPow2(memberQualifier.layoutOffset, memberAlignment)) - error(memberLoc, "must be a multiple of the member's alignment", "offset", ""); - - // "The offset qualifier forces the qualified member to start at or after the specified - // integral-constant expression, which will be its byte offset from the beginning of the buffer. - // "The actual offset of a member is computed as - // follows: If offset was declared, start with that offset, otherwise start with the next available offset." - offset = std::max(offset, memberQualifier.layoutOffset); - } - - // "The actual alignment of a member will be the greater of the specified align alignment and the standard - // (e.g., std140) base alignment for the member's type." - if (memberQualifier.hasAlign()) - memberAlignment = std::max(memberAlignment, memberQualifier.layoutAlign); - - // "If the resulting offset is not a multiple of the actual alignment, - // increase it to the first offset that is a multiple of - // the actual alignment." - RoundToPow2(offset, memberAlignment); - typeList[member].type->getQualifier().layoutOffset = offset; - offset += memberSize; - } -} - -// For an identifier that is already declared, add more qualification to it. -void HlslParseContext::addQualifierToExisting(const TSourceLoc& loc, TQualifier qualifier, const TString& identifier) -{ - TSymbol* symbol = symbolTable.find(identifier); - if (symbol == nullptr) { - error(loc, "identifier not previously declared", identifier.c_str(), ""); - return; - } - if (symbol->getAsFunction()) { - error(loc, "cannot re-qualify a function name", identifier.c_str(), ""); - return; - } - - if (qualifier.isAuxiliary() || - qualifier.isMemory() || - qualifier.isInterpolation() || - qualifier.hasLayout() || - qualifier.storage != EvqTemporary || - qualifier.precision != EpqNone) { - error(loc, "cannot add storage, auxiliary, memory, interpolation, layout, or precision qualifier to an existing variable", identifier.c_str(), ""); - return; - } - - // For read-only built-ins, add a new symbol for holding the modified qualifier. - // This will bring up an entire block, if a block type has to be modified (e.g., gl_Position inside a block) - if (symbol->isReadOnly()) - symbol = symbolTable.copyUp(symbol); - - if (qualifier.invariant) { - if (intermediate.inIoAccessed(identifier)) - error(loc, "cannot change qualification after use", "invariant", ""); - symbol->getWritableType().getQualifier().invariant = true; - } else if (qualifier.noContraction) { - if (intermediate.inIoAccessed(identifier)) - error(loc, "cannot change qualification after use", "precise", ""); - symbol->getWritableType().getQualifier().noContraction = true; - } else if (qualifier.specConstant) { - symbol->getWritableType().getQualifier().makeSpecConstant(); - if (qualifier.hasSpecConstantId()) - symbol->getWritableType().getQualifier().layoutSpecConstantId = qualifier.layoutSpecConstantId; - } else - warn(loc, "unknown requalification", "", ""); -} - -void HlslParseContext::addQualifierToExisting(const TSourceLoc& loc, TQualifier qualifier, TIdentifierList& identifiers) -{ - for (unsigned int i = 0; i < identifiers.size(); ++i) - addQualifierToExisting(loc, qualifier, *identifiers[i]); -} - -// -// Update the intermediate for the given input geometry -// -bool HlslParseContext::handleInputGeometry(const TSourceLoc& loc, const TLayoutGeometry& geometry) -{ - switch (geometry) { - case ElgPoints: // fall through - case ElgLines: // ... - case ElgTriangles: // ... - case ElgLinesAdjacency: // ... - case ElgTrianglesAdjacency: // ... - if (! intermediate.setInputPrimitive(geometry)) { - error(loc, "input primitive geometry redefinition", TQualifier::getGeometryString(geometry), ""); - return false; - } - break; - - default: - error(loc, "cannot apply to 'in'", TQualifier::getGeometryString(geometry), ""); - return false; - } - - return true; -} - -// -// Update the intermediate for the given output geometry -// -bool HlslParseContext::handleOutputGeometry(const TSourceLoc& loc, const TLayoutGeometry& geometry) -{ - // If this is not a geometry shader, ignore. It might be a mixed shader including several stages. - // Since that's an OK situation, return true for success. - if (language != EShLangGeometry) - return true; - - switch (geometry) { - case ElgPoints: - case ElgLineStrip: - case ElgTriangleStrip: - if (! intermediate.setOutputPrimitive(geometry)) { - error(loc, "output primitive geometry redefinition", TQualifier::getGeometryString(geometry), ""); - return false; - } - break; - default: - error(loc, "cannot apply to 'out'", TQualifier::getGeometryString(geometry), ""); - return false; - } - - return true; -} - -// -// Selection attributes -// -void HlslParseContext::handleSelectionAttributes(const TSourceLoc& loc, TIntermSelection* selection, - const TAttributes& attributes) -{ - if (selection == nullptr) - return; - - for (auto it = attributes.begin(); it != attributes.end(); ++it) { - switch (it->name) { - case EatFlatten: - selection->setFlatten(); - break; - case EatBranch: - selection->setDontFlatten(); - break; - default: - warn(loc, "attribute does not apply to a selection", "", ""); - break; - } - } -} - -// -// Switch attributes -// -void HlslParseContext::handleSwitchAttributes(const TSourceLoc& loc, TIntermSwitch* selection, - const TAttributes& attributes) -{ - if (selection == nullptr) - return; - - for (auto it = attributes.begin(); it != attributes.end(); ++it) { - switch (it->name) { - case EatFlatten: - selection->setFlatten(); - break; - case EatBranch: - selection->setDontFlatten(); - break; - default: - warn(loc, "attribute does not apply to a switch", "", ""); - break; - } - } -} - -// -// Loop attributes -// -void HlslParseContext::handleLoopAttributes(const TSourceLoc& loc, TIntermLoop* loop, - const TAttributes& attributes) -{ - if (loop == nullptr) - return; - - for (auto it = attributes.begin(); it != attributes.end(); ++it) { - switch (it->name) { - case EatUnroll: - loop->setUnroll(); - break; - case EatLoop: - loop->setDontUnroll(); - break; - default: - warn(loc, "attribute does not apply to a loop", "", ""); - break; - } - } -} - -// -// Updating default qualifier for the case of a declaration with just a qualifier, -// no type, block, or identifier. -// -void HlslParseContext::updateStandaloneQualifierDefaults(const TSourceLoc& loc, const TPublicType& publicType) -{ - if (publicType.shaderQualifiers.vertices != TQualifier::layoutNotSet) { - assert(language == EShLangTessControl || language == EShLangGeometry); - // const char* id = (language == EShLangTessControl) ? "vertices" : "max_vertices"; - } - if (publicType.shaderQualifiers.invocations != TQualifier::layoutNotSet) { - if (! intermediate.setInvocations(publicType.shaderQualifiers.invocations)) - error(loc, "cannot change previously set layout value", "invocations", ""); - } - if (publicType.shaderQualifiers.geometry != ElgNone) { - if (publicType.qualifier.storage == EvqVaryingIn) { - switch (publicType.shaderQualifiers.geometry) { - case ElgPoints: - case ElgLines: - case ElgLinesAdjacency: - case ElgTriangles: - case ElgTrianglesAdjacency: - case ElgQuads: - case ElgIsolines: - break; - default: - error(loc, "cannot apply to input", TQualifier::getGeometryString(publicType.shaderQualifiers.geometry), - ""); - } - } else if (publicType.qualifier.storage == EvqVaryingOut) { - handleOutputGeometry(loc, publicType.shaderQualifiers.geometry); - } else - error(loc, "cannot apply to:", TQualifier::getGeometryString(publicType.shaderQualifiers.geometry), - GetStorageQualifierString(publicType.qualifier.storage)); - } - if (publicType.shaderQualifiers.spacing != EvsNone) - intermediate.setVertexSpacing(publicType.shaderQualifiers.spacing); - if (publicType.shaderQualifiers.order != EvoNone) - intermediate.setVertexOrder(publicType.shaderQualifiers.order); - if (publicType.shaderQualifiers.pointMode) - intermediate.setPointMode(); - for (int i = 0; i < 3; ++i) { - if (publicType.shaderQualifiers.localSize[i] > 1) { - int max = 0; - switch (i) { - case 0: max = resources.maxComputeWorkGroupSizeX; break; - case 1: max = resources.maxComputeWorkGroupSizeY; break; - case 2: max = resources.maxComputeWorkGroupSizeZ; break; - default: break; - } - if (intermediate.getLocalSize(i) > (unsigned int)max) - error(loc, "too large; see gl_MaxComputeWorkGroupSize", "local_size", ""); - - // Fix the existing constant gl_WorkGroupSize with this new information. - TVariable* workGroupSize = getEditableVariable("gl_WorkGroupSize"); - workGroupSize->getWritableConstArray()[i].setUConst(intermediate.getLocalSize(i)); - } - if (publicType.shaderQualifiers.localSizeSpecId[i] != TQualifier::layoutNotSet) { - intermediate.setLocalSizeSpecId(i, publicType.shaderQualifiers.localSizeSpecId[i]); - // Set the workgroup built-in variable as a specialization constant - TVariable* workGroupSize = getEditableVariable("gl_WorkGroupSize"); - workGroupSize->getWritableType().getQualifier().specConstant = true; - } - } - if (publicType.shaderQualifiers.earlyFragmentTests) - intermediate.setEarlyFragmentTests(); - - const TQualifier& qualifier = publicType.qualifier; - - switch (qualifier.storage) { - case EvqUniform: - if (qualifier.hasMatrix()) - globalUniformDefaults.layoutMatrix = qualifier.layoutMatrix; - if (qualifier.hasPacking()) - globalUniformDefaults.layoutPacking = qualifier.layoutPacking; - break; - case EvqBuffer: - if (qualifier.hasMatrix()) - globalBufferDefaults.layoutMatrix = qualifier.layoutMatrix; - if (qualifier.hasPacking()) - globalBufferDefaults.layoutPacking = qualifier.layoutPacking; - break; - case EvqVaryingIn: - break; - case EvqVaryingOut: - if (qualifier.hasStream()) - globalOutputDefaults.layoutStream = qualifier.layoutStream; - if (qualifier.hasXfbBuffer()) - globalOutputDefaults.layoutXfbBuffer = qualifier.layoutXfbBuffer; - if (globalOutputDefaults.hasXfbBuffer() && qualifier.hasXfbStride()) { - if (! intermediate.setXfbBufferStride(globalOutputDefaults.layoutXfbBuffer, qualifier.layoutXfbStride)) - error(loc, "all stride settings must match for xfb buffer", "xfb_stride", "%d", - qualifier.layoutXfbBuffer); - } - break; - default: - error(loc, "default qualifier requires 'uniform', 'buffer', 'in', or 'out' storage qualification", "", ""); - return; - } -} - -// -// Take the sequence of statements that has been built up since the last case/default, -// put it on the list of top-level nodes for the current (inner-most) switch statement, -// and follow that by the case/default we are on now. (See switch topology comment on -// TIntermSwitch.) -// -void HlslParseContext::wrapupSwitchSubsequence(TIntermAggregate* statements, TIntermNode* branchNode) -{ - TIntermSequence* switchSequence = switchSequenceStack.back(); - - if (statements) { - statements->setOperator(EOpSequence); - switchSequence->push_back(statements); - } - if (branchNode) { - // check all previous cases for the same label (or both are 'default') - for (unsigned int s = 0; s < switchSequence->size(); ++s) { - TIntermBranch* prevBranch = (*switchSequence)[s]->getAsBranchNode(); - if (prevBranch) { - TIntermTyped* prevExpression = prevBranch->getExpression(); - TIntermTyped* newExpression = branchNode->getAsBranchNode()->getExpression(); - if (prevExpression == nullptr && newExpression == nullptr) - error(branchNode->getLoc(), "duplicate label", "default", ""); - else if (prevExpression != nullptr && - newExpression != nullptr && - prevExpression->getAsConstantUnion() && - newExpression->getAsConstantUnion() && - prevExpression->getAsConstantUnion()->getConstArray()[0].getIConst() == - newExpression->getAsConstantUnion()->getConstArray()[0].getIConst()) - error(branchNode->getLoc(), "duplicated value", "case", ""); - } - } - switchSequence->push_back(branchNode); - } -} - -// -// Turn the top-level node sequence built up of wrapupSwitchSubsequence -// into a switch node. -// -TIntermNode* HlslParseContext::addSwitch(const TSourceLoc& loc, TIntermTyped* expression, - TIntermAggregate* lastStatements, const TAttributes& attributes) -{ - wrapupSwitchSubsequence(lastStatements, nullptr); - - if (expression == nullptr || - (expression->getBasicType() != EbtInt && expression->getBasicType() != EbtUint) || - expression->getType().isArray() || expression->getType().isMatrix() || expression->getType().isVector()) - error(loc, "condition must be a scalar integer expression", "switch", ""); - - // If there is nothing to do, drop the switch but still execute the expression - TIntermSequence* switchSequence = switchSequenceStack.back(); - if (switchSequence->size() == 0) - return expression; - - if (lastStatements == nullptr) { - // emulate a break for error recovery - lastStatements = intermediate.makeAggregate(intermediate.addBranch(EOpBreak, loc)); - lastStatements->setOperator(EOpSequence); - switchSequence->push_back(lastStatements); - } - - TIntermAggregate* body = new TIntermAggregate(EOpSequence); - body->getSequence() = *switchSequenceStack.back(); - body->setLoc(loc); - - TIntermSwitch* switchNode = new TIntermSwitch(expression, body); - switchNode->setLoc(loc); - handleSwitchAttributes(loc, switchNode, attributes); - - return switchNode; -} - -// Make a new symbol-table level that is made out of the members of a structure. -// This should be done as an anonymous struct (name is "") so that the symbol table -// finds the members with no explicit reference to a 'this' variable. -void HlslParseContext::pushThisScope(const TType& thisStruct, const TVector& functionDeclarators) -{ - // member variables - TVariable& thisVariable = *new TVariable(NewPoolTString(""), thisStruct); - symbolTable.pushThis(thisVariable); - - // member functions - for (auto it = functionDeclarators.begin(); it != functionDeclarators.end(); ++it) { - // member should have a prefix matching currentTypePrefix.back() - // but, symbol lookup within the class scope will just use the - // unprefixed name. Hence, there are two: one fully prefixed and - // one with no prefix. - TFunction& member = *it->function->clone(); - member.removePrefix(currentTypePrefix.back()); - symbolTable.insert(member); - } -} - -// Track levels of class/struct/namespace nesting with a prefix string using -// the type names separated by the scoping operator. E.g., two levels -// would look like: -// -// outer::inner -// -// The string is empty when at normal global level. -// -void HlslParseContext::pushNamespace(const TString& typeName) -{ - // make new type prefix - TString newPrefix; - if (currentTypePrefix.size() > 0) - newPrefix = currentTypePrefix.back(); - newPrefix.append(typeName); - newPrefix.append(scopeMangler); - currentTypePrefix.push_back(newPrefix); -} - -// Opposite of pushNamespace(), see above -void HlslParseContext::popNamespace() -{ - currentTypePrefix.pop_back(); -} - -// Use the class/struct nesting string to create a global name for -// a member of a class/struct. -void HlslParseContext::getFullNamespaceName(TString*& name) const -{ - if (currentTypePrefix.size() == 0) - return; - - TString* fullName = NewPoolTString(currentTypePrefix.back().c_str()); - fullName->append(*name); - name = fullName; -} - -// Helper function to add the namespace scope mangling syntax to a string. -void HlslParseContext::addScopeMangler(TString& name) -{ - name.append(scopeMangler); -} - -// Return true if this has uniform-interface like decorations. -bool HlslParseContext::hasUniform(const TQualifier& qualifier) const -{ - return qualifier.hasUniformLayout() || - qualifier.layoutPushConstant; -} - -// Potentially not the opposite of hasUniform(), as if some characteristic is -// ever used for more than one thing (e.g., uniform or input), hasUniform() should -// say it exists, but clearUniform() should leave it in place. -void HlslParseContext::clearUniform(TQualifier& qualifier) -{ - qualifier.clearUniformLayout(); - qualifier.layoutPushConstant = false; -} - -// Return false if builtIn by itself doesn't force this qualifier to be an input qualifier. -bool HlslParseContext::isInputBuiltIn(const TQualifier& qualifier) const -{ - switch (qualifier.builtIn) { - case EbvPosition: - case EbvPointSize: - return language != EShLangVertex && language != EShLangCompute && language != EShLangFragment; - case EbvClipDistance: - case EbvCullDistance: - return language != EShLangVertex && language != EShLangCompute; - case EbvFragCoord: - case EbvFace: - case EbvHelperInvocation: - case EbvLayer: - case EbvPointCoord: - case EbvSampleId: - case EbvSampleMask: - case EbvSamplePosition: - case EbvViewportIndex: - return language == EShLangFragment; - case EbvGlobalInvocationId: - case EbvLocalInvocationIndex: - case EbvLocalInvocationId: - case EbvNumWorkGroups: - case EbvWorkGroupId: - case EbvWorkGroupSize: - return language == EShLangCompute; - case EbvInvocationId: - return language == EShLangTessControl || language == EShLangTessEvaluation || language == EShLangGeometry; - case EbvPatchVertices: - return language == EShLangTessControl || language == EShLangTessEvaluation; - case EbvInstanceId: - case EbvInstanceIndex: - case EbvVertexId: - case EbvVertexIndex: - return language == EShLangVertex; - case EbvPrimitiveId: - return language == EShLangGeometry || language == EShLangFragment || language == EShLangTessControl; - case EbvTessLevelInner: - case EbvTessLevelOuter: - return language == EShLangTessEvaluation; - case EbvTessCoord: - return language == EShLangTessEvaluation; - default: - return false; - } -} - -// Return true if there are decorations to preserve for input-like storage. -bool HlslParseContext::hasInput(const TQualifier& qualifier) const -{ - if (qualifier.hasAnyLocation()) - return true; - - if (language == EShLangFragment && (qualifier.isInterpolation() || qualifier.centroid || qualifier.sample)) - return true; - - if (language == EShLangTessEvaluation && qualifier.patch) - return true; - - if (isInputBuiltIn(qualifier)) - return true; - - return false; -} - -// Return false if builtIn by itself doesn't force this qualifier to be an output qualifier. -bool HlslParseContext::isOutputBuiltIn(const TQualifier& qualifier) const -{ - switch (qualifier.builtIn) { - case EbvPosition: - case EbvPointSize: - case EbvClipVertex: - case EbvClipDistance: - case EbvCullDistance: - return language != EShLangFragment && language != EShLangCompute; - case EbvFragDepth: - case EbvFragDepthGreater: - case EbvFragDepthLesser: - case EbvSampleMask: - return language == EShLangFragment; - case EbvLayer: - case EbvViewportIndex: - return language == EShLangGeometry || language == EShLangVertex; - case EbvPrimitiveId: - return language == EShLangGeometry; - case EbvTessLevelInner: - case EbvTessLevelOuter: - return language == EShLangTessControl; - default: - return false; - } -} - -// Return true if there are decorations to preserve for output-like storage. -bool HlslParseContext::hasOutput(const TQualifier& qualifier) const -{ - if (qualifier.hasAnyLocation()) - return true; - - if (language != EShLangFragment && language != EShLangCompute && qualifier.hasXfb()) - return true; - - if (language == EShLangTessControl && qualifier.patch) - return true; - - if (language == EShLangGeometry && qualifier.hasStream()) - return true; - - if (isOutputBuiltIn(qualifier)) - return true; - - return false; -} - -// Make the IO decorations etc. be appropriate only for an input interface. -void HlslParseContext::correctInput(TQualifier& qualifier) -{ - clearUniform(qualifier); - if (language == EShLangVertex) - qualifier.clearInterstage(); - if (language != EShLangTessEvaluation) - qualifier.patch = false; - if (language != EShLangFragment) { - qualifier.clearInterpolation(); - qualifier.sample = false; - } - - qualifier.clearStreamLayout(); - qualifier.clearXfbLayout(); - - if (! isInputBuiltIn(qualifier)) - qualifier.builtIn = EbvNone; -} - -// Make the IO decorations etc. be appropriate only for an output interface. -void HlslParseContext::correctOutput(TQualifier& qualifier) -{ - clearUniform(qualifier); - if (language == EShLangFragment) - qualifier.clearInterstage(); - if (language != EShLangGeometry) - qualifier.clearStreamLayout(); - if (language == EShLangFragment) - qualifier.clearXfbLayout(); - if (language != EShLangTessControl) - qualifier.patch = false; - - switch (qualifier.builtIn) { - case EbvFragDepth: - intermediate.setDepthReplacing(); - intermediate.setDepth(EldAny); - break; - case EbvFragDepthGreater: - intermediate.setDepthReplacing(); - intermediate.setDepth(EldGreater); - qualifier.builtIn = EbvFragDepth; - break; - case EbvFragDepthLesser: - intermediate.setDepthReplacing(); - intermediate.setDepth(EldLess); - qualifier.builtIn = EbvFragDepth; - break; - default: - break; - } - - if (! isOutputBuiltIn(qualifier)) - qualifier.builtIn = EbvNone; -} - -// Make the IO decorations etc. be appropriate only for uniform type interfaces. -void HlslParseContext::correctUniform(TQualifier& qualifier) -{ - if (qualifier.declaredBuiltIn == EbvNone) - qualifier.declaredBuiltIn = qualifier.builtIn; - - qualifier.builtIn = EbvNone; - qualifier.clearInterstage(); - qualifier.clearInterstageLayout(); -} - -// Clear out all IO/Uniform stuff, so this has nothing to do with being an IO interface. -void HlslParseContext::clearUniformInputOutput(TQualifier& qualifier) -{ - clearUniform(qualifier); - correctUniform(qualifier); -} - - -// Set texture return type. Returns success (not all types are valid). -bool HlslParseContext::setTextureReturnType(TSampler& sampler, const TType& retType, const TSourceLoc& loc) -{ - // Seed the output with an invalid index. We will set it to a valid one if we can. - sampler.structReturnIndex = TSampler::noReturnStruct; - - // Arrays aren't supported. - if (retType.isArray()) { - error(loc, "Arrays not supported in texture template types", "", ""); - return false; - } - - // If return type is a vector, remember the vector size in the sampler, and return. - if (retType.isVector() || retType.isScalar()) { - sampler.vectorSize = retType.getVectorSize(); - return true; - } - - // If it wasn't a vector, it must be a struct meeting certain requirements. The requirements - // are checked below: just check for struct-ness here. - if (!retType.isStruct()) { - error(loc, "Invalid texture template type", "", ""); - return false; - } - - // TODO: Subpass doesn't handle struct returns, due to some oddities with fn overloading. - if (sampler.isSubpass()) { - error(loc, "Unimplemented: structure template type in subpass input", "", ""); - return false; - } - - TTypeList* members = retType.getWritableStruct(); - - // Check for too many or not enough structure members. - if (members->size() > 4 || members->size() == 0) { - error(loc, "Invalid member count in texture template structure", "", ""); - return false; - } - - // Error checking: We must have <= 4 total components, all of the same basic type. - unsigned totalComponents = 0; - for (unsigned m = 0; m < members->size(); ++m) { - // Check for bad member types - if (!(*members)[m].type->isScalar() && !(*members)[m].type->isVector()) { - error(loc, "Invalid texture template struct member type", "", ""); - return false; - } - - const unsigned memberVectorSize = (*members)[m].type->getVectorSize(); - totalComponents += memberVectorSize; - - // too many total member components - if (totalComponents > 4) { - error(loc, "Too many components in texture template structure type", "", ""); - return false; - } - - // All members must be of a common basic type - if ((*members)[m].type->getBasicType() != (*members)[0].type->getBasicType()) { - error(loc, "Texture template structure members must same basic type", "", ""); - return false; - } - } - - // If the structure in the return type already exists in the table, we'll use it. Otherwise, we'll make - // a new entry. This is a linear search, but it hardly ever happens, and the list cannot be very large. - for (unsigned int idx = 0; idx < textureReturnStruct.size(); ++idx) { - if (textureReturnStruct[idx] == members) { - sampler.structReturnIndex = idx; - return true; - } - } - - // It wasn't found as an existing entry. See if we have room for a new one. - if (textureReturnStruct.size() >= TSampler::structReturnSlots) { - error(loc, "Texture template struct return slots exceeded", "", ""); - return false; - } - - // Insert it in the vector that tracks struct return types. - sampler.structReturnIndex = unsigned(textureReturnStruct.size()); - textureReturnStruct.push_back(members); - - // Success! - return true; -} - -// Return the sampler return type in retType. -void HlslParseContext::getTextureReturnType(const TSampler& sampler, TType& retType) const -{ - if (sampler.hasReturnStruct()) { - assert(textureReturnStruct.size() >= sampler.structReturnIndex); - - // We land here if the texture return is a structure. - TTypeList* blockStruct = textureReturnStruct[sampler.structReturnIndex]; - - const TType resultType(blockStruct, ""); - retType.shallowCopy(resultType); - } else { - // We land here if the texture return is a vector or scalar. - const TType resultType(sampler.type, EvqTemporary, sampler.getVectorSize()); - retType.shallowCopy(resultType); - } -} - - -// Return a symbol for the tessellation linkage variable of the given TBuiltInVariable type -TIntermSymbol* HlslParseContext::findTessLinkageSymbol(TBuiltInVariable biType) const -{ - const auto it = builtInTessLinkageSymbols.find(biType); - if (it == builtInTessLinkageSymbols.end()) // if it wasn't declared by the user, return nullptr - return nullptr; - - return intermediate.addSymbol(*it->second->getAsVariable()); -} - -// Find the patch constant function (issues error, returns nullptr if not found) -const TFunction* HlslParseContext::findPatchConstantFunction(const TSourceLoc& loc) -{ - if (symbolTable.isFunctionNameVariable(patchConstantFunctionName)) { - error(loc, "can't use variable in patch constant function", patchConstantFunctionName.c_str(), ""); - return nullptr; - } - - const TString mangledName = patchConstantFunctionName + "("; - - // create list of PCF candidates - TVector candidateList; - bool builtIn; - symbolTable.findFunctionNameList(mangledName, candidateList, builtIn); - - // We have to have one and only one, or we don't know which to pick: the patchconstantfunc does not - // allow any disambiguation of overloads. - if (candidateList.empty()) { - error(loc, "patch constant function not found", patchConstantFunctionName.c_str(), ""); - return nullptr; - } - - // Based on directed experiments, it appears that if there are overloaded patchconstantfunctions, - // HLSL picks the last one in shader source order. Since that isn't yet implemented here, error - // out if there is more than one candidate. - if (candidateList.size() > 1) { - error(loc, "ambiguous patch constant function", patchConstantFunctionName.c_str(), ""); - return nullptr; - } - - return candidateList[0]; -} - -// Finalization step: Add patch constant function invocation -void HlslParseContext::addPatchConstantInvocation() -{ - TSourceLoc loc; - loc.init(); - - // If there's no patch constant function, or we're not a HS, do nothing. - if (patchConstantFunctionName.empty() || language != EShLangTessControl) - return; - - // Look for built-in variables in a function's parameter list. - const auto findBuiltIns = [&](const TFunction& function, std::set& builtIns) { - for (int p=0; pgetQualifier().storage; - - if (storage == EvqConstReadOnly) // treated identically to input - storage = EvqIn; - - if (function[p].getDeclaredBuiltIn() != EbvNone) - builtIns.insert(HlslParseContext::tInterstageIoData(function[p].getDeclaredBuiltIn(), storage)); - else - builtIns.insert(HlslParseContext::tInterstageIoData(function[p].type->getQualifier().builtIn, storage)); - } - }; - - // If we synthesize a built-in interface variable, we must add it to the linkage. - const auto addToLinkage = [&](const TType& type, const TString* name, TIntermSymbol** symbolNode) { - if (name == nullptr) { - error(loc, "unable to locate patch function parameter name", "", ""); - return; - } else { - TVariable& variable = *new TVariable(name, type); - if (! symbolTable.insert(variable)) { - error(loc, "unable to declare patch constant function interface variable", name->c_str(), ""); - return; - } - - globalQualifierFix(loc, variable.getWritableType().getQualifier()); - - if (symbolNode != nullptr) - *symbolNode = intermediate.addSymbol(variable); - - trackLinkage(variable); - } - }; - - const auto isOutputPatch = [](TFunction& patchConstantFunction, int param) { - const TType& type = *patchConstantFunction[param].type; - const TBuiltInVariable biType = patchConstantFunction[param].getDeclaredBuiltIn(); - - return type.isSizedArray() && biType == EbvOutputPatch; - }; - - // We will perform these steps. Each is in a scoped block for separation: they could - // become separate functions to make addPatchConstantInvocation shorter. - // - // 1. Union the interfaces, and create built-ins for anything present in the PCF and - // declared as a built-in variable that isn't present in the entry point's signature. - // - // 2. Synthesizes a call to the patchconstfunction using built-in variables from either main, - // or the ones we created. Matching is based on built-in type. We may use synthesized - // variables from (1) above. - // - // 2B: Synthesize per control point invocations of wrapped entry point if the PCF requires them. - // - // 3. Create a return sequence: copy the return value (if any) from the PCF to a - // (non-sanitized) output variable. In case this may involve multiple copies, such as for - // an arrayed variable, a temporary copy of the PCF output is created to avoid multiple - // indirections into a complex R-value coming from the call to the PCF. - // - // 4. Create a barrier. - // - // 5/5B. Call the PCF inside an if test for (invocation id == 0). - - TFunction* patchConstantFunctionPtr = const_cast(findPatchConstantFunction(loc)); - - if (patchConstantFunctionPtr == nullptr) - return; - - TFunction& patchConstantFunction = *patchConstantFunctionPtr; - - const int pcfParamCount = patchConstantFunction.getParamCount(); - TIntermSymbol* invocationIdSym = findTessLinkageSymbol(EbvInvocationId); - TIntermSequence& epBodySeq = entryPointFunctionBody->getAsAggregate()->getSequence(); - - int outPatchParam = -1; // -1 means there isn't one. - - // ================ Step 1A: Union Interfaces ================ - // Our patch constant function. - { - std::set pcfBuiltIns; // patch constant function built-ins - std::set epfBuiltIns; // entry point function built-ins - - assert(entryPointFunction); - assert(entryPointFunctionBody); - - findBuiltIns(patchConstantFunction, pcfBuiltIns); - findBuiltIns(*entryPointFunction, epfBuiltIns); - - // Find the set of built-ins in the PCF that are not present in the entry point. - std::set notInEntryPoint; - - notInEntryPoint = pcfBuiltIns; - - // std::set_difference not usable on unordered containers - for (auto bi = epfBuiltIns.begin(); bi != epfBuiltIns.end(); ++bi) - notInEntryPoint.erase(*bi); - - // Now we'll add those to the entry and to the linkage. - for (int p=0; pgetQualifier().storage; - - // Track whether there is an output patch param - if (isOutputPatch(patchConstantFunction, p)) { - if (outPatchParam >= 0) { - // Presently we only support one per ctrl pt input. - error(loc, "unimplemented: multiple output patches in patch constant function", "", ""); - return; - } - outPatchParam = p; - } - - if (biType != EbvNone) { - TType* paramType = patchConstantFunction[p].type->clone(); - - if (storage == EvqConstReadOnly) // treated identically to input - storage = EvqIn; - - // Presently, the only non-built-in we support is InputPatch, which is treated as - // a pseudo-built-in. - if (biType == EbvInputPatch) { - builtInTessLinkageSymbols[biType] = inputPatch; - } else if (biType == EbvOutputPatch) { - // Nothing... - } else { - // Use the original declaration type for the linkage - paramType->getQualifier().builtIn = biType; - - if (notInEntryPoint.count(tInterstageIoData(biType, storage)) == 1) - addToLinkage(*paramType, patchConstantFunction[p].name, nullptr); - } - } - } - - // If we didn't find it because the shader made one, add our own. - if (invocationIdSym == nullptr) { - TType invocationIdType(EbtUint, EvqIn, 1); - TString* invocationIdName = NewPoolTString("InvocationId"); - invocationIdType.getQualifier().builtIn = EbvInvocationId; - addToLinkage(invocationIdType, invocationIdName, &invocationIdSym); - } - - assert(invocationIdSym); - } - - TIntermTyped* pcfArguments = nullptr; - TVariable* perCtrlPtVar = nullptr; - - // ================ Step 1B: Argument synthesis ================ - // Create pcfArguments for synthesis of patchconstantfunction invocation - { - for (int p=0; pgetWritableType().getQualifier().makeTemporary(); - } - inputArg = intermediate.addSymbol(*perCtrlPtVar, loc); - } else { - // find which built-in it is - const TBuiltInVariable biType = patchConstantFunction[p].getDeclaredBuiltIn(); - - if (biType == EbvInputPatch && inputPatch == nullptr) { - error(loc, "unimplemented: PCF input patch without entry point input patch parameter", "", ""); - return; - } - - inputArg = findTessLinkageSymbol(biType); - - if (inputArg == nullptr) { - error(loc, "unable to find patch constant function built-in variable", "", ""); - return; - } - } - - if (pcfParamCount == 1) - pcfArguments = inputArg; - else - pcfArguments = intermediate.growAggregate(pcfArguments, inputArg); - } - } - - // ================ Step 2: Synthesize call to PCF ================ - TIntermAggregate* pcfCallSequence = nullptr; - TIntermTyped* pcfCall = nullptr; - - { - // Create a function call to the patchconstantfunction - if (pcfArguments) - addInputArgumentConversions(patchConstantFunction, pcfArguments); - - // Synthetic call. - pcfCall = intermediate.setAggregateOperator(pcfArguments, EOpFunctionCall, patchConstantFunction.getType(), loc); - pcfCall->getAsAggregate()->setUserDefined(); - pcfCall->getAsAggregate()->setName(patchConstantFunction.getMangledName()); - intermediate.addToCallGraph(infoSink, intermediate.getEntryPointMangledName().c_str(), - patchConstantFunction.getMangledName()); - - if (pcfCall->getAsAggregate()) { - TQualifierList& qualifierList = pcfCall->getAsAggregate()->getQualifierList(); - for (int i = 0; i < patchConstantFunction.getParamCount(); ++i) { - TStorageQualifier qual = patchConstantFunction[i].type->getQualifier().storage; - qualifierList.push_back(qual); - } - pcfCall = addOutputArgumentConversions(patchConstantFunction, *pcfCall->getAsOperator()); - } - } - - // ================ Step 2B: Per Control Point synthesis ================ - // If there is per control point data, we must either emulate that with multiple - // invocations of the entry point to build up an array, or (TODO:) use a yet - // unavailable extension to look across the SIMD lanes. This is the former - // as a placeholder for the latter. - if (outPatchParam >= 0) { - // We must introduce a local temp variable of the type wanted by the PCF input. - const int arraySize = patchConstantFunction[outPatchParam].type->getOuterArraySize(); - - if (entryPointFunction->getType().getBasicType() == EbtVoid) { - error(loc, "entry point must return a value for use with patch constant function", "", ""); - return; - } - - // Create calls to wrapped main to fill in the array. We will substitute fixed values - // of invocation ID when calling the wrapped main. - - // This is the type of the each member of the per ctrl point array. - const TType derefType(perCtrlPtVar->getType(), 0); - - for (int cpt = 0; cpt < arraySize; ++cpt) { - // TODO: improve. substr(1) here is to avoid the '@' that was grafted on but isn't in the symtab - // for this function. - const TString origName = entryPointFunction->getName().substr(1); - TFunction callee(&origName, TType(EbtVoid)); - TIntermTyped* callingArgs = nullptr; - - for (int i = 0; i < entryPointFunction->getParamCount(); i++) { - TParameter& param = (*entryPointFunction)[i]; - TType& paramType = *param.type; - - if (paramType.getQualifier().isParamOutput()) { - error(loc, "unimplemented: entry point outputs in patch constant function invocation", "", ""); - return; - } - - if (paramType.getQualifier().isParamInput()) { - TIntermTyped* arg = nullptr; - if ((*entryPointFunction)[i].getDeclaredBuiltIn() == EbvInvocationId) { - // substitute invocation ID with the array element ID - arg = intermediate.addConstantUnion(cpt, loc); - } else { - TVariable* argVar = makeInternalVariable(*param.name, *param.type); - argVar->getWritableType().getQualifier().makeTemporary(); - arg = intermediate.addSymbol(*argVar); - } - - handleFunctionArgument(&callee, callingArgs, arg); - } - } - - // Call and assign to per ctrl point variable - currentCaller = intermediate.getEntryPointMangledName().c_str(); - TIntermTyped* callReturn = handleFunctionCall(loc, &callee, callingArgs); - TIntermTyped* index = intermediate.addConstantUnion(cpt, loc); - TIntermSymbol* perCtrlPtSym = intermediate.addSymbol(*perCtrlPtVar, loc); - TIntermTyped* element = intermediate.addIndex(EOpIndexDirect, perCtrlPtSym, index, loc); - element->setType(derefType); - element->setLoc(loc); - - pcfCallSequence = intermediate.growAggregate(pcfCallSequence, - handleAssign(loc, EOpAssign, element, callReturn)); - } - } - - // ================ Step 3: Create return Sequence ================ - // Return sequence: copy PCF result to a temporary, then to shader output variable. - if (pcfCall->getBasicType() != EbtVoid) { - const TType* retType = &patchConstantFunction.getType(); // return type from the PCF - TType outType; // output type that goes with the return type. - outType.shallowCopy(*retType); - - // substitute the output type - const auto newLists = ioTypeMap.find(retType->getStruct()); - if (newLists != ioTypeMap.end()) - outType.setStruct(newLists->second.output); - - // Substitute the top level type's built-in type - if (patchConstantFunction.getDeclaredBuiltInType() != EbvNone) - outType.getQualifier().builtIn = patchConstantFunction.getDeclaredBuiltInType(); - - outType.getQualifier().patch = true; // make it a per-patch variable - - TVariable* pcfOutput = makeInternalVariable("@patchConstantOutput", outType); - pcfOutput->getWritableType().getQualifier().storage = EvqVaryingOut; - - if (pcfOutput->getType().containsBuiltIn()) - split(*pcfOutput); - - assignToInterface(*pcfOutput); - - TIntermSymbol* pcfOutputSym = intermediate.addSymbol(*pcfOutput, loc); - - // The call to the PCF is a complex R-value: we want to store it in a temp to avoid - // repeated calls to the PCF: - TVariable* pcfCallResult = makeInternalVariable("@patchConstantResult", *retType); - pcfCallResult->getWritableType().getQualifier().makeTemporary(); - - TIntermSymbol* pcfResultVar = intermediate.addSymbol(*pcfCallResult, loc); - TIntermNode* pcfResultAssign = handleAssign(loc, EOpAssign, pcfResultVar, pcfCall); - TIntermNode* pcfResultToOut = handleAssign(loc, EOpAssign, pcfOutputSym, - intermediate.addSymbol(*pcfCallResult, loc)); - - pcfCallSequence = intermediate.growAggregate(pcfCallSequence, pcfResultAssign); - pcfCallSequence = intermediate.growAggregate(pcfCallSequence, pcfResultToOut); - } else { - pcfCallSequence = intermediate.growAggregate(pcfCallSequence, pcfCall); - } - - // ================ Step 4: Barrier ================ - TIntermTyped* barrier = new TIntermAggregate(EOpBarrier); - barrier->setLoc(loc); - barrier->setType(TType(EbtVoid)); - epBodySeq.insert(epBodySeq.end(), barrier); - - // ================ Step 5: Test on invocation ID ================ - TIntermTyped* zero = intermediate.addConstantUnion(0, loc, true); - TIntermTyped* cmp = intermediate.addBinaryNode(EOpEqual, invocationIdSym, zero, loc, TType(EbtBool)); - - - // ================ Step 5B: Create if statement on Invocation ID == 0 ================ - intermediate.setAggregateOperator(pcfCallSequence, EOpSequence, TType(EbtVoid), loc); - TIntermTyped* invocationIdTest = new TIntermSelection(cmp, pcfCallSequence, nullptr); - invocationIdTest->setLoc(loc); - - // add our test sequence before the return. - epBodySeq.insert(epBodySeq.end(), invocationIdTest); -} - -// Finalization step: remove unused buffer blocks from linkage (we don't know until the -// shader is entirely compiled). -// Preserve order of remaining symbols. -void HlslParseContext::removeUnusedStructBufferCounters() -{ - const auto endIt = std::remove_if(linkageSymbols.begin(), linkageSymbols.end(), - [this](const TSymbol* sym) { - const auto sbcIt = structBufferCounter.find(sym->getName()); - return sbcIt != structBufferCounter.end() && !sbcIt->second; - }); - - linkageSymbols.erase(endIt, linkageSymbols.end()); -} - -// Finalization step: patch texture shadow modes to match samplers they were combined with -void HlslParseContext::fixTextureShadowModes() -{ - for (auto symbol = linkageSymbols.begin(); symbol != linkageSymbols.end(); ++symbol) { - TSampler& sampler = (*symbol)->getWritableType().getSampler(); - - if (sampler.isTexture()) { - const auto shadowMode = textureShadowVariant.find((*symbol)->getUniqueId()); - if (shadowMode != textureShadowVariant.end()) { - - if (shadowMode->second->overloaded()) - // Texture needs legalization if it's been seen with both shadow and non-shadow modes. - intermediate.setNeedsLegalization(); - - sampler.shadow = shadowMode->second->isShadowId((*symbol)->getUniqueId()); - } - } - } -} - -// post-processing -void HlslParseContext::finish() -{ - // Error check: There was a dangling .mips operator. These are not nested constructs in the grammar, so - // cannot be detected there. This is not strictly needed in a non-validating parser; it's just helpful. - if (! mipsOperatorMipArg.empty()) { - error(mipsOperatorMipArg.back().loc, "unterminated mips operator:", "", ""); - } - - removeUnusedStructBufferCounters(); - addPatchConstantInvocation(); - fixTextureShadowModes(); - - // Communicate out (esp. for command line) that we formed AST that will make - // illegal AST SPIR-V and it needs transforms to legalize it. - if (intermediate.needsLegalization() && (messages & EShMsgHlslLegalization)) - infoSink.info << "WARNING: AST will form illegal SPIR-V; need to transform to legalize"; - - TParseContextBase::finish(); -} - -} // end namespace glslang diff --git a/External/glslang/hlsl/hlslParseHelper.h b/External/glslang/hlsl/hlslParseHelper.h deleted file mode 100644 index b16a8c2c..00000000 --- a/External/glslang/hlsl/hlslParseHelper.h +++ /dev/null @@ -1,496 +0,0 @@ -// -// Copyright (C) 2016 Google, Inc. -// 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 HLSL_PARSE_INCLUDED_ -#define HLSL_PARSE_INCLUDED_ - -#include "../glslang/MachineIndependent/parseVersions.h" -#include "../glslang/MachineIndependent/ParseHelper.h" -#include "../glslang/MachineIndependent/attribute.h" - -#include - -namespace glslang { - -class TFunctionDeclarator; - -class HlslParseContext : public TParseContextBase { -public: - HlslParseContext(TSymbolTable&, TIntermediate&, bool parsingBuiltins, - int version, EProfile, const SpvVersion& spvVersion, EShLanguage, TInfoSink&, - const TString sourceEntryPointName, - bool forwardCompatible = false, EShMessages messages = EShMsgDefault); - virtual ~HlslParseContext(); - void initializeExtensionBehavior() override; - - void setLimits(const TBuiltInResource&) override; - bool parseShaderStrings(TPpContext&, TInputScanner& input, bool versionWillBeError = false) override; - virtual const char* getGlobalUniformBlockName() const override { return "$Global"; } - virtual void setUniformBlockDefaults(TType& block) const override - { - block.getQualifier().layoutPacking = ElpStd140; - block.getQualifier().layoutMatrix = ElmRowMajor; - } - - void reservedPpErrorCheck(const TSourceLoc&, const char* /*name*/, const char* /*op*/) override { } - bool lineContinuationCheck(const TSourceLoc&, bool /*endOfComment*/) override { return true; } - bool lineDirectiveShouldSetNextLine() const override { return true; } - bool builtInName(const TString&); - - void handlePragma(const TSourceLoc&, const TVector&) override; - TIntermTyped* handleVariable(const TSourceLoc&, const TString* string); - TIntermTyped* handleBracketDereference(const TSourceLoc&, TIntermTyped* base, TIntermTyped* index); - TIntermTyped* handleBracketOperator(const TSourceLoc&, TIntermTyped* base, TIntermTyped* index); - - 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); - bool isBuiltInMethod(const TSourceLoc&, TIntermTyped* base, const TString& field); - void assignToInterface(TVariable& variable); - void handleFunctionDeclarator(const TSourceLoc&, TFunction& function, bool prototype); - TIntermAggregate* handleFunctionDefinition(const TSourceLoc&, TFunction&, const TAttributes&, TIntermNode*& entryPointTree); - TIntermNode* transformEntryPoint(const TSourceLoc&, TFunction&, const TAttributes&); - void handleEntryPointAttributes(const TSourceLoc&, const TAttributes&); - void transferTypeAttributes(const TSourceLoc&, const TAttributes&, TType&, bool allowEntry = false); - void handleFunctionBody(const TSourceLoc&, TFunction&, TIntermNode* functionBody, TIntermNode*& node); - void remapEntryPointIO(TFunction& function, TVariable*& returnValue, TVector& inputs, TVector& outputs); - void remapNonEntryPointIO(TFunction& function); - TIntermNode* handleReturnValue(const TSourceLoc&, TIntermTyped*); - void handleFunctionArgument(TFunction*, TIntermTyped*& arguments, TIntermTyped* newArg); - TIntermTyped* handleAssign(const TSourceLoc&, TOperator, TIntermTyped* left, TIntermTyped* right); - TIntermTyped* handleAssignToMatrixSwizzle(const TSourceLoc&, TOperator, TIntermTyped* left, TIntermTyped* right); - TIntermTyped* handleFunctionCall(const TSourceLoc&, TFunction*, TIntermTyped*); - TIntermAggregate* assignClipCullDistance(const TSourceLoc&, TOperator, int semanticId, TIntermTyped* left, TIntermTyped* right); - TIntermTyped* assignPosition(const TSourceLoc&, TOperator, TIntermTyped* left, TIntermTyped* right); - void decomposeIntrinsic(const TSourceLoc&, TIntermTyped*& node, TIntermNode* arguments); - void decomposeSampleMethods(const TSourceLoc&, TIntermTyped*& node, TIntermNode* arguments); - void decomposeStructBufferMethods(const TSourceLoc&, TIntermTyped*& node, TIntermNode* arguments); - void decomposeGeometryMethods(const TSourceLoc&, TIntermTyped*& node, TIntermNode* arguments); - void pushFrontArguments(TIntermTyped* front, TIntermTyped*& arguments); - void addInputArgumentConversions(const TFunction&, TIntermTyped*&); - void expandArguments(const TSourceLoc&, const TFunction&, TIntermTyped*&); - TIntermTyped* addOutputArgumentConversions(const TFunction&, TIntermOperator&); - void builtInOpCheck(const TSourceLoc&, const TFunction&, TIntermOperator&); - TFunction* makeConstructorCall(const TSourceLoc&, const TType&); - void handleSemantic(TSourceLoc, TQualifier&, TBuiltInVariable, const TString& upperCase); - void handlePackOffset(const TSourceLoc&, TQualifier&, const glslang::TString& location, - const glslang::TString* component); - void handleRegister(const TSourceLoc&, TQualifier&, const glslang::TString* profile, const glslang::TString& desc, - int subComponent, const glslang::TString*); - TIntermTyped* convertConditionalExpression(const TSourceLoc&, TIntermTyped*, bool mustBeScalar = true); - TIntermAggregate* handleSamplerTextureCombine(const TSourceLoc& loc, TIntermTyped* argTex, TIntermTyped* argSampler); - - bool parseMatrixSwizzleSelector(const TSourceLoc&, const TString&, int cols, int rows, TSwizzleSelectors&); - int getMatrixComponentsColumn(int rows, const TSwizzleSelectors&); - 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); - 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&); - void arraySizeRequiredCheck(const TSourceLoc&, const TArraySizes&); - void structArrayCheck(const TSourceLoc&, const TType& structure); - bool voidErrorCheck(const TSourceLoc&, const TString&, TBasicType); - void globalQualifierFix(const TSourceLoc&, TQualifier&); - bool structQualifierErrorCheck(const TSourceLoc&, const TPublicType& pType); - void mergeQualifiers(TQualifier& dst, const TQualifier& src); - int computeSamplerTypeIndex(TSampler&); - TSymbol* redeclareBuiltinVariable(const TSourceLoc&, const TString&, const TQualifier&, const TShaderQualifiers&); - void paramFix(TType& type); - void specializationCheck(const TSourceLoc&, const TType&, const char* op); - - void setLayoutQualifier(const TSourceLoc&, TQualifier&, TString&); - void setLayoutQualifier(const TSourceLoc&, TQualifier&, TString&, const TIntermTyped*); - void setSpecConstantId(const TSourceLoc&, TQualifier&, int value); - void mergeObjectLayoutQualifiers(TQualifier& dest, const TQualifier& src, bool inheritOnly); - void checkNoShaderLayouts(const TSourceLoc&, const TShaderQualifiers&); - - const TFunction* findFunction(const TSourceLoc& loc, TFunction& call, bool& builtIn, int& thisDepth, TIntermTyped*& args); - void addGenMulArgumentConversion(const TSourceLoc& loc, TFunction& call, TIntermTyped*& args); - void declareTypedef(const TSourceLoc&, const TString& identifier, const TType&); - void declareStruct(const TSourceLoc&, TString& structName, TType&); - TSymbol* lookupUserType(const TString&, TType&); - TIntermNode* declareVariable(const TSourceLoc&, const TString& identifier, TType&, TIntermTyped* initializer = 0); - void lengthenList(const TSourceLoc&, TIntermSequence& list, int size, TIntermTyped* scalarInit); - TIntermTyped* handleConstructor(const TSourceLoc&, TIntermTyped*, const TType&); - TIntermTyped* addConstructor(const TSourceLoc&, TIntermTyped*, const TType&); - TIntermTyped* convertArray(TIntermTyped*, const TType&); - TIntermTyped* constructAggregate(TIntermNode*, const TType&, int, const TSourceLoc&); - TIntermTyped* constructBuiltIn(const TType&, TOperator, TIntermTyped*, const TSourceLoc&, bool subset); - void declareBlock(const TSourceLoc&, TType&, const TString* instanceName = 0); - void declareStructBufferCounter(const TSourceLoc& loc, const TType& bufferType, const TString& name); - void fixBlockLocations(const TSourceLoc&, TQualifier&, TTypeList&, bool memberWithLocation, bool memberWithoutLocation); - void fixBlockXfbOffsets(TQualifier&, TTypeList&); - void fixBlockUniformOffsets(const TQualifier&, TTypeList&); - void addQualifierToExisting(const TSourceLoc&, TQualifier, const TString& identifier); - void addQualifierToExisting(const TSourceLoc&, TQualifier, TIdentifierList&); - void updateStandaloneQualifierDefaults(const TSourceLoc&, const TPublicType&); - void wrapupSwitchSubsequence(TIntermAggregate* statements, TIntermNode* branchNode); - TIntermNode* addSwitch(const TSourceLoc&, TIntermTyped* expression, TIntermAggregate* body, const TAttributes&); - - void nestLooping() { ++loopNestingLevel; } - void unnestLooping() { --loopNestingLevel; } - void nestAnnotations() { ++annotationNestingLevel; } - void unnestAnnotations() { --annotationNestingLevel; } - int getAnnotationNestingLevel() { return annotationNestingLevel; } - void pushScope() { symbolTable.push(); } - void popScope() { symbolTable.pop(0); } - - void pushThisScope(const TType&, const TVector&); - void popThisScope() { symbolTable.pop(0); } - - void pushImplicitThis(TVariable* thisParameter) { implicitThisStack.push_back(thisParameter); } - void popImplicitThis() { implicitThisStack.pop_back(); } - TVariable* getImplicitThis(int thisDepth) const { return implicitThisStack[implicitThisStack.size() - thisDepth]; } - - void pushNamespace(const TString& name); - void popNamespace(); - void getFullNamespaceName(TString*&) const; - void addScopeMangler(TString&); - - void pushSwitchSequence(TIntermSequence* sequence) { switchSequenceStack.push_back(sequence); } - void popSwitchSequence() { switchSequenceStack.pop_back(); } - - virtual void growGlobalUniformBlock(const TSourceLoc&, TType&, const TString& memberName, - TTypeList* typeList = nullptr) override; - - // Apply L-value conversions. E.g, turning a write to a RWTexture into an ImageStore. - TIntermTyped* handleLvalue(const TSourceLoc&, const char* op, TIntermTyped*& node); - bool lValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*) override; - - TLayoutFormat getLayoutFromTxType(const TSourceLoc&, const TType&); - - bool handleOutputGeometry(const TSourceLoc&, const TLayoutGeometry& geometry); - bool handleInputGeometry(const TSourceLoc&, const TLayoutGeometry& geometry); - - // Determine selection control from attributes - void handleSelectionAttributes(const TSourceLoc& loc, TIntermSelection*, const TAttributes& attributes); - void handleSwitchAttributes(const TSourceLoc& loc, TIntermSwitch*, const TAttributes& attributes); - - // Determine loop control from attributes - void handleLoopAttributes(const TSourceLoc& loc, TIntermLoop*, const TAttributes& attributes); - - // Share struct buffer deep types - void shareStructBufferType(TType&); - - // Set texture return type of the given sampler. Returns success (not all types are valid). - bool setTextureReturnType(TSampler& sampler, const TType& retType, const TSourceLoc& loc); - - // Obtain the sampler return type of the given sampler in retType. - void getTextureReturnType(const TSampler& sampler, TType& retType) const; - - TAttributeType attributeFromName(const TString& nameSpace, const TString& name) const; - -protected: - struct TFlattenData { - TFlattenData() : nextBinding(TQualifier::layoutBindingEnd), - nextLocation(TQualifier::layoutLocationEnd) { } - TFlattenData(int nb, int nl) : nextBinding(nb), nextLocation(nl) { } - - TVector members; // individual flattened variables - TVector offsets; // offset to next tree level - unsigned int nextBinding; // next binding to use. - unsigned int nextLocation; // next location to use - }; - - void fixConstInit(const TSourceLoc&, const TString& identifier, TType& type, TIntermTyped*& initializer); - void inheritGlobalDefaults(TQualifier& dst) const; - TVariable* makeInternalVariable(const char* name, const TType&) const; - TVariable* makeInternalVariable(const TString& name, const TType& type) const { - return makeInternalVariable(name.c_str(), type); - } - TIntermSymbol* makeInternalVariableNode(const TSourceLoc&, const char* name, const TType&) const; - TVariable* declareNonArray(const TSourceLoc&, const TString& identifier, const TType&, bool track); - void declareArray(const TSourceLoc&, const TString& identifier, const TType&, TSymbol*&, bool track); - TIntermNode* executeInitializer(const TSourceLoc&, TIntermTyped* initializer, TVariable* variable); - TIntermTyped* convertInitializerList(const TSourceLoc&, const TType&, TIntermTyped* initializer, TIntermTyped* scalarInit); - bool isScalarConstructor(const TIntermNode*); - TOperator mapAtomicOp(const TSourceLoc& loc, TOperator op, bool isImage); - - // Return true if this node requires L-value conversion (e.g, to an imageStore). - bool shouldConvertLValue(const TIntermNode*) const; - - // Array and struct flattening - TIntermTyped* flattenAccess(TIntermTyped* base, int member); - TIntermTyped* flattenAccess(int uniqueId, int member, TStorageQualifier outerStorage, const TType&, int subset = -1); - int findSubtreeOffset(const TIntermNode&) const; - int findSubtreeOffset(const TType&, int subset, const TVector& offsets) const; - bool shouldFlatten(const TType&, TStorageQualifier, bool topLevel) const; - bool wasFlattened(const TIntermTyped* node) const; - bool wasFlattened(int id) const { return flattenMap.find(id) != flattenMap.end(); } - int addFlattenedMember(const TVariable&, const TType&, TFlattenData&, const TString& name, bool linkage, - const TQualifier& outerQualifier, const TArraySizes* builtInArraySizes); - - // Structure splitting (splits interstage built-in types into its own struct) - void split(const TVariable&); - void splitBuiltIn(const TString& baseName, const TType& memberType, const TArraySizes*, const TQualifier&); - const TType& split(const TType& type, const TString& name, const TQualifier&); - bool wasSplit(const TIntermTyped* node) const; - bool wasSplit(int id) const { return splitNonIoVars.find(id) != splitNonIoVars.end(); } - TVariable* getSplitNonIoVar(int id) const; - void addPatchConstantInvocation(); - void fixTextureShadowModes(); - TIntermTyped* makeIntegerIndex(TIntermTyped*); - - void fixBuiltInIoType(TType&); - - void flatten(const TVariable& variable, bool linkage); - int flatten(const TVariable& variable, const TType&, TFlattenData&, TString name, bool linkage, - const TQualifier& outerQualifier, const TArraySizes* builtInArraySizes); - int flattenStruct(const TVariable& variable, const TType&, TFlattenData&, TString name, bool linkage, - const TQualifier& outerQualifier, const TArraySizes* builtInArraySizes); - int flattenArray(const TVariable& variable, const TType&, TFlattenData&, TString name, bool linkage, - const TQualifier& outerQualifier); - - bool hasUniform(const TQualifier& qualifier) const; - void clearUniform(TQualifier& qualifier); - bool isInputBuiltIn(const TQualifier& qualifier) const; - bool hasInput(const TQualifier& qualifier) const; - void correctOutput(TQualifier& qualifier); - bool isOutputBuiltIn(const TQualifier& qualifier) const; - bool hasOutput(const TQualifier& qualifier) const; - void correctInput(TQualifier& qualifier); - void correctUniform(TQualifier& qualifier); - void clearUniformInputOutput(TQualifier& qualifier); - - // Test method names - bool isStructBufferMethod(const TString& name) const; - void counterBufferType(const TSourceLoc& loc, TType& type); - - // Return standard sample position array - TIntermConstantUnion* getSamplePosArray(int count); - - TType* getStructBufferContentType(const TType& type) const; - bool isStructBufferType(const TType& type) const { return getStructBufferContentType(type) != nullptr; } - TIntermTyped* indexStructBufferContent(const TSourceLoc& loc, TIntermTyped* buffer) const; - TIntermTyped* getStructBufferCounter(const TSourceLoc& loc, TIntermTyped* buffer); - TString getStructBuffCounterName(const TString&) const; - void addStructBuffArguments(const TSourceLoc& loc, TIntermAggregate*&); - void addStructBufferHiddenCounterParam(const TSourceLoc& loc, TParameter&, TIntermAggregate*&); - - // Return true if this type is a reference. This is not currently a type method in case that's - // a language specific answer. - bool isReference(const TType& type) const { return isStructBufferType(type); } - - // Return true if this a buffer type that has an associated counter buffer. - bool hasStructBuffCounter(const TType&) const; - - // Finalization step: remove unused buffer blocks from linkage (we don't know until the - // shader is entirely compiled) - void removeUnusedStructBufferCounters(); - - static bool isClipOrCullDistance(TBuiltInVariable); - static bool isClipOrCullDistance(const TQualifier& qual) { return isClipOrCullDistance(qual.builtIn); } - static bool isClipOrCullDistance(const TType& type) { return isClipOrCullDistance(type.getQualifier()); } - - // Find the patch constant function (issues error, returns nullptr if not found) - const TFunction* findPatchConstantFunction(const TSourceLoc& loc); - - // Pass through to base class after remembering built-in mappings. - using TParseContextBase::trackLinkage; - void trackLinkage(TSymbol& variable) override; - - void finish() override; // post-processing - - // Linkage symbol helpers - TIntermSymbol* findTessLinkageSymbol(TBuiltInVariable biType) const; - - // Current state of parsing - int annotationNestingLevel; // 0 if outside all annotations - - HlslParseContext(HlslParseContext&); - HlslParseContext& operator=(HlslParseContext&); - - static const int maxSamplerIndex = EsdNumDims * (EbtNumTypes * (2 * 2 * 2)); // see computeSamplerTypeIndex() - TQualifier globalBufferDefaults; - TQualifier globalUniformDefaults; - TQualifier globalInputDefaults; - TQualifier globalOutputDefaults; - TString currentCaller; // name of last function body entered (not valid when at global scope) - 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; - - TMap flattenMap; - - // IO-type map. Maps a pure symbol-table form of a structure-member list into - // each of the (up to) three kinds of IO, as each as different allowed decorations, - // but HLSL allows mixing all in the same structure. - struct tIoKinds { - TTypeList* input; - TTypeList* output; - TTypeList* uniform; - }; - TMap ioTypeMap; - - // Structure splitting data: - TMap splitNonIoVars; // variables with the built-in interstage IO removed, indexed by unique ID. - - // Structuredbuffer shared types. Typically there are only a few. - TVector structBufferTypes; - - // This tracks texture sample user structure return types. Only a limited number are supported, as - // may fit in TSampler::structReturnIndex. - TVector textureReturnStruct; - - TMap structBufferCounter; // true if counter buffer is in use - - // The built-in interstage IO map considers e.g, EvqPosition on input and output separately, so that we - // can build the linkage correctly if position appears on both sides. Otherwise, multiple positions - // are considered identical. - struct tInterstageIoData { - tInterstageIoData(TBuiltInVariable bi, TStorageQualifier q) : - builtIn(bi), storage(q) { } - - TBuiltInVariable builtIn; - TStorageQualifier storage; - - // ordering for maps - bool operator<(const tInterstageIoData d) const { - return (builtIn != d.builtIn) ? (builtIn < d.builtIn) : (storage < d.storage); - } - }; - - TMap splitBuiltIns; // split built-ins, indexed by built-in type. - TVariable* inputPatch; // input patch is special for PCF: it's the only non-builtin PCF input, - // and is handled as a pseudo-builtin. - - unsigned int nextInLocation; - unsigned int nextOutLocation; - - TFunction* entryPointFunction; - TIntermNode* entryPointFunctionBody; - - TString patchConstantFunctionName; // hull shader patch constant function name, from function level attribute. - TMap builtInTessLinkageSymbols; // used for tessellation, finding declared built-ins - - TVector currentTypePrefix; // current scoping prefix for nested structures - TVector implicitThisStack; // currently active 'this' variables for nested structures - - TVariable* gsStreamOutput; // geometry shader stream outputs, for emit (Append method) - - TVariable* clipDistanceOutput; // synthesized clip distance out variable (shader might have >1) - TVariable* cullDistanceOutput; // synthesized cull distance out variable (shader might have >1) - TVariable* clipDistanceInput; // synthesized clip distance in variable (shader might have >1) - TVariable* cullDistanceInput; // synthesized cull distance in variable (shader might have >1) - - static const int maxClipCullRegs = 2; - std::array clipSemanticNSizeIn; // vector, indexed by clip semantic ID - std::array cullSemanticNSizeIn; // vector, indexed by cull semantic ID - std::array clipSemanticNSizeOut; // vector, indexed by clip semantic ID - std::array cullSemanticNSizeOut; // vector, indexed by cull semantic ID - - // This tracks the first (mip level) argument to the .mips[][] operator. Since this can be nested as - // in tx.mips[tx.mips[0][1].x][2], we need a stack. We also track the TSourceLoc for error reporting - // purposes. - struct tMipsOperatorData { - tMipsOperatorData(TSourceLoc l, TIntermTyped* m) : loc(l), mipLevel(m) { } - TSourceLoc loc; - TIntermTyped* mipLevel; - }; - - TVector mipsOperatorMipArg; - - // A texture object may be used with shadow and non-shadow samplers, but both may not be - // alive post-DCE in the same shader. We do not know at compilation time which are alive: that's - // only known post-DCE. If a texture is used both ways, we create two textures, and - // leave the elimiation of one to the optimizer. This maps the shader variant to - // the shadow variant. - // - // This can be removed if and when the texture shadow code in - // HlslParseContext::handleSamplerTextureCombine is removed. - struct tShadowTextureSymbols { - tShadowTextureSymbols() { symId.fill(-1); } - - void set(bool shadow, int id) { symId[int(shadow)] = id; } - int get(bool shadow) const { return symId[int(shadow)]; } - - // True if this texture has been seen with both shadow and non-shadow modes - bool overloaded() const { return symId[0] != -1 && symId[1] != -1; } - bool isShadowId(int id) const { return symId[1] == id; } - - private: - std::array symId; - }; - - TMap textureShadowVariant; -}; - -// This is the prefix we use for built-in methods to avoid namespace collisions with -// global scope user functions. -// TODO: this would be better as a nonparseable character, but that would -// require changing the scanner. -#define BUILTIN_PREFIX "__BI_" - -} // end namespace glslang - -#endif // HLSL_PARSE_INCLUDED_ diff --git a/External/glslang/hlsl/hlslParseables.cpp b/External/glslang/hlsl/hlslParseables.cpp deleted file mode 100644 index cc847ae2..00000000 --- a/External/glslang/hlsl/hlslParseables.cpp +++ /dev/null @@ -1,1324 +0,0 @@ -// -// 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. -// - -// -// Create strings that declare built-in definitions, add built-ins programmatically -// that cannot be expressed in the strings, and establish mappings between -// built-in functions and operators. -// -// Where to put a built-in: -// TBuiltInParseablesHlsl::initialize(version,profile) context-independent textual built-ins; add them to the right string -// TBuiltInParseablesHlsl::initialize(resources,...) context-dependent textual built-ins; add them to the right string -// TBuiltInParseablesHlsl::identifyBuiltIns(...,symbolTable) context-independent programmatic additions/mappings to the symbol table, -// including identifying what extensions are needed if a version does not allow a symbol -// TBuiltInParseablesHlsl::identifyBuiltIns(...,symbolTable, resources) context-dependent programmatic additions/mappings to the -// symbol table, including identifying what extensions are needed if a version does -// not allow a symbol -// - -#include "hlslParseables.h" -#include "hlslParseHelper.h" -#include -#include -#include - -namespace { // anonymous namespace functions - -const bool UseHlslTypes = true; - -const char* BaseTypeName(const char argOrder, const char* scalarName, const char* vecName, const char* matName) -{ - switch (argOrder) { - case 'S': return scalarName; - case 'V': return vecName; - case 'M': return matName; - default: return "UNKNOWN_TYPE"; - } -} - -// arg order queries -bool IsSamplerType(const char argType) { return argType == 'S' || argType == 's'; } -bool IsArrayed(const char argOrder) { return argOrder == '@' || argOrder == '&' || argOrder == '#'; } -bool IsTextureNonMS(const char argOrder) { return argOrder == '%'; } -bool IsSubpassInput(const char argOrder) { return argOrder == '[' || argOrder == ']'; } -bool IsArrayedTexture(const char argOrder) { return argOrder == '@'; } -bool IsTextureMS(const char argOrder) { return argOrder == '$' || argOrder == '&'; } -bool IsMS(const char argOrder) { return IsTextureMS(argOrder) || argOrder == ']'; } -bool IsBuffer(const char argOrder) { return argOrder == '*' || argOrder == '~'; } -bool IsImage(const char argOrder) { return argOrder == '!' || argOrder == '#' || argOrder == '~'; } - -bool IsTextureType(const char argOrder) -{ - return IsTextureNonMS(argOrder) || IsArrayedTexture(argOrder) || - IsTextureMS(argOrder) || IsBuffer(argOrder) || IsImage(argOrder); -} - -// Reject certain combinations that are illegal sample methods. For example, -// 3D arrays. -bool IsIllegalSample(const glslang::TString& name, const char* argOrder, int dim0) -{ - const bool isArrayed = IsArrayed(*argOrder); - const bool isMS = IsTextureMS(*argOrder); - const bool isBuffer = IsBuffer(*argOrder); - - // there are no 3D arrayed textures, or 3D SampleCmp(LevelZero) - if (dim0 == 3 && (isArrayed || name == "SampleCmp" || name == "SampleCmpLevelZero")) - return true; - - const int numArgs = int(std::count(argOrder, argOrder + strlen(argOrder), ',')) + 1; - - // Reject invalid offset forms with cubemaps - if (dim0 == 4) { - if ((name == "Sample" && numArgs >= 4) || - (name == "SampleBias" && numArgs >= 5) || - (name == "SampleCmp" && numArgs >= 5) || - (name == "SampleCmpLevelZero" && numArgs >= 5) || - (name == "SampleGrad" && numArgs >= 6) || - (name == "SampleLevel" && numArgs >= 5)) - return true; - } - - const bool isGather = - (name == "Gather" || - name == "GatherRed" || - name == "GatherGreen" || - name == "GatherBlue" || - name == "GatherAlpha"); - - const bool isGatherCmp = - (name == "GatherCmp" || - name == "GatherCmpRed" || - name == "GatherCmpGreen" || - name == "GatherCmpBlue" || - name == "GatherCmpAlpha"); - - // Reject invalid Gathers - if (isGather || isGatherCmp) { - if (dim0 == 1 || dim0 == 3) // there are no 1D or 3D gathers - return true; - - // no offset on cube or cube array gathers - if (dim0 == 4) { - if ((isGather && numArgs > 3) || (isGatherCmp && numArgs > 4)) - return true; - } - } - - // Reject invalid Loads - if (name == "Load" && dim0 == 4) - return true; // Load does not support any cubemaps, arrayed or not. - - // Multisample formats are only 2D and 2Darray - if (isMS && dim0 != 2) - return true; - - // Buffer are only 1D - if (isBuffer && dim0 != 1) - return true; - - return false; -} - -// Return the number of the coordinate arg, if any -int CoordinateArgPos(const glslang::TString& name, bool isTexture) -{ - if (!isTexture || (name == "GetDimensions")) - return -1; // has none - else if (name == "Load") - return 1; - else - return 2; // other texture methods are 2 -} - -// Some texture methods use an addition coordinate dimension for the mip -bool HasMipInCoord(const glslang::TString& name, bool isMS, bool isBuffer, bool isImage) -{ - return name == "Load" && !isMS && !isBuffer && !isImage; -} - -// LOD calculations don't pass the array level in the coordinate. -bool NoArrayCoord(const glslang::TString& name) -{ - return name == "CalculateLevelOfDetail" || name == "CalculateLevelOfDetailUnclamped"; -} - -// Handle IO params marked with > or < -const char* IoParam(glslang::TString& s, const char* nthArgOrder) -{ - if (*nthArgOrder == '>') { // output params - ++nthArgOrder; - s.append("out "); - } else if (*nthArgOrder == '<') { // input params - ++nthArgOrder; - s.append("in "); - } - - return nthArgOrder; -} - -// Handle repeated args -void HandleRepeatArg(const char*& arg, const char*& prev, const char* current) -{ - if (*arg == ',' || *arg == '\0') - arg = prev; - else - prev = current; -} - -// Return true for the end of a single argument key, which can be the end of the string, or -// the comma separator. -inline bool IsEndOfArg(const char* arg) -{ - return arg == nullptr || *arg == '\0' || *arg == ','; -} - -// If this is a fixed vector size, such as V3, return the size. Else return 0. -int FixedVecSize(const char* arg) -{ - while (!IsEndOfArg(arg)) { - if (isdigit(*arg)) - return *arg - '0'; - ++arg; - } - - return 0; // none found. -} - -// Create and return a type name. This is done in GLSL, not HLSL conventions, until such -// time as builtins are parsed using the HLSL parser. -// -// order: S = scalar, V = vector, M = matrix -// argType: F = float, D = double, I = int, U = uint, B = bool, S = sampler -// dim0 = vector dimension, or matrix 1st dimension -// dim1 = matrix 2nd dimension -glslang::TString& AppendTypeName(glslang::TString& s, const char* argOrder, const char* argType, int dim0, int dim1) -{ - const bool isTranspose = (argOrder[0] == '^'); - const bool isTexture = IsTextureType(argOrder[0]); - const bool isArrayed = IsArrayed(argOrder[0]); - const bool isSampler = IsSamplerType(argType[0]); - const bool isMS = IsMS(argOrder[0]); - const bool isBuffer = IsBuffer(argOrder[0]); - const bool isImage = IsImage(argOrder[0]); - const bool isSubpass = IsSubpassInput(argOrder[0]); - - char type = *argType; - - if (isTranspose) { // Take transpose of matrix dimensions - std::swap(dim0, dim1); - } else if (isTexture || isSubpass) { - if (type == 'F') // map base type to texture of that type. - type = 'T'; // e.g, int -> itexture, uint -> utexture, etc. - else if (type == 'I') - type = 'i'; - else if (type == 'U') - type = 'u'; - } - - if (isTranspose) - ++argOrder; - - char order = *argOrder; - - if (UseHlslTypes) { - switch (type) { - case '-': s += "void"; break; - case 'F': s += "float"; break; - case 'D': s += "double"; break; - case 'I': s += "int"; break; - case 'U': s += "uint"; break; - case 'L': s += "int64_t"; break; - case 'M': s += "uint64_t"; break; - case 'B': s += "bool"; break; - case 'S': s += "sampler"; break; - case 's': s += "SamplerComparisonState"; break; - case 'T': s += ((isBuffer && isImage) ? "RWBuffer" : - isSubpass ? "SubpassInput" : - isBuffer ? "Buffer" : - isImage ? "RWTexture" : "Texture"); break; - case 'i': s += ((isBuffer && isImage) ? "RWBuffer" : - isSubpass ? "SubpassInput" : - isBuffer ? "Buffer" : - isImage ? "RWTexture" : "Texture"); break; - case 'u': s += ((isBuffer && isImage) ? "RWBuffer" : - isSubpass ? "SubpassInput" : - isBuffer ? "Buffer" : - isImage ? "RWTexture" : "Texture"); break; - default: s += "UNKNOWN_TYPE"; break; - } - - if (isSubpass && isMS) - s += "MS"; - - } else { - switch (type) { - case '-': s += "void"; break; - case 'F': s += BaseTypeName(order, "float", "vec", "mat"); break; - case 'D': s += BaseTypeName(order, "double", "dvec", "dmat"); break; - case 'I': s += BaseTypeName(order, "int", "ivec", "imat"); break; - case 'U': s += BaseTypeName(order, "uint", "uvec", "umat"); break; - case 'B': s += BaseTypeName(order, "bool", "bvec", "bmat"); break; - case 'S': s += "sampler"; break; - case 's': s += "samplerShadow"; break; - case 'T': // fall through - case 'i': // ... - case 'u': // ... - if (type != 'T') // create itexture, utexture, etc - s += type; - - s += ((isImage && isBuffer) ? "imageBuffer" : - isSubpass ? "subpassInput" : - isImage ? "image" : - isBuffer ? "samplerBuffer" : - "texture"); - break; - - default: s += "UNKNOWN_TYPE"; break; - } - } - - // handle fixed vector sizes, such as float3, and only ever 3. - const int fixedVecSize = FixedVecSize(argOrder); - if (fixedVecSize != 0) - dim0 = dim1 = fixedVecSize; - - const char dim0Char = ('0' + char(dim0)); - const char dim1Char = ('0' + char(dim1)); - - // Add sampler dimensions - if (isSampler || isTexture) { - if ((order == 'V' || isTexture) && !isBuffer) { - switch (dim0) { - case 1: s += "1D"; break; - case 2: s += (isMS ? "2DMS" : "2D"); break; - case 3: s += "3D"; break; - case 4: s += "Cube"; break; - default: s += "UNKNOWN_SAMPLER"; break; - } - } - } else { - // Non-sampler type: - // verify dimensions - if (((order == 'V' || order == 'M') && (dim0 < 1 || dim0 > 4)) || - (order == 'M' && (dim1 < 1 || dim1 > 4))) { - s += "UNKNOWN_DIMENSION"; - return s; - } - - switch (order) { - case '-': break; // no dimensions for voids - case 'S': break; // no dimensions on scalars - case 'V': - s += dim0Char; - break; - case 'M': - s += dim0Char; - s += 'x'; - s += dim1Char; - break; - default: - break; - } - } - - // handle arrayed textures - if (isArrayed) - s += "Array"; - - // For HLSL, append return type for texture types - if (UseHlslTypes) { - switch (type) { - case 'i': s += " 0) // handle fixed sized vectors - dim0Min = dim0Max = fixedVecSize; -} - -} // end anonymous namespace - -namespace glslang { - -TBuiltInParseablesHlsl::TBuiltInParseablesHlsl() -{ -} - -// -// Handle creation of mat*mat specially, since it doesn't fall conveniently out of -// the generic prototype creation code below. -// -void TBuiltInParseablesHlsl::createMatTimesMat() -{ - TString& s = commonBuiltins; - - const int first = (UseHlslTypes ? 1 : 2); - - for (int xRows = first; xRows <=4; xRows++) { - for (int xCols = first; xCols <=4; xCols++) { - const int yRows = xCols; - for (int yCols = first; yCols <=4; yCols++) { - const int retRows = xRows; - const int retCols = yCols; - - // Create a mat * mat of the appropriate dimensions - AppendTypeName(s, "M", "F", retRows, retCols); // add return type - s.append(" "); // space between type and name - s.append("mul"); // intrinsic name - s.append("("); // open paren - - AppendTypeName(s, "M", "F", xRows, xCols); // add X input - s.append(", "); - AppendTypeName(s, "M", "F", yRows, yCols); // add Y input - - s.append(");\n"); // close paren - } - - // Create M*V - AppendTypeName(s, "V", "F", xRows, 1); // add return type - s.append(" "); // space between type and name - s.append("mul"); // intrinsic name - s.append("("); // open paren - - AppendTypeName(s, "M", "F", xRows, xCols); // add X input - s.append(", "); - AppendTypeName(s, "V", "F", xCols, 1); // add Y input - - s.append(");\n"); // close paren - - // Create V*M - AppendTypeName(s, "V", "F", xCols, 1); // add return type - s.append(" "); // space between type and name - s.append("mul"); // intrinsic name - s.append("("); // open paren - - AppendTypeName(s, "V", "F", xRows, 1); // add Y input - s.append(", "); - AppendTypeName(s, "M", "F", xRows, xCols); // add X input - - s.append(");\n"); // close paren - } - } -} - -// -// Add all context-independent built-in functions and variables that are present -// for the given version and profile. Share common ones across stages, otherwise -// make stage-specific entries. -// -// Most built-ins variables can be added as simple text strings. Some need to -// be added programmatically, which is done later in IdentifyBuiltIns() below. -// -void TBuiltInParseablesHlsl::initialize(int /*version*/, EProfile /*profile*/, const SpvVersion& /*spvVersion*/) -{ - static const EShLanguageMask EShLangAll = EShLanguageMask(EShLangCount - 1); - - // These are the actual stage masks defined in the documentation, in case they are - // needed for future validation. For now, they are commented out, and set below - // to EShLangAll, to allow any intrinsic to be used in any shader, which is legal - // if it is not called. - // - // static const EShLanguageMask EShLangPSCS = EShLanguageMask(EShLangFragmentMask | EShLangComputeMask); - // static const EShLanguageMask EShLangVSPSGS = EShLanguageMask(EShLangVertexMask | EShLangFragmentMask | EShLangGeometryMask); - // static const EShLanguageMask EShLangCS = EShLangComputeMask; - // static const EShLanguageMask EShLangPS = EShLangFragmentMask; - // static const EShLanguageMask EShLangHS = EShLangTessControlMask; - - // This set uses EShLangAll for everything. - static const EShLanguageMask EShLangPSCS = EShLangAll; - static const EShLanguageMask EShLangVSPSGS = EShLangAll; - static const EShLanguageMask EShLangCS = EShLangAll; - static const EShLanguageMask EShLangPS = EShLangAll; - static const EShLanguageMask EShLangHS = EShLangAll; - static const EShLanguageMask EShLangGS = EShLangAll; - - // This structure encodes the prototype information for each HLSL intrinsic. - // Because explicit enumeration would be cumbersome, it's procedurally generated. - // orderKey can be: - // S = scalar, V = vector, M = matrix, - = void - // typekey can be: - // D = double, F = float, U = uint, I = int, B = bool, S = sampler, s = shadowSampler, M = uint64_t, L = int64_t - // An empty order or type key repeats the first one. E.g: SVM,, means 3 args each of SVM. - // '>' as first letter of order creates an output parameter - // '<' as first letter of order creates an input parameter - // '^' as first letter of order takes transpose dimensions - // '%' as first letter of order creates texture of given F/I/U type (texture, itexture, etc) - // '@' as first letter of order creates arrayed texture of given type - // '$' / '&' as first letter of order creates 2DMS / 2DMSArray textures - // '*' as first letter of order creates buffer object - // '!' as first letter of order creates image object - // '#' as first letter of order creates arrayed image object - // '~' as first letter of order creates an image buffer object - // '[' / ']' as first letter of order creates a SubpassInput/SubpassInputMS object - - static const struct { - const char* name; // intrinsic name - const char* retOrder; // return type key: empty matches order of 1st argument - const char* retType; // return type key: empty matches type of 1st argument - const char* argOrder; // argument order key - const char* argType; // argument type key - unsigned int stage; // stage mask - bool method; // true if it's a method. - } hlslIntrinsics[] = { - // name retOrd retType argOrder argType stage mask method - // ---------------------------------------------------------------------------------------------------------------- - { "abort", nullptr, nullptr, "-", "-", EShLangAll, false }, - { "abs", nullptr, nullptr, "SVM", "DFUI", EShLangAll, false }, - { "acos", nullptr, nullptr, "SVM", "F", EShLangAll, false }, - { "all", "S", "B", "SVM", "BFIU", EShLangAll, false }, - { "AllMemoryBarrier", nullptr, nullptr, "-", "-", EShLangCS, false }, - { "AllMemoryBarrierWithGroupSync", nullptr, nullptr, "-", "-", EShLangCS, false }, - { "any", "S", "B", "SVM", "BFIU", EShLangAll, false }, - { "asdouble", "S", "D", "S,", "UI,", EShLangAll, false }, - { "asdouble", "V2", "D", "V2,", "UI,", EShLangAll, false }, - { "asfloat", nullptr, "F", "SVM", "BFIU", EShLangAll, false }, - { "asin", nullptr, nullptr, "SVM", "F", EShLangAll, false }, - { "asint", nullptr, "I", "SVM", "FIU", EShLangAll, false }, - { "asuint", nullptr, "U", "SVM", "FIU", EShLangAll, false }, - { "atan", nullptr, nullptr, "SVM", "F", EShLangAll, false }, - { "atan2", nullptr, nullptr, "SVM,", "F,", EShLangAll, false }, - { "ceil", nullptr, nullptr, "SVM", "F", EShLangAll, false }, - { "CheckAccessFullyMapped", "S", "B" , "S", "U", EShLangPSCS, false }, - { "clamp", nullptr, nullptr, "SVM,,", "FUI,,", EShLangAll, false }, - { "clip", "-", "-", "SVM", "FUI", EShLangPS, false }, - { "cos", nullptr, nullptr, "SVM", "F", EShLangAll, false }, - { "cosh", nullptr, nullptr, "SVM", "F", EShLangAll, false }, - { "countbits", nullptr, nullptr, "SV", "UI", EShLangAll, false }, - { "cross", nullptr, nullptr, "V3,", "F,", EShLangAll, false }, - { "D3DCOLORtoUBYTE4", "V4", "I", "V4", "F", EShLangAll, false }, - { "ddx", nullptr, nullptr, "SVM", "F", EShLangPS, false }, - { "ddx_coarse", nullptr, nullptr, "SVM", "F", EShLangPS, false }, - { "ddx_fine", nullptr, nullptr, "SVM", "F", EShLangPS, false }, - { "ddy", nullptr, nullptr, "SVM", "F", EShLangPS, false }, - { "ddy_coarse", nullptr, nullptr, "SVM", "F", EShLangPS, false }, - { "ddy_fine", nullptr, nullptr, "SVM", "F", EShLangPS, false }, - { "degrees", nullptr, nullptr, "SVM", "F", EShLangAll, false }, - { "determinant", "S", "F", "M", "F", EShLangAll, false }, - { "DeviceMemoryBarrier", nullptr, nullptr, "-", "-", EShLangPSCS, false }, - { "DeviceMemoryBarrierWithGroupSync", nullptr, nullptr, "-", "-", EShLangCS, false }, - { "distance", "S", "F", "V,", "F,", EShLangAll, false }, - { "dot", "S", nullptr, "SV,", "FI,", EShLangAll, false }, - { "dst", nullptr, nullptr, "V4,", "F,", EShLangAll, false }, - // { "errorf", "-", "-", "", "", EShLangAll, false }, TODO: varargs - { "EvaluateAttributeAtCentroid", nullptr, nullptr, "SVM", "F", EShLangPS, false }, - { "EvaluateAttributeAtSample", nullptr, nullptr, "SVM,S", "F,U", EShLangPS, false }, - { "EvaluateAttributeSnapped", nullptr, nullptr, "SVM,V2", "F,I", EShLangPS, false }, - { "exp", nullptr, nullptr, "SVM", "F", EShLangAll, false }, - { "exp2", nullptr, nullptr, "SVM", "F", EShLangAll, false }, - { "f16tof32", nullptr, "F", "SV", "U", EShLangAll, false }, - { "f32tof16", nullptr, "U", "SV", "F", EShLangAll, false }, - { "faceforward", nullptr, nullptr, "V,,", "F,,", EShLangAll, false }, - { "firstbithigh", nullptr, nullptr, "SV", "UI", EShLangAll, false }, - { "firstbitlow", nullptr, nullptr, "SV", "UI", EShLangAll, false }, - { "floor", nullptr, nullptr, "SVM", "F", EShLangAll, false }, - { "fma", nullptr, nullptr, "SVM,,", "D,,", EShLangAll, false }, - { "fmod", nullptr, nullptr, "SVM,", "F,", EShLangAll, false }, - { "frac", nullptr, nullptr, "SVM", "F", EShLangAll, false }, - { "frexp", nullptr, nullptr, "SVM,", "F,", EShLangAll, false }, - { "fwidth", nullptr, nullptr, "SVM", "F", EShLangPS, false }, - { "GetRenderTargetSampleCount", "S", "U", "-", "-", EShLangAll, false }, - { "GetRenderTargetSamplePosition", "V2", "F", "V1", "I", EShLangAll, false }, - { "GroupMemoryBarrier", nullptr, nullptr, "-", "-", EShLangCS, false }, - { "GroupMemoryBarrierWithGroupSync", nullptr, nullptr, "-", "-", EShLangCS, false }, - { "InterlockedAdd", "-", "-", "SVM,,>", "UI,,", EShLangPSCS, false }, - { "InterlockedAdd", "-", "-", "SVM,", "UI,", EShLangPSCS, false }, - { "InterlockedAnd", "-", "-", "SVM,,>", "UI,,", EShLangPSCS, false }, - { "InterlockedAnd", "-", "-", "SVM,", "UI,", EShLangPSCS, false }, - { "InterlockedCompareExchange", "-", "-", "SVM,,,>", "UI,,,", EShLangPSCS, false }, - { "InterlockedCompareStore", "-", "-", "SVM,,", "UI,,", EShLangPSCS, false }, - { "InterlockedExchange", "-", "-", "SVM,,>", "UI,,", EShLangPSCS, false }, - { "InterlockedMax", "-", "-", "SVM,,>", "UI,,", EShLangPSCS, false }, - { "InterlockedMax", "-", "-", "SVM,", "UI,", EShLangPSCS, false }, - { "InterlockedMin", "-", "-", "SVM,,>", "UI,,", EShLangPSCS, false }, - { "InterlockedMin", "-", "-", "SVM,", "UI,", EShLangPSCS, false }, - { "InterlockedOr", "-", "-", "SVM,,>", "UI,,", EShLangPSCS, false }, - { "InterlockedOr", "-", "-", "SVM,", "UI,", EShLangPSCS, false }, - { "InterlockedXor", "-", "-", "SVM,,>", "UI,,", EShLangPSCS, false }, - { "InterlockedXor", "-", "-", "SVM,", "UI,", EShLangPSCS, false }, - { "isfinite", nullptr, "B" , "SVM", "F", EShLangAll, false }, - { "isinf", nullptr, "B" , "SVM", "F", EShLangAll, false }, - { "isnan", nullptr, "B" , "SVM", "F", EShLangAll, false }, - { "ldexp", nullptr, nullptr, "SVM,", "F,", EShLangAll, false }, - { "length", "S", "F", "SV", "F", EShLangAll, false }, - { "lerp", nullptr, nullptr, "VM,,", "F,,", EShLangAll, false }, - { "lerp", nullptr, nullptr, "SVM,,S", "F,,", EShLangAll, false }, - { "lit", "V4", "F", "S,,", "F,,", EShLangAll, false }, - { "log", nullptr, nullptr, "SVM", "F", EShLangAll, false }, - { "log10", nullptr, nullptr, "SVM", "F", EShLangAll, false }, - { "log2", nullptr, nullptr, "SVM", "F", EShLangAll, false }, - { "mad", nullptr, nullptr, "SVM,,", "DFUI,,", EShLangAll, false }, - { "max", nullptr, nullptr, "SVM,", "FIU,", EShLangAll, false }, - { "min", nullptr, nullptr, "SVM,", "FIU,", EShLangAll, false }, - { "modf", nullptr, nullptr, "SVM,>", "FIU,", EShLangAll, false }, - { "msad4", "V4", "U", "S,V2,V4", "U,,", EShLangAll, false }, - { "mul", "S", nullptr, "S,S", "FI,", EShLangAll, false }, - { "mul", "V", nullptr, "S,V", "FI,", EShLangAll, false }, - { "mul", "M", nullptr, "S,M", "FI,", EShLangAll, false }, - { "mul", "V", nullptr, "V,S", "FI,", EShLangAll, false }, - { "mul", "S", nullptr, "V,V", "FI,", EShLangAll, false }, - { "mul", "M", nullptr, "M,S", "FI,", EShLangAll, false }, - // mat*mat form of mul is handled in createMatTimesMat() - { "noise", "S", "F", "V", "F", EShLangPS, false }, - { "normalize", nullptr, nullptr, "V", "F", EShLangAll, false }, - { "pow", nullptr, nullptr, "SVM,", "F,", EShLangAll, false }, - // { "printf", "-", "-", "", "", EShLangAll, false }, TODO: varargs - { "Process2DQuadTessFactorsAvg", "-", "-", "V4,V2,>V4,>V2,", "F,,,,", EShLangHS, false }, - { "Process2DQuadTessFactorsMax", "-", "-", "V4,V2,>V4,>V2,", "F,,,,", EShLangHS, false }, - { "Process2DQuadTessFactorsMin", "-", "-", "V4,V2,>V4,>V2,", "F,,,,", EShLangHS, false }, - { "ProcessIsolineTessFactors", "-", "-", "S,,>,>", "F,,,", EShLangHS, false }, - { "ProcessQuadTessFactorsAvg", "-", "-", "V4,S,>V4,>V2,", "F,,,,", EShLangHS, false }, - { "ProcessQuadTessFactorsMax", "-", "-", "V4,S,>V4,>V2,", "F,,,,", EShLangHS, false }, - { "ProcessQuadTessFactorsMin", "-", "-", "V4,S,>V4,>V2,", "F,,,,", EShLangHS, false }, - { "ProcessTriTessFactorsAvg", "-", "-", "V3,S,>V3,>S,", "F,,,,", EShLangHS, false }, - { "ProcessTriTessFactorsMax", "-", "-", "V3,S,>V3,>S,", "F,,,,", EShLangHS, false }, - { "ProcessTriTessFactorsMin", "-", "-", "V3,S,>V3,>S,", "F,,,,", EShLangHS, false }, - { "radians", nullptr, nullptr, "SVM", "F", EShLangAll, false }, - { "rcp", nullptr, nullptr, "SVM", "FD", EShLangAll, false }, - { "reflect", nullptr, nullptr, "V,", "F,", EShLangAll, false }, - { "refract", nullptr, nullptr, "V,V,S", "F,,", EShLangAll, false }, - { "reversebits", nullptr, nullptr, "SV", "UI", EShLangAll, false }, - { "round", nullptr, nullptr, "SVM", "F", EShLangAll, false }, - { "rsqrt", nullptr, nullptr, "SVM", "F", EShLangAll, false }, - { "saturate", nullptr, nullptr , "SVM", "F", EShLangAll, false }, - { "sign", nullptr, nullptr, "SVM", "FI", EShLangAll, false }, - { "sin", nullptr, nullptr, "SVM", "F", EShLangAll, false }, - { "sincos", "-", "-", "SVM,>,>", "F,,", EShLangAll, false }, - { "sinh", nullptr, nullptr, "SVM", "F", EShLangAll, false }, - { "smoothstep", nullptr, nullptr, "SVM,,", "F,,", EShLangAll, false }, - { "sqrt", nullptr, nullptr, "SVM", "F", EShLangAll, false }, - { "step", nullptr, nullptr, "SVM,", "F,", EShLangAll, false }, - { "tan", nullptr, nullptr, "SVM", "F", EShLangAll, false }, - { "tanh", nullptr, nullptr, "SVM", "F", EShLangAll, false }, - { "tex1D", "V4", "F", "V1,S", "S,F", EShLangPS, false }, - { "tex1D", "V4", "F", "V1,S,V1,", "S,F,,", EShLangPS, false }, - { "tex1Dbias", "V4", "F", "V1,V4", "S,F", EShLangPS, false }, - { "tex1Dgrad", "V4", "F", "V1,,,", "S,F,,", EShLangPS, false }, - { "tex1Dlod", "V4", "F", "V1,V4", "S,F", EShLangPS, false }, - { "tex1Dproj", "V4", "F", "V1,V4", "S,F", EShLangPS, false }, - { "tex2D", "V4", "F", "V2,", "S,F", EShLangPS, false }, - { "tex2D", "V4", "F", "V2,,,", "S,F,,", EShLangPS, false }, - { "tex2Dbias", "V4", "F", "V2,V4", "S,F", EShLangPS, false }, - { "tex2Dgrad", "V4", "F", "V2,,,", "S,F,,", EShLangPS, false }, - { "tex2Dlod", "V4", "F", "V2,V4", "S,F", EShLangPS, false }, - { "tex2Dproj", "V4", "F", "V2,V4", "S,F", EShLangPS, false }, - { "tex3D", "V4", "F", "V3,", "S,F", EShLangPS, false }, - { "tex3D", "V4", "F", "V3,,,", "S,F,,", EShLangPS, false }, - { "tex3Dbias", "V4", "F", "V3,V4", "S,F", EShLangPS, false }, - { "tex3Dgrad", "V4", "F", "V3,,,", "S,F,,", EShLangPS, false }, - { "tex3Dlod", "V4", "F", "V3,V4", "S,F", EShLangPS, false }, - { "tex3Dproj", "V4", "F", "V3,V4", "S,F", EShLangPS, false }, - { "texCUBE", "V4", "F", "V4,V3", "S,F", EShLangPS, false }, - { "texCUBE", "V4", "F", "V4,V3,,", "S,F,,", EShLangPS, false }, - { "texCUBEbias", "V4", "F", "V4,", "S,F", EShLangPS, false }, - { "texCUBEgrad", "V4", "F", "V4,V3,,", "S,F,,", EShLangPS, false }, - { "texCUBElod", "V4", "F", "V4,", "S,F", EShLangPS, false }, - { "texCUBEproj", "V4", "F", "V4,", "S,F", EShLangPS, false }, - { "transpose", "^M", nullptr, "M", "FUIB", EShLangAll, false }, - { "trunc", nullptr, nullptr, "SVM", "F", EShLangAll, false }, - - // Texture object methods. Return type can be overridden by shader declaration. - // !O = no offset, O = offset - { "Sample", /*!O*/ "V4", nullptr, "%@,S,V", "FIU,S,F", EShLangPS, true }, - { "Sample", /* O*/ "V4", nullptr, "%@,S,V,", "FIU,S,F,I", EShLangPS, true }, - - { "SampleBias", /*!O*/ "V4", nullptr, "%@,S,V,S", "FIU,S,F,", EShLangPS, true }, - { "SampleBias", /* O*/ "V4", nullptr, "%@,S,V,S,V", "FIU,S,F,,I", EShLangPS, true }, - - // TODO: FXC accepts int/uint samplers here. unclear what that means. - { "SampleCmp", /*!O*/ "S", "F", "%@,S,V,S", "FIU,s,F,", EShLangPS, true }, - { "SampleCmp", /* O*/ "S", "F", "%@,S,V,S,V", "FIU,s,F,,I", EShLangPS, true }, - - // TODO: FXC accepts int/uint samplers here. unclear what that means. - { "SampleCmpLevelZero", /*!O*/ "S", "F", "%@,S,V,S", "FIU,s,F,F", EShLangPS, true }, - { "SampleCmpLevelZero", /* O*/ "S", "F", "%@,S,V,S,V", "FIU,s,F,F,I", EShLangPS, true }, - - { "SampleGrad", /*!O*/ "V4", nullptr, "%@,S,V,,", "FIU,S,F,,", EShLangAll, true }, - { "SampleGrad", /* O*/ "V4", nullptr, "%@,S,V,,,", "FIU,S,F,,,I", EShLangAll, true }, - - { "SampleLevel", /*!O*/ "V4", nullptr, "%@,S,V,S", "FIU,S,F,", EShLangAll, true }, - { "SampleLevel", /* O*/ "V4", nullptr, "%@,S,V,S,V", "FIU,S,F,,I", EShLangAll, true }, - - { "Load", /*!O*/ "V4", nullptr, "%@,V", "FIU,I", EShLangAll, true }, - { "Load", /* O*/ "V4", nullptr, "%@,V,V", "FIU,I,I", EShLangAll, true }, - { "Load", /* +sampleidex*/ "V4", nullptr, "$&,V,S", "FIU,I,I", EShLangAll, true }, - { "Load", /* +samplindex, offset*/ "V4", nullptr, "$&,V,S,V", "FIU,I,I,I", EShLangAll, true }, - - // RWTexture loads - { "Load", "V4", nullptr, "!#,V", "FIU,I", EShLangAll, true }, - // (RW)Buffer loads - { "Load", "V4", nullptr, "~*1,V", "FIU,I", EShLangAll, true }, - - { "Gather", /*!O*/ "V4", nullptr, "%@,S,V", "FIU,S,F", EShLangAll, true }, - { "Gather", /* O*/ "V4", nullptr, "%@,S,V,V", "FIU,S,F,I", EShLangAll, true }, - - { "CalculateLevelOfDetail", "S", "F", "%@,S,V", "FUI,S,F", EShLangPS, true }, - { "CalculateLevelOfDetailUnclamped", "S", "F", "%@,S,V", "FUI,S,F", EShLangPS, true }, - - { "GetSamplePosition", "V2", "F", "$&2,S", "FUI,I", EShLangVSPSGS,true }, - - // - // UINT Width - // UINT MipLevel, UINT Width, UINT NumberOfLevels - { "GetDimensions", /* 1D */ "-", "-", "%!~1,>S", "FUI,U", EShLangAll, true }, - { "GetDimensions", /* 1D */ "-", "-", "%!~1,>S", "FUI,F", EShLangAll, true }, - { "GetDimensions", /* 1D */ "-", "-", "%1,S,>S,", "FUI,U,,", EShLangAll, true }, - { "GetDimensions", /* 1D */ "-", "-", "%1,S,>S,", "FUI,U,F,", EShLangAll, true }, - - // UINT Width, UINT Elements - // UINT MipLevel, UINT Width, UINT Elements, UINT NumberOfLevels - { "GetDimensions", /* 1DArray */ "-", "-", "@#1,>S,", "FUI,U,", EShLangAll, true }, - { "GetDimensions", /* 1DArray */ "-", "-", "@#1,>S,", "FUI,F,", EShLangAll, true }, - { "GetDimensions", /* 1DArray */ "-", "-", "@1,S,>S,,", "FUI,U,,,", EShLangAll, true }, - { "GetDimensions", /* 1DArray */ "-", "-", "@1,S,>S,,", "FUI,U,F,,", EShLangAll, true }, - - // UINT Width, UINT Height - // UINT MipLevel, UINT Width, UINT Height, UINT NumberOfLevels - { "GetDimensions", /* 2D */ "-", "-", "%!2,>S,", "FUI,U,", EShLangAll, true }, - { "GetDimensions", /* 2D */ "-", "-", "%!2,>S,", "FUI,F,", EShLangAll, true }, - { "GetDimensions", /* 2D */ "-", "-", "%2,S,>S,,", "FUI,U,,,", EShLangAll, true }, - { "GetDimensions", /* 2D */ "-", "-", "%2,S,>S,,", "FUI,U,F,,", EShLangAll, true }, - - // UINT Width, UINT Height, UINT Elements - // UINT MipLevel, UINT Width, UINT Height, UINT Elements, UINT NumberOfLevels - { "GetDimensions", /* 2DArray */ "-", "-", "@#2,>S,,", "FUI,U,,", EShLangAll, true }, - { "GetDimensions", /* 2DArray */ "-", "-", "@#2,>S,,", "FUI,F,F,F", EShLangAll, true }, - { "GetDimensions", /* 2DArray */ "-", "-", "@2,S,>S,,,", "FUI,U,,,,", EShLangAll, true }, - { "GetDimensions", /* 2DArray */ "-", "-", "@2,S,>S,,,", "FUI,U,F,,,", EShLangAll, true }, - - // UINT Width, UINT Height, UINT Depth - // UINT MipLevel, UINT Width, UINT Height, UINT Depth, UINT NumberOfLevels - { "GetDimensions", /* 3D */ "-", "-", "%!3,>S,,", "FUI,U,,", EShLangAll, true }, - { "GetDimensions", /* 3D */ "-", "-", "%!3,>S,,", "FUI,F,,", EShLangAll, true }, - { "GetDimensions", /* 3D */ "-", "-", "%3,S,>S,,,", "FUI,U,,,,", EShLangAll, true }, - { "GetDimensions", /* 3D */ "-", "-", "%3,S,>S,,,", "FUI,U,F,,,", EShLangAll, true }, - - // UINT Width, UINT Height - // UINT MipLevel, UINT Width, UINT Height, UINT NumberOfLevels - { "GetDimensions", /* Cube */ "-", "-", "%4,>S,", "FUI,U,", EShLangAll, true }, - { "GetDimensions", /* Cube */ "-", "-", "%4,>S,", "FUI,F,", EShLangAll, true }, - { "GetDimensions", /* Cube */ "-", "-", "%4,S,>S,,", "FUI,U,,,", EShLangAll, true }, - { "GetDimensions", /* Cube */ "-", "-", "%4,S,>S,,", "FUI,U,F,,", EShLangAll, true }, - - // UINT Width, UINT Height, UINT Elements - // UINT MipLevel, UINT Width, UINT Height, UINT Elements, UINT NumberOfLevels - { "GetDimensions", /* CubeArray */ "-", "-", "@4,>S,,", "FUI,U,,", EShLangAll, true }, - { "GetDimensions", /* CubeArray */ "-", "-", "@4,>S,,", "FUI,F,,", EShLangAll, true }, - { "GetDimensions", /* CubeArray */ "-", "-", "@4,S,>S,,,", "FUI,U,,,,", EShLangAll, true }, - { "GetDimensions", /* CubeArray */ "-", "-", "@4,S,>S,,,", "FUI,U,F,,,", EShLangAll, true }, - - // UINT Width, UINT Height, UINT Samples - // UINT Width, UINT Height, UINT Elements, UINT Samples - { "GetDimensions", /* 2DMS */ "-", "-", "$2,>S,,", "FUI,U,,", EShLangAll, true }, - { "GetDimensions", /* 2DMS */ "-", "-", "$2,>S,,", "FUI,U,,", EShLangAll, true }, - { "GetDimensions", /* 2DMSArray */ "-", "-", "&2,>S,,,", "FUI,U,,,", EShLangAll, true }, - { "GetDimensions", /* 2DMSArray */ "-", "-", "&2,>S,,,", "FUI,U,,,", EShLangAll, true }, - - // SM5 texture methods - { "GatherRed", /*!O*/ "V4", nullptr, "%@,S,V", "FIU,S,F", EShLangAll, true }, - { "GatherRed", /* O*/ "V4", nullptr, "%@,S,V,", "FIU,S,F,I", EShLangAll, true }, - { "GatherRed", /* O, status*/ "V4", nullptr, "%@,S,V,,>S", "FIU,S,F,I,U", EShLangAll, true }, - { "GatherRed", /* O-4 */ "V4", nullptr, "%@,S,V,,,,", "FIU,S,F,I,,,", EShLangAll, true }, - { "GatherRed", /* O-4, status */"V4", nullptr, "%@,S,V,,,,,S", "FIU,S,F,I,,,,U", EShLangAll, true }, - - { "GatherGreen", /*!O*/ "V4", nullptr, "%@,S,V", "FIU,S,F", EShLangAll, true }, - { "GatherGreen", /* O*/ "V4", nullptr, "%@,S,V,", "FIU,S,F,I", EShLangAll, true }, - { "GatherGreen", /* O, status*/ "V4", nullptr, "%@,S,V,,>S", "FIU,S,F,I,U", EShLangAll, true }, - { "GatherGreen", /* O-4 */ "V4", nullptr, "%@,S,V,,,,", "FIU,S,F,I,,,", EShLangAll, true }, - { "GatherGreen", /* O-4, status */"V4", nullptr, "%@,S,V,,,,,S", "FIU,S,F,I,,,,U", EShLangAll, true }, - - { "GatherBlue", /*!O*/ "V4", nullptr, "%@,S,V", "FIU,S,F", EShLangAll, true }, - { "GatherBlue", /* O*/ "V4", nullptr, "%@,S,V,", "FIU,S,F,I", EShLangAll, true }, - { "GatherBlue", /* O, status*/ "V4", nullptr, "%@,S,V,,>S", "FIU,S,F,I,U", EShLangAll, true }, - { "GatherBlue", /* O-4 */ "V4", nullptr, "%@,S,V,,,,", "FIU,S,F,I,,,", EShLangAll, true }, - { "GatherBlue", /* O-4, status */"V4", nullptr, "%@,S,V,,,,,S", "FIU,S,F,I,,,,U", EShLangAll, true }, - - { "GatherAlpha", /*!O*/ "V4", nullptr, "%@,S,V", "FIU,S,F", EShLangAll, true }, - { "GatherAlpha", /* O*/ "V4", nullptr, "%@,S,V,", "FIU,S,F,I", EShLangAll, true }, - { "GatherAlpha", /* O, status*/ "V4", nullptr, "%@,S,V,,>S", "FIU,S,F,I,U", EShLangAll, true }, - { "GatherAlpha", /* O-4 */ "V4", nullptr, "%@,S,V,,,,", "FIU,S,F,I,,,", EShLangAll, true }, - { "GatherAlpha", /* O-4, status */"V4", nullptr, "%@,S,V,,,,,S", "FIU,S,F,I,,,,U", EShLangAll, true }, - - { "GatherCmp", /*!O*/ "V4", nullptr, "%@,S,V,S", "FIU,s,F,", EShLangAll, true }, - { "GatherCmp", /* O*/ "V4", nullptr, "%@,S,V,S,V", "FIU,s,F,,I", EShLangAll, true }, - { "GatherCmp", /* O, status*/ "V4", nullptr, "%@,S,V,S,V,>S", "FIU,s,F,,I,U", EShLangAll, true }, - { "GatherCmp", /* O-4 */ "V4", nullptr, "%@,S,V,S,V,,,", "FIU,s,F,,I,,,", EShLangAll, true }, - { "GatherCmp", /* O-4, status */"V4", nullptr, "%@,S,V,S,V,,V,S","FIU,s,F,,I,,,,U",EShLangAll, true }, - - { "GatherCmpRed", /*!O*/ "V4", nullptr, "%@,S,V,S", "FIU,s,F,", EShLangAll, true }, - { "GatherCmpRed", /* O*/ "V4", nullptr, "%@,S,V,S,V", "FIU,s,F,,I", EShLangAll, true }, - { "GatherCmpRed", /* O, status*/ "V4", nullptr, "%@,S,V,S,V,>S", "FIU,s,F,,I,U", EShLangAll, true }, - { "GatherCmpRed", /* O-4 */ "V4", nullptr, "%@,S,V,S,V,,,", "FIU,s,F,,I,,,", EShLangAll, true }, - { "GatherCmpRed", /* O-4, status */"V4", nullptr, "%@,S,V,S,V,,V,S","FIU,s,F,,I,,,,U",EShLangAll, true }, - - { "GatherCmpGreen", /*!O*/ "V4", nullptr, "%@,S,V,S", "FIU,s,F,", EShLangAll, true }, - { "GatherCmpGreen", /* O*/ "V4", nullptr, "%@,S,V,S,V", "FIU,s,F,,I", EShLangAll, true }, - { "GatherCmpGreen", /* O, status*/ "V4", nullptr, "%@,S,V,S,V,>S", "FIU,s,F,,I,U", EShLangAll, true }, - { "GatherCmpGreen", /* O-4 */ "V4", nullptr, "%@,S,V,S,V,,,", "FIU,s,F,,I,,,", EShLangAll, true }, - { "GatherCmpGreen", /* O-4, status */"V4", nullptr, "%@,S,V,S,V,,,,S","FIU,s,F,,I,,,,U",EShLangAll, true }, - - { "GatherCmpBlue", /*!O*/ "V4", nullptr, "%@,S,V,S", "FIU,s,F,", EShLangAll, true }, - { "GatherCmpBlue", /* O*/ "V4", nullptr, "%@,S,V,S,V", "FIU,s,F,,I", EShLangAll, true }, - { "GatherCmpBlue", /* O, status*/ "V4", nullptr, "%@,S,V,S,V,>S", "FIU,s,F,,I,U", EShLangAll, true }, - { "GatherCmpBlue", /* O-4 */ "V4", nullptr, "%@,S,V,S,V,,,", "FIU,s,F,,I,,,", EShLangAll, true }, - { "GatherCmpBlue", /* O-4, status */"V4", nullptr, "%@,S,V,S,V,,,,S","FIU,s,F,,I,,,,U",EShLangAll, true }, - - { "GatherCmpAlpha", /*!O*/ "V4", nullptr, "%@,S,V,S", "FIU,s,F,", EShLangAll, true }, - { "GatherCmpAlpha", /* O*/ "V4", nullptr, "%@,S,V,S,V", "FIU,s,F,,I", EShLangAll, true }, - { "GatherCmpAlpha", /* O, status*/ "V4", nullptr, "%@,S,V,S,V,>S", "FIU,s,F,,I,U", EShLangAll, true }, - { "GatherCmpAlpha", /* O-4 */ "V4", nullptr, "%@,S,V,S,V,,,", "FIU,s,F,,I,,,", EShLangAll, true }, - { "GatherCmpAlpha", /* O-4, status */"V4", nullptr, "%@,S,V,S,V,,,,S","FIU,s,F,,I,,,,U",EShLangAll, true }, - - // geometry methods - { "Append", "-", "-", "-", "-", EShLangGS , true }, - { "RestartStrip", "-", "-", "-", "-", EShLangGS , true }, - - // Methods for structurebuffers. TODO: wildcard type matching. - { "Load", nullptr, nullptr, "-", "-", EShLangAll, true }, - { "Load2", nullptr, nullptr, "-", "-", EShLangAll, true }, - { "Load3", nullptr, nullptr, "-", "-", EShLangAll, true }, - { "Load4", nullptr, nullptr, "-", "-", EShLangAll, true }, - { "Store", nullptr, nullptr, "-", "-", EShLangAll, true }, - { "Store2", nullptr, nullptr, "-", "-", EShLangAll, true }, - { "Store3", nullptr, nullptr, "-", "-", EShLangAll, true }, - { "Store4", nullptr, nullptr, "-", "-", EShLangAll, true }, - { "GetDimensions", nullptr, nullptr, "-", "-", EShLangAll, true }, - { "InterlockedAdd", nullptr, nullptr, "-", "-", EShLangAll, true }, - { "InterlockedAnd", nullptr, nullptr, "-", "-", EShLangAll, true }, - { "InterlockedCompareExchange", nullptr, nullptr, "-", "-", EShLangAll, true }, - { "InterlockedCompareStore", nullptr, nullptr, "-", "-", EShLangAll, true }, - { "InterlockedExchange", nullptr, nullptr, "-", "-", EShLangAll, true }, - { "InterlockedMax", nullptr, nullptr, "-", "-", EShLangAll, true }, - { "InterlockedMin", nullptr, nullptr, "-", "-", EShLangAll, true }, - { "InterlockedOr", nullptr, nullptr, "-", "-", EShLangAll, true }, - { "InterlockedXor", nullptr, nullptr, "-", "-", EShLangAll, true }, - { "IncrementCounter", nullptr, nullptr, "-", "-", EShLangAll, true }, - { "DecrementCounter", nullptr, nullptr, "-", "-", EShLangAll, true }, - { "Consume", nullptr, nullptr, "-", "-", EShLangAll, true }, - - // SM 6.0 - - { "WaveIsFirstLane", "S", "B", "-", "-", EShLangPSCS, false}, - { "WaveGetLaneCount", "S", "U", "-", "-", EShLangPSCS, false}, - { "WaveGetLaneIndex", "S", "U", "-", "-", EShLangPSCS, false}, - { "WaveActiveAnyTrue", "S", "B", "S", "B", EShLangPSCS, false}, - { "WaveActiveAllTrue", "S", "B", "S", "B", EShLangPSCS, false}, - { "WaveActiveBallot", "V4", "U", "S", "B", EShLangPSCS, false}, - { "WaveReadLaneAt", nullptr, nullptr, "SV,S", "DFUI,U", EShLangPSCS, false}, - { "WaveReadLaneFirst", nullptr, nullptr, "SV", "DFUI", EShLangPSCS, false}, - { "WaveActiveAllEqual", "S", "B", "SV", "DFUI", EShLangPSCS, false}, - { "WaveActiveAllEqualBool", "S", "B", "S", "B", EShLangPSCS, false}, - { "WaveActiveCountBits", "S", "U", "S", "B", EShLangPSCS, false}, - - { "WaveActiveSum", nullptr, nullptr, "SV", "DFUI", EShLangPSCS, false}, - { "WaveActiveProduct", nullptr, nullptr, "SV", "DFUI", EShLangPSCS, false}, - { "WaveActiveBitAnd", nullptr, nullptr, "SV", "DFUI", EShLangPSCS, false}, - { "WaveActiveBitOr", nullptr, nullptr, "SV", "DFUI", EShLangPSCS, false}, - { "WaveActiveBitXor", nullptr, nullptr, "SV", "DFUI", EShLangPSCS, false}, - { "WaveActiveMin", nullptr, nullptr, "SV", "DFUI", EShLangPSCS, false}, - { "WaveActiveMax", nullptr, nullptr, "SV", "DFUI", EShLangPSCS, false}, - { "WavePrefixSum", nullptr, nullptr, "SV", "DFUI", EShLangPSCS, false}, - { "WavePrefixProduct", nullptr, nullptr, "SV", "DFUI", EShLangPSCS, false}, - { "WavePrefixCountBits", "S", "U", "S", "B", EShLangPSCS, false}, - { "QuadReadAcrossX", nullptr, nullptr, "SV", "DFUI", EShLangPSCS, false}, - { "QuadReadAcrossY", nullptr, nullptr, "SV", "DFUI", EShLangPSCS, false}, - { "QuadReadAcrossDiagonal", nullptr, nullptr, "SV", "DFUI", EShLangPSCS, false}, - { "QuadReadLaneAt", nullptr, nullptr, "SV,S", "DFUI,U", EShLangPSCS, false}, - - // Methods for subpass input objects - { "SubpassLoad", "V4", nullptr, "[", "FIU", EShLangPS, true }, - { "SubpassLoad", "V4", nullptr, "],S", "FIU,I", EShLangPS, true }, - - // Mark end of list, since we want to avoid a range-based for, as some compilers don't handle it yet. - { nullptr, nullptr, nullptr, nullptr, nullptr, 0, false }, - }; - - // Create prototypes for the intrinsics. TODO: Avoid ranged based for until all compilers can handle it. - for (int icount = 0; hlslIntrinsics[icount].name; ++icount) { - const auto& intrinsic = hlslIntrinsics[icount]; - - for (int stage = 0; stage < EShLangCount; ++stage) { // for each stage... - if ((intrinsic.stage & (1< 0 ? std::min(dim0, 3) : dim0; - - s.append(arg > 0 ? ", ": ""); // comma separator if needed - - const char* orderBegin = nthArgOrder; - nthArgOrder = IoParam(s, nthArgOrder); - - // Comma means use the previous argument order and type. - HandleRepeatArg(nthArgOrder, prevArgOrder, orderBegin); - HandleRepeatArg(nthArgType, prevArgType, nthArgType); - - // In case the repeated arg has its own I/O marker - nthArgOrder = IoParam(s, nthArgOrder); - - // arrayed textures have one extra coordinate dimension, except for - // the CalculateLevelOfDetail family. - if (isArrayed && arg == coordArg && !NoArrayCoord(intrinsic.name)) - argDim0++; - - // Some texture methods use an addition arg dimension to hold mip - if (arg == coordArg && mipInCoord) - argDim0++; - - // For textures, the 1D case isn't a 1-vector, but a scalar. - if (isTexture && argDim0 == 1 && arg > 0 && *nthArgOrder == 'V') - nthArgOrder = "S"; - - AppendTypeName(s, nthArgOrder, nthArgType, argDim0, dim1); // Add arguments - } - - s.append(");\n"); // close paren and trailing semicolon - } // dim 1 loop - } // dim 0 loop - } // arg type loop - - // skip over special characters - if (isTexture && isalpha(argOrder[1])) - ++argOrder; - if (isdigit(argOrder[1])) - ++argOrder; - } // arg order loop - - if (intrinsic.stage == EShLangAll) // common builtins are only added once. - break; - } - } - - createMatTimesMat(); // handle this case separately, for convenience - - // printf("Common:\n%s\n", getCommonString().c_str()); - // printf("Frag:\n%s\n", getStageString(EShLangFragment).c_str()); - // printf("Vertex:\n%s\n", getStageString(EShLangVertex).c_str()); - // printf("Geo:\n%s\n", getStageString(EShLangGeometry).c_str()); - // printf("TessCtrl:\n%s\n", getStageString(EShLangTessControl).c_str()); - // printf("TessEval:\n%s\n", getStageString(EShLangTessEvaluation).c_str()); - // printf("Compute:\n%s\n", getStageString(EShLangCompute).c_str()); -} - -// -// Add context-dependent built-in functions and variables that are present -// for the given version and profile. All the results are put into just the -// commonBuiltins, because it is called for just a specific stage. So, -// add stage-specific entries to the commonBuiltins, and only if that stage -// was requested. -// -void TBuiltInParseablesHlsl::initialize(const TBuiltInResource& /*resources*/, int /*version*/, EProfile /*profile*/, - const SpvVersion& /*spvVersion*/, EShLanguage /*language*/) -{ -} - -// -// Finish adding/processing context-independent built-in symbols. -// 1) Programmatically add symbols that could not be added by simple text strings above. -// 2) Map built-in functions to operators, for those that will turn into an operation node -// instead of remaining a function call. -// 3) Tag extension-related symbols added to their base version with their extensions, so -// that if an early version has the extension turned off, there is an error reported on use. -// -void TBuiltInParseablesHlsl::identifyBuiltIns(int /*version*/, EProfile /*profile*/, const SpvVersion& /*spvVersion*/, EShLanguage /*language*/, - TSymbolTable& symbolTable) -{ - // symbolTable.relateToOperator("abort", EOpAbort); - symbolTable.relateToOperator("abs", EOpAbs); - symbolTable.relateToOperator("acos", EOpAcos); - symbolTable.relateToOperator("all", EOpAll); - symbolTable.relateToOperator("AllMemoryBarrier", EOpMemoryBarrier); - symbolTable.relateToOperator("AllMemoryBarrierWithGroupSync", EOpAllMemoryBarrierWithGroupSync); - symbolTable.relateToOperator("any", EOpAny); - symbolTable.relateToOperator("asdouble", EOpAsDouble); - symbolTable.relateToOperator("asfloat", EOpIntBitsToFloat); - symbolTable.relateToOperator("asin", EOpAsin); - symbolTable.relateToOperator("asint", EOpFloatBitsToInt); - symbolTable.relateToOperator("asuint", EOpFloatBitsToUint); - symbolTable.relateToOperator("atan", EOpAtan); - symbolTable.relateToOperator("atan2", EOpAtan); - symbolTable.relateToOperator("ceil", EOpCeil); - // symbolTable.relateToOperator("CheckAccessFullyMapped"); - symbolTable.relateToOperator("clamp", EOpClamp); - symbolTable.relateToOperator("clip", EOpClip); - symbolTable.relateToOperator("cos", EOpCos); - symbolTable.relateToOperator("cosh", EOpCosh); - symbolTable.relateToOperator("countbits", EOpBitCount); - symbolTable.relateToOperator("cross", EOpCross); - symbolTable.relateToOperator("D3DCOLORtoUBYTE4", EOpD3DCOLORtoUBYTE4); - symbolTable.relateToOperator("ddx", EOpDPdx); - symbolTable.relateToOperator("ddx_coarse", EOpDPdxCoarse); - symbolTable.relateToOperator("ddx_fine", EOpDPdxFine); - symbolTable.relateToOperator("ddy", EOpDPdy); - symbolTable.relateToOperator("ddy_coarse", EOpDPdyCoarse); - symbolTable.relateToOperator("ddy_fine", EOpDPdyFine); - symbolTable.relateToOperator("degrees", EOpDegrees); - symbolTable.relateToOperator("determinant", EOpDeterminant); - symbolTable.relateToOperator("DeviceMemoryBarrier", EOpDeviceMemoryBarrier); - symbolTable.relateToOperator("DeviceMemoryBarrierWithGroupSync", EOpDeviceMemoryBarrierWithGroupSync); - symbolTable.relateToOperator("distance", EOpDistance); - symbolTable.relateToOperator("dot", EOpDot); - symbolTable.relateToOperator("dst", EOpDst); - // symbolTable.relateToOperator("errorf", EOpErrorf); - symbolTable.relateToOperator("EvaluateAttributeAtCentroid", EOpInterpolateAtCentroid); - symbolTable.relateToOperator("EvaluateAttributeAtSample", EOpInterpolateAtSample); - symbolTable.relateToOperator("EvaluateAttributeSnapped", EOpEvaluateAttributeSnapped); - symbolTable.relateToOperator("exp", EOpExp); - symbolTable.relateToOperator("exp2", EOpExp2); - symbolTable.relateToOperator("f16tof32", EOpF16tof32); - symbolTable.relateToOperator("f32tof16", EOpF32tof16); - symbolTable.relateToOperator("faceforward", EOpFaceForward); - symbolTable.relateToOperator("firstbithigh", EOpFindMSB); - symbolTable.relateToOperator("firstbitlow", EOpFindLSB); - symbolTable.relateToOperator("floor", EOpFloor); - symbolTable.relateToOperator("fma", EOpFma); - symbolTable.relateToOperator("fmod", EOpMod); - symbolTable.relateToOperator("frac", EOpFract); - symbolTable.relateToOperator("frexp", EOpFrexp); - symbolTable.relateToOperator("fwidth", EOpFwidth); - // symbolTable.relateToOperator("GetRenderTargetSampleCount"); - // symbolTable.relateToOperator("GetRenderTargetSamplePosition"); - symbolTable.relateToOperator("GroupMemoryBarrier", EOpWorkgroupMemoryBarrier); - symbolTable.relateToOperator("GroupMemoryBarrierWithGroupSync", EOpWorkgroupMemoryBarrierWithGroupSync); - symbolTable.relateToOperator("InterlockedAdd", EOpInterlockedAdd); - symbolTable.relateToOperator("InterlockedAnd", EOpInterlockedAnd); - symbolTable.relateToOperator("InterlockedCompareExchange", EOpInterlockedCompareExchange); - symbolTable.relateToOperator("InterlockedCompareStore", EOpInterlockedCompareStore); - symbolTable.relateToOperator("InterlockedExchange", EOpInterlockedExchange); - symbolTable.relateToOperator("InterlockedMax", EOpInterlockedMax); - symbolTable.relateToOperator("InterlockedMin", EOpInterlockedMin); - symbolTable.relateToOperator("InterlockedOr", EOpInterlockedOr); - symbolTable.relateToOperator("InterlockedXor", EOpInterlockedXor); - symbolTable.relateToOperator("isfinite", EOpIsFinite); - symbolTable.relateToOperator("isinf", EOpIsInf); - symbolTable.relateToOperator("isnan", EOpIsNan); - symbolTable.relateToOperator("ldexp", EOpLdexp); - symbolTable.relateToOperator("length", EOpLength); - symbolTable.relateToOperator("lerp", EOpMix); - symbolTable.relateToOperator("lit", EOpLit); - symbolTable.relateToOperator("log", EOpLog); - symbolTable.relateToOperator("log10", EOpLog10); - symbolTable.relateToOperator("log2", EOpLog2); - symbolTable.relateToOperator("mad", EOpFma); - symbolTable.relateToOperator("max", EOpMax); - symbolTable.relateToOperator("min", EOpMin); - symbolTable.relateToOperator("modf", EOpModf); - // symbolTable.relateToOperator("msad4", EOpMsad4); - symbolTable.relateToOperator("mul", EOpGenMul); - // symbolTable.relateToOperator("noise", EOpNoise); // TODO: check return type - symbolTable.relateToOperator("normalize", EOpNormalize); - symbolTable.relateToOperator("pow", EOpPow); - // symbolTable.relateToOperator("printf", EOpPrintf); - // symbolTable.relateToOperator("Process2DQuadTessFactorsAvg"); - // symbolTable.relateToOperator("Process2DQuadTessFactorsMax"); - // symbolTable.relateToOperator("Process2DQuadTessFactorsMin"); - // symbolTable.relateToOperator("ProcessIsolineTessFactors"); - // symbolTable.relateToOperator("ProcessQuadTessFactorsAvg"); - // symbolTable.relateToOperator("ProcessQuadTessFactorsMax"); - // symbolTable.relateToOperator("ProcessQuadTessFactorsMin"); - // symbolTable.relateToOperator("ProcessTriTessFactorsAvg"); - // symbolTable.relateToOperator("ProcessTriTessFactorsMax"); - // symbolTable.relateToOperator("ProcessTriTessFactorsMin"); - symbolTable.relateToOperator("radians", EOpRadians); - symbolTable.relateToOperator("rcp", EOpRcp); - symbolTable.relateToOperator("reflect", EOpReflect); - symbolTable.relateToOperator("refract", EOpRefract); - symbolTable.relateToOperator("reversebits", EOpBitFieldReverse); - symbolTable.relateToOperator("round", EOpRoundEven); - symbolTable.relateToOperator("rsqrt", EOpInverseSqrt); - symbolTable.relateToOperator("saturate", EOpSaturate); - symbolTable.relateToOperator("sign", EOpSign); - symbolTable.relateToOperator("sin", EOpSin); - symbolTable.relateToOperator("sincos", EOpSinCos); - symbolTable.relateToOperator("sinh", EOpSinh); - symbolTable.relateToOperator("smoothstep", EOpSmoothStep); - symbolTable.relateToOperator("sqrt", EOpSqrt); - symbolTable.relateToOperator("step", EOpStep); - symbolTable.relateToOperator("tan", EOpTan); - symbolTable.relateToOperator("tanh", EOpTanh); - symbolTable.relateToOperator("tex1D", EOpTexture); - symbolTable.relateToOperator("tex1Dbias", EOpTextureBias); - symbolTable.relateToOperator("tex1Dgrad", EOpTextureGrad); - symbolTable.relateToOperator("tex1Dlod", EOpTextureLod); - symbolTable.relateToOperator("tex1Dproj", EOpTextureProj); - symbolTable.relateToOperator("tex2D", EOpTexture); - symbolTable.relateToOperator("tex2Dbias", EOpTextureBias); - symbolTable.relateToOperator("tex2Dgrad", EOpTextureGrad); - symbolTable.relateToOperator("tex2Dlod", EOpTextureLod); - symbolTable.relateToOperator("tex2Dproj", EOpTextureProj); - symbolTable.relateToOperator("tex3D", EOpTexture); - symbolTable.relateToOperator("tex3Dbias", EOpTextureBias); - symbolTable.relateToOperator("tex3Dgrad", EOpTextureGrad); - symbolTable.relateToOperator("tex3Dlod", EOpTextureLod); - symbolTable.relateToOperator("tex3Dproj", EOpTextureProj); - symbolTable.relateToOperator("texCUBE", EOpTexture); - symbolTable.relateToOperator("texCUBEbias", EOpTextureBias); - symbolTable.relateToOperator("texCUBEgrad", EOpTextureGrad); - symbolTable.relateToOperator("texCUBElod", EOpTextureLod); - symbolTable.relateToOperator("texCUBEproj", EOpTextureProj); - symbolTable.relateToOperator("transpose", EOpTranspose); - symbolTable.relateToOperator("trunc", EOpTrunc); - - // Texture methods - symbolTable.relateToOperator(BUILTIN_PREFIX "Sample", EOpMethodSample); - symbolTable.relateToOperator(BUILTIN_PREFIX "SampleBias", EOpMethodSampleBias); - symbolTable.relateToOperator(BUILTIN_PREFIX "SampleCmp", EOpMethodSampleCmp); - symbolTable.relateToOperator(BUILTIN_PREFIX "SampleCmpLevelZero", EOpMethodSampleCmpLevelZero); - symbolTable.relateToOperator(BUILTIN_PREFIX "SampleGrad", EOpMethodSampleGrad); - symbolTable.relateToOperator(BUILTIN_PREFIX "SampleLevel", EOpMethodSampleLevel); - symbolTable.relateToOperator(BUILTIN_PREFIX "Load", EOpMethodLoad); - symbolTable.relateToOperator(BUILTIN_PREFIX "GetDimensions", EOpMethodGetDimensions); - symbolTable.relateToOperator(BUILTIN_PREFIX "GetSamplePosition", EOpMethodGetSamplePosition); - symbolTable.relateToOperator(BUILTIN_PREFIX "Gather", EOpMethodGather); - symbolTable.relateToOperator(BUILTIN_PREFIX "CalculateLevelOfDetail", EOpMethodCalculateLevelOfDetail); - symbolTable.relateToOperator(BUILTIN_PREFIX "CalculateLevelOfDetailUnclamped", EOpMethodCalculateLevelOfDetailUnclamped); - - // Structure buffer methods (excluding associations already made above for texture methods w/ same name) - symbolTable.relateToOperator(BUILTIN_PREFIX "Load2", EOpMethodLoad2); - symbolTable.relateToOperator(BUILTIN_PREFIX "Load3", EOpMethodLoad3); - symbolTable.relateToOperator(BUILTIN_PREFIX "Load4", EOpMethodLoad4); - symbolTable.relateToOperator(BUILTIN_PREFIX "Store", EOpMethodStore); - symbolTable.relateToOperator(BUILTIN_PREFIX "Store2", EOpMethodStore2); - symbolTable.relateToOperator(BUILTIN_PREFIX "Store3", EOpMethodStore3); - symbolTable.relateToOperator(BUILTIN_PREFIX "Store4", EOpMethodStore4); - symbolTable.relateToOperator(BUILTIN_PREFIX "IncrementCounter", EOpMethodIncrementCounter); - symbolTable.relateToOperator(BUILTIN_PREFIX "DecrementCounter", EOpMethodDecrementCounter); - // Append is also a GS method: we don't add it twice - symbolTable.relateToOperator(BUILTIN_PREFIX "Consume", EOpMethodConsume); - - symbolTable.relateToOperator(BUILTIN_PREFIX "InterlockedAdd", EOpInterlockedAdd); - symbolTable.relateToOperator(BUILTIN_PREFIX "InterlockedAnd", EOpInterlockedAnd); - symbolTable.relateToOperator(BUILTIN_PREFIX "InterlockedCompareExchange", EOpInterlockedCompareExchange); - symbolTable.relateToOperator(BUILTIN_PREFIX "InterlockedCompareStore", EOpInterlockedCompareStore); - symbolTable.relateToOperator(BUILTIN_PREFIX "InterlockedExchange", EOpInterlockedExchange); - symbolTable.relateToOperator(BUILTIN_PREFIX "InterlockedMax", EOpInterlockedMax); - symbolTable.relateToOperator(BUILTIN_PREFIX "InterlockedMin", EOpInterlockedMin); - symbolTable.relateToOperator(BUILTIN_PREFIX "InterlockedOr", EOpInterlockedOr); - symbolTable.relateToOperator(BUILTIN_PREFIX "InterlockedXor", EOpInterlockedXor); - - // SM5 Texture methods - symbolTable.relateToOperator(BUILTIN_PREFIX "GatherRed", EOpMethodGatherRed); - symbolTable.relateToOperator(BUILTIN_PREFIX "GatherGreen", EOpMethodGatherGreen); - symbolTable.relateToOperator(BUILTIN_PREFIX "GatherBlue", EOpMethodGatherBlue); - symbolTable.relateToOperator(BUILTIN_PREFIX "GatherAlpha", EOpMethodGatherAlpha); - symbolTable.relateToOperator(BUILTIN_PREFIX "GatherCmp", EOpMethodGatherCmpRed); // alias - symbolTable.relateToOperator(BUILTIN_PREFIX "GatherCmpRed", EOpMethodGatherCmpRed); - symbolTable.relateToOperator(BUILTIN_PREFIX "GatherCmpGreen", EOpMethodGatherCmpGreen); - symbolTable.relateToOperator(BUILTIN_PREFIX "GatherCmpBlue", EOpMethodGatherCmpBlue); - symbolTable.relateToOperator(BUILTIN_PREFIX "GatherCmpAlpha", EOpMethodGatherCmpAlpha); - - // GS methods - symbolTable.relateToOperator(BUILTIN_PREFIX "Append", EOpMethodAppend); - symbolTable.relateToOperator(BUILTIN_PREFIX "RestartStrip", EOpMethodRestartStrip); - - // Wave ops - symbolTable.relateToOperator("WaveIsFirstLane", EOpSubgroupElect); - symbolTable.relateToOperator("WaveGetLaneCount", EOpWaveGetLaneCount); - symbolTable.relateToOperator("WaveGetLaneIndex", EOpWaveGetLaneIndex); - symbolTable.relateToOperator("WaveActiveAnyTrue", EOpSubgroupAny); - symbolTable.relateToOperator("WaveActiveAllTrue", EOpSubgroupAll); - symbolTable.relateToOperator("WaveActiveBallot", EOpSubgroupBallot); - symbolTable.relateToOperator("WaveReadLaneFirst", EOpSubgroupBroadcastFirst); - symbolTable.relateToOperator("WaveReadLaneAt", EOpSubgroupShuffle); - symbolTable.relateToOperator("WaveActiveAllEqual", EOpSubgroupAllEqual); - symbolTable.relateToOperator("WaveActiveAllEqualBool", EOpSubgroupAllEqual); - symbolTable.relateToOperator("WaveActiveCountBits", EOpWaveActiveCountBits); - symbolTable.relateToOperator("WaveActiveSum", EOpSubgroupAdd); - symbolTable.relateToOperator("WaveActiveProduct", EOpSubgroupMul); - symbolTable.relateToOperator("WaveActiveBitAnd", EOpSubgroupAnd); - symbolTable.relateToOperator("WaveActiveBitOr", EOpSubgroupOr); - symbolTable.relateToOperator("WaveActiveBitXor", EOpSubgroupXor); - symbolTable.relateToOperator("WaveActiveMin", EOpSubgroupMin); - symbolTable.relateToOperator("WaveActiveMax", EOpSubgroupMax); - symbolTable.relateToOperator("WavePrefixSum", EOpSubgroupInclusiveAdd); - symbolTable.relateToOperator("WavePrefixProduct", EOpSubgroupInclusiveMul); - symbolTable.relateToOperator("WavePrefixCountBits", EOpWavePrefixCountBits); - symbolTable.relateToOperator("QuadReadAcrossX", EOpSubgroupQuadSwapHorizontal); - symbolTable.relateToOperator("QuadReadAcrossY", EOpSubgroupQuadSwapVertical); - symbolTable.relateToOperator("QuadReadAcrossDiagonal", EOpSubgroupQuadSwapDiagonal); - symbolTable.relateToOperator("QuadReadLaneAt", EOpSubgroupQuadBroadcast); - - // Subpass input methods - symbolTable.relateToOperator(BUILTIN_PREFIX "SubpassLoad", EOpSubpassLoad); - symbolTable.relateToOperator(BUILTIN_PREFIX "SubpassLoadMS", EOpSubpassLoadMS); -} - -// -// Add context-dependent (resource-specific) built-ins not handled by the above. These -// would be ones that need to be programmatically added because they cannot -// be added by simple text strings. For these, also -// 1) Map built-in functions to operators, for those that will turn into an operation node -// instead of remaining a function call. -// 2) Tag extension-related symbols added to their base version with their extensions, so -// that if an early version has the extension turned off, there is an error reported on use. -// -void TBuiltInParseablesHlsl::identifyBuiltIns(int /*version*/, EProfile /*profile*/, const SpvVersion& /*spvVersion*/, EShLanguage /*language*/, - TSymbolTable& /*symbolTable*/, const TBuiltInResource& /*resources*/) -{ -} - -} // end namespace glslang diff --git a/External/glslang/hlsl/hlslParseables.h b/External/glslang/hlsl/hlslParseables.h deleted file mode 100644 index 28f424b3..00000000 --- a/External/glslang/hlsl/hlslParseables.h +++ /dev/null @@ -1,64 +0,0 @@ -// -// 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 _HLSLPARSEABLES_INCLUDED_ -#define _HLSLPARSEABLES_INCLUDED_ - -#include "../glslang/MachineIndependent/Initialize.h" - -namespace glslang { - -// -// This is an HLSL specific derivation of TBuiltInParseables. See comment -// above TBuiltInParseables for details. -// -class TBuiltInParseablesHlsl : public TBuiltInParseables { -public: - POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator()) - TBuiltInParseablesHlsl(); - 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); - -private: - void createMatTimesMat(); -}; - -} // end namespace glslang - -#endif // _HLSLPARSEABLES_INCLUDED_ diff --git a/External/glslang/hlsl/hlslScanContext.cpp b/External/glslang/hlsl/hlslScanContext.cpp deleted file mode 100644 index 28a66bb4..00000000 --- a/External/glslang/hlsl/hlslScanContext.cpp +++ /dev/null @@ -1,903 +0,0 @@ -// -// Copyright (C) 2016 Google, Inc. -// 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 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. -// - -// -// HLSL scanning, leveraging the scanning done by the preprocessor. -// - -#include -#include -#include - -#include "../glslang/Include/Types.h" -#include "../glslang/MachineIndependent/SymbolTable.h" -#include "../glslang/MachineIndependent/ParseHelper.h" -#include "hlslScanContext.h" -#include "hlslTokens.h" - -// preprocessor includes -#include "../glslang/MachineIndependent/preprocessor/PpContext.h" -#include "../glslang/MachineIndependent/preprocessor/PpTokens.h" - -namespace { - -struct str_eq -{ - bool operator()(const char* lhs, const char* rhs) const - { - return strcmp(lhs, rhs) == 0; - } -}; - -struct str_hash -{ - size_t operator()(const char* str) const - { - // djb2 - unsigned long hash = 5381; - int c; - - while ((c = *str++) != 0) - hash = ((hash << 5) + hash) + c; - - return hash; - } -}; - -// A single global usable by all threads, by all versions, by all languages. -// After a single process-level initialization, this is read only and thread safe -std::unordered_map* KeywordMap = nullptr; -std::unordered_set* ReservedSet = nullptr; -std::unordered_map* SemanticMap = nullptr; - -}; - -namespace glslang { - -void HlslScanContext::fillInKeywordMap() -{ - if (KeywordMap != nullptr) { - // this is really an error, as this should called only once per process - // but, the only risk is if two threads called simultaneously - return; - } - KeywordMap = new std::unordered_map; - - (*KeywordMap)["static"] = EHTokStatic; - (*KeywordMap)["const"] = EHTokConst; - (*KeywordMap)["unorm"] = EHTokUnorm; - (*KeywordMap)["snorm"] = EHTokSNorm; - (*KeywordMap)["extern"] = EHTokExtern; - (*KeywordMap)["uniform"] = EHTokUniform; - (*KeywordMap)["volatile"] = EHTokVolatile; - (*KeywordMap)["precise"] = EHTokPrecise; - (*KeywordMap)["shared"] = EHTokShared; - (*KeywordMap)["groupshared"] = EHTokGroupShared; - (*KeywordMap)["linear"] = EHTokLinear; - (*KeywordMap)["centroid"] = EHTokCentroid; - (*KeywordMap)["nointerpolation"] = EHTokNointerpolation; - (*KeywordMap)["noperspective"] = EHTokNoperspective; - (*KeywordMap)["sample"] = EHTokSample; - (*KeywordMap)["row_major"] = EHTokRowMajor; - (*KeywordMap)["column_major"] = EHTokColumnMajor; - (*KeywordMap)["packoffset"] = EHTokPackOffset; - (*KeywordMap)["in"] = EHTokIn; - (*KeywordMap)["out"] = EHTokOut; - (*KeywordMap)["inout"] = EHTokInOut; - (*KeywordMap)["layout"] = EHTokLayout; - (*KeywordMap)["globallycoherent"] = EHTokGloballyCoherent; - (*KeywordMap)["inline"] = EHTokInline; - - (*KeywordMap)["point"] = EHTokPoint; - (*KeywordMap)["line"] = EHTokLine; - (*KeywordMap)["triangle"] = EHTokTriangle; - (*KeywordMap)["lineadj"] = EHTokLineAdj; - (*KeywordMap)["triangleadj"] = EHTokTriangleAdj; - - (*KeywordMap)["PointStream"] = EHTokPointStream; - (*KeywordMap)["LineStream"] = EHTokLineStream; - (*KeywordMap)["TriangleStream"] = EHTokTriangleStream; - - (*KeywordMap)["InputPatch"] = EHTokInputPatch; - (*KeywordMap)["OutputPatch"] = EHTokOutputPatch; - - (*KeywordMap)["Buffer"] = EHTokBuffer; - (*KeywordMap)["vector"] = EHTokVector; - (*KeywordMap)["matrix"] = EHTokMatrix; - - (*KeywordMap)["void"] = EHTokVoid; - (*KeywordMap)["string"] = EHTokString; - (*KeywordMap)["bool"] = EHTokBool; - (*KeywordMap)["int"] = EHTokInt; - (*KeywordMap)["uint"] = EHTokUint; - (*KeywordMap)["uint64_t"] = EHTokUint64; - (*KeywordMap)["dword"] = EHTokDword; - (*KeywordMap)["half"] = EHTokHalf; - (*KeywordMap)["float"] = EHTokFloat; - (*KeywordMap)["double"] = EHTokDouble; - (*KeywordMap)["min16float"] = EHTokMin16float; - (*KeywordMap)["min10float"] = EHTokMin10float; - (*KeywordMap)["min16int"] = EHTokMin16int; - (*KeywordMap)["min12int"] = EHTokMin12int; - (*KeywordMap)["min16uint"] = EHTokMin16uint; - - (*KeywordMap)["bool1"] = EHTokBool1; - (*KeywordMap)["bool2"] = EHTokBool2; - (*KeywordMap)["bool3"] = EHTokBool3; - (*KeywordMap)["bool4"] = EHTokBool4; - (*KeywordMap)["float1"] = EHTokFloat1; - (*KeywordMap)["float2"] = EHTokFloat2; - (*KeywordMap)["float3"] = EHTokFloat3; - (*KeywordMap)["float4"] = EHTokFloat4; - (*KeywordMap)["int1"] = EHTokInt1; - (*KeywordMap)["int2"] = EHTokInt2; - (*KeywordMap)["int3"] = EHTokInt3; - (*KeywordMap)["int4"] = EHTokInt4; - (*KeywordMap)["double1"] = EHTokDouble1; - (*KeywordMap)["double2"] = EHTokDouble2; - (*KeywordMap)["double3"] = EHTokDouble3; - (*KeywordMap)["double4"] = EHTokDouble4; - (*KeywordMap)["uint1"] = EHTokUint1; - (*KeywordMap)["uint2"] = EHTokUint2; - (*KeywordMap)["uint3"] = EHTokUint3; - (*KeywordMap)["uint4"] = EHTokUint4; - - (*KeywordMap)["half1"] = EHTokHalf1; - (*KeywordMap)["half2"] = EHTokHalf2; - (*KeywordMap)["half3"] = EHTokHalf3; - (*KeywordMap)["half4"] = EHTokHalf4; - (*KeywordMap)["min16float1"] = EHTokMin16float1; - (*KeywordMap)["min16float2"] = EHTokMin16float2; - (*KeywordMap)["min16float3"] = EHTokMin16float3; - (*KeywordMap)["min16float4"] = EHTokMin16float4; - (*KeywordMap)["min10float1"] = EHTokMin10float1; - (*KeywordMap)["min10float2"] = EHTokMin10float2; - (*KeywordMap)["min10float3"] = EHTokMin10float3; - (*KeywordMap)["min10float4"] = EHTokMin10float4; - (*KeywordMap)["min16int1"] = EHTokMin16int1; - (*KeywordMap)["min16int2"] = EHTokMin16int2; - (*KeywordMap)["min16int3"] = EHTokMin16int3; - (*KeywordMap)["min16int4"] = EHTokMin16int4; - (*KeywordMap)["min12int1"] = EHTokMin12int1; - (*KeywordMap)["min12int2"] = EHTokMin12int2; - (*KeywordMap)["min12int3"] = EHTokMin12int3; - (*KeywordMap)["min12int4"] = EHTokMin12int4; - (*KeywordMap)["min16uint1"] = EHTokMin16uint1; - (*KeywordMap)["min16uint2"] = EHTokMin16uint2; - (*KeywordMap)["min16uint3"] = EHTokMin16uint3; - (*KeywordMap)["min16uint4"] = EHTokMin16uint4; - - (*KeywordMap)["bool1x1"] = EHTokBool1x1; - (*KeywordMap)["bool1x2"] = EHTokBool1x2; - (*KeywordMap)["bool1x3"] = EHTokBool1x3; - (*KeywordMap)["bool1x4"] = EHTokBool1x4; - (*KeywordMap)["bool2x1"] = EHTokBool2x1; - (*KeywordMap)["bool2x2"] = EHTokBool2x2; - (*KeywordMap)["bool2x3"] = EHTokBool2x3; - (*KeywordMap)["bool2x4"] = EHTokBool2x4; - (*KeywordMap)["bool3x1"] = EHTokBool3x1; - (*KeywordMap)["bool3x2"] = EHTokBool3x2; - (*KeywordMap)["bool3x3"] = EHTokBool3x3; - (*KeywordMap)["bool3x4"] = EHTokBool3x4; - (*KeywordMap)["bool4x1"] = EHTokBool4x1; - (*KeywordMap)["bool4x2"] = EHTokBool4x2; - (*KeywordMap)["bool4x3"] = EHTokBool4x3; - (*KeywordMap)["bool4x4"] = EHTokBool4x4; - (*KeywordMap)["int1x1"] = EHTokInt1x1; - (*KeywordMap)["int1x2"] = EHTokInt1x2; - (*KeywordMap)["int1x3"] = EHTokInt1x3; - (*KeywordMap)["int1x4"] = EHTokInt1x4; - (*KeywordMap)["int2x1"] = EHTokInt2x1; - (*KeywordMap)["int2x2"] = EHTokInt2x2; - (*KeywordMap)["int2x3"] = EHTokInt2x3; - (*KeywordMap)["int2x4"] = EHTokInt2x4; - (*KeywordMap)["int3x1"] = EHTokInt3x1; - (*KeywordMap)["int3x2"] = EHTokInt3x2; - (*KeywordMap)["int3x3"] = EHTokInt3x3; - (*KeywordMap)["int3x4"] = EHTokInt3x4; - (*KeywordMap)["int4x1"] = EHTokInt4x1; - (*KeywordMap)["int4x2"] = EHTokInt4x2; - (*KeywordMap)["int4x3"] = EHTokInt4x3; - (*KeywordMap)["int4x4"] = EHTokInt4x4; - (*KeywordMap)["uint1x1"] = EHTokUint1x1; - (*KeywordMap)["uint1x2"] = EHTokUint1x2; - (*KeywordMap)["uint1x3"] = EHTokUint1x3; - (*KeywordMap)["uint1x4"] = EHTokUint1x4; - (*KeywordMap)["uint2x1"] = EHTokUint2x1; - (*KeywordMap)["uint2x2"] = EHTokUint2x2; - (*KeywordMap)["uint2x3"] = EHTokUint2x3; - (*KeywordMap)["uint2x4"] = EHTokUint2x4; - (*KeywordMap)["uint3x1"] = EHTokUint3x1; - (*KeywordMap)["uint3x2"] = EHTokUint3x2; - (*KeywordMap)["uint3x3"] = EHTokUint3x3; - (*KeywordMap)["uint3x4"] = EHTokUint3x4; - (*KeywordMap)["uint4x1"] = EHTokUint4x1; - (*KeywordMap)["uint4x2"] = EHTokUint4x2; - (*KeywordMap)["uint4x3"] = EHTokUint4x3; - (*KeywordMap)["uint4x4"] = EHTokUint4x4; - (*KeywordMap)["bool1x1"] = EHTokBool1x1; - (*KeywordMap)["bool1x2"] = EHTokBool1x2; - (*KeywordMap)["bool1x3"] = EHTokBool1x3; - (*KeywordMap)["bool1x4"] = EHTokBool1x4; - (*KeywordMap)["bool2x1"] = EHTokBool2x1; - (*KeywordMap)["bool2x2"] = EHTokBool2x2; - (*KeywordMap)["bool2x3"] = EHTokBool2x3; - (*KeywordMap)["bool2x4"] = EHTokBool2x4; - (*KeywordMap)["bool3x1"] = EHTokBool3x1; - (*KeywordMap)["bool3x2"] = EHTokBool3x2; - (*KeywordMap)["bool3x3"] = EHTokBool3x3; - (*KeywordMap)["bool3x4"] = EHTokBool3x4; - (*KeywordMap)["bool4x1"] = EHTokBool4x1; - (*KeywordMap)["bool4x2"] = EHTokBool4x2; - (*KeywordMap)["bool4x3"] = EHTokBool4x3; - (*KeywordMap)["bool4x4"] = EHTokBool4x4; - (*KeywordMap)["float1x1"] = EHTokFloat1x1; - (*KeywordMap)["float1x2"] = EHTokFloat1x2; - (*KeywordMap)["float1x3"] = EHTokFloat1x3; - (*KeywordMap)["float1x4"] = EHTokFloat1x4; - (*KeywordMap)["float2x1"] = EHTokFloat2x1; - (*KeywordMap)["float2x2"] = EHTokFloat2x2; - (*KeywordMap)["float2x3"] = EHTokFloat2x3; - (*KeywordMap)["float2x4"] = EHTokFloat2x4; - (*KeywordMap)["float3x1"] = EHTokFloat3x1; - (*KeywordMap)["float3x2"] = EHTokFloat3x2; - (*KeywordMap)["float3x3"] = EHTokFloat3x3; - (*KeywordMap)["float3x4"] = EHTokFloat3x4; - (*KeywordMap)["float4x1"] = EHTokFloat4x1; - (*KeywordMap)["float4x2"] = EHTokFloat4x2; - (*KeywordMap)["float4x3"] = EHTokFloat4x3; - (*KeywordMap)["float4x4"] = EHTokFloat4x4; - (*KeywordMap)["half1x1"] = EHTokHalf1x1; - (*KeywordMap)["half1x2"] = EHTokHalf1x2; - (*KeywordMap)["half1x3"] = EHTokHalf1x3; - (*KeywordMap)["half1x4"] = EHTokHalf1x4; - (*KeywordMap)["half2x1"] = EHTokHalf2x1; - (*KeywordMap)["half2x2"] = EHTokHalf2x2; - (*KeywordMap)["half2x3"] = EHTokHalf2x3; - (*KeywordMap)["half2x4"] = EHTokHalf2x4; - (*KeywordMap)["half3x1"] = EHTokHalf3x1; - (*KeywordMap)["half3x2"] = EHTokHalf3x2; - (*KeywordMap)["half3x3"] = EHTokHalf3x3; - (*KeywordMap)["half3x4"] = EHTokHalf3x4; - (*KeywordMap)["half4x1"] = EHTokHalf4x1; - (*KeywordMap)["half4x2"] = EHTokHalf4x2; - (*KeywordMap)["half4x3"] = EHTokHalf4x3; - (*KeywordMap)["half4x4"] = EHTokHalf4x4; - (*KeywordMap)["double1x1"] = EHTokDouble1x1; - (*KeywordMap)["double1x2"] = EHTokDouble1x2; - (*KeywordMap)["double1x3"] = EHTokDouble1x3; - (*KeywordMap)["double1x4"] = EHTokDouble1x4; - (*KeywordMap)["double2x1"] = EHTokDouble2x1; - (*KeywordMap)["double2x2"] = EHTokDouble2x2; - (*KeywordMap)["double2x3"] = EHTokDouble2x3; - (*KeywordMap)["double2x4"] = EHTokDouble2x4; - (*KeywordMap)["double3x1"] = EHTokDouble3x1; - (*KeywordMap)["double3x2"] = EHTokDouble3x2; - (*KeywordMap)["double3x3"] = EHTokDouble3x3; - (*KeywordMap)["double3x4"] = EHTokDouble3x4; - (*KeywordMap)["double4x1"] = EHTokDouble4x1; - (*KeywordMap)["double4x2"] = EHTokDouble4x2; - (*KeywordMap)["double4x3"] = EHTokDouble4x3; - (*KeywordMap)["double4x4"] = EHTokDouble4x4; - - (*KeywordMap)["sampler"] = EHTokSampler; - (*KeywordMap)["sampler1D"] = EHTokSampler1d; - (*KeywordMap)["sampler2D"] = EHTokSampler2d; - (*KeywordMap)["sampler3D"] = EHTokSampler3d; - (*KeywordMap)["samplerCube"] = EHTokSamplerCube; - (*KeywordMap)["sampler_state"] = EHTokSamplerState; - (*KeywordMap)["SamplerState"] = EHTokSamplerState; - (*KeywordMap)["SamplerComparisonState"] = EHTokSamplerComparisonState; - (*KeywordMap)["texture"] = EHTokTexture; - (*KeywordMap)["Texture1D"] = EHTokTexture1d; - (*KeywordMap)["Texture1DArray"] = EHTokTexture1darray; - (*KeywordMap)["Texture2D"] = EHTokTexture2d; - (*KeywordMap)["Texture2DArray"] = EHTokTexture2darray; - (*KeywordMap)["Texture3D"] = EHTokTexture3d; - (*KeywordMap)["TextureCube"] = EHTokTextureCube; - (*KeywordMap)["TextureCubeArray"] = EHTokTextureCubearray; - (*KeywordMap)["Texture2DMS"] = EHTokTexture2DMS; - (*KeywordMap)["Texture2DMSArray"] = EHTokTexture2DMSarray; - (*KeywordMap)["RWTexture1D"] = EHTokRWTexture1d; - (*KeywordMap)["RWTexture1DArray"] = EHTokRWTexture1darray; - (*KeywordMap)["RWTexture2D"] = EHTokRWTexture2d; - (*KeywordMap)["RWTexture2DArray"] = EHTokRWTexture2darray; - (*KeywordMap)["RWTexture3D"] = EHTokRWTexture3d; - (*KeywordMap)["RWBuffer"] = EHTokRWBuffer; - (*KeywordMap)["SubpassInput"] = EHTokSubpassInput; - (*KeywordMap)["SubpassInputMS"] = EHTokSubpassInputMS; - - (*KeywordMap)["AppendStructuredBuffer"] = EHTokAppendStructuredBuffer; - (*KeywordMap)["ByteAddressBuffer"] = EHTokByteAddressBuffer; - (*KeywordMap)["ConsumeStructuredBuffer"] = EHTokConsumeStructuredBuffer; - (*KeywordMap)["RWByteAddressBuffer"] = EHTokRWByteAddressBuffer; - (*KeywordMap)["RWStructuredBuffer"] = EHTokRWStructuredBuffer; - (*KeywordMap)["StructuredBuffer"] = EHTokStructuredBuffer; - (*KeywordMap)["TextureBuffer"] = EHTokTextureBuffer; - - (*KeywordMap)["class"] = EHTokClass; - (*KeywordMap)["struct"] = EHTokStruct; - (*KeywordMap)["cbuffer"] = EHTokCBuffer; - (*KeywordMap)["ConstantBuffer"] = EHTokConstantBuffer; - (*KeywordMap)["tbuffer"] = EHTokTBuffer; - (*KeywordMap)["typedef"] = EHTokTypedef; - (*KeywordMap)["this"] = EHTokThis; - (*KeywordMap)["namespace"] = EHTokNamespace; - - (*KeywordMap)["true"] = EHTokBoolConstant; - (*KeywordMap)["false"] = EHTokBoolConstant; - - (*KeywordMap)["for"] = EHTokFor; - (*KeywordMap)["do"] = EHTokDo; - (*KeywordMap)["while"] = EHTokWhile; - (*KeywordMap)["break"] = EHTokBreak; - (*KeywordMap)["continue"] = EHTokContinue; - (*KeywordMap)["if"] = EHTokIf; - (*KeywordMap)["else"] = EHTokElse; - (*KeywordMap)["discard"] = EHTokDiscard; - (*KeywordMap)["return"] = EHTokReturn; - (*KeywordMap)["switch"] = EHTokSwitch; - (*KeywordMap)["case"] = EHTokCase; - (*KeywordMap)["default"] = EHTokDefault; - - // TODO: get correct set here - ReservedSet = new std::unordered_set; - - ReservedSet->insert("auto"); - ReservedSet->insert("catch"); - ReservedSet->insert("char"); - ReservedSet->insert("const_cast"); - ReservedSet->insert("enum"); - ReservedSet->insert("explicit"); - ReservedSet->insert("friend"); - ReservedSet->insert("goto"); - ReservedSet->insert("long"); - ReservedSet->insert("mutable"); - ReservedSet->insert("new"); - ReservedSet->insert("operator"); - ReservedSet->insert("private"); - ReservedSet->insert("protected"); - ReservedSet->insert("public"); - ReservedSet->insert("reinterpret_cast"); - ReservedSet->insert("short"); - ReservedSet->insert("signed"); - ReservedSet->insert("sizeof"); - ReservedSet->insert("static_cast"); - ReservedSet->insert("template"); - ReservedSet->insert("throw"); - ReservedSet->insert("try"); - ReservedSet->insert("typename"); - ReservedSet->insert("union"); - ReservedSet->insert("unsigned"); - ReservedSet->insert("using"); - ReservedSet->insert("virtual"); - - SemanticMap = new std::unordered_map; - - // in DX9, all outputs had to have a semantic associated with them, that was either consumed - // by the system or was a specific register assignment - // in DX10+, only semantics with the SV_ prefix have any meaning beyond decoration - // Fxc will only accept DX9 style semantics in compat mode - // Also, in DX10 if a SV value is present as the input of a stage, but isn't appropriate for that - // stage, it would just be ignored as it is likely there as part of an output struct from one stage - // to the next - bool bParseDX9 = false; - if (bParseDX9) { - (*SemanticMap)["PSIZE"] = EbvPointSize; - (*SemanticMap)["FOG"] = EbvFogFragCoord; - (*SemanticMap)["DEPTH"] = EbvFragDepth; - (*SemanticMap)["VFACE"] = EbvFace; - (*SemanticMap)["VPOS"] = EbvFragCoord; - } - - (*SemanticMap)["SV_POSITION"] = EbvPosition; - (*SemanticMap)["SV_VERTEXID"] = EbvVertexIndex; - (*SemanticMap)["SV_VIEWPORTARRAYINDEX"] = EbvViewportIndex; - (*SemanticMap)["SV_TESSFACTOR"] = EbvTessLevelOuter; - (*SemanticMap)["SV_SAMPLEINDEX"] = EbvSampleId; - (*SemanticMap)["SV_RENDERTARGETARRAYINDEX"] = EbvLayer; - (*SemanticMap)["SV_PRIMITIVEID"] = EbvPrimitiveId; - (*SemanticMap)["SV_OUTPUTCONTROLPOINTID"] = EbvInvocationId; - (*SemanticMap)["SV_ISFRONTFACE"] = EbvFace; - (*SemanticMap)["SV_INSTANCEID"] = EbvInstanceIndex; - (*SemanticMap)["SV_INSIDETESSFACTOR"] = EbvTessLevelInner; - (*SemanticMap)["SV_GSINSTANCEID"] = EbvInvocationId; - (*SemanticMap)["SV_DISPATCHTHREADID"] = EbvGlobalInvocationId; - (*SemanticMap)["SV_GROUPTHREADID"] = EbvLocalInvocationId; - (*SemanticMap)["SV_GROUPINDEX"] = EbvLocalInvocationIndex; - (*SemanticMap)["SV_GROUPID"] = EbvWorkGroupId; - (*SemanticMap)["SV_DOMAINLOCATION"] = EbvTessCoord; - (*SemanticMap)["SV_DEPTH"] = EbvFragDepth; - (*SemanticMap)["SV_COVERAGE"] = EbvSampleMask; - (*SemanticMap)["SV_DEPTHGREATEREQUAL"] = EbvFragDepthGreater; - (*SemanticMap)["SV_DEPTHLESSEQUAL"] = EbvFragDepthLesser; - (*SemanticMap)["SV_STENCILREF"] = EbvFragStencilRef; -} - -void HlslScanContext::deleteKeywordMap() -{ - delete KeywordMap; - KeywordMap = nullptr; - delete ReservedSet; - ReservedSet = nullptr; - delete SemanticMap; - SemanticMap = nullptr; -} - -// Wrapper for tokenizeClass() to get everything inside the token. -void HlslScanContext::tokenize(HlslToken& token) -{ - EHlslTokenClass tokenClass = tokenizeClass(token); - token.tokenClass = tokenClass; -} - -glslang::TBuiltInVariable HlslScanContext::mapSemantic(const char* upperCase) -{ - auto it = SemanticMap->find(upperCase); - if (it != SemanticMap->end()) - return it->second; - else - return glslang::EbvNone; -} - -// -// Fill in token information for the next token, except for the token class. -// Returns the enum value of the token class of the next token found. -// Return 0 (EndOfTokens) on end of input. -// -EHlslTokenClass HlslScanContext::tokenizeClass(HlslToken& token) -{ - do { - parserToken = &token; - TPpToken ppToken; - int token = ppContext.tokenize(ppToken); - if (token == EndOfInput) - return EHTokNone; - - tokenText = ppToken.name; - loc = ppToken.loc; - parserToken->loc = loc; - switch (token) { - case ';': return EHTokSemicolon; - case ',': return EHTokComma; - case ':': return EHTokColon; - case '=': return EHTokAssign; - case '(': return EHTokLeftParen; - case ')': return EHTokRightParen; - case '.': return EHTokDot; - case '!': return EHTokBang; - case '-': return EHTokDash; - case '~': return EHTokTilde; - case '+': return EHTokPlus; - case '*': return EHTokStar; - case '/': return EHTokSlash; - case '%': return EHTokPercent; - case '<': return EHTokLeftAngle; - case '>': return EHTokRightAngle; - case '|': return EHTokVerticalBar; - case '^': return EHTokCaret; - case '&': return EHTokAmpersand; - case '?': return EHTokQuestion; - case '[': return EHTokLeftBracket; - case ']': return EHTokRightBracket; - case '{': return EHTokLeftBrace; - case '}': return EHTokRightBrace; - case '\\': - parseContext.error(loc, "illegal use of escape character", "\\", ""); - break; - - case PPAtomAddAssign: return EHTokAddAssign; - case PPAtomSubAssign: return EHTokSubAssign; - case PPAtomMulAssign: return EHTokMulAssign; - case PPAtomDivAssign: return EHTokDivAssign; - case PPAtomModAssign: return EHTokModAssign; - - case PpAtomRight: return EHTokRightOp; - case PpAtomLeft: return EHTokLeftOp; - - case PpAtomRightAssign: return EHTokRightAssign; - case PpAtomLeftAssign: return EHTokLeftAssign; - case PpAtomAndAssign: return EHTokAndAssign; - case PpAtomOrAssign: return EHTokOrAssign; - case PpAtomXorAssign: return EHTokXorAssign; - - case PpAtomAnd: return EHTokAndOp; - case PpAtomOr: return EHTokOrOp; - case PpAtomXor: return EHTokXorOp; - - case PpAtomEQ: return EHTokEqOp; - case PpAtomGE: return EHTokGeOp; - case PpAtomNE: return EHTokNeOp; - case PpAtomLE: return EHTokLeOp; - - case PpAtomDecrement: return EHTokDecOp; - case PpAtomIncrement: return EHTokIncOp; - - case PpAtomColonColon: return EHTokColonColon; - - case PpAtomConstInt: parserToken->i = ppToken.ival; return EHTokIntConstant; - case PpAtomConstUint: parserToken->i = ppToken.ival; return EHTokUintConstant; - case PpAtomConstFloat16: parserToken->d = ppToken.dval; return EHTokFloat16Constant; - case PpAtomConstFloat: parserToken->d = ppToken.dval; return EHTokFloatConstant; - case PpAtomConstDouble: parserToken->d = ppToken.dval; return EHTokDoubleConstant; - case PpAtomIdentifier: - { - EHlslTokenClass token = tokenizeIdentifier(); - return token; - } - - case PpAtomConstString: { - parserToken->string = NewPoolTString(tokenText); - return EHTokStringConstant; - } - - case EndOfInput: return EHTokNone; - - default: - if (token < PpAtomMaxSingle) { - char buf[2]; - buf[0] = (char)token; - buf[1] = 0; - parseContext.error(loc, "unexpected token", buf, ""); - } else if (tokenText[0] != 0) - parseContext.error(loc, "unexpected token", tokenText, ""); - else - parseContext.error(loc, "unexpected token", "", ""); - break; - } - } while (true); -} - -EHlslTokenClass HlslScanContext::tokenizeIdentifier() -{ - if (ReservedSet->find(tokenText) != ReservedSet->end()) - return reservedWord(); - - auto it = KeywordMap->find(tokenText); - if (it == KeywordMap->end()) { - // Should have an identifier of some sort - return identifierOrType(); - } - keyword = it->second; - - switch (keyword) { - - // qualifiers - case EHTokStatic: - case EHTokConst: - case EHTokSNorm: - case EHTokUnorm: - case EHTokExtern: - case EHTokUniform: - case EHTokVolatile: - case EHTokShared: - case EHTokGroupShared: - case EHTokLinear: - case EHTokCentroid: - case EHTokNointerpolation: - case EHTokNoperspective: - case EHTokSample: - case EHTokRowMajor: - case EHTokColumnMajor: - case EHTokPackOffset: - case EHTokIn: - case EHTokOut: - case EHTokInOut: - case EHTokPrecise: - case EHTokLayout: - case EHTokGloballyCoherent: - case EHTokInline: - return keyword; - - // primitive types - case EHTokPoint: - case EHTokLine: - case EHTokTriangle: - case EHTokLineAdj: - case EHTokTriangleAdj: - return keyword; - - // stream out types - case EHTokPointStream: - case EHTokLineStream: - case EHTokTriangleStream: - return keyword; - - // Tessellation patches - case EHTokInputPatch: - case EHTokOutputPatch: - return keyword; - - case EHTokBuffer: - case EHTokVector: - case EHTokMatrix: - return keyword; - - // scalar types - case EHTokVoid: - case EHTokString: - case EHTokBool: - case EHTokInt: - case EHTokUint: - case EHTokUint64: - case EHTokDword: - case EHTokHalf: - case EHTokFloat: - case EHTokDouble: - case EHTokMin16float: - case EHTokMin10float: - case EHTokMin16int: - case EHTokMin12int: - case EHTokMin16uint: - - // vector types - case EHTokBool1: - case EHTokBool2: - case EHTokBool3: - case EHTokBool4: - case EHTokFloat1: - case EHTokFloat2: - case EHTokFloat3: - case EHTokFloat4: - case EHTokInt1: - case EHTokInt2: - case EHTokInt3: - case EHTokInt4: - case EHTokDouble1: - case EHTokDouble2: - case EHTokDouble3: - case EHTokDouble4: - case EHTokUint1: - case EHTokUint2: - case EHTokUint3: - case EHTokUint4: - case EHTokHalf1: - case EHTokHalf2: - case EHTokHalf3: - case EHTokHalf4: - case EHTokMin16float1: - case EHTokMin16float2: - case EHTokMin16float3: - case EHTokMin16float4: - case EHTokMin10float1: - case EHTokMin10float2: - case EHTokMin10float3: - case EHTokMin10float4: - case EHTokMin16int1: - case EHTokMin16int2: - case EHTokMin16int3: - case EHTokMin16int4: - case EHTokMin12int1: - case EHTokMin12int2: - case EHTokMin12int3: - case EHTokMin12int4: - case EHTokMin16uint1: - case EHTokMin16uint2: - case EHTokMin16uint3: - case EHTokMin16uint4: - - // matrix types - case EHTokBool1x1: - case EHTokBool1x2: - case EHTokBool1x3: - case EHTokBool1x4: - case EHTokBool2x1: - case EHTokBool2x2: - case EHTokBool2x3: - case EHTokBool2x4: - case EHTokBool3x1: - case EHTokBool3x2: - case EHTokBool3x3: - case EHTokBool3x4: - case EHTokBool4x1: - case EHTokBool4x2: - case EHTokBool4x3: - case EHTokBool4x4: - case EHTokInt1x1: - case EHTokInt1x2: - case EHTokInt1x3: - case EHTokInt1x4: - case EHTokInt2x1: - case EHTokInt2x2: - case EHTokInt2x3: - case EHTokInt2x4: - case EHTokInt3x1: - case EHTokInt3x2: - case EHTokInt3x3: - case EHTokInt3x4: - case EHTokInt4x1: - case EHTokInt4x2: - case EHTokInt4x3: - case EHTokInt4x4: - case EHTokUint1x1: - case EHTokUint1x2: - case EHTokUint1x3: - case EHTokUint1x4: - case EHTokUint2x1: - case EHTokUint2x2: - case EHTokUint2x3: - case EHTokUint2x4: - case EHTokUint3x1: - case EHTokUint3x2: - case EHTokUint3x3: - case EHTokUint3x4: - case EHTokUint4x1: - case EHTokUint4x2: - case EHTokUint4x3: - case EHTokUint4x4: - case EHTokFloat1x1: - case EHTokFloat1x2: - case EHTokFloat1x3: - case EHTokFloat1x4: - case EHTokFloat2x1: - case EHTokFloat2x2: - case EHTokFloat2x3: - case EHTokFloat2x4: - case EHTokFloat3x1: - case EHTokFloat3x2: - case EHTokFloat3x3: - case EHTokFloat3x4: - case EHTokFloat4x1: - case EHTokFloat4x2: - case EHTokFloat4x3: - case EHTokFloat4x4: - case EHTokHalf1x1: - case EHTokHalf1x2: - case EHTokHalf1x3: - case EHTokHalf1x4: - case EHTokHalf2x1: - case EHTokHalf2x2: - case EHTokHalf2x3: - case EHTokHalf2x4: - case EHTokHalf3x1: - case EHTokHalf3x2: - case EHTokHalf3x3: - case EHTokHalf3x4: - case EHTokHalf4x1: - case EHTokHalf4x2: - case EHTokHalf4x3: - case EHTokHalf4x4: - case EHTokDouble1x1: - case EHTokDouble1x2: - case EHTokDouble1x3: - case EHTokDouble1x4: - case EHTokDouble2x1: - case EHTokDouble2x2: - case EHTokDouble2x3: - case EHTokDouble2x4: - case EHTokDouble3x1: - case EHTokDouble3x2: - case EHTokDouble3x3: - case EHTokDouble3x4: - case EHTokDouble4x1: - case EHTokDouble4x2: - case EHTokDouble4x3: - case EHTokDouble4x4: - return keyword; - - // texturing types - case EHTokSampler: - case EHTokSampler1d: - case EHTokSampler2d: - case EHTokSampler3d: - case EHTokSamplerCube: - case EHTokSamplerState: - case EHTokSamplerComparisonState: - case EHTokTexture: - case EHTokTexture1d: - case EHTokTexture1darray: - case EHTokTexture2d: - case EHTokTexture2darray: - case EHTokTexture3d: - case EHTokTextureCube: - case EHTokTextureCubearray: - case EHTokTexture2DMS: - case EHTokTexture2DMSarray: - case EHTokRWTexture1d: - case EHTokRWTexture1darray: - case EHTokRWTexture2d: - case EHTokRWTexture2darray: - case EHTokRWTexture3d: - case EHTokRWBuffer: - case EHTokAppendStructuredBuffer: - case EHTokByteAddressBuffer: - case EHTokConsumeStructuredBuffer: - case EHTokRWByteAddressBuffer: - case EHTokRWStructuredBuffer: - case EHTokStructuredBuffer: - case EHTokTextureBuffer: - case EHTokSubpassInput: - case EHTokSubpassInputMS: - return keyword; - - // variable, user type, ... - case EHTokClass: - case EHTokStruct: - case EHTokTypedef: - case EHTokCBuffer: - case EHTokConstantBuffer: - case EHTokTBuffer: - case EHTokThis: - case EHTokNamespace: - return keyword; - - case EHTokBoolConstant: - if (strcmp("true", tokenText) == 0) - parserToken->b = true; - else - parserToken->b = false; - return keyword; - - // control flow - case EHTokFor: - case EHTokDo: - case EHTokWhile: - case EHTokBreak: - case EHTokContinue: - case EHTokIf: - case EHTokElse: - case EHTokDiscard: - case EHTokReturn: - case EHTokCase: - case EHTokSwitch: - case EHTokDefault: - return keyword; - - default: - parseContext.infoSink.info.message(EPrefixInternalError, "Unknown glslang keyword", loc); - return EHTokNone; - } -} - -EHlslTokenClass HlslScanContext::identifierOrType() -{ - parserToken->string = NewPoolTString(tokenText); - - return EHTokIdentifier; -} - -// Give an error for use of a reserved symbol. -// However, allow built-in declarations to use reserved words, to allow -// extension support before the extension is enabled. -EHlslTokenClass HlslScanContext::reservedWord() -{ - if (! parseContext.symbolTable.atBuiltInLevel()) - parseContext.error(loc, "Reserved word.", tokenText, "", ""); - - return EHTokNone; -} - -} // end namespace glslang diff --git a/External/glslang/hlsl/hlslScanContext.h b/External/glslang/hlsl/hlslScanContext.h deleted file mode 100644 index 9d30a12e..00000000 --- a/External/glslang/hlsl/hlslScanContext.h +++ /dev/null @@ -1,109 +0,0 @@ -// -// Copyright (C) 2016 Google, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of Google, Inc., nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -// -// This holds context specific to the HLSL scanner, which -// sits between the preprocessor scanner and HLSL parser. -// - -#ifndef HLSLSCANCONTEXT_H_ -#define HLSLSCANCONTEXT_H_ - -#include "../glslang/MachineIndependent/ParseHelper.h" -#include "hlslTokens.h" - -namespace glslang { - -class TPpContext; -class TPpToken; - - -// -// Everything needed to fully describe a token. -// -struct HlslToken { - HlslToken() : string(nullptr) { loc.init(); } - TSourceLoc loc; // location of token in the source - EHlslTokenClass tokenClass; // what kind of token it is - union { // what data the token holds - glslang::TString *string; // for identifiers - int i; // for literals - unsigned int u; - bool b; - double d; - }; -}; - -// -// The state of scanning and translating raw tokens to slightly richer -// semantics, like knowing if an identifier is an existing symbol, or -// user-defined type. -// -class HlslScanContext { -public: - HlslScanContext(TParseContextBase& parseContext, TPpContext& ppContext) - : parseContext(parseContext), ppContext(ppContext) { } - virtual ~HlslScanContext() { } - - static void fillInKeywordMap(); - static void deleteKeywordMap(); - - void tokenize(HlslToken&); - glslang::TBuiltInVariable mapSemantic(const char*); - -protected: - HlslScanContext(HlslScanContext&); - HlslScanContext& operator=(HlslScanContext&); - - EHlslTokenClass tokenizeClass(HlslToken&); - EHlslTokenClass tokenizeIdentifier(); - EHlslTokenClass identifierOrType(); - EHlslTokenClass reservedWord(); - EHlslTokenClass identifierOrReserved(bool reserved); - EHlslTokenClass nonreservedKeyword(int version); - - TParseContextBase& parseContext; - TPpContext& ppContext; - TSourceLoc loc; - TPpToken* ppToken; - HlslToken* parserToken; - - const char* tokenText; - EHlslTokenClass keyword; -}; - -} // end namespace glslang - -#endif // HLSLSCANCONTEXT_H_ diff --git a/External/glslang/hlsl/hlslTokenStream.cpp b/External/glslang/hlsl/hlslTokenStream.cpp deleted file mode 100644 index 5d9311cf..00000000 --- a/External/glslang/hlsl/hlslTokenStream.cpp +++ /dev/null @@ -1,150 +0,0 @@ -// -// Copyright (C) 2016 Google, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of Google, Inc., nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -#include "hlslTokenStream.h" - -namespace glslang { - -void HlslTokenStream::pushPreToken(const HlslToken& tok) -{ - assert(preTokenStackSize < tokenBufferSize); - preTokenStack[preTokenStackSize++] = tok; -} - -HlslToken HlslTokenStream::popPreToken() -{ - assert(preTokenStackSize > 0); - - return preTokenStack[--preTokenStackSize]; -} - -void HlslTokenStream::pushTokenBuffer(const HlslToken& tok) -{ - tokenBuffer[tokenBufferPos] = tok; - tokenBufferPos = (tokenBufferPos+1) % tokenBufferSize; -} - -HlslToken HlslTokenStream::popTokenBuffer() -{ - // Back up - tokenBufferPos = (tokenBufferPos+tokenBufferSize-1) % tokenBufferSize; - - return tokenBuffer[tokenBufferPos]; -} - -// -// Make a new source of tokens, not from the source, but from an -// already pre-processed token stream. -// -// This interrupts current token processing which must be restored -// later. Some simplifying assumptions are made (and asserted). -// -void HlslTokenStream::pushTokenStream(const TVector* tokens) -{ - // not yet setup to interrupt a stream that has been receded - // and not yet reconsumed - assert(preTokenStackSize == 0); - - // save current state - currentTokenStack.push_back(token); - - // set up new token stream - tokenStreamStack.push_back(tokens); - - // start position at first token: - token = (*tokens)[0]; - tokenPosition.push_back(0); -} - -// Undo pushTokenStream(), see above -void HlslTokenStream::popTokenStream() -{ - tokenStreamStack.pop_back(); - tokenPosition.pop_back(); - token = currentTokenStack.back(); - currentTokenStack.pop_back(); -} - -// Load 'token' with the next token in the stream of tokens. -void HlslTokenStream::advanceToken() -{ - pushTokenBuffer(token); - if (preTokenStackSize > 0) - token = popPreToken(); - else { - if (tokenStreamStack.size() == 0) - scanner.tokenize(token); - else { - ++tokenPosition.back(); - if (tokenPosition.back() >= (int)tokenStreamStack.back()->size()) - token.tokenClass = EHTokNone; - else - token = (*tokenStreamStack.back())[tokenPosition.back()]; - } - } -} - -void HlslTokenStream::recedeToken() -{ - pushPreToken(token); - token = popTokenBuffer(); -} - -// Return the current token class. -EHlslTokenClass HlslTokenStream::peek() const -{ - return token.tokenClass; -} - -// Return true, without advancing to the next token, if the current token is -// the expected (passed in) token class. -bool HlslTokenStream::peekTokenClass(EHlslTokenClass tokenClass) const -{ - return peek() == tokenClass; -} - -// Return true and advance to the next token if the current token is the -// expected (passed in) token class. -bool HlslTokenStream::acceptTokenClass(EHlslTokenClass tokenClass) -{ - if (peekTokenClass(tokenClass)) { - advanceToken(); - return true; - } - - return false; -} - -} // end namespace glslang diff --git a/External/glslang/hlsl/hlslTokenStream.h b/External/glslang/hlsl/hlslTokenStream.h deleted file mode 100644 index cb6c9e72..00000000 --- a/External/glslang/hlsl/hlslTokenStream.h +++ /dev/null @@ -1,96 +0,0 @@ -// -// Copyright (C) 2016 Google, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of Google, Inc., nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -#ifndef HLSLTOKENSTREAM_H_ -#define HLSLTOKENSTREAM_H_ - -#include "hlslScanContext.h" - -namespace glslang { - - class HlslTokenStream { - public: - explicit HlslTokenStream(HlslScanContext& scanner) - : scanner(scanner), preTokenStackSize(0), tokenBufferPos(0) { } - virtual ~HlslTokenStream() { } - - public: - void advanceToken(); - void recedeToken(); - bool acceptTokenClass(EHlslTokenClass); - EHlslTokenClass peek() const; - bool peekTokenClass(EHlslTokenClass) const; - glslang::TBuiltInVariable mapSemantic(const char* upperCase) { return scanner.mapSemantic(upperCase); } - - void pushTokenStream(const TVector* tokens); - void popTokenStream(); - - protected: - HlslToken token; // the token we are currently looking at, but have not yet accepted - - private: - HlslTokenStream(); - HlslTokenStream& operator=(const HlslTokenStream&); - - HlslScanContext& scanner; // lexical scanner, to get next token from source file - TVector*> tokenStreamStack; // for getting the next token from an existing vector of tokens - TVector tokenPosition; - TVector currentTokenStack; - - // This is the number of tokens we can recedeToken() over. - static const int tokenBufferSize = 2; - - // Previously scanned tokens, returned for future advances, - // so logically in front of the token stream. - // Is logically a stack; needs last in last out semantics. - // Currently implemented as a stack of size 2. - HlslToken preTokenStack[tokenBufferSize]; - int preTokenStackSize; - void pushPreToken(const HlslToken&); - HlslToken popPreToken(); - - // Previously scanned tokens, not yet returned for future advances, - // but available for that. - // Is logically a fifo for normal advances, and a stack for recession. - // Currently implemented with an intrinsic size of 2. - HlslToken tokenBuffer[tokenBufferSize]; - int tokenBufferPos; - void pushTokenBuffer(const HlslToken&); - HlslToken popTokenBuffer(); - }; - -} // end namespace glslang - -#endif // HLSLTOKENSTREAM_H_ diff --git a/External/glslang/hlsl/hlslTokens.h b/External/glslang/hlsl/hlslTokens.h deleted file mode 100644 index 4426bcce..00000000 --- a/External/glslang/hlsl/hlslTokens.h +++ /dev/null @@ -1,374 +0,0 @@ -// -// Copyright (C) 2016 Google, Inc. -// 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 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 EHLSLTOKENS_H_ -#define EHLSLTOKENS_H_ - -namespace glslang { - -enum EHlslTokenClass { - EHTokNone = 0, - - // qualifiers - EHTokStatic, - EHTokConst, - EHTokSNorm, - EHTokUnorm, - EHTokExtern, - EHTokUniform, - EHTokVolatile, - EHTokPrecise, - EHTokShared, - EHTokGroupShared, - EHTokLinear, - EHTokCentroid, - EHTokNointerpolation, - EHTokNoperspective, - EHTokSample, - EHTokRowMajor, - EHTokColumnMajor, - EHTokPackOffset, - EHTokIn, - EHTokOut, - EHTokInOut, - EHTokLayout, - EHTokGloballyCoherent, - EHTokInline, - - // primitive types - EHTokPoint, - EHTokLine, - EHTokTriangle, - EHTokLineAdj, - EHTokTriangleAdj, - - // stream out types - EHTokPointStream, - EHTokLineStream, - EHTokTriangleStream, - - // Tessellation patches - EHTokInputPatch, - EHTokOutputPatch, - - // template types - EHTokBuffer, - EHTokVector, - EHTokMatrix, - - // scalar types - EHTokVoid, - EHTokString, - EHTokBool, - EHTokInt, - EHTokUint, - EHTokUint64, - EHTokDword, - EHTokHalf, - EHTokFloat, - EHTokDouble, - EHTokMin16float, - EHTokMin10float, - EHTokMin16int, - EHTokMin12int, - EHTokMin16uint, - - // vector types - EHTokBool1, - EHTokBool2, - EHTokBool3, - EHTokBool4, - EHTokFloat1, - EHTokFloat2, - EHTokFloat3, - EHTokFloat4, - EHTokInt1, - EHTokInt2, - EHTokInt3, - EHTokInt4, - EHTokDouble1, - EHTokDouble2, - EHTokDouble3, - EHTokDouble4, - EHTokUint1, - EHTokUint2, - EHTokUint3, - EHTokUint4, - EHTokHalf1, - EHTokHalf2, - EHTokHalf3, - EHTokHalf4, - EHTokMin16float1, - EHTokMin16float2, - EHTokMin16float3, - EHTokMin16float4, - EHTokMin10float1, - EHTokMin10float2, - EHTokMin10float3, - EHTokMin10float4, - EHTokMin16int1, - EHTokMin16int2, - EHTokMin16int3, - EHTokMin16int4, - EHTokMin12int1, - EHTokMin12int2, - EHTokMin12int3, - EHTokMin12int4, - EHTokMin16uint1, - EHTokMin16uint2, - EHTokMin16uint3, - EHTokMin16uint4, - - // matrix types - EHTokInt1x1, - EHTokInt1x2, - EHTokInt1x3, - EHTokInt1x4, - EHTokInt2x1, - EHTokInt2x2, - EHTokInt2x3, - EHTokInt2x4, - EHTokInt3x1, - EHTokInt3x2, - EHTokInt3x3, - EHTokInt3x4, - EHTokInt4x1, - EHTokInt4x2, - EHTokInt4x3, - EHTokInt4x4, - EHTokUint1x1, - EHTokUint1x2, - EHTokUint1x3, - EHTokUint1x4, - EHTokUint2x1, - EHTokUint2x2, - EHTokUint2x3, - EHTokUint2x4, - EHTokUint3x1, - EHTokUint3x2, - EHTokUint3x3, - EHTokUint3x4, - EHTokUint4x1, - EHTokUint4x2, - EHTokUint4x3, - EHTokUint4x4, - EHTokBool1x1, - EHTokBool1x2, - EHTokBool1x3, - EHTokBool1x4, - EHTokBool2x1, - EHTokBool2x2, - EHTokBool2x3, - EHTokBool2x4, - EHTokBool3x1, - EHTokBool3x2, - EHTokBool3x3, - EHTokBool3x4, - EHTokBool4x1, - EHTokBool4x2, - EHTokBool4x3, - EHTokBool4x4, - EHTokFloat1x1, - EHTokFloat1x2, - EHTokFloat1x3, - EHTokFloat1x4, - EHTokFloat2x1, - EHTokFloat2x2, - EHTokFloat2x3, - EHTokFloat2x4, - EHTokFloat3x1, - EHTokFloat3x2, - EHTokFloat3x3, - EHTokFloat3x4, - EHTokFloat4x1, - EHTokFloat4x2, - EHTokFloat4x3, - EHTokFloat4x4, - EHTokHalf1x1, - EHTokHalf1x2, - EHTokHalf1x3, - EHTokHalf1x4, - EHTokHalf2x1, - EHTokHalf2x2, - EHTokHalf2x3, - EHTokHalf2x4, - EHTokHalf3x1, - EHTokHalf3x2, - EHTokHalf3x3, - EHTokHalf3x4, - EHTokHalf4x1, - EHTokHalf4x2, - EHTokHalf4x3, - EHTokHalf4x4, - EHTokDouble1x1, - EHTokDouble1x2, - EHTokDouble1x3, - EHTokDouble1x4, - EHTokDouble2x1, - EHTokDouble2x2, - EHTokDouble2x3, - EHTokDouble2x4, - EHTokDouble3x1, - EHTokDouble3x2, - EHTokDouble3x3, - EHTokDouble3x4, - EHTokDouble4x1, - EHTokDouble4x2, - EHTokDouble4x3, - EHTokDouble4x4, - - // texturing types - EHTokSampler, - EHTokSampler1d, - EHTokSampler2d, - EHTokSampler3d, - EHTokSamplerCube, - EHTokSamplerState, - EHTokSamplerComparisonState, - EHTokTexture, - EHTokTexture1d, - EHTokTexture1darray, - EHTokTexture2d, - EHTokTexture2darray, - EHTokTexture3d, - EHTokTextureCube, - EHTokTextureCubearray, - EHTokTexture2DMS, - EHTokTexture2DMSarray, - EHTokRWTexture1d, - EHTokRWTexture1darray, - EHTokRWTexture2d, - EHTokRWTexture2darray, - EHTokRWTexture3d, - EHTokRWBuffer, - EHTokSubpassInput, - EHTokSubpassInputMS, - - // Structure buffer variants - EHTokAppendStructuredBuffer, - EHTokByteAddressBuffer, - EHTokConsumeStructuredBuffer, - EHTokRWByteAddressBuffer, - EHTokRWStructuredBuffer, - EHTokStructuredBuffer, - EHTokTextureBuffer, - - // variable, user type, ... - EHTokIdentifier, - EHTokClass, - EHTokStruct, - EHTokCBuffer, - EHTokTBuffer, - EHTokTypedef, - EHTokThis, - EHTokNamespace, - EHTokConstantBuffer, - - // constant - EHTokFloat16Constant, - EHTokFloatConstant, - EHTokDoubleConstant, - EHTokIntConstant, - EHTokUintConstant, - EHTokBoolConstant, - EHTokStringConstant, - - // control flow - EHTokFor, - EHTokDo, - EHTokWhile, - EHTokBreak, - EHTokContinue, - EHTokIf, - EHTokElse, - EHTokDiscard, - EHTokReturn, - EHTokSwitch, - EHTokCase, - EHTokDefault, - - // expressions - EHTokLeftOp, - EHTokRightOp, - EHTokIncOp, - EHTokDecOp, - EHTokLeOp, - EHTokGeOp, - EHTokEqOp, - EHTokNeOp, - EHTokAndOp, - EHTokOrOp, - EHTokXorOp, - EHTokAssign, - EHTokMulAssign, - EHTokDivAssign, - EHTokAddAssign, - EHTokModAssign, - EHTokLeftAssign, - EHTokRightAssign, - EHTokAndAssign, - EHTokXorAssign, - EHTokOrAssign, - EHTokSubAssign, - EHTokLeftParen, - EHTokRightParen, - EHTokLeftBracket, - EHTokRightBracket, - EHTokLeftBrace, - EHTokRightBrace, - EHTokDot, - EHTokComma, - EHTokColon, - EHTokColonColon, - EHTokSemicolon, - EHTokBang, - EHTokDash, - EHTokTilde, - EHTokPlus, - EHTokStar, - EHTokSlash, - EHTokPercent, - EHTokLeftAngle, - EHTokRightAngle, - EHTokVerticalBar, - EHTokCaret, - EHTokAmpersand, - EHTokQuestion, -}; - -} // end namespace glslang - -#endif // EHLSLTOKENS_H_ diff --git a/External/glslang/make-revision b/External/glslang/make-revision deleted file mode 100644 index a89ff087..00000000 --- a/External/glslang/make-revision +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/sh -( -echo "// This header is generated by the make-revision script." -echo -echo \#define GLSLANG_PATCH_LEVEL `git log --oneline | wc -l` -) > glslang/Include/revision.h diff --git a/External/glslang/update_glslang_sources.py b/External/glslang/update_glslang_sources.py deleted file mode 100644 index 550bc2b1..00000000 --- a/External/glslang/update_glslang_sources.py +++ /dev/null @@ -1,155 +0,0 @@ -#!/usr/bin/env python - -# Copyright 2017 The Glslang Authors. All rights reserved. -# -# 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. - -"""Get source files for Glslang and its dependencies from public repositories. -""" - -from __future__ import print_function - -import argparse -import json -import distutils.dir_util -import os.path -import subprocess -import sys - -KNOWN_GOOD_FILE = 'known_good.json' - -SITE_TO_KNOWN_GOOD_FILE = { 'github' : 'known_good.json', - 'gitlab' : 'known_good_khr.json' } - -# Maps a site name to its hostname. -SITE_TO_HOST = { 'github' : 'https://github.com/', - 'gitlab' : 'git@gitlab.khronos.org:' } - -VERBOSE = True - - -def command_output(cmd, directory, fail_ok=False): - """Runs a command in a directory and returns its standard output stream. - - Captures the standard error stream. - - Raises a RuntimeError if the command fails to launch or otherwise fails. - """ - if VERBOSE: - print('In {d}: {cmd}'.format(d=directory, cmd=cmd)) - p = subprocess.Popen(cmd, - cwd=directory, - stdout=subprocess.PIPE) - (stdout, _) = p.communicate() - if p.returncode != 0 and not fail_ok: - raise RuntimeError('Failed to run {} in {}'.format(cmd, directory)) - if VERBOSE: - print(stdout) - return stdout - - -def command_retval(cmd, directory): - """Runs a command in a directory and returns its return value. - - Captures the standard error stream. - """ - p = subprocess.Popen(cmd, - cwd=directory, - stdout=subprocess.PIPE) - (stdout, _) = p.communicate() - return p.returncode - - -class GoodCommit(object): - """Represents a good commit for a repository.""" - - def __init__(self, json): - """Initializes this good commit object. - - Args: - 'json': A fully populated JSON object describing the commit. - """ - self._json = json - self.name = json['name'] - self.site = json['site'] - self.subrepo = json['subrepo'] - self.subdir = json['subdir'] if ('subdir' in json) else '.' - self.commit = json['commit'] - - def GetUrl(self): - """Returns the URL for the repository.""" - host = SITE_TO_HOST[self.site] - return '{host}{subrepo}'.format( - host=host, - subrepo=self.subrepo) - - def AddRemote(self): - """Add the remote 'known-good' if it does not exist.""" - print('Ignore "fatal" errors for missing known-good remote:') - if command_retval(['git', 'remote', 'show', 'known-good'], self.subdir) != 0: - command_output(['git', 'remote', 'add', 'known-good', self.GetUrl()], self.subdir) - - def HasCommit(self): - """Check if the repository contains the known-good commit.""" - return 0 == subprocess.call(['git', 'rev-parse', '--verify', '--quiet', - self.commit + "^{commit}"], - cwd=self.subdir) - - def Clone(self): - distutils.dir_util.mkpath(self.subdir) - command_output(['git', 'clone', self.GetUrl(), '.'], self.subdir) - - def Fetch(self): - command_output(['git', 'fetch', 'known-good'], self.subdir) - - def Checkout(self): - if not os.path.exists(os.path.join(self.subdir,'.git')): - self.Clone() - self.AddRemote() - if not self.HasCommit(): - self.Fetch() - command_output(['git', 'checkout', self.commit], self.subdir) - - -def GetGoodCommits(site): - """Returns the latest list of GoodCommit objects.""" - known_good_file = SITE_TO_KNOWN_GOOD_FILE[site] - with open(known_good_file) as known_good: - return [GoodCommit(c) for c in json.loads(known_good.read())['commits']] - - -def main(): - parser = argparse.ArgumentParser(description='Get Glslang source dependencies at a known-good commit') - parser.add_argument('--dir', dest='dir', default='.', - help="Set target directory for Glslang source root. Default is \'.\'.") - parser.add_argument('--site', dest='site', default='github', - help="Set git server site. Default is github.") - - args = parser.parse_args() - - commits = GetGoodCommits(args.site) - - distutils.dir_util.mkpath(args.dir) - print('Change directory to {d}'.format(d=args.dir)) - os.chdir(args.dir) - - # Create the subdirectories in sorted order so that parent git repositories - # are created first. - for c in sorted(commits, key=lambda x: x.subdir): - print('Get {n}\n'.format(n=c.name)) - c.Checkout() - sys.exit(0) - - -if __name__ == '__main__': - main() -- cgit v1.2.3