From 752497910b67b2a1a80560840ca44548d8893434 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Mon, 18 May 2020 15:16:30 +0200 Subject: Remove ANGLE This marks the end of EGL and OpenGL ES support on Windows. The concepts of -opengl dynamic, -opengl desktop, QT_OPENGL=software, etc. remain unchanged, with the exception of the disapperance of everything ANGLE related. CMake builds now work identically to qmake on Windows: they default to 'dynamic' OpenGL on Windows, unless -DINPUT_opengl=desktop is specified. On Windows, Qt 6 is expected to default to the "dynamic" OpenGL model by default, just like Qt 5.15. This can be changed by switching to "desktop" OpenGL, which will link to opengl32 (publicly, so other libs and applications will do so as well) and disallows using another OpenGL DLL. The "dynamic" mode is essential still because the fallback to a software rasterizer, such as the opengl32sw.dll we ship with the Qt packages, has to to work exactly like in Qt 5, the removal of ANGLE does not change this concept in any way (except of course that the middle option of using ANGLE is now gone) When it comes to the windows plugin's OpenGL blacklist feature, it works like before and accepts the ANGLE/D3D related keywords. They will then be ignored. Similarly, requesting QT_OPENGL=angle is ignored (but will show a warning). The D3D11 and DXGI configure time tests are removed: Qt 5.14 already depends on D3D 11.1 and DXGI 1.3 headers being available unconditionally on Win32 (in QRhi's D3D11 backend). No need to test for these. [ChangeLog][Windows] ANGLE is no longer included with Qt. Dynamic OpenGL builds work like before but ANGLE is no longer an option. OpenGL proper or an alternative opengl32 implementation are the two remaining options now. Attempting to set QT_OPENGL=angle or Qt::AA_UseOpenGLES will have no effect on Windows. Fixes: QTBUG-79103 Change-Id: Ia404e0d07f3fe191b27434d863c81180112ecb3b Reviewed-by: Oliver Wolff --- .../src/compiler/translator/ASTMetadataHLSL.cpp | 462 -- .../src/compiler/translator/ASTMetadataHLSL.h | 63 - .../translator/AddAndTrueToLoopCondition.cpp | 59 - .../translator/AddAndTrueToLoopCondition.h | 20 - .../translator/AddDefaultReturnStatements.cpp | 58 - .../translator/AddDefaultReturnStatements.h | 22 - .../translator/ArrayReturnValueToOutParameter.cpp | 213 - .../translator/ArrayReturnValueToOutParameter.h | 22 - .../angle/src/compiler/translator/BaseTypes.h | 1073 ---- .../BreakVariableAliasingInInnerLoops.cpp | 107 - .../translator/BreakVariableAliasingInInnerLoops.h | 23 - .../translator/BuiltInFunctionEmulator.cpp | 355 -- .../compiler/translator/BuiltInFunctionEmulator.h | 183 - .../translator/BuiltInFunctionEmulatorGLSL.cpp | 293 - .../translator/BuiltInFunctionEmulatorGLSL.h | 40 - .../translator/BuiltInFunctionEmulatorHLSL.cpp | 184 - .../translator/BuiltInFunctionEmulatorHLSL.h | 27 - .../angle/src/compiler/translator/Cache.cpp | 99 - src/3rdparty/angle/src/compiler/translator/Cache.h | 84 - .../angle/src/compiler/translator/CallDAG.cpp | 346 -- .../angle/src/compiler/translator/CallDAG.h | 79 - .../src/compiler/translator/ClampPointSize.cpp | 47 - .../angle/src/compiler/translator/ClampPointSize.h | 22 - .../angle/src/compiler/translator/CodeGen.cpp | 75 - .../src/compiler/translator/CollectVariables.cpp | 869 --- .../src/compiler/translator/CollectVariables.h | 37 - .../angle/src/compiler/translator/Common.h | 138 - .../angle/src/compiler/translator/Compiler.cpp | 1169 ---- .../angle/src/compiler/translator/Compiler.h | 308 - .../src/compiler/translator/ConstantUnion.cpp | 681 --- .../angle/src/compiler/translator/ConstantUnion.h | 117 - ...DeclareAndInitBuiltinsForInstancedMultiview.cpp | 221 - .../DeclareAndInitBuiltinsForInstancedMultiview.h | 48 - .../translator/DeferGlobalInitializers.cpp | 147 - .../compiler/translator/DeferGlobalInitializers.h | 32 - .../angle/src/compiler/translator/Diagnostics.cpp | 105 - .../angle/src/compiler/translator/Diagnostics.h | 67 - .../src/compiler/translator/DirectiveHandler.cpp | 203 - .../src/compiler/translator/DirectiveHandler.h | 57 - .../translator/EmulateGLFragColorBroadcast.cpp | 129 - .../translator/EmulateGLFragColorBroadcast.h | 31 - .../src/compiler/translator/EmulatePrecision.cpp | 751 --- .../src/compiler/translator/EmulatePrecision.h | 73 - .../translator/ExpandIntegerPowExpressions.cpp | 153 - .../translator/ExpandIntegerPowExpressions.h | 29 - .../src/compiler/translator/ExtensionBehavior.cpp | 96 - .../src/compiler/translator/ExtensionBehavior.h | 60 - .../src/compiler/translator/ExtensionGLSL.cpp | 105 - .../angle/src/compiler/translator/ExtensionGLSL.h | 44 - .../angle/src/compiler/translator/FindMain.cpp | 38 - .../angle/src/compiler/translator/FindMain.h | 23 - .../src/compiler/translator/FindSymbolNode.cpp | 58 - .../angle/src/compiler/translator/FindSymbolNode.h | 27 - .../src/compiler/translator/FlagStd140Structs.cpp | 75 - .../src/compiler/translator/FlagStd140Structs.h | 30 - .../angle/src/compiler/translator/HashNames.cpp | 72 - .../angle/src/compiler/translator/HashNames.h | 28 - .../src/compiler/translator/ImageFunctionHLSL.cpp | 304 - .../src/compiler/translator/ImageFunctionHLSL.h | 76 - .../angle/src/compiler/translator/InfoSink.cpp | 40 - .../angle/src/compiler/translator/InfoSink.h | 120 - .../angle/src/compiler/translator/Initialize.cpp | 1135 ---- .../angle/src/compiler/translator/Initialize.h | 38 - .../src/compiler/translator/InitializeDll.cpp | 37 - .../angle/src/compiler/translator/InitializeDll.h | 15 - .../src/compiler/translator/InitializeGlobals.h | 13 - .../compiler/translator/InitializeVariables.cpp | 290 - .../src/compiler/translator/InitializeVariables.h | 53 - .../angle/src/compiler/translator/IntermNode.cpp | 3330 ----------- .../angle/src/compiler/translator/IntermNode.h | 917 --- .../translator/IntermNodePatternMatcher.cpp | 157 - .../compiler/translator/IntermNodePatternMatcher.h | 75 - .../src/compiler/translator/IntermNode_util.cpp | 254 - .../src/compiler/translator/IntermNode_util.h | 60 - .../src/compiler/translator/IntermTraverse.cpp | 983 ---- .../angle/src/compiler/translator/IntermTraverse.h | 355 -- .../compiler/translator/IsASTDepthBelowLimit.cpp | 51 - .../src/compiler/translator/IsASTDepthBelowLimit.h | 20 - .../angle/src/compiler/translator/NodeSearch.h | 56 - .../angle/src/compiler/translator/Operator.cpp | 385 -- .../angle/src/compiler/translator/Operator.h | 255 - .../angle/src/compiler/translator/OutputESSL.cpp | 47 - .../angle/src/compiler/translator/OutputESSL.h | 37 - .../angle/src/compiler/translator/OutputGLSL.cpp | 110 - .../angle/src/compiler/translator/OutputGLSL.h | 36 - .../src/compiler/translator/OutputGLSLBase.cpp | 1357 ----- .../angle/src/compiler/translator/OutputGLSLBase.h | 122 - .../angle/src/compiler/translator/OutputHLSL.cpp | 3084 ---------- .../angle/src/compiler/translator/OutputHLSL.h | 248 - .../angle/src/compiler/translator/OutputTree.cpp | 682 --- .../angle/src/compiler/translator/OutputTree.h | 22 - .../src/compiler/translator/OutputVulkanGLSL.cpp | 80 - .../src/compiler/translator/OutputVulkanGLSL.h | 34 - .../angle/src/compiler/translator/ParamType.h | 102 - .../angle/src/compiler/translator/ParseContext.cpp | 6022 -------------------- .../angle/src/compiler/translator/ParseContext.h | 657 --- .../angle/src/compiler/translator/PoolAlloc.cpp | 360 -- .../angle/src/compiler/translator/PoolAlloc.h | 319 -- .../angle/src/compiler/translator/Pragma.h | 31 - .../angle/src/compiler/translator/PruneNoOps.cpp | 156 - .../angle/src/compiler/translator/PruneNoOps.h | 24 - .../src/compiler/translator/QualifierTypes.cpp | 784 --- .../angle/src/compiler/translator/QualifierTypes.h | 191 - .../translator/RecordConstantPrecision.cpp | 167 - .../compiler/translator/RecordConstantPrecision.h | 28 - .../compiler/translator/RegenerateStructNames.cpp | 76 - .../compiler/translator/RegenerateStructNames.h | 45 - .../translator/RemoveArrayLengthMethod.cpp | 83 - .../compiler/translator/RemoveArrayLengthMethod.h | 29 - .../compiler/translator/RemoveDynamicIndexing.cpp | 550 -- .../compiler/translator/RemoveDynamicIndexing.h | 27 - .../translator/RemoveEmptySwitchStatements.cpp | 56 - .../translator/RemoveEmptySwitchStatements.h | 18 - .../translator/RemoveInvariantDeclaration.cpp | 43 - .../translator/RemoveInvariantDeclaration.h | 18 - .../RemoveNoOpCasesFromEndOfSwitchStatements.cpp | 116 - .../RemoveNoOpCasesFromEndOfSwitchStatements.h | 21 - .../angle/src/compiler/translator/RemovePow.cpp | 97 - .../angle/src/compiler/translator/RemovePow.h | 21 - .../translator/RemoveSwitchFallThrough.cpp | 270 - .../compiler/translator/RemoveSwitchFallThrough.h | 27 - .../translator/RemoveUnreferencedVariables.cpp | 358 -- .../translator/RemoveUnreferencedVariables.h | 24 - .../src/compiler/translator/RewriteDoWhile.cpp | 159 - .../angle/src/compiler/translator/RewriteDoWhile.h | 23 - .../src/compiler/translator/RewriteElseBlocks.cpp | 120 - .../src/compiler/translator/RewriteElseBlocks.h | 22 - .../translator/RewriteTexelFetchOffset.cpp | 154 - .../compiler/translator/RewriteTexelFetchOffset.h | 28 - .../translator/RewriteUnaryMinusOperatorFloat.cpp | 94 - .../translator/RewriteUnaryMinusOperatorFloat.h | 19 - .../translator/RewriteUnaryMinusOperatorInt.cpp | 112 - .../translator/RewriteUnaryMinusOperatorInt.h | 20 - .../compiler/translator/RunAtTheEndOfShader.cpp | 112 - .../src/compiler/translator/RunAtTheEndOfShader.h | 23 - .../ScalarizeVecAndMatConstructorArgs.cpp | 238 - .../translator/ScalarizeVecAndMatConstructorArgs.h | 27 - .../angle/src/compiler/translator/SearchSymbol.cpp | 38 - .../angle/src/compiler/translator/SearchSymbol.h | 33 - .../translator/SeparateArrayInitialization.cpp | 92 - .../translator/SeparateArrayInitialization.h | 29 - .../compiler/translator/SeparateDeclarations.cpp | 79 - .../src/compiler/translator/SeparateDeclarations.h | 26 - .../SeparateExpressionsReturningArrays.cpp | 126 - .../SeparateExpressionsReturningArrays.h | 23 - .../angle/src/compiler/translator/Severity.h | 22 - .../angle/src/compiler/translator/ShaderLang.cpp | 578 -- .../angle/src/compiler/translator/ShaderVars.cpp | 586 -- .../compiler/translator/SimplifyLoopConditions.cpp | 300 - .../compiler/translator/SimplifyLoopConditions.h | 25 - .../compiler/translator/SplitSequenceOperator.cpp | 171 - .../compiler/translator/SplitSequenceOperator.h | 28 - .../src/compiler/translator/StructureHLSL.cpp | 594 -- .../angle/src/compiler/translator/StructureHLSL.h | 98 - .../angle/src/compiler/translator/SymbolTable.cpp | 622 -- .../angle/src/compiler/translator/SymbolTable.h | 545 -- .../src/compiler/translator/SymbolUniqueId.cpp | 28 - .../angle/src/compiler/translator/SymbolUniqueId.h | 36 - .../compiler/translator/TextureFunctionHLSL.cpp | 1322 ----- .../src/compiler/translator/TextureFunctionHLSL.h | 76 - .../src/compiler/translator/TranslatorESSL.cpp | 184 - .../angle/src/compiler/translator/TranslatorESSL.h | 35 - .../src/compiler/translator/TranslatorGLSL.cpp | 339 -- .../angle/src/compiler/translator/TranslatorGLSL.h | 38 - .../src/compiler/translator/TranslatorHLSL.cpp | 161 - .../angle/src/compiler/translator/TranslatorHLSL.h | 41 - .../src/compiler/translator/TranslatorVulkan.cpp | 173 - .../src/compiler/translator/TranslatorVulkan.h | 34 - .../angle/src/compiler/translator/Types.cpp | 1072 ---- src/3rdparty/angle/src/compiler/translator/Types.h | 509 -- .../compiler/translator/UnfoldShortCircuitAST.cpp | 59 - .../compiler/translator/UnfoldShortCircuitAST.h | 33 - .../compiler/translator/UnfoldShortCircuitToIf.cpp | 186 - .../compiler/translator/UnfoldShortCircuitToIf.h | 25 - .../angle/src/compiler/translator/UniformHLSL.cpp | 600 -- .../angle/src/compiler/translator/UniformHLSL.h | 110 - .../translator/UseInterfaceBlockFields.cpp | 105 - .../compiler/translator/UseInterfaceBlockFields.h | 30 - .../angle/src/compiler/translator/UtilsHLSL.cpp | 970 ---- .../angle/src/compiler/translator/UtilsHLSL.h | 129 - .../translator/ValidateGlobalInitializer.cpp | 120 - .../translator/ValidateGlobalInitializer.h | 23 - .../compiler/translator/ValidateLimitations.cpp | 444 -- .../src/compiler/translator/ValidateLimitations.h | 27 - .../compiler/translator/ValidateMaxParameters.cpp | 29 - .../compiler/translator/ValidateMaxParameters.h | 21 - .../src/compiler/translator/ValidateOutputs.cpp | 174 - .../src/compiler/translator/ValidateOutputs.h | 30 - .../src/compiler/translator/ValidateSwitch.cpp | 319 -- .../angle/src/compiler/translator/ValidateSwitch.h | 28 - .../translator/ValidateVaryingLocations.cpp | 174 - .../compiler/translator/ValidateVaryingLocations.h | 25 - .../src/compiler/translator/VariablePacker.cpp | 413 -- .../angle/src/compiler/translator/VariablePacker.h | 32 - .../translator/VectorizeVectorScalarArithmetic.cpp | 284 - .../translator/VectorizeVectorScalarArithmetic.h | 25 - .../angle/src/compiler/translator/VersionGLSL.cpp | 143 - .../angle/src/compiler/translator/VersionGLSL.h | 76 - .../translator/WrapSwitchStatementsInBlocks.cpp | 132 - .../translator/WrapSwitchStatementsInBlocks.h | 22 - .../angle/src/compiler/translator/blocklayout.cpp | 281 - .../angle/src/compiler/translator/blocklayout.h | 144 - .../src/compiler/translator/blocklayoutHLSL.cpp | 166 - .../src/compiler/translator/blocklayoutHLSL.h | 68 - .../emulated_builtin_function_data_hlsl.json | 1382 ----- .../emulated_builtin_functions_hlsl_autogen.cpp | 859 --- .../angle/src/compiler/translator/glslang.h | 24 - .../angle/src/compiler/translator/glslang.l | 697 --- .../angle/src/compiler/translator/glslang.y | 1468 ----- .../angle/src/compiler/translator/length_limits.h | 26 - .../angle/src/compiler/translator/util.cpp | 714 --- src/3rdparty/angle/src/compiler/translator/util.h | 63 - 212 files changed, 55469 deletions(-) delete mode 100644 src/3rdparty/angle/src/compiler/translator/ASTMetadataHLSL.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/ASTMetadataHLSL.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/AddAndTrueToLoopCondition.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/AddAndTrueToLoopCondition.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/AddDefaultReturnStatements.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/AddDefaultReturnStatements.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/ArrayReturnValueToOutParameter.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/ArrayReturnValueToOutParameter.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/BaseTypes.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/BreakVariableAliasingInInnerLoops.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/BreakVariableAliasingInInnerLoops.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorGLSL.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorGLSL.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorHLSL.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorHLSL.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/Cache.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/Cache.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/CallDAG.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/CallDAG.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/ClampPointSize.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/ClampPointSize.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/CodeGen.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/CollectVariables.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/CollectVariables.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/Common.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/Compiler.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/Compiler.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/ConstantUnion.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/ConstantUnion.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/DeclareAndInitBuiltinsForInstancedMultiview.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/DeclareAndInitBuiltinsForInstancedMultiview.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/DeferGlobalInitializers.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/DeferGlobalInitializers.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/Diagnostics.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/Diagnostics.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/DirectiveHandler.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/DirectiveHandler.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/EmulateGLFragColorBroadcast.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/EmulateGLFragColorBroadcast.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/EmulatePrecision.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/EmulatePrecision.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/ExpandIntegerPowExpressions.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/ExpandIntegerPowExpressions.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/ExtensionBehavior.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/ExtensionBehavior.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/ExtensionGLSL.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/ExtensionGLSL.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/FindMain.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/FindMain.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/FindSymbolNode.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/FindSymbolNode.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/FlagStd140Structs.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/FlagStd140Structs.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/HashNames.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/HashNames.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/ImageFunctionHLSL.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/ImageFunctionHLSL.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/InfoSink.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/InfoSink.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/Initialize.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/Initialize.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/InitializeDll.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/InitializeDll.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/InitializeGlobals.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/InitializeVariables.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/InitializeVariables.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/IntermNode.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/IntermNode.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/IntermNodePatternMatcher.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/IntermNodePatternMatcher.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/IntermNode_util.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/IntermNode_util.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/IntermTraverse.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/IntermTraverse.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/IsASTDepthBelowLimit.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/IsASTDepthBelowLimit.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/NodeSearch.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/Operator.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/Operator.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/OutputESSL.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/OutputESSL.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/OutputGLSL.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/OutputGLSL.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/OutputHLSL.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/OutputHLSL.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/OutputTree.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/OutputTree.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/OutputVulkanGLSL.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/OutputVulkanGLSL.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/ParamType.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/ParseContext.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/ParseContext.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/PoolAlloc.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/PoolAlloc.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/Pragma.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/PruneNoOps.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/PruneNoOps.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/QualifierTypes.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/QualifierTypes.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/RecordConstantPrecision.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/RecordConstantPrecision.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/RegenerateStructNames.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/RegenerateStructNames.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/RemoveArrayLengthMethod.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/RemoveArrayLengthMethod.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/RemoveDynamicIndexing.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/RemoveDynamicIndexing.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/RemoveEmptySwitchStatements.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/RemoveEmptySwitchStatements.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/RemoveInvariantDeclaration.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/RemoveInvariantDeclaration.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/RemoveNoOpCasesFromEndOfSwitchStatements.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/RemoveNoOpCasesFromEndOfSwitchStatements.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/RemovePow.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/RemovePow.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/RemoveSwitchFallThrough.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/RemoveSwitchFallThrough.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/RemoveUnreferencedVariables.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/RemoveUnreferencedVariables.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/RewriteDoWhile.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/RewriteDoWhile.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/RewriteElseBlocks.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/RewriteElseBlocks.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/RewriteTexelFetchOffset.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/RewriteTexelFetchOffset.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/RewriteUnaryMinusOperatorFloat.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/RewriteUnaryMinusOperatorFloat.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/RewriteUnaryMinusOperatorInt.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/RewriteUnaryMinusOperatorInt.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/RunAtTheEndOfShader.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/RunAtTheEndOfShader.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/SearchSymbol.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/SearchSymbol.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/SeparateArrayInitialization.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/SeparateArrayInitialization.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/SeparateDeclarations.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/SeparateDeclarations.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/SeparateExpressionsReturningArrays.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/SeparateExpressionsReturningArrays.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/Severity.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/ShaderLang.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/ShaderVars.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/SimplifyLoopConditions.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/SimplifyLoopConditions.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/SplitSequenceOperator.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/SplitSequenceOperator.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/StructureHLSL.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/StructureHLSL.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/SymbolTable.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/SymbolTable.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/SymbolUniqueId.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/SymbolUniqueId.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/TextureFunctionHLSL.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/TextureFunctionHLSL.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/TranslatorESSL.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/TranslatorESSL.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/TranslatorVulkan.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/TranslatorVulkan.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/Types.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/Types.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitAST.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitAST.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitToIf.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitToIf.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/UniformHLSL.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/UniformHLSL.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/UseInterfaceBlockFields.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/UseInterfaceBlockFields.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/UtilsHLSL.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/UtilsHLSL.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/ValidateGlobalInitializer.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/ValidateGlobalInitializer.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/ValidateLimitations.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/ValidateLimitations.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/ValidateMaxParameters.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/ValidateMaxParameters.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/ValidateOutputs.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/ValidateOutputs.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/ValidateSwitch.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/ValidateSwitch.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/ValidateVaryingLocations.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/ValidateVaryingLocations.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/VariablePacker.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/VariablePacker.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/VectorizeVectorScalarArithmetic.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/VectorizeVectorScalarArithmetic.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/VersionGLSL.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/VersionGLSL.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/WrapSwitchStatementsInBlocks.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/WrapSwitchStatementsInBlocks.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/blocklayout.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/blocklayout.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/blocklayoutHLSL.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/blocklayoutHLSL.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/emulated_builtin_function_data_hlsl.json delete mode 100644 src/3rdparty/angle/src/compiler/translator/emulated_builtin_functions_hlsl_autogen.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/glslang.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/glslang.l delete mode 100644 src/3rdparty/angle/src/compiler/translator/glslang.y delete mode 100644 src/3rdparty/angle/src/compiler/translator/length_limits.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/util.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/util.h (limited to 'src/3rdparty/angle/src/compiler/translator') diff --git a/src/3rdparty/angle/src/compiler/translator/ASTMetadataHLSL.cpp b/src/3rdparty/angle/src/compiler/translator/ASTMetadataHLSL.cpp deleted file mode 100644 index b04fc28259..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/ASTMetadataHLSL.cpp +++ /dev/null @@ -1,462 +0,0 @@ -// -// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Analysis of the AST needed for HLSL generation - -#include "compiler/translator/ASTMetadataHLSL.h" - -#include "compiler/translator/CallDAG.h" -#include "compiler/translator/IntermTraverse.h" -#include "compiler/translator/SymbolTable.h" - -namespace sh -{ - -namespace -{ - -// Class used to traverse the AST of a function definition, checking if the -// function uses a gradient, and writing the set of control flow using gradients. -// It assumes that the analysis has already been made for the function's -// callees. -class PullGradient : public TIntermTraverser -{ - public: - PullGradient(MetadataList *metadataList, size_t index, const CallDAG &dag) - : TIntermTraverser(true, false, true), - mMetadataList(metadataList), - mMetadata(&(*metadataList)[index]), - mIndex(index), - mDag(dag) - { - ASSERT(index < metadataList->size()); - - // ESSL 100 builtin gradient functions - mGradientBuiltinFunctions.insert("texture2D"); - mGradientBuiltinFunctions.insert("texture2DProj"); - mGradientBuiltinFunctions.insert("textureCube"); - - // ESSL 300 builtin gradient functions - mGradientBuiltinFunctions.insert("texture"); - mGradientBuiltinFunctions.insert("textureProj"); - mGradientBuiltinFunctions.insert("textureOffset"); - mGradientBuiltinFunctions.insert("textureProjOffset"); - - // ESSL 310 doesn't add builtin gradient functions - } - - void traverse(TIntermFunctionDefinition *node) - { - node->traverse(this); - ASSERT(mParents.empty()); - } - - // Called when a gradient operation or a call to a function using a gradient is found. - void onGradient() - { - mMetadata->mUsesGradient = true; - // Mark the latest control flow as using a gradient. - if (!mParents.empty()) - { - mMetadata->mControlFlowsContainingGradient.insert(mParents.back()); - } - } - - void visitControlFlow(Visit visit, TIntermNode *node) - { - if (visit == PreVisit) - { - mParents.push_back(node); - } - else if (visit == PostVisit) - { - ASSERT(mParents.back() == node); - mParents.pop_back(); - // A control flow's using a gradient means its parents are too. - if (mMetadata->mControlFlowsContainingGradient.count(node) > 0 && !mParents.empty()) - { - mMetadata->mControlFlowsContainingGradient.insert(mParents.back()); - } - } - } - - bool visitLoop(Visit visit, TIntermLoop *loop) override - { - visitControlFlow(visit, loop); - return true; - } - - bool visitIfElse(Visit visit, TIntermIfElse *ifElse) override - { - visitControlFlow(visit, ifElse); - return true; - } - - bool visitUnary(Visit visit, TIntermUnary *node) override - { - if (visit == PreVisit) - { - switch (node->getOp()) - { - case EOpDFdx: - case EOpDFdy: - case EOpFwidth: - onGradient(); - default: - break; - } - } - - return true; - } - - bool visitAggregate(Visit visit, TIntermAggregate *node) override - { - if (visit == PreVisit) - { - if (node->getOp() == EOpCallFunctionInAST) - { - size_t calleeIndex = mDag.findIndex(node->getFunctionSymbolInfo()); - ASSERT(calleeIndex != CallDAG::InvalidIndex && calleeIndex < mIndex); - - if ((*mMetadataList)[calleeIndex].mUsesGradient) - { - onGradient(); - } - } - else if (node->getOp() == EOpCallBuiltInFunction) - { - if (mGradientBuiltinFunctions.find(node->getFunctionSymbolInfo()->getName()) != - mGradientBuiltinFunctions.end()) - { - onGradient(); - } - } - } - - return true; - } - - private: - MetadataList *mMetadataList; - ASTMetadataHLSL *mMetadata; - size_t mIndex; - const CallDAG &mDag; - - // Contains a stack of the control flow nodes that are parents of the node being - // currently visited. It is used to mark control flows using a gradient. - std::vector mParents; - - // A list of builtin functions that use gradients - std::set mGradientBuiltinFunctions; -}; - -// Traverses the AST of a function definition to compute the the discontinuous loops -// and the if statements containing gradient loops. It assumes that the gradient loops -// (loops that contain a gradient) have already been computed and that it has already -// traversed the current function's callees. -class PullComputeDiscontinuousAndGradientLoops : public TIntermTraverser -{ - public: - PullComputeDiscontinuousAndGradientLoops(MetadataList *metadataList, - size_t index, - const CallDAG &dag) - : TIntermTraverser(true, false, true), - mMetadataList(metadataList), - mMetadata(&(*metadataList)[index]), - mIndex(index), - mDag(dag) - { - } - - void traverse(TIntermFunctionDefinition *node) - { - node->traverse(this); - ASSERT(mLoopsAndSwitches.empty()); - ASSERT(mIfs.empty()); - } - - // Called when traversing a gradient loop or a call to a function with a - // gradient loop in its call graph. - void onGradientLoop() - { - mMetadata->mHasGradientLoopInCallGraph = true; - // Mark the latest if as using a discontinuous loop. - if (!mIfs.empty()) - { - mMetadata->mIfsContainingGradientLoop.insert(mIfs.back()); - } - } - - bool visitLoop(Visit visit, TIntermLoop *loop) override - { - if (visit == PreVisit) - { - mLoopsAndSwitches.push_back(loop); - - if (mMetadata->hasGradientInCallGraph(loop)) - { - onGradientLoop(); - } - } - else if (visit == PostVisit) - { - ASSERT(mLoopsAndSwitches.back() == loop); - mLoopsAndSwitches.pop_back(); - } - - return true; - } - - bool visitIfElse(Visit visit, TIntermIfElse *node) override - { - if (visit == PreVisit) - { - mIfs.push_back(node); - } - else if (visit == PostVisit) - { - ASSERT(mIfs.back() == node); - mIfs.pop_back(); - // An if using a discontinuous loop means its parents ifs are also discontinuous. - if (mMetadata->mIfsContainingGradientLoop.count(node) > 0 && !mIfs.empty()) - { - mMetadata->mIfsContainingGradientLoop.insert(mIfs.back()); - } - } - - return true; - } - - bool visitBranch(Visit visit, TIntermBranch *node) override - { - if (visit == PreVisit) - { - switch (node->getFlowOp()) - { - case EOpBreak: - { - ASSERT(!mLoopsAndSwitches.empty()); - TIntermLoop *loop = mLoopsAndSwitches.back()->getAsLoopNode(); - if (loop != nullptr) - { - mMetadata->mDiscontinuousLoops.insert(loop); - } - } - break; - case EOpContinue: - { - ASSERT(!mLoopsAndSwitches.empty()); - TIntermLoop *loop = nullptr; - size_t i = mLoopsAndSwitches.size(); - while (loop == nullptr && i > 0) - { - --i; - loop = mLoopsAndSwitches.at(i)->getAsLoopNode(); - } - ASSERT(loop != nullptr); - mMetadata->mDiscontinuousLoops.insert(loop); - } - break; - case EOpKill: - case EOpReturn: - // A return or discard jumps out of all the enclosing loops - if (!mLoopsAndSwitches.empty()) - { - for (TIntermNode *intermNode : mLoopsAndSwitches) - { - TIntermLoop *loop = intermNode->getAsLoopNode(); - if (loop) - { - mMetadata->mDiscontinuousLoops.insert(loop); - } - } - } - break; - default: - UNREACHABLE(); - } - } - - return true; - } - - bool visitAggregate(Visit visit, TIntermAggregate *node) override - { - if (visit == PreVisit && node->getOp() == EOpCallFunctionInAST) - { - size_t calleeIndex = mDag.findIndex(node->getFunctionSymbolInfo()); - ASSERT(calleeIndex != CallDAG::InvalidIndex && calleeIndex < mIndex); - - if ((*mMetadataList)[calleeIndex].mHasGradientLoopInCallGraph) - { - onGradientLoop(); - } - } - - return true; - } - - bool visitSwitch(Visit visit, TIntermSwitch *node) override - { - if (visit == PreVisit) - { - mLoopsAndSwitches.push_back(node); - } - else if (visit == PostVisit) - { - ASSERT(mLoopsAndSwitches.back() == node); - mLoopsAndSwitches.pop_back(); - } - return true; - } - - private: - MetadataList *mMetadataList; - ASTMetadataHLSL *mMetadata; - size_t mIndex; - const CallDAG &mDag; - - std::vector mLoopsAndSwitches; - std::vector mIfs; -}; - -// Tags all the functions called in a discontinuous loop -class PushDiscontinuousLoops : public TIntermTraverser -{ - public: - PushDiscontinuousLoops(MetadataList *metadataList, size_t index, const CallDAG &dag) - : TIntermTraverser(true, true, true), - mMetadataList(metadataList), - mMetadata(&(*metadataList)[index]), - mIndex(index), - mDag(dag), - mNestedDiscont(mMetadata->mCalledInDiscontinuousLoop ? 1 : 0) - { - } - - void traverse(TIntermFunctionDefinition *node) - { - node->traverse(this); - ASSERT(mNestedDiscont == (mMetadata->mCalledInDiscontinuousLoop ? 1 : 0)); - } - - bool visitLoop(Visit visit, TIntermLoop *loop) override - { - bool isDiscontinuous = mMetadata->mDiscontinuousLoops.count(loop) > 0; - - if (visit == PreVisit && isDiscontinuous) - { - mNestedDiscont++; - } - else if (visit == PostVisit && isDiscontinuous) - { - mNestedDiscont--; - } - - return true; - } - - bool visitAggregate(Visit visit, TIntermAggregate *node) override - { - switch (node->getOp()) - { - case EOpCallFunctionInAST: - if (visit == PreVisit && mNestedDiscont > 0) - { - size_t calleeIndex = mDag.findIndex(node->getFunctionSymbolInfo()); - ASSERT(calleeIndex != CallDAG::InvalidIndex && calleeIndex < mIndex); - - (*mMetadataList)[calleeIndex].mCalledInDiscontinuousLoop = true; - } - break; - default: - break; - } - return true; - } - - private: - MetadataList *mMetadataList; - ASTMetadataHLSL *mMetadata; - size_t mIndex; - const CallDAG &mDag; - - int mNestedDiscont; -}; -} - -bool ASTMetadataHLSL::hasGradientInCallGraph(TIntermLoop *node) -{ - return mControlFlowsContainingGradient.count(node) > 0; -} - -bool ASTMetadataHLSL::hasGradientLoop(TIntermIfElse *node) -{ - return mIfsContainingGradientLoop.count(node) > 0; -} - -MetadataList CreateASTMetadataHLSL(TIntermNode *root, const CallDAG &callDag) -{ - MetadataList metadataList(callDag.size()); - - // Compute all the information related to when gradient operations are used. - // We want to know for each function and control flow operation if they have - // a gradient operation in their call graph (shortened to "using a gradient" - // in the rest of the file). - // - // This computation is logically split in three steps: - // 1 - For each function compute if it uses a gradient in its body, ignoring - // calls to other user-defined functions. - // 2 - For each function determine if it uses a gradient in its call graph, - // using the result of step 1 and the CallDAG to know its callees. - // 3 - For each control flow statement of each function, check if it uses a - // gradient in the function's body, or if it calls a user-defined function that - // uses a gradient. - // - // We take advantage of the call graph being a DAG and instead compute 1, 2 and 3 - // for leaves first, then going down the tree. This is correct because 1 doesn't - // depend on other functions, and 2 and 3 depend only on callees. - for (size_t i = 0; i < callDag.size(); i++) - { - PullGradient pull(&metadataList, i, callDag); - pull.traverse(callDag.getRecordFromIndex(i).node); - } - - // Compute which loops are discontinuous and which function are called in - // these loops. The same way computing gradient usage is a "pull" process, - // computing "bing used in a discont. loop" is a push process. However we also - // need to know what ifs have a discontinuous loop inside so we do the same type - // of callgraph analysis as for the gradient. - - // First compute which loops are discontinuous (no specific order) and pull - // the ifs and functions using a gradient loop. - for (size_t i = 0; i < callDag.size(); i++) - { - PullComputeDiscontinuousAndGradientLoops pull(&metadataList, i, callDag); - pull.traverse(callDag.getRecordFromIndex(i).node); - } - - // Then push the information to callees, either from the a local discontinuous - // loop or from the caller being called in a discontinuous loop already - for (size_t i = callDag.size(); i-- > 0;) - { - PushDiscontinuousLoops push(&metadataList, i, callDag); - push.traverse(callDag.getRecordFromIndex(i).node); - } - - // We create "Lod0" version of functions with the gradient operations replaced - // by non-gradient operations so that the D3D compiler is happier with discont - // loops. - for (auto &metadata : metadataList) - { - metadata.mNeedsLod0 = metadata.mCalledInDiscontinuousLoop && metadata.mUsesGradient; - } - - return metadataList; -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/ASTMetadataHLSL.h b/src/3rdparty/angle/src/compiler/translator/ASTMetadataHLSL.h deleted file mode 100644 index 550a522b86..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/ASTMetadataHLSL.h +++ /dev/null @@ -1,63 +0,0 @@ -// -// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Defines analyses of the AST needed for HLSL generation - -#ifndef COMPILER_TRANSLATOR_ASTMETADATAHLSL_H_ -#define COMPILER_TRANSLATOR_ASTMETADATAHLSL_H_ - -#include -#include - -namespace sh -{ - -class CallDAG; -class TIntermNode; -class TIntermIfElse; -class TIntermLoop; - -struct ASTMetadataHLSL -{ - ASTMetadataHLSL() - : mUsesGradient(false), - mCalledInDiscontinuousLoop(false), - mHasGradientLoopInCallGraph(false), - mNeedsLod0(false) - { - } - - // Here "something uses a gradient" means here that it either contains a - // gradient operation, or a call to a function that uses a gradient. - bool hasGradientInCallGraph(TIntermLoop *node); - bool hasGradientLoop(TIntermIfElse *node); - - // Does the function use a gradient. - bool mUsesGradient; - - // Even if usesGradient is true, some control flow might not use a gradient - // so we store the set of all gradient-using control flows. - std::set mControlFlowsContainingGradient; - - // Remember information about the discontinuous loops and which functions - // are called in such loops. - bool mCalledInDiscontinuousLoop; - bool mHasGradientLoopInCallGraph; - std::set mDiscontinuousLoops; - std::set mIfsContainingGradientLoop; - - // Will we need to generate a Lod0 version of the function. - bool mNeedsLod0; -}; - -typedef std::vector MetadataList; - -// Return the AST analysis result, in the order defined by the call DAG -MetadataList CreateASTMetadataHLSL(TIntermNode *root, const CallDAG &callDag); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_ASTMETADATAHLSL_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/AddAndTrueToLoopCondition.cpp b/src/3rdparty/angle/src/compiler/translator/AddAndTrueToLoopCondition.cpp deleted file mode 100644 index 6a05104233..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/AddAndTrueToLoopCondition.cpp +++ /dev/null @@ -1,59 +0,0 @@ -// -// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/translator/AddAndTrueToLoopCondition.h" - -#include "compiler/translator/IntermTraverse.h" - -namespace sh -{ - -namespace -{ - -// An AST traverser that rewrites for and while loops by replacing "condition" with -// "condition && true" to work around condition bug on Intel Mac. -class AddAndTrueToLoopConditionTraverser : public TIntermTraverser -{ - public: - AddAndTrueToLoopConditionTraverser() : TIntermTraverser(true, false, false) {} - - bool visitLoop(Visit, TIntermLoop *loop) override - { - // do-while loop doesn't have this bug. - if (loop->getType() != ELoopFor && loop->getType() != ELoopWhile) - { - return true; - } - - // For loop may not have a condition. - if (loop->getCondition() == nullptr) - { - return true; - } - - // Constant true. - TConstantUnion *trueConstant = new TConstantUnion(); - trueConstant->setBConst(true); - TIntermTyped *trueValue = new TIntermConstantUnion(trueConstant, TType(EbtBool)); - - // CONDITION && true. - TIntermBinary *andOp = new TIntermBinary(EOpLogicalAnd, loop->getCondition(), trueValue); - loop->setCondition(andOp); - - return true; - } -}; - -} // anonymous namespace - -void AddAndTrueToLoopCondition(TIntermNode *root) -{ - AddAndTrueToLoopConditionTraverser traverser; - root->traverse(&traverser); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/AddAndTrueToLoopCondition.h b/src/3rdparty/angle/src/compiler/translator/AddAndTrueToLoopCondition.h deleted file mode 100644 index 34debe0ed9..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/AddAndTrueToLoopCondition.h +++ /dev/null @@ -1,20 +0,0 @@ -// -// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Rewrite condition in for and while loops to work around driver bug on Intel Mac. - -#ifndef COMPILER_TRANSLATOR_ADDANDTRUETOLOOPCONDITION_H_ -#define COMPILER_TRANSLATOR_ADDANDTRUETOLOOPCONDITION_H_ - -class TIntermNode; -namespace sh -{ - -void AddAndTrueToLoopCondition(TIntermNode *root); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_ADDANDTRUETOLOOPCONDITION_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/AddDefaultReturnStatements.cpp b/src/3rdparty/angle/src/compiler/translator/AddDefaultReturnStatements.cpp deleted file mode 100644 index 4dfe60c0bc..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/AddDefaultReturnStatements.cpp +++ /dev/null @@ -1,58 +0,0 @@ -// -// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// AddDefaultReturnStatements.cpp: Add default return statements to functions that do not end in a -// return. -// - -#include "compiler/translator/AddDefaultReturnStatements.h" - -#include "compiler/translator/IntermNode.h" -#include "compiler/translator/IntermNode_util.h" -#include "compiler/translator/util.h" - -namespace sh -{ - -namespace -{ - -bool NeedsReturnStatement(TIntermFunctionDefinition *node, TType *returnType) -{ - *returnType = node->getFunctionPrototype()->getType(); - if (returnType->getBasicType() == EbtVoid) - { - return false; - } - - TIntermBlock *bodyNode = node->getBody(); - TIntermBranch *returnNode = bodyNode->getSequence()->back()->getAsBranchNode(); - if (returnNode != nullptr && returnNode->getFlowOp() == EOpReturn) - { - return false; - } - - return true; -} - -} // anonymous namespace - -void AddDefaultReturnStatements(TIntermBlock *root) -{ - TType returnType; - for (TIntermNode *node : *root->getSequence()) - { - TIntermFunctionDefinition *definition = node->getAsFunctionDefinition(); - if (definition != nullptr && NeedsReturnStatement(definition, &returnType)) - { - TIntermBranch *branch = new TIntermBranch(EOpReturn, CreateZeroNode(returnType)); - - TIntermBlock *bodyNode = definition->getBody(); - bodyNode->getSequence()->push_back(branch); - } - } -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/AddDefaultReturnStatements.h b/src/3rdparty/angle/src/compiler/translator/AddDefaultReturnStatements.h deleted file mode 100644 index 40a70ad8c2..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/AddDefaultReturnStatements.h +++ /dev/null @@ -1,22 +0,0 @@ -// -// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// AddDefaultReturnStatements.h: Add default return statements to functions that do not end in a -// return. -// - -#ifndef COMPILER_TRANSLATOR_ADDDEFAULTRETURNSTATEMENTS_H_ -#define COMPILER_TRANSLATOR_ADDDEFAULTRETURNSTATEMENTS_H_ - -class TIntermBlock; - -namespace sh -{ - -void AddDefaultReturnStatements(TIntermBlock *root); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_ADDDEFAULTRETURNSTATEMENTS_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/ArrayReturnValueToOutParameter.cpp b/src/3rdparty/angle/src/compiler/translator/ArrayReturnValueToOutParameter.cpp deleted file mode 100644 index 17721fb0dc..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/ArrayReturnValueToOutParameter.cpp +++ /dev/null @@ -1,213 +0,0 @@ -// -// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// The ArrayReturnValueToOutParameter function changes return values of an array type to out -// parameters in function definitions, prototypes, and call sites. - -#include "compiler/translator/ArrayReturnValueToOutParameter.h" - -#include - -#include "compiler/translator/IntermTraverse.h" -#include "compiler/translator/SymbolTable.h" - -namespace sh -{ - -namespace -{ - -void CopyAggregateChildren(TIntermAggregateBase *from, TIntermAggregateBase *to) -{ - const TIntermSequence *fromSequence = from->getSequence(); - for (size_t ii = 0; ii < fromSequence->size(); ++ii) - { - to->getSequence()->push_back(fromSequence->at(ii)); - } -} - -TIntermSymbol *CreateReturnValueSymbol(const TSymbolUniqueId &id, const TType &type) -{ - TIntermSymbol *node = new TIntermSymbol(id, "angle_return", type); - node->setInternal(true); - node->getTypePointer()->setQualifier(EvqOut); - return node; -} - -TIntermAggregate *CreateReplacementCall(TIntermAggregate *originalCall, - TIntermTyped *returnValueTarget) -{ - TIntermSequence *replacementArguments = new TIntermSequence(); - TIntermSequence *originalArguments = originalCall->getSequence(); - for (auto &arg : *originalArguments) - { - replacementArguments->push_back(arg); - } - replacementArguments->push_back(returnValueTarget); - TIntermAggregate *replacementCall = TIntermAggregate::CreateFunctionCall( - TType(EbtVoid), originalCall->getFunctionSymbolInfo()->getId(), - originalCall->getFunctionSymbolInfo()->getNameObj(), replacementArguments); - replacementCall->setLine(originalCall->getLine()); - return replacementCall; -} - -class ArrayReturnValueToOutParameterTraverser : private TIntermTraverser -{ - public: - static void apply(TIntermNode *root, TSymbolTable *symbolTable); - - private: - ArrayReturnValueToOutParameterTraverser(TSymbolTable *symbolTable); - - bool visitFunctionPrototype(Visit visit, TIntermFunctionPrototype *node) override; - bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override; - bool visitAggregate(Visit visit, TIntermAggregate *node) override; - bool visitBranch(Visit visit, TIntermBranch *node) override; - bool visitBinary(Visit visit, TIntermBinary *node) override; - - // Set when traversal is inside a function with array return value. - TIntermFunctionDefinition *mFunctionWithArrayReturnValue; - - // Map from function symbol ids to array return value ids. - std::map mReturnValueIds; -}; - -void ArrayReturnValueToOutParameterTraverser::apply(TIntermNode *root, TSymbolTable *symbolTable) -{ - ArrayReturnValueToOutParameterTraverser arrayReturnValueToOutParam(symbolTable); - root->traverse(&arrayReturnValueToOutParam); - arrayReturnValueToOutParam.updateTree(); -} - -ArrayReturnValueToOutParameterTraverser::ArrayReturnValueToOutParameterTraverser( - TSymbolTable *symbolTable) - : TIntermTraverser(true, false, true, symbolTable), mFunctionWithArrayReturnValue(nullptr) -{ -} - -bool ArrayReturnValueToOutParameterTraverser::visitFunctionDefinition( - Visit visit, - TIntermFunctionDefinition *node) -{ - if (node->getFunctionPrototype()->isArray() && visit == PreVisit) - { - // Replacing the function header is done on visitFunctionPrototype(). - mFunctionWithArrayReturnValue = node; - } - if (visit == PostVisit) - { - mFunctionWithArrayReturnValue = nullptr; - } - return true; -} - -bool ArrayReturnValueToOutParameterTraverser::visitFunctionPrototype(Visit visit, - TIntermFunctionPrototype *node) -{ - if (visit == PreVisit && node->isArray()) - { - // Replace the whole prototype node with another node that has the out parameter - // added. Also set the function to return void. - TIntermFunctionPrototype *replacement = - new TIntermFunctionPrototype(TType(EbtVoid), node->getFunctionSymbolInfo()->getId()); - CopyAggregateChildren(node, replacement); - const TSymbolUniqueId &functionId = node->getFunctionSymbolInfo()->getId(); - if (mReturnValueIds.find(functionId.get()) == mReturnValueIds.end()) - { - mReturnValueIds[functionId.get()] = new TSymbolUniqueId(mSymbolTable); - } - replacement->getSequence()->push_back( - CreateReturnValueSymbol(*mReturnValueIds[functionId.get()], node->getType())); - *replacement->getFunctionSymbolInfo() = *node->getFunctionSymbolInfo(); - replacement->setLine(node->getLine()); - - queueReplacement(replacement, OriginalNode::IS_DROPPED); - } - return false; -} - -bool ArrayReturnValueToOutParameterTraverser::visitAggregate(Visit visit, TIntermAggregate *node) -{ - ASSERT(!node->isArray() || node->getOp() != EOpCallInternalRawFunction); - if (visit == PreVisit && node->isArray() && node->getOp() == EOpCallFunctionInAST) - { - // Handle call sites where the returned array is not assigned. - // Examples where f() is a function returning an array: - // 1. f(); - // 2. another_array == f(); - // 3. another_function(f()); - // 4. return f(); - // Cases 2 to 4 are already converted to simpler cases by - // SeparateExpressionsReturningArrays, so we only need to worry about the case where a - // function call returning an array forms an expression by itself. - TIntermBlock *parentBlock = getParentNode()->getAsBlock(); - if (parentBlock) - { - nextTemporaryId(); - TIntermSequence replacements; - replacements.push_back(createTempDeclaration(node->getType())); - TIntermSymbol *returnSymbol = createTempSymbol(node->getType()); - replacements.push_back(CreateReplacementCall(node, returnSymbol)); - mMultiReplacements.push_back( - NodeReplaceWithMultipleEntry(parentBlock, node, replacements)); - } - return false; - } - return true; -} - -bool ArrayReturnValueToOutParameterTraverser::visitBranch(Visit visit, TIntermBranch *node) -{ - if (mFunctionWithArrayReturnValue && node->getFlowOp() == EOpReturn) - { - // Instead of returning a value, assign to the out parameter and then return. - TIntermSequence replacements; - - TIntermTyped *expression = node->getExpression(); - ASSERT(expression != nullptr); - const TSymbolUniqueId &functionId = - mFunctionWithArrayReturnValue->getFunctionSymbolInfo()->getId(); - ASSERT(mReturnValueIds.find(functionId.get()) != mReturnValueIds.end()); - const TSymbolUniqueId &returnValueId = *mReturnValueIds[functionId.get()]; - TIntermSymbol *returnValueSymbol = - CreateReturnValueSymbol(returnValueId, expression->getType()); - TIntermBinary *replacementAssignment = - new TIntermBinary(EOpAssign, returnValueSymbol, expression); - replacementAssignment->setLine(expression->getLine()); - replacements.push_back(replacementAssignment); - - TIntermBranch *replacementBranch = new TIntermBranch(EOpReturn, nullptr); - replacementBranch->setLine(node->getLine()); - replacements.push_back(replacementBranch); - - mMultiReplacements.push_back( - NodeReplaceWithMultipleEntry(getParentNode()->getAsBlock(), node, replacements)); - } - return false; -} - -bool ArrayReturnValueToOutParameterTraverser::visitBinary(Visit visit, TIntermBinary *node) -{ - if (node->getOp() == EOpAssign && node->getLeft()->isArray()) - { - TIntermAggregate *rightAgg = node->getRight()->getAsAggregate(); - ASSERT(rightAgg == nullptr || rightAgg->getOp() != EOpCallInternalRawFunction); - if (rightAgg != nullptr && rightAgg->getOp() == EOpCallFunctionInAST) - { - TIntermAggregate *replacementCall = CreateReplacementCall(rightAgg, node->getLeft()); - queueReplacement(replacementCall, OriginalNode::IS_DROPPED); - } - } - return false; -} - -} // namespace - -void ArrayReturnValueToOutParameter(TIntermNode *root, TSymbolTable *symbolTable) -{ - ArrayReturnValueToOutParameterTraverser::apply(root, symbolTable); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/ArrayReturnValueToOutParameter.h b/src/3rdparty/angle/src/compiler/translator/ArrayReturnValueToOutParameter.h deleted file mode 100644 index 469c7a3b14..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/ArrayReturnValueToOutParameter.h +++ /dev/null @@ -1,22 +0,0 @@ -// -// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// The ArrayReturnValueToOutParameter function changes return values of an array type to out -// parameters in function definitions, prototypes and call sites. - -#ifndef COMPILER_TRANSLATOR_ARRAYRETURNVALUETOOUTPARAMETER_H_ -#define COMPILER_TRANSLATOR_ARRAYRETURNVALUETOOUTPARAMETER_H_ - -namespace sh -{ - -class TIntermNode; -class TSymbolTable; - -void ArrayReturnValueToOutParameter(TIntermNode *root, TSymbolTable *symbolTable); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_ARRAYRETURNVALUETOOUTPARAMETER_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/BaseTypes.h b/src/3rdparty/angle/src/compiler/translator/BaseTypes.h deleted file mode 100644 index b2070f3baf..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/BaseTypes.h +++ /dev/null @@ -1,1073 +0,0 @@ -// -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_TRANSLATOR_BASETYPES_H_ -#define COMPILER_TRANSLATOR_BASETYPES_H_ - -#include -#include - -#include "common/debug.h" -#include "GLSLANG/ShaderLang.h" - -namespace sh -{ - -// -// Precision qualifiers -// -enum TPrecision -{ - // These need to be kept sorted - EbpUndefined, - EbpLow, - EbpMedium, - EbpHigh, - - // end of list - EbpLast -}; - -inline const char *getPrecisionString(TPrecision p) -{ - switch (p) - { - case EbpHigh: - return "highp"; - case EbpMedium: - return "mediump"; - case EbpLow: - return "lowp"; - default: - return "mediump"; // Safest fallback - } -} - -// -// Basic type. Arrays, vectors, etc., are orthogonal to this. -// -enum TBasicType -{ - EbtVoid, - EbtFloat, - EbtInt, - EbtUInt, - EbtBool, - EbtGVec4, // non type: represents vec4, ivec4, and uvec4 - EbtGenType, // non type: represents float, vec2, vec3, and vec4 - EbtGenIType, // non type: represents int, ivec2, ivec3, and ivec4 - EbtGenUType, // non type: represents uint, uvec2, uvec3, and uvec4 - EbtGenBType, // non type: represents bool, bvec2, bvec3, and bvec4 - EbtVec, // non type: represents vec2, vec3, and vec4 - EbtIVec, // non type: represents ivec2, ivec3, and ivec4 - EbtUVec, // non type: represents uvec2, uvec3, and uvec4 - EbtBVec, // non type: represents bvec2, bvec3, and bvec4 - EbtYuvCscStandardEXT, // Only valid if EXT_YUV_target exists. - EbtGuardSamplerBegin, // non type: see implementation of IsSampler() - EbtSampler2D, - EbtSampler3D, - EbtSamplerCube, - EbtSampler2DArray, - EbtSamplerExternalOES, // Only valid if OES_EGL_image_external exists. - EbtSamplerExternal2DY2YEXT, // Only valid if GL_EXT_YUV_target exists. - EbtSampler2DRect, // Only valid if GL_ARB_texture_rectangle exists. - EbtSampler2DMS, - EbtISampler2D, - EbtISampler3D, - EbtISamplerCube, - EbtISampler2DArray, - EbtISampler2DMS, - EbtUSampler2D, - EbtUSampler3D, - EbtUSamplerCube, - EbtUSampler2DArray, - EbtUSampler2DMS, - EbtSampler2DShadow, - EbtSamplerCubeShadow, - EbtSampler2DArrayShadow, - EbtGuardSamplerEnd, // non type: see implementation of IsSampler() - EbtGSampler2D, // non type: represents sampler2D, isampler2D, and usampler2D - EbtGSampler3D, // non type: represents sampler3D, isampler3D, and usampler3D - EbtGSamplerCube, // non type: represents samplerCube, isamplerCube, and usamplerCube - EbtGSampler2DArray, // non type: represents sampler2DArray, isampler2DArray, and - // usampler2DArray - EbtGSampler2DMS, // non type: represents sampler2DMS, isampler2DMS, and usampler2DMS - - // images - EbtGuardImageBegin, - EbtImage2D, - EbtIImage2D, - EbtUImage2D, - EbtImage3D, - EbtIImage3D, - EbtUImage3D, - EbtImage2DArray, - EbtIImage2DArray, - EbtUImage2DArray, - EbtImageCube, - EbtIImageCube, - EbtUImageCube, - EbtGuardImageEnd, - - EbtGuardGImageBegin, - EbtGImage2D, // non type: represents image2D, uimage2D, iimage2D - EbtGImage3D, // non type: represents image3D, uimage3D, iimage3D - EbtGImage2DArray, // non type: represents image2DArray, uimage2DArray, iimage2DArray - EbtGImageCube, // non type: represents imageCube, uimageCube, iimageCube - EbtGuardGImageEnd, - - EbtStruct, - EbtInterfaceBlock, - EbtAddress, // should be deprecated?? - - EbtAtomicCounter, - - // end of list - EbtLast -}; - -inline TBasicType convertGImageToFloatImage(TBasicType type) -{ - switch (type) - { - case EbtGImage2D: - return EbtImage2D; - case EbtGImage3D: - return EbtImage3D; - case EbtGImage2DArray: - return EbtImage2DArray; - case EbtGImageCube: - return EbtImageCube; - default: - UNREACHABLE(); - } - return EbtLast; -} - -inline TBasicType convertGImageToIntImage(TBasicType type) -{ - switch (type) - { - case EbtGImage2D: - return EbtIImage2D; - case EbtGImage3D: - return EbtIImage3D; - case EbtGImage2DArray: - return EbtIImage2DArray; - case EbtGImageCube: - return EbtIImageCube; - default: - UNREACHABLE(); - } - return EbtLast; -} - -inline TBasicType convertGImageToUnsignedImage(TBasicType type) -{ - switch (type) - { - case EbtGImage2D: - return EbtUImage2D; - case EbtGImage3D: - return EbtUImage3D; - case EbtGImage2DArray: - return EbtUImage2DArray; - case EbtGImageCube: - return EbtUImageCube; - default: - UNREACHABLE(); - } - return EbtLast; -} - -const char *getBasicString(TBasicType t); - -inline bool IsSampler(TBasicType type) -{ - return type > EbtGuardSamplerBegin && type < EbtGuardSamplerEnd; -} - -inline bool IsImage(TBasicType type) -{ - return type > EbtGuardImageBegin && type < EbtGuardImageEnd; -} - -inline bool IsGImage(TBasicType type) -{ - return type > EbtGuardGImageBegin && type < EbtGuardGImageEnd; -} - -inline bool IsAtomicCounter(TBasicType type) -{ - return type == EbtAtomicCounter; -} - -inline bool IsOpaqueType(TBasicType type) -{ - return IsSampler(type) || IsImage(type) || IsAtomicCounter(type); -} - -inline bool IsIntegerSampler(TBasicType type) -{ - switch (type) - { - case EbtISampler2D: - case EbtISampler3D: - case EbtISamplerCube: - case EbtISampler2DArray: - case EbtISampler2DMS: - case EbtUSampler2D: - case EbtUSampler3D: - case EbtUSamplerCube: - case EbtUSampler2DArray: - case EbtUSampler2DMS: - return true; - case EbtSampler2D: - case EbtSampler3D: - case EbtSamplerCube: - case EbtSamplerExternalOES: - case EbtSamplerExternal2DY2YEXT: - case EbtSampler2DRect: - case EbtSampler2DArray: - case EbtSampler2DShadow: - case EbtSamplerCubeShadow: - case EbtSampler2DArrayShadow: - case EbtSampler2DMS: - return false; - default: - assert(!IsSampler(type)); - } - - return false; -} - -inline bool IsSampler2DMS(TBasicType type) -{ - switch (type) - { - case EbtSampler2DMS: - case EbtISampler2DMS: - case EbtUSampler2DMS: - return true; - default: - return false; - } -} - -inline bool IsFloatImage(TBasicType type) -{ - switch (type) - { - case EbtImage2D: - case EbtImage3D: - case EbtImage2DArray: - case EbtImageCube: - return true; - default: - break; - } - - return false; -} - -inline bool IsIntegerImage(TBasicType type) -{ - - switch (type) - { - case EbtIImage2D: - case EbtIImage3D: - case EbtIImage2DArray: - case EbtIImageCube: - return true; - default: - break; - } - - return false; -} - -inline bool IsUnsignedImage(TBasicType type) -{ - - switch (type) - { - case EbtUImage2D: - case EbtUImage3D: - case EbtUImage2DArray: - case EbtUImageCube: - return true; - default: - break; - } - - return false; -} - -inline bool IsSampler2D(TBasicType type) -{ - switch (type) - { - case EbtSampler2D: - case EbtISampler2D: - case EbtUSampler2D: - case EbtSampler2DArray: - case EbtISampler2DArray: - case EbtUSampler2DArray: - case EbtSampler2DRect: - case EbtSamplerExternalOES: - case EbtSamplerExternal2DY2YEXT: - case EbtSampler2DShadow: - case EbtSampler2DArrayShadow: - case EbtSampler2DMS: - case EbtISampler2DMS: - case EbtUSampler2DMS: - return true; - case EbtSampler3D: - case EbtISampler3D: - case EbtUSampler3D: - case EbtISamplerCube: - case EbtUSamplerCube: - case EbtSamplerCube: - case EbtSamplerCubeShadow: - return false; - default: - assert(!IsSampler(type)); - } - - return false; -} - -inline bool IsSamplerCube(TBasicType type) -{ - switch (type) - { - case EbtSamplerCube: - case EbtISamplerCube: - case EbtUSamplerCube: - case EbtSamplerCubeShadow: - return true; - case EbtSampler2D: - case EbtSampler3D: - case EbtSamplerExternalOES: - case EbtSamplerExternal2DY2YEXT: - case EbtSampler2DRect: - case EbtSampler2DArray: - case EbtSampler2DMS: - case EbtISampler2D: - case EbtISampler3D: - case EbtISampler2DArray: - case EbtISampler2DMS: - case EbtUSampler2D: - case EbtUSampler3D: - case EbtUSampler2DArray: - case EbtUSampler2DMS: - case EbtSampler2DShadow: - case EbtSampler2DArrayShadow: - return false; - default: - assert(!IsSampler(type)); - } - - return false; -} - -inline bool IsSampler3D(TBasicType type) -{ - switch (type) - { - case EbtSampler3D: - case EbtISampler3D: - case EbtUSampler3D: - return true; - case EbtSampler2D: - case EbtSamplerCube: - case EbtSamplerExternalOES: - case EbtSamplerExternal2DY2YEXT: - case EbtSampler2DRect: - case EbtSampler2DArray: - case EbtSampler2DMS: - case EbtISampler2D: - case EbtISamplerCube: - case EbtISampler2DArray: - case EbtISampler2DMS: - case EbtUSampler2D: - case EbtUSamplerCube: - case EbtUSampler2DArray: - case EbtUSampler2DMS: - case EbtSampler2DShadow: - case EbtSamplerCubeShadow: - case EbtSampler2DArrayShadow: - return false; - default: - assert(!IsSampler(type)); - } - - return false; -} - -inline bool IsSamplerArray(TBasicType type) -{ - switch (type) - { - case EbtSampler2DArray: - case EbtISampler2DArray: - case EbtUSampler2DArray: - case EbtSampler2DArrayShadow: - return true; - case EbtSampler2D: - case EbtISampler2D: - case EbtUSampler2D: - case EbtSampler2DRect: - case EbtSamplerExternalOES: - case EbtSamplerExternal2DY2YEXT: - case EbtSampler3D: - case EbtISampler3D: - case EbtUSampler3D: - case EbtISamplerCube: - case EbtUSamplerCube: - case EbtSamplerCube: - case EbtSampler2DShadow: - case EbtSamplerCubeShadow: - case EbtSampler2DMS: - case EbtISampler2DMS: - case EbtUSampler2DMS: - return false; - default: - assert(!IsSampler(type)); - } - - return false; -} - -inline bool IsShadowSampler(TBasicType type) -{ - switch (type) - { - case EbtSampler2DShadow: - case EbtSamplerCubeShadow: - case EbtSampler2DArrayShadow: - return true; - case EbtISampler2D: - case EbtISampler3D: - case EbtISamplerCube: - case EbtISampler2DArray: - case EbtISampler2DMS: - case EbtUSampler2D: - case EbtUSampler3D: - case EbtUSamplerCube: - case EbtUSampler2DArray: - case EbtUSampler2DMS: - case EbtSampler2D: - case EbtSampler3D: - case EbtSamplerCube: - case EbtSamplerExternalOES: - case EbtSamplerExternal2DY2YEXT: - case EbtSampler2DRect: - case EbtSampler2DArray: - case EbtSampler2DMS: - return false; - default: - assert(!IsSampler(type)); - } - - return false; -} - -inline bool IsImage2D(TBasicType type) -{ - switch (type) - { - case EbtImage2D: - case EbtIImage2D: - case EbtUImage2D: - return true; - case EbtImage3D: - case EbtIImage3D: - case EbtUImage3D: - case EbtImage2DArray: - case EbtIImage2DArray: - case EbtUImage2DArray: - case EbtImageCube: - case EbtIImageCube: - case EbtUImageCube: - return false; - default: - assert(!IsImage(type)); - } - - return false; -} - -inline bool IsImage3D(TBasicType type) -{ - switch (type) - { - case EbtImage3D: - case EbtIImage3D: - case EbtUImage3D: - return true; - case EbtImage2D: - case EbtIImage2D: - case EbtUImage2D: - case EbtImage2DArray: - case EbtIImage2DArray: - case EbtUImage2DArray: - case EbtImageCube: - case EbtIImageCube: - case EbtUImageCube: - return false; - default: - assert(!IsImage(type)); - } - - return false; -} - -inline bool IsImage2DArray(TBasicType type) -{ - switch (type) - { - case EbtImage2DArray: - case EbtIImage2DArray: - case EbtUImage2DArray: - return true; - case EbtImage2D: - case EbtIImage2D: - case EbtUImage2D: - case EbtImage3D: - case EbtIImage3D: - case EbtUImage3D: - case EbtImageCube: - case EbtIImageCube: - case EbtUImageCube: - return false; - default: - assert(!IsImage(type)); - } - - return false; -} - -inline bool IsImageCube(TBasicType type) -{ - switch (type) - { - case EbtImageCube: - case EbtIImageCube: - case EbtUImageCube: - return true; - case EbtImage2D: - case EbtIImage2D: - case EbtUImage2D: - case EbtImage3D: - case EbtIImage3D: - case EbtUImage3D: - case EbtImage2DArray: - case EbtIImage2DArray: - case EbtUImage2DArray: - return false; - default: - assert(!IsImage(type)); - } - - return false; -} - -inline bool IsInteger(TBasicType type) -{ - return type == EbtInt || type == EbtUInt; -} - -inline bool SupportsPrecision(TBasicType type) -{ - return type == EbtFloat || type == EbtInt || type == EbtUInt || IsOpaqueType(type); -} - -// -// Qualifiers and built-ins. These are mainly used to see what can be read -// or written, and by the machine dependent translator to know which registers -// to allocate variables in. Since built-ins tend to go to different registers -// than varying or uniform, it makes sense they are peers, not sub-classes. -// -enum TQualifier -{ - EvqTemporary, // For temporaries (within a function), read/write - EvqGlobal, // For globals read/write - EvqConst, // User defined constants and non-output parameters in functions - EvqAttribute, // Readonly - EvqVaryingIn, // readonly, fragment shaders only - EvqVaryingOut, // vertex shaders only read/write - EvqUniform, // Readonly, vertex and fragment - EvqBuffer, // read/write, vertex, fragment and compute shader - - EvqVertexIn, // Vertex shader input - EvqFragmentOut, // Fragment shader output - EvqVertexOut, // Vertex shader output - EvqFragmentIn, // Fragment shader input - - // parameters - EvqIn, - EvqOut, - EvqInOut, - EvqConstReadOnly, - - // built-ins read by vertex shader - EvqInstanceID, - EvqVertexID, - - // built-ins written by vertex shader - EvqPosition, - EvqPointSize, - - // built-ins read by fragment shader - EvqFragCoord, - EvqFrontFacing, - EvqPointCoord, - - // built-ins written by fragment shader - EvqFragColor, - EvqFragData, - - EvqFragDepth, // gl_FragDepth for ESSL300. - EvqFragDepthEXT, // gl_FragDepthEXT for ESSL100, EXT_frag_depth. - - EvqSecondaryFragColorEXT, // EXT_blend_func_extended - EvqSecondaryFragDataEXT, // EXT_blend_func_extended - - EvqViewIDOVR, // OVR_multiview - EvqViewportIndex, // gl_ViewportIndex - - // built-ins written by the shader_framebuffer_fetch extension(s) - EvqLastFragColor, - EvqLastFragData, - - // GLSL ES 3.0 vertex output and fragment input - EvqSmooth, // Incomplete qualifier, smooth is the default - EvqFlat, // Incomplete qualifier - EvqCentroid, // Incomplete qualifier - EvqSmoothOut, - EvqFlatOut, - EvqCentroidOut, // Implies smooth - EvqSmoothIn, - EvqFlatIn, - EvqCentroidIn, // Implies smooth - - // GLSL ES 3.1 compute shader special variables - EvqShared, - EvqComputeIn, - EvqNumWorkGroups, - EvqWorkGroupSize, - EvqWorkGroupID, - EvqLocalInvocationID, - EvqGlobalInvocationID, - EvqLocalInvocationIndex, - - // GLSL ES 3.1 memory qualifiers - EvqReadOnly, - EvqWriteOnly, - EvqCoherent, - EvqRestrict, - EvqVolatile, - - // GLSL ES 3.1 extension OES_geometry_shader qualifiers - EvqGeometryIn, - EvqGeometryOut, - EvqPerVertexIn, // gl_in - EvqPrimitiveIDIn, // gl_PrimitiveIDIn - EvqInvocationID, // gl_InvocationID - EvqPrimitiveID, // gl_PrimitiveID - EvqLayer, // gl_Layer - - // end of list - EvqLast -}; - -inline bool IsQualifierUnspecified(TQualifier qualifier) -{ - return (qualifier == EvqTemporary || qualifier == EvqGlobal); -} - -enum TLayoutImageInternalFormat -{ - EiifUnspecified, - EiifRGBA32F, - EiifRGBA16F, - EiifR32F, - EiifRGBA32UI, - EiifRGBA16UI, - EiifRGBA8UI, - EiifR32UI, - EiifRGBA32I, - EiifRGBA16I, - EiifRGBA8I, - EiifR32I, - EiifRGBA8, - EiifRGBA8_SNORM -}; - -enum TLayoutMatrixPacking -{ - EmpUnspecified, - EmpRowMajor, - EmpColumnMajor -}; - -enum TLayoutBlockStorage -{ - EbsUnspecified, - EbsShared, - EbsPacked, - EbsStd140, - EbsStd430 -}; - -enum TYuvCscStandardEXT -{ - EycsUndefined, - EycsItu601, - EycsItu601FullRange, - EycsItu709 -}; - -enum TLayoutPrimitiveType -{ - EptUndefined, - EptPoints, - EptLines, - EptLinesAdjacency, - EptTriangles, - EptTrianglesAdjacency, - EptLineStrip, - EptTriangleStrip -}; - -struct TLayoutQualifier -{ - // Must have a trivial default constructor since it is used in YYSTYPE. - TLayoutQualifier() = default; - - constexpr static TLayoutQualifier Create() { return TLayoutQualifier(0); } - - bool isEmpty() const - { - return location == -1 && binding == -1 && offset == -1 && numViews == -1 && yuv == false && - matrixPacking == EmpUnspecified && blockStorage == EbsUnspecified && - !localSize.isAnyValueSet() && imageInternalFormat == EiifUnspecified && - primitiveType == EptUndefined && invocations == 0 && maxVertices == -1; - } - - bool isCombinationValid() const - { - bool workSizeSpecified = localSize.isAnyValueSet(); - bool numViewsSet = (numViews != -1); - bool geometryShaderSpecified = - (primitiveType != EptUndefined) || (invocations != 0) || (maxVertices != -1); - bool otherLayoutQualifiersSpecified = - (location != -1 || binding != -1 || matrixPacking != EmpUnspecified || - blockStorage != EbsUnspecified || imageInternalFormat != EiifUnspecified); - - // we can have either the work group size specified, or number of views, - // or yuv layout qualifier, or the other layout qualifiers. - return (workSizeSpecified ? 1 : 0) + (numViewsSet ? 1 : 0) + (yuv ? 1 : 0) + - (otherLayoutQualifiersSpecified ? 1 : 0) + (geometryShaderSpecified ? 1 : 0) <= - 1; - } - - bool isLocalSizeEqual(const sh::WorkGroupSize &localSizeIn) const - { - return localSize.isWorkGroupSizeMatching(localSizeIn); - } - - int location; - unsigned int locationsSpecified; - TLayoutMatrixPacking matrixPacking; - TLayoutBlockStorage blockStorage; - - // Compute shader layout qualifiers. - sh::WorkGroupSize localSize; - - int binding; - int offset; - - // Image format layout qualifier - TLayoutImageInternalFormat imageInternalFormat; - - // OVR_multiview num_views. - int numViews; - - // EXT_YUV_target yuv layout qualifier. - bool yuv; - - // OES_geometry_shader layout qualifiers. - TLayoutPrimitiveType primitiveType; - int invocations; - int maxVertices; - - private: - explicit constexpr TLayoutQualifier(int /*placeholder*/) - : location(-1), - locationsSpecified(0), - matrixPacking(EmpUnspecified), - blockStorage(EbsUnspecified), - localSize(-1), - binding(-1), - offset(-1), - imageInternalFormat(EiifUnspecified), - numViews(-1), - yuv(false), - primitiveType(EptUndefined), - invocations(0), - maxVertices(-1) - { - } -}; - -struct TMemoryQualifier -{ - // Must have a trivial default constructor since it is used in YYSTYPE. - TMemoryQualifier() = default; - - bool isEmpty() const - { - return !readonly && !writeonly && !coherent && !restrictQualifier && !volatileQualifier; - } - - constexpr static TMemoryQualifier Create() { return TMemoryQualifier(0); } - - // GLSL ES 3.10 Revision 4, 4.9 Memory Access Qualifiers - // An image can be qualified as both readonly and writeonly. It still can be can be used with - // imageSize(). - bool readonly; - bool writeonly; - bool coherent; - - // restrict and volatile are reserved keywords in C/C++ - bool restrictQualifier; - bool volatileQualifier; - - private: - explicit constexpr TMemoryQualifier(int /*placeholder*/) - : readonly(false), - writeonly(false), - coherent(false), - restrictQualifier(false), - volatileQualifier(false) - { - } -}; - -inline const char *getWorkGroupSizeString(size_t dimension) -{ - switch (dimension) - { - case 0u: - return "local_size_x"; - case 1u: - return "local_size_y"; - case 2u: - return "local_size_z"; - default: - UNREACHABLE(); - return "dimension out of bounds"; - } -} - -// -// This is just for debug and error message print out, carried along with the definitions above. -// -inline const char *getQualifierString(TQualifier q) -{ - // clang-format off - switch(q) - { - case EvqTemporary: return "Temporary"; - case EvqGlobal: return "Global"; - case EvqConst: return "const"; - case EvqAttribute: return "attribute"; - case EvqVaryingIn: return "varying"; - case EvqVaryingOut: return "varying"; - case EvqUniform: return "uniform"; - case EvqBuffer: return "buffer"; - case EvqVertexIn: return "in"; - case EvqFragmentOut: return "out"; - case EvqVertexOut: return "out"; - case EvqFragmentIn: return "in"; - case EvqIn: return "in"; - case EvqOut: return "out"; - case EvqInOut: return "inout"; - case EvqConstReadOnly: return "const"; - case EvqInstanceID: return "InstanceID"; - case EvqVertexID: return "VertexID"; - case EvqPosition: return "Position"; - case EvqPointSize: return "PointSize"; - case EvqFragCoord: return "FragCoord"; - case EvqFrontFacing: return "FrontFacing"; - case EvqPointCoord: return "PointCoord"; - case EvqFragColor: return "FragColor"; - case EvqFragData: return "FragData"; - case EvqFragDepthEXT: return "FragDepth"; - case EvqFragDepth: return "FragDepth"; - case EvqSecondaryFragColorEXT: return "SecondaryFragColorEXT"; - case EvqSecondaryFragDataEXT: return "SecondaryFragDataEXT"; - case EvqViewIDOVR: return "ViewIDOVR"; - case EvqViewportIndex: return "ViewportIndex"; - case EvqLayer: return "Layer"; - case EvqLastFragColor: return "LastFragColor"; - case EvqLastFragData: return "LastFragData"; - case EvqSmoothOut: return "smooth out"; - case EvqCentroidOut: return "smooth centroid out"; - case EvqFlatOut: return "flat out"; - case EvqSmoothIn: return "smooth in"; - case EvqFlatIn: return "flat in"; - case EvqCentroidIn: return "smooth centroid in"; - case EvqCentroid: return "centroid"; - case EvqFlat: return "flat"; - case EvqSmooth: return "smooth"; - case EvqShared: return "shared"; - case EvqComputeIn: return "in"; - case EvqNumWorkGroups: return "NumWorkGroups"; - case EvqWorkGroupSize: return "WorkGroupSize"; - case EvqWorkGroupID: return "WorkGroupID"; - case EvqLocalInvocationID: return "LocalInvocationID"; - case EvqGlobalInvocationID: return "GlobalInvocationID"; - case EvqLocalInvocationIndex: return "LocalInvocationIndex"; - case EvqReadOnly: return "readonly"; - case EvqWriteOnly: return "writeonly"; - case EvqGeometryIn: return "in"; - case EvqGeometryOut: return "out"; - case EvqPerVertexIn: return "gl_in"; - default: UNREACHABLE(); return "unknown qualifier"; - } - // clang-format on -} - -inline const char *getMatrixPackingString(TLayoutMatrixPacking mpq) -{ - switch (mpq) - { - case EmpUnspecified: - return "mp_unspecified"; - case EmpRowMajor: - return "row_major"; - case EmpColumnMajor: - return "column_major"; - default: - UNREACHABLE(); - return "unknown matrix packing"; - } -} - -inline const char *getBlockStorageString(TLayoutBlockStorage bsq) -{ - switch (bsq) - { - case EbsUnspecified: - return "bs_unspecified"; - case EbsShared: - return "shared"; - case EbsPacked: - return "packed"; - case EbsStd140: - return "std140"; - case EbsStd430: - return "std430"; - default: - UNREACHABLE(); - return "unknown block storage"; - } -} - -inline const char *getImageInternalFormatString(TLayoutImageInternalFormat iifq) -{ - switch (iifq) - { - case EiifRGBA32F: - return "rgba32f"; - case EiifRGBA16F: - return "rgba16f"; - case EiifR32F: - return "r32f"; - case EiifRGBA32UI: - return "rgba32ui"; - case EiifRGBA16UI: - return "rgba16ui"; - case EiifRGBA8UI: - return "rgba8ui"; - case EiifR32UI: - return "r32ui"; - case EiifRGBA32I: - return "rgba32i"; - case EiifRGBA16I: - return "rgba16i"; - case EiifRGBA8I: - return "rgba8i"; - case EiifR32I: - return "r32i"; - case EiifRGBA8: - return "rgba8"; - case EiifRGBA8_SNORM: - return "rgba8_snorm"; - default: - UNREACHABLE(); - return "unknown internal image format"; - } -} - -inline TYuvCscStandardEXT getYuvCscStandardEXT(const std::string &str) -{ - if (str == "itu_601") - return EycsItu601; - else if (str == "itu_601_full_range") - return EycsItu601FullRange; - else if (str == "itu_709") - return EycsItu709; - return EycsUndefined; -} - -inline const char *getYuvCscStandardEXTString(TYuvCscStandardEXT ycsq) -{ - switch (ycsq) - { - case EycsItu601: - return "itu_601"; - case EycsItu601FullRange: - return "itu_601_full_range"; - case EycsItu709: - return "itu_709"; - default: - UNREACHABLE(); - return "unknown color space conversion standard"; - } -} - -inline const char *getGeometryShaderPrimitiveTypeString(TLayoutPrimitiveType primitiveType) -{ - switch (primitiveType) - { - case EptPoints: - return "points"; - case EptLines: - return "lines"; - case EptTriangles: - return "triangles"; - case EptLinesAdjacency: - return "lines_adjacency"; - case EptTrianglesAdjacency: - return "triangles_adjacency"; - case EptLineStrip: - return "line_strip"; - case EptTriangleStrip: - return "triangle_strip"; - default: - UNREACHABLE(); - return "unknown geometry shader primitive type"; - } -} - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_BASETYPES_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/BreakVariableAliasingInInnerLoops.cpp b/src/3rdparty/angle/src/compiler/translator/BreakVariableAliasingInInnerLoops.cpp deleted file mode 100644 index d6a1e025de..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/BreakVariableAliasingInInnerLoops.cpp +++ /dev/null @@ -1,107 +0,0 @@ -// -// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// BreakVariableAliasingInInnerLoops.h: To optimize simple assignments, the HLSL compiler frontend -// may record a variable as aliasing another. Sometimes the alias information gets garbled -// so we work around this issue by breaking the aliasing chain in inner loops. - -#include "BreakVariableAliasingInInnerLoops.h" - -#include "compiler/translator/IntermNode_util.h" -#include "compiler/translator/IntermTraverse.h" - -// A HLSL compiler developer gave us more details on the root cause and the workaround needed: -// The root problem is that if the HLSL compiler is applying aliasing information even on -// incomplete simulations (in this case, a single pass). The bug is triggered by an assignment -// that comes from a series of assignments, possibly with swizzled or ternary operators with -// known conditionals, where the source is before the loop. -// So, a workaround is to add a +0 term to variables the first time they are assigned to in -// an inner loop (if they are declared in an outside scope, otherwise there is no need). -// This will break the aliasing chain. - -// For simplicity here we add a +0 to any assignment that is in at least two nested loops. Because -// the bug only shows up with swizzles, and ternary assignment, whole array or whole structure -// assignment don't need a workaround. - -namespace sh -{ - -namespace -{ - -class AliasingBreaker : public TIntermTraverser -{ - public: - AliasingBreaker() : TIntermTraverser(true, false, true) {} - - protected: - bool visitBinary(Visit visit, TIntermBinary *binary) - { - if (visit != PreVisit) - { - return false; - } - - if (mLoopLevel < 2 || !binary->isAssignment()) - { - return true; - } - - TIntermTyped *B = binary->getRight(); - TType type = B->getType(); - - if (!type.isScalar() && !type.isVector() && !type.isMatrix()) - { - return true; - } - - if (type.isArray() || IsSampler(type.getBasicType())) - { - return true; - } - - // We have a scalar / vector / matrix assignment with loop depth 2. - // Transform it from - // A = B - // to - // A = (B + typeof(0)); - - TIntermBinary *bPlusZero = new TIntermBinary(EOpAdd, B, CreateZeroNode(type)); - bPlusZero->setLine(B->getLine()); - - binary->replaceChildNode(B, bPlusZero); - - return true; - } - - bool visitLoop(Visit visit, TIntermLoop *loop) - { - if (visit == PreVisit) - { - mLoopLevel++; - } - else - { - ASSERT(mLoopLevel > 0); - mLoopLevel--; - } - - return true; - } - - private: - int mLoopLevel = 0; -}; - -} // anonymous namespace - -void BreakVariableAliasingInInnerLoops(TIntermNode *root) -{ - AliasingBreaker breaker; - root->traverse(&breaker); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/BreakVariableAliasingInInnerLoops.h b/src/3rdparty/angle/src/compiler/translator/BreakVariableAliasingInInnerLoops.h deleted file mode 100644 index b1d906f919..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/BreakVariableAliasingInInnerLoops.h +++ /dev/null @@ -1,23 +0,0 @@ -// -// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// BreakVariableAliasingInInnerLoops.h: To optimize simple assignments, the HLSL compiler frontend -// may record a variable as aliasing another. Sometimes the alias information gets garbled -// so we work around this issue by breaking the aliasing chain in inner loops. - -#ifndef COMPILER_TRANSLATOR_BREAKVARIABLEALIASINGININNERLOOPS_H_ -#define COMPILER_TRANSLATOR_BREAKVARIABLEALIASINGININNERLOOPS_H_ - -class TIntermNode; - -namespace sh -{ - -void BreakVariableAliasingInInnerLoops(TIntermNode *root); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_BREAKVARIABLEALIASINGININNERLOOPS_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.cpp b/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.cpp deleted file mode 100644 index 905e634fd1..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.cpp +++ /dev/null @@ -1,355 +0,0 @@ -// -// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/translator/BuiltInFunctionEmulator.h" -#include "angle_gl.h" -#include "compiler/translator/Cache.h" -#include "compiler/translator/IntermTraverse.h" -#include "compiler/translator/SymbolTable.h" - -namespace sh -{ - -class BuiltInFunctionEmulator::BuiltInFunctionEmulationMarker : public TIntermTraverser -{ - public: - BuiltInFunctionEmulationMarker(BuiltInFunctionEmulator &emulator) - : TIntermTraverser(true, false, false), mEmulator(emulator) - { - } - - bool visitUnary(Visit visit, TIntermUnary *node) override - { - if (visit == PreVisit) - { - bool needToEmulate = - mEmulator.setFunctionCalled(node->getOp(), node->getOperand()->getType()); - if (needToEmulate) - node->setUseEmulatedFunction(); - } - return true; - } - - bool visitAggregate(Visit visit, TIntermAggregate *node) override - { - if (visit == PreVisit) - { - // Here we handle all the built-in functions mapped to ops, not just the ones that are - // currently identified as problematic. - if (node->isConstructor() || node->isFunctionCall()) - { - return true; - } - const TIntermSequence &sequence = *(node->getSequence()); - bool needToEmulate = false; - // Right now we only handle built-in functions with two to four parameters. - if (sequence.size() == 2) - { - TIntermTyped *param1 = sequence[0]->getAsTyped(); - TIntermTyped *param2 = sequence[1]->getAsTyped(); - if (!param1 || !param2) - return true; - needToEmulate = mEmulator.setFunctionCalled(node->getOp(), param1->getType(), - param2->getType()); - } - else if (sequence.size() == 3) - { - TIntermTyped *param1 = sequence[0]->getAsTyped(); - TIntermTyped *param2 = sequence[1]->getAsTyped(); - TIntermTyped *param3 = sequence[2]->getAsTyped(); - if (!param1 || !param2 || !param3) - return true; - needToEmulate = mEmulator.setFunctionCalled(node->getOp(), param1->getType(), - param2->getType(), param3->getType()); - } - else if (sequence.size() == 4) - { - TIntermTyped *param1 = sequence[0]->getAsTyped(); - TIntermTyped *param2 = sequence[1]->getAsTyped(); - TIntermTyped *param3 = sequence[2]->getAsTyped(); - TIntermTyped *param4 = sequence[3]->getAsTyped(); - if (!param1 || !param2 || !param3 || !param4) - return true; - needToEmulate = - mEmulator.setFunctionCalled(node->getOp(), param1->getType(), param2->getType(), - param3->getType(), param4->getType()); - } - else - { - return true; - } - - if (needToEmulate) - node->setUseEmulatedFunction(); - } - return true; - } - - private: - BuiltInFunctionEmulator &mEmulator; -}; - -BuiltInFunctionEmulator::BuiltInFunctionEmulator() -{ -} - -FunctionId BuiltInFunctionEmulator::addEmulatedFunction(TOperator op, - const TType *param, - const char *emulatedFunctionDefinition) -{ - FunctionId id(op, param); - mEmulatedFunctions[id] = std::string(emulatedFunctionDefinition); - return id; -} - -FunctionId BuiltInFunctionEmulator::addEmulatedFunction(TOperator op, - const TType *param1, - const TType *param2, - const char *emulatedFunctionDefinition) -{ - FunctionId id(op, param1, param2); - mEmulatedFunctions[id] = std::string(emulatedFunctionDefinition); - return id; -} - -FunctionId BuiltInFunctionEmulator::addEmulatedFunctionWithDependency( - const FunctionId &dependency, - TOperator op, - const TType *param1, - const TType *param2, - const char *emulatedFunctionDefinition) -{ - FunctionId id(op, param1, param2); - mEmulatedFunctions[id] = std::string(emulatedFunctionDefinition); - mFunctionDependencies[id] = dependency; - return id; -} - -FunctionId BuiltInFunctionEmulator::addEmulatedFunction(TOperator op, - const TType *param1, - const TType *param2, - const TType *param3, - const char *emulatedFunctionDefinition) -{ - FunctionId id(op, param1, param2, param3); - mEmulatedFunctions[id] = std::string(emulatedFunctionDefinition); - return id; -} - -FunctionId BuiltInFunctionEmulator::addEmulatedFunction(TOperator op, - const TType *param1, - const TType *param2, - const TType *param3, - const TType *param4, - const char *emulatedFunctionDefinition) -{ - FunctionId id(op, param1, param2, param3, param4); - mEmulatedFunctions[id] = std::string(emulatedFunctionDefinition); - return id; -} - -FunctionId BuiltInFunctionEmulator::addEmulatedFunctionWithDependency( - const FunctionId &dependency, - TOperator op, - const TType *param1, - const TType *param2, - const TType *param3, - const TType *param4, - const char *emulatedFunctionDefinition) -{ - FunctionId id(op, param1, param2, param3, param4); - mEmulatedFunctions[id] = std::string(emulatedFunctionDefinition); - mFunctionDependencies[id] = dependency; - return id; -} - -bool BuiltInFunctionEmulator::isOutputEmpty() const -{ - return (mFunctions.size() == 0); -} - -void BuiltInFunctionEmulator::outputEmulatedFunctions(TInfoSinkBase &out) const -{ - for (const auto &function : mFunctions) - { - const char *body = findEmulatedFunction(function); - ASSERT(body); - out << body; - out << "\n\n"; - } -} - -bool BuiltInFunctionEmulator::setFunctionCalled(TOperator op, const TType ¶m) -{ - return setFunctionCalled(FunctionId(op, ¶m)); -} - -bool BuiltInFunctionEmulator::setFunctionCalled(TOperator op, - const TType ¶m1, - const TType ¶m2) -{ - return setFunctionCalled(FunctionId(op, ¶m1, ¶m2)); -} - -bool BuiltInFunctionEmulator::setFunctionCalled(TOperator op, - const TType ¶m1, - const TType ¶m2, - const TType ¶m3) -{ - return setFunctionCalled(FunctionId(op, ¶m1, ¶m2, ¶m3)); -} - -bool BuiltInFunctionEmulator::setFunctionCalled(TOperator op, - const TType ¶m1, - const TType ¶m2, - const TType ¶m3, - const TType ¶m4) -{ - return setFunctionCalled(FunctionId(op, ¶m1, ¶m2, ¶m3, ¶m4)); -} - -const char *BuiltInFunctionEmulator::findEmulatedFunction(const FunctionId &functionId) const -{ - for (const auto &queryFunction : mQueryFunctions) - { - const char *result = queryFunction(functionId); - if (result) - { - return result; - } - } - - const auto &result = mEmulatedFunctions.find(functionId); - if (result != mEmulatedFunctions.end()) - { - return result->second.c_str(); - } - - return nullptr; -} - -bool BuiltInFunctionEmulator::setFunctionCalled(const FunctionId &functionId) -{ - if (!findEmulatedFunction(functionId)) - { - return false; - } - - for (size_t i = 0; i < mFunctions.size(); ++i) - { - if (mFunctions[i] == functionId) - return true; - } - // If the function depends on another, mark the dependency as called. - auto dependency = mFunctionDependencies.find(functionId); - if (dependency != mFunctionDependencies.end()) - { - setFunctionCalled((*dependency).second); - } - // Copy the functionId if it needs to be stored, to make sure that the TType pointers inside - // remain valid and constant. - mFunctions.push_back(functionId.getCopy()); - return true; -} - -void BuiltInFunctionEmulator::markBuiltInFunctionsForEmulation(TIntermNode *root) -{ - ASSERT(root); - - if (mEmulatedFunctions.empty() && mQueryFunctions.empty()) - return; - - BuiltInFunctionEmulationMarker marker(*this); - root->traverse(&marker); -} - -void BuiltInFunctionEmulator::cleanup() -{ - mFunctions.clear(); - mFunctionDependencies.clear(); -} - -void BuiltInFunctionEmulator::addFunctionMap(BuiltinQueryFunc queryFunc) -{ - mQueryFunctions.push_back(queryFunc); -} - -// static -void BuiltInFunctionEmulator::WriteEmulatedFunctionName(TInfoSinkBase &out, const char *name) -{ - ASSERT(name[strlen(name) - 1] != '('); - out << name << "_emu"; -} - -FunctionId::FunctionId() - : mOp(EOpNull), - mParam1(TCache::getType(EbtVoid)), - mParam2(TCache::getType(EbtVoid)), - mParam3(TCache::getType(EbtVoid)), - mParam4(TCache::getType(EbtVoid)) -{ -} - -FunctionId::FunctionId(TOperator op, const TType *param) - : mOp(op), - mParam1(param), - mParam2(TCache::getType(EbtVoid)), - mParam3(TCache::getType(EbtVoid)), - mParam4(TCache::getType(EbtVoid)) -{ -} - -FunctionId::FunctionId(TOperator op, const TType *param1, const TType *param2) - : mOp(op), - mParam1(param1), - mParam2(param2), - mParam3(TCache::getType(EbtVoid)), - mParam4(TCache::getType(EbtVoid)) -{ -} - -FunctionId::FunctionId(TOperator op, const TType *param1, const TType *param2, const TType *param3) - : mOp(op), mParam1(param1), mParam2(param2), mParam3(param3), mParam4(TCache::getType(EbtVoid)) -{ -} - -FunctionId::FunctionId(TOperator op, - const TType *param1, - const TType *param2, - const TType *param3, - const TType *param4) - : mOp(op), mParam1(param1), mParam2(param2), mParam3(param3), mParam4(param4) -{ -} - -bool FunctionId::operator==(const FunctionId &other) const -{ - return (mOp == other.mOp && *mParam1 == *other.mParam1 && *mParam2 == *other.mParam2 && - *mParam3 == *other.mParam3 && *mParam4 == *other.mParam4); -} - -bool FunctionId::operator<(const FunctionId &other) const -{ - if (mOp != other.mOp) - return mOp < other.mOp; - if (*mParam1 != *other.mParam1) - return *mParam1 < *other.mParam1; - if (*mParam2 != *other.mParam2) - return *mParam2 < *other.mParam2; - if (*mParam3 != *other.mParam3) - return *mParam3 < *other.mParam3; - if (*mParam4 != *other.mParam4) - return *mParam4 < *other.mParam4; - return false; // all fields are equal -} - -FunctionId FunctionId::getCopy() const -{ - return FunctionId(mOp, new TType(*mParam1), new TType(*mParam2), new TType(*mParam3), - new TType(*mParam4)); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.h b/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.h deleted file mode 100644 index 5f15f66224..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.h +++ /dev/null @@ -1,183 +0,0 @@ -// -// Copyright (c) 2011 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATOR_H_ -#define COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATOR_H_ - -#include "compiler/translator/InfoSink.h" -#include "compiler/translator/IntermNode.h" -#include "compiler/translator/ParamType.h" - -namespace sh -{ - -struct MiniFunctionId -{ - constexpr MiniFunctionId(TOperator op = EOpNull, - ParamType paramType1 = ParamType::Void, - ParamType paramType2 = ParamType::Void, - ParamType paramType3 = ParamType::Void, - ParamType paramType4 = ParamType::Void) - : op(op), - paramType1(paramType1), - paramType2(paramType2), - paramType3(paramType3), - paramType4(paramType4) - { - } - - TOperator op; - ParamType paramType1; - ParamType paramType2; - ParamType paramType3; - ParamType paramType4; -}; - -class FunctionId final -{ - public: - FunctionId(); - FunctionId(TOperator op, const TType *param); - FunctionId(TOperator op, const TType *param1, const TType *param2); - FunctionId(TOperator op, const TType *param1, const TType *param2, const TType *param3); - FunctionId(TOperator op, - const TType *param1, - const TType *param2, - const TType *param3, - const TType *param4); - - FunctionId(const FunctionId &) = default; - FunctionId &operator=(const FunctionId &) = default; - - bool operator==(const FunctionId &other) const; - bool operator<(const FunctionId &other) const; - - FunctionId getCopy() const; - - private: - friend bool operator==(const MiniFunctionId &miniId, const FunctionId &functionId); - TOperator mOp; - - // The memory that these TType objects use is freed by PoolAllocator. The - // BuiltInFunctionEmulator's lifetime can extend until after the memory pool is freed, but - // that's not an issue since this class never destructs these objects. - const TType *mParam1; - const TType *mParam2; - const TType *mParam3; - const TType *mParam4; -}; - -inline bool operator==(ParamType paramType, const TType *type) -{ - return SameParamType(paramType, type->getBasicType(), type->getNominalSize(), - type->getSecondarySize()); -} - -inline bool operator==(const MiniFunctionId &miniId, const FunctionId &functionId) -{ - return miniId.op == functionId.mOp && miniId.paramType1 == functionId.mParam1 && - miniId.paramType2 == functionId.mParam2 && miniId.paramType3 == functionId.mParam3 && - miniId.paramType4 == functionId.mParam4; -} - -using BuiltinQueryFunc = const char *(const FunctionId &); - -// -// This class decides which built-in functions need to be replaced with the emulated ones. It can be -// used to work around driver bugs or implement functions that are not natively implemented on a -// specific platform. -// -class BuiltInFunctionEmulator -{ - public: - BuiltInFunctionEmulator(); - - void markBuiltInFunctionsForEmulation(TIntermNode *root); - - void cleanup(); - - // "name" gets written as "name_emu". - static void WriteEmulatedFunctionName(TInfoSinkBase &out, const char *name); - - bool isOutputEmpty() const; - - // Output function emulation definition. This should be before any other shader source. - void outputEmulatedFunctions(TInfoSinkBase &out) const; - - // Add functions that need to be emulated. - FunctionId addEmulatedFunction(TOperator op, - const TType *param, - const char *emulatedFunctionDefinition); - FunctionId addEmulatedFunction(TOperator op, - const TType *param1, - const TType *param2, - const char *emulatedFunctionDefinition); - FunctionId addEmulatedFunction(TOperator op, - const TType *param1, - const TType *param2, - const TType *param3, - const char *emulatedFunctionDefinition); - FunctionId addEmulatedFunction(TOperator op, - const TType *param1, - const TType *param2, - const TType *param3, - const TType *param4, - const char *emulatedFunctionDefinition); - - FunctionId addEmulatedFunctionWithDependency(const FunctionId &dependency, - TOperator op, - const TType *param1, - const TType *param2, - const char *emulatedFunctionDefinition); - FunctionId addEmulatedFunctionWithDependency(const FunctionId &dependency, - TOperator op, - const TType *param1, - const TType *param2, - const TType *param3, - const TType *param4, - const char *emulatedFunctionDefinition); - - void addFunctionMap(BuiltinQueryFunc queryFunc); - - private: - class BuiltInFunctionEmulationMarker; - - // Records that a function is called by the shader and might need to be emulated. If the - // function is not in mEmulatedFunctions, this becomes a no-op. Returns true if the function - // call needs to be replaced with an emulated one. - bool setFunctionCalled(TOperator op, const TType ¶m); - bool setFunctionCalled(TOperator op, const TType ¶m1, const TType ¶m2); - bool setFunctionCalled(TOperator op, - const TType ¶m1, - const TType ¶m2, - const TType ¶m3); - bool setFunctionCalled(TOperator op, - const TType ¶m1, - const TType ¶m2, - const TType ¶m3, - const TType ¶m4); - - bool setFunctionCalled(const FunctionId &functionId); - - const char *findEmulatedFunction(const FunctionId &functionId) const; - - // Map from function id to emulated function definition - std::map mEmulatedFunctions; - - // Map from dependent functions to their dependencies. This structure allows each function to - // have at most one dependency. - std::map mFunctionDependencies; - - // Called function ids - std::vector mFunctions; - - // Constexpr function tables. - std::vector mQueryFunctions; -}; - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATOR_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorGLSL.cpp b/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorGLSL.cpp deleted file mode 100644 index 27ee04da35..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorGLSL.cpp +++ /dev/null @@ -1,293 +0,0 @@ -// -// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "angle_gl.h" -#include "compiler/translator/BuiltInFunctionEmulator.h" -#include "compiler/translator/BuiltInFunctionEmulatorGLSL.h" -#include "compiler/translator/Cache.h" -#include "compiler/translator/SymbolTable.h" -#include "compiler/translator/VersionGLSL.h" - -namespace sh -{ - -void InitBuiltInAbsFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator *emu, - sh::GLenum shaderType) -{ - if (shaderType == GL_VERTEX_SHADER) - { - const TType *int1 = TCache::getType(EbtInt); - emu->addEmulatedFunction(EOpAbs, int1, "int abs_emu(int x) { return x * sign(x); }"); - } -} - -void InitBuiltInIsnanFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator *emu, - int targetGLSLVersion) -{ - // isnan() is supported since GLSL 1.3. - if (targetGLSLVersion < GLSL_VERSION_130) - return; - - const TType *float1 = TCache::getType(EbtFloat); - const TType *float2 = TCache::getType(EbtFloat, 2); - const TType *float3 = TCache::getType(EbtFloat, 3); - const TType *float4 = TCache::getType(EbtFloat, 4); - - // !(x > 0.0 || x < 0.0 || x == 0.0) will be optimized and always equal to false. - emu->addEmulatedFunction( - EOpIsNan, float1, - "bool isnan_emu(float x) { return (x > 0.0 || x < 0.0) ? false : x != 0.0; }"); - emu->addEmulatedFunction( - EOpIsNan, float2, - "bvec2 isnan_emu(vec2 x)\n" - "{\n" - " bvec2 isnan;\n" - " for (int i = 0; i < 2; i++)\n" - " {\n" - " isnan[i] = (x[i] > 0.0 || x[i] < 0.0) ? false : x[i] != 0.0;\n" - " }\n" - " return isnan;\n" - "}\n"); - emu->addEmulatedFunction( - EOpIsNan, float3, - "bvec3 isnan_emu(vec3 x)\n" - "{\n" - " bvec3 isnan;\n" - " for (int i = 0; i < 3; i++)\n" - " {\n" - " isnan[i] = (x[i] > 0.0 || x[i] < 0.0) ? false : x[i] != 0.0;\n" - " }\n" - " return isnan;\n" - "}\n"); - emu->addEmulatedFunction( - EOpIsNan, float4, - "bvec4 isnan_emu(vec4 x)\n" - "{\n" - " bvec4 isnan;\n" - " for (int i = 0; i < 4; i++)\n" - " {\n" - " isnan[i] = (x[i] > 0.0 || x[i] < 0.0) ? false : x[i] != 0.0;\n" - " }\n" - " return isnan;\n" - "}\n"); -} - -void InitBuiltInAtanFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator *emu) -{ - const TType *float1 = TCache::getType(EbtFloat); - auto floatFuncId = emu->addEmulatedFunction( - EOpAtan, float1, float1, - "emu_precision float atan_emu(emu_precision float y, emu_precision " - "float x)\n" - "{\n" - " if (x > 0.0) return atan(y / x);\n" - " else if (x < 0.0 && y >= 0.0) return atan(y / x) + 3.14159265;\n" - " else if (x < 0.0 && y < 0.0) return atan(y / x) - 3.14159265;\n" - " else return 1.57079632 * sign(y);\n" - "}\n"); - for (int dim = 2; dim <= 4; ++dim) - { - const TType *floatVec = TCache::getType(EbtFloat, static_cast(dim)); - std::stringstream ss; - ss << "emu_precision vec" << dim << " atan_emu(emu_precision vec" << dim - << " y, emu_precision vec" << dim << " x)\n" - << "{\n" - " return vec" - << dim << "("; - for (int i = 0; i < dim; ++i) - { - ss << "atan_emu(y[" << i << "], x[" << i << "])"; - if (i < dim - 1) - { - ss << ", "; - } - } - ss << ");\n" - "}\n"; - emu->addEmulatedFunctionWithDependency(floatFuncId, EOpAtan, floatVec, floatVec, - ss.str().c_str()); - } -} - -// Emulate built-in functions missing from GLSL 1.30 and higher -void InitBuiltInFunctionEmulatorForGLSLMissingFunctions(BuiltInFunctionEmulator *emu, - sh::GLenum shaderType, - int targetGLSLVersion) -{ - // Emulate packUnorm2x16 and unpackUnorm2x16 (GLSL 4.10) - if (targetGLSLVersion < GLSL_VERSION_410) - { - const TType *float2 = TCache::getType(EbtFloat, 2); - const TType *uint1 = TCache::getType(EbtUInt); - - // clang-format off - emu->addEmulatedFunction(EOpPackUnorm2x16, float2, - "uint packUnorm2x16_emu(vec2 v)\n" - "{\n" - " int x = int(round(clamp(v.x, 0.0, 1.0) * 65535.0));\n" - " int y = int(round(clamp(v.y, 0.0, 1.0) * 65535.0));\n" - " return uint((y << 16) | (x & 0xFFFF));\n" - "}\n"); - - emu->addEmulatedFunction(EOpUnpackUnorm2x16, uint1, - "vec2 unpackUnorm2x16_emu(uint u)\n" - "{\n" - " float x = float(u & 0xFFFFu) / 65535.0;\n" - " float y = float(u >> 16) / 65535.0;\n" - " return vec2(x, y);\n" - "}\n"); - // clang-format on - } - - // Emulate packSnorm2x16, packHalf2x16, unpackSnorm2x16, and unpackHalf2x16 (GLSL 4.20) - // by using floatBitsToInt, floatBitsToUint, intBitsToFloat, and uintBitsToFloat (GLSL 3.30). - if (targetGLSLVersion >= GLSL_VERSION_330 && targetGLSLVersion < GLSL_VERSION_420) - { - const TType *float2 = TCache::getType(EbtFloat, 2); - const TType *uint1 = TCache::getType(EbtUInt); - - // clang-format off - emu->addEmulatedFunction(EOpPackSnorm2x16, float2, - "uint packSnorm2x16_emu(vec2 v)\n" - "{\n" - " #if defined(GL_ARB_shading_language_packing)\n" - " return packSnorm2x16(v);\n" - " #else\n" - " int x = int(round(clamp(v.x, -1.0, 1.0) * 32767.0));\n" - " int y = int(round(clamp(v.y, -1.0, 1.0) * 32767.0));\n" - " return uint((y << 16) | (x & 0xFFFF));\n" - " #endif\n" - "}\n"); - emu->addEmulatedFunction(EOpUnpackSnorm2x16, uint1, - "#if !defined(GL_ARB_shading_language_packing)\n" - " float fromSnorm(uint x)\n" - " {\n" - " int xi = (int(x) & 0x7FFF) - (int(x) & 0x8000);\n" - " return clamp(float(xi) / 32767.0, -1.0, 1.0);\n" - " }\n" - "#endif\n" - "\n" - "vec2 unpackSnorm2x16_emu(uint u)\n" - "{\n" - " #if defined(GL_ARB_shading_language_packing)\n" - " return unpackSnorm2x16(u);\n" - " #else\n" - " uint y = (u >> 16);\n" - " uint x = u;\n" - " return vec2(fromSnorm(x), fromSnorm(y));\n" - " #endif\n" - "}\n"); - // Functions uint f32tof16(float val) and float f16tof32(uint val) are - // based on the OpenGL redbook Appendix Session "Floating-Point Formats Used in OpenGL". - emu->addEmulatedFunction(EOpPackHalf2x16, float2, - "#if !defined(GL_ARB_shading_language_packing)\n" - " uint f32tof16(float val)\n" - " {\n" - " uint f32 = floatBitsToUint(val);\n" - " uint f16 = 0u;\n" - " uint sign = (f32 >> 16) & 0x8000u;\n" - " int exponent = int((f32 >> 23) & 0xFFu) - 127;\n" - " uint mantissa = f32 & 0x007FFFFFu;\n" - " if (exponent == 128)\n" - " {\n" - " // Infinity or NaN\n" - " // NaN bits that are masked out by 0x3FF get discarded.\n" - " // This can turn some NaNs to infinity, but this is allowed by the spec.\n" - " f16 = sign | (0x1Fu << 10);\n" - " f16 |= (mantissa & 0x3FFu);\n" - " }\n" - " else if (exponent > 15)\n" - " {\n" - " // Overflow - flush to Infinity\n" - " f16 = sign | (0x1Fu << 10);\n" - " }\n" - " else if (exponent > -15)\n" - " {\n" - " // Representable value\n" - " exponent += 15;\n" - " mantissa >>= 13;\n" - " f16 = sign | uint(exponent << 10) | mantissa;\n" - " }\n" - " else\n" - " {\n" - " f16 = sign;\n" - " }\n" - " return f16;\n" - " }\n" - "#endif\n" - "\n" - "uint packHalf2x16_emu(vec2 v)\n" - "{\n" - " #if defined(GL_ARB_shading_language_packing)\n" - " return packHalf2x16(v);\n" - " #else\n" - " uint x = f32tof16(v.x);\n" - " uint y = f32tof16(v.y);\n" - " return (y << 16) | x;\n" - " #endif\n" - "}\n"); - emu->addEmulatedFunction(EOpUnpackHalf2x16, uint1, - "#if !defined(GL_ARB_shading_language_packing)\n" - " float f16tof32(uint val)\n" - " {\n" - " uint sign = (val & 0x8000u) << 16;\n" - " int exponent = int((val & 0x7C00u) >> 10);\n" - " uint mantissa = val & 0x03FFu;\n" - " float f32 = 0.0;\n" - " if(exponent == 0)\n" - " {\n" - " if (mantissa != 0u)\n" - " {\n" - " const float scale = 1.0 / (1 << 24);\n" - " f32 = scale * mantissa;\n" - " }\n" - " }\n" - " else if (exponent == 31)\n" - " {\n" - " return uintBitsToFloat(sign | 0x7F800000u | mantissa);\n" - " }\n" - " else\n" - " {\n" - " exponent -= 15;\n" - " float scale;\n" - " if(exponent < 0)\n" - " {\n" - " // The negative unary operator is buggy on OSX.\n" - " // Work around this by using abs instead.\n" - " scale = 1.0 / (1 << abs(exponent));\n" - " }\n" - " else\n" - " {\n" - " scale = 1 << exponent;\n" - " }\n" - " float decimal = 1.0 + float(mantissa) / float(1 << 10);\n" - " f32 = scale * decimal;\n" - " }\n" - "\n" - " if (sign != 0u)\n" - " {\n" - " f32 = -f32;\n" - " }\n" - "\n" - " return f32;\n" - " }\n" - "#endif\n" - "\n" - "vec2 unpackHalf2x16_emu(uint u)\n" - "{\n" - " #if defined(GL_ARB_shading_language_packing)\n" - " return unpackHalf2x16(u);\n" - " #else\n" - " uint y = (u >> 16);\n" - " uint x = u & 0xFFFFu;\n" - " return vec2(f16tof32(x), f16tof32(y));\n" - " #endif\n" - "}\n"); - // clang-format on - } -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorGLSL.h b/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorGLSL.h deleted file mode 100644 index e1b4779bd5..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorGLSL.h +++ /dev/null @@ -1,40 +0,0 @@ -// -// Copyright (c) 2011 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATORGLSL_H_ -#define COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATORGLSL_H_ - -#include "GLSLANG/ShaderLang.h" - -namespace sh -{ -class BuiltInFunctionEmulator; - -// -// This works around bug in Intel Mac drivers. -// -void InitBuiltInAbsFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator *emu, - sh::GLenum shaderType); - -// -// This works around isnan() bug in Intel Mac drivers -// -void InitBuiltInIsnanFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator *emu, - int targetGLSLVersion); -// -// This works around atan(y, x) bug in NVIDIA drivers. -// -void InitBuiltInAtanFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator *emu); - -// -// This function is emulating built-in functions missing from GLSL 1.30 and higher. -// -void InitBuiltInFunctionEmulatorForGLSLMissingFunctions(BuiltInFunctionEmulator *emu, - sh::GLenum shaderType, - int targetGLSLVersion); -} // namespace sh - -#endif // COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATORGLSL_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorHLSL.cpp b/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorHLSL.cpp deleted file mode 100644 index e78d86d00a..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorHLSL.cpp +++ /dev/null @@ -1,184 +0,0 @@ -// -// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "angle_gl.h" -#include "compiler/translator/BuiltInFunctionEmulator.h" -#include "compiler/translator/BuiltInFunctionEmulatorHLSL.h" -#include "compiler/translator/SymbolTable.h" -#include "compiler/translator/VersionGLSL.h" - -namespace sh -{ - -// Defined in emulated_builtin_functions_hlsl_autogen.cpp. -const char *FindHLSLFunction(const FunctionId &functionID); - -void InitBuiltInIsnanFunctionEmulatorForHLSLWorkarounds(BuiltInFunctionEmulator *emu, - int targetGLSLVersion) -{ - if (targetGLSLVersion < GLSL_VERSION_130) - return; - - TType *float1 = new TType(EbtFloat); - TType *float2 = new TType(EbtFloat, 2); - TType *float3 = new TType(EbtFloat, 3); - TType *float4 = new TType(EbtFloat, 4); - - emu->addEmulatedFunction(EOpIsNan, float1, - "bool isnan_emu(float x)\n" - "{\n" - " return (x > 0.0 || x < 0.0) ? false : x != 0.0;\n" - "}\n" - "\n"); - - emu->addEmulatedFunction( - EOpIsNan, float2, - "bool2 isnan_emu(float2 x)\n" - "{\n" - " bool2 isnan;\n" - " for (int i = 0; i < 2; i++)\n" - " {\n" - " isnan[i] = (x[i] > 0.0 || x[i] < 0.0) ? false : x[i] != 0.0;\n" - " }\n" - " return isnan;\n" - "}\n"); - - emu->addEmulatedFunction( - EOpIsNan, float3, - "bool3 isnan_emu(float3 x)\n" - "{\n" - " bool3 isnan;\n" - " for (int i = 0; i < 3; i++)\n" - " {\n" - " isnan[i] = (x[i] > 0.0 || x[i] < 0.0) ? false : x[i] != 0.0;\n" - " }\n" - " return isnan;\n" - "}\n"); - - emu->addEmulatedFunction( - EOpIsNan, float4, - "bool4 isnan_emu(float4 x)\n" - "{\n" - " bool4 isnan;\n" - " for (int i = 0; i < 4; i++)\n" - " {\n" - " isnan[i] = (x[i] > 0.0 || x[i] < 0.0) ? false : x[i] != 0.0;\n" - " }\n" - " return isnan;\n" - "}\n"); -} - -void InitBuiltInFunctionEmulatorForHLSL(BuiltInFunctionEmulator *emu) -{ - TType *int1 = new TType(EbtInt); - TType *int2 = new TType(EbtInt, 2); - TType *int3 = new TType(EbtInt, 3); - TType *int4 = new TType(EbtInt, 4); - TType *uint1 = new TType(EbtUInt); - TType *uint2 = new TType(EbtUInt, 2); - TType *uint3 = new TType(EbtUInt, 3); - TType *uint4 = new TType(EbtUInt, 4); - - emu->addFunctionMap(FindHLSLFunction); - - // (a + b2^16) * (c + d2^16) = ac + (ad + bc) * 2^16 + bd * 2^32 - // Also note that below, a * d + ((a * c) >> 16) is guaranteed not to overflow, because: - // a <= 0xffff, d <= 0xffff, ((a * c) >> 16) <= 0xffff and 0xffff * 0xffff + 0xffff = 0xffff0000 - FunctionId umulExtendedUint1 = emu->addEmulatedFunction( - EOpUmulExtended, uint1, uint1, uint1, uint1, - "void umulExtended_emu(uint x, uint y, out uint msb, out uint lsb)\n" - "{\n" - " lsb = x * y;\n" - " uint a = (x & 0xffffu);\n" - " uint b = (x >> 16);\n" - " uint c = (y & 0xffffu);\n" - " uint d = (y >> 16);\n" - " uint ad = a * d + ((a * c) >> 16);\n" - " uint bc = b * c;\n" - " uint carry = uint(ad > (0xffffffffu - bc));\n" - " msb = ((ad + bc) >> 16) + (carry << 16) + b * d;\n" - "}\n"); - emu->addEmulatedFunctionWithDependency( - umulExtendedUint1, EOpUmulExtended, uint2, uint2, uint2, uint2, - "void umulExtended_emu(uint2 x, uint2 y, out uint2 msb, out uint2 lsb)\n" - "{\n" - " umulExtended_emu(x.x, y.x, msb.x, lsb.x);\n" - " umulExtended_emu(x.y, y.y, msb.y, lsb.y);\n" - "}\n"); - emu->addEmulatedFunctionWithDependency( - umulExtendedUint1, EOpUmulExtended, uint3, uint3, uint3, uint3, - "void umulExtended_emu(uint3 x, uint3 y, out uint3 msb, out uint3 lsb)\n" - "{\n" - " umulExtended_emu(x.x, y.x, msb.x, lsb.x);\n" - " umulExtended_emu(x.y, y.y, msb.y, lsb.y);\n" - " umulExtended_emu(x.z, y.z, msb.z, lsb.z);\n" - "}\n"); - emu->addEmulatedFunctionWithDependency( - umulExtendedUint1, EOpUmulExtended, uint4, uint4, uint4, uint4, - "void umulExtended_emu(uint4 x, uint4 y, out uint4 msb, out uint4 lsb)\n" - "{\n" - " umulExtended_emu(x.x, y.x, msb.x, lsb.x);\n" - " umulExtended_emu(x.y, y.y, msb.y, lsb.y);\n" - " umulExtended_emu(x.z, y.z, msb.z, lsb.z);\n" - " umulExtended_emu(x.w, y.w, msb.w, lsb.w);\n" - "}\n"); - - // The imul emulation does two's complement negation on the lsb and msb manually in case the - // result needs to be negative. - // TODO(oetuaho): Note that this code doesn't take one edge case into account, where x or y is - // -2^31. abs(-2^31) is undefined. - FunctionId imulExtendedInt1 = emu->addEmulatedFunctionWithDependency( - umulExtendedUint1, EOpImulExtended, int1, int1, int1, int1, - "void imulExtended_emu(int x, int y, out int msb, out int lsb)\n" - "{\n" - " uint unsignedMsb;\n" - " uint unsignedLsb;\n" - " bool negative = (x < 0) != (y < 0);\n" - " umulExtended_emu(uint(abs(x)), uint(abs(y)), unsignedMsb, unsignedLsb);\n" - " lsb = asint(unsignedLsb);\n" - " msb = asint(unsignedMsb);\n" - " if (negative)\n" - " {\n" - " lsb = ~lsb;\n" - " msb = ~msb;\n" - " if (lsb == 0xffffffff)\n" - " {\n" - " lsb = 0;\n" - " msb += 1;\n" - " }\n" - " else\n" - " {\n" - " lsb += 1;\n" - " }\n" - " }\n" - "}\n"); - emu->addEmulatedFunctionWithDependency( - imulExtendedInt1, EOpImulExtended, int2, int2, int2, int2, - "void imulExtended_emu(int2 x, int2 y, out int2 msb, out int2 lsb)\n" - "{\n" - " imulExtended_emu(x.x, y.x, msb.x, lsb.x);\n" - " imulExtended_emu(x.y, y.y, msb.y, lsb.y);\n" - "}\n"); - emu->addEmulatedFunctionWithDependency( - imulExtendedInt1, EOpImulExtended, int3, int3, int3, int3, - "void imulExtended_emu(int3 x, int3 y, out int3 msb, out int3 lsb)\n" - "{\n" - " imulExtended_emu(x.x, y.x, msb.x, lsb.x);\n" - " imulExtended_emu(x.y, y.y, msb.y, lsb.y);\n" - " imulExtended_emu(x.z, y.z, msb.z, lsb.z);\n" - "}\n"); - emu->addEmulatedFunctionWithDependency( - imulExtendedInt1, EOpImulExtended, int4, int4, int4, int4, - "void imulExtended_emu(int4 x, int4 y, out int4 msb, out int4 lsb)\n" - "{\n" - " imulExtended_emu(x.x, y.x, msb.x, lsb.x);\n" - " imulExtended_emu(x.y, y.y, msb.y, lsb.y);\n" - " imulExtended_emu(x.z, y.z, msb.z, lsb.z);\n" - " imulExtended_emu(x.w, y.w, msb.w, lsb.w);\n" - "}\n"); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorHLSL.h b/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorHLSL.h deleted file mode 100644 index 48da73f58e..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorHLSL.h +++ /dev/null @@ -1,27 +0,0 @@ -// -// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATORHLSL_H_ -#define COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATORHLSL_H_ - -#include "GLSLANG/ShaderLang.h" - -namespace sh -{ - -class BuiltInFunctionEmulator; - -void InitBuiltInFunctionEmulatorForHLSL(BuiltInFunctionEmulator *emu); - -// -// This works around isnan() bug on some Intel drivers. -// -void InitBuiltInIsnanFunctionEmulatorForHLSLWorkarounds(BuiltInFunctionEmulator *emu, - int targetGLSLVersion); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATORHLSL_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/Cache.cpp b/src/3rdparty/angle/src/compiler/translator/Cache.cpp deleted file mode 100644 index 417e82403a..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/Cache.cpp +++ /dev/null @@ -1,99 +0,0 @@ -// -// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Cache.cpp: Implements a cache for various commonly created objects. - -#include - -#include "common/angleutils.h" -#include "common/debug.h" -#include "compiler/translator/Cache.h" - -namespace sh -{ - -namespace -{ - -class TScopedAllocator : angle::NonCopyable -{ - public: - TScopedAllocator(TPoolAllocator *allocator) : mPreviousAllocator(GetGlobalPoolAllocator()) - { - SetGlobalPoolAllocator(allocator); - } - ~TScopedAllocator() { SetGlobalPoolAllocator(mPreviousAllocator); } - - private: - TPoolAllocator *mPreviousAllocator; -}; - -} // namespace - -TCache::TypeKey::TypeKey(TBasicType basicType, - TPrecision precision, - TQualifier qualifier, - unsigned char primarySize, - unsigned char secondarySize) -{ - static_assert(sizeof(components) <= sizeof(value), "TypeKey::value is too small"); - - const size_t MaxEnumValue = std::numeric_limits::max(); - - // TODO: change to static_assert() once we deprecate MSVC 2013 support - ASSERT(MaxEnumValue >= EbtLast && MaxEnumValue >= EbpLast && MaxEnumValue >= EvqLast && - "TypeKey::EnumComponentType is too small"); - - value = 0; - components.basicType = static_cast(basicType); - components.precision = static_cast(precision); - components.qualifier = static_cast(qualifier); - components.primarySize = primarySize; - components.secondarySize = secondarySize; -} - -TCache *TCache::sCache = nullptr; - -TCache::TCache() -{ -} - -void TCache::initialize() -{ - if (sCache == nullptr) - { - sCache = new TCache(); - } -} - -void TCache::destroy() -{ - SafeDelete(sCache); -} - -const TType *TCache::getType(TBasicType basicType, - TPrecision precision, - TQualifier qualifier, - unsigned char primarySize, - unsigned char secondarySize) -{ - TypeKey key(basicType, precision, qualifier, primarySize, secondarySize); - auto it = sCache->mTypes.find(key); - if (it != sCache->mTypes.end()) - { - return it->second; - } - - TScopedAllocator scopedAllocator(&sCache->mAllocator); - - TType *type = new TType(basicType, precision, qualifier, primarySize, secondarySize); - type->realize(); - sCache->mTypes.insert(std::make_pair(key, type)); - - return type; -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/Cache.h b/src/3rdparty/angle/src/compiler/translator/Cache.h deleted file mode 100644 index a182b07f51..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/Cache.h +++ /dev/null @@ -1,84 +0,0 @@ -// -// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Cache.h: Implements a cache for various commonly created objects. - -#ifndef COMPILER_TRANSLATOR_CACHE_H_ -#define COMPILER_TRANSLATOR_CACHE_H_ - -#include -#include -#include - -#include "compiler/translator/Types.h" -#include "compiler/translator/PoolAlloc.h" - -namespace sh -{ - -class TCache -{ - public: - static void initialize(); - static void destroy(); - - static const TType *getType(TBasicType basicType, TPrecision precision) - { - return getType(basicType, precision, EvqTemporary, 1, 1); - } - static const TType *getType(TBasicType basicType, - unsigned char primarySize = 1, - unsigned char secondarySize = 1) - { - return getType(basicType, EbpUndefined, EvqGlobal, primarySize, secondarySize); - } - static const TType *getType(TBasicType basicType, - TQualifier qualifier, - unsigned char primarySize = 1, - unsigned char secondarySize = 1) - { - return getType(basicType, EbpUndefined, qualifier, primarySize, secondarySize); - } - static const TType *getType(TBasicType basicType, - TPrecision precision, - TQualifier qualifier, - unsigned char primarySize, - unsigned char secondarySize); - - private: - TCache(); - - union TypeKey { - TypeKey(TBasicType basicType, - TPrecision precision, - TQualifier qualifier, - unsigned char primarySize, - unsigned char secondarySize); - - typedef uint8_t EnumComponentType; - struct - { - EnumComponentType basicType; - EnumComponentType precision; - EnumComponentType qualifier; - unsigned char primarySize; - unsigned char secondarySize; - } components; - uint64_t value; - - bool operator<(const TypeKey &other) const { return value < other.value; } - }; - typedef std::map TypeMap; - - TypeMap mTypes; - TPoolAllocator mAllocator; - - static TCache *sCache; -}; - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_CACHE_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/CallDAG.cpp b/src/3rdparty/angle/src/compiler/translator/CallDAG.cpp deleted file mode 100644 index 5f54e80898..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/CallDAG.cpp +++ /dev/null @@ -1,346 +0,0 @@ -// -// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// CallDAG.h: Implements a call graph DAG of functions to be re-used accross -// analyses, allows to efficiently traverse the functions in topological -// order. - -#include "compiler/translator/CallDAG.h" - -#include "compiler/translator/Diagnostics.h" -#include "compiler/translator/IntermTraverse.h" -#include "compiler/translator/SymbolTable.h" - -namespace sh -{ - -// The CallDAGCreator does all the processing required to create the CallDAG -// structure so that the latter contains only the necessary variables. -class CallDAG::CallDAGCreator : public TIntermTraverser -{ - public: - CallDAGCreator(TDiagnostics *diagnostics) - : TIntermTraverser(true, false, true), - mDiagnostics(diagnostics), - mCurrentFunction(nullptr), - mCurrentIndex(0) - { - } - - InitResult assignIndices() - { - int skipped = 0; - for (auto &it : mFunctions) - { - // Skip unimplemented functions - if (it.second.node) - { - InitResult result = assignIndicesInternal(&it.second); - if (result != INITDAG_SUCCESS) - { - return result; - } - } - else - { - skipped++; - } - } - - ASSERT(mFunctions.size() == mCurrentIndex + skipped); - return INITDAG_SUCCESS; - } - - void fillDataStructures(std::vector *records, std::map *idToIndex) - { - ASSERT(records->empty()); - ASSERT(idToIndex->empty()); - - records->resize(mCurrentIndex); - - for (auto &it : mFunctions) - { - CreatorFunctionData &data = it.second; - // Skip unimplemented functions - if (!data.node) - { - continue; - } - ASSERT(data.index < records->size()); - Record &record = (*records)[data.index]; - - record.name = data.name.data(); - record.node = data.node; - - record.callees.reserve(data.callees.size()); - for (auto &callee : data.callees) - { - record.callees.push_back(static_cast(callee->index)); - } - - (*idToIndex)[data.node->getFunctionSymbolInfo()->getId().get()] = - static_cast(data.index); - } - } - - private: - struct CreatorFunctionData - { - CreatorFunctionData() : node(nullptr), index(0), indexAssigned(false), visiting(false) {} - - std::set callees; - TIntermFunctionDefinition *node; - TString name; - size_t index; - bool indexAssigned; - bool visiting; - }; - - bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override - { - // Create the record if need be and remember the node. - if (visit == PreVisit) - { - auto it = mFunctions.find(node->getFunctionSymbolInfo()->getId().get()); - - if (it == mFunctions.end()) - { - mCurrentFunction = &mFunctions[node->getFunctionSymbolInfo()->getId().get()]; - mCurrentFunction->name = node->getFunctionSymbolInfo()->getName(); - } - else - { - mCurrentFunction = &it->second; - ASSERT(mCurrentFunction->name == node->getFunctionSymbolInfo()->getName()); - } - - mCurrentFunction->node = node; - } - else if (visit == PostVisit) - { - mCurrentFunction = nullptr; - } - return true; - } - - bool visitFunctionPrototype(Visit visit, TIntermFunctionPrototype *node) override - { - ASSERT(visit == PreVisit); - if (mCurrentFunction != nullptr) - { - return false; - } - - // Function declaration, create an empty record. - auto &record = mFunctions[node->getFunctionSymbolInfo()->getId().get()]; - record.name = node->getFunctionSymbolInfo()->getName(); - - // No need to traverse the parameters. - return false; - } - - // Aggregates the AST node for each function as well as the name of the functions called by it - bool visitAggregate(Visit visit, TIntermAggregate *node) override - { - if (visit == PreVisit && node->getOp() == EOpCallFunctionInAST) - { - // Function call, add the callees - auto it = mFunctions.find(node->getFunctionSymbolInfo()->getId().get()); - ASSERT(it != mFunctions.end()); - - // We might be traversing the initializer of a global variable. Even though function - // calls in global scope are forbidden by the parser, some subsequent AST - // transformations can add them to emulate particular features. - if (mCurrentFunction) - { - mCurrentFunction->callees.insert(&it->second); - } - } - return true; - } - - // Recursively assigns indices to a sub DAG - InitResult assignIndicesInternal(CreatorFunctionData *root) - { - // Iterative implementation of the index assignment algorithm. A recursive version - // would be prettier but since the CallDAG creation runs before the limiting of the - // call depth, we might get stack overflows (computation of the call depth uses the - // CallDAG). - - ASSERT(root); - - if (root->indexAssigned) - { - return INITDAG_SUCCESS; - } - - // If we didn't have to detect recursion, functionsToProcess could be a simple queue - // in which we add the function being processed's callees. However in order to detect - // recursion we need to know which functions we are currently visiting. For that reason - // functionsToProcess will look like a concatenation of segments of the form - // [F visiting = true, subset of F callees with visiting = false] and the following - // segment (if any) will be start with a callee of F. - // This way we can remember when we started visiting a function, to put visiting back - // to false. - TVector functionsToProcess; - functionsToProcess.push_back(root); - - InitResult result = INITDAG_SUCCESS; - - std::stringstream errorStream; - - while (!functionsToProcess.empty()) - { - CreatorFunctionData *function = functionsToProcess.back(); - - if (function->visiting) - { - function->visiting = false; - function->index = mCurrentIndex++; - function->indexAssigned = true; - - functionsToProcess.pop_back(); - continue; - } - - if (!function->node) - { - errorStream << "Undefined function '" << function->name - << ")' used in the following call chain:"; - result = INITDAG_UNDEFINED; - break; - } - - if (function->indexAssigned) - { - functionsToProcess.pop_back(); - continue; - } - - function->visiting = true; - - for (auto callee : function->callees) - { - functionsToProcess.push_back(callee); - - // Check if the callee is already being visited after pushing it so that it appears - // in the chain printed in the info log. - if (callee->visiting) - { - errorStream << "Recursive function call in the following call chain:"; - result = INITDAG_RECURSION; - break; - } - } - - if (result != INITDAG_SUCCESS) - { - break; - } - } - - // The call chain is made of the function we were visiting when the error was detected. - if (result != INITDAG_SUCCESS) - { - bool first = true; - for (auto function : functionsToProcess) - { - if (function->visiting) - { - if (!first) - { - errorStream << " -> "; - } - errorStream << function->name << ")"; - first = false; - } - } - if (mDiagnostics) - { - std::string errorStr = errorStream.str(); - mDiagnostics->globalError(errorStr.c_str()); - } - } - - return result; - } - - TDiagnostics *mDiagnostics; - - std::map mFunctions; - CreatorFunctionData *mCurrentFunction; - size_t mCurrentIndex; -}; - -// CallDAG - -CallDAG::CallDAG() -{ -} - -CallDAG::~CallDAG() -{ -} - -const size_t CallDAG::InvalidIndex = std::numeric_limits::max(); - -size_t CallDAG::findIndex(const TFunctionSymbolInfo *functionInfo) const -{ - auto it = mFunctionIdToIndex.find(functionInfo->getId().get()); - - if (it == mFunctionIdToIndex.end()) - { - return InvalidIndex; - } - else - { - return it->second; - } -} - -const CallDAG::Record &CallDAG::getRecordFromIndex(size_t index) const -{ - ASSERT(index != InvalidIndex && index < mRecords.size()); - return mRecords[index]; -} - -const CallDAG::Record &CallDAG::getRecord(const TIntermAggregate *function) const -{ - size_t index = findIndex(function->getFunctionSymbolInfo()); - ASSERT(index != InvalidIndex && index < mRecords.size()); - return mRecords[index]; -} - -size_t CallDAG::size() const -{ - return mRecords.size(); -} - -void CallDAG::clear() -{ - mRecords.clear(); - mFunctionIdToIndex.clear(); -} - -CallDAG::InitResult CallDAG::init(TIntermNode *root, TDiagnostics *diagnostics) -{ - CallDAGCreator creator(diagnostics); - - // Creates the mapping of functions to callees - root->traverse(&creator); - - // Does the topological sort and detects recursions - InitResult result = creator.assignIndices(); - if (result != INITDAG_SUCCESS) - { - return result; - } - - creator.fillDataStructures(&mRecords, &mFunctionIdToIndex); - return INITDAG_SUCCESS; -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/CallDAG.h b/src/3rdparty/angle/src/compiler/translator/CallDAG.h deleted file mode 100644 index 155081c9a2..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/CallDAG.h +++ /dev/null @@ -1,79 +0,0 @@ -// -// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// CallDAG.h: Defines a call graph DAG of functions to be re-used accross -// analyses, allows to efficiently traverse the functions in topological -// order. - -#ifndef COMPILER_TRANSLATOR_CALLDAG_H_ -#define COMPILER_TRANSLATOR_CALLDAG_H_ - -#include - -#include "compiler/translator/IntermNode.h" - -namespace sh -{ - -// The translator needs to analyze the the graph of the function calls -// to run checks and analyses; since in GLSL recursion is not allowed -// that graph is a DAG. -// This class is used to precompute that function call DAG so that it -// can be reused by multiple analyses. -// -// It stores a vector of function records, with one record per function. -// Records are accessed by index but a function symbol id can be converted -// to the index of the corresponding record. The records mostly contain the -// AST node of the function and the indices of the function's callees. -// -// In addition, records are in reverse topological order: a function F being -// called by a function G will have index index(F) < index(G), that way -// depth-first analysis becomes analysis in the order of indices. - -class CallDAG : angle::NonCopyable -{ - public: - CallDAG(); - ~CallDAG(); - - struct Record - { - std::string name; - TIntermFunctionDefinition *node; - std::vector callees; - }; - - enum InitResult - { - INITDAG_SUCCESS, - INITDAG_RECURSION, - INITDAG_UNDEFINED, - }; - - // Returns INITDAG_SUCCESS if it was able to create the DAG, otherwise prints - // the initialization error in diagnostics, if present. - InitResult init(TIntermNode *root, TDiagnostics *diagnostics); - - // Returns InvalidIndex if the function wasn't found - size_t findIndex(const TFunctionSymbolInfo *functionInfo) const; - - const Record &getRecordFromIndex(size_t index) const; - const Record &getRecord(const TIntermAggregate *function) const; - size_t size() const; - void clear(); - - const static size_t InvalidIndex; - - private: - std::vector mRecords; - std::map mFunctionIdToIndex; - - class CallDAGCreator; -}; - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_CALLDAG_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/ClampPointSize.cpp b/src/3rdparty/angle/src/compiler/translator/ClampPointSize.cpp deleted file mode 100644 index 8598a137f5..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/ClampPointSize.cpp +++ /dev/null @@ -1,47 +0,0 @@ -// -// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// ClampPointSize.cpp: Limit the value that is written to gl_PointSize. -// - -#include "compiler/translator/ClampPointSize.h" - -#include "compiler/translator/FindSymbolNode.h" -#include "compiler/translator/IntermNode_util.h" -#include "compiler/translator/RunAtTheEndOfShader.h" -#include "compiler/translator/SymbolTable.h" - -namespace sh -{ - -void ClampPointSize(TIntermBlock *root, float maxPointSize, TSymbolTable *symbolTable) -{ - // Only clamp gl_PointSize if it's used in the shader. - if (!FindSymbolNode(root, TString("gl_PointSize"), EbtFloat)) - { - return; - } - - TIntermSymbol *pointSizeNode = ReferenceBuiltInVariable("gl_PointSize", *symbolTable, 100); - - TConstantUnion *maxPointSizeConstant = new TConstantUnion(); - maxPointSizeConstant->setFConst(maxPointSize); - TIntermConstantUnion *maxPointSizeNode = - new TIntermConstantUnion(maxPointSizeConstant, TType(EbtFloat, EbpHigh, EvqConst)); - - // min(gl_PointSize, maxPointSize) - TIntermSequence *minArguments = new TIntermSequence(); - minArguments->push_back(pointSizeNode->deepCopy()); - minArguments->push_back(maxPointSizeNode); - TIntermTyped *clampedPointSize = - CreateBuiltInFunctionCallNode("min", minArguments, *symbolTable, 100); - - // gl_PointSize = min(gl_PointSize, maxPointSize) - TIntermBinary *assignPointSize = new TIntermBinary(EOpAssign, pointSizeNode, clampedPointSize); - - RunAtTheEndOfShader(root, assignPointSize, symbolTable); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/ClampPointSize.h b/src/3rdparty/angle/src/compiler/translator/ClampPointSize.h deleted file mode 100644 index 0c71ae6b0d..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/ClampPointSize.h +++ /dev/null @@ -1,22 +0,0 @@ -// -// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// ClampPointSize.h: Limit the value that is written to gl_PointSize. -// - -#ifndef COMPILER_TRANSLATOR_CLAMPPOINTSIZE_H_ -#define COMPILER_TRANSLATOR_CLAMPPOINTSIZE_H_ - -namespace sh -{ - -class TIntermBlock; -class TSymbolTable; - -void ClampPointSize(TIntermBlock *root, float maxPointSize, TSymbolTable *symbolTable); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_CLAMPPOINTSIZE_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/CodeGen.cpp b/src/3rdparty/angle/src/compiler/translator/CodeGen.cpp deleted file mode 100644 index 3e25cc2339..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/CodeGen.cpp +++ /dev/null @@ -1,75 +0,0 @@ -// -// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifdef ANGLE_ENABLE_ESSL -#include "compiler/translator/TranslatorESSL.h" -#endif // ANGLE_ENABLE_ESSL - -#ifdef ANGLE_ENABLE_GLSL -#include "compiler/translator/TranslatorGLSL.h" -#endif // ANGLE_ENABLE_GLSL - -#ifdef ANGLE_ENABLE_HLSL -#include "compiler/translator/TranslatorHLSL.h" -#endif // ANGLE_ENABLE_HLSL - -#ifdef ANGLE_ENABLE_VULKAN -#include "compiler/translator/TranslatorVulkan.h" -#endif // ANGLE_ENABLE_VULKAN - -#include "compiler/translator/util.h" - -namespace sh -{ - -// -// This function must be provided to create the actual -// compile object used by higher level code. It returns -// a subclass of TCompiler. -// -TCompiler *ConstructCompiler(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output) -{ -#ifdef ANGLE_ENABLE_ESSL - if (IsOutputESSL(output)) - { - return new TranslatorESSL(type, spec); - } -#endif // ANGLE_ENABLE_ESSL - -#ifdef ANGLE_ENABLE_GLSL - if (IsOutputGLSL(output)) - { - return new TranslatorGLSL(type, spec, output); - } -#endif // ANGLE_ENABLE_GLSL - -#ifdef ANGLE_ENABLE_HLSL - if (IsOutputHLSL(output)) - { - return new TranslatorHLSL(type, spec, output); - } -#endif // ANGLE_ENABLE_HLSL - -#ifdef ANGLE_ENABLE_VULKAN - if (IsOutputVulkan(output)) - { - return new TranslatorVulkan(type, spec); - } -#endif // ANGLE_ENABLE_VULKAN - - // Unsupported compiler or unknown format. Return nullptr per the sh::ConstructCompiler API. - return nullptr; -} - -// -// Delete the compiler made by ConstructCompiler -// -void DeleteCompiler(TCompiler *compiler) -{ - SafeDelete(compiler); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/CollectVariables.cpp b/src/3rdparty/angle/src/compiler/translator/CollectVariables.cpp deleted file mode 100644 index bd8cbc971a..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/CollectVariables.cpp +++ /dev/null @@ -1,869 +0,0 @@ -// -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// CollectVariables.cpp: Collect lists of shader interface variables based on the AST. - -#include "compiler/translator/CollectVariables.h" - -#include "angle_gl.h" -#include "common/utilities.h" -#include "compiler/translator/HashNames.h" -#include "compiler/translator/IntermTraverse.h" -#include "compiler/translator/SymbolTable.h" -#include "compiler/translator/util.h" - -namespace sh -{ - -namespace -{ - -BlockLayoutType GetBlockLayoutType(TLayoutBlockStorage blockStorage) -{ - switch (blockStorage) - { - case EbsPacked: - return BLOCKLAYOUT_PACKED; - case EbsShared: - return BLOCKLAYOUT_SHARED; - case EbsStd140: - return BLOCKLAYOUT_STD140; - case EbsStd430: - return BLOCKLAYOUT_STD430; - default: - UNREACHABLE(); - return BLOCKLAYOUT_SHARED; - } -} - -// TODO(jiawei.shao@intel.com): implement GL_OES_shader_io_blocks. -BlockType GetBlockType(TQualifier qualifier) -{ - switch (qualifier) - { - case EvqUniform: - return BlockType::BLOCK_UNIFORM; - case EvqBuffer: - return BlockType::BLOCK_BUFFER; - case EvqPerVertexIn: - return BlockType::BLOCK_IN; - default: - UNREACHABLE(); - return BlockType::BLOCK_UNIFORM; - } -} - -template -VarT *FindVariable(const TString &name, std::vector *infoList) -{ - // TODO(zmo): optimize this function. - for (size_t ii = 0; ii < infoList->size(); ++ii) - { - if ((*infoList)[ii].name.c_str() == name) - return &((*infoList)[ii]); - } - - return nullptr; -} - -// Note that this shouldn't be called for interface blocks - static use information is collected for -// individual fields in case of interface blocks. -void MarkStaticallyUsed(ShaderVariable *variable) -{ - if (!variable->staticUse) - { - if (variable->isStruct()) - { - // Conservatively assume all fields are statically used as well. - for (auto &field : variable->fields) - { - MarkStaticallyUsed(&field); - } - } - variable->staticUse = true; - } -} - -ShaderVariable *FindVariableInInterfaceBlock(const TString &name, - const TInterfaceBlock *interfaceBlock, - std::vector *infoList) -{ - ASSERT(interfaceBlock); - InterfaceBlock *namedBlock = FindVariable(interfaceBlock->name(), infoList); - ASSERT(namedBlock); - - // Set static use on the parent interface block here - namedBlock->staticUse = true; - return FindVariable(name, &namedBlock->fields); -} - -// Traverses the intermediate tree to collect all attributes, uniforms, varyings, fragment outputs, -// and interface blocks. -class CollectVariablesTraverser : public TIntermTraverser -{ - public: - CollectVariablesTraverser(std::vector *attribs, - std::vector *outputVariables, - std::vector *uniforms, - std::vector *inputVaryings, - std::vector *outputVaryings, - std::vector *uniformBlocks, - std::vector *shaderStorageBlocks, - std::vector *inBlocks, - ShHashFunction64 hashFunction, - TSymbolTable *symbolTable, - int shaderVersion, - GLenum shaderType, - const TExtensionBehavior &extensionBehavior); - - void visitSymbol(TIntermSymbol *symbol) override; - bool visitDeclaration(Visit, TIntermDeclaration *node) override; - bool visitBinary(Visit visit, TIntermBinary *binaryNode) override; - - private: - std::string getMappedName(const TName &name) const; - - void setCommonVariableProperties(const TType &type, - const TName &name, - ShaderVariable *variableOut) const; - - Attribute recordAttribute(const TIntermSymbol &variable) const; - OutputVariable recordOutputVariable(const TIntermSymbol &variable) const; - Varying recordVarying(const TIntermSymbol &variable) const; - void recordInterfaceBlock(const TType &interfaceBlockType, - InterfaceBlock *interfaceBlock) const; - Uniform recordUniform(const TIntermSymbol &variable) const; - - void setBuiltInInfoFromSymbolTable(const char *name, ShaderVariable *info); - - void recordBuiltInVaryingUsed(const char *name, - bool *addedFlag, - std::vector *varyings); - void recordBuiltInFragmentOutputUsed(const char *name, bool *addedFlag); - void recordBuiltInAttributeUsed(const char *name, bool *addedFlag); - InterfaceBlock *recordGLInUsed(const TType &glInType); - InterfaceBlock *findNamedInterfaceBlock(const TString &name) const; - - std::vector *mAttribs; - std::vector *mOutputVariables; - std::vector *mUniforms; - std::vector *mInputVaryings; - std::vector *mOutputVaryings; - std::vector *mUniformBlocks; - std::vector *mShaderStorageBlocks; - std::vector *mInBlocks; - - std::map mInterfaceBlockFields; - - // Shader uniforms - bool mDepthRangeAdded; - - // Vertex Shader builtins - bool mInstanceIDAdded; - bool mVertexIDAdded; - bool mPointSizeAdded; - - // Vertex Shader and Geometry Shader builtins - bool mPositionAdded; - - // Fragment Shader builtins - bool mPointCoordAdded; - bool mFrontFacingAdded; - bool mFragCoordAdded; - bool mLastFragDataAdded; - bool mFragColorAdded; - bool mFragDataAdded; - bool mFragDepthEXTAdded; - bool mFragDepthAdded; - bool mSecondaryFragColorEXTAdded; - bool mSecondaryFragDataEXTAdded; - - // Geometry Shader builtins - bool mPerVertexInAdded; - bool mPrimitiveIDInAdded; - bool mInvocationIDAdded; - - // Geometry Shader and Fragment Shader builtins - bool mPrimitiveIDAdded; - bool mLayerAdded; - - ShHashFunction64 mHashFunction; - - int mShaderVersion; - GLenum mShaderType; - const TExtensionBehavior &mExtensionBehavior; -}; - -CollectVariablesTraverser::CollectVariablesTraverser( - std::vector *attribs, - std::vector *outputVariables, - std::vector *uniforms, - std::vector *inputVaryings, - std::vector *outputVaryings, - std::vector *uniformBlocks, - std::vector *shaderStorageBlocks, - std::vector *inBlocks, - ShHashFunction64 hashFunction, - TSymbolTable *symbolTable, - int shaderVersion, - GLenum shaderType, - const TExtensionBehavior &extensionBehavior) - : TIntermTraverser(true, false, false, symbolTable), - mAttribs(attribs), - mOutputVariables(outputVariables), - mUniforms(uniforms), - mInputVaryings(inputVaryings), - mOutputVaryings(outputVaryings), - mUniformBlocks(uniformBlocks), - mShaderStorageBlocks(shaderStorageBlocks), - mInBlocks(inBlocks), - mDepthRangeAdded(false), - mInstanceIDAdded(false), - mVertexIDAdded(false), - mPointSizeAdded(false), - mPositionAdded(false), - mPointCoordAdded(false), - mFrontFacingAdded(false), - mFragCoordAdded(false), - mLastFragDataAdded(false), - mFragColorAdded(false), - mFragDataAdded(false), - mFragDepthEXTAdded(false), - mFragDepthAdded(false), - mSecondaryFragColorEXTAdded(false), - mSecondaryFragDataEXTAdded(false), - mPerVertexInAdded(false), - mPrimitiveIDInAdded(false), - mInvocationIDAdded(false), - mPrimitiveIDAdded(false), - mLayerAdded(false), - mHashFunction(hashFunction), - mShaderVersion(shaderVersion), - mShaderType(shaderType), - mExtensionBehavior(extensionBehavior) -{ -} - -std::string CollectVariablesTraverser::getMappedName(const TName &name) const -{ - return HashName(name, mHashFunction, nullptr).c_str(); -} - -void CollectVariablesTraverser::setBuiltInInfoFromSymbolTable(const char *name, - ShaderVariable *info) -{ - TVariable *symbolTableVar = - reinterpret_cast(mSymbolTable->findBuiltIn(name, mShaderVersion)); - ASSERT(symbolTableVar); - const TType &type = symbolTableVar->getType(); - - info->name = name; - info->mappedName = name; - info->type = GLVariableType(type); - info->precision = GLVariablePrecision(type); - if (auto *arraySizes = type.getArraySizes()) - { - info->arraySizes.assign(arraySizes->begin(), arraySizes->end()); - } -} - -void CollectVariablesTraverser::recordBuiltInVaryingUsed(const char *name, - bool *addedFlag, - std::vector *varyings) -{ - ASSERT(varyings); - if (!(*addedFlag)) - { - Varying info; - setBuiltInInfoFromSymbolTable(name, &info); - info.staticUse = true; - info.isInvariant = mSymbolTable->isVaryingInvariant(name); - varyings->push_back(info); - (*addedFlag) = true; - } -} - -void CollectVariablesTraverser::recordBuiltInFragmentOutputUsed(const char *name, bool *addedFlag) -{ - if (!(*addedFlag)) - { - OutputVariable info; - setBuiltInInfoFromSymbolTable(name, &info); - info.staticUse = true; - mOutputVariables->push_back(info); - (*addedFlag) = true; - } -} - -void CollectVariablesTraverser::recordBuiltInAttributeUsed(const char *name, bool *addedFlag) -{ - if (!(*addedFlag)) - { - Attribute info; - setBuiltInInfoFromSymbolTable(name, &info); - info.staticUse = true; - info.location = -1; - mAttribs->push_back(info); - (*addedFlag) = true; - } -} - -InterfaceBlock *CollectVariablesTraverser::recordGLInUsed(const TType &glInType) -{ - if (!mPerVertexInAdded) - { - ASSERT(glInType.getQualifier() == EvqPerVertexIn); - InterfaceBlock info; - recordInterfaceBlock(glInType, &info); - info.staticUse = true; - - mPerVertexInAdded = true; - mInBlocks->push_back(info); - return &mInBlocks->back(); - } - else - { - return FindVariable("gl_PerVertex", mInBlocks); - } -} - -// We want to check whether a uniform/varying is statically used -// because we only count the used ones in packing computing. -// Also, gl_FragCoord, gl_PointCoord, and gl_FrontFacing count -// toward varying counting if they are statically used in a fragment -// shader. -void CollectVariablesTraverser::visitSymbol(TIntermSymbol *symbol) -{ - ASSERT(symbol != nullptr); - - if (symbol->getName().isInternal()) - { - // Internal variables are not collected. - return; - } - - ShaderVariable *var = nullptr; - const TString &symbolName = symbol->getName().getString(); - - if (IsVaryingIn(symbol->getQualifier())) - { - var = FindVariable(symbolName, mInputVaryings); - } - else if (IsVaryingOut(symbol->getQualifier())) - { - var = FindVariable(symbolName, mOutputVaryings); - } - else if (symbol->getType().getBasicType() == EbtInterfaceBlock) - { - UNREACHABLE(); - } - else if (symbolName == "gl_DepthRange") - { - ASSERT(symbol->getQualifier() == EvqUniform); - - if (!mDepthRangeAdded) - { - Uniform info; - const char kName[] = "gl_DepthRange"; - info.name = kName; - info.mappedName = kName; - info.type = GL_NONE; - info.precision = GL_NONE; - info.staticUse = true; - - ShaderVariable nearInfo(GL_FLOAT); - const char kNearName[] = "near"; - nearInfo.name = kNearName; - nearInfo.mappedName = kNearName; - nearInfo.precision = GL_HIGH_FLOAT; - nearInfo.staticUse = true; - - ShaderVariable farInfo(GL_FLOAT); - const char kFarName[] = "far"; - farInfo.name = kFarName; - farInfo.mappedName = kFarName; - farInfo.precision = GL_HIGH_FLOAT; - farInfo.staticUse = true; - - ShaderVariable diffInfo(GL_FLOAT); - const char kDiffName[] = "diff"; - diffInfo.name = kDiffName; - diffInfo.mappedName = kDiffName; - diffInfo.precision = GL_HIGH_FLOAT; - diffInfo.staticUse = true; - - info.fields.push_back(nearInfo); - info.fields.push_back(farInfo); - info.fields.push_back(diffInfo); - - mUniforms->push_back(info); - mDepthRangeAdded = true; - } - } - else - { - switch (symbol->getQualifier()) - { - case EvqAttribute: - case EvqVertexIn: - var = FindVariable(symbolName, mAttribs); - break; - case EvqFragmentOut: - var = FindVariable(symbolName, mOutputVariables); - break; - case EvqUniform: - { - const TInterfaceBlock *interfaceBlock = symbol->getType().getInterfaceBlock(); - if (interfaceBlock) - { - var = FindVariableInInterfaceBlock(symbolName, interfaceBlock, mUniformBlocks); - } - else - { - var = FindVariable(symbolName, mUniforms); - } - - // It's an internal error to reference an undefined user uniform - ASSERT(symbolName.compare(0, 3, "gl_") != 0 || var); - } - break; - case EvqBuffer: - { - const TInterfaceBlock *interfaceBlock = symbol->getType().getInterfaceBlock(); - var = - FindVariableInInterfaceBlock(symbolName, interfaceBlock, mShaderStorageBlocks); - } - break; - case EvqFragCoord: - recordBuiltInVaryingUsed("gl_FragCoord", &mFragCoordAdded, mInputVaryings); - return; - case EvqFrontFacing: - recordBuiltInVaryingUsed("gl_FrontFacing", &mFrontFacingAdded, mInputVaryings); - return; - case EvqPointCoord: - recordBuiltInVaryingUsed("gl_PointCoord", &mPointCoordAdded, mInputVaryings); - return; - case EvqInstanceID: - // Whenever the SH_INITIALIZE_BUILTINS_FOR_INSTANCED_MULTIVIEW option is set, - // gl_InstanceID is added inside expressions to initialize ViewID_OVR and - // InstanceID. gl_InstanceID is not added to the symbol table for ESSL1 shaders - // which makes it necessary to populate the type information explicitly instead of - // extracting it from the symbol table. - if (!mInstanceIDAdded) - { - Attribute info; - const char kName[] = "gl_InstanceID"; - info.name = kName; - info.mappedName = kName; - info.type = GL_INT; - info.precision = GL_HIGH_INT; // Defined by spec. - info.staticUse = true; - info.location = -1; - mAttribs->push_back(info); - mInstanceIDAdded = true; - } - return; - case EvqVertexID: - recordBuiltInAttributeUsed("gl_VertexID", &mVertexIDAdded); - return; - case EvqPosition: - recordBuiltInVaryingUsed("gl_Position", &mPositionAdded, mOutputVaryings); - return; - case EvqPointSize: - recordBuiltInVaryingUsed("gl_PointSize", &mPointSizeAdded, mOutputVaryings); - return; - case EvqLastFragData: - recordBuiltInVaryingUsed("gl_LastFragData", &mLastFragDataAdded, mInputVaryings); - return; - case EvqFragColor: - recordBuiltInFragmentOutputUsed("gl_FragColor", &mFragColorAdded); - return; - case EvqFragData: - if (!mFragDataAdded) - { - OutputVariable info; - setBuiltInInfoFromSymbolTable("gl_FragData", &info); - if (!IsExtensionEnabled(mExtensionBehavior, TExtension::EXT_draw_buffers)) - { - ASSERT(info.arraySizes.size() == 1u); - info.arraySizes.back() = 1u; - } - info.staticUse = true; - mOutputVariables->push_back(info); - mFragDataAdded = true; - } - return; - case EvqFragDepthEXT: - recordBuiltInFragmentOutputUsed("gl_FragDepthEXT", &mFragDepthEXTAdded); - return; - case EvqFragDepth: - recordBuiltInFragmentOutputUsed("gl_FragDepth", &mFragDepthAdded); - return; - case EvqSecondaryFragColorEXT: - recordBuiltInFragmentOutputUsed("gl_SecondaryFragColorEXT", - &mSecondaryFragColorEXTAdded); - return; - case EvqSecondaryFragDataEXT: - recordBuiltInFragmentOutputUsed("gl_SecondaryFragDataEXT", - &mSecondaryFragDataEXTAdded); - return; - case EvqInvocationID: - recordBuiltInVaryingUsed("gl_InvocationID", &mInvocationIDAdded, mInputVaryings); - break; - case EvqPrimitiveIDIn: - recordBuiltInVaryingUsed("gl_PrimitiveIDIn", &mPrimitiveIDInAdded, mInputVaryings); - break; - case EvqPrimitiveID: - if (mShaderType == GL_GEOMETRY_SHADER_OES) - { - recordBuiltInVaryingUsed("gl_PrimitiveID", &mPrimitiveIDAdded, mOutputVaryings); - } - else - { - ASSERT(mShaderType == GL_FRAGMENT_SHADER); - recordBuiltInVaryingUsed("gl_PrimitiveID", &mPrimitiveIDAdded, mInputVaryings); - } - break; - case EvqLayer: - if (mShaderType == GL_GEOMETRY_SHADER_OES) - { - recordBuiltInVaryingUsed("gl_Layer", &mLayerAdded, mOutputVaryings); - } - else if (mShaderType == GL_FRAGMENT_SHADER) - { - recordBuiltInVaryingUsed("gl_Layer", &mLayerAdded, mInputVaryings); - } - else - { - ASSERT(mShaderType == GL_VERTEX_SHADER && - IsExtensionEnabled(mExtensionBehavior, TExtension::OVR_multiview)); - } - break; - default: - break; - } - } - if (var) - { - MarkStaticallyUsed(var); - } -} - -void CollectVariablesTraverser::setCommonVariableProperties(const TType &type, - const TName &name, - ShaderVariable *variableOut) const -{ - ASSERT(variableOut); - - const TStructure *structure = type.getStruct(); - - if (!structure) - { - variableOut->type = GLVariableType(type); - variableOut->precision = GLVariablePrecision(type); - } - else - { - // Structures use a NONE type that isn't exposed outside ANGLE. - variableOut->type = GL_NONE; - variableOut->structName = structure->name().c_str(); - - const TFieldList &fields = structure->fields(); - - for (TField *field : fields) - { - // Regardless of the variable type (uniform, in/out etc.) its fields are always plain - // ShaderVariable objects. - ShaderVariable fieldVariable; - setCommonVariableProperties(*field->type(), TName(field->name()), &fieldVariable); - variableOut->fields.push_back(fieldVariable); - } - } - variableOut->name = name.getString().c_str(); - variableOut->mappedName = getMappedName(name); - - if (auto *arraySizes = type.getArraySizes()) - { - variableOut->arraySizes.assign(arraySizes->begin(), arraySizes->end()); - } -} - -Attribute CollectVariablesTraverser::recordAttribute(const TIntermSymbol &variable) const -{ - const TType &type = variable.getType(); - ASSERT(!type.getStruct()); - - Attribute attribute; - setCommonVariableProperties(type, variable.getName(), &attribute); - - attribute.location = type.getLayoutQualifier().location; - return attribute; -} - -OutputVariable CollectVariablesTraverser::recordOutputVariable(const TIntermSymbol &variable) const -{ - const TType &type = variable.getType(); - ASSERT(!type.getStruct()); - - OutputVariable outputVariable; - setCommonVariableProperties(type, variable.getName(), &outputVariable); - - outputVariable.location = type.getLayoutQualifier().location; - return outputVariable; -} - -Varying CollectVariablesTraverser::recordVarying(const TIntermSymbol &variable) const -{ - const TType &type = variable.getType(); - - Varying varying; - setCommonVariableProperties(type, variable.getName(), &varying); - varying.location = type.getLayoutQualifier().location; - - switch (type.getQualifier()) - { - case EvqVaryingIn: - case EvqVaryingOut: - case EvqVertexOut: - case EvqSmoothOut: - case EvqFlatOut: - case EvqCentroidOut: - case EvqGeometryOut: - if (mSymbolTable->isVaryingInvariant(std::string(variable.getSymbol().c_str())) || - type.isInvariant()) - { - varying.isInvariant = true; - } - break; - default: - break; - } - - varying.interpolation = GetInterpolationType(type.getQualifier()); - return varying; -} - -// TODO(jiawei.shao@intel.com): implement GL_OES_shader_io_blocks. -void CollectVariablesTraverser::recordInterfaceBlock(const TType &interfaceBlockType, - InterfaceBlock *interfaceBlock) const -{ - ASSERT(interfaceBlockType.getBasicType() == EbtInterfaceBlock); - ASSERT(interfaceBlock); - - const TInterfaceBlock *blockType = interfaceBlockType.getInterfaceBlock(); - ASSERT(blockType); - - interfaceBlock->name = blockType->name().c_str(); - interfaceBlock->mappedName = getMappedName(TName(blockType->name())); - interfaceBlock->instanceName = - (blockType->hasInstanceName() ? blockType->instanceName().c_str() : ""); - ASSERT(!interfaceBlockType.isArrayOfArrays()); // Disallowed by GLSL ES 3.10 section 4.3.9 - interfaceBlock->arraySize = interfaceBlockType.isArray() ? interfaceBlockType.getOutermostArraySize() : 0; - - interfaceBlock->blockType = GetBlockType(interfaceBlockType.getQualifier()); - if (interfaceBlock->blockType == BlockType::BLOCK_UNIFORM || - interfaceBlock->blockType == BlockType::BLOCK_BUFFER) - { - interfaceBlock->isRowMajorLayout = (blockType->matrixPacking() == EmpRowMajor); - interfaceBlock->binding = blockType->blockBinding(); - interfaceBlock->layout = GetBlockLayoutType(blockType->blockStorage()); - } - - // Gather field information - for (const TField *field : blockType->fields()) - { - const TType &fieldType = *field->type(); - - InterfaceBlockField fieldVariable; - setCommonVariableProperties(fieldType, TName(field->name()), &fieldVariable); - fieldVariable.isRowMajorLayout = - (fieldType.getLayoutQualifier().matrixPacking == EmpRowMajor); - interfaceBlock->fields.push_back(fieldVariable); - } -} - -Uniform CollectVariablesTraverser::recordUniform(const TIntermSymbol &variable) const -{ - Uniform uniform; - setCommonVariableProperties(variable.getType(), variable.getName(), &uniform); - uniform.binding = variable.getType().getLayoutQualifier().binding; - uniform.location = variable.getType().getLayoutQualifier().location; - uniform.offset = variable.getType().getLayoutQualifier().offset; - return uniform; -} - -bool CollectVariablesTraverser::visitDeclaration(Visit, TIntermDeclaration *node) -{ - const TIntermSequence &sequence = *(node->getSequence()); - ASSERT(!sequence.empty()); - - const TIntermTyped &typedNode = *(sequence.front()->getAsTyped()); - TQualifier qualifier = typedNode.getQualifier(); - - bool isShaderVariable = qualifier == EvqAttribute || qualifier == EvqVertexIn || - qualifier == EvqFragmentOut || qualifier == EvqUniform || - IsVarying(qualifier); - - if (typedNode.getBasicType() != EbtInterfaceBlock && !isShaderVariable) - { - return true; - } - - for (TIntermNode *variableNode : sequence) - { - // The only case in which the sequence will not contain a TIntermSymbol node is - // initialization. It will contain a TInterBinary node in that case. Since attributes, - // uniforms, varyings, outputs and interface blocks cannot be initialized in a shader, we - // must have only TIntermSymbol nodes in the sequence in the cases we are interested in. - const TIntermSymbol &variable = *variableNode->getAsSymbolNode(); - if (variable.getName().isInternal()) - { - // Internal variables are not collected. - continue; - } - - // TODO(jiawei.shao@intel.com): implement GL_OES_shader_io_blocks. - if (typedNode.getBasicType() == EbtInterfaceBlock) - { - InterfaceBlock interfaceBlock; - recordInterfaceBlock(variable.getType(), &interfaceBlock); - - switch (qualifier) - { - case EvqUniform: - mUniformBlocks->push_back(interfaceBlock); - break; - case EvqBuffer: - mShaderStorageBlocks->push_back(interfaceBlock); - break; - default: - UNREACHABLE(); - } - } - else - { - switch (qualifier) - { - case EvqAttribute: - case EvqVertexIn: - mAttribs->push_back(recordAttribute(variable)); - break; - case EvqFragmentOut: - mOutputVariables->push_back(recordOutputVariable(variable)); - break; - case EvqUniform: - mUniforms->push_back(recordUniform(variable)); - break; - default: - if (IsVaryingIn(qualifier)) - { - mInputVaryings->push_back(recordVarying(variable)); - } - else - { - ASSERT(IsVaryingOut(qualifier)); - mOutputVaryings->push_back(recordVarying(variable)); - } - break; - } - } - } - - // None of the recorded variables can have initializers, so we don't need to traverse the - // declarators. - return false; -} - -// TODO(jiawei.shao@intel.com): add search on mInBlocks and mOutBlocks when implementing -// GL_OES_shader_io_blocks. -InterfaceBlock *CollectVariablesTraverser::findNamedInterfaceBlock(const TString &blockName) const -{ - InterfaceBlock *namedBlock = FindVariable(blockName, mUniformBlocks); - if (!namedBlock) - { - namedBlock = FindVariable(blockName, mShaderStorageBlocks); - } - return namedBlock; -} - -bool CollectVariablesTraverser::visitBinary(Visit, TIntermBinary *binaryNode) -{ - if (binaryNode->getOp() == EOpIndexDirectInterfaceBlock) - { - // NOTE: we do not determine static use for individual blocks of an array - TIntermTyped *blockNode = binaryNode->getLeft()->getAsTyped(); - ASSERT(blockNode); - - TIntermConstantUnion *constantUnion = binaryNode->getRight()->getAsConstantUnion(); - ASSERT(constantUnion); - - InterfaceBlock *namedBlock = nullptr; - - bool traverseIndexExpression = false; - TIntermBinary *interfaceIndexingNode = blockNode->getAsBinaryNode(); - if (interfaceIndexingNode) - { - TIntermTyped *interfaceNode = interfaceIndexingNode->getLeft()->getAsTyped(); - ASSERT(interfaceNode); - - const TType &interfaceType = interfaceNode->getType(); - if (interfaceType.getQualifier() == EvqPerVertexIn) - { - namedBlock = recordGLInUsed(interfaceType); - ASSERT(namedBlock); - - // We need to continue traversing to collect useful variables in the index - // expression of gl_in. - traverseIndexExpression = true; - } - } - - const TInterfaceBlock *interfaceBlock = blockNode->getType().getInterfaceBlock(); - if (!namedBlock) - { - namedBlock = findNamedInterfaceBlock(interfaceBlock->name()); - } - ASSERT(namedBlock); - namedBlock->staticUse = true; - unsigned int fieldIndex = static_cast(constantUnion->getIConst(0)); - ASSERT(fieldIndex < namedBlock->fields.size()); - namedBlock->fields[fieldIndex].staticUse = true; - - if (traverseIndexExpression) - { - ASSERT(interfaceIndexingNode); - interfaceIndexingNode->getRight()->traverse(this); - } - return false; - } - - return true; -} - -} // anonymous namespace - -void CollectVariables(TIntermBlock *root, - std::vector *attributes, - std::vector *outputVariables, - std::vector *uniforms, - std::vector *inputVaryings, - std::vector *outputVaryings, - std::vector *uniformBlocks, - std::vector *shaderStorageBlocks, - std::vector *inBlocks, - ShHashFunction64 hashFunction, - TSymbolTable *symbolTable, - int shaderVersion, - GLenum shaderType, - const TExtensionBehavior &extensionBehavior) -{ - CollectVariablesTraverser collect(attributes, outputVariables, uniforms, inputVaryings, - outputVaryings, uniformBlocks, shaderStorageBlocks, inBlocks, - hashFunction, symbolTable, shaderVersion, shaderType, - extensionBehavior); - root->traverse(&collect); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/CollectVariables.h b/src/3rdparty/angle/src/compiler/translator/CollectVariables.h deleted file mode 100644 index 4d0d1192e0..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/CollectVariables.h +++ /dev/null @@ -1,37 +0,0 @@ -// -// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// CollectVariables.h: Collect lists of shader interface variables based on the AST. - -#ifndef COMPILER_TRANSLATOR_COLLECTVARIABLES_H_ -#define COMPILER_TRANSLATOR_COLLECTVARIABLES_H_ - -#include - -#include "compiler/translator/ExtensionBehavior.h" - -namespace sh -{ - -class TIntermBlock; -class TSymbolTable; - -void CollectVariables(TIntermBlock *root, - std::vector *attributes, - std::vector *outputVariables, - std::vector *uniforms, - std::vector *inputVaryings, - std::vector *outputVaryings, - std::vector *uniformBlocks, - std::vector *shaderStorageBlocks, - std::vector *inBlocks, - ShHashFunction64 hashFunction, - TSymbolTable *symbolTable, - int shaderVersion, - GLenum shaderType, - const TExtensionBehavior &extensionBehavior); -} - -#endif // COMPILER_TRANSLATOR_COLLECTVARIABLES_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/Common.h b/src/3rdparty/angle/src/compiler/translator/Common.h deleted file mode 100644 index cb3a680d85..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/Common.h +++ /dev/null @@ -1,138 +0,0 @@ -// -// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_TRANSLATOR_COMMON_H_ -#define COMPILER_TRANSLATOR_COMMON_H_ - -#include -#include -#include -#include -#include -#include -#include - -#include "common/angleutils.h" -#include "common/debug.h" -#include "common/third_party/smhasher/src/PMurHash.h" -#include "compiler/translator/PoolAlloc.h" - -namespace sh -{ - -struct TSourceLoc -{ - int first_file; - int first_line; - int last_file; - int last_line; -}; - -// -// Put POOL_ALLOCATOR_NEW_DELETE in base classes to make them use this scheme. -// -#define POOL_ALLOCATOR_NEW_DELETE() \ - void *operator new(size_t s) { return GetGlobalPoolAllocator()->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 GetGlobalPoolAllocator()->allocate(s); } \ - void *operator new[](size_t, void *_Where) { return (_Where); } \ - void operator delete[](void *) {} \ - void operator delete[](void *, void *) {} - -// -// Pool version of string. -// -typedef pool_allocator TStringAllocator; -typedef std::basic_string, TStringAllocator> TString; -typedef std::basic_ostringstream, TStringAllocator> TStringStream; -inline TString *NewPoolTString(const char *s) -{ - void *memory = GetGlobalPoolAllocator()->allocate(sizeof(TString)); - return new (memory) TString(s); -} - -// -// Persistent string memory. Should only be used for strings that survive -// across compiles. -// -#define TPersistString std::string -#define TPersistStringStream std::ostringstream - -// -// Pool allocator versions of vectors, lists, and maps -// -template -class TVector : public std::vector> -{ - public: - POOL_ALLOCATOR_NEW_DELETE(); - - 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) {} -}; - -template , class CMP = std::equal_to> -class TUnorderedMap : public std::unordered_map>> -{ - public: - POOL_ALLOCATOR_NEW_DELETE(); - typedef pool_allocator> tAllocator; - - TUnorderedMap() : std::unordered_map() {} - // use correct two-stage name lookup supported in gcc 3.4 and above - TUnorderedMap(const tAllocator &a) - : std::unordered_map( - std::unordered_map::key_compare(), - a) - { - } -}; - -template > -class TMap : public std::map>> -{ - public: - POOL_ALLOCATOR_NEW_DELETE(); - typedef pool_allocator> tAllocator; - - TMap() : std::map() {} - // use correct two-stage name lookup supported in gcc 3.4 and above - TMap(const tAllocator &a) - : std::map(std::map::key_compare(), a) - { - } -}; - -// Integer to TString conversion -template -inline TString str(T i) -{ - ASSERT(std::numeric_limits::is_integer); - char buffer[((8 * sizeof(T)) / 3) + 3]; - const char *formatStr = std::numeric_limits::is_signed ? "%d" : "%u"; - snprintf(buffer, sizeof(buffer), formatStr, i); - return buffer; -} - -} // namespace sh - -namespace std -{ -template <> -struct hash -{ - size_t operator()(const sh::TString &s) const - { - return angle::PMurHash32(0, s.data(), static_cast(s.length())); - } -}; -} // namespace std - -#endif // COMPILER_TRANSLATOR_COMMON_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/Compiler.cpp b/src/3rdparty/angle/src/compiler/translator/Compiler.cpp deleted file mode 100644 index 2f411cb58c..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/Compiler.cpp +++ /dev/null @@ -1,1169 +0,0 @@ -// -// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/translator/Compiler.h" - -#include - -#include "angle_gl.h" -#include "common/utilities.h" -#include "compiler/translator/AddAndTrueToLoopCondition.h" -#include "compiler/translator/Cache.h" -#include "compiler/translator/CallDAG.h" -#include "compiler/translator/ClampPointSize.h" -#include "compiler/translator/CollectVariables.h" -#include "compiler/translator/DeclareAndInitBuiltinsForInstancedMultiview.h" -#include "compiler/translator/DeferGlobalInitializers.h" -#include "compiler/translator/EmulateGLFragColorBroadcast.h" -#include "compiler/translator/EmulatePrecision.h" -#include "compiler/translator/Initialize.h" -#include "compiler/translator/InitializeVariables.h" -#include "compiler/translator/IntermNodePatternMatcher.h" -#include "compiler/translator/IsASTDepthBelowLimit.h" -#include "compiler/translator/OutputTree.h" -#include "compiler/translator/ParseContext.h" -#include "compiler/translator/PruneNoOps.h" -#include "compiler/translator/RegenerateStructNames.h" -#include "compiler/translator/RemoveArrayLengthMethod.h" -#include "compiler/translator/RemoveEmptySwitchStatements.h" -#include "compiler/translator/RemoveInvariantDeclaration.h" -#include "compiler/translator/RemoveNoOpCasesFromEndOfSwitchStatements.h" -#include "compiler/translator/RemovePow.h" -#include "compiler/translator/RemoveUnreferencedVariables.h" -#include "compiler/translator/RewriteDoWhile.h" -#include "compiler/translator/ScalarizeVecAndMatConstructorArgs.h" -#include "compiler/translator/SeparateDeclarations.h" -#include "compiler/translator/SimplifyLoopConditions.h" -#include "compiler/translator/SplitSequenceOperator.h" -#include "compiler/translator/UnfoldShortCircuitAST.h" -#include "compiler/translator/UseInterfaceBlockFields.h" -#include "compiler/translator/ValidateLimitations.h" -#include "compiler/translator/ValidateMaxParameters.h" -#include "compiler/translator/ValidateOutputs.h" -#include "compiler/translator/ValidateVaryingLocations.h" -#include "compiler/translator/VariablePacker.h" -#include "compiler/translator/VectorizeVectorScalarArithmetic.h" -#include "compiler/translator/util.h" -#include "third_party/compiler/ArrayBoundsClamper.h" - -namespace sh -{ - -namespace -{ - -#if defined(ANGLE_ENABLE_FUZZER_CORPUS_OUTPUT) -void DumpFuzzerCase(char const *const *shaderStrings, - size_t numStrings, - uint32_t type, - uint32_t spec, - uint32_t output, - uint64_t options) -{ - static int fileIndex = 0; - - std::ostringstream o; - o << "corpus/" << fileIndex++ << ".sample"; - std::string s = o.str(); - - // Must match the input format of the fuzzer - FILE *f = fopen(s.c_str(), "w"); - fwrite(&type, sizeof(type), 1, f); - fwrite(&spec, sizeof(spec), 1, f); - fwrite(&output, sizeof(output), 1, f); - fwrite(&options, sizeof(options), 1, f); - - char zero[128 - 20] = {0}; - fwrite(&zero, 128 - 20, 1, f); - - for (size_t i = 0; i < numStrings; i++) - { - fwrite(shaderStrings[i], sizeof(char), strlen(shaderStrings[i]), f); - } - fwrite(&zero, 1, 1, f); - - fclose(f); -} -#endif // defined(ANGLE_ENABLE_FUZZER_CORPUS_OUTPUT) -} // anonymous namespace - -bool IsWebGLBasedSpec(ShShaderSpec spec) -{ - return (spec == SH_WEBGL_SPEC || spec == SH_WEBGL2_SPEC || spec == SH_WEBGL3_SPEC); -} - -bool IsGLSL130OrNewer(ShShaderOutput output) -{ - return (output == SH_GLSL_130_OUTPUT || output == SH_GLSL_140_OUTPUT || - output == SH_GLSL_150_CORE_OUTPUT || output == SH_GLSL_330_CORE_OUTPUT || - output == SH_GLSL_400_CORE_OUTPUT || output == SH_GLSL_410_CORE_OUTPUT || - output == SH_GLSL_420_CORE_OUTPUT || output == SH_GLSL_430_CORE_OUTPUT || - output == SH_GLSL_440_CORE_OUTPUT || output == SH_GLSL_450_CORE_OUTPUT); -} - -bool IsGLSL420OrNewer(ShShaderOutput output) -{ - return (output == SH_GLSL_420_CORE_OUTPUT || output == SH_GLSL_430_CORE_OUTPUT || - output == SH_GLSL_440_CORE_OUTPUT || output == SH_GLSL_450_CORE_OUTPUT); -} - -bool IsGLSL410OrOlder(ShShaderOutput output) -{ - return (output == SH_GLSL_130_OUTPUT || output == SH_GLSL_140_OUTPUT || - output == SH_GLSL_150_CORE_OUTPUT || output == SH_GLSL_330_CORE_OUTPUT || - output == SH_GLSL_400_CORE_OUTPUT || output == SH_GLSL_410_CORE_OUTPUT); -} - -bool RemoveInvariant(sh::GLenum shaderType, - int shaderVersion, - ShShaderOutput outputType, - ShCompileOptions compileOptions) -{ - if ((compileOptions & SH_DONT_REMOVE_INVARIANT_FOR_FRAGMENT_INPUT) == 0 && - shaderType == GL_FRAGMENT_SHADER && IsGLSL420OrNewer(outputType)) - return true; - - if ((compileOptions & SH_REMOVE_INVARIANT_AND_CENTROID_FOR_ESSL3) != 0 && - shaderVersion >= 300 && shaderType == GL_VERTEX_SHADER) - return true; - - return false; -} - -size_t GetGlobalMaxTokenSize(ShShaderSpec spec) -{ - // WebGL defines a max token length of 256, while ES2 leaves max token - // size undefined. ES3 defines a max size of 1024 characters. - switch (spec) - { - case SH_WEBGL_SPEC: - return 256; - default: - return 1024; - } -} - -int GetMaxUniformVectorsForShaderType(GLenum shaderType, const ShBuiltInResources &resources) -{ - switch (shaderType) - { - case GL_VERTEX_SHADER: - return resources.MaxVertexUniformVectors; - case GL_FRAGMENT_SHADER: - return resources.MaxFragmentUniformVectors; - - // TODO (jiawei.shao@intel.com): check if we need finer-grained component counting - case GL_COMPUTE_SHADER: - return resources.MaxComputeUniformComponents / 4; - case GL_GEOMETRY_SHADER_OES: - return resources.MaxGeometryUniformComponents / 4; - default: - UNREACHABLE(); - return -1; - } -} - -namespace -{ - -class TScopedPoolAllocator -{ - public: - TScopedPoolAllocator(TPoolAllocator *allocator) : mAllocator(allocator) - { - mAllocator->push(); - SetGlobalPoolAllocator(mAllocator); - } - ~TScopedPoolAllocator() - { - SetGlobalPoolAllocator(nullptr); - mAllocator->pop(); - } - - private: - TPoolAllocator *mAllocator; -}; - -class TScopedSymbolTableLevel -{ - public: - TScopedSymbolTableLevel(TSymbolTable *table) : mTable(table) - { - ASSERT(mTable->atBuiltInLevel()); - mTable->push(); - } - ~TScopedSymbolTableLevel() - { - while (!mTable->atBuiltInLevel()) - mTable->pop(); - } - - private: - TSymbolTable *mTable; -}; - -int MapSpecToShaderVersion(ShShaderSpec spec) -{ - switch (spec) - { - case SH_GLES2_SPEC: - case SH_WEBGL_SPEC: - return 100; - case SH_GLES3_SPEC: - case SH_WEBGL2_SPEC: - return 300; - case SH_GLES3_1_SPEC: - case SH_WEBGL3_SPEC: - return 310; - default: - UNREACHABLE(); - return 0; - } -} - -} // namespace - -TShHandleBase::TShHandleBase() -{ - allocator.push(); - SetGlobalPoolAllocator(&allocator); -} - -TShHandleBase::~TShHandleBase() -{ - SetGlobalPoolAllocator(nullptr); - allocator.popAll(); -} - -TCompiler::TCompiler(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output) - : variablesCollected(false), - mGLPositionInitialized(false), - shaderType(type), - shaderSpec(spec), - outputType(output), - maxUniformVectors(0), - maxExpressionComplexity(0), - maxCallStackDepth(0), - maxFunctionParameters(0), - fragmentPrecisionHigh(false), - clampingStrategy(SH_CLAMP_WITH_CLAMP_INTRINSIC), - builtInFunctionEmulator(), - mDiagnostics(infoSink.info), - mSourcePath(nullptr), - mComputeShaderLocalSizeDeclared(false), - mComputeShaderLocalSize(1), - mGeometryShaderMaxVertices(-1), - mGeometryShaderInvocations(0), - mGeometryShaderInputPrimitiveType(EptUndefined), - mGeometryShaderOutputPrimitiveType(EptUndefined) -{ -} - -TCompiler::~TCompiler() -{ -} - -bool TCompiler::shouldRunLoopAndIndexingValidation(ShCompileOptions compileOptions) const -{ - // If compiling an ESSL 1.00 shader for WebGL, or if its been requested through the API, - // validate loop and indexing as well (to verify that the shader only uses minimal functionality - // of ESSL 1.00 as in Appendix A of the spec). - return (IsWebGLBasedSpec(shaderSpec) && shaderVersion == 100) || - (compileOptions & SH_VALIDATE_LOOP_INDEXING); -} - -bool TCompiler::Init(const ShBuiltInResources &resources) -{ - shaderVersion = 100; - - maxUniformVectors = GetMaxUniformVectorsForShaderType(shaderType, resources); - - maxExpressionComplexity = resources.MaxExpressionComplexity; - maxCallStackDepth = resources.MaxCallStackDepth; - maxFunctionParameters = resources.MaxFunctionParameters; - - SetGlobalPoolAllocator(&allocator); - - // Generate built-in symbol table. - if (!InitBuiltInSymbolTable(resources)) - return false; - InitExtensionBehavior(resources, extensionBehavior); - fragmentPrecisionHigh = resources.FragmentPrecisionHigh == 1; - - arrayBoundsClamper.SetClampingStrategy(resources.ArrayIndexClampingStrategy); - clampingStrategy = resources.ArrayIndexClampingStrategy; - - hashFunction = resources.HashFunction; - - return true; -} - -TIntermBlock *TCompiler::compileTreeForTesting(const char *const shaderStrings[], - size_t numStrings, - ShCompileOptions compileOptions) -{ - return compileTreeImpl(shaderStrings, numStrings, compileOptions); -} - -TIntermBlock *TCompiler::compileTreeImpl(const char *const shaderStrings[], - size_t numStrings, - const ShCompileOptions compileOptions) -{ - clearResults(); - - ASSERT(numStrings > 0); - ASSERT(GetGlobalPoolAllocator()); - - // Reset the extension behavior for each compilation unit. - ResetExtensionBehavior(extensionBehavior); - - // First string is path of source file if flag is set. The actual source follows. - size_t firstSource = 0; - if (compileOptions & SH_SOURCE_PATH) - { - mSourcePath = shaderStrings[0]; - ++firstSource; - } - - TParseContext parseContext(symbolTable, extensionBehavior, shaderType, shaderSpec, - compileOptions, true, &mDiagnostics, getResources()); - - parseContext.setFragmentPrecisionHighOnESSL1(fragmentPrecisionHigh); - - // We preserve symbols at the built-in level from compile-to-compile. - // Start pushing the user-defined symbols at global level. - TScopedSymbolTableLevel scopedSymbolLevel(&symbolTable); - - // Parse shader. - if (PaParseStrings(numStrings - firstSource, &shaderStrings[firstSource], nullptr, - &parseContext) != 0) - { - return nullptr; - } - - if (parseContext.getTreeRoot() == nullptr) - { - return nullptr; - } - - setASTMetadata(parseContext); - - if (MapSpecToShaderVersion(shaderSpec) < shaderVersion) - { - mDiagnostics.globalError("unsupported shader version"); - return nullptr; - } - - TIntermBlock *root = parseContext.getTreeRoot(); - if (!checkAndSimplifyAST(root, parseContext, compileOptions)) - { - return nullptr; - } - - return root; -} - -void TCompiler::setASTMetadata(const TParseContext &parseContext) -{ - shaderVersion = parseContext.getShaderVersion(); - - mPragma = parseContext.pragma(); - symbolTable.setGlobalInvariant(mPragma.stdgl.invariantAll); - - mComputeShaderLocalSizeDeclared = parseContext.isComputeShaderLocalSizeDeclared(); - mComputeShaderLocalSize = parseContext.getComputeShaderLocalSize(); - - mNumViews = parseContext.getNumViews(); - - // Highp might have been auto-enabled based on shader version - fragmentPrecisionHigh = parseContext.getFragmentPrecisionHigh(); - - if (shaderType == GL_GEOMETRY_SHADER_OES) - { - mGeometryShaderInputPrimitiveType = parseContext.getGeometryShaderInputPrimitiveType(); - mGeometryShaderOutputPrimitiveType = parseContext.getGeometryShaderOutputPrimitiveType(); - mGeometryShaderMaxVertices = parseContext.getGeometryShaderMaxVertices(); - mGeometryShaderInvocations = parseContext.getGeometryShaderInvocations(); - } -} - -bool TCompiler::checkAndSimplifyAST(TIntermBlock *root, - const TParseContext &parseContext, - ShCompileOptions compileOptions) -{ - // Disallow expressions deemed too complex. - if ((compileOptions & SH_LIMIT_EXPRESSION_COMPLEXITY) && !limitExpressionComplexity(root)) - { - return false; - } - - // We prune no-ops to work around driver bugs and to keep AST processing and output simple. - // The following kinds of no-ops are pruned: - // 1. Empty declarations "int;". - // 2. Literal statements: "1.0;". The ESSL output doesn't define a default precision - // for float, so float literal statements would end up with no precision which is - // invalid ESSL. - // After this empty declarations are not allowed in the AST. - PruneNoOps(root); - - // In case the last case inside a switch statement is a certain type of no-op, GLSL - // compilers in drivers may not accept it. In this case we clean up the dead code from the - // end of switch statements. This is also required because PruneNoOps may have left switch - // statements that only contained an empty declaration inside the final case in an invalid - // state. Relies on that PruneNoOps has already been run. - RemoveNoOpCasesFromEndOfSwitchStatements(root, &symbolTable); - - // Remove empty switch statements - this makes output simpler. - RemoveEmptySwitchStatements(root); - - // Create the function DAG and check there is no recursion - if (!initCallDag(root)) - { - return false; - } - - if ((compileOptions & SH_LIMIT_CALL_STACK_DEPTH) && !checkCallDepth()) - { - return false; - } - - // Checks which functions are used and if "main" exists - functionMetadata.clear(); - functionMetadata.resize(mCallDag.size()); - if (!tagUsedFunctions()) - { - return false; - } - - if (!(compileOptions & SH_DONT_PRUNE_UNUSED_FUNCTIONS)) - { - pruneUnusedFunctions(root); - } - - if (shaderVersion >= 310 && !ValidateVaryingLocations(root, &mDiagnostics, shaderType)) - { - return false; - } - - if (shaderVersion >= 300 && shaderType == GL_FRAGMENT_SHADER && - !ValidateOutputs(root, getExtensionBehavior(), compileResources.MaxDrawBuffers, - &mDiagnostics)) - { - return false; - } - - if (shouldRunLoopAndIndexingValidation(compileOptions) && - !ValidateLimitations(root, shaderType, &symbolTable, shaderVersion, &mDiagnostics)) - { - return false; - } - - // Fail compilation if precision emulation not supported. - if (getResources().WEBGL_debug_shader_precision && getPragma().debugShaderPrecision && - !EmulatePrecision::SupportedInLanguage(outputType)) - { - mDiagnostics.globalError("Precision emulation not supported for this output type."); - return false; - } - - // Clamping uniform array bounds needs to happen after validateLimitations pass. - if (compileOptions & SH_CLAMP_INDIRECT_ARRAY_BOUNDS) - { - arrayBoundsClamper.MarkIndirectArrayBoundsForClamping(root); - } - - if ((compileOptions & SH_INITIALIZE_BUILTINS_FOR_INSTANCED_MULTIVIEW) && - parseContext.isExtensionEnabled(TExtension::OVR_multiview) && - getShaderType() != GL_COMPUTE_SHADER) - { - DeclareAndInitBuiltinsForInstancedMultiview(root, mNumViews, shaderType, compileOptions, - outputType, &symbolTable); - } - - // This pass might emit short circuits so keep it before the short circuit unfolding - if (compileOptions & SH_REWRITE_DO_WHILE_LOOPS) - RewriteDoWhile(root, &symbolTable); - - if (compileOptions & SH_ADD_AND_TRUE_TO_LOOP_CONDITION) - sh::AddAndTrueToLoopCondition(root); - - if (compileOptions & SH_UNFOLD_SHORT_CIRCUIT) - { - UnfoldShortCircuitAST unfoldShortCircuit; - root->traverse(&unfoldShortCircuit); - unfoldShortCircuit.updateTree(); - } - - if (compileOptions & SH_REMOVE_POW_WITH_CONSTANT_EXPONENT) - { - RemovePow(root); - } - - if (compileOptions & SH_REGENERATE_STRUCT_NAMES) - { - RegenerateStructNames gen(&symbolTable, shaderVersion); - root->traverse(&gen); - } - - if (shaderType == GL_FRAGMENT_SHADER && shaderVersion == 100 && - compileResources.EXT_draw_buffers && compileResources.MaxDrawBuffers > 1 && - IsExtensionEnabled(extensionBehavior, TExtension::EXT_draw_buffers)) - { - EmulateGLFragColorBroadcast(root, compileResources.MaxDrawBuffers, &outputVariables, - &symbolTable, shaderVersion); - } - - // Split multi declarations and remove calls to array length(). - // Note that SimplifyLoopConditions needs to be run before any other AST transformations - // that may need to generate new statements from loop conditions or loop expressions. - SimplifyLoopConditions( - root, - IntermNodePatternMatcher::kMultiDeclaration | IntermNodePatternMatcher::kArrayLengthMethod, - &getSymbolTable(), getShaderVersion()); - - // Note that separate declarations need to be run before other AST transformations that - // generate new statements from expressions. - SeparateDeclarations(root); - - SplitSequenceOperator(root, IntermNodePatternMatcher::kArrayLengthMethod, &getSymbolTable(), - getShaderVersion()); - - RemoveArrayLengthMethod(root); - - RemoveUnreferencedVariables(root, &symbolTable); - - // Built-in function emulation needs to happen after validateLimitations pass. - // TODO(jmadill): Remove global pool allocator. - GetGlobalPoolAllocator()->lock(); - initBuiltInFunctionEmulator(&builtInFunctionEmulator, compileOptions); - GetGlobalPoolAllocator()->unlock(); - builtInFunctionEmulator.markBuiltInFunctionsForEmulation(root); - - if (compileOptions & SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS) - { - ScalarizeVecAndMatConstructorArgs(root, shaderType, fragmentPrecisionHigh, &symbolTable); - } - - if (shouldCollectVariables(compileOptions)) - { - ASSERT(!variablesCollected); - CollectVariables(root, &attributes, &outputVariables, &uniforms, &inputVaryings, - &outputVaryings, &uniformBlocks, &shaderStorageBlocks, &inBlocks, - hashFunction, &symbolTable, shaderVersion, shaderType, extensionBehavior); - collectInterfaceBlocks(); - variablesCollected = true; - if (compileOptions & SH_USE_UNUSED_STANDARD_SHARED_BLOCKS) - { - useAllMembersInUnusedStandardAndSharedBlocks(root); - } - if (compileOptions & SH_ENFORCE_PACKING_RESTRICTIONS) - { - // Returns true if, after applying the packing rules in the GLSL ES 1.00.17 spec - // Appendix A, section 7, the shader does not use too many uniforms. - if (!CheckVariablesInPackingLimits(maxUniformVectors, uniforms)) - { - mDiagnostics.globalError("too many uniforms"); - return false; - } - } - if (compileOptions & SH_INIT_OUTPUT_VARIABLES) - { - initializeOutputVariables(root); - } - } - - // Removing invariant declarations must be done after collecting variables. - // Otherwise, built-in invariant declarations don't apply. - if (RemoveInvariant(shaderType, shaderVersion, outputType, compileOptions)) - { - RemoveInvariantDeclaration(root); - } - - // gl_Position is always written in compatibility output mode. - // It may have been already initialized among other output variables, in that case we don't - // need to initialize it twice. - if (shaderType == GL_VERTEX_SHADER && !mGLPositionInitialized && - ((compileOptions & SH_INIT_GL_POSITION) || (outputType == SH_GLSL_COMPATIBILITY_OUTPUT))) - { - initializeGLPosition(root); - mGLPositionInitialized = true; - } - - // DeferGlobalInitializers needs to be run before other AST transformations that generate new - // statements from expressions. But it's fine to run DeferGlobalInitializers after the above - // SplitSequenceOperator and RemoveArrayLengthMethod since they only have an effect on the AST - // on ESSL >= 3.00, and the initializers that need to be deferred can only exist in ESSL < 3.00. - bool initializeLocalsAndGlobals = - (compileOptions & SH_INITIALIZE_UNINITIALIZED_LOCALS) && !IsOutputHLSL(getOutputType()); - bool canUseLoopsToInitialize = !(compileOptions & SH_DONT_USE_LOOPS_TO_INITIALIZE_VARIABLES); - DeferGlobalInitializers(root, initializeLocalsAndGlobals, canUseLoopsToInitialize, &symbolTable); - - if (initializeLocalsAndGlobals) - { - // Initialize uninitialized local variables. - // In some cases initializing can generate extra statements in the parent block, such as - // when initializing nameless structs or initializing arrays in ESSL 1.00. In that case - // we need to first simplify loop conditions. We've already separated declarations - // earlier, which is also required. If we don't follow the Appendix A limitations, loop - // init statements can declare arrays or nameless structs and have multiple - // declarations. - - if (!shouldRunLoopAndIndexingValidation(compileOptions)) - { - SimplifyLoopConditions(root, - IntermNodePatternMatcher::kArrayDeclaration | - IntermNodePatternMatcher::kNamelessStructDeclaration, - &getSymbolTable(), getShaderVersion()); - } - - InitializeUninitializedLocals(root, getShaderVersion(), canUseLoopsToInitialize, - &getSymbolTable()); - } - - if (getShaderType() == GL_VERTEX_SHADER && (compileOptions & SH_CLAMP_POINT_SIZE)) - { - ClampPointSize(root, compileResources.MaxPointSize, &getSymbolTable()); - } - - if (compileOptions & SH_REWRITE_VECTOR_SCALAR_ARITHMETIC) - { - VectorizeVectorScalarArithmetic(root, &getSymbolTable()); - } - - return true; -} - -bool TCompiler::compile(const char *const shaderStrings[], - size_t numStrings, - ShCompileOptions compileOptionsIn) -{ -#if defined(ANGLE_ENABLE_FUZZER_CORPUS_OUTPUT) - DumpFuzzerCase(shaderStrings, numStrings, shaderType, shaderSpec, outputType, compileOptionsIn); -#endif // defined(ANGLE_ENABLE_FUZZER_CORPUS_OUTPUT) - - if (numStrings == 0) - return true; - - ShCompileOptions compileOptions = compileOptionsIn; - - // Apply key workarounds. - if (shouldFlattenPragmaStdglInvariantAll()) - { - // This should be harmless to do in all cases, but for the moment, do it only conditionally. - compileOptions |= SH_FLATTEN_PRAGMA_STDGL_INVARIANT_ALL; - } - - TScopedPoolAllocator scopedAlloc(&allocator); - TIntermBlock *root = compileTreeImpl(shaderStrings, numStrings, compileOptions); - - if (root) - { - if (compileOptions & SH_INTERMEDIATE_TREE) - OutputTree(root, infoSink.info); - - if (compileOptions & SH_OBJECT_CODE) - { - PerformanceDiagnostics perfDiagnostics(&mDiagnostics); - translate(root, compileOptions, &perfDiagnostics); - } - - // The IntermNode tree doesn't need to be deleted here, since the - // memory will be freed in a big chunk by the PoolAllocator. - return true; - } - return false; -} - -bool TCompiler::InitBuiltInSymbolTable(const ShBuiltInResources &resources) -{ - if (resources.MaxDrawBuffers < 1) - { - return false; - } - if (resources.EXT_blend_func_extended && resources.MaxDualSourceDrawBuffers < 1) - { - return false; - } - - compileResources = resources; - setResourceString(); - - ASSERT(symbolTable.isEmpty()); - symbolTable.push(); // COMMON_BUILTINS - symbolTable.push(); // ESSL1_BUILTINS - symbolTable.push(); // ESSL3_BUILTINS - symbolTable.push(); // ESSL3_1_BUILTINS - symbolTable.push(); // GLSL_BUILTINS - - switch (shaderType) - { - case GL_FRAGMENT_SHADER: - symbolTable.setDefaultPrecision(EbtInt, EbpMedium); - break; - case GL_VERTEX_SHADER: - case GL_COMPUTE_SHADER: - case GL_GEOMETRY_SHADER_OES: - symbolTable.setDefaultPrecision(EbtInt, EbpHigh); - symbolTable.setDefaultPrecision(EbtFloat, EbpHigh); - break; - default: - UNREACHABLE(); - } - // Set defaults for sampler types that have default precision, even those that are - // only available if an extension exists. - // New sampler types in ESSL3 don't have default precision. ESSL1 types do. - initSamplerDefaultPrecision(EbtSampler2D); - initSamplerDefaultPrecision(EbtSamplerCube); - // SamplerExternalOES is specified in the extension to have default precision. - initSamplerDefaultPrecision(EbtSamplerExternalOES); - // SamplerExternal2DY2YEXT is specified in the extension to have default precision. - initSamplerDefaultPrecision(EbtSamplerExternal2DY2YEXT); - // It isn't specified whether Sampler2DRect has default precision. - initSamplerDefaultPrecision(EbtSampler2DRect); - - symbolTable.setDefaultPrecision(EbtAtomicCounter, EbpHigh); - - InsertBuiltInFunctions(shaderType, shaderSpec, resources, symbolTable); - - IdentifyBuiltIns(shaderType, shaderSpec, resources, symbolTable); - - return true; -} - -void TCompiler::initSamplerDefaultPrecision(TBasicType samplerType) -{ - ASSERT(samplerType > EbtGuardSamplerBegin && samplerType < EbtGuardSamplerEnd); - symbolTable.setDefaultPrecision(samplerType, EbpLow); -} - -void TCompiler::setResourceString() -{ - std::ostringstream strstream; - - // clang-format off - strstream << ":MaxVertexAttribs:" << compileResources.MaxVertexAttribs - << ":MaxVertexUniformVectors:" << compileResources.MaxVertexUniformVectors - << ":MaxVaryingVectors:" << compileResources.MaxVaryingVectors - << ":MaxVertexTextureImageUnits:" << compileResources.MaxVertexTextureImageUnits - << ":MaxCombinedTextureImageUnits:" << compileResources.MaxCombinedTextureImageUnits - << ":MaxTextureImageUnits:" << compileResources.MaxTextureImageUnits - << ":MaxFragmentUniformVectors:" << compileResources.MaxFragmentUniformVectors - << ":MaxDrawBuffers:" << compileResources.MaxDrawBuffers - << ":OES_standard_derivatives:" << compileResources.OES_standard_derivatives - << ":OES_EGL_image_external:" << compileResources.OES_EGL_image_external - << ":OES_EGL_image_external_essl3:" << compileResources.OES_EGL_image_external_essl3 - << ":NV_EGL_stream_consumer_external:" << compileResources.NV_EGL_stream_consumer_external - << ":ARB_texture_rectangle:" << compileResources.ARB_texture_rectangle - << ":EXT_draw_buffers:" << compileResources.EXT_draw_buffers - << ":FragmentPrecisionHigh:" << compileResources.FragmentPrecisionHigh - << ":MaxExpressionComplexity:" << compileResources.MaxExpressionComplexity - << ":MaxCallStackDepth:" << compileResources.MaxCallStackDepth - << ":MaxFunctionParameters:" << compileResources.MaxFunctionParameters - << ":EXT_blend_func_extended:" << compileResources.EXT_blend_func_extended - << ":EXT_frag_depth:" << compileResources.EXT_frag_depth - << ":EXT_shader_texture_lod:" << compileResources.EXT_shader_texture_lod - << ":EXT_shader_framebuffer_fetch:" << compileResources.EXT_shader_framebuffer_fetch - << ":NV_shader_framebuffer_fetch:" << compileResources.NV_shader_framebuffer_fetch - << ":ARM_shader_framebuffer_fetch:" << compileResources.ARM_shader_framebuffer_fetch - << ":OVR_multiview:" << compileResources.OVR_multiview - << ":EXT_YUV_target:" << compileResources.EXT_YUV_target - << ":OES_geometry_shader:" << compileResources.OES_geometry_shader - << ":MaxVertexOutputVectors:" << compileResources.MaxVertexOutputVectors - << ":MaxFragmentInputVectors:" << compileResources.MaxFragmentInputVectors - << ":MinProgramTexelOffset:" << compileResources.MinProgramTexelOffset - << ":MaxProgramTexelOffset:" << compileResources.MaxProgramTexelOffset - << ":MaxDualSourceDrawBuffers:" << compileResources.MaxDualSourceDrawBuffers - << ":MaxViewsOVR:" << compileResources.MaxViewsOVR - << ":NV_draw_buffers:" << compileResources.NV_draw_buffers - << ":WEBGL_debug_shader_precision:" << compileResources.WEBGL_debug_shader_precision - << ":MinProgramTextureGatherOffset:" << compileResources.MinProgramTextureGatherOffset - << ":MaxProgramTextureGatherOffset:" << compileResources.MaxProgramTextureGatherOffset - << ":MaxImageUnits:" << compileResources.MaxImageUnits - << ":MaxVertexImageUniforms:" << compileResources.MaxVertexImageUniforms - << ":MaxFragmentImageUniforms:" << compileResources.MaxFragmentImageUniforms - << ":MaxComputeImageUniforms:" << compileResources.MaxComputeImageUniforms - << ":MaxCombinedImageUniforms:" << compileResources.MaxCombinedImageUniforms - << ":MaxCombinedShaderOutputResources:" << compileResources.MaxCombinedShaderOutputResources - << ":MaxComputeWorkGroupCountX:" << compileResources.MaxComputeWorkGroupCount[0] - << ":MaxComputeWorkGroupCountY:" << compileResources.MaxComputeWorkGroupCount[1] - << ":MaxComputeWorkGroupCountZ:" << compileResources.MaxComputeWorkGroupCount[2] - << ":MaxComputeWorkGroupSizeX:" << compileResources.MaxComputeWorkGroupSize[0] - << ":MaxComputeWorkGroupSizeY:" << compileResources.MaxComputeWorkGroupSize[1] - << ":MaxComputeWorkGroupSizeZ:" << compileResources.MaxComputeWorkGroupSize[2] - << ":MaxComputeUniformComponents:" << compileResources.MaxComputeUniformComponents - << ":MaxComputeTextureImageUnits:" << compileResources.MaxComputeTextureImageUnits - << ":MaxComputeAtomicCounters:" << compileResources.MaxComputeAtomicCounters - << ":MaxComputeAtomicCounterBuffers:" << compileResources.MaxComputeAtomicCounterBuffers - << ":MaxVertexAtomicCounters:" << compileResources.MaxVertexAtomicCounters - << ":MaxFragmentAtomicCounters:" << compileResources.MaxFragmentAtomicCounters - << ":MaxCombinedAtomicCounters:" << compileResources.MaxCombinedAtomicCounters - << ":MaxAtomicCounterBindings:" << compileResources.MaxAtomicCounterBindings - << ":MaxVertexAtomicCounterBuffers:" << compileResources.MaxVertexAtomicCounterBuffers - << ":MaxFragmentAtomicCounterBuffers:" << compileResources.MaxFragmentAtomicCounterBuffers - << ":MaxCombinedAtomicCounterBuffers:" << compileResources.MaxCombinedAtomicCounterBuffers - << ":MaxAtomicCounterBufferSize:" << compileResources.MaxAtomicCounterBufferSize - << ":MaxGeometryUniformComponents:" << compileResources.MaxGeometryUniformComponents - << ":MaxGeometryUniformBlocks:" << compileResources.MaxGeometryUniformBlocks - << ":MaxGeometryInputComponents:" << compileResources.MaxGeometryInputComponents - << ":MaxGeometryOutputComponents:" << compileResources.MaxGeometryOutputComponents - << ":MaxGeometryOutputVertices:" << compileResources.MaxGeometryOutputVertices - << ":MaxGeometryTotalOutputComponents:" << compileResources.MaxGeometryTotalOutputComponents - << ":MaxGeometryTextureImageUnits:" << compileResources.MaxGeometryTextureImageUnits - << ":MaxGeometryAtomicCounterBuffers:" << compileResources.MaxGeometryAtomicCounterBuffers - << ":MaxGeometryAtomicCounters:" << compileResources.MaxGeometryAtomicCounters - << ":MaxGeometryShaderStorageBlocks:" << compileResources.MaxGeometryShaderStorageBlocks - << ":MaxGeometryShaderInvocations:" << compileResources.MaxGeometryShaderInvocations - << ":MaxGeometryImageUniforms:" << compileResources.MaxGeometryImageUniforms; - // clang-format on - - builtInResourcesString = strstream.str(); -} - -void TCompiler::collectInterfaceBlocks() -{ - ASSERT(interfaceBlocks.empty()); - interfaceBlocks.reserve(uniformBlocks.size() + shaderStorageBlocks.size() + inBlocks.size()); - interfaceBlocks.insert(interfaceBlocks.end(), uniformBlocks.begin(), uniformBlocks.end()); - interfaceBlocks.insert(interfaceBlocks.end(), shaderStorageBlocks.begin(), - shaderStorageBlocks.end()); - interfaceBlocks.insert(interfaceBlocks.end(), inBlocks.begin(), inBlocks.end()); -} - -void TCompiler::clearResults() -{ - arrayBoundsClamper.Cleanup(); - infoSink.info.erase(); - infoSink.obj.erase(); - infoSink.debug.erase(); - mDiagnostics.resetErrorCount(); - - attributes.clear(); - outputVariables.clear(); - uniforms.clear(); - inputVaryings.clear(); - outputVaryings.clear(); - interfaceBlocks.clear(); - uniformBlocks.clear(); - shaderStorageBlocks.clear(); - inBlocks.clear(); - variablesCollected = false; - mGLPositionInitialized = false; - - mNumViews = -1; - - mGeometryShaderInputPrimitiveType = EptUndefined; - mGeometryShaderOutputPrimitiveType = EptUndefined; - mGeometryShaderInvocations = 0; - mGeometryShaderMaxVertices = -1; - - builtInFunctionEmulator.cleanup(); - - nameMap.clear(); - - mSourcePath = nullptr; -} - -bool TCompiler::initCallDag(TIntermNode *root) -{ - mCallDag.clear(); - - switch (mCallDag.init(root, &mDiagnostics)) - { - case CallDAG::INITDAG_SUCCESS: - return true; - case CallDAG::INITDAG_RECURSION: - case CallDAG::INITDAG_UNDEFINED: - // Error message has already been written out. - ASSERT(mDiagnostics.numErrors() > 0); - return false; - } - - UNREACHABLE(); - return true; -} - -bool TCompiler::checkCallDepth() -{ - std::vector depths(mCallDag.size()); - - for (size_t i = 0; i < mCallDag.size(); i++) - { - int depth = 0; - auto &record = mCallDag.getRecordFromIndex(i); - - for (auto &calleeIndex : record.callees) - { - depth = std::max(depth, depths[calleeIndex] + 1); - } - - depths[i] = depth; - - if (depth >= maxCallStackDepth) - { - // Trace back the function chain to have a meaningful info log. - std::stringstream errorStream; - errorStream << "Call stack too deep (larger than " << maxCallStackDepth - << ") with the following call chain: " << record.name; - - int currentFunction = static_cast(i); - int currentDepth = depth; - - while (currentFunction != -1) - { - errorStream << " -> " << mCallDag.getRecordFromIndex(currentFunction).name; - - int nextFunction = -1; - for (auto &calleeIndex : mCallDag.getRecordFromIndex(currentFunction).callees) - { - if (depths[calleeIndex] == currentDepth - 1) - { - currentDepth--; - nextFunction = calleeIndex; - } - } - - currentFunction = nextFunction; - } - - std::string errorStr = errorStream.str(); - mDiagnostics.globalError(errorStr.c_str()); - - return false; - } - } - - return true; -} - -bool TCompiler::tagUsedFunctions() -{ - // Search from main, starting from the end of the DAG as it usually is the root. - for (size_t i = mCallDag.size(); i-- > 0;) - { - if (mCallDag.getRecordFromIndex(i).name == "main") - { - internalTagUsedFunction(i); - return true; - } - } - - mDiagnostics.globalError("Missing main()"); - return false; -} - -void TCompiler::internalTagUsedFunction(size_t index) -{ - if (functionMetadata[index].used) - { - return; - } - - functionMetadata[index].used = true; - - for (int calleeIndex : mCallDag.getRecordFromIndex(index).callees) - { - internalTagUsedFunction(calleeIndex); - } -} - -// A predicate for the stl that returns if a top-level node is unused -class TCompiler::UnusedPredicate -{ - public: - UnusedPredicate(const CallDAG *callDag, const std::vector *metadatas) - : mCallDag(callDag), mMetadatas(metadatas) - { - } - - bool operator()(TIntermNode *node) - { - const TIntermFunctionPrototype *asFunctionPrototype = node->getAsFunctionPrototypeNode(); - const TIntermFunctionDefinition *asFunctionDefinition = node->getAsFunctionDefinition(); - - const TFunctionSymbolInfo *functionInfo = nullptr; - - if (asFunctionDefinition) - { - functionInfo = asFunctionDefinition->getFunctionSymbolInfo(); - } - else if (asFunctionPrototype) - { - functionInfo = asFunctionPrototype->getFunctionSymbolInfo(); - } - if (functionInfo == nullptr) - { - return false; - } - - size_t callDagIndex = mCallDag->findIndex(functionInfo); - if (callDagIndex == CallDAG::InvalidIndex) - { - // This happens only for unimplemented prototypes which are thus unused - ASSERT(asFunctionPrototype); - return true; - } - - ASSERT(callDagIndex < mMetadatas->size()); - return !(*mMetadatas)[callDagIndex].used; - } - - private: - const CallDAG *mCallDag; - const std::vector *mMetadatas; -}; - -void TCompiler::pruneUnusedFunctions(TIntermBlock *root) -{ - UnusedPredicate isUnused(&mCallDag, &functionMetadata); - TIntermSequence *sequence = root->getSequence(); - - if (!sequence->empty()) - { - sequence->erase(std::remove_if(sequence->begin(), sequence->end(), isUnused), - sequence->end()); - } -} - -bool TCompiler::limitExpressionComplexity(TIntermBlock *root) -{ - if (!IsASTDepthBelowLimit(root, maxExpressionComplexity)) - { - mDiagnostics.globalError("Expression too complex."); - return false; - } - - if (!ValidateMaxParameters(root, maxFunctionParameters)) - { - mDiagnostics.globalError("Function has too many parameters."); - return false; - } - - return true; -} - -bool TCompiler::shouldCollectVariables(ShCompileOptions compileOptions) -{ - return (compileOptions & SH_VARIABLES) != 0; -} - -bool TCompiler::wereVariablesCollected() const -{ - return variablesCollected; -} - -void TCompiler::initializeGLPosition(TIntermBlock *root) -{ - InitVariableList list; - sh::ShaderVariable var(GL_FLOAT_VEC4); - var.name = "gl_Position"; - list.push_back(var); - InitializeVariables(root, list, &symbolTable, shaderVersion, extensionBehavior, false); -} - -void TCompiler::useAllMembersInUnusedStandardAndSharedBlocks(TIntermBlock *root) -{ - sh::InterfaceBlockList list; - - for (auto block : uniformBlocks) - { - if (!block.staticUse && - (block.layout == sh::BLOCKLAYOUT_STD140 || block.layout == sh::BLOCKLAYOUT_SHARED)) - { - list.push_back(block); - } - } - - sh::UseInterfaceBlockFields(root, list, symbolTable); -} - -void TCompiler::initializeOutputVariables(TIntermBlock *root) -{ - InitVariableList list; - if (shaderType == GL_VERTEX_SHADER || shaderType == GL_GEOMETRY_SHADER_OES) - { - for (auto var : outputVaryings) - { - list.push_back(var); - if (var.name == "gl_Position") - { - ASSERT(!mGLPositionInitialized); - mGLPositionInitialized = true; - } - } - } - else - { - ASSERT(shaderType == GL_FRAGMENT_SHADER); - for (auto var : outputVariables) - { - list.push_back(var); - } - } - InitializeVariables(root, list, &symbolTable, shaderVersion, extensionBehavior, false); -} - -const TExtensionBehavior &TCompiler::getExtensionBehavior() const -{ - return extensionBehavior; -} - -const char *TCompiler::getSourcePath() const -{ - return mSourcePath; -} - -const ShBuiltInResources &TCompiler::getResources() const -{ - return compileResources; -} - -const ArrayBoundsClamper &TCompiler::getArrayBoundsClamper() const -{ - return arrayBoundsClamper; -} - -ShArrayIndexClampingStrategy TCompiler::getArrayIndexClampingStrategy() const -{ - return clampingStrategy; -} - -const BuiltInFunctionEmulator &TCompiler::getBuiltInFunctionEmulator() const -{ - return builtInFunctionEmulator; -} - -void TCompiler::writePragma(ShCompileOptions compileOptions) -{ - if (!(compileOptions & SH_FLATTEN_PRAGMA_STDGL_INVARIANT_ALL)) - { - TInfoSinkBase &sink = infoSink.obj; - if (mPragma.stdgl.invariantAll) - sink << "#pragma STDGL invariant(all)\n"; - } -} - -bool TCompiler::isVaryingDefined(const char *varyingName) -{ - ASSERT(variablesCollected); - for (size_t ii = 0; ii < inputVaryings.size(); ++ii) - { - if (inputVaryings[ii].name == varyingName) - { - return true; - } - } - for (size_t ii = 0; ii < outputVaryings.size(); ++ii) - { - if (outputVaryings[ii].name == varyingName) - { - return true; - } - } - - return false; -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/Compiler.h b/src/3rdparty/angle/src/compiler/translator/Compiler.h deleted file mode 100644 index 753cfb8e7b..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/Compiler.h +++ /dev/null @@ -1,308 +0,0 @@ -// -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_TRANSLATOR_COMPILER_H_ -#define COMPILER_TRANSLATOR_COMPILER_H_ - -// -// Machine independent part of the compiler private objects -// sent as ShHandle to the driver. -// -// This should not be included by driver code. -// - -#include - -#include "compiler/translator/BuiltInFunctionEmulator.h" -#include "compiler/translator/CallDAG.h" -#include "compiler/translator/Diagnostics.h" -#include "compiler/translator/ExtensionBehavior.h" -#include "compiler/translator/HashNames.h" -#include "compiler/translator/InfoSink.h" -#include "compiler/translator/Pragma.h" -#include "compiler/translator/SymbolTable.h" -#include "third_party/compiler/ArrayBoundsClamper.h" - -namespace sh -{ - -class TCompiler; -class TParseContext; -#ifdef ANGLE_ENABLE_HLSL -class TranslatorHLSL; -#endif // ANGLE_ENABLE_HLSL - -// -// Helper function to identify specs that are based on the WebGL spec. -// -bool IsWebGLBasedSpec(ShShaderSpec spec); - -// -// Helper function to check if the shader type is GLSL. -// -bool IsGLSL130OrNewer(ShShaderOutput output); -bool IsGLSL420OrNewer(ShShaderOutput output); -bool IsGLSL410OrOlder(ShShaderOutput output); - -// -// Helper function to check if the invariant qualifier can be removed. -// -bool RemoveInvariant(sh::GLenum shaderType, - int shaderVersion, - ShShaderOutput outputType, - ShCompileOptions compileOptions); - -// -// The base class used to back handles returned to the driver. -// -class TShHandleBase -{ - public: - TShHandleBase(); - virtual ~TShHandleBase(); - virtual TCompiler *getAsCompiler() { return 0; } -#ifdef ANGLE_ENABLE_HLSL - virtual TranslatorHLSL *getAsTranslatorHLSL() { return 0; } -#endif // ANGLE_ENABLE_HLSL - - protected: - // Memory allocator. Allocates and tracks memory required by the compiler. - // Deallocates all memory when compiler is destructed. - TPoolAllocator allocator; -}; - -// -// The base class for the machine dependent compiler to derive from -// for managing object code from the compile. -// -class TCompiler : public TShHandleBase -{ - public: - TCompiler(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output); - ~TCompiler() override; - TCompiler *getAsCompiler() override { return this; } - - bool Init(const ShBuiltInResources &resources); - - // compileTreeForTesting should be used only when tests require access to - // the AST. Users of this function need to manually manage the global pool - // allocator. Returns nullptr whenever there are compilation errors. - TIntermBlock *compileTreeForTesting(const char *const shaderStrings[], - size_t numStrings, - ShCompileOptions compileOptions); - - bool compile(const char *const shaderStrings[], - size_t numStrings, - ShCompileOptions compileOptions); - - // Get results of the last compilation. - int getShaderVersion() const { return shaderVersion; } - TInfoSink &getInfoSink() { return infoSink; } - - bool isComputeShaderLocalSizeDeclared() const { return mComputeShaderLocalSizeDeclared; } - const sh::WorkGroupSize &getComputeShaderLocalSize() const { return mComputeShaderLocalSize; } - int getNumViews() const { return mNumViews; } - - // Clears the results from the previous compilation. - void clearResults(); - - const std::vector &getAttributes() const { return attributes; } - const std::vector &getOutputVariables() const { return outputVariables; } - const std::vector &getUniforms() const { return uniforms; } - const std::vector &getInputVaryings() const { return inputVaryings; } - const std::vector &getOutputVaryings() const { return outputVaryings; } - const std::vector &getInterfaceBlocks() const { return interfaceBlocks; } - const std::vector &getUniformBlocks() const { return uniformBlocks; } - const std::vector &getShaderStorageBlocks() const - { - return shaderStorageBlocks; - } - const std::vector &getInBlocks() const { return inBlocks; } - - ShHashFunction64 getHashFunction() const { return hashFunction; } - NameMap &getNameMap() { return nameMap; } - TSymbolTable &getSymbolTable() { return symbolTable; } - ShShaderSpec getShaderSpec() const { return shaderSpec; } - ShShaderOutput getOutputType() const { return outputType; } - const std::string &getBuiltInResourcesString() const { return builtInResourcesString; } - - bool shouldRunLoopAndIndexingValidation(ShCompileOptions compileOptions) const; - - // Get the resources set by InitBuiltInSymbolTable - const ShBuiltInResources &getResources() const; - - int getGeometryShaderMaxVertices() const { return mGeometryShaderMaxVertices; } - int getGeometryShaderInvocations() const { return mGeometryShaderInvocations; } - TLayoutPrimitiveType getGeometryShaderInputPrimitiveType() const - { - return mGeometryShaderInputPrimitiveType; - } - TLayoutPrimitiveType getGeometryShaderOutputPrimitiveType() const - { - return mGeometryShaderOutputPrimitiveType; - } - - sh::GLenum getShaderType() const { return shaderType; } - - protected: - // Initialize symbol-table with built-in symbols. - bool InitBuiltInSymbolTable(const ShBuiltInResources &resources); - // Compute the string representation of the built-in resources - void setResourceString(); - // Return false if the call depth is exceeded. - bool checkCallDepth(); - // Add emulated functions to the built-in function emulator. - virtual void initBuiltInFunctionEmulator(BuiltInFunctionEmulator *emu, - ShCompileOptions compileOptions){}; - // Translate to object code. May generate performance warnings through the diagnostics. - virtual void translate(TIntermBlock *root, - ShCompileOptions compileOptions, - PerformanceDiagnostics *perfDiagnostics) = 0; - // Insert statements to reference all members in unused uniform blocks with standard and shared - // layout. This is to work around a Mac driver that treats unused standard/shared - // uniform blocks as inactive. - void useAllMembersInUnusedStandardAndSharedBlocks(TIntermBlock *root); - // Insert statements to initialize output variables in the beginning of main(). - // This is to avoid undefined behaviors. - void initializeOutputVariables(TIntermBlock *root); - // Insert gl_Position = vec4(0,0,0,0) to the beginning of main(). - // It is to work around a Linux driver bug where missing this causes compile failure - // while spec says it is allowed. - // This function should only be applied to vertex shaders. - void initializeGLPosition(TIntermBlock *root); - // Return true if the maximum expression complexity is below the limit. - bool limitExpressionComplexity(TIntermBlock *root); - // Get built-in extensions with default behavior. - const TExtensionBehavior &getExtensionBehavior() const; - const char *getSourcePath() const; - const TPragma &getPragma() const { return mPragma; } - void writePragma(ShCompileOptions compileOptions); - // Relies on collectVariables having been called. - bool isVaryingDefined(const char *varyingName); - - const ArrayBoundsClamper &getArrayBoundsClamper() const; - ShArrayIndexClampingStrategy getArrayIndexClampingStrategy() const; - const BuiltInFunctionEmulator &getBuiltInFunctionEmulator() const; - - virtual bool shouldFlattenPragmaStdglInvariantAll() = 0; - virtual bool shouldCollectVariables(ShCompileOptions compileOptions); - - bool wereVariablesCollected() const; - std::vector attributes; - std::vector outputVariables; - std::vector uniforms; - std::vector inputVaryings; - std::vector outputVaryings; - std::vector interfaceBlocks; - std::vector uniformBlocks; - std::vector shaderStorageBlocks; - std::vector inBlocks; - - private: - // Creates the function call DAG for further analysis, returning false if there is a recursion - bool initCallDag(TIntermNode *root); - // Return false if "main" doesn't exist - bool tagUsedFunctions(); - void internalTagUsedFunction(size_t index); - - void initSamplerDefaultPrecision(TBasicType samplerType); - - void collectInterfaceBlocks(); - - bool variablesCollected; - - bool mGLPositionInitialized; - - // Removes unused function declarations and prototypes from the AST - class UnusedPredicate; - void pruneUnusedFunctions(TIntermBlock *root); - - TIntermBlock *compileTreeImpl(const char *const shaderStrings[], - size_t numStrings, - const ShCompileOptions compileOptions); - - // Fetches and stores shader metadata that is not stored within the AST itself, such as shader - // version. - void setASTMetadata(const TParseContext &parseContext); - - // Does checks that need to be run after parsing is complete and returns true if they pass. - bool checkAndSimplifyAST(TIntermBlock *root, - const TParseContext &parseContext, - ShCompileOptions compileOptions); - - sh::GLenum shaderType; - ShShaderSpec shaderSpec; - ShShaderOutput outputType; - - struct FunctionMetadata - { - FunctionMetadata() : used(false) {} - bool used; - }; - - CallDAG mCallDag; - std::vector functionMetadata; - - int maxUniformVectors; - int maxExpressionComplexity; - int maxCallStackDepth; - int maxFunctionParameters; - - ShBuiltInResources compileResources; - std::string builtInResourcesString; - - // Built-in symbol table for the given language, spec, and resources. - // It is preserved from compile-to-compile. - TSymbolTable symbolTable; - // Built-in extensions with default behavior. - TExtensionBehavior extensionBehavior; - bool fragmentPrecisionHigh; - - ArrayBoundsClamper arrayBoundsClamper; - ShArrayIndexClampingStrategy clampingStrategy; - BuiltInFunctionEmulator builtInFunctionEmulator; - - // Results of compilation. - int shaderVersion; - TInfoSink infoSink; // Output sink. - TDiagnostics mDiagnostics; - const char *mSourcePath; // Path of source file or NULL - - // compute shader local group size - bool mComputeShaderLocalSizeDeclared; - sh::WorkGroupSize mComputeShaderLocalSize; - - // GL_OVR_multiview num_views. - int mNumViews; - - // geometry shader parameters. - int mGeometryShaderMaxVertices; - int mGeometryShaderInvocations; - TLayoutPrimitiveType mGeometryShaderInputPrimitiveType; - TLayoutPrimitiveType mGeometryShaderOutputPrimitiveType; - - // name hashing. - ShHashFunction64 hashFunction; - NameMap nameMap; - - TPragma mPragma; -}; - -// -// 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(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output); -void DeleteCompiler(TCompiler *); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_COMPILER_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/ConstantUnion.cpp b/src/3rdparty/angle/src/compiler/translator/ConstantUnion.cpp deleted file mode 100644 index 7004aedee3..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/ConstantUnion.cpp +++ /dev/null @@ -1,681 +0,0 @@ -// -// Copyright 2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// ConstantUnion: Constant folding helper class. - -#include "compiler/translator/ConstantUnion.h" - -#include "common/mathutil.h" -#include "compiler/translator/Diagnostics.h" - -namespace sh -{ - -namespace -{ - -float CheckedSum(float lhs, float rhs, TDiagnostics *diag, const TSourceLoc &line) -{ - float result = lhs + rhs; - if (gl::isNaN(result) && !gl::isNaN(lhs) && !gl::isNaN(rhs)) - { - diag->warning(line, "Constant folded undefined addition generated NaN", "+"); - } - else if (gl::isInf(result) && !gl::isInf(lhs) && !gl::isInf(rhs)) - { - diag->warning(line, "Constant folded addition overflowed to infinity", "+"); - } - return result; -} - -float CheckedDiff(float lhs, float rhs, TDiagnostics *diag, const TSourceLoc &line) -{ - float result = lhs - rhs; - if (gl::isNaN(result) && !gl::isNaN(lhs) && !gl::isNaN(rhs)) - { - diag->warning(line, "Constant folded undefined subtraction generated NaN", "-"); - } - else if (gl::isInf(result) && !gl::isInf(lhs) && !gl::isInf(rhs)) - { - diag->warning(line, "Constant folded subtraction overflowed to infinity", "-"); - } - return result; -} - -float CheckedMul(float lhs, float rhs, TDiagnostics *diag, const TSourceLoc &line) -{ - float result = lhs * rhs; - if (gl::isNaN(result) && !gl::isNaN(lhs) && !gl::isNaN(rhs)) - { - diag->warning(line, "Constant folded undefined multiplication generated NaN", "*"); - } - else if (gl::isInf(result) && !gl::isInf(lhs) && !gl::isInf(rhs)) - { - diag->warning(line, "Constant folded multiplication overflowed to infinity", "*"); - } - return result; -} - -bool IsValidShiftOffset(const TConstantUnion &rhs) -{ - return (rhs.getType() == EbtInt && (rhs.getIConst() >= 0 && rhs.getIConst() <= 31)) || - (rhs.getType() == EbtUInt && rhs.getUConst() <= 31u); -} - -} // anonymous namespace - -TConstantUnion::TConstantUnion() -{ - iConst = 0; - type = EbtVoid; -} - -int TConstantUnion::getIConst() const -{ - ASSERT(type == EbtInt); - return iConst; -} - -unsigned int TConstantUnion::getUConst() const -{ - ASSERT(type == EbtUInt); - return uConst; -} - -float TConstantUnion::getFConst() const -{ - ASSERT(type == EbtFloat); - return fConst; -} - -bool TConstantUnion::getBConst() const -{ - ASSERT(type == EbtBool); - return bConst; -} - -TYuvCscStandardEXT TConstantUnion::getYuvCscStandardEXTConst() const -{ - ASSERT(type == EbtYuvCscStandardEXT); - return yuvCscStandardEXTConst; -} - -bool TConstantUnion::cast(TBasicType newType, const TConstantUnion &constant) -{ - switch (newType) - { - case EbtFloat: - switch (constant.type) - { - case EbtInt: - setFConst(static_cast(constant.getIConst())); - break; - case EbtUInt: - setFConst(static_cast(constant.getUConst())); - break; - case EbtBool: - setFConst(static_cast(constant.getBConst())); - break; - case EbtFloat: - setFConst(static_cast(constant.getFConst())); - break; - default: - return false; - } - break; - case EbtInt: - switch (constant.type) - { - case EbtInt: - setIConst(static_cast(constant.getIConst())); - break; - case EbtUInt: - setIConst(static_cast(constant.getUConst())); - break; - case EbtBool: - setIConst(static_cast(constant.getBConst())); - break; - case EbtFloat: - setIConst(static_cast(constant.getFConst())); - break; - default: - return false; - } - break; - case EbtUInt: - switch (constant.type) - { - case EbtInt: - setUConst(static_cast(constant.getIConst())); - break; - case EbtUInt: - setUConst(static_cast(constant.getUConst())); - break; - case EbtBool: - setUConst(static_cast(constant.getBConst())); - break; - case EbtFloat: - setUConst(static_cast(constant.getFConst())); - break; - default: - return false; - } - break; - case EbtBool: - switch (constant.type) - { - case EbtInt: - setBConst(constant.getIConst() != 0); - break; - case EbtUInt: - setBConst(constant.getUConst() != 0); - break; - case EbtBool: - setBConst(constant.getBConst()); - break; - case EbtFloat: - setBConst(constant.getFConst() != 0.0f); - break; - default: - return false; - } - break; - case EbtStruct: // Struct fields don't get cast - switch (constant.type) - { - case EbtInt: - setIConst(constant.getIConst()); - break; - case EbtUInt: - setUConst(constant.getUConst()); - break; - case EbtBool: - setBConst(constant.getBConst()); - break; - case EbtFloat: - setFConst(constant.getFConst()); - break; - default: - return false; - } - break; - default: - return false; - } - - return true; -} - -bool TConstantUnion::operator==(const int i) const -{ - return i == iConst; -} - -bool TConstantUnion::operator==(const unsigned int u) const -{ - return u == uConst; -} - -bool TConstantUnion::operator==(const float f) const -{ - return f == fConst; -} - -bool TConstantUnion::operator==(const bool b) const -{ - return b == bConst; -} - -bool TConstantUnion::operator==(const TYuvCscStandardEXT s) const -{ - return s == yuvCscStandardEXTConst; -} - -bool TConstantUnion::operator==(const TConstantUnion &constant) const -{ - if (constant.type != type) - return false; - - switch (type) - { - case EbtInt: - return constant.iConst == iConst; - case EbtUInt: - return constant.uConst == uConst; - case EbtFloat: - return constant.fConst == fConst; - case EbtBool: - return constant.bConst == bConst; - case EbtYuvCscStandardEXT: - return constant.yuvCscStandardEXTConst == yuvCscStandardEXTConst; - default: - return false; - } -} - -bool TConstantUnion::operator!=(const int i) const -{ - return !operator==(i); -} - -bool TConstantUnion::operator!=(const unsigned int u) const -{ - return !operator==(u); -} - -bool TConstantUnion::operator!=(const float f) const -{ - return !operator==(f); -} - -bool TConstantUnion::operator!=(const bool b) const -{ - return !operator==(b); -} - -bool TConstantUnion::operator!=(const TYuvCscStandardEXT s) const -{ - return !operator==(s); -} - -bool TConstantUnion::operator!=(const TConstantUnion &constant) const -{ - return !operator==(constant); -} - -bool TConstantUnion::operator>(const TConstantUnion &constant) const -{ - ASSERT(type == constant.type); - switch (type) - { - case EbtInt: - return iConst > constant.iConst; - case EbtUInt: - return uConst > constant.uConst; - case EbtFloat: - return fConst > constant.fConst; - default: - return false; // Invalid operation, handled at semantic analysis - } -} - -bool TConstantUnion::operator<(const TConstantUnion &constant) const -{ - ASSERT(type == constant.type); - switch (type) - { - case EbtInt: - return iConst < constant.iConst; - case EbtUInt: - return uConst < constant.uConst; - case EbtFloat: - return fConst < constant.fConst; - default: - return false; // Invalid operation, handled at semantic analysis - } -} - -// static -TConstantUnion TConstantUnion::add(const TConstantUnion &lhs, - const TConstantUnion &rhs, - TDiagnostics *diag, - const TSourceLoc &line) -{ - TConstantUnion returnValue; - ASSERT(lhs.type == rhs.type); - switch (lhs.type) - { - case EbtInt: - returnValue.setIConst(gl::WrappingSum(lhs.iConst, rhs.iConst)); - break; - case EbtUInt: - returnValue.setUConst(gl::WrappingSum(lhs.uConst, rhs.uConst)); - break; - case EbtFloat: - returnValue.setFConst(CheckedSum(lhs.fConst, rhs.fConst, diag, line)); - break; - default: - UNREACHABLE(); - } - - return returnValue; -} - -// static -TConstantUnion TConstantUnion::sub(const TConstantUnion &lhs, - const TConstantUnion &rhs, - TDiagnostics *diag, - const TSourceLoc &line) -{ - TConstantUnion returnValue; - ASSERT(lhs.type == rhs.type); - switch (lhs.type) - { - case EbtInt: - returnValue.setIConst(gl::WrappingDiff(lhs.iConst, rhs.iConst)); - break; - case EbtUInt: - returnValue.setUConst(gl::WrappingDiff(lhs.uConst, rhs.uConst)); - break; - case EbtFloat: - returnValue.setFConst(CheckedDiff(lhs.fConst, rhs.fConst, diag, line)); - break; - default: - UNREACHABLE(); - } - - return returnValue; -} - -// static -TConstantUnion TConstantUnion::mul(const TConstantUnion &lhs, - const TConstantUnion &rhs, - TDiagnostics *diag, - const TSourceLoc &line) -{ - TConstantUnion returnValue; - ASSERT(lhs.type == rhs.type); - switch (lhs.type) - { - case EbtInt: - returnValue.setIConst(gl::WrappingMul(lhs.iConst, rhs.iConst)); - break; - case EbtUInt: - // Unsigned integer math in C++ is defined to be done in modulo 2^n, so we rely on that - // to implement wrapping multiplication. - returnValue.setUConst(lhs.uConst * rhs.uConst); - break; - case EbtFloat: - returnValue.setFConst(CheckedMul(lhs.fConst, rhs.fConst, diag, line)); - break; - default: - UNREACHABLE(); - } - - return returnValue; -} - -TConstantUnion TConstantUnion::operator%(const TConstantUnion &constant) const -{ - TConstantUnion returnValue; - ASSERT(type == constant.type); - switch (type) - { - case EbtInt: - returnValue.setIConst(iConst % constant.iConst); - break; - case EbtUInt: - returnValue.setUConst(uConst % constant.uConst); - break; - default: - UNREACHABLE(); - } - - return returnValue; -} - -// static -TConstantUnion TConstantUnion::rshift(const TConstantUnion &lhs, - const TConstantUnion &rhs, - TDiagnostics *diag, - const TSourceLoc &line) -{ - TConstantUnion returnValue; - ASSERT(lhs.type == EbtInt || lhs.type == EbtUInt); - ASSERT(rhs.type == EbtInt || rhs.type == EbtUInt); - if (!IsValidShiftOffset(rhs)) - { - diag->warning(line, "Undefined shift (operand out of range)", ">>"); - switch (lhs.type) - { - case EbtInt: - returnValue.setIConst(0); - break; - case EbtUInt: - returnValue.setUConst(0u); - break; - default: - UNREACHABLE(); - } - return returnValue; - } - - switch (lhs.type) - { - case EbtInt: - { - unsigned int shiftOffset = 0; - switch (rhs.type) - { - case EbtInt: - shiftOffset = static_cast(rhs.iConst); - break; - case EbtUInt: - shiftOffset = rhs.uConst; - break; - default: - UNREACHABLE(); - } - if (shiftOffset > 0) - { - // ESSL 3.00.6 section 5.9: "If E1 is a signed integer, the right-shift will extend - // the sign bit." In C++ shifting negative integers is undefined, so we implement - // extending the sign bit manually. - int lhsSafe = lhs.iConst; - if (lhsSafe == std::numeric_limits::min()) - { - // The min integer needs special treatment because only bit it has set is the - // sign bit, which we clear later to implement safe right shift of negative - // numbers. - lhsSafe = -0x40000000; - --shiftOffset; - } - if (shiftOffset > 0) - { - bool extendSignBit = false; - if (lhsSafe < 0) - { - extendSignBit = true; - // Clear the sign bit so that bitshift right is defined in C++. - lhsSafe &= 0x7fffffff; - ASSERT(lhsSafe > 0); - } - returnValue.setIConst(lhsSafe >> shiftOffset); - - // Manually fill in the extended sign bit if necessary. - if (extendSignBit) - { - int extendedSignBit = static_cast(0xffffffffu << (31 - shiftOffset)); - returnValue.setIConst(returnValue.getIConst() | extendedSignBit); - } - } - else - { - returnValue.setIConst(lhsSafe); - } - } - else - { - returnValue.setIConst(lhs.iConst); - } - break; - } - case EbtUInt: - switch (rhs.type) - { - case EbtInt: - returnValue.setUConst(lhs.uConst >> rhs.iConst); - break; - case EbtUInt: - returnValue.setUConst(lhs.uConst >> rhs.uConst); - break; - default: - UNREACHABLE(); - } - break; - - default: - UNREACHABLE(); - } - return returnValue; -} - -// static -TConstantUnion TConstantUnion::lshift(const TConstantUnion &lhs, - const TConstantUnion &rhs, - TDiagnostics *diag, - const TSourceLoc &line) -{ - TConstantUnion returnValue; - ASSERT(lhs.type == EbtInt || lhs.type == EbtUInt); - ASSERT(rhs.type == EbtInt || rhs.type == EbtUInt); - if (!IsValidShiftOffset(rhs)) - { - diag->warning(line, "Undefined shift (operand out of range)", "<<"); - switch (lhs.type) - { - case EbtInt: - returnValue.setIConst(0); - break; - case EbtUInt: - returnValue.setUConst(0u); - break; - default: - UNREACHABLE(); - } - return returnValue; - } - - switch (lhs.type) - { - case EbtInt: - switch (rhs.type) - { - // Cast to unsigned integer before shifting, since ESSL 3.00.6 section 5.9 says that - // lhs is "interpreted as a bit pattern". This also avoids the possibility of signed - // integer overflow or undefined shift of a negative integer. - case EbtInt: - returnValue.setIConst( - static_cast(static_cast(lhs.iConst) << rhs.iConst)); - break; - case EbtUInt: - returnValue.setIConst( - static_cast(static_cast(lhs.iConst) << rhs.uConst)); - break; - default: - UNREACHABLE(); - } - break; - - case EbtUInt: - switch (rhs.type) - { - case EbtInt: - returnValue.setUConst(lhs.uConst << rhs.iConst); - break; - case EbtUInt: - returnValue.setUConst(lhs.uConst << rhs.uConst); - break; - default: - UNREACHABLE(); - } - break; - - default: - UNREACHABLE(); - } - return returnValue; -} - -TConstantUnion TConstantUnion::operator&(const TConstantUnion &constant) const -{ - TConstantUnion returnValue; - ASSERT(constant.type == EbtInt || constant.type == EbtUInt); - switch (type) - { - case EbtInt: - returnValue.setIConst(iConst & constant.iConst); - break; - case EbtUInt: - returnValue.setUConst(uConst & constant.uConst); - break; - default: - UNREACHABLE(); - } - - return returnValue; -} - -TConstantUnion TConstantUnion::operator|(const TConstantUnion &constant) const -{ - TConstantUnion returnValue; - ASSERT(type == constant.type); - switch (type) - { - case EbtInt: - returnValue.setIConst(iConst | constant.iConst); - break; - case EbtUInt: - returnValue.setUConst(uConst | constant.uConst); - break; - default: - UNREACHABLE(); - } - - return returnValue; -} - -TConstantUnion TConstantUnion::operator^(const TConstantUnion &constant) const -{ - TConstantUnion returnValue; - ASSERT(type == constant.type); - switch (type) - { - case EbtInt: - returnValue.setIConst(iConst ^ constant.iConst); - break; - case EbtUInt: - returnValue.setUConst(uConst ^ constant.uConst); - break; - default: - UNREACHABLE(); - } - - return returnValue; -} - -TConstantUnion TConstantUnion::operator&&(const TConstantUnion &constant) const -{ - TConstantUnion returnValue; - ASSERT(type == constant.type); - switch (type) - { - case EbtBool: - returnValue.setBConst(bConst && constant.bConst); - break; - default: - UNREACHABLE(); - } - - return returnValue; -} - -TConstantUnion TConstantUnion::operator||(const TConstantUnion &constant) const -{ - TConstantUnion returnValue; - ASSERT(type == constant.type); - switch (type) - { - case EbtBool: - returnValue.setBConst(bConst || constant.bConst); - break; - default: - UNREACHABLE(); - } - - return returnValue; -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/ConstantUnion.h b/src/3rdparty/angle/src/compiler/translator/ConstantUnion.h deleted file mode 100644 index c1b3db9070..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/ConstantUnion.h +++ /dev/null @@ -1,117 +0,0 @@ -// -// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_TRANSLATOR_CONSTANTUNION_H_ -#define COMPILER_TRANSLATOR_CONSTANTUNION_H_ - -#include - -#include "compiler/translator/Common.h" -#include "compiler/translator/BaseTypes.h" - -namespace sh -{ - -class TDiagnostics; - -class TConstantUnion -{ - public: - POOL_ALLOCATOR_NEW_DELETE(); - TConstantUnion(); - - bool cast(TBasicType newType, const TConstantUnion &constant); - - void setIConst(int i) - { - iConst = i; - type = EbtInt; - } - void setUConst(unsigned int u) - { - uConst = u; - type = EbtUInt; - } - void setFConst(float f) - { - fConst = f; - type = EbtFloat; - } - void setBConst(bool b) - { - bConst = b; - type = EbtBool; - } - - void setYuvCscStandardEXTConst(TYuvCscStandardEXT s) - { - yuvCscStandardEXTConst = s; - type = EbtYuvCscStandardEXT; - } - - int getIConst() const; - unsigned int getUConst() const; - float getFConst() const; - bool getBConst() const; - TYuvCscStandardEXT getYuvCscStandardEXTConst() const; - - bool operator==(const int i) const; - bool operator==(const unsigned int u) const; - bool operator==(const float f) const; - bool operator==(const bool b) const; - bool operator==(const TYuvCscStandardEXT s) const; - bool operator==(const TConstantUnion &constant) const; - bool operator!=(const int i) const; - bool operator!=(const unsigned int u) const; - bool operator!=(const float f) const; - bool operator!=(const bool b) const; - bool operator!=(const TYuvCscStandardEXT s) const; - bool operator!=(const TConstantUnion &constant) const; - bool operator>(const TConstantUnion &constant) const; - bool operator<(const TConstantUnion &constant) const; - static TConstantUnion add(const TConstantUnion &lhs, - const TConstantUnion &rhs, - TDiagnostics *diag, - const TSourceLoc &line); - static TConstantUnion sub(const TConstantUnion &lhs, - const TConstantUnion &rhs, - TDiagnostics *diag, - const TSourceLoc &line); - static TConstantUnion mul(const TConstantUnion &lhs, - const TConstantUnion &rhs, - TDiagnostics *diag, - const TSourceLoc &line); - TConstantUnion operator%(const TConstantUnion &constant) const; - static TConstantUnion rshift(const TConstantUnion &lhs, - const TConstantUnion &rhs, - TDiagnostics *diag, - const TSourceLoc &line); - static TConstantUnion lshift(const TConstantUnion &lhs, - const TConstantUnion &rhs, - TDiagnostics *diag, - const TSourceLoc &line); - TConstantUnion operator&(const TConstantUnion &constant) const; - TConstantUnion operator|(const TConstantUnion &constant) const; - TConstantUnion operator^(const TConstantUnion &constant) const; - TConstantUnion operator&&(const TConstantUnion &constant) const; - TConstantUnion operator||(const TConstantUnion &constant) const; - - TBasicType getType() const { return type; } - private: - union { - int iConst; // used for ivec, scalar ints - unsigned int uConst; // used for uvec, scalar uints - bool bConst; // used for bvec, scalar bools - float fConst; // used for vec, mat, scalar floats - TYuvCscStandardEXT yuvCscStandardEXTConst; - }; - - TBasicType type; -}; - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_CONSTANTUNION_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/DeclareAndInitBuiltinsForInstancedMultiview.cpp b/src/3rdparty/angle/src/compiler/translator/DeclareAndInitBuiltinsForInstancedMultiview.cpp deleted file mode 100644 index ce9828f1f9..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/DeclareAndInitBuiltinsForInstancedMultiview.cpp +++ /dev/null @@ -1,221 +0,0 @@ -// -// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// Applies the necessary AST transformations to support multiview rendering through instancing. -// Check the header file For more information. -// - -#include "compiler/translator/DeclareAndInitBuiltinsForInstancedMultiview.h" - -#include "compiler/translator/FindMain.h" -#include "compiler/translator/InitializeVariables.h" -#include "compiler/translator/IntermNode_util.h" -#include "compiler/translator/IntermTraverse.h" -#include "compiler/translator/SymbolTable.h" -#include "compiler/translator/util.h" - -namespace sh -{ - -namespace -{ - -class ReplaceVariableTraverser : public TIntermTraverser -{ - public: - ReplaceVariableTraverser(const TString &symbolName, TIntermSymbol *newSymbol) - : TIntermTraverser(true, false, false), mSymbolName(symbolName), mNewSymbol(newSymbol) - { - } - - void visitSymbol(TIntermSymbol *node) override - { - TName &name = node->getName(); - if (name.getString() == mSymbolName) - { - queueReplacement(mNewSymbol->deepCopy(), OriginalNode::IS_DROPPED); - } - } - - private: - TString mSymbolName; - TIntermSymbol *mNewSymbol; -}; - -TIntermSymbol *CreateGLInstanceIDSymbol(const TSymbolTable &symbolTable) -{ - return ReferenceBuiltInVariable("gl_InstanceID", symbolTable, 300); -} - -// Adds the InstanceID and ViewID_OVR initializers to the end of the initializers' sequence. -void InitializeViewIDAndInstanceID(TIntermTyped *viewIDSymbol, - TIntermTyped *instanceIDSymbol, - unsigned numberOfViews, - const TSymbolTable &symbolTable, - TIntermSequence *initializers) -{ - // Create an unsigned numberOfViews node. - TConstantUnion *numberOfViewsUnsignedConstant = new TConstantUnion(); - numberOfViewsUnsignedConstant->setUConst(numberOfViews); - TIntermConstantUnion *numberOfViewsUint = - new TIntermConstantUnion(numberOfViewsUnsignedConstant, TType(EbtUInt, EbpHigh, EvqConst)); - - // Create a uint(gl_InstanceID) node. - TIntermSequence *glInstanceIDSymbolCastArguments = new TIntermSequence(); - glInstanceIDSymbolCastArguments->push_back(CreateGLInstanceIDSymbol(symbolTable)); - TIntermAggregate *glInstanceIDAsUint = TIntermAggregate::CreateConstructor( - TType(EbtUInt, EbpHigh, EvqTemporary), glInstanceIDSymbolCastArguments); - - // Create a uint(gl_InstanceID) / numberOfViews node. - TIntermBinary *normalizedInstanceID = - new TIntermBinary(EOpDiv, glInstanceIDAsUint, numberOfViewsUint); - - // Create an int(uint(gl_InstanceID) / numberOfViews) node. - TIntermSequence *normalizedInstanceIDCastArguments = new TIntermSequence(); - normalizedInstanceIDCastArguments->push_back(normalizedInstanceID); - TIntermAggregate *normalizedInstanceIDAsInt = TIntermAggregate::CreateConstructor( - TType(EbtInt, EbpHigh, EvqTemporary), normalizedInstanceIDCastArguments); - - // Create an InstanceID = int(uint(gl_InstanceID) / numberOfViews) node. - TIntermBinary *instanceIDInitializer = - new TIntermBinary(EOpAssign, instanceIDSymbol->deepCopy(), normalizedInstanceIDAsInt); - initializers->push_back(instanceIDInitializer); - - // Create a uint(gl_InstanceID) % numberOfViews node. - TIntermBinary *normalizedViewID = - new TIntermBinary(EOpIMod, glInstanceIDAsUint->deepCopy(), numberOfViewsUint->deepCopy()); - - // Create a ViewID_OVR = uint(gl_InstanceID) % numberOfViews node. - TIntermBinary *viewIDInitializer = - new TIntermBinary(EOpAssign, viewIDSymbol->deepCopy(), normalizedViewID); - initializers->push_back(viewIDInitializer); -} - -// Replaces every occurrence of a symbol with the name specified in symbolName with newSymbolNode. -void ReplaceSymbol(TIntermBlock *root, const TString &symbolName, TIntermSymbol *newSymbolNode) -{ - ReplaceVariableTraverser traverser(symbolName, newSymbolNode); - root->traverse(&traverser); - traverser.updateTree(); -} - -void DeclareGlobalVariable(TIntermBlock *root, TIntermTyped *typedNode) -{ - TIntermSequence *globalSequence = root->getSequence(); - TIntermDeclaration *declaration = new TIntermDeclaration(); - declaration->appendDeclarator(typedNode->deepCopy()); - globalSequence->insert(globalSequence->begin(), declaration); -} - -// Adds a branch to write int(ViewID_OVR) to either gl_ViewportIndex or gl_Layer. The branch is -// added to the end of the initializers' sequence. -void SelectViewIndexInVertexShader(TIntermTyped *viewIDSymbol, - TIntermTyped *multiviewBaseViewLayerIndexSymbol, - TIntermSequence *initializers, - const TSymbolTable &symbolTable) -{ - // Create an int(ViewID_OVR) node. - TIntermSequence *viewIDSymbolCastArguments = new TIntermSequence(); - viewIDSymbolCastArguments->push_back(viewIDSymbol); - TIntermAggregate *viewIDAsInt = TIntermAggregate::CreateConstructor( - TType(EbtInt, EbpHigh, EvqTemporary), viewIDSymbolCastArguments); - - // Create a gl_ViewportIndex node. - TIntermSymbol *viewportIndexSymbol = - ReferenceBuiltInVariable("gl_ViewportIndex", symbolTable, 0); - - // Create a { gl_ViewportIndex = int(ViewID_OVR) } node. - TIntermBlock *viewportIndexInitializerInBlock = new TIntermBlock(); - viewportIndexInitializerInBlock->appendStatement( - new TIntermBinary(EOpAssign, viewportIndexSymbol, viewIDAsInt)); - - // Create a gl_Layer node. - TIntermSymbol *layerSymbol = ReferenceBuiltInVariable("gl_Layer", symbolTable, 0); - - // Create an int(ViewID_OVR) + multiviewBaseViewLayerIndex node - TIntermBinary *sumOfViewIDAndBaseViewIndex = - new TIntermBinary(EOpAdd, viewIDAsInt->deepCopy(), multiviewBaseViewLayerIndexSymbol); - - // Create a { gl_Layer = int(ViewID_OVR) + multiviewBaseViewLayerIndex } node. - TIntermBlock *layerInitializerInBlock = new TIntermBlock(); - layerInitializerInBlock->appendStatement( - new TIntermBinary(EOpAssign, layerSymbol, sumOfViewIDAndBaseViewIndex)); - - // Create a node to compare whether the base view index uniform is less than zero. - TIntermBinary *multiviewBaseViewLayerIndexZeroComparison = - new TIntermBinary(EOpLessThan, multiviewBaseViewLayerIndexSymbol->deepCopy(), - CreateZeroNode(TType(EbtInt, EbpHigh, EvqConst))); - - // Create an if-else statement to select the code path. - TIntermIfElse *multiviewBranch = - new TIntermIfElse(multiviewBaseViewLayerIndexZeroComparison, - viewportIndexInitializerInBlock, layerInitializerInBlock); - - initializers->push_back(multiviewBranch); -} - -} // namespace - -void DeclareAndInitBuiltinsForInstancedMultiview(TIntermBlock *root, - unsigned numberOfViews, - GLenum shaderType, - ShCompileOptions compileOptions, - ShShaderOutput shaderOutput, - TSymbolTable *symbolTable) -{ - ASSERT(shaderType == GL_VERTEX_SHADER || shaderType == GL_FRAGMENT_SHADER); - - TQualifier viewIDQualifier = (shaderType == GL_VERTEX_SHADER) ? EvqFlatOut : EvqFlatIn; - TIntermSymbol *viewIDSymbol = new TIntermSymbol(symbolTable->nextUniqueId(), "ViewID_OVR", - TType(EbtUInt, EbpHigh, viewIDQualifier)); - viewIDSymbol->setInternal(true); - - DeclareGlobalVariable(root, viewIDSymbol); - ReplaceSymbol(root, "gl_ViewID_OVR", viewIDSymbol); - if (shaderType == GL_VERTEX_SHADER) - { - // Replacing gl_InstanceID with InstanceID should happen before adding the initializers of - // InstanceID and ViewID. - TIntermSymbol *instanceIDSymbol = new TIntermSymbol( - symbolTable->nextUniqueId(), "InstanceID", TType(EbtInt, EbpHigh, EvqGlobal)); - instanceIDSymbol->setInternal(true); - DeclareGlobalVariable(root, instanceIDSymbol); - ReplaceSymbol(root, "gl_InstanceID", instanceIDSymbol); - - TIntermSequence *initializers = new TIntermSequence(); - InitializeViewIDAndInstanceID(viewIDSymbol, instanceIDSymbol, numberOfViews, *symbolTable, - initializers); - - // The AST transformation which adds the expression to select the viewport index should - // be done only for the GLSL and ESSL output. - const bool selectView = (compileOptions & SH_SELECT_VIEW_IN_NV_GLSL_VERTEX_SHADER) != 0u; - // Assert that if the view is selected in the vertex shader, then the output is - // either GLSL or ESSL. - ASSERT(!selectView || IsOutputGLSL(shaderOutput) || IsOutputESSL(shaderOutput)); - if (selectView) - { - // Add a uniform to switch between side-by-side and layered rendering. - TIntermSymbol *multiviewBaseViewLayerIndexSymbol = - new TIntermSymbol(symbolTable->nextUniqueId(), "multiviewBaseViewLayerIndex", - TType(EbtInt, EbpHigh, EvqUniform)); - multiviewBaseViewLayerIndexSymbol->setInternal(true); - DeclareGlobalVariable(root, multiviewBaseViewLayerIndexSymbol); - - // Setting a value to gl_ViewportIndex or gl_Layer should happen after ViewID_OVR's - // initialization. - SelectViewIndexInVertexShader(viewIDSymbol->deepCopy(), - multiviewBaseViewLayerIndexSymbol->deepCopy(), - initializers, *symbolTable); - } - - // Insert initializers at the beginning of main(). - TIntermBlock *initializersBlock = new TIntermBlock(); - initializersBlock->getSequence()->swap(*initializers); - TIntermBlock *mainBody = FindMainBody(root); - mainBody->getSequence()->insert(mainBody->getSequence()->begin(), initializersBlock); - } -} - -} // namespace sh \ No newline at end of file diff --git a/src/3rdparty/angle/src/compiler/translator/DeclareAndInitBuiltinsForInstancedMultiview.h b/src/3rdparty/angle/src/compiler/translator/DeclareAndInitBuiltinsForInstancedMultiview.h deleted file mode 100644 index b4ab05fd0e..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/DeclareAndInitBuiltinsForInstancedMultiview.h +++ /dev/null @@ -1,48 +0,0 @@ -// -// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// Regardless of the shader type, the following AST transformations are applied: -// - Add declaration of View_ID_OVR. -// - Replace every occurrence of gl_ViewID_OVR with ViewID_OVR, mark ViewID_OVR as internal and -// declare it as a flat varying. -// -// If the shader type is a vertex shader, the following AST transformations are applied: -// - Replace every occurrence of gl_InstanceID with InstanceID, mark InstanceID as internal and set -// its qualifier to EvqTemporary. -// - Add initializers of ViewID_OVR and InstanceID to the beginning of the body of main. The pass -// should be executed before any variables get collected so that usage of gl_InstanceID is recorded. -// - If the output is ESSL or GLSL and the SH_SELECT_VIEW_IN_NV_GLSL_VERTEX_SHADER option is -// enabled, the expression -// "if (multiviewBaseViewLayerIndex < 0) { -// gl_ViewportIndex = int(ViewID_OVR); -// } else { -// gl_Layer = int(ViewID_OVR) + multiviewBaseViewLayerIndex; -// }" -// is added after ViewID and InstanceID are initialized. Also, MultiviewRenderPath is added as a -// uniform. -// - -#ifndef COMPILER_TRANSLATOR_DECLAREANDINITBUILTINSFORINSTANCEDMULTIVIEW_H_ -#define COMPILER_TRANSLATOR_DECLAREANDINITBUILTINSFORINSTANCEDMULTIVIEW_H_ - -#include "GLSLANG/ShaderLang.h" -#include "angle_gl.h" - -namespace sh -{ - -class TIntermBlock; -class TSymbolTable; - -void DeclareAndInitBuiltinsForInstancedMultiview(TIntermBlock *root, - unsigned numberOfViews, - GLenum shaderType, - ShCompileOptions compileOptions, - ShShaderOutput shaderOutput, - TSymbolTable *symbolTable); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_DECLAREANDINITBUILTINSFORINSTANCEDMULTIVIEW_H_ \ No newline at end of file diff --git a/src/3rdparty/angle/src/compiler/translator/DeferGlobalInitializers.cpp b/src/3rdparty/angle/src/compiler/translator/DeferGlobalInitializers.cpp deleted file mode 100644 index 67d51ea87b..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/DeferGlobalInitializers.cpp +++ /dev/null @@ -1,147 +0,0 @@ -// -// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// DeferGlobalInitializers is an AST traverser that moves global initializers into a separate -// function that is called in the beginning of main(). This enables initialization of globals with -// uniforms or non-constant globals, as allowed by the WebGL spec. Some initializers referencing -// non-constants may need to be unfolded into if statements in HLSL - this kind of steps should be -// done after DeferGlobalInitializers is run. Note that it's important that the function definition -// is at the end of the shader, as some globals may be declared after main(). -// -// It can also initialize all uninitialized globals. -// - -#include "compiler/translator/DeferGlobalInitializers.h" - -#include "compiler/translator/FindMain.h" -#include "compiler/translator/InitializeVariables.h" -#include "compiler/translator/IntermNode.h" -#include "compiler/translator/IntermNode_util.h" -#include "compiler/translator/SymbolTable.h" - -namespace sh -{ - -namespace -{ - -void GetDeferredInitializers(TIntermDeclaration *declaration, - bool initializeUninitializedGlobals, - bool canUseLoopsToInitialize, - TIntermSequence *deferredInitializersOut, - TSymbolTable *symbolTable) -{ - // SeparateDeclarations should have already been run. - ASSERT(declaration->getSequence()->size() == 1); - - TIntermNode *declarator = declaration->getSequence()->back(); - TIntermBinary *init = declarator->getAsBinaryNode(); - if (init) - { - TIntermSymbol *symbolNode = init->getLeft()->getAsSymbolNode(); - ASSERT(symbolNode); - TIntermTyped *expression = init->getRight(); - - if ((expression->getQualifier() != EvqConst || - (expression->getAsConstantUnion() == nullptr && - !expression->isConstructorWithOnlyConstantUnionParameters()))) - { - // For variables which are not constant, defer their real initialization until - // after we initialize uniforms. - // Deferral is done also in any cases where the variable has not been constant - // folded, since otherwise there's a chance that HLSL output will generate extra - // statements from the initializer expression. - - // Change const global to a regular global if its initialization is deferred. - // This can happen if ANGLE has not been able to fold the constant expression used - // as an initializer. - ASSERT(symbolNode->getQualifier() == EvqConst || - symbolNode->getQualifier() == EvqGlobal); - if (symbolNode->getQualifier() == EvqConst) - { - symbolNode->getTypePointer()->setQualifier(EvqGlobal); - } - - TIntermBinary *deferredInit = - new TIntermBinary(EOpAssign, symbolNode->deepCopy(), init->getRight()); - deferredInitializersOut->push_back(deferredInit); - - // Remove the initializer from the global scope and just declare the global instead. - declaration->replaceChildNode(init, symbolNode); - } - } - else if (initializeUninitializedGlobals) - { - TIntermSymbol *symbolNode = declarator->getAsSymbolNode(); - ASSERT(symbolNode); - - // Ignore ANGLE internal variables. - if (symbolNode->getName().isInternal()) - return; - - if (symbolNode->getQualifier() == EvqGlobal && symbolNode->getSymbol() != "") - { - TIntermSequence *initCode = - CreateInitCode(symbolNode, canUseLoopsToInitialize, symbolTable); - deferredInitializersOut->insert(deferredInitializersOut->end(), initCode->begin(), - initCode->end()); - } - } -} - -void InsertInitCallToMain(TIntermBlock *root, - TIntermSequence *deferredInitializers, - TSymbolTable *symbolTable) -{ - TIntermBlock *initGlobalsBlock = new TIntermBlock(); - initGlobalsBlock->getSequence()->swap(*deferredInitializers); - - TSymbolUniqueId initGlobalsFunctionId(symbolTable); - - const char *kInitGlobalsFunctionName = "initGlobals"; - - TIntermFunctionPrototype *initGlobalsFunctionPrototype = - CreateInternalFunctionPrototypeNode(TType(), kInitGlobalsFunctionName, initGlobalsFunctionId); - root->getSequence()->insert(root->getSequence()->begin(), initGlobalsFunctionPrototype); - TIntermFunctionDefinition *initGlobalsFunctionDefinition = CreateInternalFunctionDefinitionNode( - TType(), kInitGlobalsFunctionName, initGlobalsBlock, initGlobalsFunctionId); - root->appendStatement(initGlobalsFunctionDefinition); - - TIntermAggregate *initGlobalsCall = CreateInternalFunctionCallNode( - TType(), kInitGlobalsFunctionName, initGlobalsFunctionId, new TIntermSequence()); - - TIntermBlock *mainBody = FindMainBody(root); - mainBody->getSequence()->insert(mainBody->getSequence()->begin(), initGlobalsCall); -} - -} // namespace - -void DeferGlobalInitializers(TIntermBlock *root, - bool initializeUninitializedGlobals, - bool canUseLoopsToInitialize, - TSymbolTable *symbolTable) -{ - TIntermSequence *deferredInitializers = new TIntermSequence(); - - // Loop over all global statements and process the declarations. This is simpler than using a - // traverser. - for (TIntermNode *statement : *root->getSequence()) - { - TIntermDeclaration *declaration = statement->getAsDeclarationNode(); - if (declaration) - { - GetDeferredInitializers(declaration, initializeUninitializedGlobals, - canUseLoopsToInitialize, deferredInitializers, symbolTable); - } - } - - // Add the function with initialization and the call to that. - if (!deferredInitializers->empty()) - { - InsertInitCallToMain(root, deferredInitializers, symbolTable); - } -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/DeferGlobalInitializers.h b/src/3rdparty/angle/src/compiler/translator/DeferGlobalInitializers.h deleted file mode 100644 index 86930a585f..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/DeferGlobalInitializers.h +++ /dev/null @@ -1,32 +0,0 @@ -// -// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// DeferGlobalInitializers is an AST traverser that moves global initializers into a separate -// function that is called in the beginning of main(). This enables initialization of globals with -// uniforms or non-constant globals, as allowed by the WebGL spec. Some initializers referencing -// non-constants may need to be unfolded into if statements in HLSL - this kind of steps should be -// done after DeferGlobalInitializers is run. Note that it's important that the function definition -// is at the end of the shader, as some globals may be declared after main(). -// -// It can also initialize all uninitialized globals. -// - -#ifndef COMPILER_TRANSLATOR_DEFERGLOBALINITIALIZERS_H_ -#define COMPILER_TRANSLATOR_DEFERGLOBALINITIALIZERS_H_ - -namespace sh -{ - -class TIntermBlock; -class TSymbolTable; - -void DeferGlobalInitializers(TIntermBlock *root, - bool initializeUninitializedGlobals, - bool canUseLoopsToInitialize, - TSymbolTable *symbolTable); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_DEFERGLOBALINITIALIZERS_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/Diagnostics.cpp b/src/3rdparty/angle/src/compiler/translator/Diagnostics.cpp deleted file mode 100644 index 1744e5ab3e..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/Diagnostics.cpp +++ /dev/null @@ -1,105 +0,0 @@ -// -// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/translator/Diagnostics.h" - -#include "common/debug.h" -#include "compiler/preprocessor/SourceLocation.h" -#include "compiler/translator/Common.h" -#include "compiler/translator/InfoSink.h" - -namespace sh -{ - -TDiagnostics::TDiagnostics(TInfoSinkBase &infoSink) - : mInfoSink(infoSink), mNumErrors(0), mNumWarnings(0) -{ -} - -TDiagnostics::~TDiagnostics() -{ -} - -void TDiagnostics::writeInfo(Severity severity, - const pp::SourceLocation &loc, - const char *reason, - const char *token) -{ - switch (severity) - { - case SH_ERROR: - ++mNumErrors; - break; - case SH_WARNING: - ++mNumWarnings; - break; - default: - UNREACHABLE(); - break; - } - - /* VC++ format: file(linenum) : error #: 'token' : extrainfo */ - mInfoSink.prefix(severity); - mInfoSink.location(loc.file, loc.line); - mInfoSink << "'" << token << "' : " << reason << "\n"; -} - -void TDiagnostics::globalError(const char *message) -{ - ++mNumErrors; - mInfoSink.prefix(SH_ERROR); - mInfoSink << message << "\n"; -} - -void TDiagnostics::error(const pp::SourceLocation &loc, const char *reason, const char *token) -{ - writeInfo(SH_ERROR, loc, reason, token); -} - -void TDiagnostics::warning(const pp::SourceLocation &loc, const char *reason, const char *token) -{ - writeInfo(SH_WARNING, loc, reason, token); -} - -void TDiagnostics::error(const TSourceLoc &loc, const char *reason, const char *token) -{ - pp::SourceLocation srcLoc; - srcLoc.file = loc.first_file; - srcLoc.line = loc.first_line; - error(srcLoc, reason, token); -} - -void TDiagnostics::warning(const TSourceLoc &loc, const char *reason, const char *token) -{ - pp::SourceLocation srcLoc; - srcLoc.file = loc.first_file; - srcLoc.line = loc.first_line; - warning(srcLoc, reason, token); -} - -void TDiagnostics::print(ID id, const pp::SourceLocation &loc, const std::string &text) -{ - writeInfo(isError(id) ? SH_ERROR : SH_WARNING, loc, message(id), text.c_str()); -} - -void TDiagnostics::resetErrorCount() -{ - mNumErrors = 0; - mNumWarnings = 0; -} - -PerformanceDiagnostics::PerformanceDiagnostics(TDiagnostics *diagnostics) - : mDiagnostics(diagnostics) -{ - ASSERT(diagnostics); -} - -void PerformanceDiagnostics::warning(const TSourceLoc &loc, const char *reason, const char *token) -{ - mDiagnostics->warning(loc, reason, token); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/Diagnostics.h b/src/3rdparty/angle/src/compiler/translator/Diagnostics.h deleted file mode 100644 index 55b88991df..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/Diagnostics.h +++ /dev/null @@ -1,67 +0,0 @@ -// -// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_TRANSLATOR_DIAGNOSTICS_H_ -#define COMPILER_TRANSLATOR_DIAGNOSTICS_H_ - -#include "common/angleutils.h" -#include "compiler/preprocessor/DiagnosticsBase.h" -#include "compiler/translator/Severity.h" - -namespace sh -{ - -class TInfoSinkBase; -struct TSourceLoc; - -class TDiagnostics : public pp::Diagnostics, angle::NonCopyable -{ - public: - TDiagnostics(TInfoSinkBase &infoSink); - ~TDiagnostics() override; - - int numErrors() const { return mNumErrors; } - int numWarnings() const { return mNumWarnings; } - - void error(const pp::SourceLocation &loc, const char *reason, const char *token); - void warning(const pp::SourceLocation &loc, const char *reason, const char *token); - - void error(const TSourceLoc &loc, const char *reason, const char *token); - void warning(const TSourceLoc &loc, const char *reason, const char *token); - - void globalError(const char *message); - - void resetErrorCount(); - - protected: - void writeInfo(Severity severity, - const pp::SourceLocation &loc, - const char *reason, - const char *token); - - void print(ID id, const pp::SourceLocation &loc, const std::string &text) override; - - private: - TInfoSinkBase &mInfoSink; - int mNumErrors; - int mNumWarnings; -}; - -// Diagnostics wrapper to use when the code is only allowed to generate warnings. -class PerformanceDiagnostics : public angle::NonCopyable -{ - public: - PerformanceDiagnostics(TDiagnostics *diagnostics); - - void warning(const TSourceLoc &loc, const char *reason, const char *token); - - private: - TDiagnostics *mDiagnostics; -}; - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_DIAGNOSTICS_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/DirectiveHandler.cpp b/src/3rdparty/angle/src/compiler/translator/DirectiveHandler.cpp deleted file mode 100644 index 485e66670c..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/DirectiveHandler.cpp +++ /dev/null @@ -1,203 +0,0 @@ -// -// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/translator/DirectiveHandler.h" - -#include - -#include "angle_gl.h" -#include "common/debug.h" -#include "compiler/translator/Diagnostics.h" - -namespace sh -{ - -static TBehavior getBehavior(const std::string &str) -{ - const char kRequire[] = "require"; - const char kEnable[] = "enable"; - const char kDisable[] = "disable"; - const char kWarn[] = "warn"; - - if (str == kRequire) - return EBhRequire; - else if (str == kEnable) - return EBhEnable; - else if (str == kDisable) - return EBhDisable; - else if (str == kWarn) - return EBhWarn; - return EBhUndefined; -} - -TDirectiveHandler::TDirectiveHandler(TExtensionBehavior &extBehavior, - TDiagnostics &diagnostics, - int &shaderVersion, - sh::GLenum shaderType, - bool debugShaderPrecisionSupported) - : mExtensionBehavior(extBehavior), - mDiagnostics(diagnostics), - mShaderVersion(shaderVersion), - mShaderType(shaderType), - mDebugShaderPrecisionSupported(debugShaderPrecisionSupported) -{ -} - -TDirectiveHandler::~TDirectiveHandler() -{ -} - -void TDirectiveHandler::handleError(const pp::SourceLocation &loc, const std::string &msg) -{ - mDiagnostics.error(loc, msg.c_str(), ""); -} - -void TDirectiveHandler::handlePragma(const pp::SourceLocation &loc, - const std::string &name, - const std::string &value, - bool stdgl) -{ - if (stdgl) - { - const char kInvariant[] = "invariant"; - const char kAll[] = "all"; - - if (name == kInvariant && value == kAll) - { - if (mShaderVersion == 300 && mShaderType == GL_FRAGMENT_SHADER) - { - // ESSL 3.00.4 section 4.6.1 - mDiagnostics.error( - loc, "#pragma STDGL invariant(all) can not be used in fragment shader", - name.c_str()); - } - mPragma.stdgl.invariantAll = true; - } - // The STDGL pragma is used to reserve pragmas for use by future - // revisions of GLSL. Do not generate an error on unexpected - // name and value. - return; - } - else - { - const char kOptimize[] = "optimize"; - const char kDebug[] = "debug"; - const char kDebugShaderPrecision[] = "webgl_debug_shader_precision"; - const char kOn[] = "on"; - const char kOff[] = "off"; - - bool invalidValue = false; - if (name == kOptimize) - { - if (value == kOn) - mPragma.optimize = true; - else if (value == kOff) - mPragma.optimize = false; - else - invalidValue = true; - } - else if (name == kDebug) - { - if (value == kOn) - mPragma.debug = true; - else if (value == kOff) - mPragma.debug = false; - else - invalidValue = true; - } - else if (name == kDebugShaderPrecision && mDebugShaderPrecisionSupported) - { - if (value == kOn) - mPragma.debugShaderPrecision = true; - else if (value == kOff) - mPragma.debugShaderPrecision = false; - else - invalidValue = true; - } - else - { - mDiagnostics.report(pp::Diagnostics::PP_UNRECOGNIZED_PRAGMA, loc, name); - return; - } - - if (invalidValue) - { - mDiagnostics.error(loc, "invalid pragma value - 'on' or 'off' expected", value.c_str()); - } - } -} - -void TDirectiveHandler::handleExtension(const pp::SourceLocation &loc, - const std::string &name, - const std::string &behavior) -{ - const char kExtAll[] = "all"; - - TBehavior behaviorVal = getBehavior(behavior); - if (behaviorVal == EBhUndefined) - { - mDiagnostics.error(loc, "behavior invalid", name.c_str()); - return; - } - - if (name == kExtAll) - { - if (behaviorVal == EBhRequire) - { - mDiagnostics.error(loc, "extension cannot have 'require' behavior", name.c_str()); - } - else if (behaviorVal == EBhEnable) - { - mDiagnostics.error(loc, "extension cannot have 'enable' behavior", name.c_str()); - } - else - { - for (TExtensionBehavior::iterator iter = mExtensionBehavior.begin(); - iter != mExtensionBehavior.end(); ++iter) - iter->second = behaviorVal; - } - return; - } - - TExtensionBehavior::iterator iter = mExtensionBehavior.find(GetExtensionByName(name.c_str())); - if (iter != mExtensionBehavior.end()) - { - iter->second = behaviorVal; - return; - } - - switch (behaviorVal) - { - case EBhRequire: - mDiagnostics.error(loc, "extension is not supported", name.c_str()); - break; - case EBhEnable: - case EBhWarn: - case EBhDisable: - mDiagnostics.warning(loc, "extension is not supported", name.c_str()); - break; - default: - UNREACHABLE(); - break; - } -} - -void TDirectiveHandler::handleVersion(const pp::SourceLocation &loc, int version) -{ - if (version == 100 || version == 300 || version == 310) - { - mShaderVersion = version; - } - else - { - std::stringstream stream; - stream << version; - std::string str = stream.str(); - mDiagnostics.error(loc, "version number not supported", str.c_str()); - } -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/DirectiveHandler.h b/src/3rdparty/angle/src/compiler/translator/DirectiveHandler.h deleted file mode 100644 index 8e8cb9bbf6..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/DirectiveHandler.h +++ /dev/null @@ -1,57 +0,0 @@ -// -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_TRANSLATOR_DIRECTIVEHANDLER_H_ -#define COMPILER_TRANSLATOR_DIRECTIVEHANDLER_H_ - -#include "common/angleutils.h" -#include "compiler/translator/ExtensionBehavior.h" -#include "compiler/translator/Pragma.h" -#include "compiler/preprocessor/DirectiveHandlerBase.h" -#include "GLSLANG/ShaderLang.h" - -namespace sh -{ -class TDiagnostics; - -class TDirectiveHandler : public pp::DirectiveHandler, angle::NonCopyable -{ - public: - TDirectiveHandler(TExtensionBehavior &extBehavior, - TDiagnostics &diagnostics, - int &shaderVersion, - sh::GLenum shaderType, - bool debugShaderPrecisionSupported); - ~TDirectiveHandler() override; - - const TPragma &pragma() const { return mPragma; } - const TExtensionBehavior &extensionBehavior() const { return mExtensionBehavior; } - - void handleError(const pp::SourceLocation &loc, const std::string &msg) override; - - void handlePragma(const pp::SourceLocation &loc, - const std::string &name, - const std::string &value, - bool stdgl) override; - - void handleExtension(const pp::SourceLocation &loc, - const std::string &name, - const std::string &behavior) override; - - void handleVersion(const pp::SourceLocation &loc, int version) override; - - private: - TPragma mPragma; - TExtensionBehavior &mExtensionBehavior; - TDiagnostics &mDiagnostics; - int &mShaderVersion; - sh::GLenum mShaderType; - bool mDebugShaderPrecisionSupported; -}; - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_DIRECTIVEHANDLER_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/EmulateGLFragColorBroadcast.cpp b/src/3rdparty/angle/src/compiler/translator/EmulateGLFragColorBroadcast.cpp deleted file mode 100644 index 189ea341eb..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/EmulateGLFragColorBroadcast.cpp +++ /dev/null @@ -1,129 +0,0 @@ -// -// Copyright (c) 2002-2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// gl_FragColor needs to broadcast to all color buffers in ES2 if -// GL_EXT_draw_buffers is explicitly enabled in a fragment shader. -// -// We emulate this by replacing all gl_FragColor with gl_FragData[0], and in the end -// of main() function, assigning gl_FragData[1], ..., gl_FragData[maxDrawBuffers-1] -// with gl_FragData[0]. -// - -#include "compiler/translator/EmulateGLFragColorBroadcast.h" - -#include "compiler/translator/IntermNode_util.h" -#include "compiler/translator/IntermTraverse.h" -#include "compiler/translator/RunAtTheEndOfShader.h" - -namespace sh -{ - -namespace -{ - -class GLFragColorBroadcastTraverser : public TIntermTraverser -{ - public: - GLFragColorBroadcastTraverser(int maxDrawBuffers, TSymbolTable *symbolTable, int shaderVersion) - : TIntermTraverser(true, false, false, symbolTable), - mGLFragColorUsed(false), - mMaxDrawBuffers(maxDrawBuffers), - mShaderVersion(shaderVersion) - { - } - - void broadcastGLFragColor(TIntermBlock *root); - - bool isGLFragColorUsed() const { return mGLFragColorUsed; } - - protected: - void visitSymbol(TIntermSymbol *node) override; - - TIntermBinary *constructGLFragDataNode(int index) const; - TIntermBinary *constructGLFragDataAssignNode(int index) const; - - private: - bool mGLFragColorUsed; - int mMaxDrawBuffers; - const int mShaderVersion; -}; - -TIntermBinary *GLFragColorBroadcastTraverser::constructGLFragDataNode(int index) const -{ - TIntermSymbol *symbol = - ReferenceBuiltInVariable(TString("gl_FragData"), *mSymbolTable, mShaderVersion); - TIntermTyped *indexNode = CreateIndexNode(index); - - TIntermBinary *binary = new TIntermBinary(EOpIndexDirect, symbol, indexNode); - return binary; -} - -TIntermBinary *GLFragColorBroadcastTraverser::constructGLFragDataAssignNode(int index) const -{ - TIntermTyped *fragDataIndex = constructGLFragDataNode(index); - TIntermTyped *fragDataZero = constructGLFragDataNode(0); - - return new TIntermBinary(EOpAssign, fragDataIndex, fragDataZero); -} - -void GLFragColorBroadcastTraverser::visitSymbol(TIntermSymbol *node) -{ - if (node->getSymbol() == "gl_FragColor") - { - queueReplacement(constructGLFragDataNode(0), OriginalNode::IS_DROPPED); - mGLFragColorUsed = true; - } -} - -void GLFragColorBroadcastTraverser::broadcastGLFragColor(TIntermBlock *root) -{ - ASSERT(mMaxDrawBuffers > 1); - if (!mGLFragColorUsed) - { - return; - } - - TIntermBlock *broadcastBlock = new TIntermBlock(); - // Now insert statements - // gl_FragData[1] = gl_FragData[0]; - // ... - // gl_FragData[maxDrawBuffers - 1] = gl_FragData[0]; - for (int colorIndex = 1; colorIndex < mMaxDrawBuffers; ++colorIndex) - { - broadcastBlock->appendStatement(constructGLFragDataAssignNode(colorIndex)); - } - RunAtTheEndOfShader(root, broadcastBlock, mSymbolTable); -} - -} // namespace anonymous - -void EmulateGLFragColorBroadcast(TIntermBlock *root, - int maxDrawBuffers, - std::vector *outputVariables, - TSymbolTable *symbolTable, - int shaderVersion) -{ - ASSERT(maxDrawBuffers > 1); - GLFragColorBroadcastTraverser traverser(maxDrawBuffers, symbolTable, shaderVersion); - root->traverse(&traverser); - if (traverser.isGLFragColorUsed()) - { - traverser.updateTree(); - traverser.broadcastGLFragColor(root); - for (auto &var : *outputVariables) - { - if (var.name == "gl_FragColor") - { - // TODO(zmo): Find a way to keep the original variable information. - var.name = "gl_FragData"; - var.mappedName = "gl_FragData"; - var.arraySizes.push_back(maxDrawBuffers); - ASSERT(var.arraySizes.size() == 1u); - } - } - } -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/EmulateGLFragColorBroadcast.h b/src/3rdparty/angle/src/compiler/translator/EmulateGLFragColorBroadcast.h deleted file mode 100644 index e652b7e07e..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/EmulateGLFragColorBroadcast.h +++ /dev/null @@ -1,31 +0,0 @@ -// -// Copyright (c) 2002-2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// Emulate gl_FragColor broadcast behaviors in ES2 where -// GL_EXT_draw_buffers is explicitly enabled in a fragment shader. -// - -#ifndef COMPILER_TRANSLATOR_EMULATEGLFRAGCOLORBROADCAST_H_ -#define COMPILER_TRANSLATOR_EMULATEGLFRAGCOLORBROADCAST_H_ - -#include - -namespace sh -{ -struct OutputVariable; -class TIntermBlock; -class TSymbolTable; - -// Replace all gl_FragColor with gl_FragData[0], and in the end of main() function, -// assign gl_FragData[1] ... gl_FragData[maxDrawBuffers - 1] with gl_FragData[0]. -// If gl_FragColor is in outputVariables, it is replaced by gl_FragData. -void EmulateGLFragColorBroadcast(TIntermBlock *root, - int maxDrawBuffers, - std::vector *outputVariables, - TSymbolTable *symbolTable, - int shaderVersion); -} - -#endif // COMPILER_TRANSLATOR_EMULATEGLFRAGCOLORBROADCAST_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/EmulatePrecision.cpp b/src/3rdparty/angle/src/compiler/translator/EmulatePrecision.cpp deleted file mode 100644 index ba09fd77df..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/EmulatePrecision.cpp +++ /dev/null @@ -1,751 +0,0 @@ -// -// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/translator/EmulatePrecision.h" - -#include - -namespace sh -{ - -namespace -{ - -class RoundingHelperWriter : angle::NonCopyable -{ - public: - static RoundingHelperWriter *createHelperWriter(const ShShaderOutput outputLanguage); - - void writeCommonRoundingHelpers(TInfoSinkBase &sink, const int shaderVersion); - void writeCompoundAssignmentHelper(TInfoSinkBase &sink, - const char *lType, - const char *rType, - const char *opStr, - const char *opNameStr); - - virtual ~RoundingHelperWriter() {} - - protected: - RoundingHelperWriter(const ShShaderOutput outputLanguage) : mOutputLanguage(outputLanguage) {} - RoundingHelperWriter() = delete; - - const ShShaderOutput mOutputLanguage; - - private: - virtual std::string getTypeString(const char *glslType) = 0; - virtual void writeFloatRoundingHelpers(TInfoSinkBase &sink) = 0; - virtual void writeVectorRoundingHelpers(TInfoSinkBase &sink, const unsigned int size) = 0; - virtual void writeMatrixRoundingHelper(TInfoSinkBase &sink, - const unsigned int columns, - const unsigned int rows, - const char *functionName) = 0; -}; - -class RoundingHelperWriterGLSL : public RoundingHelperWriter -{ - public: - RoundingHelperWriterGLSL(const ShShaderOutput outputLanguage) - : RoundingHelperWriter(outputLanguage) - { - } - - private: - std::string getTypeString(const char *glslType) override; - void writeFloatRoundingHelpers(TInfoSinkBase &sink) override; - void writeVectorRoundingHelpers(TInfoSinkBase &sink, const unsigned int size) override; - void writeMatrixRoundingHelper(TInfoSinkBase &sink, - const unsigned int columns, - const unsigned int rows, - const char *functionName) override; -}; - -class RoundingHelperWriterESSL : public RoundingHelperWriterGLSL -{ - public: - RoundingHelperWriterESSL(const ShShaderOutput outputLanguage) - : RoundingHelperWriterGLSL(outputLanguage) - { - } - - private: - std::string getTypeString(const char *glslType) override; -}; - -class RoundingHelperWriterHLSL : public RoundingHelperWriter -{ - public: - RoundingHelperWriterHLSL(const ShShaderOutput outputLanguage) - : RoundingHelperWriter(outputLanguage) - { - } - - private: - std::string getTypeString(const char *glslType) override; - void writeFloatRoundingHelpers(TInfoSinkBase &sink) override; - void writeVectorRoundingHelpers(TInfoSinkBase &sink, const unsigned int size) override; - void writeMatrixRoundingHelper(TInfoSinkBase &sink, - const unsigned int columns, - const unsigned int rows, - const char *functionName) override; -}; - -RoundingHelperWriter *RoundingHelperWriter::createHelperWriter(const ShShaderOutput outputLanguage) -{ - ASSERT(EmulatePrecision::SupportedInLanguage(outputLanguage)); - switch (outputLanguage) - { - case SH_HLSL_4_1_OUTPUT: - return new RoundingHelperWriterHLSL(outputLanguage); - case SH_ESSL_OUTPUT: - return new RoundingHelperWriterESSL(outputLanguage); - default: - return new RoundingHelperWriterGLSL(outputLanguage); - } -} - -void RoundingHelperWriter::writeCommonRoundingHelpers(TInfoSinkBase &sink, const int shaderVersion) -{ - // Write the angle_frm functions that round floating point numbers to - // half precision, and angle_frl functions that round them to minimum lowp - // precision. - - writeFloatRoundingHelpers(sink); - writeVectorRoundingHelpers(sink, 2); - writeVectorRoundingHelpers(sink, 3); - writeVectorRoundingHelpers(sink, 4); - if (shaderVersion > 100) - { - for (unsigned int columns = 2; columns <= 4; ++columns) - { - for (unsigned int rows = 2; rows <= 4; ++rows) - { - writeMatrixRoundingHelper(sink, columns, rows, "angle_frm"); - writeMatrixRoundingHelper(sink, columns, rows, "angle_frl"); - } - } - } - else - { - for (unsigned int size = 2; size <= 4; ++size) - { - writeMatrixRoundingHelper(sink, size, size, "angle_frm"); - writeMatrixRoundingHelper(sink, size, size, "angle_frl"); - } - } -} - -void RoundingHelperWriter::writeCompoundAssignmentHelper(TInfoSinkBase &sink, - const char *lType, - const char *rType, - const char *opStr, - const char *opNameStr) -{ - std::string lTypeStr = getTypeString(lType); - std::string rTypeStr = getTypeString(rType); - - // Note that y should be passed through angle_frm at the function call site, - // but x can't be passed through angle_frm there since it is an inout parameter. - // So only pass x and the result through angle_frm here. - // clang-format off - sink << - lTypeStr << " angle_compound_" << opNameStr << "_frm(inout " << lTypeStr << " x, in " << rTypeStr << " y) {\n" - " x = angle_frm(angle_frm(x) " << opStr << " y);\n" - " return x;\n" - "}\n"; - sink << - lTypeStr << " angle_compound_" << opNameStr << "_frl(inout " << lTypeStr << " x, in " << rTypeStr << " y) {\n" - " x = angle_frl(angle_frl(x) " << opStr << " y);\n" - " return x;\n" - "}\n"; - // clang-format on -} - -std::string RoundingHelperWriterGLSL::getTypeString(const char *glslType) -{ - return glslType; -} - -std::string RoundingHelperWriterESSL::getTypeString(const char *glslType) -{ - std::stringstream typeStrStr; - typeStrStr << "highp " << glslType; - return typeStrStr.str(); -} - -void RoundingHelperWriterGLSL::writeFloatRoundingHelpers(TInfoSinkBase &sink) -{ - // Unoptimized version of angle_frm for single floats: - // - // int webgl_maxNormalExponent(in int exponentBits) - // { - // int possibleExponents = int(exp2(float(exponentBits))); - // int exponentBias = possibleExponents / 2 - 1; - // int allExponentBitsOne = possibleExponents - 1; - // return (allExponentBitsOne - 1) - exponentBias; - // } - // - // float angle_frm(in float x) - // { - // int mantissaBits = 10; - // int exponentBits = 5; - // float possibleMantissas = exp2(float(mantissaBits)); - // float mantissaMax = 2.0 - 1.0 / possibleMantissas; - // int maxNE = webgl_maxNormalExponent(exponentBits); - // float max = exp2(float(maxNE)) * mantissaMax; - // if (x > max) - // { - // return max; - // } - // if (x < -max) - // { - // return -max; - // } - // float exponent = floor(log2(abs(x))); - // if (abs(x) == 0.0 || exponent < -float(maxNE)) - // { - // return 0.0 * sign(x) - // } - // x = x * exp2(-(exponent - float(mantissaBits))); - // x = sign(x) * floor(abs(x)); - // return x * exp2(exponent - float(mantissaBits)); - // } - - // All numbers with a magnitude less than 2^-15 are subnormal, and are - // flushed to zero. - - // Note the constant numbers below: - // a) 65504 is the maximum possible mantissa (1.1111111111 in binary) times - // 2^15, the maximum normal exponent. - // b) 10.0 is the number of mantissa bits. - // c) -25.0 is the minimum normal half-float exponent -15.0 minus the number - // of mantissa bits. - // d) + 1e-30 is to make sure the argument of log2() won't be zero. It can - // only affect the result of log2 on x where abs(x) < 1e-22. Since these - // numbers will be flushed to zero either way (2^-15 is the smallest - // normal positive number), this does not introduce any error. - - std::string floatType = getTypeString("float"); - - // clang-format off - sink << - floatType << " angle_frm(in " << floatType << " x) {\n" - " x = clamp(x, -65504.0, 65504.0);\n" - " " << floatType << " exponent = floor(log2(abs(x) + 1e-30)) - 10.0;\n" - " bool isNonZero = (exponent >= -25.0);\n" - " x = x * exp2(-exponent);\n" - " x = sign(x) * floor(abs(x));\n" - " return x * exp2(exponent) * float(isNonZero);\n" - "}\n"; - - sink << - floatType << " angle_frl(in " << floatType << " x) {\n" - " x = clamp(x, -2.0, 2.0);\n" - " x = x * 256.0;\n" - " x = sign(x) * floor(abs(x));\n" - " return x * 0.00390625;\n" - "}\n"; - // clang-format on -} - -void RoundingHelperWriterGLSL::writeVectorRoundingHelpers(TInfoSinkBase &sink, - const unsigned int size) -{ - std::stringstream vecTypeStrStr; - vecTypeStrStr << "vec" << size; - std::string vecType = getTypeString(vecTypeStrStr.str().c_str()); - - // clang-format off - sink << - vecType << " angle_frm(in " << vecType << " v) {\n" - " v = clamp(v, -65504.0, 65504.0);\n" - " " << vecType << " exponent = floor(log2(abs(v) + 1e-30)) - 10.0;\n" - " bvec" << size << " isNonZero = greaterThanEqual(exponent, vec" << size << "(-25.0));\n" - " v = v * exp2(-exponent);\n" - " v = sign(v) * floor(abs(v));\n" - " return v * exp2(exponent) * vec" << size << "(isNonZero);\n" - "}\n"; - - sink << - vecType << " angle_frl(in " << vecType << " v) {\n" - " v = clamp(v, -2.0, 2.0);\n" - " v = v * 256.0;\n" - " v = sign(v) * floor(abs(v));\n" - " return v * 0.00390625;\n" - "}\n"; - // clang-format on -} - -void RoundingHelperWriterGLSL::writeMatrixRoundingHelper(TInfoSinkBase &sink, - const unsigned int columns, - const unsigned int rows, - const char *functionName) -{ - std::stringstream matTypeStrStr; - matTypeStrStr << "mat" << columns; - if (rows != columns) - { - matTypeStrStr << "x" << rows; - } - std::string matType = getTypeString(matTypeStrStr.str().c_str()); - - sink << matType << " " << functionName << "(in " << matType << " m) {\n" - << " " << matType << " rounded;\n"; - - for (unsigned int i = 0; i < columns; ++i) - { - sink << " rounded[" << i << "] = " << functionName << "(m[" << i << "]);\n"; - } - - sink << " return rounded;\n" - "}\n"; -} - -static const char *GetHLSLTypeStr(const char *floatTypeStr) -{ - if (strcmp(floatTypeStr, "float") == 0) - { - return "float"; - } - if (strcmp(floatTypeStr, "vec2") == 0) - { - return "float2"; - } - if (strcmp(floatTypeStr, "vec3") == 0) - { - return "float3"; - } - if (strcmp(floatTypeStr, "vec4") == 0) - { - return "float4"; - } - if (strcmp(floatTypeStr, "mat2") == 0) - { - return "float2x2"; - } - if (strcmp(floatTypeStr, "mat3") == 0) - { - return "float3x3"; - } - if (strcmp(floatTypeStr, "mat4") == 0) - { - return "float4x4"; - } - if (strcmp(floatTypeStr, "mat2x3") == 0) - { - return "float2x3"; - } - if (strcmp(floatTypeStr, "mat2x4") == 0) - { - return "float2x4"; - } - if (strcmp(floatTypeStr, "mat3x2") == 0) - { - return "float3x2"; - } - if (strcmp(floatTypeStr, "mat3x4") == 0) - { - return "float3x4"; - } - if (strcmp(floatTypeStr, "mat4x2") == 0) - { - return "float4x2"; - } - if (strcmp(floatTypeStr, "mat4x3") == 0) - { - return "float4x3"; - } - UNREACHABLE(); - return nullptr; -} - -std::string RoundingHelperWriterHLSL::getTypeString(const char *glslType) -{ - return GetHLSLTypeStr(glslType); -} - -void RoundingHelperWriterHLSL::writeFloatRoundingHelpers(TInfoSinkBase &sink) -{ - // In HLSL scalars are the same as 1-vectors. - writeVectorRoundingHelpers(sink, 1); -} - -void RoundingHelperWriterHLSL::writeVectorRoundingHelpers(TInfoSinkBase &sink, - const unsigned int size) -{ - std::stringstream vecTypeStrStr; - vecTypeStrStr << "float" << size; - std::string vecType = vecTypeStrStr.str(); - - // clang-format off - sink << - vecType << " angle_frm(" << vecType << " v) {\n" - " v = clamp(v, -65504.0, 65504.0);\n" - " " << vecType << " exponent = floor(log2(abs(v) + 1e-30)) - 10.0;\n" - " bool" << size << " isNonZero = exponent < -25.0;\n" - " v = v * exp2(-exponent);\n" - " v = sign(v) * floor(abs(v));\n" - " return v * exp2(exponent) * (float" << size << ")(isNonZero);\n" - "}\n"; - - sink << - vecType << " angle_frl(" << vecType << " v) {\n" - " v = clamp(v, -2.0, 2.0);\n" - " v = v * 256.0;\n" - " v = sign(v) * floor(abs(v));\n" - " return v * 0.00390625;\n" - "}\n"; - // clang-format on -} - -void RoundingHelperWriterHLSL::writeMatrixRoundingHelper(TInfoSinkBase &sink, - const unsigned int columns, - const unsigned int rows, - const char *functionName) -{ - std::stringstream matTypeStrStr; - matTypeStrStr << "float" << columns << "x" << rows; - std::string matType = matTypeStrStr.str(); - - sink << matType << " " << functionName << "(" << matType << " m) {\n" - << " " << matType << " rounded;\n"; - - for (unsigned int i = 0; i < columns; ++i) - { - sink << " rounded[" << i << "] = " << functionName << "(m[" << i << "]);\n"; - } - - sink << " return rounded;\n" - "}\n"; -} - -bool canRoundFloat(const TType &type) -{ - return type.getBasicType() == EbtFloat && !type.isArray() && - (type.getPrecision() == EbpLow || type.getPrecision() == EbpMedium); -} - -TIntermAggregate *createInternalFunctionCallNode(const TType &type, - TString name, - TIntermSequence *arguments) -{ - TName nameObj(name); - nameObj.setInternal(true); - TIntermAggregate *callNode = - TIntermAggregate::Create(type, EOpCallInternalRawFunction, arguments); - callNode->getFunctionSymbolInfo()->setNameObj(nameObj); - return callNode; -} - -TIntermAggregate *createRoundingFunctionCallNode(TIntermTyped *roundedChild) -{ - TString roundFunctionName; - if (roundedChild->getPrecision() == EbpMedium) - roundFunctionName = "angle_frm"; - else - roundFunctionName = "angle_frl"; - TIntermSequence *arguments = new TIntermSequence(); - arguments->push_back(roundedChild); - TIntermAggregate *callNode = - createInternalFunctionCallNode(roundedChild->getType(), roundFunctionName, arguments); - callNode->getFunctionSymbolInfo()->setKnownToNotHaveSideEffects(true); - return callNode; -} - -TIntermAggregate *createCompoundAssignmentFunctionCallNode(TIntermTyped *left, - TIntermTyped *right, - const char *opNameStr) -{ - std::stringstream strstr; - if (left->getPrecision() == EbpMedium) - strstr << "angle_compound_" << opNameStr << "_frm"; - else - strstr << "angle_compound_" << opNameStr << "_frl"; - TString functionName = strstr.str().c_str(); - TIntermSequence *arguments = new TIntermSequence(); - arguments->push_back(left); - arguments->push_back(right); - return createInternalFunctionCallNode(left->getType(), functionName, arguments); -} - -bool ParentUsesResult(TIntermNode *parent, TIntermTyped *node) -{ - if (!parent) - { - return false; - } - - TIntermBlock *blockParent = parent->getAsBlock(); - // If the parent is a block, the result is not assigned anywhere, - // so rounding it is not needed. In particular, this can avoid a lot of - // unnecessary rounding of unused return values of assignment. - if (blockParent) - { - return false; - } - TIntermBinary *binaryParent = parent->getAsBinaryNode(); - if (binaryParent && binaryParent->getOp() == EOpComma && (binaryParent->getRight() != node)) - { - return false; - } - return true; -} - -bool ParentConstructorTakesCareOfRounding(TIntermNode *parent, TIntermTyped *node) -{ - if (!parent) - { - return false; - } - TIntermAggregate *parentConstructor = parent->getAsAggregate(); - if (!parentConstructor || parentConstructor->getOp() != EOpConstruct) - { - return false; - } - if (parentConstructor->getPrecision() != node->getPrecision()) - { - return false; - } - return canRoundFloat(parentConstructor->getType()); -} - -} // namespace anonymous - -EmulatePrecision::EmulatePrecision(TSymbolTable *symbolTable, int shaderVersion) - : TLValueTrackingTraverser(true, true, true, symbolTable, shaderVersion), - mDeclaringVariables(false) -{ -} - -void EmulatePrecision::visitSymbol(TIntermSymbol *node) -{ - TIntermNode *parent = getParentNode(); - if (canRoundFloat(node->getType()) && ParentUsesResult(parent, node) && - !ParentConstructorTakesCareOfRounding(parent, node) && !mDeclaringVariables && - !isLValueRequiredHere()) - { - TIntermNode *replacement = createRoundingFunctionCallNode(node); - queueReplacement(replacement, OriginalNode::BECOMES_CHILD); - } -} - -bool EmulatePrecision::visitBinary(Visit visit, TIntermBinary *node) -{ - bool visitChildren = true; - - TOperator op = node->getOp(); - - // RHS of initialize is not being declared. - if (op == EOpInitialize && visit == InVisit) - mDeclaringVariables = false; - - if ((op == EOpIndexDirectStruct) && visit == InVisit) - visitChildren = false; - - if (visit != PreVisit) - return visitChildren; - - const TType &type = node->getType(); - bool roundFloat = canRoundFloat(type); - - if (roundFloat) - { - switch (op) - { - // Math operators that can result in a float may need to apply rounding to the return - // value. Note that in the case of assignment, the rounding is applied to its return - // value here, not the value being assigned. - case EOpAssign: - case EOpAdd: - case EOpSub: - case EOpMul: - case EOpDiv: - case EOpVectorTimesScalar: - case EOpVectorTimesMatrix: - case EOpMatrixTimesVector: - case EOpMatrixTimesScalar: - case EOpMatrixTimesMatrix: - { - TIntermNode *parent = getParentNode(); - if (!ParentUsesResult(parent, node) || - ParentConstructorTakesCareOfRounding(parent, node)) - { - break; - } - TIntermNode *replacement = createRoundingFunctionCallNode(node); - queueReplacement(replacement, OriginalNode::BECOMES_CHILD); - break; - } - - // Compound assignment cases need to replace the operator with a function call. - case EOpAddAssign: - { - mEmulateCompoundAdd.insert( - TypePair(type.getBuiltInTypeNameString(), - node->getRight()->getType().getBuiltInTypeNameString())); - TIntermNode *replacement = createCompoundAssignmentFunctionCallNode( - node->getLeft(), node->getRight(), "add"); - queueReplacement(replacement, OriginalNode::IS_DROPPED); - break; - } - case EOpSubAssign: - { - mEmulateCompoundSub.insert( - TypePair(type.getBuiltInTypeNameString(), - node->getRight()->getType().getBuiltInTypeNameString())); - TIntermNode *replacement = createCompoundAssignmentFunctionCallNode( - node->getLeft(), node->getRight(), "sub"); - queueReplacement(replacement, OriginalNode::IS_DROPPED); - break; - } - case EOpMulAssign: - case EOpVectorTimesMatrixAssign: - case EOpVectorTimesScalarAssign: - case EOpMatrixTimesScalarAssign: - case EOpMatrixTimesMatrixAssign: - { - mEmulateCompoundMul.insert( - TypePair(type.getBuiltInTypeNameString(), - node->getRight()->getType().getBuiltInTypeNameString())); - TIntermNode *replacement = createCompoundAssignmentFunctionCallNode( - node->getLeft(), node->getRight(), "mul"); - queueReplacement(replacement, OriginalNode::IS_DROPPED); - break; - } - case EOpDivAssign: - { - mEmulateCompoundDiv.insert( - TypePair(type.getBuiltInTypeNameString(), - node->getRight()->getType().getBuiltInTypeNameString())); - TIntermNode *replacement = createCompoundAssignmentFunctionCallNode( - node->getLeft(), node->getRight(), "div"); - queueReplacement(replacement, OriginalNode::IS_DROPPED); - break; - } - default: - // The rest of the binary operations should not need precision emulation. - break; - } - } - return visitChildren; -} - -bool EmulatePrecision::visitDeclaration(Visit visit, TIntermDeclaration *node) -{ - // Variable or interface block declaration. - if (visit == PreVisit) - { - mDeclaringVariables = true; - } - else if (visit == InVisit) - { - mDeclaringVariables = true; - } - else - { - mDeclaringVariables = false; - } - return true; -} - -bool EmulatePrecision::visitInvariantDeclaration(Visit visit, TIntermInvariantDeclaration *node) -{ - return false; -} - -bool EmulatePrecision::visitFunctionPrototype(Visit visit, TIntermFunctionPrototype *node) -{ - return false; -} - -bool EmulatePrecision::visitAggregate(Visit visit, TIntermAggregate *node) -{ - if (visit != PreVisit) - return true; - switch (node->getOp()) - { - case EOpCallInternalRawFunction: - case EOpCallFunctionInAST: - // User-defined function return values are not rounded. The calculations that produced - // the value inside the function definition should have been rounded. - break; - case EOpConstruct: - if (node->getBasicType() == EbtStruct) - { - break; - } - default: - TIntermNode *parent = getParentNode(); - if (canRoundFloat(node->getType()) && ParentUsesResult(parent, node) && - !ParentConstructorTakesCareOfRounding(parent, node)) - { - TIntermNode *replacement = createRoundingFunctionCallNode(node); - queueReplacement(replacement, OriginalNode::BECOMES_CHILD); - } - break; - } - return true; -} - -bool EmulatePrecision::visitUnary(Visit visit, TIntermUnary *node) -{ - switch (node->getOp()) - { - case EOpNegative: - case EOpLogicalNot: - case EOpPostIncrement: - case EOpPostDecrement: - case EOpPreIncrement: - case EOpPreDecrement: - case EOpLogicalNotComponentWise: - break; - default: - if (canRoundFloat(node->getType()) && visit == PreVisit) - { - TIntermNode *replacement = createRoundingFunctionCallNode(node); - queueReplacement(replacement, OriginalNode::BECOMES_CHILD); - } - break; - } - - return true; -} - -void EmulatePrecision::writeEmulationHelpers(TInfoSinkBase &sink, - const int shaderVersion, - const ShShaderOutput outputLanguage) -{ - std::unique_ptr roundingHelperWriter( - RoundingHelperWriter::createHelperWriter(outputLanguage)); - - roundingHelperWriter->writeCommonRoundingHelpers(sink, shaderVersion); - - EmulationSet::const_iterator it; - for (it = mEmulateCompoundAdd.begin(); it != mEmulateCompoundAdd.end(); it++) - roundingHelperWriter->writeCompoundAssignmentHelper(sink, it->lType, it->rType, "+", "add"); - for (it = mEmulateCompoundSub.begin(); it != mEmulateCompoundSub.end(); it++) - roundingHelperWriter->writeCompoundAssignmentHelper(sink, it->lType, it->rType, "-", "sub"); - for (it = mEmulateCompoundDiv.begin(); it != mEmulateCompoundDiv.end(); it++) - roundingHelperWriter->writeCompoundAssignmentHelper(sink, it->lType, it->rType, "/", "div"); - for (it = mEmulateCompoundMul.begin(); it != mEmulateCompoundMul.end(); it++) - roundingHelperWriter->writeCompoundAssignmentHelper(sink, it->lType, it->rType, "*", "mul"); -} - -// static -bool EmulatePrecision::SupportedInLanguage(const ShShaderOutput outputLanguage) -{ - switch (outputLanguage) - { - case SH_HLSL_4_1_OUTPUT: - case SH_ESSL_OUTPUT: - return true; - default: - // Other languages not yet supported - return (outputLanguage == SH_GLSL_COMPATIBILITY_OUTPUT || - sh::IsGLSL130OrNewer(outputLanguage)); - } -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/EmulatePrecision.h b/src/3rdparty/angle/src/compiler/translator/EmulatePrecision.h deleted file mode 100644 index 8044465410..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/EmulatePrecision.h +++ /dev/null @@ -1,73 +0,0 @@ -// -// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_TRANSLATOR_EMULATE_PRECISION_H_ -#define COMPILER_TRANSLATOR_EMULATE_PRECISION_H_ - -#include "GLSLANG/ShaderLang.h" -#include "common/angleutils.h" -#include "compiler/translator/Compiler.h" -#include "compiler/translator/InfoSink.h" -#include "compiler/translator/IntermTraverse.h" - -// This class gathers all compound assignments from the AST and can then write -// the functions required for their precision emulation. This way there is no -// need to write a huge number of variations of the emulated compound assignment -// to every translated shader with emulation enabled. - -namespace sh -{ - -class EmulatePrecision : public TLValueTrackingTraverser -{ - public: - EmulatePrecision(TSymbolTable *symbolTable, int shaderVersion); - - void visitSymbol(TIntermSymbol *node) override; - bool visitBinary(Visit visit, TIntermBinary *node) override; - bool visitUnary(Visit visit, TIntermUnary *node) override; - bool visitAggregate(Visit visit, TIntermAggregate *node) override; - bool visitInvariantDeclaration(Visit visit, TIntermInvariantDeclaration *node) override; - bool visitDeclaration(Visit visit, TIntermDeclaration *node) override; - bool visitFunctionPrototype(Visit visit, TIntermFunctionPrototype *node) override; - - void writeEmulationHelpers(TInfoSinkBase &sink, - const int shaderVersion, - const ShShaderOutput outputLanguage); - - static bool SupportedInLanguage(const ShShaderOutput outputLanguage); - - private: - struct TypePair - { - TypePair(const char *l, const char *r) : lType(l), rType(r) {} - - const char *lType; - const char *rType; - }; - - struct TypePairComparator - { - bool operator()(const TypePair &l, const TypePair &r) const - { - if (l.lType == r.lType) - return l.rType < r.rType; - return l.lType < r.lType; - } - }; - - typedef std::set EmulationSet; - EmulationSet mEmulateCompoundAdd; - EmulationSet mEmulateCompoundSub; - EmulationSet mEmulateCompoundMul; - EmulationSet mEmulateCompoundDiv; - - bool mDeclaringVariables; -}; - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_EMULATE_PRECISION_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/ExpandIntegerPowExpressions.cpp b/src/3rdparty/angle/src/compiler/translator/ExpandIntegerPowExpressions.cpp deleted file mode 100644 index f17dd73657..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/ExpandIntegerPowExpressions.cpp +++ /dev/null @@ -1,153 +0,0 @@ -// -// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// Implementation of the integer pow expressions HLSL bug workaround. -// See header for more info. - -#include "compiler/translator/ExpandIntegerPowExpressions.h" - -#include -#include - -#include "compiler/translator/IntermTraverse.h" - -namespace sh -{ - -namespace -{ - -class Traverser : public TIntermTraverser -{ - public: - static void Apply(TIntermNode *root, TSymbolTable *symbolTable); - - private: - Traverser(TSymbolTable *symbolTable); - bool visitAggregate(Visit visit, TIntermAggregate *node) override; - void nextIteration(); - - bool mFound = false; -}; - -// static -void Traverser::Apply(TIntermNode *root, TSymbolTable *symbolTable) -{ - Traverser traverser(symbolTable); - do - { - traverser.nextIteration(); - root->traverse(&traverser); - if (traverser.mFound) - { - traverser.updateTree(); - } - } while (traverser.mFound); -} - -Traverser::Traverser(TSymbolTable *symbolTable) : TIntermTraverser(true, false, false, symbolTable) -{ -} - -void Traverser::nextIteration() -{ - mFound = false; - nextTemporaryId(); -} - -bool Traverser::visitAggregate(Visit visit, TIntermAggregate *node) -{ - if (mFound) - { - return false; - } - - // Test 0: skip non-pow operators. - if (node->getOp() != EOpPow) - { - return true; - } - - const TIntermSequence *sequence = node->getSequence(); - ASSERT(sequence->size() == 2u); - const TIntermConstantUnion *constantNode = sequence->at(1)->getAsConstantUnion(); - - // Test 1: check for a single constant. - if (!constantNode || constantNode->getNominalSize() != 1) - { - return true; - } - - const TConstantUnion *constant = constantNode->getUnionArrayPointer(); - - TConstantUnion asFloat; - asFloat.cast(EbtFloat, *constant); - - float value = asFloat.getFConst(); - - // Test 2: value is in the problematic range. - if (value < -5.0f || value > 9.0f) - { - return true; - } - - // Test 3: value is integer or pretty close to an integer. - float absval = std::abs(value); - float frac = absval - std::round(absval); - if (frac > 0.0001f) - { - return true; - } - - // Test 4: skip -1, 0, and 1 - int exponent = static_cast(value); - int n = std::abs(exponent); - if (n < 2) - { - return true; - } - - // Potential problem case detected, apply workaround. - nextTemporaryId(); - - TIntermTyped *lhs = sequence->at(0)->getAsTyped(); - ASSERT(lhs); - - TIntermDeclaration *init = createTempInitDeclaration(lhs); - TIntermTyped *current = createTempSymbol(lhs->getType()); - - insertStatementInParentBlock(init); - - // Create a chain of n-1 multiples. - for (int i = 1; i < n; ++i) - { - TIntermBinary *mul = new TIntermBinary(EOpMul, current, createTempSymbol(lhs->getType())); - mul->setLine(node->getLine()); - current = mul; - } - - // For negative pow, compute the reciprocal of the positive pow. - if (exponent < 0) - { - TConstantUnion *oneVal = new TConstantUnion(); - oneVal->setFConst(1.0f); - TIntermConstantUnion *oneNode = new TIntermConstantUnion(oneVal, node->getType()); - TIntermBinary *div = new TIntermBinary(EOpDiv, oneNode, current); - current = div; - } - - queueReplacement(current, OriginalNode::IS_DROPPED); - mFound = true; - return false; -} - -} // anonymous namespace - -void ExpandIntegerPowExpressions(TIntermNode *root, TSymbolTable *symbolTable) -{ - Traverser::Apply(root, symbolTable); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/ExpandIntegerPowExpressions.h b/src/3rdparty/angle/src/compiler/translator/ExpandIntegerPowExpressions.h deleted file mode 100644 index 0074e5d663..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/ExpandIntegerPowExpressions.h +++ /dev/null @@ -1,29 +0,0 @@ -// -// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// This mutating tree traversal works around a bug in the HLSL compiler optimizer with "pow" that -// manifests under the following conditions: -// -// - If pow() has a literal exponent value -// - ... and this value is integer or within 10e-6 of an integer -// - ... and it is in {-4, -3, -2, 2, 3, 4, 5, 6, 7, 8} -// -// The workaround is to replace the pow with a series of multiplies. -// See http://anglebug.com/851 - -#ifndef COMPILER_TRANSLATOR_EXPANDINTEGERPOWEXPRESSIONS_H_ -#define COMPILER_TRANSLATOR_EXPANDINTEGERPOWEXPRESSIONS_H_ - -namespace sh -{ - -class TIntermNode; -class TSymbolTable; - -void ExpandIntegerPowExpressions(TIntermNode *root, TSymbolTable *symbolTable); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_EXPANDINTEGERPOWEXPRESSIONS_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/ExtensionBehavior.cpp b/src/3rdparty/angle/src/compiler/translator/ExtensionBehavior.cpp deleted file mode 100644 index 3f910b9050..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/ExtensionBehavior.cpp +++ /dev/null @@ -1,96 +0,0 @@ -// -// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// ExtensionBehavior.cpp: Extension name enumeration and data structures for storing extension -// behavior. - -#include "compiler/translator/ExtensionBehavior.h" - -#include "common/debug.h" - -#include - -#define LIST_EXTENSIONS(OP) \ - OP(ARB_texture_rectangle) \ - OP(ARM_shader_framebuffer_fetch) \ - OP(EXT_blend_func_extended) \ - OP(EXT_draw_buffers) \ - OP(EXT_frag_depth) \ - OP(EXT_geometry_shader) \ - OP(EXT_shader_framebuffer_fetch) \ - OP(EXT_shader_texture_lod) \ - OP(EXT_YUV_target) \ - OP(NV_EGL_stream_consumer_external) \ - OP(NV_shader_framebuffer_fetch) \ - OP(OES_EGL_image_external) \ - OP(OES_EGL_image_external_essl3) \ - OP(OES_geometry_shader) \ - OP(OES_standard_derivatives) \ - OP(OVR_multiview) - -namespace sh -{ - -#define RETURN_EXTENSION_NAME_CASE(ext) \ - case TExtension::ext: \ - return "GL_" #ext; - -const char *GetExtensionNameString(TExtension extension) -{ - switch (extension) - { - LIST_EXTENSIONS(RETURN_EXTENSION_NAME_CASE) - default: - UNREACHABLE(); - return ""; - } -} - -#define RETURN_EXTENSION_IF_NAME_MATCHES(ext) \ - if (strcmp(extWithoutGLPrefix, #ext) == 0) \ - { \ - return TExtension::ext; \ - } - -TExtension GetExtensionByName(const char *extension) -{ - // If first characters of the extension don't equal "GL_", early out. - if (strncmp(extension, "GL_", 3) != 0) - { - return TExtension::UNDEFINED; - } - const char *extWithoutGLPrefix = extension + 3; - - LIST_EXTENSIONS(RETURN_EXTENSION_IF_NAME_MATCHES) - - return TExtension::UNDEFINED; -} - -const char *GetBehaviorString(TBehavior b) -{ - switch (b) - { - case EBhRequire: - return "require"; - case EBhEnable: - return "enable"; - case EBhWarn: - return "warn"; - case EBhDisable: - return "disable"; - default: - return nullptr; - } -} - -bool IsExtensionEnabled(const TExtensionBehavior &extBehavior, TExtension extension) -{ - ASSERT(extension != TExtension::UNDEFINED); - auto iter = extBehavior.find(extension); - return iter != extBehavior.end() && - (iter->second == EBhEnable || iter->second == EBhRequire || iter->second == EBhWarn); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/ExtensionBehavior.h b/src/3rdparty/angle/src/compiler/translator/ExtensionBehavior.h deleted file mode 100644 index 09cc03f10f..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/ExtensionBehavior.h +++ /dev/null @@ -1,60 +0,0 @@ -// -// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// ExtensionBehavior.h: Extension name enumeration and data structures for storing extension -// behavior. - -#ifndef COMPILER_TRANSLATOR_EXTENSIONBEHAVIOR_H_ -#define COMPILER_TRANSLATOR_EXTENSIONBEHAVIOR_H_ - -#include - -namespace sh -{ - -enum class TExtension -{ - UNDEFINED, // Special value used to indicate no extension. - - ARB_texture_rectangle, - ARM_shader_framebuffer_fetch, - EXT_blend_func_extended, - EXT_draw_buffers, - EXT_frag_depth, - EXT_geometry_shader, - EXT_shader_framebuffer_fetch, - EXT_shader_texture_lod, - EXT_YUV_target, - NV_EGL_stream_consumer_external, - NV_shader_framebuffer_fetch, - OES_EGL_image_external, - OES_EGL_image_external_essl3, - OES_geometry_shader, - OES_standard_derivatives, - OVR_multiview -}; - -enum TBehavior -{ - EBhRequire, - EBhEnable, - EBhWarn, - EBhDisable, - EBhUndefined -}; - -const char *GetExtensionNameString(TExtension extension); -TExtension GetExtensionByName(const char *extension); - -const char *GetBehaviorString(TBehavior b); - -// Mapping between extension id and behavior. -typedef std::map TExtensionBehavior; - -bool IsExtensionEnabled(const TExtensionBehavior &extBehavior, TExtension extension); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_EXTENSIONBEHAVIOR_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/ExtensionGLSL.cpp b/src/3rdparty/angle/src/compiler/translator/ExtensionGLSL.cpp deleted file mode 100644 index 5b5dc580e9..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/ExtensionGLSL.cpp +++ /dev/null @@ -1,105 +0,0 @@ -// -// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// ExtensionGLSL.cpp: Implements the TExtensionGLSL class that tracks GLSL extension requirements -// of shaders. - -#include "compiler/translator/ExtensionGLSL.h" - -#include "compiler/translator/VersionGLSL.h" - -namespace sh -{ - -TExtensionGLSL::TExtensionGLSL(ShShaderOutput output) - : TIntermTraverser(true, false, false), mTargetVersion(ShaderOutputTypeToGLSLVersion(output)) -{ -} - -const std::set &TExtensionGLSL::getEnabledExtensions() const -{ - return mEnabledExtensions; -} - -const std::set &TExtensionGLSL::getRequiredExtensions() const -{ - return mRequiredExtensions; -} - -bool TExtensionGLSL::visitUnary(Visit, TIntermUnary *node) -{ - checkOperator(node); - - return true; -} - -bool TExtensionGLSL::visitAggregate(Visit, TIntermAggregate *node) -{ - checkOperator(node); - - return true; -} - -void TExtensionGLSL::checkOperator(TIntermOperator *node) -{ - if (mTargetVersion < GLSL_VERSION_130) - { - return; - } - - switch (node->getOp()) - { - case EOpAbs: - break; - - case EOpSign: - break; - - case EOpMix: - break; - - case EOpFloatBitsToInt: - case EOpFloatBitsToUint: - case EOpIntBitsToFloat: - case EOpUintBitsToFloat: - if (mTargetVersion < GLSL_VERSION_330) - { - // Bit conversion functions cannot be emulated. - mRequiredExtensions.insert("GL_ARB_shader_bit_encoding"); - } - break; - - case EOpPackSnorm2x16: - case EOpPackHalf2x16: - case EOpUnpackSnorm2x16: - case EOpUnpackHalf2x16: - if (mTargetVersion < GLSL_VERSION_420) - { - mEnabledExtensions.insert("GL_ARB_shading_language_packing"); - - if (mTargetVersion < GLSL_VERSION_330) - { - // floatBitsToUint and uintBitsToFloat are needed to emulate - // packHalf2x16 and unpackHalf2x16 respectively and cannot be - // emulated themselves. - mRequiredExtensions.insert("GL_ARB_shader_bit_encoding"); - } - } - break; - - case EOpPackUnorm2x16: - case EOpUnpackUnorm2x16: - if (mTargetVersion < GLSL_VERSION_410) - { - mEnabledExtensions.insert("GL_ARB_shading_language_packing"); - } - break; - - default: - break; - } -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/ExtensionGLSL.h b/src/3rdparty/angle/src/compiler/translator/ExtensionGLSL.h deleted file mode 100644 index a1b9cb2225..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/ExtensionGLSL.h +++ /dev/null @@ -1,44 +0,0 @@ -// -// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// ExtensionGLSL.h: Defines the TExtensionGLSL class that tracks GLSL extension requirements of -// shaders. - -#ifndef COMPILER_TRANSLATOR_EXTENSIONGLSL_H_ -#define COMPILER_TRANSLATOR_EXTENSIONGLSL_H_ - -#include -#include - -#include "compiler/translator/IntermTraverse.h" - -namespace sh -{ - -// Traverses the intermediate tree to determine which GLSL extensions are required -// to support the shader. -class TExtensionGLSL : public TIntermTraverser -{ - public: - TExtensionGLSL(ShShaderOutput output); - - const std::set &getEnabledExtensions() const; - const std::set &getRequiredExtensions() const; - - bool visitUnary(Visit visit, TIntermUnary *node) override; - bool visitAggregate(Visit visit, TIntermAggregate *node) override; - - private: - void checkOperator(TIntermOperator *node); - - int mTargetVersion; - - std::set mEnabledExtensions; - std::set mRequiredExtensions; -}; - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_EXTENSIONGLSL_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/FindMain.cpp b/src/3rdparty/angle/src/compiler/translator/FindMain.cpp deleted file mode 100644 index 7417fbac8a..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/FindMain.cpp +++ /dev/null @@ -1,38 +0,0 @@ -// -// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// FindMain.cpp: Find the main() function definition in a given AST. - -#include "compiler/translator/FindMain.h" - -#include "compiler/translator/IntermNode.h" - -namespace sh -{ - -TIntermFunctionDefinition *FindMain(TIntermBlock *root) -{ - for (TIntermNode *node : *root->getSequence()) - { - TIntermFunctionDefinition *nodeFunction = node->getAsFunctionDefinition(); - if (nodeFunction != nullptr && nodeFunction->getFunctionSymbolInfo()->isMain()) - { - return nodeFunction; - } - } - return nullptr; -} - -TIntermBlock *FindMainBody(TIntermBlock *root) -{ - TIntermFunctionDefinition *main = FindMain(root); - ASSERT(main != nullptr); - TIntermBlock *mainBody = main->getBody(); - ASSERT(mainBody != nullptr); - return mainBody; -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/FindMain.h b/src/3rdparty/angle/src/compiler/translator/FindMain.h deleted file mode 100644 index bf2c45d871..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/FindMain.h +++ /dev/null @@ -1,23 +0,0 @@ -// -// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// FindMain.h: Adds functions to get the main function definition and its body. - -#ifndef COMPILER_TRANSLATOR_FINDMAIN_H_ -#define COMPILER_TRANSLATOR_FINDMAIN_H_ - -namespace sh -{ - -class TIntermBlock; -class TIntermFunctionDefinition; - -TIntermFunctionDefinition *FindMain(TIntermBlock *root); -TIntermBlock *FindMainBody(TIntermBlock *root); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_FINDMAIN_H_ \ No newline at end of file diff --git a/src/3rdparty/angle/src/compiler/translator/FindSymbolNode.cpp b/src/3rdparty/angle/src/compiler/translator/FindSymbolNode.cpp deleted file mode 100644 index a2a10f128d..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/FindSymbolNode.cpp +++ /dev/null @@ -1,58 +0,0 @@ -// -// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// FindSymbol.cpp: -// Utility for finding a symbol node inside an AST tree. - -#include "compiler/translator/FindSymbolNode.h" - -#include "compiler/translator/IntermTraverse.h" - -namespace sh -{ - -namespace -{ - -class SymbolFinder : public TIntermTraverser -{ - public: - SymbolFinder(const TString &symbolName, TBasicType basicType) - : TIntermTraverser(true, false, false), - mSymbolName(symbolName), - mNodeFound(nullptr), - mBasicType(basicType) - { - } - - void visitSymbol(TIntermSymbol *node) - { - if (node->getBasicType() == mBasicType && node->getSymbol() == mSymbolName) - { - mNodeFound = node; - } - } - - bool isFound() const { return mNodeFound != nullptr; } - const TIntermSymbol *getNode() const { return mNodeFound; } - - private: - TString mSymbolName; - TIntermSymbol *mNodeFound; - TBasicType mBasicType; -}; - -} // anonymous namespace - -const TIntermSymbol *FindSymbolNode(TIntermNode *root, - const TString &symbolName, - TBasicType basicType) -{ - SymbolFinder finder(symbolName, basicType); - root->traverse(&finder); - return finder.getNode(); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/FindSymbolNode.h b/src/3rdparty/angle/src/compiler/translator/FindSymbolNode.h deleted file mode 100644 index 08dfb9a222..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/FindSymbolNode.h +++ /dev/null @@ -1,27 +0,0 @@ -// -// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// FindSymbolNode.h: -// Utility for finding a symbol node inside an AST tree. - -#ifndef COMPILER_TRANSLATOR_FIND_SYMBOL_H_ -#define COMPILER_TRANSLATOR_FIND_SYMBOL_H_ - -#include "compiler/translator/BaseTypes.h" -#include "compiler/translator/Common.h" - -namespace sh -{ - -class TIntermNode; -class TIntermSymbol; - -const TIntermSymbol *FindSymbolNode(TIntermNode *root, - const TString &symbolName, - TBasicType basicType); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_FIND_SYMBOL_H_ \ No newline at end of file diff --git a/src/3rdparty/angle/src/compiler/translator/FlagStd140Structs.cpp b/src/3rdparty/angle/src/compiler/translator/FlagStd140Structs.cpp deleted file mode 100644 index fba837f55c..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/FlagStd140Structs.cpp +++ /dev/null @@ -1,75 +0,0 @@ -// -// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// FlagStd140Structs.cpp: Find structs in std140 blocks, where the padding added in the translator -// conflicts with the "natural" unpadded type. - -#include "compiler/translator/FlagStd140Structs.h" - -#include "compiler/translator/IntermTraverse.h" - -namespace sh -{ - -namespace -{ - -class FlagStd140StructsTraverser : public TIntermTraverser -{ - public: - FlagStd140StructsTraverser() : TIntermTraverser(true, false, false) {} - - const std::vector getMappedStructs() const { return mMappedStructs; } - - protected: - bool visitDeclaration(Visit visit, TIntermDeclaration *node) override; - - private: - void mapBlockStructMembers(TIntermSymbol *blockDeclarator, TInterfaceBlock *block); - - std::vector mMappedStructs; -}; - -void FlagStd140StructsTraverser::mapBlockStructMembers(TIntermSymbol *blockDeclarator, - TInterfaceBlock *block) -{ - for (auto *field : block->fields()) - { - if (field->type()->getBasicType() == EbtStruct) - { - MappedStruct mappedStruct; - mappedStruct.blockDeclarator = blockDeclarator; - mappedStruct.field = field; - mMappedStructs.push_back(mappedStruct); - } - } -} - -bool FlagStd140StructsTraverser::visitDeclaration(Visit visit, TIntermDeclaration *node) -{ - TIntermTyped *declarator = node->getSequence()->back()->getAsTyped(); - if (declarator->getBasicType() == EbtInterfaceBlock) - { - TInterfaceBlock *block = declarator->getType().getInterfaceBlock(); - if (block->blockStorage() == EbsStd140) - { - mapBlockStructMembers(declarator->getAsSymbolNode(), block); - } - } - return false; -} - -} // anonymous namespace - -std::vector FlagStd140Structs(TIntermNode *node) -{ - FlagStd140StructsTraverser flaggingTraversal; - - node->traverse(&flaggingTraversal); - - return flaggingTraversal.getMappedStructs(); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/FlagStd140Structs.h b/src/3rdparty/angle/src/compiler/translator/FlagStd140Structs.h deleted file mode 100644 index f548d8b6ed..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/FlagStd140Structs.h +++ /dev/null @@ -1,30 +0,0 @@ -// -// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// FlagStd140Structs.h: Find structs in std140 blocks, where the padding added in the translator -// conflicts with the "natural" unpadded type. - -#ifndef COMPILER_TRANSLATOR_FLAGSTD140STRUCTS_H_ -#define COMPILER_TRANSLATOR_FLAGSTD140STRUCTS_H_ - -#include - -namespace sh -{ - -class TField; -class TIntermNode; -class TIntermSymbol; - -struct MappedStruct -{ - TIntermSymbol *blockDeclarator; - TField *field; -}; - -std::vector FlagStd140Structs(TIntermNode *node); -} - -#endif // COMPILER_TRANSLATOR_FLAGSTD140STRUCTS_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/HashNames.cpp b/src/3rdparty/angle/src/compiler/translator/HashNames.cpp deleted file mode 100644 index 6bc90faf94..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/HashNames.cpp +++ /dev/null @@ -1,72 +0,0 @@ -// -// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/translator/HashNames.h" - -#include "compiler/translator/IntermNode.h" - -namespace sh -{ - -namespace -{ - -// GLSL ES 3.00.6 section 3.9: the maximum length of an identifier is 1024 characters. -static const unsigned int kESSLMaxIdentifierLength = 1024u; - -static const char *kHashedNamePrefix = "webgl_"; - -// Can't prefix with just _ because then we might introduce a double underscore, which is not safe -// in GLSL (ESSL 3.00.6 section 3.8: All identifiers containing a double underscore are reserved for -// use by the underlying implementation). u is short for user-defined. -static const char *kUnhashedNamePrefix = "_u"; -static const unsigned int kUnhashedNamePrefixLength = 2u; - -TString HashName(const TString &name, ShHashFunction64 hashFunction) -{ - ASSERT(!name.empty()); - ASSERT(hashFunction); - khronos_uint64_t number = (*hashFunction)(name.c_str(), name.length()); - TStringStream stream; - stream << kHashedNamePrefix << std::hex << number; - TString hashedName = stream.str(); - return hashedName; -} - -} // anonymous namespace - -TString HashName(const TName &name, ShHashFunction64 hashFunction, NameMap *nameMap) -{ - if (name.getString().empty() || name.isInternal()) - { - return name.getString(); - } - if (hashFunction == nullptr) - { - if (name.getString().length() + kUnhashedNamePrefixLength > kESSLMaxIdentifierLength) - { - // If the identifier length is already close to the limit, we can't prefix it. This is - // not a problem since there are no builtins or ANGLE's internal variables that would - // have as long names and could conflict. - return name.getString(); - } - return kUnhashedNamePrefix + name.getString(); - } - if (nameMap) - { - NameMap::const_iterator it = nameMap->find(name.getString().c_str()); - if (it != nameMap->end()) - return it->second.c_str(); - } - TString hashedName = HashName(name.getString(), hashFunction); - if (nameMap) - { - (*nameMap)[name.getString().c_str()] = hashedName.c_str(); - } - return hashedName; -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/HashNames.h b/src/3rdparty/angle/src/compiler/translator/HashNames.h deleted file mode 100644 index 28e861b309..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/HashNames.h +++ /dev/null @@ -1,28 +0,0 @@ -// -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_TRANSLATOR_HASHNAMES_H_ -#define COMPILER_TRANSLATOR_HASHNAMES_H_ - -#include - -#include "GLSLANG/ShaderLang.h" -#include "compiler/translator/Common.h" - -namespace sh -{ - -typedef std::map NameMap; - -class TName; - -// Hash user-defined name for GLSL output, with special handling for internal names. -// The nameMap parameter is optional and is used to cache hashed names if set. -TString HashName(const TName &name, ShHashFunction64 hashFunction, NameMap *nameMap); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_HASHNAMES_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/ImageFunctionHLSL.cpp b/src/3rdparty/angle/src/compiler/translator/ImageFunctionHLSL.cpp deleted file mode 100644 index 40b5e1f1e2..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/ImageFunctionHLSL.cpp +++ /dev/null @@ -1,304 +0,0 @@ -// -// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// ImageFunctionHLSL: Class for writing implementations of ESSL image functions into HLSL output. -// - -#include "compiler/translator/ImageFunctionHLSL.h" -#include "compiler/translator/UtilsHLSL.h" - -namespace sh -{ - -// static -void ImageFunctionHLSL::OutputImageFunctionArgumentList( - TInfoSinkBase &out, - const ImageFunctionHLSL::ImageFunction &imageFunction) -{ - if (imageFunction.readonly) - { - out << TextureString(imageFunction.image, imageFunction.imageInternalFormat) << " tex"; - } - else - { - out << RWTextureString(imageFunction.image, imageFunction.imageInternalFormat) << " tex"; - } - - if (imageFunction.method == ImageFunctionHLSL::ImageFunction::Method::LOAD || - imageFunction.method == ImageFunctionHLSL::ImageFunction::Method::STORE) - { - switch (imageFunction.image) - { - case EbtImage2D: - case EbtIImage2D: - case EbtUImage2D: - out << ", int2 p"; - break; - case EbtImage3D: - case EbtIImage3D: - case EbtUImage3D: - case EbtImageCube: - case EbtIImageCube: - case EbtUImageCube: - case EbtImage2DArray: - case EbtIImage2DArray: - case EbtUImage2DArray: - out << ", int3 p"; - break; - default: - UNREACHABLE(); - } - - if (imageFunction.method == ImageFunctionHLSL::ImageFunction::Method::STORE) - { - switch (imageFunction.image) - { - case EbtImage2D: - case EbtImage3D: - case EbtImageCube: - case EbtImage2DArray: - out << ", float4 data"; - break; - case EbtIImage2D: - case EbtIImage3D: - case EbtIImageCube: - case EbtIImage2DArray: - out << ", int4 data"; - break; - case EbtUImage2D: - case EbtUImage3D: - case EbtUImageCube: - case EbtUImage2DArray: - out << ", uint4 data"; - break; - default: - UNREACHABLE(); - } - } - } -} - -// static -void ImageFunctionHLSL::OutputImageSizeFunctionBody( - TInfoSinkBase &out, - const ImageFunctionHLSL::ImageFunction &imageFunction, - const TString &imageReference) -{ - if (IsImage3D(imageFunction.image) || IsImage2DArray(imageFunction.image) || - IsImageCube(imageFunction.image)) - { - // "depth" stores either the number of layers in an array texture or 3D depth - out << " uint width; uint height; uint depth;\n" - << " " << imageReference << ".GetDimensions(width, height, depth);\n"; - } - else if (IsImage2D(imageFunction.image)) - { - out << " uint width; uint height;\n" - << " " << imageReference << ".GetDimensions(width, height);\n"; - } - else - UNREACHABLE(); - - if (strcmp(imageFunction.getReturnType(), "int3") == 0) - { - out << " return int3(width, height, depth);\n"; - } - else - { - out << " return int2(width, height);\n"; - } -} - -// static -void ImageFunctionHLSL::OutputImageLoadFunctionBody( - TInfoSinkBase &out, - const ImageFunctionHLSL::ImageFunction &imageFunction, - const TString &imageReference) -{ - if (IsImage3D(imageFunction.image) || IsImage2DArray(imageFunction.image) || - IsImageCube(imageFunction.image)) - { - out << " return " << imageReference << "[uint3(p.x, p.y, p.z)];\n"; - } - else if (IsImage2D(imageFunction.image)) - { - out << " return " << imageReference << "[uint2(p.x, p.y)];\n"; - } - else - UNREACHABLE(); -} - -// static -void ImageFunctionHLSL::OutputImageStoreFunctionBody( - TInfoSinkBase &out, - const ImageFunctionHLSL::ImageFunction &imageFunction, - const TString &imageReference) -{ - if (IsImage3D(imageFunction.image) || IsImage2DArray(imageFunction.image) || - IsImage2D(imageFunction.image) || IsImageCube(imageFunction.image)) - { - out << " " << imageReference << "[p] = data;\n"; - } - else - UNREACHABLE(); -} - -TString ImageFunctionHLSL::ImageFunction::name() const -{ - TString name = "gl_image"; - if (readonly) - { - name += TextureTypeSuffix(image, imageInternalFormat); - } - else - { - name += RWTextureTypeSuffix(image, imageInternalFormat); - } - - switch (method) - { - case Method::SIZE: - name += "Size"; - break; - case Method::LOAD: - name += "Load"; - break; - case Method::STORE: - name += "Store"; - break; - default: - UNREACHABLE(); - } - - return name; -} - -const char *ImageFunctionHLSL::ImageFunction::getReturnType() const -{ - if (method == ImageFunction::Method::SIZE) - { - switch (image) - { - case EbtImage2D: - case EbtIImage2D: - case EbtUImage2D: - case EbtImageCube: - case EbtIImageCube: - case EbtUImageCube: - return "int2"; - case EbtImage3D: - case EbtIImage3D: - case EbtUImage3D: - case EbtImage2DArray: - case EbtIImage2DArray: - case EbtUImage2DArray: - return "int3"; - default: - UNREACHABLE(); - } - } - else if (method == ImageFunction::Method::LOAD) - { - switch (image) - { - case EbtImage2D: - case EbtImage3D: - case EbtImageCube: - case EbtImage2DArray: - return "float4"; - case EbtIImage2D: - case EbtIImage3D: - case EbtIImageCube: - case EbtIImage2DArray: - return "int4"; - case EbtUImage2D: - case EbtUImage3D: - case EbtUImageCube: - case EbtUImage2DArray: - return "uint4"; - default: - UNREACHABLE(); - } - } - else if (method == ImageFunction::Method::STORE) - { - return "void"; - } - else - { - UNREACHABLE(); - } - return ""; -} - -bool ImageFunctionHLSL::ImageFunction::operator<(const ImageFunction &rhs) const -{ - return std::tie(image, imageInternalFormat, readonly, method) < - std::tie(rhs.image, rhs.imageInternalFormat, rhs.readonly, rhs.method); -} - -TString ImageFunctionHLSL::useImageFunction(const TString &name, - const TBasicType &type, - TLayoutImageInternalFormat imageInternalFormat, - bool readonly) -{ - ASSERT(IsImage(type)); - ImageFunction imageFunction; - imageFunction.image = type; - imageFunction.imageInternalFormat = imageInternalFormat; - imageFunction.readonly = readonly; - - if (name == "imageSize") - { - imageFunction.method = ImageFunction::Method::SIZE; - } - else if (name == "imageLoad") - { - imageFunction.method = ImageFunction::Method::LOAD; - } - else if (name == "imageStore") - { - imageFunction.method = ImageFunction::Method::STORE; - } - else - UNREACHABLE(); - - mUsesImage.insert(imageFunction); - return imageFunction.name(); -} - -void ImageFunctionHLSL::imageFunctionHeader(TInfoSinkBase &out) -{ - for (const ImageFunction &imageFunction : mUsesImage) - { - // Function header - out << imageFunction.getReturnType() << " " << imageFunction.name() << "("; - - OutputImageFunctionArgumentList(out, imageFunction); - - out << ")\n" - "{\n"; - - TString imageReference("tex"); - - if (imageFunction.method == ImageFunction::Method::SIZE) - { - OutputImageSizeFunctionBody(out, imageFunction, imageReference); - } - else if (imageFunction.method == ImageFunction::Method::LOAD) - { - OutputImageLoadFunctionBody(out, imageFunction, imageReference); - } - else - { - OutputImageStoreFunctionBody(out, imageFunction, imageReference); - } - - out << "}\n" - "\n"; - } -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/ImageFunctionHLSL.h b/src/3rdparty/angle/src/compiler/translator/ImageFunctionHLSL.h deleted file mode 100644 index 9db17a6bbf..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/ImageFunctionHLSL.h +++ /dev/null @@ -1,76 +0,0 @@ -// -// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// ImageFunctionHLSL: Class for writing implementations of ESSL image functions into HLSL output. -// - -#ifndef COMPILER_TRANSLATOR_IMAGEFUNCTIONHLSL_H_ -#define COMPILER_TRANSLATOR_IMAGEFUNCTIONHLSL_H_ - -#include - -#include "GLSLANG/ShaderLang.h" -#include "compiler/translator/BaseTypes.h" -#include "compiler/translator/Common.h" -#include "compiler/translator/InfoSink.h" -#include "compiler/translator/Types.h" - -namespace sh -{ - -class ImageFunctionHLSL final : angle::NonCopyable -{ - public: - // Returns the name of the image function implementation to caller. - // The name that's passed in is the name of the GLSL image function that it should implement. - TString useImageFunction(const TString &name, - const TBasicType &type, - TLayoutImageInternalFormat imageInternalFormat, - bool readonly); - - void imageFunctionHeader(TInfoSinkBase &out); - - private: - struct ImageFunction - { - // See ESSL 3.10.4 section 8.12 for reference about what the different methods below do. - enum class Method - { - SIZE, - LOAD, - STORE - }; - - TString name() const; - - bool operator<(const ImageFunction &rhs) const; - - const char *getReturnType() const; - - TBasicType image; - TLayoutImageInternalFormat imageInternalFormat; - bool readonly; - Method method; - }; - - static void OutputImageFunctionArgumentList( - TInfoSinkBase &out, - const ImageFunctionHLSL::ImageFunction &imageFunction); - static void OutputImageSizeFunctionBody(TInfoSinkBase &out, - const ImageFunctionHLSL::ImageFunction &imageFunction, - const TString &imageReference); - static void OutputImageLoadFunctionBody(TInfoSinkBase &out, - const ImageFunctionHLSL::ImageFunction &imageFunction, - const TString &imageReference); - static void OutputImageStoreFunctionBody(TInfoSinkBase &out, - const ImageFunctionHLSL::ImageFunction &imageFunction, - const TString &imageReference); - using ImageFunctionSet = std::set; - ImageFunctionSet mUsesImage; -}; - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_IMAGEFUNCTIONHLSL_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/InfoSink.cpp b/src/3rdparty/angle/src/compiler/translator/InfoSink.cpp deleted file mode 100644 index db26aa67e8..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/InfoSink.cpp +++ /dev/null @@ -1,40 +0,0 @@ -// -// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/translator/InfoSink.h" - -namespace sh -{ - -void TInfoSinkBase::prefix(Severity severity) -{ - switch (severity) - { - case SH_WARNING: - sink.append("WARNING: "); - break; - case SH_ERROR: - sink.append("ERROR: "); - break; - default: - sink.append("UNKOWN ERROR: "); - break; - } -} - -void TInfoSinkBase::location(int file, int line) -{ - TPersistStringStream stream; - if (line) - stream << file << ":" << line; - else - stream << file << ":? "; - stream << ": "; - - sink.append(stream.str()); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/InfoSink.h b/src/3rdparty/angle/src/compiler/translator/InfoSink.h deleted file mode 100644 index 2705f48d59..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/InfoSink.h +++ /dev/null @@ -1,120 +0,0 @@ -// -// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_TRANSLATOR_INFOSINK_H_ -#define COMPILER_TRANSLATOR_INFOSINK_H_ - -#include -#include -#include "compiler/translator/Common.h" -#include "compiler/translator/Severity.h" - -namespace sh -{ - -// Returns the fractional part of the given floating-point number. -inline float fractionalPart(float f) -{ - float intPart = 0.0f; - return modff(f, &intPart); -} - -// -// 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() {} - - template - TInfoSinkBase &operator<<(const T &t) - { - TPersistStringStream stream; - stream << t; - sink.append(stream.str()); - return *this; - } - // Override << operator for specific types. It is faster to append strings - // and characters directly to the sink. - TInfoSinkBase &operator<<(char c) - { - sink.append(1, c); - return *this; - } - TInfoSinkBase &operator<<(const char *str) - { - sink.append(str); - return *this; - } - TInfoSinkBase &operator<<(const TPersistString &str) - { - sink.append(str); - return *this; - } - TInfoSinkBase &operator<<(const TString &str) - { - sink.append(str.c_str()); - return *this; - } - // Make sure floats are written with correct precision. - TInfoSinkBase &operator<<(float f) - { - // Make sure that at least one decimal point is written. If a number - // does not have a fractional part, the default precision format does - // not write the decimal portion which gets interpreted as integer by - // the compiler. - TPersistStringStream stream; - if (fractionalPart(f) == 0.0f) - { - stream.precision(1); - stream << std::showpoint << std::fixed << f; - } - else - { - stream.unsetf(std::ios::fixed); - stream.unsetf(std::ios::scientific); - stream.precision(8); - stream << f; - } - sink.append(stream.str()); - return *this; - } - // Write boolean values as their names instead of integral value. - TInfoSinkBase &operator<<(bool b) - { - const char *str = b ? "true" : "false"; - sink.append(str); - return *this; - } - - void erase() { sink.clear(); } - int size() { return static_cast(sink.size()); } - - const TPersistString &str() const { return sink; } - const char *c_str() const { return sink.c_str(); } - - void prefix(Severity severity); - void location(int file, int line); - - private: - TPersistString sink; -}; - -class TInfoSink -{ - public: - TInfoSinkBase info; - TInfoSinkBase debug; - TInfoSinkBase obj; -}; - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_INFOSINK_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/Initialize.cpp b/src/3rdparty/angle/src/compiler/translator/Initialize.cpp deleted file mode 100644 index 6f8baee96b..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/Initialize.cpp +++ /dev/null @@ -1,1135 +0,0 @@ -// -// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// -// Create symbols that declare built-in definitions, add built-ins that -// cannot be expressed in the files, and establish mappings between -// built-in functions and operators. -// - -#include "compiler/translator/Initialize.h" -#include "compiler/translator/Cache.h" - -#include "compiler/translator/IntermNode.h" -#include "angle_gl.h" - -namespace sh -{ - -void InsertBuiltInFunctions(sh::GLenum type, - ShShaderSpec spec, - const ShBuiltInResources &resources, - TSymbolTable &symbolTable) -{ - const TType *voidType = TCache::getType(EbtVoid); - const TType *float1 = TCache::getType(EbtFloat); - const TType *float2 = TCache::getType(EbtFloat, 2); - const TType *float3 = TCache::getType(EbtFloat, 3); - const TType *float4 = TCache::getType(EbtFloat, 4); - const TType *int1 = TCache::getType(EbtInt); - const TType *int2 = TCache::getType(EbtInt, 2); - const TType *int3 = TCache::getType(EbtInt, 3); - const TType *uint1 = TCache::getType(EbtUInt); - const TType *bool1 = TCache::getType(EbtBool); - const TType *genType = TCache::getType(EbtGenType); - const TType *genIType = TCache::getType(EbtGenIType); - const TType *genUType = TCache::getType(EbtGenUType); - const TType *genBType = TCache::getType(EbtGenBType); - - // - // Angle and Trigonometric Functions. - // - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpRadians, genType, genType); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpDegrees, genType, genType); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpSin, genType, genType); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpCos, genType, genType); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpTan, genType, genType); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpAsin, genType, genType); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpAcos, genType, genType); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpAtan, genType, genType, genType); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpAtan, genType, genType); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpSinh, genType, genType); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpCosh, genType, genType); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpTanh, genType, genType); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpAsinh, genType, genType); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpAcosh, genType, genType); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpAtanh, genType, genType); - - // - // Exponential Functions. - // - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpPow, genType, genType, genType); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpExp, genType, genType); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpLog, genType, genType); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpExp2, genType, genType); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpLog2, genType, genType); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpSqrt, genType, genType); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpInverseSqrt, genType, genType); - - // - // Common Functions. - // - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpAbs, genType, genType); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpAbs, genIType, genIType); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpSign, genType, genType); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpSign, genIType, genIType); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpFloor, genType, genType); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpTrunc, genType, genType); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpRound, genType, genType); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpRoundEven, genType, genType); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpCeil, genType, genType); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpFract, genType, genType); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpMod, genType, genType, float1); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpMod, genType, genType, genType); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpMin, genType, genType, float1); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpMin, genType, genType, genType); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpMin, genIType, genIType, genIType); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpMin, genIType, genIType, int1); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpMin, genUType, genUType, genUType); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpMin, genUType, genUType, uint1); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpMax, genType, genType, float1); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpMax, genType, genType, genType); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpMax, genIType, genIType, genIType); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpMax, genIType, genIType, int1); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpMax, genUType, genUType, genUType); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpMax, genUType, genUType, uint1); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpClamp, genType, genType, float1, float1); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpClamp, genType, genType, genType, genType); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpClamp, genIType, genIType, int1, int1); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpClamp, genIType, genIType, genIType, genIType); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpClamp, genUType, genUType, uint1, uint1); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpClamp, genUType, genUType, genUType, genUType); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpMix, genType, genType, genType, float1); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpMix, genType, genType, genType, genType); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpMix, genType, genType, genType, genBType); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpStep, genType, genType, genType); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpStep, genType, float1, genType); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpSmoothStep, genType, genType, genType, genType); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpSmoothStep, genType, float1, float1, genType); - - const TType *outGenType = TCache::getType(EbtGenType, EvqOut); - const TType *outGenIType = TCache::getType(EbtGenIType, EvqOut); - - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpModf, genType, genType, outGenType); - - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpIsNan, genBType, genType); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpIsInf, genBType, genType); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpFloatBitsToInt, genIType, genType); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpFloatBitsToUint, genUType, genType); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpIntBitsToFloat, genType, genIType); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpUintBitsToFloat, genType, genUType); - - symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpFrexp, genType, genType, outGenIType); - symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpLdexp, genType, genType, genIType); - - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpPackSnorm2x16, uint1, float2); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpPackUnorm2x16, uint1, float2); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpPackHalf2x16, uint1, float2); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpUnpackSnorm2x16, float2, uint1); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpUnpackUnorm2x16, float2, uint1); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpUnpackHalf2x16, float2, uint1); - - symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpPackUnorm4x8, uint1, float4); - symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpPackSnorm4x8, uint1, float4); - symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpUnpackUnorm4x8, float4, uint1); - symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpUnpackSnorm4x8, float4, uint1); - - // - // Geometric Functions. - // - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpLength, float1, genType); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpDistance, float1, genType, genType); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpDot, float1, genType, genType); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpCross, float3, float3, float3); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpNormalize, genType, genType); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpFaceforward, genType, genType, genType, - genType); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpReflect, genType, genType, genType); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpRefract, genType, genType, genType, float1); - - const TType *mat2 = TCache::getType(EbtFloat, 2, 2); - const TType *mat3 = TCache::getType(EbtFloat, 3, 3); - const TType *mat4 = TCache::getType(EbtFloat, 4, 4); - const TType *mat2x3 = TCache::getType(EbtFloat, 2, 3); - const TType *mat3x2 = TCache::getType(EbtFloat, 3, 2); - const TType *mat2x4 = TCache::getType(EbtFloat, 2, 4); - const TType *mat4x2 = TCache::getType(EbtFloat, 4, 2); - const TType *mat3x4 = TCache::getType(EbtFloat, 3, 4); - const TType *mat4x3 = TCache::getType(EbtFloat, 4, 3); - - // - // Matrix Functions. - // - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpMulMatrixComponentWise, mat2, mat2, mat2); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpMulMatrixComponentWise, mat3, mat3, mat3); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpMulMatrixComponentWise, mat4, mat4, mat4); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpMulMatrixComponentWise, mat2x3, mat2x3, mat2x3); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpMulMatrixComponentWise, mat3x2, mat3x2, mat3x2); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpMulMatrixComponentWise, mat2x4, mat2x4, mat2x4); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpMulMatrixComponentWise, mat4x2, mat4x2, mat4x2); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpMulMatrixComponentWise, mat3x4, mat3x4, mat3x4); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpMulMatrixComponentWise, mat4x3, mat4x3, mat4x3); - - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpOuterProduct, mat2, float2, float2); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpOuterProduct, mat3, float3, float3); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpOuterProduct, mat4, float4, float4); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpOuterProduct, mat2x3, float3, float2); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpOuterProduct, mat3x2, float2, float3); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpOuterProduct, mat2x4, float4, float2); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpOuterProduct, mat4x2, float2, float4); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpOuterProduct, mat3x4, float4, float3); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpOuterProduct, mat4x3, float3, float4); - - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpTranspose, mat2, mat2); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpTranspose, mat3, mat3); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpTranspose, mat4, mat4); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpTranspose, mat2x3, mat3x2); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpTranspose, mat3x2, mat2x3); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpTranspose, mat2x4, mat4x2); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpTranspose, mat4x2, mat2x4); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpTranspose, mat3x4, mat4x3); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpTranspose, mat4x3, mat3x4); - - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpDeterminant, float1, mat2); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpDeterminant, float1, mat3); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpDeterminant, float1, mat4); - - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpInverse, mat2, mat2); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpInverse, mat3, mat3); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpInverse, mat4, mat4); - - const TType *vec = TCache::getType(EbtVec); - const TType *ivec = TCache::getType(EbtIVec); - const TType *uvec = TCache::getType(EbtUVec); - const TType *bvec = TCache::getType(EbtBVec); - - // - // Vector relational functions. - // - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpLessThanComponentWise, bvec, vec, vec); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpLessThanComponentWise, bvec, ivec, ivec); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpLessThanComponentWise, bvec, uvec, uvec); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpLessThanEqualComponentWise, bvec, vec, vec); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpLessThanEqualComponentWise, bvec, ivec, ivec); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpLessThanEqualComponentWise, bvec, uvec, uvec); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpGreaterThanComponentWise, bvec, vec, vec); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpGreaterThanComponentWise, bvec, ivec, ivec); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpGreaterThanComponentWise, bvec, uvec, uvec); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpGreaterThanEqualComponentWise, bvec, vec, vec); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpGreaterThanEqualComponentWise, bvec, ivec, - ivec); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpGreaterThanEqualComponentWise, bvec, uvec, uvec); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpEqualComponentWise, bvec, vec, vec); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpEqualComponentWise, bvec, ivec, ivec); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpEqualComponentWise, bvec, uvec, uvec); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpEqualComponentWise, bvec, bvec, bvec); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpNotEqualComponentWise, bvec, vec, vec); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpNotEqualComponentWise, bvec, ivec, ivec); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpNotEqualComponentWise, bvec, uvec, uvec); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpNotEqualComponentWise, bvec, bvec, bvec); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpAny, bool1, bvec); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpAll, bool1, bvec); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpLogicalNotComponentWise, bvec, bvec); - - // - // Integer functions - // - const TType *outGenUType = TCache::getType(EbtGenUType, EvqOut); - - symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpBitfieldExtract, genIType, genIType, int1, - int1); - symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpBitfieldExtract, genUType, genUType, int1, - int1); - symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpBitfieldInsert, genIType, genIType, genIType, - int1, int1); - symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpBitfieldInsert, genUType, genUType, genUType, - int1, int1); - symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpBitfieldReverse, genIType, genIType); - symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpBitfieldReverse, genUType, genUType); - symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpBitCount, genIType, genIType); - symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpBitCount, genIType, genUType); - symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpFindLSB, genIType, genIType); - symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpFindLSB, genIType, genUType); - symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpFindMSB, genIType, genIType); - symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpFindMSB, genIType, genUType); - symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpUaddCarry, genUType, genUType, genUType, - outGenUType); - symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpUsubBorrow, genUType, genUType, genUType, - outGenUType); - symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpUmulExtended, voidType, genUType, genUType, - outGenUType, outGenUType); - symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpImulExtended, voidType, genIType, genIType, - outGenIType, outGenIType); - - const TType *sampler2D = TCache::getType(EbtSampler2D); - const TType *samplerCube = TCache::getType(EbtSamplerCube); - - // - // Texture Functions for GLSL ES 1.0 - // - symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2D", sampler2D, float2); - symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProj", sampler2D, float3); - symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProj", sampler2D, float4); - symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "textureCube", samplerCube, float3); - - if (resources.OES_EGL_image_external || resources.NV_EGL_stream_consumer_external) - { - const TType *samplerExternalOES = TCache::getType(EbtSamplerExternalOES); - - symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2D", samplerExternalOES, float2); - symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProj", samplerExternalOES, - float3); - symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProj", samplerExternalOES, - float4); - } - - if (resources.ARB_texture_rectangle) - { - const TType *sampler2DRect = TCache::getType(EbtSampler2DRect); - - symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DRect", sampler2DRect, float2); - symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DRectProj", sampler2DRect, - float3); - symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DRectProj", sampler2DRect, - float4); - } - - if (resources.EXT_shader_texture_lod) - { - /* The *Grad* variants are new to both vertex and fragment shaders; the fragment - * shader specific pieces are added separately below. - */ - symbolTable.insertBuiltIn(ESSL1_BUILTINS, TExtension::EXT_shader_texture_lod, float4, - "texture2DGradEXT", sampler2D, float2, float2, float2); - symbolTable.insertBuiltIn(ESSL1_BUILTINS, TExtension::EXT_shader_texture_lod, float4, - "texture2DProjGradEXT", sampler2D, float3, float2, float2); - symbolTable.insertBuiltIn(ESSL1_BUILTINS, TExtension::EXT_shader_texture_lod, float4, - "texture2DProjGradEXT", sampler2D, float4, float2, float2); - symbolTable.insertBuiltIn(ESSL1_BUILTINS, TExtension::EXT_shader_texture_lod, float4, - "textureCubeGradEXT", samplerCube, float3, float3, float3); - } - - if (type == GL_FRAGMENT_SHADER) - { - symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2D", sampler2D, float2, float1); - symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProj", sampler2D, float3, - float1); - symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProj", sampler2D, float4, - float1); - symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "textureCube", samplerCube, float3, - float1); - - if (resources.OES_standard_derivatives) - { - symbolTable.insertBuiltInOp(ESSL1_BUILTINS, EOpDFdx, - TExtension::OES_standard_derivatives, genType, genType); - symbolTable.insertBuiltInOp(ESSL1_BUILTINS, EOpDFdy, - TExtension::OES_standard_derivatives, genType, genType); - symbolTable.insertBuiltInOp(ESSL1_BUILTINS, EOpFwidth, - TExtension::OES_standard_derivatives, genType, genType); - } - - if (resources.EXT_shader_texture_lod) - { - symbolTable.insertBuiltIn(ESSL1_BUILTINS, TExtension::EXT_shader_texture_lod, float4, - "texture2DLodEXT", sampler2D, float2, float1); - symbolTable.insertBuiltIn(ESSL1_BUILTINS, TExtension::EXT_shader_texture_lod, float4, - "texture2DProjLodEXT", sampler2D, float3, float1); - symbolTable.insertBuiltIn(ESSL1_BUILTINS, TExtension::EXT_shader_texture_lod, float4, - "texture2DProjLodEXT", sampler2D, float4, float1); - symbolTable.insertBuiltIn(ESSL1_BUILTINS, TExtension::EXT_shader_texture_lod, float4, - "textureCubeLodEXT", samplerCube, float3, float1); - } - } - - if (type == GL_VERTEX_SHADER) - { - symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DLod", sampler2D, float2, - float1); - symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProjLod", sampler2D, float3, - float1); - symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProjLod", sampler2D, float4, - float1); - symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "textureCubeLod", samplerCube, float3, - float1); - } - - const TType *gvec4 = TCache::getType(EbtGVec4); - - const TType *gsampler2D = TCache::getType(EbtGSampler2D); - const TType *gsamplerCube = TCache::getType(EbtGSamplerCube); - const TType *gsampler3D = TCache::getType(EbtGSampler3D); - const TType *gsampler2DArray = TCache::getType(EbtGSampler2DArray); - const TType *gsampler2DMS = TCache::getType(EbtGSampler2DMS); - - // - // Texture Functions for GLSL ES 3.0 - // - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texture", gsampler2D, float2); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texture", gsampler3D, float3); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texture", gsamplerCube, float3); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texture", gsampler2DArray, float3); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProj", gsampler2D, float3); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProj", gsampler2D, float4); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProj", gsampler3D, float4); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureLod", gsampler2D, float2, float1); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureLod", gsampler3D, float3, float1); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureLod", gsamplerCube, float3, float1); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureLod", gsampler2DArray, float3, float1); - - if (resources.OES_EGL_image_external_essl3) - { - const TType *samplerExternalOES = TCache::getType(EbtSamplerExternalOES); - - symbolTable.insertBuiltIn(ESSL3_BUILTINS, float4, "texture", samplerExternalOES, float2); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, float4, "textureProj", samplerExternalOES, - float3); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, float4, "textureProj", samplerExternalOES, - float4); - } - - if (resources.EXT_YUV_target) - { - const TType *samplerExternal2DY2YEXT = TCache::getType(EbtSamplerExternal2DY2YEXT); - - symbolTable.insertBuiltIn(ESSL3_BUILTINS, TExtension::EXT_YUV_target, float4, "texture", - samplerExternal2DY2YEXT, float2); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, TExtension::EXT_YUV_target, float4, "textureProj", - samplerExternal2DY2YEXT, float3); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, TExtension::EXT_YUV_target, float4, "textureProj", - samplerExternal2DY2YEXT, float4); - - const TType *yuvCscStandardEXT = TCache::getType(EbtYuvCscStandardEXT); - - symbolTable.insertBuiltIn(ESSL3_BUILTINS, TExtension::EXT_YUV_target, float3, "rgb_2_yuv", - float3, yuvCscStandardEXT); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, TExtension::EXT_YUV_target, float3, "yuv_2_rgb", - float3, yuvCscStandardEXT); - } - - if (type == GL_FRAGMENT_SHADER) - { - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texture", gsampler2D, float2, float1); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texture", gsampler3D, float3, float1); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texture", gsamplerCube, float3, float1); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texture", gsampler2DArray, float3, - float1); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProj", gsampler2D, float3, float1); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProj", gsampler2D, float4, float1); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProj", gsampler3D, float4, float1); - - if (resources.OES_EGL_image_external_essl3) - { - const TType *samplerExternalOES = TCache::getType(EbtSamplerExternalOES); - - symbolTable.insertBuiltIn(ESSL3_BUILTINS, float4, "texture", samplerExternalOES, float2, - float1); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, float4, "textureProj", samplerExternalOES, - float3, float1); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, float4, "textureProj", samplerExternalOES, - float4, float1); - } - - if (resources.EXT_YUV_target) - { - const TType *samplerExternal2DY2YEXT = TCache::getType(EbtSamplerExternal2DY2YEXT); - - symbolTable.insertBuiltIn(ESSL3_BUILTINS, TExtension::EXT_YUV_target, float4, "texture", - samplerExternal2DY2YEXT, float2, float1); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, TExtension::EXT_YUV_target, float4, - "textureProj", samplerExternal2DY2YEXT, float3, float1); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, TExtension::EXT_YUV_target, float4, - "textureProj", samplerExternal2DY2YEXT, float4, float1); - } - } - - const TType *sampler2DShadow = TCache::getType(EbtSampler2DShadow); - const TType *samplerCubeShadow = TCache::getType(EbtSamplerCubeShadow); - const TType *sampler2DArrayShadow = TCache::getType(EbtSampler2DArrayShadow); - - symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "texture", sampler2DShadow, float3); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "texture", samplerCubeShadow, float4); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "texture", sampler2DArrayShadow, float4); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureProj", sampler2DShadow, float4); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureLod", sampler2DShadow, float3, - float1); - - if (type == GL_FRAGMENT_SHADER) - { - symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "texture", sampler2DShadow, float3, - float1); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "texture", samplerCubeShadow, float4, - float1); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureProj", sampler2DShadow, float4, - float1); - } - - symbolTable.insertBuiltIn(ESSL3_BUILTINS, int2, "textureSize", gsampler2D, int1); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, int3, "textureSize", gsampler3D, int1); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, int2, "textureSize", gsamplerCube, int1); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, int3, "textureSize", gsampler2DArray, int1); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, int2, "textureSize", sampler2DShadow, int1); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, int2, "textureSize", samplerCubeShadow, int1); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, int3, "textureSize", sampler2DArrayShadow, int1); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, int2, "textureSize", gsampler2DMS); - - if (resources.OES_EGL_image_external_essl3) - { - const TType *samplerExternalOES = TCache::getType(EbtSamplerExternalOES); - - symbolTable.insertBuiltIn(ESSL3_BUILTINS, int2, "textureSize", samplerExternalOES, int1); - } - - if (resources.EXT_YUV_target) - { - const TType *samplerExternal2DY2YEXT = TCache::getType(EbtSamplerExternal2DY2YEXT); - - symbolTable.insertBuiltIn(ESSL3_BUILTINS, TExtension::EXT_YUV_target, int2, "textureSize", - samplerExternal2DY2YEXT, int1); - } - - if (type == GL_FRAGMENT_SHADER) - { - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpDFdx, genType, genType); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpDFdy, genType, genType); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpFwidth, genType, genType); - } - - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureOffset", gsampler2D, float2, int2); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureOffset", gsampler3D, float3, int3); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureOffset", sampler2DShadow, float3, - int2); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureOffset", gsampler2DArray, float3, - int2); - - if (type == GL_FRAGMENT_SHADER) - { - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureOffset", gsampler2D, float2, int2, - float1); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureOffset", gsampler3D, float3, int3, - float1); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureOffset", sampler2DShadow, float3, - int2, float1); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureOffset", gsampler2DArray, float3, - int2, float1); - } - - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjOffset", gsampler2D, float3, int2); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjOffset", gsampler2D, float4, int2); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjOffset", gsampler3D, float4, int3); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureProjOffset", sampler2DShadow, float4, - int2); - - if (type == GL_FRAGMENT_SHADER) - { - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjOffset", gsampler2D, float3, - int2, float1); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjOffset", gsampler2D, float4, - int2, float1); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjOffset", gsampler3D, float4, - int3, float1); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureProjOffset", sampler2DShadow, - float4, int2, float1); - } - - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureLodOffset", gsampler2D, float2, float1, - int2); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureLodOffset", gsampler3D, float3, float1, - int3); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureLodOffset", sampler2DShadow, float3, - float1, int2); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureLodOffset", gsampler2DArray, float3, - float1, int2); - - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjLod", gsampler2D, float3, float1); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjLod", gsampler2D, float4, float1); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjLod", gsampler3D, float4, float1); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureProjLod", sampler2DShadow, float4, - float1); - - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjLodOffset", gsampler2D, float3, - float1, int2); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjLodOffset", gsampler2D, float4, - float1, int2); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjLodOffset", gsampler3D, float4, - float1, int3); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureProjLodOffset", sampler2DShadow, - float4, float1, int2); - - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texelFetch", gsampler2D, int2, int1); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texelFetch", gsampler3D, int3, int1); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texelFetch", gsampler2DArray, int3, int1); - - if (resources.OES_EGL_image_external_essl3) - { - const TType *samplerExternalOES = TCache::getType(EbtSamplerExternalOES); - - symbolTable.insertBuiltIn(ESSL3_BUILTINS, float4, "texelFetch", samplerExternalOES, int2, - int1); - } - - if (resources.EXT_YUV_target) - { - const TType *samplerExternal2DY2YEXT = TCache::getType(EbtSamplerExternal2DY2YEXT); - - symbolTable.insertBuiltIn(ESSL3_BUILTINS, TExtension::EXT_YUV_target, float4, "texelFetch", - samplerExternal2DY2YEXT, int2, int1); - } - - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texelFetchOffset", gsampler2D, int2, int1, - int2); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texelFetchOffset", gsampler3D, int3, int1, - int3); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texelFetchOffset", gsampler2DArray, int3, - int1, int2); - - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureGrad", gsampler2D, float2, float2, - float2); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureGrad", gsampler3D, float3, float3, - float3); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureGrad", gsamplerCube, float3, float3, - float3); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureGrad", sampler2DShadow, float3, - float2, float2); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureGrad", samplerCubeShadow, float4, - float3, float3); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureGrad", gsampler2DArray, float3, float2, - float2); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureGrad", sampler2DArrayShadow, float4, - float2, float2); - - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureGradOffset", gsampler2D, float2, - float2, float2, int2); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureGradOffset", gsampler3D, float3, - float3, float3, int3); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureGradOffset", sampler2DShadow, float3, - float2, float2, int2); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureGradOffset", gsampler2DArray, float3, - float2, float2, int2); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureGradOffset", sampler2DArrayShadow, - float4, float2, float2, int2); - - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjGrad", gsampler2D, float3, float2, - float2); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjGrad", gsampler2D, float4, float2, - float2); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjGrad", gsampler3D, float4, float3, - float3); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureProjGrad", sampler2DShadow, float4, - float2, float2); - - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjGradOffset", gsampler2D, float3, - float2, float2, int2); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjGradOffset", gsampler2D, float4, - float2, float2, int2); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjGradOffset", gsampler3D, float4, - float3, float3, int3); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureProjGradOffset", sampler2DShadow, - float4, float2, float2, int2); - - const TType *atomicCounter = TCache::getType(EbtAtomicCounter); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, uint1, "atomicCounter", atomicCounter); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, uint1, "atomicCounterIncrement", atomicCounter); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, uint1, "atomicCounterDecrement", atomicCounter); - - // Insert all atomic memory functions - const TType *int1InOut = TCache::getType(EbtInt, EvqInOut); - const TType *uint1InOut = TCache::getType(EbtUInt, EvqInOut); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, uint1, "atomicAdd", uint1InOut, uint1); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, int1, "atomicAdd", int1InOut, int1); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, uint1, "atomicMin", uint1InOut, uint1); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, int1, "atomicMin", int1InOut, int1); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, uint1, "atomicMax", uint1InOut, uint1); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, int1, "atomicMax", int1InOut, int1); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, uint1, "atomicAnd", uint1InOut, uint1); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, int1, "atomicAnd", int1InOut, int1); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, uint1, "atomicOr", uint1InOut, uint1); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, int1, "atomicOr", int1InOut, int1); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, uint1, "atomicXor", uint1InOut, uint1); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, int1, "atomicXor", int1InOut, int1); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, uint1, "atomicExchange", uint1InOut, uint1); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, int1, "atomicExchange", int1InOut, int1); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, uint1, "atomicCompSwap", uint1InOut, uint1, uint1); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, int1, "atomicCompSwap", int1InOut, int1, int1); - - const TType *gimage2D = TCache::getType(EbtGImage2D); - const TType *gimage3D = TCache::getType(EbtGImage3D); - const TType *gimage2DArray = TCache::getType(EbtGImage2DArray); - const TType *gimageCube = TCache::getType(EbtGImageCube); - - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, voidType, "imageStore", gimage2D, int2, gvec4); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, voidType, "imageStore", gimage3D, int3, gvec4); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, voidType, "imageStore", gimage2DArray, int3, gvec4); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, voidType, "imageStore", gimageCube, int3, gvec4); - - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, gvec4, "imageLoad", gimage2D, int2); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, gvec4, "imageLoad", gimage3D, int3); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, gvec4, "imageLoad", gimage2DArray, int3); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, gvec4, "imageLoad", gimageCube, int3); - - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, int2, "imageSize", gimage2D); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, int3, "imageSize", gimage3D); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, int3, "imageSize", gimage2DArray); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, int2, "imageSize", gimageCube); - - symbolTable.insertBuiltInFunctionNoParameters(ESSL3_1_BUILTINS, EOpMemoryBarrier, voidType, - "memoryBarrier"); - symbolTable.insertBuiltInFunctionNoParameters(ESSL3_1_BUILTINS, EOpMemoryBarrierAtomicCounter, - voidType, "memoryBarrierAtomicCounter"); - symbolTable.insertBuiltInFunctionNoParameters(ESSL3_1_BUILTINS, EOpMemoryBarrierBuffer, - voidType, "memoryBarrierBuffer"); - symbolTable.insertBuiltInFunctionNoParameters(ESSL3_1_BUILTINS, EOpMemoryBarrierImage, voidType, - "memoryBarrierImage"); - - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, gvec4, "texelFetch", gsampler2DMS, int2, int1); - - // Insert all variations of textureGather. - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, gvec4, "textureGather", gsampler2D, float2); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, gvec4, "textureGather", gsampler2D, float2, int1); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, gvec4, "textureGather", gsampler2DArray, float3); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, gvec4, "textureGather", gsampler2DArray, float3, - int1); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, gvec4, "textureGather", gsamplerCube, float3); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, gvec4, "textureGather", gsamplerCube, float3, int1); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, float4, "textureGather", sampler2DShadow, float2); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, float4, "textureGather", sampler2DShadow, float2, - float1); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, float4, "textureGather", sampler2DArrayShadow, - float3); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, float4, "textureGather", sampler2DArrayShadow, - float3, float1); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, float4, "textureGather", samplerCubeShadow, float3); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, float4, "textureGather", samplerCubeShadow, float3, - float1); - - // Insert all variations of textureGatherOffset. - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, gvec4, "textureGatherOffset", gsampler2D, float2, - int2); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, gvec4, "textureGatherOffset", gsampler2D, float2, - int2, int1); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, gvec4, "textureGatherOffset", gsampler2DArray, - float3, int2); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, gvec4, "textureGatherOffset", gsampler2DArray, - float3, int2, int1); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, float4, "textureGatherOffset", sampler2DShadow, - float2, float1, int2); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, float4, "textureGatherOffset", sampler2DArrayShadow, - float3, float1, int2); - - if (type == GL_COMPUTE_SHADER) - { - symbolTable.insertBuiltInFunctionNoParameters(ESSL3_1_BUILTINS, EOpBarrier, voidType, - "barrier"); - symbolTable.insertBuiltInFunctionNoParameters(ESSL3_1_BUILTINS, EOpMemoryBarrierShared, - voidType, "memoryBarrierShared"); - symbolTable.insertBuiltInFunctionNoParameters(ESSL3_1_BUILTINS, EOpGroupMemoryBarrier, - voidType, "groupMemoryBarrier"); - } - - if (type == GL_GEOMETRY_SHADER_OES) - { - TExtension extension = TExtension::OES_geometry_shader; - symbolTable.insertBuiltInFunctionNoParametersExt(ESSL3_1_BUILTINS, extension, EOpEmitVertex, - voidType, "EmitVertex"); - symbolTable.insertBuiltInFunctionNoParametersExt(ESSL3_1_BUILTINS, extension, - EOpEndPrimitive, voidType, "EndPrimitive"); - } - - // - // Depth range in window coordinates - // - TFieldList *fields = NewPoolTFieldList(); - TSourceLoc zeroSourceLoc = {0, 0, 0, 0}; - auto highpFloat1 = new TType(EbtFloat, EbpHigh, EvqGlobal, 1); - TField *near = new TField(highpFloat1, NewPoolTString("near"), zeroSourceLoc); - TField *far = new TField(highpFloat1, NewPoolTString("far"), zeroSourceLoc); - TField *diff = new TField(highpFloat1, NewPoolTString("diff"), zeroSourceLoc); - fields->push_back(near); - fields->push_back(far); - fields->push_back(diff); - TStructure *depthRangeStruct = - new TStructure(&symbolTable, NewPoolTString("gl_DepthRangeParameters"), fields); - symbolTable.insertStructType(COMMON_BUILTINS, depthRangeStruct); - TType depthRangeType(depthRangeStruct); - depthRangeType.setQualifier(EvqUniform); - symbolTable.insertVariable(COMMON_BUILTINS, "gl_DepthRange", depthRangeType); - - // - // Implementation dependent built-in constants. - // - symbolTable.insertConstInt(COMMON_BUILTINS, "gl_MaxVertexAttribs", resources.MaxVertexAttribs, - EbpMedium); - symbolTable.insertConstInt(COMMON_BUILTINS, "gl_MaxVertexUniformVectors", - resources.MaxVertexUniformVectors, EbpMedium); - symbolTable.insertConstInt(COMMON_BUILTINS, "gl_MaxVertexTextureImageUnits", - resources.MaxVertexTextureImageUnits, EbpMedium); - symbolTable.insertConstInt(COMMON_BUILTINS, "gl_MaxCombinedTextureImageUnits", - resources.MaxCombinedTextureImageUnits, EbpMedium); - symbolTable.insertConstInt(COMMON_BUILTINS, "gl_MaxTextureImageUnits", - resources.MaxTextureImageUnits, EbpMedium); - symbolTable.insertConstInt(COMMON_BUILTINS, "gl_MaxFragmentUniformVectors", - resources.MaxFragmentUniformVectors, EbpMedium); - - symbolTable.insertConstInt(ESSL1_BUILTINS, "gl_MaxVaryingVectors", resources.MaxVaryingVectors, - EbpMedium); - - symbolTable.insertConstInt(COMMON_BUILTINS, "gl_MaxDrawBuffers", resources.MaxDrawBuffers, - EbpMedium); - if (resources.EXT_blend_func_extended) - { - symbolTable.insertConstIntExt(COMMON_BUILTINS, TExtension::EXT_blend_func_extended, - "gl_MaxDualSourceDrawBuffersEXT", - resources.MaxDualSourceDrawBuffers, EbpMedium); - } - - symbolTable.insertConstInt(ESSL3_BUILTINS, "gl_MaxVertexOutputVectors", - resources.MaxVertexOutputVectors, EbpMedium); - symbolTable.insertConstInt(ESSL3_BUILTINS, "gl_MaxFragmentInputVectors", - resources.MaxFragmentInputVectors, EbpMedium); - symbolTable.insertConstInt(ESSL3_BUILTINS, "gl_MinProgramTexelOffset", - resources.MinProgramTexelOffset, EbpMedium); - symbolTable.insertConstInt(ESSL3_BUILTINS, "gl_MaxProgramTexelOffset", - resources.MaxProgramTexelOffset, EbpMedium); - - symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxImageUnits", resources.MaxImageUnits, - EbpMedium); - symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxVertexImageUniforms", - resources.MaxVertexImageUniforms, EbpMedium); - symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxFragmentImageUniforms", - resources.MaxFragmentImageUniforms, EbpMedium); - symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxComputeImageUniforms", - resources.MaxComputeImageUniforms, EbpMedium); - symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxCombinedImageUniforms", - resources.MaxCombinedImageUniforms, EbpMedium); - - symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxCombinedShaderOutputResources", - resources.MaxCombinedShaderOutputResources, EbpMedium); - - symbolTable.insertConstIvec3(ESSL3_1_BUILTINS, "gl_MaxComputeWorkGroupCount", - resources.MaxComputeWorkGroupCount, EbpHigh); - symbolTable.insertConstIvec3(ESSL3_1_BUILTINS, "gl_MaxComputeWorkGroupSize", - resources.MaxComputeWorkGroupSize, EbpHigh); - symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxComputeUniformComponents", - resources.MaxComputeUniformComponents, EbpMedium); - symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxComputeTextureImageUnits", - resources.MaxComputeTextureImageUnits, EbpMedium); - - symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxComputeAtomicCounters", - resources.MaxComputeAtomicCounters, EbpMedium); - symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxComputeAtomicCounterBuffers", - resources.MaxComputeAtomicCounterBuffers, EbpMedium); - - symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxVertexAtomicCounters", - resources.MaxVertexAtomicCounters, EbpMedium); - symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxFragmentAtomicCounters", - resources.MaxFragmentAtomicCounters, EbpMedium); - symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxCombinedAtomicCounters", - resources.MaxCombinedAtomicCounters, EbpMedium); - symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxAtomicCounterBindings", - resources.MaxAtomicCounterBindings, EbpMedium); - - symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxVertexAtomicCounterBuffers", - resources.MaxVertexAtomicCounterBuffers, EbpMedium); - symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxFragmentAtomicCounterBuffers", - resources.MaxFragmentAtomicCounterBuffers, EbpMedium); - symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxCombinedAtomicCounterBuffers", - resources.MaxCombinedAtomicCounterBuffers, EbpMedium); - symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxAtomicCounterBufferSize", - resources.MaxAtomicCounterBufferSize, EbpMedium); - - if (resources.OES_geometry_shader) - { - TExtension ext = TExtension::OES_geometry_shader; - symbolTable.insertConstIntExt(ESSL3_1_BUILTINS, ext, "gl_MaxGeometryInputComponents", - resources.MaxGeometryInputComponents, EbpMedium); - symbolTable.insertConstIntExt(ESSL3_1_BUILTINS, ext, "gl_MaxGeometryOutputComponents", - resources.MaxGeometryOutputComponents, EbpMedium); - symbolTable.insertConstIntExt(ESSL3_1_BUILTINS, ext, "gl_MaxGeometryImageUniforms", - resources.MaxGeometryImageUniforms, EbpMedium); - symbolTable.insertConstIntExt(ESSL3_1_BUILTINS, ext, "gl_MaxGeometryTextureImageUnits", - resources.MaxGeometryTextureImageUnits, EbpMedium); - symbolTable.insertConstIntExt(ESSL3_1_BUILTINS, ext, "gl_MaxGeometryOutputVertices", - resources.MaxGeometryOutputVertices, EbpMedium); - symbolTable.insertConstIntExt(ESSL3_1_BUILTINS, ext, "gl_MaxGeometryTotalOutputComponents", - resources.MaxGeometryTotalOutputComponents, EbpMedium); - symbolTable.insertConstIntExt(ESSL3_1_BUILTINS, ext, "gl_MaxGeometryUniformComponents", - resources.MaxGeometryUniformComponents, EbpMedium); - symbolTable.insertConstIntExt(ESSL3_1_BUILTINS, ext, "gl_MaxGeometryAtomicCounters", - resources.MaxGeometryAtomicCounters, EbpMedium); - symbolTable.insertConstIntExt(ESSL3_1_BUILTINS, ext, "gl_MaxGeometryAtomicCounterBuffers", - resources.MaxGeometryAtomicCounterBuffers, EbpMedium); - } -} - -void IdentifyBuiltIns(sh::GLenum type, - ShShaderSpec spec, - const ShBuiltInResources &resources, - TSymbolTable &symbolTable) -{ - // - // Insert some special built-in variables that are not in - // the built-in header files. - // - - if (resources.OVR_multiview && type != GL_COMPUTE_SHADER) - { - symbolTable.insertVariableExt(ESSL3_BUILTINS, TExtension::OVR_multiview, "gl_ViewID_OVR", - TType(EbtUInt, EbpHigh, EvqViewIDOVR, 1)); - - // ESSL 1.00 doesn't have unsigned integers, so gl_ViewID_OVR is a signed integer in ESSL - // 1.00. This is specified in the WEBGL_multiview spec. - symbolTable.insertVariableExt(ESSL1_BUILTINS, TExtension::OVR_multiview, "gl_ViewID_OVR", - TType(EbtInt, EbpHigh, EvqViewIDOVR, 1)); - } - - switch (type) - { - case GL_FRAGMENT_SHADER: - { - symbolTable.insertVariable(COMMON_BUILTINS, "gl_FragCoord", - TType(EbtFloat, EbpMedium, EvqFragCoord, 4)); - symbolTable.insertVariable(COMMON_BUILTINS, "gl_FrontFacing", - TType(EbtBool, EbpUndefined, EvqFrontFacing, 1)); - symbolTable.insertVariable(COMMON_BUILTINS, "gl_PointCoord", - TType(EbtFloat, EbpMedium, EvqPointCoord, 2)); - - symbolTable.insertVariable(ESSL1_BUILTINS, "gl_FragColor", - TType(EbtFloat, EbpMedium, EvqFragColor, 4)); - TType fragData(EbtFloat, EbpMedium, EvqFragData, 4); - if (spec != SH_WEBGL2_SPEC && spec != SH_WEBGL3_SPEC) - { - fragData.makeArray(resources.MaxDrawBuffers); - } - else - { - fragData.makeArray(1u); - } - symbolTable.insertVariable(ESSL1_BUILTINS, "gl_FragData", fragData); - - if (resources.EXT_blend_func_extended) - { - symbolTable.insertVariableExt( - ESSL1_BUILTINS, TExtension::EXT_blend_func_extended, "gl_SecondaryFragColorEXT", - TType(EbtFloat, EbpMedium, EvqSecondaryFragColorEXT, 4)); - TType secondaryFragData(EbtFloat, EbpMedium, EvqSecondaryFragDataEXT, 4, 1); - secondaryFragData.makeArray(resources.MaxDualSourceDrawBuffers); - symbolTable.insertVariableExt(ESSL1_BUILTINS, TExtension::EXT_blend_func_extended, - "gl_SecondaryFragDataEXT", secondaryFragData); - } - - if (resources.EXT_frag_depth) - { - symbolTable.insertVariableExt( - ESSL1_BUILTINS, TExtension::EXT_frag_depth, "gl_FragDepthEXT", - TType(EbtFloat, resources.FragmentPrecisionHigh ? EbpHigh : EbpMedium, - EvqFragDepthEXT, 1)); - } - - symbolTable.insertVariable(ESSL3_BUILTINS, "gl_FragDepth", - TType(EbtFloat, EbpHigh, EvqFragDepth, 1)); - - if (resources.EXT_shader_framebuffer_fetch || resources.NV_shader_framebuffer_fetch) - { - TType lastFragData(EbtFloat, EbpMedium, EvqLastFragData, 4, 1); - lastFragData.makeArray(resources.MaxDrawBuffers); - - if (resources.EXT_shader_framebuffer_fetch) - { - symbolTable.insertVariableExt(ESSL1_BUILTINS, - TExtension::EXT_shader_framebuffer_fetch, - "gl_LastFragData", lastFragData); - } - else if (resources.NV_shader_framebuffer_fetch) - { - symbolTable.insertVariableExt( - ESSL1_BUILTINS, TExtension::NV_shader_framebuffer_fetch, "gl_LastFragColor", - TType(EbtFloat, EbpMedium, EvqLastFragColor, 4)); - symbolTable.insertVariableExt(ESSL1_BUILTINS, - TExtension::NV_shader_framebuffer_fetch, - "gl_LastFragData", lastFragData); - } - } - else if (resources.ARM_shader_framebuffer_fetch) - { - symbolTable.insertVariableExt( - ESSL1_BUILTINS, TExtension::ARM_shader_framebuffer_fetch, "gl_LastFragColorARM", - TType(EbtFloat, EbpMedium, EvqLastFragColor, 4)); - } - - if (resources.OES_geometry_shader) - { - TExtension extension = TExtension::OES_geometry_shader; - symbolTable.insertVariableExt(ESSL3_1_BUILTINS, extension, "gl_PrimitiveID", - TType(EbtInt, EbpHigh, EvqPrimitiveID, 1)); - symbolTable.insertVariableExt(ESSL3_1_BUILTINS, extension, "gl_Layer", - TType(EbtInt, EbpHigh, EvqLayer, 1)); - } - - break; - } - case GL_VERTEX_SHADER: - { - symbolTable.insertVariable(COMMON_BUILTINS, "gl_Position", - TType(EbtFloat, EbpHigh, EvqPosition, 4)); - symbolTable.insertVariable(COMMON_BUILTINS, "gl_PointSize", - TType(EbtFloat, EbpMedium, EvqPointSize, 1)); - symbolTable.insertVariable(ESSL3_BUILTINS, "gl_InstanceID", - TType(EbtInt, EbpHigh, EvqInstanceID, 1)); - symbolTable.insertVariable(ESSL3_BUILTINS, "gl_VertexID", - TType(EbtInt, EbpHigh, EvqVertexID, 1)); - - // For internal use by ANGLE - not exposed to the parser. - symbolTable.insertVariable(GLSL_BUILTINS, "gl_ViewportIndex", - TType(EbtInt, EbpHigh, EvqViewportIndex)); - // gl_Layer exists in other shader stages in ESSL, but not in vertex shader so far. - symbolTable.insertVariable(GLSL_BUILTINS, "gl_Layer", TType(EbtInt, EbpHigh, EvqLayer)); - break; - } - case GL_COMPUTE_SHADER: - { - symbolTable.insertVariable(ESSL3_1_BUILTINS, "gl_NumWorkGroups", - TType(EbtUInt, EbpUndefined, EvqNumWorkGroups, 3)); - symbolTable.insertVariable(ESSL3_1_BUILTINS, "gl_WorkGroupSize", - TType(EbtUInt, EbpUndefined, EvqWorkGroupSize, 3)); - symbolTable.insertVariable(ESSL3_1_BUILTINS, "gl_WorkGroupID", - TType(EbtUInt, EbpUndefined, EvqWorkGroupID, 3)); - symbolTable.insertVariable(ESSL3_1_BUILTINS, "gl_LocalInvocationID", - TType(EbtUInt, EbpUndefined, EvqLocalInvocationID, 3)); - symbolTable.insertVariable(ESSL3_1_BUILTINS, "gl_GlobalInvocationID", - TType(EbtUInt, EbpUndefined, EvqGlobalInvocationID, 3)); - symbolTable.insertVariable(ESSL3_1_BUILTINS, "gl_LocalInvocationIndex", - TType(EbtUInt, EbpUndefined, EvqLocalInvocationIndex, 1)); - break; - } - - case GL_GEOMETRY_SHADER_OES: - { - TExtension extension = TExtension::OES_geometry_shader; - - // Add built-in interface block gl_PerVertex and the built-in array gl_in. - // TODO(jiawei.shao@intel.com): implement GL_OES_geometry_point_size. - const TString *glPerVertexString = NewPoolTString("gl_PerVertex"); - symbolTable.insertInterfaceBlockNameExt(ESSL3_1_BUILTINS, extension, glPerVertexString); - - TFieldList *fieldList = NewPoolTFieldList(); - TSourceLoc zeroSourceLoc = {0, 0, 0, 0}; - TField *glPositionField = new TField(new TType(EbtFloat, EbpHigh, EvqPosition, 4), - NewPoolTString("gl_Position"), zeroSourceLoc); - fieldList->push_back(glPositionField); - - TInterfaceBlock *glInBlock = new TInterfaceBlock( - glPerVertexString, fieldList, NewPoolTString("gl_in"), TLayoutQualifier::Create()); - - // The array size of gl_in is undefined until we get a valid input primitive - // declaration. - TType glInType(glInBlock, EvqPerVertexIn, TLayoutQualifier::Create()); - glInType.makeArray(0u); - symbolTable.insertVariableExt(ESSL3_1_BUILTINS, extension, "gl_in", glInType); - - TType glPositionType(EbtFloat, EbpHigh, EvqPosition, 4); - glPositionType.setInterfaceBlock(new TInterfaceBlock( - glPerVertexString, fieldList, nullptr, TLayoutQualifier::Create())); - symbolTable.insertVariableExt(ESSL3_1_BUILTINS, extension, "gl_Position", - glPositionType); - symbolTable.insertVariableExt(ESSL3_1_BUILTINS, extension, "gl_PrimitiveIDIn", - TType(EbtInt, EbpHigh, EvqPrimitiveIDIn, 1)); - symbolTable.insertVariableExt(ESSL3_1_BUILTINS, extension, "gl_InvocationID", - TType(EbtInt, EbpHigh, EvqInvocationID, 1)); - symbolTable.insertVariableExt(ESSL3_1_BUILTINS, extension, "gl_PrimitiveID", - TType(EbtInt, EbpHigh, EvqPrimitiveID, 1)); - symbolTable.insertVariableExt(ESSL3_1_BUILTINS, extension, "gl_Layer", - TType(EbtInt, EbpHigh, EvqLayer, 1)); - - break; - } - default: - UNREACHABLE(); - } -} - -void InitExtensionBehavior(const ShBuiltInResources &resources, TExtensionBehavior &extBehavior) -{ - if (resources.OES_standard_derivatives) - { - extBehavior[TExtension::OES_standard_derivatives] = EBhUndefined; - } - if (resources.OES_EGL_image_external) - { - extBehavior[TExtension::OES_EGL_image_external] = EBhUndefined; - } - if (resources.OES_EGL_image_external_essl3) - { - extBehavior[TExtension::OES_EGL_image_external_essl3] = EBhUndefined; - } - if (resources.NV_EGL_stream_consumer_external) - { - extBehavior[TExtension::NV_EGL_stream_consumer_external] = EBhUndefined; - } - if (resources.ARB_texture_rectangle) - { - // Special: ARB_texture_rectangle extension does not follow the standard for #extension - // directives - it is enabled by default. An extension directive may still disable it. - extBehavior[TExtension::ARB_texture_rectangle] = EBhEnable; - } - if (resources.EXT_blend_func_extended) - { - extBehavior[TExtension::EXT_blend_func_extended] = EBhUndefined; - } - if (resources.EXT_draw_buffers) - { - extBehavior[TExtension::EXT_draw_buffers] = EBhUndefined; - } - if (resources.EXT_frag_depth) - { - extBehavior[TExtension::EXT_frag_depth] = EBhUndefined; - } - if (resources.EXT_shader_texture_lod) - { - extBehavior[TExtension::EXT_shader_texture_lod] = EBhUndefined; - } - if (resources.EXT_shader_framebuffer_fetch) - { - extBehavior[TExtension::EXT_shader_framebuffer_fetch] = EBhUndefined; - } - if (resources.NV_shader_framebuffer_fetch) - { - extBehavior[TExtension::NV_shader_framebuffer_fetch] = EBhUndefined; - } - if (resources.ARM_shader_framebuffer_fetch) - { - extBehavior[TExtension::ARM_shader_framebuffer_fetch] = EBhUndefined; - } - if (resources.OVR_multiview) - { - extBehavior[TExtension::OVR_multiview] = EBhUndefined; - } - if (resources.EXT_YUV_target) - { - extBehavior[TExtension::EXT_YUV_target] = EBhUndefined; - } - if (resources.OES_geometry_shader) - { - extBehavior[TExtension::OES_geometry_shader] = EBhUndefined; - extBehavior[TExtension::EXT_geometry_shader] = EBhUndefined; - } -} - -void ResetExtensionBehavior(TExtensionBehavior &extBehavior) -{ - for (auto &ext : extBehavior) - { - if (ext.first == TExtension::ARB_texture_rectangle) - { - ext.second = EBhEnable; - } - else - { - ext.second = EBhUndefined; - } - } -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/Initialize.h b/src/3rdparty/angle/src/compiler/translator/Initialize.h deleted file mode 100644 index 2e61218a0f..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/Initialize.h +++ /dev/null @@ -1,38 +0,0 @@ -// -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_TRANSLATOR_INITIALIZE_H_ -#define COMPILER_TRANSLATOR_INITIALIZE_H_ - -#include "compiler/translator/Common.h" -#include "compiler/translator/Compiler.h" -#include "compiler/translator/SymbolTable.h" - -namespace sh -{ - -void InsertBuiltInFunctions(sh::GLenum type, - ShShaderSpec spec, - const ShBuiltInResources &resources, - TSymbolTable &table); - -void IdentifyBuiltIns(sh::GLenum type, - ShShaderSpec spec, - const ShBuiltInResources &resources, - TSymbolTable &symbolTable); - -void InitExtensionBehavior(const ShBuiltInResources &resources, - TExtensionBehavior &extensionBehavior); - -// Resets the behavior of the extensions listed in |extensionBehavior| to the -// undefined state. These extensions will only be those initially supported in -// the ShBuiltInResources object for this compiler instance. All other -// extensions will remain unsupported. -void ResetExtensionBehavior(TExtensionBehavior &extensionBehavior); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_INITIALIZE_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/InitializeDll.cpp b/src/3rdparty/angle/src/compiler/translator/InitializeDll.cpp deleted file mode 100644 index 43c215f52b..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/InitializeDll.cpp +++ /dev/null @@ -1,37 +0,0 @@ -// -// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/translator/Cache.h" -#include "compiler/translator/InitializeDll.h" -#include "compiler/translator/InitializeGlobals.h" - -#include "common/platform.h" - -#include - -namespace sh -{ - -bool InitProcess() -{ - if (!InitializePoolIndex()) - { - assert(0 && "InitProcess(): Failed to initalize global pool"); - return false; - } - - TCache::initialize(); - - return true; -} - -void DetachProcess() -{ - FreePoolIndex(); - TCache::destroy(); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/InitializeDll.h b/src/3rdparty/angle/src/compiler/translator/InitializeDll.h deleted file mode 100644 index 87f7251470..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/InitializeDll.h +++ /dev/null @@ -1,15 +0,0 @@ -// -// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -#ifndef COMPILER_TRANSLATOR_INITIALIZEDLL_H_ -#define COMPILER_TRANSLATOR_INITIALIZEDLL_H_ - -namespace sh -{ -bool InitProcess(); -void DetachProcess(); -} // namespace sh - -#endif // COMPILER_TRANSLATOR_INITIALIZEDLL_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/InitializeGlobals.h b/src/3rdparty/angle/src/compiler/translator/InitializeGlobals.h deleted file mode 100644 index 9a67ed0e04..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/InitializeGlobals.h +++ /dev/null @@ -1,13 +0,0 @@ -// -// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_TRANSLATOR_INITIALIZEGLOBALS_H_ -#define COMPILER_TRANSLATOR_INITIALIZEGLOBALS_H_ - -bool InitializePoolIndex(); -void FreePoolIndex(); - -#endif // COMPILER_TRANSLATOR_INITIALIZEGLOBALS_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/InitializeVariables.cpp b/src/3rdparty/angle/src/compiler/translator/InitializeVariables.cpp deleted file mode 100644 index aa1a042fac..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/InitializeVariables.cpp +++ /dev/null @@ -1,290 +0,0 @@ -// -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/translator/InitializeVariables.h" - -#include "angle_gl.h" -#include "common/debug.h" -#include "compiler/translator/FindMain.h" -#include "compiler/translator/IntermNode_util.h" -#include "compiler/translator/IntermTraverse.h" -#include "compiler/translator/SymbolTable.h" -#include "compiler/translator/util.h" - -namespace sh -{ - -namespace -{ - -void AddArrayZeroInitSequence(const TIntermTyped *initializedNode, - bool canUseLoopsToInitialize, - TIntermSequence *initSequenceOut, - TSymbolTable *symbolTable); - -void AddStructZeroInitSequence(const TIntermTyped *initializedNode, - bool canUseLoopsToInitialize, - TIntermSequence *initSequenceOut, - TSymbolTable *symbolTable); - -TIntermBinary *CreateZeroInitAssignment(const TIntermTyped *initializedNode) -{ - TIntermTyped *zero = CreateZeroNode(initializedNode->getType()); - return new TIntermBinary(EOpAssign, initializedNode->deepCopy(), zero); -} - -void AddZeroInitSequence(const TIntermTyped *initializedNode, - bool canUseLoopsToInitialize, - TIntermSequence *initSequenceOut, - TSymbolTable *symbolTable) -{ - if (initializedNode->isArray()) - { - AddArrayZeroInitSequence(initializedNode, canUseLoopsToInitialize, initSequenceOut, - symbolTable); - } - else if (initializedNode->getType().isStructureContainingArrays() || - initializedNode->getType().isNamelessStruct()) - { - AddStructZeroInitSequence(initializedNode, canUseLoopsToInitialize, initSequenceOut, - symbolTable); - } - else - { - initSequenceOut->push_back(CreateZeroInitAssignment(initializedNode)); - } -} - -void AddStructZeroInitSequence(const TIntermTyped *initializedNode, - bool canUseLoopsToInitialize, - TIntermSequence *initSequenceOut, - TSymbolTable *symbolTable) -{ - ASSERT(initializedNode->getBasicType() == EbtStruct); - const TStructure *structType = initializedNode->getType().getStruct(); - for (int i = 0; i < static_cast(structType->fields().size()); ++i) - { - TIntermBinary *element = new TIntermBinary(EOpIndexDirectStruct, - initializedNode->deepCopy(), CreateIndexNode(i)); - // Structs can't be defined inside structs, so the type of a struct field can't be a - // nameless struct. - ASSERT(!element->getType().isNamelessStruct()); - AddZeroInitSequence(element, canUseLoopsToInitialize, initSequenceOut, symbolTable); - } -} - -void AddArrayZeroInitStatementList(const TIntermTyped *initializedNode, - bool canUseLoopsToInitialize, - TIntermSequence *initSequenceOut, - TSymbolTable *symbolTable) -{ - for (unsigned int i = 0; i < initializedNode->getOutermostArraySize(); ++i) - { - TIntermBinary *element = - new TIntermBinary(EOpIndexDirect, initializedNode->deepCopy(), CreateIndexNode(i)); - AddZeroInitSequence(element, canUseLoopsToInitialize, initSequenceOut, symbolTable); - } -} - -void AddArrayZeroInitForLoop(const TIntermTyped *initializedNode, - TIntermSequence *initSequenceOut, - TSymbolTable *symbolTable) -{ - ASSERT(initializedNode->isArray()); - TSymbolUniqueId indexSymbol(symbolTable); - - TIntermSymbol *indexSymbolNode = CreateTempSymbolNode(indexSymbol, TType(EbtInt), EvqTemporary); - TIntermDeclaration *indexInit = - CreateTempInitDeclarationNode(indexSymbol, CreateZeroNode(TType(EbtInt)), EvqTemporary); - TIntermConstantUnion *arraySizeNode = CreateIndexNode(initializedNode->getOutermostArraySize()); - TIntermBinary *indexSmallerThanSize = - new TIntermBinary(EOpLessThan, indexSymbolNode->deepCopy(), arraySizeNode); - TIntermUnary *indexIncrement = new TIntermUnary(EOpPreIncrement, indexSymbolNode->deepCopy()); - - TIntermBlock *forLoopBody = new TIntermBlock(); - TIntermSequence *forLoopBodySeq = forLoopBody->getSequence(); - - TIntermBinary *element = new TIntermBinary(EOpIndexIndirect, initializedNode->deepCopy(), - indexSymbolNode->deepCopy()); - AddZeroInitSequence(element, true, forLoopBodySeq, symbolTable); - - TIntermLoop *forLoop = - new TIntermLoop(ELoopFor, indexInit, indexSmallerThanSize, indexIncrement, forLoopBody); - initSequenceOut->push_back(forLoop); -} - -void AddArrayZeroInitSequence(const TIntermTyped *initializedNode, - bool canUseLoopsToInitialize, - TIntermSequence *initSequenceOut, - TSymbolTable *symbolTable) -{ - // The array elements are assigned one by one to keep the AST compatible with ESSL 1.00 which - // doesn't have array assignment. We'll do this either with a for loop or just a list of - // statements assigning to each array index. Note that it is important to have the array init in - // the right order to workaround http://crbug.com/709317 - bool isSmallArray = initializedNode->getOutermostArraySize() <= 1u || - (initializedNode->getBasicType() != EbtStruct && - !initializedNode->getType().isArrayOfArrays() && - initializedNode->getOutermostArraySize() <= 3u); - if (initializedNode->getQualifier() == EvqFragData || - initializedNode->getQualifier() == EvqFragmentOut || isSmallArray || - !canUseLoopsToInitialize) - { - // Fragment outputs should not be indexed by non-constant indices. - // Also it doesn't make sense to use loops to initialize very small arrays. - AddArrayZeroInitStatementList(initializedNode, canUseLoopsToInitialize, initSequenceOut, - symbolTable); - } - else - { - AddArrayZeroInitForLoop(initializedNode, initSequenceOut, symbolTable); - } -} - -void InsertInitCode(TIntermSequence *mainBody, - const InitVariableList &variables, - TSymbolTable *symbolTable, - int shaderVersion, - const TExtensionBehavior &extensionBehavior, - bool canUseLoopsToInitialize) -{ - for (const auto &var : variables) - { - TString name = TString(var.name.c_str()); - size_t pos = name.find_last_of('['); - if (pos != TString::npos) - { - name = name.substr(0, pos); - } - - TIntermTyped *initializedSymbol = nullptr; - if (var.isBuiltIn()) - { - initializedSymbol = ReferenceBuiltInVariable(name, *symbolTable, shaderVersion); - if (initializedSymbol->getQualifier() == EvqFragData && - !IsExtensionEnabled(extensionBehavior, TExtension::EXT_draw_buffers)) - { - // If GL_EXT_draw_buffers is disabled, only the 0th index of gl_FragData can be - // written to. - // TODO(oetuaho): This is a bit hacky and would be better to remove, if we came up - // with a good way to do it. Right now "gl_FragData" in symbol table is initialized - // to have the array size of MaxDrawBuffers, and the initialization happens before - // the shader sets the extensions it is using. - initializedSymbol = - new TIntermBinary(EOpIndexDirect, initializedSymbol, CreateIndexNode(0)); - } - } - else - { - initializedSymbol = ReferenceGlobalVariable(name, *symbolTable); - } - ASSERT(initializedSymbol != nullptr); - - TIntermSequence *initCode = - CreateInitCode(initializedSymbol, canUseLoopsToInitialize, symbolTable); - mainBody->insert(mainBody->begin(), initCode->begin(), initCode->end()); - } -} - -class InitializeLocalsTraverser : public TIntermTraverser -{ - public: - InitializeLocalsTraverser(int shaderVersion, - TSymbolTable *symbolTable, - bool canUseLoopsToInitialize) - : TIntermTraverser(true, false, false, symbolTable), - mShaderVersion(shaderVersion), - mCanUseLoopsToInitialize(canUseLoopsToInitialize) - { - } - - protected: - bool visitDeclaration(Visit visit, TIntermDeclaration *node) override - { - for (TIntermNode *declarator : *node->getSequence()) - { - if (!mInGlobalScope && !declarator->getAsBinaryNode()) - { - TIntermSymbol *symbol = declarator->getAsSymbolNode(); - ASSERT(symbol); - if (symbol->getSymbol() == "") - { - continue; - } - - // Arrays may need to be initialized one element at a time, since ESSL 1.00 does not - // support array constructors or assigning arrays. - bool arrayConstructorUnavailable = - (symbol->isArray() || symbol->getType().isStructureContainingArrays()) && - mShaderVersion == 100; - // Nameless struct constructors can't be referred to, so they also need to be - // initialized one element at a time. - // TODO(oetuaho): Check if it makes sense to initialize using a loop, even if we - // could use an initializer. It could at least reduce code size for very large - // arrays, but could hurt runtime performance. - if (arrayConstructorUnavailable || symbol->getType().isNamelessStruct()) - { - // SimplifyLoopConditions should have been run so the parent node of this node - // should not be a loop. - ASSERT(getParentNode()->getAsLoopNode() == nullptr); - // SeparateDeclarations should have already been run, so we don't need to worry - // about further declarators in this declaration depending on the effects of - // this declarator. - ASSERT(node->getSequence()->size() == 1); - insertStatementsInParentBlock( - TIntermSequence(), - *CreateInitCode(symbol, mCanUseLoopsToInitialize, mSymbolTable)); - } - else - { - TIntermBinary *init = - new TIntermBinary(EOpInitialize, symbol, CreateZeroNode(symbol->getType())); - queueReplacementWithParent(node, symbol, init, OriginalNode::BECOMES_CHILD); - } - } - } - return false; - } - - private: - int mShaderVersion; - bool mCanUseLoopsToInitialize; -}; - -} // namespace anonymous - -TIntermSequence *CreateInitCode(const TIntermTyped *initializedSymbol, - bool canUseLoopsToInitialize, - TSymbolTable *symbolTable) -{ - TIntermSequence *initCode = new TIntermSequence(); - AddZeroInitSequence(initializedSymbol, canUseLoopsToInitialize, initCode, symbolTable); - return initCode; -} - -void InitializeUninitializedLocals(TIntermBlock *root, - int shaderVersion, - bool canUseLoopsToInitialize, - TSymbolTable *symbolTable) -{ - InitializeLocalsTraverser traverser(shaderVersion, symbolTable, canUseLoopsToInitialize); - root->traverse(&traverser); - traverser.updateTree(); -} - -void InitializeVariables(TIntermBlock *root, - const InitVariableList &vars, - TSymbolTable *symbolTable, - int shaderVersion, - const TExtensionBehavior &extensionBehavior, - bool canUseLoopsToInitialize) -{ - TIntermBlock *body = FindMainBody(root); - InsertInitCode(body->getSequence(), vars, symbolTable, shaderVersion, extensionBehavior, - canUseLoopsToInitialize); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/InitializeVariables.h b/src/3rdparty/angle/src/compiler/translator/InitializeVariables.h deleted file mode 100644 index 1a7b3c0f24..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/InitializeVariables.h +++ /dev/null @@ -1,53 +0,0 @@ -// -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_TRANSLATOR_INITIALIZEVARIABLES_H_ -#define COMPILER_TRANSLATOR_INITIALIZEVARIABLES_H_ - -#include - -#include "compiler/translator/ExtensionBehavior.h" -#include "compiler/translator/IntermNode.h" - -namespace sh -{ -class TSymbolTable; - -typedef std::vector InitVariableList; - -// For all of the functions below: If canUseLoopsToInitialize is set, for loops are used instead of -// a large number of initializers where it can make sense, such as for initializing large arrays. - -// Return a sequence of assignment operations to initialize "initializedSymbol". initializedSymbol -// may be an array, struct or any combination of these, as long as it contains only basic types. -TIntermSequence *CreateInitCode(const TIntermTyped *initializedSymbol, - bool canUseLoopsToInitialize, - TSymbolTable *symbolTable); - -// Initialize all uninitialized local variables, so that undefined behavior is avoided. -void InitializeUninitializedLocals(TIntermBlock *root, - int shaderVersion, - bool canUseLoopsToInitialize, - TSymbolTable *symbolTable); - -// This function can initialize all the types that CreateInitCode is able to initialize. All -// variables must be globals which can be found in the symbol table. For now it is used for the -// following two scenarios: -// 1. Initializing gl_Position; -// 2. Initializing output variables referred to in the shader source. -// Note: The type of each lvalue in an initializer is retrieved from the symbol table. gl_FragData -// requires special handling because the number of indices which can be initialized is determined by -// enabled extensions. -void InitializeVariables(TIntermBlock *root, - const InitVariableList &vars, - TSymbolTable *symbolTable, - int shaderVersion, - const TExtensionBehavior &extensionBehavior, - bool canUseLoopsToInitialize); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_INITIALIZEVARIABLES_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/IntermNode.cpp b/src/3rdparty/angle/src/compiler/translator/IntermNode.cpp deleted file mode 100644 index a57ffcb4bc..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/IntermNode.cpp +++ /dev/null @@ -1,3330 +0,0 @@ -// -// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// -// Build the intermediate representation. -// - -#include -#include -#include -#include -#include -#include - -#include "common/mathutil.h" -#include "common/matrix_utils.h" -#include "compiler/translator/Diagnostics.h" -#include "compiler/translator/IntermNode.h" -#include "compiler/translator/SymbolTable.h" -#include "compiler/translator/util.h" - -namespace sh -{ - -namespace -{ - -const float kPi = 3.14159265358979323846f; -const float kDegreesToRadiansMultiplier = kPi / 180.0f; -const float kRadiansToDegreesMultiplier = 180.0f / kPi; - -TPrecision GetHigherPrecision(TPrecision left, TPrecision right) -{ - return left > right ? left : right; -} - -TConstantUnion *Vectorize(const TConstantUnion &constant, size_t size) -{ - TConstantUnion *constUnion = new TConstantUnion[size]; - for (unsigned int i = 0; i < size; ++i) - constUnion[i] = constant; - - return constUnion; -} - -void UndefinedConstantFoldingError(const TSourceLoc &loc, - TOperator op, - TBasicType basicType, - TDiagnostics *diagnostics, - TConstantUnion *result) -{ - diagnostics->warning(loc, "operation result is undefined for the values passed in", - GetOperatorString(op)); - - switch (basicType) - { - case EbtFloat: - result->setFConst(0.0f); - break; - case EbtInt: - result->setIConst(0); - break; - case EbtUInt: - result->setUConst(0u); - break; - case EbtBool: - result->setBConst(false); - break; - default: - break; - } -} - -float VectorLength(const TConstantUnion *paramArray, size_t paramArraySize) -{ - float result = 0.0f; - for (size_t i = 0; i < paramArraySize; i++) - { - float f = paramArray[i].getFConst(); - result += f * f; - } - return sqrtf(result); -} - -float VectorDotProduct(const TConstantUnion *paramArray1, - const TConstantUnion *paramArray2, - size_t paramArraySize) -{ - float result = 0.0f; - for (size_t i = 0; i < paramArraySize; i++) - result += paramArray1[i].getFConst() * paramArray2[i].getFConst(); - return result; -} - -TIntermTyped *CreateFoldedNode(const TConstantUnion *constArray, - const TIntermTyped *originalNode, - TQualifier qualifier) -{ - if (constArray == nullptr) - { - return nullptr; - } - TIntermTyped *folded = new TIntermConstantUnion(constArray, originalNode->getType()); - folded->getTypePointer()->setQualifier(qualifier); - folded->setLine(originalNode->getLine()); - return folded; -} - -angle::Matrix GetMatrix(const TConstantUnion *paramArray, - const unsigned int &rows, - const unsigned int &cols) -{ - std::vector elements; - for (size_t i = 0; i < rows * cols; i++) - elements.push_back(paramArray[i].getFConst()); - // Transpose is used since the Matrix constructor expects arguments in row-major order, - // whereas the paramArray is in column-major order. Rows/cols parameters are also flipped below - // so that the created matrix will have the expected dimensions after the transpose. - return angle::Matrix(elements, cols, rows).transpose(); -} - -angle::Matrix GetMatrix(const TConstantUnion *paramArray, const unsigned int &size) -{ - std::vector elements; - for (size_t i = 0; i < size * size; i++) - elements.push_back(paramArray[i].getFConst()); - // Transpose is used since the Matrix constructor expects arguments in row-major order, - // whereas the paramArray is in column-major order. - return angle::Matrix(elements, size).transpose(); -} - -void SetUnionArrayFromMatrix(const angle::Matrix &m, TConstantUnion *resultArray) -{ - // Transpose is used since the input Matrix is in row-major order, - // whereas the actual result should be in column-major order. - angle::Matrix result = m.transpose(); - std::vector resultElements = result.elements(); - for (size_t i = 0; i < resultElements.size(); i++) - resultArray[i].setFConst(resultElements[i]); -} - -} // namespace anonymous - -//////////////////////////////////////////////////////////////// -// -// Member functions of the nodes used for building the tree. -// -//////////////////////////////////////////////////////////////// - -void TIntermTyped::setTypePreservePrecision(const TType &t) -{ - TPrecision precision = getPrecision(); - mType = t; - ASSERT(mType.getBasicType() != EbtBool || precision == EbpUndefined); - mType.setPrecision(precision); -} - -#define REPLACE_IF_IS(node, type, original, replacement) \ - if (node == original) \ - { \ - node = static_cast(replacement); \ - return true; \ - } - -bool TIntermLoop::replaceChildNode(TIntermNode *original, TIntermNode *replacement) -{ - ASSERT(original != nullptr); // This risks replacing multiple children. - REPLACE_IF_IS(mInit, TIntermNode, original, replacement); - REPLACE_IF_IS(mCond, TIntermTyped, original, replacement); - REPLACE_IF_IS(mExpr, TIntermTyped, original, replacement); - REPLACE_IF_IS(mBody, TIntermBlock, original, replacement); - return false; -} - -bool TIntermBranch::replaceChildNode(TIntermNode *original, TIntermNode *replacement) -{ - REPLACE_IF_IS(mExpression, TIntermTyped, original, replacement); - return false; -} - -bool TIntermSwizzle::replaceChildNode(TIntermNode *original, TIntermNode *replacement) -{ - ASSERT(original->getAsTyped()->getType() == replacement->getAsTyped()->getType()); - REPLACE_IF_IS(mOperand, TIntermTyped, original, replacement); - return false; -} - -bool TIntermBinary::replaceChildNode(TIntermNode *original, TIntermNode *replacement) -{ - REPLACE_IF_IS(mLeft, TIntermTyped, original, replacement); - REPLACE_IF_IS(mRight, TIntermTyped, original, replacement); - return false; -} - -bool TIntermUnary::replaceChildNode(TIntermNode *original, TIntermNode *replacement) -{ - ASSERT(original->getAsTyped()->getType() == replacement->getAsTyped()->getType()); - REPLACE_IF_IS(mOperand, TIntermTyped, original, replacement); - return false; -} - -bool TIntermInvariantDeclaration::replaceChildNode(TIntermNode *original, TIntermNode *replacement) -{ - REPLACE_IF_IS(mSymbol, TIntermSymbol, original, replacement); - return false; -} - -bool TIntermFunctionDefinition::replaceChildNode(TIntermNode *original, TIntermNode *replacement) -{ - REPLACE_IF_IS(mPrototype, TIntermFunctionPrototype, original, replacement); - REPLACE_IF_IS(mBody, TIntermBlock, original, replacement); - return false; -} - -bool TIntermAggregate::replaceChildNode(TIntermNode *original, TIntermNode *replacement) -{ - return replaceChildNodeInternal(original, replacement); -} - -bool TIntermBlock::replaceChildNode(TIntermNode *original, TIntermNode *replacement) -{ - return replaceChildNodeInternal(original, replacement); -} - -bool TIntermFunctionPrototype::replaceChildNode(TIntermNode *original, TIntermNode *replacement) -{ - return replaceChildNodeInternal(original, replacement); -} - -bool TIntermDeclaration::replaceChildNode(TIntermNode *original, TIntermNode *replacement) -{ - return replaceChildNodeInternal(original, replacement); -} - -bool TIntermAggregateBase::replaceChildNodeInternal(TIntermNode *original, TIntermNode *replacement) -{ - for (size_t ii = 0; ii < getSequence()->size(); ++ii) - { - REPLACE_IF_IS((*getSequence())[ii], TIntermNode, original, replacement); - } - return false; -} - -bool TIntermAggregateBase::replaceChildNodeWithMultiple(TIntermNode *original, - const TIntermSequence &replacements) -{ - for (auto it = getSequence()->begin(); it < getSequence()->end(); ++it) - { - if (*it == original) - { - it = getSequence()->erase(it); - getSequence()->insert(it, replacements.begin(), replacements.end()); - return true; - } - } - return false; -} - -bool TIntermAggregateBase::insertChildNodes(TIntermSequence::size_type position, - const TIntermSequence &insertions) -{ - if (position > getSequence()->size()) - { - return false; - } - auto it = getSequence()->begin() + position; - getSequence()->insert(it, insertions.begin(), insertions.end()); - return true; -} - -TIntermAggregate *TIntermAggregate::CreateFunctionCall(const TFunction &func, - TIntermSequence *arguments) -{ - TIntermAggregate *callNode = - new TIntermAggregate(func.getReturnType(), EOpCallFunctionInAST, arguments); - callNode->getFunctionSymbolInfo()->setFromFunction(func); - return callNode; -} - -TIntermAggregate *TIntermAggregate::CreateFunctionCall(const TType &type, - const TSymbolUniqueId &id, - const TName &name, - TIntermSequence *arguments) -{ - TIntermAggregate *callNode = new TIntermAggregate(type, EOpCallFunctionInAST, arguments); - callNode->getFunctionSymbolInfo()->setId(id); - callNode->getFunctionSymbolInfo()->setNameObj(name); - return callNode; -} - -TIntermAggregate *TIntermAggregate::CreateBuiltInFunctionCall(const TFunction &func, - TIntermSequence *arguments) -{ - TIntermAggregate *callNode = - new TIntermAggregate(func.getReturnType(), EOpCallBuiltInFunction, arguments); - callNode->getFunctionSymbolInfo()->setFromFunction(func); - // Note that name needs to be set before texture function type is determined. - callNode->setBuiltInFunctionPrecision(); - return callNode; -} - -TIntermAggregate *TIntermAggregate::CreateConstructor(const TType &type, - TIntermSequence *arguments) -{ - return new TIntermAggregate(type, EOpConstruct, arguments); -} - -TIntermAggregate *TIntermAggregate::Create(const TType &type, - TOperator op, - TIntermSequence *arguments) -{ - TIntermAggregate *node = new TIntermAggregate(type, op, arguments); - ASSERT(op != EOpCallFunctionInAST); // Should use CreateFunctionCall - ASSERT(op != EOpCallBuiltInFunction); // Should use CreateBuiltInFunctionCall - ASSERT(!node->isConstructor()); // Should use CreateConstructor - return node; -} - -TIntermAggregate::TIntermAggregate(const TType &type, TOperator op, TIntermSequence *arguments) - : TIntermOperator(op), mUseEmulatedFunction(false), mGotPrecisionFromChildren(false) -{ - if (arguments != nullptr) - { - mArguments.swap(*arguments); - } - setTypePrecisionAndQualifier(type); -} - -void TIntermAggregate::setTypePrecisionAndQualifier(const TType &type) -{ - setType(type); - mType.setQualifier(EvqTemporary); - if (!isFunctionCall()) - { - if (isConstructor()) - { - // Structs should not be precision qualified, the individual members may be. - // Built-in types on the other hand should be precision qualified. - if (getBasicType() != EbtStruct) - { - setPrecisionFromChildren(); - } - } - else - { - setPrecisionForBuiltInOp(); - } - if (areChildrenConstQualified()) - { - mType.setQualifier(EvqConst); - } - } -} - -bool TIntermAggregate::areChildrenConstQualified() -{ - for (TIntermNode *&arg : mArguments) - { - TIntermTyped *typedArg = arg->getAsTyped(); - if (typedArg && typedArg->getQualifier() != EvqConst) - { - return false; - } - } - return true; -} - -void TIntermAggregate::setPrecisionFromChildren() -{ - mGotPrecisionFromChildren = true; - if (getBasicType() == EbtBool) - { - mType.setPrecision(EbpUndefined); - return; - } - - TPrecision precision = EbpUndefined; - TIntermSequence::iterator childIter = mArguments.begin(); - while (childIter != mArguments.end()) - { - TIntermTyped *typed = (*childIter)->getAsTyped(); - if (typed) - precision = GetHigherPrecision(typed->getPrecision(), precision); - ++childIter; - } - mType.setPrecision(precision); -} - -void TIntermAggregate::setPrecisionForBuiltInOp() -{ - ASSERT(!isConstructor()); - ASSERT(!isFunctionCall()); - if (!setPrecisionForSpecialBuiltInOp()) - { - setPrecisionFromChildren(); - } -} - -bool TIntermAggregate::setPrecisionForSpecialBuiltInOp() -{ - switch (mOp) - { - case EOpBitfieldExtract: - mType.setPrecision(mArguments[0]->getAsTyped()->getPrecision()); - mGotPrecisionFromChildren = true; - return true; - case EOpBitfieldInsert: - mType.setPrecision(GetHigherPrecision(mArguments[0]->getAsTyped()->getPrecision(), - mArguments[1]->getAsTyped()->getPrecision())); - mGotPrecisionFromChildren = true; - return true; - case EOpUaddCarry: - case EOpUsubBorrow: - mType.setPrecision(EbpHigh); - return true; - default: - return false; - } -} - -void TIntermAggregate::setBuiltInFunctionPrecision() -{ - // All built-ins returning bool should be handled as ops, not functions. - ASSERT(getBasicType() != EbtBool); - ASSERT(mOp == EOpCallBuiltInFunction); - - TPrecision precision = EbpUndefined; - for (TIntermNode *arg : mArguments) - { - TIntermTyped *typed = arg->getAsTyped(); - // ESSL spec section 8: texture functions get their precision from the sampler. - if (typed && IsSampler(typed->getBasicType())) - { - precision = typed->getPrecision(); - break; - } - } - // ESSL 3.0 spec section 8: textureSize always gets highp precision. - // All other functions that take a sampler are assumed to be texture functions. - if (mFunctionInfo.getName().find("textureSize") == 0) - mType.setPrecision(EbpHigh); - else - mType.setPrecision(precision); -} - -TString TIntermAggregate::getSymbolTableMangledName() const -{ - ASSERT(!isConstructor()); - switch (mOp) - { - case EOpCallInternalRawFunction: - case EOpCallBuiltInFunction: - case EOpCallFunctionInAST: - return TFunction::GetMangledNameFromCall(mFunctionInfo.getName(), mArguments); - default: - TString opString = GetOperatorString(mOp); - return TFunction::GetMangledNameFromCall(opString, mArguments); - } -} - -bool TIntermAggregate::hasSideEffects() const -{ - if (isFunctionCall() && mFunctionInfo.isKnownToNotHaveSideEffects()) - { - for (TIntermNode *arg : mArguments) - { - if (arg->getAsTyped()->hasSideEffects()) - { - return true; - } - } - return false; - } - // Conservatively assume most aggregate operators have side-effects - return true; -} - -void TIntermBlock::appendStatement(TIntermNode *statement) -{ - // Declaration nodes with no children can appear if it was an empty declaration or if all the - // declarators just added constants to the symbol table instead of generating code. We still - // need to add the declaration to the AST in that case because it might be relevant to the - // validity of switch/case. - if (statement != nullptr) - { - mStatements.push_back(statement); - } -} - -void TIntermFunctionPrototype::appendParameter(TIntermSymbol *parameter) -{ - ASSERT(parameter != nullptr); - mParameters.push_back(parameter); -} - -void TIntermDeclaration::appendDeclarator(TIntermTyped *declarator) -{ - ASSERT(declarator != nullptr); - ASSERT(declarator->getAsSymbolNode() != nullptr || - (declarator->getAsBinaryNode() != nullptr && - declarator->getAsBinaryNode()->getOp() == EOpInitialize)); - ASSERT(mDeclarators.empty() || - declarator->getType().sameNonArrayType(mDeclarators.back()->getAsTyped()->getType())); - mDeclarators.push_back(declarator); -} - -bool TIntermTernary::replaceChildNode(TIntermNode *original, TIntermNode *replacement) -{ - REPLACE_IF_IS(mCondition, TIntermTyped, original, replacement); - REPLACE_IF_IS(mTrueExpression, TIntermTyped, original, replacement); - REPLACE_IF_IS(mFalseExpression, TIntermTyped, original, replacement); - return false; -} - -bool TIntermIfElse::replaceChildNode(TIntermNode *original, TIntermNode *replacement) -{ - REPLACE_IF_IS(mCondition, TIntermTyped, original, replacement); - REPLACE_IF_IS(mTrueBlock, TIntermBlock, original, replacement); - REPLACE_IF_IS(mFalseBlock, TIntermBlock, original, replacement); - return false; -} - -bool TIntermSwitch::replaceChildNode(TIntermNode *original, TIntermNode *replacement) -{ - REPLACE_IF_IS(mInit, TIntermTyped, original, replacement); - REPLACE_IF_IS(mStatementList, TIntermBlock, original, replacement); - ASSERT(mStatementList); - return false; -} - -bool TIntermCase::replaceChildNode(TIntermNode *original, TIntermNode *replacement) -{ - REPLACE_IF_IS(mCondition, TIntermTyped, original, replacement); - return false; -} - -TIntermTyped::TIntermTyped(const TIntermTyped &node) : TIntermNode(), mType(node.mType) -{ - // Copy constructor is disallowed for TIntermNode in order to disallow it for subclasses that - // don't explicitly allow it, so normal TIntermNode constructor is used to construct the copy. - // We need to manually copy any fields of TIntermNode besides handling fields in TIntermTyped. - mLine = node.mLine; -} - -bool TIntermTyped::isConstructorWithOnlyConstantUnionParameters() -{ - TIntermAggregate *constructor = getAsAggregate(); - if (!constructor || !constructor->isConstructor()) - { - return false; - } - for (TIntermNode *&node : *constructor->getSequence()) - { - if (!node->getAsConstantUnion()) - return false; - } - return true; -} - -TIntermConstantUnion::TIntermConstantUnion(const TIntermConstantUnion &node) : TIntermTyped(node) -{ - mUnionArrayPointer = node.mUnionArrayPointer; -} - -void TFunctionSymbolInfo::setFromFunction(const TFunction &function) -{ - setName(function.getName()); - setId(TSymbolUniqueId(function)); -} - -TFunctionSymbolInfo::TFunctionSymbolInfo(const TSymbolUniqueId &id) - : mId(new TSymbolUniqueId(id)), mKnownToNotHaveSideEffects(false) -{ -} - -TFunctionSymbolInfo::TFunctionSymbolInfo(const TFunctionSymbolInfo &info) - : mName(info.mName), mId(nullptr), mKnownToNotHaveSideEffects(info.mKnownToNotHaveSideEffects) -{ - if (info.mId) - { - mId = new TSymbolUniqueId(*info.mId); - } -} - -TFunctionSymbolInfo &TFunctionSymbolInfo::operator=(const TFunctionSymbolInfo &info) -{ - mName = info.mName; - if (info.mId) - { - mId = new TSymbolUniqueId(*info.mId); - } - else - { - mId = nullptr; - } - return *this; -} - -void TFunctionSymbolInfo::setId(const TSymbolUniqueId &id) -{ - mId = new TSymbolUniqueId(id); -} - -const TSymbolUniqueId &TFunctionSymbolInfo::getId() const -{ - ASSERT(mId); - return *mId; -} - -TIntermAggregate::TIntermAggregate(const TIntermAggregate &node) - : TIntermOperator(node), - mUseEmulatedFunction(node.mUseEmulatedFunction), - mGotPrecisionFromChildren(node.mGotPrecisionFromChildren), - mFunctionInfo(node.mFunctionInfo) -{ - for (TIntermNode *arg : node.mArguments) - { - TIntermTyped *typedArg = arg->getAsTyped(); - ASSERT(typedArg != nullptr); - TIntermTyped *argCopy = typedArg->deepCopy(); - mArguments.push_back(argCopy); - } -} - -TIntermAggregate *TIntermAggregate::shallowCopy() const -{ - TIntermSequence *copySeq = new TIntermSequence(); - copySeq->insert(copySeq->begin(), getSequence()->begin(), getSequence()->end()); - TIntermAggregate *copyNode = new TIntermAggregate(mType, mOp, copySeq); - *copyNode->getFunctionSymbolInfo() = mFunctionInfo; - copyNode->setLine(mLine); - return copyNode; -} - -TIntermSwizzle::TIntermSwizzle(const TIntermSwizzle &node) : TIntermTyped(node) -{ - TIntermTyped *operandCopy = node.mOperand->deepCopy(); - ASSERT(operandCopy != nullptr); - mOperand = operandCopy; - mSwizzleOffsets = node.mSwizzleOffsets; -} - -TIntermBinary::TIntermBinary(const TIntermBinary &node) - : TIntermOperator(node), mAddIndexClamp(node.mAddIndexClamp) -{ - TIntermTyped *leftCopy = node.mLeft->deepCopy(); - TIntermTyped *rightCopy = node.mRight->deepCopy(); - ASSERT(leftCopy != nullptr && rightCopy != nullptr); - mLeft = leftCopy; - mRight = rightCopy; -} - -TIntermUnary::TIntermUnary(const TIntermUnary &node) - : TIntermOperator(node), mUseEmulatedFunction(node.mUseEmulatedFunction) -{ - TIntermTyped *operandCopy = node.mOperand->deepCopy(); - ASSERT(operandCopy != nullptr); - mOperand = operandCopy; -} - -TIntermTernary::TIntermTernary(const TIntermTernary &node) : TIntermTyped(node) -{ - TIntermTyped *conditionCopy = node.mCondition->deepCopy(); - TIntermTyped *trueCopy = node.mTrueExpression->deepCopy(); - TIntermTyped *falseCopy = node.mFalseExpression->deepCopy(); - ASSERT(conditionCopy != nullptr && trueCopy != nullptr && falseCopy != nullptr); - mCondition = conditionCopy; - mTrueExpression = trueCopy; - mFalseExpression = falseCopy; -} - -bool TIntermOperator::isAssignment() const -{ - return IsAssignment(mOp); -} - -bool TIntermOperator::isMultiplication() const -{ - switch (mOp) - { - case EOpMul: - case EOpMatrixTimesMatrix: - case EOpMatrixTimesVector: - case EOpMatrixTimesScalar: - case EOpVectorTimesMatrix: - case EOpVectorTimesScalar: - return true; - default: - return false; - } -} - -bool TIntermOperator::isConstructor() const -{ - return (mOp == EOpConstruct); -} - -bool TIntermOperator::isFunctionCall() const -{ - switch (mOp) - { - case EOpCallFunctionInAST: - case EOpCallBuiltInFunction: - case EOpCallInternalRawFunction: - return true; - default: - return false; - } -} - -TOperator TIntermBinary::GetMulOpBasedOnOperands(const TType &left, const TType &right) -{ - if (left.isMatrix()) - { - if (right.isMatrix()) - { - return EOpMatrixTimesMatrix; - } - else - { - if (right.isVector()) - { - return EOpMatrixTimesVector; - } - else - { - return EOpMatrixTimesScalar; - } - } - } - else - { - if (right.isMatrix()) - { - if (left.isVector()) - { - return EOpVectorTimesMatrix; - } - else - { - return EOpMatrixTimesScalar; - } - } - else - { - // Neither operand is a matrix. - if (left.isVector() == right.isVector()) - { - // Leave as component product. - return EOpMul; - } - else - { - return EOpVectorTimesScalar; - } - } - } -} - -TOperator TIntermBinary::GetMulAssignOpBasedOnOperands(const TType &left, const TType &right) -{ - if (left.isMatrix()) - { - if (right.isMatrix()) - { - return EOpMatrixTimesMatrixAssign; - } - else - { - // right should be scalar, but this may not be validated yet. - return EOpMatrixTimesScalarAssign; - } - } - else - { - if (right.isMatrix()) - { - // Left should be a vector, but this may not be validated yet. - return EOpVectorTimesMatrixAssign; - } - else - { - // Neither operand is a matrix. - if (left.isVector() == right.isVector()) - { - // Leave as component product. - return EOpMulAssign; - } - else - { - // left should be vector and right should be scalar, but this may not be validated - // yet. - return EOpVectorTimesScalarAssign; - } - } - } -} - -// -// Make sure the type of a unary operator is appropriate for its -// combination of operation and operand type. -// -void TIntermUnary::promote() -{ - if (mOp == EOpArrayLength) - { - // Special case: the qualifier of .length() doesn't depend on the operand qualifier. - setType(TType(EbtInt, EbpUndefined, EvqConst)); - return; - } - - TQualifier resultQualifier = EvqTemporary; - if (mOperand->getQualifier() == EvqConst) - resultQualifier = EvqConst; - - unsigned char operandPrimarySize = - static_cast(mOperand->getType().getNominalSize()); - switch (mOp) - { - case EOpFloatBitsToInt: - setType(TType(EbtInt, EbpHigh, resultQualifier, operandPrimarySize)); - break; - case EOpFloatBitsToUint: - setType(TType(EbtUInt, EbpHigh, resultQualifier, operandPrimarySize)); - break; - case EOpIntBitsToFloat: - case EOpUintBitsToFloat: - setType(TType(EbtFloat, EbpHigh, resultQualifier, operandPrimarySize)); - break; - case EOpPackSnorm2x16: - case EOpPackUnorm2x16: - case EOpPackHalf2x16: - case EOpPackUnorm4x8: - case EOpPackSnorm4x8: - setType(TType(EbtUInt, EbpHigh, resultQualifier)); - break; - case EOpUnpackSnorm2x16: - case EOpUnpackUnorm2x16: - setType(TType(EbtFloat, EbpHigh, resultQualifier, 2)); - break; - case EOpUnpackHalf2x16: - setType(TType(EbtFloat, EbpMedium, resultQualifier, 2)); - break; - case EOpUnpackUnorm4x8: - case EOpUnpackSnorm4x8: - setType(TType(EbtFloat, EbpMedium, resultQualifier, 4)); - break; - case EOpAny: - case EOpAll: - setType(TType(EbtBool, EbpUndefined, resultQualifier)); - break; - case EOpLength: - case EOpDeterminant: - setType(TType(EbtFloat, mOperand->getType().getPrecision(), resultQualifier)); - break; - case EOpTranspose: - setType(TType(EbtFloat, mOperand->getType().getPrecision(), resultQualifier, - static_cast(mOperand->getType().getRows()), - static_cast(mOperand->getType().getCols()))); - break; - case EOpIsInf: - case EOpIsNan: - setType(TType(EbtBool, EbpUndefined, resultQualifier, operandPrimarySize)); - break; - case EOpBitfieldReverse: - setType(TType(mOperand->getBasicType(), EbpHigh, resultQualifier, operandPrimarySize)); - break; - case EOpBitCount: - setType(TType(EbtInt, EbpLow, resultQualifier, operandPrimarySize)); - break; - case EOpFindLSB: - setType(TType(EbtInt, EbpLow, resultQualifier, operandPrimarySize)); - break; - case EOpFindMSB: - setType(TType(EbtInt, EbpLow, resultQualifier, operandPrimarySize)); - break; - default: - setType(mOperand->getType()); - mType.setQualifier(resultQualifier); - break; - } -} - -TIntermSwizzle::TIntermSwizzle(TIntermTyped *operand, const TVector &swizzleOffsets) - : TIntermTyped(TType(EbtFloat, EbpUndefined)), - mOperand(operand), - mSwizzleOffsets(swizzleOffsets) -{ - ASSERT(mSwizzleOffsets.size() <= 4); - promote(); -} - -TIntermUnary::TIntermUnary(TOperator op, TIntermTyped *operand) - : TIntermOperator(op), mOperand(operand), mUseEmulatedFunction(false) -{ - promote(); -} - -TIntermBinary::TIntermBinary(TOperator op, TIntermTyped *left, TIntermTyped *right) - : TIntermOperator(op), mLeft(left), mRight(right), mAddIndexClamp(false) -{ - promote(); -} - -TIntermInvariantDeclaration::TIntermInvariantDeclaration(TIntermSymbol *symbol, const TSourceLoc &line) - : TIntermNode(), mSymbol(symbol) -{ - ASSERT(symbol); - setLine(line); -} - -TIntermTernary::TIntermTernary(TIntermTyped *cond, - TIntermTyped *trueExpression, - TIntermTyped *falseExpression) - : TIntermTyped(trueExpression->getType()), - mCondition(cond), - mTrueExpression(trueExpression), - mFalseExpression(falseExpression) -{ - getTypePointer()->setQualifier( - TIntermTernary::DetermineQualifier(cond, trueExpression, falseExpression)); -} - -TIntermLoop::TIntermLoop(TLoopType type, - TIntermNode *init, - TIntermTyped *cond, - TIntermTyped *expr, - TIntermBlock *body) - : mType(type), mInit(init), mCond(cond), mExpr(expr), mBody(body) -{ - // Declaration nodes with no children can appear if all the declarators just added constants to - // the symbol table instead of generating code. They're no-ops so don't add them to the tree. - if (mInit && mInit->getAsDeclarationNode() && - mInit->getAsDeclarationNode()->getSequence()->empty()) - { - mInit = nullptr; - } -} - -TIntermIfElse::TIntermIfElse(TIntermTyped *cond, TIntermBlock *trueB, TIntermBlock *falseB) - : TIntermNode(), mCondition(cond), mTrueBlock(trueB), mFalseBlock(falseB) -{ - // Prune empty false blocks so that there won't be unnecessary operations done on it. - if (mFalseBlock && mFalseBlock->getSequence()->empty()) - { - mFalseBlock = nullptr; - } -} - -TIntermSwitch::TIntermSwitch(TIntermTyped *init, TIntermBlock *statementList) - : TIntermNode(), mInit(init), mStatementList(statementList) -{ - ASSERT(mStatementList); -} - -void TIntermSwitch::setStatementList(TIntermBlock *statementList) -{ - ASSERT(statementList); - mStatementList = statementList; -} - -// static -TQualifier TIntermTernary::DetermineQualifier(TIntermTyped *cond, - TIntermTyped *trueExpression, - TIntermTyped *falseExpression) -{ - if (cond->getQualifier() == EvqConst && trueExpression->getQualifier() == EvqConst && - falseExpression->getQualifier() == EvqConst) - { - return EvqConst; - } - return EvqTemporary; -} - -TIntermTyped *TIntermTernary::fold() -{ - if (mCondition->getAsConstantUnion()) - { - if (mCondition->getAsConstantUnion()->getBConst(0)) - { - mTrueExpression->getTypePointer()->setQualifier(mType.getQualifier()); - return mTrueExpression; - } - else - { - mFalseExpression->getTypePointer()->setQualifier(mType.getQualifier()); - return mFalseExpression; - } - } - return this; -} - -void TIntermSwizzle::promote() -{ - TQualifier resultQualifier = EvqTemporary; - if (mOperand->getQualifier() == EvqConst) - resultQualifier = EvqConst; - - auto numFields = mSwizzleOffsets.size(); - setType(TType(mOperand->getBasicType(), mOperand->getPrecision(), resultQualifier, - static_cast(numFields))); -} - -bool TIntermSwizzle::hasDuplicateOffsets() const -{ - int offsetCount[4] = {0u, 0u, 0u, 0u}; - for (const auto offset : mSwizzleOffsets) - { - offsetCount[offset]++; - if (offsetCount[offset] > 1) - { - return true; - } - } - return false; -} - -bool TIntermSwizzle::offsetsMatch(int offset) const -{ - return mSwizzleOffsets.size() == 1 && mSwizzleOffsets[0] == offset; -} - -void TIntermSwizzle::writeOffsetsAsXYZW(TInfoSinkBase *out) const -{ - for (const int offset : mSwizzleOffsets) - { - switch (offset) - { - case 0: - *out << "x"; - break; - case 1: - *out << "y"; - break; - case 2: - *out << "z"; - break; - case 3: - *out << "w"; - break; - default: - UNREACHABLE(); - } - } -} - -TQualifier TIntermBinary::GetCommaQualifier(int shaderVersion, - const TIntermTyped *left, - const TIntermTyped *right) -{ - // ESSL3.00 section 12.43: The result of a sequence operator is not a constant-expression. - if (shaderVersion >= 300 || left->getQualifier() != EvqConst || - right->getQualifier() != EvqConst) - { - return EvqTemporary; - } - return EvqConst; -} - -// Establishes the type of the result of the binary operation. -void TIntermBinary::promote() -{ - ASSERT(!isMultiplication() || - mOp == GetMulOpBasedOnOperands(mLeft->getType(), mRight->getType())); - - // Comma is handled as a special case. Note that the comma node qualifier depends on the shader - // version and so is not being set here. - if (mOp == EOpComma) - { - setType(mRight->getType()); - return; - } - - // Base assumption: just make the type the same as the left - // operand. Then only deviations from this need be coded. - setType(mLeft->getType()); - - TQualifier resultQualifier = EvqConst; - // Binary operations results in temporary variables unless both - // operands are const. - if (mLeft->getQualifier() != EvqConst || mRight->getQualifier() != EvqConst) - { - resultQualifier = EvqTemporary; - getTypePointer()->setQualifier(EvqTemporary); - } - - // Handle indexing ops. - switch (mOp) - { - case EOpIndexDirect: - case EOpIndexIndirect: - if (mLeft->isArray()) - { - mType.toArrayElementType(); - } - else if (mLeft->isMatrix()) - { - setType(TType(mLeft->getBasicType(), mLeft->getPrecision(), resultQualifier, - static_cast(mLeft->getRows()))); - } - else if (mLeft->isVector()) - { - setType(TType(mLeft->getBasicType(), mLeft->getPrecision(), resultQualifier)); - } - else - { - UNREACHABLE(); - } - return; - case EOpIndexDirectStruct: - { - const TFieldList &fields = mLeft->getType().getStruct()->fields(); - const int i = mRight->getAsConstantUnion()->getIConst(0); - setType(*fields[i]->type()); - getTypePointer()->setQualifier(resultQualifier); - return; - } - case EOpIndexDirectInterfaceBlock: - { - const TFieldList &fields = mLeft->getType().getInterfaceBlock()->fields(); - const int i = mRight->getAsConstantUnion()->getIConst(0); - setType(*fields[i]->type()); - getTypePointer()->setQualifier(resultQualifier); - return; - } - default: - break; - } - - ASSERT(mLeft->isArray() == mRight->isArray()); - - // The result gets promoted to the highest precision. - TPrecision higherPrecision = GetHigherPrecision(mLeft->getPrecision(), mRight->getPrecision()); - getTypePointer()->setPrecision(higherPrecision); - - const int nominalSize = std::max(mLeft->getNominalSize(), mRight->getNominalSize()); - - // - // All scalars or structs. Code after this test assumes this case is removed! - // - if (nominalSize == 1) - { - switch (mOp) - { - // - // Promote to conditional - // - case EOpEqual: - case EOpNotEqual: - case EOpLessThan: - case EOpGreaterThan: - case EOpLessThanEqual: - case EOpGreaterThanEqual: - setType(TType(EbtBool, EbpUndefined, resultQualifier)); - break; - - // - // And and Or operate on conditionals - // - case EOpLogicalAnd: - case EOpLogicalXor: - case EOpLogicalOr: - ASSERT(mLeft->getBasicType() == EbtBool && mRight->getBasicType() == EbtBool); - setType(TType(EbtBool, EbpUndefined, resultQualifier)); - break; - - default: - break; - } - return; - } - - // If we reach here, at least one of the operands is vector or matrix. - // The other operand could be a scalar, vector, or matrix. - TBasicType basicType = mLeft->getBasicType(); - - switch (mOp) - { - case EOpMul: - break; - case EOpMatrixTimesScalar: - if (mRight->isMatrix()) - { - setType(TType(basicType, higherPrecision, resultQualifier, - static_cast(mRight->getCols()), - static_cast(mRight->getRows()))); - } - break; - case EOpMatrixTimesVector: - setType(TType(basicType, higherPrecision, resultQualifier, - static_cast(mLeft->getRows()), 1)); - break; - case EOpMatrixTimesMatrix: - setType(TType(basicType, higherPrecision, resultQualifier, - static_cast(mRight->getCols()), - static_cast(mLeft->getRows()))); - break; - case EOpVectorTimesScalar: - setType(TType(basicType, higherPrecision, resultQualifier, - static_cast(nominalSize), 1)); - break; - case EOpVectorTimesMatrix: - setType(TType(basicType, higherPrecision, resultQualifier, - static_cast(mRight->getCols()), 1)); - break; - case EOpMulAssign: - case EOpVectorTimesScalarAssign: - case EOpVectorTimesMatrixAssign: - case EOpMatrixTimesScalarAssign: - case EOpMatrixTimesMatrixAssign: - ASSERT(mOp == GetMulAssignOpBasedOnOperands(mLeft->getType(), mRight->getType())); - break; - case EOpAssign: - case EOpInitialize: - ASSERT((mLeft->getNominalSize() == mRight->getNominalSize()) && - (mLeft->getSecondarySize() == mRight->getSecondarySize())); - break; - case EOpAdd: - case EOpSub: - case EOpDiv: - case EOpIMod: - case EOpBitShiftLeft: - case EOpBitShiftRight: - case EOpBitwiseAnd: - case EOpBitwiseXor: - case EOpBitwiseOr: - case EOpAddAssign: - case EOpSubAssign: - case EOpDivAssign: - case EOpIModAssign: - case EOpBitShiftLeftAssign: - case EOpBitShiftRightAssign: - case EOpBitwiseAndAssign: - case EOpBitwiseXorAssign: - case EOpBitwiseOrAssign: - { - const int secondarySize = - std::max(mLeft->getSecondarySize(), mRight->getSecondarySize()); - setType(TType(basicType, higherPrecision, resultQualifier, - static_cast(nominalSize), - static_cast(secondarySize))); - ASSERT(!mLeft->isArray() && !mRight->isArray()); - break; - } - case EOpEqual: - case EOpNotEqual: - case EOpLessThan: - case EOpGreaterThan: - case EOpLessThanEqual: - case EOpGreaterThanEqual: - ASSERT((mLeft->getNominalSize() == mRight->getNominalSize()) && - (mLeft->getSecondarySize() == mRight->getSecondarySize())); - setType(TType(EbtBool, EbpUndefined, resultQualifier)); - break; - - case EOpIndexDirect: - case EOpIndexIndirect: - case EOpIndexDirectInterfaceBlock: - case EOpIndexDirectStruct: - // These ops should be already fully handled. - UNREACHABLE(); - break; - default: - UNREACHABLE(); - break; - } -} - -const TConstantUnion *TIntermConstantUnion::foldIndexing(int index) -{ - if (isArray()) - { - ASSERT(index < static_cast(getType().getOutermostArraySize())); - TType arrayElementType = getType(); - arrayElementType.toArrayElementType(); - size_t arrayElementSize = arrayElementType.getObjectSize(); - return &mUnionArrayPointer[arrayElementSize * index]; - } - else if (isMatrix()) - { - ASSERT(index < getType().getCols()); - int size = getType().getRows(); - return &mUnionArrayPointer[size * index]; - } - else if (isVector()) - { - ASSERT(index < getType().getNominalSize()); - return &mUnionArrayPointer[index]; - } - else - { - UNREACHABLE(); - return nullptr; - } -} - -TIntermTyped *TIntermSwizzle::fold() -{ - TIntermConstantUnion *operandConstant = mOperand->getAsConstantUnion(); - if (operandConstant == nullptr) - { - return this; - } - - TConstantUnion *constArray = new TConstantUnion[mSwizzleOffsets.size()]; - for (size_t i = 0; i < mSwizzleOffsets.size(); ++i) - { - constArray[i] = *operandConstant->foldIndexing(mSwizzleOffsets.at(i)); - } - return CreateFoldedNode(constArray, this, mType.getQualifier()); -} - -TIntermTyped *TIntermBinary::fold(TDiagnostics *diagnostics) -{ - TIntermConstantUnion *leftConstant = mLeft->getAsConstantUnion(); - TIntermConstantUnion *rightConstant = mRight->getAsConstantUnion(); - switch (mOp) - { - case EOpComma: - { - if (mLeft->hasSideEffects()) - { - return this; - } - mRight->getTypePointer()->setQualifier(mType.getQualifier()); - return mRight; - } - case EOpIndexDirect: - { - if (leftConstant == nullptr || rightConstant == nullptr) - { - return this; - } - int index = rightConstant->getIConst(0); - - const TConstantUnion *constArray = leftConstant->foldIndexing(index); - if (!constArray) - { - return this; - } - return CreateFoldedNode(constArray, this, mType.getQualifier()); - } - case EOpIndexDirectStruct: - { - if (leftConstant == nullptr || rightConstant == nullptr) - { - return this; - } - const TFieldList &fields = mLeft->getType().getStruct()->fields(); - size_t index = static_cast(rightConstant->getIConst(0)); - - size_t previousFieldsSize = 0; - for (size_t i = 0; i < index; ++i) - { - previousFieldsSize += fields[i]->type()->getObjectSize(); - } - - const TConstantUnion *constArray = leftConstant->getUnionArrayPointer(); - return CreateFoldedNode(constArray + previousFieldsSize, this, mType.getQualifier()); - } - case EOpIndexIndirect: - case EOpIndexDirectInterfaceBlock: - // Can never be constant folded. - return this; - default: - { - if (leftConstant == nullptr || rightConstant == nullptr) - { - return this; - } - TConstantUnion *constArray = - leftConstant->foldBinary(mOp, rightConstant, diagnostics, mLeft->getLine()); - if (!constArray) - { - return this; - } - - // Nodes may be constant folded without being qualified as constant. - return CreateFoldedNode(constArray, this, mType.getQualifier()); - } - } -} - -TIntermTyped *TIntermUnary::fold(TDiagnostics *diagnostics) -{ - TConstantUnion *constArray = nullptr; - - if (mOp == EOpArrayLength) - { - // The size of runtime-sized arrays may only be determined at runtime. - if (mOperand->hasSideEffects() || mOperand->getType().isUnsizedArray()) - { - return this; - } - constArray = new TConstantUnion[1]; - constArray->setIConst(mOperand->getOutermostArraySize()); - } - else - { - TIntermConstantUnion *operandConstant = mOperand->getAsConstantUnion(); - if (operandConstant == nullptr) - { - return this; - } - - switch (mOp) - { - case EOpAny: - case EOpAll: - case EOpLength: - case EOpTranspose: - case EOpDeterminant: - case EOpInverse: - case EOpPackSnorm2x16: - case EOpUnpackSnorm2x16: - case EOpPackUnorm2x16: - case EOpUnpackUnorm2x16: - case EOpPackHalf2x16: - case EOpUnpackHalf2x16: - case EOpPackUnorm4x8: - case EOpPackSnorm4x8: - case EOpUnpackUnorm4x8: - case EOpUnpackSnorm4x8: - constArray = operandConstant->foldUnaryNonComponentWise(mOp); - break; - default: - constArray = operandConstant->foldUnaryComponentWise(mOp, diagnostics); - break; - } - } - if (constArray == nullptr) - { - return this; - } - - // Nodes may be constant folded without being qualified as constant. - return CreateFoldedNode(constArray, this, mType.getQualifier()); -} - -TIntermTyped *TIntermAggregate::fold(TDiagnostics *diagnostics) -{ - // Make sure that all params are constant before actual constant folding. - for (auto *param : *getSequence()) - { - if (param->getAsConstantUnion() == nullptr) - { - return this; - } - } - TConstantUnion *constArray = nullptr; - if (isConstructor()) - constArray = TIntermConstantUnion::FoldAggregateConstructor(this); - else - constArray = TIntermConstantUnion::FoldAggregateBuiltIn(this, diagnostics); - - // Nodes may be constant folded without being qualified as constant. - return CreateFoldedNode(constArray, this, getQualifier()); -} - -// -// The fold functions see if an operation on a constant can be done in place, -// without generating run-time code. -// -// Returns the constant value to keep using or nullptr. -// -TConstantUnion *TIntermConstantUnion::foldBinary(TOperator op, - TIntermConstantUnion *rightNode, - TDiagnostics *diagnostics, - const TSourceLoc &line) -{ - const TConstantUnion *leftArray = getUnionArrayPointer(); - const TConstantUnion *rightArray = rightNode->getUnionArrayPointer(); - - ASSERT(leftArray && rightArray); - - size_t objectSize = getType().getObjectSize(); - - // for a case like float f = vec4(2, 3, 4, 5) + 1.2; - if (rightNode->getType().getObjectSize() == 1 && objectSize > 1) - { - rightArray = Vectorize(*rightNode->getUnionArrayPointer(), objectSize); - } - else if (rightNode->getType().getObjectSize() > 1 && objectSize == 1) - { - // for a case like float f = 1.2 + vec4(2, 3, 4, 5); - leftArray = Vectorize(*getUnionArrayPointer(), rightNode->getType().getObjectSize()); - objectSize = rightNode->getType().getObjectSize(); - } - - TConstantUnion *resultArray = nullptr; - - switch (op) - { - case EOpAdd: - resultArray = new TConstantUnion[objectSize]; - for (size_t i = 0; i < objectSize; i++) - resultArray[i] = - TConstantUnion::add(leftArray[i], rightArray[i], diagnostics, line); - break; - case EOpSub: - resultArray = new TConstantUnion[objectSize]; - for (size_t i = 0; i < objectSize; i++) - resultArray[i] = - TConstantUnion::sub(leftArray[i], rightArray[i], diagnostics, line); - break; - - case EOpMul: - case EOpVectorTimesScalar: - case EOpMatrixTimesScalar: - resultArray = new TConstantUnion[objectSize]; - for (size_t i = 0; i < objectSize; i++) - resultArray[i] = - TConstantUnion::mul(leftArray[i], rightArray[i], diagnostics, line); - break; - - case EOpMatrixTimesMatrix: - { - // TODO(jmadll): This code should check for overflows. - ASSERT(getType().getBasicType() == EbtFloat && rightNode->getBasicType() == EbtFloat); - - const int leftCols = getCols(); - const int leftRows = getRows(); - const int rightCols = rightNode->getType().getCols(); - const int rightRows = rightNode->getType().getRows(); - const int resultCols = rightCols; - const int resultRows = leftRows; - - resultArray = new TConstantUnion[resultCols * resultRows]; - for (int row = 0; row < resultRows; row++) - { - for (int column = 0; column < resultCols; column++) - { - resultArray[resultRows * column + row].setFConst(0.0f); - for (int i = 0; i < leftCols; i++) - { - resultArray[resultRows * column + row].setFConst( - resultArray[resultRows * column + row].getFConst() + - leftArray[i * leftRows + row].getFConst() * - rightArray[column * rightRows + i].getFConst()); - } - } - } - } - break; - - case EOpDiv: - case EOpIMod: - { - resultArray = new TConstantUnion[objectSize]; - for (size_t i = 0; i < objectSize; i++) - { - switch (getType().getBasicType()) - { - case EbtFloat: - { - ASSERT(op == EOpDiv); - float dividend = leftArray[i].getFConst(); - float divisor = rightArray[i].getFConst(); - if (divisor == 0.0f) - { - if (dividend == 0.0f) - { - diagnostics->warning( - getLine(), - "Zero divided by zero during constant folding generated NaN", - "/"); - resultArray[i].setFConst(std::numeric_limits::quiet_NaN()); - } - else - { - diagnostics->warning(getLine(), - "Divide by zero during constant folding", "/"); - bool negativeResult = - std::signbit(dividend) != std::signbit(divisor); - resultArray[i].setFConst( - negativeResult ? -std::numeric_limits::infinity() - : std::numeric_limits::infinity()); - } - } - else if (gl::isInf(dividend) && gl::isInf(divisor)) - { - diagnostics->warning(getLine(), - "Infinity divided by infinity during constant " - "folding generated NaN", - "/"); - resultArray[i].setFConst(std::numeric_limits::quiet_NaN()); - } - else - { - float result = dividend / divisor; - if (!gl::isInf(dividend) && gl::isInf(result)) - { - diagnostics->warning( - getLine(), "Constant folded division overflowed to infinity", - "/"); - } - resultArray[i].setFConst(result); - } - break; - } - case EbtInt: - if (rightArray[i] == 0) - { - diagnostics->warning( - getLine(), "Divide by zero error during constant folding", "/"); - resultArray[i].setIConst(INT_MAX); - } - else - { - int lhs = leftArray[i].getIConst(); - int divisor = rightArray[i].getIConst(); - if (op == EOpDiv) - { - // Check for the special case where the minimum representable number - // is - // divided by -1. If left alone this leads to integer overflow in - // C++. - // ESSL 3.00.6 section 4.1.3 Integers: - // "However, for the case where the minimum representable value is - // divided by -1, it is allowed to return either the minimum - // representable value or the maximum representable value." - if (lhs == -0x7fffffff - 1 && divisor == -1) - { - resultArray[i].setIConst(0x7fffffff); - } - else - { - resultArray[i].setIConst(lhs / divisor); - } - } - else - { - ASSERT(op == EOpIMod); - if (lhs < 0 || divisor < 0) - { - // ESSL 3.00.6 section 5.9: Results of modulus are undefined - // when - // either one of the operands is negative. - diagnostics->warning(getLine(), - "Negative modulus operator operand " - "encountered during constant folding", - "%"); - resultArray[i].setIConst(0); - } - else - { - resultArray[i].setIConst(lhs % divisor); - } - } - } - break; - - case EbtUInt: - if (rightArray[i] == 0) - { - diagnostics->warning( - getLine(), "Divide by zero error during constant folding", "/"); - resultArray[i].setUConst(UINT_MAX); - } - else - { - if (op == EOpDiv) - { - resultArray[i].setUConst(leftArray[i].getUConst() / - rightArray[i].getUConst()); - } - else - { - ASSERT(op == EOpIMod); - resultArray[i].setUConst(leftArray[i].getUConst() % - rightArray[i].getUConst()); - } - } - break; - - default: - UNREACHABLE(); - return nullptr; - } - } - } - break; - - case EOpMatrixTimesVector: - { - // TODO(jmadll): This code should check for overflows. - ASSERT(rightNode->getBasicType() == EbtFloat); - - const int matrixCols = getCols(); - const int matrixRows = getRows(); - - resultArray = new TConstantUnion[matrixRows]; - - for (int matrixRow = 0; matrixRow < matrixRows; matrixRow++) - { - resultArray[matrixRow].setFConst(0.0f); - for (int col = 0; col < matrixCols; col++) - { - resultArray[matrixRow].setFConst( - resultArray[matrixRow].getFConst() + - leftArray[col * matrixRows + matrixRow].getFConst() * - rightArray[col].getFConst()); - } - } - } - break; - - case EOpVectorTimesMatrix: - { - // TODO(jmadll): This code should check for overflows. - ASSERT(getType().getBasicType() == EbtFloat); - - const int matrixCols = rightNode->getType().getCols(); - const int matrixRows = rightNode->getType().getRows(); - - resultArray = new TConstantUnion[matrixCols]; - - for (int matrixCol = 0; matrixCol < matrixCols; matrixCol++) - { - resultArray[matrixCol].setFConst(0.0f); - for (int matrixRow = 0; matrixRow < matrixRows; matrixRow++) - { - resultArray[matrixCol].setFConst( - resultArray[matrixCol].getFConst() + - leftArray[matrixRow].getFConst() * - rightArray[matrixCol * matrixRows + matrixRow].getFConst()); - } - } - } - break; - - case EOpLogicalAnd: - { - resultArray = new TConstantUnion[objectSize]; - for (size_t i = 0; i < objectSize; i++) - { - resultArray[i] = leftArray[i] && rightArray[i]; - } - } - break; - - case EOpLogicalOr: - { - resultArray = new TConstantUnion[objectSize]; - for (size_t i = 0; i < objectSize; i++) - { - resultArray[i] = leftArray[i] || rightArray[i]; - } - } - break; - - case EOpLogicalXor: - { - ASSERT(getType().getBasicType() == EbtBool); - resultArray = new TConstantUnion[objectSize]; - for (size_t i = 0; i < objectSize; i++) - { - resultArray[i].setBConst(leftArray[i] != rightArray[i]); - } - } - break; - - case EOpBitwiseAnd: - resultArray = new TConstantUnion[objectSize]; - for (size_t i = 0; i < objectSize; i++) - resultArray[i] = leftArray[i] & rightArray[i]; - break; - case EOpBitwiseXor: - resultArray = new TConstantUnion[objectSize]; - for (size_t i = 0; i < objectSize; i++) - resultArray[i] = leftArray[i] ^ rightArray[i]; - break; - case EOpBitwiseOr: - resultArray = new TConstantUnion[objectSize]; - for (size_t i = 0; i < objectSize; i++) - resultArray[i] = leftArray[i] | rightArray[i]; - break; - case EOpBitShiftLeft: - resultArray = new TConstantUnion[objectSize]; - for (size_t i = 0; i < objectSize; i++) - resultArray[i] = - TConstantUnion::lshift(leftArray[i], rightArray[i], diagnostics, line); - break; - case EOpBitShiftRight: - resultArray = new TConstantUnion[objectSize]; - for (size_t i = 0; i < objectSize; i++) - resultArray[i] = - TConstantUnion::rshift(leftArray[i], rightArray[i], diagnostics, line); - break; - - case EOpLessThan: - ASSERT(objectSize == 1); - resultArray = new TConstantUnion[1]; - resultArray->setBConst(*leftArray < *rightArray); - break; - - case EOpGreaterThan: - ASSERT(objectSize == 1); - resultArray = new TConstantUnion[1]; - resultArray->setBConst(*leftArray > *rightArray); - break; - - case EOpLessThanEqual: - ASSERT(objectSize == 1); - resultArray = new TConstantUnion[1]; - resultArray->setBConst(!(*leftArray > *rightArray)); - break; - - case EOpGreaterThanEqual: - ASSERT(objectSize == 1); - resultArray = new TConstantUnion[1]; - resultArray->setBConst(!(*leftArray < *rightArray)); - break; - - case EOpEqual: - case EOpNotEqual: - { - resultArray = new TConstantUnion[1]; - bool equal = true; - for (size_t i = 0; i < objectSize; i++) - { - if (leftArray[i] != rightArray[i]) - { - equal = false; - break; // break out of for loop - } - } - if (op == EOpEqual) - { - resultArray->setBConst(equal); - } - else - { - resultArray->setBConst(!equal); - } - } - break; - - default: - UNREACHABLE(); - return nullptr; - } - return resultArray; -} - -// The fold functions do operations on a constant at GLSL compile time, without generating run-time -// code. Returns the constant value to keep using. Nullptr should not be returned. -TConstantUnion *TIntermConstantUnion::foldUnaryNonComponentWise(TOperator op) -{ - // Do operations where the return type may have a different number of components compared to the - // operand type. - - const TConstantUnion *operandArray = getUnionArrayPointer(); - ASSERT(operandArray); - - size_t objectSize = getType().getObjectSize(); - TConstantUnion *resultArray = nullptr; - switch (op) - { - case EOpAny: - ASSERT(getType().getBasicType() == EbtBool); - resultArray = new TConstantUnion(); - resultArray->setBConst(false); - for (size_t i = 0; i < objectSize; i++) - { - if (operandArray[i].getBConst()) - { - resultArray->setBConst(true); - break; - } - } - break; - - case EOpAll: - ASSERT(getType().getBasicType() == EbtBool); - resultArray = new TConstantUnion(); - resultArray->setBConst(true); - for (size_t i = 0; i < objectSize; i++) - { - if (!operandArray[i].getBConst()) - { - resultArray->setBConst(false); - break; - } - } - break; - - case EOpLength: - ASSERT(getType().getBasicType() == EbtFloat); - resultArray = new TConstantUnion(); - resultArray->setFConst(VectorLength(operandArray, objectSize)); - break; - - case EOpTranspose: - { - ASSERT(getType().getBasicType() == EbtFloat); - resultArray = new TConstantUnion[objectSize]; - angle::Matrix result = - GetMatrix(operandArray, getType().getRows(), getType().getCols()).transpose(); - SetUnionArrayFromMatrix(result, resultArray); - break; - } - - case EOpDeterminant: - { - ASSERT(getType().getBasicType() == EbtFloat); - unsigned int size = getType().getNominalSize(); - ASSERT(size >= 2 && size <= 4); - resultArray = new TConstantUnion(); - resultArray->setFConst(GetMatrix(operandArray, size).determinant()); - break; - } - - case EOpInverse: - { - ASSERT(getType().getBasicType() == EbtFloat); - unsigned int size = getType().getNominalSize(); - ASSERT(size >= 2 && size <= 4); - resultArray = new TConstantUnion[objectSize]; - angle::Matrix result = GetMatrix(operandArray, size).inverse(); - SetUnionArrayFromMatrix(result, resultArray); - break; - } - - case EOpPackSnorm2x16: - ASSERT(getType().getBasicType() == EbtFloat); - ASSERT(getType().getNominalSize() == 2); - resultArray = new TConstantUnion(); - resultArray->setUConst( - gl::packSnorm2x16(operandArray[0].getFConst(), operandArray[1].getFConst())); - break; - - case EOpUnpackSnorm2x16: - { - ASSERT(getType().getBasicType() == EbtUInt); - resultArray = new TConstantUnion[2]; - float f1, f2; - gl::unpackSnorm2x16(operandArray[0].getUConst(), &f1, &f2); - resultArray[0].setFConst(f1); - resultArray[1].setFConst(f2); - break; - } - - case EOpPackUnorm2x16: - ASSERT(getType().getBasicType() == EbtFloat); - ASSERT(getType().getNominalSize() == 2); - resultArray = new TConstantUnion(); - resultArray->setUConst( - gl::packUnorm2x16(operandArray[0].getFConst(), operandArray[1].getFConst())); - break; - - case EOpUnpackUnorm2x16: - { - ASSERT(getType().getBasicType() == EbtUInt); - resultArray = new TConstantUnion[2]; - float f1, f2; - gl::unpackUnorm2x16(operandArray[0].getUConst(), &f1, &f2); - resultArray[0].setFConst(f1); - resultArray[1].setFConst(f2); - break; - } - - case EOpPackHalf2x16: - ASSERT(getType().getBasicType() == EbtFloat); - ASSERT(getType().getNominalSize() == 2); - resultArray = new TConstantUnion(); - resultArray->setUConst( - gl::packHalf2x16(operandArray[0].getFConst(), operandArray[1].getFConst())); - break; - - case EOpUnpackHalf2x16: - { - ASSERT(getType().getBasicType() == EbtUInt); - resultArray = new TConstantUnion[2]; - float f1, f2; - gl::unpackHalf2x16(operandArray[0].getUConst(), &f1, &f2); - resultArray[0].setFConst(f1); - resultArray[1].setFConst(f2); - break; - } - - case EOpPackUnorm4x8: - { - ASSERT(getType().getBasicType() == EbtFloat); - resultArray = new TConstantUnion(); - resultArray->setUConst( - gl::PackUnorm4x8(operandArray[0].getFConst(), operandArray[1].getFConst(), - operandArray[2].getFConst(), operandArray[3].getFConst())); - break; - } - case EOpPackSnorm4x8: - { - ASSERT(getType().getBasicType() == EbtFloat); - resultArray = new TConstantUnion(); - resultArray->setUConst( - gl::PackSnorm4x8(operandArray[0].getFConst(), operandArray[1].getFConst(), - operandArray[2].getFConst(), operandArray[3].getFConst())); - break; - } - case EOpUnpackUnorm4x8: - { - ASSERT(getType().getBasicType() == EbtUInt); - resultArray = new TConstantUnion[4]; - float f[4]; - gl::UnpackUnorm4x8(operandArray[0].getUConst(), f); - for (size_t i = 0; i < 4; ++i) - { - resultArray[i].setFConst(f[i]); - } - break; - } - case EOpUnpackSnorm4x8: - { - ASSERT(getType().getBasicType() == EbtUInt); - resultArray = new TConstantUnion[4]; - float f[4]; - gl::UnpackSnorm4x8(operandArray[0].getUConst(), f); - for (size_t i = 0; i < 4; ++i) - { - resultArray[i].setFConst(f[i]); - } - break; - } - - default: - UNREACHABLE(); - break; - } - - return resultArray; -} - -TConstantUnion *TIntermConstantUnion::foldUnaryComponentWise(TOperator op, - TDiagnostics *diagnostics) -{ - // Do unary operations where each component of the result is computed based on the corresponding - // component of the operand. Also folds normalize, though the divisor in that case takes all - // components into account. - - const TConstantUnion *operandArray = getUnionArrayPointer(); - ASSERT(operandArray); - - size_t objectSize = getType().getObjectSize(); - - TConstantUnion *resultArray = new TConstantUnion[objectSize]; - for (size_t i = 0; i < objectSize; i++) - { - switch (op) - { - case EOpNegative: - switch (getType().getBasicType()) - { - case EbtFloat: - resultArray[i].setFConst(-operandArray[i].getFConst()); - break; - case EbtInt: - if (operandArray[i] == std::numeric_limits::min()) - { - // The minimum representable integer doesn't have a positive - // counterpart, rather the negation overflows and in ESSL is supposed to - // wrap back to the minimum representable integer. Make sure that we - // don't actually let the negation overflow, which has undefined - // behavior in C++. - resultArray[i].setIConst(std::numeric_limits::min()); - } - else - { - resultArray[i].setIConst(-operandArray[i].getIConst()); - } - break; - case EbtUInt: - if (operandArray[i] == 0x80000000u) - { - resultArray[i].setUConst(0x80000000u); - } - else - { - resultArray[i].setUConst(static_cast( - -static_cast(operandArray[i].getUConst()))); - } - break; - default: - UNREACHABLE(); - return nullptr; - } - break; - - case EOpPositive: - switch (getType().getBasicType()) - { - case EbtFloat: - resultArray[i].setFConst(operandArray[i].getFConst()); - break; - case EbtInt: - resultArray[i].setIConst(operandArray[i].getIConst()); - break; - case EbtUInt: - resultArray[i].setUConst(static_cast( - static_cast(operandArray[i].getUConst()))); - break; - default: - UNREACHABLE(); - return nullptr; - } - break; - - case EOpLogicalNot: - switch (getType().getBasicType()) - { - case EbtBool: - resultArray[i].setBConst(!operandArray[i].getBConst()); - break; - default: - UNREACHABLE(); - return nullptr; - } - break; - - case EOpBitwiseNot: - switch (getType().getBasicType()) - { - case EbtInt: - resultArray[i].setIConst(~operandArray[i].getIConst()); - break; - case EbtUInt: - resultArray[i].setUConst(~operandArray[i].getUConst()); - break; - default: - UNREACHABLE(); - return nullptr; - } - break; - - case EOpRadians: - ASSERT(getType().getBasicType() == EbtFloat); - resultArray[i].setFConst(kDegreesToRadiansMultiplier * operandArray[i].getFConst()); - break; - - case EOpDegrees: - ASSERT(getType().getBasicType() == EbtFloat); - resultArray[i].setFConst(kRadiansToDegreesMultiplier * operandArray[i].getFConst()); - break; - - case EOpSin: - foldFloatTypeUnary(operandArray[i], &sinf, &resultArray[i]); - break; - - case EOpCos: - foldFloatTypeUnary(operandArray[i], &cosf, &resultArray[i]); - break; - - case EOpTan: - foldFloatTypeUnary(operandArray[i], &tanf, &resultArray[i]); - break; - - case EOpAsin: - // For asin(x), results are undefined if |x| > 1, we are choosing to set result to - // 0. - if (fabsf(operandArray[i].getFConst()) > 1.0f) - UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), - diagnostics, &resultArray[i]); - else - foldFloatTypeUnary(operandArray[i], &asinf, &resultArray[i]); - break; - - case EOpAcos: - // For acos(x), results are undefined if |x| > 1, we are choosing to set result to - // 0. - if (fabsf(operandArray[i].getFConst()) > 1.0f) - UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), - diagnostics, &resultArray[i]); - else - foldFloatTypeUnary(operandArray[i], &acosf, &resultArray[i]); - break; - - case EOpAtan: - foldFloatTypeUnary(operandArray[i], &atanf, &resultArray[i]); - break; - - case EOpSinh: - foldFloatTypeUnary(operandArray[i], &sinhf, &resultArray[i]); - break; - - case EOpCosh: - foldFloatTypeUnary(operandArray[i], &coshf, &resultArray[i]); - break; - - case EOpTanh: - foldFloatTypeUnary(operandArray[i], &tanhf, &resultArray[i]); - break; - - case EOpAsinh: - foldFloatTypeUnary(operandArray[i], &asinhf, &resultArray[i]); - break; - - case EOpAcosh: - // For acosh(x), results are undefined if x < 1, we are choosing to set result to 0. - if (operandArray[i].getFConst() < 1.0f) - UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), - diagnostics, &resultArray[i]); - else - foldFloatTypeUnary(operandArray[i], &acoshf, &resultArray[i]); - break; - - case EOpAtanh: - // For atanh(x), results are undefined if |x| >= 1, we are choosing to set result to - // 0. - if (fabsf(operandArray[i].getFConst()) >= 1.0f) - UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), - diagnostics, &resultArray[i]); - else - foldFloatTypeUnary(operandArray[i], &atanhf, &resultArray[i]); - break; - - case EOpAbs: - switch (getType().getBasicType()) - { - case EbtFloat: - resultArray[i].setFConst(fabsf(operandArray[i].getFConst())); - break; - case EbtInt: - resultArray[i].setIConst(abs(operandArray[i].getIConst())); - break; - default: - UNREACHABLE(); - return nullptr; - } - break; - - case EOpSign: - switch (getType().getBasicType()) - { - case EbtFloat: - { - float fConst = operandArray[i].getFConst(); - float fResult = 0.0f; - if (fConst > 0.0f) - fResult = 1.0f; - else if (fConst < 0.0f) - fResult = -1.0f; - resultArray[i].setFConst(fResult); - break; - } - case EbtInt: - { - int iConst = operandArray[i].getIConst(); - int iResult = 0; - if (iConst > 0) - iResult = 1; - else if (iConst < 0) - iResult = -1; - resultArray[i].setIConst(iResult); - break; - } - default: - UNREACHABLE(); - return nullptr; - } - break; - - case EOpFloor: - foldFloatTypeUnary(operandArray[i], &floorf, &resultArray[i]); - break; - - case EOpTrunc: - foldFloatTypeUnary(operandArray[i], &truncf, &resultArray[i]); - break; - - case EOpRound: - foldFloatTypeUnary(operandArray[i], &roundf, &resultArray[i]); - break; - - case EOpRoundEven: - { - ASSERT(getType().getBasicType() == EbtFloat); - float x = operandArray[i].getFConst(); - float result; - float fractPart = modff(x, &result); - if (fabsf(fractPart) == 0.5f) - result = 2.0f * roundf(x / 2.0f); - else - result = roundf(x); - resultArray[i].setFConst(result); - break; - } - - case EOpCeil: - foldFloatTypeUnary(operandArray[i], &ceilf, &resultArray[i]); - break; - - case EOpFract: - { - ASSERT(getType().getBasicType() == EbtFloat); - float x = operandArray[i].getFConst(); - resultArray[i].setFConst(x - floorf(x)); - break; - } - - case EOpIsNan: - ASSERT(getType().getBasicType() == EbtFloat); - resultArray[i].setBConst(gl::isNaN(operandArray[0].getFConst())); - break; - - case EOpIsInf: - ASSERT(getType().getBasicType() == EbtFloat); - resultArray[i].setBConst(gl::isInf(operandArray[0].getFConst())); - break; - - case EOpFloatBitsToInt: - ASSERT(getType().getBasicType() == EbtFloat); - resultArray[i].setIConst(gl::bitCast(operandArray[0].getFConst())); - break; - - case EOpFloatBitsToUint: - ASSERT(getType().getBasicType() == EbtFloat); - resultArray[i].setUConst(gl::bitCast(operandArray[0].getFConst())); - break; - - case EOpIntBitsToFloat: - ASSERT(getType().getBasicType() == EbtInt); - resultArray[i].setFConst(gl::bitCast(operandArray[0].getIConst())); - break; - - case EOpUintBitsToFloat: - ASSERT(getType().getBasicType() == EbtUInt); - resultArray[i].setFConst(gl::bitCast(operandArray[0].getUConst())); - break; - - case EOpExp: - foldFloatTypeUnary(operandArray[i], &expf, &resultArray[i]); - break; - - case EOpLog: - // For log(x), results are undefined if x <= 0, we are choosing to set result to 0. - if (operandArray[i].getFConst() <= 0.0f) - UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), - diagnostics, &resultArray[i]); - else - foldFloatTypeUnary(operandArray[i], &logf, &resultArray[i]); - break; - - case EOpExp2: - foldFloatTypeUnary(operandArray[i], &exp2f, &resultArray[i]); - break; - - case EOpLog2: - // For log2(x), results are undefined if x <= 0, we are choosing to set result to 0. - // And log2f is not available on some plarforms like old android, so just using - // log(x)/log(2) here. - if (operandArray[i].getFConst() <= 0.0f) - UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), - diagnostics, &resultArray[i]); - else - { - foldFloatTypeUnary(operandArray[i], &logf, &resultArray[i]); - resultArray[i].setFConst(resultArray[i].getFConst() / logf(2.0f)); - } - break; - - case EOpSqrt: - // For sqrt(x), results are undefined if x < 0, we are choosing to set result to 0. - if (operandArray[i].getFConst() < 0.0f) - UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), - diagnostics, &resultArray[i]); - else - foldFloatTypeUnary(operandArray[i], &sqrtf, &resultArray[i]); - break; - - case EOpInverseSqrt: - // There is no stdlib built-in function equavalent for GLES built-in inversesqrt(), - // so getting the square root first using builtin function sqrt() and then taking - // its inverse. - // Also, for inversesqrt(x), results are undefined if x <= 0, we are choosing to set - // result to 0. - if (operandArray[i].getFConst() <= 0.0f) - UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), - diagnostics, &resultArray[i]); - else - { - foldFloatTypeUnary(operandArray[i], &sqrtf, &resultArray[i]); - resultArray[i].setFConst(1.0f / resultArray[i].getFConst()); - } - break; - - case EOpLogicalNotComponentWise: - ASSERT(getType().getBasicType() == EbtBool); - resultArray[i].setBConst(!operandArray[i].getBConst()); - break; - - case EOpNormalize: - { - ASSERT(getType().getBasicType() == EbtFloat); - float x = operandArray[i].getFConst(); - float length = VectorLength(operandArray, objectSize); - if (length) - resultArray[i].setFConst(x / length); - else - UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), - diagnostics, &resultArray[i]); - break; - } - case EOpBitfieldReverse: - { - uint32_t value; - if (getType().getBasicType() == EbtInt) - { - value = static_cast(operandArray[i].getIConst()); - } - else - { - ASSERT(getType().getBasicType() == EbtUInt); - value = operandArray[i].getUConst(); - } - uint32_t result = gl::BitfieldReverse(value); - if (getType().getBasicType() == EbtInt) - { - resultArray[i].setIConst(static_cast(result)); - } - else - { - resultArray[i].setUConst(result); - } - break; - } - case EOpBitCount: - { - uint32_t value; - if (getType().getBasicType() == EbtInt) - { - value = static_cast(operandArray[i].getIConst()); - } - else - { - ASSERT(getType().getBasicType() == EbtUInt); - value = operandArray[i].getUConst(); - } - int result = gl::BitCount(value); - resultArray[i].setIConst(result); - break; - } - case EOpFindLSB: - { - uint32_t value; - if (getType().getBasicType() == EbtInt) - { - value = static_cast(operandArray[i].getIConst()); - } - else - { - ASSERT(getType().getBasicType() == EbtUInt); - value = operandArray[i].getUConst(); - } - resultArray[i].setIConst(gl::FindLSB(value)); - break; - } - case EOpFindMSB: - { - uint32_t value; - if (getType().getBasicType() == EbtInt) - { - int intValue = operandArray[i].getIConst(); - value = static_cast(intValue); - if (intValue < 0) - { - // Look for zero instead of one in value. This also handles the intValue == - // -1 special case, where the return value needs to be -1. - value = ~value; - } - } - else - { - ASSERT(getType().getBasicType() == EbtUInt); - value = operandArray[i].getUConst(); - } - resultArray[i].setIConst(gl::FindMSB(value)); - break; - } - case EOpDFdx: - case EOpDFdy: - case EOpFwidth: - ASSERT(getType().getBasicType() == EbtFloat); - // Derivatives of constant arguments should be 0. - resultArray[i].setFConst(0.0f); - break; - - default: - return nullptr; - } - } - - return resultArray; -} - -void TIntermConstantUnion::foldFloatTypeUnary(const TConstantUnion ¶meter, - FloatTypeUnaryFunc builtinFunc, - TConstantUnion *result) const -{ - ASSERT(builtinFunc); - - ASSERT(getType().getBasicType() == EbtFloat); - result->setFConst(builtinFunc(parameter.getFConst())); -} - -// static -TConstantUnion *TIntermConstantUnion::FoldAggregateConstructor(TIntermAggregate *aggregate) -{ - ASSERT(aggregate->getSequence()->size() > 0u); - size_t resultSize = aggregate->getType().getObjectSize(); - TConstantUnion *resultArray = new TConstantUnion[resultSize]; - TBasicType basicType = aggregate->getBasicType(); - - size_t resultIndex = 0u; - - if (aggregate->getSequence()->size() == 1u) - { - TIntermNode *argument = aggregate->getSequence()->front(); - TIntermConstantUnion *argumentConstant = argument->getAsConstantUnion(); - const TConstantUnion *argumentUnionArray = argumentConstant->getUnionArrayPointer(); - // Check the special case of constructing a matrix diagonal from a single scalar, - // or a vector from a single scalar. - if (argumentConstant->getType().getObjectSize() == 1u) - { - if (aggregate->isMatrix()) - { - int resultCols = aggregate->getType().getCols(); - int resultRows = aggregate->getType().getRows(); - for (int col = 0; col < resultCols; ++col) - { - for (int row = 0; row < resultRows; ++row) - { - if (col == row) - { - resultArray[resultIndex].cast(basicType, argumentUnionArray[0]); - } - else - { - resultArray[resultIndex].setFConst(0.0f); - } - ++resultIndex; - } - } - } - else - { - while (resultIndex < resultSize) - { - resultArray[resultIndex].cast(basicType, argumentUnionArray[0]); - ++resultIndex; - } - } - ASSERT(resultIndex == resultSize); - return resultArray; - } - else if (aggregate->isMatrix() && argumentConstant->isMatrix()) - { - // The special case of constructing a matrix from a matrix. - int argumentCols = argumentConstant->getType().getCols(); - int argumentRows = argumentConstant->getType().getRows(); - int resultCols = aggregate->getType().getCols(); - int resultRows = aggregate->getType().getRows(); - for (int col = 0; col < resultCols; ++col) - { - for (int row = 0; row < resultRows; ++row) - { - if (col < argumentCols && row < argumentRows) - { - resultArray[resultIndex].cast(basicType, - argumentUnionArray[col * argumentRows + row]); - } - else if (col == row) - { - resultArray[resultIndex].setFConst(1.0f); - } - else - { - resultArray[resultIndex].setFConst(0.0f); - } - ++resultIndex; - } - } - ASSERT(resultIndex == resultSize); - return resultArray; - } - } - - for (TIntermNode *&argument : *aggregate->getSequence()) - { - TIntermConstantUnion *argumentConstant = argument->getAsConstantUnion(); - size_t argumentSize = argumentConstant->getType().getObjectSize(); - const TConstantUnion *argumentUnionArray = argumentConstant->getUnionArrayPointer(); - for (size_t i = 0u; i < argumentSize; ++i) - { - if (resultIndex >= resultSize) - break; - resultArray[resultIndex].cast(basicType, argumentUnionArray[i]); - ++resultIndex; - } - } - ASSERT(resultIndex == resultSize); - return resultArray; -} - -bool TIntermAggregate::CanFoldAggregateBuiltInOp(TOperator op) -{ - switch (op) - { - case EOpAtan: - case EOpPow: - case EOpMod: - case EOpMin: - case EOpMax: - case EOpClamp: - case EOpMix: - case EOpStep: - case EOpSmoothStep: - case EOpLdexp: - case EOpMulMatrixComponentWise: - case EOpOuterProduct: - case EOpEqualComponentWise: - case EOpNotEqualComponentWise: - case EOpLessThanComponentWise: - case EOpLessThanEqualComponentWise: - case EOpGreaterThanComponentWise: - case EOpGreaterThanEqualComponentWise: - case EOpDistance: - case EOpDot: - case EOpCross: - case EOpFaceforward: - case EOpReflect: - case EOpRefract: - case EOpBitfieldExtract: - case EOpBitfieldInsert: - return true; - default: - return false; - } -} - -// static -TConstantUnion *TIntermConstantUnion::FoldAggregateBuiltIn(TIntermAggregate *aggregate, - TDiagnostics *diagnostics) -{ - TOperator op = aggregate->getOp(); - TIntermSequence *arguments = aggregate->getSequence(); - unsigned int argsCount = static_cast(arguments->size()); - std::vector unionArrays(argsCount); - std::vector objectSizes(argsCount); - size_t maxObjectSize = 0; - TBasicType basicType = EbtVoid; - TSourceLoc loc; - for (unsigned int i = 0; i < argsCount; i++) - { - TIntermConstantUnion *argConstant = (*arguments)[i]->getAsConstantUnion(); - ASSERT(argConstant != nullptr); // Should be checked already. - - if (i == 0) - { - basicType = argConstant->getType().getBasicType(); - loc = argConstant->getLine(); - } - unionArrays[i] = argConstant->getUnionArrayPointer(); - objectSizes[i] = argConstant->getType().getObjectSize(); - if (objectSizes[i] > maxObjectSize) - maxObjectSize = objectSizes[i]; - } - - if (!(*arguments)[0]->getAsTyped()->isMatrix() && aggregate->getOp() != EOpOuterProduct) - { - for (unsigned int i = 0; i < argsCount; i++) - if (objectSizes[i] != maxObjectSize) - unionArrays[i] = Vectorize(*unionArrays[i], maxObjectSize); - } - - TConstantUnion *resultArray = nullptr; - - switch (op) - { - case EOpAtan: - { - ASSERT(basicType == EbtFloat); - resultArray = new TConstantUnion[maxObjectSize]; - for (size_t i = 0; i < maxObjectSize; i++) - { - float y = unionArrays[0][i].getFConst(); - float x = unionArrays[1][i].getFConst(); - // Results are undefined if x and y are both 0. - if (x == 0.0f && y == 0.0f) - UndefinedConstantFoldingError(loc, op, basicType, diagnostics, &resultArray[i]); - else - resultArray[i].setFConst(atan2f(y, x)); - } - break; - } - - case EOpPow: - { - ASSERT(basicType == EbtFloat); - resultArray = new TConstantUnion[maxObjectSize]; - for (size_t i = 0; i < maxObjectSize; i++) - { - float x = unionArrays[0][i].getFConst(); - float y = unionArrays[1][i].getFConst(); - // Results are undefined if x < 0. - // Results are undefined if x = 0 and y <= 0. - if (x < 0.0f) - UndefinedConstantFoldingError(loc, op, basicType, diagnostics, &resultArray[i]); - else if (x == 0.0f && y <= 0.0f) - UndefinedConstantFoldingError(loc, op, basicType, diagnostics, &resultArray[i]); - else - resultArray[i].setFConst(powf(x, y)); - } - break; - } - - case EOpMod: - { - ASSERT(basicType == EbtFloat); - resultArray = new TConstantUnion[maxObjectSize]; - for (size_t i = 0; i < maxObjectSize; i++) - { - float x = unionArrays[0][i].getFConst(); - float y = unionArrays[1][i].getFConst(); - resultArray[i].setFConst(x - y * floorf(x / y)); - } - break; - } - - case EOpMin: - { - resultArray = new TConstantUnion[maxObjectSize]; - for (size_t i = 0; i < maxObjectSize; i++) - { - switch (basicType) - { - case EbtFloat: - resultArray[i].setFConst( - std::min(unionArrays[0][i].getFConst(), unionArrays[1][i].getFConst())); - break; - case EbtInt: - resultArray[i].setIConst( - std::min(unionArrays[0][i].getIConst(), unionArrays[1][i].getIConst())); - break; - case EbtUInt: - resultArray[i].setUConst( - std::min(unionArrays[0][i].getUConst(), unionArrays[1][i].getUConst())); - break; - default: - UNREACHABLE(); - break; - } - } - break; - } - - case EOpMax: - { - resultArray = new TConstantUnion[maxObjectSize]; - for (size_t i = 0; i < maxObjectSize; i++) - { - switch (basicType) - { - case EbtFloat: - resultArray[i].setFConst( - std::max(unionArrays[0][i].getFConst(), unionArrays[1][i].getFConst())); - break; - case EbtInt: - resultArray[i].setIConst( - std::max(unionArrays[0][i].getIConst(), unionArrays[1][i].getIConst())); - break; - case EbtUInt: - resultArray[i].setUConst( - std::max(unionArrays[0][i].getUConst(), unionArrays[1][i].getUConst())); - break; - default: - UNREACHABLE(); - break; - } - } - break; - } - - case EOpStep: - { - ASSERT(basicType == EbtFloat); - resultArray = new TConstantUnion[maxObjectSize]; - for (size_t i = 0; i < maxObjectSize; i++) - resultArray[i].setFConst( - unionArrays[1][i].getFConst() < unionArrays[0][i].getFConst() ? 0.0f : 1.0f); - break; - } - - case EOpLessThanComponentWise: - { - resultArray = new TConstantUnion[maxObjectSize]; - for (size_t i = 0; i < maxObjectSize; i++) - { - switch (basicType) - { - case EbtFloat: - resultArray[i].setBConst(unionArrays[0][i].getFConst() < - unionArrays[1][i].getFConst()); - break; - case EbtInt: - resultArray[i].setBConst(unionArrays[0][i].getIConst() < - unionArrays[1][i].getIConst()); - break; - case EbtUInt: - resultArray[i].setBConst(unionArrays[0][i].getUConst() < - unionArrays[1][i].getUConst()); - break; - default: - UNREACHABLE(); - break; - } - } - break; - } - - case EOpLessThanEqualComponentWise: - { - resultArray = new TConstantUnion[maxObjectSize]; - for (size_t i = 0; i < maxObjectSize; i++) - { - switch (basicType) - { - case EbtFloat: - resultArray[i].setBConst(unionArrays[0][i].getFConst() <= - unionArrays[1][i].getFConst()); - break; - case EbtInt: - resultArray[i].setBConst(unionArrays[0][i].getIConst() <= - unionArrays[1][i].getIConst()); - break; - case EbtUInt: - resultArray[i].setBConst(unionArrays[0][i].getUConst() <= - unionArrays[1][i].getUConst()); - break; - default: - UNREACHABLE(); - break; - } - } - break; - } - - case EOpGreaterThanComponentWise: - { - resultArray = new TConstantUnion[maxObjectSize]; - for (size_t i = 0; i < maxObjectSize; i++) - { - switch (basicType) - { - case EbtFloat: - resultArray[i].setBConst(unionArrays[0][i].getFConst() > - unionArrays[1][i].getFConst()); - break; - case EbtInt: - resultArray[i].setBConst(unionArrays[0][i].getIConst() > - unionArrays[1][i].getIConst()); - break; - case EbtUInt: - resultArray[i].setBConst(unionArrays[0][i].getUConst() > - unionArrays[1][i].getUConst()); - break; - default: - UNREACHABLE(); - break; - } - } - break; - } - case EOpGreaterThanEqualComponentWise: - { - resultArray = new TConstantUnion[maxObjectSize]; - for (size_t i = 0; i < maxObjectSize; i++) - { - switch (basicType) - { - case EbtFloat: - resultArray[i].setBConst(unionArrays[0][i].getFConst() >= - unionArrays[1][i].getFConst()); - break; - case EbtInt: - resultArray[i].setBConst(unionArrays[0][i].getIConst() >= - unionArrays[1][i].getIConst()); - break; - case EbtUInt: - resultArray[i].setBConst(unionArrays[0][i].getUConst() >= - unionArrays[1][i].getUConst()); - break; - default: - UNREACHABLE(); - break; - } - } - } - break; - - case EOpEqualComponentWise: - { - resultArray = new TConstantUnion[maxObjectSize]; - for (size_t i = 0; i < maxObjectSize; i++) - { - switch (basicType) - { - case EbtFloat: - resultArray[i].setBConst(unionArrays[0][i].getFConst() == - unionArrays[1][i].getFConst()); - break; - case EbtInt: - resultArray[i].setBConst(unionArrays[0][i].getIConst() == - unionArrays[1][i].getIConst()); - break; - case EbtUInt: - resultArray[i].setBConst(unionArrays[0][i].getUConst() == - unionArrays[1][i].getUConst()); - break; - case EbtBool: - resultArray[i].setBConst(unionArrays[0][i].getBConst() == - unionArrays[1][i].getBConst()); - break; - default: - UNREACHABLE(); - break; - } - } - break; - } - - case EOpNotEqualComponentWise: - { - resultArray = new TConstantUnion[maxObjectSize]; - for (size_t i = 0; i < maxObjectSize; i++) - { - switch (basicType) - { - case EbtFloat: - resultArray[i].setBConst(unionArrays[0][i].getFConst() != - unionArrays[1][i].getFConst()); - break; - case EbtInt: - resultArray[i].setBConst(unionArrays[0][i].getIConst() != - unionArrays[1][i].getIConst()); - break; - case EbtUInt: - resultArray[i].setBConst(unionArrays[0][i].getUConst() != - unionArrays[1][i].getUConst()); - break; - case EbtBool: - resultArray[i].setBConst(unionArrays[0][i].getBConst() != - unionArrays[1][i].getBConst()); - break; - default: - UNREACHABLE(); - break; - } - } - break; - } - - case EOpDistance: - { - ASSERT(basicType == EbtFloat); - TConstantUnion *distanceArray = new TConstantUnion[maxObjectSize]; - resultArray = new TConstantUnion(); - for (size_t i = 0; i < maxObjectSize; i++) - { - float x = unionArrays[0][i].getFConst(); - float y = unionArrays[1][i].getFConst(); - distanceArray[i].setFConst(x - y); - } - resultArray->setFConst(VectorLength(distanceArray, maxObjectSize)); - break; - } - - case EOpDot: - ASSERT(basicType == EbtFloat); - resultArray = new TConstantUnion(); - resultArray->setFConst(VectorDotProduct(unionArrays[0], unionArrays[1], maxObjectSize)); - break; - - case EOpCross: - { - ASSERT(basicType == EbtFloat && maxObjectSize == 3); - resultArray = new TConstantUnion[maxObjectSize]; - float x0 = unionArrays[0][0].getFConst(); - float x1 = unionArrays[0][1].getFConst(); - float x2 = unionArrays[0][2].getFConst(); - float y0 = unionArrays[1][0].getFConst(); - float y1 = unionArrays[1][1].getFConst(); - float y2 = unionArrays[1][2].getFConst(); - resultArray[0].setFConst(x1 * y2 - y1 * x2); - resultArray[1].setFConst(x2 * y0 - y2 * x0); - resultArray[2].setFConst(x0 * y1 - y0 * x1); - break; - } - - case EOpReflect: - { - ASSERT(basicType == EbtFloat); - // genType reflect (genType I, genType N) : - // For the incident vector I and surface orientation N, returns the reflection - // direction: - // I - 2 * dot(N, I) * N. - resultArray = new TConstantUnion[maxObjectSize]; - float dotProduct = VectorDotProduct(unionArrays[1], unionArrays[0], maxObjectSize); - for (size_t i = 0; i < maxObjectSize; i++) - { - float result = unionArrays[0][i].getFConst() - - 2.0f * dotProduct * unionArrays[1][i].getFConst(); - resultArray[i].setFConst(result); - } - break; - } - - case EOpMulMatrixComponentWise: - { - ASSERT(basicType == EbtFloat && (*arguments)[0]->getAsTyped()->isMatrix() && - (*arguments)[1]->getAsTyped()->isMatrix()); - // Perform component-wise matrix multiplication. - resultArray = new TConstantUnion[maxObjectSize]; - int size = (*arguments)[0]->getAsTyped()->getNominalSize(); - angle::Matrix result = - GetMatrix(unionArrays[0], size).compMult(GetMatrix(unionArrays[1], size)); - SetUnionArrayFromMatrix(result, resultArray); - break; - } - - case EOpOuterProduct: - { - ASSERT(basicType == EbtFloat); - size_t numRows = (*arguments)[0]->getAsTyped()->getType().getObjectSize(); - size_t numCols = (*arguments)[1]->getAsTyped()->getType().getObjectSize(); - resultArray = new TConstantUnion[numRows * numCols]; - angle::Matrix result = - GetMatrix(unionArrays[0], static_cast(numRows), 1) - .outerProduct(GetMatrix(unionArrays[1], 1, static_cast(numCols))); - SetUnionArrayFromMatrix(result, resultArray); - break; - } - - case EOpClamp: - { - resultArray = new TConstantUnion[maxObjectSize]; - for (size_t i = 0; i < maxObjectSize; i++) - { - switch (basicType) - { - case EbtFloat: - { - float x = unionArrays[0][i].getFConst(); - float min = unionArrays[1][i].getFConst(); - float max = unionArrays[2][i].getFConst(); - // Results are undefined if min > max. - if (min > max) - UndefinedConstantFoldingError(loc, op, basicType, diagnostics, - &resultArray[i]); - else - resultArray[i].setFConst(gl::clamp(x, min, max)); - break; - } - - case EbtInt: - { - int x = unionArrays[0][i].getIConst(); - int min = unionArrays[1][i].getIConst(); - int max = unionArrays[2][i].getIConst(); - // Results are undefined if min > max. - if (min > max) - UndefinedConstantFoldingError(loc, op, basicType, diagnostics, - &resultArray[i]); - else - resultArray[i].setIConst(gl::clamp(x, min, max)); - break; - } - case EbtUInt: - { - unsigned int x = unionArrays[0][i].getUConst(); - unsigned int min = unionArrays[1][i].getUConst(); - unsigned int max = unionArrays[2][i].getUConst(); - // Results are undefined if min > max. - if (min > max) - UndefinedConstantFoldingError(loc, op, basicType, diagnostics, - &resultArray[i]); - else - resultArray[i].setUConst(gl::clamp(x, min, max)); - break; - } - default: - UNREACHABLE(); - break; - } - } - break; - } - - case EOpMix: - { - ASSERT(basicType == EbtFloat); - resultArray = new TConstantUnion[maxObjectSize]; - for (size_t i = 0; i < maxObjectSize; i++) - { - float x = unionArrays[0][i].getFConst(); - float y = unionArrays[1][i].getFConst(); - TBasicType type = (*arguments)[2]->getAsTyped()->getType().getBasicType(); - if (type == EbtFloat) - { - // Returns the linear blend of x and y, i.e., x * (1 - a) + y * a. - float a = unionArrays[2][i].getFConst(); - resultArray[i].setFConst(x * (1.0f - a) + y * a); - } - else // 3rd parameter is EbtBool - { - ASSERT(type == EbtBool); - // Selects which vector each returned component comes from. - // For a component of a that is false, the corresponding component of x is - // returned. - // For a component of a that is true, the corresponding component of y is - // returned. - bool a = unionArrays[2][i].getBConst(); - resultArray[i].setFConst(a ? y : x); - } - } - break; - } - - case EOpSmoothStep: - { - ASSERT(basicType == EbtFloat); - resultArray = new TConstantUnion[maxObjectSize]; - for (size_t i = 0; i < maxObjectSize; i++) - { - float edge0 = unionArrays[0][i].getFConst(); - float edge1 = unionArrays[1][i].getFConst(); - float x = unionArrays[2][i].getFConst(); - // Results are undefined if edge0 >= edge1. - if (edge0 >= edge1) - { - UndefinedConstantFoldingError(loc, op, basicType, diagnostics, &resultArray[i]); - } - else - { - // Returns 0.0 if x <= edge0 and 1.0 if x >= edge1 and performs smooth - // Hermite interpolation between 0 and 1 when edge0 < x < edge1. - float t = gl::clamp((x - edge0) / (edge1 - edge0), 0.0f, 1.0f); - resultArray[i].setFConst(t * t * (3.0f - 2.0f * t)); - } - } - break; - } - - case EOpLdexp: - { - resultArray = new TConstantUnion[maxObjectSize]; - for (size_t i = 0; i < maxObjectSize; i++) - { - float x = unionArrays[0][i].getFConst(); - int exp = unionArrays[1][i].getIConst(); - if (exp > 128) - { - UndefinedConstantFoldingError(loc, op, basicType, diagnostics, &resultArray[i]); - } - else - { - resultArray[i].setFConst(gl::Ldexp(x, exp)); - } - } - break; - } - - case EOpFaceforward: - { - ASSERT(basicType == EbtFloat); - // genType faceforward(genType N, genType I, genType Nref) : - // If dot(Nref, I) < 0 return N, otherwise return -N. - resultArray = new TConstantUnion[maxObjectSize]; - float dotProduct = VectorDotProduct(unionArrays[2], unionArrays[1], maxObjectSize); - for (size_t i = 0; i < maxObjectSize; i++) - { - if (dotProduct < 0) - resultArray[i].setFConst(unionArrays[0][i].getFConst()); - else - resultArray[i].setFConst(-unionArrays[0][i].getFConst()); - } - break; - } - - case EOpRefract: - { - ASSERT(basicType == EbtFloat); - // genType refract(genType I, genType N, float eta) : - // For the incident vector I and surface normal N, and the ratio of indices of - // refraction eta, - // return the refraction vector. The result is computed by - // k = 1.0 - eta * eta * (1.0 - dot(N, I) * dot(N, I)) - // if (k < 0.0) - // return genType(0.0) - // else - // return eta * I - (eta * dot(N, I) + sqrt(k)) * N - resultArray = new TConstantUnion[maxObjectSize]; - float dotProduct = VectorDotProduct(unionArrays[1], unionArrays[0], maxObjectSize); - for (size_t i = 0; i < maxObjectSize; i++) - { - float eta = unionArrays[2][i].getFConst(); - float k = 1.0f - eta * eta * (1.0f - dotProduct * dotProduct); - if (k < 0.0f) - resultArray[i].setFConst(0.0f); - else - resultArray[i].setFConst(eta * unionArrays[0][i].getFConst() - - (eta * dotProduct + sqrtf(k)) * - unionArrays[1][i].getFConst()); - } - break; - } - case EOpBitfieldExtract: - { - resultArray = new TConstantUnion[maxObjectSize]; - for (size_t i = 0; i < maxObjectSize; ++i) - { - int offset = unionArrays[1][0].getIConst(); - int bits = unionArrays[2][0].getIConst(); - if (bits == 0) - { - if (aggregate->getBasicType() == EbtInt) - { - resultArray[i].setIConst(0); - } - else - { - ASSERT(aggregate->getBasicType() == EbtUInt); - resultArray[i].setUConst(0); - } - } - else if (offset < 0 || bits < 0 || offset >= 32 || bits > 32 || offset + bits > 32) - { - UndefinedConstantFoldingError(loc, op, aggregate->getBasicType(), diagnostics, - &resultArray[i]); - } - else - { - // bits can be 32 here, so we need to avoid bit shift overflow. - uint32_t maskMsb = 1u << (bits - 1); - uint32_t mask = ((maskMsb - 1u) | maskMsb) << offset; - if (aggregate->getBasicType() == EbtInt) - { - uint32_t value = static_cast(unionArrays[0][i].getIConst()); - uint32_t resultUnsigned = (value & mask) >> offset; - if ((resultUnsigned & maskMsb) != 0) - { - // The most significant bits (from bits+1 to the most significant bit) - // should be set to 1. - uint32_t higherBitsMask = ((1u << (32 - bits)) - 1u) << bits; - resultUnsigned |= higherBitsMask; - } - resultArray[i].setIConst(static_cast(resultUnsigned)); - } - else - { - ASSERT(aggregate->getBasicType() == EbtUInt); - uint32_t value = unionArrays[0][i].getUConst(); - resultArray[i].setUConst((value & mask) >> offset); - } - } - } - break; - } - case EOpBitfieldInsert: - { - resultArray = new TConstantUnion[maxObjectSize]; - for (size_t i = 0; i < maxObjectSize; ++i) - { - int offset = unionArrays[2][0].getIConst(); - int bits = unionArrays[3][0].getIConst(); - if (bits == 0) - { - if (aggregate->getBasicType() == EbtInt) - { - int32_t base = unionArrays[0][i].getIConst(); - resultArray[i].setIConst(base); - } - else - { - ASSERT(aggregate->getBasicType() == EbtUInt); - uint32_t base = unionArrays[0][i].getUConst(); - resultArray[i].setUConst(base); - } - } - else if (offset < 0 || bits < 0 || offset >= 32 || bits > 32 || offset + bits > 32) - { - UndefinedConstantFoldingError(loc, op, aggregate->getBasicType(), diagnostics, - &resultArray[i]); - } - else - { - // bits can be 32 here, so we need to avoid bit shift overflow. - uint32_t maskMsb = 1u << (bits - 1); - uint32_t insertMask = ((maskMsb - 1u) | maskMsb) << offset; - uint32_t baseMask = ~insertMask; - if (aggregate->getBasicType() == EbtInt) - { - uint32_t base = static_cast(unionArrays[0][i].getIConst()); - uint32_t insert = static_cast(unionArrays[1][i].getIConst()); - uint32_t resultUnsigned = - (base & baseMask) | ((insert << offset) & insertMask); - resultArray[i].setIConst(static_cast(resultUnsigned)); - } - else - { - ASSERT(aggregate->getBasicType() == EbtUInt); - uint32_t base = unionArrays[0][i].getUConst(); - uint32_t insert = unionArrays[1][i].getUConst(); - resultArray[i].setUConst((base & baseMask) | - ((insert << offset) & insertMask)); - } - } - } - break; - } - - default: - UNREACHABLE(); - return nullptr; - } - return resultArray; -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/IntermNode.h b/src/3rdparty/angle/src/compiler/translator/IntermNode.h deleted file mode 100644 index 2170916201..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/IntermNode.h +++ /dev/null @@ -1,917 +0,0 @@ -// -// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// -// 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 COMPILER_TRANSLATOR_INTERMNODE_H_ -#define COMPILER_TRANSLATOR_INTERMNODE_H_ - -#include "GLSLANG/ShaderLang.h" - -#include -#include - -#include "common/angleutils.h" -#include "compiler/translator/Common.h" -#include "compiler/translator/ConstantUnion.h" -#include "compiler/translator/Operator.h" -#include "compiler/translator/SymbolUniqueId.h" -#include "compiler/translator/Types.h" - -namespace sh -{ - -class TDiagnostics; - -class TIntermTraverser; -class TIntermAggregate; -class TIntermBlock; -class TIntermInvariantDeclaration; -class TIntermDeclaration; -class TIntermFunctionPrototype; -class TIntermFunctionDefinition; -class TIntermSwizzle; -class TIntermBinary; -class TIntermUnary; -class TIntermConstantUnion; -class TIntermTernary; -class TIntermIfElse; -class TIntermSwitch; -class TIntermCase; -class TIntermTyped; -class TIntermSymbol; -class TIntermLoop; -class TInfoSink; -class TInfoSinkBase; -class TIntermRaw; -class TIntermBranch; - -class TSymbolTable; -class TFunction; - -// Encapsulate an identifier string and track whether it is coming from the original shader code -// (not internal) or from ANGLE (internal). Usually internal names shouldn't be decorated or hashed. -class TName -{ - public: - POOL_ALLOCATOR_NEW_DELETE(); - explicit TName(const TString &name) : mName(name), mIsInternal(false) {} - TName() : mName(), mIsInternal(false) {} - TName(const TName &) = default; - TName &operator=(const TName &) = default; - - const TString &getString() const { return mName; } - void setString(const TString &string) { mName = string; } - bool isInternal() const { return mIsInternal; } - void setInternal(bool isInternal) { mIsInternal = isInternal; } - - private: - TString mName; - bool mIsInternal; -}; - -// -// Base class for the tree nodes -// -class TIntermNode : angle::NonCopyable -{ - public: - POOL_ALLOCATOR_NEW_DELETE(); - TIntermNode() - { - // TODO: Move this to TSourceLoc constructor - // after getting rid of TPublicType. - mLine.first_file = mLine.last_file = 0; - mLine.first_line = mLine.last_line = 0; - } - virtual ~TIntermNode() {} - - const TSourceLoc &getLine() const { return mLine; } - void setLine(const TSourceLoc &l) { mLine = l; } - - virtual void traverse(TIntermTraverser *) = 0; - virtual TIntermTyped *getAsTyped() { return 0; } - virtual TIntermConstantUnion *getAsConstantUnion() { return 0; } - virtual TIntermFunctionDefinition *getAsFunctionDefinition() { return nullptr; } - virtual TIntermAggregate *getAsAggregate() { return 0; } - virtual TIntermBlock *getAsBlock() { return nullptr; } - virtual TIntermFunctionPrototype *getAsFunctionPrototypeNode() { return nullptr; } - virtual TIntermInvariantDeclaration *getAsInvariantDeclarationNode() { return nullptr; } - virtual TIntermDeclaration *getAsDeclarationNode() { return nullptr; } - virtual TIntermSwizzle *getAsSwizzleNode() { return nullptr; } - virtual TIntermBinary *getAsBinaryNode() { return 0; } - virtual TIntermUnary *getAsUnaryNode() { return 0; } - virtual TIntermTernary *getAsTernaryNode() { return nullptr; } - virtual TIntermIfElse *getAsIfElseNode() { return nullptr; } - virtual TIntermSwitch *getAsSwitchNode() { return 0; } - virtual TIntermCase *getAsCaseNode() { return 0; } - virtual TIntermSymbol *getAsSymbolNode() { return 0; } - virtual TIntermLoop *getAsLoopNode() { return 0; } - virtual TIntermRaw *getAsRawNode() { return 0; } - virtual TIntermBranch *getAsBranchNode() { return 0; } - - // Replace a child node. Return true if |original| is a child - // node and it is replaced; otherwise, return false. - virtual bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) = 0; - - protected: - TSourceLoc mLine; -}; - -// -// 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) : mType(t) {} - - virtual TIntermTyped *deepCopy() const = 0; - - TIntermTyped *getAsTyped() override { return this; } - - // True if executing the expression represented by this node affects state, like values of - // variables. False if the executing the expression only computes its return value without - // affecting state. May return true conservatively. - virtual bool hasSideEffects() const = 0; - - void setType(const TType &t) { mType = t; } - void setTypePreservePrecision(const TType &t); - const TType &getType() const { return mType; } - TType *getTypePointer() { return &mType; } - - TBasicType getBasicType() const { return mType.getBasicType(); } - TQualifier getQualifier() const { return mType.getQualifier(); } - TPrecision getPrecision() const { return mType.getPrecision(); } - TMemoryQualifier getMemoryQualifier() const { return mType.getMemoryQualifier(); } - int getCols() const { return mType.getCols(); } - int getRows() const { return mType.getRows(); } - int getNominalSize() const { return mType.getNominalSize(); } - int getSecondarySize() const { return mType.getSecondarySize(); } - - bool isInterfaceBlock() const { return mType.isInterfaceBlock(); } - bool isMatrix() const { return mType.isMatrix(); } - bool isArray() const { return mType.isArray(); } - bool isVector() const { return mType.isVector(); } - bool isScalar() const { return mType.isScalar(); } - bool isScalarInt() const { return mType.isScalarInt(); } - const char *getBasicString() const { return mType.getBasicString(); } - TString getCompleteString() const { return mType.getCompleteString(); } - - unsigned int getOutermostArraySize() const { return mType.getOutermostArraySize(); } - - bool isConstructorWithOnlyConstantUnionParameters(); - - protected: - TType mType; - - TIntermTyped(const TIntermTyped &node); -}; - -// -// Handle for, do-while, and while loops. -// -enum TLoopType -{ - ELoopFor, - ELoopWhile, - ELoopDoWhile -}; - -class TIntermLoop : public TIntermNode -{ - public: - TIntermLoop(TLoopType type, - TIntermNode *init, - TIntermTyped *cond, - TIntermTyped *expr, - TIntermBlock *body); - - TIntermLoop *getAsLoopNode() override { return this; } - void traverse(TIntermTraverser *it) override; - bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override; - - TLoopType getType() const { return mType; } - TIntermNode *getInit() { return mInit; } - TIntermTyped *getCondition() { return mCond; } - TIntermTyped *getExpression() { return mExpr; } - TIntermBlock *getBody() { return mBody; } - - void setInit(TIntermNode *init) { mInit = init; } - void setCondition(TIntermTyped *condition) { mCond = condition; } - void setExpression(TIntermTyped *expression) { mExpr = expression; } - void setBody(TIntermBlock *body) { mBody = body; } - - protected: - TLoopType mType; - TIntermNode *mInit; // for-loop initialization - TIntermTyped *mCond; // loop exit condition - TIntermTyped *mExpr; // for-loop expression - TIntermBlock *mBody; // loop body -}; - -// -// Handle break, continue, return, and kill. -// -class TIntermBranch : public TIntermNode -{ - public: - TIntermBranch(TOperator op, TIntermTyped *e) : mFlowOp(op), mExpression(e) {} - - void traverse(TIntermTraverser *it) override; - TIntermBranch *getAsBranchNode() override { return this; } - bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override; - - TOperator getFlowOp() { return mFlowOp; } - TIntermTyped *getExpression() { return mExpression; } - - protected: - TOperator mFlowOp; - TIntermTyped *mExpression; // non-zero except for "return exp;" statements -}; - -// -// 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 poolallocator of sym. - // If sym comes from per process globalpoolallocator, then it causes increased memory usage - // per compile it is essential to use "symbol = sym" to assign to symbol - TIntermSymbol(const TSymbolUniqueId &id, const TString &symbol, const TType &type) - : TIntermTyped(type), mId(id), mSymbol(symbol) - { - } - - TIntermTyped *deepCopy() const override { return new TIntermSymbol(*this); } - - bool hasSideEffects() const override { return false; } - - int getId() const { return mId.get(); } - const TString &getSymbol() const { return mSymbol.getString(); } - const TName &getName() const { return mSymbol; } - TName &getName() { return mSymbol; } - - void setInternal(bool internal) { mSymbol.setInternal(internal); } - - void traverse(TIntermTraverser *it) override; - TIntermSymbol *getAsSymbolNode() override { return this; } - bool replaceChildNode(TIntermNode *, TIntermNode *) override { return false; } - - protected: - const TSymbolUniqueId mId; - TName mSymbol; - - private: - TIntermSymbol(const TIntermSymbol &) = default; // Note: not deleted, just private! -}; - -// A Raw node stores raw code, that the translator will insert verbatim -// into the output stream. Useful for transformation operations that make -// complex code that might not fit naturally into the GLSL model. -class TIntermRaw : public TIntermTyped -{ - public: - TIntermRaw(const TType &type, const TString &rawText) : TIntermTyped(type), mRawText(rawText) {} - TIntermRaw(const TIntermRaw &) = delete; - - TIntermTyped *deepCopy() const override - { - UNREACHABLE(); - return nullptr; - } - - bool hasSideEffects() const override { return false; } - - TString getRawText() const { return mRawText; } - - void traverse(TIntermTraverser *it) override; - - TIntermRaw *getAsRawNode() override { return this; } - bool replaceChildNode(TIntermNode *, TIntermNode *) override { return false; } - - protected: - TString mRawText; -}; - -// Constant folded node. -// Note that nodes may be constant folded and not be constant expressions with the EvqConst -// qualifier. This happens for example when the following expression is processed: -// "true ? 1.0 : non_constant" -// Other nodes than TIntermConstantUnion may also be constant expressions. -// -class TIntermConstantUnion : public TIntermTyped -{ - public: - TIntermConstantUnion(const TConstantUnion *unionPointer, const TType &type) - : TIntermTyped(type), mUnionArrayPointer(unionPointer) - { - ASSERT(unionPointer); - } - - TIntermTyped *deepCopy() const override { return new TIntermConstantUnion(*this); } - - bool hasSideEffects() const override { return false; } - - const TConstantUnion *getUnionArrayPointer() const { return mUnionArrayPointer; } - - int getIConst(size_t index) const - { - return mUnionArrayPointer ? mUnionArrayPointer[index].getIConst() : 0; - } - unsigned int getUConst(size_t index) const - { - return mUnionArrayPointer ? mUnionArrayPointer[index].getUConst() : 0; - } - float getFConst(size_t index) const - { - return mUnionArrayPointer ? mUnionArrayPointer[index].getFConst() : 0.0f; - } - bool getBConst(size_t index) const - { - return mUnionArrayPointer ? mUnionArrayPointer[index].getBConst() : false; - } - - void replaceConstantUnion(const TConstantUnion *safeConstantUnion) - { - ASSERT(safeConstantUnion); - // Previous union pointer freed on pool deallocation. - mUnionArrayPointer = safeConstantUnion; - } - - TIntermConstantUnion *getAsConstantUnion() override { return this; } - void traverse(TIntermTraverser *it) override; - bool replaceChildNode(TIntermNode *, TIntermNode *) override { return false; } - - TConstantUnion *foldBinary(TOperator op, - TIntermConstantUnion *rightNode, - TDiagnostics *diagnostics, - const TSourceLoc &line); - const TConstantUnion *foldIndexing(int index); - TConstantUnion *foldUnaryNonComponentWise(TOperator op); - TConstantUnion *foldUnaryComponentWise(TOperator op, TDiagnostics *diagnostics); - - static TConstantUnion *FoldAggregateConstructor(TIntermAggregate *aggregate); - static TConstantUnion *FoldAggregateBuiltIn(TIntermAggregate *aggregate, - TDiagnostics *diagnostics); - - protected: - // Same data may be shared between multiple constant unions, so it can't be modified. - const TConstantUnion *mUnionArrayPointer; - - private: - typedef float (*FloatTypeUnaryFunc)(float); - void foldFloatTypeUnary(const TConstantUnion ¶meter, - FloatTypeUnaryFunc builtinFunc, - TConstantUnion *result) const; - - TIntermConstantUnion(const TIntermConstantUnion &node); // Note: not deleted, just private! -}; - -// -// Intermediate class for node types that hold operators. -// -class TIntermOperator : public TIntermTyped -{ - public: - TOperator getOp() const { return mOp; } - - bool isAssignment() const; - bool isMultiplication() const; - bool isConstructor() const; - - // Returns true for calls mapped to EOpCall*, false for built-ins that have their own specific - // ops. - bool isFunctionCall() const; - - bool hasSideEffects() const override { return isAssignment(); } - - protected: - TIntermOperator(TOperator op) : TIntermTyped(TType(EbtFloat, EbpUndefined)), mOp(op) {} - TIntermOperator(TOperator op, const TType &type) : TIntermTyped(type), mOp(op) {} - - TIntermOperator(const TIntermOperator &) = default; - - const TOperator mOp; -}; - -// Node for vector swizzles. -class TIntermSwizzle : public TIntermTyped -{ - public: - // This constructor determines the type of the node based on the operand. - TIntermSwizzle(TIntermTyped *operand, const TVector &swizzleOffsets); - - TIntermTyped *deepCopy() const override { return new TIntermSwizzle(*this); } - - TIntermSwizzle *getAsSwizzleNode() override { return this; }; - void traverse(TIntermTraverser *it) override; - bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override; - - bool hasSideEffects() const override { return mOperand->hasSideEffects(); } - - TIntermTyped *getOperand() { return mOperand; } - void writeOffsetsAsXYZW(TInfoSinkBase *out) const; - - bool hasDuplicateOffsets() const; - bool offsetsMatch(int offset) const; - - TIntermTyped *fold(); - - protected: - TIntermTyped *mOperand; - TVector mSwizzleOffsets; - - private: - void promote(); - - TIntermSwizzle(const TIntermSwizzle &node); // Note: not deleted, just private! -}; - -// -// Nodes for all the basic binary math operators. -// -class TIntermBinary : public TIntermOperator -{ - public: - // This constructor determines the type of the binary node based on the operands and op. - TIntermBinary(TOperator op, TIntermTyped *left, TIntermTyped *right); - - TIntermTyped *deepCopy() const override { return new TIntermBinary(*this); } - - static TOperator GetMulOpBasedOnOperands(const TType &left, const TType &right); - static TOperator GetMulAssignOpBasedOnOperands(const TType &left, const TType &right); - static TQualifier GetCommaQualifier(int shaderVersion, - const TIntermTyped *left, - const TIntermTyped *right); - - TIntermBinary *getAsBinaryNode() override { return this; }; - void traverse(TIntermTraverser *it) override; - bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override; - - bool hasSideEffects() const override - { - return isAssignment() || mLeft->hasSideEffects() || mRight->hasSideEffects(); - } - - TIntermTyped *getLeft() const { return mLeft; } - TIntermTyped *getRight() const { return mRight; } - TIntermTyped *fold(TDiagnostics *diagnostics); - - void setAddIndexClamp() { mAddIndexClamp = true; } - bool getAddIndexClamp() { return mAddIndexClamp; } - - protected: - TIntermTyped *mLeft; - TIntermTyped *mRight; - - // If set to true, wrap any EOpIndexIndirect with a clamp to bounds. - bool mAddIndexClamp; - - private: - void promote(); - - TIntermBinary(const TIntermBinary &node); // Note: not deleted, just private! -}; - -// -// Nodes for unary math operators. -// -class TIntermUnary : public TIntermOperator -{ - public: - TIntermUnary(TOperator op, TIntermTyped *operand); - - TIntermTyped *deepCopy() const override { return new TIntermUnary(*this); } - - void traverse(TIntermTraverser *it) override; - TIntermUnary *getAsUnaryNode() override { return this; } - bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override; - - bool hasSideEffects() const override { return isAssignment() || mOperand->hasSideEffects(); } - - TIntermTyped *getOperand() { return mOperand; } - TIntermTyped *fold(TDiagnostics *diagnostics); - - void setUseEmulatedFunction() { mUseEmulatedFunction = true; } - bool getUseEmulatedFunction() { return mUseEmulatedFunction; } - - protected: - TIntermTyped *mOperand; - - // If set to true, replace the built-in function call with an emulated one - // to work around driver bugs. - bool mUseEmulatedFunction; - - private: - void promote(); - - TIntermUnary(const TIntermUnary &node); // note: not deleted, just private! -}; - -class TFunctionSymbolInfo -{ - public: - POOL_ALLOCATOR_NEW_DELETE(); - TFunctionSymbolInfo(const TSymbolUniqueId &id); - TFunctionSymbolInfo() : mId(nullptr), mKnownToNotHaveSideEffects(false) {} - - TFunctionSymbolInfo(const TFunctionSymbolInfo &info); - TFunctionSymbolInfo &operator=(const TFunctionSymbolInfo &info); - - void setFromFunction(const TFunction &function); - - void setNameObj(const TName &name) { mName = name; } - const TName &getNameObj() const { return mName; } - - const TString &getName() const { return mName.getString(); } - void setName(const TString &name) { mName.setString(name); } - bool isMain() const { return mName.getString() == "main"; } - - void setKnownToNotHaveSideEffects(bool knownToNotHaveSideEffects) - { - mKnownToNotHaveSideEffects = knownToNotHaveSideEffects; - } - bool isKnownToNotHaveSideEffects() const { return mKnownToNotHaveSideEffects; } - - void setId(const TSymbolUniqueId &functionId); - const TSymbolUniqueId &getId() const; - - bool isImageFunction() const - { - return getName() == "imageSize" || getName() == "imageLoad" || getName() == "imageStore"; - } - - private: - TName mName; - TSymbolUniqueId *mId; - bool mKnownToNotHaveSideEffects; -}; - -typedef TVector TIntermSequence; -typedef TVector TQualifierList; - -// -// This is just to help yacc. -// -struct TIntermFunctionCallOrMethod -{ - TIntermSequence *arguments; - TIntermNode *thisNode; -}; - -// Interface for node classes that have an arbitrarily sized set of children. -class TIntermAggregateBase -{ - public: - virtual ~TIntermAggregateBase() {} - - virtual TIntermSequence *getSequence() = 0; - virtual const TIntermSequence *getSequence() const = 0; - - bool replaceChildNodeWithMultiple(TIntermNode *original, const TIntermSequence &replacements); - bool insertChildNodes(TIntermSequence::size_type position, const TIntermSequence &insertions); - - protected: - TIntermAggregateBase() {} - - bool replaceChildNodeInternal(TIntermNode *original, TIntermNode *replacement); -}; - -// -// Nodes that operate on an arbitrary sized set of children. -// -class TIntermAggregate : public TIntermOperator, public TIntermAggregateBase -{ - public: - static TIntermAggregate *CreateFunctionCall(const TFunction &func, TIntermSequence *arguments); - - // If using this, ensure that there's a consistent function definition with the same symbol id - // added to the AST. - static TIntermAggregate *CreateFunctionCall(const TType &type, - const TSymbolUniqueId &id, - const TName &name, - TIntermSequence *arguments); - - static TIntermAggregate *CreateBuiltInFunctionCall(const TFunction &func, - TIntermSequence *arguments); - static TIntermAggregate *CreateConstructor(const TType &type, - TIntermSequence *arguments); - static TIntermAggregate *Create(const TType &type, TOperator op, TIntermSequence *arguments); - ~TIntermAggregate() {} - - // Note: only supported for nodes that can be a part of an expression. - TIntermTyped *deepCopy() const override { return new TIntermAggregate(*this); } - - TIntermAggregate *shallowCopy() const; - - TIntermAggregate *getAsAggregate() override { return this; } - void traverse(TIntermTraverser *it) override; - bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override; - - bool hasSideEffects() const override; - - static bool CanFoldAggregateBuiltInOp(TOperator op); - TIntermTyped *fold(TDiagnostics *diagnostics); - - TIntermSequence *getSequence() override { return &mArguments; } - const TIntermSequence *getSequence() const override { return &mArguments; } - - TString getSymbolTableMangledName() const; - - void setUseEmulatedFunction() { mUseEmulatedFunction = true; } - bool getUseEmulatedFunction() { return mUseEmulatedFunction; } - - // Returns true if changing parameter precision may affect the return value. - bool gotPrecisionFromChildren() const { return mGotPrecisionFromChildren; } - - TFunctionSymbolInfo *getFunctionSymbolInfo() { return &mFunctionInfo; } - const TFunctionSymbolInfo *getFunctionSymbolInfo() const { return &mFunctionInfo; } - - protected: - TIntermSequence mArguments; - - // If set to true, replace the built-in function call with an emulated one - // to work around driver bugs. Only for calls mapped to ops other than EOpCall*. - bool mUseEmulatedFunction; - - bool mGotPrecisionFromChildren; - - TFunctionSymbolInfo mFunctionInfo; - - private: - TIntermAggregate(const TType &type, TOperator op, TIntermSequence *arguments); - - TIntermAggregate(const TIntermAggregate &node); // note: not deleted, just private! - - void setTypePrecisionAndQualifier(const TType &type); - - bool areChildrenConstQualified(); - - void setPrecisionFromChildren(); - - void setPrecisionForBuiltInOp(); - - // Returns true if precision was set according to special rules for this built-in. - bool setPrecisionForSpecialBuiltInOp(); - - // Used for built-in functions under EOpCallBuiltInFunction. The function name in the symbol - // info needs to be set before calling this. - void setBuiltInFunctionPrecision(); -}; - -// A list of statements. Either the root node which contains declarations and function definitions, -// or a block that can be marked with curly braces {}. -class TIntermBlock : public TIntermNode, public TIntermAggregateBase -{ - public: - TIntermBlock() : TIntermNode() {} - ~TIntermBlock() {} - - TIntermBlock *getAsBlock() override { return this; } - void traverse(TIntermTraverser *it) override; - bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override; - - // Only intended for initially building the block. - void appendStatement(TIntermNode *statement); - - TIntermSequence *getSequence() override { return &mStatements; } - const TIntermSequence *getSequence() const override { return &mStatements; } - - protected: - TIntermSequence mStatements; -}; - -// Function prototype. May be in the AST either as a function prototype declaration or as a part of -// a function definition. The type of the node is the function return type. -class TIntermFunctionPrototype : public TIntermTyped, public TIntermAggregateBase -{ - public: - // TODO(oetuaho@nvidia.com): See if TFunctionSymbolInfo could be added to constructor - // parameters. - TIntermFunctionPrototype(const TType &type, const TSymbolUniqueId &id) - : TIntermTyped(type), mFunctionInfo(id) - { - } - ~TIntermFunctionPrototype() {} - - TIntermFunctionPrototype *getAsFunctionPrototypeNode() override { return this; } - void traverse(TIntermTraverser *it) override; - bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override; - - TIntermTyped *deepCopy() const override - { - UNREACHABLE(); - return nullptr; - } - bool hasSideEffects() const override - { - UNREACHABLE(); - return true; - } - - // Only intended for initially building the declaration. - void appendParameter(TIntermSymbol *parameter); - - TIntermSequence *getSequence() override { return &mParameters; } - const TIntermSequence *getSequence() const override { return &mParameters; } - - TFunctionSymbolInfo *getFunctionSymbolInfo() { return &mFunctionInfo; } - const TFunctionSymbolInfo *getFunctionSymbolInfo() const { return &mFunctionInfo; } - - protected: - TIntermSequence mParameters; - - TFunctionSymbolInfo mFunctionInfo; -}; - -// Node for function definitions. The prototype child node stores the function header including -// parameters, and the body child node stores the function body. -class TIntermFunctionDefinition : public TIntermNode -{ - public: - TIntermFunctionDefinition(TIntermFunctionPrototype *prototype, TIntermBlock *body) - : TIntermNode(), mPrototype(prototype), mBody(body) - { - ASSERT(prototype != nullptr); - ASSERT(body != nullptr); - } - - TIntermFunctionDefinition *getAsFunctionDefinition() override { return this; } - void traverse(TIntermTraverser *it) override; - bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override; - - TIntermFunctionPrototype *getFunctionPrototype() const { return mPrototype; } - TIntermBlock *getBody() const { return mBody; } - - const TFunctionSymbolInfo *getFunctionSymbolInfo() const - { - return mPrototype->getFunctionSymbolInfo(); - } - - private: - TIntermFunctionPrototype *mPrototype; - TIntermBlock *mBody; -}; - -// Struct, interface block or variable declaration. Can contain multiple variable declarators. -class TIntermDeclaration : public TIntermNode, public TIntermAggregateBase -{ - public: - TIntermDeclaration() : TIntermNode() {} - ~TIntermDeclaration() {} - - TIntermDeclaration *getAsDeclarationNode() override { return this; } - void traverse(TIntermTraverser *it) override; - bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override; - - // Only intended for initially building the declaration. - // The declarator node should be either TIntermSymbol or TIntermBinary with op set to - // EOpInitialize. - void appendDeclarator(TIntermTyped *declarator); - - TIntermSequence *getSequence() override { return &mDeclarators; } - const TIntermSequence *getSequence() const override { return &mDeclarators; } - protected: - TIntermSequence mDeclarators; -}; - -// Specialized declarations for attributing invariance. -class TIntermInvariantDeclaration : public TIntermNode -{ - public: - TIntermInvariantDeclaration(TIntermSymbol *symbol, const TSourceLoc &line); - - virtual TIntermInvariantDeclaration *getAsInvariantDeclarationNode() override { return this; } - - TIntermSymbol *getSymbol() { return mSymbol; } - - void traverse(TIntermTraverser *it) override; - bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override; - - private: - TIntermSymbol *mSymbol; -}; - -// For ternary operators like a ? b : c. -class TIntermTernary : public TIntermTyped -{ - public: - TIntermTernary(TIntermTyped *cond, TIntermTyped *trueExpression, TIntermTyped *falseExpression); - - void traverse(TIntermTraverser *it) override; - bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override; - - TIntermTyped *getCondition() const { return mCondition; } - TIntermTyped *getTrueExpression() const { return mTrueExpression; } - TIntermTyped *getFalseExpression() const { return mFalseExpression; } - TIntermTernary *getAsTernaryNode() override { return this; } - - TIntermTyped *deepCopy() const override { return new TIntermTernary(*this); } - - bool hasSideEffects() const override - { - return mCondition->hasSideEffects() || mTrueExpression->hasSideEffects() || - mFalseExpression->hasSideEffects(); - } - - TIntermTyped *fold(); - - private: - TIntermTernary(const TIntermTernary &node); // Note: not deleted, just private! - - static TQualifier DetermineQualifier(TIntermTyped *cond, - TIntermTyped *trueExpression, - TIntermTyped *falseExpression); - - TIntermTyped *mCondition; - TIntermTyped *mTrueExpression; - TIntermTyped *mFalseExpression; -}; - -class TIntermIfElse : public TIntermNode -{ - public: - TIntermIfElse(TIntermTyped *cond, TIntermBlock *trueB, TIntermBlock *falseB); - - void traverse(TIntermTraverser *it) override; - bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override; - - TIntermTyped *getCondition() const { return mCondition; } - TIntermBlock *getTrueBlock() const { return mTrueBlock; } - TIntermBlock *getFalseBlock() const { return mFalseBlock; } - TIntermIfElse *getAsIfElseNode() override { return this; } - - protected: - TIntermTyped *mCondition; - TIntermBlock *mTrueBlock; - TIntermBlock *mFalseBlock; -}; - -// -// Switch statement. -// -class TIntermSwitch : public TIntermNode -{ - public: - TIntermSwitch(TIntermTyped *init, TIntermBlock *statementList); - - void traverse(TIntermTraverser *it) override; - bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override; - - TIntermSwitch *getAsSwitchNode() override { return this; } - - TIntermTyped *getInit() { return mInit; } - TIntermBlock *getStatementList() { return mStatementList; } - - // Must be called with a non-null statementList. - void setStatementList(TIntermBlock *statementList); - - protected: - TIntermTyped *mInit; - TIntermBlock *mStatementList; -}; - -// -// Case label. -// -class TIntermCase : public TIntermNode -{ - public: - TIntermCase(TIntermTyped *condition) : TIntermNode(), mCondition(condition) {} - - void traverse(TIntermTraverser *it) override; - bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override; - - TIntermCase *getAsCaseNode() override { return this; } - - bool hasCondition() const { return mCondition != nullptr; } - TIntermTyped *getCondition() const { return mCondition; } - - protected: - TIntermTyped *mCondition; -}; - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_INTERMNODE_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/IntermNodePatternMatcher.cpp b/src/3rdparty/angle/src/compiler/translator/IntermNodePatternMatcher.cpp deleted file mode 100644 index 567e8f7440..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/IntermNodePatternMatcher.cpp +++ /dev/null @@ -1,157 +0,0 @@ -// -// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// IntermNodePatternMatcher is a helper class for matching node trees to given patterns. -// It can be used whenever the same checks for certain node structures are common to multiple AST -// traversers. -// - -#include "compiler/translator/IntermNodePatternMatcher.h" - -#include "compiler/translator/IntermNode.h" - -namespace sh -{ - -IntermNodePatternMatcher::IntermNodePatternMatcher(const unsigned int mask) : mMask(mask) -{ -} - -// static -bool IntermNodePatternMatcher::IsDynamicIndexingOfVectorOrMatrix(TIntermBinary *node) -{ - return node->getOp() == EOpIndexIndirect && !node->getLeft()->isArray() && - node->getLeft()->getBasicType() != EbtStruct; -} - -bool IntermNodePatternMatcher::matchInternal(TIntermBinary *node, TIntermNode *parentNode) -{ - if ((mMask & kExpressionReturningArray) != 0) - { - if (node->isArray() && node->getOp() == EOpAssign && parentNode != nullptr && - !parentNode->getAsBlock()) - { - return true; - } - } - - if ((mMask & kUnfoldedShortCircuitExpression) != 0) - { - if (node->getRight()->hasSideEffects() && - (node->getOp() == EOpLogicalOr || node->getOp() == EOpLogicalAnd)) - { - return true; - } - } - return false; -} - -bool IntermNodePatternMatcher::match(TIntermUnary *node) -{ - if ((mMask & kArrayLengthMethod) != 0) - { - if (node->getOp() == EOpArrayLength) - { - return true; - } - } - return false; -} - -bool IntermNodePatternMatcher::match(TIntermBinary *node, TIntermNode *parentNode) -{ - // L-value tracking information is needed to check for dynamic indexing in L-value. - // Traversers that don't track l-values can still use this class and match binary nodes with - // this variation of this method if they don't need to check for dynamic indexing in l-values. - ASSERT((mMask & kDynamicIndexingOfVectorOrMatrixInLValue) == 0); - return matchInternal(node, parentNode); -} - -bool IntermNodePatternMatcher::match(TIntermBinary *node, - TIntermNode *parentNode, - bool isLValueRequiredHere) -{ - if (matchInternal(node, parentNode)) - { - return true; - } - if ((mMask & kDynamicIndexingOfVectorOrMatrixInLValue) != 0) - { - if (isLValueRequiredHere && IsDynamicIndexingOfVectorOrMatrix(node)) - { - return true; - } - } - return false; -} - -bool IntermNodePatternMatcher::match(TIntermAggregate *node, TIntermNode *parentNode) -{ - if ((mMask & kExpressionReturningArray) != 0) - { - if (parentNode != nullptr) - { - TIntermBinary *parentBinary = parentNode->getAsBinaryNode(); - bool parentIsAssignment = - (parentBinary != nullptr && - (parentBinary->getOp() == EOpAssign || parentBinary->getOp() == EOpInitialize)); - - if (node->getType().isArray() && !parentIsAssignment && - (node->isConstructor() || node->isFunctionCall()) && !parentNode->getAsBlock()) - { - return true; - } - } - } - return false; -} - -bool IntermNodePatternMatcher::match(TIntermTernary *node) -{ - if ((mMask & kUnfoldedShortCircuitExpression) != 0) - { - return true; - } - return false; -} - -bool IntermNodePatternMatcher::match(TIntermDeclaration *node) -{ - if ((mMask & kMultiDeclaration) != 0) - { - if (node->getSequence()->size() > 1) - { - return true; - } - } - if ((mMask & kArrayDeclaration) != 0) - { - if (node->getSequence()->front()->getAsTyped()->getType().isStructureContainingArrays()) - { - return true; - } - // Need to check from all declarators whether they are arrays since that may vary between - // declarators. - for (TIntermNode *declarator : *node->getSequence()) - { - if (declarator->getAsTyped()->isArray()) - { - return true; - } - } - } - if ((mMask & kNamelessStructDeclaration) != 0) - { - TIntermTyped *declarator = node->getSequence()->front()->getAsTyped(); - if (declarator->getBasicType() == EbtStruct && - declarator->getType().getStruct()->name() == "") - { - return true; - } - } - return false; -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/IntermNodePatternMatcher.h b/src/3rdparty/angle/src/compiler/translator/IntermNodePatternMatcher.h deleted file mode 100644 index 997fc2ef10..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/IntermNodePatternMatcher.h +++ /dev/null @@ -1,75 +0,0 @@ -// -// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// IntermNodePatternMatcher is a helper class for matching node trees to given patterns. -// It can be used whenever the same checks for certain node structures are common to multiple AST -// traversers. -// - -#ifndef COMPILER_TRANSLATOR_INTERMNODEPATTERNMATCHER_H_ -#define COMPILER_TRANSLATOR_INTERMNODEPATTERNMATCHER_H_ - -namespace sh -{ - -class TIntermAggregate; -class TIntermBinary; -class TIntermDeclaration; -class TIntermNode; -class TIntermTernary; -class TIntermUnary; - -class IntermNodePatternMatcher -{ - public: - static bool IsDynamicIndexingOfVectorOrMatrix(TIntermBinary *node); - - enum PatternType - { - // Matches expressions that are unfolded to if statements by UnfoldShortCircuitToIf - kUnfoldedShortCircuitExpression = 0x0001, - - // Matches expressions that return arrays with the exception of simple statements where a - // constructor or function call result is assigned. - kExpressionReturningArray = 0x0001 << 1, - - // Matches dynamic indexing of vectors or matrices in l-values. - kDynamicIndexingOfVectorOrMatrixInLValue = 0x0001 << 2, - - // Matches declarations with more than one declared variables. - kMultiDeclaration = 0x0001 << 3, - - // Matches declarations of arrays. - kArrayDeclaration = 0x0001 << 4, - - // Matches declarations of structs where the struct type does not have a name. - kNamelessStructDeclaration = 0x0001 << 5, - - // Matches array length() method. - kArrayLengthMethod = 0x0001 << 6 - }; - IntermNodePatternMatcher(const unsigned int mask); - - bool match(TIntermUnary *node); - - bool match(TIntermBinary *node, TIntermNode *parentNode); - - // Use this version for checking binary node matches in case you're using flag - // kDynamicIndexingOfVectorOrMatrixInLValue. - bool match(TIntermBinary *node, TIntermNode *parentNode, bool isLValueRequiredHere); - - bool match(TIntermAggregate *node, TIntermNode *parentNode); - bool match(TIntermTernary *node); - bool match(TIntermDeclaration *node); - - private: - const unsigned int mMask; - - bool matchInternal(TIntermBinary *node, TIntermNode *parentNode); -}; - -} // namespace sh - -#endif diff --git a/src/3rdparty/angle/src/compiler/translator/IntermNode_util.cpp b/src/3rdparty/angle/src/compiler/translator/IntermNode_util.cpp deleted file mode 100644 index 9f1f596c43..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/IntermNode_util.cpp +++ /dev/null @@ -1,254 +0,0 @@ -// -// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// IntermNode_util.cpp: High-level utilities for creating AST nodes and node hierarchies. Mostly -// meant to be used in AST transforms. - -#include "compiler/translator/IntermNode_util.h" - -#include "compiler/translator/SymbolTable.h" - -namespace sh -{ - -namespace -{ - -TName GetInternalFunctionName(const char *name) -{ - TString nameStr(name); - TName nameObj(nameStr); - nameObj.setInternal(true); - return nameObj; -} - -const TFunction *LookUpBuiltInFunction(const TString &name, - const TIntermSequence *arguments, - const TSymbolTable &symbolTable, - int shaderVersion) -{ - TString mangledName = TFunction::GetMangledNameFromCall(name, *arguments); - TSymbol *symbol = symbolTable.findBuiltIn(mangledName, shaderVersion); - if (symbol) - { - ASSERT(symbol->isFunction()); - return static_cast(symbol); - } - return nullptr; -} - -} // anonymous namespace - -TIntermFunctionPrototype *CreateInternalFunctionPrototypeNode(const TType &returnType, - const char *name, - const TSymbolUniqueId &functionId) -{ - TIntermFunctionPrototype *functionNode = new TIntermFunctionPrototype(returnType, functionId); - functionNode->getFunctionSymbolInfo()->setNameObj(GetInternalFunctionName(name)); - return functionNode; -} - -TIntermFunctionDefinition *CreateInternalFunctionDefinitionNode(const TType &returnType, - const char *name, - TIntermBlock *functionBody, - const TSymbolUniqueId &functionId) -{ - TIntermFunctionPrototype *prototypeNode = - CreateInternalFunctionPrototypeNode(returnType, name, functionId); - return new TIntermFunctionDefinition(prototypeNode, functionBody); -} - -TIntermAggregate *CreateInternalFunctionCallNode(const TType &returnType, - const char *name, - const TSymbolUniqueId &functionId, - TIntermSequence *arguments) -{ - TIntermAggregate *functionNode = TIntermAggregate::CreateFunctionCall( - returnType, functionId, GetInternalFunctionName(name), arguments); - return functionNode; -} - -TIntermTyped *CreateZeroNode(const TType &type) -{ - TType constType(type); - constType.setQualifier(EvqConst); - - if (!type.isArray() && type.getBasicType() != EbtStruct) - { - size_t size = constType.getObjectSize(); - TConstantUnion *u = new TConstantUnion[size]; - for (size_t i = 0; i < size; ++i) - { - switch (type.getBasicType()) - { - case EbtFloat: - u[i].setFConst(0.0f); - break; - case EbtInt: - u[i].setIConst(0); - break; - case EbtUInt: - u[i].setUConst(0u); - break; - case EbtBool: - u[i].setBConst(false); - break; - default: - // CreateZeroNode is called by ParseContext that keeps parsing even when an - // error occurs, so it is possible for CreateZeroNode to be called with - // non-basic types. This happens only on error condition but CreateZeroNode - // needs to return a value with the correct type to continue the typecheck. - // That's why we handle non-basic type by setting whatever value, we just need - // the type to be right. - u[i].setIConst(42); - break; - } - } - - TIntermConstantUnion *node = new TIntermConstantUnion(u, constType); - return node; - } - - if (type.getBasicType() == EbtVoid) - { - // Void array. This happens only on error condition, similarly to the case above. We don't - // have a constructor operator for void, so this needs special handling. We'll end up with a - // value without the array type, but that should not be a problem. - while (constType.isArray()) - { - constType.toArrayElementType(); - } - return CreateZeroNode(constType); - } - - TIntermSequence *arguments = new TIntermSequence(); - - if (type.isArray()) - { - TType elementType(type); - elementType.toArrayElementType(); - - size_t arraySize = type.getOutermostArraySize(); - for (size_t i = 0; i < arraySize; ++i) - { - arguments->push_back(CreateZeroNode(elementType)); - } - } - else - { - ASSERT(type.getBasicType() == EbtStruct); - - const TStructure *structure = type.getStruct(); - for (const auto &field : structure->fields()) - { - arguments->push_back(CreateZeroNode(*field->type())); - } - } - - return TIntermAggregate::CreateConstructor(constType, arguments); -} - -TIntermConstantUnion *CreateIndexNode(int index) -{ - TConstantUnion *u = new TConstantUnion[1]; - u[0].setIConst(index); - - TType type(EbtInt, EbpUndefined, EvqConst, 1); - TIntermConstantUnion *node = new TIntermConstantUnion(u, type); - return node; -} - -TIntermConstantUnion *CreateBoolNode(bool value) -{ - TConstantUnion *u = new TConstantUnion[1]; - u[0].setBConst(value); - - TType type(EbtBool, EbpUndefined, EvqConst, 1); - TIntermConstantUnion *node = new TIntermConstantUnion(u, type); - return node; -} - -TIntermSymbol *CreateTempSymbolNode(const TSymbolUniqueId &id, - const TType &type, - TQualifier qualifier) -{ - TInfoSinkBase symbolNameOut; - symbolNameOut << "s" << id.get(); - TString symbolName = symbolNameOut.c_str(); - - TIntermSymbol *node = new TIntermSymbol(id, symbolName, type); - node->setInternal(true); - - ASSERT(qualifier == EvqTemporary || qualifier == EvqConst || qualifier == EvqGlobal); - node->getTypePointer()->setQualifier(qualifier); - - // TODO(oetuaho): Might be useful to sanitize layout qualifier etc. on the type of the created - // symbol. This might need to be done in other places as well. - return node; -} - -TIntermDeclaration *CreateTempInitDeclarationNode(const TSymbolUniqueId &id, - TIntermTyped *initializer, - TQualifier qualifier) -{ - ASSERT(initializer != nullptr); - TIntermSymbol *tempSymbol = CreateTempSymbolNode(id, initializer->getType(), qualifier); - TIntermDeclaration *tempDeclaration = new TIntermDeclaration(); - TIntermBinary *tempInit = new TIntermBinary(EOpInitialize, tempSymbol, initializer); - tempDeclaration->appendDeclarator(tempInit); - return tempDeclaration; -} - -TIntermBlock *EnsureBlock(TIntermNode *node) -{ - if (node == nullptr) - return nullptr; - TIntermBlock *blockNode = node->getAsBlock(); - if (blockNode != nullptr) - return blockNode; - - blockNode = new TIntermBlock(); - blockNode->setLine(node->getLine()); - blockNode->appendStatement(node); - return blockNode; -} - -TIntermSymbol *ReferenceGlobalVariable(const TString &name, const TSymbolTable &symbolTable) -{ - TVariable *var = reinterpret_cast(symbolTable.findGlobal(name)); - ASSERT(var); - return new TIntermSymbol(var->getUniqueId(), name, var->getType()); -} - -TIntermSymbol *ReferenceBuiltInVariable(const TString &name, - const TSymbolTable &symbolTable, - int shaderVersion) -{ - const TVariable *var = - reinterpret_cast(symbolTable.findBuiltIn(name, shaderVersion, true)); - ASSERT(var); - return new TIntermSymbol(var->getUniqueId(), name, var->getType()); -} - -TIntermTyped *CreateBuiltInFunctionCallNode(const TString &name, - TIntermSequence *arguments, - const TSymbolTable &symbolTable, - int shaderVersion) -{ - const TFunction *fn = LookUpBuiltInFunction(name, arguments, symbolTable, shaderVersion); - ASSERT(fn); - TOperator op = fn->getBuiltInOp(); - if (op != EOpNull) - { - if (arguments->size() == 1) - { - return new TIntermUnary(op, arguments->at(0)->getAsTyped()); - } - return TIntermAggregate::Create(fn->getReturnType(), op, arguments); - } - return TIntermAggregate::CreateBuiltInFunctionCall(*fn, arguments); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/IntermNode_util.h b/src/3rdparty/angle/src/compiler/translator/IntermNode_util.h deleted file mode 100644 index 6f3b0674f0..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/IntermNode_util.h +++ /dev/null @@ -1,60 +0,0 @@ -// -// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// IntermNode_util.h: High-level utilities for creating AST nodes and node hierarchies. Mostly meant -// to be used in AST transforms. - -#ifndef COMPILER_TRANSLATOR_INTERMNODEUTIL_H_ -#define COMPILER_TRANSLATOR_INTERMNODEUTIL_H_ - -#include "compiler/translator/IntermNode.h" - -namespace sh -{ - -TIntermFunctionPrototype *CreateInternalFunctionPrototypeNode(const TType &returnType, - const char *name, - const TSymbolUniqueId &functionId); -TIntermFunctionDefinition *CreateInternalFunctionDefinitionNode(const TType &returnType, - const char *name, - TIntermBlock *functionBody, - const TSymbolUniqueId &functionId); -TIntermAggregate *CreateInternalFunctionCallNode(const TType &returnType, - const char *name, - const TSymbolUniqueId &functionId, - TIntermSequence *arguments); - -TIntermTyped *CreateZeroNode(const TType &type); -TIntermConstantUnion *CreateIndexNode(int index); -TIntermConstantUnion *CreateBoolNode(bool value); - -TIntermSymbol *CreateTempSymbolNode(const TSymbolUniqueId &id, - const TType &type, - TQualifier qualifier); -TIntermDeclaration *CreateTempInitDeclarationNode(const TSymbolUniqueId &id, - TIntermTyped *initializer, - TQualifier qualifier); - -// If the input node is nullptr, return nullptr. -// If the input node is a block node, return it. -// If the input node is not a block node, put it inside a block node and return that. -TIntermBlock *EnsureBlock(TIntermNode *node); - -// Should be called from inside Compiler::compileTreeImpl() where the global level is in scope. -TIntermSymbol *ReferenceGlobalVariable(const TString &name, const TSymbolTable &symbolTable); - -// Note: this can access desktop GLSL built-ins that are hidden from the parser. -TIntermSymbol *ReferenceBuiltInVariable(const TString &name, - const TSymbolTable &symbolTable, - int shaderVersion); - -TIntermTyped *CreateBuiltInFunctionCallNode(const TString &name, - TIntermSequence *arguments, - const TSymbolTable &symbolTable, - int shaderVersion); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_INTERMNODEUTIL_H_ \ No newline at end of file diff --git a/src/3rdparty/angle/src/compiler/translator/IntermTraverse.cpp b/src/3rdparty/angle/src/compiler/translator/IntermTraverse.cpp deleted file mode 100644 index 6c25c6c35a..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/IntermTraverse.cpp +++ /dev/null @@ -1,983 +0,0 @@ -// -// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/translator/IntermTraverse.h" - -#include "compiler/translator/InfoSink.h" -#include "compiler/translator/IntermNode_util.h" -#include "compiler/translator/SymbolTable.h" - -namespace sh -{ - -void TIntermSymbol::traverse(TIntermTraverser *it) -{ - it->traverseSymbol(this); -} - -void TIntermRaw::traverse(TIntermTraverser *it) -{ - it->traverseRaw(this); -} - -void TIntermConstantUnion::traverse(TIntermTraverser *it) -{ - it->traverseConstantUnion(this); -} - -void TIntermSwizzle::traverse(TIntermTraverser *it) -{ - it->traverseSwizzle(this); -} - -void TIntermBinary::traverse(TIntermTraverser *it) -{ - it->traverseBinary(this); -} - -void TIntermUnary::traverse(TIntermTraverser *it) -{ - it->traverseUnary(this); -} - -void TIntermTernary::traverse(TIntermTraverser *it) -{ - it->traverseTernary(this); -} - -void TIntermIfElse::traverse(TIntermTraverser *it) -{ - it->traverseIfElse(this); -} - -void TIntermSwitch::traverse(TIntermTraverser *it) -{ - it->traverseSwitch(this); -} - -void TIntermCase::traverse(TIntermTraverser *it) -{ - it->traverseCase(this); -} - -void TIntermFunctionDefinition::traverse(TIntermTraverser *it) -{ - it->traverseFunctionDefinition(this); -} - -void TIntermBlock::traverse(TIntermTraverser *it) -{ - it->traverseBlock(this); -} - -void TIntermInvariantDeclaration::traverse(TIntermTraverser *it) -{ - it->traverseInvariantDeclaration(this); -} - -void TIntermDeclaration::traverse(TIntermTraverser *it) -{ - it->traverseDeclaration(this); -} - -void TIntermFunctionPrototype::traverse(TIntermTraverser *it) -{ - it->traverseFunctionPrototype(this); -} - -void TIntermAggregate::traverse(TIntermTraverser *it) -{ - it->traverseAggregate(this); -} - -void TIntermLoop::traverse(TIntermTraverser *it) -{ - it->traverseLoop(this); -} - -void TIntermBranch::traverse(TIntermTraverser *it) -{ - it->traverseBranch(this); -} - -TIntermTraverser::TIntermTraverser(bool preVisit, - bool inVisit, - bool postVisit, - TSymbolTable *symbolTable) - : preVisit(preVisit), - inVisit(inVisit), - postVisit(postVisit), - mDepth(-1), - mMaxDepth(0), - mInGlobalScope(true), - mSymbolTable(symbolTable), - mTemporaryId(nullptr) -{ -} - -TIntermTraverser::~TIntermTraverser() -{ -} - -const TIntermBlock *TIntermTraverser::getParentBlock() const -{ - if (!mParentBlockStack.empty()) - { - return mParentBlockStack.back().node; - } - return nullptr; -} - -void TIntermTraverser::pushParentBlock(TIntermBlock *node) -{ - mParentBlockStack.push_back(ParentBlock(node, 0)); -} - -void TIntermTraverser::incrementParentBlockPos() -{ - ++mParentBlockStack.back().pos; -} - -void TIntermTraverser::popParentBlock() -{ - ASSERT(!mParentBlockStack.empty()); - mParentBlockStack.pop_back(); -} - -void TIntermTraverser::insertStatementsInParentBlock(const TIntermSequence &insertions) -{ - TIntermSequence emptyInsertionsAfter; - insertStatementsInParentBlock(insertions, emptyInsertionsAfter); -} - -void TIntermTraverser::insertStatementsInParentBlock(const TIntermSequence &insertionsBefore, - const TIntermSequence &insertionsAfter) -{ - ASSERT(!mParentBlockStack.empty()); - ParentBlock &parentBlock = mParentBlockStack.back(); - if (mPath.back() == parentBlock.node) - { - ASSERT(mParentBlockStack.size() >= 2u); - // The current node is a block node, so the parent block is not the topmost one in the block - // stack, but the one below that. - parentBlock = mParentBlockStack.at(mParentBlockStack.size() - 2u); - } - NodeInsertMultipleEntry insert(parentBlock.node, parentBlock.pos, insertionsBefore, - insertionsAfter); - mInsertions.push_back(insert); -} - -void TIntermTraverser::insertStatementInParentBlock(TIntermNode *statement) -{ - TIntermSequence insertions; - insertions.push_back(statement); - insertStatementsInParentBlock(insertions); -} - -TIntermSymbol *TIntermTraverser::createTempSymbol(const TType &type, TQualifier qualifier) -{ - ASSERT(mTemporaryId != nullptr); - // nextTemporaryId() needs to be called when the code wants to start using another temporary - // symbol. - return CreateTempSymbolNode(*mTemporaryId, type, qualifier); -} - -TIntermSymbol *TIntermTraverser::createTempSymbol(const TType &type) -{ - return createTempSymbol(type, EvqTemporary); -} - -TIntermDeclaration *TIntermTraverser::createTempDeclaration(const TType &type) -{ - ASSERT(mTemporaryId != nullptr); - TIntermDeclaration *tempDeclaration = new TIntermDeclaration(); - tempDeclaration->appendDeclarator(CreateTempSymbolNode(*mTemporaryId, type, EvqTemporary)); - return tempDeclaration; -} - -TIntermDeclaration *TIntermTraverser::createTempInitDeclaration(TIntermTyped *initializer, - TQualifier qualifier) -{ - ASSERT(mTemporaryId != nullptr); - return CreateTempInitDeclarationNode(*mTemporaryId, initializer, qualifier); -} - -TIntermDeclaration *TIntermTraverser::createTempInitDeclaration(TIntermTyped *initializer) -{ - return createTempInitDeclaration(initializer, EvqTemporary); -} - -TIntermBinary *TIntermTraverser::createTempAssignment(TIntermTyped *rightNode) -{ - ASSERT(rightNode != nullptr); - TIntermSymbol *tempSymbol = createTempSymbol(rightNode->getType()); - TIntermBinary *assignment = new TIntermBinary(EOpAssign, tempSymbol, rightNode); - return assignment; -} - -void TIntermTraverser::nextTemporaryId() -{ - ASSERT(mSymbolTable); - if (!mTemporaryId) - { - mTemporaryId = new TSymbolUniqueId(mSymbolTable); - return; - } - *mTemporaryId = TSymbolUniqueId(mSymbolTable); -} - -void TLValueTrackingTraverser::addToFunctionMap(const TSymbolUniqueId &id, - TIntermSequence *paramSequence) -{ - mFunctionMap[id.get()] = paramSequence; -} - -bool TLValueTrackingTraverser::isInFunctionMap(const TIntermAggregate *callNode) const -{ - ASSERT(callNode->getOp() == EOpCallFunctionInAST); - return (mFunctionMap.find(callNode->getFunctionSymbolInfo()->getId().get()) != - mFunctionMap.end()); -} - -TIntermSequence *TLValueTrackingTraverser::getFunctionParameters(const TIntermAggregate *callNode) -{ - ASSERT(isInFunctionMap(callNode)); - return mFunctionMap[callNode->getFunctionSymbolInfo()->getId().get()]; -} - -void TLValueTrackingTraverser::setInFunctionCallOutParameter(bool inOutParameter) -{ - mInFunctionCallOutParameter = inOutParameter; -} - -bool TLValueTrackingTraverser::isInFunctionCallOutParameter() const -{ - return mInFunctionCallOutParameter; -} - -// -// 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. -// - -// -// Traversal functions for terminals are straighforward.... -// -void TIntermTraverser::traverseSymbol(TIntermSymbol *node) -{ - ScopedNodeInTraversalPath addToPath(this, node); - visitSymbol(node); -} - -void TIntermTraverser::traverseConstantUnion(TIntermConstantUnion *node) -{ - ScopedNodeInTraversalPath addToPath(this, node); - visitConstantUnion(node); -} - -void TIntermTraverser::traverseSwizzle(TIntermSwizzle *node) -{ - ScopedNodeInTraversalPath addToPath(this, node); - - bool visit = true; - - if (preVisit) - visit = visitSwizzle(PreVisit, node); - - if (visit) - { - node->getOperand()->traverse(this); - } - - if (visit && postVisit) - visitSwizzle(PostVisit, node); -} - -// -// Traverse a binary node. -// -void TIntermTraverser::traverseBinary(TIntermBinary *node) -{ - ScopedNodeInTraversalPath addToPath(this, node); - - bool visit = true; - - // - // visit the node before children if pre-visiting. - // - if (preVisit) - visit = visitBinary(PreVisit, node); - - // - // Visit the children, in the right order. - // - if (visit) - { - if (node->getLeft()) - node->getLeft()->traverse(this); - - if (inVisit) - visit = visitBinary(InVisit, node); - - if (visit && node->getRight()) - node->getRight()->traverse(this); - } - - // - // Visit the node after the children, if requested and the traversal - // hasn't been cancelled yet. - // - if (visit && postVisit) - visitBinary(PostVisit, node); -} - -void TLValueTrackingTraverser::traverseBinary(TIntermBinary *node) -{ - ScopedNodeInTraversalPath addToPath(this, node); - - bool visit = true; - - // - // visit the node before children if pre-visiting. - // - if (preVisit) - visit = visitBinary(PreVisit, node); - - // - // Visit the children, in the right order. - // - if (visit) - { - // Some binary operations like indexing can be inside an expression which must be an - // l-value. - bool parentOperatorRequiresLValue = operatorRequiresLValue(); - bool parentInFunctionCallOutParameter = isInFunctionCallOutParameter(); - if (node->isAssignment()) - { - ASSERT(!isLValueRequiredHere()); - setOperatorRequiresLValue(true); - } - - if (node->getLeft()) - node->getLeft()->traverse(this); - - if (inVisit) - visit = visitBinary(InVisit, node); - - if (node->isAssignment()) - setOperatorRequiresLValue(false); - - // Index is not required to be an l-value even when the surrounding expression is required - // to be an l-value. - TOperator op = node->getOp(); - if (op == EOpIndexDirect || op == EOpIndexDirectInterfaceBlock || - op == EOpIndexDirectStruct || op == EOpIndexIndirect) - { - setOperatorRequiresLValue(false); - setInFunctionCallOutParameter(false); - } - - if (visit && node->getRight()) - node->getRight()->traverse(this); - - setOperatorRequiresLValue(parentOperatorRequiresLValue); - setInFunctionCallOutParameter(parentInFunctionCallOutParameter); - } - - // - // Visit the node after the children, if requested and the traversal - // hasn't been cancelled yet. - // - if (visit && postVisit) - visitBinary(PostVisit, node); -} - -// -// Traverse a unary node. Same comments in binary node apply here. -// -void TIntermTraverser::traverseUnary(TIntermUnary *node) -{ - ScopedNodeInTraversalPath addToPath(this, node); - - bool visit = true; - - if (preVisit) - visit = visitUnary(PreVisit, node); - - if (visit) - { - node->getOperand()->traverse(this); - } - - if (visit && postVisit) - visitUnary(PostVisit, node); -} - -void TLValueTrackingTraverser::traverseUnary(TIntermUnary *node) -{ - ScopedNodeInTraversalPath addToPath(this, node); - - bool visit = true; - - if (preVisit) - visit = visitUnary(PreVisit, node); - - if (visit) - { - ASSERT(!operatorRequiresLValue()); - switch (node->getOp()) - { - case EOpPostIncrement: - case EOpPostDecrement: - case EOpPreIncrement: - case EOpPreDecrement: - setOperatorRequiresLValue(true); - break; - default: - break; - } - - node->getOperand()->traverse(this); - - setOperatorRequiresLValue(false); - } - - if (visit && postVisit) - visitUnary(PostVisit, node); -} - -// Traverse a function definition node. -void TIntermTraverser::traverseFunctionDefinition(TIntermFunctionDefinition *node) -{ - ScopedNodeInTraversalPath addToPath(this, node); - - bool visit = true; - - if (preVisit) - visit = visitFunctionDefinition(PreVisit, node); - - if (visit) - { - mInGlobalScope = false; - - node->getFunctionPrototype()->traverse(this); - if (inVisit) - visit = visitFunctionDefinition(InVisit, node); - node->getBody()->traverse(this); - - mInGlobalScope = true; - } - - if (visit && postVisit) - visitFunctionDefinition(PostVisit, node); -} - -// Traverse a block node. -void TIntermTraverser::traverseBlock(TIntermBlock *node) -{ - ScopedNodeInTraversalPath addToPath(this, node); - pushParentBlock(node); - - bool visit = true; - - TIntermSequence *sequence = node->getSequence(); - - if (preVisit) - visit = visitBlock(PreVisit, node); - - if (visit) - { - for (auto *child : *sequence) - { - child->traverse(this); - if (visit && inVisit) - { - if (child != sequence->back()) - visit = visitBlock(InVisit, node); - } - - incrementParentBlockPos(); - } - } - - if (visit && postVisit) - visitBlock(PostVisit, node); - - popParentBlock(); -} - -void TIntermTraverser::traverseInvariantDeclaration(TIntermInvariantDeclaration *node) -{ - ScopedNodeInTraversalPath addToPath(this, node); - - bool visit = true; - - if (preVisit) - { - visit = visitInvariantDeclaration(PreVisit, node); - } - - if (visit) - { - node->getSymbol()->traverse(this); - if (postVisit) - { - visitInvariantDeclaration(PostVisit, node); - } - } -} - -// Traverse a declaration node. -void TIntermTraverser::traverseDeclaration(TIntermDeclaration *node) -{ - ScopedNodeInTraversalPath addToPath(this, node); - - bool visit = true; - - TIntermSequence *sequence = node->getSequence(); - - if (preVisit) - visit = visitDeclaration(PreVisit, node); - - if (visit) - { - for (auto *child : *sequence) - { - child->traverse(this); - if (visit && inVisit) - { - if (child != sequence->back()) - visit = visitDeclaration(InVisit, node); - } - } - } - - if (visit && postVisit) - visitDeclaration(PostVisit, node); -} - -void TIntermTraverser::traverseFunctionPrototype(TIntermFunctionPrototype *node) -{ - ScopedNodeInTraversalPath addToPath(this, node); - - bool visit = true; - - TIntermSequence *sequence = node->getSequence(); - - if (preVisit) - visit = visitFunctionPrototype(PreVisit, node); - - if (visit) - { - for (auto *child : *sequence) - { - child->traverse(this); - if (visit && inVisit) - { - if (child != sequence->back()) - visit = visitFunctionPrototype(InVisit, node); - } - } - } - - if (visit && postVisit) - visitFunctionPrototype(PostVisit, node); -} - -// Traverse an aggregate node. Same comments in binary node apply here. -void TIntermTraverser::traverseAggregate(TIntermAggregate *node) -{ - ScopedNodeInTraversalPath addToPath(this, node); - - bool visit = true; - - TIntermSequence *sequence = node->getSequence(); - - if (preVisit) - visit = visitAggregate(PreVisit, node); - - if (visit) - { - for (auto *child : *sequence) - { - child->traverse(this); - if (visit && inVisit) - { - if (child != sequence->back()) - visit = visitAggregate(InVisit, node); - } - } - } - - if (visit && postVisit) - visitAggregate(PostVisit, node); -} - -bool TIntermTraverser::CompareInsertion(const NodeInsertMultipleEntry &a, - const NodeInsertMultipleEntry &b) -{ - if (a.parent != b.parent) - { - return a.parent > b.parent; - } - return a.position > b.position; -} - -void TIntermTraverser::updateTree() -{ - // Sort the insertions so that insertion position is decreasing. This way multiple insertions to - // the same parent node are handled correctly. - std::sort(mInsertions.begin(), mInsertions.end(), CompareInsertion); - for (size_t ii = 0; ii < mInsertions.size(); ++ii) - { - // We can't know here what the intended ordering of two insertions to the same position is, - // so it is not supported. - ASSERT(ii == 0 || mInsertions[ii].position != mInsertions[ii - 1].position || - mInsertions[ii].parent != mInsertions[ii - 1].parent); - const NodeInsertMultipleEntry &insertion = mInsertions[ii]; - ASSERT(insertion.parent); - if (!insertion.insertionsAfter.empty()) - { - bool inserted = insertion.parent->insertChildNodes(insertion.position + 1, - insertion.insertionsAfter); - ASSERT(inserted); - } - if (!insertion.insertionsBefore.empty()) - { - bool inserted = - insertion.parent->insertChildNodes(insertion.position, insertion.insertionsBefore); - ASSERT(inserted); - } - } - for (size_t ii = 0; ii < mReplacements.size(); ++ii) - { - const NodeUpdateEntry &replacement = mReplacements[ii]; - ASSERT(replacement.parent); - bool replaced = - replacement.parent->replaceChildNode(replacement.original, replacement.replacement); - ASSERT(replaced); - - if (!replacement.originalBecomesChildOfReplacement) - { - // In AST traversing, a parent is visited before its children. - // After we replace a node, if its immediate child is to - // be replaced, we need to make sure we don't update the replaced - // node; instead, we update the replacement node. - for (size_t jj = ii + 1; jj < mReplacements.size(); ++jj) - { - NodeUpdateEntry &replacement2 = mReplacements[jj]; - if (replacement2.parent == replacement.original) - replacement2.parent = replacement.replacement; - } - } - } - for (size_t ii = 0; ii < mMultiReplacements.size(); ++ii) - { - const NodeReplaceWithMultipleEntry &replacement = mMultiReplacements[ii]; - ASSERT(replacement.parent); - bool replaced = replacement.parent->replaceChildNodeWithMultiple(replacement.original, - replacement.replacements); - ASSERT(replaced); - } - - clearReplacementQueue(); -} - -void TIntermTraverser::clearReplacementQueue() -{ - mReplacements.clear(); - mMultiReplacements.clear(); - mInsertions.clear(); -} - -void TIntermTraverser::queueReplacement(TIntermNode *replacement, OriginalNode originalStatus) -{ - queueReplacementWithParent(getParentNode(), mPath.back(), replacement, originalStatus); -} - -void TIntermTraverser::queueReplacementWithParent(TIntermNode *parent, - TIntermNode *original, - TIntermNode *replacement, - OriginalNode originalStatus) -{ - bool originalBecomesChild = (originalStatus == OriginalNode::BECOMES_CHILD); - mReplacements.push_back(NodeUpdateEntry(parent, original, replacement, originalBecomesChild)); -} - -TLValueTrackingTraverser::TLValueTrackingTraverser(bool preVisit, - bool inVisit, - bool postVisit, - TSymbolTable *symbolTable, - int shaderVersion) - : TIntermTraverser(preVisit, inVisit, postVisit, symbolTable), - mOperatorRequiresLValue(false), - mInFunctionCallOutParameter(false), - mShaderVersion(shaderVersion) -{ - ASSERT(symbolTable); -} - -void TLValueTrackingTraverser::traverseFunctionPrototype(TIntermFunctionPrototype *node) -{ - TIntermSequence *sequence = node->getSequence(); - addToFunctionMap(node->getFunctionSymbolInfo()->getId(), sequence); - - TIntermTraverser::traverseFunctionPrototype(node); -} - -void TLValueTrackingTraverser::traverseAggregate(TIntermAggregate *node) -{ - ScopedNodeInTraversalPath addToPath(this, node); - - bool visit = true; - - TIntermSequence *sequence = node->getSequence(); - - if (preVisit) - visit = visitAggregate(PreVisit, node); - - if (visit) - { - if (node->getOp() == EOpCallFunctionInAST) - { - if (isInFunctionMap(node)) - { - TIntermSequence *params = getFunctionParameters(node); - TIntermSequence::iterator paramIter = params->begin(); - for (auto *child : *sequence) - { - ASSERT(paramIter != params->end()); - TQualifier qualifier = (*paramIter)->getAsTyped()->getQualifier(); - setInFunctionCallOutParameter(qualifier == EvqOut || qualifier == EvqInOut); - - child->traverse(this); - if (visit && inVisit) - { - if (child != sequence->back()) - visit = visitAggregate(InVisit, node); - } - - ++paramIter; - } - } - else - { - // The node might not be in the function map in case we're in the middle of - // transforming the AST, and have inserted function call nodes without inserting the - // function definitions yet. - setInFunctionCallOutParameter(false); - for (auto *child : *sequence) - { - child->traverse(this); - if (visit && inVisit) - { - if (child != sequence->back()) - visit = visitAggregate(InVisit, node); - } - } - } - - setInFunctionCallOutParameter(false); - } - else - { - // Find the built-in function corresponding to this op so that we can determine the - // in/out qualifiers of its parameters. - TFunction *builtInFunc = nullptr; - if (!node->isFunctionCall() && !node->isConstructor()) - { - builtInFunc = static_cast( - mSymbolTable->findBuiltIn(node->getSymbolTableMangledName(), mShaderVersion)); - } - - size_t paramIndex = 0; - - for (auto *child : *sequence) - { - // This assumes that raw functions called with - // EOpCallInternalRawFunction don't have out parameters. - TQualifier qualifier = EvqIn; - if (builtInFunc != nullptr) - qualifier = builtInFunc->getParam(paramIndex).type->getQualifier(); - setInFunctionCallOutParameter(qualifier == EvqOut || qualifier == EvqInOut); - child->traverse(this); - - if (visit && inVisit) - { - if (child != sequence->back()) - visit = visitAggregate(InVisit, node); - } - - ++paramIndex; - } - - setInFunctionCallOutParameter(false); - } - } - - if (visit && postVisit) - visitAggregate(PostVisit, node); -} - -// -// Traverse a ternary node. Same comments in binary node apply here. -// -void TIntermTraverser::traverseTernary(TIntermTernary *node) -{ - ScopedNodeInTraversalPath addToPath(this, node); - - bool visit = true; - - if (preVisit) - visit = visitTernary(PreVisit, node); - - if (visit) - { - node->getCondition()->traverse(this); - if (node->getTrueExpression()) - node->getTrueExpression()->traverse(this); - if (node->getFalseExpression()) - node->getFalseExpression()->traverse(this); - } - - if (visit && postVisit) - visitTernary(PostVisit, node); -} - -// Traverse an if-else node. Same comments in binary node apply here. -void TIntermTraverser::traverseIfElse(TIntermIfElse *node) -{ - ScopedNodeInTraversalPath addToPath(this, node); - - bool visit = true; - - if (preVisit) - visit = visitIfElse(PreVisit, node); - - if (visit) - { - node->getCondition()->traverse(this); - if (node->getTrueBlock()) - node->getTrueBlock()->traverse(this); - if (node->getFalseBlock()) - node->getFalseBlock()->traverse(this); - } - - if (visit && postVisit) - visitIfElse(PostVisit, node); -} - -// -// Traverse a switch node. Same comments in binary node apply here. -// -void TIntermTraverser::traverseSwitch(TIntermSwitch *node) -{ - ScopedNodeInTraversalPath addToPath(this, node); - - bool visit = true; - - if (preVisit) - visit = visitSwitch(PreVisit, node); - - if (visit) - { - node->getInit()->traverse(this); - if (inVisit) - visit = visitSwitch(InVisit, node); - if (visit && node->getStatementList()) - node->getStatementList()->traverse(this); - } - - if (visit && postVisit) - visitSwitch(PostVisit, node); -} - -// -// Traverse a case node. Same comments in binary node apply here. -// -void TIntermTraverser::traverseCase(TIntermCase *node) -{ - ScopedNodeInTraversalPath addToPath(this, node); - - bool visit = true; - - if (preVisit) - visit = visitCase(PreVisit, node); - - if (visit && node->getCondition()) - { - node->getCondition()->traverse(this); - } - - if (visit && postVisit) - visitCase(PostVisit, node); -} - -// -// Traverse a loop node. Same comments in binary node apply here. -// -void TIntermTraverser::traverseLoop(TIntermLoop *node) -{ - ScopedNodeInTraversalPath addToPath(this, node); - - bool visit = true; - - if (preVisit) - visit = visitLoop(PreVisit, node); - - if (visit) - { - if (node->getInit()) - node->getInit()->traverse(this); - - if (node->getCondition()) - node->getCondition()->traverse(this); - - if (node->getBody()) - node->getBody()->traverse(this); - - if (node->getExpression()) - node->getExpression()->traverse(this); - } - - if (visit && postVisit) - visitLoop(PostVisit, node); -} - -// -// Traverse a branch node. Same comments in binary node apply here. -// -void TIntermTraverser::traverseBranch(TIntermBranch *node) -{ - ScopedNodeInTraversalPath addToPath(this, node); - - bool visit = true; - - if (preVisit) - visit = visitBranch(PreVisit, node); - - if (visit && node->getExpression()) - { - node->getExpression()->traverse(this); - } - - if (visit && postVisit) - visitBranch(PostVisit, node); -} - -void TIntermTraverser::traverseRaw(TIntermRaw *node) -{ - ScopedNodeInTraversalPath addToPath(this, node); - visitRaw(node); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/IntermTraverse.h b/src/3rdparty/angle/src/compiler/translator/IntermTraverse.h deleted file mode 100644 index f0300b586b..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/IntermTraverse.h +++ /dev/null @@ -1,355 +0,0 @@ -// -// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// IntermTraverse.h : base classes for AST traversers that walk the AST and -// also have the ability to transform it by replacing nodes. - -#ifndef COMPILER_TRANSLATOR_INTERMTRAVERSE_H_ -#define COMPILER_TRANSLATOR_INTERMTRAVERSE_H_ - -#include "compiler/translator/IntermNode.h" - -namespace sh -{ - -class TSymbolTable; -class TSymbolUniqueId; - -enum Visit -{ - PreVisit, - InVisit, - PostVisit -}; - -// For traversing the tree. User should derive from this class overriding the visit functions, -// and then pass an object of the subclass to a traverse method of a node. -// -// The traverse*() functions may also be overridden to do other bookkeeping on the tree to provide -// contextual information to the visit functions, such as whether the node is the target of an -// assignment. This is complex to maintain and so should only be done in special cases. -// -// 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. -class TIntermTraverser : angle::NonCopyable -{ - public: - POOL_ALLOCATOR_NEW_DELETE(); - TIntermTraverser(bool preVisit, - bool inVisit, - bool postVisit, - TSymbolTable *symbolTable = nullptr); - virtual ~TIntermTraverser(); - - virtual void visitSymbol(TIntermSymbol *node) {} - virtual void visitRaw(TIntermRaw *node) {} - virtual void visitConstantUnion(TIntermConstantUnion *node) {} - virtual bool visitSwizzle(Visit visit, TIntermSwizzle *node) { return true; } - virtual bool visitBinary(Visit visit, TIntermBinary *node) { return true; } - virtual bool visitUnary(Visit visit, TIntermUnary *node) { return true; } - virtual bool visitTernary(Visit visit, TIntermTernary *node) { return true; } - virtual bool visitIfElse(Visit visit, TIntermIfElse *node) { return true; } - virtual bool visitSwitch(Visit visit, TIntermSwitch *node) { return true; } - virtual bool visitCase(Visit visit, TIntermCase *node) { return true; } - virtual bool visitFunctionPrototype(Visit visit, TIntermFunctionPrototype *node) - { - return true; - } - virtual bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) - { - return true; - } - virtual bool visitAggregate(Visit visit, TIntermAggregate *node) { return true; } - virtual bool visitBlock(Visit visit, TIntermBlock *node) { return true; } - virtual bool visitInvariantDeclaration(Visit visit, TIntermInvariantDeclaration *node) - { - return true; - } - virtual bool visitDeclaration(Visit visit, TIntermDeclaration *node) { return true; } - virtual bool visitLoop(Visit visit, TIntermLoop *node) { return true; } - virtual bool visitBranch(Visit visit, TIntermBranch *node) { return true; } - - // The traverse functions contain logic for iterating over the children of the node - // and calling the visit functions in the appropriate places. They also track some - // context that may be used by the visit functions. - virtual void traverseSymbol(TIntermSymbol *node); - virtual void traverseRaw(TIntermRaw *node); - virtual void traverseConstantUnion(TIntermConstantUnion *node); - virtual void traverseSwizzle(TIntermSwizzle *node); - virtual void traverseBinary(TIntermBinary *node); - virtual void traverseUnary(TIntermUnary *node); - virtual void traverseTernary(TIntermTernary *node); - virtual void traverseIfElse(TIntermIfElse *node); - virtual void traverseSwitch(TIntermSwitch *node); - virtual void traverseCase(TIntermCase *node); - virtual void traverseFunctionPrototype(TIntermFunctionPrototype *node); - virtual void traverseFunctionDefinition(TIntermFunctionDefinition *node); - virtual void traverseAggregate(TIntermAggregate *node); - virtual void traverseBlock(TIntermBlock *node); - virtual void traverseInvariantDeclaration(TIntermInvariantDeclaration *node); - virtual void traverseDeclaration(TIntermDeclaration *node); - virtual void traverseLoop(TIntermLoop *node); - virtual void traverseBranch(TIntermBranch *node); - - int getMaxDepth() const { return mMaxDepth; } - - // If traversers need to replace nodes, they can add the replacements in - // mReplacements/mMultiReplacements during traversal and the user of the traverser should call - // this function after traversal to perform them. - void updateTree(); - - protected: - // Should only be called from traverse*() functions - void incrementDepth(TIntermNode *current) - { - mDepth++; - mMaxDepth = std::max(mMaxDepth, mDepth); - mPath.push_back(current); - } - - // Should only be called from traverse*() functions - void decrementDepth() - { - mDepth--; - mPath.pop_back(); - } - - // RAII helper for incrementDepth/decrementDepth - class ScopedNodeInTraversalPath - { - public: - ScopedNodeInTraversalPath(TIntermTraverser *traverser, TIntermNode *current) - : mTraverser(traverser) - { - mTraverser->incrementDepth(current); - } - ~ScopedNodeInTraversalPath() { mTraverser->decrementDepth(); } - - private: - TIntermTraverser *mTraverser; - }; - - TIntermNode *getParentNode() { return mPath.size() <= 1 ? nullptr : mPath[mPath.size() - 2u]; } - - // Return the nth ancestor of the node being traversed. getAncestorNode(0) == getParentNode() - TIntermNode *getAncestorNode(unsigned int n) - { - if (mPath.size() > n + 1u) - { - return mPath[mPath.size() - n - 2u]; - } - return nullptr; - } - - const TIntermBlock *getParentBlock() const; - - void pushParentBlock(TIntermBlock *node); - void incrementParentBlockPos(); - void popParentBlock(); - - // To replace a single node with multiple nodes in the parent aggregate. May be used with blocks - // but also with other nodes like declarations. - struct NodeReplaceWithMultipleEntry - { - NodeReplaceWithMultipleEntry(TIntermAggregateBase *_parent, - TIntermNode *_original, - TIntermSequence _replacements) - : parent(_parent), original(_original), replacements(_replacements) - { - } - - TIntermAggregateBase *parent; - TIntermNode *original; - TIntermSequence replacements; - }; - - // Helper to insert statements in the parent block of the node currently being traversed. - // The statements will be inserted before the node being traversed once updateTree is called. - // Should only be called during PreVisit or PostVisit if called from block nodes. - // Note that two insertions to the same position in the same block are not supported. - void insertStatementsInParentBlock(const TIntermSequence &insertions); - - // Same as above, but supports simultaneous insertion of statements before and after the node - // currently being traversed. - void insertStatementsInParentBlock(const TIntermSequence &insertionsBefore, - const TIntermSequence &insertionsAfter); - - // Helper to insert a single statement. - void insertStatementInParentBlock(TIntermNode *statement); - - // Helper to create a temporary symbol node with the given qualifier. - TIntermSymbol *createTempSymbol(const TType &type, TQualifier qualifier); - // Helper to create a temporary symbol node. - TIntermSymbol *createTempSymbol(const TType &type); - // Create a node that declares but doesn't initialize a temporary symbol. - TIntermDeclaration *createTempDeclaration(const TType &type); - // Create a node that initializes the current temporary symbol with initializer. The symbol will - // have the given qualifier. - TIntermDeclaration *createTempInitDeclaration(TIntermTyped *initializer, TQualifier qualifier); - // Create a node that initializes the current temporary symbol with initializer. - TIntermDeclaration *createTempInitDeclaration(TIntermTyped *initializer); - // Create a node that assigns rightNode to the current temporary symbol. - TIntermBinary *createTempAssignment(TIntermTyped *rightNode); - // Increment temporary symbol index. - void nextTemporaryId(); - - enum class OriginalNode - { - BECOMES_CHILD, - IS_DROPPED - }; - - void clearReplacementQueue(); - - // Replace the node currently being visited with replacement. - void queueReplacement(TIntermNode *replacement, OriginalNode originalStatus); - // Explicitly specify a node to replace with replacement. - void queueReplacementWithParent(TIntermNode *parent, - TIntermNode *original, - TIntermNode *replacement, - OriginalNode originalStatus); - - const bool preVisit; - const bool inVisit; - const bool postVisit; - - int mDepth; - int mMaxDepth; - - bool mInGlobalScope; - - // During traversing, save all the changes that need to happen into - // mReplacements/mMultiReplacements, then do them by calling updateTree(). - // Multi replacements are processed after single replacements. - std::vector mMultiReplacements; - - TSymbolTable *mSymbolTable; - - private: - // To insert multiple nodes into the parent block. - struct NodeInsertMultipleEntry - { - NodeInsertMultipleEntry(TIntermBlock *_parent, - TIntermSequence::size_type _position, - TIntermSequence _insertionsBefore, - TIntermSequence _insertionsAfter) - : parent(_parent), - position(_position), - insertionsBefore(_insertionsBefore), - insertionsAfter(_insertionsAfter) - { - } - - TIntermBlock *parent; - TIntermSequence::size_type position; - TIntermSequence insertionsBefore; - TIntermSequence insertionsAfter; - }; - - static bool CompareInsertion(const NodeInsertMultipleEntry &a, - const NodeInsertMultipleEntry &b); - - // To replace a single node with another on the parent node - struct NodeUpdateEntry - { - NodeUpdateEntry(TIntermNode *_parent, - TIntermNode *_original, - TIntermNode *_replacement, - bool _originalBecomesChildOfReplacement) - : parent(_parent), - original(_original), - replacement(_replacement), - originalBecomesChildOfReplacement(_originalBecomesChildOfReplacement) - { - } - - TIntermNode *parent; - TIntermNode *original; - TIntermNode *replacement; - bool originalBecomesChildOfReplacement; - }; - - struct ParentBlock - { - ParentBlock(TIntermBlock *nodeIn, TIntermSequence::size_type posIn) - : node(nodeIn), pos(posIn) - { - } - - TIntermBlock *node; - TIntermSequence::size_type pos; - }; - - std::vector mInsertions; - std::vector mReplacements; - - // All the nodes from root to the current node during traversing. - TVector mPath; - - // All the code blocks from the root to the current node's parent during traversal. - std::vector mParentBlockStack; - - TSymbolUniqueId *mTemporaryId; -}; - -// Traverser parent class that tracks where a node is a destination of a write operation and so is -// required to be an l-value. -class TLValueTrackingTraverser : public TIntermTraverser -{ - public: - TLValueTrackingTraverser(bool preVisit, - bool inVisit, - bool postVisit, - TSymbolTable *symbolTable, - int shaderVersion); - virtual ~TLValueTrackingTraverser() {} - - void traverseBinary(TIntermBinary *node) final; - void traverseUnary(TIntermUnary *node) final; - void traverseFunctionPrototype(TIntermFunctionPrototype *node) final; - void traverseAggregate(TIntermAggregate *node) final; - - protected: - bool isLValueRequiredHere() const - { - return mOperatorRequiresLValue || mInFunctionCallOutParameter; - } - - private: - // Track whether an l-value is required in the node that is currently being traversed by the - // surrounding operator. - // Use isLValueRequiredHere to check all conditions which require an l-value. - void setOperatorRequiresLValue(bool lValueRequired) - { - mOperatorRequiresLValue = lValueRequired; - } - bool operatorRequiresLValue() const { return mOperatorRequiresLValue; } - - // Add a function encountered during traversal to the function map. - void addToFunctionMap(const TSymbolUniqueId &id, TIntermSequence *paramSequence); - - // Return true if the prototype or definition of the function being called has been encountered - // during traversal. - bool isInFunctionMap(const TIntermAggregate *callNode) const; - - // Return the parameters sequence from the function definition or prototype. - TIntermSequence *getFunctionParameters(const TIntermAggregate *callNode); - - // Track whether an l-value is required inside a function call. - void setInFunctionCallOutParameter(bool inOutParameter); - bool isInFunctionCallOutParameter() const; - - bool mOperatorRequiresLValue; - bool mInFunctionCallOutParameter; - - // Map from function symbol id values to their parameter sequences - TMap mFunctionMap; - - const int mShaderVersion; -}; - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_INTERMTRAVERSE_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/IsASTDepthBelowLimit.cpp b/src/3rdparty/angle/src/compiler/translator/IsASTDepthBelowLimit.cpp deleted file mode 100644 index aaad4f3c68..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/IsASTDepthBelowLimit.cpp +++ /dev/null @@ -1,51 +0,0 @@ -// -// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/translator/IsASTDepthBelowLimit.h" - -#include "compiler/translator/IntermTraverse.h" - -namespace sh -{ - -namespace -{ - -// Traverse the tree and compute max depth. Takes a maximum depth limit to prevent stack overflow. -class MaxDepthTraverser : public TIntermTraverser -{ - public: - MaxDepthTraverser(int depthLimit) : TIntermTraverser(true, true, false), mDepthLimit(depthLimit) - { - } - - bool visitBinary(Visit, TIntermBinary *) override { return depthCheck(); } - bool visitUnary(Visit, TIntermUnary *) override { return depthCheck(); } - bool visitTernary(Visit, TIntermTernary *) override { return depthCheck(); } - bool visitSwizzle(Visit, TIntermSwizzle *) override { return depthCheck(); } - bool visitIfElse(Visit, TIntermIfElse *) override { return depthCheck(); } - bool visitAggregate(Visit, TIntermAggregate *) override { return depthCheck(); } - bool visitBlock(Visit, TIntermBlock *) override { return depthCheck(); } - bool visitLoop(Visit, TIntermLoop *) override { return depthCheck(); } - bool visitBranch(Visit, TIntermBranch *) override { return depthCheck(); } - - protected: - bool depthCheck() const { return mMaxDepth < mDepthLimit; } - - int mDepthLimit; -}; - -} // anonymous namespace - -bool IsASTDepthBelowLimit(TIntermNode *root, int maxDepth) -{ - MaxDepthTraverser traverser(maxDepth + 1); - root->traverse(&traverser); - - return traverser.getMaxDepth() <= maxDepth; -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/IsASTDepthBelowLimit.h b/src/3rdparty/angle/src/compiler/translator/IsASTDepthBelowLimit.h deleted file mode 100644 index ef2f02c974..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/IsASTDepthBelowLimit.h +++ /dev/null @@ -1,20 +0,0 @@ -// -// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// IsASTDepthBelowLimit: Check whether AST depth is below a specific limit. - -#ifndef COMPILER_TRANSLATOR_ISASTDEPTHBELOWLIMIT_H_ -#define COMPILER_TRANSLATOR_ISASTDEPTHBELOWLIMIT_H_ - -namespace sh -{ - -class TIntermNode; - -bool IsASTDepthBelowLimit(TIntermNode *root, int maxDepth); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_ISASTDEPTHBELOWLIMIT_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/NodeSearch.h b/src/3rdparty/angle/src/compiler/translator/NodeSearch.h deleted file mode 100644 index af86b8bde4..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/NodeSearch.h +++ /dev/null @@ -1,56 +0,0 @@ -// -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// NodeSearch.h: Utilities for searching translator node graphs -// - -#ifndef COMPILER_TRANSLATOR_NODESEARCH_H_ -#define COMPILER_TRANSLATOR_NODESEARCH_H_ - -#include "compiler/translator/IntermTraverse.h" - -namespace sh -{ - -template -class NodeSearchTraverser : public TIntermTraverser -{ - public: - NodeSearchTraverser() : TIntermTraverser(true, false, false), mFound(false) {} - - bool found() const { return mFound; } - - static bool search(TIntermNode *node) - { - Parent searchTraverser; - node->traverse(&searchTraverser); - return searchTraverser.found(); - } - - protected: - bool mFound; -}; - -class FindDiscard : public NodeSearchTraverser -{ - public: - virtual bool visitBranch(Visit visit, TIntermBranch *node) - { - switch (node->getFlowOp()) - { - case EOpKill: - mFound = true; - break; - - default: - break; - } - - return !mFound; - } -}; -} - -#endif // COMPILER_TRANSLATOR_NODESEARCH_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/Operator.cpp b/src/3rdparty/angle/src/compiler/translator/Operator.cpp deleted file mode 100644 index 7a2156611a..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/Operator.cpp +++ /dev/null @@ -1,385 +0,0 @@ -// -// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/translator/Operator.h" - -const char *GetOperatorString(TOperator op) -{ - switch (op) - { - // Note: EOpNull and EOpCall* can't be handled here. - - case EOpNegative: - return "-"; - case EOpPositive: - return "+"; - case EOpLogicalNot: - return "!"; - case EOpBitwiseNot: - return "~"; - - case EOpPostIncrement: - return "++"; - case EOpPostDecrement: - return "--"; - case EOpPreIncrement: - return "++"; - case EOpPreDecrement: - return "--"; - - case EOpArrayLength: - return ".length()"; - - case EOpAdd: - return "+"; - case EOpSub: - return "-"; - case EOpMul: - return "*"; - case EOpDiv: - return "/"; - case EOpIMod: - return "%"; - - case EOpEqual: - return "=="; - case EOpNotEqual: - return "!="; - case EOpLessThan: - return "<"; - case EOpGreaterThan: - return ">"; - case EOpLessThanEqual: - return "<="; - case EOpGreaterThanEqual: - return ">="; - - case EOpEqualComponentWise: - return "equal"; - case EOpNotEqualComponentWise: - return "notEqual"; - case EOpLessThanComponentWise: - return "lessThan"; - case EOpGreaterThanComponentWise: - return "greaterThan"; - case EOpLessThanEqualComponentWise: - return "lessThanEqual"; - case EOpGreaterThanEqualComponentWise: - return "greaterThanEqual"; - - case EOpComma: - return ","; - - // Fall-through. - case EOpVectorTimesScalar: - case EOpVectorTimesMatrix: - case EOpMatrixTimesVector: - case EOpMatrixTimesScalar: - case EOpMatrixTimesMatrix: - return "*"; - - case EOpLogicalOr: - return "||"; - case EOpLogicalXor: - return "^^"; - case EOpLogicalAnd: - return "&&"; - - case EOpBitShiftLeft: - return "<<"; - case EOpBitShiftRight: - return ">>"; - - case EOpBitwiseAnd: - return "&"; - case EOpBitwiseXor: - return "^"; - case EOpBitwiseOr: - return "|"; - - // Fall-through. - case EOpIndexDirect: - case EOpIndexIndirect: - return "[]"; - - case EOpIndexDirectStruct: - case EOpIndexDirectInterfaceBlock: - return "."; - - case EOpRadians: - return "radians"; - case EOpDegrees: - return "degrees"; - case EOpSin: - return "sin"; - case EOpCos: - return "cos"; - case EOpTan: - return "tan"; - case EOpAsin: - return "asin"; - case EOpAcos: - return "acos"; - case EOpAtan: - return "atan"; - - case EOpSinh: - return "sinh"; - case EOpCosh: - return "cosh"; - case EOpTanh: - return "tanh"; - case EOpAsinh: - return "asinh"; - case EOpAcosh: - return "acosh"; - case EOpAtanh: - return "atanh"; - - case EOpPow: - return "pow"; - case EOpExp: - return "exp"; - case EOpLog: - return "log"; - case EOpExp2: - return "exp2"; - case EOpLog2: - return "log2"; - case EOpSqrt: - return "sqrt"; - case EOpInverseSqrt: - return "inversesqrt"; - - case EOpAbs: - return "abs"; - case EOpSign: - return "sign"; - case EOpFloor: - return "floor"; - case EOpTrunc: - return "trunc"; - case EOpRound: - return "round"; - case EOpRoundEven: - return "roundEven"; - case EOpCeil: - return "ceil"; - case EOpFract: - return "fract"; - case EOpMod: - return "mod"; - case EOpModf: - return "modf"; - case EOpMin: - return "min"; - case EOpMax: - return "max"; - case EOpClamp: - return "clamp"; - case EOpMix: - return "mix"; - case EOpStep: - return "step"; - case EOpSmoothStep: - return "smoothstep"; - case EOpIsNan: - return "isnan"; - case EOpIsInf: - return "isinf"; - - case EOpFloatBitsToInt: - return "floatBitsToInt"; - case EOpFloatBitsToUint: - return "floatBitsToUint"; - case EOpIntBitsToFloat: - return "intBitsToFloat"; - case EOpUintBitsToFloat: - return "uintBitsToFloat"; - - case EOpFrexp: - return "frexp"; - case EOpLdexp: - return "ldexp"; - - case EOpPackSnorm2x16: - return "packSnorm2x16"; - case EOpPackUnorm2x16: - return "packUnorm2x16"; - case EOpPackHalf2x16: - return "packHalf2x16"; - case EOpUnpackSnorm2x16: - return "unpackSnorm2x16"; - case EOpUnpackUnorm2x16: - return "unpackUnorm2x16"; - case EOpUnpackHalf2x16: - return "unpackHalf2x16"; - - case EOpPackUnorm4x8: - return "packUnorm4x8"; - case EOpPackSnorm4x8: - return "packSnorm4x8"; - case EOpUnpackUnorm4x8: - return "unpackUnorm4x8"; - case EOpUnpackSnorm4x8: - return "unpackSnorm4x8"; - - case EOpLength: - return "length"; - case EOpDistance: - return "distance"; - case EOpDot: - return "dot"; - case EOpCross: - return "cross"; - case EOpNormalize: - return "normalize"; - case EOpFaceforward: - return "faceforward"; - case EOpReflect: - return "reflect"; - case EOpRefract: - return "refract"; - - case EOpDFdx: - return "dFdx"; - case EOpDFdy: - return "dFdy"; - case EOpFwidth: - return "fwidth"; - - case EOpMulMatrixComponentWise: - return "matrixCompMult"; - case EOpOuterProduct: - return "outerProduct"; - case EOpTranspose: - return "transpose"; - case EOpDeterminant: - return "determinant"; - case EOpInverse: - return "inverse"; - - case EOpAny: - return "any"; - case EOpAll: - return "all"; - case EOpLogicalNotComponentWise: - return "not"; - - case EOpBitfieldExtract: - return "bitfieldExtract"; - case EOpBitfieldInsert: - return "bitfieldInsert"; - case EOpBitfieldReverse: - return "bitfieldReverse"; - case EOpBitCount: - return "bitCount"; - case EOpFindLSB: - return "findLSB"; - case EOpFindMSB: - return "findMSB"; - case EOpUaddCarry: - return "uaddCarry"; - case EOpUsubBorrow: - return "usubBorrow"; - case EOpUmulExtended: - return "umulExtended"; - case EOpImulExtended: - return "imulExtended"; - - case EOpKill: - return "kill"; - case EOpReturn: - return "return"; - case EOpBreak: - return "break"; - case EOpContinue: - return "continue"; - - case EOpAssign: - return "="; - case EOpInitialize: - return "="; - case EOpAddAssign: - return "+="; - case EOpSubAssign: - return "-="; - - // Fall-through. - case EOpMulAssign: - case EOpVectorTimesMatrixAssign: - case EOpVectorTimesScalarAssign: - case EOpMatrixTimesScalarAssign: - case EOpMatrixTimesMatrixAssign: - return "*="; - - case EOpDivAssign: - return "/="; - case EOpIModAssign: - return "%="; - case EOpBitShiftLeftAssign: - return "<<="; - case EOpBitShiftRightAssign: - return ">>="; - case EOpBitwiseAndAssign: - return "&="; - case EOpBitwiseXorAssign: - return "^="; - case EOpBitwiseOrAssign: - return "|="; - case EOpBarrier: - return "barrier"; - case EOpMemoryBarrier: - return "memoryBarrier"; - case EOpMemoryBarrierAtomicCounter: - return "memoryBarrierAtomicCounter"; - case EOpMemoryBarrierBuffer: - return "memoryBarrierBuffer"; - case EOpMemoryBarrierImage: - return "memoryBarrierImage"; - case EOpMemoryBarrierShared: - return "memoryBarrierShared"; - case EOpGroupMemoryBarrier: - return "groupMemoryBarrier"; - - case EOpEmitVertex: - return "EmitVertex"; - case EOpEndPrimitive: - return "EndPrimitive"; - default: - break; - } - return ""; -} - -bool IsAssignment(TOperator op) -{ - 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 EOpIModAssign: - case EOpBitShiftLeftAssign: - case EOpBitShiftRightAssign: - case EOpBitwiseAndAssign: - case EOpBitwiseXorAssign: - case EOpBitwiseOrAssign: - return true; - default: - return false; - } -} \ No newline at end of file diff --git a/src/3rdparty/angle/src/compiler/translator/Operator.h b/src/3rdparty/angle/src/compiler/translator/Operator.h deleted file mode 100644 index 72f3dbf3f6..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/Operator.h +++ /dev/null @@ -1,255 +0,0 @@ -// -// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_TRANSLATOR_OPERATOR_H_ -#define COMPILER_TRANSLATOR_OPERATOR_H_ - -// -// 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 - - // Call a function defined in the AST. This might be a user-defined function or a function - // inserted by an AST transformation. - EOpCallFunctionInAST, - - // Call an internal helper function with a raw implementation - the implementation can't be - // subject to AST transformations. Raw functions have a few constraints to keep them compatible - // with AST traversers: - // * They should not return arrays. - // * They should not have out parameters. - EOpCallInternalRawFunction, - - // Call a built-in function like a texture or image function. - EOpCallBuiltInFunction, - - // - // Unary operators - // - - EOpNegative, - EOpPositive, - EOpLogicalNot, - EOpBitwiseNot, - - EOpPostIncrement, - EOpPostDecrement, - EOpPreIncrement, - EOpPreDecrement, - - EOpArrayLength, - - // - // binary operations (ones with special GLSL syntax are used in TIntermBinary nodes, others in - // TIntermAggregate nodes) - // - - EOpAdd, - EOpSub, - EOpMul, - EOpDiv, - EOpIMod, - - EOpEqual, - EOpNotEqual, - EOpLessThan, - EOpGreaterThan, - EOpLessThanEqual, - EOpGreaterThanEqual, - - EOpEqualComponentWise, - EOpNotEqualComponentWise, - EOpLessThanComponentWise, - EOpLessThanEqualComponentWise, - EOpGreaterThanComponentWise, - EOpGreaterThanEqualComponentWise, - - EOpComma, - - EOpVectorTimesScalar, - EOpVectorTimesMatrix, - EOpMatrixTimesVector, - EOpMatrixTimesScalar, - EOpMatrixTimesMatrix, - - EOpLogicalOr, - EOpLogicalXor, - EOpLogicalAnd, - - EOpBitShiftLeft, - EOpBitShiftRight, - - EOpBitwiseAnd, - EOpBitwiseXor, - EOpBitwiseOr, - - EOpIndexDirect, - EOpIndexIndirect, - EOpIndexDirectStruct, - EOpIndexDirectInterfaceBlock, - - // - // Built-in functions mapped to operators (either unary or with multiple parameters) - // - - 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, - EOpMod, - EOpModf, - EOpMin, - EOpMax, - EOpClamp, - EOpMix, - EOpStep, - EOpSmoothStep, - EOpIsNan, - EOpIsInf, - - EOpFloatBitsToInt, - EOpFloatBitsToUint, - EOpIntBitsToFloat, - EOpUintBitsToFloat, - - EOpFrexp, - EOpLdexp, - - EOpPackSnorm2x16, - EOpPackUnorm2x16, - EOpPackHalf2x16, - EOpUnpackSnorm2x16, - EOpUnpackUnorm2x16, - EOpUnpackHalf2x16, - - EOpPackUnorm4x8, - EOpPackSnorm4x8, - EOpUnpackUnorm4x8, - EOpUnpackSnorm4x8, - - EOpLength, - EOpDistance, - EOpDot, - EOpCross, - EOpNormalize, - EOpFaceforward, - EOpReflect, - EOpRefract, - - EOpDFdx, // Fragment only, OES_standard_derivatives extension - EOpDFdy, // Fragment only, OES_standard_derivatives extension - EOpFwidth, // Fragment only, OES_standard_derivatives extension - - EOpMulMatrixComponentWise, - EOpOuterProduct, - EOpTranspose, - EOpDeterminant, - EOpInverse, - - EOpAny, - EOpAll, - EOpLogicalNotComponentWise, - - EOpBitfieldExtract, - EOpBitfieldInsert, - EOpBitfieldReverse, - EOpBitCount, - EOpFindLSB, - EOpFindMSB, - EOpUaddCarry, - EOpUsubBorrow, - EOpUmulExtended, - EOpImulExtended, - - // - // Branch - // - - EOpKill, // Fragment only - EOpReturn, - EOpBreak, - EOpContinue, - - // - // Constructor - // - - EOpConstruct, - - // - // moves - // - - EOpAssign, - EOpInitialize, - EOpAddAssign, - EOpSubAssign, - - EOpMulAssign, - EOpVectorTimesMatrixAssign, - EOpVectorTimesScalarAssign, - EOpMatrixTimesScalarAssign, - EOpMatrixTimesMatrixAssign, - - EOpDivAssign, - EOpIModAssign, - EOpBitShiftLeftAssign, - EOpBitShiftRightAssign, - EOpBitwiseAndAssign, - EOpBitwiseXorAssign, - EOpBitwiseOrAssign, - - // barriers - EOpBarrier, - EOpMemoryBarrier, - EOpMemoryBarrierAtomicCounter, - EOpMemoryBarrierBuffer, - EOpMemoryBarrierImage, - EOpMemoryBarrierShared, - EOpGroupMemoryBarrier, - - // Geometry only - EOpEmitVertex, - EOpEndPrimitive -}; - -// Returns the string corresponding to the operator in GLSL -const char *GetOperatorString(TOperator op); - -// Say whether or not a binary or unary operation changes the value of a variable. -bool IsAssignment(TOperator op); - -#endif // COMPILER_TRANSLATOR_OPERATOR_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/OutputESSL.cpp b/src/3rdparty/angle/src/compiler/translator/OutputESSL.cpp deleted file mode 100644 index 50626c91c0..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/OutputESSL.cpp +++ /dev/null @@ -1,47 +0,0 @@ -// -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/translator/OutputESSL.h" - -namespace sh -{ - -TOutputESSL::TOutputESSL(TInfoSinkBase &objSink, - ShArrayIndexClampingStrategy clampingStrategy, - ShHashFunction64 hashFunction, - NameMap &nameMap, - TSymbolTable *symbolTable, - sh::GLenum shaderType, - int shaderVersion, - bool forceHighp, - ShCompileOptions compileOptions) - : TOutputGLSLBase(objSink, - clampingStrategy, - hashFunction, - nameMap, - symbolTable, - shaderType, - shaderVersion, - SH_ESSL_OUTPUT, - compileOptions), - mForceHighp(forceHighp) -{ -} - -bool TOutputESSL::writeVariablePrecision(TPrecision precision) -{ - if (precision == EbpUndefined) - return false; - - TInfoSinkBase &out = objSink(); - if (mForceHighp) - out << getPrecisionString(EbpHigh); - else - out << getPrecisionString(precision); - return true; -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/OutputESSL.h b/src/3rdparty/angle/src/compiler/translator/OutputESSL.h deleted file mode 100644 index e0c7bf2ae6..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/OutputESSL.h +++ /dev/null @@ -1,37 +0,0 @@ -// -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_TRANSLATOR_OUTPUTESSL_H_ -#define COMPILER_TRANSLATOR_OUTPUTESSL_H_ - -#include "compiler/translator/OutputGLSLBase.h" - -namespace sh -{ - -class TOutputESSL : public TOutputGLSLBase -{ - public: - TOutputESSL(TInfoSinkBase &objSink, - ShArrayIndexClampingStrategy clampingStrategy, - ShHashFunction64 hashFunction, - NameMap &nameMap, - TSymbolTable *symbolTable, - sh::GLenum shaderType, - int shaderVersion, - bool forceHighp, - ShCompileOptions compileOptions); - - protected: - bool writeVariablePrecision(TPrecision precision) override; - - private: - bool mForceHighp; -}; - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_OUTPUTESSL_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/OutputGLSL.cpp b/src/3rdparty/angle/src/compiler/translator/OutputGLSL.cpp deleted file mode 100644 index 1bad05dab9..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/OutputGLSL.cpp +++ /dev/null @@ -1,110 +0,0 @@ -// -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/translator/OutputGLSL.h" - -#include "compiler/translator/Compiler.h" - -namespace sh -{ - -TOutputGLSL::TOutputGLSL(TInfoSinkBase &objSink, - ShArrayIndexClampingStrategy clampingStrategy, - ShHashFunction64 hashFunction, - NameMap &nameMap, - TSymbolTable *symbolTable, - sh::GLenum shaderType, - int shaderVersion, - ShShaderOutput output, - ShCompileOptions compileOptions) - : TOutputGLSLBase(objSink, - clampingStrategy, - hashFunction, - nameMap, - symbolTable, - shaderType, - shaderVersion, - output, - compileOptions) -{ -} - -bool TOutputGLSL::writeVariablePrecision(TPrecision) -{ - return false; -} - -void TOutputGLSL::visitSymbol(TIntermSymbol *node) -{ - TInfoSinkBase &out = objSink(); - - const TString &symbol = node->getSymbol(); - if (symbol == "gl_FragDepthEXT") - { - out << "gl_FragDepth"; - } - else if (symbol == "gl_FragColor" && sh::IsGLSL130OrNewer(getShaderOutput())) - { - out << "webgl_FragColor"; - } - else if (symbol == "gl_FragData" && sh::IsGLSL130OrNewer(getShaderOutput())) - { - out << "webgl_FragData"; - } - else if (symbol == "gl_SecondaryFragColorEXT") - { - out << "angle_SecondaryFragColor"; - } - else if (symbol == "gl_SecondaryFragDataEXT") - { - out << "angle_SecondaryFragData"; - } - else - { - TOutputGLSLBase::visitSymbol(node); - } -} - -TString TOutputGLSL::translateTextureFunction(const TString &name) -{ - static const char *simpleRename[] = {"texture2DLodEXT", - "texture2DLod", - "texture2DProjLodEXT", - "texture2DProjLod", - "textureCubeLodEXT", - "textureCubeLod", - "texture2DGradEXT", - "texture2DGradARB", - "texture2DProjGradEXT", - "texture2DProjGradARB", - "textureCubeGradEXT", - "textureCubeGradARB", - nullptr, - nullptr}; - static const char *legacyToCoreRename[] = { - "texture2D", "texture", "texture2DProj", "textureProj", "texture2DLod", "textureLod", - "texture2DProjLod", "textureProjLod", "texture2DRect", "texture", "textureCube", "texture", - "textureCubeLod", "textureLod", - // Extensions - "texture2DLodEXT", "textureLod", "texture2DProjLodEXT", "textureProjLod", - "textureCubeLodEXT", "textureLod", "texture2DGradEXT", "textureGrad", - "texture2DProjGradEXT", "textureProjGrad", "textureCubeGradEXT", "textureGrad", nullptr, - nullptr}; - const char **mapping = - (sh::IsGLSL130OrNewer(getShaderOutput())) ? legacyToCoreRename : simpleRename; - - for (int i = 0; mapping[i] != nullptr; i += 2) - { - if (name == mapping[i]) - { - return mapping[i + 1]; - } - } - - return name; -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/OutputGLSL.h b/src/3rdparty/angle/src/compiler/translator/OutputGLSL.h deleted file mode 100644 index c80abec1a6..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/OutputGLSL.h +++ /dev/null @@ -1,36 +0,0 @@ -// -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_TRANSLATOR_OUTPUTGLSL_H_ -#define COMPILER_TRANSLATOR_OUTPUTGLSL_H_ - -#include "compiler/translator/OutputGLSLBase.h" - -namespace sh -{ - -class TOutputGLSL : public TOutputGLSLBase -{ - public: - TOutputGLSL(TInfoSinkBase &objSink, - ShArrayIndexClampingStrategy clampingStrategy, - ShHashFunction64 hashFunction, - NameMap &nameMap, - TSymbolTable *symbolTable, - sh::GLenum shaderType, - int shaderVersion, - ShShaderOutput output, - ShCompileOptions compileOptions); - - protected: - bool writeVariablePrecision(TPrecision) override; - void visitSymbol(TIntermSymbol *node) override; - TString translateTextureFunction(const TString &name) override; -}; - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_OUTPUTGLSL_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.cpp b/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.cpp deleted file mode 100644 index edaf2ebebf..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.cpp +++ /dev/null @@ -1,1357 +0,0 @@ -// -// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/translator/OutputGLSLBase.h" - -#include "angle_gl.h" -#include "common/debug.h" -#include "common/mathutil.h" -#include "compiler/translator/Compiler.h" -#include "compiler/translator/util.h" - -#include - -namespace sh -{ - -namespace -{ - -bool isSingleStatement(TIntermNode *node) -{ - if (node->getAsFunctionDefinition()) - { - return false; - } - else if (node->getAsBlock()) - { - return false; - } - else if (node->getAsIfElseNode()) - { - return false; - } - else if (node->getAsLoopNode()) - { - return false; - } - else if (node->getAsSwitchNode()) - { - return false; - } - else if (node->getAsCaseNode()) - { - return false; - } - return true; -} - -class CommaSeparatedListItemPrefixGenerator -{ - public: - CommaSeparatedListItemPrefixGenerator() : mFirst(true) {} - private: - bool mFirst; - - friend TInfoSinkBase &operator<<(TInfoSinkBase &out, - CommaSeparatedListItemPrefixGenerator &gen); -}; - -TInfoSinkBase &operator<<(TInfoSinkBase &out, CommaSeparatedListItemPrefixGenerator &gen) -{ - if (gen.mFirst) - { - gen.mFirst = false; - } - else - { - out << ", "; - } - return out; -} - -} // namespace - -TOutputGLSLBase::TOutputGLSLBase(TInfoSinkBase &objSink, - ShArrayIndexClampingStrategy clampingStrategy, - ShHashFunction64 hashFunction, - NameMap &nameMap, - TSymbolTable *symbolTable, - sh::GLenum shaderType, - int shaderVersion, - ShShaderOutput output, - ShCompileOptions compileOptions) - : TIntermTraverser(true, true, true, symbolTable), - mObjSink(objSink), - mDeclaringVariable(false), - mClampingStrategy(clampingStrategy), - mHashFunction(hashFunction), - mNameMap(nameMap), - mShaderType(shaderType), - mShaderVersion(shaderVersion), - mOutput(output), - mCompileOptions(compileOptions) -{ -} - -void TOutputGLSLBase::writeInvariantQualifier(const TType &type) -{ - if (!sh::RemoveInvariant(mShaderType, mShaderVersion, mOutput, mCompileOptions)) - { - TInfoSinkBase &out = objSink(); - out << "invariant "; - } -} - -void TOutputGLSLBase::writeFloat(TInfoSinkBase &out, float f) -{ - if ((gl::isInf(f) || gl::isNaN(f)) && mShaderVersion >= 300) - { - out << "uintBitsToFloat(" << gl::bitCast(f) << "u)"; - } - else - { - out << std::min(FLT_MAX, std::max(-FLT_MAX, f)); - } -} - -void TOutputGLSLBase::writeTriplet(Visit visit, - const char *preStr, - const char *inStr, - const char *postStr) -{ - TInfoSinkBase &out = objSink(); - if (visit == PreVisit && preStr) - out << preStr; - else if (visit == InVisit && inStr) - out << inStr; - else if (visit == PostVisit && postStr) - out << postStr; -} - -void TOutputGLSLBase::writeBuiltInFunctionTriplet(Visit visit, - TOperator op, - bool useEmulatedFunction) -{ - TInfoSinkBase &out = objSink(); - if (visit == PreVisit) - { - const char *opStr(GetOperatorString(op)); - if (useEmulatedFunction) - { - BuiltInFunctionEmulator::WriteEmulatedFunctionName(out, opStr); - } - else - { - out << opStr; - } - out << "("; - } - else - { - writeTriplet(visit, nullptr, ", ", ")"); - } -} - -void TOutputGLSLBase::writeLayoutQualifier(TIntermTyped *variable) -{ - const TType &type = variable->getType(); - - if (!NeedsToWriteLayoutQualifier(type)) - { - return; - } - - TInfoSinkBase &out = objSink(); - const TLayoutQualifier &layoutQualifier = type.getLayoutQualifier(); - out << "layout("; - - CommaSeparatedListItemPrefixGenerator listItemPrefix; - - if (type.getQualifier() == EvqFragmentOut || type.getQualifier() == EvqVertexIn || - IsVarying(type.getQualifier())) - { - if (layoutQualifier.location >= 0) - { - out << listItemPrefix << "location = " << layoutQualifier.location; - } - } - - if (type.getQualifier() == EvqFragmentOut) - { - if (layoutQualifier.yuv == true) - { - out << listItemPrefix << "yuv"; - } - } - - if (IsOpaqueType(type.getBasicType())) - { - if (layoutQualifier.binding >= 0) - { - out << listItemPrefix << "binding = " << layoutQualifier.binding; - } - } - - if (IsImage(type.getBasicType())) - { - if (layoutQualifier.imageInternalFormat != EiifUnspecified) - { - ASSERT(type.getQualifier() == EvqTemporary || type.getQualifier() == EvqUniform); - out << listItemPrefix - << getImageInternalFormatString(layoutQualifier.imageInternalFormat); - } - } - - if (IsAtomicCounter(type.getBasicType())) - { - out << listItemPrefix << "offset = " << layoutQualifier.offset; - } - - out << ") "; -} - -const char *TOutputGLSLBase::mapQualifierToString(TQualifier qualifier) -{ - if (sh::IsGLSL410OrOlder(mOutput) && mShaderVersion >= 300 && - (mCompileOptions & SH_REMOVE_INVARIANT_AND_CENTROID_FOR_ESSL3) != 0) - { - switch (qualifier) - { - // The return string is consistent with sh::getQualifierString() from - // BaseTypes.h minus the "centroid" keyword. - case EvqCentroid: - return ""; - case EvqCentroidIn: - return "smooth in"; - case EvqCentroidOut: - return "smooth out"; - default: - break; - } - } - if (sh::IsGLSL130OrNewer(mOutput)) - { - switch (qualifier) - { - case EvqAttribute: - return "in"; - case EvqVaryingIn: - return "in"; - case EvqVaryingOut: - return "out"; - default: - break; - } - } - return sh::getQualifierString(qualifier); -} - -void TOutputGLSLBase::writeVariableType(const TType &type) -{ - TQualifier qualifier = type.getQualifier(); - TInfoSinkBase &out = objSink(); - if (type.isInvariant()) - { - writeInvariantQualifier(type); - } - if (type.getBasicType() == EbtInterfaceBlock) - { - TInterfaceBlock *interfaceBlock = type.getInterfaceBlock(); - declareInterfaceBlockLayout(interfaceBlock); - } - if (qualifier != EvqTemporary && qualifier != EvqGlobal) - { - const char *qualifierString = mapQualifierToString(qualifier); - if (qualifierString && qualifierString[0] != '\0') - { - out << qualifierString << " "; - } - } - - const TMemoryQualifier &memoryQualifier = type.getMemoryQualifier(); - if (memoryQualifier.readonly) - { - ASSERT(IsImage(type.getBasicType())); - out << "readonly "; - } - - if (memoryQualifier.writeonly) - { - ASSERT(IsImage(type.getBasicType())); - out << "writeonly "; - } - - if (memoryQualifier.coherent) - { - ASSERT(IsImage(type.getBasicType())); - out << "coherent "; - } - - if (memoryQualifier.restrictQualifier) - { - ASSERT(IsImage(type.getBasicType())); - out << "restrict "; - } - - if (memoryQualifier.volatileQualifier) - { - ASSERT(IsImage(type.getBasicType())); - out << "volatile "; - } - - // Declare the struct if we have not done so already. - if (type.getBasicType() == EbtStruct && !structDeclared(type.getStruct())) - { - const TStructure *structure = type.getStruct(); - - declareStruct(structure); - - if (!structure->name().empty()) - { - mDeclaredStructs.insert(structure->uniqueId()); - } - } - else if (type.getBasicType() == EbtInterfaceBlock) - { - TInterfaceBlock *interfaceBlock = type.getInterfaceBlock(); - declareInterfaceBlock(interfaceBlock); - } - else - { - if (writeVariablePrecision(type.getPrecision())) - out << " "; - out << getTypeName(type); - } -} - -void TOutputGLSLBase::writeFunctionParameters(const TIntermSequence &args) -{ - TInfoSinkBase &out = objSink(); - for (TIntermSequence::const_iterator iter = args.begin(); iter != args.end(); ++iter) - { - const TIntermSymbol *arg = (*iter)->getAsSymbolNode(); - ASSERT(arg != nullptr); - - const TType &type = arg->getType(); - writeVariableType(type); - - if (!arg->getName().getString().empty()) - out << " " << hashName(arg->getName()); - if (type.isArray()) - out << ArrayString(type); - - // Put a comma if this is not the last argument. - if (iter != args.end() - 1) - out << ", "; - } -} - -const TConstantUnion *TOutputGLSLBase::writeConstantUnion(const TType &type, - const TConstantUnion *pConstUnion) -{ - TInfoSinkBase &out = objSink(); - - if (type.getBasicType() == EbtStruct) - { - const TStructure *structure = type.getStruct(); - out << hashName(TName(structure->name())) << "("; - - const TFieldList &fields = structure->fields(); - for (size_t i = 0; i < fields.size(); ++i) - { - const TType *fieldType = fields[i]->type(); - ASSERT(fieldType != nullptr); - pConstUnion = writeConstantUnion(*fieldType, pConstUnion); - if (i != fields.size() - 1) - out << ", "; - } - out << ")"; - } - else - { - size_t size = type.getObjectSize(); - bool writeType = size > 1; - if (writeType) - out << getTypeName(type) << "("; - for (size_t i = 0; i < size; ++i, ++pConstUnion) - { - switch (pConstUnion->getType()) - { - case EbtFloat: - writeFloat(out, pConstUnion->getFConst()); - break; - case EbtInt: - out << pConstUnion->getIConst(); - break; - case EbtUInt: - out << pConstUnion->getUConst() << "u"; - break; - case EbtBool: - out << pConstUnion->getBConst(); - break; - case EbtYuvCscStandardEXT: - out << getYuvCscStandardEXTString(pConstUnion->getYuvCscStandardEXTConst()); - break; - default: - UNREACHABLE(); - } - if (i != size - 1) - out << ", "; - } - if (writeType) - out << ")"; - } - return pConstUnion; -} - -void TOutputGLSLBase::writeConstructorTriplet(Visit visit, const TType &type) -{ - TInfoSinkBase &out = objSink(); - if (visit == PreVisit) - { - if (type.isArray()) - { - out << getTypeName(type); - out << ArrayString(type); - out << "("; - } - else - { - out << getTypeName(type) << "("; - } - } - else - { - writeTriplet(visit, nullptr, ", ", ")"); - } -} - -void TOutputGLSLBase::visitSymbol(TIntermSymbol *node) -{ - TInfoSinkBase &out = objSink(); - out << hashVariableName(node->getName()); - - if (mDeclaringVariable && node->getType().isArray()) - out << ArrayString(node->getType()); -} - -void TOutputGLSLBase::visitConstantUnion(TIntermConstantUnion *node) -{ - writeConstantUnion(node->getType(), node->getUnionArrayPointer()); -} - -bool TOutputGLSLBase::visitSwizzle(Visit visit, TIntermSwizzle *node) -{ - TInfoSinkBase &out = objSink(); - if (visit == PostVisit) - { - out << "."; - node->writeOffsetsAsXYZW(&out); - } - return true; -} - -bool TOutputGLSLBase::visitBinary(Visit visit, TIntermBinary *node) -{ - bool visitChildren = true; - TInfoSinkBase &out = objSink(); - switch (node->getOp()) - { - case EOpComma: - writeTriplet(visit, "(", ", ", ")"); - break; - case EOpInitialize: - if (visit == InVisit) - { - out << " = "; - // RHS of initialize is not being declared. - mDeclaringVariable = false; - } - break; - case EOpAssign: - writeTriplet(visit, "(", " = ", ")"); - break; - case EOpAddAssign: - writeTriplet(visit, "(", " += ", ")"); - break; - case EOpSubAssign: - writeTriplet(visit, "(", " -= ", ")"); - break; - case EOpDivAssign: - writeTriplet(visit, "(", " /= ", ")"); - break; - case EOpIModAssign: - writeTriplet(visit, "(", " %= ", ")"); - break; - // Notice the fall-through. - case EOpMulAssign: - case EOpVectorTimesMatrixAssign: - case EOpVectorTimesScalarAssign: - case EOpMatrixTimesScalarAssign: - case EOpMatrixTimesMatrixAssign: - writeTriplet(visit, "(", " *= ", ")"); - break; - case EOpBitShiftLeftAssign: - writeTriplet(visit, "(", " <<= ", ")"); - break; - case EOpBitShiftRightAssign: - writeTriplet(visit, "(", " >>= ", ")"); - break; - case EOpBitwiseAndAssign: - writeTriplet(visit, "(", " &= ", ")"); - break; - case EOpBitwiseXorAssign: - writeTriplet(visit, "(", " ^= ", ")"); - break; - case EOpBitwiseOrAssign: - writeTriplet(visit, "(", " |= ", ")"); - break; - - case EOpIndexDirect: - writeTriplet(visit, nullptr, "[", "]"); - break; - case EOpIndexIndirect: - if (node->getAddIndexClamp()) - { - if (visit == InVisit) - { - if (mClampingStrategy == SH_CLAMP_WITH_CLAMP_INTRINSIC) - out << "[int(clamp(float("; - else - out << "[webgl_int_clamp("; - } - else if (visit == PostVisit) - { - TIntermTyped *left = node->getLeft(); - TType leftType = left->getType(); - - if (mClampingStrategy == SH_CLAMP_WITH_CLAMP_INTRINSIC) - out << "), 0.0, float("; - else - out << ", 0, "; - - if (leftType.isUnsizedArray()) - { - // For runtime-sized arrays in ESSL 3.10 we need to call the length method - // to get the length to clamp against. See ESSL 3.10 section 4.1.9. Note - // that a runtime-sized array expression is guaranteed not to have side - // effects, so it's fine to add the expression to the output twice. - ASSERT(mShaderVersion >= 310); - ASSERT(!left->hasSideEffects()); - left->traverse(this); - out << ".length() - 1"; - } - else - { - int maxSize; - if (leftType.isArray()) - { - maxSize = static_cast(leftType.getOutermostArraySize()) - 1; - } - else - { - maxSize = leftType.getNominalSize() - 1; - } - out << maxSize; - } - if (mClampingStrategy == SH_CLAMP_WITH_CLAMP_INTRINSIC) - out << ")))]"; - else - out << ")]"; - } - } - else - { - writeTriplet(visit, nullptr, "[", "]"); - } - break; - case EOpIndexDirectStruct: - if (visit == InVisit) - { - // Here we are writing out "foo.bar", where "foo" is struct - // and "bar" is field. In AST, it is represented as a binary - // node, where left child represents "foo" and right child "bar". - // The node itself represents ".". The struct field "bar" is - // actually stored as an index into TStructure::fields. - out << "."; - const TStructure *structure = node->getLeft()->getType().getStruct(); - const TIntermConstantUnion *index = node->getRight()->getAsConstantUnion(); - const TField *field = structure->fields()[index->getIConst(0)]; - - TString fieldName = field->name(); - if (!mSymbolTable->findBuiltIn(structure->name(), mShaderVersion)) - fieldName = hashName(TName(fieldName)); - - out << fieldName; - visitChildren = false; - } - break; - case EOpIndexDirectInterfaceBlock: - if (visit == InVisit) - { - out << "."; - const TInterfaceBlock *interfaceBlock = - node->getLeft()->getType().getInterfaceBlock(); - const TIntermConstantUnion *index = node->getRight()->getAsConstantUnion(); - const TField *field = interfaceBlock->fields()[index->getIConst(0)]; - - TString fieldName = field->name(); - if (!mSymbolTable->findBuiltIn(interfaceBlock->name(), mShaderVersion)) - { - fieldName = hashName(TName(fieldName)); - } - else - { - ASSERT(interfaceBlock->name() == "gl_PerVertex"); - } - - out << fieldName; - visitChildren = false; - } - break; - - case EOpAdd: - writeTriplet(visit, "(", " + ", ")"); - break; - case EOpSub: - writeTriplet(visit, "(", " - ", ")"); - break; - case EOpMul: - writeTriplet(visit, "(", " * ", ")"); - break; - case EOpDiv: - writeTriplet(visit, "(", " / ", ")"); - break; - case EOpIMod: - writeTriplet(visit, "(", " % ", ")"); - break; - case EOpBitShiftLeft: - writeTriplet(visit, "(", " << ", ")"); - break; - case EOpBitShiftRight: - writeTriplet(visit, "(", " >> ", ")"); - break; - case EOpBitwiseAnd: - writeTriplet(visit, "(", " & ", ")"); - break; - case EOpBitwiseXor: - writeTriplet(visit, "(", " ^ ", ")"); - break; - case EOpBitwiseOr: - writeTriplet(visit, "(", " | ", ")"); - break; - - case EOpEqual: - writeTriplet(visit, "(", " == ", ")"); - break; - case EOpNotEqual: - writeTriplet(visit, "(", " != ", ")"); - break; - case EOpLessThan: - writeTriplet(visit, "(", " < ", ")"); - break; - case EOpGreaterThan: - writeTriplet(visit, "(", " > ", ")"); - break; - case EOpLessThanEqual: - writeTriplet(visit, "(", " <= ", ")"); - break; - case EOpGreaterThanEqual: - writeTriplet(visit, "(", " >= ", ")"); - break; - - // Notice the fall-through. - case EOpVectorTimesScalar: - case EOpVectorTimesMatrix: - case EOpMatrixTimesVector: - case EOpMatrixTimesScalar: - case EOpMatrixTimesMatrix: - writeTriplet(visit, "(", " * ", ")"); - break; - - case EOpLogicalOr: - writeTriplet(visit, "(", " || ", ")"); - break; - case EOpLogicalXor: - writeTriplet(visit, "(", " ^^ ", ")"); - break; - case EOpLogicalAnd: - writeTriplet(visit, "(", " && ", ")"); - break; - default: - UNREACHABLE(); - } - - return visitChildren; -} - -bool TOutputGLSLBase::visitUnary(Visit visit, TIntermUnary *node) -{ - TString preString; - TString postString = ")"; - - switch (node->getOp()) - { - case EOpNegative: - preString = "(-"; - break; - case EOpPositive: - preString = "(+"; - break; - case EOpLogicalNot: - preString = "(!"; - break; - case EOpBitwiseNot: - preString = "(~"; - break; - - case EOpPostIncrement: - preString = "("; - postString = "++)"; - break; - case EOpPostDecrement: - preString = "("; - postString = "--)"; - break; - case EOpPreIncrement: - preString = "(++"; - break; - case EOpPreDecrement: - preString = "(--"; - break; - case EOpArrayLength: - preString = "(("; - postString = ").length())"; - break; - - case EOpRadians: - case EOpDegrees: - case EOpSin: - case EOpCos: - case EOpTan: - case EOpAsin: - case EOpAcos: - case EOpAtan: - case EOpSinh: - case EOpCosh: - case EOpTanh: - case EOpAsinh: - case EOpAcosh: - case EOpAtanh: - case EOpExp: - case EOpLog: - case EOpExp2: - case EOpLog2: - case EOpSqrt: - case EOpInverseSqrt: - case EOpAbs: - case EOpSign: - case EOpFloor: - case EOpTrunc: - case EOpRound: - case EOpRoundEven: - case EOpCeil: - case EOpFract: - case EOpIsNan: - case EOpIsInf: - case EOpFloatBitsToInt: - case EOpFloatBitsToUint: - case EOpIntBitsToFloat: - case EOpUintBitsToFloat: - case EOpPackSnorm2x16: - case EOpPackUnorm2x16: - case EOpPackHalf2x16: - case EOpUnpackSnorm2x16: - case EOpUnpackUnorm2x16: - case EOpUnpackHalf2x16: - case EOpPackUnorm4x8: - case EOpPackSnorm4x8: - case EOpUnpackUnorm4x8: - case EOpUnpackSnorm4x8: - case EOpLength: - case EOpNormalize: - case EOpDFdx: - case EOpDFdy: - case EOpFwidth: - case EOpTranspose: - case EOpDeterminant: - case EOpInverse: - case EOpAny: - case EOpAll: - case EOpLogicalNotComponentWise: - case EOpBitfieldReverse: - case EOpBitCount: - case EOpFindLSB: - case EOpFindMSB: - writeBuiltInFunctionTriplet(visit, node->getOp(), node->getUseEmulatedFunction()); - return true; - default: - UNREACHABLE(); - } - - writeTriplet(visit, preString.c_str(), nullptr, postString.c_str()); - - return true; -} - -bool TOutputGLSLBase::visitTernary(Visit visit, TIntermTernary *node) -{ - TInfoSinkBase &out = objSink(); - // Notice two brackets at the beginning and end. The outer ones - // encapsulate the whole ternary expression. This preserves the - // order of precedence when ternary expressions are used in a - // compound expression, i.e., c = 2 * (a < b ? 1 : 2). - out << "(("; - node->getCondition()->traverse(this); - out << ") ? ("; - node->getTrueExpression()->traverse(this); - out << ") : ("; - node->getFalseExpression()->traverse(this); - out << "))"; - return false; -} - -bool TOutputGLSLBase::visitIfElse(Visit visit, TIntermIfElse *node) -{ - TInfoSinkBase &out = objSink(); - - out << "if ("; - node->getCondition()->traverse(this); - out << ")\n"; - - visitCodeBlock(node->getTrueBlock()); - - if (node->getFalseBlock()) - { - out << "else\n"; - visitCodeBlock(node->getFalseBlock()); - } - return false; -} - -bool TOutputGLSLBase::visitSwitch(Visit visit, TIntermSwitch *node) -{ - ASSERT(node->getStatementList()); - writeTriplet(visit, "switch (", ") ", nullptr); - // The curly braces get written when visiting the statementList aggregate - return true; -} - -bool TOutputGLSLBase::visitCase(Visit visit, TIntermCase *node) -{ - if (node->hasCondition()) - { - writeTriplet(visit, "case (", nullptr, "):\n"); - return true; - } - else - { - TInfoSinkBase &out = objSink(); - out << "default:\n"; - return false; - } -} - -bool TOutputGLSLBase::visitBlock(Visit visit, TIntermBlock *node) -{ - TInfoSinkBase &out = objSink(); - // Scope the blocks except when at the global scope. - if (mDepth > 0) - { - out << "{\n"; - } - - for (TIntermSequence::const_iterator iter = node->getSequence()->begin(); - iter != node->getSequence()->end(); ++iter) - { - TIntermNode *curNode = *iter; - ASSERT(curNode != nullptr); - curNode->traverse(this); - - if (isSingleStatement(curNode)) - out << ";\n"; - } - - // Scope the blocks except when at the global scope. - if (mDepth > 0) - { - out << "}\n"; - } - return false; -} - -bool TOutputGLSLBase::visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) -{ - TIntermFunctionPrototype *prototype = node->getFunctionPrototype(); - prototype->traverse(this); - visitCodeBlock(node->getBody()); - - // Fully processed; no need to visit children. - return false; -} - -bool TOutputGLSLBase::visitInvariantDeclaration(Visit visit, TIntermInvariantDeclaration *node) -{ - TInfoSinkBase &out = objSink(); - ASSERT(visit == PreVisit); - const TIntermSymbol *symbol = node->getSymbol(); - out << "invariant " << hashVariableName(symbol->getName()); - return false; -} - -bool TOutputGLSLBase::visitFunctionPrototype(Visit visit, TIntermFunctionPrototype *node) -{ - TInfoSinkBase &out = objSink(); - ASSERT(visit == PreVisit); - - const TType &type = node->getType(); - writeVariableType(type); - if (type.isArray()) - out << ArrayString(type); - - out << " " << hashFunctionNameIfNeeded(*node->getFunctionSymbolInfo()); - - out << "("; - writeFunctionParameters(*(node->getSequence())); - out << ")"; - - return false; -} - -bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node) -{ - bool visitChildren = true; - TInfoSinkBase &out = objSink(); - switch (node->getOp()) - { - case EOpCallFunctionInAST: - case EOpCallInternalRawFunction: - case EOpCallBuiltInFunction: - // Function call. - if (visit == PreVisit) - { - if (node->getOp() == EOpCallBuiltInFunction) - { - out << translateTextureFunction(node->getFunctionSymbolInfo()->getName()); - } - else - { - out << hashFunctionNameIfNeeded(*node->getFunctionSymbolInfo()); - } - out << "("; - } - else if (visit == InVisit) - out << ", "; - else - out << ")"; - break; - case EOpConstruct: - writeConstructorTriplet(visit, node->getType()); - break; - - case EOpEqualComponentWise: - case EOpNotEqualComponentWise: - case EOpLessThanComponentWise: - case EOpGreaterThanComponentWise: - case EOpLessThanEqualComponentWise: - case EOpGreaterThanEqualComponentWise: - case EOpMod: - case EOpModf: - case EOpPow: - case EOpAtan: - case EOpMin: - case EOpMax: - case EOpClamp: - case EOpMix: - case EOpStep: - case EOpSmoothStep: - case EOpFrexp: - case EOpLdexp: - case EOpDistance: - case EOpDot: - case EOpCross: - case EOpFaceforward: - case EOpReflect: - case EOpRefract: - case EOpMulMatrixComponentWise: - case EOpOuterProduct: - case EOpBitfieldExtract: - case EOpBitfieldInsert: - case EOpUaddCarry: - case EOpUsubBorrow: - case EOpUmulExtended: - case EOpImulExtended: - case EOpBarrier: - case EOpMemoryBarrier: - case EOpMemoryBarrierAtomicCounter: - case EOpMemoryBarrierBuffer: - case EOpMemoryBarrierImage: - case EOpMemoryBarrierShared: - case EOpGroupMemoryBarrier: - case EOpEmitVertex: - case EOpEndPrimitive: - writeBuiltInFunctionTriplet(visit, node->getOp(), node->getUseEmulatedFunction()); - break; - default: - UNREACHABLE(); - } - return visitChildren; -} - -bool TOutputGLSLBase::visitDeclaration(Visit visit, TIntermDeclaration *node) -{ - TInfoSinkBase &out = objSink(); - - // Variable declaration. - if (visit == PreVisit) - { - const TIntermSequence &sequence = *(node->getSequence()); - TIntermTyped *variable = sequence.front()->getAsTyped(); - writeLayoutQualifier(variable); - writeVariableType(variable->getType()); - if (variable->getAsSymbolNode() == nullptr || - !variable->getAsSymbolNode()->getSymbol().empty()) - { - out << " "; - } - mDeclaringVariable = true; - } - else if (visit == InVisit) - { - UNREACHABLE(); - } - else - { - mDeclaringVariable = false; - } - return true; -} - -bool TOutputGLSLBase::visitLoop(Visit visit, TIntermLoop *node) -{ - TInfoSinkBase &out = objSink(); - - TLoopType loopType = node->getType(); - - if (loopType == ELoopFor) // for loop - { - out << "for ("; - if (node->getInit()) - node->getInit()->traverse(this); - out << "; "; - - if (node->getCondition()) - node->getCondition()->traverse(this); - out << "; "; - - if (node->getExpression()) - node->getExpression()->traverse(this); - out << ")\n"; - - visitCodeBlock(node->getBody()); - } - else if (loopType == ELoopWhile) // while loop - { - out << "while ("; - ASSERT(node->getCondition() != nullptr); - node->getCondition()->traverse(this); - out << ")\n"; - - visitCodeBlock(node->getBody()); - } - else // do-while loop - { - ASSERT(loopType == ELoopDoWhile); - out << "do\n"; - - visitCodeBlock(node->getBody()); - - out << "while ("; - ASSERT(node->getCondition() != nullptr); - node->getCondition()->traverse(this); - out << ");\n"; - } - - // No need to visit children. They have been already processed in - // this function. - return false; -} - -bool TOutputGLSLBase::visitBranch(Visit visit, TIntermBranch *node) -{ - switch (node->getFlowOp()) - { - case EOpKill: - writeTriplet(visit, "discard", nullptr, nullptr); - break; - case EOpBreak: - writeTriplet(visit, "break", nullptr, nullptr); - break; - case EOpContinue: - writeTriplet(visit, "continue", nullptr, nullptr); - break; - case EOpReturn: - writeTriplet(visit, "return ", nullptr, nullptr); - break; - default: - UNREACHABLE(); - } - - return true; -} - -void TOutputGLSLBase::visitCodeBlock(TIntermBlock *node) -{ - TInfoSinkBase &out = objSink(); - if (node != nullptr) - { - node->traverse(this); - // Single statements not part of a sequence need to be terminated - // with semi-colon. - if (isSingleStatement(node)) - out << ";\n"; - } - else - { - out << "{\n}\n"; // Empty code block. - } -} - -TString TOutputGLSLBase::getTypeName(const TType &type) -{ - return GetTypeName(type, mHashFunction, &mNameMap); -} - -TString TOutputGLSLBase::hashName(const TName &name) -{ - return HashName(name, mHashFunction, &mNameMap); -} - -TString TOutputGLSLBase::hashVariableName(const TName &name) -{ - if (mSymbolTable->findBuiltIn(name.getString(), mShaderVersion) != nullptr || - name.getString().substr(0, 3) == "gl_") - { - if (mCompileOptions & SH_TRANSLATE_VIEWID_OVR_TO_UNIFORM && - name.getString() == "gl_ViewID_OVR") - { - TName uniformName(TString("ViewID_OVR")); - uniformName.setInternal(true); - return hashName(uniformName); - } - return name.getString(); - } - return hashName(name); -} - -TString TOutputGLSLBase::hashFunctionNameIfNeeded(const TFunctionSymbolInfo &info) -{ - if (info.isMain()) - { - return info.getName(); - } - else - { - return hashName(info.getNameObj()); - } -} - -bool TOutputGLSLBase::structDeclared(const TStructure *structure) const -{ - ASSERT(structure); - if (structure->name().empty()) - { - return false; - } - - return (mDeclaredStructs.count(structure->uniqueId()) > 0); -} - -void TOutputGLSLBase::declareStruct(const TStructure *structure) -{ - TInfoSinkBase &out = objSink(); - - out << "struct " << hashName(TName(structure->name())) << "{\n"; - const TFieldList &fields = structure->fields(); - for (size_t i = 0; i < fields.size(); ++i) - { - const TField *field = fields[i]; - if (writeVariablePrecision(field->type()->getPrecision())) - out << " "; - out << getTypeName(*field->type()) << " " << hashName(TName(field->name())); - if (field->type()->isArray()) - out << ArrayString(*field->type()); - out << ";\n"; - } - out << "}"; -} - -void TOutputGLSLBase::declareInterfaceBlockLayout(const TInterfaceBlock *interfaceBlock) -{ - TInfoSinkBase &out = objSink(); - - out << "layout("; - - switch (interfaceBlock->blockStorage()) - { - case EbsUnspecified: - case EbsShared: - // Default block storage is shared. - out << "shared"; - break; - - case EbsPacked: - out << "packed"; - break; - - case EbsStd140: - out << "std140"; - break; - - case EbsStd430: - out << "std430"; - break; - - default: - UNREACHABLE(); - break; - } - - out << ", "; - - if (interfaceBlock->blockBinding() > 0) - { - out << "binding = " << interfaceBlock->blockBinding(); - out << ", "; - } - - switch (interfaceBlock->matrixPacking()) - { - case EmpUnspecified: - case EmpColumnMajor: - // Default matrix packing is column major. - out << "column_major"; - break; - - case EmpRowMajor: - out << "row_major"; - break; - - default: - UNREACHABLE(); - break; - } - - out << ") "; -} - -void TOutputGLSLBase::declareInterfaceBlock(const TInterfaceBlock *interfaceBlock) -{ - TInfoSinkBase &out = objSink(); - - out << hashName(TName(interfaceBlock->name())) << "{\n"; - const TFieldList &fields = interfaceBlock->fields(); - for (size_t i = 0; i < fields.size(); ++i) - { - const TField *field = fields[i]; - if (writeVariablePrecision(field->type()->getPrecision())) - out << " "; - out << getTypeName(*field->type()) << " " << hashName(TName(field->name())); - if (field->type()->isArray()) - out << ArrayString(*field->type()); - out << ";\n"; - } - out << "}"; -} - -void WriteGeometryShaderLayoutQualifiers(TInfoSinkBase &out, - sh::TLayoutPrimitiveType inputPrimitive, - int invocations, - sh::TLayoutPrimitiveType outputPrimitive, - int maxVertices) -{ - // Omit 'invocations = 1' - if (inputPrimitive != EptUndefined || invocations > 1) - { - out << "layout ("; - - if (inputPrimitive != EptUndefined) - { - out << getGeometryShaderPrimitiveTypeString(inputPrimitive); - } - - if (invocations > 1) - { - if (inputPrimitive != EptUndefined) - { - out << ", "; - } - out << "invocations = " << invocations; - } - out << ") in;\n"; - } - - if (outputPrimitive != EptUndefined || maxVertices != -1) - { - out << "layout ("; - - if (outputPrimitive != EptUndefined) - { - out << getGeometryShaderPrimitiveTypeString(outputPrimitive); - } - - if (maxVertices != -1) - { - if (outputPrimitive != EptUndefined) - { - out << ", "; - } - out << "max_vertices = " << maxVertices; - } - out << ") out;\n"; - } -} - -// If SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS is enabled, layout qualifiers are spilled whenever -// variables with specified layout qualifiers are copied. Additional checks are needed against the -// type and storage qualifier of the variable to verify that layout qualifiers have to be outputted. -// TODO (mradev): Fix layout qualifier spilling in ScalarizeVecAndMatConstructorArgs and remove -// NeedsToWriteLayoutQualifier. -bool NeedsToWriteLayoutQualifier(const TType &type) -{ - if (type.getBasicType() == EbtInterfaceBlock) - { - return false; - } - - const TLayoutQualifier &layoutQualifier = type.getLayoutQualifier(); - - if ((type.getQualifier() == EvqFragmentOut || type.getQualifier() == EvqVertexIn || - IsVarying(type.getQualifier())) && - layoutQualifier.location >= 0) - { - return true; - } - - if (type.getQualifier() == EvqFragmentOut && layoutQualifier.yuv == true) - { - return true; - } - - if (IsOpaqueType(type.getBasicType()) && layoutQualifier.binding != -1) - { - return true; - } - - if (IsImage(type.getBasicType()) && layoutQualifier.imageInternalFormat != EiifUnspecified) - { - return true; - } - return false; -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.h b/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.h deleted file mode 100644 index 592a310be4..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.h +++ /dev/null @@ -1,122 +0,0 @@ -// -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_TRANSLATOR_OUTPUTGLSLBASE_H_ -#define COMPILER_TRANSLATOR_OUTPUTGLSLBASE_H_ - -#include - -#include "compiler/translator/HashNames.h" -#include "compiler/translator/InfoSink.h" -#include "compiler/translator/IntermTraverse.h" - -namespace sh -{ - -class TOutputGLSLBase : public TIntermTraverser -{ - public: - TOutputGLSLBase(TInfoSinkBase &objSink, - ShArrayIndexClampingStrategy clampingStrategy, - ShHashFunction64 hashFunction, - NameMap &nameMap, - TSymbolTable *symbolTable, - sh::GLenum shaderType, - int shaderVersion, - ShShaderOutput output, - ShCompileOptions compileOptions); - - ShShaderOutput getShaderOutput() const { return mOutput; } - - // Return the original name if hash function pointer is NULL; - // otherwise return the hashed name. Has special handling for internal names, which are not - // hashed. - TString hashName(const TName &name); - - protected: - TInfoSinkBase &objSink() { return mObjSink; } - void writeFloat(TInfoSinkBase &out, float f); - void writeTriplet(Visit visit, const char *preStr, const char *inStr, const char *postStr); - virtual void writeLayoutQualifier(TIntermTyped *variable); - void writeInvariantQualifier(const TType &type); - void writeVariableType(const TType &type); - virtual bool writeVariablePrecision(TPrecision precision) = 0; - void writeFunctionParameters(const TIntermSequence &args); - const TConstantUnion *writeConstantUnion(const TType &type, const TConstantUnion *pConstUnion); - void writeConstructorTriplet(Visit visit, const TType &type); - TString getTypeName(const TType &type); - - void visitSymbol(TIntermSymbol *node) override; - void visitConstantUnion(TIntermConstantUnion *node) override; - bool visitSwizzle(Visit visit, TIntermSwizzle *node) override; - bool visitBinary(Visit visit, TIntermBinary *node) override; - bool visitUnary(Visit visit, TIntermUnary *node) override; - bool visitTernary(Visit visit, TIntermTernary *node) override; - bool visitIfElse(Visit visit, TIntermIfElse *node) override; - bool visitSwitch(Visit visit, TIntermSwitch *node) override; - bool visitCase(Visit visit, TIntermCase *node) override; - bool visitFunctionPrototype(Visit visit, TIntermFunctionPrototype *node) override; - bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override; - bool visitAggregate(Visit visit, TIntermAggregate *node) override; - bool visitBlock(Visit visit, TIntermBlock *node) override; - bool visitInvariantDeclaration(Visit visit, TIntermInvariantDeclaration *node) override; - bool visitDeclaration(Visit visit, TIntermDeclaration *node) override; - bool visitLoop(Visit visit, TIntermLoop *node) override; - bool visitBranch(Visit visit, TIntermBranch *node) override; - - void visitCodeBlock(TIntermBlock *node); - - // Same as hashName(), but without hashing built-in variables. - TString hashVariableName(const TName &name); - // Same as hashName(), but without hashing internal functions or "main". - TString hashFunctionNameIfNeeded(const TFunctionSymbolInfo &info); - // Used to translate function names for differences between ESSL and GLSL - virtual TString translateTextureFunction(const TString &name) { return name; } - - private: - bool structDeclared(const TStructure *structure) const; - void declareStruct(const TStructure *structure); - - void declareInterfaceBlockLayout(const TInterfaceBlock *interfaceBlock); - void declareInterfaceBlock(const TInterfaceBlock *interfaceBlock); - - void writeBuiltInFunctionTriplet(Visit visit, TOperator op, bool useEmulatedFunction); - - const char *mapQualifierToString(TQualifier qialifier); - - TInfoSinkBase &mObjSink; - bool mDeclaringVariable; - - // This set contains all the ids of the structs from every scope. - std::set mDeclaredStructs; - - ShArrayIndexClampingStrategy mClampingStrategy; - - // name hashing. - ShHashFunction64 mHashFunction; - - NameMap &mNameMap; - - sh::GLenum mShaderType; - - const int mShaderVersion; - - ShShaderOutput mOutput; - - ShCompileOptions mCompileOptions; -}; - -void WriteGeometryShaderLayoutQualifiers(TInfoSinkBase &out, - sh::TLayoutPrimitiveType inputPrimitive, - int invocations, - sh::TLayoutPrimitiveType outputPrimitive, - int maxVertices); - -bool NeedsToWriteLayoutQualifier(const TType &type); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_OUTPUTGLSLBASE_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/OutputHLSL.cpp b/src/3rdparty/angle/src/compiler/translator/OutputHLSL.cpp deleted file mode 100644 index d5ff761430..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/OutputHLSL.cpp +++ /dev/null @@ -1,3084 +0,0 @@ -// -// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/translator/OutputHLSL.h" - -#include -#include -#include - -#include "common/angleutils.h" -#include "common/debug.h" -#include "common/utilities.h" -#include "compiler/translator/BuiltInFunctionEmulator.h" -#include "compiler/translator/BuiltInFunctionEmulatorHLSL.h" -#include "compiler/translator/ImageFunctionHLSL.h" -#include "compiler/translator/InfoSink.h" -#include "compiler/translator/NodeSearch.h" -#include "compiler/translator/RemoveSwitchFallThrough.h" -#include "compiler/translator/SearchSymbol.h" -#include "compiler/translator/StructureHLSL.h" -#include "compiler/translator/TextureFunctionHLSL.h" -#include "compiler/translator/TranslatorHLSL.h" -#include "compiler/translator/UniformHLSL.h" -#include "compiler/translator/UtilsHLSL.h" -#include "compiler/translator/blocklayout.h" -#include "compiler/translator/util.h" - -namespace sh -{ - -namespace -{ - -TString ArrayHelperFunctionName(const char *prefix, const TType &type) -{ - TStringStream fnName; - fnName << prefix << "_"; - if (type.isArray()) - { - for (unsigned int arraySize : *type.getArraySizes()) - { - fnName << arraySize << "_"; - } - } - fnName << TypeString(type); - return fnName.str(); -} - -bool IsDeclarationWrittenOut(TIntermDeclaration *node) -{ - TIntermSequence *sequence = node->getSequence(); - TIntermTyped *variable = (*sequence)[0]->getAsTyped(); - ASSERT(sequence->size() == 1); - ASSERT(variable); - return (variable->getQualifier() == EvqTemporary || variable->getQualifier() == EvqGlobal || - variable->getQualifier() == EvqConst); -} - -bool IsInStd140InterfaceBlock(TIntermTyped *node) -{ - TIntermBinary *binaryNode = node->getAsBinaryNode(); - - if (binaryNode) - { - return IsInStd140InterfaceBlock(binaryNode->getLeft()); - } - - const TType &type = node->getType(); - - // determine if we are in the standard layout - const TInterfaceBlock *interfaceBlock = type.getInterfaceBlock(); - if (interfaceBlock) - { - return (interfaceBlock->blockStorage() == EbsStd140); - } - - return false; -} - -} // anonymous namespace - -void OutputHLSL::writeFloat(TInfoSinkBase &out, float f) -{ - // This is known not to work for NaN on all drivers but make the best effort to output NaNs - // regardless. - if ((gl::isInf(f) || gl::isNaN(f)) && mShaderVersion >= 300 && - mOutputType == SH_HLSL_4_1_OUTPUT) - { - out << "asfloat(" << gl::bitCast(f) << "u)"; - } - else - { - out << std::min(FLT_MAX, std::max(-FLT_MAX, f)); - } -} - -void OutputHLSL::writeSingleConstant(TInfoSinkBase &out, const TConstantUnion *const constUnion) -{ - ASSERT(constUnion != nullptr); - switch (constUnion->getType()) - { - case EbtFloat: - writeFloat(out, constUnion->getFConst()); - break; - case EbtInt: - out << constUnion->getIConst(); - break; - case EbtUInt: - out << constUnion->getUConst(); - break; - case EbtBool: - out << constUnion->getBConst(); - break; - default: - UNREACHABLE(); - } -} - -const TConstantUnion *OutputHLSL::writeConstantUnionArray(TInfoSinkBase &out, - const TConstantUnion *const constUnion, - const size_t size) -{ - const TConstantUnion *constUnionIterated = constUnion; - for (size_t i = 0; i < size; i++, constUnionIterated++) - { - writeSingleConstant(out, constUnionIterated); - - if (i != size - 1) - { - out << ", "; - } - } - return constUnionIterated; -} - -OutputHLSL::OutputHLSL(sh::GLenum shaderType, - int shaderVersion, - const TExtensionBehavior &extensionBehavior, - const char *sourcePath, - ShShaderOutput outputType, - int numRenderTargets, - const std::vector &uniforms, - ShCompileOptions compileOptions, - TSymbolTable *symbolTable, - PerformanceDiagnostics *perfDiagnostics) - : TIntermTraverser(true, true, true, symbolTable), - mShaderType(shaderType), - mShaderVersion(shaderVersion), - mExtensionBehavior(extensionBehavior), - mSourcePath(sourcePath), - mOutputType(outputType), - mCompileOptions(compileOptions), - mNumRenderTargets(numRenderTargets), - mCurrentFunctionMetadata(nullptr), - mPerfDiagnostics(perfDiagnostics) -{ - mInsideFunction = false; - - mUsesFragColor = false; - mUsesFragData = false; - mUsesDepthRange = false; - mUsesFragCoord = false; - mUsesPointCoord = false; - mUsesFrontFacing = false; - mUsesPointSize = false; - mUsesInstanceID = false; - mHasMultiviewExtensionEnabled = - IsExtensionEnabled(mExtensionBehavior, TExtension::OVR_multiview); - mUsesViewID = false; - mUsesVertexID = false; - mUsesFragDepth = false; - mUsesNumWorkGroups = false; - mUsesWorkGroupID = false; - mUsesLocalInvocationID = false; - mUsesGlobalInvocationID = false; - mUsesLocalInvocationIndex = false; - mUsesXor = false; - mUsesDiscardRewriting = false; - mUsesNestedBreak = false; - mRequiresIEEEStrictCompiling = false; - - mUniqueIndex = 0; - - mOutputLod0Function = false; - mInsideDiscontinuousLoop = false; - mNestedLoopDepth = 0; - - mExcessiveLoopIndex = nullptr; - - mStructureHLSL = new StructureHLSL; - mUniformHLSL = new UniformHLSL(shaderType, mStructureHLSL, outputType, uniforms); - mTextureFunctionHLSL = new TextureFunctionHLSL; - mImageFunctionHLSL = new ImageFunctionHLSL; - - if (mOutputType == SH_HLSL_3_0_OUTPUT) - { - // Fragment shaders need dx_DepthRange, dx_ViewCoords and dx_DepthFront. - // Vertex shaders need a slightly different set: dx_DepthRange, dx_ViewCoords and - // dx_ViewAdjust. - // In both cases total 3 uniform registers need to be reserved. - mUniformHLSL->reserveUniformRegisters(3); - } - - // Reserve registers for the default uniform block and driver constants - mUniformHLSL->reserveUniformBlockRegisters(2); -} - -OutputHLSL::~OutputHLSL() -{ - SafeDelete(mStructureHLSL); - SafeDelete(mUniformHLSL); - SafeDelete(mTextureFunctionHLSL); - SafeDelete(mImageFunctionHLSL); - for (auto &eqFunction : mStructEqualityFunctions) - { - SafeDelete(eqFunction); - } - for (auto &eqFunction : mArrayEqualityFunctions) - { - SafeDelete(eqFunction); - } -} - -void OutputHLSL::output(TIntermNode *treeRoot, TInfoSinkBase &objSink) -{ - BuiltInFunctionEmulator builtInFunctionEmulator; - InitBuiltInFunctionEmulatorForHLSL(&builtInFunctionEmulator); - if ((mCompileOptions & SH_EMULATE_ISNAN_FLOAT_FUNCTION) != 0) - { - InitBuiltInIsnanFunctionEmulatorForHLSLWorkarounds(&builtInFunctionEmulator, - mShaderVersion); - } - - builtInFunctionEmulator.markBuiltInFunctionsForEmulation(treeRoot); - - // Now that we are done changing the AST, do the analyses need for HLSL generation - CallDAG::InitResult success = mCallDag.init(treeRoot, nullptr); - ASSERT(success == CallDAG::INITDAG_SUCCESS); - mASTMetadataList = CreateASTMetadataHLSL(treeRoot, mCallDag); - - const std::vector std140Structs = FlagStd140Structs(treeRoot); - // TODO(oetuaho): The std140Structs could be filtered based on which ones actually get used in - // the shader code. When we add shader storage blocks we might also consider an alternative - // solution, since the struct mapping won't work very well for shader storage blocks. - - // Output the body and footer first to determine what has to go in the header - mInfoSinkStack.push(&mBody); - treeRoot->traverse(this); - mInfoSinkStack.pop(); - - mInfoSinkStack.push(&mFooter); - mInfoSinkStack.pop(); - - mInfoSinkStack.push(&mHeader); - header(mHeader, std140Structs, &builtInFunctionEmulator); - mInfoSinkStack.pop(); - - objSink << mHeader.c_str(); - objSink << mBody.c_str(); - objSink << mFooter.c_str(); - - builtInFunctionEmulator.cleanup(); -} - -const std::map &OutputHLSL::getUniformBlockRegisterMap() const -{ - return mUniformHLSL->getUniformBlockRegisterMap(); -} - -const std::map &OutputHLSL::getUniformRegisterMap() const -{ - return mUniformHLSL->getUniformRegisterMap(); -} - -TString OutputHLSL::structInitializerString(int indent, - const TType &type, - const TString &name) const -{ - TString init; - - TString indentString; - for (int spaces = 0; spaces < indent; spaces++) - { - indentString += " "; - } - - if (type.isArray()) - { - init += indentString + "{\n"; - for (unsigned int arrayIndex = 0u; arrayIndex < type.getOutermostArraySize(); ++arrayIndex) - { - TStringStream indexedString; - indexedString << name << "[" << arrayIndex << "]"; - TType elementType = type; - elementType.toArrayElementType(); - init += structInitializerString(indent + 1, elementType, indexedString.str()); - if (arrayIndex < type.getOutermostArraySize() - 1) - { - init += ","; - } - init += "\n"; - } - init += indentString + "}"; - } - else if (type.getBasicType() == EbtStruct) - { - init += indentString + "{\n"; - const TStructure &structure = *type.getStruct(); - const TFieldList &fields = structure.fields(); - for (unsigned int fieldIndex = 0; fieldIndex < fields.size(); fieldIndex++) - { - const TField &field = *fields[fieldIndex]; - const TString &fieldName = name + "." + Decorate(field.name()); - const TType &fieldType = *field.type(); - - init += structInitializerString(indent + 1, fieldType, fieldName); - if (fieldIndex < fields.size() - 1) - { - init += ","; - } - init += "\n"; - } - init += indentString + "}"; - } - else - { - init += indentString + name; - } - - return init; -} - -TString OutputHLSL::generateStructMapping(const std::vector &std140Structs) const -{ - TString mappedStructs; - - for (auto &mappedStruct : std140Structs) - { - TInterfaceBlock *interfaceBlock = - mappedStruct.blockDeclarator->getType().getInterfaceBlock(); - const TString &interfaceBlockName = interfaceBlock->name(); - const TName &instanceName = mappedStruct.blockDeclarator->getName(); - if (mReferencedUniformBlocks.count(interfaceBlockName) == 0 && - (instanceName.getString() == "" || - mReferencedUniformBlocks.count(instanceName.getString()) == 0)) - { - continue; - } - - unsigned int instanceCount = 1u; - bool isInstanceArray = mappedStruct.blockDeclarator->isArray(); - if (isInstanceArray) - { - instanceCount = mappedStruct.blockDeclarator->getOutermostArraySize(); - } - - for (unsigned int instanceArrayIndex = 0; instanceArrayIndex < instanceCount; - ++instanceArrayIndex) - { - TString originalName; - TString mappedName("map"); - - if (instanceName.getString() != "") - { - unsigned int instanceStringArrayIndex = GL_INVALID_INDEX; - if (isInstanceArray) - instanceStringArrayIndex = instanceArrayIndex; - TString instanceString = mUniformHLSL->uniformBlockInstanceString( - *interfaceBlock, instanceStringArrayIndex); - originalName += instanceString; - mappedName += instanceString; - originalName += "."; - mappedName += "_"; - } - - TString fieldName = Decorate(mappedStruct.field->name()); - originalName += fieldName; - mappedName += fieldName; - - TType *structType = mappedStruct.field->type(); - mappedStructs += - "static " + Decorate(structType->getStruct()->name()) + " " + mappedName; - - if (structType->isArray()) - { - mappedStructs += ArrayString(*mappedStruct.field->type()); - } - - mappedStructs += " =\n"; - mappedStructs += structInitializerString(0, *structType, originalName); - mappedStructs += ";\n"; - } - } - return mappedStructs; -} - -void OutputHLSL::header(TInfoSinkBase &out, - const std::vector &std140Structs, - const BuiltInFunctionEmulator *builtInFunctionEmulator) const -{ - TString varyings; - TString attributes; - TString mappedStructs = generateStructMapping(std140Structs); - - for (ReferencedSymbols::const_iterator varying = mReferencedVaryings.begin(); - varying != mReferencedVaryings.end(); varying++) - { - const TType &type = varying->second->getType(); - const TString &name = varying->second->getSymbol(); - - // Program linking depends on this exact format - varyings += "static " + InterpolationString(type.getQualifier()) + " " + TypeString(type) + - " " + Decorate(name) + ArrayString(type) + " = " + initializer(type) + ";\n"; - } - - for (ReferencedSymbols::const_iterator attribute = mReferencedAttributes.begin(); - attribute != mReferencedAttributes.end(); attribute++) - { - const TType &type = attribute->second->getType(); - const TString &name = attribute->second->getSymbol(); - - attributes += "static " + TypeString(type) + " " + Decorate(name) + ArrayString(type) + - " = " + initializer(type) + ";\n"; - } - - out << mStructureHLSL->structsHeader(); - - mUniformHLSL->uniformsHeader(out, mOutputType, mReferencedUniforms, mSymbolTable); - out << mUniformHLSL->uniformBlocksHeader(mReferencedUniformBlocks); - - if (!mEqualityFunctions.empty()) - { - out << "\n// Equality functions\n\n"; - for (const auto &eqFunction : mEqualityFunctions) - { - out << eqFunction->functionDefinition << "\n"; - } - } - if (!mArrayAssignmentFunctions.empty()) - { - out << "\n// Assignment functions\n\n"; - for (const auto &assignmentFunction : mArrayAssignmentFunctions) - { - out << assignmentFunction.functionDefinition << "\n"; - } - } - if (!mArrayConstructIntoFunctions.empty()) - { - out << "\n// Array constructor functions\n\n"; - for (const auto &constructIntoFunction : mArrayConstructIntoFunctions) - { - out << constructIntoFunction.functionDefinition << "\n"; - } - } - - if (mUsesDiscardRewriting) - { - out << "#define ANGLE_USES_DISCARD_REWRITING\n"; - } - - if (mUsesNestedBreak) - { - out << "#define ANGLE_USES_NESTED_BREAK\n"; - } - - if (mRequiresIEEEStrictCompiling) - { - out << "#define ANGLE_REQUIRES_IEEE_STRICT_COMPILING\n"; - } - - out << "#ifdef ANGLE_ENABLE_LOOP_FLATTEN\n" - "#define LOOP [loop]\n" - "#define FLATTEN [flatten]\n" - "#else\n" - "#define LOOP\n" - "#define FLATTEN\n" - "#endif\n"; - - if (mShaderType == GL_FRAGMENT_SHADER) - { - const bool usingMRTExtension = - IsExtensionEnabled(mExtensionBehavior, TExtension::EXT_draw_buffers); - - out << "// Varyings\n"; - out << varyings; - out << "\n"; - - if (mShaderVersion >= 300) - { - for (ReferencedSymbols::const_iterator outputVariableIt = - mReferencedOutputVariables.begin(); - outputVariableIt != mReferencedOutputVariables.end(); outputVariableIt++) - { - const TString &variableName = outputVariableIt->first; - const TType &variableType = outputVariableIt->second->getType(); - - out << "static " + TypeString(variableType) + " out_" + variableName + - ArrayString(variableType) + " = " + initializer(variableType) + ";\n"; - } - } - else - { - const unsigned int numColorValues = usingMRTExtension ? mNumRenderTargets : 1; - - out << "static float4 gl_Color[" << numColorValues << "] =\n" - "{\n"; - for (unsigned int i = 0; i < numColorValues; i++) - { - out << " float4(0, 0, 0, 0)"; - if (i + 1 != numColorValues) - { - out << ","; - } - out << "\n"; - } - - out << "};\n"; - } - - if (mUsesFragDepth) - { - out << "static float gl_Depth = 0.0;\n"; - } - - if (mUsesFragCoord) - { - out << "static float4 gl_FragCoord = float4(0, 0, 0, 0);\n"; - } - - if (mUsesPointCoord) - { - out << "static float2 gl_PointCoord = float2(0.5, 0.5);\n"; - } - - if (mUsesFrontFacing) - { - out << "static bool gl_FrontFacing = false;\n"; - } - - out << "\n"; - - if (mUsesDepthRange) - { - out << "struct gl_DepthRangeParameters\n" - "{\n" - " float near;\n" - " float far;\n" - " float diff;\n" - "};\n" - "\n"; - } - - if (mOutputType == SH_HLSL_4_1_OUTPUT || mOutputType == SH_HLSL_4_0_FL9_3_OUTPUT) - { - out << "cbuffer DriverConstants : register(b1)\n" - "{\n"; - - if (mUsesDepthRange) - { - out << " float3 dx_DepthRange : packoffset(c0);\n"; - } - - if (mUsesFragCoord) - { - out << " float4 dx_ViewCoords : packoffset(c1);\n"; - } - - if (mUsesFragCoord || mUsesFrontFacing) - { - out << " float3 dx_DepthFront : packoffset(c2);\n"; - } - - if (mUsesFragCoord) - { - // dx_ViewScale is only used in the fragment shader to correct - // the value for glFragCoord if necessary - out << " float2 dx_ViewScale : packoffset(c3);\n"; - } - - if (mHasMultiviewExtensionEnabled) - { - // We have to add a value which we can use to keep track of which multi-view code - // path is to be selected in the GS. - out << " float multiviewSelectViewportIndex : packoffset(c3.z);\n"; - } - - if (mOutputType == SH_HLSL_4_1_OUTPUT) - { - mUniformHLSL->samplerMetadataUniforms(out, "c4"); - } - - out << "};\n"; - } - else - { - if (mUsesDepthRange) - { - out << "uniform float3 dx_DepthRange : register(c0);"; - } - - if (mUsesFragCoord) - { - out << "uniform float4 dx_ViewCoords : register(c1);\n"; - } - - if (mUsesFragCoord || mUsesFrontFacing) - { - out << "uniform float3 dx_DepthFront : register(c2);\n"; - } - } - - out << "\n"; - - if (mUsesDepthRange) - { - out << "static gl_DepthRangeParameters gl_DepthRange = {dx_DepthRange.x, " - "dx_DepthRange.y, dx_DepthRange.z};\n" - "\n"; - } - - if (!mappedStructs.empty()) - { - out << "// Structures from std140 blocks with padding removed\n"; - out << "\n"; - out << mappedStructs; - out << "\n"; - } - - if (usingMRTExtension && mNumRenderTargets > 1) - { - out << "#define GL_USES_MRT\n"; - } - - if (mUsesFragColor) - { - out << "#define GL_USES_FRAG_COLOR\n"; - } - - if (mUsesFragData) - { - out << "#define GL_USES_FRAG_DATA\n"; - } - } - else if (mShaderType == GL_VERTEX_SHADER) - { - out << "// Attributes\n"; - out << attributes; - out << "\n" - "static float4 gl_Position = float4(0, 0, 0, 0);\n"; - - if (mUsesPointSize) - { - out << "static float gl_PointSize = float(1);\n"; - } - - if (mUsesInstanceID) - { - out << "static int gl_InstanceID;"; - } - - if (mUsesVertexID) - { - out << "static int gl_VertexID;"; - } - - out << "\n" - "// Varyings\n"; - out << varyings; - out << "\n"; - - if (mUsesDepthRange) - { - out << "struct gl_DepthRangeParameters\n" - "{\n" - " float near;\n" - " float far;\n" - " float diff;\n" - "};\n" - "\n"; - } - - if (mOutputType == SH_HLSL_4_1_OUTPUT || mOutputType == SH_HLSL_4_0_FL9_3_OUTPUT) - { - out << "cbuffer DriverConstants : register(b1)\n" - "{\n"; - - if (mUsesDepthRange) - { - out << " float3 dx_DepthRange : packoffset(c0);\n"; - } - - // dx_ViewAdjust and dx_ViewCoords will only be used in Feature Level 9 - // shaders. However, we declare it for all shaders (including Feature Level 10+). - // The bytecode is the same whether we declare it or not, since D3DCompiler removes it - // if it's unused. - out << " float4 dx_ViewAdjust : packoffset(c1);\n"; - out << " float2 dx_ViewCoords : packoffset(c2);\n"; - out << " float2 dx_ViewScale : packoffset(c3);\n"; - - if (mHasMultiviewExtensionEnabled) - { - // We have to add a value which we can use to keep track of which multi-view code - // path is to be selected in the GS. - out << " float multiviewSelectViewportIndex : packoffset(c3.z);\n"; - } - - if (mOutputType == SH_HLSL_4_1_OUTPUT) - { - mUniformHLSL->samplerMetadataUniforms(out, "c4"); - } - - out << "};\n" - "\n"; - } - else - { - if (mUsesDepthRange) - { - out << "uniform float3 dx_DepthRange : register(c0);\n"; - } - - out << "uniform float4 dx_ViewAdjust : register(c1);\n"; - out << "uniform float2 dx_ViewCoords : register(c2);\n" - "\n"; - } - - if (mUsesDepthRange) - { - out << "static gl_DepthRangeParameters gl_DepthRange = {dx_DepthRange.x, " - "dx_DepthRange.y, dx_DepthRange.z};\n" - "\n"; - } - - if (!mappedStructs.empty()) - { - out << "// Structures from std140 blocks with padding removed\n"; - out << "\n"; - out << mappedStructs; - out << "\n"; - } - } - else // Compute shader - { - ASSERT(mShaderType == GL_COMPUTE_SHADER); - - out << "cbuffer DriverConstants : register(b1)\n" - "{\n"; - if (mUsesNumWorkGroups) - { - out << " uint3 gl_NumWorkGroups : packoffset(c0);\n"; - } - ASSERT(mOutputType == SH_HLSL_4_1_OUTPUT); - mUniformHLSL->samplerMetadataUniforms(out, "c1"); - out << "};\n"; - - // Follow built-in variables would be initialized in - // DynamicHLSL::generateComputeShaderLinkHLSL, if they - // are used in compute shader. - if (mUsesWorkGroupID) - { - out << "static uint3 gl_WorkGroupID = uint3(0, 0, 0);\n"; - } - - if (mUsesLocalInvocationID) - { - out << "static uint3 gl_LocalInvocationID = uint3(0, 0, 0);\n"; - } - - if (mUsesGlobalInvocationID) - { - out << "static uint3 gl_GlobalInvocationID = uint3(0, 0, 0);\n"; - } - - if (mUsesLocalInvocationIndex) - { - out << "static uint gl_LocalInvocationIndex = uint(0);\n"; - } - } - - bool getDimensionsIgnoresBaseLevel = - (mCompileOptions & SH_HLSL_GET_DIMENSIONS_IGNORES_BASE_LEVEL) != 0; - mTextureFunctionHLSL->textureFunctionHeader(out, mOutputType, getDimensionsIgnoresBaseLevel); - mImageFunctionHLSL->imageFunctionHeader(out); - - if (mUsesFragCoord) - { - out << "#define GL_USES_FRAG_COORD\n"; - } - - if (mUsesPointCoord) - { - out << "#define GL_USES_POINT_COORD\n"; - } - - if (mUsesFrontFacing) - { - out << "#define GL_USES_FRONT_FACING\n"; - } - - if (mUsesPointSize) - { - out << "#define GL_USES_POINT_SIZE\n"; - } - - if (mHasMultiviewExtensionEnabled) - { - out << "#define GL_ANGLE_MULTIVIEW_ENABLED\n"; - } - - if (mUsesViewID) - { - out << "#define GL_USES_VIEW_ID\n"; - } - - if (mUsesFragDepth) - { - out << "#define GL_USES_FRAG_DEPTH\n"; - } - - if (mUsesDepthRange) - { - out << "#define GL_USES_DEPTH_RANGE\n"; - } - - if (mUsesNumWorkGroups) - { - out << "#define GL_USES_NUM_WORK_GROUPS\n"; - } - - if (mUsesWorkGroupID) - { - out << "#define GL_USES_WORK_GROUP_ID\n"; - } - - if (mUsesLocalInvocationID) - { - out << "#define GL_USES_LOCAL_INVOCATION_ID\n"; - } - - if (mUsesGlobalInvocationID) - { - out << "#define GL_USES_GLOBAL_INVOCATION_ID\n"; - } - - if (mUsesLocalInvocationIndex) - { - out << "#define GL_USES_LOCAL_INVOCATION_INDEX\n"; - } - - if (mUsesXor) - { - out << "bool xor(bool p, bool q)\n" - "{\n" - " return (p || q) && !(p && q);\n" - "}\n" - "\n"; - } - - builtInFunctionEmulator->outputEmulatedFunctions(out); -} - -void OutputHLSL::visitSymbol(TIntermSymbol *node) -{ - TInfoSinkBase &out = getInfoSink(); - - // Handle accessing std140 structs by value - if (IsInStd140InterfaceBlock(node) && node->getBasicType() == EbtStruct) - { - out << "map"; - } - - TString name = node->getSymbol(); - - if (name == "gl_DepthRange") - { - mUsesDepthRange = true; - out << name; - } - else - { - const TType &nodeType = node->getType(); - TQualifier qualifier = node->getQualifier(); - - ensureStructDefined(nodeType); - - if (qualifier == EvqUniform) - { - const TInterfaceBlock *interfaceBlock = nodeType.getInterfaceBlock(); - - if (interfaceBlock) - { - mReferencedUniformBlocks[interfaceBlock->name()] = node; - } - else - { - mReferencedUniforms[name] = node; - } - - out << DecorateVariableIfNeeded(node->getName()); - } - else if (qualifier == EvqAttribute || qualifier == EvqVertexIn) - { - mReferencedAttributes[name] = node; - out << Decorate(name); - } - else if (IsVarying(qualifier)) - { - mReferencedVaryings[name] = node; - out << Decorate(name); - if (name == "ViewID_OVR") - { - mUsesViewID = true; - } - } - else if (qualifier == EvqFragmentOut) - { - mReferencedOutputVariables[name] = node; - out << "out_" << name; - } - else if (qualifier == EvqFragColor) - { - out << "gl_Color[0]"; - mUsesFragColor = true; - } - else if (qualifier == EvqFragData) - { - out << "gl_Color"; - mUsesFragData = true; - } - else if (qualifier == EvqFragCoord) - { - mUsesFragCoord = true; - out << name; - } - else if (qualifier == EvqPointCoord) - { - mUsesPointCoord = true; - out << name; - } - else if (qualifier == EvqFrontFacing) - { - mUsesFrontFacing = true; - out << name; - } - else if (qualifier == EvqPointSize) - { - mUsesPointSize = true; - out << name; - } - else if (qualifier == EvqInstanceID) - { - mUsesInstanceID = true; - out << name; - } - else if (qualifier == EvqVertexID) - { - mUsesVertexID = true; - out << name; - } - else if (name == "gl_FragDepthEXT" || name == "gl_FragDepth") - { - mUsesFragDepth = true; - out << "gl_Depth"; - } - else if (qualifier == EvqNumWorkGroups) - { - mUsesNumWorkGroups = true; - out << name; - } - else if (qualifier == EvqWorkGroupID) - { - mUsesWorkGroupID = true; - out << name; - } - else if (qualifier == EvqLocalInvocationID) - { - mUsesLocalInvocationID = true; - out << name; - } - else if (qualifier == EvqGlobalInvocationID) - { - mUsesGlobalInvocationID = true; - out << name; - } - else if (qualifier == EvqLocalInvocationIndex) - { - mUsesLocalInvocationIndex = true; - out << name; - } - else - { - out << DecorateVariableIfNeeded(node->getName()); - } - } -} - -void OutputHLSL::visitRaw(TIntermRaw *node) -{ - getInfoSink() << node->getRawText(); -} - -void OutputHLSL::outputEqual(Visit visit, const TType &type, TOperator op, TInfoSinkBase &out) -{ - if (type.isScalar() && !type.isArray()) - { - if (op == EOpEqual) - { - outputTriplet(out, visit, "(", " == ", ")"); - } - else - { - outputTriplet(out, visit, "(", " != ", ")"); - } - } - else - { - if (visit == PreVisit && op == EOpNotEqual) - { - out << "!"; - } - - if (type.isArray()) - { - const TString &functionName = addArrayEqualityFunction(type); - outputTriplet(out, visit, (functionName + "(").c_str(), ", ", ")"); - } - else if (type.getBasicType() == EbtStruct) - { - const TStructure &structure = *type.getStruct(); - const TString &functionName = addStructEqualityFunction(structure); - outputTriplet(out, visit, (functionName + "(").c_str(), ", ", ")"); - } - else - { - ASSERT(type.isMatrix() || type.isVector()); - outputTriplet(out, visit, "all(", " == ", ")"); - } - } -} - -void OutputHLSL::outputAssign(Visit visit, const TType &type, TInfoSinkBase &out) -{ - if (type.isArray()) - { - const TString &functionName = addArrayAssignmentFunction(type); - outputTriplet(out, visit, (functionName + "(").c_str(), ", ", ")"); - } - else - { - outputTriplet(out, visit, "(", " = ", ")"); - } -} - -bool OutputHLSL::ancestorEvaluatesToSamplerInStruct() -{ - for (unsigned int n = 0u; getAncestorNode(n) != nullptr; ++n) - { - TIntermNode *ancestor = getAncestorNode(n); - const TIntermBinary *ancestorBinary = ancestor->getAsBinaryNode(); - if (ancestorBinary == nullptr) - { - return false; - } - switch (ancestorBinary->getOp()) - { - case EOpIndexDirectStruct: - { - const TStructure *structure = ancestorBinary->getLeft()->getType().getStruct(); - const TIntermConstantUnion *index = - ancestorBinary->getRight()->getAsConstantUnion(); - const TField *field = structure->fields()[index->getIConst(0)]; - if (IsSampler(field->type()->getBasicType())) - { - return true; - } - break; - } - case EOpIndexDirect: - break; - default: - // Returning a sampler from indirect indexing is not supported. - return false; - } - } - return false; -} - -bool OutputHLSL::visitSwizzle(Visit visit, TIntermSwizzle *node) -{ - TInfoSinkBase &out = getInfoSink(); - if (visit == PostVisit) - { - out << "."; - node->writeOffsetsAsXYZW(&out); - } - return true; -} - -bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node) -{ - TInfoSinkBase &out = getInfoSink(); - - switch (node->getOp()) - { - case EOpComma: - outputTriplet(out, visit, "(", ", ", ")"); - break; - case EOpAssign: - if (node->isArray()) - { - TIntermAggregate *rightAgg = node->getRight()->getAsAggregate(); - if (rightAgg != nullptr && rightAgg->isConstructor()) - { - const TString &functionName = addArrayConstructIntoFunction(node->getType()); - out << functionName << "("; - node->getLeft()->traverse(this); - TIntermSequence *seq = rightAgg->getSequence(); - for (auto &arrayElement : *seq) - { - out << ", "; - arrayElement->traverse(this); - } - out << ")"; - return false; - } - // ArrayReturnValueToOutParameter should have eliminated expressions where a - // function call is assigned. - ASSERT(rightAgg == nullptr); - } - outputAssign(visit, node->getType(), out); - break; - case EOpInitialize: - if (visit == PreVisit) - { - TIntermSymbol *symbolNode = node->getLeft()->getAsSymbolNode(); - ASSERT(symbolNode); - TIntermTyped *expression = node->getRight(); - - // Global initializers must be constant at this point. - ASSERT(symbolNode->getQualifier() != EvqGlobal || - canWriteAsHLSLLiteral(expression)); - - // GLSL allows to write things like "float x = x;" where a new variable x is defined - // and the value of an existing variable x is assigned. HLSL uses C semantics (the - // new variable is created before the assignment is evaluated), so we need to - // convert - // this to "float t = x, x = t;". - if (writeSameSymbolInitializer(out, symbolNode, expression)) - { - // Skip initializing the rest of the expression - return false; - } - else if (writeConstantInitialization(out, symbolNode, expression)) - { - return false; - } - } - else if (visit == InVisit) - { - out << " = "; - } - break; - case EOpAddAssign: - outputTriplet(out, visit, "(", " += ", ")"); - break; - case EOpSubAssign: - outputTriplet(out, visit, "(", " -= ", ")"); - break; - case EOpMulAssign: - outputTriplet(out, visit, "(", " *= ", ")"); - break; - case EOpVectorTimesScalarAssign: - outputTriplet(out, visit, "(", " *= ", ")"); - break; - case EOpMatrixTimesScalarAssign: - outputTriplet(out, visit, "(", " *= ", ")"); - break; - case EOpVectorTimesMatrixAssign: - if (visit == PreVisit) - { - out << "("; - } - else if (visit == InVisit) - { - out << " = mul("; - node->getLeft()->traverse(this); - out << ", transpose("; - } - else - { - out << ")))"; - } - break; - case EOpMatrixTimesMatrixAssign: - if (visit == PreVisit) - { - out << "("; - } - else if (visit == InVisit) - { - out << " = transpose(mul(transpose("; - node->getLeft()->traverse(this); - out << "), transpose("; - } - else - { - out << "))))"; - } - break; - case EOpDivAssign: - outputTriplet(out, visit, "(", " /= ", ")"); - break; - case EOpIModAssign: - outputTriplet(out, visit, "(", " %= ", ")"); - break; - case EOpBitShiftLeftAssign: - outputTriplet(out, visit, "(", " <<= ", ")"); - break; - case EOpBitShiftRightAssign: - outputTriplet(out, visit, "(", " >>= ", ")"); - break; - case EOpBitwiseAndAssign: - outputTriplet(out, visit, "(", " &= ", ")"); - break; - case EOpBitwiseXorAssign: - outputTriplet(out, visit, "(", " ^= ", ")"); - break; - case EOpBitwiseOrAssign: - outputTriplet(out, visit, "(", " |= ", ")"); - break; - case EOpIndexDirect: - { - const TType &leftType = node->getLeft()->getType(); - if (leftType.isInterfaceBlock()) - { - if (visit == PreVisit) - { - TInterfaceBlock *interfaceBlock = leftType.getInterfaceBlock(); - const int arrayIndex = node->getRight()->getAsConstantUnion()->getIConst(0); - mReferencedUniformBlocks[interfaceBlock->instanceName()] = - node->getLeft()->getAsSymbolNode(); - out << mUniformHLSL->uniformBlockInstanceString(*interfaceBlock, arrayIndex); - return false; - } - } - else if (ancestorEvaluatesToSamplerInStruct()) - { - // All parts of an expression that access a sampler in a struct need to use _ as - // separator to access the sampler variable that has been moved out of the struct. - outputTriplet(out, visit, "", "_", ""); - } - else - { - outputTriplet(out, visit, "", "[", "]"); - } - } - break; - case EOpIndexIndirect: - // We do not currently support indirect references to interface blocks - ASSERT(node->getLeft()->getBasicType() != EbtInterfaceBlock); - outputTriplet(out, visit, "", "[", "]"); - break; - case EOpIndexDirectStruct: - { - const TStructure *structure = node->getLeft()->getType().getStruct(); - const TIntermConstantUnion *index = node->getRight()->getAsConstantUnion(); - const TField *field = structure->fields()[index->getIConst(0)]; - - // In cases where indexing returns a sampler, we need to access the sampler variable - // that has been moved out of the struct. - bool indexingReturnsSampler = IsSampler(field->type()->getBasicType()); - if (visit == PreVisit && indexingReturnsSampler) - { - // Samplers extracted from structs have "angle" prefix to avoid name conflicts. - // This prefix is only output at the beginning of the indexing expression, which - // may have multiple parts. - out << "angle"; - } - if (!indexingReturnsSampler) - { - // All parts of an expression that access a sampler in a struct need to use _ as - // separator to access the sampler variable that has been moved out of the struct. - indexingReturnsSampler = ancestorEvaluatesToSamplerInStruct(); - } - if (visit == InVisit) - { - if (indexingReturnsSampler) - { - out << "_" + field->name(); - } - else - { - out << "." + DecorateField(field->name(), *structure); - } - - return false; - } - } - break; - case EOpIndexDirectInterfaceBlock: - { - bool structInStd140Block = - node->getBasicType() == EbtStruct && IsInStd140InterfaceBlock(node->getLeft()); - if (visit == PreVisit && structInStd140Block) - { - out << "map"; - } - if (visit == InVisit) - { - const TInterfaceBlock *interfaceBlock = - node->getLeft()->getType().getInterfaceBlock(); - const TIntermConstantUnion *index = node->getRight()->getAsConstantUnion(); - const TField *field = interfaceBlock->fields()[index->getIConst(0)]; - if (structInStd140Block) - { - out << "_"; - } - else - { - out << "."; - } - out << Decorate(field->name()); - - return false; - } - break; - } - case EOpAdd: - outputTriplet(out, visit, "(", " + ", ")"); - break; - case EOpSub: - outputTriplet(out, visit, "(", " - ", ")"); - break; - case EOpMul: - outputTriplet(out, visit, "(", " * ", ")"); - break; - case EOpDiv: - outputTriplet(out, visit, "(", " / ", ")"); - break; - case EOpIMod: - outputTriplet(out, visit, "(", " % ", ")"); - break; - case EOpBitShiftLeft: - outputTriplet(out, visit, "(", " << ", ")"); - break; - case EOpBitShiftRight: - outputTriplet(out, visit, "(", " >> ", ")"); - break; - case EOpBitwiseAnd: - outputTriplet(out, visit, "(", " & ", ")"); - break; - case EOpBitwiseXor: - outputTriplet(out, visit, "(", " ^ ", ")"); - break; - case EOpBitwiseOr: - outputTriplet(out, visit, "(", " | ", ")"); - break; - case EOpEqual: - case EOpNotEqual: - outputEqual(visit, node->getLeft()->getType(), node->getOp(), out); - break; - case EOpLessThan: - outputTriplet(out, visit, "(", " < ", ")"); - break; - case EOpGreaterThan: - outputTriplet(out, visit, "(", " > ", ")"); - break; - case EOpLessThanEqual: - outputTriplet(out, visit, "(", " <= ", ")"); - break; - case EOpGreaterThanEqual: - outputTriplet(out, visit, "(", " >= ", ")"); - break; - case EOpVectorTimesScalar: - outputTriplet(out, visit, "(", " * ", ")"); - break; - case EOpMatrixTimesScalar: - outputTriplet(out, visit, "(", " * ", ")"); - break; - case EOpVectorTimesMatrix: - outputTriplet(out, visit, "mul(", ", transpose(", "))"); - break; - case EOpMatrixTimesVector: - outputTriplet(out, visit, "mul(transpose(", "), ", ")"); - break; - case EOpMatrixTimesMatrix: - outputTriplet(out, visit, "transpose(mul(transpose(", "), transpose(", ")))"); - break; - case EOpLogicalOr: - // HLSL doesn't short-circuit ||, so we assume that || affected by short-circuiting have - // been unfolded. - ASSERT(!node->getRight()->hasSideEffects()); - outputTriplet(out, visit, "(", " || ", ")"); - return true; - case EOpLogicalXor: - mUsesXor = true; - outputTriplet(out, visit, "xor(", ", ", ")"); - break; - case EOpLogicalAnd: - // HLSL doesn't short-circuit &&, so we assume that && affected by short-circuiting have - // been unfolded. - ASSERT(!node->getRight()->hasSideEffects()); - outputTriplet(out, visit, "(", " && ", ")"); - return true; - default: - UNREACHABLE(); - } - - return true; -} - -bool OutputHLSL::visitUnary(Visit visit, TIntermUnary *node) -{ - TInfoSinkBase &out = getInfoSink(); - - switch (node->getOp()) - { - case EOpNegative: - outputTriplet(out, visit, "(-", "", ")"); - break; - case EOpPositive: - outputTriplet(out, visit, "(+", "", ")"); - break; - case EOpLogicalNot: - outputTriplet(out, visit, "(!", "", ")"); - break; - case EOpBitwiseNot: - outputTriplet(out, visit, "(~", "", ")"); - break; - case EOpPostIncrement: - outputTriplet(out, visit, "(", "", "++)"); - break; - case EOpPostDecrement: - outputTriplet(out, visit, "(", "", "--)"); - break; - case EOpPreIncrement: - outputTriplet(out, visit, "(++", "", ")"); - break; - case EOpPreDecrement: - outputTriplet(out, visit, "(--", "", ")"); - break; - case EOpRadians: - outputTriplet(out, visit, "radians(", "", ")"); - break; - case EOpDegrees: - outputTriplet(out, visit, "degrees(", "", ")"); - break; - case EOpSin: - outputTriplet(out, visit, "sin(", "", ")"); - break; - case EOpCos: - outputTriplet(out, visit, "cos(", "", ")"); - break; - case EOpTan: - outputTriplet(out, visit, "tan(", "", ")"); - break; - case EOpAsin: - outputTriplet(out, visit, "asin(", "", ")"); - break; - case EOpAcos: - outputTriplet(out, visit, "acos(", "", ")"); - break; - case EOpAtan: - outputTriplet(out, visit, "atan(", "", ")"); - break; - case EOpSinh: - outputTriplet(out, visit, "sinh(", "", ")"); - break; - case EOpCosh: - outputTriplet(out, visit, "cosh(", "", ")"); - break; - case EOpTanh: - outputTriplet(out, visit, "tanh(", "", ")"); - break; - case EOpAsinh: - case EOpAcosh: - case EOpAtanh: - ASSERT(node->getUseEmulatedFunction()); - writeEmulatedFunctionTriplet(out, visit, node->getOp()); - break; - case EOpExp: - outputTriplet(out, visit, "exp(", "", ")"); - break; - case EOpLog: - outputTriplet(out, visit, "log(", "", ")"); - break; - case EOpExp2: - outputTriplet(out, visit, "exp2(", "", ")"); - break; - case EOpLog2: - outputTriplet(out, visit, "log2(", "", ")"); - break; - case EOpSqrt: - outputTriplet(out, visit, "sqrt(", "", ")"); - break; - case EOpInverseSqrt: - outputTriplet(out, visit, "rsqrt(", "", ")"); - break; - case EOpAbs: - outputTriplet(out, visit, "abs(", "", ")"); - break; - case EOpSign: - outputTriplet(out, visit, "sign(", "", ")"); - break; - case EOpFloor: - outputTriplet(out, visit, "floor(", "", ")"); - break; - case EOpTrunc: - outputTriplet(out, visit, "trunc(", "", ")"); - break; - case EOpRound: - outputTriplet(out, visit, "round(", "", ")"); - break; - case EOpRoundEven: - ASSERT(node->getUseEmulatedFunction()); - writeEmulatedFunctionTriplet(out, visit, node->getOp()); - break; - case EOpCeil: - outputTriplet(out, visit, "ceil(", "", ")"); - break; - case EOpFract: - outputTriplet(out, visit, "frac(", "", ")"); - break; - case EOpIsNan: - if (node->getUseEmulatedFunction()) - writeEmulatedFunctionTriplet(out, visit, node->getOp()); - else - outputTriplet(out, visit, "isnan(", "", ")"); - mRequiresIEEEStrictCompiling = true; - break; - case EOpIsInf: - outputTriplet(out, visit, "isinf(", "", ")"); - break; - case EOpFloatBitsToInt: - outputTriplet(out, visit, "asint(", "", ")"); - break; - case EOpFloatBitsToUint: - outputTriplet(out, visit, "asuint(", "", ")"); - break; - case EOpIntBitsToFloat: - outputTriplet(out, visit, "asfloat(", "", ")"); - break; - case EOpUintBitsToFloat: - outputTriplet(out, visit, "asfloat(", "", ")"); - break; - case EOpPackSnorm2x16: - case EOpPackUnorm2x16: - case EOpPackHalf2x16: - case EOpUnpackSnorm2x16: - case EOpUnpackUnorm2x16: - case EOpUnpackHalf2x16: - case EOpPackUnorm4x8: - case EOpPackSnorm4x8: - case EOpUnpackUnorm4x8: - case EOpUnpackSnorm4x8: - ASSERT(node->getUseEmulatedFunction()); - writeEmulatedFunctionTriplet(out, visit, node->getOp()); - break; - case EOpLength: - outputTriplet(out, visit, "length(", "", ")"); - break; - case EOpNormalize: - outputTriplet(out, visit, "normalize(", "", ")"); - break; - case EOpDFdx: - if (mInsideDiscontinuousLoop || mOutputLod0Function) - { - outputTriplet(out, visit, "(", "", ", 0.0)"); - } - else - { - outputTriplet(out, visit, "ddx(", "", ")"); - } - break; - case EOpDFdy: - if (mInsideDiscontinuousLoop || mOutputLod0Function) - { - outputTriplet(out, visit, "(", "", ", 0.0)"); - } - else - { - outputTriplet(out, visit, "ddy(", "", ")"); - } - break; - case EOpFwidth: - if (mInsideDiscontinuousLoop || mOutputLod0Function) - { - outputTriplet(out, visit, "(", "", ", 0.0)"); - } - else - { - outputTriplet(out, visit, "fwidth(", "", ")"); - } - break; - case EOpTranspose: - outputTriplet(out, visit, "transpose(", "", ")"); - break; - case EOpDeterminant: - outputTriplet(out, visit, "determinant(transpose(", "", "))"); - break; - case EOpInverse: - ASSERT(node->getUseEmulatedFunction()); - writeEmulatedFunctionTriplet(out, visit, node->getOp()); - break; - - case EOpAny: - outputTriplet(out, visit, "any(", "", ")"); - break; - case EOpAll: - outputTriplet(out, visit, "all(", "", ")"); - break; - case EOpLogicalNotComponentWise: - outputTriplet(out, visit, "(!", "", ")"); - break; - case EOpBitfieldReverse: - outputTriplet(out, visit, "reversebits(", "", ")"); - break; - case EOpBitCount: - outputTriplet(out, visit, "countbits(", "", ")"); - break; - case EOpFindLSB: - // Note that it's unclear from the HLSL docs what this returns for 0, but this is tested - // in GLSLTest and results are consistent with GL. - outputTriplet(out, visit, "firstbitlow(", "", ")"); - break; - case EOpFindMSB: - // Note that it's unclear from the HLSL docs what this returns for 0 or -1, but this is - // tested in GLSLTest and results are consistent with GL. - outputTriplet(out, visit, "firstbithigh(", "", ")"); - break; - default: - UNREACHABLE(); - } - - return true; -} - -TString OutputHLSL::samplerNamePrefixFromStruct(TIntermTyped *node) -{ - if (node->getAsSymbolNode()) - { - return node->getAsSymbolNode()->getSymbol(); - } - TIntermBinary *nodeBinary = node->getAsBinaryNode(); - switch (nodeBinary->getOp()) - { - case EOpIndexDirect: - { - int index = nodeBinary->getRight()->getAsConstantUnion()->getIConst(0); - - TInfoSinkBase prefixSink; - prefixSink << samplerNamePrefixFromStruct(nodeBinary->getLeft()) << "_" << index; - return TString(prefixSink.c_str()); - } - case EOpIndexDirectStruct: - { - const TStructure *s = nodeBinary->getLeft()->getAsTyped()->getType().getStruct(); - int index = nodeBinary->getRight()->getAsConstantUnion()->getIConst(0); - const TField *field = s->fields()[index]; - - TInfoSinkBase prefixSink; - prefixSink << samplerNamePrefixFromStruct(nodeBinary->getLeft()) << "_" - << field->name(); - return TString(prefixSink.c_str()); - } - default: - UNREACHABLE(); - return TString(""); - } -} - -bool OutputHLSL::visitBlock(Visit visit, TIntermBlock *node) -{ - TInfoSinkBase &out = getInfoSink(); - - if (mInsideFunction) - { - outputLineDirective(out, node->getLine().first_line); - out << "{\n"; - } - - for (TIntermNode *statement : *node->getSequence()) - { - outputLineDirective(out, statement->getLine().first_line); - - statement->traverse(this); - - // Don't output ; after case labels, they're terminated by : - // This is needed especially since outputting a ; after a case statement would turn empty - // case statements into non-empty case statements, disallowing fall-through from them. - // Also the output code is clearer if we don't output ; after statements where it is not - // needed: - // * if statements - // * switch statements - // * blocks - // * function definitions - // * loops (do-while loops output the semicolon in VisitLoop) - // * declarations that don't generate output. - if (statement->getAsCaseNode() == nullptr && statement->getAsIfElseNode() == nullptr && - statement->getAsBlock() == nullptr && statement->getAsLoopNode() == nullptr && - statement->getAsSwitchNode() == nullptr && - statement->getAsFunctionDefinition() == nullptr && - (statement->getAsDeclarationNode() == nullptr || - IsDeclarationWrittenOut(statement->getAsDeclarationNode())) && - statement->getAsInvariantDeclarationNode() == nullptr) - { - out << ";\n"; - } - } - - if (mInsideFunction) - { - outputLineDirective(out, node->getLine().last_line); - out << "}\n"; - } - - return false; -} - -bool OutputHLSL::visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) -{ - TInfoSinkBase &out = getInfoSink(); - - ASSERT(mCurrentFunctionMetadata == nullptr); - - size_t index = mCallDag.findIndex(node->getFunctionSymbolInfo()); - ASSERT(index != CallDAG::InvalidIndex); - mCurrentFunctionMetadata = &mASTMetadataList[index]; - - out << TypeString(node->getFunctionPrototype()->getType()) << " "; - - TIntermSequence *parameters = node->getFunctionPrototype()->getSequence(); - - if (node->getFunctionSymbolInfo()->isMain()) - { - out << "gl_main("; - } - else - { - out << DecorateFunctionIfNeeded(node->getFunctionSymbolInfo()->getNameObj()) - << DisambiguateFunctionName(parameters) << (mOutputLod0Function ? "Lod0(" : "("); - } - - for (unsigned int i = 0; i < parameters->size(); i++) - { - TIntermSymbol *symbol = (*parameters)[i]->getAsSymbolNode(); - - if (symbol) - { - ensureStructDefined(symbol->getType()); - - out << argumentString(symbol); - - if (i < parameters->size() - 1) - { - out << ", "; - } - } - else - UNREACHABLE(); - } - - out << ")\n"; - - mInsideFunction = true; - // The function body node will output braces. - node->getBody()->traverse(this); - mInsideFunction = false; - - mCurrentFunctionMetadata = nullptr; - - bool needsLod0 = mASTMetadataList[index].mNeedsLod0; - if (needsLod0 && !mOutputLod0Function && mShaderType == GL_FRAGMENT_SHADER) - { - ASSERT(!node->getFunctionSymbolInfo()->isMain()); - mOutputLod0Function = true; - node->traverse(this); - mOutputLod0Function = false; - } - - return false; -} - -bool OutputHLSL::visitDeclaration(Visit visit, TIntermDeclaration *node) -{ - if (visit == PreVisit) - { - TIntermSequence *sequence = node->getSequence(); - TIntermTyped *variable = (*sequence)[0]->getAsTyped(); - ASSERT(sequence->size() == 1); - ASSERT(variable); - - if (IsDeclarationWrittenOut(node)) - { - TInfoSinkBase &out = getInfoSink(); - ensureStructDefined(variable->getType()); - - if (!variable->getAsSymbolNode() || - variable->getAsSymbolNode()->getSymbol() != "") // Variable declaration - { - if (!mInsideFunction) - { - out << "static "; - } - - out << TypeString(variable->getType()) + " "; - - TIntermSymbol *symbol = variable->getAsSymbolNode(); - - if (symbol) - { - symbol->traverse(this); - out << ArrayString(symbol->getType()); - out << " = " + initializer(symbol->getType()); - } - else - { - variable->traverse(this); - } - } - else if (variable->getAsSymbolNode() && - variable->getAsSymbolNode()->getSymbol() == "") // Type (struct) declaration - { - ASSERT(variable->getBasicType() == EbtStruct); - // ensureStructDefined has already been called. - } - else - UNREACHABLE(); - } - else if (IsVaryingOut(variable->getQualifier())) - { - TIntermSymbol *symbol = variable->getAsSymbolNode(); - ASSERT(symbol); // Varying declarations can't have initializers. - - // Vertex outputs which are declared but not written to should still be declared to - // allow successful linking. - mReferencedVaryings[symbol->getSymbol()] = symbol; - } - } - return false; -} - -bool OutputHLSL::visitInvariantDeclaration(Visit visit, TIntermInvariantDeclaration *node) -{ - // Do not do any translation - return false; -} - -bool OutputHLSL::visitFunctionPrototype(Visit visit, TIntermFunctionPrototype *node) -{ - TInfoSinkBase &out = getInfoSink(); - - ASSERT(visit == PreVisit); - size_t index = mCallDag.findIndex(node->getFunctionSymbolInfo()); - // Skip the prototype if it is not implemented (and thus not used) - if (index == CallDAG::InvalidIndex) - { - return false; - } - - TIntermSequence *arguments = node->getSequence(); - - TString name = DecorateFunctionIfNeeded(node->getFunctionSymbolInfo()->getNameObj()); - out << TypeString(node->getType()) << " " << name << DisambiguateFunctionName(arguments) - << (mOutputLod0Function ? "Lod0(" : "("); - - for (unsigned int i = 0; i < arguments->size(); i++) - { - TIntermSymbol *symbol = (*arguments)[i]->getAsSymbolNode(); - ASSERT(symbol != nullptr); - - out << argumentString(symbol); - - if (i < arguments->size() - 1) - { - out << ", "; - } - } - - out << ");\n"; - - // Also prototype the Lod0 variant if needed - bool needsLod0 = mASTMetadataList[index].mNeedsLod0; - if (needsLod0 && !mOutputLod0Function && mShaderType == GL_FRAGMENT_SHADER) - { - mOutputLod0Function = true; - node->traverse(this); - mOutputLod0Function = false; - } - - return false; -} - -bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) -{ - TInfoSinkBase &out = getInfoSink(); - - switch (node->getOp()) - { - case EOpCallBuiltInFunction: - case EOpCallFunctionInAST: - case EOpCallInternalRawFunction: - { - TIntermSequence *arguments = node->getSequence(); - - bool lod0 = mInsideDiscontinuousLoop || mOutputLod0Function; - if (node->getOp() == EOpCallFunctionInAST) - { - if (node->isArray()) - { - UNIMPLEMENTED(); - } - size_t index = mCallDag.findIndex(node->getFunctionSymbolInfo()); - ASSERT(index != CallDAG::InvalidIndex); - lod0 &= mASTMetadataList[index].mNeedsLod0; - - out << DecorateFunctionIfNeeded(node->getFunctionSymbolInfo()->getNameObj()); - out << DisambiguateFunctionName(node->getSequence()); - out << (lod0 ? "Lod0(" : "("); - } - else if (node->getOp() == EOpCallInternalRawFunction) - { - // This path is used for internal functions that don't have their definitions in the - // AST, such as precision emulation functions. - out << DecorateFunctionIfNeeded(node->getFunctionSymbolInfo()->getNameObj()) << "("; - } - else if (node->getFunctionSymbolInfo()->isImageFunction()) - { - TString name = node->getFunctionSymbolInfo()->getName(); - TType type = (*arguments)[0]->getAsTyped()->getType(); - TString imageFunctionName = mImageFunctionHLSL->useImageFunction( - name, type.getBasicType(), type.getLayoutQualifier().imageInternalFormat, - type.getMemoryQualifier().readonly); - out << imageFunctionName << "("; - } - else - { - const TString &name = node->getFunctionSymbolInfo()->getName(); - TBasicType samplerType = (*arguments)[0]->getAsTyped()->getType().getBasicType(); - int coords = 0; // textureSize(gsampler2DMS) doesn't have a second argument. - if (arguments->size() > 1) - { - coords = (*arguments)[1]->getAsTyped()->getNominalSize(); - } - TString textureFunctionName = mTextureFunctionHLSL->useTextureFunction( - name, samplerType, coords, arguments->size(), lod0, mShaderType); - out << textureFunctionName << "("; - } - - for (TIntermSequence::iterator arg = arguments->begin(); arg != arguments->end(); arg++) - { - TIntermTyped *typedArg = (*arg)->getAsTyped(); - if (mOutputType == SH_HLSL_4_0_FL9_3_OUTPUT && IsSampler(typedArg->getBasicType())) - { - out << "texture_"; - (*arg)->traverse(this); - out << ", sampler_"; - } - - (*arg)->traverse(this); - - if (typedArg->getType().isStructureContainingSamplers()) - { - const TType &argType = typedArg->getType(); - TVector samplerSymbols; - TString structName = samplerNamePrefixFromStruct(typedArg); - argType.createSamplerSymbols("angle_" + structName, "", &samplerSymbols, - nullptr, mSymbolTable); - for (const TIntermSymbol *sampler : samplerSymbols) - { - if (mOutputType == SH_HLSL_4_0_FL9_3_OUTPUT) - { - out << ", texture_" << sampler->getSymbol(); - out << ", sampler_" << sampler->getSymbol(); - } - else - { - // In case of HLSL 4.1+, this symbol is the sampler index, and in case - // of D3D9, it's the sampler variable. - out << ", " + sampler->getSymbol(); - } - } - } - - if (arg < arguments->end() - 1) - { - out << ", "; - } - } - - out << ")"; - - return false; - } - case EOpConstruct: - outputConstructor(out, visit, node); - break; - case EOpEqualComponentWise: - outputTriplet(out, visit, "(", " == ", ")"); - break; - case EOpNotEqualComponentWise: - outputTriplet(out, visit, "(", " != ", ")"); - break; - case EOpLessThanComponentWise: - outputTriplet(out, visit, "(", " < ", ")"); - break; - case EOpGreaterThanComponentWise: - outputTriplet(out, visit, "(", " > ", ")"); - break; - case EOpLessThanEqualComponentWise: - outputTriplet(out, visit, "(", " <= ", ")"); - break; - case EOpGreaterThanEqualComponentWise: - outputTriplet(out, visit, "(", " >= ", ")"); - break; - case EOpMod: - ASSERT(node->getUseEmulatedFunction()); - writeEmulatedFunctionTriplet(out, visit, node->getOp()); - break; - case EOpModf: - outputTriplet(out, visit, "modf(", ", ", ")"); - break; - case EOpPow: - outputTriplet(out, visit, "pow(", ", ", ")"); - break; - case EOpAtan: - ASSERT(node->getSequence()->size() == 2); // atan(x) is a unary operator - ASSERT(node->getUseEmulatedFunction()); - writeEmulatedFunctionTriplet(out, visit, node->getOp()); - break; - case EOpMin: - outputTriplet(out, visit, "min(", ", ", ")"); - break; - case EOpMax: - outputTriplet(out, visit, "max(", ", ", ")"); - break; - case EOpClamp: - outputTriplet(out, visit, "clamp(", ", ", ")"); - break; - case EOpMix: - { - TIntermTyped *lastParamNode = (*(node->getSequence()))[2]->getAsTyped(); - if (lastParamNode->getType().getBasicType() == EbtBool) - { - // There is no HLSL equivalent for ESSL3 built-in "genType mix (genType x, genType - // y, genBType a)", - // so use emulated version. - ASSERT(node->getUseEmulatedFunction()); - writeEmulatedFunctionTriplet(out, visit, node->getOp()); - } - else - { - outputTriplet(out, visit, "lerp(", ", ", ")"); - } - break; - } - case EOpStep: - outputTriplet(out, visit, "step(", ", ", ")"); - break; - case EOpSmoothStep: - outputTriplet(out, visit, "smoothstep(", ", ", ")"); - break; - case EOpFrexp: - case EOpLdexp: - ASSERT(node->getUseEmulatedFunction()); - writeEmulatedFunctionTriplet(out, visit, node->getOp()); - break; - case EOpDistance: - outputTriplet(out, visit, "distance(", ", ", ")"); - break; - case EOpDot: - outputTriplet(out, visit, "dot(", ", ", ")"); - break; - case EOpCross: - outputTriplet(out, visit, "cross(", ", ", ")"); - break; - case EOpFaceforward: - ASSERT(node->getUseEmulatedFunction()); - writeEmulatedFunctionTriplet(out, visit, node->getOp()); - break; - case EOpReflect: - outputTriplet(out, visit, "reflect(", ", ", ")"); - break; - case EOpRefract: - outputTriplet(out, visit, "refract(", ", ", ")"); - break; - case EOpOuterProduct: - ASSERT(node->getUseEmulatedFunction()); - writeEmulatedFunctionTriplet(out, visit, node->getOp()); - break; - case EOpMulMatrixComponentWise: - outputTriplet(out, visit, "(", " * ", ")"); - break; - case EOpBitfieldExtract: - case EOpBitfieldInsert: - case EOpUaddCarry: - case EOpUsubBorrow: - case EOpUmulExtended: - case EOpImulExtended: - ASSERT(node->getUseEmulatedFunction()); - writeEmulatedFunctionTriplet(out, visit, node->getOp()); - break; - default: - UNREACHABLE(); - } - - return true; -} - -void OutputHLSL::writeIfElse(TInfoSinkBase &out, TIntermIfElse *node) -{ - out << "if ("; - - node->getCondition()->traverse(this); - - out << ")\n"; - - outputLineDirective(out, node->getLine().first_line); - - bool discard = false; - - if (node->getTrueBlock()) - { - // The trueBlock child node will output braces. - node->getTrueBlock()->traverse(this); - - // Detect true discard - discard = (discard || FindDiscard::search(node->getTrueBlock())); - } - else - { - // TODO(oetuaho): Check if the semicolon inside is necessary. - // It's there as a result of conservative refactoring of the output. - out << "{;}\n"; - } - - outputLineDirective(out, node->getLine().first_line); - - if (node->getFalseBlock()) - { - out << "else\n"; - - outputLineDirective(out, node->getFalseBlock()->getLine().first_line); - - // The falseBlock child node will output braces. - node->getFalseBlock()->traverse(this); - - outputLineDirective(out, node->getFalseBlock()->getLine().first_line); - - // Detect false discard - discard = (discard || FindDiscard::search(node->getFalseBlock())); - } - - // ANGLE issue 486: Detect problematic conditional discard - if (discard) - { - mUsesDiscardRewriting = true; - } -} - -bool OutputHLSL::visitTernary(Visit, TIntermTernary *) -{ - // Ternary ops should have been already converted to something else in the AST. HLSL ternary - // operator doesn't short-circuit, so it's not the same as the GLSL ternary operator. - UNREACHABLE(); - return false; -} - -bool OutputHLSL::visitIfElse(Visit visit, TIntermIfElse *node) -{ - TInfoSinkBase &out = getInfoSink(); - - ASSERT(mInsideFunction); - - // D3D errors when there is a gradient operation in a loop in an unflattened if. - if (mShaderType == GL_FRAGMENT_SHADER && mCurrentFunctionMetadata->hasGradientLoop(node)) - { - out << "FLATTEN "; - } - - writeIfElse(out, node); - - return false; -} - -bool OutputHLSL::visitSwitch(Visit visit, TIntermSwitch *node) -{ - TInfoSinkBase &out = getInfoSink(); - - ASSERT(node->getStatementList()); - if (visit == PreVisit) - { - node->setStatementList(RemoveSwitchFallThrough(node->getStatementList(), mPerfDiagnostics)); - } - outputTriplet(out, visit, "switch (", ") ", ""); - // The curly braces get written when visiting the statementList block. - return true; -} - -bool OutputHLSL::visitCase(Visit visit, TIntermCase *node) -{ - TInfoSinkBase &out = getInfoSink(); - - if (node->hasCondition()) - { - outputTriplet(out, visit, "case (", "", "):\n"); - return true; - } - else - { - out << "default:\n"; - return false; - } -} - -void OutputHLSL::visitConstantUnion(TIntermConstantUnion *node) -{ - TInfoSinkBase &out = getInfoSink(); - writeConstantUnion(out, node->getType(), node->getUnionArrayPointer()); -} - -bool OutputHLSL::visitLoop(Visit visit, TIntermLoop *node) -{ - mNestedLoopDepth++; - - bool wasDiscontinuous = mInsideDiscontinuousLoop; - mInsideDiscontinuousLoop = - mInsideDiscontinuousLoop || mCurrentFunctionMetadata->mDiscontinuousLoops.count(node) > 0; - - TInfoSinkBase &out = getInfoSink(); - - if (mOutputType == SH_HLSL_3_0_OUTPUT) - { - if (handleExcessiveLoop(out, node)) - { - mInsideDiscontinuousLoop = wasDiscontinuous; - mNestedLoopDepth--; - - return false; - } - } - - const char *unroll = mCurrentFunctionMetadata->hasGradientInCallGraph(node) ? "LOOP" : ""; - if (node->getType() == ELoopDoWhile) - { - out << "{" << unroll << " do\n"; - - outputLineDirective(out, node->getLine().first_line); - } - else - { - out << "{" << unroll << " for("; - - if (node->getInit()) - { - node->getInit()->traverse(this); - } - - out << "; "; - - if (node->getCondition()) - { - node->getCondition()->traverse(this); - } - - out << "; "; - - if (node->getExpression()) - { - node->getExpression()->traverse(this); - } - - out << ")\n"; - - outputLineDirective(out, node->getLine().first_line); - } - - if (node->getBody()) - { - // The loop body node will output braces. - node->getBody()->traverse(this); - } - else - { - // TODO(oetuaho): Check if the semicolon inside is necessary. - // It's there as a result of conservative refactoring of the output. - out << "{;}\n"; - } - - outputLineDirective(out, node->getLine().first_line); - - if (node->getType() == ELoopDoWhile) - { - outputLineDirective(out, node->getCondition()->getLine().first_line); - out << "while ("; - - node->getCondition()->traverse(this); - - out << ");\n"; - } - - out << "}\n"; - - mInsideDiscontinuousLoop = wasDiscontinuous; - mNestedLoopDepth--; - - return false; -} - -bool OutputHLSL::visitBranch(Visit visit, TIntermBranch *node) -{ - if (visit == PreVisit) - { - TInfoSinkBase &out = getInfoSink(); - - switch (node->getFlowOp()) - { - case EOpKill: - out << "discard"; - break; - case EOpBreak: - if (mNestedLoopDepth > 1) - { - mUsesNestedBreak = true; - } - - if (mExcessiveLoopIndex) - { - out << "{Break"; - mExcessiveLoopIndex->traverse(this); - out << " = true; break;}\n"; - } - else - { - out << "break"; - } - break; - case EOpContinue: - out << "continue"; - break; - case EOpReturn: - if (node->getExpression()) - { - out << "return "; - } - else - { - out << "return"; - } - break; - default: - UNREACHABLE(); - } - } - - return true; -} - -// Handle loops with more than 254 iterations (unsupported by D3D9) by splitting them -// (The D3D documentation says 255 iterations, but the compiler complains at anything more than -// 254). -bool OutputHLSL::handleExcessiveLoop(TInfoSinkBase &out, TIntermLoop *node) -{ - const int MAX_LOOP_ITERATIONS = 254; - - // Parse loops of the form: - // for(int index = initial; index [comparator] limit; index += increment) - TIntermSymbol *index = nullptr; - TOperator comparator = EOpNull; - int initial = 0; - int limit = 0; - int increment = 0; - - // Parse index name and intial value - if (node->getInit()) - { - TIntermDeclaration *init = node->getInit()->getAsDeclarationNode(); - - if (init) - { - TIntermSequence *sequence = init->getSequence(); - TIntermTyped *variable = (*sequence)[0]->getAsTyped(); - - if (variable && variable->getQualifier() == EvqTemporary) - { - TIntermBinary *assign = variable->getAsBinaryNode(); - - if (assign->getOp() == EOpInitialize) - { - TIntermSymbol *symbol = assign->getLeft()->getAsSymbolNode(); - TIntermConstantUnion *constant = assign->getRight()->getAsConstantUnion(); - - if (symbol && constant) - { - if (constant->getBasicType() == EbtInt && constant->isScalar()) - { - index = symbol; - initial = constant->getIConst(0); - } - } - } - } - } - } - - // Parse comparator and limit value - if (index != nullptr && node->getCondition()) - { - TIntermBinary *test = node->getCondition()->getAsBinaryNode(); - - if (test && test->getLeft()->getAsSymbolNode()->getId() == index->getId()) - { - TIntermConstantUnion *constant = test->getRight()->getAsConstantUnion(); - - if (constant) - { - if (constant->getBasicType() == EbtInt && constant->isScalar()) - { - comparator = test->getOp(); - limit = constant->getIConst(0); - } - } - } - } - - // Parse increment - if (index != nullptr && comparator != EOpNull && node->getExpression()) - { - TIntermBinary *binaryTerminal = node->getExpression()->getAsBinaryNode(); - TIntermUnary *unaryTerminal = node->getExpression()->getAsUnaryNode(); - - if (binaryTerminal) - { - TOperator op = binaryTerminal->getOp(); - TIntermConstantUnion *constant = binaryTerminal->getRight()->getAsConstantUnion(); - - if (constant) - { - if (constant->getBasicType() == EbtInt && constant->isScalar()) - { - int value = constant->getIConst(0); - - switch (op) - { - case EOpAddAssign: - increment = value; - break; - case EOpSubAssign: - increment = -value; - break; - default: - UNIMPLEMENTED(); - } - } - } - } - else if (unaryTerminal) - { - TOperator op = unaryTerminal->getOp(); - - switch (op) - { - case EOpPostIncrement: - increment = 1; - break; - case EOpPostDecrement: - increment = -1; - break; - case EOpPreIncrement: - increment = 1; - break; - case EOpPreDecrement: - increment = -1; - break; - default: - UNIMPLEMENTED(); - } - } - } - - if (index != nullptr && comparator != EOpNull && increment != 0) - { - if (comparator == EOpLessThanEqual) - { - comparator = EOpLessThan; - limit += 1; - } - - if (comparator == EOpLessThan) - { - int iterations = (limit - initial) / increment; - - if (iterations <= MAX_LOOP_ITERATIONS) - { - return false; // Not an excessive loop - } - - TIntermSymbol *restoreIndex = mExcessiveLoopIndex; - mExcessiveLoopIndex = index; - - out << "{int "; - index->traverse(this); - out << ";\n" - "bool Break"; - index->traverse(this); - out << " = false;\n"; - - bool firstLoopFragment = true; - - while (iterations > 0) - { - int clampedLimit = initial + increment * std::min(MAX_LOOP_ITERATIONS, iterations); - - if (!firstLoopFragment) - { - out << "if (!Break"; - index->traverse(this); - out << ") {\n"; - } - - if (iterations <= MAX_LOOP_ITERATIONS) // Last loop fragment - { - mExcessiveLoopIndex = nullptr; // Stops setting the Break flag - } - - // for(int index = initial; index < clampedLimit; index += increment) - const char *unroll = - mCurrentFunctionMetadata->hasGradientInCallGraph(node) ? "LOOP" : ""; - - out << unroll << " for("; - index->traverse(this); - out << " = "; - out << initial; - - out << "; "; - index->traverse(this); - out << " < "; - out << clampedLimit; - - out << "; "; - index->traverse(this); - out << " += "; - out << increment; - out << ")\n"; - - outputLineDirective(out, node->getLine().first_line); - out << "{\n"; - - if (node->getBody()) - { - node->getBody()->traverse(this); - } - - outputLineDirective(out, node->getLine().first_line); - out << ";}\n"; - - if (!firstLoopFragment) - { - out << "}\n"; - } - - firstLoopFragment = false; - - initial += MAX_LOOP_ITERATIONS * increment; - iterations -= MAX_LOOP_ITERATIONS; - } - - out << "}"; - - mExcessiveLoopIndex = restoreIndex; - - return true; - } - else - UNIMPLEMENTED(); - } - - return false; // Not handled as an excessive loop -} - -void OutputHLSL::outputTriplet(TInfoSinkBase &out, - Visit visit, - const char *preString, - const char *inString, - const char *postString) -{ - if (visit == PreVisit) - { - out << preString; - } - else if (visit == InVisit) - { - out << inString; - } - else if (visit == PostVisit) - { - out << postString; - } -} - -void OutputHLSL::outputLineDirective(TInfoSinkBase &out, int line) -{ - if ((mCompileOptions & SH_LINE_DIRECTIVES) && (line > 0)) - { - out << "\n"; - out << "#line " << line; - - if (mSourcePath) - { - out << " \"" << mSourcePath << "\""; - } - - out << "\n"; - } -} - -TString OutputHLSL::argumentString(const TIntermSymbol *symbol) -{ - TQualifier qualifier = symbol->getQualifier(); - const TType &type = symbol->getType(); - const TName &name = symbol->getName(); - TString nameStr; - - if (name.getString().empty()) // HLSL demands named arguments, also for prototypes - { - nameStr = "x" + str(mUniqueIndex++); - } - else - { - nameStr = DecorateVariableIfNeeded(name); - } - - if (IsSampler(type.getBasicType())) - { - if (mOutputType == SH_HLSL_4_1_OUTPUT) - { - // Samplers are passed as indices to the sampler array. - ASSERT(qualifier != EvqOut && qualifier != EvqInOut); - return "const uint " + nameStr + ArrayString(type); - } - if (mOutputType == SH_HLSL_4_0_FL9_3_OUTPUT) - { - return QualifierString(qualifier) + " " + TextureString(type.getBasicType()) + - " texture_" + nameStr + ArrayString(type) + ", " + QualifierString(qualifier) + - " " + SamplerString(type.getBasicType()) + " sampler_" + nameStr + - ArrayString(type); - } - } - - TStringStream argString; - argString << QualifierString(qualifier) << " " << TypeString(type) << " " << nameStr - << ArrayString(type); - - // If the structure parameter contains samplers, they need to be passed into the function as - // separate parameters. HLSL doesn't natively support samplers in structs. - if (type.isStructureContainingSamplers()) - { - ASSERT(qualifier != EvqOut && qualifier != EvqInOut); - TVector samplerSymbols; - type.createSamplerSymbols("angle" + nameStr, "", &samplerSymbols, nullptr, mSymbolTable); - for (const TIntermSymbol *sampler : samplerSymbols) - { - const TType &samplerType = sampler->getType(); - if (mOutputType == SH_HLSL_4_1_OUTPUT) - { - argString << ", const uint " << sampler->getSymbol() << ArrayString(samplerType); - } - else if (mOutputType == SH_HLSL_4_0_FL9_3_OUTPUT) - { - ASSERT(IsSampler(samplerType.getBasicType())); - argString << ", " << QualifierString(qualifier) << " " - << TextureString(samplerType.getBasicType()) << " texture_" - << sampler->getSymbol() << ArrayString(samplerType) << ", " - << QualifierString(qualifier) << " " - << SamplerString(samplerType.getBasicType()) << " sampler_" - << sampler->getSymbol() << ArrayString(samplerType); - } - else - { - ASSERT(IsSampler(samplerType.getBasicType())); - argString << ", " << QualifierString(qualifier) << " " << TypeString(samplerType) - << " " << sampler->getSymbol() << ArrayString(samplerType); - } - } - } - - return argString.str(); -} - -TString OutputHLSL::initializer(const TType &type) -{ - TString string; - - size_t size = type.getObjectSize(); - for (size_t component = 0; component < size; component++) - { - string += "0"; - - if (component + 1 < size) - { - string += ", "; - } - } - - return "{" + string + "}"; -} - -void OutputHLSL::outputConstructor(TInfoSinkBase &out, Visit visit, TIntermAggregate *node) -{ - // Array constructors should have been already pruned from the code. - ASSERT(!node->getType().isArray()); - - if (visit == PreVisit) - { - TString constructorName; - if (node->getBasicType() == EbtStruct) - { - constructorName = mStructureHLSL->addStructConstructor(*node->getType().getStruct()); - } - else - { - constructorName = - mStructureHLSL->addBuiltInConstructor(node->getType(), node->getSequence()); - } - out << constructorName << "("; - } - else if (visit == InVisit) - { - out << ", "; - } - else if (visit == PostVisit) - { - out << ")"; - } -} - -const TConstantUnion *OutputHLSL::writeConstantUnion(TInfoSinkBase &out, - const TType &type, - const TConstantUnion *const constUnion) -{ - const TConstantUnion *constUnionIterated = constUnion; - - const TStructure *structure = type.getStruct(); - if (structure) - { - out << mStructureHLSL->addStructConstructor(*structure) << "("; - - const TFieldList &fields = structure->fields(); - - for (size_t i = 0; i < fields.size(); i++) - { - const TType *fieldType = fields[i]->type(); - constUnionIterated = writeConstantUnion(out, *fieldType, constUnionIterated); - - if (i != fields.size() - 1) - { - out << ", "; - } - } - - out << ")"; - } - else - { - size_t size = type.getObjectSize(); - bool writeType = size > 1; - - if (writeType) - { - out << TypeString(type) << "("; - } - constUnionIterated = writeConstantUnionArray(out, constUnionIterated, size); - if (writeType) - { - out << ")"; - } - } - - return constUnionIterated; -} - -void OutputHLSL::writeEmulatedFunctionTriplet(TInfoSinkBase &out, Visit visit, TOperator op) -{ - if (visit == PreVisit) - { - const char *opStr = GetOperatorString(op); - BuiltInFunctionEmulator::WriteEmulatedFunctionName(out, opStr); - out << "("; - } - else - { - outputTriplet(out, visit, nullptr, ", ", ")"); - } -} - -bool OutputHLSL::writeSameSymbolInitializer(TInfoSinkBase &out, - TIntermSymbol *symbolNode, - TIntermTyped *expression) -{ - sh::SearchSymbol searchSymbol(symbolNode->getSymbol()); - expression->traverse(&searchSymbol); - - if (searchSymbol.foundMatch()) - { - // Type already printed - out << "t" + str(mUniqueIndex) + " = "; - expression->traverse(this); - out << ", "; - symbolNode->traverse(this); - out << " = t" + str(mUniqueIndex); - - mUniqueIndex++; - return true; - } - - return false; -} - -bool OutputHLSL::canWriteAsHLSLLiteral(TIntermTyped *expression) -{ - // We support writing constant unions and constructors that only take constant unions as - // parameters as HLSL literals. - return !expression->getType().isArrayOfArrays() && - (expression->getAsConstantUnion() || - expression->isConstructorWithOnlyConstantUnionParameters()); -} - -bool OutputHLSL::writeConstantInitialization(TInfoSinkBase &out, - TIntermSymbol *symbolNode, - TIntermTyped *initializer) -{ - if (canWriteAsHLSLLiteral(initializer)) - { - symbolNode->traverse(this); - ASSERT(!symbolNode->getType().isArrayOfArrays()); - if (symbolNode->getType().isArray()) - { - out << "[" << symbolNode->getType().getOutermostArraySize() << "]"; - } - out << " = {"; - if (initializer->getAsConstantUnion()) - { - TIntermConstantUnion *nodeConst = initializer->getAsConstantUnion(); - const TConstantUnion *constUnion = nodeConst->getUnionArrayPointer(); - writeConstantUnionArray(out, constUnion, nodeConst->getType().getObjectSize()); - } - else - { - TIntermAggregate *constructor = initializer->getAsAggregate(); - ASSERT(constructor != nullptr); - for (TIntermNode *&node : *constructor->getSequence()) - { - TIntermConstantUnion *nodeConst = node->getAsConstantUnion(); - ASSERT(nodeConst); - const TConstantUnion *constUnion = nodeConst->getUnionArrayPointer(); - writeConstantUnionArray(out, constUnion, nodeConst->getType().getObjectSize()); - if (node != constructor->getSequence()->back()) - { - out << ", "; - } - } - } - out << "}"; - return true; - } - return false; -} - -TString OutputHLSL::addStructEqualityFunction(const TStructure &structure) -{ - const TFieldList &fields = structure.fields(); - - for (const auto &eqFunction : mStructEqualityFunctions) - { - if (eqFunction->structure == &structure) - { - return eqFunction->functionName; - } - } - - const TString &structNameString = StructNameString(structure); - - StructEqualityFunction *function = new StructEqualityFunction(); - function->structure = &structure; - function->functionName = "angle_eq_" + structNameString; - - TInfoSinkBase fnOut; - - fnOut << "bool " << function->functionName << "(" << structNameString << " a, " - << structNameString + " b)\n" - << "{\n" - " return "; - - for (size_t i = 0; i < fields.size(); i++) - { - const TField *field = fields[i]; - const TType *fieldType = field->type(); - - const TString &fieldNameA = "a." + Decorate(field->name()); - const TString &fieldNameB = "b." + Decorate(field->name()); - - if (i > 0) - { - fnOut << " && "; - } - - fnOut << "("; - outputEqual(PreVisit, *fieldType, EOpEqual, fnOut); - fnOut << fieldNameA; - outputEqual(InVisit, *fieldType, EOpEqual, fnOut); - fnOut << fieldNameB; - outputEqual(PostVisit, *fieldType, EOpEqual, fnOut); - fnOut << ")"; - } - - fnOut << ";\n" - << "}\n"; - - function->functionDefinition = fnOut.c_str(); - - mStructEqualityFunctions.push_back(function); - mEqualityFunctions.push_back(function); - - return function->functionName; -} - -TString OutputHLSL::addArrayEqualityFunction(const TType &type) -{ - for (const auto &eqFunction : mArrayEqualityFunctions) - { - if (eqFunction->type == type) - { - return eqFunction->functionName; - } - } - - TType elementType(type); - elementType.toArrayElementType(); - - ArrayHelperFunction *function = new ArrayHelperFunction(); - function->type = type; - - function->functionName = ArrayHelperFunctionName("angle_eq", type); - - TInfoSinkBase fnOut; - - const TString &typeName = TypeString(type); - fnOut << "bool " << function->functionName << "(" << typeName << " a" << ArrayString(type) - << ", " << typeName << " b" << ArrayString(type) << ")\n" - << "{\n" - " for (int i = 0; i < " - << type.getOutermostArraySize() - << "; ++i)\n" - " {\n" - " if ("; - - outputEqual(PreVisit, elementType, EOpNotEqual, fnOut); - fnOut << "a[i]"; - outputEqual(InVisit, elementType, EOpNotEqual, fnOut); - fnOut << "b[i]"; - outputEqual(PostVisit, elementType, EOpNotEqual, fnOut); - - fnOut << ") { return false; }\n" - " }\n" - " return true;\n" - "}\n"; - - function->functionDefinition = fnOut.c_str(); - - mArrayEqualityFunctions.push_back(function); - mEqualityFunctions.push_back(function); - - return function->functionName; -} - -TString OutputHLSL::addArrayAssignmentFunction(const TType &type) -{ - for (const auto &assignFunction : mArrayAssignmentFunctions) - { - if (assignFunction.type == type) - { - return assignFunction.functionName; - } - } - - TType elementType(type); - elementType.toArrayElementType(); - - ArrayHelperFunction function; - function.type = type; - - function.functionName = ArrayHelperFunctionName("angle_assign", type); - - TInfoSinkBase fnOut; - - const TString &typeName = TypeString(type); - fnOut << "void " << function.functionName << "(out " << typeName << " a" << ArrayString(type) - << ", " << typeName << " b" << ArrayString(type) << ")\n" - << "{\n" - " for (int i = 0; i < " - << type.getOutermostArraySize() - << "; ++i)\n" - " {\n" - " "; - - outputAssign(PreVisit, elementType, fnOut); - fnOut << "a[i]"; - outputAssign(InVisit, elementType, fnOut); - fnOut << "b[i]"; - outputAssign(PostVisit, elementType, fnOut); - - fnOut << ";\n" - " }\n" - "}\n"; - - function.functionDefinition = fnOut.c_str(); - - mArrayAssignmentFunctions.push_back(function); - - return function.functionName; -} - -TString OutputHLSL::addArrayConstructIntoFunction(const TType &type) -{ - for (const auto &constructIntoFunction : mArrayConstructIntoFunctions) - { - if (constructIntoFunction.type == type) - { - return constructIntoFunction.functionName; - } - } - - TType elementType(type); - elementType.toArrayElementType(); - - ArrayHelperFunction function; - function.type = type; - - function.functionName = ArrayHelperFunctionName("angle_construct_into", type); - - TInfoSinkBase fnOut; - - const TString &typeName = TypeString(type); - fnOut << "void " << function.functionName << "(out " << typeName << " a" << ArrayString(type); - for (unsigned int i = 0u; i < type.getOutermostArraySize(); ++i) - { - fnOut << ", " << typeName << " b" << i << ArrayString(elementType); - } - fnOut << ")\n" - "{\n"; - - for (unsigned int i = 0u; i < type.getOutermostArraySize(); ++i) - { - fnOut << " "; - outputAssign(PreVisit, elementType, fnOut); - fnOut << "a[" << i << "]"; - outputAssign(InVisit, elementType, fnOut); - fnOut << "b" << i; - outputAssign(PostVisit, elementType, fnOut); - fnOut << ";\n"; - } - fnOut << "}\n"; - - function.functionDefinition = fnOut.c_str(); - - mArrayConstructIntoFunctions.push_back(function); - - return function.functionName; -} - -void OutputHLSL::ensureStructDefined(const TType &type) -{ - const TStructure *structure = type.getStruct(); - if (structure) - { - ASSERT(type.getBasicType() == EbtStruct); - mStructureHLSL->ensureStructDefined(*structure); - } -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/OutputHLSL.h b/src/3rdparty/angle/src/compiler/translator/OutputHLSL.h deleted file mode 100644 index 014f4f5002..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/OutputHLSL.h +++ /dev/null @@ -1,248 +0,0 @@ -// -// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_TRANSLATOR_OUTPUTHLSL_H_ -#define COMPILER_TRANSLATOR_OUTPUTHLSL_H_ - -#include -#include -#include - -#include "angle_gl.h" -#include "compiler/translator/ASTMetadataHLSL.h" -#include "compiler/translator/Compiler.h" -#include "compiler/translator/FlagStd140Structs.h" -#include "compiler/translator/IntermTraverse.h" - -class BuiltInFunctionEmulator; - -namespace sh -{ -class StructureHLSL; -class TextureFunctionHLSL; -class TSymbolTable; -class ImageFunctionHLSL; -class UnfoldShortCircuit; -class UniformHLSL; - -typedef std::map ReferencedSymbols; - -class OutputHLSL : public TIntermTraverser -{ - public: - OutputHLSL(sh::GLenum shaderType, - int shaderVersion, - const TExtensionBehavior &extensionBehavior, - const char *sourcePath, - ShShaderOutput outputType, - int numRenderTargets, - const std::vector &uniforms, - ShCompileOptions compileOptions, - TSymbolTable *symbolTable, - PerformanceDiagnostics *perfDiagnostics); - - ~OutputHLSL(); - - void output(TIntermNode *treeRoot, TInfoSinkBase &objSink); - - const std::map &getUniformBlockRegisterMap() const; - const std::map &getUniformRegisterMap() const; - - static TString initializer(const TType &type); - - TInfoSinkBase &getInfoSink() - { - ASSERT(!mInfoSinkStack.empty()); - return *mInfoSinkStack.top(); - } - - static bool canWriteAsHLSLLiteral(TIntermTyped *expression); - - protected: - void header(TInfoSinkBase &out, - const std::vector &std140Structs, - const BuiltInFunctionEmulator *builtInFunctionEmulator) const; - - void writeFloat(TInfoSinkBase &out, float f); - void writeSingleConstant(TInfoSinkBase &out, const TConstantUnion *const constUnion); - const TConstantUnion *writeConstantUnionArray(TInfoSinkBase &out, - const TConstantUnion *const constUnion, - const size_t size); - - // Visit AST nodes and output their code to the body stream - void visitSymbol(TIntermSymbol *) override; - void visitRaw(TIntermRaw *) override; - void visitConstantUnion(TIntermConstantUnion *) override; - bool visitSwizzle(Visit visit, TIntermSwizzle *node) override; - bool visitBinary(Visit visit, TIntermBinary *) override; - bool visitUnary(Visit visit, TIntermUnary *) override; - bool visitTernary(Visit visit, TIntermTernary *) override; - bool visitIfElse(Visit visit, TIntermIfElse *) override; - bool visitSwitch(Visit visit, TIntermSwitch *) override; - bool visitCase(Visit visit, TIntermCase *) override; - bool visitFunctionPrototype(Visit visit, TIntermFunctionPrototype *node) override; - bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override; - bool visitAggregate(Visit visit, TIntermAggregate *) override; - bool visitBlock(Visit visit, TIntermBlock *node) override; - bool visitInvariantDeclaration(Visit visit, TIntermInvariantDeclaration *node) override; - bool visitDeclaration(Visit visit, TIntermDeclaration *node) override; - bool visitLoop(Visit visit, TIntermLoop *) override; - bool visitBranch(Visit visit, TIntermBranch *) override; - - bool handleExcessiveLoop(TInfoSinkBase &out, TIntermLoop *node); - - // Emit one of three strings depending on traverse phase. Called with literal strings so using - // const char* instead of TString. - void outputTriplet(TInfoSinkBase &out, - Visit visit, - const char *preString, - const char *inString, - const char *postString); - void outputLineDirective(TInfoSinkBase &out, int line); - TString argumentString(const TIntermSymbol *symbol); - - void outputConstructor(TInfoSinkBase &out, Visit visit, TIntermAggregate *node); - const TConstantUnion *writeConstantUnion(TInfoSinkBase &out, - const TType &type, - const TConstantUnion *constUnion); - - void outputEqual(Visit visit, const TType &type, TOperator op, TInfoSinkBase &out); - void outputAssign(Visit visit, const TType &type, TInfoSinkBase &out); - - void writeEmulatedFunctionTriplet(TInfoSinkBase &out, Visit visit, TOperator op); - - // Returns true if it found a 'same symbol' initializer (initializer that references the - // variable it's initting) - bool writeSameSymbolInitializer(TInfoSinkBase &out, - TIntermSymbol *symbolNode, - TIntermTyped *expression); - // Returns true if variable initializer could be written using literal {} notation. - bool writeConstantInitialization(TInfoSinkBase &out, - TIntermSymbol *symbolNode, - TIntermTyped *expression); - - void writeIfElse(TInfoSinkBase &out, TIntermIfElse *node); - - // Returns the function name - TString addStructEqualityFunction(const TStructure &structure); - TString addArrayEqualityFunction(const TType &type); - TString addArrayAssignmentFunction(const TType &type); - TString addArrayConstructIntoFunction(const TType &type); - - // Ensures if the type is a struct, the struct is defined - void ensureStructDefined(const TType &type); - - sh::GLenum mShaderType; - int mShaderVersion; - const TExtensionBehavior &mExtensionBehavior; - const char *mSourcePath; - const ShShaderOutput mOutputType; - ShCompileOptions mCompileOptions; - - bool mInsideFunction; - - // Output streams - TInfoSinkBase mHeader; - TInfoSinkBase mBody; - TInfoSinkBase mFooter; - - // A stack is useful when we want to traverse in the header, or in helper functions, but not - // always write to the body. Instead use an InfoSink stack to keep our current state intact. - // TODO (jmadill): Just passing an InfoSink in function parameters would be simpler. - std::stack mInfoSinkStack; - - ReferencedSymbols mReferencedUniforms; - ReferencedSymbols mReferencedUniformBlocks; - ReferencedSymbols mReferencedAttributes; - ReferencedSymbols mReferencedVaryings; - ReferencedSymbols mReferencedOutputVariables; - - StructureHLSL *mStructureHLSL; - UniformHLSL *mUniformHLSL; - TextureFunctionHLSL *mTextureFunctionHLSL; - ImageFunctionHLSL *mImageFunctionHLSL; - - // Parameters determining what goes in the header output - bool mUsesFragColor; - bool mUsesFragData; - bool mUsesDepthRange; - bool mUsesFragCoord; - bool mUsesPointCoord; - bool mUsesFrontFacing; - bool mUsesPointSize; - bool mUsesInstanceID; - bool mHasMultiviewExtensionEnabled; - bool mUsesViewID; - bool mUsesVertexID; - bool mUsesFragDepth; - bool mUsesNumWorkGroups; - bool mUsesWorkGroupID; - bool mUsesLocalInvocationID; - bool mUsesGlobalInvocationID; - bool mUsesLocalInvocationIndex; - bool mUsesXor; - bool mUsesDiscardRewriting; - bool mUsesNestedBreak; - bool mRequiresIEEEStrictCompiling; - - int mNumRenderTargets; - - int mUniqueIndex; // For creating unique names - - CallDAG mCallDag; - MetadataList mASTMetadataList; - ASTMetadataHLSL *mCurrentFunctionMetadata; - bool mOutputLod0Function; - bool mInsideDiscontinuousLoop; - int mNestedLoopDepth; - - TIntermSymbol *mExcessiveLoopIndex; - - TString structInitializerString(int indent, const TType &type, const TString &name) const; - - struct HelperFunction - { - TString functionName; - TString functionDefinition; - - virtual ~HelperFunction() {} - }; - - // A list of all equality comparison functions. It's important to preserve the order at - // which we add the functions, since nested structures call each other recursively, and - // structure equality functions may need to call array equality functions and vice versa. - // The ownership of the pointers is maintained by the type-specific arrays. - std::vector mEqualityFunctions; - - struct StructEqualityFunction : public HelperFunction - { - const TStructure *structure; - }; - std::vector mStructEqualityFunctions; - - struct ArrayHelperFunction : public HelperFunction - { - TType type; - }; - std::vector mArrayEqualityFunctions; - - std::vector mArrayAssignmentFunctions; - - // The construct-into functions are functions that fill an N-element array passed as an out - // parameter with the other N parameters of the function. This is used to work around that - // arrays can't be return values in HLSL. - std::vector mArrayConstructIntoFunctions; - - PerformanceDiagnostics *mPerfDiagnostics; - - private: - TString generateStructMapping(const std::vector &std140Structs) const; - TString samplerNamePrefixFromStruct(TIntermTyped *node); - bool ancestorEvaluatesToSamplerInStruct(); -}; -} - -#endif // COMPILER_TRANSLATOR_OUTPUTHLSL_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/OutputTree.cpp b/src/3rdparty/angle/src/compiler/translator/OutputTree.cpp deleted file mode 100644 index 25e8298af3..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/OutputTree.cpp +++ /dev/null @@ -1,682 +0,0 @@ -// -// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/translator/IntermTraverse.h" -#include "compiler/translator/SymbolTable.h" - -namespace sh -{ - -namespace -{ - -void OutputFunction(TInfoSinkBase &out, const char *str, TFunctionSymbolInfo *info) -{ - const char *internal = info->getNameObj().isInternal() ? " (internal function)" : ""; - out << str << internal << ": " << info->getNameObj().getString() << " (symbol id " - << info->getId().get() << ")"; -} - -// 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, though -// that's not recommended if it can be avoided. -// 2. Print out a text based description of the tree. - -// The traverser subclass is used to carry along data from node to node in the traversal. -class TOutputTraverser : public TIntermTraverser -{ - public: - TOutputTraverser(TInfoSinkBase &out) : TIntermTraverser(true, false, false), mOut(out) {} - - protected: - void visitSymbol(TIntermSymbol *) override; - void visitConstantUnion(TIntermConstantUnion *) override; - bool visitSwizzle(Visit visit, TIntermSwizzle *node) override; - bool visitBinary(Visit visit, TIntermBinary *) override; - bool visitUnary(Visit visit, TIntermUnary *) override; - bool visitTernary(Visit visit, TIntermTernary *node) override; - bool visitIfElse(Visit visit, TIntermIfElse *node) override; - bool visitSwitch(Visit visit, TIntermSwitch *node) override; - bool visitCase(Visit visit, TIntermCase *node) override; - bool visitFunctionPrototype(Visit visit, TIntermFunctionPrototype *node) override; - bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override; - bool visitAggregate(Visit visit, TIntermAggregate *) override; - bool visitBlock(Visit visit, TIntermBlock *) override; - bool visitInvariantDeclaration(Visit visit, TIntermInvariantDeclaration *node) override; - bool visitDeclaration(Visit visit, TIntermDeclaration *node) override; - bool visitLoop(Visit visit, TIntermLoop *) override; - bool visitBranch(Visit visit, TIntermBranch *) override; - - TInfoSinkBase &mOut; -}; - -// -// Helper functions for printing, not part of traversing. -// -void OutputTreeText(TInfoSinkBase &out, TIntermNode *node, const int depth) -{ - int i; - - out.location(node->getLine().first_file, node->getLine().first_line); - - for (i = 0; i < depth; ++i) - out << " "; -} - -// -// 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. -// - -void TOutputTraverser::visitSymbol(TIntermSymbol *node) -{ - OutputTreeText(mOut, node, mDepth); - - mOut << "'" << node->getSymbol() << "' "; - mOut << "(symbol id " << node->getId() << ") "; - mOut << "(" << node->getCompleteString() << ")"; - mOut << "\n"; -} - -bool TOutputTraverser::visitSwizzle(Visit visit, TIntermSwizzle *node) -{ - OutputTreeText(mOut, node, mDepth); - mOut << "vector swizzle ("; - node->writeOffsetsAsXYZW(&mOut); - mOut << ")"; - - mOut << " (" << node->getCompleteString() << ")"; - mOut << "\n"; - return true; -} - -bool TOutputTraverser::visitBinary(Visit visit, TIntermBinary *node) -{ - OutputTreeText(mOut, node, mDepth); - - switch (node->getOp()) - { - case EOpComma: - mOut << "comma"; - break; - case EOpAssign: - mOut << "move second child to first child"; - break; - case EOpInitialize: - mOut << "initialize first child with second child"; - break; - case EOpAddAssign: - mOut << "add second child into first child"; - break; - case EOpSubAssign: - mOut << "subtract second child into first child"; - break; - case EOpMulAssign: - mOut << "multiply second child into first child"; - break; - case EOpVectorTimesMatrixAssign: - mOut << "matrix mult second child into first child"; - break; - case EOpVectorTimesScalarAssign: - mOut << "vector scale second child into first child"; - break; - case EOpMatrixTimesScalarAssign: - mOut << "matrix scale second child into first child"; - break; - case EOpMatrixTimesMatrixAssign: - mOut << "matrix mult second child into first child"; - break; - case EOpDivAssign: - mOut << "divide second child into first child"; - break; - case EOpIModAssign: - mOut << "modulo second child into first child"; - break; - case EOpBitShiftLeftAssign: - mOut << "bit-wise shift first child left by second child"; - break; - case EOpBitShiftRightAssign: - mOut << "bit-wise shift first child right by second child"; - break; - case EOpBitwiseAndAssign: - mOut << "bit-wise and second child into first child"; - break; - case EOpBitwiseXorAssign: - mOut << "bit-wise xor second child into first child"; - break; - case EOpBitwiseOrAssign: - mOut << "bit-wise or second child into first child"; - break; - - case EOpIndexDirect: - mOut << "direct index"; - break; - case EOpIndexIndirect: - mOut << "indirect index"; - break; - case EOpIndexDirectStruct: - mOut << "direct index for structure"; - break; - case EOpIndexDirectInterfaceBlock: - mOut << "direct index for interface block"; - break; - - case EOpAdd: - mOut << "add"; - break; - case EOpSub: - mOut << "subtract"; - break; - case EOpMul: - mOut << "component-wise multiply"; - break; - case EOpDiv: - mOut << "divide"; - break; - case EOpIMod: - mOut << "modulo"; - break; - case EOpBitShiftLeft: - mOut << "bit-wise shift left"; - break; - case EOpBitShiftRight: - mOut << "bit-wise shift right"; - break; - case EOpBitwiseAnd: - mOut << "bit-wise and"; - break; - case EOpBitwiseXor: - mOut << "bit-wise xor"; - break; - case EOpBitwiseOr: - mOut << "bit-wise or"; - break; - - case EOpEqual: - mOut << "Compare Equal"; - break; - case EOpNotEqual: - mOut << "Compare Not Equal"; - break; - case EOpLessThan: - mOut << "Compare Less Than"; - break; - case EOpGreaterThan: - mOut << "Compare Greater Than"; - break; - case EOpLessThanEqual: - mOut << "Compare Less Than or Equal"; - break; - case EOpGreaterThanEqual: - mOut << "Compare Greater Than or Equal"; - break; - - case EOpVectorTimesScalar: - mOut << "vector-scale"; - break; - case EOpVectorTimesMatrix: - mOut << "vector-times-matrix"; - break; - case EOpMatrixTimesVector: - mOut << "matrix-times-vector"; - break; - case EOpMatrixTimesScalar: - mOut << "matrix-scale"; - break; - case EOpMatrixTimesMatrix: - mOut << "matrix-multiply"; - break; - - case EOpLogicalOr: - mOut << "logical-or"; - break; - case EOpLogicalXor: - mOut << "logical-xor"; - break; - case EOpLogicalAnd: - mOut << "logical-and"; - break; - default: - mOut << ""; - } - - mOut << " (" << node->getCompleteString() << ")"; - - mOut << "\n"; - - // Special handling for direct indexes. Because constant - // unions are not aware they are struct indexes, treat them - // here where we have that contextual knowledge. - if (node->getOp() == EOpIndexDirectStruct || node->getOp() == EOpIndexDirectInterfaceBlock) - { - node->getLeft()->traverse(this); - - TIntermConstantUnion *intermConstantUnion = node->getRight()->getAsConstantUnion(); - ASSERT(intermConstantUnion); - - OutputTreeText(mOut, intermConstantUnion, mDepth + 1); - - // The following code finds the field name from the constant union - const TConstantUnion *constantUnion = intermConstantUnion->getUnionArrayPointer(); - const TStructure *structure = node->getLeft()->getType().getStruct(); - const TInterfaceBlock *interfaceBlock = node->getLeft()->getType().getInterfaceBlock(); - ASSERT(structure || interfaceBlock); - - const TFieldList &fields = structure ? structure->fields() : interfaceBlock->fields(); - - const TField *field = fields[constantUnion->getIConst()]; - - mOut << constantUnion->getIConst() << " (field '" << field->name() << "')"; - - mOut << "\n"; - - return false; - } - - return true; -} - -bool TOutputTraverser::visitUnary(Visit visit, TIntermUnary *node) -{ - OutputTreeText(mOut, node, mDepth); - - switch (node->getOp()) - { - // Give verbose names for ops that have special syntax and some built-in functions that are - // easy to confuse with others, but mostly use GLSL names for functions. - case EOpNegative: - mOut << "Negate value"; - break; - case EOpPositive: - mOut << "Positive sign"; - break; - case EOpLogicalNot: - mOut << "negation"; - break; - case EOpBitwiseNot: - mOut << "bit-wise not"; - break; - - case EOpPostIncrement: - mOut << "Post-Increment"; - break; - case EOpPostDecrement: - mOut << "Post-Decrement"; - break; - case EOpPreIncrement: - mOut << "Pre-Increment"; - break; - case EOpPreDecrement: - mOut << "Pre-Decrement"; - break; - - case EOpArrayLength: - mOut << "Array length"; - break; - - case EOpLogicalNotComponentWise: - mOut << "component-wise not"; - break; - - default: - mOut << GetOperatorString(node->getOp()); - break; - } - - mOut << " (" << node->getCompleteString() << ")"; - - mOut << "\n"; - - return true; -} - -bool TOutputTraverser::visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) -{ - OutputTreeText(mOut, node, mDepth); - mOut << "Function Definition:\n"; - mOut << "\n"; - return true; -} - -bool TOutputTraverser::visitInvariantDeclaration(Visit visit, TIntermInvariantDeclaration *node) -{ - OutputTreeText(mOut, node, mDepth); - mOut << "Invariant Declaration:\n"; - return true; -} - -bool TOutputTraverser::visitFunctionPrototype(Visit visit, TIntermFunctionPrototype *node) -{ - OutputTreeText(mOut, node, mDepth); - OutputFunction(mOut, "Function Prototype", node->getFunctionSymbolInfo()); - mOut << " (" << node->getCompleteString() << ")"; - mOut << "\n"; - - return true; -} - -bool TOutputTraverser::visitAggregate(Visit visit, TIntermAggregate *node) -{ - OutputTreeText(mOut, node, mDepth); - - if (node->getOp() == EOpNull) - { - mOut.prefix(SH_ERROR); - mOut << "node is still EOpNull!\n"; - return true; - } - - // Give verbose names for some built-in functions that are easy to confuse with others, but - // mostly use GLSL names for functions. - switch (node->getOp()) - { - case EOpCallFunctionInAST: - OutputFunction(mOut, "Call an user-defined function", node->getFunctionSymbolInfo()); - break; - case EOpCallInternalRawFunction: - OutputFunction(mOut, "Call an internal function with raw implementation", - node->getFunctionSymbolInfo()); - break; - case EOpCallBuiltInFunction: - OutputFunction(mOut, "Call a built-in function", node->getFunctionSymbolInfo()); - break; - - case EOpConstruct: - // The type of the constructor will be printed below. - mOut << "Construct"; - break; - - case EOpEqualComponentWise: - mOut << "component-wise equal"; - break; - case EOpNotEqualComponentWise: - mOut << "component-wise not equal"; - break; - case EOpLessThanComponentWise: - mOut << "component-wise less than"; - break; - case EOpGreaterThanComponentWise: - mOut << "component-wise greater than"; - break; - case EOpLessThanEqualComponentWise: - mOut << "component-wise less than or equal"; - break; - case EOpGreaterThanEqualComponentWise: - mOut << "component-wise greater than or equal"; - break; - - case EOpDot: - mOut << "dot product"; - break; - case EOpCross: - mOut << "cross product"; - break; - case EOpMulMatrixComponentWise: - mOut << "component-wise multiply"; - break; - - default: - mOut << GetOperatorString(node->getOp()); - break; - } - - mOut << " (" << node->getCompleteString() << ")"; - - mOut << "\n"; - - return true; -} - -bool TOutputTraverser::visitBlock(Visit visit, TIntermBlock *node) -{ - OutputTreeText(mOut, node, mDepth); - mOut << "Code block\n"; - - return true; -} - -bool TOutputTraverser::visitDeclaration(Visit visit, TIntermDeclaration *node) -{ - OutputTreeText(mOut, node, mDepth); - mOut << "Declaration\n"; - - return true; -} - -bool TOutputTraverser::visitTernary(Visit visit, TIntermTernary *node) -{ - OutputTreeText(mOut, node, mDepth); - - mOut << "Ternary selection"; - mOut << " (" << node->getCompleteString() << ")\n"; - - ++mDepth; - - OutputTreeText(mOut, node, mDepth); - mOut << "Condition\n"; - node->getCondition()->traverse(this); - - OutputTreeText(mOut, node, mDepth); - if (node->getTrueExpression()) - { - mOut << "true case\n"; - node->getTrueExpression()->traverse(this); - } - if (node->getFalseExpression()) - { - OutputTreeText(mOut, node, mDepth); - mOut << "false case\n"; - node->getFalseExpression()->traverse(this); - } - - --mDepth; - - return false; -} - -bool TOutputTraverser::visitIfElse(Visit visit, TIntermIfElse *node) -{ - OutputTreeText(mOut, node, mDepth); - - mOut << "If test\n"; - - ++mDepth; - - OutputTreeText(mOut, node, mDepth); - mOut << "Condition\n"; - node->getCondition()->traverse(this); - - OutputTreeText(mOut, node, mDepth); - if (node->getTrueBlock()) - { - mOut << "true case\n"; - node->getTrueBlock()->traverse(this); - } - else - { - mOut << "true case is null\n"; - } - - if (node->getFalseBlock()) - { - OutputTreeText(mOut, node, mDepth); - mOut << "false case\n"; - node->getFalseBlock()->traverse(this); - } - - --mDepth; - - return false; -} - -bool TOutputTraverser::visitSwitch(Visit visit, TIntermSwitch *node) -{ - OutputTreeText(mOut, node, mDepth); - - mOut << "Switch\n"; - - return true; -} - -bool TOutputTraverser::visitCase(Visit visit, TIntermCase *node) -{ - OutputTreeText(mOut, node, mDepth); - - if (node->getCondition() == nullptr) - { - mOut << "Default\n"; - } - else - { - mOut << "Case\n"; - } - - return true; -} - -void TOutputTraverser::visitConstantUnion(TIntermConstantUnion *node) -{ - size_t size = node->getType().getObjectSize(); - - for (size_t i = 0; i < size; i++) - { - OutputTreeText(mOut, node, mDepth); - switch (node->getUnionArrayPointer()[i].getType()) - { - case EbtBool: - if (node->getUnionArrayPointer()[i].getBConst()) - mOut << "true"; - else - mOut << "false"; - - mOut << " (" - << "const bool" - << ")"; - mOut << "\n"; - break; - case EbtFloat: - mOut << node->getUnionArrayPointer()[i].getFConst(); - mOut << " (const float)\n"; - break; - case EbtInt: - mOut << node->getUnionArrayPointer()[i].getIConst(); - mOut << " (const int)\n"; - break; - case EbtUInt: - mOut << node->getUnionArrayPointer()[i].getUConst(); - mOut << " (const uint)\n"; - break; - case EbtYuvCscStandardEXT: - mOut << getYuvCscStandardEXTString( - node->getUnionArrayPointer()[i].getYuvCscStandardEXTConst()); - mOut << " (const yuvCscStandardEXT)\n"; - break; - default: - mOut.prefix(SH_ERROR); - mOut << "Unknown constant\n"; - break; - } - } -} - -bool TOutputTraverser::visitLoop(Visit visit, TIntermLoop *node) -{ - OutputTreeText(mOut, node, mDepth); - - mOut << "Loop with condition "; - if (node->getType() == ELoopDoWhile) - mOut << "not "; - mOut << "tested first\n"; - - ++mDepth; - - OutputTreeText(mOut, node, mDepth); - if (node->getCondition()) - { - mOut << "Loop Condition\n"; - node->getCondition()->traverse(this); - } - else - { - mOut << "No loop condition\n"; - } - - OutputTreeText(mOut, node, mDepth); - if (node->getBody()) - { - mOut << "Loop Body\n"; - node->getBody()->traverse(this); - } - else - { - mOut << "No loop body\n"; - } - - if (node->getExpression()) - { - OutputTreeText(mOut, node, mDepth); - mOut << "Loop Terminal Expression\n"; - node->getExpression()->traverse(this); - } - - --mDepth; - - return false; -} - -bool TOutputTraverser::visitBranch(Visit visit, TIntermBranch *node) -{ - OutputTreeText(mOut, node, mDepth); - - switch (node->getFlowOp()) - { - case EOpKill: - mOut << "Branch: Kill"; - break; - case EOpBreak: - mOut << "Branch: Break"; - break; - case EOpContinue: - mOut << "Branch: Continue"; - break; - case EOpReturn: - mOut << "Branch: Return"; - break; - default: - mOut << "Branch: Unknown Branch"; - break; - } - - if (node->getExpression()) - { - mOut << " with expression\n"; - ++mDepth; - node->getExpression()->traverse(this); - --mDepth; - } - else - { - mOut << "\n"; - } - - return false; -} - -} // anonymous namespace - -void OutputTree(TIntermNode *root, TInfoSinkBase &out) -{ - TOutputTraverser it(out); - ASSERT(root); - root->traverse(&it); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/OutputTree.h b/src/3rdparty/angle/src/compiler/translator/OutputTree.h deleted file mode 100644 index 9f11989cb1..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/OutputTree.h +++ /dev/null @@ -1,22 +0,0 @@ -// -// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// Output the AST intermediate representation of the GLSL code. - -#ifndef COMPILER_TRANSLATOR_OUTPUTTREE_H_ -#define COMPILER_TRANSLATOR_OUTPUTTREE_H_ - -namespace sh -{ - -class TIntermNode; -class TInfoSinkBase; - -// Output the AST along with metadata. -void OutputTree(TIntermNode *root, TInfoSinkBase &out); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_OUTPUTTREE_H_ \ No newline at end of file diff --git a/src/3rdparty/angle/src/compiler/translator/OutputVulkanGLSL.cpp b/src/3rdparty/angle/src/compiler/translator/OutputVulkanGLSL.cpp deleted file mode 100644 index 6d11deb898..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/OutputVulkanGLSL.cpp +++ /dev/null @@ -1,80 +0,0 @@ -// -// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// OutputVulkanGLSL: -// Code that outputs shaders that fit GL_KHR_vulkan_glsl. -// The shaders are then fed into glslang to spit out SPIR-V (libANGLE-side). -// See: https://www.khronos.org/registry/vulkan/specs/misc/GL_KHR_vulkan_glsl.txt -// - -#include "compiler/translator/OutputVulkanGLSL.h" - -#include "compiler/translator/util.h" - -namespace sh -{ - -TOutputVulkanGLSL::TOutputVulkanGLSL(TInfoSinkBase &objSink, - ShArrayIndexClampingStrategy clampingStrategy, - ShHashFunction64 hashFunction, - NameMap &nameMap, - TSymbolTable *symbolTable, - sh::GLenum shaderType, - int shaderVersion, - ShShaderOutput output, - ShCompileOptions compileOptions) - : TOutputGLSL(objSink, - clampingStrategy, - hashFunction, - nameMap, - symbolTable, - shaderType, - shaderVersion, - output, - compileOptions) -{ -} - -// TODO(jmadill): This is not complete. -void TOutputVulkanGLSL::writeLayoutQualifier(TIntermTyped *variable) -{ - const TType &type = variable->getType(); - - bool needsCustomLayout = - (type.getQualifier() == EvqAttribute || type.getQualifier() == EvqFragmentOut || - type.getQualifier() == EvqVertexIn || IsVarying(type.getQualifier()) || - IsSampler(type.getBasicType())); - - if (!NeedsToWriteLayoutQualifier(type) && !needsCustomLayout) - { - return; - } - - TInfoSinkBase &out = objSink(); - const TLayoutQualifier &layoutQualifier = type.getLayoutQualifier(); - out << "layout("; - - // This isn't super clean, but it gets the job done. - // See corresponding code in GlslangWrapper.cpp. - // TODO(jmadill): Ensure declarations are separated. - - TIntermSymbol *symbol = variable->getAsSymbolNode(); - ASSERT(symbol); - - if (needsCustomLayout) - { - out << "@@ LAYOUT-" << symbol->getName().getString() << " @@"; - } - - if (IsImage(type.getBasicType()) && layoutQualifier.imageInternalFormat != EiifUnspecified) - { - ASSERT(type.getQualifier() == EvqTemporary || type.getQualifier() == EvqUniform); - out << getImageInternalFormatString(layoutQualifier.imageInternalFormat); - } - - out << ") "; -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/OutputVulkanGLSL.h b/src/3rdparty/angle/src/compiler/translator/OutputVulkanGLSL.h deleted file mode 100644 index 6e5da8b53e..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/OutputVulkanGLSL.h +++ /dev/null @@ -1,34 +0,0 @@ -// -// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// OutputVulkanGLSL: -// Code that outputs shaders that fit GL_KHR_vulkan_glsl. -// The shaders are then fed into glslang to spit out SPIR-V (libANGLE-side). -// See: https://www.khronos.org/registry/vulkan/specs/misc/GL_KHR_vulkan_glsl.txt -// - -#include "compiler/translator/OutputGLSL.h" - -namespace sh -{ - -class TOutputVulkanGLSL : public TOutputGLSL -{ - public: - TOutputVulkanGLSL(TInfoSinkBase &objSink, - ShArrayIndexClampingStrategy clampingStrategy, - ShHashFunction64 hashFunction, - NameMap &nameMap, - TSymbolTable *symbolTable, - sh::GLenum shaderType, - int shaderVersion, - ShShaderOutput output, - ShCompileOptions compileOptions); - - protected: - void writeLayoutQualifier(TIntermTyped *variable) override; -}; - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/ParamType.h b/src/3rdparty/angle/src/compiler/translator/ParamType.h deleted file mode 100644 index dddb4e9901..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/ParamType.h +++ /dev/null @@ -1,102 +0,0 @@ -// -// Copyright 2017 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// ParamType: -// Helper type for built-in function emulator tables. Defines types for parameters. - -#ifndef COMPILER_TRANSLATOR_PARAMTYPE_H_ -#define COMPILER_TRANSLATOR_PARAMTYPE_H_ - -#include "common/angleutils.h" -#include "compiler/translator/BaseTypes.h" - -namespace sh -{ - -enum class ParamType : uint8_t -{ - Void, - Bool1, - Bool2, - Bool3, - Bool4, - Float1, - Float2, - Float3, - Float4, - Int1, - Int2, - Int3, - Int4, - Mat2, - Mat3, - Mat4, - Uint1, - Uint2, - Uint3, - Uint4, - Last, -}; - -struct ParamTypeInfo -{ - ParamType self; - TBasicType basicType; - int primarySize; - int secondarySize; -}; - -constexpr ParamTypeInfo g_ParamTypeInfo[] = { - {ParamType::Void, EbtVoid, 1, 1}, {ParamType::Bool1, EbtBool, 1, 1}, - {ParamType::Bool2, EbtBool, 2, 1}, {ParamType::Bool3, EbtBool, 3, 1}, - {ParamType::Bool4, EbtBool, 4, 1}, {ParamType::Float1, EbtFloat, 1, 1}, - {ParamType::Float2, EbtFloat, 2, 1}, {ParamType::Float3, EbtFloat, 3, 1}, - {ParamType::Float4, EbtFloat, 4, 1}, {ParamType::Int1, EbtInt, 1, 1}, - {ParamType::Int2, EbtInt, 2, 1}, {ParamType::Int3, EbtInt, 3, 1}, - {ParamType::Int4, EbtInt, 4, 1}, {ParamType::Mat2, EbtFloat, 2, 2}, - {ParamType::Mat3, EbtFloat, 3, 3}, {ParamType::Mat4, EbtFloat, 4, 4}, - {ParamType::Uint1, EbtUInt, 1, 1}, {ParamType::Uint2, EbtUInt, 2, 1}, - {ParamType::Uint3, EbtUInt, 3, 1}, {ParamType::Uint4, EbtUInt, 4, 1}, -}; - -constexpr size_t ParamTypeIndex(ParamType paramType) -{ - return static_cast(paramType); -} - -constexpr size_t NumParamTypes() -{ - return ParamTypeIndex(ParamType::Last); -} - -static_assert(ArraySize(g_ParamTypeInfo) == NumParamTypes(), "Invalid array size"); - -constexpr TBasicType GetBasicType(ParamType paramType) -{ - return g_ParamTypeInfo[ParamTypeIndex(paramType)].basicType; -} - -constexpr int GetPrimarySize(ParamType paramType) -{ - return g_ParamTypeInfo[ParamTypeIndex(paramType)].primarySize; -} - -constexpr int GetSecondarySize(ParamType paramType) -{ - return g_ParamTypeInfo[ParamTypeIndex(paramType)].secondarySize; -} - -constexpr bool SameParamType(ParamType paramType, - TBasicType basicType, - int primarySize, - int secondarySize) -{ - return GetBasicType(paramType) == basicType && primarySize == GetPrimarySize(paramType) && - secondarySize == GetSecondarySize(paramType); -} - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_PARAMTYPE_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/ParseContext.cpp b/src/3rdparty/angle/src/compiler/translator/ParseContext.cpp deleted file mode 100644 index c97f91d781..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/ParseContext.cpp +++ /dev/null @@ -1,6022 +0,0 @@ -// -// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/translator/ParseContext.h" - -#include -#include - -#include "common/mathutil.h" -#include "compiler/preprocessor/SourceLocation.h" -#include "compiler/translator/Cache.h" -#include "compiler/translator/IntermNode_util.h" -#include "compiler/translator/ValidateGlobalInitializer.h" -#include "compiler/translator/ValidateSwitch.h" -#include "compiler/translator/glslang.h" -#include "compiler/translator/util.h" - -namespace sh -{ - -/////////////////////////////////////////////////////////////////////// -// -// Sub- vector and matrix fields -// -//////////////////////////////////////////////////////////////////////// - -namespace -{ - -const int kWebGLMaxStructNesting = 4; - -const std::array kAtomicBuiltin = {{"atomicAdd", "atomicMin", "atomicMax", - "atomicAnd", "atomicOr", "atomicXor", - "atomicExchange", "atomicCompSwap"}}; - -bool IsAtomicBuiltin(const TString &name) -{ - for (size_t i = 0; i < kAtomicBuiltin.size(); ++i) - { - if (name.compare(kAtomicBuiltin[i]) == 0) - { - return true; - } - } - return false; -} - -bool ContainsSampler(const TStructure *structType); - -bool ContainsSampler(const TType &type) -{ - if (IsSampler(type.getBasicType())) - { - return true; - } - if (type.getBasicType() == EbtStruct) - { - return ContainsSampler(type.getStruct()); - } - - return false; -} - -bool ContainsSampler(const TStructure *structType) -{ - for (const auto &field : structType->fields()) - { - if (ContainsSampler(*field->type())) - return true; - } - return false; -} - -// Get a token from an image argument to use as an error message token. -const char *GetImageArgumentToken(TIntermTyped *imageNode) -{ - ASSERT(IsImage(imageNode->getBasicType())); - while (imageNode->getAsBinaryNode() && - (imageNode->getAsBinaryNode()->getOp() == EOpIndexIndirect || - imageNode->getAsBinaryNode()->getOp() == EOpIndexDirect)) - { - imageNode = imageNode->getAsBinaryNode()->getLeft(); - } - TIntermSymbol *imageSymbol = imageNode->getAsSymbolNode(); - if (imageSymbol) - { - return imageSymbol->getSymbol().c_str(); - } - return "image"; -} - -bool CanSetDefaultPrecisionOnType(const TPublicType &type) -{ - if (!SupportsPrecision(type.getBasicType())) - { - return false; - } - if (type.getBasicType() == EbtUInt) - { - // ESSL 3.00.4 section 4.5.4 - return false; - } - if (type.isAggregate()) - { - // Not allowed to set for aggregate types - return false; - } - return true; -} - -// Map input primitive types to input array sizes in a geometry shader. -GLuint GetGeometryShaderInputArraySize(TLayoutPrimitiveType primitiveType) -{ - switch (primitiveType) - { - case EptPoints: - return 1u; - case EptLines: - return 2u; - case EptTriangles: - return 3u; - case EptLinesAdjacency: - return 4u; - case EptTrianglesAdjacency: - return 6u; - default: - UNREACHABLE(); - return 0u; - } -} - -bool IsBufferOrSharedVariable(TIntermTyped *var) -{ - if (var->isInterfaceBlock() || var->getQualifier() == EvqBuffer || - var->getQualifier() == EvqShared) - { - return true; - } - return false; -} - -} // namespace - -// This tracks each binding point's current default offset for inheritance of subsequent -// variables using the same binding, and keeps offsets unique and non overlapping. -// See GLSL ES 3.1, section 4.4.6. -class TParseContext::AtomicCounterBindingState -{ - public: - AtomicCounterBindingState() : mDefaultOffset(0) {} - // Inserts a new span and returns -1 if overlapping, else returns the starting offset of - // newly inserted span. - int insertSpan(int start, size_t length) - { - gl::RangeI newSpan(start, start + static_cast(length)); - for (const auto &span : mSpans) - { - if (newSpan.intersects(span)) - { - return -1; - } - } - mSpans.push_back(newSpan); - mDefaultOffset = newSpan.high(); - return start; - } - // Inserts a new span starting from the default offset. - int appendSpan(size_t length) { return insertSpan(mDefaultOffset, length); } - void setDefaultOffset(int offset) { mDefaultOffset = offset; } - - private: - int mDefaultOffset; - std::vector mSpans; -}; - -TParseContext::TParseContext(TSymbolTable &symt, - TExtensionBehavior &ext, - sh::GLenum type, - ShShaderSpec spec, - ShCompileOptions options, - bool checksPrecErrors, - TDiagnostics *diagnostics, - const ShBuiltInResources &resources) - : symbolTable(symt), - mDeferredNonEmptyDeclarationErrorCheck(false), - mShaderType(type), - mShaderSpec(spec), - mCompileOptions(options), - mShaderVersion(100), - mTreeRoot(nullptr), - mLoopNestingLevel(0), - mStructNestingLevel(0), - mSwitchNestingLevel(0), - mCurrentFunctionType(nullptr), - mFunctionReturnsValue(false), - mChecksPrecisionErrors(checksPrecErrors), - mFragmentPrecisionHighOnESSL1(false), - mDefaultUniformMatrixPacking(EmpColumnMajor), - mDefaultUniformBlockStorage(sh::IsWebGLBasedSpec(spec) ? EbsStd140 : EbsShared), - mDefaultBufferMatrixPacking(EmpColumnMajor), - mDefaultBufferBlockStorage(sh::IsWebGLBasedSpec(spec) ? EbsStd140 : EbsShared), - mDiagnostics(diagnostics), - mDirectiveHandler(ext, - *mDiagnostics, - mShaderVersion, - mShaderType, - resources.WEBGL_debug_shader_precision == 1), - mPreprocessor(mDiagnostics, &mDirectiveHandler, pp::PreprocessorSettings()), - mScanner(nullptr), - mUsesFragData(false), - mUsesFragColor(false), - mUsesSecondaryOutputs(false), - mMinProgramTexelOffset(resources.MinProgramTexelOffset), - mMaxProgramTexelOffset(resources.MaxProgramTexelOffset), - mMinProgramTextureGatherOffset(resources.MinProgramTextureGatherOffset), - mMaxProgramTextureGatherOffset(resources.MaxProgramTextureGatherOffset), - mComputeShaderLocalSizeDeclared(false), - mComputeShaderLocalSize(-1), - mNumViews(-1), - mMaxNumViews(resources.MaxViewsOVR), - mMaxImageUnits(resources.MaxImageUnits), - mMaxCombinedTextureImageUnits(resources.MaxCombinedTextureImageUnits), - mMaxUniformLocations(resources.MaxUniformLocations), - mMaxUniformBufferBindings(resources.MaxUniformBufferBindings), - mMaxAtomicCounterBindings(resources.MaxAtomicCounterBindings), - mMaxShaderStorageBufferBindings(resources.MaxShaderStorageBufferBindings), - mDeclaringFunction(false), - mGeometryShaderInputPrimitiveType(EptUndefined), - mGeometryShaderOutputPrimitiveType(EptUndefined), - mGeometryShaderInvocations(0), - mGeometryShaderMaxVertices(-1), - mMaxGeometryShaderInvocations(resources.MaxGeometryShaderInvocations), - mMaxGeometryShaderMaxVertices(resources.MaxGeometryOutputVertices), - mGeometryShaderInputArraySize(0u) -{ -} - -TParseContext::~TParseContext() -{ -} - -bool TParseContext::parseVectorFields(const TSourceLoc &line, - const TString &compString, - int vecSize, - TVector *fieldOffsets) -{ - ASSERT(fieldOffsets); - size_t fieldCount = compString.size(); - if (fieldCount > 4u) - { - error(line, "illegal vector field selection", compString.c_str()); - return false; - } - fieldOffsets->resize(fieldCount); - - enum - { - exyzw, - ergba, - estpq - } fieldSet[4]; - - for (unsigned int i = 0u; i < fieldOffsets->size(); ++i) - { - switch (compString[i]) - { - case 'x': - (*fieldOffsets)[i] = 0; - fieldSet[i] = exyzw; - break; - case 'r': - (*fieldOffsets)[i] = 0; - fieldSet[i] = ergba; - break; - case 's': - (*fieldOffsets)[i] = 0; - fieldSet[i] = estpq; - break; - case 'y': - (*fieldOffsets)[i] = 1; - fieldSet[i] = exyzw; - break; - case 'g': - (*fieldOffsets)[i] = 1; - fieldSet[i] = ergba; - break; - case 't': - (*fieldOffsets)[i] = 1; - fieldSet[i] = estpq; - break; - case 'z': - (*fieldOffsets)[i] = 2; - fieldSet[i] = exyzw; - break; - case 'b': - (*fieldOffsets)[i] = 2; - fieldSet[i] = ergba; - break; - case 'p': - (*fieldOffsets)[i] = 2; - fieldSet[i] = estpq; - break; - - case 'w': - (*fieldOffsets)[i] = 3; - fieldSet[i] = exyzw; - break; - case 'a': - (*fieldOffsets)[i] = 3; - fieldSet[i] = ergba; - break; - case 'q': - (*fieldOffsets)[i] = 3; - fieldSet[i] = estpq; - break; - default: - error(line, "illegal vector field selection", compString.c_str()); - return false; - } - } - - for (unsigned int i = 0u; i < fieldOffsets->size(); ++i) - { - if ((*fieldOffsets)[i] >= vecSize) - { - error(line, "vector field selection out of range", compString.c_str()); - return false; - } - - if (i > 0) - { - if (fieldSet[i] != fieldSet[i - 1]) - { - error(line, "illegal - vector component fields not from the same set", - compString.c_str()); - return false; - } - } - } - - return true; -} - -/////////////////////////////////////////////////////////////////////// -// -// Errors -// -//////////////////////////////////////////////////////////////////////// - -// -// Used by flex/bison to output all syntax and parsing errors. -// -void TParseContext::error(const TSourceLoc &loc, const char *reason, const char *token) -{ - mDiagnostics->error(loc, reason, token); -} - -void TParseContext::warning(const TSourceLoc &loc, const char *reason, const char *token) -{ - mDiagnostics->warning(loc, reason, token); -} - -void TParseContext::outOfRangeError(bool isError, - const TSourceLoc &loc, - const char *reason, - const char *token) -{ - if (isError) - { - error(loc, reason, token); - } - else - { - warning(loc, reason, token); - } -} - -// -// Same error message for all places assignments don't work. -// -void TParseContext::assignError(const TSourceLoc &line, const char *op, TString left, TString right) -{ - std::stringstream reasonStream; - reasonStream << "cannot convert from '" << right << "' to '" << left << "'"; - std::string reason = reasonStream.str(); - error(line, reason.c_str(), op); -} - -// -// Same error message for all places unary operations don't work. -// -void TParseContext::unaryOpError(const TSourceLoc &line, const char *op, TString operand) -{ - std::stringstream reasonStream; - reasonStream << "wrong operand type - no operation '" << op - << "' exists that takes an operand of type " << operand - << " (or there is no acceptable conversion)"; - std::string reason = reasonStream.str(); - error(line, reason.c_str(), op); -} - -// -// Same error message for all binary operations don't work. -// -void TParseContext::binaryOpError(const TSourceLoc &line, - const char *op, - TString left, - TString right) -{ - std::stringstream reasonStream; - reasonStream << "wrong operand types - no operation '" << op - << "' exists that takes a left-hand operand of type '" << left - << "' and a right operand of type '" << right - << "' (or there is no acceptable conversion)"; - std::string reason = reasonStream.str(); - error(line, reason.c_str(), op); -} - -void TParseContext::checkPrecisionSpecified(const TSourceLoc &line, - TPrecision precision, - TBasicType type) -{ - if (!mChecksPrecisionErrors) - return; - - if (precision != EbpUndefined && !SupportsPrecision(type)) - { - error(line, "illegal type for precision qualifier", getBasicString(type)); - } - - if (precision == EbpUndefined) - { - switch (type) - { - case EbtFloat: - error(line, "No precision specified for (float)", ""); - return; - case EbtInt: - case EbtUInt: - UNREACHABLE(); // there's always a predeclared qualifier - error(line, "No precision specified (int)", ""); - return; - default: - if (IsOpaqueType(type)) - { - error(line, "No precision specified", getBasicString(type)); - return; - } - } - } -} - -// 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. -bool TParseContext::checkCanBeLValue(const TSourceLoc &line, const char *op, TIntermTyped *node) -{ - TIntermSymbol *symNode = node->getAsSymbolNode(); - TIntermBinary *binaryNode = node->getAsBinaryNode(); - TIntermSwizzle *swizzleNode = node->getAsSwizzleNode(); - - if (swizzleNode) - { - bool ok = checkCanBeLValue(line, op, swizzleNode->getOperand()); - if (ok && swizzleNode->hasDuplicateOffsets()) - { - error(line, " l-value of swizzle cannot have duplicate components", op); - return false; - } - return ok; - } - - if (binaryNode) - { - switch (binaryNode->getOp()) - { - case EOpIndexDirect: - case EOpIndexIndirect: - case EOpIndexDirectStruct: - case EOpIndexDirectInterfaceBlock: - return checkCanBeLValue(line, op, binaryNode->getLeft()); - default: - break; - } - error(line, " l-value required", op); - return false; - } - - std::string message; - switch (node->getQualifier()) - { - case EvqConst: - message = "can't modify a const"; - break; - case EvqConstReadOnly: - message = "can't modify a const"; - break; - case EvqAttribute: - message = "can't modify an attribute"; - break; - case EvqFragmentIn: - case EvqVertexIn: - case EvqGeometryIn: - case EvqFlatIn: - case EvqSmoothIn: - case EvqCentroidIn: - message = "can't modify an input"; - break; - case EvqUniform: - message = "can't modify a uniform"; - break; - case EvqVaryingIn: - message = "can't modify a varying"; - break; - case EvqFragCoord: - message = "can't modify gl_FragCoord"; - break; - case EvqFrontFacing: - message = "can't modify gl_FrontFacing"; - break; - case EvqPointCoord: - message = "can't modify gl_PointCoord"; - break; - case EvqNumWorkGroups: - message = "can't modify gl_NumWorkGroups"; - break; - case EvqWorkGroupSize: - message = "can't modify gl_WorkGroupSize"; - break; - case EvqWorkGroupID: - message = "can't modify gl_WorkGroupID"; - break; - case EvqLocalInvocationID: - message = "can't modify gl_LocalInvocationID"; - break; - case EvqGlobalInvocationID: - message = "can't modify gl_GlobalInvocationID"; - break; - case EvqLocalInvocationIndex: - message = "can't modify gl_LocalInvocationIndex"; - break; - case EvqViewIDOVR: - message = "can't modify gl_ViewID_OVR"; - break; - case EvqComputeIn: - message = "can't modify work group size variable"; - break; - case EvqPerVertexIn: - message = "can't modify any member in gl_in"; - break; - case EvqPrimitiveIDIn: - message = "can't modify gl_PrimitiveIDIn"; - break; - case EvqInvocationID: - message = "can't modify gl_InvocationID"; - break; - case EvqPrimitiveID: - if (mShaderType == GL_FRAGMENT_SHADER) - { - message = "can't modify gl_PrimitiveID in a fragment shader"; - } - break; - case EvqLayer: - if (mShaderType == GL_FRAGMENT_SHADER) - { - message = "can't modify gl_Layer in a fragment shader"; - } - break; - default: - // - // Type that can't be written to? - // - if (node->getBasicType() == EbtVoid) - { - message = "can't modify void"; - } - if (IsOpaqueType(node->getBasicType())) - { - message = "can't modify a variable with type "; - message += getBasicString(node->getBasicType()); - } - else if (node->getMemoryQualifier().readonly) - { - message = "can't modify a readonly variable"; - } - } - - if (message.empty() && binaryNode == 0 && symNode == 0) - { - error(line, "l-value required", op); - - return false; - } - - // - // Everything else is okay, no error. - // - if (message.empty()) - return true; - - // - // If we get here, we have an error and a message. - // - if (symNode) - { - const char *symbol = symNode->getSymbol().c_str(); - std::stringstream reasonStream; - reasonStream << "l-value required (" << message << " \"" << symbol << "\")"; - std::string reason = reasonStream.str(); - error(line, reason.c_str(), op); - } - else - { - std::stringstream reasonStream; - reasonStream << "l-value required (" << message << ")"; - std::string reason = reasonStream.str(); - error(line, reason.c_str(), op); - } - - return false; -} - -// Both test, and if necessary spit out an error, to see if the node is really -// a constant. -void TParseContext::checkIsConst(TIntermTyped *node) -{ - if (node->getQualifier() != EvqConst) - { - error(node->getLine(), "constant expression required", ""); - } -} - -// Both test, and if necessary spit out an error, to see if the node is really -// an integer. -void TParseContext::checkIsScalarInteger(TIntermTyped *node, const char *token) -{ - if (!node->isScalarInt()) - { - error(node->getLine(), "integer expression required", token); - } -} - -// Both test, and if necessary spit out an error, to see if we are currently -// globally scoped. -bool TParseContext::checkIsAtGlobalLevel(const TSourceLoc &line, const char *token) -{ - if (!symbolTable.atGlobalLevel()) - { - error(line, "only allowed at global scope", token); - return false; - } - return true; -} - -// ESSL 3.00.5 sections 3.8 and 3.9. -// If it starts "gl_" or contains two consecutive underscores, it's reserved. -// Also checks for "webgl_" and "_webgl_" reserved identifiers if parsing a webgl shader. -bool TParseContext::checkIsNotReserved(const TSourceLoc &line, const TString &identifier) -{ - static const char *reservedErrMsg = "reserved built-in name"; - if (identifier.compare(0, 3, "gl_") == 0) - { - error(line, reservedErrMsg, "gl_"); - return false; - } - if (sh::IsWebGLBasedSpec(mShaderSpec)) - { - if (identifier.compare(0, 6, "webgl_") == 0) - { - error(line, reservedErrMsg, "webgl_"); - return false; - } - if (identifier.compare(0, 7, "_webgl_") == 0) - { - error(line, reservedErrMsg, "_webgl_"); - return false; - } - } - if (identifier.find("__") != TString::npos) - { - error(line, - "identifiers containing two consecutive underscores (__) are reserved as " - "possible future keywords", - identifier.c_str()); - return false; - } - return true; -} - -// Make sure the argument types are correct for constructing a specific type. -bool TParseContext::checkConstructorArguments(const TSourceLoc &line, - const TIntermSequence *arguments, - const TType &type) -{ - if (arguments->empty()) - { - error(line, "constructor does not have any arguments", "constructor"); - return false; - } - - for (TIntermNode *arg : *arguments) - { - const TIntermTyped *argTyped = arg->getAsTyped(); - ASSERT(argTyped != nullptr); - if (type.getBasicType() != EbtStruct && IsOpaqueType(argTyped->getBasicType())) - { - std::string reason("cannot convert a variable with type "); - reason += getBasicString(argTyped->getBasicType()); - error(line, reason.c_str(), "constructor"); - return false; - } - else if (argTyped->getMemoryQualifier().writeonly) - { - error(line, "cannot convert a variable with writeonly", "constructor"); - return false; - } - if (argTyped->getBasicType() == EbtVoid) - { - error(line, "cannot convert a void", "constructor"); - return false; - } - } - - if (type.isArray()) - { - // The size of an unsized constructor should already have been determined. - ASSERT(!type.isUnsizedArray()); - if (static_cast(type.getOutermostArraySize()) != arguments->size()) - { - error(line, "array constructor needs one argument per array element", "constructor"); - return false; - } - // GLSL ES 3.00 section 5.4.4: Each argument must be the same type as the element type of - // the array. - for (TIntermNode *const &argNode : *arguments) - { - const TType &argType = argNode->getAsTyped()->getType(); - if (mShaderVersion < 310 && argType.isArray()) - { - error(line, "constructing from a non-dereferenced array", "constructor"); - return false; - } - if (!argType.isElementTypeOf(type)) - { - error(line, "Array constructor argument has an incorrect type", "constructor"); - return false; - } - } - } - else if (type.getBasicType() == EbtStruct) - { - const TFieldList &fields = type.getStruct()->fields(); - if (fields.size() != arguments->size()) - { - error(line, - "Number of constructor parameters does not match the number of structure fields", - "constructor"); - return false; - } - - for (size_t i = 0; i < fields.size(); i++) - { - if (i >= arguments->size() || - (*arguments)[i]->getAsTyped()->getType() != *fields[i]->type()) - { - error(line, "Structure constructor arguments do not match structure fields", - "constructor"); - return false; - } - } - } - else - { - // We're constructing a scalar, vector, or matrix. - - // Note: It's okay to have too many components available, but not okay to have unused - // arguments. 'full' will go to true when enough args have been seen. If we loop again, - // there is an extra argument, so 'overFull' will become true. - - size_t size = 0; - bool full = false; - bool overFull = false; - bool matrixArg = false; - for (TIntermNode *arg : *arguments) - { - const TIntermTyped *argTyped = arg->getAsTyped(); - ASSERT(argTyped != nullptr); - - if (argTyped->getBasicType() == EbtStruct) - { - error(line, "a struct cannot be used as a constructor argument for this type", - "constructor"); - return false; - } - if (argTyped->getType().isArray()) - { - error(line, "constructing from a non-dereferenced array", "constructor"); - return false; - } - if (argTyped->getType().isMatrix()) - { - matrixArg = true; - } - - size += argTyped->getType().getObjectSize(); - if (full) - { - overFull = true; - } - if (size >= type.getObjectSize()) - { - full = true; - } - } - - if (type.isMatrix() && matrixArg) - { - if (arguments->size() != 1) - { - error(line, "constructing matrix from matrix can only take one argument", - "constructor"); - return false; - } - } - else - { - if (size != 1 && size < type.getObjectSize()) - { - error(line, "not enough data provided for construction", "constructor"); - return false; - } - if (overFull) - { - error(line, "too many arguments", "constructor"); - return false; - } - } - } - - return true; -} - -// This function 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::checkIsNonVoid(const TSourceLoc &line, - const TString &identifier, - const TBasicType &type) -{ - if (type == EbtVoid) - { - error(line, "illegal use of type 'void'", identifier.c_str()); - return false; - } - - return true; -} - -// This function checks to see if the node (for the expression) contains a scalar boolean expression -// or not. -bool TParseContext::checkIsScalarBool(const TSourceLoc &line, const TIntermTyped *type) -{ - if (type->getBasicType() != EbtBool || !type->isScalar()) - { - error(line, "boolean expression expected", ""); - return false; - } - return true; -} - -// This function checks to see if the node (for the expression) contains a scalar boolean expression -// or not. -void TParseContext::checkIsScalarBool(const TSourceLoc &line, const TPublicType &pType) -{ - if (pType.getBasicType() != EbtBool || pType.isAggregate()) - { - error(line, "boolean expression expected", ""); - } -} - -bool TParseContext::checkIsNotOpaqueType(const TSourceLoc &line, - const TTypeSpecifierNonArray &pType, - const char *reason) -{ - if (pType.type == EbtStruct) - { - if (ContainsSampler(pType.userDef)) - { - std::stringstream reasonStream; - reasonStream << reason << " (structure contains a sampler)"; - std::string reasonStr = reasonStream.str(); - error(line, reasonStr.c_str(), getBasicString(pType.type)); - return false; - } - // only samplers need to be checked from structs, since other opaque types can't be struct - // members. - return true; - } - else if (IsOpaqueType(pType.type)) - { - error(line, reason, getBasicString(pType.type)); - return false; - } - - return true; -} - -void TParseContext::checkDeclaratorLocationIsNotSpecified(const TSourceLoc &line, - const TPublicType &pType) -{ - if (pType.layoutQualifier.location != -1) - { - error(line, "location must only be specified for a single input or output variable", - "location"); - } -} - -void TParseContext::checkLocationIsNotSpecified(const TSourceLoc &location, - const TLayoutQualifier &layoutQualifier) -{ - if (layoutQualifier.location != -1) - { - const char *errorMsg = "invalid layout qualifier: only valid on program inputs and outputs"; - if (mShaderVersion >= 310) - { - errorMsg = - "invalid layout qualifier: only valid on shader inputs, outputs, and uniforms"; - } - error(location, errorMsg, "location"); - } -} - -void TParseContext::checkStd430IsForShaderStorageBlock(const TSourceLoc &location, - const TLayoutBlockStorage &blockStorage, - const TQualifier &qualifier) -{ - if (blockStorage == EbsStd430 && qualifier != EvqBuffer) - { - error(location, "The std430 layout is supported only for shader storage blocks.", "std430"); - } -} - -void TParseContext::checkOutParameterIsNotOpaqueType(const TSourceLoc &line, - TQualifier qualifier, - const TType &type) -{ - ASSERT(qualifier == EvqOut || qualifier == EvqInOut); - if (IsOpaqueType(type.getBasicType())) - { - error(line, "opaque types cannot be output parameters", type.getBasicString()); - } -} - -// Do size checking for an array type's size. -unsigned int TParseContext::checkIsValidArraySize(const TSourceLoc &line, TIntermTyped *expr) -{ - TIntermConstantUnion *constant = expr->getAsConstantUnion(); - - // TODO(oetuaho@nvidia.com): Get rid of the constant == nullptr check here once all constant - // expressions can be folded. Right now we don't allow constant expressions that ANGLE can't - // fold as array size. - if (expr->getQualifier() != EvqConst || constant == nullptr || !constant->isScalarInt()) - { - error(line, "array size must be a constant integer expression", ""); - return 1u; - } - - unsigned int size = 0u; - - if (constant->getBasicType() == EbtUInt) - { - size = constant->getUConst(0); - } - else - { - int signedSize = constant->getIConst(0); - - if (signedSize < 0) - { - error(line, "array size must be non-negative", ""); - return 1u; - } - - size = static_cast(signedSize); - } - - if (size == 0u) - { - error(line, "array size must be greater than zero", ""); - return 1u; - } - - // The size of arrays is restricted here to prevent issues further down the - // compiler/translator/driver stack. Shader Model 5 generation hardware is limited to - // 4096 registers so this should be reasonable even for aggressively optimizable code. - const unsigned int sizeLimit = 65536; - - if (size > sizeLimit) - { - error(line, "array size too large", ""); - return 1u; - } - - return size; -} - -// See if this qualifier can be an array. -bool TParseContext::checkIsValidQualifierForArray(const TSourceLoc &line, - const TPublicType &elementQualifier) -{ - if ((elementQualifier.qualifier == EvqAttribute) || - (elementQualifier.qualifier == EvqVertexIn) || - (elementQualifier.qualifier == EvqConst && mShaderVersion < 300)) - { - error(line, "cannot declare arrays of this qualifier", - TType(elementQualifier).getQualifierString()); - return false; - } - - return true; -} - -// See if this element type can be formed into an array. -bool TParseContext::checkArrayElementIsNotArray(const TSourceLoc &line, - const TPublicType &elementType) -{ - if (mShaderVersion < 310 && elementType.isArray()) - { - error(line, "cannot declare arrays of arrays", - TType(elementType).getCompleteString().c_str()); - return false; - } - return true; -} - -// Check if this qualified element type can be formed into an array. This is only called when array -// brackets are associated with an identifier in a declaration, like this: -// float a[2]; -// Similar checks are done in addFullySpecifiedType for array declarations where the array brackets -// are associated with the type, like this: -// float[2] a; -bool TParseContext::checkIsValidTypeAndQualifierForArray(const TSourceLoc &indexLocation, - const TPublicType &elementType) -{ - if (!checkArrayElementIsNotArray(indexLocation, elementType)) - { - return false; - } - // In ESSL1.00 shaders, structs cannot be varying (section 4.3.5). This is checked elsewhere. - // In ESSL3.00 shaders, struct inputs/outputs are allowed but not arrays of structs (section - // 4.3.4). - if (mShaderVersion >= 300 && elementType.getBasicType() == EbtStruct && - sh::IsVarying(elementType.qualifier)) - { - error(indexLocation, "cannot declare arrays of structs of this qualifier", - TType(elementType).getCompleteString().c_str()); - return false; - } - return checkIsValidQualifierForArray(indexLocation, elementType); -} - -// Enforce non-initializer type/qualifier rules. -void TParseContext::checkCanBeDeclaredWithoutInitializer(const TSourceLoc &line, - const TString &identifier, - TType *type) -{ - ASSERT(type != nullptr); - if (type->getQualifier() == EvqConst) - { - // Make the qualifier make sense. - type->setQualifier(EvqTemporary); - - // Generate informative error messages for ESSL1. - // In ESSL3 arrays and structures containing arrays can be constant. - if (mShaderVersion < 300 && type->isStructureContainingArrays()) - { - error(line, - "structures containing arrays may not be declared constant since they cannot be " - "initialized", - identifier.c_str()); - } - else - { - error(line, "variables with qualifier 'const' must be initialized", identifier.c_str()); - } - } - // This will make the type sized if it isn't sized yet. - checkIsNotUnsizedArray(line, "implicitly sized arrays need to be initialized", - identifier.c_str(), type); -} - -// Do some simple checks that are shared between all variable declarations, -// and update the symbol table. -// -// Returns true if declaring the variable succeeded. -// -bool TParseContext::declareVariable(const TSourceLoc &line, - const TString &identifier, - const TType &type, - TVariable **variable) -{ - ASSERT((*variable) == nullptr); - - checkBindingIsValid(line, type); - - bool needsReservedCheck = true; - - // gl_LastFragData may be redeclared with a new precision qualifier - if (type.isArray() && identifier.compare(0, 15, "gl_LastFragData") == 0) - { - const TVariable *maxDrawBuffers = static_cast( - symbolTable.findBuiltIn("gl_MaxDrawBuffers", mShaderVersion)); - if (type.isArrayOfArrays()) - { - error(line, "redeclaration of gl_LastFragData as an array of arrays", - identifier.c_str()); - return false; - } - else if (static_cast(type.getOutermostArraySize()) == - maxDrawBuffers->getConstPointer()->getIConst()) - { - if (TSymbol *builtInSymbol = symbolTable.findBuiltIn(identifier, mShaderVersion)) - { - needsReservedCheck = !checkCanUseExtension(line, builtInSymbol->getExtension()); - } - } - else - { - error(line, "redeclaration of gl_LastFragData with size != gl_MaxDrawBuffers", - identifier.c_str()); - return false; - } - } - - if (needsReservedCheck && !checkIsNotReserved(line, identifier)) - return false; - - (*variable) = symbolTable.declareVariable(&identifier, type); - if (!(*variable)) - { - error(line, "redefinition", identifier.c_str()); - return false; - } - - if (!checkIsNonVoid(line, identifier, type.getBasicType())) - return false; - - return true; -} - -void TParseContext::checkIsParameterQualifierValid( - const TSourceLoc &line, - const TTypeQualifierBuilder &typeQualifierBuilder, - TType *type) -{ - // The only parameter qualifiers a parameter can have are in, out, inout or const. - TTypeQualifier typeQualifier = typeQualifierBuilder.getParameterTypeQualifier(mDiagnostics); - - if (typeQualifier.qualifier == EvqOut || typeQualifier.qualifier == EvqInOut) - { - checkOutParameterIsNotOpaqueType(line, typeQualifier.qualifier, *type); - } - - if (!IsImage(type->getBasicType())) - { - checkMemoryQualifierIsNotSpecified(typeQualifier.memoryQualifier, line); - } - else - { - type->setMemoryQualifier(typeQualifier.memoryQualifier); - } - - type->setQualifier(typeQualifier.qualifier); - - if (typeQualifier.precision != EbpUndefined) - { - type->setPrecision(typeQualifier.precision); - } -} - -template -bool TParseContext::checkCanUseOneOfExtensions(const TSourceLoc &line, - const std::array &extensions) -{ - ASSERT(!extensions.empty()); - const TExtensionBehavior &extBehavior = extensionBehavior(); - - bool canUseWithWarning = false; - bool canUseWithoutWarning = false; - - const char *errorMsgString = ""; - TExtension errorMsgExtension = TExtension::UNDEFINED; - - for (TExtension extension : extensions) - { - auto extIter = extBehavior.find(extension); - if (canUseWithWarning) - { - // We already have an extension that we can use, but with a warning. - // See if we can use the alternative extension without a warning. - if (extIter == extBehavior.end()) - { - continue; - } - if (extIter->second == EBhEnable || extIter->second == EBhRequire) - { - canUseWithoutWarning = true; - break; - } - continue; - } - if (extIter == extBehavior.end()) - { - errorMsgString = "extension is not supported"; - errorMsgExtension = extension; - } - else if (extIter->second == EBhUndefined || extIter->second == EBhDisable) - { - errorMsgString = "extension is disabled"; - errorMsgExtension = extension; - } - else if (extIter->second == EBhWarn) - { - errorMsgExtension = extension; - canUseWithWarning = true; - } - else - { - ASSERT(extIter->second == EBhEnable || extIter->second == EBhRequire); - canUseWithoutWarning = true; - break; - } - } - - if (canUseWithoutWarning) - { - return true; - } - if (canUseWithWarning) - { - warning(line, "extension is being used", GetExtensionNameString(errorMsgExtension)); - return true; - } - error(line, errorMsgString, GetExtensionNameString(errorMsgExtension)); - return false; -} - -template bool TParseContext::checkCanUseOneOfExtensions( - const TSourceLoc &line, - const std::array &extensions); -template bool TParseContext::checkCanUseOneOfExtensions( - const TSourceLoc &line, - const std::array &extensions); -template bool TParseContext::checkCanUseOneOfExtensions( - const TSourceLoc &line, - const std::array &extensions); - -bool TParseContext::checkCanUseExtension(const TSourceLoc &line, TExtension extension) -{ - ASSERT(extension != TExtension::UNDEFINED); - ASSERT(extension != TExtension::EXT_geometry_shader); - if (extension == TExtension::OES_geometry_shader) - { - // OES_geometry_shader and EXT_geometry_shader are always interchangeable. - constexpr std::array extensions{ - {TExtension::EXT_geometry_shader, TExtension::OES_geometry_shader}}; - return checkCanUseOneOfExtensions(line, extensions); - } - return checkCanUseOneOfExtensions(line, std::array{{extension}}); -} - -// ESSL 3.00.6 section 4.8 Empty Declarations: "The combinations of qualifiers that cause -// compile-time or link-time errors are the same whether or not the declaration is empty". -// This function implements all the checks that are done on qualifiers regardless of if the -// declaration is empty. -void TParseContext::declarationQualifierErrorCheck(const sh::TQualifier qualifier, - const sh::TLayoutQualifier &layoutQualifier, - const TSourceLoc &location) -{ - if (qualifier == EvqShared && !layoutQualifier.isEmpty()) - { - error(location, "Shared memory declarations cannot have layout specified", "layout"); - } - - if (layoutQualifier.matrixPacking != EmpUnspecified) - { - error(location, "layout qualifier only valid for interface blocks", - getMatrixPackingString(layoutQualifier.matrixPacking)); - return; - } - - if (layoutQualifier.blockStorage != EbsUnspecified) - { - error(location, "layout qualifier only valid for interface blocks", - getBlockStorageString(layoutQualifier.blockStorage)); - return; - } - - if (qualifier == EvqFragmentOut) - { - if (layoutQualifier.location != -1 && layoutQualifier.yuv == true) - { - error(location, "invalid layout qualifier combination", "yuv"); - return; - } - } - else - { - checkYuvIsNotSpecified(location, layoutQualifier.yuv); - } - - // If multiview extension is enabled, "in" qualifier is allowed in the vertex shader in previous - // parsing steps. So it needs to be checked here. - if (isExtensionEnabled(TExtension::OVR_multiview) && mShaderVersion < 300 && - qualifier == EvqVertexIn) - { - error(location, "storage qualifier supported in GLSL ES 3.00 and above only", "in"); - } - - bool canHaveLocation = qualifier == EvqVertexIn || qualifier == EvqFragmentOut; - if (mShaderVersion >= 310) - { - canHaveLocation = canHaveLocation || qualifier == EvqUniform || IsVarying(qualifier); - // We're not checking whether the uniform location is in range here since that depends on - // the type of the variable. - // The type can only be fully determined for non-empty declarations. - } - if (!canHaveLocation) - { - checkLocationIsNotSpecified(location, layoutQualifier); - } -} - -void TParseContext::atomicCounterQualifierErrorCheck(const TPublicType &publicType, - const TSourceLoc &location) -{ - if (publicType.precision != EbpHigh) - { - error(location, "Can only be highp", "atomic counter"); - } - // dEQP enforces compile error if location is specified. See uniform_location.test. - if (publicType.layoutQualifier.location != -1) - { - error(location, "location must not be set for atomic_uint", "layout"); - } - if (publicType.layoutQualifier.binding == -1) - { - error(location, "no binding specified", "atomic counter"); - } -} - -void TParseContext::emptyDeclarationErrorCheck(const TType &type, const TSourceLoc &location) -{ - if (type.isUnsizedArray()) - { - // ESSL3 spec section 4.1.9: Array declaration which leaves the size unspecified is an - // error. It is assumed that this applies to empty declarations as well. - error(location, "empty array declaration needs to specify a size", ""); - } -} - -// These checks are done for all declarations that are non-empty. They're done for non-empty -// declarations starting a declarator list, and declarators that follow an empty declaration. -void TParseContext::nonEmptyDeclarationErrorCheck(const TPublicType &publicType, - const TSourceLoc &identifierLocation) -{ - switch (publicType.qualifier) - { - case EvqVaryingIn: - case EvqVaryingOut: - case EvqAttribute: - case EvqVertexIn: - case EvqFragmentOut: - case EvqComputeIn: - if (publicType.getBasicType() == EbtStruct) - { - error(identifierLocation, "cannot be used with a structure", - getQualifierString(publicType.qualifier)); - return; - } - break; - case EvqBuffer: - if (publicType.getBasicType() != EbtInterfaceBlock) - { - error(identifierLocation, - "cannot declare buffer variables at global scope(outside a block)", - getQualifierString(publicType.qualifier)); - return; - } - break; - default: - break; - } - std::string reason(getBasicString(publicType.getBasicType())); - reason += "s must be uniform"; - if (publicType.qualifier != EvqUniform && - !checkIsNotOpaqueType(identifierLocation, publicType.typeSpecifierNonArray, reason.c_str())) - { - return; - } - - if ((publicType.qualifier != EvqTemporary && publicType.qualifier != EvqGlobal && - publicType.qualifier != EvqConst) && - publicType.getBasicType() == EbtYuvCscStandardEXT) - { - error(identifierLocation, "cannot be used with a yuvCscStandardEXT", - getQualifierString(publicType.qualifier)); - return; - } - - if (mShaderVersion >= 310 && publicType.qualifier == EvqUniform) - { - // Valid uniform declarations can't be unsized arrays since uniforms can't be initialized. - // But invalid shaders may still reach here with an unsized array declaration. - TType type(publicType); - if (!type.isUnsizedArray()) - { - checkUniformLocationInRange(identifierLocation, type.getLocationCount(), - publicType.layoutQualifier); - } - } - - // check for layout qualifier issues - const TLayoutQualifier layoutQualifier = publicType.layoutQualifier; - - if (IsImage(publicType.getBasicType())) - { - - switch (layoutQualifier.imageInternalFormat) - { - case EiifRGBA32F: - case EiifRGBA16F: - case EiifR32F: - case EiifRGBA8: - case EiifRGBA8_SNORM: - if (!IsFloatImage(publicType.getBasicType())) - { - error(identifierLocation, - "internal image format requires a floating image type", - getBasicString(publicType.getBasicType())); - return; - } - break; - case EiifRGBA32I: - case EiifRGBA16I: - case EiifRGBA8I: - case EiifR32I: - if (!IsIntegerImage(publicType.getBasicType())) - { - error(identifierLocation, - "internal image format requires an integer image type", - getBasicString(publicType.getBasicType())); - return; - } - break; - case EiifRGBA32UI: - case EiifRGBA16UI: - case EiifRGBA8UI: - case EiifR32UI: - if (!IsUnsignedImage(publicType.getBasicType())) - { - error(identifierLocation, - "internal image format requires an unsigned image type", - getBasicString(publicType.getBasicType())); - return; - } - break; - case EiifUnspecified: - error(identifierLocation, "layout qualifier", "No image internal format specified"); - return; - default: - error(identifierLocation, "layout qualifier", "unrecognized token"); - return; - } - - // GLSL ES 3.10 Revision 4, 4.9 Memory Access Qualifiers - switch (layoutQualifier.imageInternalFormat) - { - case EiifR32F: - case EiifR32I: - case EiifR32UI: - break; - default: - if (!publicType.memoryQualifier.readonly && !publicType.memoryQualifier.writeonly) - { - error(identifierLocation, "layout qualifier", - "Except for images with the r32f, r32i and r32ui format qualifiers, " - "image variables must be qualified readonly and/or writeonly"); - return; - } - break; - } - } - else - { - checkInternalFormatIsNotSpecified(identifierLocation, layoutQualifier.imageInternalFormat); - checkMemoryQualifierIsNotSpecified(publicType.memoryQualifier, identifierLocation); - } - - if (IsAtomicCounter(publicType.getBasicType())) - { - atomicCounterQualifierErrorCheck(publicType, identifierLocation); - } - else - { - checkOffsetIsNotSpecified(identifierLocation, layoutQualifier.offset); - } -} - -void TParseContext::checkBindingIsValid(const TSourceLoc &identifierLocation, const TType &type) -{ - TLayoutQualifier layoutQualifier = type.getLayoutQualifier(); - // Note that the ESSL 3.10 section 4.4.5 is not particularly clear on how the binding qualifier - // on arrays of arrays should be handled. We interpret the spec so that the binding value is - // incremented for each element of the innermost nested arrays. This is in line with how arrays - // of arrays of blocks are specified to behave in GLSL 4.50 and a conservative interpretation - // when it comes to which shaders are accepted by the compiler. - int arrayTotalElementCount = type.getArraySizeProduct(); - if (IsImage(type.getBasicType())) - { - checkImageBindingIsValid(identifierLocation, layoutQualifier.binding, - arrayTotalElementCount); - } - else if (IsSampler(type.getBasicType())) - { - checkSamplerBindingIsValid(identifierLocation, layoutQualifier.binding, - arrayTotalElementCount); - } - else if (IsAtomicCounter(type.getBasicType())) - { - checkAtomicCounterBindingIsValid(identifierLocation, layoutQualifier.binding); - } - else - { - ASSERT(!IsOpaqueType(type.getBasicType())); - checkBindingIsNotSpecified(identifierLocation, layoutQualifier.binding); - } -} - -void TParseContext::checkLayoutQualifierSupported(const TSourceLoc &location, - const TString &layoutQualifierName, - int versionRequired) -{ - - if (mShaderVersion < versionRequired) - { - error(location, "invalid layout qualifier: not supported", layoutQualifierName.c_str()); - } -} - -bool TParseContext::checkWorkGroupSizeIsNotSpecified(const TSourceLoc &location, - const TLayoutQualifier &layoutQualifier) -{ - const sh::WorkGroupSize &localSize = layoutQualifier.localSize; - for (size_t i = 0u; i < localSize.size(); ++i) - { - if (localSize[i] != -1) - { - error(location, - "invalid layout qualifier: only valid when used with 'in' in a compute shader " - "global layout declaration", - getWorkGroupSizeString(i)); - return false; - } - } - - return true; -} - -void TParseContext::checkInternalFormatIsNotSpecified(const TSourceLoc &location, - TLayoutImageInternalFormat internalFormat) -{ - if (internalFormat != EiifUnspecified) - { - error(location, "invalid layout qualifier: only valid when used with images", - getImageInternalFormatString(internalFormat)); - } -} - -void TParseContext::checkBindingIsNotSpecified(const TSourceLoc &location, int binding) -{ - if (binding != -1) - { - error(location, - "invalid layout qualifier: only valid when used with opaque types or blocks", - "binding"); - } -} - -void TParseContext::checkOffsetIsNotSpecified(const TSourceLoc &location, int offset) -{ - if (offset != -1) - { - error(location, "invalid layout qualifier: only valid when used with atomic counters", - "offset"); - } -} - -void TParseContext::checkImageBindingIsValid(const TSourceLoc &location, - int binding, - int arrayTotalElementCount) -{ - // Expects arraySize to be 1 when setting binding for only a single variable. - if (binding >= 0 && binding + arrayTotalElementCount > mMaxImageUnits) - { - error(location, "image binding greater than gl_MaxImageUnits", "binding"); - } -} - -void TParseContext::checkSamplerBindingIsValid(const TSourceLoc &location, - int binding, - int arrayTotalElementCount) -{ - // Expects arraySize to be 1 when setting binding for only a single variable. - if (binding >= 0 && binding + arrayTotalElementCount > mMaxCombinedTextureImageUnits) - { - error(location, "sampler binding greater than maximum texture units", "binding"); - } -} - -void TParseContext::checkBlockBindingIsValid(const TSourceLoc &location, - const TQualifier &qualifier, - int binding, - int arraySize) -{ - int size = (arraySize == 0 ? 1 : arraySize); - if (qualifier == EvqUniform) - { - if (binding + size > mMaxUniformBufferBindings) - { - error(location, "uniform block binding greater than MAX_UNIFORM_BUFFER_BINDINGS", - "binding"); - } - } - else if (qualifier == EvqBuffer) - { - if (binding + size > mMaxShaderStorageBufferBindings) - { - error(location, - "shader storage block binding greater than MAX_SHADER_STORAGE_BUFFER_BINDINGS", - "binding"); - } - } -} -void TParseContext::checkAtomicCounterBindingIsValid(const TSourceLoc &location, int binding) -{ - if (binding >= mMaxAtomicCounterBindings) - { - error(location, "atomic counter binding greater than gl_MaxAtomicCounterBindings", - "binding"); - } -} - -void TParseContext::checkUniformLocationInRange(const TSourceLoc &location, - int objectLocationCount, - const TLayoutQualifier &layoutQualifier) -{ - int loc = layoutQualifier.location; - if (loc >= 0 && loc + objectLocationCount > mMaxUniformLocations) - { - error(location, "Uniform location out of range", "location"); - } -} - -void TParseContext::checkYuvIsNotSpecified(const TSourceLoc &location, bool yuv) -{ - if (yuv != false) - { - error(location, "invalid layout qualifier: only valid on program outputs", "yuv"); - } -} - -void TParseContext::functionCallRValueLValueErrorCheck(const TFunction *fnCandidate, - TIntermAggregate *fnCall) -{ - for (size_t i = 0; i < fnCandidate->getParamCount(); ++i) - { - TQualifier qual = fnCandidate->getParam(i).type->getQualifier(); - TIntermTyped *argument = (*(fnCall->getSequence()))[i]->getAsTyped(); - if (!IsImage(argument->getBasicType()) && (IsQualifierUnspecified(qual) || qual == EvqIn || - qual == EvqInOut || qual == EvqConstReadOnly)) - { - if (argument->getMemoryQualifier().writeonly) - { - error(argument->getLine(), - "Writeonly value cannot be passed for 'in' or 'inout' parameters.", - fnCall->getFunctionSymbolInfo()->getName().c_str()); - return; - } - } - if (qual == EvqOut || qual == EvqInOut) - { - if (!checkCanBeLValue(argument->getLine(), "assign", argument)) - { - error(argument->getLine(), - "Constant value cannot be passed for 'out' or 'inout' parameters.", - fnCall->getFunctionSymbolInfo()->getName().c_str()); - return; - } - } - } -} - -void TParseContext::checkInvariantVariableQualifier(bool invariant, - const TQualifier qualifier, - const TSourceLoc &invariantLocation) -{ - if (!invariant) - return; - - if (mShaderVersion < 300) - { - // input variables in the fragment shader can be also qualified as invariant - if (!sh::CanBeInvariantESSL1(qualifier)) - { - error(invariantLocation, "Cannot be qualified as invariant.", "invariant"); - } - } - else - { - if (!sh::CanBeInvariantESSL3OrGreater(qualifier)) - { - error(invariantLocation, "Cannot be qualified as invariant.", "invariant"); - } - } -} - -bool TParseContext::isExtensionEnabled(TExtension extension) const -{ - return IsExtensionEnabled(extensionBehavior(), extension); -} - -void TParseContext::handleExtensionDirective(const TSourceLoc &loc, - const char *extName, - const char *behavior) -{ - pp::SourceLocation srcLoc; - srcLoc.file = loc.first_file; - srcLoc.line = loc.first_line; - mDirectiveHandler.handleExtension(srcLoc, extName, behavior); -} - -void TParseContext::handlePragmaDirective(const TSourceLoc &loc, - const char *name, - const char *value, - bool stdgl) -{ - pp::SourceLocation srcLoc; - srcLoc.file = loc.first_file; - srcLoc.line = loc.first_line; - mDirectiveHandler.handlePragma(srcLoc, name, value, stdgl); -} - -sh::WorkGroupSize TParseContext::getComputeShaderLocalSize() const -{ - sh::WorkGroupSize result(-1); - for (size_t i = 0u; i < result.size(); ++i) - { - if (mComputeShaderLocalSizeDeclared && mComputeShaderLocalSize[i] == -1) - { - result[i] = 1; - } - else - { - result[i] = mComputeShaderLocalSize[i]; - } - } - return result; -} - -TIntermConstantUnion *TParseContext::addScalarLiteral(const TConstantUnion *constantUnion, - const TSourceLoc &line) -{ - TIntermConstantUnion *node = new TIntermConstantUnion( - constantUnion, TType(constantUnion->getType(), EbpUndefined, EvqConst)); - node->setLine(line); - return node; -} - -///////////////////////////////////////////////////////////////////////////////// -// -// Non-Errors. -// -///////////////////////////////////////////////////////////////////////////////// - -const TVariable *TParseContext::getNamedVariable(const TSourceLoc &location, - const TString *name, - const TSymbol *symbol) -{ - if (!symbol) - { - error(location, "undeclared identifier", name->c_str()); - return nullptr; - } - - if (!symbol->isVariable()) - { - error(location, "variable expected", name->c_str()); - return nullptr; - } - - const TVariable *variable = static_cast(symbol); - - if (variable->getExtension() != TExtension::UNDEFINED) - { - checkCanUseExtension(location, variable->getExtension()); - } - - // Reject shaders using both gl_FragData and gl_FragColor - TQualifier qualifier = variable->getType().getQualifier(); - if (qualifier == EvqFragData || qualifier == EvqSecondaryFragDataEXT) - { - mUsesFragData = true; - } - else if (qualifier == EvqFragColor || qualifier == EvqSecondaryFragColorEXT) - { - mUsesFragColor = true; - } - if (qualifier == EvqSecondaryFragDataEXT || qualifier == EvqSecondaryFragColorEXT) - { - mUsesSecondaryOutputs = true; - } - - // This validation is not quite correct - it's only an error to write to - // both FragData and FragColor. For simplicity, and because users shouldn't - // be rewarded for reading from undefined varaibles, return an error - // if they are both referenced, rather than assigned. - if (mUsesFragData && mUsesFragColor) - { - const char *errorMessage = "cannot use both gl_FragData and gl_FragColor"; - if (mUsesSecondaryOutputs) - { - errorMessage = - "cannot use both output variable sets (gl_FragData, gl_SecondaryFragDataEXT)" - " and (gl_FragColor, gl_SecondaryFragColorEXT)"; - } - error(location, errorMessage, name->c_str()); - } - - // GLSL ES 3.1 Revision 4, 7.1.3 Compute Shader Special Variables - if (getShaderType() == GL_COMPUTE_SHADER && !mComputeShaderLocalSizeDeclared && - qualifier == EvqWorkGroupSize) - { - error(location, - "It is an error to use gl_WorkGroupSize before declaring the local group size", - "gl_WorkGroupSize"); - } - return variable; -} - -TIntermTyped *TParseContext::parseVariableIdentifier(const TSourceLoc &location, - const TString *name, - const TSymbol *symbol) -{ - const TVariable *variable = getNamedVariable(location, name, symbol); - - if (!variable) - { - TIntermTyped *node = CreateZeroNode(TType(EbtFloat, EbpHigh, EvqConst)); - node->setLine(location); - return node; - } - - const TType &variableType = variable->getType(); - TIntermTyped *node = nullptr; - - if (variable->getConstPointer()) - { - const TConstantUnion *constArray = variable->getConstPointer(); - node = new TIntermConstantUnion(constArray, variableType); - } - else if (variableType.getQualifier() == EvqWorkGroupSize && mComputeShaderLocalSizeDeclared) - { - // gl_WorkGroupSize can be used to size arrays according to the ESSL 3.10.4 spec, so it - // needs to be added to the AST as a constant and not as a symbol. - sh::WorkGroupSize workGroupSize = getComputeShaderLocalSize(); - TConstantUnion *constArray = new TConstantUnion[3]; - for (size_t i = 0; i < 3; ++i) - { - constArray[i].setUConst(static_cast(workGroupSize[i])); - } - - ASSERT(variableType.getBasicType() == EbtUInt); - ASSERT(variableType.getObjectSize() == 3); - - TType type(variableType); - type.setQualifier(EvqConst); - node = new TIntermConstantUnion(constArray, type); - } - else if ((mGeometryShaderInputPrimitiveType != EptUndefined) && - (variableType.getQualifier() == EvqPerVertexIn)) - { - ASSERT(mGeometryShaderInputArraySize > 0u); - - node = new TIntermSymbol(variable->getUniqueId(), variable->getName(), variableType); - node->getTypePointer()->sizeOutermostUnsizedArray(mGeometryShaderInputArraySize); - } - else - { - node = new TIntermSymbol(variable->getUniqueId(), variable->getName(), variableType); - } - ASSERT(node != nullptr); - node->setLine(location); - return node; -} - -// Initializers show up in several places in the grammar. Have one set of -// code to handle them here. -// -// Returns true on success. -bool TParseContext::executeInitializer(const TSourceLoc &line, - const TString &identifier, - TType type, - TIntermTyped *initializer, - TIntermBinary **initNode) -{ - ASSERT(initNode != nullptr); - ASSERT(*initNode == nullptr); - - TVariable *variable = nullptr; - if (type.isUnsizedArray()) - { - // In case initializer is not an array or type has more dimensions than initializer, this - // will default to setting array sizes to 1. We have not checked yet whether the initializer - // actually is an array or not. Having a non-array initializer for an unsized array will - // result in an error later, so we don't generate an error message here. - auto *arraySizes = initializer->getType().getArraySizes(); - type.sizeUnsizedArrays(arraySizes); - } - if (!declareVariable(line, identifier, type, &variable)) - { - return false; - } - - bool globalInitWarning = false; - if (symbolTable.atGlobalLevel() && - !ValidateGlobalInitializer(initializer, this, &globalInitWarning)) - { - // Error message does not completely match behavior with ESSL 1.00, but - // we want to steer developers towards only using constant expressions. - error(line, "global variable initializers must be constant expressions", "="); - return false; - } - if (globalInitWarning) - { - warning( - line, - "global variable initializers should be constant expressions " - "(uniforms and globals are allowed in global initializers for legacy compatibility)", - "="); - } - - // - // identifier must be of type constant, a global, or a temporary - // - TQualifier qualifier = variable->getType().getQualifier(); - if ((qualifier != EvqTemporary) && (qualifier != EvqGlobal) && (qualifier != EvqConst)) - { - error(line, " cannot initialize this type of qualifier ", - variable->getType().getQualifierString()); - return false; - } - // - // test for and propagate constant - // - - if (qualifier == EvqConst) - { - if (qualifier != initializer->getType().getQualifier()) - { - std::stringstream reasonStream; - reasonStream << "assigning non-constant to '" << variable->getType().getCompleteString() - << "'"; - std::string reason = reasonStream.str(); - error(line, reason.c_str(), "="); - variable->getType().setQualifier(EvqTemporary); - return false; - } - if (type != initializer->getType()) - { - error(line, " non-matching types for const initializer ", - variable->getType().getQualifierString()); - variable->getType().setQualifier(EvqTemporary); - return false; - } - - // Save the constant folded value to the variable if possible. For example array - // initializers are not folded, since that way copying the array literal to multiple places - // in the shader is avoided. - // TODO(oetuaho@nvidia.com): Consider constant folding array initialization in cases where - // it would be beneficial. - if (initializer->getAsConstantUnion()) - { - variable->shareConstPointer(initializer->getAsConstantUnion()->getUnionArrayPointer()); - ASSERT(*initNode == nullptr); - return true; - } - else if (initializer->getAsSymbolNode()) - { - const TSymbol *symbol = - symbolTable.find(initializer->getAsSymbolNode()->getSymbol(), 0); - const TVariable *tVar = static_cast(symbol); - - const TConstantUnion *constArray = tVar->getConstPointer(); - if (constArray) - { - variable->shareConstPointer(constArray); - ASSERT(*initNode == nullptr); - return true; - } - } - } - - TIntermSymbol *intermSymbol = - new TIntermSymbol(variable->getUniqueId(), variable->getName(), variable->getType()); - intermSymbol->setLine(line); - *initNode = createAssign(EOpInitialize, intermSymbol, initializer, line); - if (*initNode == nullptr) - { - assignError(line, "=", intermSymbol->getCompleteString(), initializer->getCompleteString()); - return false; - } - - return true; -} - -TIntermNode *TParseContext::addConditionInitializer(const TPublicType &pType, - const TString &identifier, - TIntermTyped *initializer, - const TSourceLoc &loc) -{ - checkIsScalarBool(loc, pType); - TIntermBinary *initNode = nullptr; - TType type(pType); - if (executeInitializer(loc, identifier, type, initializer, &initNode)) - { - // The initializer is valid. The init condition needs to have a node - either the - // initializer node, or a constant node in case the initialized variable is const and won't - // be recorded in the AST. - if (initNode == nullptr) - { - return initializer; - } - else - { - TIntermDeclaration *declaration = new TIntermDeclaration(); - declaration->appendDeclarator(initNode); - return declaration; - } - } - return nullptr; -} - -TIntermNode *TParseContext::addLoop(TLoopType type, - TIntermNode *init, - TIntermNode *cond, - TIntermTyped *expr, - TIntermNode *body, - const TSourceLoc &line) -{ - TIntermNode *node = nullptr; - TIntermTyped *typedCond = nullptr; - if (cond) - { - typedCond = cond->getAsTyped(); - } - if (cond == nullptr || typedCond) - { - if (type == ELoopDoWhile) - { - checkIsScalarBool(line, typedCond); - } - // In the case of other loops, it was checked before that the condition is a scalar boolean. - ASSERT(mDiagnostics->numErrors() > 0 || typedCond == nullptr || - (typedCond->getBasicType() == EbtBool && !typedCond->isArray() && - !typedCond->isVector())); - - node = new TIntermLoop(type, init, typedCond, expr, EnsureBlock(body)); - node->setLine(line); - return node; - } - - ASSERT(type != ELoopDoWhile); - - TIntermDeclaration *declaration = cond->getAsDeclarationNode(); - ASSERT(declaration); - TIntermBinary *declarator = declaration->getSequence()->front()->getAsBinaryNode(); - ASSERT(declarator->getLeft()->getAsSymbolNode()); - - // The condition is a declaration. In the AST representation we don't support declarations as - // loop conditions. Wrap the loop to a block that declares the condition variable and contains - // the loop. - TIntermBlock *block = new TIntermBlock(); - - TIntermDeclaration *declareCondition = new TIntermDeclaration(); - declareCondition->appendDeclarator(declarator->getLeft()->deepCopy()); - block->appendStatement(declareCondition); - - TIntermBinary *conditionInit = new TIntermBinary(EOpAssign, declarator->getLeft()->deepCopy(), - declarator->getRight()->deepCopy()); - TIntermLoop *loop = new TIntermLoop(type, init, conditionInit, expr, EnsureBlock(body)); - block->appendStatement(loop); - loop->setLine(line); - block->setLine(line); - return block; -} - -TIntermNode *TParseContext::addIfElse(TIntermTyped *cond, - TIntermNodePair code, - const TSourceLoc &loc) -{ - bool isScalarBool = checkIsScalarBool(loc, cond); - - // For compile time constant conditions, prune the code now. - if (isScalarBool && cond->getAsConstantUnion()) - { - if (cond->getAsConstantUnion()->getBConst(0) == true) - { - return EnsureBlock(code.node1); - } - else - { - return EnsureBlock(code.node2); - } - } - - TIntermIfElse *node = new TIntermIfElse(cond, EnsureBlock(code.node1), EnsureBlock(code.node2)); - node->setLine(loc); - - return node; -} - -void TParseContext::addFullySpecifiedType(TPublicType *typeSpecifier) -{ - checkPrecisionSpecified(typeSpecifier->getLine(), typeSpecifier->precision, - typeSpecifier->getBasicType()); - - if (mShaderVersion < 300 && typeSpecifier->isArray()) - { - error(typeSpecifier->getLine(), "not supported", "first-class array"); - typeSpecifier->clearArrayness(); - } -} - -TPublicType TParseContext::addFullySpecifiedType(const TTypeQualifierBuilder &typeQualifierBuilder, - const TPublicType &typeSpecifier) -{ - TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics); - - TPublicType returnType = typeSpecifier; - returnType.qualifier = typeQualifier.qualifier; - returnType.invariant = typeQualifier.invariant; - returnType.layoutQualifier = typeQualifier.layoutQualifier; - returnType.memoryQualifier = typeQualifier.memoryQualifier; - returnType.precision = typeSpecifier.precision; - - if (typeQualifier.precision != EbpUndefined) - { - returnType.precision = typeQualifier.precision; - } - - checkPrecisionSpecified(typeSpecifier.getLine(), returnType.precision, - typeSpecifier.getBasicType()); - - checkInvariantVariableQualifier(returnType.invariant, returnType.qualifier, - typeSpecifier.getLine()); - - checkWorkGroupSizeIsNotSpecified(typeSpecifier.getLine(), returnType.layoutQualifier); - - if (mShaderVersion < 300) - { - if (typeSpecifier.isArray()) - { - error(typeSpecifier.getLine(), "not supported", "first-class array"); - returnType.clearArrayness(); - } - - if (returnType.qualifier == EvqAttribute && - (typeSpecifier.getBasicType() == EbtBool || typeSpecifier.getBasicType() == EbtInt)) - { - error(typeSpecifier.getLine(), "cannot be bool or int", - getQualifierString(returnType.qualifier)); - } - - if ((returnType.qualifier == EvqVaryingIn || returnType.qualifier == EvqVaryingOut) && - (typeSpecifier.getBasicType() == EbtBool || typeSpecifier.getBasicType() == EbtInt)) - { - error(typeSpecifier.getLine(), "cannot be bool or int", - getQualifierString(returnType.qualifier)); - } - } - else - { - if (!returnType.layoutQualifier.isEmpty()) - { - checkIsAtGlobalLevel(typeSpecifier.getLine(), "layout"); - } - if (sh::IsVarying(returnType.qualifier) || returnType.qualifier == EvqVertexIn || - returnType.qualifier == EvqFragmentOut) - { - checkInputOutputTypeIsValidES3(returnType.qualifier, typeSpecifier, - typeSpecifier.getLine()); - } - if (returnType.qualifier == EvqComputeIn) - { - error(typeSpecifier.getLine(), "'in' can be only used to specify the local group size", - "in"); - } - } - - return returnType; -} - -void TParseContext::checkInputOutputTypeIsValidES3(const TQualifier qualifier, - const TPublicType &type, - const TSourceLoc &qualifierLocation) -{ - // An input/output variable can never be bool or a sampler. Samplers are checked elsewhere. - if (type.getBasicType() == EbtBool) - { - error(qualifierLocation, "cannot be bool", getQualifierString(qualifier)); - } - - // Specific restrictions apply for vertex shader inputs and fragment shader outputs. - switch (qualifier) - { - case EvqVertexIn: - // ESSL 3.00 section 4.3.4 - if (type.isArray()) - { - error(qualifierLocation, "cannot be array", getQualifierString(qualifier)); - } - // Vertex inputs with a struct type are disallowed in nonEmptyDeclarationErrorCheck - return; - case EvqFragmentOut: - // ESSL 3.00 section 4.3.6 - if (type.typeSpecifierNonArray.isMatrix()) - { - error(qualifierLocation, "cannot be matrix", getQualifierString(qualifier)); - } - // Fragment outputs with a struct type are disallowed in nonEmptyDeclarationErrorCheck - return; - default: - break; - } - - // Vertex shader outputs / fragment shader inputs have a different, slightly more lenient set of - // restrictions. - bool typeContainsIntegers = - (type.getBasicType() == EbtInt || type.getBasicType() == EbtUInt || - type.isStructureContainingType(EbtInt) || type.isStructureContainingType(EbtUInt)); - if (typeContainsIntegers && qualifier != EvqFlatIn && qualifier != EvqFlatOut) - { - error(qualifierLocation, "must use 'flat' interpolation here", - getQualifierString(qualifier)); - } - - if (type.getBasicType() == EbtStruct) - { - // ESSL 3.00 sections 4.3.4 and 4.3.6. - // These restrictions are only implied by the ESSL 3.00 spec, but - // the ESSL 3.10 spec lists these restrictions explicitly. - if (type.isArray()) - { - error(qualifierLocation, "cannot be an array of structures", - getQualifierString(qualifier)); - } - if (type.isStructureContainingArrays()) - { - error(qualifierLocation, "cannot be a structure containing an array", - getQualifierString(qualifier)); - } - if (type.isStructureContainingType(EbtStruct)) - { - error(qualifierLocation, "cannot be a structure containing a structure", - getQualifierString(qualifier)); - } - if (type.isStructureContainingType(EbtBool)) - { - error(qualifierLocation, "cannot be a structure containing a bool", - getQualifierString(qualifier)); - } - } -} - -void TParseContext::checkLocalVariableConstStorageQualifier(const TQualifierWrapperBase &qualifier) -{ - if (qualifier.getType() == QtStorage) - { - const TStorageQualifierWrapper &storageQualifier = - static_cast(qualifier); - if (!declaringFunction() && storageQualifier.getQualifier() != EvqConst && - !symbolTable.atGlobalLevel()) - { - error(storageQualifier.getLine(), - "Local variables can only use the const storage qualifier.", - storageQualifier.getQualifierString().c_str()); - } - } -} - -void TParseContext::checkMemoryQualifierIsNotSpecified(const TMemoryQualifier &memoryQualifier, - const TSourceLoc &location) -{ - const std::string reason( - "Only allowed with shader storage blocks, variables declared within shader storage blocks " - "and variables declared as image types."); - if (memoryQualifier.readonly) - { - error(location, reason.c_str(), "readonly"); - } - if (memoryQualifier.writeonly) - { - error(location, reason.c_str(), "writeonly"); - } - if (memoryQualifier.coherent) - { - error(location, reason.c_str(), "coherent"); - } - if (memoryQualifier.restrictQualifier) - { - error(location, reason.c_str(), "restrict"); - } - if (memoryQualifier.volatileQualifier) - { - error(location, reason.c_str(), "volatile"); - } -} - -// Make sure there is no offset overlapping, and store the newly assigned offset to "type" in -// intermediate tree. -void TParseContext::checkAtomicCounterOffsetDoesNotOverlap(bool forceAppend, - const TSourceLoc &loc, - TType *type) -{ - if (!IsAtomicCounter(type->getBasicType())) - { - return; - } - - const size_t size = type->isArray() ? kAtomicCounterArrayStride * type->getArraySizeProduct() - : kAtomicCounterSize; - TLayoutQualifier layoutQualifier = type->getLayoutQualifier(); - auto &bindingState = mAtomicCounterBindingStates[layoutQualifier.binding]; - int offset; - if (layoutQualifier.offset == -1 || forceAppend) - { - offset = bindingState.appendSpan(size); - } - else - { - offset = bindingState.insertSpan(layoutQualifier.offset, size); - } - if (offset == -1) - { - error(loc, "Offset overlapping", "atomic counter"); - return; - } - layoutQualifier.offset = offset; - type->setLayoutQualifier(layoutQualifier); -} - -void TParseContext::checkGeometryShaderInputAndSetArraySize(const TSourceLoc &location, - const char *token, - TType *type) -{ - if (IsGeometryShaderInput(mShaderType, type->getQualifier())) - { - if (type->isArray() && type->getOutermostArraySize() == 0u) - { - // Set size for the unsized geometry shader inputs if they are declared after a valid - // input primitive declaration. - if (mGeometryShaderInputPrimitiveType != EptUndefined) - { - ASSERT(mGeometryShaderInputArraySize > 0u); - type->sizeOutermostUnsizedArray(mGeometryShaderInputArraySize); - } - else - { - // [GLSL ES 3.2 SPEC Chapter 4.4.1.2] - // An input can be declared without an array size if there is a previous layout - // which specifies the size. - error(location, - "Missing a valid input primitive declaration before declaring an unsized " - "array input", - token); - } - } - else if (type->isArray()) - { - setGeometryShaderInputArraySize(type->getOutermostArraySize(), location); - } - else - { - error(location, "Geometry shader input variable must be declared as an array", token); - } - } -} - -TIntermDeclaration *TParseContext::parseSingleDeclaration( - TPublicType &publicType, - const TSourceLoc &identifierOrTypeLocation, - const TString &identifier) -{ - TType type(publicType); - if ((mCompileOptions & SH_FLATTEN_PRAGMA_STDGL_INVARIANT_ALL) && - mDirectiveHandler.pragma().stdgl.invariantAll) - { - TQualifier qualifier = type.getQualifier(); - - // The directive handler has already taken care of rejecting invalid uses of this pragma - // (for example, in ESSL 3.00 fragment shaders), so at this point, flatten it into all - // affected variable declarations: - // - // 1. Built-in special variables which are inputs to the fragment shader. (These are handled - // elsewhere, in TranslatorGLSL.) - // - // 2. Outputs from vertex shaders in ESSL 1.00 and 3.00 (EvqVaryingOut and EvqVertexOut). It - // is actually less likely that there will be bugs in the handling of ESSL 3.00 shaders, but - // the way this is currently implemented we have to enable this compiler option before - // parsing the shader and determining the shading language version it uses. If this were - // implemented as a post-pass, the workaround could be more targeted. - // - // 3. Inputs in ESSL 1.00 fragment shaders (EvqVaryingIn). This is somewhat in violation of - // the specification, but there are desktop OpenGL drivers that expect that this is the - // behavior of the #pragma when specified in ESSL 1.00 fragment shaders. - if (qualifier == EvqVaryingOut || qualifier == EvqVertexOut || qualifier == EvqVaryingIn) - { - type.setInvariant(true); - } - } - - checkGeometryShaderInputAndSetArraySize(identifierOrTypeLocation, identifier.c_str(), &type); - - declarationQualifierErrorCheck(publicType.qualifier, publicType.layoutQualifier, - identifierOrTypeLocation); - - bool emptyDeclaration = (identifier == ""); - mDeferredNonEmptyDeclarationErrorCheck = emptyDeclaration; - - TIntermSymbol *symbol = nullptr; - if (emptyDeclaration) - { - emptyDeclarationErrorCheck(type, identifierOrTypeLocation); - // In most cases we don't need to create a symbol node for an empty declaration. - // But if the empty declaration is declaring a struct type, the symbol node will store that. - if (type.getBasicType() == EbtStruct) - { - symbol = new TIntermSymbol(symbolTable.getEmptySymbolId(), "", type); - } - else if (IsAtomicCounter(publicType.getBasicType())) - { - setAtomicCounterBindingDefaultOffset(publicType, identifierOrTypeLocation); - } - } - else - { - nonEmptyDeclarationErrorCheck(publicType, identifierOrTypeLocation); - - checkCanBeDeclaredWithoutInitializer(identifierOrTypeLocation, identifier, &type); - - checkAtomicCounterOffsetDoesNotOverlap(false, identifierOrTypeLocation, &type); - - TVariable *variable = nullptr; - declareVariable(identifierOrTypeLocation, identifier, type, &variable); - - if (variable) - { - symbol = new TIntermSymbol(variable->getUniqueId(), identifier, type); - } - } - - TIntermDeclaration *declaration = new TIntermDeclaration(); - declaration->setLine(identifierOrTypeLocation); - if (symbol) - { - symbol->setLine(identifierOrTypeLocation); - declaration->appendDeclarator(symbol); - } - return declaration; -} - -TIntermDeclaration *TParseContext::parseSingleArrayDeclaration( - TPublicType &elementType, - const TSourceLoc &identifierLocation, - const TString &identifier, - const TSourceLoc &indexLocation, - const TVector &arraySizes) -{ - mDeferredNonEmptyDeclarationErrorCheck = false; - - declarationQualifierErrorCheck(elementType.qualifier, elementType.layoutQualifier, - identifierLocation); - - nonEmptyDeclarationErrorCheck(elementType, identifierLocation); - - checkIsValidTypeAndQualifierForArray(indexLocation, elementType); - - TType arrayType(elementType); - arrayType.makeArrays(arraySizes); - - checkGeometryShaderInputAndSetArraySize(indexLocation, identifier.c_str(), &arrayType); - - checkCanBeDeclaredWithoutInitializer(identifierLocation, identifier, &arrayType); - - checkAtomicCounterOffsetDoesNotOverlap(false, identifierLocation, &arrayType); - - TVariable *variable = nullptr; - declareVariable(identifierLocation, identifier, arrayType, &variable); - - TIntermDeclaration *declaration = new TIntermDeclaration(); - declaration->setLine(identifierLocation); - - if (variable) - { - TIntermSymbol *symbol = new TIntermSymbol(variable->getUniqueId(), identifier, arrayType); - symbol->setLine(identifierLocation); - declaration->appendDeclarator(symbol); - } - - return declaration; -} - -TIntermDeclaration *TParseContext::parseSingleInitDeclaration(const TPublicType &publicType, - const TSourceLoc &identifierLocation, - const TString &identifier, - const TSourceLoc &initLocation, - TIntermTyped *initializer) -{ - mDeferredNonEmptyDeclarationErrorCheck = false; - - declarationQualifierErrorCheck(publicType.qualifier, publicType.layoutQualifier, - identifierLocation); - - nonEmptyDeclarationErrorCheck(publicType, identifierLocation); - - TIntermDeclaration *declaration = new TIntermDeclaration(); - declaration->setLine(identifierLocation); - - TIntermBinary *initNode = nullptr; - TType type(publicType); - if (executeInitializer(identifierLocation, identifier, type, initializer, &initNode)) - { - if (initNode) - { - declaration->appendDeclarator(initNode); - } - } - return declaration; -} - -TIntermDeclaration *TParseContext::parseSingleArrayInitDeclaration( - TPublicType &elementType, - const TSourceLoc &identifierLocation, - const TString &identifier, - const TSourceLoc &indexLocation, - const TVector &arraySizes, - const TSourceLoc &initLocation, - TIntermTyped *initializer) -{ - mDeferredNonEmptyDeclarationErrorCheck = false; - - declarationQualifierErrorCheck(elementType.qualifier, elementType.layoutQualifier, - identifierLocation); - - nonEmptyDeclarationErrorCheck(elementType, identifierLocation); - - checkIsValidTypeAndQualifierForArray(indexLocation, elementType); - - TType arrayType(elementType); - arrayType.makeArrays(arraySizes); - - TIntermDeclaration *declaration = new TIntermDeclaration(); - declaration->setLine(identifierLocation); - - // initNode will correspond to the whole of "type b[n] = initializer". - TIntermBinary *initNode = nullptr; - if (executeInitializer(identifierLocation, identifier, arrayType, initializer, &initNode)) - { - if (initNode) - { - declaration->appendDeclarator(initNode); - } - } - - return declaration; -} - -TIntermInvariantDeclaration *TParseContext::parseInvariantDeclaration( - const TTypeQualifierBuilder &typeQualifierBuilder, - const TSourceLoc &identifierLoc, - const TString *identifier, - const TSymbol *symbol) -{ - TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics); - - if (!typeQualifier.invariant) - { - error(identifierLoc, "Expected invariant", identifier->c_str()); - return nullptr; - } - if (!checkIsAtGlobalLevel(identifierLoc, "invariant varying")) - { - return nullptr; - } - if (!symbol) - { - error(identifierLoc, "undeclared identifier declared as invariant", identifier->c_str()); - return nullptr; - } - if (!IsQualifierUnspecified(typeQualifier.qualifier)) - { - error(identifierLoc, "invariant declaration specifies qualifier", - getQualifierString(typeQualifier.qualifier)); - } - if (typeQualifier.precision != EbpUndefined) - { - error(identifierLoc, "invariant declaration specifies precision", - getPrecisionString(typeQualifier.precision)); - } - if (!typeQualifier.layoutQualifier.isEmpty()) - { - error(identifierLoc, "invariant declaration specifies layout", "'layout'"); - } - - const TVariable *variable = getNamedVariable(identifierLoc, identifier, symbol); - if (!variable) - { - return nullptr; - } - const TType &type = variable->getType(); - - checkInvariantVariableQualifier(typeQualifier.invariant, type.getQualifier(), - typeQualifier.line); - checkMemoryQualifierIsNotSpecified(typeQualifier.memoryQualifier, typeQualifier.line); - - symbolTable.addInvariantVarying(std::string(identifier->c_str())); - - TIntermSymbol *intermSymbol = new TIntermSymbol(variable->getUniqueId(), *identifier, type); - intermSymbol->setLine(identifierLoc); - - return new TIntermInvariantDeclaration(intermSymbol, identifierLoc); -} - -void TParseContext::parseDeclarator(TPublicType &publicType, - const TSourceLoc &identifierLocation, - const TString &identifier, - TIntermDeclaration *declarationOut) -{ - // If the declaration starting this declarator list was empty (example: int,), some checks were - // not performed. - if (mDeferredNonEmptyDeclarationErrorCheck) - { - nonEmptyDeclarationErrorCheck(publicType, identifierLocation); - mDeferredNonEmptyDeclarationErrorCheck = false; - } - - checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType); - - TVariable *variable = nullptr; - TType type(publicType); - - checkGeometryShaderInputAndSetArraySize(identifierLocation, identifier.c_str(), &type); - - checkCanBeDeclaredWithoutInitializer(identifierLocation, identifier, &type); - - checkAtomicCounterOffsetDoesNotOverlap(true, identifierLocation, &type); - - declareVariable(identifierLocation, identifier, type, &variable); - - if (variable) - { - TIntermSymbol *symbol = new TIntermSymbol(variable->getUniqueId(), identifier, type); - symbol->setLine(identifierLocation); - declarationOut->appendDeclarator(symbol); - } -} - -void TParseContext::parseArrayDeclarator(TPublicType &elementType, - const TSourceLoc &identifierLocation, - const TString &identifier, - const TSourceLoc &arrayLocation, - const TVector &arraySizes, - TIntermDeclaration *declarationOut) -{ - // If the declaration starting this declarator list was empty (example: int,), some checks were - // not performed. - if (mDeferredNonEmptyDeclarationErrorCheck) - { - nonEmptyDeclarationErrorCheck(elementType, identifierLocation); - mDeferredNonEmptyDeclarationErrorCheck = false; - } - - checkDeclaratorLocationIsNotSpecified(identifierLocation, elementType); - - if (checkIsValidTypeAndQualifierForArray(arrayLocation, elementType)) - { - TType arrayType(elementType); - arrayType.makeArrays(arraySizes); - - checkGeometryShaderInputAndSetArraySize(identifierLocation, identifier.c_str(), &arrayType); - - checkCanBeDeclaredWithoutInitializer(identifierLocation, identifier, &arrayType); - - checkAtomicCounterOffsetDoesNotOverlap(true, identifierLocation, &arrayType); - - TVariable *variable = nullptr; - declareVariable(identifierLocation, identifier, arrayType, &variable); - - if (variable) - { - TIntermSymbol *symbol = - new TIntermSymbol(variable->getUniqueId(), identifier, arrayType); - symbol->setLine(identifierLocation); - declarationOut->appendDeclarator(symbol); - } - } -} - -void TParseContext::parseInitDeclarator(const TPublicType &publicType, - const TSourceLoc &identifierLocation, - const TString &identifier, - const TSourceLoc &initLocation, - TIntermTyped *initializer, - TIntermDeclaration *declarationOut) -{ - // If the declaration starting this declarator list was empty (example: int,), some checks were - // not performed. - if (mDeferredNonEmptyDeclarationErrorCheck) - { - nonEmptyDeclarationErrorCheck(publicType, identifierLocation); - mDeferredNonEmptyDeclarationErrorCheck = false; - } - - checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType); - - TIntermBinary *initNode = nullptr; - TType type(publicType); - if (executeInitializer(identifierLocation, identifier, type, initializer, &initNode)) - { - // - // build the intermediate representation - // - if (initNode) - { - declarationOut->appendDeclarator(initNode); - } - } -} - -void TParseContext::parseArrayInitDeclarator(const TPublicType &elementType, - const TSourceLoc &identifierLocation, - const TString &identifier, - const TSourceLoc &indexLocation, - const TVector &arraySizes, - const TSourceLoc &initLocation, - TIntermTyped *initializer, - TIntermDeclaration *declarationOut) -{ - // If the declaration starting this declarator list was empty (example: int,), some checks were - // not performed. - if (mDeferredNonEmptyDeclarationErrorCheck) - { - nonEmptyDeclarationErrorCheck(elementType, identifierLocation); - mDeferredNonEmptyDeclarationErrorCheck = false; - } - - checkDeclaratorLocationIsNotSpecified(identifierLocation, elementType); - - checkIsValidTypeAndQualifierForArray(indexLocation, elementType); - - TType arrayType(elementType); - arrayType.makeArrays(arraySizes); - - // initNode will correspond to the whole of "b[n] = initializer". - TIntermBinary *initNode = nullptr; - if (executeInitializer(identifierLocation, identifier, arrayType, initializer, &initNode)) - { - if (initNode) - { - declarationOut->appendDeclarator(initNode); - } - } -} - -TIntermNode *TParseContext::addEmptyStatement(const TSourceLoc &location) -{ - // It's simpler to parse an empty statement as a constant expression rather than having a - // different type of node just for empty statements, that will be pruned from the AST anyway. - TIntermNode *node = CreateZeroNode(TType(EbtInt, EbpMedium)); - node->setLine(location); - return node; -} - -void TParseContext::setAtomicCounterBindingDefaultOffset(const TPublicType &publicType, - const TSourceLoc &location) -{ - const TLayoutQualifier &layoutQualifier = publicType.layoutQualifier; - checkAtomicCounterBindingIsValid(location, layoutQualifier.binding); - if (layoutQualifier.binding == -1 || layoutQualifier.offset == -1) - { - error(location, "Requires both binding and offset", "layout"); - return; - } - mAtomicCounterBindingStates[layoutQualifier.binding].setDefaultOffset(layoutQualifier.offset); -} - -void TParseContext::parseDefaultPrecisionQualifier(const TPrecision precision, - const TPublicType &type, - const TSourceLoc &loc) -{ - if ((precision == EbpHigh) && (getShaderType() == GL_FRAGMENT_SHADER) && - !getFragmentPrecisionHigh()) - { - error(loc, "precision is not supported in fragment shader", "highp"); - } - - if (!CanSetDefaultPrecisionOnType(type)) - { - error(loc, "illegal type argument for default precision qualifier", - getBasicString(type.getBasicType())); - return; - } - symbolTable.setDefaultPrecision(type.getBasicType(), precision); -} - -bool TParseContext::checkPrimitiveTypeMatchesTypeQualifier(const TTypeQualifier &typeQualifier) -{ - switch (typeQualifier.layoutQualifier.primitiveType) - { - case EptLines: - case EptLinesAdjacency: - case EptTriangles: - case EptTrianglesAdjacency: - return typeQualifier.qualifier == EvqGeometryIn; - - case EptLineStrip: - case EptTriangleStrip: - return typeQualifier.qualifier == EvqGeometryOut; - - case EptPoints: - return true; - - default: - UNREACHABLE(); - return false; - } -} - -void TParseContext::setGeometryShaderInputArraySize(unsigned int inputArraySize, - const TSourceLoc &line) -{ - if (mGeometryShaderInputArraySize == 0u) - { - mGeometryShaderInputArraySize = inputArraySize; - } - else if (mGeometryShaderInputArraySize != inputArraySize) - { - error(line, - "Array size or input primitive declaration doesn't match the size of earlier sized " - "array inputs.", - "layout"); - } -} - -bool TParseContext::parseGeometryShaderInputLayoutQualifier(const TTypeQualifier &typeQualifier) -{ - ASSERT(typeQualifier.qualifier == EvqGeometryIn); - - const TLayoutQualifier &layoutQualifier = typeQualifier.layoutQualifier; - - if (layoutQualifier.maxVertices != -1) - { - error(typeQualifier.line, - "max_vertices can only be declared in 'out' layout in a geometry shader", "layout"); - return false; - } - - // Set mGeometryInputPrimitiveType if exists - if (layoutQualifier.primitiveType != EptUndefined) - { - if (!checkPrimitiveTypeMatchesTypeQualifier(typeQualifier)) - { - error(typeQualifier.line, "invalid primitive type for 'in' layout", "layout"); - return false; - } - - if (mGeometryShaderInputPrimitiveType == EptUndefined) - { - mGeometryShaderInputPrimitiveType = layoutQualifier.primitiveType; - setGeometryShaderInputArraySize( - GetGeometryShaderInputArraySize(mGeometryShaderInputPrimitiveType), - typeQualifier.line); - } - else if (mGeometryShaderInputPrimitiveType != layoutQualifier.primitiveType) - { - error(typeQualifier.line, "primitive doesn't match earlier input primitive declaration", - "layout"); - return false; - } - } - - // Set mGeometryInvocations if exists - if (layoutQualifier.invocations > 0) - { - if (mGeometryShaderInvocations == 0) - { - mGeometryShaderInvocations = layoutQualifier.invocations; - } - else if (mGeometryShaderInvocations != layoutQualifier.invocations) - { - error(typeQualifier.line, "invocations contradicts to the earlier declaration", - "layout"); - return false; - } - } - - return true; -} - -bool TParseContext::parseGeometryShaderOutputLayoutQualifier(const TTypeQualifier &typeQualifier) -{ - ASSERT(typeQualifier.qualifier == EvqGeometryOut); - - const TLayoutQualifier &layoutQualifier = typeQualifier.layoutQualifier; - - if (layoutQualifier.invocations > 0) - { - error(typeQualifier.line, - "invocations can only be declared in 'in' layout in a geometry shader", "layout"); - return false; - } - - // Set mGeometryOutputPrimitiveType if exists - if (layoutQualifier.primitiveType != EptUndefined) - { - if (!checkPrimitiveTypeMatchesTypeQualifier(typeQualifier)) - { - error(typeQualifier.line, "invalid primitive type for 'out' layout", "layout"); - return false; - } - - if (mGeometryShaderOutputPrimitiveType == EptUndefined) - { - mGeometryShaderOutputPrimitiveType = layoutQualifier.primitiveType; - } - else if (mGeometryShaderOutputPrimitiveType != layoutQualifier.primitiveType) - { - error(typeQualifier.line, - "primitive doesn't match earlier output primitive declaration", "layout"); - return false; - } - } - - // Set mGeometryMaxVertices if exists - if (layoutQualifier.maxVertices > -1) - { - if (mGeometryShaderMaxVertices == -1) - { - mGeometryShaderMaxVertices = layoutQualifier.maxVertices; - } - else if (mGeometryShaderMaxVertices != layoutQualifier.maxVertices) - { - error(typeQualifier.line, "max_vertices contradicts to the earlier declaration", - "layout"); - return false; - } - } - - return true; -} - -void TParseContext::parseGlobalLayoutQualifier(const TTypeQualifierBuilder &typeQualifierBuilder) -{ - TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics); - const TLayoutQualifier layoutQualifier = typeQualifier.layoutQualifier; - - checkInvariantVariableQualifier(typeQualifier.invariant, typeQualifier.qualifier, - typeQualifier.line); - - // It should never be the case, but some strange parser errors can send us here. - if (layoutQualifier.isEmpty()) - { - error(typeQualifier.line, "Error during layout qualifier parsing.", "?"); - return; - } - - if (!layoutQualifier.isCombinationValid()) - { - error(typeQualifier.line, "invalid layout qualifier combination", "layout"); - return; - } - - checkBindingIsNotSpecified(typeQualifier.line, layoutQualifier.binding); - - checkMemoryQualifierIsNotSpecified(typeQualifier.memoryQualifier, typeQualifier.line); - - checkInternalFormatIsNotSpecified(typeQualifier.line, layoutQualifier.imageInternalFormat); - - checkYuvIsNotSpecified(typeQualifier.line, layoutQualifier.yuv); - - checkOffsetIsNotSpecified(typeQualifier.line, layoutQualifier.offset); - - checkStd430IsForShaderStorageBlock(typeQualifier.line, layoutQualifier.blockStorage, - typeQualifier.qualifier); - - if (typeQualifier.qualifier == EvqComputeIn) - { - if (mComputeShaderLocalSizeDeclared && - !layoutQualifier.isLocalSizeEqual(mComputeShaderLocalSize)) - { - error(typeQualifier.line, "Work group size does not match the previous declaration", - "layout"); - return; - } - - if (mShaderVersion < 310) - { - error(typeQualifier.line, "in type qualifier supported in GLSL ES 3.10 only", "layout"); - return; - } - - if (!layoutQualifier.localSize.isAnyValueSet()) - { - error(typeQualifier.line, "No local work group size specified", "layout"); - return; - } - - const TVariable *maxComputeWorkGroupSize = static_cast( - symbolTable.findBuiltIn("gl_MaxComputeWorkGroupSize", mShaderVersion)); - - const TConstantUnion *maxComputeWorkGroupSizeData = - maxComputeWorkGroupSize->getConstPointer(); - - for (size_t i = 0u; i < layoutQualifier.localSize.size(); ++i) - { - if (layoutQualifier.localSize[i] != -1) - { - mComputeShaderLocalSize[i] = layoutQualifier.localSize[i]; - const int maxComputeWorkGroupSizeValue = maxComputeWorkGroupSizeData[i].getIConst(); - if (mComputeShaderLocalSize[i] < 1 || - mComputeShaderLocalSize[i] > maxComputeWorkGroupSizeValue) - { - std::stringstream reasonStream; - reasonStream << "invalid value: Value must be at least 1 and no greater than " - << maxComputeWorkGroupSizeValue; - const std::string &reason = reasonStream.str(); - - error(typeQualifier.line, reason.c_str(), getWorkGroupSizeString(i)); - return; - } - } - } - - mComputeShaderLocalSizeDeclared = true; - } - else if (typeQualifier.qualifier == EvqGeometryIn) - { - if (mShaderVersion < 310) - { - error(typeQualifier.line, "in type qualifier supported in GLSL ES 3.10 only", "layout"); - return; - } - - if (!parseGeometryShaderInputLayoutQualifier(typeQualifier)) - { - return; - } - } - else if (typeQualifier.qualifier == EvqGeometryOut) - { - if (mShaderVersion < 310) - { - error(typeQualifier.line, "out type qualifier supported in GLSL ES 3.10 only", - "layout"); - return; - } - - if (!parseGeometryShaderOutputLayoutQualifier(typeQualifier)) - { - return; - } - } - else if (isExtensionEnabled(TExtension::OVR_multiview) && - typeQualifier.qualifier == EvqVertexIn) - { - // This error is only specified in WebGL, but tightens unspecified behavior in the native - // specification. - if (mNumViews != -1 && layoutQualifier.numViews != mNumViews) - { - error(typeQualifier.line, "Number of views does not match the previous declaration", - "layout"); - return; - } - - if (layoutQualifier.numViews == -1) - { - error(typeQualifier.line, "No num_views specified", "layout"); - return; - } - - if (layoutQualifier.numViews > mMaxNumViews) - { - error(typeQualifier.line, "num_views greater than the value of GL_MAX_VIEWS_OVR", - "layout"); - return; - } - - mNumViews = layoutQualifier.numViews; - } - else - { - if (!checkWorkGroupSizeIsNotSpecified(typeQualifier.line, layoutQualifier)) - { - return; - } - - if (typeQualifier.qualifier != EvqUniform && typeQualifier.qualifier != EvqBuffer) - { - error(typeQualifier.line, "invalid qualifier: global layout can only be set for blocks", - getQualifierString(typeQualifier.qualifier)); - return; - } - - if (mShaderVersion < 300) - { - error(typeQualifier.line, "layout qualifiers supported in GLSL ES 3.00 and above", - "layout"); - return; - } - - checkLocationIsNotSpecified(typeQualifier.line, layoutQualifier); - - if (layoutQualifier.matrixPacking != EmpUnspecified) - { - if (typeQualifier.qualifier == EvqUniform) - { - mDefaultUniformMatrixPacking = layoutQualifier.matrixPacking; - } - else if (typeQualifier.qualifier == EvqBuffer) - { - mDefaultBufferMatrixPacking = layoutQualifier.matrixPacking; - } - } - - if (layoutQualifier.blockStorage != EbsUnspecified) - { - if (typeQualifier.qualifier == EvqUniform) - { - mDefaultUniformBlockStorage = layoutQualifier.blockStorage; - } - else if (typeQualifier.qualifier == EvqBuffer) - { - mDefaultBufferBlockStorage = layoutQualifier.blockStorage; - } - } - } -} - -TIntermFunctionPrototype *TParseContext::createPrototypeNodeFromFunction( - const TFunction &function, - const TSourceLoc &location, - bool insertParametersToSymbolTable) -{ - checkIsNotReserved(location, function.getName()); - - TIntermFunctionPrototype *prototype = - new TIntermFunctionPrototype(function.getReturnType(), TSymbolUniqueId(function)); - // TODO(oetuaho@nvidia.com): Instead of converting the function information here, the node could - // point to the data that already exists in the symbol table. - prototype->getFunctionSymbolInfo()->setFromFunction(function); - prototype->setLine(location); - - for (size_t i = 0; i < function.getParamCount(); i++) - { - const TConstParameter ¶m = function.getParam(i); - - TIntermSymbol *symbol = nullptr; - - // If the parameter has no name, it's not an error, just don't add it to symbol table (could - // be used for unused args). - if (param.name != nullptr) - { - // Insert the parameter in the symbol table. - if (insertParametersToSymbolTable) - { - TVariable *variable = symbolTable.declareVariable(param.name, *param.type); - if (variable) - { - symbol = new TIntermSymbol(variable->getUniqueId(), variable->getName(), - variable->getType()); - } - else - { - error(location, "redefinition", param.name->c_str()); - } - } - // Unsized type of a named parameter should have already been checked and sanitized. - ASSERT(!param.type->isUnsizedArray()); - } - else - { - if (param.type->isUnsizedArray()) - { - error(location, "function parameter array must be sized at compile time", "[]"); - // We don't need to size the arrays since the parameter is unnamed and hence - // inaccessible. - } - } - if (!symbol) - { - // The parameter had no name or declaring the symbol failed - either way, add a nameless - // symbol. - symbol = new TIntermSymbol(symbolTable.getEmptySymbolId(), "", *param.type); - } - symbol->setLine(location); - prototype->appendParameter(symbol); - } - return prototype; -} - -TIntermFunctionPrototype *TParseContext::addFunctionPrototypeDeclaration( - const TFunction &parsedFunction, - const TSourceLoc &location) -{ - // Note: function found from the symbol table could be the same as parsedFunction if this is the - // first declaration. Either way the instance in the symbol table is used to track whether the - // function is declared multiple times. - TFunction *function = static_cast( - symbolTable.find(parsedFunction.getMangledName(), getShaderVersion())); - if (function->hasPrototypeDeclaration() && mShaderVersion == 100) - { - // ESSL 1.00.17 section 4.2.7. - // Doesn't apply to ESSL 3.00.4: see section 4.2.3. - error(location, "duplicate function prototype declarations are not allowed", "function"); - } - function->setHasPrototypeDeclaration(); - - TIntermFunctionPrototype *prototype = - createPrototypeNodeFromFunction(*function, location, false); - - symbolTable.pop(); - - if (!symbolTable.atGlobalLevel()) - { - // ESSL 3.00.4 section 4.2.4. - error(location, "local function prototype declarations are not allowed", "function"); - } - - return prototype; -} - -TIntermFunctionDefinition *TParseContext::addFunctionDefinition( - TIntermFunctionPrototype *functionPrototype, - TIntermBlock *functionBody, - const TSourceLoc &location) -{ - // Check that non-void functions have at least one return statement. - if (mCurrentFunctionType->getBasicType() != EbtVoid && !mFunctionReturnsValue) - { - error(location, "function does not return a value:", - functionPrototype->getFunctionSymbolInfo()->getName().c_str()); - } - - if (functionBody == nullptr) - { - functionBody = new TIntermBlock(); - functionBody->setLine(location); - } - TIntermFunctionDefinition *functionNode = - new TIntermFunctionDefinition(functionPrototype, functionBody); - functionNode->setLine(location); - - symbolTable.pop(); - return functionNode; -} - -void TParseContext::parseFunctionDefinitionHeader(const TSourceLoc &location, - TFunction **function, - TIntermFunctionPrototype **prototypeOut) -{ - ASSERT(function); - ASSERT(*function); - const TSymbol *builtIn = - symbolTable.findBuiltIn((*function)->getMangledName(), getShaderVersion()); - - if (builtIn) - { - error(location, "built-in functions cannot be redefined", (*function)->getName().c_str()); - } - else - { - TFunction *prevDec = static_cast( - symbolTable.find((*function)->getMangledName(), getShaderVersion())); - - // 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 - // occurance. - if (*function != prevDec) - { - // Swap the parameters of the previous declaration to the parameters of the function - // definition (parameter names may differ). - prevDec->swapParameters(**function); - - // The function definition will share the same symbol as any previous declaration. - *function = prevDec; - } - - if ((*function)->isDefined()) - { - error(location, "function already has a body", (*function)->getName().c_str()); - } - - (*function)->setDefined(); - } - - // Remember the return type for later checking for return statements. - mCurrentFunctionType = &((*function)->getReturnType()); - mFunctionReturnsValue = false; - - *prototypeOut = createPrototypeNodeFromFunction(**function, location, true); - setLoopNestingLevel(0); -} - -TFunction *TParseContext::parseFunctionDeclarator(const TSourceLoc &location, TFunction *function) -{ - // - // We don't know at this point whether this is a function definition or a prototype. - // The definition production code will check for redefinitions. - // In the case of ESSL 1.00 the prototype production code will also check for redeclarations. - // - // Return types and parameter qualifiers must match in all redeclarations, so those are checked - // here. - // - TFunction *prevDec = - static_cast(symbolTable.find(function->getMangledName(), getShaderVersion())); - - for (size_t i = 0u; i < function->getParamCount(); ++i) - { - auto ¶m = function->getParam(i); - if (param.type->isStructSpecifier()) - { - // ESSL 3.00.6 section 12.10. - error(location, "Function parameter type cannot be a structure definition", - function->getName().c_str()); - } - } - - if (getShaderVersion() >= 300 && - symbolTable.hasUnmangledBuiltInForShaderVersion(function->getName().c_str(), - getShaderVersion())) - { - // With ESSL 3.00 and above, names of built-in functions cannot be redeclared as functions. - // Therefore overloading or redefining builtin functions is an error. - error(location, "Name of a built-in function cannot be redeclared as function", - function->getName().c_str()); - } - else if (prevDec) - { - if (prevDec->getReturnType() != function->getReturnType()) - { - error(location, "function must have the same return type in all of its declarations", - function->getReturnType().getBasicString()); - } - for (size_t i = 0; i < prevDec->getParamCount(); ++i) - { - if (prevDec->getParam(i).type->getQualifier() != - function->getParam(i).type->getQualifier()) - { - error(location, - "function must have the same parameter qualifiers in all of its declarations", - function->getParam(i).type->getQualifierString()); - } - } - } - - // - // Check for previously declared variables using the same name. - // - TSymbol *prevSym = symbolTable.find(function->getName(), getShaderVersion()); - if (prevSym) - { - if (!prevSym->isFunction()) - { - error(location, "redefinition of a function", function->getName().c_str()); - } - } - else - { - // Insert the unmangled name to detect potential future redefinition as a variable. - symbolTable.getOuterLevel()->insertUnmangled(function); - } - - // We're at the inner scope level of the function's arguments and body statement. - // Add the function prototype to the surrounding scope instead. - symbolTable.getOuterLevel()->insert(function); - - // Raise error message if main function takes any parameters or return anything other than void - if (function->getName() == "main") - { - if (function->getParamCount() > 0) - { - error(location, "function cannot take any parameter(s)", "main"); - } - if (function->getReturnType().getBasicType() != EbtVoid) - { - error(location, "main function cannot return a value", - function->getReturnType().getBasicString()); - } - } - - // - // If this is a redeclaration, it could also be a definition, in which case, we want to use the - // variable names from this one, and not the one that's - // being redeclared. So, pass back up this declaration, not the one in the symbol table. - // - return function; -} - -TFunction *TParseContext::parseFunctionHeader(const TPublicType &type, - const TString *name, - const TSourceLoc &location) -{ - if (type.qualifier != EvqGlobal && type.qualifier != EvqTemporary) - { - error(location, "no qualifiers allowed for function return", - getQualifierString(type.qualifier)); - } - if (!type.layoutQualifier.isEmpty()) - { - error(location, "no qualifiers allowed for function return", "layout"); - } - // make sure an opaque type is not involved as well... - std::string reason(getBasicString(type.getBasicType())); - reason += "s can't be function return values"; - checkIsNotOpaqueType(location, type.typeSpecifierNonArray, reason.c_str()); - if (mShaderVersion < 300) - { - // Array return values are forbidden, but there's also no valid syntax for declaring array - // return values in ESSL 1.00. - ASSERT(!type.isArray() || mDiagnostics->numErrors() > 0); - - if (type.isStructureContainingArrays()) - { - // ESSL 1.00.17 section 6.1 Function Definitions - error(location, "structures containing arrays can't be function return values", - TType(type).getCompleteString().c_str()); - } - } - - // Add the function as a prototype after parsing it (we do not support recursion) - return new TFunction(&symbolTable, name, new TType(type)); -} - -TFunction *TParseContext::addNonConstructorFunc(const TString *name, const TSourceLoc &loc) -{ - const TType *returnType = TCache::getType(EbtVoid, EbpUndefined); - return new TFunction(&symbolTable, name, returnType); -} - -TFunction *TParseContext::addConstructorFunc(const TPublicType &publicType) -{ - if (mShaderVersion < 300 && publicType.isArray()) - { - error(publicType.getLine(), "array constructor supported in GLSL ES 3.00 and above only", - "[]"); - } - if (publicType.isStructSpecifier()) - { - error(publicType.getLine(), "constructor can't be a structure definition", - getBasicString(publicType.getBasicType())); - } - - TType *type = new TType(publicType); - if (!type->canBeConstructed()) - { - error(publicType.getLine(), "cannot construct this type", - getBasicString(publicType.getBasicType())); - type->setBasicType(EbtFloat); - } - - return new TFunction(&symbolTable, nullptr, type, EOpConstruct); -} - -void TParseContext::checkIsNotUnsizedArray(const TSourceLoc &line, - const char *errorMessage, - const char *token, - TType *arrayType) -{ - if (arrayType->isUnsizedArray()) - { - error(line, errorMessage, token); - arrayType->sizeUnsizedArrays(nullptr); - } -} - -TParameter TParseContext::parseParameterDeclarator(TType *type, - const TString *name, - const TSourceLoc &nameLoc) -{ - ASSERT(type); - checkIsNotUnsizedArray(nameLoc, "function parameter array must specify a size", name->c_str(), - type); - if (type->getBasicType() == EbtVoid) - { - error(nameLoc, "illegal use of type 'void'", name->c_str()); - } - checkIsNotReserved(nameLoc, *name); - TParameter param = {name, type}; - return param; -} - -TParameter TParseContext::parseParameterDeclarator(const TPublicType &publicType, - const TString *name, - const TSourceLoc &nameLoc) -{ - TType *type = new TType(publicType); - return parseParameterDeclarator(type, name, nameLoc); -} - -TParameter TParseContext::parseParameterArrayDeclarator(const TString *name, - const TSourceLoc &nameLoc, - const TVector &arraySizes, - const TSourceLoc &arrayLoc, - TPublicType *elementType) -{ - checkArrayElementIsNotArray(arrayLoc, *elementType); - TType *arrayType = new TType(*elementType); - arrayType->makeArrays(arraySizes); - return parseParameterDeclarator(arrayType, name, nameLoc); -} - -bool TParseContext::checkUnsizedArrayConstructorArgumentDimensionality(TIntermSequence *arguments, - TType type, - const TSourceLoc &line) -{ - if (arguments->empty()) - { - error(line, "implicitly sized array constructor must have at least one argument", "[]"); - return false; - } - for (TIntermNode *arg : *arguments) - { - TIntermTyped *element = arg->getAsTyped(); - ASSERT(element); - size_t dimensionalityFromElement = element->getType().getNumArraySizes() + 1u; - if (dimensionalityFromElement > type.getNumArraySizes()) - { - error(line, "constructing from a non-dereferenced array", "constructor"); - return false; - } - else if (dimensionalityFromElement < type.getNumArraySizes()) - { - if (dimensionalityFromElement == 1u) - { - error(line, "implicitly sized array of arrays constructor argument is not an array", - "constructor"); - } - else - { - error(line, - "implicitly sized array of arrays constructor argument dimensionality is too " - "low", - "constructor"); - } - return false; - } - } - return true; -} - -// This function is used to test for the correctness of the parameters passed to various constructor -// functions and also convert them to the right datatype if it is allowed and required. -// -// Returns a node to add to the tree regardless of if an error was generated or not. -// -TIntermTyped *TParseContext::addConstructor(TIntermSequence *arguments, - TType type, - const TSourceLoc &line) -{ - if (type.isUnsizedArray()) - { - if (!checkUnsizedArrayConstructorArgumentDimensionality(arguments, type, line)) - { - type.sizeUnsizedArrays(nullptr); - return CreateZeroNode(type); - } - TIntermTyped *firstElement = arguments->at(0)->getAsTyped(); - ASSERT(firstElement); - if (type.getOutermostArraySize() == 0u) - { - type.sizeOutermostUnsizedArray(static_cast(arguments->size())); - } - for (size_t i = 0; i < firstElement->getType().getNumArraySizes(); ++i) - { - if ((*type.getArraySizes())[i] == 0u) - { - type.setArraySize(i, (*firstElement->getType().getArraySizes())[i]); - } - } - ASSERT(!type.isUnsizedArray()); - } - - if (!checkConstructorArguments(line, arguments, type)) - { - return CreateZeroNode(type); - } - - TIntermAggregate *constructorNode = TIntermAggregate::CreateConstructor(type, arguments); - constructorNode->setLine(line); - - // TODO(oetuaho@nvidia.com): Add support for folding array constructors. - if (!constructorNode->isArray()) - { - return constructorNode->fold(mDiagnostics); - } - return constructorNode; -} - -// -// Interface/uniform blocks -// TODO(jiawei.shao@intel.com): implement GL_OES_shader_io_blocks. -// -TIntermDeclaration *TParseContext::addInterfaceBlock( - const TTypeQualifierBuilder &typeQualifierBuilder, - const TSourceLoc &nameLine, - const TString &blockName, - TFieldList *fieldList, - const TString *instanceName, - const TSourceLoc &instanceLine, - TIntermTyped *arrayIndex, - const TSourceLoc &arrayIndexLine) -{ - checkIsNotReserved(nameLine, blockName); - - TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics); - - if (mShaderVersion < 310 && typeQualifier.qualifier != EvqUniform) - { - error(typeQualifier.line, - "invalid qualifier: interface blocks must be uniform in version lower than GLSL ES " - "3.10", - getQualifierString(typeQualifier.qualifier)); - } - else if (typeQualifier.qualifier != EvqUniform && typeQualifier.qualifier != EvqBuffer) - { - error(typeQualifier.line, "invalid qualifier: interface blocks must be uniform or buffer", - getQualifierString(typeQualifier.qualifier)); - } - - if (typeQualifier.invariant) - { - error(typeQualifier.line, "invalid qualifier on interface block member", "invariant"); - } - - if (typeQualifier.qualifier != EvqBuffer) - { - checkMemoryQualifierIsNotSpecified(typeQualifier.memoryQualifier, typeQualifier.line); - } - - // add array index - unsigned int arraySize = 0; - if (arrayIndex != nullptr) - { - arraySize = checkIsValidArraySize(arrayIndexLine, arrayIndex); - } - - if (mShaderVersion < 310) - { - checkBindingIsNotSpecified(typeQualifier.line, typeQualifier.layoutQualifier.binding); - } - else - { - checkBlockBindingIsValid(typeQualifier.line, typeQualifier.qualifier, - typeQualifier.layoutQualifier.binding, arraySize); - } - - checkYuvIsNotSpecified(typeQualifier.line, typeQualifier.layoutQualifier.yuv); - - TLayoutQualifier blockLayoutQualifier = typeQualifier.layoutQualifier; - checkLocationIsNotSpecified(typeQualifier.line, blockLayoutQualifier); - checkStd430IsForShaderStorageBlock(typeQualifier.line, blockLayoutQualifier.blockStorage, - typeQualifier.qualifier); - - if (blockLayoutQualifier.matrixPacking == EmpUnspecified) - { - if (typeQualifier.qualifier == EvqUniform) - { - blockLayoutQualifier.matrixPacking = mDefaultUniformMatrixPacking; - } - else if (typeQualifier.qualifier == EvqBuffer) - { - blockLayoutQualifier.matrixPacking = mDefaultBufferMatrixPacking; - } - } - - if (blockLayoutQualifier.blockStorage == EbsUnspecified) - { - if (typeQualifier.qualifier == EvqUniform) - { - blockLayoutQualifier.blockStorage = mDefaultUniformBlockStorage; - } - else if (typeQualifier.qualifier == EvqBuffer) - { - blockLayoutQualifier.blockStorage = mDefaultBufferBlockStorage; - } - } - - checkWorkGroupSizeIsNotSpecified(nameLine, blockLayoutQualifier); - - checkInternalFormatIsNotSpecified(nameLine, blockLayoutQualifier.imageInternalFormat); - - if (!symbolTable.declareInterfaceBlockName(&blockName)) - { - error(nameLine, "redefinition of an interface block name", blockName.c_str()); - } - - // check for sampler types and apply layout qualifiers - for (size_t memberIndex = 0; memberIndex < fieldList->size(); ++memberIndex) - { - TField *field = (*fieldList)[memberIndex]; - TType *fieldType = field->type(); - if (IsOpaqueType(fieldType->getBasicType())) - { - std::string reason("unsupported type - "); - reason += fieldType->getBasicString(); - reason += " types are not allowed in interface blocks"; - error(field->line(), reason.c_str(), fieldType->getBasicString()); - } - - const TQualifier qualifier = fieldType->getQualifier(); - switch (qualifier) - { - case EvqGlobal: - break; - case EvqUniform: - if (typeQualifier.qualifier == EvqBuffer) - { - error(field->line(), "invalid qualifier on shader storage block member", - getQualifierString(qualifier)); - } - break; - case EvqBuffer: - if (typeQualifier.qualifier == EvqUniform) - { - error(field->line(), "invalid qualifier on uniform block member", - getQualifierString(qualifier)); - } - break; - default: - error(field->line(), "invalid qualifier on interface block member", - getQualifierString(qualifier)); - break; - } - - if (fieldType->isInvariant()) - { - error(field->line(), "invalid qualifier on interface block member", "invariant"); - } - - // check layout qualifiers - TLayoutQualifier fieldLayoutQualifier = fieldType->getLayoutQualifier(); - checkLocationIsNotSpecified(field->line(), fieldLayoutQualifier); - checkBindingIsNotSpecified(field->line(), fieldLayoutQualifier.binding); - - if (fieldLayoutQualifier.blockStorage != EbsUnspecified) - { - error(field->line(), "invalid layout qualifier: cannot be used here", - getBlockStorageString(fieldLayoutQualifier.blockStorage)); - } - - if (fieldLayoutQualifier.matrixPacking == EmpUnspecified) - { - fieldLayoutQualifier.matrixPacking = blockLayoutQualifier.matrixPacking; - } - else if (!fieldType->isMatrix() && fieldType->getBasicType() != EbtStruct) - { - warning(field->line(), - "extraneous layout qualifier: only has an effect on matrix types", - getMatrixPackingString(fieldLayoutQualifier.matrixPacking)); - } - - fieldType->setLayoutQualifier(fieldLayoutQualifier); - - if (mShaderVersion < 310 || memberIndex != fieldList->size() - 1u || - typeQualifier.qualifier != EvqBuffer) - { - // ESSL 3.10 spec section 4.1.9 allows for runtime-sized arrays. - checkIsNotUnsizedArray(field->line(), - "array members of interface blocks must specify a size", - field->name().c_str(), field->type()); - } - - if (typeQualifier.qualifier == EvqBuffer) - { - // set memory qualifiers - // GLSL ES 3.10 session 4.9 [Memory Access Qualifiers]. When a block declaration is - // qualified with a memory qualifier, it is as if all of its members were declared with - // the same memory qualifier. - const TMemoryQualifier &blockMemoryQualifier = typeQualifier.memoryQualifier; - TMemoryQualifier fieldMemoryQualifier = fieldType->getMemoryQualifier(); - fieldMemoryQualifier.readonly |= blockMemoryQualifier.readonly; - fieldMemoryQualifier.writeonly |= blockMemoryQualifier.writeonly; - fieldMemoryQualifier.coherent |= blockMemoryQualifier.coherent; - fieldMemoryQualifier.restrictQualifier |= blockMemoryQualifier.restrictQualifier; - fieldMemoryQualifier.volatileQualifier |= blockMemoryQualifier.volatileQualifier; - // TODO(jiajia.qin@intel.com): Decide whether if readonly and writeonly buffer variable - // is legal. See bug https://github.com/KhronosGroup/OpenGL-API/issues/7 - fieldType->setMemoryQualifier(fieldMemoryQualifier); - } - } - - TInterfaceBlock *interfaceBlock = - new TInterfaceBlock(&blockName, fieldList, instanceName, blockLayoutQualifier); - TType interfaceBlockType(interfaceBlock, typeQualifier.qualifier, blockLayoutQualifier); - if (arrayIndex != nullptr) - { - interfaceBlockType.makeArray(arraySize); - } - - TString symbolName = ""; - const TSymbolUniqueId *symbolId = nullptr; - - if (!instanceName) - { - // define symbols for the members of the interface block - for (size_t memberIndex = 0; memberIndex < fieldList->size(); ++memberIndex) - { - TField *field = (*fieldList)[memberIndex]; - TType *fieldType = field->type(); - - // set parent pointer of the field variable - fieldType->setInterfaceBlock(interfaceBlock); - - TVariable *fieldVariable = symbolTable.declareVariable(&field->name(), *fieldType); - - if (fieldVariable) - { - fieldVariable->setQualifier(typeQualifier.qualifier); - } - else - { - error(field->line(), "redefinition of an interface block member name", - field->name().c_str()); - } - } - symbolId = &symbolTable.getEmptySymbolId(); - } - else - { - checkIsNotReserved(instanceLine, *instanceName); - - // add a symbol for this interface block - TVariable *instanceTypeDef = symbolTable.declareVariable(instanceName, interfaceBlockType); - if (instanceTypeDef) - { - instanceTypeDef->setQualifier(typeQualifier.qualifier); - symbolId = &instanceTypeDef->getUniqueId(); - } - else - { - error(instanceLine, "redefinition of an interface block instance name", - instanceName->c_str()); - } - symbolName = *instanceName; - } - - TIntermDeclaration *declaration = nullptr; - - if (symbolId) - { - TIntermSymbol *blockSymbol = new TIntermSymbol(*symbolId, symbolName, interfaceBlockType); - blockSymbol->setLine(typeQualifier.line); - declaration = new TIntermDeclaration(); - declaration->appendDeclarator(blockSymbol); - declaration->setLine(nameLine); - } - - exitStructDeclaration(); - return declaration; -} - -void TParseContext::enterStructDeclaration(const TSourceLoc &line, const TString &identifier) -{ - ++mStructNestingLevel; - - // Embedded structure definitions are not supported per GLSL ES spec. - // ESSL 1.00.17 section 10.9. ESSL 3.00.6 section 12.11. - if (mStructNestingLevel > 1) - { - error(line, "Embedded struct definitions are not allowed", "struct"); - } -} - -void TParseContext::exitStructDeclaration() -{ - --mStructNestingLevel; -} - -void TParseContext::checkIsBelowStructNestingLimit(const TSourceLoc &line, const TField &field) -{ - if (!sh::IsWebGLBasedSpec(mShaderSpec)) - { - return; - } - - if (field.type()->getBasicType() != EbtStruct) - { - return; - } - - // We're already inside a structure definition at this point, so add - // one to the field's struct nesting. - if (1 + field.type()->getDeepestStructNesting() > kWebGLMaxStructNesting) - { - std::stringstream reasonStream; - reasonStream << "Reference of struct type " << field.type()->getStruct()->name().c_str() - << " exceeds maximum allowed nesting level of " << kWebGLMaxStructNesting; - std::string reason = reasonStream.str(); - error(line, reason.c_str(), field.name().c_str()); - return; - } -} - -// -// Parse an array index expression -// -TIntermTyped *TParseContext::addIndexExpression(TIntermTyped *baseExpression, - const TSourceLoc &location, - TIntermTyped *indexExpression) -{ - if (!baseExpression->isArray() && !baseExpression->isMatrix() && !baseExpression->isVector()) - { - if (baseExpression->getAsSymbolNode()) - { - error(location, " left of '[' is not of type array, matrix, or vector ", - baseExpression->getAsSymbolNode()->getSymbol().c_str()); - } - else - { - error(location, " left of '[' is not of type array, matrix, or vector ", "expression"); - } - - return CreateZeroNode(TType(EbtFloat, EbpHigh, EvqConst)); - } - - if (baseExpression->getQualifier() == EvqPerVertexIn) - { - ASSERT(mShaderType == GL_GEOMETRY_SHADER_OES); - if (mGeometryShaderInputPrimitiveType == EptUndefined) - { - error(location, "missing input primitive declaration before indexing gl_in.", "["); - return CreateZeroNode(TType(EbtFloat, EbpHigh, EvqConst)); - } - } - - TIntermConstantUnion *indexConstantUnion = indexExpression->getAsConstantUnion(); - - // TODO(oetuaho@nvidia.com): Get rid of indexConstantUnion == nullptr below once ANGLE is able - // to constant fold all constant expressions. Right now we don't allow indexing interface blocks - // or fragment outputs with expressions that ANGLE is not able to constant fold, even if the - // index is a constant expression. - if (indexExpression->getQualifier() != EvqConst || indexConstantUnion == nullptr) - { - if (baseExpression->isInterfaceBlock()) - { - // TODO(jiawei.shao@intel.com): implement GL_OES_shader_io_blocks. - switch (baseExpression->getQualifier()) - { - case EvqPerVertexIn: - break; - case EvqUniform: - case EvqBuffer: - error(location, - "array indexes for uniform block arrays and shader storage block arrays " - "must be constant integral expressions", - "["); - break; - default: - // We can reach here only in error cases. - ASSERT(mDiagnostics->numErrors() > 0); - break; - } - } - else if (baseExpression->getQualifier() == EvqFragmentOut) - { - error(location, - "array indexes for fragment outputs must be constant integral expressions", "["); - } - else if (mShaderSpec == SH_WEBGL2_SPEC && baseExpression->getQualifier() == EvqFragData) - { - error(location, "array index for gl_FragData must be constant zero", "["); - } - } - - if (indexConstantUnion) - { - // If an out-of-range index is not qualified as constant, the behavior in the spec is - // undefined. This applies even if ANGLE has been able to constant fold it (ANGLE may - // constant fold expressions that are not constant expressions). The most compatible way to - // handle this case is to report a warning instead of an error and force the index to be in - // the correct range. - bool outOfRangeIndexIsError = indexExpression->getQualifier() == EvqConst; - int index = 0; - if (indexConstantUnion->getBasicType() == EbtInt) - { - index = indexConstantUnion->getIConst(0); - } - else if (indexConstantUnion->getBasicType() == EbtUInt) - { - index = static_cast(indexConstantUnion->getUConst(0)); - } - - int safeIndex = -1; - - if (index < 0) - { - outOfRangeError(outOfRangeIndexIsError, location, "index expression is negative", "[]"); - safeIndex = 0; - } - - if (!baseExpression->getType().isUnsizedArray()) - { - if (baseExpression->isArray()) - { - if (baseExpression->getQualifier() == EvqFragData && index > 0) - { - if (!isExtensionEnabled(TExtension::EXT_draw_buffers)) - { - outOfRangeError(outOfRangeIndexIsError, location, - "array index for gl_FragData must be zero when " - "GL_EXT_draw_buffers is disabled", - "[]"); - safeIndex = 0; - } - } - // Only do generic out-of-range check if similar error hasn't already been reported. - if (safeIndex < 0) - { - safeIndex = checkIndexLessThan(outOfRangeIndexIsError, location, index, - baseExpression->getOutermostArraySize(), - "array index out of range"); - } - } - else if (baseExpression->isMatrix()) - { - safeIndex = checkIndexLessThan(outOfRangeIndexIsError, location, index, - baseExpression->getType().getCols(), - "matrix field selection out of range"); - } - else if (baseExpression->isVector()) - { - safeIndex = checkIndexLessThan(outOfRangeIndexIsError, location, index, - baseExpression->getType().getNominalSize(), - "vector field selection out of range"); - } - - ASSERT(safeIndex >= 0); - // Data of constant unions can't be changed, because it may be shared with other - // constant unions or even builtins, like gl_MaxDrawBuffers. Instead use a new - // sanitized object. - if (safeIndex != index || indexConstantUnion->getBasicType() != EbtInt) - { - TConstantUnion *safeConstantUnion = new TConstantUnion(); - safeConstantUnion->setIConst(safeIndex); - indexConstantUnion->replaceConstantUnion(safeConstantUnion); - indexConstantUnion->getTypePointer()->setBasicType(EbtInt); - } - - TIntermBinary *node = - new TIntermBinary(EOpIndexDirect, baseExpression, indexExpression); - node->setLine(location); - return node->fold(mDiagnostics); - } - } - - TIntermBinary *node = new TIntermBinary(EOpIndexIndirect, baseExpression, indexExpression); - node->setLine(location); - // Indirect indexing can never be constant folded. - return node; -} - -int TParseContext::checkIndexLessThan(bool outOfRangeIndexIsError, - const TSourceLoc &location, - int index, - int arraySize, - const char *reason) -{ - // Should not reach here with an unsized / runtime-sized array. - ASSERT(arraySize > 0); - if (index >= arraySize) - { - std::stringstream reasonStream; - reasonStream << reason << " '" << index << "'"; - std::string token = reasonStream.str(); - outOfRangeError(outOfRangeIndexIsError, location, reason, "[]"); - return arraySize - 1; - } - return index; -} - -TIntermTyped *TParseContext::addFieldSelectionExpression(TIntermTyped *baseExpression, - const TSourceLoc &dotLocation, - const TString &fieldString, - const TSourceLoc &fieldLocation) -{ - if (baseExpression->isArray()) - { - error(fieldLocation, "cannot apply dot operator to an array", "."); - return baseExpression; - } - - if (baseExpression->isVector()) - { - TVector fieldOffsets; - if (!parseVectorFields(fieldLocation, fieldString, baseExpression->getNominalSize(), - &fieldOffsets)) - { - fieldOffsets.resize(1); - fieldOffsets[0] = 0; - } - TIntermSwizzle *node = new TIntermSwizzle(baseExpression, fieldOffsets); - node->setLine(dotLocation); - - return node->fold(); - } - else if (baseExpression->getBasicType() == EbtStruct) - { - const TFieldList &fields = baseExpression->getType().getStruct()->fields(); - if (fields.empty()) - { - error(dotLocation, "structure has no fields", "Internal Error"); - return baseExpression; - } - else - { - bool fieldFound = false; - unsigned int i; - for (i = 0; i < fields.size(); ++i) - { - if (fields[i]->name() == fieldString) - { - fieldFound = true; - break; - } - } - if (fieldFound) - { - TIntermTyped *index = CreateIndexNode(i); - index->setLine(fieldLocation); - TIntermBinary *node = - new TIntermBinary(EOpIndexDirectStruct, baseExpression, index); - node->setLine(dotLocation); - return node->fold(mDiagnostics); - } - else - { - error(dotLocation, " no such field in structure", fieldString.c_str()); - return baseExpression; - } - } - } - else if (baseExpression->isInterfaceBlock()) - { - const TFieldList &fields = baseExpression->getType().getInterfaceBlock()->fields(); - if (fields.empty()) - { - error(dotLocation, "interface block has no fields", "Internal Error"); - return baseExpression; - } - else - { - bool fieldFound = false; - unsigned int i; - for (i = 0; i < fields.size(); ++i) - { - if (fields[i]->name() == fieldString) - { - fieldFound = true; - break; - } - } - if (fieldFound) - { - TIntermTyped *index = CreateIndexNode(i); - index->setLine(fieldLocation); - TIntermBinary *node = - new TIntermBinary(EOpIndexDirectInterfaceBlock, baseExpression, index); - node->setLine(dotLocation); - // Indexing interface blocks can never be constant folded. - return node; - } - else - { - error(dotLocation, " no such field in interface block", fieldString.c_str()); - return baseExpression; - } - } - } - else - { - if (mShaderVersion < 300) - { - error(dotLocation, " field selection requires structure or vector on left hand side", - fieldString.c_str()); - } - else - { - error(dotLocation, - " field selection requires structure, vector, or interface block on left hand " - "side", - fieldString.c_str()); - } - return baseExpression; - } -} - -TLayoutQualifier TParseContext::parseLayoutQualifier(const TString &qualifierType, - const TSourceLoc &qualifierTypeLine) -{ - TLayoutQualifier qualifier = TLayoutQualifier::Create(); - - if (qualifierType == "shared") - { - if (sh::IsWebGLBasedSpec(mShaderSpec)) - { - error(qualifierTypeLine, "Only std140 layout is allowed in WebGL", "shared"); - } - qualifier.blockStorage = EbsShared; - } - else if (qualifierType == "packed") - { - if (sh::IsWebGLBasedSpec(mShaderSpec)) - { - error(qualifierTypeLine, "Only std140 layout is allowed in WebGL", "packed"); - } - qualifier.blockStorage = EbsPacked; - } - else if (qualifierType == "std430") - { - checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310); - qualifier.blockStorage = EbsStd430; - } - else if (qualifierType == "std140") - { - qualifier.blockStorage = EbsStd140; - } - else if (qualifierType == "row_major") - { - qualifier.matrixPacking = EmpRowMajor; - } - else if (qualifierType == "column_major") - { - qualifier.matrixPacking = EmpColumnMajor; - } - else if (qualifierType == "location") - { - error(qualifierTypeLine, "invalid layout qualifier: location requires an argument", - qualifierType.c_str()); - } - else if (qualifierType == "yuv" && mShaderType == GL_FRAGMENT_SHADER) - { - if (checkCanUseExtension(qualifierTypeLine, TExtension::EXT_YUV_target)) - { - qualifier.yuv = true; - } - } - else if (qualifierType == "rgba32f") - { - checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310); - qualifier.imageInternalFormat = EiifRGBA32F; - } - else if (qualifierType == "rgba16f") - { - checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310); - qualifier.imageInternalFormat = EiifRGBA16F; - } - else if (qualifierType == "r32f") - { - checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310); - qualifier.imageInternalFormat = EiifR32F; - } - else if (qualifierType == "rgba8") - { - checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310); - qualifier.imageInternalFormat = EiifRGBA8; - } - else if (qualifierType == "rgba8_snorm") - { - checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310); - qualifier.imageInternalFormat = EiifRGBA8_SNORM; - } - else if (qualifierType == "rgba32i") - { - checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310); - qualifier.imageInternalFormat = EiifRGBA32I; - } - else if (qualifierType == "rgba16i") - { - checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310); - qualifier.imageInternalFormat = EiifRGBA16I; - } - else if (qualifierType == "rgba8i") - { - checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310); - qualifier.imageInternalFormat = EiifRGBA8I; - } - else if (qualifierType == "r32i") - { - checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310); - qualifier.imageInternalFormat = EiifR32I; - } - else if (qualifierType == "rgba32ui") - { - checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310); - qualifier.imageInternalFormat = EiifRGBA32UI; - } - else if (qualifierType == "rgba16ui") - { - checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310); - qualifier.imageInternalFormat = EiifRGBA16UI; - } - else if (qualifierType == "rgba8ui") - { - checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310); - qualifier.imageInternalFormat = EiifRGBA8UI; - } - else if (qualifierType == "r32ui") - { - checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310); - qualifier.imageInternalFormat = EiifR32UI; - } - else if (qualifierType == "points" && mShaderType == GL_GEOMETRY_SHADER_OES && - checkCanUseExtension(qualifierTypeLine, TExtension::OES_geometry_shader)) - { - checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310); - qualifier.primitiveType = EptPoints; - } - else if (qualifierType == "lines" && mShaderType == GL_GEOMETRY_SHADER_OES && - checkCanUseExtension(qualifierTypeLine, TExtension::OES_geometry_shader)) - { - checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310); - qualifier.primitiveType = EptLines; - } - else if (qualifierType == "lines_adjacency" && mShaderType == GL_GEOMETRY_SHADER_OES && - checkCanUseExtension(qualifierTypeLine, TExtension::OES_geometry_shader)) - { - checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310); - qualifier.primitiveType = EptLinesAdjacency; - } - else if (qualifierType == "triangles" && mShaderType == GL_GEOMETRY_SHADER_OES && - checkCanUseExtension(qualifierTypeLine, TExtension::OES_geometry_shader)) - { - checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310); - qualifier.primitiveType = EptTriangles; - } - else if (qualifierType == "triangles_adjacency" && mShaderType == GL_GEOMETRY_SHADER_OES && - checkCanUseExtension(qualifierTypeLine, TExtension::OES_geometry_shader)) - { - checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310); - qualifier.primitiveType = EptTrianglesAdjacency; - } - else if (qualifierType == "line_strip" && mShaderType == GL_GEOMETRY_SHADER_OES && - checkCanUseExtension(qualifierTypeLine, TExtension::OES_geometry_shader)) - { - checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310); - qualifier.primitiveType = EptLineStrip; - } - else if (qualifierType == "triangle_strip" && mShaderType == GL_GEOMETRY_SHADER_OES && - checkCanUseExtension(qualifierTypeLine, TExtension::OES_geometry_shader)) - { - checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310); - qualifier.primitiveType = EptTriangleStrip; - } - - else - { - error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str()); - } - - return qualifier; -} - -void TParseContext::parseLocalSize(const TString &qualifierType, - const TSourceLoc &qualifierTypeLine, - int intValue, - const TSourceLoc &intValueLine, - const std::string &intValueString, - size_t index, - sh::WorkGroupSize *localSize) -{ - checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310); - if (intValue < 1) - { - std::stringstream reasonStream; - reasonStream << "out of range: " << getWorkGroupSizeString(index) << " must be positive"; - std::string reason = reasonStream.str(); - error(intValueLine, reason.c_str(), intValueString.c_str()); - } - (*localSize)[index] = intValue; -} - -void TParseContext::parseNumViews(int intValue, - const TSourceLoc &intValueLine, - const std::string &intValueString, - int *numViews) -{ - // This error is only specified in WebGL, but tightens unspecified behavior in the native - // specification. - if (intValue < 1) - { - error(intValueLine, "out of range: num_views must be positive", intValueString.c_str()); - } - *numViews = intValue; -} - -void TParseContext::parseInvocations(int intValue, - const TSourceLoc &intValueLine, - const std::string &intValueString, - int *numInvocations) -{ - // Although SPEC isn't clear whether invocations can be less than 1, we add this limit because - // it doesn't make sense to accept invocations <= 0. - if (intValue < 1 || intValue > mMaxGeometryShaderInvocations) - { - error(intValueLine, - "out of range: invocations must be in the range of [1, " - "MAX_GEOMETRY_SHADER_INVOCATIONS_OES]", - intValueString.c_str()); - } - else - { - *numInvocations = intValue; - } -} - -void TParseContext::parseMaxVertices(int intValue, - const TSourceLoc &intValueLine, - const std::string &intValueString, - int *maxVertices) -{ - // Although SPEC isn't clear whether max_vertices can be less than 0, we add this limit because - // it doesn't make sense to accept max_vertices < 0. - if (intValue < 0 || intValue > mMaxGeometryShaderMaxVertices) - { - error( - intValueLine, - "out of range: max_vertices must be in the range of [0, gl_MaxGeometryOutputVertices]", - intValueString.c_str()); - } - else - { - *maxVertices = intValue; - } -} - -TLayoutQualifier TParseContext::parseLayoutQualifier(const TString &qualifierType, - const TSourceLoc &qualifierTypeLine, - int intValue, - const TSourceLoc &intValueLine) -{ - TLayoutQualifier qualifier = TLayoutQualifier::Create(); - - std::string intValueString = Str(intValue); - - if (qualifierType == "location") - { - // must check that location is non-negative - if (intValue < 0) - { - error(intValueLine, "out of range: location must be non-negative", - intValueString.c_str()); - } - else - { - qualifier.location = intValue; - qualifier.locationsSpecified = 1; - } - } - else if (qualifierType == "binding") - { - checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310); - if (intValue < 0) - { - error(intValueLine, "out of range: binding must be non-negative", - intValueString.c_str()); - } - else - { - qualifier.binding = intValue; - } - } - else if (qualifierType == "offset") - { - checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310); - if (intValue < 0) - { - error(intValueLine, "out of range: offset must be non-negative", - intValueString.c_str()); - } - else - { - qualifier.offset = intValue; - } - } - else if (qualifierType == "local_size_x") - { - parseLocalSize(qualifierType, qualifierTypeLine, intValue, intValueLine, intValueString, 0u, - &qualifier.localSize); - } - else if (qualifierType == "local_size_y") - { - parseLocalSize(qualifierType, qualifierTypeLine, intValue, intValueLine, intValueString, 1u, - &qualifier.localSize); - } - else if (qualifierType == "local_size_z") - { - parseLocalSize(qualifierType, qualifierTypeLine, intValue, intValueLine, intValueString, 2u, - &qualifier.localSize); - } - else if (qualifierType == "num_views" && mShaderType == GL_VERTEX_SHADER) - { - if (checkCanUseExtension(qualifierTypeLine, TExtension::OVR_multiview)) - { - parseNumViews(intValue, intValueLine, intValueString, &qualifier.numViews); - } - } - else if (qualifierType == "invocations" && mShaderType == GL_GEOMETRY_SHADER_OES && - checkCanUseExtension(qualifierTypeLine, TExtension::OES_geometry_shader)) - { - parseInvocations(intValue, intValueLine, intValueString, &qualifier.invocations); - } - else if (qualifierType == "max_vertices" && mShaderType == GL_GEOMETRY_SHADER_OES && - checkCanUseExtension(qualifierTypeLine, TExtension::OES_geometry_shader)) - { - parseMaxVertices(intValue, intValueLine, intValueString, &qualifier.maxVertices); - } - - else - { - error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str()); - } - - return qualifier; -} - -TTypeQualifierBuilder *TParseContext::createTypeQualifierBuilder(const TSourceLoc &loc) -{ - return new TTypeQualifierBuilder( - new TStorageQualifierWrapper(symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary, loc), - mShaderVersion); -} - -TStorageQualifierWrapper *TParseContext::parseGlobalStorageQualifier(TQualifier qualifier, - const TSourceLoc &loc) -{ - checkIsAtGlobalLevel(loc, getQualifierString(qualifier)); - return new TStorageQualifierWrapper(qualifier, loc); -} - -TStorageQualifierWrapper *TParseContext::parseVaryingQualifier(const TSourceLoc &loc) -{ - if (getShaderType() == GL_VERTEX_SHADER) - { - return parseGlobalStorageQualifier(EvqVaryingOut, loc); - } - return parseGlobalStorageQualifier(EvqVaryingIn, loc); -} - -TStorageQualifierWrapper *TParseContext::parseInQualifier(const TSourceLoc &loc) -{ - if (declaringFunction()) - { - return new TStorageQualifierWrapper(EvqIn, loc); - } - - switch (getShaderType()) - { - case GL_VERTEX_SHADER: - { - if (mShaderVersion < 300 && !isExtensionEnabled(TExtension::OVR_multiview)) - { - error(loc, "storage qualifier supported in GLSL ES 3.00 and above only", "in"); - } - return new TStorageQualifierWrapper(EvqVertexIn, loc); - } - case GL_FRAGMENT_SHADER: - { - if (mShaderVersion < 300) - { - error(loc, "storage qualifier supported in GLSL ES 3.00 and above only", "in"); - } - return new TStorageQualifierWrapper(EvqFragmentIn, loc); - } - case GL_COMPUTE_SHADER: - { - return new TStorageQualifierWrapper(EvqComputeIn, loc); - } - case GL_GEOMETRY_SHADER_OES: - { - return new TStorageQualifierWrapper(EvqGeometryIn, loc); - } - default: - { - UNREACHABLE(); - return new TStorageQualifierWrapper(EvqLast, loc); - } - } -} - -TStorageQualifierWrapper *TParseContext::parseOutQualifier(const TSourceLoc &loc) -{ - if (declaringFunction()) - { - return new TStorageQualifierWrapper(EvqOut, loc); - } - switch (getShaderType()) - { - case GL_VERTEX_SHADER: - { - if (mShaderVersion < 300) - { - error(loc, "storage qualifier supported in GLSL ES 3.00 and above only", "out"); - } - return new TStorageQualifierWrapper(EvqVertexOut, loc); - } - case GL_FRAGMENT_SHADER: - { - if (mShaderVersion < 300) - { - error(loc, "storage qualifier supported in GLSL ES 3.00 and above only", "out"); - } - return new TStorageQualifierWrapper(EvqFragmentOut, loc); - } - case GL_COMPUTE_SHADER: - { - error(loc, "storage qualifier isn't supported in compute shaders", "out"); - return new TStorageQualifierWrapper(EvqLast, loc); - } - case GL_GEOMETRY_SHADER_OES: - { - return new TStorageQualifierWrapper(EvqGeometryOut, loc); - } - default: - { - UNREACHABLE(); - return new TStorageQualifierWrapper(EvqLast, loc); - } - } -} - -TStorageQualifierWrapper *TParseContext::parseInOutQualifier(const TSourceLoc &loc) -{ - if (!declaringFunction()) - { - error(loc, "invalid qualifier: can be only used with function parameters", "inout"); - } - return new TStorageQualifierWrapper(EvqInOut, loc); -} - -TLayoutQualifier TParseContext::joinLayoutQualifiers(TLayoutQualifier leftQualifier, - TLayoutQualifier rightQualifier, - const TSourceLoc &rightQualifierLocation) -{ - return sh::JoinLayoutQualifiers(leftQualifier, rightQualifier, rightQualifierLocation, - mDiagnostics); -} - -TField *TParseContext::parseStructDeclarator(TString *identifier, const TSourceLoc &loc) -{ - checkIsNotReserved(loc, *identifier); - TType *type = new TType(EbtVoid, EbpUndefined); - return new TField(type, identifier, loc); -} - -TField *TParseContext::parseStructArrayDeclarator(TString *identifier, - const TSourceLoc &loc, - const TVector &arraySizes, - const TSourceLoc &arraySizeLoc) -{ - checkIsNotReserved(loc, *identifier); - - TType *type = new TType(EbtVoid, EbpUndefined); - type->makeArrays(arraySizes); - - return new TField(type, identifier, loc); -} - -void TParseContext::checkDoesNotHaveDuplicateFieldName(const TFieldList::const_iterator begin, - const TFieldList::const_iterator end, - const TString &name, - const TSourceLoc &location) -{ - for (auto fieldIter = begin; fieldIter != end; ++fieldIter) - { - if ((*fieldIter)->name() == name) - { - error(location, "duplicate field name in structure", name.c_str()); - } - } -} - -TFieldList *TParseContext::addStructFieldList(TFieldList *fields, const TSourceLoc &location) -{ - for (TFieldList::const_iterator fieldIter = fields->begin(); fieldIter != fields->end(); - ++fieldIter) - { - checkDoesNotHaveDuplicateFieldName(fields->begin(), fieldIter, (*fieldIter)->name(), - location); - } - return fields; -} - -TFieldList *TParseContext::combineStructFieldLists(TFieldList *processedFields, - const TFieldList *newlyAddedFields, - const TSourceLoc &location) -{ - for (TField *field : *newlyAddedFields) - { - checkDoesNotHaveDuplicateFieldName(processedFields->begin(), processedFields->end(), - field->name(), location); - processedFields->push_back(field); - } - return processedFields; -} - -TFieldList *TParseContext::addStructDeclaratorListWithQualifiers( - const TTypeQualifierBuilder &typeQualifierBuilder, - TPublicType *typeSpecifier, - TFieldList *fieldList) -{ - TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics); - - typeSpecifier->qualifier = typeQualifier.qualifier; - typeSpecifier->layoutQualifier = typeQualifier.layoutQualifier; - typeSpecifier->memoryQualifier = typeQualifier.memoryQualifier; - typeSpecifier->invariant = typeQualifier.invariant; - if (typeQualifier.precision != EbpUndefined) - { - typeSpecifier->precision = typeQualifier.precision; - } - return addStructDeclaratorList(*typeSpecifier, fieldList); -} - -TFieldList *TParseContext::addStructDeclaratorList(const TPublicType &typeSpecifier, - TFieldList *declaratorList) -{ - checkPrecisionSpecified(typeSpecifier.getLine(), typeSpecifier.precision, - typeSpecifier.getBasicType()); - - checkIsNonVoid(typeSpecifier.getLine(), (*declaratorList)[0]->name(), - typeSpecifier.getBasicType()); - - checkWorkGroupSizeIsNotSpecified(typeSpecifier.getLine(), typeSpecifier.layoutQualifier); - - for (TField *declarator : *declaratorList) - { - // Don't allow arrays of arrays in ESSL < 3.10. - if (declarator->type()->isArray()) - { - checkArrayElementIsNotArray(typeSpecifier.getLine(), typeSpecifier); - } - - auto *declaratorArraySizes = declarator->type()->getArraySizes(); - - TType *type = declarator->type(); - *type = TType(typeSpecifier); - if (declaratorArraySizes != nullptr) - { - for (unsigned int arraySize : *declaratorArraySizes) - { - type->makeArray(arraySize); - } - } - - checkIsBelowStructNestingLimit(typeSpecifier.getLine(), *declarator); - } - - return declaratorList; -} - -TTypeSpecifierNonArray TParseContext::addStructure(const TSourceLoc &structLine, - const TSourceLoc &nameLine, - const TString *structName, - TFieldList *fieldList) -{ - TStructure *structure = new TStructure(&symbolTable, structName, fieldList); - - // Store a bool in the struct if we're at global scope, to allow us to - // skip the local struct scoping workaround in HLSL. - structure->setAtGlobalScope(symbolTable.atGlobalLevel()); - - if (!structName->empty()) - { - checkIsNotReserved(nameLine, *structName); - if (!symbolTable.declareStructType(structure)) - { - error(nameLine, "redefinition of a struct", structName->c_str()); - } - } - - // ensure we do not specify any storage qualifiers on the struct members - for (unsigned int typeListIndex = 0; typeListIndex < fieldList->size(); typeListIndex++) - { - TField &field = *(*fieldList)[typeListIndex]; - const TQualifier qualifier = field.type()->getQualifier(); - switch (qualifier) - { - case EvqGlobal: - case EvqTemporary: - break; - default: - error(field.line(), "invalid qualifier on struct member", - getQualifierString(qualifier)); - break; - } - if (field.type()->isInvariant()) - { - error(field.line(), "invalid qualifier on struct member", "invariant"); - } - // ESSL 3.10 section 4.1.8 -- atomic_uint or images are not allowed as structure member. - if (IsImage(field.type()->getBasicType()) || IsAtomicCounter(field.type()->getBasicType())) - { - error(field.line(), "disallowed type in struct", field.type()->getBasicString()); - } - - checkIsNotUnsizedArray(field.line(), "array members of structs must specify a size", - field.name().c_str(), field.type()); - - checkMemoryQualifierIsNotSpecified(field.type()->getMemoryQualifier(), field.line()); - - checkBindingIsNotSpecified(field.line(), field.type()->getLayoutQualifier().binding); - - checkLocationIsNotSpecified(field.line(), field.type()->getLayoutQualifier()); - } - - TTypeSpecifierNonArray typeSpecifierNonArray; - typeSpecifierNonArray.initializeStruct(structure, true, structLine); - exitStructDeclaration(); - - return typeSpecifierNonArray; -} - -TIntermSwitch *TParseContext::addSwitch(TIntermTyped *init, - TIntermBlock *statementList, - const TSourceLoc &loc) -{ - TBasicType switchType = init->getBasicType(); - if ((switchType != EbtInt && switchType != EbtUInt) || init->isMatrix() || init->isArray() || - init->isVector()) - { - error(init->getLine(), "init-expression in a switch statement must be a scalar integer", - "switch"); - return nullptr; - } - - ASSERT(statementList); - if (!ValidateSwitchStatementList(switchType, mShaderVersion, mDiagnostics, statementList, loc)) - { - ASSERT(mDiagnostics->numErrors() > 0); - return nullptr; - } - - TIntermSwitch *node = new TIntermSwitch(init, statementList); - node->setLine(loc); - return node; -} - -TIntermCase *TParseContext::addCase(TIntermTyped *condition, const TSourceLoc &loc) -{ - if (mSwitchNestingLevel == 0) - { - error(loc, "case labels need to be inside switch statements", "case"); - return nullptr; - } - if (condition == nullptr) - { - error(loc, "case label must have a condition", "case"); - return nullptr; - } - if ((condition->getBasicType() != EbtInt && condition->getBasicType() != EbtUInt) || - condition->isMatrix() || condition->isArray() || condition->isVector()) - { - error(condition->getLine(), "case label must be a scalar integer", "case"); - } - TIntermConstantUnion *conditionConst = condition->getAsConstantUnion(); - // TODO(oetuaho@nvidia.com): Get rid of the conditionConst == nullptr check once all constant - // expressions can be folded. Right now we don't allow constant expressions that ANGLE can't - // fold in case labels. - if (condition->getQualifier() != EvqConst || conditionConst == nullptr) - { - error(condition->getLine(), "case label must be constant", "case"); - } - TIntermCase *node = new TIntermCase(condition); - node->setLine(loc); - return node; -} - -TIntermCase *TParseContext::addDefault(const TSourceLoc &loc) -{ - if (mSwitchNestingLevel == 0) - { - error(loc, "default labels need to be inside switch statements", "default"); - return nullptr; - } - TIntermCase *node = new TIntermCase(nullptr); - node->setLine(loc); - return node; -} - -TIntermTyped *TParseContext::createUnaryMath(TOperator op, - TIntermTyped *child, - const TSourceLoc &loc) -{ - ASSERT(child != nullptr); - - switch (op) - { - case EOpLogicalNot: - if (child->getBasicType() != EbtBool || child->isMatrix() || child->isArray() || - child->isVector()) - { - unaryOpError(loc, GetOperatorString(op), child->getCompleteString()); - return nullptr; - } - break; - case EOpBitwiseNot: - if ((child->getBasicType() != EbtInt && child->getBasicType() != EbtUInt) || - child->isMatrix() || child->isArray()) - { - unaryOpError(loc, GetOperatorString(op), child->getCompleteString()); - return nullptr; - } - break; - case EOpPostIncrement: - case EOpPreIncrement: - case EOpPostDecrement: - case EOpPreDecrement: - case EOpNegative: - case EOpPositive: - if (child->getBasicType() == EbtStruct || child->isInterfaceBlock() || - child->getBasicType() == EbtBool || child->isArray() || - IsOpaqueType(child->getBasicType())) - { - unaryOpError(loc, GetOperatorString(op), child->getCompleteString()); - return nullptr; - } - // Operators for built-ins are already type checked against their prototype. - default: - break; - } - - if (child->getMemoryQualifier().writeonly) - { - unaryOpError(loc, GetOperatorString(op), child->getCompleteString()); - return nullptr; - } - - TIntermUnary *node = new TIntermUnary(op, child); - node->setLine(loc); - - return node->fold(mDiagnostics); -} - -TIntermTyped *TParseContext::addUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &loc) -{ - ASSERT(op != EOpNull); - TIntermTyped *node = createUnaryMath(op, child, loc); - if (node == nullptr) - { - return child; - } - return node; -} - -TIntermTyped *TParseContext::addUnaryMathLValue(TOperator op, - TIntermTyped *child, - const TSourceLoc &loc) -{ - checkCanBeLValue(loc, GetOperatorString(op), child); - return addUnaryMath(op, child, loc); -} - -bool TParseContext::binaryOpCommonCheck(TOperator op, - TIntermTyped *left, - TIntermTyped *right, - const TSourceLoc &loc) -{ - // Check opaque types are not allowed to be operands in expressions other than array indexing - // and structure member selection. - if (IsOpaqueType(left->getBasicType()) || IsOpaqueType(right->getBasicType())) - { - switch (op) - { - case EOpIndexDirect: - case EOpIndexIndirect: - break; - case EOpIndexDirectStruct: - UNREACHABLE(); - - default: - error(loc, "Invalid operation for variables with an opaque type", - GetOperatorString(op)); - return false; - } - } - - if (right->getMemoryQualifier().writeonly) - { - error(loc, "Invalid operation for variables with writeonly", GetOperatorString(op)); - return false; - } - - if (left->getMemoryQualifier().writeonly) - { - switch (op) - { - case EOpAssign: - case EOpInitialize: - case EOpIndexDirect: - case EOpIndexIndirect: - case EOpIndexDirectStruct: - case EOpIndexDirectInterfaceBlock: - break; - default: - error(loc, "Invalid operation for variables with writeonly", GetOperatorString(op)); - return false; - } - } - - if (left->getType().getStruct() || right->getType().getStruct()) - { - switch (op) - { - case EOpIndexDirectStruct: - ASSERT(left->getType().getStruct()); - break; - case EOpEqual: - case EOpNotEqual: - case EOpAssign: - case EOpInitialize: - if (left->getType() != right->getType()) - { - return false; - } - break; - default: - error(loc, "Invalid operation for structs", GetOperatorString(op)); - return false; - } - } - - if (left->isInterfaceBlock() || right->isInterfaceBlock()) - { - switch (op) - { - case EOpIndexDirectInterfaceBlock: - ASSERT(left->getType().getInterfaceBlock()); - break; - default: - error(loc, "Invalid operation for interface blocks", GetOperatorString(op)); - return false; - } - } - - if (left->isArray() != right->isArray()) - { - error(loc, "array / non-array mismatch", GetOperatorString(op)); - return false; - } - - if (left->isArray()) - { - ASSERT(right->isArray()); - if (mShaderVersion < 300) - { - error(loc, "Invalid operation for arrays", GetOperatorString(op)); - return false; - } - - switch (op) - { - case EOpEqual: - case EOpNotEqual: - case EOpAssign: - case EOpInitialize: - break; - default: - error(loc, "Invalid operation for arrays", GetOperatorString(op)); - return false; - } - // At this point, size of implicitly sized arrays should be resolved. - if (*left->getType().getArraySizes() != *right->getType().getArraySizes()) - { - error(loc, "array size mismatch", GetOperatorString(op)); - return false; - } - } - - // Check ops which require integer / ivec parameters - bool isBitShift = false; - switch (op) - { - case EOpBitShiftLeft: - case EOpBitShiftRight: - case EOpBitShiftLeftAssign: - case EOpBitShiftRightAssign: - // Unsigned can be bit-shifted by signed and vice versa, but we need to - // check that the basic type is an integer type. - isBitShift = true; - if (!IsInteger(left->getBasicType()) || !IsInteger(right->getBasicType())) - { - return false; - } - break; - case EOpBitwiseAnd: - case EOpBitwiseXor: - case EOpBitwiseOr: - case EOpBitwiseAndAssign: - case EOpBitwiseXorAssign: - case EOpBitwiseOrAssign: - // It is enough to check the type of only one operand, since later it - // is checked that the operand types match. - if (!IsInteger(left->getBasicType())) - { - return false; - } - break; - default: - break; - } - - // GLSL ES 1.00 and 3.00 do not support implicit type casting. - // So the basic type should usually match. - if (!isBitShift && left->getBasicType() != right->getBasicType()) - { - return false; - } - - // Check that: - // 1. Type sizes match exactly on ops that require that. - // 2. Restrictions for structs that contain arrays or samplers are respected. - // 3. Arithmetic op type dimensionality restrictions for ops other than multiply are respected. - switch (op) - { - case EOpAssign: - case EOpInitialize: - case EOpEqual: - case EOpNotEqual: - // ESSL 1.00 sections 5.7, 5.8, 5.9 - if (mShaderVersion < 300 && left->getType().isStructureContainingArrays()) - { - error(loc, "undefined operation for structs containing arrays", - GetOperatorString(op)); - return false; - } - // Samplers as l-values are disallowed also in ESSL 3.00, see section 4.1.7, - // we interpret the spec so that this extends to structs containing samplers, - // similarly to ESSL 1.00 spec. - if ((mShaderVersion < 300 || op == EOpAssign || op == EOpInitialize) && - left->getType().isStructureContainingSamplers()) - { - error(loc, "undefined operation for structs containing samplers", - GetOperatorString(op)); - return false; - } - - if ((left->getNominalSize() != right->getNominalSize()) || - (left->getSecondarySize() != right->getSecondarySize())) - { - error(loc, "dimension mismatch", GetOperatorString(op)); - return false; - } - break; - case EOpLessThan: - case EOpGreaterThan: - case EOpLessThanEqual: - case EOpGreaterThanEqual: - if (!left->isScalar() || !right->isScalar()) - { - error(loc, "comparison operator only defined for scalars", GetOperatorString(op)); - return false; - } - break; - case EOpAdd: - case EOpSub: - case EOpDiv: - case EOpIMod: - case EOpBitShiftLeft: - case EOpBitShiftRight: - case EOpBitwiseAnd: - case EOpBitwiseXor: - case EOpBitwiseOr: - case EOpAddAssign: - case EOpSubAssign: - case EOpDivAssign: - case EOpIModAssign: - case EOpBitShiftLeftAssign: - case EOpBitShiftRightAssign: - case EOpBitwiseAndAssign: - case EOpBitwiseXorAssign: - case EOpBitwiseOrAssign: - if ((left->isMatrix() && right->isVector()) || (left->isVector() && right->isMatrix())) - { - return false; - } - - // Are the sizes compatible? - if (left->getNominalSize() != right->getNominalSize() || - left->getSecondarySize() != right->getSecondarySize()) - { - // If the nominal sizes of operands do not match: - // One of them must be a scalar. - if (!left->isScalar() && !right->isScalar()) - return false; - - // In the case of compound assignment other than multiply-assign, - // the right side needs to be a scalar. Otherwise a vector/matrix - // would be assigned to a scalar. A scalar can't be shifted by a - // vector either. - if (!right->isScalar() && - (IsAssignment(op) || op == EOpBitShiftLeft || op == EOpBitShiftRight)) - return false; - } - break; - default: - break; - } - - return true; -} - -bool TParseContext::isMultiplicationTypeCombinationValid(TOperator op, - const TType &left, - const TType &right) -{ - switch (op) - { - case EOpMul: - case EOpMulAssign: - return left.getNominalSize() == right.getNominalSize() && - left.getSecondarySize() == right.getSecondarySize(); - case EOpVectorTimesScalar: - return true; - case EOpVectorTimesScalarAssign: - ASSERT(!left.isMatrix() && !right.isMatrix()); - return left.isVector() && !right.isVector(); - case EOpVectorTimesMatrix: - return left.getNominalSize() == right.getRows(); - case EOpVectorTimesMatrixAssign: - ASSERT(!left.isMatrix() && right.isMatrix()); - return left.isVector() && left.getNominalSize() == right.getRows() && - left.getNominalSize() == right.getCols(); - case EOpMatrixTimesVector: - return left.getCols() == right.getNominalSize(); - case EOpMatrixTimesScalar: - return true; - case EOpMatrixTimesScalarAssign: - ASSERT(left.isMatrix() && !right.isMatrix()); - return !right.isVector(); - case EOpMatrixTimesMatrix: - return left.getCols() == right.getRows(); - case EOpMatrixTimesMatrixAssign: - ASSERT(left.isMatrix() && right.isMatrix()); - // We need to check two things: - // 1. The matrix multiplication step is valid. - // 2. The result will have the same number of columns as the lvalue. - return left.getCols() == right.getRows() && left.getCols() == right.getCols(); - - default: - UNREACHABLE(); - return false; - } -} - -TIntermTyped *TParseContext::addBinaryMathInternal(TOperator op, - TIntermTyped *left, - TIntermTyped *right, - const TSourceLoc &loc) -{ - if (!binaryOpCommonCheck(op, left, right, loc)) - return nullptr; - - switch (op) - { - case EOpEqual: - case EOpNotEqual: - case EOpLessThan: - case EOpGreaterThan: - case EOpLessThanEqual: - case EOpGreaterThanEqual: - break; - case EOpLogicalOr: - case EOpLogicalXor: - case EOpLogicalAnd: - ASSERT(!left->isArray() && !right->isArray() && !left->getType().getStruct() && - !right->getType().getStruct()); - if (left->getBasicType() != EbtBool || !left->isScalar() || !right->isScalar()) - { - return nullptr; - } - // Basic types matching should have been already checked. - ASSERT(right->getBasicType() == EbtBool); - break; - case EOpAdd: - case EOpSub: - case EOpDiv: - case EOpMul: - ASSERT(!left->isArray() && !right->isArray() && !left->getType().getStruct() && - !right->getType().getStruct()); - if (left->getBasicType() == EbtBool) - { - return nullptr; - } - break; - case EOpIMod: - ASSERT(!left->isArray() && !right->isArray() && !left->getType().getStruct() && - !right->getType().getStruct()); - // Note that this is only for the % operator, not for mod() - if (left->getBasicType() == EbtBool || left->getBasicType() == EbtFloat) - { - return nullptr; - } - break; - default: - break; - } - - if (op == EOpMul) - { - op = TIntermBinary::GetMulOpBasedOnOperands(left->getType(), right->getType()); - if (!isMultiplicationTypeCombinationValid(op, left->getType(), right->getType())) - { - return nullptr; - } - } - - TIntermBinary *node = new TIntermBinary(op, left, right); - node->setLine(loc); - - // See if we can fold constants. - return node->fold(mDiagnostics); -} - -TIntermTyped *TParseContext::addBinaryMath(TOperator op, - TIntermTyped *left, - TIntermTyped *right, - const TSourceLoc &loc) -{ - TIntermTyped *node = addBinaryMathInternal(op, left, right, loc); - if (node == 0) - { - binaryOpError(loc, GetOperatorString(op), left->getCompleteString(), - right->getCompleteString()); - return left; - } - return node; -} - -TIntermTyped *TParseContext::addBinaryMathBooleanResult(TOperator op, - TIntermTyped *left, - TIntermTyped *right, - const TSourceLoc &loc) -{ - TIntermTyped *node = addBinaryMathInternal(op, left, right, loc); - if (node == nullptr) - { - binaryOpError(loc, GetOperatorString(op), left->getCompleteString(), - right->getCompleteString()); - node = CreateBoolNode(false); - node->setLine(loc); - } - return node; -} - -TIntermBinary *TParseContext::createAssign(TOperator op, - TIntermTyped *left, - TIntermTyped *right, - const TSourceLoc &loc) -{ - if (binaryOpCommonCheck(op, left, right, loc)) - { - if (op == EOpMulAssign) - { - op = TIntermBinary::GetMulAssignOpBasedOnOperands(left->getType(), right->getType()); - if (!isMultiplicationTypeCombinationValid(op, left->getType(), right->getType())) - { - return nullptr; - } - } - TIntermBinary *node = new TIntermBinary(op, left, right); - node->setLine(loc); - - return node; - } - return nullptr; -} - -TIntermTyped *TParseContext::addAssign(TOperator op, - TIntermTyped *left, - TIntermTyped *right, - const TSourceLoc &loc) -{ - checkCanBeLValue(loc, "assign", left); - TIntermTyped *node = createAssign(op, left, right, loc); - if (node == nullptr) - { - assignError(loc, "assign", left->getCompleteString(), right->getCompleteString()); - return left; - } - return node; -} - -TIntermTyped *TParseContext::addComma(TIntermTyped *left, - TIntermTyped *right, - const TSourceLoc &loc) -{ - // WebGL2 section 5.26, the following results in an error: - // "Sequence operator applied to void, arrays, or structs containing arrays" - if (mShaderSpec == SH_WEBGL2_SPEC && - (left->isArray() || left->getBasicType() == EbtVoid || - left->getType().isStructureContainingArrays() || right->isArray() || - right->getBasicType() == EbtVoid || right->getType().isStructureContainingArrays())) - { - error(loc, - "sequence operator is not allowed for void, arrays, or structs containing arrays", - ","); - } - - TIntermBinary *commaNode = new TIntermBinary(EOpComma, left, right); - TQualifier resultQualifier = TIntermBinary::GetCommaQualifier(mShaderVersion, left, right); - commaNode->getTypePointer()->setQualifier(resultQualifier); - return commaNode->fold(mDiagnostics); -} - -TIntermBranch *TParseContext::addBranch(TOperator op, const TSourceLoc &loc) -{ - switch (op) - { - case EOpContinue: - if (mLoopNestingLevel <= 0) - { - error(loc, "continue statement only allowed in loops", ""); - } - break; - case EOpBreak: - if (mLoopNestingLevel <= 0 && mSwitchNestingLevel <= 0) - { - error(loc, "break statement only allowed in loops and switch statements", ""); - } - break; - case EOpReturn: - if (mCurrentFunctionType->getBasicType() != EbtVoid) - { - error(loc, "non-void function must return a value", "return"); - } - break; - case EOpKill: - if (mShaderType != GL_FRAGMENT_SHADER) - { - error(loc, "discard supported in fragment shaders only", "discard"); - } - break; - default: - UNREACHABLE(); - break; - } - return addBranch(op, nullptr, loc); -} - -TIntermBranch *TParseContext::addBranch(TOperator op, - TIntermTyped *expression, - const TSourceLoc &loc) -{ - if (expression != nullptr) - { - ASSERT(op == EOpReturn); - mFunctionReturnsValue = true; - if (mCurrentFunctionType->getBasicType() == EbtVoid) - { - error(loc, "void function cannot return a value", "return"); - } - else if (*mCurrentFunctionType != expression->getType()) - { - error(loc, "function return is not matching type:", "return"); - } - } - TIntermBranch *node = new TIntermBranch(op, expression); - node->setLine(loc); - return node; -} - -void TParseContext::checkTextureGather(TIntermAggregate *functionCall) -{ - ASSERT(functionCall->getOp() == EOpCallBuiltInFunction); - const TString &name = functionCall->getFunctionSymbolInfo()->getName(); - bool isTextureGather = (name == "textureGather"); - bool isTextureGatherOffset = (name == "textureGatherOffset"); - if (isTextureGather || isTextureGatherOffset) - { - TIntermNode *componentNode = nullptr; - TIntermSequence *arguments = functionCall->getSequence(); - ASSERT(arguments->size() >= 2u && arguments->size() <= 4u); - const TIntermTyped *sampler = arguments->front()->getAsTyped(); - ASSERT(sampler != nullptr); - switch (sampler->getBasicType()) - { - case EbtSampler2D: - case EbtISampler2D: - case EbtUSampler2D: - case EbtSampler2DArray: - case EbtISampler2DArray: - case EbtUSampler2DArray: - if ((isTextureGather && arguments->size() == 3u) || - (isTextureGatherOffset && arguments->size() == 4u)) - { - componentNode = arguments->back(); - } - break; - case EbtSamplerCube: - case EbtISamplerCube: - case EbtUSamplerCube: - ASSERT(!isTextureGatherOffset); - if (arguments->size() == 3u) - { - componentNode = arguments->back(); - } - break; - case EbtSampler2DShadow: - case EbtSampler2DArrayShadow: - case EbtSamplerCubeShadow: - break; - default: - UNREACHABLE(); - break; - } - if (componentNode) - { - const TIntermConstantUnion *componentConstantUnion = - componentNode->getAsConstantUnion(); - if (componentNode->getAsTyped()->getQualifier() != EvqConst || !componentConstantUnion) - { - error(functionCall->getLine(), "Texture component must be a constant expression", - name.c_str()); - } - else - { - int component = componentConstantUnion->getIConst(0); - if (component < 0 || component > 3) - { - error(functionCall->getLine(), "Component must be in the range [0;3]", - name.c_str()); - } - } - } - } -} - -void TParseContext::checkTextureOffsetConst(TIntermAggregate *functionCall) -{ - ASSERT(functionCall->getOp() == EOpCallBuiltInFunction); - const TString &name = functionCall->getFunctionSymbolInfo()->getName(); - TIntermNode *offset = nullptr; - TIntermSequence *arguments = functionCall->getSequence(); - bool useTextureGatherOffsetConstraints = false; - if (name == "texelFetchOffset" || name == "textureLodOffset" || - name == "textureProjLodOffset" || name == "textureGradOffset" || - name == "textureProjGradOffset") - { - offset = arguments->back(); - } - else if (name == "textureOffset" || name == "textureProjOffset") - { - // A bias parameter might follow the offset parameter. - ASSERT(arguments->size() >= 3); - offset = (*arguments)[2]; - } - else if (name == "textureGatherOffset") - { - ASSERT(arguments->size() >= 3u); - const TIntermTyped *sampler = arguments->front()->getAsTyped(); - ASSERT(sampler != nullptr); - switch (sampler->getBasicType()) - { - case EbtSampler2D: - case EbtISampler2D: - case EbtUSampler2D: - case EbtSampler2DArray: - case EbtISampler2DArray: - case EbtUSampler2DArray: - offset = (*arguments)[2]; - break; - case EbtSampler2DShadow: - case EbtSampler2DArrayShadow: - offset = (*arguments)[3]; - break; - default: - UNREACHABLE(); - break; - } - useTextureGatherOffsetConstraints = true; - } - if (offset != nullptr) - { - TIntermConstantUnion *offsetConstantUnion = offset->getAsConstantUnion(); - if (offset->getAsTyped()->getQualifier() != EvqConst || !offsetConstantUnion) - { - error(functionCall->getLine(), "Texture offset must be a constant expression", - name.c_str()); - } - else - { - ASSERT(offsetConstantUnion->getBasicType() == EbtInt); - size_t size = offsetConstantUnion->getType().getObjectSize(); - const TConstantUnion *values = offsetConstantUnion->getUnionArrayPointer(); - int minOffsetValue = useTextureGatherOffsetConstraints ? mMinProgramTextureGatherOffset - : mMinProgramTexelOffset; - int maxOffsetValue = useTextureGatherOffsetConstraints ? mMaxProgramTextureGatherOffset - : mMaxProgramTexelOffset; - for (size_t i = 0u; i < size; ++i) - { - int offsetValue = values[i].getIConst(); - if (offsetValue > maxOffsetValue || offsetValue < minOffsetValue) - { - std::stringstream tokenStream; - tokenStream << offsetValue; - std::string token = tokenStream.str(); - error(offset->getLine(), "Texture offset value out of valid range", - token.c_str()); - } - } - } - } -} - -void TParseContext::checkAtomicMemoryBuiltinFunctions(TIntermAggregate *functionCall) -{ - const TString &name = functionCall->getFunctionSymbolInfo()->getName(); - if (IsAtomicBuiltin(name)) - { - TIntermSequence *arguments = functionCall->getSequence(); - TIntermTyped *memNode = (*arguments)[0]->getAsTyped(); - - if (IsBufferOrSharedVariable(memNode)) - { - return; - } - - while (memNode->getAsBinaryNode()) - { - memNode = memNode->getAsBinaryNode()->getLeft(); - if (IsBufferOrSharedVariable(memNode)) - { - return; - } - } - - error(memNode->getLine(), - "The value passed to the mem argument of an atomic memory function does not " - "correspond to a buffer or shared variable.", - functionCall->getFunctionSymbolInfo()->getName().c_str()); - } -} - -// GLSL ES 3.10 Revision 4, 4.9 Memory Access Qualifiers -void TParseContext::checkImageMemoryAccessForBuiltinFunctions(TIntermAggregate *functionCall) -{ - ASSERT(functionCall->getOp() == EOpCallBuiltInFunction); - const TString &name = functionCall->getFunctionSymbolInfo()->getName(); - - if (name.compare(0, 5, "image") == 0) - { - TIntermSequence *arguments = functionCall->getSequence(); - TIntermTyped *imageNode = (*arguments)[0]->getAsTyped(); - - const TMemoryQualifier &memoryQualifier = imageNode->getMemoryQualifier(); - - if (name.compare(5, 5, "Store") == 0) - { - if (memoryQualifier.readonly) - { - error(imageNode->getLine(), - "'imageStore' cannot be used with images qualified as 'readonly'", - GetImageArgumentToken(imageNode)); - } - } - else if (name.compare(5, 4, "Load") == 0) - { - if (memoryQualifier.writeonly) - { - error(imageNode->getLine(), - "'imageLoad' cannot be used with images qualified as 'writeonly'", - GetImageArgumentToken(imageNode)); - } - } - } -} - -// GLSL ES 3.10 Revision 4, 13.51 Matching of Memory Qualifiers in Function Parameters -void TParseContext::checkImageMemoryAccessForUserDefinedFunctions( - const TFunction *functionDefinition, - const TIntermAggregate *functionCall) -{ - ASSERT(functionCall->getOp() == EOpCallFunctionInAST); - - const TIntermSequence &arguments = *functionCall->getSequence(); - - ASSERT(functionDefinition->getParamCount() == arguments.size()); - - for (size_t i = 0; i < arguments.size(); ++i) - { - TIntermTyped *typedArgument = arguments[i]->getAsTyped(); - const TType &functionArgumentType = typedArgument->getType(); - const TType &functionParameterType = *functionDefinition->getParam(i).type; - ASSERT(functionArgumentType.getBasicType() == functionParameterType.getBasicType()); - - if (IsImage(functionArgumentType.getBasicType())) - { - const TMemoryQualifier &functionArgumentMemoryQualifier = - functionArgumentType.getMemoryQualifier(); - const TMemoryQualifier &functionParameterMemoryQualifier = - functionParameterType.getMemoryQualifier(); - if (functionArgumentMemoryQualifier.readonly && - !functionParameterMemoryQualifier.readonly) - { - error(functionCall->getLine(), - "Function call discards the 'readonly' qualifier from image", - GetImageArgumentToken(typedArgument)); - } - - if (functionArgumentMemoryQualifier.writeonly && - !functionParameterMemoryQualifier.writeonly) - { - error(functionCall->getLine(), - "Function call discards the 'writeonly' qualifier from image", - GetImageArgumentToken(typedArgument)); - } - - if (functionArgumentMemoryQualifier.coherent && - !functionParameterMemoryQualifier.coherent) - { - error(functionCall->getLine(), - "Function call discards the 'coherent' qualifier from image", - GetImageArgumentToken(typedArgument)); - } - - if (functionArgumentMemoryQualifier.volatileQualifier && - !functionParameterMemoryQualifier.volatileQualifier) - { - error(functionCall->getLine(), - "Function call discards the 'volatile' qualifier from image", - GetImageArgumentToken(typedArgument)); - } - } - } -} - -TIntermSequence *TParseContext::createEmptyArgumentsList() -{ - return new TIntermSequence(); -} - -TIntermTyped *TParseContext::addFunctionCallOrMethod(TFunction *fnCall, - TIntermSequence *arguments, - TIntermNode *thisNode, - const TSourceLoc &loc) -{ - if (thisNode != nullptr) - { - return addMethod(fnCall, arguments, thisNode, loc); - } - - TOperator op = fnCall->getBuiltInOp(); - if (op == EOpConstruct) - { - return addConstructor(arguments, fnCall->getReturnType(), loc); - } - else - { - ASSERT(op == EOpNull); - return addNonConstructorFunctionCall(fnCall, arguments, loc); - } -} - -TIntermTyped *TParseContext::addMethod(TFunction *fnCall, - TIntermSequence *arguments, - TIntermNode *thisNode, - const TSourceLoc &loc) -{ - TIntermTyped *typedThis = thisNode->getAsTyped(); - // It's possible for the name pointer in the TFunction to be null in case it gets parsed as - // a constructor. But such a TFunction can't reach here, since the lexer goes into FIELDS - // mode after a dot, which makes type identifiers to be parsed as FIELD_SELECTION instead. - // So accessing fnCall->getName() below is safe. - if (fnCall->getName() != "length") - { - error(loc, "invalid method", fnCall->getName().c_str()); - } - else if (!arguments->empty()) - { - error(loc, "method takes no parameters", "length"); - } - else if (typedThis == nullptr || !typedThis->isArray()) - { - error(loc, "length can only be called on arrays", "length"); - } - else if (typedThis->getQualifier() == EvqPerVertexIn && - mGeometryShaderInputPrimitiveType == EptUndefined) - { - ASSERT(mShaderType == GL_GEOMETRY_SHADER_OES); - error(loc, "missing input primitive declaration before calling length on gl_in", "length"); - } - else - { - TIntermUnary *node = new TIntermUnary(EOpArrayLength, typedThis); - node->setLine(loc); - return node->fold(mDiagnostics); - } - return CreateZeroNode(TType(EbtInt, EbpUndefined, EvqConst)); -} - -TIntermTyped *TParseContext::addNonConstructorFunctionCall(TFunction *fnCall, - TIntermSequence *arguments, - const TSourceLoc &loc) -{ - // First find by unmangled name to check whether the function name has been - // hidden by a variable name or struct typename. - // If a function is found, check for one with a matching argument list. - bool builtIn; - const TSymbol *symbol = symbolTable.find(fnCall->getName(), mShaderVersion, &builtIn); - if (symbol != nullptr && !symbol->isFunction()) - { - error(loc, "function name expected", fnCall->getName().c_str()); - } - else - { - symbol = symbolTable.find(TFunction::GetMangledNameFromCall(fnCall->getName(), *arguments), - mShaderVersion, &builtIn); - if (symbol == nullptr) - { - error(loc, "no matching overloaded function found", fnCall->getName().c_str()); - } - else - { - const TFunction *fnCandidate = static_cast(symbol); - // - // A declared function. - // - if (builtIn && fnCandidate->getExtension() != TExtension::UNDEFINED) - { - checkCanUseExtension(loc, fnCandidate->getExtension()); - } - TOperator op = fnCandidate->getBuiltInOp(); - if (builtIn && op != EOpNull) - { - // A function call mapped to a built-in operation. - if (fnCandidate->getParamCount() == 1) - { - // Treat it like a built-in unary operator. - TIntermNode *unaryParamNode = arguments->front(); - TIntermTyped *callNode = createUnaryMath(op, unaryParamNode->getAsTyped(), loc); - ASSERT(callNode != nullptr); - return callNode; - } - else - { - TIntermAggregate *callNode = - TIntermAggregate::Create(fnCandidate->getReturnType(), op, arguments); - callNode->setLine(loc); - - // Some built-in functions have out parameters too. - functionCallRValueLValueErrorCheck(fnCandidate, callNode); - - if (TIntermAggregate::CanFoldAggregateBuiltInOp(callNode->getOp())) - { - // See if we can constant fold a built-in. Note that this may be possible - // even if it is not const-qualified. - return callNode->fold(mDiagnostics); - } - else - { - return callNode; - } - } - } - else - { - // This is a real function call - TIntermAggregate *callNode = nullptr; - - // If builtIn == false, the function is user defined - could be an overloaded - // built-in as well. - // if builtIn == true, it's a builtIn function with no op associated with it. - // This needs to happen after the function info including name is set. - if (builtIn) - { - callNode = TIntermAggregate::CreateBuiltInFunctionCall(*fnCandidate, arguments); - checkTextureOffsetConst(callNode); - checkTextureGather(callNode); - checkImageMemoryAccessForBuiltinFunctions(callNode); - checkAtomicMemoryBuiltinFunctions(callNode); - } - else - { - callNode = TIntermAggregate::CreateFunctionCall(*fnCandidate, arguments); - checkImageMemoryAccessForUserDefinedFunctions(fnCandidate, callNode); - } - - functionCallRValueLValueErrorCheck(fnCandidate, callNode); - - callNode->setLine(loc); - - return callNode; - } - } - } - - // Error message was already written. Put on a dummy node for error recovery. - return CreateZeroNode(TType(EbtFloat, EbpMedium, EvqConst)); -} - -TIntermTyped *TParseContext::addTernarySelection(TIntermTyped *cond, - TIntermTyped *trueExpression, - TIntermTyped *falseExpression, - const TSourceLoc &loc) -{ - if (!checkIsScalarBool(loc, cond)) - { - return falseExpression; - } - - if (trueExpression->getType() != falseExpression->getType()) - { - std::stringstream reasonStream; - reasonStream << "mismatching ternary operator operand types '" - << trueExpression->getCompleteString() << " and '" - << falseExpression->getCompleteString() << "'"; - std::string reason = reasonStream.str(); - error(loc, reason.c_str(), "?:"); - return falseExpression; - } - if (IsOpaqueType(trueExpression->getBasicType())) - { - // ESSL 1.00 section 4.1.7 - // ESSL 3.00.6 section 4.1.7 - // Opaque/sampler types are not allowed in most types of expressions, including ternary. - // Note that structs containing opaque types don't need to be checked as structs are - // forbidden below. - error(loc, "ternary operator is not allowed for opaque types", "?:"); - return falseExpression; - } - - if (cond->getMemoryQualifier().writeonly || trueExpression->getMemoryQualifier().writeonly || - falseExpression->getMemoryQualifier().writeonly) - { - error(loc, "ternary operator is not allowed for variables with writeonly", "?:"); - return falseExpression; - } - - // ESSL 1.00.17 sections 5.2 and 5.7: - // Ternary operator is not among the operators allowed for structures/arrays. - // ESSL 3.00.6 section 5.7: - // Ternary operator support is optional for arrays. No certainty that it works across all - // devices with struct either, so we err on the side of caution here. TODO (oetuaho@nvidia.com): - // Would be nice to make the spec and implementation agree completely here. - if (trueExpression->isArray() || trueExpression->getBasicType() == EbtStruct) - { - error(loc, "ternary operator is not allowed for structures or arrays", "?:"); - return falseExpression; - } - if (trueExpression->getBasicType() == EbtInterfaceBlock) - { - error(loc, "ternary operator is not allowed for interface blocks", "?:"); - return falseExpression; - } - - // WebGL2 section 5.26, the following results in an error: - // "Ternary operator applied to void, arrays, or structs containing arrays" - if (mShaderSpec == SH_WEBGL2_SPEC && trueExpression->getBasicType() == EbtVoid) - { - error(loc, "ternary operator is not allowed for void", "?:"); - return falseExpression; - } - - // Note that the node resulting from here can be a constant union without being qualified as - // constant. - TIntermTernary *node = new TIntermTernary(cond, trueExpression, falseExpression); - node->setLine(loc); - - return node->fold(); -} - -// -// Parse an array of strings using yyparse. -// -// Returns 0 for success. -// -int PaParseStrings(size_t count, - const char *const string[], - const int length[], - TParseContext *context) -{ - if ((count == 0) || (string == nullptr)) - return 1; - - if (glslang_initialize(context)) - return 1; - - int error = glslang_scan(count, string, length, context); - if (!error) - error = glslang_parse(context); - - glslang_finalize(context); - - return (error == 0) && (context->numErrors() == 0) ? 0 : 1; -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/ParseContext.h b/src/3rdparty/angle/src/compiler/translator/ParseContext.h deleted file mode 100644 index 8bfdbd5e3f..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/ParseContext.h +++ /dev/null @@ -1,657 +0,0 @@ -// -// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -#ifndef COMPILER_TRANSLATOR_PARSECONTEXT_H_ -#define COMPILER_TRANSLATOR_PARSECONTEXT_H_ - -#include "compiler/translator/Compiler.h" -#include "compiler/translator/Diagnostics.h" -#include "compiler/translator/DirectiveHandler.h" -#include "compiler/translator/SymbolTable.h" -#include "compiler/translator/QualifierTypes.h" -#include "compiler/preprocessor/Preprocessor.h" - -namespace sh -{ - -struct TMatrixFields -{ - bool wholeRow; - bool wholeCol; - int row; - int col; -}; - -// -// The following are extra variables needed during parsing, grouped together so -// they can be passed to the parser without needing a global. -// -class TParseContext : angle::NonCopyable -{ - public: - TParseContext(TSymbolTable &symt, - TExtensionBehavior &ext, - sh::GLenum type, - ShShaderSpec spec, - ShCompileOptions options, - bool checksPrecErrors, - TDiagnostics *diagnostics, - const ShBuiltInResources &resources); - ~TParseContext(); - - const pp::Preprocessor &getPreprocessor() const { return mPreprocessor; } - pp::Preprocessor &getPreprocessor() { return mPreprocessor; } - void *getScanner() const { return mScanner; } - void setScanner(void *scanner) { mScanner = scanner; } - int getShaderVersion() const { return mShaderVersion; } - sh::GLenum getShaderType() const { return mShaderType; } - ShShaderSpec getShaderSpec() const { return mShaderSpec; } - int numErrors() const { return mDiagnostics->numErrors(); } - void error(const TSourceLoc &loc, const char *reason, const char *token); - void warning(const TSourceLoc &loc, const char *reason, const char *token); - - // If isError is false, a warning will be reported instead. - void outOfRangeError(bool isError, - const TSourceLoc &loc, - const char *reason, - const char *token); - - TIntermBlock *getTreeRoot() const { return mTreeRoot; } - void setTreeRoot(TIntermBlock *treeRoot) { mTreeRoot = treeRoot; } - - bool getFragmentPrecisionHigh() const - { - return mFragmentPrecisionHighOnESSL1 || mShaderVersion >= 300; - } - void setFragmentPrecisionHighOnESSL1(bool fragmentPrecisionHigh) - { - mFragmentPrecisionHighOnESSL1 = fragmentPrecisionHigh; - } - - void setLoopNestingLevel(int loopNestintLevel) { mLoopNestingLevel = loopNestintLevel; } - - void incrLoopNestingLevel() { ++mLoopNestingLevel; } - void decrLoopNestingLevel() { --mLoopNestingLevel; } - - void incrSwitchNestingLevel() { ++mSwitchNestingLevel; } - void decrSwitchNestingLevel() { --mSwitchNestingLevel; } - - bool isComputeShaderLocalSizeDeclared() const { return mComputeShaderLocalSizeDeclared; } - sh::WorkGroupSize getComputeShaderLocalSize() const; - - int getNumViews() const { return mNumViews; } - - void enterFunctionDeclaration() { mDeclaringFunction = true; } - - void exitFunctionDeclaration() { mDeclaringFunction = false; } - - bool declaringFunction() const { return mDeclaringFunction; } - - TIntermConstantUnion *addScalarLiteral(const TConstantUnion *constantUnion, - const TSourceLoc &line); - - // This method is guaranteed to succeed, even if no variable with 'name' exists. - const TVariable *getNamedVariable(const TSourceLoc &location, - const TString *name, - const TSymbol *symbol); - TIntermTyped *parseVariableIdentifier(const TSourceLoc &location, - const TString *name, - const TSymbol *symbol); - - // Look at a '.' field selector string and change it into offsets for a vector. - bool parseVectorFields(const TSourceLoc &line, - const TString &compString, - int vecSize, - TVector *fieldOffsets); - - void assignError(const TSourceLoc &line, const char *op, TString left, TString right); - void unaryOpError(const TSourceLoc &line, const char *op, TString operand); - void binaryOpError(const TSourceLoc &line, const char *op, TString left, TString right); - - // Check functions - the ones that return bool return false if an error was generated. - - bool checkIsNotReserved(const TSourceLoc &line, const TString &identifier); - void checkPrecisionSpecified(const TSourceLoc &line, TPrecision precision, TBasicType type); - bool checkCanBeLValue(const TSourceLoc &line, const char *op, TIntermTyped *node); - void checkIsConst(TIntermTyped *node); - void checkIsScalarInteger(TIntermTyped *node, const char *token); - bool checkIsAtGlobalLevel(const TSourceLoc &line, const char *token); - bool checkConstructorArguments(const TSourceLoc &line, - const TIntermSequence *arguments, - const TType &type); - - // Returns a sanitized array size to use (the size is at least 1). - unsigned int checkIsValidArraySize(const TSourceLoc &line, TIntermTyped *expr); - bool checkIsValidQualifierForArray(const TSourceLoc &line, const TPublicType &elementQualifier); - bool checkArrayElementIsNotArray(const TSourceLoc &line, const TPublicType &elementType); - bool checkIsNonVoid(const TSourceLoc &line, const TString &identifier, const TBasicType &type); - bool checkIsScalarBool(const TSourceLoc &line, const TIntermTyped *type); - void checkIsScalarBool(const TSourceLoc &line, const TPublicType &pType); - bool checkIsNotOpaqueType(const TSourceLoc &line, - const TTypeSpecifierNonArray &pType, - const char *reason); - void checkDeclaratorLocationIsNotSpecified(const TSourceLoc &line, const TPublicType &pType); - void checkLocationIsNotSpecified(const TSourceLoc &location, - const TLayoutQualifier &layoutQualifier); - void checkStd430IsForShaderStorageBlock(const TSourceLoc &location, - const TLayoutBlockStorage &blockStorage, - const TQualifier &qualifier); - void checkIsParameterQualifierValid(const TSourceLoc &line, - const TTypeQualifierBuilder &typeQualifierBuilder, - TType *type); - - // Check if at least one of the specified extensions can be used, and generate error/warning as - // appropriate according to the spec. - // This function is only needed for a few different small constant sizes of extension array, and - // we want to avoid unnecessary dynamic allocations. That's why checkCanUseOneOfExtensions is a - // template function rather than one taking a vector. - template - bool checkCanUseOneOfExtensions(const TSourceLoc &line, - const std::array &extensions); - bool checkCanUseExtension(const TSourceLoc &line, TExtension extension); - - // Done for all declarations, whether empty or not. - void declarationQualifierErrorCheck(const sh::TQualifier qualifier, - const sh::TLayoutQualifier &layoutQualifier, - const TSourceLoc &location); - // Done for the first non-empty declarator in a declaration. - void nonEmptyDeclarationErrorCheck(const TPublicType &publicType, - const TSourceLoc &identifierLocation); - // Done only for empty declarations. - void emptyDeclarationErrorCheck(const TType &type, const TSourceLoc &location); - - void checkLayoutQualifierSupported(const TSourceLoc &location, - const TString &layoutQualifierName, - int versionRequired); - bool checkWorkGroupSizeIsNotSpecified(const TSourceLoc &location, - const TLayoutQualifier &layoutQualifier); - void functionCallRValueLValueErrorCheck(const TFunction *fnCandidate, TIntermAggregate *fnCall); - void checkInvariantVariableQualifier(bool invariant, - const TQualifier qualifier, - const TSourceLoc &invariantLocation); - void checkInputOutputTypeIsValidES3(const TQualifier qualifier, - const TPublicType &type, - const TSourceLoc &qualifierLocation); - void checkLocalVariableConstStorageQualifier(const TQualifierWrapperBase &qualifier); - const TPragma &pragma() const { return mDirectiveHandler.pragma(); } - const TExtensionBehavior &extensionBehavior() const - { - return mDirectiveHandler.extensionBehavior(); - } - - bool isExtensionEnabled(TExtension extension) const; - void handleExtensionDirective(const TSourceLoc &loc, const char *extName, const char *behavior); - void handlePragmaDirective(const TSourceLoc &loc, - const char *name, - const char *value, - bool stdgl); - - // Returns true on success. *initNode may still be nullptr on success in case the initialization - // is not needed in the AST. - bool executeInitializer(const TSourceLoc &line, - const TString &identifier, - TType type, - TIntermTyped *initializer, - TIntermBinary **initNode); - TIntermNode *addConditionInitializer(const TPublicType &pType, - const TString &identifier, - TIntermTyped *initializer, - const TSourceLoc &loc); - TIntermNode *addLoop(TLoopType type, - TIntermNode *init, - TIntermNode *cond, - TIntermTyped *expr, - TIntermNode *body, - const TSourceLoc &loc); - - // For "if" test nodes. There are three children: a condition, a true path, and a false path. - // The two paths are in TIntermNodePair code. - TIntermNode *addIfElse(TIntermTyped *cond, TIntermNodePair code, const TSourceLoc &loc); - - void addFullySpecifiedType(TPublicType *typeSpecifier); - TPublicType addFullySpecifiedType(const TTypeQualifierBuilder &typeQualifierBuilder, - const TPublicType &typeSpecifier); - - TIntermDeclaration *parseSingleDeclaration(TPublicType &publicType, - const TSourceLoc &identifierOrTypeLocation, - const TString &identifier); - TIntermDeclaration *parseSingleArrayDeclaration(TPublicType &elementType, - const TSourceLoc &identifierLocation, - const TString &identifier, - const TSourceLoc &indexLocation, - const TVector &arraySizes); - TIntermDeclaration *parseSingleInitDeclaration(const TPublicType &publicType, - const TSourceLoc &identifierLocation, - const TString &identifier, - const TSourceLoc &initLocation, - TIntermTyped *initializer); - - // Parse a declaration like "type a[n] = initializer" - // Note that this does not apply to declarations like "type[n] a = initializer" - TIntermDeclaration *parseSingleArrayInitDeclaration(TPublicType &elementType, - const TSourceLoc &identifierLocation, - const TString &identifier, - const TSourceLoc &indexLocation, - const TVector &arraySizes, - const TSourceLoc &initLocation, - TIntermTyped *initializer); - - TIntermInvariantDeclaration *parseInvariantDeclaration( - const TTypeQualifierBuilder &typeQualifierBuilder, - const TSourceLoc &identifierLoc, - const TString *identifier, - const TSymbol *symbol); - - void parseDeclarator(TPublicType &publicType, - const TSourceLoc &identifierLocation, - const TString &identifier, - TIntermDeclaration *declarationOut); - void parseArrayDeclarator(TPublicType &elementType, - const TSourceLoc &identifierLocation, - const TString &identifier, - const TSourceLoc &arrayLocation, - const TVector &arraySizes, - TIntermDeclaration *declarationOut); - void parseInitDeclarator(const TPublicType &publicType, - const TSourceLoc &identifierLocation, - const TString &identifier, - const TSourceLoc &initLocation, - TIntermTyped *initializer, - TIntermDeclaration *declarationOut); - - // Parse a declarator like "a[n] = initializer" - void parseArrayInitDeclarator(const TPublicType &elementType, - const TSourceLoc &identifierLocation, - const TString &identifier, - const TSourceLoc &indexLocation, - const TVector &arraySizes, - const TSourceLoc &initLocation, - TIntermTyped *initializer, - TIntermDeclaration *declarationOut); - - TIntermNode *addEmptyStatement(const TSourceLoc &location); - - void parseDefaultPrecisionQualifier(const TPrecision precision, - const TPublicType &type, - const TSourceLoc &loc); - void parseGlobalLayoutQualifier(const TTypeQualifierBuilder &typeQualifierBuilder); - - TIntermFunctionPrototype *addFunctionPrototypeDeclaration(const TFunction &parsedFunction, - const TSourceLoc &location); - TIntermFunctionDefinition *addFunctionDefinition(TIntermFunctionPrototype *functionPrototype, - TIntermBlock *functionBody, - const TSourceLoc &location); - void parseFunctionDefinitionHeader(const TSourceLoc &location, - TFunction **function, - TIntermFunctionPrototype **prototypeOut); - TFunction *parseFunctionDeclarator(const TSourceLoc &location, TFunction *function); - TFunction *parseFunctionHeader(const TPublicType &type, - const TString *name, - const TSourceLoc &location); - TFunction *addNonConstructorFunc(const TString *name, const TSourceLoc &loc); - TFunction *addConstructorFunc(const TPublicType &publicType); - TParameter parseParameterDeclarator(const TPublicType &publicType, - const TString *name, - const TSourceLoc &nameLoc); - - TParameter parseParameterArrayDeclarator(const TString *name, - const TSourceLoc &nameLoc, - const TVector &arraySizes, - const TSourceLoc &arrayLoc, - TPublicType *elementType); - - TIntermTyped *addIndexExpression(TIntermTyped *baseExpression, - const TSourceLoc &location, - TIntermTyped *indexExpression); - TIntermTyped *addFieldSelectionExpression(TIntermTyped *baseExpression, - const TSourceLoc &dotLocation, - const TString &fieldString, - const TSourceLoc &fieldLocation); - - // Parse declarator for a single field - TField *parseStructDeclarator(TString *identifier, const TSourceLoc &loc); - TField *parseStructArrayDeclarator(TString *identifier, - const TSourceLoc &loc, - const TVector &arraySizes, - const TSourceLoc &arraySizeLoc); - - void checkDoesNotHaveDuplicateFieldName(const TFieldList::const_iterator begin, - const TFieldList::const_iterator end, - const TString &name, - const TSourceLoc &location); - TFieldList *addStructFieldList(TFieldList *fields, const TSourceLoc &location); - TFieldList *combineStructFieldLists(TFieldList *processedFields, - const TFieldList *newlyAddedFields, - const TSourceLoc &location); - TFieldList *addStructDeclaratorListWithQualifiers( - const TTypeQualifierBuilder &typeQualifierBuilder, - TPublicType *typeSpecifier, - TFieldList *fieldList); - TFieldList *addStructDeclaratorList(const TPublicType &typeSpecifier, TFieldList *fieldList); - TTypeSpecifierNonArray addStructure(const TSourceLoc &structLine, - const TSourceLoc &nameLine, - const TString *structName, - TFieldList *fieldList); - - TIntermDeclaration *addInterfaceBlock(const TTypeQualifierBuilder &typeQualifierBuilder, - const TSourceLoc &nameLine, - const TString &blockName, - TFieldList *fieldList, - const TString *instanceName, - const TSourceLoc &instanceLine, - TIntermTyped *arrayIndex, - const TSourceLoc &arrayIndexLine); - - void parseLocalSize(const TString &qualifierType, - const TSourceLoc &qualifierTypeLine, - int intValue, - const TSourceLoc &intValueLine, - const std::string &intValueString, - size_t index, - sh::WorkGroupSize *localSize); - void parseNumViews(int intValue, - const TSourceLoc &intValueLine, - const std::string &intValueString, - int *numViews); - void parseInvocations(int intValue, - const TSourceLoc &intValueLine, - const std::string &intValueString, - int *numInvocations); - void parseMaxVertices(int intValue, - const TSourceLoc &intValueLine, - const std::string &intValueString, - int *numMaxVertices); - TLayoutQualifier parseLayoutQualifier(const TString &qualifierType, - const TSourceLoc &qualifierTypeLine); - TLayoutQualifier parseLayoutQualifier(const TString &qualifierType, - const TSourceLoc &qualifierTypeLine, - int intValue, - const TSourceLoc &intValueLine); - TTypeQualifierBuilder *createTypeQualifierBuilder(const TSourceLoc &loc); - TStorageQualifierWrapper *parseGlobalStorageQualifier(TQualifier qualifier, - const TSourceLoc &loc); - TStorageQualifierWrapper *parseVaryingQualifier(const TSourceLoc &loc); - TStorageQualifierWrapper *parseInQualifier(const TSourceLoc &loc); - TStorageQualifierWrapper *parseOutQualifier(const TSourceLoc &loc); - TStorageQualifierWrapper *parseInOutQualifier(const TSourceLoc &loc); - TLayoutQualifier joinLayoutQualifiers(TLayoutQualifier leftQualifier, - TLayoutQualifier rightQualifier, - const TSourceLoc &rightQualifierLocation); - - // Performs an error check for embedded struct declarations. - void enterStructDeclaration(const TSourceLoc &line, const TString &identifier); - void exitStructDeclaration(); - - void checkIsBelowStructNestingLimit(const TSourceLoc &line, const TField &field); - - TIntermSwitch *addSwitch(TIntermTyped *init, - TIntermBlock *statementList, - const TSourceLoc &loc); - TIntermCase *addCase(TIntermTyped *condition, const TSourceLoc &loc); - TIntermCase *addDefault(const TSourceLoc &loc); - - TIntermTyped *addUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &loc); - TIntermTyped *addUnaryMathLValue(TOperator op, TIntermTyped *child, const TSourceLoc &loc); - TIntermTyped *addBinaryMath(TOperator op, - TIntermTyped *left, - TIntermTyped *right, - const TSourceLoc &loc); - TIntermTyped *addBinaryMathBooleanResult(TOperator op, - TIntermTyped *left, - TIntermTyped *right, - const TSourceLoc &loc); - TIntermTyped *addAssign(TOperator op, - TIntermTyped *left, - TIntermTyped *right, - const TSourceLoc &loc); - - TIntermTyped *addComma(TIntermTyped *left, TIntermTyped *right, const TSourceLoc &loc); - - TIntermBranch *addBranch(TOperator op, const TSourceLoc &loc); - TIntermBranch *addBranch(TOperator op, TIntermTyped *expression, const TSourceLoc &loc); - - void checkTextureGather(TIntermAggregate *functionCall); - void checkTextureOffsetConst(TIntermAggregate *functionCall); - void checkImageMemoryAccessForBuiltinFunctions(TIntermAggregate *functionCall); - void checkImageMemoryAccessForUserDefinedFunctions(const TFunction *functionDefinition, - const TIntermAggregate *functionCall); - void checkAtomicMemoryBuiltinFunctions(TIntermAggregate *functionCall); - TIntermSequence *createEmptyArgumentsList(); - - // fnCall is only storing the built-in op, and function name or constructor type. arguments - // has the arguments. - TIntermTyped *addFunctionCallOrMethod(TFunction *fnCall, - TIntermSequence *arguments, - TIntermNode *thisNode, - const TSourceLoc &loc); - - TIntermTyped *addTernarySelection(TIntermTyped *cond, - TIntermTyped *trueExpression, - TIntermTyped *falseExpression, - const TSourceLoc &line); - - int getGeometryShaderMaxVertices() const { return mGeometryShaderMaxVertices; } - int getGeometryShaderInvocations() const - { - return (mGeometryShaderInvocations > 0) ? mGeometryShaderInvocations : 1; - } - TLayoutPrimitiveType getGeometryShaderInputPrimitiveType() const - { - return mGeometryShaderInputPrimitiveType; - } - TLayoutPrimitiveType getGeometryShaderOutputPrimitiveType() const - { - return mGeometryShaderOutputPrimitiveType; - } - - // TODO(jmadill): make this private - TSymbolTable &symbolTable; // symbol table that goes with the language currently being parsed - - private: - class AtomicCounterBindingState; - constexpr static size_t kAtomicCounterSize = 4; - // UNIFORM_ARRAY_STRIDE for atomic counter arrays is an implementation-dependent value which - // can be queried after a program is linked according to ES 3.10 section 7.7.1. This is - // controversial with the offset inheritance as described in ESSL 3.10 section 4.4.6. Currently - // we treat it as always 4 in favour of the original interpretation in - // "ARB_shader_atomic_counters". - // TODO(jie.a.chen@intel.com): Double check this once the spec vagueness is resolved. - // Note that there may be tests in AtomicCounter_test that will need to be updated as well. - constexpr static size_t kAtomicCounterArrayStride = 4; - - // Returns a clamped index. If it prints out an error message, the token is "[]". - int checkIndexLessThan(bool outOfRangeIndexIsError, - const TSourceLoc &location, - int index, - int arraySize, - const char *reason); - - bool declareVariable(const TSourceLoc &line, - const TString &identifier, - const TType &type, - TVariable **variable); - - void checkCanBeDeclaredWithoutInitializer(const TSourceLoc &line, - const TString &identifier, - TType *type); - - TParameter parseParameterDeclarator(TType *type, - const TString *name, - const TSourceLoc &nameLoc); - - bool checkIsValidTypeAndQualifierForArray(const TSourceLoc &indexLocation, - const TPublicType &elementType); - // Done for all atomic counter declarations, whether empty or not. - void atomicCounterQualifierErrorCheck(const TPublicType &publicType, - const TSourceLoc &location); - - // Assumes that multiplication op has already been set based on the types. - bool isMultiplicationTypeCombinationValid(TOperator op, const TType &left, const TType &right); - - void checkOutParameterIsNotOpaqueType(const TSourceLoc &line, - TQualifier qualifier, - const TType &type); - - void checkInternalFormatIsNotSpecified(const TSourceLoc &location, - TLayoutImageInternalFormat internalFormat); - void checkMemoryQualifierIsNotSpecified(const TMemoryQualifier &memoryQualifier, - const TSourceLoc &location); - void checkAtomicCounterOffsetDoesNotOverlap(bool forceAppend, - const TSourceLoc &loc, - TType *type); - void checkBindingIsValid(const TSourceLoc &identifierLocation, const TType &type); - void checkBindingIsNotSpecified(const TSourceLoc &location, int binding); - void checkOffsetIsNotSpecified(const TSourceLoc &location, int offset); - void checkImageBindingIsValid(const TSourceLoc &location, - int binding, - int arrayTotalElementCount); - void checkSamplerBindingIsValid(const TSourceLoc &location, - int binding, - int arrayTotalElementCount); - void checkBlockBindingIsValid(const TSourceLoc &location, - const TQualifier &qualifier, - int binding, - int arraySize); - void checkAtomicCounterBindingIsValid(const TSourceLoc &location, int binding); - - void checkUniformLocationInRange(const TSourceLoc &location, - int objectLocationCount, - const TLayoutQualifier &layoutQualifier); - - void checkYuvIsNotSpecified(const TSourceLoc &location, bool yuv); - - bool checkUnsizedArrayConstructorArgumentDimensionality(TIntermSequence *arguments, - TType type, - const TSourceLoc &line); - - // Will set the size of the outermost array according to geometry shader input layout. - void checkGeometryShaderInputAndSetArraySize(const TSourceLoc &location, - const char *token, - TType *type); - - // Will size any unsized array type so unsized arrays won't need to be taken into account - // further along the line in parsing. - void checkIsNotUnsizedArray(const TSourceLoc &line, - const char *errorMessage, - const char *token, - TType *arrayType); - - TIntermTyped *addBinaryMathInternal(TOperator op, - TIntermTyped *left, - TIntermTyped *right, - const TSourceLoc &loc); - TIntermBinary *createAssign(TOperator op, - TIntermTyped *left, - TIntermTyped *right, - const TSourceLoc &loc); - TIntermTyped *createUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &loc); - - TIntermTyped *addMethod(TFunction *fnCall, - TIntermSequence *arguments, - TIntermNode *thisNode, - const TSourceLoc &loc); - TIntermTyped *addConstructor(TIntermSequence *arguments, - TType type, - const TSourceLoc &line); - TIntermTyped *addNonConstructorFunctionCall(TFunction *fnCall, - TIntermSequence *arguments, - const TSourceLoc &loc); - - // Return true if the checks pass - bool binaryOpCommonCheck(TOperator op, - TIntermTyped *left, - TIntermTyped *right, - const TSourceLoc &loc); - - TIntermFunctionPrototype *createPrototypeNodeFromFunction(const TFunction &function, - const TSourceLoc &location, - bool insertParametersToSymbolTable); - - void setAtomicCounterBindingDefaultOffset(const TPublicType &declaration, - const TSourceLoc &location); - - bool checkPrimitiveTypeMatchesTypeQualifier(const TTypeQualifier &typeQualifier); - bool parseGeometryShaderInputLayoutQualifier(const TTypeQualifier &typeQualifier); - bool parseGeometryShaderOutputLayoutQualifier(const TTypeQualifier &typeQualifier); - void setGeometryShaderInputArraySize(unsigned int inputArraySize, const TSourceLoc &line); - - // Set to true when the last/current declarator list was started with an empty declaration. The - // non-empty declaration error check will need to be performed if the empty declaration is - // followed by a declarator. - bool mDeferredNonEmptyDeclarationErrorCheck; - - sh::GLenum mShaderType; // vertex or fragment language (future: pack or unpack) - ShShaderSpec mShaderSpec; // The language specification compiler conforms to - GLES2 or WebGL. - ShCompileOptions mCompileOptions; // Options passed to TCompiler - int mShaderVersion; - TIntermBlock *mTreeRoot; // root of parse tree being created - int mLoopNestingLevel; // 0 if outside all loops - int mStructNestingLevel; // incremented while parsing a struct declaration - int mSwitchNestingLevel; // 0 if outside all switch statements - const TType - *mCurrentFunctionType; // the return type of the function that's currently being parsed - bool mFunctionReturnsValue; // true if a non-void function has a return - bool mChecksPrecisionErrors; // true if an error will be generated when a variable is declared - // without precision, explicit or implicit. - bool mFragmentPrecisionHighOnESSL1; // true if highp precision is supported when compiling - // ESSL1. - TLayoutMatrixPacking mDefaultUniformMatrixPacking; - TLayoutBlockStorage mDefaultUniformBlockStorage; - TLayoutMatrixPacking mDefaultBufferMatrixPacking; - TLayoutBlockStorage mDefaultBufferBlockStorage; - TString mHashErrMsg; - TDiagnostics *mDiagnostics; - TDirectiveHandler mDirectiveHandler; - pp::Preprocessor mPreprocessor; - void *mScanner; - bool mUsesFragData; // track if we are using both gl_FragData and gl_FragColor - bool mUsesFragColor; - bool mUsesSecondaryOutputs; // Track if we are using either gl_SecondaryFragData or - // gl_Secondary FragColor or both. - int mMinProgramTexelOffset; - int mMaxProgramTexelOffset; - - int mMinProgramTextureGatherOffset; - int mMaxProgramTextureGatherOffset; - - // keep track of local group size declared in layout. It should be declared only once. - bool mComputeShaderLocalSizeDeclared; - sh::WorkGroupSize mComputeShaderLocalSize; - // keep track of number of views declared in layout. - int mNumViews; - int mMaxNumViews; - int mMaxImageUnits; - int mMaxCombinedTextureImageUnits; - int mMaxUniformLocations; - int mMaxUniformBufferBindings; - int mMaxAtomicCounterBindings; - int mMaxShaderStorageBufferBindings; - - // keeps track whether we are declaring / defining a function - bool mDeclaringFunction; - - // Track the state of each atomic counter binding. - std::map mAtomicCounterBindingStates; - - // Track the geometry shader global parameters declared in layout. - TLayoutPrimitiveType mGeometryShaderInputPrimitiveType; - TLayoutPrimitiveType mGeometryShaderOutputPrimitiveType; - int mGeometryShaderInvocations; - int mGeometryShaderMaxVertices; - int mMaxGeometryShaderInvocations; - int mMaxGeometryShaderMaxVertices; - - // Track if all input array sizes are same and matches the latter input primitive declaration. - unsigned int mGeometryShaderInputArraySize; -}; - -int PaParseStrings(size_t count, - const char *const string[], - const int length[], - TParseContext *context); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_PARSECONTEXT_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/PoolAlloc.cpp b/src/3rdparty/angle/src/compiler/translator/PoolAlloc.cpp deleted file mode 100644 index 0f1cd8b5c9..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/PoolAlloc.cpp +++ /dev/null @@ -1,360 +0,0 @@ -// -// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/translator/PoolAlloc.h" - -#include -#include -#include - -#include "common/angleutils.h" -#include "common/debug.h" -#include "common/platform.h" -#include "common/tls.h" -#include "compiler/translator/InitializeGlobals.h" - -TLSIndex PoolIndex = TLS_INVALID_INDEX; - -bool InitializePoolIndex() -{ - assert(PoolIndex == TLS_INVALID_INDEX); - - PoolIndex = CreateTLSIndex(); - return PoolIndex != TLS_INVALID_INDEX; -} - -void FreePoolIndex() -{ - assert(PoolIndex != TLS_INVALID_INDEX); - - DestroyTLSIndex(PoolIndex); - PoolIndex = TLS_INVALID_INDEX; -} - -TPoolAllocator *GetGlobalPoolAllocator() -{ - assert(PoolIndex != TLS_INVALID_INDEX); - return static_cast(GetTLSValue(PoolIndex)); -} - -void SetGlobalPoolAllocator(TPoolAllocator *poolAllocator) -{ - assert(PoolIndex != TLS_INVALID_INDEX); - SetTLSValue(PoolIndex, poolAllocator); -} - -// -// Implement the functionality of the TPoolAllocator class, which -// is documented in PoolAlloc.h. -// -TPoolAllocator::TPoolAllocator(int growthIncrement, int allocationAlignment) - : alignment(allocationAlignment), -#if !defined(ANGLE_TRANSLATOR_DISABLE_POOL_ALLOC) - pageSize(growthIncrement), - freeList(0), - inUseList(0), - numCalls(0), - totalBytes(0), -#endif - mLocked(false) -{ - // - // 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; - -#if !defined(ANGLE_TRANSLATOR_DISABLE_POOL_ALLOC) - // - // 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; - - // - // Align header skip - // - headerSkip = minAlign; - if (headerSkip < sizeof(tHeader)) - { - headerSkip = (sizeof(tHeader) + alignmentMask) & ~alignmentMask; - } -#else // !defined(ANGLE_TRANSLATOR_DISABLE_POOL_ALLOC) - mStack.push_back({}); -#endif -} - -TPoolAllocator::~TPoolAllocator() -{ -#if !defined(ANGLE_TRANSLATOR_DISABLE_POOL_ALLOC) - while (inUseList) - { - tHeader *next = inUseList->nextPage; - inUseList->~tHeader(); - delete[] reinterpret_cast(inUseList); - inUseList = next; - } - - // 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; - } -#else // !defined(ANGLE_TRANSLATOR_DISABLE_POOL_ALLOC) - for (auto &allocs : mStack) - { - for (auto alloc : allocs) - { - free(alloc); - } - } - mStack.clear(); -#endif -} - -// Support MSVC++ 6.0 -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 -// -void TAllocation::checkGuardBlock(unsigned char *blockMem, - unsigned char val, - const char *locText) const -{ -#ifdef GUARD_BLOCKS - for (size_t x = 0; x < guardBlockSize; x++) - { - if (blockMem[x] != val) - { - char assertMsg[80]; - -// We don't print the assert message. It's here just to be helpful. -#if defined(_MSC_VER) - snprintf(assertMsg, sizeof(assertMsg), - "PoolAlloc: Damage %s %Iu byte allocation at 0x%p\n", locText, size, data()); -#else - snprintf(assertMsg, sizeof(assertMsg), - "PoolAlloc: Damage %s %zu byte allocation at 0x%p\n", locText, size, data()); -#endif - assert(0 && "PoolAlloc: Damage in guard block"); - } - } -#endif -} - -void TPoolAllocator::push() -{ -#if !defined(ANGLE_TRANSLATOR_DISABLE_POOL_ALLOC) - tAllocState state = {currentPageOffset, inUseList}; - - mStack.push_back(state); - - // - // Indicate there is no current page to allocate from. - // - currentPageOffset = pageSize; -#else // !defined(ANGLE_TRANSLATOR_DISABLE_POOL_ALLOC) - mStack.push_back({}); -#endif -} - -// -// 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 (mStack.size() < 1) - return; - -#if !defined(ANGLE_TRANSLATOR_DISABLE_POOL_ALLOC) - tHeader *page = mStack.back().page; - currentPageOffset = mStack.back().offset; - - while (inUseList != page) - { - // invoke destructor to free allocation list - inUseList->~tHeader(); - - tHeader *nextInUse = inUseList->nextPage; - if (inUseList->pageCount > 1) - delete[] reinterpret_cast(inUseList); - else - { - inUseList->nextPage = freeList; - freeList = inUseList; - } - inUseList = nextInUse; - } - - mStack.pop_back(); -#else // !defined(ANGLE_TRANSLATOR_DISABLE_POOL_ALLOC) - for (auto &alloc : mStack.back()) - { - free(alloc); - } - mStack.pop_back(); -#endif -} - -// -// Do a mass-deallocation of all the individual allocations -// that have occurred. -// -void TPoolAllocator::popAll() -{ - while (mStack.size() > 0) - pop(); -} - -void *TPoolAllocator::allocate(size_t numBytes) -{ - ASSERT(!mLocked); - -#if !defined(ANGLE_TRANSLATOR_DISABLE_POOL_ALLOC) - // - // Just keep some interesting statistics. - // - ++numCalls; - totalBytes += 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); - // Detect integer overflow. - if (allocationSize < numBytes) - return 0; - - // - // Do the allocation, most likely case first, for efficiency. - // This step could be moved to be inline sometime. - // - if (allocationSize <= pageSize - currentPageOffset) - { - // - // 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 > pageSize - headerSkip) - { - // - // 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; - // Detect integer overflow. - if (numBytesToAlloc < allocationSize) - return 0; - - 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); -#else // !defined(ANGLE_TRANSLATOR_DISABLE_POOL_ALLOC) - void *alloc = malloc(numBytes + alignmentMask); - mStack.back().push_back(alloc); - - intptr_t intAlloc = reinterpret_cast(alloc); - intAlloc = (intAlloc + alignmentMask) & ~alignmentMask; - return reinterpret_cast(intAlloc); -#endif -} - -void TPoolAllocator::lock() -{ - ASSERT(!mLocked); - mLocked = true; -} - -void TPoolAllocator::unlock() -{ - ASSERT(mLocked); - mLocked = false; -} - -// -// 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(); -} diff --git a/src/3rdparty/angle/src/compiler/translator/PoolAlloc.h b/src/3rdparty/angle/src/compiler/translator/PoolAlloc.h deleted file mode 100644 index ad63bc4cd6..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/PoolAlloc.h +++ /dev/null @@ -1,319 +0,0 @@ -// -// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_TRANSLATOR_POOLALLOC_H_ -#define COMPILER_TRANSLATOR_POOLALLOC_H_ - -#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 - -// If we are using guard blocks, we must track each indivual -// 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 accomodate 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 - - // Support MSVC++ 6.0 - 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. - // - - // Catch unwanted allocations. - // TODO(jmadill): Remove this when we remove the global allocator. - void lock(); - void unlock(); - - private: - size_t alignment; // all returned allocations will be aligned at - // this granularity, which will be a power of 2 - size_t alignmentMask; - -#if !defined(ANGLE_TRANSLATOR_DISABLE_POOL_ALLOC) - friend struct tHeader; - - struct tHeader - { - tHeader(tHeader *nextPage, size_t pageCount) - : nextPage(nextPage), - pageCount(pageCount) -#ifdef GUARD_BLOCKS - , - lastAllocation(0) -#endif - { - } - - ~tHeader() - { -#ifdef GUARD_BLOCKS - if (lastAllocation) - lastAllocation->checkAllocList(); -#endif - } - - tHeader *nextPage; - size_t pageCount; -#ifdef GUARD_BLOCKS - TAllocation *lastAllocation; -#endif - }; - - struct tAllocState - { - size_t offset; - tHeader *page; - }; - typedef std::vector tAllocStack; - - // Track allocations if and only if we're using guard blocks - void *initializeAllocation(tHeader *block, unsigned char *memory, size_t numBytes) - { -#ifdef GUARD_BLOCKS - 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 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 mStack; // stack of where to allocate from, to partition pool - - int numCalls; // just an interesting statistic - size_t totalBytes; // just an interesting statistic - -#else // !defined(ANGLE_TRANSLATOR_DISABLE_POOL_ALLOC) - std::vector> mStack; -#endif - - TPoolAllocator &operator=(const TPoolAllocator &); // dont allow assignment operator - TPoolAllocator(const TPoolAllocator &); // dont allow default copy constructor - bool mLocked; -}; - -// -// 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 *GetGlobalPoolAllocator(); -extern void SetGlobalPoolAllocator(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() {} - - template - pool_allocator(const pool_allocator &p) - { - } - - template - pool_allocator &operator=(const pool_allocator &p) - { - return *this; - } - -#if defined(__SUNPRO_CC) && !defined(_RWSTD_ALLOCATOR) - // libCStd on some platforms have a different allocate/deallocate interface. - // Caller pre-bakes sizeof(T) into 'n' which is the number of bytes to be - // allocated, not the number of elements. - void *allocate(size_type n) { return getAllocator().allocate(n); } - void *allocate(size_type n, const void *) { return getAllocator().allocate(n); } - void deallocate(void *, size_type) {} -#else - 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(pointer, size_type) {} -#endif // _RWSTD_ALLOCATOR - - 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 true; } - bool operator!=(const pool_allocator &rhs) const { return false; } - - size_type max_size() const { return static_cast(-1) / sizeof(T); } - size_type max_size(int size) const { return static_cast(-1) / size; } - - TPoolAllocator &getAllocator() const { return *GetGlobalPoolAllocator(); } -}; - -#endif // COMPILER_TRANSLATOR_POOLALLOC_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/Pragma.h b/src/3rdparty/angle/src/compiler/translator/Pragma.h deleted file mode 100644 index 8c419fc17e..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/Pragma.h +++ /dev/null @@ -1,31 +0,0 @@ -// -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_TRANSLATOR_PRAGMA_H_ -#define COMPILER_TRANSLATOR_PRAGMA_H_ - -struct TPragma -{ - struct STDGL - { - STDGL() : invariantAll(false) {} - - bool invariantAll; - }; - - // By default optimization is turned on and debug is turned off. - // Precision emulation is turned on by default, but has no effect unless - // the extension is enabled. - TPragma() : optimize(true), debug(false), debugShaderPrecision(true) {} - TPragma(bool o, bool d) : optimize(o), debug(d), debugShaderPrecision(true) {} - - bool optimize; - bool debug; - bool debugShaderPrecision; - STDGL stdgl; -}; - -#endif // COMPILER_TRANSLATOR_PRAGMA_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/PruneNoOps.cpp b/src/3rdparty/angle/src/compiler/translator/PruneNoOps.cpp deleted file mode 100644 index 6c9a02cd1c..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/PruneNoOps.cpp +++ /dev/null @@ -1,156 +0,0 @@ -// -// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// PruneNoOps.cpp: The PruneNoOps function prunes: -// 1. Empty declarations "int;". Empty declarators will be pruned as well, so for example: -// int , a; -// is turned into -// int a; -// 2. Literal statements: "1.0;". The ESSL output doesn't define a default precision for float, -// so float literal statements would end up with no precision which is invalid ESSL. - -#include "compiler/translator/PruneNoOps.h" - -#include "compiler/translator/IntermTraverse.h" - -namespace sh -{ - -namespace -{ - -bool IsNoOp(TIntermNode *node) -{ - if (node->getAsConstantUnion() != nullptr) - { - return true; - } - bool isEmptyDeclaration = node->getAsDeclarationNode() != nullptr && - node->getAsDeclarationNode()->getSequence()->empty(); - if (isEmptyDeclaration) - { - return true; - } - return false; -} - -class PruneNoOpsTraverser : private TIntermTraverser -{ - public: - static void apply(TIntermBlock *root); - - private: - PruneNoOpsTraverser(); - bool visitDeclaration(Visit, TIntermDeclaration *node) override; - bool visitBlock(Visit visit, TIntermBlock *node) override; - bool visitLoop(Visit visit, TIntermLoop *loop) override; -}; - -void PruneNoOpsTraverser::apply(TIntermBlock *root) -{ - PruneNoOpsTraverser prune; - root->traverse(&prune); - prune.updateTree(); -} - -PruneNoOpsTraverser::PruneNoOpsTraverser() : TIntermTraverser(true, false, false) -{ -} - -bool PruneNoOpsTraverser::visitDeclaration(Visit, TIntermDeclaration *node) -{ - TIntermSequence *sequence = node->getSequence(); - if (sequence->size() >= 1) - { - TIntermSymbol *sym = sequence->front()->getAsSymbolNode(); - // Prune declarations without a variable name, unless it's an interface block declaration. - if (sym != nullptr && sym->getSymbol() == "" && !sym->isInterfaceBlock()) - { - if (sequence->size() > 1) - { - // Generate a replacement that will remove the empty declarator in the beginning of - // a declarator list. Example of a declaration that will be changed: - // float, a; - // will be changed to - // float a; - // This applies also to struct declarations. - TIntermSequence emptyReplacement; - mMultiReplacements.push_back( - NodeReplaceWithMultipleEntry(node, sym, emptyReplacement)); - } - else if (sym->getBasicType() != EbtStruct) - { - // If there are entirely empty non-struct declarations, they result in - // TIntermDeclaration nodes without any children in the parsing stage. These are - // handled in visitBlock and visitLoop. - UNREACHABLE(); - } - else if (sym->getType().getQualifier() != EvqGlobal && - sym->getType().getQualifier() != EvqTemporary) - { - // Single struct declarations may just declare the struct type and no variables, so - // they should not be pruned. Here we handle an empty struct declaration with a - // qualifier, for example like this: - // const struct a { int i; }; - // NVIDIA GL driver version 367.27 doesn't accept this kind of declarations, so we - // convert the declaration to a regular struct declaration. This is okay, since ESSL - // 1.00 spec section 4.1.8 says about structs that "The optional qualifiers only - // apply to any declarators, and are not part of the type being defined for name." - - if (mInGlobalScope) - { - sym->getTypePointer()->setQualifier(EvqGlobal); - } - else - { - sym->getTypePointer()->setQualifier(EvqTemporary); - } - } - } - } - return false; -} - -bool PruneNoOpsTraverser::visitBlock(Visit visit, TIntermBlock *node) -{ - TIntermSequence *statements = node->getSequence(); - - for (TIntermNode *statement : *statements) - { - if (IsNoOp(statement)) - { - TIntermSequence emptyReplacement; - mMultiReplacements.push_back( - NodeReplaceWithMultipleEntry(node, statement, emptyReplacement)); - } - } - - return true; -} - -bool PruneNoOpsTraverser::visitLoop(Visit visit, TIntermLoop *loop) -{ - TIntermTyped *expr = loop->getExpression(); - if (expr != nullptr && IsNoOp(expr)) - { - loop->setExpression(nullptr); - } - TIntermNode *init = loop->getInit(); - if (init != nullptr && IsNoOp(init)) - { - loop->setInit(nullptr); - } - - return true; -} - -} // namespace - -void PruneNoOps(TIntermBlock *root) -{ - PruneNoOpsTraverser::apply(root); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/PruneNoOps.h b/src/3rdparty/angle/src/compiler/translator/PruneNoOps.h deleted file mode 100644 index c421cecca4..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/PruneNoOps.h +++ /dev/null @@ -1,24 +0,0 @@ -// -// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// PruneNoOps.h: The PruneNoOps function prunes: -// 1. Empty declarations "int;". Empty declarators will be pruned as well, so for example: -// int , a; -// is turned into -// int a; -// 2. Literal statements: "1.0;". The ESSL output doesn't define a default precision for float, -// so float literal statements would end up with no precision which is invalid ESSL. - -#ifndef COMPILER_TRANSLATOR_PRUNENOOPS_H_ -#define COMPILER_TRANSLATOR_PRUNENOOPS_H_ - -namespace sh -{ -class TIntermBlock; - -void PruneNoOps(TIntermBlock *root); -} - -#endif // COMPILER_TRANSLATOR_PRUNENOOPS_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/QualifierTypes.cpp b/src/3rdparty/angle/src/compiler/translator/QualifierTypes.cpp deleted file mode 100644 index f748175957..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/QualifierTypes.cpp +++ /dev/null @@ -1,784 +0,0 @@ -// -// Copyright (c) 2002-2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/translator/QualifierTypes.h" - -#include "compiler/translator/Diagnostics.h" - -#include - -namespace sh -{ - -namespace -{ - -// GLSL ES 3.10 does not impose a strict order on type qualifiers and allows multiple layout -// declarations. -// GLSL ES 3.10 Revision 4, 4.10 Order of Qualification -bool AreTypeQualifierChecksRelaxed(int shaderVersion) -{ - return shaderVersion >= 310; -} - -bool IsScopeQualifier(TQualifier qualifier) -{ - return qualifier == EvqGlobal || qualifier == EvqTemporary; -} - -bool IsScopeQualifierWrapper(const TQualifierWrapperBase *qualifier) -{ - if (qualifier->getType() != QtStorage) - return false; - const TStorageQualifierWrapper *storageQualifier = - static_cast(qualifier); - TQualifier q = storageQualifier->getQualifier(); - return IsScopeQualifier(q); -} - -// Returns true if the invariant for the qualifier sequence holds -bool IsInvariantCorrect(const TTypeQualifierBuilder::QualifierSequence &qualifiers) -{ - // We should have at least one qualifier. - // The first qualifier always tells the scope. - return qualifiers.size() >= 1 && IsScopeQualifierWrapper(qualifiers[0]); -} - -// Returns true if there are qualifiers which have been specified multiple times -// If areQualifierChecksRelaxed is set to true, then layout qualifier repetition is allowed. -bool HasRepeatingQualifiers(const TTypeQualifierBuilder::QualifierSequence &qualifiers, - bool areQualifierChecksRelaxed, - std::string *errorMessage) -{ - bool invariantFound = false; - bool precisionFound = false; - bool layoutFound = false; - bool interpolationFound = false; - - unsigned int locationsSpecified = 0; - bool isOut = false; - - // The iteration starts from one since the first qualifier only reveals the scope of the - // expression. It is inserted first whenever the sequence gets created. - for (size_t i = 1; i < qualifiers.size(); ++i) - { - switch (qualifiers[i]->getType()) - { - case QtInvariant: - { - if (invariantFound) - { - *errorMessage = "The invariant qualifier specified multiple times."; - return true; - } - invariantFound = true; - break; - } - case QtPrecision: - { - if (precisionFound) - { - *errorMessage = "The precision qualifier specified multiple times."; - return true; - } - precisionFound = true; - break; - } - case QtLayout: - { - if (layoutFound && !areQualifierChecksRelaxed) - { - *errorMessage = "The layout qualifier specified multiple times."; - return true; - } - if (invariantFound && !areQualifierChecksRelaxed) - { - // This combination is not correct according to the syntax specified in the - // formal grammar in the ESSL 3.00 spec. In ESSL 3.10 the grammar does not have - // a similar restriction. - *errorMessage = - "The layout qualifier and invariant qualifier cannot coexist in the same " - "declaration according to the grammar."; - return true; - } - layoutFound = true; - const TLayoutQualifier ¤tQualifier = - static_cast(qualifiers[i])->getQualifier(); - locationsSpecified += currentQualifier.locationsSpecified; - break; - } - case QtInterpolation: - { - // 'centroid' is treated as a storage qualifier - // 'flat centroid' will be squashed to 'flat' - // 'smooth centroid' will be squashed to 'centroid' - if (interpolationFound) - { - *errorMessage = "The interpolation qualifier specified multiple times."; - return true; - } - interpolationFound = true; - break; - } - case QtStorage: - { - // Go over all of the storage qualifiers up until the current one and check for - // repetitions. - TQualifier currentQualifier = - static_cast(qualifiers[i])->getQualifier(); - if (currentQualifier == EvqVertexOut || currentQualifier == EvqFragmentOut) - { - isOut = true; - } - for (size_t j = 1; j < i; ++j) - { - if (qualifiers[j]->getType() == QtStorage) - { - const TStorageQualifierWrapper *previousQualifierWrapper = - static_cast(qualifiers[j]); - TQualifier previousQualifier = previousQualifierWrapper->getQualifier(); - if (currentQualifier == previousQualifier) - { - *errorMessage = previousQualifierWrapper->getQualifierString().c_str(); - *errorMessage += " specified multiple times"; - return true; - } - } - } - break; - } - case QtMemory: - { - // Go over all of the memory qualifiers up until the current one and check for - // repetitions. - // Having both readonly and writeonly in a sequence is valid. - // GLSL ES 3.10 Revision 4, 4.9 Memory Access Qualifiers - TQualifier currentQualifier = - static_cast(qualifiers[i])->getQualifier(); - for (size_t j = 1; j < i; ++j) - { - if (qualifiers[j]->getType() == QtMemory) - { - const TMemoryQualifierWrapper *previousQualifierWrapper = - static_cast(qualifiers[j]); - TQualifier previousQualifier = previousQualifierWrapper->getQualifier(); - if (currentQualifier == previousQualifier) - { - *errorMessage = previousQualifierWrapper->getQualifierString().c_str(); - *errorMessage += " specified multiple times"; - return true; - } - } - } - break; - } - default: - UNREACHABLE(); - } - } - - if (locationsSpecified > 1 && isOut) - { - // GLSL ES 3.00.6 section 4.3.8.2 Output Layout Qualifiers - // GLSL ES 3.10 section 4.4.2 Output Layout Qualifiers - // "The qualifier may appear at most once within a declaration." - *errorMessage = "Output layout location specified multiple times."; - return true; - } - - return false; -} - -// GLSL ES 3.00_6, 4.7 Order of Qualification -// The correct order of qualifiers is: -// invariant-qualifier interpolation-qualifier storage-qualifier precision-qualifier -// layout-qualifier has to be before storage-qualifier. -bool AreQualifiersInOrder(const TTypeQualifierBuilder::QualifierSequence &qualifiers, - std::string *errorMessage) -{ - bool foundInterpolation = false; - bool foundStorage = false; - bool foundPrecision = false; - for (size_t i = 1; i < qualifiers.size(); ++i) - { - switch (qualifiers[i]->getType()) - { - case QtInvariant: - if (foundInterpolation || foundStorage || foundPrecision) - { - *errorMessage = "The invariant qualifier has to be first in the expression."; - return false; - } - break; - case QtInterpolation: - if (foundStorage) - { - *errorMessage = "Storage qualifiers have to be after interpolation qualifiers."; - return false; - } - else if (foundPrecision) - { - *errorMessage = - "Precision qualifiers have to be after interpolation qualifiers."; - return false; - } - foundInterpolation = true; - break; - case QtLayout: - if (foundStorage) - { - *errorMessage = "Storage qualifiers have to be after layout qualifiers."; - return false; - } - else if (foundPrecision) - { - *errorMessage = "Precision qualifiers have to be after layout qualifiers."; - return false; - } - break; - case QtStorage: - if (foundPrecision) - { - *errorMessage = "Precision qualifiers have to be after storage qualifiers."; - return false; - } - foundStorage = true; - break; - case QtMemory: - if (foundPrecision) - { - *errorMessage = "Precision qualifiers have to be after memory qualifiers."; - return false; - } - break; - case QtPrecision: - foundPrecision = true; - break; - default: - UNREACHABLE(); - } - } - return true; -} - -struct QualifierComparator -{ - bool operator()(const TQualifierWrapperBase *q1, const TQualifierWrapperBase *q2) - { - return q1->getRank() < q2->getRank(); - } -}; - -void SortSequence(TTypeQualifierBuilder::QualifierSequence &qualifiers) -{ - // We need a stable sorting algorithm since the order of layout-qualifier declarations matter. - // The sorting starts from index 1, instead of 0, since the element at index 0 tells the scope - // and we always want it to be first. - std::stable_sort(qualifiers.begin() + 1, qualifiers.end(), QualifierComparator()); -} - -// Handles the joining of storage qualifiers for variables. -bool JoinVariableStorageQualifier(TQualifier *joinedQualifier, TQualifier storageQualifier) -{ - switch (*joinedQualifier) - { - case EvqGlobal: - *joinedQualifier = storageQualifier; - break; - case EvqTemporary: - { - switch (storageQualifier) - { - case EvqConst: - *joinedQualifier = storageQualifier; - break; - default: - return false; - } - break; - } - case EvqSmooth: - { - switch (storageQualifier) - { - case EvqCentroid: - *joinedQualifier = EvqCentroid; - break; - case EvqVertexOut: - case EvqGeometryOut: - *joinedQualifier = EvqSmoothOut; - break; - case EvqFragmentIn: - case EvqGeometryIn: - *joinedQualifier = EvqSmoothIn; - break; - default: - return false; - } - break; - } - case EvqFlat: - { - switch (storageQualifier) - { - case EvqCentroid: - *joinedQualifier = EvqFlat; - break; - case EvqVertexOut: - case EvqGeometryOut: - *joinedQualifier = EvqFlatOut; - break; - case EvqFragmentIn: - case EvqGeometryIn: - *joinedQualifier = EvqFlatIn; - break; - default: - return false; - } - break; - } - case EvqCentroid: - { - switch (storageQualifier) - { - case EvqVertexOut: - case EvqGeometryOut: - *joinedQualifier = EvqCentroidOut; - break; - case EvqFragmentIn: - case EvqGeometryIn: - *joinedQualifier = EvqCentroidIn; - break; - default: - return false; - } - break; - } - default: - return false; - } - return true; -} - -// Handles the joining of storage qualifiers for a parameter in a function. -bool JoinParameterStorageQualifier(TQualifier *joinedQualifier, TQualifier storageQualifier) -{ - switch (*joinedQualifier) - { - case EvqTemporary: - *joinedQualifier = storageQualifier; - break; - case EvqConst: - { - switch (storageQualifier) - { - case EvqIn: - *joinedQualifier = EvqConstReadOnly; - break; - default: - return false; - } - break; - } - default: - return false; - } - return true; -} - -bool JoinMemoryQualifier(TMemoryQualifier *joinedMemoryQualifier, TQualifier memoryQualifier) -{ - switch (memoryQualifier) - { - case EvqReadOnly: - joinedMemoryQualifier->readonly = true; - break; - case EvqWriteOnly: - joinedMemoryQualifier->writeonly = true; - break; - case EvqCoherent: - joinedMemoryQualifier->coherent = true; - break; - case EvqRestrict: - joinedMemoryQualifier->restrictQualifier = true; - break; - case EvqVolatile: - // Variables having the volatile qualifier are automatcally treated as coherent as well. - // GLSL ES 3.10, Revision 4, 4.9 Memory Access Qualifiers - joinedMemoryQualifier->volatileQualifier = true; - joinedMemoryQualifier->coherent = true; - break; - default: - UNREACHABLE(); - } - return true; -} - -TTypeQualifier GetVariableTypeQualifierFromSortedSequence( - const TTypeQualifierBuilder::QualifierSequence &sortedSequence, - TDiagnostics *diagnostics) -{ - TTypeQualifier typeQualifier( - static_cast(sortedSequence[0])->getQualifier(), - sortedSequence[0]->getLine()); - for (size_t i = 1; i < sortedSequence.size(); ++i) - { - const TQualifierWrapperBase *qualifier = sortedSequence[i]; - bool isQualifierValid = false; - switch (qualifier->getType()) - { - case QtInvariant: - isQualifierValid = true; - typeQualifier.invariant = true; - break; - case QtInterpolation: - { - switch (typeQualifier.qualifier) - { - case EvqGlobal: - isQualifierValid = true; - typeQualifier.qualifier = - static_cast(qualifier) - ->getQualifier(); - break; - default: - isQualifierValid = false; - } - break; - } - case QtLayout: - { - const TLayoutQualifierWrapper *layoutQualifierWrapper = - static_cast(qualifier); - isQualifierValid = true; - typeQualifier.layoutQualifier = sh::JoinLayoutQualifiers( - typeQualifier.layoutQualifier, layoutQualifierWrapper->getQualifier(), - layoutQualifierWrapper->getLine(), diagnostics); - break; - } - case QtStorage: - isQualifierValid = JoinVariableStorageQualifier( - &typeQualifier.qualifier, - static_cast(qualifier)->getQualifier()); - break; - case QtPrecision: - isQualifierValid = true; - typeQualifier.precision = - static_cast(qualifier)->getQualifier(); - ASSERT(typeQualifier.precision != EbpUndefined); - break; - case QtMemory: - isQualifierValid = JoinMemoryQualifier( - &typeQualifier.memoryQualifier, - static_cast(qualifier)->getQualifier()); - break; - default: - UNREACHABLE(); - } - if (!isQualifierValid) - { - const TString &qualifierString = qualifier->getQualifierString(); - diagnostics->error(qualifier->getLine(), "invalid qualifier combination", - qualifierString.c_str()); - break; - } - } - return typeQualifier; -} - -TTypeQualifier GetParameterTypeQualifierFromSortedSequence( - const TTypeQualifierBuilder::QualifierSequence &sortedSequence, - TDiagnostics *diagnostics) -{ - TTypeQualifier typeQualifier(EvqTemporary, sortedSequence[0]->getLine()); - for (size_t i = 1; i < sortedSequence.size(); ++i) - { - const TQualifierWrapperBase *qualifier = sortedSequence[i]; - bool isQualifierValid = false; - switch (qualifier->getType()) - { - case QtInvariant: - case QtInterpolation: - case QtLayout: - break; - case QtMemory: - isQualifierValid = JoinMemoryQualifier( - &typeQualifier.memoryQualifier, - static_cast(qualifier)->getQualifier()); - break; - case QtStorage: - isQualifierValid = JoinParameterStorageQualifier( - &typeQualifier.qualifier, - static_cast(qualifier)->getQualifier()); - break; - case QtPrecision: - isQualifierValid = true; - typeQualifier.precision = - static_cast(qualifier)->getQualifier(); - ASSERT(typeQualifier.precision != EbpUndefined); - break; - default: - UNREACHABLE(); - } - if (!isQualifierValid) - { - const TString &qualifierString = qualifier->getQualifierString(); - diagnostics->error(qualifier->getLine(), "invalid parameter qualifier", - qualifierString.c_str()); - break; - } - } - - switch (typeQualifier.qualifier) - { - case EvqIn: - case EvqConstReadOnly: // const in - case EvqOut: - case EvqInOut: - break; - case EvqConst: - typeQualifier.qualifier = EvqConstReadOnly; - break; - case EvqTemporary: - // no qualifier has been specified, set it to EvqIn which is the default - typeQualifier.qualifier = EvqIn; - break; - default: - diagnostics->error(sortedSequence[0]->getLine(), "Invalid parameter qualifier ", - getQualifierString(typeQualifier.qualifier)); - } - return typeQualifier; -} -} // namespace - -TLayoutQualifier JoinLayoutQualifiers(TLayoutQualifier leftQualifier, - TLayoutQualifier rightQualifier, - const TSourceLoc &rightQualifierLocation, - TDiagnostics *diagnostics) -{ - TLayoutQualifier joinedQualifier = leftQualifier; - - if (rightQualifier.location != -1) - { - joinedQualifier.location = rightQualifier.location; - ++joinedQualifier.locationsSpecified; - } - if (rightQualifier.yuv != false) - { - joinedQualifier.yuv = rightQualifier.yuv; - } - if (rightQualifier.binding != -1) - { - joinedQualifier.binding = rightQualifier.binding; - } - if (rightQualifier.offset != -1) - { - joinedQualifier.offset = rightQualifier.offset; - } - if (rightQualifier.matrixPacking != EmpUnspecified) - { - joinedQualifier.matrixPacking = rightQualifier.matrixPacking; - } - if (rightQualifier.blockStorage != EbsUnspecified) - { - joinedQualifier.blockStorage = rightQualifier.blockStorage; - } - - for (size_t i = 0u; i < rightQualifier.localSize.size(); ++i) - { - if (rightQualifier.localSize[i] != -1) - { - if (joinedQualifier.localSize[i] != -1 && - joinedQualifier.localSize[i] != rightQualifier.localSize[i]) - { - diagnostics->error(rightQualifierLocation, - "Cannot have multiple different work group size specifiers", - getWorkGroupSizeString(i)); - } - joinedQualifier.localSize[i] = rightQualifier.localSize[i]; - } - } - - if (rightQualifier.numViews != -1) - { - joinedQualifier.numViews = rightQualifier.numViews; - } - - if (rightQualifier.imageInternalFormat != EiifUnspecified) - { - joinedQualifier.imageInternalFormat = rightQualifier.imageInternalFormat; - } - - if (rightQualifier.primitiveType != EptUndefined) - { - if (joinedQualifier.primitiveType != EptUndefined && - joinedQualifier.primitiveType != rightQualifier.primitiveType) - { - diagnostics->error(rightQualifierLocation, - "Cannot have multiple different primitive specifiers", - getGeometryShaderPrimitiveTypeString(rightQualifier.primitiveType)); - } - joinedQualifier.primitiveType = rightQualifier.primitiveType; - } - - if (rightQualifier.invocations != 0) - { - if (joinedQualifier.invocations != 0 && - joinedQualifier.invocations != rightQualifier.invocations) - { - diagnostics->error(rightQualifierLocation, - "Cannot have multiple different invocations specifiers", - "invocations"); - } - joinedQualifier.invocations = rightQualifier.invocations; - } - - if (rightQualifier.maxVertices != -1) - { - if (joinedQualifier.maxVertices != -1 && - joinedQualifier.maxVertices != rightQualifier.maxVertices) - { - diagnostics->error(rightQualifierLocation, - "Cannot have multiple different max_vertices specifiers", - "max_vertices"); - } - joinedQualifier.maxVertices = rightQualifier.maxVertices; - } - - return joinedQualifier; -} - -unsigned int TInvariantQualifierWrapper::getRank() const -{ - return 0u; -} - -unsigned int TInterpolationQualifierWrapper::getRank() const -{ - return 1u; -} - -unsigned int TLayoutQualifierWrapper::getRank() const -{ - return 2u; -} - -unsigned int TStorageQualifierWrapper::getRank() const -{ - // Force the 'centroid' auxilary storage qualifier to be always first among all storage - // qualifiers. - if (mStorageQualifier == EvqCentroid) - { - return 3u; - } - else - { - return 4u; - } -} - -unsigned int TMemoryQualifierWrapper::getRank() const -{ - return 4u; -} - -unsigned int TPrecisionQualifierWrapper::getRank() const -{ - return 5u; -} - -TTypeQualifier::TTypeQualifier(TQualifier scope, const TSourceLoc &loc) - : layoutQualifier(TLayoutQualifier::Create()), - memoryQualifier(TMemoryQualifier::Create()), - precision(EbpUndefined), - qualifier(scope), - invariant(false), - line(loc) -{ - ASSERT(IsScopeQualifier(qualifier)); -} - -TTypeQualifierBuilder::TTypeQualifierBuilder(const TStorageQualifierWrapper *scope, - int shaderVersion) - : mShaderVersion(shaderVersion) -{ - ASSERT(IsScopeQualifier(scope->getQualifier())); - mQualifiers.push_back(scope); -} - -void TTypeQualifierBuilder::appendQualifier(const TQualifierWrapperBase *qualifier) -{ - mQualifiers.push_back(qualifier); -} - -bool TTypeQualifierBuilder::checkSequenceIsValid(TDiagnostics *diagnostics) const -{ - bool areQualifierChecksRelaxed = AreTypeQualifierChecksRelaxed(mShaderVersion); - std::string errorMessage; - if (HasRepeatingQualifiers(mQualifiers, areQualifierChecksRelaxed, &errorMessage)) - { - diagnostics->error(mQualifiers[0]->getLine(), errorMessage.c_str(), "qualifier sequence"); - return false; - } - - if (!areQualifierChecksRelaxed && !AreQualifiersInOrder(mQualifiers, &errorMessage)) - { - diagnostics->error(mQualifiers[0]->getLine(), errorMessage.c_str(), "qualifier sequence"); - return false; - } - - return true; -} - -TTypeQualifier TTypeQualifierBuilder::getParameterTypeQualifier(TDiagnostics *diagnostics) const -{ - ASSERT(IsInvariantCorrect(mQualifiers)); - ASSERT(static_cast(mQualifiers[0])->getQualifier() == - EvqTemporary); - - if (!checkSequenceIsValid(diagnostics)) - { - return TTypeQualifier(EvqTemporary, mQualifiers[0]->getLine()); - } - - // If the qualifier checks are relaxed, then it is easier to sort the qualifiers so - // that the order imposed by the GLSL ES 3.00 spec is kept. Then we can use the same code to - // combine the qualifiers. - if (AreTypeQualifierChecksRelaxed(mShaderVersion)) - { - // Copy the qualifier sequence so that we can sort them. - QualifierSequence sortedQualifierSequence = mQualifiers; - SortSequence(sortedQualifierSequence); - return GetParameterTypeQualifierFromSortedSequence(sortedQualifierSequence, diagnostics); - } - return GetParameterTypeQualifierFromSortedSequence(mQualifiers, diagnostics); -} - -TTypeQualifier TTypeQualifierBuilder::getVariableTypeQualifier(TDiagnostics *diagnostics) const -{ - ASSERT(IsInvariantCorrect(mQualifiers)); - - if (!checkSequenceIsValid(diagnostics)) - { - return TTypeQualifier( - static_cast(mQualifiers[0])->getQualifier(), - mQualifiers[0]->getLine()); - } - - // If the qualifier checks are relaxed, then it is easier to sort the qualifiers so - // that the order imposed by the GLSL ES 3.00 spec is kept. Then we can use the same code to - // combine the qualifiers. - if (AreTypeQualifierChecksRelaxed(mShaderVersion)) - { - // Copy the qualifier sequence so that we can sort them. - QualifierSequence sortedQualifierSequence = mQualifiers; - SortSequence(sortedQualifierSequence); - return GetVariableTypeQualifierFromSortedSequence(sortedQualifierSequence, diagnostics); - } - return GetVariableTypeQualifierFromSortedSequence(mQualifiers, diagnostics); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/QualifierTypes.h b/src/3rdparty/angle/src/compiler/translator/QualifierTypes.h deleted file mode 100644 index 10bdeed89d..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/QualifierTypes.h +++ /dev/null @@ -1,191 +0,0 @@ -// -// Copyright (c) 2002-2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_TRANSLATOR_QUALIFIER_TYPES_H_ -#define COMPILER_TRANSLATOR_QUALIFIER_TYPES_H_ - -#include "common/angleutils.h" -#include "compiler/translator/BaseTypes.h" -#include "compiler/translator/Types.h" - -namespace sh -{ -class TDiagnostics; - -TLayoutQualifier JoinLayoutQualifiers(TLayoutQualifier leftQualifier, - TLayoutQualifier rightQualifier, - const TSourceLoc &rightQualifierLocation, - TDiagnostics *diagnostics); - -enum TQualifierType -{ - QtInvariant, - QtInterpolation, - QtLayout, - QtStorage, - QtPrecision, - QtMemory -}; - -class TQualifierWrapperBase : angle::NonCopyable -{ - public: - POOL_ALLOCATOR_NEW_DELETE(); - TQualifierWrapperBase(const TSourceLoc &line) : mLine(line) {} - virtual ~TQualifierWrapperBase(){}; - virtual TQualifierType getType() const = 0; - virtual TString getQualifierString() const = 0; - virtual unsigned int getRank() const = 0; - const TSourceLoc &getLine() const { return mLine; } - private: - TSourceLoc mLine; -}; - -class TInvariantQualifierWrapper final : public TQualifierWrapperBase -{ - public: - TInvariantQualifierWrapper(const TSourceLoc &line) : TQualifierWrapperBase(line) {} - ~TInvariantQualifierWrapper() {} - - TQualifierType getType() const { return QtInvariant; } - TString getQualifierString() const { return "invariant"; } - unsigned int getRank() const; -}; - -class TInterpolationQualifierWrapper final : public TQualifierWrapperBase -{ - public: - TInterpolationQualifierWrapper(TQualifier interpolationQualifier, const TSourceLoc &line) - : TQualifierWrapperBase(line), mInterpolationQualifier(interpolationQualifier) - { - } - ~TInterpolationQualifierWrapper() {} - - TQualifierType getType() const { return QtInterpolation; } - TString getQualifierString() const { return sh::getQualifierString(mInterpolationQualifier); } - TQualifier getQualifier() const { return mInterpolationQualifier; } - unsigned int getRank() const; - - private: - TQualifier mInterpolationQualifier; -}; - -class TLayoutQualifierWrapper final : public TQualifierWrapperBase -{ - public: - TLayoutQualifierWrapper(TLayoutQualifier layoutQualifier, const TSourceLoc &line) - : TQualifierWrapperBase(line), mLayoutQualifier(layoutQualifier) - { - } - ~TLayoutQualifierWrapper() {} - - TQualifierType getType() const { return QtLayout; } - TString getQualifierString() const { return "layout"; } - const TLayoutQualifier &getQualifier() const { return mLayoutQualifier; } - unsigned int getRank() const; - - private: - TLayoutQualifier mLayoutQualifier; -}; - -class TStorageQualifierWrapper final : public TQualifierWrapperBase -{ - public: - TStorageQualifierWrapper(TQualifier storageQualifier, const TSourceLoc &line) - : TQualifierWrapperBase(line), mStorageQualifier(storageQualifier) - { - } - ~TStorageQualifierWrapper() {} - - TQualifierType getType() const { return QtStorage; } - TString getQualifierString() const { return sh::getQualifierString(mStorageQualifier); } - TQualifier getQualifier() const { return mStorageQualifier; } - unsigned int getRank() const; - - private: - TQualifier mStorageQualifier; -}; - -class TPrecisionQualifierWrapper final : public TQualifierWrapperBase -{ - public: - TPrecisionQualifierWrapper(TPrecision precisionQualifier, const TSourceLoc &line) - : TQualifierWrapperBase(line), mPrecisionQualifier(precisionQualifier) - { - } - ~TPrecisionQualifierWrapper() {} - - TQualifierType getType() const { return QtPrecision; } - TString getQualifierString() const { return sh::getPrecisionString(mPrecisionQualifier); } - TPrecision getQualifier() const { return mPrecisionQualifier; } - unsigned int getRank() const; - - private: - TPrecision mPrecisionQualifier; -}; - -class TMemoryQualifierWrapper final : public TQualifierWrapperBase -{ - public: - TMemoryQualifierWrapper(TQualifier memoryQualifier, const TSourceLoc &line) - : TQualifierWrapperBase(line), mMemoryQualifier(memoryQualifier) - { - } - ~TMemoryQualifierWrapper() {} - - TQualifierType getType() const { return QtMemory; } - TString getQualifierString() const { return sh::getQualifierString(mMemoryQualifier); } - TQualifier getQualifier() const { return mMemoryQualifier; } - unsigned int getRank() const; - - private: - TQualifier mMemoryQualifier; -}; - -// TTypeQualifier tightly covers type_qualifier from the grammar -struct TTypeQualifier -{ - // initializes all of the qualifiers and sets the scope - TTypeQualifier(TQualifier scope, const TSourceLoc &loc); - - TLayoutQualifier layoutQualifier; - TMemoryQualifier memoryQualifier; - TPrecision precision; - TQualifier qualifier; - bool invariant; - TSourceLoc line; -}; - -// TTypeQualifierBuilder contains all of the qualifiers when type_qualifier gets parsed. -// It is to be used to validate the qualifier sequence and build a TTypeQualifier from it. -class TTypeQualifierBuilder : angle::NonCopyable -{ - public: - using QualifierSequence = TVector; - - public: - POOL_ALLOCATOR_NEW_DELETE(); - TTypeQualifierBuilder(const TStorageQualifierWrapper *scope, int shaderVersion); - // Adds the passed qualifier to the end of the sequence. - void appendQualifier(const TQualifierWrapperBase *qualifier); - // Checks for the order of qualification and repeating qualifiers. - bool checkSequenceIsValid(TDiagnostics *diagnostics) const; - // Goes over the qualifier sequence and parses it to form a type qualifier for a function - // parameter. - // The returned object is initialized even if the parsing fails. - TTypeQualifier getParameterTypeQualifier(TDiagnostics *diagnostics) const; - // Goes over the qualifier sequence and parses it to form a type qualifier for a variable. - // The returned object is initialized even if the parsing fails. - TTypeQualifier getVariableTypeQualifier(TDiagnostics *diagnostics) const; - - private: - QualifierSequence mQualifiers; - int mShaderVersion; -}; - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_QUALIFIER_TYPES_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/RecordConstantPrecision.cpp b/src/3rdparty/angle/src/compiler/translator/RecordConstantPrecision.cpp deleted file mode 100644 index 5233a29f19..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/RecordConstantPrecision.cpp +++ /dev/null @@ -1,167 +0,0 @@ -// -// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// During parsing, all constant expressions are folded to constant union nodes. The expressions that -// have been folded may have had precision qualifiers, which should affect the precision of the -// consuming operation. If the folded constant union nodes are written to output as such they won't -// have any precision qualifiers, and their effect on the precision of the consuming operation is -// lost. -// -// RecordConstantPrecision is an AST traverser that inspects the precision qualifiers of constants -// and hoists the constants outside the containing expression as precision qualified named variables -// in case that is required for correct precision propagation. -// - -#include "compiler/translator/RecordConstantPrecision.h" - -#include "compiler/translator/InfoSink.h" -#include "compiler/translator/IntermTraverse.h" - -namespace sh -{ - -namespace -{ - -class RecordConstantPrecisionTraverser : public TIntermTraverser -{ - public: - RecordConstantPrecisionTraverser(TSymbolTable *symbolTable); - - void visitConstantUnion(TIntermConstantUnion *node) override; - - void nextIteration(); - - bool foundHigherPrecisionConstant() const { return mFoundHigherPrecisionConstant; } - protected: - bool operandAffectsParentOperationPrecision(TIntermTyped *operand); - - bool mFoundHigherPrecisionConstant; -}; - -RecordConstantPrecisionTraverser::RecordConstantPrecisionTraverser(TSymbolTable *symbolTable) - : TIntermTraverser(true, false, true, symbolTable), mFoundHigherPrecisionConstant(false) -{ -} - -bool RecordConstantPrecisionTraverser::operandAffectsParentOperationPrecision(TIntermTyped *operand) -{ - if (getParentNode()->getAsCaseNode() || getParentNode()->getAsBlock()) - { - return false; - } - - const TIntermBinary *parentAsBinary = getParentNode()->getAsBinaryNode(); - if (parentAsBinary != nullptr) - { - // If the constant is assigned or is used to initialize a variable, or if it's an index, - // its precision has no effect. - switch (parentAsBinary->getOp()) - { - case EOpInitialize: - case EOpAssign: - case EOpIndexDirect: - case EOpIndexDirectStruct: - case EOpIndexDirectInterfaceBlock: - case EOpIndexIndirect: - return false; - default: - break; - } - - TIntermTyped *otherOperand = parentAsBinary->getRight(); - if (otherOperand == operand) - { - otherOperand = parentAsBinary->getLeft(); - } - // If the precision of the other child is at least as high as the precision of the constant, - // the precision of the constant has no effect. - if (otherOperand->getAsConstantUnion() == nullptr && - otherOperand->getPrecision() >= operand->getPrecision()) - { - return false; - } - } - - TIntermAggregate *parentAsAggregate = getParentNode()->getAsAggregate(); - if (parentAsAggregate != nullptr) - { - if (!parentAsAggregate->gotPrecisionFromChildren()) - { - // This can be either: - // * a call to an user-defined function - // * a call to a texture function - // * some other kind of aggregate - // In any of these cases the constant precision has no effect. - return false; - } - if (parentAsAggregate->isConstructor() && parentAsAggregate->getBasicType() == EbtBool) - { - return false; - } - // If the precision of operands does affect the result, but the precision of any of the - // other children has a precision that's at least as high as the precision of the constant, - // the precision of the constant has no effect. - TIntermSequence *parameters = parentAsAggregate->getSequence(); - for (TIntermNode *parameter : *parameters) - { - const TIntermTyped *typedParameter = parameter->getAsTyped(); - if (parameter != operand && typedParameter != nullptr && - parameter->getAsConstantUnion() == nullptr && - typedParameter->getPrecision() >= operand->getPrecision()) - { - return false; - } - } - } - return true; -} - -void RecordConstantPrecisionTraverser::visitConstantUnion(TIntermConstantUnion *node) -{ - if (mFoundHigherPrecisionConstant) - return; - - // If the constant has lowp or undefined precision, it can't increase the precision of consuming - // operations. - if (node->getPrecision() < EbpMedium) - return; - - // It's possible the node has no effect on the precision of the consuming expression, depending - // on the consuming expression, and the precision of the other parameters of the expression. - if (!operandAffectsParentOperationPrecision(node)) - return; - - // Make the constant a precision-qualified named variable to make sure it affects the precision - // of the consuming expression. - TIntermSequence insertions; - insertions.push_back(createTempInitDeclaration(node, EvqConst)); - insertStatementsInParentBlock(insertions); - queueReplacement(createTempSymbol(node->getType()), OriginalNode::IS_DROPPED); - mFoundHigherPrecisionConstant = true; -} - -void RecordConstantPrecisionTraverser::nextIteration() -{ - nextTemporaryId(); - mFoundHigherPrecisionConstant = false; -} - -} // namespace - -void RecordConstantPrecision(TIntermNode *root, TSymbolTable *symbolTable) -{ - RecordConstantPrecisionTraverser traverser(symbolTable); - // Iterate as necessary, and reset the traverser between iterations. - do - { - traverser.nextIteration(); - root->traverse(&traverser); - if (traverser.foundHigherPrecisionConstant()) - traverser.updateTree(); - } while (traverser.foundHigherPrecisionConstant()); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/RecordConstantPrecision.h b/src/3rdparty/angle/src/compiler/translator/RecordConstantPrecision.h deleted file mode 100644 index f86c2a8693..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/RecordConstantPrecision.h +++ /dev/null @@ -1,28 +0,0 @@ -// -// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// During parsing, all constant expressions are folded to constant union nodes. The expressions that -// have been folded may have had precision qualifiers, which should affect the precision of the -// consuming operation. If the folded constant union nodes are written to output as such they won't -// have any precision qualifiers, and their effect on the precision of the consuming operation is -// lost. -// -// RecordConstantPrecision is an AST traverser that inspects the precision qualifiers of constants -// and hoists the constants outside the containing expression as precision qualified named variables -// in case that is required for correct precision propagation. -// - -#ifndef COMPILER_TRANSLATOR_RECORDCONSTANTPRECISION_H_ -#define COMPILER_TRANSLATOR_RECORDCONSTANTPRECISION_H_ - -namespace sh -{ -class TIntermNode; -class TSymbolTable; - -void RecordConstantPrecision(TIntermNode *root, TSymbolTable *symbolTable); -} // namespace sh - -#endif // COMPILER_TRANSLATOR_RECORDCONSTANTPRECISION_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/RegenerateStructNames.cpp b/src/3rdparty/angle/src/compiler/translator/RegenerateStructNames.cpp deleted file mode 100644 index 55fb124a42..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/RegenerateStructNames.cpp +++ /dev/null @@ -1,76 +0,0 @@ -// -// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "common/debug.h" -#include "compiler/translator/RegenerateStructNames.h" - -namespace sh -{ - -void RegenerateStructNames::visitSymbol(TIntermSymbol *symbol) -{ - ASSERT(symbol); - TType *type = symbol->getTypePointer(); - ASSERT(type); - TStructure *userType = type->getStruct(); - if (!userType) - return; - - if (mSymbolTable->findBuiltIn(userType->name(), mShaderVersion)) - { - // Built-in struct, do not touch it. - return; - } - - int uniqueId = userType->uniqueId(); - - ASSERT(mScopeDepth > 0); - if (mScopeDepth == 1) - { - // If a struct is defined at global scope, we don't map its name. - // This is because at global level, the struct might be used to - // declare a uniform, so the same name needs to stay the same for - // vertex/fragment shaders. However, our mapping uses internal ID, - // which will be different for the same struct in vertex/fragment - // shaders. - // This is OK because names for any structs defined in other scopes - // will begin with "_webgl", which is reserved. So there will be - // no conflicts among unmapped struct names from global scope and - // mapped struct names from other scopes. - // However, we need to keep track of these global structs, so if a - // variable is used in a local scope, we don't try to modify the - // struct name through that variable. - mDeclaredGlobalStructs.insert(uniqueId); - return; - } - if (mDeclaredGlobalStructs.count(uniqueId) > 0) - return; - // Map {name} to _webgl_struct_{uniqueId}_{name}. - const char kPrefix[] = "_webgl_struct_"; - if (userType->name().find(kPrefix) == 0) - { - // The name has already been regenerated. - return; - } - std::string id = Str(uniqueId); - TString tmp = kPrefix + TString(id.c_str()); - tmp += "_" + userType->name(); - userType->setName(tmp); -} - -bool RegenerateStructNames::visitBlock(Visit, TIntermBlock *block) -{ - ++mScopeDepth; - TIntermSequence &sequence = *(block->getSequence()); - for (TIntermNode *node : sequence) - { - node->traverse(this); - } - --mScopeDepth; - return false; -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/RegenerateStructNames.h b/src/3rdparty/angle/src/compiler/translator/RegenerateStructNames.h deleted file mode 100644 index 293720b6a4..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/RegenerateStructNames.h +++ /dev/null @@ -1,45 +0,0 @@ -// -// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_TRANSLATOR_REGENERATESTRUCTNAMES_H_ -#define COMPILER_TRANSLATOR_REGENERATESTRUCTNAMES_H_ - -#include "compiler/translator/IntermTraverse.h" -#include "compiler/translator/SymbolTable.h" - -#include - -namespace sh -{ - -class RegenerateStructNames : public TIntermTraverser -{ - public: - RegenerateStructNames(TSymbolTable *symbolTable, int shaderVersion) - : TIntermTraverser(true, false, false, symbolTable), - mShaderVersion(shaderVersion), - mScopeDepth(0) - { - } - - protected: - void visitSymbol(TIntermSymbol *) override; - bool visitBlock(Visit, TIntermBlock *block) override; - - private: - int mShaderVersion; - - // Indicating the depth of the current scope. - // The global scope is 1. - int mScopeDepth; - - // If a struct's declared globally, push its ID in this set. - std::set mDeclaredGlobalStructs; -}; - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_REGENERATESTRUCTNAMES_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/RemoveArrayLengthMethod.cpp b/src/3rdparty/angle/src/compiler/translator/RemoveArrayLengthMethod.cpp deleted file mode 100644 index e9e6a17013..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/RemoveArrayLengthMethod.cpp +++ /dev/null @@ -1,83 +0,0 @@ -// -// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// RemoveArrayLengthMethod.cpp: -// Fold array length expressions, including cases where the "this" node has side effects. -// Example: -// int i = (a = b).length(); -// int j = (func()).length(); -// becomes: -// (a = b); -// int i = ; -// func(); -// int j = ; -// -// Must be run after SplitSequenceOperator, SimplifyLoopConditions and SeparateDeclarations steps -// have been done to expressions containing calls of the array length method. -// -// Does nothing to length method calls done on runtime-sized arrays. - -#include "compiler/translator/RemoveArrayLengthMethod.h" - -#include "compiler/translator/IntermNode.h" -#include "compiler/translator/IntermTraverse.h" - -namespace sh -{ - -namespace -{ - -class RemoveArrayLengthTraverser : public TIntermTraverser -{ - public: - RemoveArrayLengthTraverser() : TIntermTraverser(true, false, false), mFoundArrayLength(false) {} - - bool visitUnary(Visit visit, TIntermUnary *node) override; - - void nextIteration() { mFoundArrayLength = false; } - - bool foundArrayLength() const { return mFoundArrayLength; } - - private: - bool mFoundArrayLength; -}; - -bool RemoveArrayLengthTraverser::visitUnary(Visit visit, TIntermUnary *node) -{ - // The only case where we leave array length() in place is for runtime-sized arrays. - if (node->getOp() == EOpArrayLength && !node->getOperand()->getType().isUnsizedArray()) - { - mFoundArrayLength = true; - if (!node->getOperand()->hasSideEffects()) - { - queueReplacement(node->fold(nullptr), OriginalNode::IS_DROPPED); - return false; - } - insertStatementInParentBlock(node->getOperand()->deepCopy()); - TConstantUnion *constArray = new TConstantUnion[1]; - constArray->setIConst(node->getOperand()->getOutermostArraySize()); - queueReplacement(new TIntermConstantUnion(constArray, node->getType()), - OriginalNode::IS_DROPPED); - return false; - } - return true; -} - -} // anonymous namespace - -void RemoveArrayLengthMethod(TIntermBlock *root) -{ - RemoveArrayLengthTraverser traverser; - do - { - traverser.nextIteration(); - root->traverse(&traverser); - if (traverser.foundArrayLength()) - traverser.updateTree(); - } while (traverser.foundArrayLength()); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/RemoveArrayLengthMethod.h b/src/3rdparty/angle/src/compiler/translator/RemoveArrayLengthMethod.h deleted file mode 100644 index 3b2c6df824..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/RemoveArrayLengthMethod.h +++ /dev/null @@ -1,29 +0,0 @@ -// -// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// RemoveArrayLengthMethod.h: -// Fold array length expressions, including cases where the "this" node has side effects. -// Example: -// int i = (a = b).length(); -// int j = (func()).length(); -// becomes: -// (a = b); -// int i = ; -// func(); -// int j = ; -// -// Must be run after SplitSequenceOperator, SimplifyLoopConditions and SeparateDeclarations steps -// have been done to expressions containing calls of the array length method. -// -// Does nothing to length method calls done on runtime-sized arrays. - -namespace sh -{ - -class TIntermBlock; - -void RemoveArrayLengthMethod(TIntermBlock *root); - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/RemoveDynamicIndexing.cpp b/src/3rdparty/angle/src/compiler/translator/RemoveDynamicIndexing.cpp deleted file mode 100644 index 7766c1abc6..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/RemoveDynamicIndexing.cpp +++ /dev/null @@ -1,550 +0,0 @@ -// -// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// RemoveDynamicIndexing is an AST traverser to remove dynamic indexing of vectors and matrices, -// replacing them with calls to functions that choose which component to return or write. -// - -#include "compiler/translator/RemoveDynamicIndexing.h" - -#include "compiler/translator/Diagnostics.h" -#include "compiler/translator/InfoSink.h" -#include "compiler/translator/IntermNodePatternMatcher.h" -#include "compiler/translator/IntermNode_util.h" -#include "compiler/translator/IntermTraverse.h" -#include "compiler/translator/SymbolTable.h" - -namespace sh -{ - -namespace -{ - -std::string GetIndexFunctionName(const TType &type, bool write) -{ - TInfoSinkBase nameSink; - nameSink << "dyn_index_"; - if (write) - { - nameSink << "write_"; - } - if (type.isMatrix()) - { - nameSink << "mat" << type.getCols() << "x" << type.getRows(); - } - else - { - switch (type.getBasicType()) - { - case EbtInt: - nameSink << "ivec"; - break; - case EbtBool: - nameSink << "bvec"; - break; - case EbtUInt: - nameSink << "uvec"; - break; - case EbtFloat: - nameSink << "vec"; - break; - default: - UNREACHABLE(); - } - nameSink << type.getNominalSize(); - } - return nameSink.str(); -} - -TIntermSymbol *CreateBaseSymbol(const TType &type, TQualifier qualifier, TSymbolTable *symbolTable) -{ - TIntermSymbol *symbol = new TIntermSymbol(symbolTable->nextUniqueId(), "base", type); - symbol->setInternal(true); - symbol->getTypePointer()->setQualifier(qualifier); - return symbol; -} - -TIntermSymbol *CreateIndexSymbol(TSymbolTable *symbolTable) -{ - TIntermSymbol *symbol = - new TIntermSymbol(symbolTable->nextUniqueId(), "index", TType(EbtInt, EbpHigh)); - symbol->setInternal(true); - symbol->getTypePointer()->setQualifier(EvqIn); - return symbol; -} - -TIntermSymbol *CreateValueSymbol(const TType &type, TSymbolTable *symbolTable) -{ - TIntermSymbol *symbol = new TIntermSymbol(symbolTable->nextUniqueId(), "value", type); - symbol->setInternal(true); - symbol->getTypePointer()->setQualifier(EvqIn); - return symbol; -} - -TIntermConstantUnion *CreateIntConstantNode(int i) -{ - TConstantUnion *constant = new TConstantUnion(); - constant->setIConst(i); - return new TIntermConstantUnion(constant, TType(EbtInt, EbpHigh)); -} - -TIntermTyped *EnsureSignedInt(TIntermTyped *node) -{ - if (node->getBasicType() == EbtInt) - return node; - - TIntermSequence *arguments = new TIntermSequence(); - arguments->push_back(node); - return TIntermAggregate::CreateConstructor(TType(EbtInt), arguments); -} - -TType GetFieldType(const TType &indexedType) -{ - if (indexedType.isMatrix()) - { - TType fieldType = TType(indexedType.getBasicType(), indexedType.getPrecision()); - fieldType.setPrimarySize(static_cast(indexedType.getRows())); - return fieldType; - } - else - { - return TType(indexedType.getBasicType(), indexedType.getPrecision()); - } -} - -// Generate a read or write function for one field in a vector/matrix. -// Out-of-range indices are clamped. This is consistent with how ANGLE handles out-of-range -// indices in other places. -// Note that indices can be either int or uint. We create only int versions of the functions, -// and convert uint indices to int at the call site. -// read function example: -// float dyn_index_vec2(in vec2 base, in int index) -// { -// switch(index) -// { -// case (0): -// return base[0]; -// case (1): -// return base[1]; -// default: -// break; -// } -// if (index < 0) -// return base[0]; -// return base[1]; -// } -// write function example: -// void dyn_index_write_vec2(inout vec2 base, in int index, in float value) -// { -// switch(index) -// { -// case (0): -// base[0] = value; -// return; -// case (1): -// base[1] = value; -// return; -// default: -// break; -// } -// if (index < 0) -// { -// base[0] = value; -// return; -// } -// base[1] = value; -// } -// Note that else is not used in above functions to avoid the RewriteElseBlocks transformation. -TIntermFunctionDefinition *GetIndexFunctionDefinition(TType type, - bool write, - const TSymbolUniqueId &functionId, - TSymbolTable *symbolTable) -{ - ASSERT(!type.isArray()); - // Conservatively use highp here, even if the indexed type is not highp. That way the code can't - // end up using mediump version of an indexing function for a highp value, if both mediump and - // highp values are being indexed in the shader. For HLSL precision doesn't matter, but in - // principle this code could be used with multiple backends. - type.setPrecision(EbpHigh); - - TType fieldType = GetFieldType(type); - int numCases = 0; - if (type.isMatrix()) - { - numCases = type.getCols(); - } - else - { - numCases = type.getNominalSize(); - } - - TType returnType(EbtVoid); - if (!write) - { - returnType = fieldType; - } - - std::string functionName = GetIndexFunctionName(type, write); - TIntermFunctionPrototype *prototypeNode = - CreateInternalFunctionPrototypeNode(returnType, functionName.c_str(), functionId); - - TQualifier baseQualifier = EvqInOut; - if (!write) - baseQualifier = EvqIn; - TIntermSymbol *baseParam = CreateBaseSymbol(type, baseQualifier, symbolTable); - prototypeNode->getSequence()->push_back(baseParam); - TIntermSymbol *indexParam = CreateIndexSymbol(symbolTable); - prototypeNode->getSequence()->push_back(indexParam); - TIntermSymbol *valueParam = nullptr; - if (write) - { - valueParam = CreateValueSymbol(fieldType, symbolTable); - prototypeNode->getSequence()->push_back(valueParam); - } - - TIntermBlock *statementList = new TIntermBlock(); - for (int i = 0; i < numCases; ++i) - { - TIntermCase *caseNode = new TIntermCase(CreateIntConstantNode(i)); - statementList->getSequence()->push_back(caseNode); - - TIntermBinary *indexNode = - new TIntermBinary(EOpIndexDirect, baseParam->deepCopy(), CreateIndexNode(i)); - if (write) - { - TIntermBinary *assignNode = - new TIntermBinary(EOpAssign, indexNode, valueParam->deepCopy()); - statementList->getSequence()->push_back(assignNode); - TIntermBranch *returnNode = new TIntermBranch(EOpReturn, nullptr); - statementList->getSequence()->push_back(returnNode); - } - else - { - TIntermBranch *returnNode = new TIntermBranch(EOpReturn, indexNode); - statementList->getSequence()->push_back(returnNode); - } - } - - // Default case - TIntermCase *defaultNode = new TIntermCase(nullptr); - statementList->getSequence()->push_back(defaultNode); - TIntermBranch *breakNode = new TIntermBranch(EOpBreak, nullptr); - statementList->getSequence()->push_back(breakNode); - - TIntermSwitch *switchNode = new TIntermSwitch(indexParam->deepCopy(), statementList); - - TIntermBlock *bodyNode = new TIntermBlock(); - bodyNode->getSequence()->push_back(switchNode); - - TIntermBinary *cond = - new TIntermBinary(EOpLessThan, indexParam->deepCopy(), CreateIntConstantNode(0)); - cond->setType(TType(EbtBool, EbpUndefined)); - - // Two blocks: one accesses (either reads or writes) the first element and returns, - // the other accesses the last element. - TIntermBlock *useFirstBlock = new TIntermBlock(); - TIntermBlock *useLastBlock = new TIntermBlock(); - TIntermBinary *indexFirstNode = - new TIntermBinary(EOpIndexDirect, baseParam->deepCopy(), CreateIndexNode(0)); - TIntermBinary *indexLastNode = - new TIntermBinary(EOpIndexDirect, baseParam->deepCopy(), CreateIndexNode(numCases - 1)); - if (write) - { - TIntermBinary *assignFirstNode = - new TIntermBinary(EOpAssign, indexFirstNode, valueParam->deepCopy()); - useFirstBlock->getSequence()->push_back(assignFirstNode); - TIntermBranch *returnNode = new TIntermBranch(EOpReturn, nullptr); - useFirstBlock->getSequence()->push_back(returnNode); - - TIntermBinary *assignLastNode = - new TIntermBinary(EOpAssign, indexLastNode, valueParam->deepCopy()); - useLastBlock->getSequence()->push_back(assignLastNode); - } - else - { - TIntermBranch *returnFirstNode = new TIntermBranch(EOpReturn, indexFirstNode); - useFirstBlock->getSequence()->push_back(returnFirstNode); - - TIntermBranch *returnLastNode = new TIntermBranch(EOpReturn, indexLastNode); - useLastBlock->getSequence()->push_back(returnLastNode); - } - TIntermIfElse *ifNode = new TIntermIfElse(cond, useFirstBlock, nullptr); - bodyNode->getSequence()->push_back(ifNode); - bodyNode->getSequence()->push_back(useLastBlock); - - TIntermFunctionDefinition *indexingFunction = - new TIntermFunctionDefinition(prototypeNode, bodyNode); - return indexingFunction; -} - -class RemoveDynamicIndexingTraverser : public TLValueTrackingTraverser -{ - public: - RemoveDynamicIndexingTraverser(TSymbolTable *symbolTable, - int shaderVersion, - PerformanceDiagnostics *perfDiagnostics); - - bool visitBinary(Visit visit, TIntermBinary *node) override; - - void insertHelperDefinitions(TIntermNode *root); - - void nextIteration(); - - bool usedTreeInsertion() const { return mUsedTreeInsertion; } - - protected: - // Maps of types that are indexed to the indexing function ids used for them. Note that these - // can not store multiple variants of the same type with different precisions - only one - // precision gets stored. - std::map mIndexedVecAndMatrixTypes; - std::map mWrittenVecAndMatrixTypes; - - bool mUsedTreeInsertion; - - // When true, the traverser will remove side effects from any indexing expression. - // This is done so that in code like - // V[j++][i]++. - // where V is an array of vectors, j++ will only be evaluated once. - bool mRemoveIndexSideEffectsInSubtree; - - PerformanceDiagnostics *mPerfDiagnostics; -}; - -RemoveDynamicIndexingTraverser::RemoveDynamicIndexingTraverser( - TSymbolTable *symbolTable, - int shaderVersion, - PerformanceDiagnostics *perfDiagnostics) - : TLValueTrackingTraverser(true, false, false, symbolTable, shaderVersion), - mUsedTreeInsertion(false), - mRemoveIndexSideEffectsInSubtree(false), - mPerfDiagnostics(perfDiagnostics) -{ -} - -void RemoveDynamicIndexingTraverser::insertHelperDefinitions(TIntermNode *root) -{ - TIntermBlock *rootBlock = root->getAsBlock(); - ASSERT(rootBlock != nullptr); - TIntermSequence insertions; - for (auto &type : mIndexedVecAndMatrixTypes) - { - insertions.push_back( - GetIndexFunctionDefinition(type.first, false, *type.second, mSymbolTable)); - } - for (auto &type : mWrittenVecAndMatrixTypes) - { - insertions.push_back( - GetIndexFunctionDefinition(type.first, true, *type.second, mSymbolTable)); - } - rootBlock->insertChildNodes(0, insertions); -} - -// Create a call to dyn_index_*() based on an indirect indexing op node -TIntermAggregate *CreateIndexFunctionCall(TIntermBinary *node, - TIntermTyped *index, - const TSymbolUniqueId &functionId) -{ - ASSERT(node->getOp() == EOpIndexIndirect); - TIntermSequence *arguments = new TIntermSequence(); - arguments->push_back(node->getLeft()); - arguments->push_back(index); - - TType fieldType = GetFieldType(node->getLeft()->getType()); - std::string functionName = GetIndexFunctionName(node->getLeft()->getType(), false); - TIntermAggregate *indexingCall = - CreateInternalFunctionCallNode(fieldType, functionName.c_str(), functionId, arguments); - indexingCall->setLine(node->getLine()); - indexingCall->getFunctionSymbolInfo()->setKnownToNotHaveSideEffects(true); - return indexingCall; -} - -TIntermAggregate *CreateIndexedWriteFunctionCall(TIntermBinary *node, - TIntermTyped *index, - TIntermTyped *writtenValue, - const TSymbolUniqueId &functionId) -{ - ASSERT(node->getOp() == EOpIndexIndirect); - TIntermSequence *arguments = new TIntermSequence(); - // Deep copy the child nodes so that two pointers to the same node don't end up in the tree. - arguments->push_back(node->getLeft()->deepCopy()); - arguments->push_back(index->deepCopy()); - arguments->push_back(writtenValue); - - std::string functionName = GetIndexFunctionName(node->getLeft()->getType(), true); - TIntermAggregate *indexedWriteCall = - CreateInternalFunctionCallNode(TType(EbtVoid), functionName.c_str(), functionId, arguments); - indexedWriteCall->setLine(node->getLine()); - return indexedWriteCall; -} - -bool RemoveDynamicIndexingTraverser::visitBinary(Visit visit, TIntermBinary *node) -{ - if (mUsedTreeInsertion) - return false; - - if (node->getOp() == EOpIndexIndirect) - { - if (mRemoveIndexSideEffectsInSubtree) - { - ASSERT(node->getRight()->hasSideEffects()); - // In case we're just removing index side effects, convert - // v_expr[index_expr] - // to this: - // int s0 = index_expr; v_expr[s0]; - // Now v_expr[s0] can be safely executed several times without unintended side effects. - - // Init the temp variable holding the index - TIntermDeclaration *initIndex = createTempInitDeclaration(node->getRight()); - insertStatementInParentBlock(initIndex); - mUsedTreeInsertion = true; - - // Replace the index with the temp variable - TIntermSymbol *tempIndex = createTempSymbol(node->getRight()->getType()); - queueReplacementWithParent(node, node->getRight(), tempIndex, OriginalNode::IS_DROPPED); - } - else if (IntermNodePatternMatcher::IsDynamicIndexingOfVectorOrMatrix(node)) - { - mPerfDiagnostics->warning(node->getLine(), - "Performance: dynamic indexing of vectors and " - "matrices is emulated and can be slow.", - "[]"); - bool write = isLValueRequiredHere(); - -#if defined(ANGLE_ENABLE_ASSERTS) - // Make sure that IntermNodePatternMatcher is consistent with the slightly differently - // implemented checks in this traverser. - IntermNodePatternMatcher matcher( - IntermNodePatternMatcher::kDynamicIndexingOfVectorOrMatrixInLValue); - ASSERT(matcher.match(node, getParentNode(), isLValueRequiredHere()) == write); -#endif - - const TType &type = node->getLeft()->getType(); - TSymbolUniqueId *indexingFunctionId = new TSymbolUniqueId(mSymbolTable); - if (mIndexedVecAndMatrixTypes.find(type) == mIndexedVecAndMatrixTypes.end()) - { - mIndexedVecAndMatrixTypes[type] = indexingFunctionId; - } - else - { - indexingFunctionId = mIndexedVecAndMatrixTypes[type]; - } - - if (write) - { - // Convert: - // v_expr[index_expr]++; - // to this: - // int s0 = index_expr; float s1 = dyn_index(v_expr, s0); s1++; - // dyn_index_write(v_expr, s0, s1); - // This works even if index_expr has some side effects. - if (node->getLeft()->hasSideEffects()) - { - // If v_expr has side effects, those need to be removed before proceeding. - // Otherwise the side effects of v_expr would be evaluated twice. - // The only case where an l-value can have side effects is when it is - // indexing. For example, it can be V[j++] where V is an array of vectors. - mRemoveIndexSideEffectsInSubtree = true; - return true; - } - - TIntermBinary *leftBinary = node->getLeft()->getAsBinaryNode(); - if (leftBinary != nullptr && - IntermNodePatternMatcher::IsDynamicIndexingOfVectorOrMatrix(leftBinary)) - { - // This is a case like: - // mat2 m; - // m[a][b]++; - // Process the child node m[a] first. - return true; - } - - // TODO(oetuaho@nvidia.com): This is not optimal if the expression using the value - // only writes it and doesn't need the previous value. http://anglebug.com/1116 - - TSymbolUniqueId *indexedWriteFunctionId = new TSymbolUniqueId(mSymbolTable); - if (mWrittenVecAndMatrixTypes.find(type) == mWrittenVecAndMatrixTypes.end()) - { - mWrittenVecAndMatrixTypes[type] = indexedWriteFunctionId; - } - else - { - indexedWriteFunctionId = mWrittenVecAndMatrixTypes[type]; - } - TType fieldType = GetFieldType(type); - - TIntermSequence insertionsBefore; - TIntermSequence insertionsAfter; - - // Store the index in a temporary signed int variable. - TIntermTyped *indexInitializer = EnsureSignedInt(node->getRight()); - TIntermDeclaration *initIndex = createTempInitDeclaration(indexInitializer); - initIndex->setLine(node->getLine()); - insertionsBefore.push_back(initIndex); - - // Create a node for referring to the index after the nextTemporaryId() call - // below. - TIntermSymbol *tempIndex = createTempSymbol(indexInitializer->getType()); - - TIntermAggregate *indexingCall = - CreateIndexFunctionCall(node, tempIndex, *indexingFunctionId); - - nextTemporaryId(); // From now on, creating temporary symbols that refer to the - // field value. - insertionsBefore.push_back(createTempInitDeclaration(indexingCall)); - - TIntermAggregate *indexedWriteCall = CreateIndexedWriteFunctionCall( - node, tempIndex, createTempSymbol(fieldType), *indexedWriteFunctionId); - insertionsAfter.push_back(indexedWriteCall); - insertStatementsInParentBlock(insertionsBefore, insertionsAfter); - queueReplacement(createTempSymbol(fieldType), OriginalNode::IS_DROPPED); - mUsedTreeInsertion = true; - } - else - { - // The indexed value is not being written, so we can simply convert - // v_expr[index_expr] - // into - // dyn_index(v_expr, index_expr) - // If the index_expr is unsigned, we'll convert it to signed. - ASSERT(!mRemoveIndexSideEffectsInSubtree); - TIntermAggregate *indexingCall = CreateIndexFunctionCall( - node, EnsureSignedInt(node->getRight()), *indexingFunctionId); - queueReplacement(indexingCall, OriginalNode::IS_DROPPED); - } - } - } - return !mUsedTreeInsertion; -} - -void RemoveDynamicIndexingTraverser::nextIteration() -{ - mUsedTreeInsertion = false; - mRemoveIndexSideEffectsInSubtree = false; - nextTemporaryId(); -} - -} // namespace - -void RemoveDynamicIndexing(TIntermNode *root, - TSymbolTable *symbolTable, - int shaderVersion, - PerformanceDiagnostics *perfDiagnostics) -{ - RemoveDynamicIndexingTraverser traverser(symbolTable, shaderVersion, perfDiagnostics); - do - { - traverser.nextIteration(); - root->traverse(&traverser); - traverser.updateTree(); - } while (traverser.usedTreeInsertion()); - // TODO(oetuaho@nvidia.com): It might be nicer to add the helper definitions also in the middle - // of traversal. Now the tree ends up in an inconsistent state in the middle, since there are - // function call nodes with no corresponding definition nodes. This needs special handling in - // TIntermLValueTrackingTraverser, and creates intricacies that are not easily apparent from a - // superficial reading of the code. - traverser.insertHelperDefinitions(root); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/RemoveDynamicIndexing.h b/src/3rdparty/angle/src/compiler/translator/RemoveDynamicIndexing.h deleted file mode 100644 index 543cf569a6..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/RemoveDynamicIndexing.h +++ /dev/null @@ -1,27 +0,0 @@ -// -// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// RemoveDynamicIndexing is an AST traverser to remove dynamic indexing of vectors and matrices, -// replacing them with calls to functions that choose which component to return or write. -// - -#ifndef COMPILER_TRANSLATOR_REMOVEDYNAMICINDEXING_H_ -#define COMPILER_TRANSLATOR_REMOVEDYNAMICINDEXING_H_ - -namespace sh -{ - -class TIntermNode; -class TSymbolTable; -class PerformanceDiagnostics; - -void RemoveDynamicIndexing(TIntermNode *root, - TSymbolTable *symbolTable, - int shaderVersion, - PerformanceDiagnostics *perfDiagnostics); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_REMOVEDYNAMICINDEXING_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/RemoveEmptySwitchStatements.cpp b/src/3rdparty/angle/src/compiler/translator/RemoveEmptySwitchStatements.cpp deleted file mode 100644 index b39c912e9c..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/RemoveEmptySwitchStatements.cpp +++ /dev/null @@ -1,56 +0,0 @@ -// -// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// RemoveEmptySwitchStatements.cpp: Remove switch statements that have an empty statement list. - -#include "compiler/translator/RemoveEmptySwitchStatements.h" - -#include "compiler/translator/IntermTraverse.h" - -namespace sh -{ - -namespace -{ - -class RemoveEmptySwitchStatementsTraverser : public TIntermTraverser -{ - public: - RemoveEmptySwitchStatementsTraverser() : TIntermTraverser(true, false, false) {} - - bool visitSwitch(Visit visit, TIntermSwitch *node); -}; - -bool RemoveEmptySwitchStatementsTraverser::visitSwitch(Visit visit, TIntermSwitch *node) -{ - if (node->getStatementList()->getSequence()->empty()) - { - // Just output the init statement. - if (node->getInit()->hasSideEffects()) - { - queueReplacement(node->getInit(), OriginalNode::IS_DROPPED); - } - else - { - TIntermSequence emptyReplacement; - ASSERT(getParentNode()->getAsBlock()); - mMultiReplacements.push_back(NodeReplaceWithMultipleEntry(getParentNode()->getAsBlock(), - node, emptyReplacement)); - } - return false; // Nothing inside the child nodes to traverse. - } - return true; -} - -} // anonymous namespace - -void RemoveEmptySwitchStatements(TIntermBlock *root) -{ - RemoveEmptySwitchStatementsTraverser traverser; - root->traverse(&traverser); - traverser.updateTree(); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/RemoveEmptySwitchStatements.h b/src/3rdparty/angle/src/compiler/translator/RemoveEmptySwitchStatements.h deleted file mode 100644 index 1018a50d82..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/RemoveEmptySwitchStatements.h +++ /dev/null @@ -1,18 +0,0 @@ -// -// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// RemoveEmptySwitchStatements.h: Remove switch statements that have an empty statement list. - -#ifndef COMPILER_TRANSLATOR_REMOVEEMPTYSWITCHSTATEMENTS_H_ -#define COMPILER_TRANSLATOR_REMOVEEMPTYSWITCHSTATEMENTS_H_ - -namespace sh -{ -class TIntermBlock; - -void RemoveEmptySwitchStatements(TIntermBlock *root); -} - -#endif // COMPILER_TRANSLATOR_REMOVEEMPTYSWITCHSTATEMENTS_H_ \ No newline at end of file diff --git a/src/3rdparty/angle/src/compiler/translator/RemoveInvariantDeclaration.cpp b/src/3rdparty/angle/src/compiler/translator/RemoveInvariantDeclaration.cpp deleted file mode 100644 index 4b533dc7b5..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/RemoveInvariantDeclaration.cpp +++ /dev/null @@ -1,43 +0,0 @@ -// -// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/translator/RemoveInvariantDeclaration.h" - -#include "compiler/translator/IntermTraverse.h" - -namespace sh -{ - -namespace -{ - -// An AST traverser that removes invariant declaration for input in fragment shader -// when GLSL >= 4.20 and for output in vertex shader when GLSL < 4.2. -class RemoveInvariantDeclarationTraverser : public TIntermTraverser -{ - public: - RemoveInvariantDeclarationTraverser() : TIntermTraverser(true, false, false) {} - - private: - bool visitInvariantDeclaration(Visit visit, TIntermInvariantDeclaration *node) override - { - TIntermSequence emptyReplacement; - mMultiReplacements.push_back( - NodeReplaceWithMultipleEntry(getParentNode()->getAsBlock(), node, emptyReplacement)); - return false; - } -}; - -} // anonymous namespace - -void RemoveInvariantDeclaration(TIntermNode *root) -{ - RemoveInvariantDeclarationTraverser traverser; - root->traverse(&traverser); - traverser.updateTree(); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/RemoveInvariantDeclaration.h b/src/3rdparty/angle/src/compiler/translator/RemoveInvariantDeclaration.h deleted file mode 100644 index cf9d4aa4c2..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/RemoveInvariantDeclaration.h +++ /dev/null @@ -1,18 +0,0 @@ -// -// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_TRANSLATOR_REMOVEINVARIANTDECLARATION_H_ -#define COMPILER_TRANSLATOR_REMOVEINVARIANTDECLARATION_H_ - -class TIntermNode; -namespace sh -{ - -void RemoveInvariantDeclaration(TIntermNode *root); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_REMOVEINVARIANTDECLARATION_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/RemoveNoOpCasesFromEndOfSwitchStatements.cpp b/src/3rdparty/angle/src/compiler/translator/RemoveNoOpCasesFromEndOfSwitchStatements.cpp deleted file mode 100644 index b86d64d7a3..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/RemoveNoOpCasesFromEndOfSwitchStatements.cpp +++ /dev/null @@ -1,116 +0,0 @@ -// -// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// RemoveNoOpCasesFromEndOfSwitchStatements.cpp: Clean up cases from the end of a switch statement -// that only contain no-ops. - -#include "compiler/translator/RemoveNoOpCasesFromEndOfSwitchStatements.h" - -#include "compiler/translator/IntermNode.h" -#include "compiler/translator/IntermNode_util.h" -#include "compiler/translator/IntermTraverse.h" -#include "compiler/translator/SymbolTable.h" - -namespace sh -{ - -namespace -{ - -bool AreEmptyBlocks(TIntermSequence *statements, size_t i); - -bool IsEmptyBlock(TIntermNode *node) -{ - TIntermBlock *asBlock = node->getAsBlock(); - if (asBlock) - { - if (asBlock->getSequence()->empty()) - { - return true; - } - return AreEmptyBlocks(asBlock->getSequence(), 0u); - } - // Empty declarations should have already been pruned, otherwise they would need to be handled - // here. Note that declarations for struct types do contain a nameless child node. - ASSERT(node->getAsDeclarationNode() == nullptr || - !node->getAsDeclarationNode()->getSequence()->empty()); - // Pure literal statements should also already be pruned. - ASSERT(node->getAsConstantUnion() == nullptr); - return false; -} - -// Return true if all statements in "statements" starting from index i consist only of empty blocks -// and no-op statements. Returns true also if there are no statements. -bool AreEmptyBlocks(TIntermSequence *statements, size_t i) -{ - for (; i < statements->size(); ++i) - { - if (!IsEmptyBlock(statements->at(i))) - { - return false; - } - } - return true; -} - -void RemoveNoOpCasesFromEndOfStatementList(TIntermBlock *statementList, TSymbolTable *symbolTable) -{ - TIntermSequence *statements = statementList->getSequence(); - - bool foundDeadCase = false; - do - { - if (statements->empty()) - { - return; - } - - // Find the last case label. - size_t i = statements->size(); - while (i > 0u && !(*statements)[i - 1]->getAsCaseNode()) - { - --i; - } - // Now i is the index of the first statement following the last label inside the switch - // statement. - ASSERT(i > 0u); - - foundDeadCase = AreEmptyBlocks(statements, i); - if (foundDeadCase) - { - statements->erase(statements->begin() + (i - 1u), statements->end()); - } - } while (foundDeadCase); -} - -class RemoveNoOpCasesFromEndOfSwitchTraverser : public TIntermTraverser -{ - public: - RemoveNoOpCasesFromEndOfSwitchTraverser(TSymbolTable *symbolTable) - : TIntermTraverser(true, false, false, symbolTable) - { - } - - bool visitSwitch(Visit visit, TIntermSwitch *node) override; -}; - -bool RemoveNoOpCasesFromEndOfSwitchTraverser::visitSwitch(Visit visit, TIntermSwitch *node) -{ - // Here we may mutate the statement list, but it's safe since traversal has not yet reached - // there. - RemoveNoOpCasesFromEndOfStatementList(node->getStatementList(), mSymbolTable); - // Handle also nested switch statements. - return true; -} - -} // anonymous namespace - -void RemoveNoOpCasesFromEndOfSwitchStatements(TIntermBlock *root, TSymbolTable *symbolTable) -{ - RemoveNoOpCasesFromEndOfSwitchTraverser traverser(symbolTable); - root->traverse(&traverser); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/RemoveNoOpCasesFromEndOfSwitchStatements.h b/src/3rdparty/angle/src/compiler/translator/RemoveNoOpCasesFromEndOfSwitchStatements.h deleted file mode 100644 index ebd75eb774..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/RemoveNoOpCasesFromEndOfSwitchStatements.h +++ /dev/null @@ -1,21 +0,0 @@ -// -// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// RemoveNoOpCasesFromEndOfSwitchStatements.h: Clean up cases from the end of a switch statement -// that only contain no-ops. - -#ifndef COMPILER_TRANSLATOR_REMOVENOOPCASESFROMENDOFSWITCHSTATEMENTS_H_ -#define COMPILER_TRANSLATOR_REMOVENOOPCASESFROMENDOFSWITCHSTATEMENTS_H_ - -namespace sh -{ -class TIntermBlock; -class TSymbolTable; - -void RemoveNoOpCasesFromEndOfSwitchStatements(TIntermBlock *root, TSymbolTable *symbolTable); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_REMOVENOOPCASESFROMENDOFSWITCHSTATEMENTS_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/RemovePow.cpp b/src/3rdparty/angle/src/compiler/translator/RemovePow.cpp deleted file mode 100644 index b2cdac55f0..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/RemovePow.cpp +++ /dev/null @@ -1,97 +0,0 @@ -// -// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// RemovePow is an AST traverser to convert pow(x, y) built-in calls where y is a -// constant to exp2(y * log2(x)). This works around an issue in NVIDIA 311 series -// OpenGL drivers. -// - -#include "compiler/translator/RemovePow.h" - -#include "compiler/translator/InfoSink.h" -#include "compiler/translator/IntermTraverse.h" - -namespace sh -{ - -namespace -{ - -bool IsProblematicPow(TIntermTyped *node) -{ - TIntermAggregate *agg = node->getAsAggregate(); - if (agg != nullptr && agg->getOp() == EOpPow) - { - ASSERT(agg->getSequence()->size() == 2); - return agg->getSequence()->at(1)->getAsConstantUnion() != nullptr; - } - return false; -} - -// Traverser that converts all pow operations simultaneously. -class RemovePowTraverser : public TIntermTraverser -{ - public: - RemovePowTraverser(); - - bool visitAggregate(Visit visit, TIntermAggregate *node) override; - - void nextIteration() { mNeedAnotherIteration = false; } - bool needAnotherIteration() const { return mNeedAnotherIteration; } - - protected: - bool mNeedAnotherIteration; -}; - -RemovePowTraverser::RemovePowTraverser() - : TIntermTraverser(true, false, false), mNeedAnotherIteration(false) -{ -} - -bool RemovePowTraverser::visitAggregate(Visit visit, TIntermAggregate *node) -{ - if (IsProblematicPow(node)) - { - TIntermTyped *x = node->getSequence()->at(0)->getAsTyped(); - TIntermTyped *y = node->getSequence()->at(1)->getAsTyped(); - - TIntermUnary *log = new TIntermUnary(EOpLog2, x); - log->setLine(node->getLine()); - - TOperator op = TIntermBinary::GetMulOpBasedOnOperands(y->getType(), log->getType()); - TIntermBinary *mul = new TIntermBinary(op, y, log); - mul->setLine(node->getLine()); - - TIntermUnary *exp = new TIntermUnary(EOpExp2, mul); - exp->setLine(node->getLine()); - - queueReplacement(exp, OriginalNode::IS_DROPPED); - - // If the x parameter also needs to be replaced, we need to do that in another traversal, - // since it's parent node will change in a way that's not handled correctly by updateTree(). - if (IsProblematicPow(x)) - { - mNeedAnotherIteration = true; - return false; - } - } - return true; -} - -} // namespace - -void RemovePow(TIntermNode *root) -{ - RemovePowTraverser traverser; - // Iterate as necessary, and reset the traverser between iterations. - do - { - traverser.nextIteration(); - root->traverse(&traverser); - traverser.updateTree(); - } while (traverser.needAnotherIteration()); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/RemovePow.h b/src/3rdparty/angle/src/compiler/translator/RemovePow.h deleted file mode 100644 index 3cd84988a9..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/RemovePow.h +++ /dev/null @@ -1,21 +0,0 @@ -// -// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// RemovePow is an AST traverser to convert pow(x, y) built-in calls where y is a -// constant to exp2(y * log2(x)). This works around an issue in NVIDIA 311 series -// OpenGL drivers. -// - -#ifndef COMPILER_TRANSLATOR_REMOVEPOW_H_ -#define COMPILER_TRANSLATOR_REMOVEPOW_H_ - -namespace sh -{ -class TIntermNode; - -void RemovePow(TIntermNode *root); -} // namespace sh - -#endif // COMPILER_TRANSLATOR_REMOVEPOW_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/RemoveSwitchFallThrough.cpp b/src/3rdparty/angle/src/compiler/translator/RemoveSwitchFallThrough.cpp deleted file mode 100644 index dea949f448..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/RemoveSwitchFallThrough.cpp +++ /dev/null @@ -1,270 +0,0 @@ -// -// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// RemoveSwitchFallThrough.cpp: Remove fall-through from switch statements. -// Note that it is unsafe to do further AST transformations on the AST generated -// by this function. It leaves duplicate nodes in the AST making replacements -// unreliable. - -#include "compiler/translator/RemoveSwitchFallThrough.h" - -#include "compiler/translator/Diagnostics.h" -#include "compiler/translator/IntermTraverse.h" - -namespace sh -{ - -namespace -{ - -class RemoveSwitchFallThroughTraverser : public TIntermTraverser -{ - public: - static TIntermBlock *removeFallThrough(TIntermBlock *statementList, - PerformanceDiagnostics *perfDiagnostics); - - private: - RemoveSwitchFallThroughTraverser(TIntermBlock *statementList, - PerformanceDiagnostics *perfDiagnostics); - - void visitSymbol(TIntermSymbol *node) override; - void visitConstantUnion(TIntermConstantUnion *node) override; - bool visitDeclaration(Visit, TIntermDeclaration *node) override; - bool visitBinary(Visit, TIntermBinary *node) override; - bool visitUnary(Visit, TIntermUnary *node) override; - bool visitTernary(Visit visit, TIntermTernary *node) override; - bool visitSwizzle(Visit, TIntermSwizzle *node) override; - bool visitIfElse(Visit visit, TIntermIfElse *node) override; - bool visitSwitch(Visit, TIntermSwitch *node) override; - bool visitCase(Visit, TIntermCase *node) override; - bool visitAggregate(Visit, TIntermAggregate *node) override; - bool visitBlock(Visit, TIntermBlock *node) override; - bool visitLoop(Visit, TIntermLoop *node) override; - bool visitBranch(Visit, TIntermBranch *node) override; - - void outputSequence(TIntermSequence *sequence, size_t startIndex); - void handlePreviousCase(); - - TIntermBlock *mStatementList; - TIntermBlock *mStatementListOut; - bool mLastStatementWasBreak; - TIntermBlock *mPreviousCase; - std::vector mCasesSharingBreak; - PerformanceDiagnostics *mPerfDiagnostics; -}; - -TIntermBlock *RemoveSwitchFallThroughTraverser::removeFallThrough( - TIntermBlock *statementList, - PerformanceDiagnostics *perfDiagnostics) -{ - RemoveSwitchFallThroughTraverser rm(statementList, perfDiagnostics); - ASSERT(statementList); - statementList->traverse(&rm); - ASSERT(rm.mPreviousCase || statementList->getSequence()->empty()); - if (!rm.mLastStatementWasBreak && rm.mPreviousCase) - { - // Make sure that there's a branch at the end of the final case inside the switch statement. - // This also ensures that any cases that fall through to the final case will get the break. - TIntermBranch *finalBreak = new TIntermBranch(EOpBreak, nullptr); - rm.mPreviousCase->getSequence()->push_back(finalBreak); - rm.mLastStatementWasBreak = true; - } - rm.handlePreviousCase(); - return rm.mStatementListOut; -} - -RemoveSwitchFallThroughTraverser::RemoveSwitchFallThroughTraverser( - TIntermBlock *statementList, - PerformanceDiagnostics *perfDiagnostics) - : TIntermTraverser(true, false, false), - mStatementList(statementList), - mLastStatementWasBreak(false), - mPreviousCase(nullptr), - mPerfDiagnostics(perfDiagnostics) -{ - mStatementListOut = new TIntermBlock(); -} - -void RemoveSwitchFallThroughTraverser::visitSymbol(TIntermSymbol *node) -{ - // Note that this assumes that switch statements which don't begin by a case statement - // have already been weeded out in validation. - mPreviousCase->getSequence()->push_back(node); - mLastStatementWasBreak = false; -} - -void RemoveSwitchFallThroughTraverser::visitConstantUnion(TIntermConstantUnion *node) -{ - // Conditions of case labels are not traversed, so this is a constant statement like "0;". - // These are no-ops so there's no need to add them back to the statement list. Should have - // already been pruned out of the AST, in fact. - UNREACHABLE(); -} - -bool RemoveSwitchFallThroughTraverser::visitDeclaration(Visit, TIntermDeclaration *node) -{ - mPreviousCase->getSequence()->push_back(node); - mLastStatementWasBreak = false; - return false; -} - -bool RemoveSwitchFallThroughTraverser::visitBinary(Visit, TIntermBinary *node) -{ - mPreviousCase->getSequence()->push_back(node); - mLastStatementWasBreak = false; - return false; -} - -bool RemoveSwitchFallThroughTraverser::visitUnary(Visit, TIntermUnary *node) -{ - mPreviousCase->getSequence()->push_back(node); - mLastStatementWasBreak = false; - return false; -} - -bool RemoveSwitchFallThroughTraverser::visitTernary(Visit, TIntermTernary *node) -{ - mPreviousCase->getSequence()->push_back(node); - mLastStatementWasBreak = false; - return false; -} - -bool RemoveSwitchFallThroughTraverser::visitSwizzle(Visit, TIntermSwizzle *node) -{ - mPreviousCase->getSequence()->push_back(node); - mLastStatementWasBreak = false; - return false; -} - -bool RemoveSwitchFallThroughTraverser::visitIfElse(Visit, TIntermIfElse *node) -{ - mPreviousCase->getSequence()->push_back(node); - mLastStatementWasBreak = false; - return false; -} - -bool RemoveSwitchFallThroughTraverser::visitSwitch(Visit, TIntermSwitch *node) -{ - mPreviousCase->getSequence()->push_back(node); - mLastStatementWasBreak = false; - // Don't go into nested switch statements - return false; -} - -void RemoveSwitchFallThroughTraverser::outputSequence(TIntermSequence *sequence, size_t startIndex) -{ - for (size_t i = startIndex; i < sequence->size(); ++i) - { - mStatementListOut->getSequence()->push_back(sequence->at(i)); - } -} - -void RemoveSwitchFallThroughTraverser::handlePreviousCase() -{ - if (mPreviousCase) - mCasesSharingBreak.push_back(mPreviousCase); - if (mLastStatementWasBreak) - { - for (size_t i = 0; i < mCasesSharingBreak.size(); ++i) - { - ASSERT(!mCasesSharingBreak.at(i)->getSequence()->empty()); - if (mCasesSharingBreak.at(i)->getSequence()->size() == 1) - { - // Fall-through is allowed in case the label has no statements. - outputSequence(mCasesSharingBreak.at(i)->getSequence(), 0); - } - else - { - // Include all the statements that this case can fall through under the same label. - if (mCasesSharingBreak.size() > i + 1u) - { - mPerfDiagnostics->warning(mCasesSharingBreak.at(i)->getLine(), - "Performance: non-empty fall-through cases in " - "switch statements generate extra code.", - "switch"); - } - for (size_t j = i; j < mCasesSharingBreak.size(); ++j) - { - size_t startIndex = - j > i ? 1 : 0; // Add the label only from the first sequence. - outputSequence(mCasesSharingBreak.at(j)->getSequence(), startIndex); - } - } - } - mCasesSharingBreak.clear(); - } - mLastStatementWasBreak = false; - mPreviousCase = nullptr; -} - -bool RemoveSwitchFallThroughTraverser::visitCase(Visit, TIntermCase *node) -{ - handlePreviousCase(); - mPreviousCase = new TIntermBlock(); - mPreviousCase->getSequence()->push_back(node); - mPreviousCase->setLine(node->getLine()); - // Don't traverse the condition of the case statement - return false; -} - -bool RemoveSwitchFallThroughTraverser::visitAggregate(Visit, TIntermAggregate *node) -{ - mPreviousCase->getSequence()->push_back(node); - mLastStatementWasBreak = false; - return false; -} - -bool DoesBlockAlwaysBreak(TIntermBlock *node) -{ - if (node->getSequence()->empty()) - { - return false; - } - - TIntermBlock *lastStatementAsBlock = node->getSequence()->back()->getAsBlock(); - if (lastStatementAsBlock) - { - return DoesBlockAlwaysBreak(lastStatementAsBlock); - } - - TIntermBranch *lastStatementAsBranch = node->getSequence()->back()->getAsBranchNode(); - return lastStatementAsBranch != nullptr; -} - -bool RemoveSwitchFallThroughTraverser::visitBlock(Visit, TIntermBlock *node) -{ - if (node != mStatementList) - { - mPreviousCase->getSequence()->push_back(node); - mLastStatementWasBreak = DoesBlockAlwaysBreak(node); - return false; - } - return true; -} - -bool RemoveSwitchFallThroughTraverser::visitLoop(Visit, TIntermLoop *node) -{ - mPreviousCase->getSequence()->push_back(node); - mLastStatementWasBreak = false; - return false; -} - -bool RemoveSwitchFallThroughTraverser::visitBranch(Visit, TIntermBranch *node) -{ - mPreviousCase->getSequence()->push_back(node); - // TODO: Verify that accepting return or continue statements here doesn't cause problems. - mLastStatementWasBreak = true; - return false; -} - -} // anonymous namespace - -TIntermBlock *RemoveSwitchFallThrough(TIntermBlock *statementList, - PerformanceDiagnostics *perfDiagnostics) -{ - return RemoveSwitchFallThroughTraverser::removeFallThrough(statementList, perfDiagnostics); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/RemoveSwitchFallThrough.h b/src/3rdparty/angle/src/compiler/translator/RemoveSwitchFallThrough.h deleted file mode 100644 index 7a3b1963f2..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/RemoveSwitchFallThrough.h +++ /dev/null @@ -1,27 +0,0 @@ -// -// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// RemoveSwitchFallThrough.h: Remove fall-through from switch statements. -// Note that it is unsafe to do further AST transformations on the AST generated -// by this function. It leaves duplicate nodes in the AST making replacements -// unreliable. - -#ifndef COMPILER_TRANSLATOR_REMOVESWITCHFALLTHROUGH_H_ -#define COMPILER_TRANSLATOR_REMOVESWITCHFALLTHROUGH_H_ - -namespace sh -{ - -class TIntermBlock; -class PerformanceDiagnostics; - -// When given a statementList from a switch AST node, return an updated -// statementList that has fall-through removed. -TIntermBlock *RemoveSwitchFallThrough(TIntermBlock *statementList, - PerformanceDiagnostics *perfDiagnostics); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_REMOVESWITCHFALLTHROUGH_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/RemoveUnreferencedVariables.cpp b/src/3rdparty/angle/src/compiler/translator/RemoveUnreferencedVariables.cpp deleted file mode 100644 index 74b5e73f71..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/RemoveUnreferencedVariables.cpp +++ /dev/null @@ -1,358 +0,0 @@ -// -// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// RemoveUnreferencedVariables.cpp: -// Drop variables that are declared but never referenced in the AST. This avoids adding unnecessary -// initialization code for them. Also removes unreferenced struct types. -// - -#include "compiler/translator/RemoveUnreferencedVariables.h" - -#include "compiler/translator/IntermTraverse.h" -#include "compiler/translator/SymbolTable.h" - -namespace sh -{ - -namespace -{ - -class CollectVariableRefCountsTraverser : public TIntermTraverser -{ - public: - CollectVariableRefCountsTraverser(); - - using RefCountMap = std::unordered_map; - RefCountMap &getSymbolIdRefCounts() { return mSymbolIdRefCounts; } - RefCountMap &getStructIdRefCounts() { return mStructIdRefCounts; } - - void visitSymbol(TIntermSymbol *node) override; - bool visitAggregate(Visit visit, TIntermAggregate *node) override; - bool visitFunctionPrototype(Visit visit, TIntermFunctionPrototype *node) override; - - private: - void incrementStructTypeRefCount(const TType &type); - - RefCountMap mSymbolIdRefCounts; - - // Structure reference counts are counted from symbols, constructors, function calls, function - // return values and from interface block and structure fields. We need to track both function - // calls and function return values since there's a compiler option not to prune unused - // functions. The type of a constant union may also be a struct, but statements that are just a - // constant union are always pruned, and if the constant union is used somehow it will get - // counted by something else. - RefCountMap mStructIdRefCounts; -}; - -CollectVariableRefCountsTraverser::CollectVariableRefCountsTraverser() - : TIntermTraverser(true, false, false) -{ -} - -void CollectVariableRefCountsTraverser::incrementStructTypeRefCount(const TType &type) -{ - if (type.isInterfaceBlock()) - { - const auto *block = type.getInterfaceBlock(); - ASSERT(block); - - // We can end up incrementing ref counts of struct types referenced from an interface block - // multiple times for the same block. This doesn't matter, because interface blocks can't be - // pruned so we'll never do the reverse operation. - for (const auto &field : block->fields()) - { - ASSERT(!field->type()->isInterfaceBlock()); - incrementStructTypeRefCount(*field->type()); - } - return; - } - - const auto *structure = type.getStruct(); - if (structure != nullptr) - { - auto structIter = mStructIdRefCounts.find(structure->uniqueId()); - if (structIter == mStructIdRefCounts.end()) - { - mStructIdRefCounts[structure->uniqueId()] = 1u; - - for (const auto &field : structure->fields()) - { - incrementStructTypeRefCount(*field->type()); - } - - return; - } - ++(structIter->second); - } -} - -void CollectVariableRefCountsTraverser::visitSymbol(TIntermSymbol *node) -{ - incrementStructTypeRefCount(node->getType()); - - auto iter = mSymbolIdRefCounts.find(node->getId()); - if (iter == mSymbolIdRefCounts.end()) - { - mSymbolIdRefCounts[node->getId()] = 1u; - return; - } - ++(iter->second); -} - -bool CollectVariableRefCountsTraverser::visitAggregate(Visit visit, TIntermAggregate *node) -{ - // This tracks struct references in both function calls and constructors. - incrementStructTypeRefCount(node->getType()); - return true; -} - -bool CollectVariableRefCountsTraverser::visitFunctionPrototype(Visit visit, - TIntermFunctionPrototype *node) -{ - incrementStructTypeRefCount(node->getType()); - return true; -} - -// Traverser that removes all unreferenced variables on one traversal. -class RemoveUnreferencedVariablesTraverser : public TIntermTraverser -{ - public: - RemoveUnreferencedVariablesTraverser( - CollectVariableRefCountsTraverser::RefCountMap *symbolIdRefCounts, - CollectVariableRefCountsTraverser::RefCountMap *structIdRefCounts, - TSymbolTable *symbolTable); - - bool visitDeclaration(Visit visit, TIntermDeclaration *node) override; - void visitSymbol(TIntermSymbol *node) override; - bool visitAggregate(Visit visit, TIntermAggregate *node) override; - - // Traverse loop and block nodes in reverse order. Note that this traverser does not track - // parent block positions, so insertStatementInParentBlock is unusable! - void traverseBlock(TIntermBlock *block) override; - void traverseLoop(TIntermLoop *loop) override; - - private: - void removeVariableDeclaration(TIntermDeclaration *node, TIntermTyped *declarator); - void decrementStructTypeRefCount(const TType &type); - - CollectVariableRefCountsTraverser::RefCountMap *mSymbolIdRefCounts; - CollectVariableRefCountsTraverser::RefCountMap *mStructIdRefCounts; - bool mRemoveReferences; -}; - -RemoveUnreferencedVariablesTraverser::RemoveUnreferencedVariablesTraverser( - CollectVariableRefCountsTraverser::RefCountMap *symbolIdRefCounts, - CollectVariableRefCountsTraverser::RefCountMap *structIdRefCounts, - TSymbolTable *symbolTable) - : TIntermTraverser(true, false, true, symbolTable), - mSymbolIdRefCounts(symbolIdRefCounts), - mStructIdRefCounts(structIdRefCounts), - mRemoveReferences(false) -{ -} - -void RemoveUnreferencedVariablesTraverser::decrementStructTypeRefCount(const TType &type) -{ - auto *structure = type.getStruct(); - if (structure != nullptr) - { - ASSERT(mStructIdRefCounts->find(structure->uniqueId()) != mStructIdRefCounts->end()); - unsigned int structRefCount = --(*mStructIdRefCounts)[structure->uniqueId()]; - - if (structRefCount == 0) - { - for (const auto &field : structure->fields()) - { - decrementStructTypeRefCount(*field->type()); - } - } - } -} - -void RemoveUnreferencedVariablesTraverser::removeVariableDeclaration(TIntermDeclaration *node, - TIntermTyped *declarator) -{ - if (declarator->getType().isStructSpecifier() && !declarator->getType().isNamelessStruct()) - { - unsigned int structId = declarator->getType().getStruct()->uniqueId(); - if ((*mStructIdRefCounts)[structId] > 1u) - { - // If this declaration declares a named struct type that is used elsewhere, we need to - // keep it. We can still change the declarator though so that it doesn't declare an - // unreferenced variable. - - // Note that since we're not removing the entire declaration, the struct's reference - // count will end up being one less than the correct refcount. But since the struct - // declaration is kept, the incorrect refcount can't cause any other problems. - - if (declarator->getAsSymbolNode() && declarator->getAsSymbolNode()->getSymbol().empty()) - { - // Already an empty declaration - nothing to do. - return; - } - queueReplacementWithParent(node, declarator, - new TIntermSymbol(mSymbolTable->getEmptySymbolId(), - TString(""), declarator->getType()), - OriginalNode::IS_DROPPED); - return; - } - } - - if (getParentNode()->getAsBlock()) - { - TIntermSequence emptyReplacement; - mMultiReplacements.push_back( - NodeReplaceWithMultipleEntry(getParentNode()->getAsBlock(), node, emptyReplacement)); - } - else - { - ASSERT(getParentNode()->getAsLoopNode()); - queueReplacement(nullptr, OriginalNode::IS_DROPPED); - } -} - -bool RemoveUnreferencedVariablesTraverser::visitDeclaration(Visit visit, TIntermDeclaration *node) -{ - if (visit == PreVisit) - { - // SeparateDeclarations should have already been run. - ASSERT(node->getSequence()->size() == 1u); - - TIntermTyped *declarator = node->getSequence()->back()->getAsTyped(); - ASSERT(declarator); - - // We can only remove variables that are not a part of the shader interface. - TQualifier qualifier = declarator->getQualifier(); - if (qualifier != EvqTemporary && qualifier != EvqGlobal) - { - return true; - } - - bool canRemoveVariable = false; - TIntermSymbol *symbolNode = declarator->getAsSymbolNode(); - if (symbolNode != nullptr) - { - canRemoveVariable = - (*mSymbolIdRefCounts)[symbolNode->getId()] == 1u || symbolNode->getSymbol().empty(); - } - TIntermBinary *initNode = declarator->getAsBinaryNode(); - if (initNode != nullptr) - { - ASSERT(initNode->getLeft()->getAsSymbolNode()); - int symbolId = initNode->getLeft()->getAsSymbolNode()->getId(); - canRemoveVariable = - (*mSymbolIdRefCounts)[symbolId] == 1u && !initNode->getRight()->hasSideEffects(); - } - - if (canRemoveVariable) - { - removeVariableDeclaration(node, declarator); - mRemoveReferences = true; - } - return true; - } - ASSERT(visit == PostVisit); - mRemoveReferences = false; - return true; -} - -void RemoveUnreferencedVariablesTraverser::visitSymbol(TIntermSymbol *node) -{ - if (mRemoveReferences) - { - ASSERT(mSymbolIdRefCounts->find(node->getId()) != mSymbolIdRefCounts->end()); - --(*mSymbolIdRefCounts)[node->getId()]; - - decrementStructTypeRefCount(node->getType()); - } -} - -bool RemoveUnreferencedVariablesTraverser::visitAggregate(Visit visit, TIntermAggregate *node) -{ - if (mRemoveReferences) - { - decrementStructTypeRefCount(node->getType()); - } - return true; -} - -void RemoveUnreferencedVariablesTraverser::traverseBlock(TIntermBlock *node) -{ - // We traverse blocks in reverse order. This way reference counts can be decremented when - // removing initializers, and variables that become unused when initializers are removed can be - // removed on the same traversal. - - ScopedNodeInTraversalPath addToPath(this, node); - - bool visit = true; - - TIntermSequence *sequence = node->getSequence(); - - if (preVisit) - visit = visitBlock(PreVisit, node); - - if (visit) - { - for (auto iter = sequence->rbegin(); iter != sequence->rend(); ++iter) - { - (*iter)->traverse(this); - if (visit && inVisit) - { - if ((iter + 1) != sequence->rend()) - visit = visitBlock(InVisit, node); - } - } - } - - if (visit && postVisit) - visitBlock(PostVisit, node); -} - -void RemoveUnreferencedVariablesTraverser::traverseLoop(TIntermLoop *node) -{ - // We traverse loops in reverse order as well. The loop body gets traversed before the init - // node. - - ScopedNodeInTraversalPath addToPath(this, node); - - bool visit = true; - - if (preVisit) - visit = visitLoop(PreVisit, node); - - if (visit) - { - // We don't need to traverse loop expressions or conditions since they can't be declarations - // in the AST (loops which have a declaration in their condition get transformed in the - // parsing stage). - ASSERT(node->getExpression() == nullptr || - node->getExpression()->getAsDeclarationNode() == nullptr); - ASSERT(node->getCondition() == nullptr || - node->getCondition()->getAsDeclarationNode() == nullptr); - - if (node->getBody()) - node->getBody()->traverse(this); - - if (node->getInit()) - node->getInit()->traverse(this); - } - - if (visit && postVisit) - visitLoop(PostVisit, node); -} - -} // namespace - -void RemoveUnreferencedVariables(TIntermBlock *root, TSymbolTable *symbolTable) -{ - CollectVariableRefCountsTraverser collector; - root->traverse(&collector); - RemoveUnreferencedVariablesTraverser traverser(&collector.getSymbolIdRefCounts(), - &collector.getStructIdRefCounts(), symbolTable); - root->traverse(&traverser); - traverser.updateTree(); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/RemoveUnreferencedVariables.h b/src/3rdparty/angle/src/compiler/translator/RemoveUnreferencedVariables.h deleted file mode 100644 index 39c8327776..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/RemoveUnreferencedVariables.h +++ /dev/null @@ -1,24 +0,0 @@ -// -// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// RemoveUnreferencedVariables.h: -// Drop variables that are declared but never referenced in the AST. This avoids adding unnecessary -// initialization code for them. Also removes unreferenced struct types. -// - -#ifndef COMPILER_TRANSLATOR_REMOVEUNREFERENCEDVARIABLES_H_ -#define COMPILER_TRANSLATOR_REMOVEUNREFERENCEDVARIABLES_H_ - -namespace sh -{ - -class TIntermBlock; -class TSymbolTable; - -void RemoveUnreferencedVariables(TIntermBlock *root, TSymbolTable *symbolTable); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_REMOVEUNREFERENCEDVARIABLES_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/RewriteDoWhile.cpp b/src/3rdparty/angle/src/compiler/translator/RewriteDoWhile.cpp deleted file mode 100644 index dc3fb7a74e..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/RewriteDoWhile.cpp +++ /dev/null @@ -1,159 +0,0 @@ -// -// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// RewriteDoWhile.cpp: rewrites do-while loops using another equivalent -// construct. - -#include "compiler/translator/RewriteDoWhile.h" - -#include "compiler/translator/IntermTraverse.h" - -namespace sh -{ - -namespace -{ - -// An AST traverser that rewrites loops of the form -// do { -// CODE; -// } while (CONDITION) -// -// to loops of the form -// bool temp = false; -// while (true) { -// if (temp) { -// if (!CONDITION) { -// break; -// } -// } -// temp = true; -// CODE; -// } -// -// The reason we don't use a simpler form, with for example just (temp && !CONDITION) in the -// while condition, is that short-circuit is often badly supported by driver shader compiler. -// The double if has the same effect, but forces shader compilers to behave. -// -// TODO(cwallez) when UnfoldShortCircuitIntoIf handles loops correctly, revisit this as we might -// be able to use while (temp || CONDITION) with temp initially set to true then run -// UnfoldShortCircuitIntoIf -class DoWhileRewriter : public TIntermTraverser -{ - public: - DoWhileRewriter(TSymbolTable *symbolTable) : TIntermTraverser(true, false, false, symbolTable) - { - } - - bool visitBlock(Visit, TIntermBlock *node) override - { - // A well-formed AST can only have do-while inside TIntermBlock. By doing a prefix traversal - // we are able to replace the do-while in the sequence directly as the content of the - // do-while will be traversed later. - - TIntermSequence *statements = node->getSequence(); - - // The statements vector will have new statements inserted when we encounter a do-while, - // which prevents us from using a range-based for loop. Using the usual i++ works, as - // the (two) new statements inserted replace the statement at the current position. - for (size_t i = 0; i < statements->size(); i++) - { - TIntermNode *statement = (*statements)[i]; - TIntermLoop *loop = statement->getAsLoopNode(); - - if (loop == nullptr || loop->getType() != ELoopDoWhile) - { - continue; - } - - // Found a loop to change. - nextTemporaryId(); - - TType boolType = TType(EbtBool); - - // bool temp = false; - TIntermDeclaration *tempDeclaration = nullptr; - { - TConstantUnion *falseConstant = new TConstantUnion(); - falseConstant->setBConst(false); - TIntermTyped *falseValue = new TIntermConstantUnion(falseConstant, boolType); - - tempDeclaration = createTempInitDeclaration(falseValue); - } - - // temp = true; - TIntermBinary *assignTrue = nullptr; - { - TConstantUnion *trueConstant = new TConstantUnion(); - trueConstant->setBConst(true); - TIntermTyped *trueValue = new TIntermConstantUnion(trueConstant, boolType); - - assignTrue = createTempAssignment(trueValue); - } - - // if (temp) { - // if (!CONDITION) { - // break; - // } - // } - TIntermIfElse *breakIf = nullptr; - { - TIntermBranch *breakStatement = new TIntermBranch(EOpBreak, nullptr); - - TIntermBlock *breakBlock = new TIntermBlock(); - breakBlock->getSequence()->push_back(breakStatement); - - TIntermUnary *negatedCondition = - new TIntermUnary(EOpLogicalNot, loop->getCondition()); - - TIntermIfElse *innerIf = new TIntermIfElse(negatedCondition, breakBlock, nullptr); - - TIntermBlock *innerIfBlock = new TIntermBlock(); - innerIfBlock->getSequence()->push_back(innerIf); - - breakIf = new TIntermIfElse(createTempSymbol(boolType), innerIfBlock, nullptr); - } - - // Assemble the replacement loops, reusing the do-while loop's body and inserting our - // statements at the front. - TIntermLoop *newLoop = nullptr; - { - TConstantUnion *trueConstant = new TConstantUnion(); - trueConstant->setBConst(true); - TIntermTyped *trueValue = new TIntermConstantUnion(trueConstant, boolType); - - TIntermBlock *body = loop->getBody(); - if (body == nullptr) - { - body = new TIntermBlock(); - } - auto sequence = body->getSequence(); - sequence->insert(sequence->begin(), assignTrue); - sequence->insert(sequence->begin(), breakIf); - - newLoop = new TIntermLoop(ELoopWhile, nullptr, trueValue, nullptr, body); - } - - TIntermSequence replacement; - replacement.push_back(tempDeclaration); - replacement.push_back(newLoop); - - node->replaceChildNodeWithMultiple(loop, replacement); - } - return true; - } -}; - -} // anonymous namespace - -void RewriteDoWhile(TIntermNode *root, TSymbolTable *symbolTable) -{ - DoWhileRewriter rewriter(symbolTable); - - root->traverse(&rewriter); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/RewriteDoWhile.h b/src/3rdparty/angle/src/compiler/translator/RewriteDoWhile.h deleted file mode 100644 index e83bfc4b56..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/RewriteDoWhile.h +++ /dev/null @@ -1,23 +0,0 @@ -// -// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// RewriteDoWhile.h: rewrite do-while loops as while loops to work around -// driver bugs - -#ifndef COMPILER_TRANSLATOR_REWRITEDOWHILE_H_ -#define COMPILER_TRANSLATOR_REWRITEDOWHILE_H_ - -namespace sh -{ - -class TIntermNode; -class TSymbolTable; - -void RewriteDoWhile(TIntermNode *root, TSymbolTable *symbolTable); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_REWRITEDOWHILE_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/RewriteElseBlocks.cpp b/src/3rdparty/angle/src/compiler/translator/RewriteElseBlocks.cpp deleted file mode 100644 index ed1bfad8a8..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/RewriteElseBlocks.cpp +++ /dev/null @@ -1,120 +0,0 @@ -// -// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// RewriteElseBlocks.cpp: Implementation for tree transform to change -// all if-else blocks to if-if blocks. -// - -#include "compiler/translator/RewriteElseBlocks.h" - -#include "compiler/translator/IntermNode.h" -#include "compiler/translator/IntermNode_util.h" -#include "compiler/translator/NodeSearch.h" -#include "compiler/translator/SymbolTable.h" - -namespace sh -{ - -namespace -{ - -class ElseBlockRewriter : public TIntermTraverser -{ - public: - ElseBlockRewriter(TSymbolTable *symbolTable); - - protected: - bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *aggregate) override; - bool visitBlock(Visit visit, TIntermBlock *block) override; - - private: - TIntermNode *rewriteIfElse(TIntermIfElse *ifElse); - - const TType *mFunctionType; -}; - -ElseBlockRewriter::ElseBlockRewriter(TSymbolTable *symbolTable) - : TIntermTraverser(true, false, true, symbolTable), mFunctionType(nullptr) -{ -} - -bool ElseBlockRewriter::visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) -{ - // Store the current function context (see comment below) - mFunctionType = ((visit == PreVisit) ? &node->getFunctionPrototype()->getType() : nullptr); - return true; -} - -bool ElseBlockRewriter::visitBlock(Visit visit, TIntermBlock *node) -{ - if (visit == PostVisit) - { - for (size_t statementIndex = 0; statementIndex != node->getSequence()->size(); - statementIndex++) - { - TIntermNode *statement = (*node->getSequence())[statementIndex]; - TIntermIfElse *ifElse = statement->getAsIfElseNode(); - if (ifElse && ifElse->getFalseBlock() != nullptr) - { - (*node->getSequence())[statementIndex] = rewriteIfElse(ifElse); - } - } - } - return true; -} - -TIntermNode *ElseBlockRewriter::rewriteIfElse(TIntermIfElse *ifElse) -{ - ASSERT(ifElse != nullptr); - - nextTemporaryId(); - - TIntermDeclaration *storeCondition = createTempInitDeclaration(ifElse->getCondition()); - - TIntermBlock *falseBlock = nullptr; - - TType boolType(EbtBool, EbpUndefined, EvqTemporary); - - if (ifElse->getFalseBlock()) - { - TIntermBlock *negatedElse = nullptr; - // crbug.com/346463 - // D3D generates error messages claiming a function has no return value, when rewriting - // an if-else clause that returns something non-void in a function. By appending dummy - // returns (that are unreachable) we can silence this compile error. - if (mFunctionType && mFunctionType->getBasicType() != EbtVoid) - { - TIntermNode *returnNode = new TIntermBranch(EOpReturn, CreateZeroNode(*mFunctionType)); - negatedElse = new TIntermBlock(); - negatedElse->appendStatement(returnNode); - } - - TIntermSymbol *conditionSymbolElse = createTempSymbol(boolType); - TIntermUnary *negatedCondition = new TIntermUnary(EOpLogicalNot, conditionSymbolElse); - TIntermIfElse *falseIfElse = - new TIntermIfElse(negatedCondition, ifElse->getFalseBlock(), negatedElse); - falseBlock = EnsureBlock(falseIfElse); - } - - TIntermSymbol *conditionSymbolSel = createTempSymbol(boolType); - TIntermIfElse *newIfElse = - new TIntermIfElse(conditionSymbolSel, ifElse->getTrueBlock(), falseBlock); - - TIntermBlock *block = new TIntermBlock(); - block->getSequence()->push_back(storeCondition); - block->getSequence()->push_back(newIfElse); - - return block; -} - -} // anonymous namespace - -void RewriteElseBlocks(TIntermNode *node, TSymbolTable *symbolTable) -{ - ElseBlockRewriter rewriter(symbolTable); - node->traverse(&rewriter); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/RewriteElseBlocks.h b/src/3rdparty/angle/src/compiler/translator/RewriteElseBlocks.h deleted file mode 100644 index 2586b5405c..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/RewriteElseBlocks.h +++ /dev/null @@ -1,22 +0,0 @@ -// -// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// RewriteElseBlocks.h: Prototype for tree transform to change -// all if-else blocks to if-if blocks. -// - -#ifndef COMPILER_TRANSLATOR_REWRITEELSEBLOCKS_H_ -#define COMPILER_TRANSLATOR_REWRITEELSEBLOCKS_H_ - -namespace sh -{ - -class TIntermNode; -class TSymbolTable; - -void RewriteElseBlocks(TIntermNode *node, TSymbolTable *symbolTable); -} - -#endif // COMPILER_TRANSLATOR_REWRITEELSEBLOCKS_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/RewriteTexelFetchOffset.cpp b/src/3rdparty/angle/src/compiler/translator/RewriteTexelFetchOffset.cpp deleted file mode 100644 index b602e0c923..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/RewriteTexelFetchOffset.cpp +++ /dev/null @@ -1,154 +0,0 @@ -// -// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// Implementation of texelFetchOffset translation issue workaround. -// See header for more info. - -#include "compiler/translator/RewriteTexelFetchOffset.h" - -#include "common/angleutils.h" -#include "compiler/translator/IntermNode_util.h" -#include "compiler/translator/IntermTraverse.h" -#include "compiler/translator/SymbolTable.h" - -namespace sh -{ - -namespace -{ - -class Traverser : public TIntermTraverser -{ - public: - static void Apply(TIntermNode *root, const TSymbolTable &symbolTable, int shaderVersion); - - private: - Traverser(const TSymbolTable &symbolTable, int shaderVersion); - bool visitAggregate(Visit visit, TIntermAggregate *node) override; - void nextIteration(); - - const TSymbolTable *symbolTable; - const int shaderVersion; - bool mFound = false; -}; - -Traverser::Traverser(const TSymbolTable &symbolTable, int shaderVersion) - : TIntermTraverser(true, false, false), symbolTable(&symbolTable), shaderVersion(shaderVersion) -{ -} - -// static -void Traverser::Apply(TIntermNode *root, const TSymbolTable &symbolTable, int shaderVersion) -{ - Traverser traverser(symbolTable, shaderVersion); - do - { - traverser.nextIteration(); - root->traverse(&traverser); - if (traverser.mFound) - { - traverser.updateTree(); - } - } while (traverser.mFound); -} - -void Traverser::nextIteration() -{ - mFound = false; -} - -bool Traverser::visitAggregate(Visit visit, TIntermAggregate *node) -{ - if (mFound) - { - return false; - } - - // Decide if the node represents the call of texelFetchOffset. - if (node->getOp() != EOpCallBuiltInFunction) - { - return true; - } - - if (node->getFunctionSymbolInfo()->getName() != "texelFetchOffset") - { - return true; - } - - // Potential problem case detected, apply workaround. - const TIntermSequence *sequence = node->getSequence(); - ASSERT(sequence->size() == 4u); - - // Decide if the sampler is a 2DArray sampler. In that case position is ivec3 and offset is - // ivec2. - bool is2DArray = sequence->at(1)->getAsTyped()->getNominalSize() == 3 && - sequence->at(3)->getAsTyped()->getNominalSize() == 2; - - // Create new node that represents the call of function texelFetch. - // Its argument list will be: texelFetch(sampler, Position+offset, lod). - - TIntermSequence *texelFetchArguments = new TIntermSequence(); - - // sampler - texelFetchArguments->push_back(sequence->at(0)); - - // Position - TIntermTyped *texCoordNode = sequence->at(1)->getAsTyped(); - ASSERT(texCoordNode); - - // offset - TIntermTyped *offsetNode = nullptr; - ASSERT(sequence->at(3)->getAsTyped()); - if (is2DArray) - { - // For 2DArray samplers, Position is ivec3 and offset is ivec2; - // So offset must be converted into an ivec3 before being added to Position. - TIntermSequence *constructOffsetIvecArguments = new TIntermSequence(); - constructOffsetIvecArguments->push_back(sequence->at(3)->getAsTyped()); - - TIntermTyped *zeroNode = CreateZeroNode(TType(EbtInt)); - constructOffsetIvecArguments->push_back(zeroNode); - - offsetNode = TIntermAggregate::CreateConstructor(texCoordNode->getType(), - constructOffsetIvecArguments); - offsetNode->setLine(texCoordNode->getLine()); - } - else - { - offsetNode = sequence->at(3)->getAsTyped(); - } - - // Position+offset - TIntermBinary *add = new TIntermBinary(EOpAdd, texCoordNode, offsetNode); - add->setLine(texCoordNode->getLine()); - texelFetchArguments->push_back(add); - - // lod - texelFetchArguments->push_back(sequence->at(2)); - - ASSERT(texelFetchArguments->size() == 3u); - - TIntermTyped *texelFetchNode = CreateBuiltInFunctionCallNode("texelFetch", texelFetchArguments, - *symbolTable, shaderVersion); - texelFetchNode->setLine(node->getLine()); - - // Replace the old node by this new node. - queueReplacement(texelFetchNode, OriginalNode::IS_DROPPED); - mFound = true; - return false; -} - -} // anonymous namespace - -void RewriteTexelFetchOffset(TIntermNode *root, const TSymbolTable &symbolTable, int shaderVersion) -{ - // texelFetchOffset is only valid in GLSL 3.0 and later. - if (shaderVersion < 300) - return; - - Traverser::Apply(root, symbolTable, shaderVersion); -} - -} // namespace sh \ No newline at end of file diff --git a/src/3rdparty/angle/src/compiler/translator/RewriteTexelFetchOffset.h b/src/3rdparty/angle/src/compiler/translator/RewriteTexelFetchOffset.h deleted file mode 100644 index 694d709f8e..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/RewriteTexelFetchOffset.h +++ /dev/null @@ -1,28 +0,0 @@ -// -// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// This mutating tree traversal works around an issue on the translation -// from texelFetchOffset into HLSL function Load on INTEL drivers. It -// works by translating texelFetchOffset into texelFetch: -// -// - From: texelFetchOffset(sampler, Position, lod, offset) -// - To: texelFetch(sampler, Position+offset, lod) -// -// See http://anglebug.com/1469 - -#ifndef COMPILER_TRANSLATOR_REWRITE_TEXELFETCHOFFSET_H_ -#define COMPILER_TRANSLATOR_REWRITE_TEXELFETCHOFFSET_H_ - -class TIntermNode; -class TSymbolTable; - -namespace sh -{ - -void RewriteTexelFetchOffset(TIntermNode *root, const TSymbolTable &symbolTable, int shaderVersion); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_REWRITE_TEXELFETCHOFFSET_H_ \ No newline at end of file diff --git a/src/3rdparty/angle/src/compiler/translator/RewriteUnaryMinusOperatorFloat.cpp b/src/3rdparty/angle/src/compiler/translator/RewriteUnaryMinusOperatorFloat.cpp deleted file mode 100644 index 696a49536c..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/RewriteUnaryMinusOperatorFloat.cpp +++ /dev/null @@ -1,94 +0,0 @@ -// -// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/translator/RewriteUnaryMinusOperatorFloat.h" - -#include "compiler/translator/IntermNode_util.h" -#include "compiler/translator/IntermTraverse.h" - -namespace sh -{ - -namespace -{ - -class Traverser : public TIntermTraverser -{ - public: - static void Apply(TIntermNode *root); - - private: - Traverser(); - bool visitUnary(Visit visit, TIntermUnary *node) override; - void nextIteration(); - - bool mFound = false; -}; - -// static -void Traverser::Apply(TIntermNode *root) -{ - Traverser traverser; - do - { - traverser.nextIteration(); - root->traverse(&traverser); - if (traverser.mFound) - { - traverser.updateTree(); - } - } while (traverser.mFound); -} - -Traverser::Traverser() : TIntermTraverser(true, false, false) -{ -} - -void Traverser::nextIteration() -{ - mFound = false; -} - -bool Traverser::visitUnary(Visit visit, TIntermUnary *node) -{ - if (mFound) - { - return false; - } - - // Detect if the current operator is unary minus operator. - if (node->getOp() != EOpNegative) - { - return true; - } - - // Detect if the current operand is a float variable. - TIntermTyped *fValue = node->getOperand(); - if (!fValue->getType().isScalarFloat()) - { - return true; - } - - // 0.0 - float - TIntermTyped *zero = CreateZeroNode(fValue->getType()); - zero->setLine(fValue->getLine()); - TIntermBinary *sub = new TIntermBinary(EOpSub, zero, fValue); - sub->setLine(fValue->getLine()); - - queueReplacement(sub, OriginalNode::IS_DROPPED); - - mFound = true; - return false; -} - -} // anonymous namespace - -void RewriteUnaryMinusOperatorFloat(TIntermNode *root) -{ - Traverser::Apply(root); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/RewriteUnaryMinusOperatorFloat.h b/src/3rdparty/angle/src/compiler/translator/RewriteUnaryMinusOperatorFloat.h deleted file mode 100644 index ccbfbcbd9e..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/RewriteUnaryMinusOperatorFloat.h +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// Rewrite "-float" to "0.0 - float" to work around unary minus operator on float issue on Intel Mac -// OSX 10.11. - -#ifndef COMPILER_TRANSLATOR_REWRITEUNARYMINUSOPERATORFLOAT_H_ -#define COMPILER_TRANSLATOR_REWRITEUNARYMINUSOPERATORFLOAT_H_ - -class TIntermNode; -namespace sh -{ - -void RewriteUnaryMinusOperatorFloat(TIntermNode *root); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_REWRITEUNARYMINUSOPERATORFLOAT_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/RewriteUnaryMinusOperatorInt.cpp b/src/3rdparty/angle/src/compiler/translator/RewriteUnaryMinusOperatorInt.cpp deleted file mode 100644 index fe2ef948b4..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/RewriteUnaryMinusOperatorInt.cpp +++ /dev/null @@ -1,112 +0,0 @@ -// -// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// Implementation of evaluating unary integer variable bug workaround. -// See header for more info. - -#include "compiler/translator/RewriteUnaryMinusOperatorInt.h" - -#include "compiler/translator/IntermTraverse.h" - -namespace sh -{ - -namespace -{ - -class Traverser : public TIntermTraverser -{ - public: - static void Apply(TIntermNode *root); - - private: - Traverser(); - bool visitUnary(Visit visit, TIntermUnary *node) override; - void nextIteration(); - - bool mFound = false; -}; - -// static -void Traverser::Apply(TIntermNode *root) -{ - Traverser traverser; - do - { - traverser.nextIteration(); - root->traverse(&traverser); - if (traverser.mFound) - { - traverser.updateTree(); - } - } while (traverser.mFound); -} - -Traverser::Traverser() : TIntermTraverser(true, false, false) -{ -} - -void Traverser::nextIteration() -{ - mFound = false; -} - -bool Traverser::visitUnary(Visit visit, TIntermUnary *node) -{ - if (mFound) - { - return false; - } - - // Decide if the current unary operator is unary minus. - if (node->getOp() != EOpNegative) - { - return true; - } - - // Decide if the current operand is an integer variable. - TIntermTyped *opr = node->getOperand(); - if (!opr->getType().isScalarInt()) - { - return true; - } - - // Potential problem case detected, apply workaround: -(int) -> ~(int) + 1. - // ~(int) - TIntermUnary *bitwiseNot = new TIntermUnary(EOpBitwiseNot, opr); - bitwiseNot->setLine(opr->getLine()); - - // Constant 1 (or 1u) - TConstantUnion *one = new TConstantUnion(); - if (opr->getType().getBasicType() == EbtInt) - { - one->setIConst(1); - } - else - { - one->setUConst(1u); - } - TIntermConstantUnion *oneNode = new TIntermConstantUnion(one, opr->getType()); - oneNode->getTypePointer()->setQualifier(EvqConst); - oneNode->setLine(opr->getLine()); - - // ~(int) + 1 - TIntermBinary *add = new TIntermBinary(EOpAdd, bitwiseNot, oneNode); - add->setLine(opr->getLine()); - - queueReplacement(add, OriginalNode::IS_DROPPED); - - mFound = true; - return false; -} - -} // anonymous namespace - -void RewriteUnaryMinusOperatorInt(TIntermNode *root) -{ - Traverser::Apply(root); -} - -} // namespace sh \ No newline at end of file diff --git a/src/3rdparty/angle/src/compiler/translator/RewriteUnaryMinusOperatorInt.h b/src/3rdparty/angle/src/compiler/translator/RewriteUnaryMinusOperatorInt.h deleted file mode 100644 index 50f0c442a7..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/RewriteUnaryMinusOperatorInt.h +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// This mutating tree traversal works around a bug on evaluating unary -// integer variable on Intel D3D driver. It works by rewriting -(int) to -// ~(int) + 1 when evaluating unary integer variables. - -#ifndef COMPILER_TRANSLATOR_REWRITEUNARYMINUSOPERATORINT_H_ -#define COMPILER_TRANSLATOR_REWRITEUNARYMINUSOPERATORINT_H_ - -class TIntermNode; -namespace sh -{ - -void RewriteUnaryMinusOperatorInt(TIntermNode *root); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_REWRITEUNARYMINUSOPERATORINT_H_ \ No newline at end of file diff --git a/src/3rdparty/angle/src/compiler/translator/RunAtTheEndOfShader.cpp b/src/3rdparty/angle/src/compiler/translator/RunAtTheEndOfShader.cpp deleted file mode 100644 index 3c4209c539..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/RunAtTheEndOfShader.cpp +++ /dev/null @@ -1,112 +0,0 @@ -// -// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// RunAtTheEndOfShader.cpp: Add code to be run at the end of the shader. In case main() contains a -// return statement, this is done by replacing the main() function with another function that calls -// the old main, like this: -// -// void main() { body } -// => -// void main0() { body } -// void main() -// { -// main0(); -// codeToRun -// } -// -// This way the code will get run even if the return statement inside main is executed. -// - -#include "compiler/translator/RunAtTheEndOfShader.h" - -#include "compiler/translator/FindMain.h" -#include "compiler/translator/IntermNode.h" -#include "compiler/translator/IntermNode_util.h" -#include "compiler/translator/IntermTraverse.h" -#include "compiler/translator/SymbolTable.h" - -namespace sh -{ - -namespace -{ - -class ContainsReturnTraverser : public TIntermTraverser -{ - public: - ContainsReturnTraverser() : TIntermTraverser(true, false, false), mContainsReturn(false) {} - - bool visitBranch(Visit visit, TIntermBranch *node) override - { - if (node->getFlowOp() == EOpReturn) - { - mContainsReturn = true; - } - return false; - } - - bool containsReturn() { return mContainsReturn; } - - private: - bool mContainsReturn; -}; - -bool ContainsReturn(TIntermNode *node) -{ - ContainsReturnTraverser traverser; - node->traverse(&traverser); - return traverser.containsReturn(); -} - -void WrapMainAndAppend(TIntermBlock *root, - TIntermFunctionDefinition *main, - TIntermNode *codeToRun, - TSymbolTable *symbolTable) -{ - // Replace main() with main0() with the same body. - TSymbolUniqueId oldMainId(symbolTable); - std::stringstream oldMainName; - oldMainName << "main" << oldMainId.get(); - TIntermFunctionDefinition *oldMain = CreateInternalFunctionDefinitionNode( - TType(EbtVoid), oldMainName.str().c_str(), main->getBody(), oldMainId); - - bool replaced = root->replaceChildNode(main, oldMain); - ASSERT(replaced); - - // void main() - TIntermFunctionPrototype *newMainProto = new TIntermFunctionPrototype( - TType(EbtVoid), main->getFunctionPrototype()->getFunctionSymbolInfo()->getId()); - newMainProto->getFunctionSymbolInfo()->setName("main"); - - // { - // main0(); - // codeToRun - // } - TIntermBlock *newMainBody = new TIntermBlock(); - TIntermAggregate *oldMainCall = CreateInternalFunctionCallNode( - TType(EbtVoid), oldMainName.str().c_str(), oldMainId, new TIntermSequence()); - newMainBody->appendStatement(oldMainCall); - newMainBody->appendStatement(codeToRun); - - // Add the new main() to the root node. - TIntermFunctionDefinition *newMain = new TIntermFunctionDefinition(newMainProto, newMainBody); - root->appendStatement(newMain); -} - -} // anonymous namespace - -void RunAtTheEndOfShader(TIntermBlock *root, TIntermNode *codeToRun, TSymbolTable *symbolTable) -{ - TIntermFunctionDefinition *main = FindMain(root); - if (!ContainsReturn(main)) - { - main->getBody()->appendStatement(codeToRun); - return; - } - - WrapMainAndAppend(root, main, codeToRun, symbolTable); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/RunAtTheEndOfShader.h b/src/3rdparty/angle/src/compiler/translator/RunAtTheEndOfShader.h deleted file mode 100644 index ed94c28dae..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/RunAtTheEndOfShader.h +++ /dev/null @@ -1,23 +0,0 @@ -// -// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// RunAtTheEndOfShader.h: Add code to be run at the end of the shader. -// - -#ifndef COMPILER_TRANSLATOR_RUNATTHEENDOFSHADER_H_ -#define COMPILER_TRANSLATOR_RUNATTHEENDOFSHADER_H_ - -namespace sh -{ - -class TIntermBlock; -class TIntermNode; -class TSymbolTable; - -void RunAtTheEndOfShader(TIntermBlock *root, TIntermNode *codeToRun, TSymbolTable *symbolTable); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_RUNATTHEENDOFSHADER_H_ \ No newline at end of file diff --git a/src/3rdparty/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.cpp b/src/3rdparty/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.cpp deleted file mode 100644 index 746c16e2e6..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.cpp +++ /dev/null @@ -1,238 +0,0 @@ -// -// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// Scalarize vector and matrix constructor args, so that vectors built from components don't have -// matrix arguments, and matrices built from components don't have vector arguments. This avoids -// driver bugs around vector and matrix constructors. -// - -#include "common/debug.h" -#include "compiler/translator/ScalarizeVecAndMatConstructorArgs.h" - -#include - -#include "angle_gl.h" -#include "common/angleutils.h" -#include "compiler/translator/IntermNode_util.h" -#include "compiler/translator/IntermTraverse.h" - -namespace sh -{ - -namespace -{ - -bool ContainsMatrixNode(const TIntermSequence &sequence) -{ - for (size_t ii = 0; ii < sequence.size(); ++ii) - { - TIntermTyped *node = sequence[ii]->getAsTyped(); - if (node && node->isMatrix()) - return true; - } - return false; -} - -bool ContainsVectorNode(const TIntermSequence &sequence) -{ - for (size_t ii = 0; ii < sequence.size(); ++ii) - { - TIntermTyped *node = sequence[ii]->getAsTyped(); - if (node && node->isVector()) - return true; - } - return false; -} - -TIntermBinary *ConstructVectorIndexBinaryNode(TIntermSymbol *symbolNode, int index) -{ - return new TIntermBinary(EOpIndexDirect, symbolNode, CreateIndexNode(index)); -} - -TIntermBinary *ConstructMatrixIndexBinaryNode(TIntermSymbol *symbolNode, int colIndex, int rowIndex) -{ - TIntermBinary *colVectorNode = ConstructVectorIndexBinaryNode(symbolNode, colIndex); - - return new TIntermBinary(EOpIndexDirect, colVectorNode, CreateIndexNode(rowIndex)); -} - -class ScalarizeArgsTraverser : public TIntermTraverser -{ - public: - ScalarizeArgsTraverser(sh::GLenum shaderType, - bool fragmentPrecisionHigh, - TSymbolTable *symbolTable) - : TIntermTraverser(true, false, false, symbolTable), - mShaderType(shaderType), - mFragmentPrecisionHigh(fragmentPrecisionHigh) - { - } - - protected: - bool visitAggregate(Visit visit, TIntermAggregate *node) override; - bool visitBlock(Visit visit, TIntermBlock *node) override; - - private: - void scalarizeArgs(TIntermAggregate *aggregate, bool scalarizeVector, bool scalarizeMatrix); - - // If we have the following code: - // mat4 m(0); - // vec4 v(1, m); - // We will rewrite to: - // mat4 m(0); - // mat4 s0 = m; - // vec4 v(1, s0[0][0], s0[0][1], s0[0][2]); - // This function is to create nodes for "mat4 s0 = m;" and insert it to the code sequence. This - // way the possible side effects of the constructor argument will only be evaluated once. - void createTempVariable(TIntermTyped *original); - - std::vector mBlockStack; - - sh::GLenum mShaderType; - bool mFragmentPrecisionHigh; -}; - -bool ScalarizeArgsTraverser::visitAggregate(Visit visit, TIntermAggregate *node) -{ - if (visit == PreVisit && node->getOp() == EOpConstruct) - { - if (node->getType().isVector() && ContainsMatrixNode(*(node->getSequence()))) - scalarizeArgs(node, false, true); - else if (node->getType().isMatrix() && ContainsVectorNode(*(node->getSequence()))) - scalarizeArgs(node, true, false); - } - return true; -} - -bool ScalarizeArgsTraverser::visitBlock(Visit visit, TIntermBlock *node) -{ - mBlockStack.push_back(TIntermSequence()); - { - for (TIntermNode *child : *node->getSequence()) - { - ASSERT(child != nullptr); - child->traverse(this); - mBlockStack.back().push_back(child); - } - } - if (mBlockStack.back().size() > node->getSequence()->size()) - { - node->getSequence()->clear(); - *(node->getSequence()) = mBlockStack.back(); - } - mBlockStack.pop_back(); - return false; -} - -void ScalarizeArgsTraverser::scalarizeArgs(TIntermAggregate *aggregate, - bool scalarizeVector, - bool scalarizeMatrix) -{ - ASSERT(aggregate); - ASSERT(!aggregate->isArray()); - int size = static_cast(aggregate->getType().getObjectSize()); - TIntermSequence *sequence = aggregate->getSequence(); - TIntermSequence original(*sequence); - sequence->clear(); - for (size_t ii = 0; ii < original.size(); ++ii) - { - ASSERT(size > 0); - TIntermTyped *node = original[ii]->getAsTyped(); - ASSERT(node); - createTempVariable(node); - if (node->isScalar()) - { - sequence->push_back(createTempSymbol(node->getType())); - size--; - } - else if (node->isVector()) - { - if (scalarizeVector) - { - int repeat = std::min(size, node->getNominalSize()); - size -= repeat; - for (int index = 0; index < repeat; ++index) - { - TIntermSymbol *symbolNode = createTempSymbol(node->getType()); - TIntermBinary *newNode = ConstructVectorIndexBinaryNode(symbolNode, index); - sequence->push_back(newNode); - } - } - else - { - TIntermSymbol *symbolNode = createTempSymbol(node->getType()); - sequence->push_back(symbolNode); - size -= node->getNominalSize(); - } - } - else - { - ASSERT(node->isMatrix()); - if (scalarizeMatrix) - { - int colIndex = 0, rowIndex = 0; - int repeat = std::min(size, node->getCols() * node->getRows()); - size -= repeat; - while (repeat > 0) - { - TIntermSymbol *symbolNode = createTempSymbol(node->getType()); - TIntermBinary *newNode = - ConstructMatrixIndexBinaryNode(symbolNode, colIndex, rowIndex); - sequence->push_back(newNode); - rowIndex++; - if (rowIndex >= node->getRows()) - { - rowIndex = 0; - colIndex++; - } - repeat--; - } - } - else - { - TIntermSymbol *symbolNode = createTempSymbol(node->getType()); - sequence->push_back(symbolNode); - size -= node->getCols() * node->getRows(); - } - } - } -} - -void ScalarizeArgsTraverser::createTempVariable(TIntermTyped *original) -{ - ASSERT(original); - nextTemporaryId(); - TIntermDeclaration *decl = createTempInitDeclaration(original); - - TType type = original->getType(); - if (mShaderType == GL_FRAGMENT_SHADER && type.getBasicType() == EbtFloat && - type.getPrecision() == EbpUndefined) - { - // We use the highest available precision for the temporary variable - // to avoid computing the actual precision using the rules defined - // in GLSL ES 1.0 Section 4.5.2. - TIntermBinary *init = decl->getSequence()->at(0)->getAsBinaryNode(); - init->getTypePointer()->setPrecision(mFragmentPrecisionHigh ? EbpHigh : EbpMedium); - init->getLeft()->getTypePointer()->setPrecision(mFragmentPrecisionHigh ? EbpHigh - : EbpMedium); - } - - ASSERT(mBlockStack.size() > 0); - TIntermSequence &sequence = mBlockStack.back(); - sequence.push_back(decl); -} - -} // namespace anonymous - -void ScalarizeVecAndMatConstructorArgs(TIntermBlock *root, - sh::GLenum shaderType, - bool fragmentPrecisionHigh, - TSymbolTable *symbolTable) -{ - ScalarizeArgsTraverser scalarizer(shaderType, fragmentPrecisionHigh, symbolTable); - root->traverse(&scalarizer); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.h b/src/3rdparty/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.h deleted file mode 100644 index b8f782d1ec..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.h +++ /dev/null @@ -1,27 +0,0 @@ -// -// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// Scalarize vector and matrix constructor args, so that vectors built from components don't have -// matrix arguments, and matrices built from components don't have vector arguments. This avoids -// driver bugs around vector and matrix constructors. -// - -#ifndef COMPILER_TRANSLATOR_SCALARIZEVECANDMATCONSTRUCTORARGS_H_ -#define COMPILER_TRANSLATOR_SCALARIZEVECANDMATCONSTRUCTORARGS_H_ - -#include "GLSLANG/ShaderLang.h" - -namespace sh -{ -class TIntermBlock; -class TSymbolTable; - -void ScalarizeVecAndMatConstructorArgs(TIntermBlock *root, - sh::GLenum shaderType, - bool fragmentPrecisionHigh, - TSymbolTable *symbolTable); -} // namespace sh - -#endif // COMPILER_TRANSLATOR_SCALARIZEVECANDMATCONSTRUCTORARGS_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/SearchSymbol.cpp b/src/3rdparty/angle/src/compiler/translator/SearchSymbol.cpp deleted file mode 100644 index 34c644d028..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/SearchSymbol.cpp +++ /dev/null @@ -1,38 +0,0 @@ -// -// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// SearchSymbol is an AST traverser to detect the use of a given symbol name -// - -#include "compiler/translator/SearchSymbol.h" - -#include "compiler/translator/InfoSink.h" - -namespace sh -{ -SearchSymbol::SearchSymbol(const TString &symbol) - : TIntermTraverser(true, false, false), mSymbol(symbol) -{ - match = false; -} - -void SearchSymbol::traverse(TIntermNode *node) -{ - node->traverse(this); -} - -void SearchSymbol::visitSymbol(TIntermSymbol *symbolNode) -{ - if (symbolNode->getSymbol() == mSymbol) - { - match = true; - } -} - -bool SearchSymbol::foundMatch() const -{ - return match; -} -} diff --git a/src/3rdparty/angle/src/compiler/translator/SearchSymbol.h b/src/3rdparty/angle/src/compiler/translator/SearchSymbol.h deleted file mode 100644 index b8379e041f..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/SearchSymbol.h +++ /dev/null @@ -1,33 +0,0 @@ -// -// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// SearchSymbol is an AST traverser to detect the use of a given symbol name -// - -#ifndef COMPILER_TRANSLATOR_SEARCHSYMBOL_H_ -#define COMPILER_TRANSLATOR_SEARCHSYMBOL_H_ - -#include "compiler/translator/IntermTraverse.h" -#include "compiler/translator/ParseContext.h" - -namespace sh -{ -class SearchSymbol : public TIntermTraverser -{ - public: - SearchSymbol(const TString &symbol); - - void traverse(TIntermNode *node); - void visitSymbol(TIntermSymbol *symbolNode) override; - - bool foundMatch() const; - - protected: - const TString &mSymbol; - bool match; -}; -} - -#endif // COMPILER_TRANSLATOR_SEARCHSYMBOL_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/SeparateArrayInitialization.cpp b/src/3rdparty/angle/src/compiler/translator/SeparateArrayInitialization.cpp deleted file mode 100644 index fe25823e38..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/SeparateArrayInitialization.cpp +++ /dev/null @@ -1,92 +0,0 @@ -// -// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// The SeparateArrayInitialization function splits each array initialization into a declaration and -// an assignment. -// Example: -// type[n] a = initializer; -// will effectively become -// type[n] a; -// a = initializer; -// -// Note that if the array is declared as const, the initialization may still be split, making the -// AST technically invalid. Because of that this transformation should only be used when subsequent -// stages don't care about const qualifiers. However, the initialization will not be split if the -// initializer can be written as a HLSL literal. - -#include "compiler/translator/SeparateArrayInitialization.h" - -#include "compiler/translator/IntermNode.h" -#include "compiler/translator/OutputHLSL.h" - -namespace sh -{ - -namespace -{ - -class SeparateArrayInitTraverser : private TIntermTraverser -{ - public: - static void apply(TIntermNode *root); - - private: - SeparateArrayInitTraverser(); - bool visitDeclaration(Visit, TIntermDeclaration *node) override; -}; - -void SeparateArrayInitTraverser::apply(TIntermNode *root) -{ - SeparateArrayInitTraverser separateInit; - root->traverse(&separateInit); - separateInit.updateTree(); -} - -SeparateArrayInitTraverser::SeparateArrayInitTraverser() : TIntermTraverser(true, false, false) -{ -} - -bool SeparateArrayInitTraverser::visitDeclaration(Visit, TIntermDeclaration *node) -{ - TIntermSequence *sequence = node->getSequence(); - TIntermBinary *initNode = sequence->back()->getAsBinaryNode(); - if (initNode != nullptr && initNode->getOp() == EOpInitialize) - { - TIntermTyped *initializer = initNode->getRight(); - if (initializer->isArray() && !sh::OutputHLSL::canWriteAsHLSLLiteral(initializer)) - { - // We rely on that array declarations have been isolated to single declarations. - ASSERT(sequence->size() == 1); - TIntermTyped *symbol = initNode->getLeft(); - TIntermBlock *parentBlock = getParentNode()->getAsBlock(); - ASSERT(parentBlock != nullptr); - - TIntermSequence replacements; - - TIntermDeclaration *replacementDeclaration = new TIntermDeclaration(); - replacementDeclaration->appendDeclarator(symbol); - replacementDeclaration->setLine(symbol->getLine()); - replacements.push_back(replacementDeclaration); - - TIntermBinary *replacementAssignment = - new TIntermBinary(EOpAssign, symbol, initializer); - replacementAssignment->setLine(symbol->getLine()); - replacements.push_back(replacementAssignment); - - mMultiReplacements.push_back( - NodeReplaceWithMultipleEntry(parentBlock, node, replacements)); - } - } - return false; -} - -} // namespace - -void SeparateArrayInitialization(TIntermNode *root) -{ - SeparateArrayInitTraverser::apply(root); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/SeparateArrayInitialization.h b/src/3rdparty/angle/src/compiler/translator/SeparateArrayInitialization.h deleted file mode 100644 index 3a9bb55dd1..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/SeparateArrayInitialization.h +++ /dev/null @@ -1,29 +0,0 @@ -// -// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// The SeparateArrayInitialization function splits each array initialization into a declaration and -// an assignment. -// Example: -// type[n] a = initializer; -// will effectively become -// type[n] a; -// a = initializer; -// -// Note that if the array is declared as const, the initialization may still be split, making the -// AST technically invalid. Because of that this transformation should only be used when subsequent -// stages don't care about const qualifiers. However, the initialization will not be split if the -// initializer can be written as a HLSL literal. - -#ifndef COMPILER_TRANSLATOR_SEPARATEARRAYINITIALIZATION_H_ -#define COMPILER_TRANSLATOR_SEPARATEARRAYINITIALIZATION_H_ - -namespace sh -{ -class TIntermNode; - -void SeparateArrayInitialization(TIntermNode *root); -} // namespace sh - -#endif // COMPILER_TRANSLATOR_SEPARATEARRAYINITIALIZATION_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/SeparateDeclarations.cpp b/src/3rdparty/angle/src/compiler/translator/SeparateDeclarations.cpp deleted file mode 100644 index 9a066075c0..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/SeparateDeclarations.cpp +++ /dev/null @@ -1,79 +0,0 @@ -// -// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// The SeparateDeclarations function processes declarations, so that in the end each declaration -// contains only one declarator. -// This is useful as an intermediate step when initialization needs to be separated from -// declaration, or when things need to be unfolded out of the initializer. -// Example: -// int a[1] = int[1](1), b[1] = int[1](2); -// gets transformed when run through this class into the AST equivalent of: -// int a[1] = int[1](1); -// int b[1] = int[1](2); - -#include "compiler/translator/SeparateDeclarations.h" - -#include "compiler/translator/IntermTraverse.h" - -namespace sh -{ - -namespace -{ - -class SeparateDeclarationsTraverser : private TIntermTraverser -{ - public: - static void apply(TIntermNode *root); - - private: - SeparateDeclarationsTraverser(); - bool visitDeclaration(Visit, TIntermDeclaration *node) override; -}; - -void SeparateDeclarationsTraverser::apply(TIntermNode *root) -{ - SeparateDeclarationsTraverser separateDecl; - root->traverse(&separateDecl); - separateDecl.updateTree(); -} - -SeparateDeclarationsTraverser::SeparateDeclarationsTraverser() - : TIntermTraverser(true, false, false) -{ -} - -bool SeparateDeclarationsTraverser::visitDeclaration(Visit, TIntermDeclaration *node) -{ - TIntermSequence *sequence = node->getSequence(); - if (sequence->size() > 1) - { - TIntermBlock *parentBlock = getParentNode()->getAsBlock(); - ASSERT(parentBlock != nullptr); - - TIntermSequence replacementDeclarations; - for (size_t ii = 0; ii < sequence->size(); ++ii) - { - TIntermDeclaration *replacementDeclaration = new TIntermDeclaration(); - - replacementDeclaration->appendDeclarator(sequence->at(ii)->getAsTyped()); - replacementDeclaration->setLine(sequence->at(ii)->getLine()); - replacementDeclarations.push_back(replacementDeclaration); - } - - mMultiReplacements.push_back( - NodeReplaceWithMultipleEntry(parentBlock, node, replacementDeclarations)); - } - return false; -} - -} // namespace - -void SeparateDeclarations(TIntermNode *root) -{ - SeparateDeclarationsTraverser::apply(root); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/SeparateDeclarations.h b/src/3rdparty/angle/src/compiler/translator/SeparateDeclarations.h deleted file mode 100644 index 8142faea1c..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/SeparateDeclarations.h +++ /dev/null @@ -1,26 +0,0 @@ -// -// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// The SeparateDeclarations function processes declarations, so that in the end each declaration -// contains only one declarator. -// This is useful as an intermediate step when initialization needs to be separated from -// declaration, or when things need to be unfolded out of the initializer. -// Example: -// int a[1] = int[1](1), b[1] = int[1](2); -// gets transformed when run through this class into the AST equivalent of: -// int a[1] = int[1](1); -// int b[1] = int[1](2); - -#ifndef COMPILER_TRANSLATOR_SEPARATEDECLARATIONS_H_ -#define COMPILER_TRANSLATOR_SEPARATEDECLARATIONS_H_ - -namespace sh -{ -class TIntermNode; - -void SeparateDeclarations(TIntermNode *root); -} // namespace sh - -#endif // COMPILER_TRANSLATOR_SEPARATEDECLARATIONS_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/SeparateExpressionsReturningArrays.cpp b/src/3rdparty/angle/src/compiler/translator/SeparateExpressionsReturningArrays.cpp deleted file mode 100644 index 01d627937c..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/SeparateExpressionsReturningArrays.cpp +++ /dev/null @@ -1,126 +0,0 @@ -// -// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// SeparateExpressionsReturningArrays splits array-returning expressions that are not array names -// from more complex expressions, assigning them to a temporary variable a#. -// Examples where a, b and c are all arrays: -// (a = b) == (a = c) is split into a = b; type[n] a1 = a; a = c; type[n] a2 = a; a1 == a2; -// type d = type[n](...)[i]; is split into type[n] a1 = type[n](...); type d = a1[i]; - -#include "compiler/translator/SeparateExpressionsReturningArrays.h" - -#include "compiler/translator/IntermNodePatternMatcher.h" -#include "compiler/translator/IntermTraverse.h" - -namespace sh -{ - -namespace -{ - -// Traverser that separates one array expression into a statement at a time. -class SeparateExpressionsTraverser : public TIntermTraverser -{ - public: - SeparateExpressionsTraverser(TSymbolTable *symbolTable); - - bool visitBinary(Visit visit, TIntermBinary *node) override; - bool visitAggregate(Visit visit, TIntermAggregate *node) override; - - void nextIteration(); - bool foundArrayExpression() const { return mFoundArrayExpression; } - - protected: - // Marked to true once an operation that needs to be hoisted out of the expression has been - // found. After that, no more AST updates are performed on that traversal. - bool mFoundArrayExpression; - - IntermNodePatternMatcher mPatternToSeparateMatcher; -}; - -SeparateExpressionsTraverser::SeparateExpressionsTraverser(TSymbolTable *symbolTable) - : TIntermTraverser(true, false, false, symbolTable), - mFoundArrayExpression(false), - mPatternToSeparateMatcher(IntermNodePatternMatcher::kExpressionReturningArray) -{ -} - -// Performs a shallow copy of an assignment node. -// These shallow copies are useful when a node gets inserted into an aggregate node -// and also needs to be replaced in its original location by a different node. -TIntermBinary *CopyAssignmentNode(TIntermBinary *node) -{ - return new TIntermBinary(node->getOp(), node->getLeft(), node->getRight()); -} - -bool SeparateExpressionsTraverser::visitBinary(Visit visit, TIntermBinary *node) -{ - if (mFoundArrayExpression) - return false; - - // Return if the expression is not an array or if we're not inside a complex expression. - if (!mPatternToSeparateMatcher.match(node, getParentNode())) - return true; - - ASSERT(node->getOp() == EOpAssign); - - mFoundArrayExpression = true; - - TIntermSequence insertions; - insertions.push_back(CopyAssignmentNode(node)); - // TODO(oetuaho): In some cases it would be more optimal to not add the temporary node, but just - // use the original target of the assignment. Care must be taken so that this doesn't happen - // when the same array symbol is a target of assignment more than once in one expression. - insertions.push_back(createTempInitDeclaration(node->getLeft())); - insertStatementsInParentBlock(insertions); - - queueReplacement(createTempSymbol(node->getType()), OriginalNode::IS_DROPPED); - - return false; -} - -bool SeparateExpressionsTraverser::visitAggregate(Visit visit, TIntermAggregate *node) -{ - if (mFoundArrayExpression) - return false; // No need to traverse further - - if (!mPatternToSeparateMatcher.match(node, getParentNode())) - return true; - - ASSERT(node->isConstructor() || node->getOp() == EOpCallFunctionInAST); - - mFoundArrayExpression = true; - - TIntermSequence insertions; - insertions.push_back(createTempInitDeclaration(node->shallowCopy())); - insertStatementsInParentBlock(insertions); - - queueReplacement(createTempSymbol(node->getType()), OriginalNode::IS_DROPPED); - - return false; -} - -void SeparateExpressionsTraverser::nextIteration() -{ - mFoundArrayExpression = false; - nextTemporaryId(); -} - -} // namespace - -void SeparateExpressionsReturningArrays(TIntermNode *root, TSymbolTable *symbolTable) -{ - SeparateExpressionsTraverser traverser(symbolTable); - // Separate one expression at a time, and reset the traverser between iterations. - do - { - traverser.nextIteration(); - root->traverse(&traverser); - if (traverser.foundArrayExpression()) - traverser.updateTree(); - } while (traverser.foundArrayExpression()); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/SeparateExpressionsReturningArrays.h b/src/3rdparty/angle/src/compiler/translator/SeparateExpressionsReturningArrays.h deleted file mode 100644 index f8eb438748..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/SeparateExpressionsReturningArrays.h +++ /dev/null @@ -1,23 +0,0 @@ -// -// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// SeparateExpressionsReturningArrays splits array-returning expressions that are not array names -// from more complex expressions, assigning them to a temporary variable a#. -// Examples where a, b and c are all arrays: -// (a = b) == (a = c) is split into a = b; type[n] a1 = a; a = c; type[n] a2 = a; a1 == a2; -// type d = type[n](...)[i]; is split into type[n] a1 = type[n](...); type d = a1[i]; - -#ifndef COMPILER_TRANSLATOR_SEPARATEEXPRESSIONSRETURNINGARRAYS_H_ -#define COMPILER_TRANSLATOR_SEPARATEEXPRESSIONSRETURNINGARRAYS_H_ - -namespace sh -{ -class TIntermNode; -class TSymbolTable; - -void SeparateExpressionsReturningArrays(TIntermNode *root, TSymbolTable *symbolTable); -} // namespace sh - -#endif // COMPILER_TRANSLATOR_SEPARATEEXPRESSIONSRETURNINGARRAYS_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/Severity.h b/src/3rdparty/angle/src/compiler/translator/Severity.h deleted file mode 100644 index 47808a16a7..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/Severity.h +++ /dev/null @@ -1,22 +0,0 @@ -// -// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_TRANSLATOR_SEVERITY_H_ -#define COMPILER_TRANSLATOR_SEVERITY_H_ - -namespace sh -{ - -// Severity is used to classify info log messages. -enum Severity -{ - SH_WARNING, - SH_ERROR -}; - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_SEVERITY_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/ShaderLang.cpp b/src/3rdparty/angle/src/compiler/translator/ShaderLang.cpp deleted file mode 100644 index eeb13f2ec0..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/ShaderLang.cpp +++ /dev/null @@ -1,578 +0,0 @@ -// -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// -// Implement the top-level of interface to the compiler, -// as defined in ShaderLang.h -// - -#include "GLSLANG/ShaderLang.h" - -#include "compiler/translator/Compiler.h" -#include "compiler/translator/InitializeDll.h" -#include "compiler/translator/length_limits.h" -#ifdef ANGLE_ENABLE_HLSL -#include "compiler/translator/TranslatorHLSL.h" -#endif // ANGLE_ENABLE_HLSL -#include "compiler/translator/VariablePacker.h" -#include "angle_gl.h" - -namespace sh -{ - -namespace -{ - -bool isInitialized = false; - -// -// This is the platform independent interface between an OGL driver -// and the shading language compiler. -// - -template -const std::vector *GetVariableList(const TCompiler *compiler); - -template <> -const std::vector *GetVariableList(const TCompiler *compiler) -{ - return &compiler->getUniforms(); -} - -template <> -const std::vector *GetVariableList(const TCompiler *compiler) -{ - switch (compiler->getShaderType()) - { - case GL_VERTEX_SHADER: - return &compiler->getOutputVaryings(); - case GL_FRAGMENT_SHADER: - return &compiler->getInputVaryings(); - case GL_COMPUTE_SHADER: - ASSERT(compiler->getOutputVaryings().empty() && compiler->getInputVaryings().empty()); - return &compiler->getOutputVaryings(); - // Since geometry shaders have both input and output varyings, we shouldn't call GetVaryings - // on a geometry shader. - default: - return nullptr; - } -} - -template <> -const std::vector *GetVariableList(const TCompiler *compiler) -{ - return &compiler->getAttributes(); -} - -template <> -const std::vector *GetVariableList(const TCompiler *compiler) -{ - return &compiler->getOutputVariables(); -} - -template <> -const std::vector *GetVariableList(const TCompiler *compiler) -{ - return &compiler->getInterfaceBlocks(); -} - -TCompiler *GetCompilerFromHandle(ShHandle handle) -{ - if (!handle) - { - return nullptr; - } - - TShHandleBase *base = static_cast(handle); - return base->getAsCompiler(); -} - -template -const std::vector *GetShaderVariables(const ShHandle handle) -{ - TCompiler *compiler = GetCompilerFromHandle(handle); - if (!compiler) - { - return nullptr; - } - - return GetVariableList(compiler); -} - -#ifdef ANGLE_ENABLE_HLSL -TranslatorHLSL *GetTranslatorHLSLFromHandle(ShHandle handle) -{ - if (!handle) - return nullptr; - TShHandleBase *base = static_cast(handle); - return base->getAsTranslatorHLSL(); -} -#endif // ANGLE_ENABLE_HLSL - -GLenum GetGeometryShaderPrimitiveTypeEnum(sh::TLayoutPrimitiveType primitiveType) -{ - switch (primitiveType) - { - case EptPoints: - return GL_POINTS; - case EptLines: - return GL_LINES; - case EptLinesAdjacency: - return GL_LINES_ADJACENCY_EXT; - case EptTriangles: - return GL_TRIANGLES; - case EptTrianglesAdjacency: - return GL_TRIANGLES_ADJACENCY_EXT; - - case EptLineStrip: - return GL_LINE_STRIP; - case EptTriangleStrip: - return GL_TRIANGLE_STRIP; - - case EptUndefined: - return GL_INVALID_VALUE; - - default: - UNREACHABLE(); - return GL_INVALID_VALUE; - } -} - -} // anonymous namespace - -// -// Driver must call this first, once, before doing any other compiler operations. -// Subsequent calls to this function are no-op. -// -bool Initialize() -{ - if (!isInitialized) - { - isInitialized = InitProcess(); - } - return isInitialized; -} - -// -// Cleanup symbol tables -// -bool Finalize() -{ - if (isInitialized) - { - DetachProcess(); - isInitialized = false; - } - return true; -} - -// -// Initialize built-in resources with minimum expected values. -// -void InitBuiltInResources(ShBuiltInResources *resources) -{ - // Make comparable. - memset(resources, 0, sizeof(*resources)); - - // Constants. - resources->MaxVertexAttribs = 8; - resources->MaxVertexUniformVectors = 128; - resources->MaxVaryingVectors = 8; - resources->MaxVertexTextureImageUnits = 0; - resources->MaxCombinedTextureImageUnits = 8; - resources->MaxTextureImageUnits = 8; - resources->MaxFragmentUniformVectors = 16; - resources->MaxDrawBuffers = 1; - - // Extensions. - resources->OES_standard_derivatives = 0; - resources->OES_EGL_image_external = 0; - resources->OES_EGL_image_external_essl3 = 0; - resources->NV_EGL_stream_consumer_external = 0; - resources->ARB_texture_rectangle = 0; - resources->EXT_blend_func_extended = 0; - resources->EXT_draw_buffers = 0; - resources->EXT_frag_depth = 0; - resources->EXT_shader_texture_lod = 0; - resources->WEBGL_debug_shader_precision = 0; - resources->EXT_shader_framebuffer_fetch = 0; - resources->NV_shader_framebuffer_fetch = 0; - resources->ARM_shader_framebuffer_fetch = 0; - resources->OVR_multiview = 0; - resources->EXT_YUV_target = 0; - resources->OES_geometry_shader = 0; - - resources->NV_draw_buffers = 0; - - // Disable highp precision in fragment shader by default. - resources->FragmentPrecisionHigh = 0; - - // GLSL ES 3.0 constants. - resources->MaxVertexOutputVectors = 16; - resources->MaxFragmentInputVectors = 15; - resources->MinProgramTexelOffset = -8; - resources->MaxProgramTexelOffset = 7; - - // Extensions constants. - resources->MaxDualSourceDrawBuffers = 0; - - resources->MaxViewsOVR = 4; - - // Disable name hashing by default. - resources->HashFunction = nullptr; - - resources->ArrayIndexClampingStrategy = SH_CLAMP_WITH_CLAMP_INTRINSIC; - - resources->MaxExpressionComplexity = 256; - resources->MaxCallStackDepth = 256; - resources->MaxFunctionParameters = 1024; - - // ES 3.1 Revision 4, 7.2 Built-in Constants - - // ES 3.1, Revision 4, 8.13 Texture minification - // "The value of MIN_PROGRAM_TEXTURE_GATHER_OFFSET must be less than or equal to the value of - // MIN_PROGRAM_TEXEL_OFFSET. The value of MAX_PROGRAM_TEXTURE_GATHER_OFFSET must be greater than - // or equal to the value of MAX_PROGRAM_TEXEL_OFFSET" - resources->MinProgramTextureGatherOffset = -8; - resources->MaxProgramTextureGatherOffset = 7; - - resources->MaxImageUnits = 4; - resources->MaxVertexImageUniforms = 0; - resources->MaxFragmentImageUniforms = 0; - resources->MaxComputeImageUniforms = 4; - resources->MaxCombinedImageUniforms = 4; - - resources->MaxUniformLocations = 1024; - - resources->MaxCombinedShaderOutputResources = 4; - - resources->MaxComputeWorkGroupCount[0] = 65535; - resources->MaxComputeWorkGroupCount[1] = 65535; - resources->MaxComputeWorkGroupCount[2] = 65535; - resources->MaxComputeWorkGroupSize[0] = 128; - resources->MaxComputeWorkGroupSize[1] = 128; - resources->MaxComputeWorkGroupSize[2] = 64; - resources->MaxComputeUniformComponents = 512; - resources->MaxComputeTextureImageUnits = 16; - - resources->MaxComputeAtomicCounters = 8; - resources->MaxComputeAtomicCounterBuffers = 1; - - resources->MaxVertexAtomicCounters = 0; - resources->MaxFragmentAtomicCounters = 0; - resources->MaxCombinedAtomicCounters = 8; - resources->MaxAtomicCounterBindings = 1; - - resources->MaxVertexAtomicCounterBuffers = 0; - resources->MaxFragmentAtomicCounterBuffers = 0; - resources->MaxCombinedAtomicCounterBuffers = 1; - resources->MaxAtomicCounterBufferSize = 32; - - resources->MaxUniformBufferBindings = 32; - resources->MaxShaderStorageBufferBindings = 4; - - resources->MaxGeometryUniformComponents = 1024; - resources->MaxGeometryUniformBlocks = 12; - resources->MaxGeometryInputComponents = 64; - resources->MaxGeometryOutputComponents = 64; - resources->MaxGeometryOutputVertices = 256; - resources->MaxGeometryTotalOutputComponents = 1024; - resources->MaxGeometryTextureImageUnits = 16; - resources->MaxGeometryAtomicCounterBuffers = 0; - resources->MaxGeometryAtomicCounters = 0; - resources->MaxGeometryShaderStorageBlocks = 0; - resources->MaxGeometryShaderInvocations = 32; - resources->MaxGeometryImageUniforms = 0; -} - -// -// Driver calls these to create and destroy compiler objects. -// -ShHandle ConstructCompiler(sh::GLenum type, - ShShaderSpec spec, - ShShaderOutput output, - const ShBuiltInResources *resources) -{ - TShHandleBase *base = static_cast(ConstructCompiler(type, spec, output)); - if (base == nullptr) - { - return 0; - } - - TCompiler *compiler = base->getAsCompiler(); - if (compiler == nullptr) - { - return 0; - } - - // Generate built-in symbol table. - if (!compiler->Init(*resources)) - { - Destruct(base); - return 0; - } - - return reinterpret_cast(base); -} - -void Destruct(ShHandle handle) -{ - if (handle == 0) - return; - - TShHandleBase *base = static_cast(handle); - - if (base->getAsCompiler()) - DeleteCompiler(base->getAsCompiler()); -} - -const std::string &GetBuiltInResourcesString(const ShHandle handle) -{ - TCompiler *compiler = GetCompilerFromHandle(handle); - ASSERT(compiler); - return compiler->getBuiltInResourcesString(); -} - -// -// Do an actual compile on the given strings. The result is left -// in the given compile object. -// -// Return: The return value of ShCompile is really boolean, indicating -// success or failure. -// -bool Compile(const ShHandle handle, - const char *const shaderStrings[], - size_t numStrings, - ShCompileOptions compileOptions) -{ - TCompiler *compiler = GetCompilerFromHandle(handle); - ASSERT(compiler); - - return compiler->compile(shaderStrings, numStrings, compileOptions); -} - -void ClearResults(const ShHandle handle) -{ - TCompiler *compiler = GetCompilerFromHandle(handle); - ASSERT(compiler); - compiler->clearResults(); -} - -int GetShaderVersion(const ShHandle handle) -{ - TCompiler *compiler = GetCompilerFromHandle(handle); - ASSERT(compiler); - return compiler->getShaderVersion(); -} - -ShShaderOutput GetShaderOutputType(const ShHandle handle) -{ - TCompiler *compiler = GetCompilerFromHandle(handle); - ASSERT(compiler); - return compiler->getOutputType(); -} - -// -// Return any compiler log of messages for the application. -// -const std::string &GetInfoLog(const ShHandle handle) -{ - TCompiler *compiler = GetCompilerFromHandle(handle); - ASSERT(compiler); - - TInfoSink &infoSink = compiler->getInfoSink(); - return infoSink.info.str(); -} - -// -// Return any object code. -// -const std::string &GetObjectCode(const ShHandle handle) -{ - TCompiler *compiler = GetCompilerFromHandle(handle); - ASSERT(compiler); - - TInfoSink &infoSink = compiler->getInfoSink(); - return infoSink.obj.str(); -} - -const std::map *GetNameHashingMap(const ShHandle handle) -{ - TCompiler *compiler = GetCompilerFromHandle(handle); - ASSERT(compiler); - return &(compiler->getNameMap()); -} - -const std::vector *GetUniforms(const ShHandle handle) -{ - return GetShaderVariables(handle); -} - -const std::vector *GetInputVaryings(const ShHandle handle) -{ - TCompiler *compiler = GetCompilerFromHandle(handle); - if (compiler == nullptr) - { - return nullptr; - } - return &compiler->getInputVaryings(); -} - -const std::vector *GetOutputVaryings(const ShHandle handle) -{ - TCompiler *compiler = GetCompilerFromHandle(handle); - if (compiler == nullptr) - { - return nullptr; - } - return &compiler->getOutputVaryings(); -} - -const std::vector *GetVaryings(const ShHandle handle) -{ - return GetShaderVariables(handle); -} - -const std::vector *GetAttributes(const ShHandle handle) -{ - return GetShaderVariables(handle); -} - -const std::vector *GetOutputVariables(const ShHandle handle) -{ - return GetShaderVariables(handle); -} - -const std::vector *GetInterfaceBlocks(const ShHandle handle) -{ - return GetShaderVariables(handle); -} - -const std::vector *GetUniformBlocks(const ShHandle handle) -{ - ASSERT(handle); - TShHandleBase *base = static_cast(handle); - TCompiler *compiler = base->getAsCompiler(); - ASSERT(compiler); - - return &compiler->getUniformBlocks(); -} - -const std::vector *GetShaderStorageBlocks(const ShHandle handle) -{ - ASSERT(handle); - TShHandleBase *base = static_cast(handle); - TCompiler *compiler = base->getAsCompiler(); - ASSERT(compiler); - - return &compiler->getShaderStorageBlocks(); -} - -WorkGroupSize GetComputeShaderLocalGroupSize(const ShHandle handle) -{ - ASSERT(handle); - - TShHandleBase *base = static_cast(handle); - TCompiler *compiler = base->getAsCompiler(); - ASSERT(compiler); - - return compiler->getComputeShaderLocalSize(); -} - -int GetVertexShaderNumViews(const ShHandle handle) -{ - ASSERT(handle); - TShHandleBase *base = static_cast(handle); - TCompiler *compiler = base->getAsCompiler(); - ASSERT(compiler); - - return compiler->getNumViews(); -} - -bool CheckVariablesWithinPackingLimits(int maxVectors, const std::vector &variables) -{ - return CheckVariablesInPackingLimits(maxVectors, variables); -} - -bool GetUniformBlockRegister(const ShHandle handle, - const std::string &uniformBlockName, - unsigned int *indexOut) -{ -#ifdef ANGLE_ENABLE_HLSL - ASSERT(indexOut); - - TranslatorHLSL *translator = GetTranslatorHLSLFromHandle(handle); - ASSERT(translator); - - if (!translator->hasUniformBlock(uniformBlockName)) - { - return false; - } - - *indexOut = translator->getUniformBlockRegister(uniformBlockName); - return true; -#else - return false; -#endif // ANGLE_ENABLE_HLSL -} - -const std::map *GetUniformRegisterMap(const ShHandle handle) -{ -#ifdef ANGLE_ENABLE_HLSL - TranslatorHLSL *translator = GetTranslatorHLSLFromHandle(handle); - ASSERT(translator); - - return translator->getUniformRegisterMap(); -#else - return nullptr; -#endif // ANGLE_ENABLE_HLSL -} - -GLenum GetGeometryShaderInputPrimitiveType(const ShHandle handle) -{ - ASSERT(handle); - - TShHandleBase *base = static_cast(handle); - TCompiler *compiler = base->getAsCompiler(); - ASSERT(compiler); - - return GetGeometryShaderPrimitiveTypeEnum(compiler->getGeometryShaderInputPrimitiveType()); -} - -GLenum GetGeometryShaderOutputPrimitiveType(const ShHandle handle) -{ - ASSERT(handle); - - TShHandleBase *base = static_cast(handle); - TCompiler *compiler = base->getAsCompiler(); - ASSERT(compiler); - - return GetGeometryShaderPrimitiveTypeEnum(compiler->getGeometryShaderOutputPrimitiveType()); -} - -int GetGeometryShaderInvocations(const ShHandle handle) -{ - ASSERT(handle); - - TShHandleBase *base = static_cast(handle); - TCompiler *compiler = base->getAsCompiler(); - ASSERT(compiler); - - return compiler->getGeometryShaderInvocations(); -} - -int GetGeometryShaderMaxVertices(const ShHandle handle) -{ - ASSERT(handle); - - TShHandleBase *base = static_cast(handle); - TCompiler *compiler = base->getAsCompiler(); - ASSERT(compiler); - - return compiler->getGeometryShaderMaxVertices(); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/ShaderVars.cpp b/src/3rdparty/angle/src/compiler/translator/ShaderVars.cpp deleted file mode 100644 index 4ab574e935..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/ShaderVars.cpp +++ /dev/null @@ -1,586 +0,0 @@ -// -// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// ShaderVars.cpp: -// Methods for GL variable types (varyings, uniforms, etc) -// - -#include - -#include "common/debug.h" -#include "common/utilities.h" - -namespace sh -{ - -namespace -{ - -InterpolationType GetNonAuxiliaryInterpolationType(InterpolationType interpolation) -{ - return (interpolation == INTERPOLATION_CENTROID ? INTERPOLATION_SMOOTH : interpolation); -} -} -// The ES 3.0 spec is not clear on this point, but the ES 3.1 spec, and discussion -// on Khronos.org, clarifies that a smooth/flat mismatch produces a link error, -// but auxiliary qualifier mismatch (centroid) does not. -bool InterpolationTypesMatch(InterpolationType a, InterpolationType b) -{ - return (GetNonAuxiliaryInterpolationType(a) == GetNonAuxiliaryInterpolationType(b)); -} - -ShaderVariable::ShaderVariable() - : type(0), precision(0), flattenedOffsetInParentArrays(0), staticUse(false) -{ -} - -ShaderVariable::ShaderVariable(GLenum typeIn) - : type(typeIn), precision(0), flattenedOffsetInParentArrays(0), staticUse(false) -{ -} - -ShaderVariable::ShaderVariable(GLenum typeIn, unsigned int arraySizeIn) - : type(typeIn), precision(0), flattenedOffsetInParentArrays(0), staticUse(false) -{ - ASSERT(arraySizeIn != 0); - arraySizes.push_back(arraySizeIn); -} - -ShaderVariable::~ShaderVariable() -{ -} - -ShaderVariable::ShaderVariable(const ShaderVariable &other) - : type(other.type), - precision(other.precision), - name(other.name), - mappedName(other.mappedName), - arraySizes(other.arraySizes), - flattenedOffsetInParentArrays(other.flattenedOffsetInParentArrays), - staticUse(other.staticUse), - fields(other.fields), - structName(other.structName) -{ -} - -ShaderVariable &ShaderVariable::operator=(const ShaderVariable &other) -{ - type = other.type; - precision = other.precision; - name = other.name; - mappedName = other.mappedName; - arraySizes = other.arraySizes; - staticUse = other.staticUse; - flattenedOffsetInParentArrays = other.flattenedOffsetInParentArrays; - fields = other.fields; - structName = other.structName; - return *this; -} - -bool ShaderVariable::operator==(const ShaderVariable &other) const -{ - if (type != other.type || precision != other.precision || name != other.name || - mappedName != other.mappedName || arraySizes != other.arraySizes || - staticUse != other.staticUse || fields.size() != other.fields.size() || - structName != other.structName) - { - return false; - } - for (size_t ii = 0; ii < fields.size(); ++ii) - { - if (fields[ii] != other.fields[ii]) - return false; - } - return true; -} - -void ShaderVariable::setArraySize(unsigned int size) -{ - arraySizes.clear(); - if (size != 0) - { - arraySizes.push_back(size); - } -} - -unsigned int ShaderVariable::getArraySizeProduct() const -{ - return gl::ArraySizeProduct(arraySizes); -} - -void ShaderVariable::indexIntoArray(unsigned int arrayIndex) -{ - ASSERT(isArray()); - flattenedOffsetInParentArrays = - arrayIndex + getOutermostArraySize() * flattenedOffsetInParentArrays; - arraySizes.pop_back(); -} - -unsigned int ShaderVariable::getNestedArraySize(unsigned int arrayNestingIndex) const -{ - ASSERT(arraySizes.size() > arrayNestingIndex); - return arraySizes[arraySizes.size() - 1u - arrayNestingIndex]; -} - -unsigned int ShaderVariable::getBasicTypeElementCount() const -{ - // GLES 3.1 Nov 2016 section 7.3.1.1 page 77 specifies that a separate entry should be generated - // for each array element when dealing with an array of arrays or an array of structs. - ASSERT(!isArrayOfArrays()); - ASSERT(!isStruct() || !isArray()); - - // GLES 3.1 Nov 2016 page 82. - if (isArray()) - { - return getOutermostArraySize(); - } - return 1u; -} - -bool ShaderVariable::findInfoByMappedName(const std::string &mappedFullName, - const ShaderVariable **leafVar, - std::string *originalFullName) const -{ - ASSERT(leafVar && originalFullName); - // There are three cases: - // 1) the top variable is of struct type; - // 2) the top variable is an array; - // 3) otherwise. - size_t pos = mappedFullName.find_first_of(".["); - - if (pos == std::string::npos) - { - // Case 3. - if (mappedFullName != this->mappedName) - return false; - *originalFullName = this->name; - *leafVar = this; - return true; - } - else - { - std::string topName = mappedFullName.substr(0, pos); - if (topName != this->mappedName) - return false; - std::string originalName = this->name; - std::string remaining; - if (mappedFullName[pos] == '[') - { - // Case 2. - size_t closePos = mappedFullName.find_first_of(']'); - if (closePos < pos || closePos == std::string::npos) - return false; - // Append '[index]'. - originalName += mappedFullName.substr(pos, closePos - pos + 1); - if (closePos + 1 == mappedFullName.size()) - { - *originalFullName = originalName; - *leafVar = this; - return true; - } - else - { - // In the form of 'a[0].b', so after ']', '.' is expected. - if (mappedFullName[closePos + 1] != '.') - return false; - remaining = mappedFullName.substr(closePos + 2); // Skip "]." - } - } - else - { - // Case 1. - remaining = mappedFullName.substr(pos + 1); // Skip "." - } - for (size_t ii = 0; ii < this->fields.size(); ++ii) - { - const ShaderVariable *fieldVar = nullptr; - std::string originalFieldName; - bool found = fields[ii].findInfoByMappedName(remaining, &fieldVar, &originalFieldName); - if (found) - { - *originalFullName = originalName + "." + originalFieldName; - *leafVar = fieldVar; - return true; - } - } - return false; - } -} - -bool ShaderVariable::isBuiltIn() const -{ - return (name.size() >= 4 && name[0] == 'g' && name[1] == 'l' && name[2] == '_'); -} - -bool ShaderVariable::isSameVariableAtLinkTime(const ShaderVariable &other, - bool matchPrecision, - bool matchName) const -{ - if (type != other.type) - return false; - if (matchPrecision && precision != other.precision) - return false; - if (matchName && name != other.name) - return false; - ASSERT(!matchName || mappedName == other.mappedName); - if (arraySizes != other.arraySizes) - return false; - if (fields.size() != other.fields.size()) - return false; - - // [OpenGL ES 3.1 SPEC Chapter 7.4.1] - // Variables declared as structures are considered to match in type if and only if structure - // members match in name, type, qualification, and declaration order. - for (size_t ii = 0; ii < fields.size(); ++ii) - { - if (!fields[ii].isSameVariableAtLinkTime(other.fields[ii], matchPrecision, true)) - { - return false; - } - } - if (structName != other.structName) - return false; - return true; -} - -Uniform::Uniform() : binding(-1), offset(-1) -{ -} - -Uniform::~Uniform() -{ -} - -Uniform::Uniform(const Uniform &other) - : VariableWithLocation(other), binding(other.binding), offset(other.offset) -{ -} - -Uniform &Uniform::operator=(const Uniform &other) -{ - VariableWithLocation::operator=(other); - binding = other.binding; - offset = other.offset; - return *this; -} - -bool Uniform::operator==(const Uniform &other) const -{ - return VariableWithLocation::operator==(other) && binding == other.binding && - offset == other.offset; -} - -bool Uniform::isSameUniformAtLinkTime(const Uniform &other) const -{ - // Enforce a consistent match. - // https://cvs.khronos.org/bugzilla/show_bug.cgi?id=16261 - if (binding != -1 && other.binding != -1 && binding != other.binding) - { - return false; - } - if (location != -1 && other.location != -1 && location != other.location) - { - return false; - } - if (offset != other.offset) - { - return false; - } - return VariableWithLocation::isSameVariableAtLinkTime(other, true, true); -} - -VariableWithLocation::VariableWithLocation() : location(-1) -{ -} - -VariableWithLocation::~VariableWithLocation() -{ -} - -VariableWithLocation::VariableWithLocation(const VariableWithLocation &other) - : ShaderVariable(other), location(other.location) -{ -} - -VariableWithLocation &VariableWithLocation::operator=(const VariableWithLocation &other) -{ - ShaderVariable::operator=(other); - location = other.location; - return *this; -} - -bool VariableWithLocation::operator==(const VariableWithLocation &other) const -{ - return (ShaderVariable::operator==(other) && location == other.location); -} - -Attribute::Attribute() -{ -} - -Attribute::~Attribute() -{ -} - -Attribute::Attribute(const Attribute &other) : VariableWithLocation(other) -{ -} - -Attribute &Attribute::operator=(const Attribute &other) -{ - VariableWithLocation::operator=(other); - return *this; -} - -bool Attribute::operator==(const Attribute &other) const -{ - return VariableWithLocation::operator==(other); -} - -OutputVariable::OutputVariable() -{ -} - -OutputVariable::~OutputVariable() -{ -} - -OutputVariable::OutputVariable(const OutputVariable &other) : VariableWithLocation(other) -{ -} - -OutputVariable &OutputVariable::operator=(const OutputVariable &other) -{ - VariableWithLocation::operator=(other); - return *this; -} - -bool OutputVariable::operator==(const OutputVariable &other) const -{ - return VariableWithLocation::operator==(other); -} - -InterfaceBlockField::InterfaceBlockField() : isRowMajorLayout(false) -{ -} - -InterfaceBlockField::~InterfaceBlockField() -{ -} - -InterfaceBlockField::InterfaceBlockField(const InterfaceBlockField &other) - : ShaderVariable(other), isRowMajorLayout(other.isRowMajorLayout) -{ -} - -InterfaceBlockField &InterfaceBlockField::operator=(const InterfaceBlockField &other) -{ - ShaderVariable::operator=(other); - isRowMajorLayout = other.isRowMajorLayout; - return *this; -} - -bool InterfaceBlockField::operator==(const InterfaceBlockField &other) const -{ - return (ShaderVariable::operator==(other) && isRowMajorLayout == other.isRowMajorLayout); -} - -bool InterfaceBlockField::isSameInterfaceBlockFieldAtLinkTime( - const InterfaceBlockField &other) const -{ - return (ShaderVariable::isSameVariableAtLinkTime(other, true, true) && - isRowMajorLayout == other.isRowMajorLayout); -} - -Varying::Varying() : interpolation(INTERPOLATION_SMOOTH), isInvariant(false) -{ -} - -Varying::~Varying() -{ -} - -Varying::Varying(const Varying &other) - : VariableWithLocation(other), - interpolation(other.interpolation), - isInvariant(other.isInvariant) -{ -} - -Varying &Varying::operator=(const Varying &other) -{ - VariableWithLocation::operator=(other); - interpolation = other.interpolation; - isInvariant = other.isInvariant; - return *this; -} - -bool Varying::operator==(const Varying &other) const -{ - return (VariableWithLocation::operator==(other) && interpolation == other.interpolation && - isInvariant == other.isInvariant); -} - -bool Varying::isSameVaryingAtLinkTime(const Varying &other) const -{ - return isSameVaryingAtLinkTime(other, 100); -} - -bool Varying::isSameVaryingAtLinkTime(const Varying &other, int shaderVersion) const -{ - return (ShaderVariable::isSameVariableAtLinkTime(other, false, false) && - InterpolationTypesMatch(interpolation, other.interpolation) && - (shaderVersion >= 300 || isInvariant == other.isInvariant) && - (location == other.location) && - (name == other.name || (shaderVersion >= 310 && location >= 0))); -} - -InterfaceBlock::InterfaceBlock() - : arraySize(0), - layout(BLOCKLAYOUT_PACKED), - isRowMajorLayout(false), - binding(-1), - staticUse(false), - blockType(BlockType::BLOCK_UNIFORM) -{ -} - -InterfaceBlock::~InterfaceBlock() -{ -} - -InterfaceBlock::InterfaceBlock(const InterfaceBlock &other) - : name(other.name), - mappedName(other.mappedName), - instanceName(other.instanceName), - arraySize(other.arraySize), - layout(other.layout), - isRowMajorLayout(other.isRowMajorLayout), - binding(other.binding), - staticUse(other.staticUse), - blockType(other.blockType), - fields(other.fields) -{ -} - -InterfaceBlock &InterfaceBlock::operator=(const InterfaceBlock &other) -{ - name = other.name; - mappedName = other.mappedName; - instanceName = other.instanceName; - arraySize = other.arraySize; - layout = other.layout; - isRowMajorLayout = other.isRowMajorLayout; - binding = other.binding; - staticUse = other.staticUse; - blockType = other.blockType; - fields = other.fields; - return *this; -} - -std::string InterfaceBlock::fieldPrefix() const -{ - return instanceName.empty() ? "" : name; -} - -std::string InterfaceBlock::fieldMappedPrefix() const -{ - return instanceName.empty() ? "" : mappedName; -} - -bool InterfaceBlock::isSameInterfaceBlockAtLinkTime(const InterfaceBlock &other) const -{ - if (name != other.name || mappedName != other.mappedName || arraySize != other.arraySize || - layout != other.layout || isRowMajorLayout != other.isRowMajorLayout || - binding != other.binding || blockType != other.blockType || - fields.size() != other.fields.size()) - { - return false; - } - - for (size_t fieldIndex = 0; fieldIndex < fields.size(); ++fieldIndex) - { - if (!fields[fieldIndex].isSameInterfaceBlockFieldAtLinkTime(other.fields[fieldIndex])) - { - return false; - } - } - - return true; -} - -bool InterfaceBlock::isBuiltIn() const -{ - return (name.size() >= 4 && name[0] == 'g' && name[1] == 'l' && name[2] == '_'); -} - -void WorkGroupSize::fill(int fillValue) -{ - localSizeQualifiers[0] = fillValue; - localSizeQualifiers[1] = fillValue; - localSizeQualifiers[2] = fillValue; -} - -void WorkGroupSize::setLocalSize(int localSizeX, int localSizeY, int localSizeZ) -{ - localSizeQualifiers[0] = localSizeX; - localSizeQualifiers[1] = localSizeY; - localSizeQualifiers[2] = localSizeZ; -} - -// check that if one of them is less than 1, then all of them are. -// Or if one is positive, then all of them are positive. -bool WorkGroupSize::isLocalSizeValid() const -{ - return ( - (localSizeQualifiers[0] < 1 && localSizeQualifiers[1] < 1 && localSizeQualifiers[2] < 1) || - (localSizeQualifiers[0] > 0 && localSizeQualifiers[1] > 0 && localSizeQualifiers[2] > 0)); -} - -bool WorkGroupSize::isAnyValueSet() const -{ - return localSizeQualifiers[0] > 0 || localSizeQualifiers[1] > 0 || localSizeQualifiers[2] > 0; -} - -bool WorkGroupSize::isDeclared() const -{ - bool localSizeDeclared = localSizeQualifiers[0] > 0; - ASSERT(isLocalSizeValid()); - return localSizeDeclared; -} - -bool WorkGroupSize::isWorkGroupSizeMatching(const WorkGroupSize &right) const -{ - for (size_t i = 0u; i < size(); ++i) - { - bool result = (localSizeQualifiers[i] == right.localSizeQualifiers[i] || - (localSizeQualifiers[i] == 1 && right.localSizeQualifiers[i] == -1) || - (localSizeQualifiers[i] == -1 && right.localSizeQualifiers[i] == 1)); - if (!result) - { - return false; - } - } - return true; -} - -int &WorkGroupSize::operator[](size_t index) -{ - ASSERT(index < size()); - return localSizeQualifiers[index]; -} - -int WorkGroupSize::operator[](size_t index) const -{ - ASSERT(index < size()); - return localSizeQualifiers[index]; -} - -size_t WorkGroupSize::size() const -{ - return 3u; -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/SimplifyLoopConditions.cpp b/src/3rdparty/angle/src/compiler/translator/SimplifyLoopConditions.cpp deleted file mode 100644 index 9704046839..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/SimplifyLoopConditions.cpp +++ /dev/null @@ -1,300 +0,0 @@ -// -// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// SimplifyLoopConditions is an AST traverser that converts loop conditions and loop expressions -// to regular statements inside the loop. This way further transformations that generate statements -// from loop conditions and loop expressions work correctly. -// - -#include "compiler/translator/SimplifyLoopConditions.h" - -#include "compiler/translator/IntermNodePatternMatcher.h" -#include "compiler/translator/IntermNode_util.h" -#include "compiler/translator/IntermTraverse.h" - -namespace sh -{ - -namespace -{ - -class SimplifyLoopConditionsTraverser : public TLValueTrackingTraverser -{ - public: - SimplifyLoopConditionsTraverser(unsigned int conditionsToSimplifyMask, - TSymbolTable *symbolTable, - int shaderVersion); - - void traverseLoop(TIntermLoop *node) override; - - bool visitUnary(Visit visit, TIntermUnary *node) override; - bool visitBinary(Visit visit, TIntermBinary *node) override; - bool visitAggregate(Visit visit, TIntermAggregate *node) override; - bool visitTernary(Visit visit, TIntermTernary *node) override; - bool visitDeclaration(Visit visit, TIntermDeclaration *node) override; - - bool foundLoopToChange() const { return mFoundLoopToChange; } - - protected: - // Marked to true once an operation that needs to be hoisted out of a loop expression has been - // found. - bool mFoundLoopToChange; - bool mInsideLoopInitConditionOrExpression; - IntermNodePatternMatcher mConditionsToSimplify; -}; - -SimplifyLoopConditionsTraverser::SimplifyLoopConditionsTraverser( - unsigned int conditionsToSimplifyMask, - TSymbolTable *symbolTable, - int shaderVersion) - : TLValueTrackingTraverser(true, false, false, symbolTable, shaderVersion), - mFoundLoopToChange(false), - mInsideLoopInitConditionOrExpression(false), - mConditionsToSimplify(conditionsToSimplifyMask) -{ -} - -// If we're inside a loop initialization, condition, or expression, we check for expressions that -// should be moved out of the loop condition or expression. If one is found, the loop is -// transformed. -// If we're not inside loop initialization, condition, or expression, we only need to traverse nodes -// that may contain loops. - -bool SimplifyLoopConditionsTraverser::visitUnary(Visit visit, TIntermUnary *node) -{ - if (!mInsideLoopInitConditionOrExpression) - return false; - - if (mFoundLoopToChange) - return false; // Already decided to change this loop. - - mFoundLoopToChange = mConditionsToSimplify.match(node); - return !mFoundLoopToChange; -} - -bool SimplifyLoopConditionsTraverser::visitBinary(Visit visit, TIntermBinary *node) -{ - if (!mInsideLoopInitConditionOrExpression) - return false; - - if (mFoundLoopToChange) - return false; // Already decided to change this loop. - - mFoundLoopToChange = mConditionsToSimplify.match(node, getParentNode(), isLValueRequiredHere()); - return !mFoundLoopToChange; -} - -bool SimplifyLoopConditionsTraverser::visitAggregate(Visit visit, TIntermAggregate *node) -{ - if (!mInsideLoopInitConditionOrExpression) - return false; - - if (mFoundLoopToChange) - return false; // Already decided to change this loop. - - mFoundLoopToChange = mConditionsToSimplify.match(node, getParentNode()); - return !mFoundLoopToChange; -} - -bool SimplifyLoopConditionsTraverser::visitTernary(Visit visit, TIntermTernary *node) -{ - if (!mInsideLoopInitConditionOrExpression) - return false; - - if (mFoundLoopToChange) - return false; // Already decided to change this loop. - - mFoundLoopToChange = mConditionsToSimplify.match(node); - return !mFoundLoopToChange; -} - -bool SimplifyLoopConditionsTraverser::visitDeclaration(Visit visit, TIntermDeclaration *node) -{ - if (!mInsideLoopInitConditionOrExpression) - return false; - - if (mFoundLoopToChange) - return false; // Already decided to change this loop. - - mFoundLoopToChange = mConditionsToSimplify.match(node); - return !mFoundLoopToChange; -} - -void SimplifyLoopConditionsTraverser::traverseLoop(TIntermLoop *node) -{ - // Mark that we're inside a loop condition or expression, and determine if the loop needs to be - // transformed. - - ScopedNodeInTraversalPath addToPath(this, node); - - mInsideLoopInitConditionOrExpression = true; - mFoundLoopToChange = false; - - if (!mFoundLoopToChange && node->getInit()) - { - node->getInit()->traverse(this); - } - - if (!mFoundLoopToChange && node->getCondition()) - { - node->getCondition()->traverse(this); - } - - if (!mFoundLoopToChange && node->getExpression()) - { - node->getExpression()->traverse(this); - } - - mInsideLoopInitConditionOrExpression = false; - - if (mFoundLoopToChange) - { - nextTemporaryId(); - - // Replace the loop condition with a boolean variable that's updated on each iteration. - TLoopType loopType = node->getType(); - if (loopType == ELoopWhile) - { - // Transform: - // while (expr) { body; } - // into - // bool s0 = expr; - // while (s0) { { body; } s0 = expr; } - TIntermSequence tempInitSeq; - tempInitSeq.push_back(createTempInitDeclaration(node->getCondition()->deepCopy())); - insertStatementsInParentBlock(tempInitSeq); - - TIntermBlock *newBody = new TIntermBlock(); - if (node->getBody()) - { - newBody->getSequence()->push_back(node->getBody()); - } - newBody->getSequence()->push_back( - createTempAssignment(node->getCondition()->deepCopy())); - - // Can't use queueReplacement to replace old body, since it may have been nullptr. - // It's safe to do the replacements in place here - the new body will still be - // traversed, but that won't create any problems. - node->setBody(newBody); - node->setCondition(createTempSymbol(node->getCondition()->getType())); - } - else if (loopType == ELoopDoWhile) - { - // Transform: - // do { - // body; - // } while (expr); - // into - // bool s0 = true; - // do { - // { body; } - // s0 = expr; - // } while (s0); - TIntermSequence tempInitSeq; - tempInitSeq.push_back(createTempInitDeclaration(CreateBoolNode(true))); - insertStatementsInParentBlock(tempInitSeq); - - TIntermBlock *newBody = new TIntermBlock(); - if (node->getBody()) - { - newBody->getSequence()->push_back(node->getBody()); - } - newBody->getSequence()->push_back( - createTempAssignment(node->getCondition()->deepCopy())); - - // Can't use queueReplacement to replace old body, since it may have been nullptr. - // It's safe to do the replacements in place here - the new body will still be - // traversed, but that won't create any problems. - node->setBody(newBody); - node->setCondition(createTempSymbol(node->getCondition()->getType())); - } - else if (loopType == ELoopFor) - { - // Move the loop condition inside the loop. - // Transform: - // for (init; expr; exprB) { body; } - // into - // { - // init; - // bool s0 = expr; - // while (s0) { - // { body; } - // exprB; - // s0 = expr; - // } - // } - TIntermBlock *loopScope = new TIntermBlock(); - TIntermSequence *loopScopeSequence = loopScope->getSequence(); - - // Insert "init;" - if (node->getInit()) - { - loopScopeSequence->push_back(node->getInit()); - } - - // Insert "bool s0 = expr;" if applicable, "bool s0 = true;" otherwise - TIntermTyped *conditionInitializer = nullptr; - if (node->getCondition()) - { - conditionInitializer = node->getCondition()->deepCopy(); - } - else - { - conditionInitializer = CreateBoolNode(true); - } - loopScopeSequence->push_back(createTempInitDeclaration(conditionInitializer)); - - // Insert "{ body; }" in the while loop - TIntermBlock *whileLoopBody = new TIntermBlock(); - if (node->getBody()) - { - whileLoopBody->getSequence()->push_back(node->getBody()); - } - // Insert "exprB;" in the while loop - if (node->getExpression()) - { - whileLoopBody->getSequence()->push_back(node->getExpression()); - } - // Insert "s0 = expr;" in the while loop - if (node->getCondition()) - { - whileLoopBody->getSequence()->push_back( - createTempAssignment(node->getCondition()->deepCopy())); - } - - // Create "while(s0) { whileLoopBody }" - TIntermLoop *whileLoop = new TIntermLoop( - ELoopWhile, nullptr, createTempSymbol(conditionInitializer->getType()), nullptr, - whileLoopBody); - loopScope->getSequence()->push_back(whileLoop); - queueReplacement(loopScope, OriginalNode::IS_DROPPED); - - // After this the old body node will be traversed and loops inside it may be - // transformed. This is fine, since the old body node will still be in the AST after the - // transformation that's queued here, and transforming loops inside it doesn't need to - // know the exact post-transform path to it. - } - } - - mFoundLoopToChange = false; - - // We traverse the body of the loop even if the loop is transformed. - if (node->getBody()) - node->getBody()->traverse(this); -} - -} // namespace - -void SimplifyLoopConditions(TIntermNode *root, - unsigned int conditionsToSimplifyMask, - TSymbolTable *symbolTable, - int shaderVersion) -{ - SimplifyLoopConditionsTraverser traverser(conditionsToSimplifyMask, symbolTable, shaderVersion); - root->traverse(&traverser); - traverser.updateTree(); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/SimplifyLoopConditions.h b/src/3rdparty/angle/src/compiler/translator/SimplifyLoopConditions.h deleted file mode 100644 index d8f95cd2c8..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/SimplifyLoopConditions.h +++ /dev/null @@ -1,25 +0,0 @@ -// -// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// SimplifyLoopConditions is an AST traverser that converts loop conditions and loop expressions -// to regular statements inside the loop. This way further transformations that generate statements -// from loop conditions and loop expressions work correctly. -// - -#ifndef COMPILER_TRANSLATOR_SIMPLIFYLOOPCONDITIONS_H_ -#define COMPILER_TRANSLATOR_SIMPLIFYLOOPCONDITIONS_H_ - -namespace sh -{ -class TIntermNode; -class TSymbolTable; - -void SimplifyLoopConditions(TIntermNode *root, - unsigned int conditionsToSimplify, - TSymbolTable *symbolTable, - int shaderVersion); -} // namespace sh - -#endif // COMPILER_TRANSLATOR_SIMPLIFYLOOPCONDITIONS_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/SplitSequenceOperator.cpp b/src/3rdparty/angle/src/compiler/translator/SplitSequenceOperator.cpp deleted file mode 100644 index 5df3154560..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/SplitSequenceOperator.cpp +++ /dev/null @@ -1,171 +0,0 @@ -// -// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// SplitSequenceOperator is an AST traverser that detects sequence operator expressions that -// go through further AST transformations that generate statements, and splits them so that -// possible side effects of earlier parts of the sequence operator expression are guaranteed to be -// evaluated before the latter parts of the sequence operator expression are evaluated. -// - -#include "compiler/translator/SplitSequenceOperator.h" - -#include "compiler/translator/IntermNodePatternMatcher.h" -#include "compiler/translator/IntermTraverse.h" - -namespace sh -{ - -namespace -{ - -class SplitSequenceOperatorTraverser : public TLValueTrackingTraverser -{ - public: - SplitSequenceOperatorTraverser(unsigned int patternsToSplitMask, - TSymbolTable *symbolTable, - int shaderVersion); - - bool visitUnary(Visit visit, TIntermUnary *node) override; - bool visitBinary(Visit visit, TIntermBinary *node) override; - bool visitAggregate(Visit visit, TIntermAggregate *node) override; - bool visitTernary(Visit visit, TIntermTernary *node) override; - - void nextIteration(); - bool foundExpressionToSplit() const { return mFoundExpressionToSplit; } - - protected: - // Marked to true once an operation that needs to be hoisted out of the expression has been - // found. After that, no more AST updates are performed on that traversal. - bool mFoundExpressionToSplit; - int mInsideSequenceOperator; - - IntermNodePatternMatcher mPatternToSplitMatcher; -}; - -SplitSequenceOperatorTraverser::SplitSequenceOperatorTraverser(unsigned int patternsToSplitMask, - TSymbolTable *symbolTable, - int shaderVersion) - : TLValueTrackingTraverser(true, false, true, symbolTable, shaderVersion), - mFoundExpressionToSplit(false), - mInsideSequenceOperator(0), - mPatternToSplitMatcher(patternsToSplitMask) -{ -} - -void SplitSequenceOperatorTraverser::nextIteration() -{ - mFoundExpressionToSplit = false; - mInsideSequenceOperator = 0; - nextTemporaryId(); -} - -bool SplitSequenceOperatorTraverser::visitAggregate(Visit visit, TIntermAggregate *node) -{ - if (mFoundExpressionToSplit) - return false; - - if (mInsideSequenceOperator > 0 && visit == PreVisit) - { - // Detect expressions that need to be simplified - mFoundExpressionToSplit = mPatternToSplitMatcher.match(node, getParentNode()); - return !mFoundExpressionToSplit; - } - - return true; -} - -bool SplitSequenceOperatorTraverser::visitUnary(Visit visit, TIntermUnary *node) -{ - if (mFoundExpressionToSplit) - return false; - - if (mInsideSequenceOperator > 0 && visit == PreVisit) - { - // Detect expressions that need to be simplified - mFoundExpressionToSplit = mPatternToSplitMatcher.match(node); - return !mFoundExpressionToSplit; - } - - return true; -} - -bool SplitSequenceOperatorTraverser::visitBinary(Visit visit, TIntermBinary *node) -{ - if (node->getOp() == EOpComma) - { - if (visit == PreVisit) - { - if (mFoundExpressionToSplit) - { - return false; - } - mInsideSequenceOperator++; - } - else if (visit == PostVisit) - { - // Split sequence operators starting from the outermost one to preserve correct - // execution order. - if (mFoundExpressionToSplit && mInsideSequenceOperator == 1) - { - // Move the left side operand into a separate statement in the parent block. - TIntermSequence insertions; - insertions.push_back(node->getLeft()); - insertStatementsInParentBlock(insertions); - // Replace the comma node with its right side operand. - queueReplacement(node->getRight(), OriginalNode::IS_DROPPED); - } - mInsideSequenceOperator--; - } - return true; - } - - if (mFoundExpressionToSplit) - return false; - - if (mInsideSequenceOperator > 0 && visit == PreVisit) - { - // Detect expressions that need to be simplified - mFoundExpressionToSplit = - mPatternToSplitMatcher.match(node, getParentNode(), isLValueRequiredHere()); - return !mFoundExpressionToSplit; - } - - return true; -} - -bool SplitSequenceOperatorTraverser::visitTernary(Visit visit, TIntermTernary *node) -{ - if (mFoundExpressionToSplit) - return false; - - if (mInsideSequenceOperator > 0 && visit == PreVisit) - { - // Detect expressions that need to be simplified - mFoundExpressionToSplit = mPatternToSplitMatcher.match(node); - return !mFoundExpressionToSplit; - } - - return true; -} - -} // namespace - -void SplitSequenceOperator(TIntermNode *root, - int patternsToSplitMask, - TSymbolTable *symbolTable, - int shaderVersion) -{ - SplitSequenceOperatorTraverser traverser(patternsToSplitMask, symbolTable, shaderVersion); - // Separate one expression at a time, and reset the traverser between iterations. - do - { - traverser.nextIteration(); - root->traverse(&traverser); - if (traverser.foundExpressionToSplit()) - traverser.updateTree(); - } while (traverser.foundExpressionToSplit()); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/SplitSequenceOperator.h b/src/3rdparty/angle/src/compiler/translator/SplitSequenceOperator.h deleted file mode 100644 index 8f1a766775..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/SplitSequenceOperator.h +++ /dev/null @@ -1,28 +0,0 @@ -// -// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// SplitSequenceOperator is an AST traverser that detects sequence operator expressions that -// go through further AST transformations that generate statements, and splits them so that -// possible side effects of earlier parts of the sequence operator expression are guaranteed to be -// evaluated before the latter parts of the sequence operator expression are evaluated. -// - -#ifndef COMPILER_TRANSLATOR_SPLITSEQUENCEOPERATOR_H_ -#define COMPILER_TRANSLATOR_SPLITSEQUENCEOPERATOR_H_ - -namespace sh -{ - -class TIntermNode; -class TSymbolTable; - -void SplitSequenceOperator(TIntermNode *root, - int patternsToSplitMask, - TSymbolTable *symbolTable, - int shaderVersion); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_SPLITSEQUENCEOPERATOR_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/StructureHLSL.cpp b/src/3rdparty/angle/src/compiler/translator/StructureHLSL.cpp deleted file mode 100644 index 61a9431ceb..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/StructureHLSL.cpp +++ /dev/null @@ -1,594 +0,0 @@ -// -// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// StructureHLSL.cpp: -// HLSL translation of GLSL constructors and structures. -// - -#include "compiler/translator/StructureHLSL.h" -#include "common/utilities.h" -#include "compiler/translator/OutputHLSL.h" -#include "compiler/translator/Types.h" -#include "compiler/translator/util.h" -#include "compiler/translator/UtilsHLSL.h" - -namespace sh -{ - -namespace -{ - -TString Define(const TStructure &structure, - bool useHLSLRowMajorPacking, - bool useStd140Packing, - Std140PaddingHelper *padHelper) -{ - const TFieldList &fields = structure.fields(); - const bool isNameless = (structure.name() == ""); - const TString &structName = - QualifiedStructNameString(structure, useHLSLRowMajorPacking, useStd140Packing); - const TString declareString = (isNameless ? "struct" : "struct " + structName); - - TString string; - string += declareString + - "\n" - "{\n"; - - for (const TField *field : fields) - { - const TType &fieldType = *field->type(); - if (!IsSampler(fieldType.getBasicType())) - { - const TStructure *fieldStruct = fieldType.getStruct(); - const TString &fieldTypeString = - fieldStruct ? QualifiedStructNameString(*fieldStruct, useHLSLRowMajorPacking, - useStd140Packing) - : TypeString(fieldType); - - if (padHelper) - { - string += padHelper->prePaddingString(fieldType); - } - - string += " " + fieldTypeString + " " + DecorateField(field->name(), structure) + - ArrayString(fieldType) + ";\n"; - - if (padHelper) - { - string += padHelper->postPaddingString(fieldType, useHLSLRowMajorPacking); - } - } - } - - // Nameless structs do not finish with a semicolon and newline, to leave room for an instance - // variable - string += (isNameless ? "} " : "};\n"); - - return string; -} - -TString WriteParameterList(const std::vector ¶meters) -{ - TString parameterList; - for (size_t parameter = 0u; parameter < parameters.size(); parameter++) - { - const TType ¶mType = parameters[parameter]; - - parameterList += TypeString(paramType) + " x" + str(parameter) + ArrayString(paramType); - - if (parameter < parameters.size() - 1u) - { - parameterList += ", "; - } - } - return parameterList; -} - -} // anonymous namespace - -Std140PaddingHelper::Std140PaddingHelper(const std::map &structElementIndexes, - unsigned *uniqueCounter) - : mPaddingCounter(uniqueCounter), mElementIndex(0), mStructElementIndexes(&structElementIndexes) -{ -} - -Std140PaddingHelper::Std140PaddingHelper(const Std140PaddingHelper &other) - : mPaddingCounter(other.mPaddingCounter), - mElementIndex(other.mElementIndex), - mStructElementIndexes(other.mStructElementIndexes) -{ -} - -Std140PaddingHelper &Std140PaddingHelper::operator=(const Std140PaddingHelper &other) -{ - mPaddingCounter = other.mPaddingCounter; - mElementIndex = other.mElementIndex; - mStructElementIndexes = other.mStructElementIndexes; - return *this; -} - -TString Std140PaddingHelper::next() -{ - unsigned value = (*mPaddingCounter)++; - return str(value); -} - -int Std140PaddingHelper::prePadding(const TType &type) -{ - if (type.getBasicType() == EbtStruct || type.isMatrix() || type.isArray()) - { - // no padding needed, HLSL will align the field to a new register - mElementIndex = 0; - return 0; - } - - const GLenum glType = GLVariableType(type); - const int numComponents = gl::VariableComponentCount(glType); - - if (numComponents >= 4) - { - // no padding needed, HLSL will align the field to a new register - mElementIndex = 0; - return 0; - } - - if (mElementIndex + numComponents > 4) - { - // no padding needed, HLSL will align the field to a new register - mElementIndex = numComponents; - return 0; - } - - const int alignment = numComponents == 3 ? 4 : numComponents; - const int paddingOffset = (mElementIndex % alignment); - const int paddingCount = (paddingOffset != 0 ? (alignment - paddingOffset) : 0); - - mElementIndex += paddingCount; - mElementIndex += numComponents; - mElementIndex %= 4; - - return paddingCount; -} - -TString Std140PaddingHelper::prePaddingString(const TType &type) -{ - int paddingCount = prePadding(type); - - TString padding; - - for (int paddingIndex = 0; paddingIndex < paddingCount; paddingIndex++) - { - padding += " float pad_" + next() + ";\n"; - } - - return padding; -} - -TString Std140PaddingHelper::postPaddingString(const TType &type, bool useHLSLRowMajorPacking) -{ - if (!type.isMatrix() && !type.isArray() && type.getBasicType() != EbtStruct) - { - return ""; - } - - int numComponents = 0; - const TStructure *structure = type.getStruct(); - - if (type.isMatrix()) - { - // This method can also be called from structureString, which does not use layout - // qualifiers. - // Thus, use the method parameter for determining the matrix packing. - // - // Note HLSL row major packing corresponds to GL API column-major, and vice-versa, since we - // wish to always transpose GL matrices to play well with HLSL's matrix array indexing. - // - const bool isRowMajorMatrix = !useHLSLRowMajorPacking; - const GLenum glType = GLVariableType(type); - numComponents = gl::MatrixComponentCount(glType, isRowMajorMatrix); - } - else if (structure) - { - const TString &structName = - QualifiedStructNameString(*structure, useHLSLRowMajorPacking, true); - numComponents = mStructElementIndexes->find(structName)->second; - - if (numComponents == 0) - { - return ""; - } - } - else - { - const GLenum glType = GLVariableType(type); - numComponents = gl::VariableComponentCount(glType); - } - - TString padding; - for (int paddingOffset = numComponents; paddingOffset < 4; paddingOffset++) - { - padding += " float pad_" + next() + ";\n"; - } - return padding; -} - -StructureHLSL::StructureHLSL() : mUniquePaddingCounter(0) -{ -} - -Std140PaddingHelper StructureHLSL::getPaddingHelper() -{ - return Std140PaddingHelper(mStd140StructElementIndexes, &mUniquePaddingCounter); -} - -TString StructureHLSL::defineQualified(const TStructure &structure, - bool useHLSLRowMajorPacking, - bool useStd140Packing) -{ - if (useStd140Packing) - { - Std140PaddingHelper padHelper = getPaddingHelper(); - return Define(structure, useHLSLRowMajorPacking, useStd140Packing, &padHelper); - } - else - { - return Define(structure, useHLSLRowMajorPacking, useStd140Packing, nullptr); - } -} - -TString StructureHLSL::defineNameless(const TStructure &structure) -{ - return Define(structure, false, false, nullptr); -} - -StructureHLSL::DefinedStructs::iterator StructureHLSL::defineVariants(const TStructure &structure, - const TString &name) -{ - ASSERT(mDefinedStructs.find(name) == mDefinedStructs.end()); - - for (const TField *field : structure.fields()) - { - const TType *fieldType = field->type(); - if (fieldType->getBasicType() == EbtStruct) - { - ensureStructDefined(*fieldType->getStruct()); - } - } - - DefinedStructs::iterator addedStruct = - mDefinedStructs.insert(std::make_pair(name, new TStructProperties())).first; - // Add element index - storeStd140ElementIndex(structure, false); - storeStd140ElementIndex(structure, true); - - const TString &structString = defineQualified(structure, false, false); - - ASSERT(std::find(mStructDeclarations.begin(), mStructDeclarations.end(), structString) == - mStructDeclarations.end()); - // Add row-major packed struct for interface blocks - TString rowMajorString = "#pragma pack_matrix(row_major)\n" + - defineQualified(structure, true, false) + - "#pragma pack_matrix(column_major)\n"; - - TString std140String = defineQualified(structure, false, true); - TString std140RowMajorString = "#pragma pack_matrix(row_major)\n" + - defineQualified(structure, true, true) + - "#pragma pack_matrix(column_major)\n"; - - mStructDeclarations.push_back(structString); - mStructDeclarations.push_back(rowMajorString); - mStructDeclarations.push_back(std140String); - mStructDeclarations.push_back(std140RowMajorString); - return addedStruct; -} - -void StructureHLSL::ensureStructDefined(const TStructure &structure) -{ - const TString name = StructNameString(structure); - if (name == "") - { - return; // Nameless structures are not defined - } - if (mDefinedStructs.find(name) == mDefinedStructs.end()) - { - defineVariants(structure, name); - } -} - -TString StructureHLSL::addStructConstructor(const TStructure &structure) -{ - const TString name = StructNameString(structure); - - if (name == "") - { - return TString(); // Nameless structures don't have constructors - } - - auto definedStruct = mDefinedStructs.find(name); - if (definedStruct == mDefinedStructs.end()) - { - definedStruct = defineVariants(structure, name); - } - const TString constructorFunctionName = TString(name) + "_ctor"; - TString *constructor = &definedStruct->second->constructor; - if (!constructor->empty()) - { - return constructorFunctionName; // Already added - } - *constructor += name + " " + constructorFunctionName + "("; - - std::vector ctorParameters; - const TFieldList &fields = structure.fields(); - for (const TField *field : fields) - { - const TType *fieldType = field->type(); - if (!IsSampler(fieldType->getBasicType())) - { - ctorParameters.push_back(*fieldType); - } - } - // Structs that have sampler members should not have constructor calls, and otherwise structs - // are guaranteed to be non-empty by the grammar. Structs can't contain empty declarations - // either. - ASSERT(!ctorParameters.empty()); - - *constructor += WriteParameterList(ctorParameters); - - *constructor += - ")\n" - "{\n" - " " + - name + " structure = { "; - - for (size_t parameterIndex = 0u; parameterIndex < ctorParameters.size(); ++parameterIndex) - { - *constructor += "x" + str(parameterIndex); - if (parameterIndex < ctorParameters.size() - 1u) - { - *constructor += ", "; - } - } - *constructor += - "};\n" - " return structure;\n" - "}\n"; - - return constructorFunctionName; -} - -TString StructureHLSL::addBuiltInConstructor(const TType &type, const TIntermSequence *parameters) -{ - ASSERT(!type.isArray()); - ASSERT(type.getStruct() == nullptr); - ASSERT(parameters); - - TType ctorType = type; - ctorType.setPrecision(EbpHigh); - ctorType.setQualifier(EvqTemporary); - - const TString constructorFunctionName = - TString(type.getBuiltInTypeNameString()) + "_ctor" + DisambiguateFunctionName(parameters); - TString constructor = TypeString(ctorType) + " " + constructorFunctionName + "("; - - std::vector ctorParameters; - for (auto parameter : *parameters) - { - const TType ¶mType = parameter->getAsTyped()->getType(); - ASSERT(!paramType.isArray()); - ctorParameters.push_back(paramType); - } - constructor += WriteParameterList(ctorParameters); - - constructor += - ")\n" - "{\n" - " return " + - TypeString(ctorType) + "("; - - if (ctorType.isMatrix() && ctorParameters.size() == 1) - { - int rows = ctorType.getRows(); - int cols = ctorType.getCols(); - const TType ¶meter = ctorParameters[0]; - - if (parameter.isScalar()) - { - for (int col = 0; col < cols; col++) - { - for (int row = 0; row < rows; row++) - { - constructor += TString((row == col) ? "x0" : "0.0"); - - if (row < rows - 1 || col < cols - 1) - { - constructor += ", "; - } - } - } - } - else if (parameter.isMatrix()) - { - for (int col = 0; col < cols; col++) - { - for (int row = 0; row < rows; row++) - { - if (row < parameter.getRows() && col < parameter.getCols()) - { - constructor += TString("x0") + "[" + str(col) + "][" + str(row) + "]"; - } - else - { - constructor += TString((row == col) ? "1.0" : "0.0"); - } - - if (row < rows - 1 || col < cols - 1) - { - constructor += ", "; - } - } - } - } - else - { - ASSERT(rows == 2 && cols == 2 && parameter.isVector() && - parameter.getNominalSize() == 4); - - constructor += "x0"; - } - } - else - { - size_t remainingComponents = ctorType.getObjectSize(); - size_t parameterIndex = 0; - - while (remainingComponents > 0) - { - const TType ¶meter = ctorParameters[parameterIndex]; - const size_t parameterSize = parameter.getObjectSize(); - bool moreParameters = parameterIndex + 1 < ctorParameters.size(); - - constructor += "x" + str(parameterIndex); - - if (parameter.isScalar()) - { - remainingComponents -= parameter.getObjectSize(); - } - else if (parameter.isVector()) - { - if (remainingComponents == parameterSize || moreParameters) - { - ASSERT(parameterSize <= remainingComponents); - remainingComponents -= parameterSize; - } - else if (remainingComponents < static_cast(parameter.getNominalSize())) - { - switch (remainingComponents) - { - case 1: - constructor += ".x"; - break; - case 2: - constructor += ".xy"; - break; - case 3: - constructor += ".xyz"; - break; - case 4: - constructor += ".xyzw"; - break; - default: - UNREACHABLE(); - } - - remainingComponents = 0; - } - else - UNREACHABLE(); - } - else if (parameter.isMatrix()) - { - int column = 0; - while (remainingComponents > 0 && column < parameter.getCols()) - { - constructor += "[" + str(column) + "]"; - - if (remainingComponents < static_cast(parameter.getRows())) - { - switch (remainingComponents) - { - case 1: - constructor += ".x"; - break; - case 2: - constructor += ".xy"; - break; - case 3: - constructor += ".xyz"; - break; - default: - UNREACHABLE(); - } - - remainingComponents = 0; - } - else - { - remainingComponents -= parameter.getRows(); - - if (remainingComponents > 0) - { - constructor += ", x" + str(parameterIndex); - } - } - - column++; - } - } - else - { - UNREACHABLE(); - } - - if (moreParameters) - { - parameterIndex++; - } - - if (remainingComponents) - { - constructor += ", "; - } - } - } - - constructor += - ");\n" - "}\n"; - - mBuiltInConstructors.insert(constructor); - - return constructorFunctionName; -} - -std::string StructureHLSL::structsHeader() const -{ - TInfoSinkBase out; - - for (auto &declaration : mStructDeclarations) - { - out << declaration; - } - - for (auto &structure : mDefinedStructs) - { - out << structure.second->constructor; - } - - for (auto &constructor : mBuiltInConstructors) - { - out << constructor; - } - - return out.str(); -} - -void StructureHLSL::storeStd140ElementIndex(const TStructure &structure, - bool useHLSLRowMajorPacking) -{ - Std140PaddingHelper padHelper = getPaddingHelper(); - const TFieldList &fields = structure.fields(); - - for (const TField *field : fields) - { - padHelper.prePadding(*field->type()); - } - - // Add remaining element index to the global map, for use with nested structs in standard - // layouts - const TString &structName = QualifiedStructNameString(structure, useHLSLRowMajorPacking, true); - mStd140StructElementIndexes[structName] = padHelper.elementIndex(); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/StructureHLSL.h b/src/3rdparty/angle/src/compiler/translator/StructureHLSL.h deleted file mode 100644 index daced8f8d1..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/StructureHLSL.h +++ /dev/null @@ -1,98 +0,0 @@ -// -// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// StructureHLSL.h: -// HLSL translation of GLSL constructors and structures. -// - -#ifndef COMPILER_TRANSLATOR_STRUCTUREHLSL_H_ -#define COMPILER_TRANSLATOR_STRUCTUREHLSL_H_ - -#include "compiler/translator/Common.h" -#include "compiler/translator/IntermNode.h" - -#include - -class TInfoSinkBase; -class TScopeBracket; - -namespace sh -{ - -// This helper class assists structure and interface block definitions in determining -// how to pack std140 structs within HLSL's packing rules. -class Std140PaddingHelper -{ - public: - explicit Std140PaddingHelper(const std::map &structElementIndexes, - unsigned int *uniqueCounter); - Std140PaddingHelper(const Std140PaddingHelper &other); - Std140PaddingHelper &operator=(const Std140PaddingHelper &other); - - int elementIndex() const { return mElementIndex; } - int prePadding(const TType &type); - TString prePaddingString(const TType &type); - TString postPaddingString(const TType &type, bool useHLSLRowMajorPacking); - - private: - TString next(); - - unsigned *mPaddingCounter; - int mElementIndex; - const std::map *mStructElementIndexes; -}; - -class StructureHLSL : angle::NonCopyable -{ - public: - StructureHLSL(); - - // Returns the name of the constructor function. - TString addStructConstructor(const TStructure &structure); - TString addBuiltInConstructor(const TType &type, const TIntermSequence *parameters); - - static TString defineNameless(const TStructure &structure); - void ensureStructDefined(const TStructure &structure); - - std::string structsHeader() const; - - Std140PaddingHelper getPaddingHelper(); - - private: - unsigned mUniquePaddingCounter; - - std::map mStd140StructElementIndexes; - - struct TStructProperties : public angle::NonCopyable - { - POOL_ALLOCATOR_NEW_DELETE(); - - TStructProperties() {} - - // Constructor is an empty string in case the struct doesn't have a constructor yet. - TString constructor; - }; - - // Map from struct name to struct properties. - typedef std::map DefinedStructs; - DefinedStructs mDefinedStructs; - - // Struct declarations need to be kept in a vector instead of having them inside mDefinedStructs - // since maintaining the original order is necessary for nested structs. - typedef std::vector StructDeclarations; - StructDeclarations mStructDeclarations; - - typedef std::set BuiltInConstructors; - BuiltInConstructors mBuiltInConstructors; - - void storeStd140ElementIndex(const TStructure &structure, bool useHLSLRowMajorPacking); - TString defineQualified(const TStructure &structure, - bool useHLSLRowMajorPacking, - bool useStd140Packing); - DefinedStructs::iterator defineVariants(const TStructure &structure, const TString &name); -}; -} - -#endif // COMPILER_TRANSLATOR_STRUCTUREHLSL_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/SymbolTable.cpp b/src/3rdparty/angle/src/compiler/translator/SymbolTable.cpp deleted file mode 100644 index 6c38461469..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/SymbolTable.cpp +++ /dev/null @@ -1,622 +0,0 @@ -// -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// Symbol table for parsing. The design principles and most of the functionality are documented in -// the header file. -// - -#if defined(_MSC_VER) -#pragma warning(disable : 4718) -#endif - -#include "compiler/translator/SymbolTable.h" - -#include "compiler/translator/Cache.h" -#include "compiler/translator/IntermNode.h" - -#include -#include - -namespace sh -{ - -namespace -{ - -static const char kFunctionMangledNameSeparator = '('; - -} // anonymous namespace - -TSymbol::TSymbol(TSymbolTable *symbolTable, const TString *n) - : uniqueId(symbolTable->nextUniqueId()), name(n), extension(TExtension::UNDEFINED) -{ -} - -// -// Functions have buried pointers to delete. -// -TFunction::~TFunction() -{ - clearParameters(); -} - -void TFunction::clearParameters() -{ - for (TParamList::iterator i = parameters.begin(); i != parameters.end(); ++i) - delete (*i).type; - parameters.clear(); - mangledName = nullptr; -} - -void TFunction::swapParameters(const TFunction ¶metersSource) -{ - clearParameters(); - for (auto parameter : parametersSource.parameters) - { - addParameter(parameter); - } -} - -const TString *TFunction::buildMangledName() const -{ - std::string newName = getName().c_str(); - newName += kFunctionMangledNameSeparator; - - for (const auto &p : parameters) - { - newName += p.type->getMangledName(); - } - return NewPoolTString(newName.c_str()); -} - -const TString &TFunction::GetMangledNameFromCall(const TString &functionName, - const TIntermSequence &arguments) -{ - std::string newName = functionName.c_str(); - newName += kFunctionMangledNameSeparator; - - for (TIntermNode *argument : arguments) - { - newName += argument->getAsTyped()->getType().getMangledName(); - } - return *NewPoolTString(newName.c_str()); -} - -// -// 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; -} - -bool TSymbolTableLevel::insert(TSymbol *symbol) -{ - // returning true means symbol was added to the table - tInsertResult result = level.insert(tLevelPair(symbol->getMangledName(), symbol)); - - return result.second; -} - -bool TSymbolTableLevel::insertUnmangled(TFunction *function) -{ - // returning true means symbol was added to the table - tInsertResult result = level.insert(tLevelPair(function->getName(), function)); - - return result.second; -} - -TSymbol *TSymbolTableLevel::find(const TString &name) const -{ - tLevel::const_iterator it = level.find(name); - if (it == level.end()) - return 0; - else - return (*it).second; -} - -TSymbol *TSymbolTable::find(const TString &name, - int shaderVersion, - bool *builtIn, - bool *sameScope) const -{ - int level = currentLevel(); - TSymbol *symbol; - - do - { - if (level == GLSL_BUILTINS) - level--; - if (level == ESSL3_1_BUILTINS && shaderVersion != 310) - level--; - if (level == ESSL3_BUILTINS && shaderVersion < 300) - level--; - if (level == ESSL1_BUILTINS && shaderVersion != 100) - level--; - - symbol = table[level]->find(name); - } while (symbol == 0 && --level >= 0); - - if (builtIn) - *builtIn = (level <= LAST_BUILTIN_LEVEL); - if (sameScope) - *sameScope = (level == currentLevel()); - - return symbol; -} - -TSymbol *TSymbolTable::findGlobal(const TString &name) const -{ - ASSERT(table.size() > GLOBAL_LEVEL); - return table[GLOBAL_LEVEL]->find(name); -} - -TSymbol *TSymbolTable::findBuiltIn(const TString &name, int shaderVersion) const -{ - return findBuiltIn(name, shaderVersion, false); -} - -TSymbol *TSymbolTable::findBuiltIn(const TString &name, - int shaderVersion, - bool includeGLSLBuiltins) const -{ - for (int level = LAST_BUILTIN_LEVEL; level >= 0; level--) - { - if (level == GLSL_BUILTINS && !includeGLSLBuiltins) - level--; - if (level == ESSL3_1_BUILTINS && shaderVersion != 310) - level--; - if (level == ESSL3_BUILTINS && shaderVersion < 300) - level--; - if (level == ESSL1_BUILTINS && shaderVersion != 100) - level--; - - TSymbol *symbol = table[level]->find(name); - - if (symbol) - return symbol; - } - - return nullptr; -} - -TSymbolTable::~TSymbolTable() -{ - while (table.size() > 0) - pop(); -} - -bool IsGenType(const TType *type) -{ - if (type) - { - TBasicType basicType = type->getBasicType(); - return basicType == EbtGenType || basicType == EbtGenIType || basicType == EbtGenUType || - basicType == EbtGenBType; - } - - return false; -} - -bool IsVecType(const TType *type) -{ - if (type) - { - TBasicType basicType = type->getBasicType(); - return basicType == EbtVec || basicType == EbtIVec || basicType == EbtUVec || - basicType == EbtBVec; - } - - return false; -} - -const TType *SpecificType(const TType *type, int size) -{ - ASSERT(size >= 1 && size <= 4); - - if (!type) - { - return nullptr; - } - - ASSERT(!IsVecType(type)); - - switch (type->getBasicType()) - { - case EbtGenType: - return TCache::getType(EbtFloat, type->getQualifier(), - static_cast(size)); - case EbtGenIType: - return TCache::getType(EbtInt, type->getQualifier(), static_cast(size)); - case EbtGenUType: - return TCache::getType(EbtUInt, type->getQualifier(), static_cast(size)); - case EbtGenBType: - return TCache::getType(EbtBool, type->getQualifier(), static_cast(size)); - default: - return type; - } -} - -const TType *VectorType(const TType *type, int size) -{ - ASSERT(size >= 2 && size <= 4); - - if (!type) - { - return nullptr; - } - - ASSERT(!IsGenType(type)); - - switch (type->getBasicType()) - { - case EbtVec: - return TCache::getType(EbtFloat, static_cast(size)); - case EbtIVec: - return TCache::getType(EbtInt, static_cast(size)); - case EbtUVec: - return TCache::getType(EbtUInt, static_cast(size)); - case EbtBVec: - return TCache::getType(EbtBool, static_cast(size)); - default: - return type; - } -} - -TVariable *TSymbolTable::declareVariable(const TString *name, const TType &type) -{ - return insertVariable(currentLevel(), name, type); -} - -TVariable *TSymbolTable::declareStructType(TStructure *str) -{ - return insertStructType(currentLevel(), str); -} - -TInterfaceBlockName *TSymbolTable::declareInterfaceBlockName(const TString *name) -{ - TInterfaceBlockName *blockNameSymbol = new TInterfaceBlockName(this, name); - if (insert(currentLevel(), blockNameSymbol)) - { - return blockNameSymbol; - } - return nullptr; -} - -TInterfaceBlockName *TSymbolTable::insertInterfaceBlockNameExt(ESymbolLevel level, - TExtension ext, - const TString *name) -{ - TInterfaceBlockName *blockNameSymbol = new TInterfaceBlockName(this, name); - if (insert(level, ext, blockNameSymbol)) - { - return blockNameSymbol; - } - return nullptr; -} - -TVariable *TSymbolTable::insertVariable(ESymbolLevel level, const char *name, const TType &type) -{ - return insertVariable(level, NewPoolTString(name), type); -} - -TVariable *TSymbolTable::insertVariable(ESymbolLevel level, const TString *name, const TType &type) -{ - TVariable *var = new TVariable(this, name, type); - if (insert(level, var)) - { - // Do lazy initialization for struct types, so we allocate to the current scope. - if (var->getType().getBasicType() == EbtStruct) - { - var->getType().realize(); - } - return var; - } - return nullptr; -} - -TVariable *TSymbolTable::insertVariableExt(ESymbolLevel level, - TExtension ext, - const char *name, - const TType &type) -{ - TVariable *var = new TVariable(this, NewPoolTString(name), type); - if (insert(level, ext, var)) - { - if (var->getType().getBasicType() == EbtStruct) - { - var->getType().realize(); - } - return var; - } - return nullptr; -} - -TVariable *TSymbolTable::insertStructType(ESymbolLevel level, TStructure *str) -{ - TVariable *var = new TVariable(this, &str->name(), TType(str), true); - if (insert(level, var)) - { - var->getType().realize(); - return var; - } - return nullptr; -} - -void TSymbolTable::insertBuiltIn(ESymbolLevel level, - TOperator op, - TExtension ext, - const TType *rvalue, - const char *name, - const TType *ptype1, - const TType *ptype2, - const TType *ptype3, - const TType *ptype4, - const TType *ptype5) -{ - if (ptype1->getBasicType() == EbtGSampler2D) - { - insertUnmangledBuiltInName(name, level); - bool gvec4 = (rvalue->getBasicType() == EbtGVec4); - insertBuiltIn(level, gvec4 ? TCache::getType(EbtFloat, 4) : rvalue, name, - TCache::getType(EbtSampler2D), ptype2, ptype3, ptype4, ptype5); - insertBuiltIn(level, gvec4 ? TCache::getType(EbtInt, 4) : rvalue, name, - TCache::getType(EbtISampler2D), ptype2, ptype3, ptype4, ptype5); - insertBuiltIn(level, gvec4 ? TCache::getType(EbtUInt, 4) : rvalue, name, - TCache::getType(EbtUSampler2D), ptype2, ptype3, ptype4, ptype5); - } - else if (ptype1->getBasicType() == EbtGSampler3D) - { - insertUnmangledBuiltInName(name, level); - bool gvec4 = (rvalue->getBasicType() == EbtGVec4); - insertBuiltIn(level, gvec4 ? TCache::getType(EbtFloat, 4) : rvalue, name, - TCache::getType(EbtSampler3D), ptype2, ptype3, ptype4, ptype5); - insertBuiltIn(level, gvec4 ? TCache::getType(EbtInt, 4) : rvalue, name, - TCache::getType(EbtISampler3D), ptype2, ptype3, ptype4, ptype5); - insertBuiltIn(level, gvec4 ? TCache::getType(EbtUInt, 4) : rvalue, name, - TCache::getType(EbtUSampler3D), ptype2, ptype3, ptype4, ptype5); - } - else if (ptype1->getBasicType() == EbtGSamplerCube) - { - insertUnmangledBuiltInName(name, level); - bool gvec4 = (rvalue->getBasicType() == EbtGVec4); - insertBuiltIn(level, gvec4 ? TCache::getType(EbtFloat, 4) : rvalue, name, - TCache::getType(EbtSamplerCube), ptype2, ptype3, ptype4, ptype5); - insertBuiltIn(level, gvec4 ? TCache::getType(EbtInt, 4) : rvalue, name, - TCache::getType(EbtISamplerCube), ptype2, ptype3, ptype4, ptype5); - insertBuiltIn(level, gvec4 ? TCache::getType(EbtUInt, 4) : rvalue, name, - TCache::getType(EbtUSamplerCube), ptype2, ptype3, ptype4, ptype5); - } - else if (ptype1->getBasicType() == EbtGSampler2DArray) - { - insertUnmangledBuiltInName(name, level); - bool gvec4 = (rvalue->getBasicType() == EbtGVec4); - insertBuiltIn(level, gvec4 ? TCache::getType(EbtFloat, 4) : rvalue, name, - TCache::getType(EbtSampler2DArray), ptype2, ptype3, ptype4, ptype5); - insertBuiltIn(level, gvec4 ? TCache::getType(EbtInt, 4) : rvalue, name, - TCache::getType(EbtISampler2DArray), ptype2, ptype3, ptype4, ptype5); - insertBuiltIn(level, gvec4 ? TCache::getType(EbtUInt, 4) : rvalue, name, - TCache::getType(EbtUSampler2DArray), ptype2, ptype3, ptype4, ptype5); - } - else if (ptype1->getBasicType() == EbtGSampler2DMS) - { - insertUnmangledBuiltInName(name, level); - bool gvec4 = (rvalue->getBasicType() == EbtGVec4); - insertBuiltIn(level, gvec4 ? TCache::getType(EbtFloat, 4) : rvalue, name, - TCache::getType(EbtSampler2DMS), ptype2, ptype3, ptype4, ptype5); - insertBuiltIn(level, gvec4 ? TCache::getType(EbtInt, 4) : rvalue, name, - TCache::getType(EbtISampler2DMS), ptype2, ptype3, ptype4, ptype5); - insertBuiltIn(level, gvec4 ? TCache::getType(EbtUInt, 4) : rvalue, name, - TCache::getType(EbtUSampler2DMS), ptype2, ptype3, ptype4, ptype5); - } - else if (IsGImage(ptype1->getBasicType())) - { - insertUnmangledBuiltInName(name, level); - - const TType *floatType = TCache::getType(EbtFloat, 4); - const TType *intType = TCache::getType(EbtInt, 4); - const TType *unsignedType = TCache::getType(EbtUInt, 4); - - const TType *floatImage = - TCache::getType(convertGImageToFloatImage(ptype1->getBasicType())); - const TType *intImage = TCache::getType(convertGImageToIntImage(ptype1->getBasicType())); - const TType *unsignedImage = - TCache::getType(convertGImageToUnsignedImage(ptype1->getBasicType())); - - // GLSL ES 3.10, Revision 4, 8.12 Image Functions - if (rvalue->getBasicType() == EbtGVec4) - { - // imageLoad - insertBuiltIn(level, floatType, name, floatImage, ptype2, ptype3, ptype4, ptype5); - insertBuiltIn(level, intType, name, intImage, ptype2, ptype3, ptype4, ptype5); - insertBuiltIn(level, unsignedType, name, unsignedImage, ptype2, ptype3, ptype4, ptype5); - } - else if (rvalue->getBasicType() == EbtVoid) - { - // imageStore - insertBuiltIn(level, rvalue, name, floatImage, ptype2, floatType, ptype4, ptype5); - insertBuiltIn(level, rvalue, name, intImage, ptype2, intType, ptype4, ptype5); - insertBuiltIn(level, rvalue, name, unsignedImage, ptype2, unsignedType, ptype4, ptype5); - } - else - { - // imageSize - insertBuiltIn(level, rvalue, name, floatImage, ptype2, ptype3, ptype4, ptype5); - insertBuiltIn(level, rvalue, name, intImage, ptype2, ptype3, ptype4, ptype5); - insertBuiltIn(level, rvalue, name, unsignedImage, ptype2, ptype3, ptype4, ptype5); - } - } - else if (IsGenType(rvalue) || IsGenType(ptype1) || IsGenType(ptype2) || IsGenType(ptype3) || - IsGenType(ptype4)) - { - ASSERT(!ptype5); - insertUnmangledBuiltInName(name, level); - insertBuiltIn(level, op, ext, SpecificType(rvalue, 1), name, SpecificType(ptype1, 1), - SpecificType(ptype2, 1), SpecificType(ptype3, 1), SpecificType(ptype4, 1)); - insertBuiltIn(level, op, ext, SpecificType(rvalue, 2), name, SpecificType(ptype1, 2), - SpecificType(ptype2, 2), SpecificType(ptype3, 2), SpecificType(ptype4, 2)); - insertBuiltIn(level, op, ext, SpecificType(rvalue, 3), name, SpecificType(ptype1, 3), - SpecificType(ptype2, 3), SpecificType(ptype3, 3), SpecificType(ptype4, 3)); - insertBuiltIn(level, op, ext, SpecificType(rvalue, 4), name, SpecificType(ptype1, 4), - SpecificType(ptype2, 4), SpecificType(ptype3, 4), SpecificType(ptype4, 4)); - } - else if (IsVecType(rvalue) || IsVecType(ptype1) || IsVecType(ptype2) || IsVecType(ptype3)) - { - ASSERT(!ptype4 && !ptype5); - insertUnmangledBuiltInName(name, level); - insertBuiltIn(level, op, ext, VectorType(rvalue, 2), name, VectorType(ptype1, 2), - VectorType(ptype2, 2), VectorType(ptype3, 2)); - insertBuiltIn(level, op, ext, VectorType(rvalue, 3), name, VectorType(ptype1, 3), - VectorType(ptype2, 3), VectorType(ptype3, 3)); - insertBuiltIn(level, op, ext, VectorType(rvalue, 4), name, VectorType(ptype1, 4), - VectorType(ptype2, 4), VectorType(ptype3, 4)); - } - else - { - TFunction *function = new TFunction(this, NewPoolTString(name), rvalue, op, ext); - - function->addParameter(TConstParameter(ptype1)); - - if (ptype2) - { - function->addParameter(TConstParameter(ptype2)); - } - - if (ptype3) - { - function->addParameter(TConstParameter(ptype3)); - } - - if (ptype4) - { - function->addParameter(TConstParameter(ptype4)); - } - - if (ptype5) - { - function->addParameter(TConstParameter(ptype5)); - } - - ASSERT(hasUnmangledBuiltInAtLevel(name, level)); - insert(level, function); - } -} - -void TSymbolTable::insertBuiltInOp(ESymbolLevel level, - TOperator op, - const TType *rvalue, - const TType *ptype1, - const TType *ptype2, - const TType *ptype3, - const TType *ptype4, - const TType *ptype5) -{ - const char *name = GetOperatorString(op); - ASSERT(strlen(name) > 0); - insertUnmangledBuiltInName(name, level); - insertBuiltIn(level, op, TExtension::UNDEFINED, rvalue, name, ptype1, ptype2, ptype3, ptype4, - ptype5); -} - -void TSymbolTable::insertBuiltInOp(ESymbolLevel level, - TOperator op, - TExtension ext, - const TType *rvalue, - const TType *ptype1, - const TType *ptype2, - const TType *ptype3, - const TType *ptype4, - const TType *ptype5) -{ - const char *name = GetOperatorString(op); - insertUnmangledBuiltInName(name, level); - insertBuiltIn(level, op, ext, rvalue, name, ptype1, ptype2, ptype3, ptype4, ptype5); -} - -void TSymbolTable::insertBuiltInFunctionNoParameters(ESymbolLevel level, - TOperator op, - const TType *rvalue, - const char *name) -{ - insertUnmangledBuiltInName(name, level); - insert(level, new TFunction(this, NewPoolTString(name), rvalue, op)); -} - -void TSymbolTable::insertBuiltInFunctionNoParametersExt(ESymbolLevel level, - TExtension ext, - TOperator op, - const TType *rvalue, - const char *name) -{ - insertUnmangledBuiltInName(name, level); - insert(level, new TFunction(this, NewPoolTString(name), rvalue, op, ext)); -} - -TPrecision TSymbolTable::getDefaultPrecision(TBasicType type) const -{ - if (!SupportsPrecision(type)) - return EbpUndefined; - - // unsigned integers use the same precision as signed - TBasicType baseType = (type == EbtUInt) ? EbtInt : type; - - int level = static_cast(precisionStack.size()) - 1; - assert(level >= 0); // Just to be safe. Should not happen. - // If we dont find anything we return this. Some types don't have predefined default precision. - TPrecision prec = EbpUndefined; - while (level >= 0) - { - PrecisionStackLevel::iterator it = precisionStack[level]->find(baseType); - if (it != precisionStack[level]->end()) - { - prec = (*it).second; - break; - } - level--; - } - return prec; -} - -void TSymbolTable::insertUnmangledBuiltInName(const char *name, ESymbolLevel level) -{ - ASSERT(level >= 0 && level < static_cast(table.size())); - table[level]->insertUnmangledBuiltInName(std::string(name)); -} - -bool TSymbolTable::hasUnmangledBuiltInAtLevel(const char *name, ESymbolLevel level) -{ - ASSERT(level >= 0 && level < static_cast(table.size())); - return table[level]->hasUnmangledBuiltIn(std::string(name)); -} - -bool TSymbolTable::hasUnmangledBuiltInForShaderVersion(const char *name, int shaderVersion) -{ - ASSERT(static_cast(table.size()) > LAST_BUILTIN_LEVEL); - - for (int level = LAST_BUILTIN_LEVEL; level >= 0; --level) - { - if (level == ESSL3_1_BUILTINS && shaderVersion != 310) - { - --level; - } - if (level == ESSL3_BUILTINS && shaderVersion < 300) - { - --level; - } - if (level == ESSL1_BUILTINS && shaderVersion != 100) - { - --level; - } - - if (table[level]->hasUnmangledBuiltIn(name)) - { - return true; - } - } - return false; -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/SymbolTable.h b/src/3rdparty/angle/src/compiler/translator/SymbolTable.h deleted file mode 100644 index 5d792ec188..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/SymbolTable.h +++ /dev/null @@ -1,545 +0,0 @@ -// -// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_TRANSLATOR_SYMBOLTABLE_H_ -#define COMPILER_TRANSLATOR_SYMBOLTABLE_H_ - -// -// 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. -// -// * 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 -#include - -#include "common/angleutils.h" -#include "compiler/translator/ExtensionBehavior.h" -#include "compiler/translator/InfoSink.h" -#include "compiler/translator/IntermNode.h" -#include "compiler/translator/SymbolUniqueId.h" - -namespace sh -{ - -// Symbol base class. (Can build functions or variables out of these...) -class TSymbol : angle::NonCopyable -{ - public: - POOL_ALLOCATOR_NEW_DELETE(); - TSymbol(TSymbolTable *symbolTable, const TString *n); - - virtual ~TSymbol() - { - // don't delete name, it's from the pool - } - - const TString &getName() const { return *name; } - virtual const TString &getMangledName() const { return getName(); } - virtual bool isFunction() const { return false; } - virtual bool isVariable() const { return false; } - const TSymbolUniqueId &getUniqueId() const { return uniqueId; } - void relateToExtension(TExtension ext) { extension = ext; } - TExtension getExtension() const { return extension; } - - private: - const TSymbolUniqueId uniqueId; - const TString *name; - TExtension extension; -}; - -// Variable, meaning a symbol that's not a function. -// -// May store the value of a constant variable of any type (float, int, bool or struct). -class TVariable : public TSymbol -{ - public: - ~TVariable() override {} - bool isVariable() const override { return true; } - TType &getType() { return type; } - const TType &getType() const { return type; } - bool isUserType() const { return userType; } - void setQualifier(TQualifier qualifier) { type.setQualifier(qualifier); } - - const TConstantUnion *getConstPointer() const { return unionArray; } - - void shareConstPointer(const TConstantUnion *constArray) { unionArray = constArray; } - - private: - friend class TSymbolTable; - - TVariable(TSymbolTable *symbolTable, - const TString *name, - const TType &t, - bool isUserTypeDefinition = false) - : TSymbol(symbolTable, name), type(t), userType(isUserTypeDefinition), unionArray(0) - { - } - - TType type; - - // Set to true if this represents a struct type, as opposed to a variable. - bool userType; - - // we are assuming that Pool Allocator will free the memory - // allocated to unionArray when this object is destroyed. - const TConstantUnion *unionArray; -}; - -// Immutable version of TParameter. -struct TConstParameter -{ - TConstParameter() : name(nullptr), type(nullptr) {} - explicit TConstParameter(const TString *n) : name(n), type(nullptr) {} - explicit TConstParameter(const TType *t) : name(nullptr), type(t) {} - TConstParameter(const TString *n, const TType *t) : name(n), type(t) {} - - // Both constructor arguments must be const. - TConstParameter(TString *n, TType *t) = delete; - TConstParameter(const TString *n, TType *t) = delete; - TConstParameter(TString *n, const TType *t) = delete; - - const TString *const name; - const TType *const type; -}; - -// The function sub-class of symbols and the parser will need to -// share this definition of a function parameter. -struct TParameter -{ - // Destructively converts to TConstParameter. - // This method resets name and type to nullptrs to make sure - // their content cannot be modified after the call. - TConstParameter turnToConst() - { - const TString *constName = name; - const TType *constType = type; - name = nullptr; - type = nullptr; - return TConstParameter(constName, constType); - } - - const TString *name; - TType *type; -}; - -// The function sub-class of a symbol. -class TFunction : public TSymbol -{ - public: - TFunction(TSymbolTable *symbolTable, - const TString *name, - const TType *retType, - TOperator tOp = EOpNull, - TExtension ext = TExtension::UNDEFINED) - : TSymbol(symbolTable, name), - returnType(retType), - mangledName(nullptr), - op(tOp), - defined(false), - mHasPrototypeDeclaration(false) - { - relateToExtension(ext); - } - ~TFunction() override; - bool isFunction() const override { return true; } - - void addParameter(const TConstParameter &p) - { - parameters.push_back(p); - mangledName = nullptr; - } - - void swapParameters(const TFunction ¶metersSource); - - const TString &getMangledName() const override - { - if (mangledName == nullptr) - { - mangledName = buildMangledName(); - } - return *mangledName; - } - - static const TString &GetMangledNameFromCall(const TString &functionName, - const TIntermSequence &arguments); - - const TType &getReturnType() const { return *returnType; } - - TOperator getBuiltInOp() const { return op; } - - void setDefined() { defined = true; } - bool isDefined() { return defined; } - void setHasPrototypeDeclaration() { mHasPrototypeDeclaration = true; } - bool hasPrototypeDeclaration() const { return mHasPrototypeDeclaration; } - - size_t getParamCount() const { return parameters.size(); } - const TConstParameter &getParam(size_t i) const { return parameters[i]; } - - private: - void clearParameters(); - - const TString *buildMangledName() const; - - typedef TVector TParamList; - TParamList parameters; - const TType *returnType; - mutable const TString *mangledName; - TOperator op; - bool defined; - bool mHasPrototypeDeclaration; -}; - -// Interface block name sub-symbol -class TInterfaceBlockName : public TSymbol -{ - public: - virtual ~TInterfaceBlockName() {} - - private: - friend class TSymbolTable; - TInterfaceBlockName(TSymbolTable *symbolTable, const TString *name) : TSymbol(symbolTable, name) - { - } -}; - -class TSymbolTableLevel -{ - public: - typedef TUnorderedMap tLevel; - typedef tLevel::const_iterator const_iterator; - typedef const tLevel::value_type tLevelPair; - typedef std::pair tInsertResult; - - TSymbolTableLevel() : mGlobalInvariant(false) {} - ~TSymbolTableLevel(); - - bool insert(TSymbol *symbol); - - // Insert a function using its unmangled name as the key. - bool insertUnmangled(TFunction *function); - - TSymbol *find(const TString &name) const; - - void addInvariantVarying(const std::string &name) { mInvariantVaryings.insert(name); } - - bool isVaryingInvariant(const std::string &name) - { - return (mGlobalInvariant || mInvariantVaryings.count(name) > 0); - } - - void setGlobalInvariant(bool invariant) { mGlobalInvariant = invariant; } - - void insertUnmangledBuiltInName(const std::string &name) - { - mUnmangledBuiltInNames.insert(name); - } - - bool hasUnmangledBuiltIn(const std::string &name) - { - return mUnmangledBuiltInNames.count(name) > 0; - } - - protected: - tLevel level; - std::set mInvariantVaryings; - bool mGlobalInvariant; - - private: - std::set mUnmangledBuiltInNames; -}; - -// Define ESymbolLevel as int rather than an enum since level can go -// above GLOBAL_LEVEL and cause atBuiltInLevel() to fail if the -// compiler optimizes the >= of the last element to ==. -typedef int ESymbolLevel; -const int COMMON_BUILTINS = 0; -const int ESSL1_BUILTINS = 1; -const int ESSL3_BUILTINS = 2; -const int ESSL3_1_BUILTINS = 3; -// GLSL_BUILTINS are desktop GLSL builtins that don't exist in ESSL but are used to implement -// features in ANGLE's GLSL backend. They're not visible to the parser. -const int GLSL_BUILTINS = 4; -const int LAST_BUILTIN_LEVEL = GLSL_BUILTINS; -const int GLOBAL_LEVEL = 5; - -class TSymbolTable : angle::NonCopyable -{ - public: - TSymbolTable() : mUniqueIdCounter(0), mEmptySymbolId(this) - { - // The symbol table cannot be used until push() is called, but - // the lack of an initial call to push() can be used to detect - // that the symbol table has not been preloaded with built-ins. - } - - ~TSymbolTable(); - - // When the symbol table is initialized with the built-ins, there should - // 'push' calls, so that built-ins are at level 0 and the shader - // globals are at level 1. - bool isEmpty() const { return table.empty(); } - bool atBuiltInLevel() const { return currentLevel() <= LAST_BUILTIN_LEVEL; } - bool atGlobalLevel() const { return currentLevel() == GLOBAL_LEVEL; } - void push() - { - table.push_back(new TSymbolTableLevel); - precisionStack.push_back(new PrecisionStackLevel); - } - - void pop() - { - delete table.back(); - table.pop_back(); - - delete precisionStack.back(); - precisionStack.pop_back(); - } - - // The declare* entry points are used when parsing and declare symbols at the current scope. - // They return the created symbol in case the declaration was successful, and nullptr if the - // declaration failed due to redefinition. - TVariable *declareVariable(const TString *name, const TType &type); - TVariable *declareStructType(TStructure *str); - TInterfaceBlockName *declareInterfaceBlockName(const TString *name); - - // The insert* entry points are used when initializing the symbol table with built-ins. - // They return the created symbol in case the declaration was successful, and nullptr if the - // declaration failed due to redefinition. - TVariable *insertVariable(ESymbolLevel level, const char *name, const TType &type); - TVariable *insertVariableExt(ESymbolLevel level, - TExtension ext, - const char *name, - const TType &type); - TVariable *insertStructType(ESymbolLevel level, TStructure *str); - TInterfaceBlockName *insertInterfaceBlockNameExt(ESymbolLevel level, - TExtension ext, - const TString *name); - - bool insertConstInt(ESymbolLevel level, const char *name, int value, TPrecision precision) - { - TVariable *constant = - new TVariable(this, NewPoolTString(name), TType(EbtInt, precision, EvqConst, 1)); - TConstantUnion *unionArray = new TConstantUnion[1]; - unionArray[0].setIConst(value); - constant->shareConstPointer(unionArray); - return insert(level, constant); - } - - bool insertConstIntExt(ESymbolLevel level, - TExtension ext, - const char *name, - int value, - TPrecision precision) - { - TVariable *constant = - new TVariable(this, NewPoolTString(name), TType(EbtInt, precision, EvqConst, 1)); - TConstantUnion *unionArray = new TConstantUnion[1]; - unionArray[0].setIConst(value); - constant->shareConstPointer(unionArray); - return insert(level, ext, constant); - } - - bool insertConstIvec3(ESymbolLevel level, - const char *name, - const std::array &values, - TPrecision precision) - { - TVariable *constantIvec3 = - new TVariable(this, NewPoolTString(name), TType(EbtInt, precision, EvqConst, 3)); - - TConstantUnion *unionArray = new TConstantUnion[3]; - for (size_t index = 0u; index < 3u; ++index) - { - unionArray[index].setIConst(values[index]); - } - constantIvec3->shareConstPointer(unionArray); - - return insert(level, constantIvec3); - } - - void insertBuiltIn(ESymbolLevel level, - TOperator op, - TExtension ext, - const TType *rvalue, - const char *name, - const TType *ptype1, - const TType *ptype2 = 0, - const TType *ptype3 = 0, - const TType *ptype4 = 0, - const TType *ptype5 = 0); - - void insertBuiltIn(ESymbolLevel level, - const TType *rvalue, - const char *name, - const TType *ptype1, - const TType *ptype2 = 0, - const TType *ptype3 = 0, - const TType *ptype4 = 0, - const TType *ptype5 = 0) - { - insertUnmangledBuiltInName(name, level); - insertBuiltIn(level, EOpNull, TExtension::UNDEFINED, rvalue, name, ptype1, ptype2, ptype3, - ptype4, ptype5); - } - - void insertBuiltIn(ESymbolLevel level, - TExtension ext, - const TType *rvalue, - const char *name, - const TType *ptype1, - const TType *ptype2 = 0, - const TType *ptype3 = 0, - const TType *ptype4 = 0, - const TType *ptype5 = 0) - { - insertUnmangledBuiltInName(name, level); - insertBuiltIn(level, EOpNull, ext, rvalue, name, ptype1, ptype2, ptype3, ptype4, ptype5); - } - - void insertBuiltInOp(ESymbolLevel level, - TOperator op, - const TType *rvalue, - const TType *ptype1, - const TType *ptype2 = 0, - const TType *ptype3 = 0, - const TType *ptype4 = 0, - const TType *ptype5 = 0); - - void insertBuiltInOp(ESymbolLevel level, - TOperator op, - TExtension ext, - const TType *rvalue, - const TType *ptype1, - const TType *ptype2 = 0, - const TType *ptype3 = 0, - const TType *ptype4 = 0, - const TType *ptype5 = 0); - - void insertBuiltInFunctionNoParameters(ESymbolLevel level, - TOperator op, - const TType *rvalue, - const char *name); - - void insertBuiltInFunctionNoParametersExt(ESymbolLevel level, - TExtension ext, - TOperator op, - const TType *rvalue, - const char *name); - - TSymbol *find(const TString &name, - int shaderVersion, - bool *builtIn = nullptr, - bool *sameScope = nullptr) const; - - TSymbol *findGlobal(const TString &name) const; - - TSymbol *findBuiltIn(const TString &name, int shaderVersion) const; - - TSymbol *findBuiltIn(const TString &name, int shaderVersion, bool includeGLSLBuiltins) const; - - TSymbolTableLevel *getOuterLevel() - { - assert(currentLevel() >= 1); - return table[currentLevel() - 1]; - } - - void setDefaultPrecision(TBasicType type, TPrecision prec) - { - int indexOfLastElement = static_cast(precisionStack.size()) - 1; - // Uses map operator [], overwrites the current value - (*precisionStack[indexOfLastElement])[type] = prec; - } - - // Searches down the precisionStack for a precision qualifier - // for the specified TBasicType - TPrecision getDefaultPrecision(TBasicType type) const; - - // This records invariant varyings declared through - // "invariant varying_name;". - void addInvariantVarying(const std::string &originalName) - { - ASSERT(atGlobalLevel()); - table[currentLevel()]->addInvariantVarying(originalName); - } - // If this returns false, the varying could still be invariant - // if it is set as invariant during the varying variable - // declaration - this piece of information is stored in the - // variable's type, not here. - bool isVaryingInvariant(const std::string &originalName) const - { - ASSERT(atGlobalLevel()); - return table[currentLevel()]->isVaryingInvariant(originalName); - } - - void setGlobalInvariant(bool invariant) - { - ASSERT(atGlobalLevel()); - table[currentLevel()]->setGlobalInvariant(invariant); - } - - const TSymbolUniqueId nextUniqueId() { return TSymbolUniqueId(this); } - - // The empty symbol id is shared between all empty string ("") symbols. They are used in the - // AST for unused function parameters and struct type declarations that don't declare a - // variable, for example. - const TSymbolUniqueId &getEmptySymbolId() { return mEmptySymbolId; } - - // Checks whether there is a built-in accessible by a shader with the specified version. - bool hasUnmangledBuiltInForShaderVersion(const char *name, int shaderVersion); - - private: - friend class TSymbolUniqueId; - int nextUniqueIdValue() { return ++mUniqueIdCounter; } - - ESymbolLevel currentLevel() const { return static_cast(table.size() - 1); } - - TVariable *insertVariable(ESymbolLevel level, const TString *name, const TType &type); - - bool insert(ESymbolLevel level, TSymbol *symbol) { return table[level]->insert(symbol); } - - bool insert(ESymbolLevel level, TExtension ext, TSymbol *symbol) - { - symbol->relateToExtension(ext); - return table[level]->insert(symbol); - } - - // Used to insert unmangled functions to check redeclaration of built-ins in ESSL 3.00 and - // above. - void insertUnmangledBuiltInName(const char *name, ESymbolLevel level); - - bool hasUnmangledBuiltInAtLevel(const char *name, ESymbolLevel level); - - std::vector table; - typedef TMap PrecisionStackLevel; - std::vector precisionStack; - - int mUniqueIdCounter; - - const TSymbolUniqueId mEmptySymbolId; -}; - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_SYMBOLTABLE_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/SymbolUniqueId.cpp b/src/3rdparty/angle/src/compiler/translator/SymbolUniqueId.cpp deleted file mode 100644 index 2a68ae3e70..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/SymbolUniqueId.cpp +++ /dev/null @@ -1,28 +0,0 @@ -// -// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// SymbolUniqueId.cpp: Encapsulates a unique id for a symbol. - -#include "compiler/translator/SymbolUniqueId.h" - -#include "compiler/translator/SymbolTable.h" - -namespace sh -{ - -TSymbolUniqueId::TSymbolUniqueId(TSymbolTable *symbolTable) : mId(symbolTable->nextUniqueIdValue()) -{ -} - -TSymbolUniqueId::TSymbolUniqueId(const TSymbol &symbol) : mId(symbol.getUniqueId().get()) -{ -} - -int TSymbolUniqueId::get() const -{ - return mId; -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/SymbolUniqueId.h b/src/3rdparty/angle/src/compiler/translator/SymbolUniqueId.h deleted file mode 100644 index 4bd5604246..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/SymbolUniqueId.h +++ /dev/null @@ -1,36 +0,0 @@ -// -// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// SymbolUniqueId.h: Encapsulates a unique id for a symbol. - -#ifndef COMPILER_TRANSLATOR_SYMBOLUNIQUEID_H_ -#define COMPILER_TRANSLATOR_SYMBOLUNIQUEID_H_ - -#include "compiler/translator/Common.h" - -namespace sh -{ - -class TSymbolTable; -class TSymbol; - -class TSymbolUniqueId -{ - public: - POOL_ALLOCATOR_NEW_DELETE(); - explicit TSymbolUniqueId(TSymbolTable *symbolTable); - explicit TSymbolUniqueId(const TSymbol &symbol); - TSymbolUniqueId(const TSymbolUniqueId &) = default; - TSymbolUniqueId &operator=(const TSymbolUniqueId &) = default; - - int get() const; - - private: - int mId; -}; - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_SYMBOLUNIQUEID_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/TextureFunctionHLSL.cpp b/src/3rdparty/angle/src/compiler/translator/TextureFunctionHLSL.cpp deleted file mode 100644 index d2b65a6c56..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/TextureFunctionHLSL.cpp +++ /dev/null @@ -1,1322 +0,0 @@ -// -// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// TextureFunctionHLSL: Class for writing implementations of ESSL texture functions into HLSL -// output. Some of the implementations are straightforward and just call the HLSL equivalent of the -// ESSL texture function, others do more work to emulate ESSL texture sampling or size query -// behavior. -// - -#include "compiler/translator/TextureFunctionHLSL.h" - -#include "compiler/translator/UtilsHLSL.h" - -namespace sh -{ - -namespace -{ - -void OutputIntTexCoordWrap(TInfoSinkBase &out, - const char *wrapMode, - const char *size, - const TString &texCoord, - const TString &texCoordOffset, - const char *texCoordOutName) -{ - // GLES 3.0.4 table 3.22 specifies how the wrap modes work. We don't use the formulas verbatim - // but rather use equivalent formulas that map better to HLSL. - out << "int " << texCoordOutName << ";\n"; - out << "float " << texCoordOutName << "Offset = " << texCoord << " + float(" << texCoordOffset - << ") / " << size << ";\n"; - - // CLAMP_TO_EDGE - out << "if (" << wrapMode << " == 1)\n"; - out << "{\n"; - out << " " << texCoordOutName << " = clamp(int(floor(" << size << " * " << texCoordOutName - << "Offset)), 0, int(" << size << ") - 1);\n"; - out << "}\n"; - - // MIRRORED_REPEAT - out << "else if (" << wrapMode << " == 3)\n"; - out << "{\n"; - out << " float coordWrapped = 1.0 - abs(frac(abs(" << texCoordOutName - << "Offset) * 0.5) * 2.0 - 1.0);\n"; - out << " " << texCoordOutName << " = int(floor(" << size << " * coordWrapped));\n"; - out << "}\n"; - - // REPEAT - out << "else\n"; - out << "{\n"; - out << " " << texCoordOutName << " = int(floor(" << size << " * frac(" << texCoordOutName - << "Offset)));\n"; - out << "}\n"; -} - -void OutputIntTexCoordWraps(TInfoSinkBase &out, - const TextureFunctionHLSL::TextureFunction &textureFunction, - TString *texCoordX, - TString *texCoordY, - TString *texCoordZ) -{ - // Convert from normalized floating-point to integer - out << "int wrapS = samplerMetadata[samplerIndex].wrapModes & 0x3;\n"; - if (textureFunction.offset) - { - OutputIntTexCoordWrap(out, "wrapS", "width", *texCoordX, "offset.x", "tix"); - } - else - { - OutputIntTexCoordWrap(out, "wrapS", "width", *texCoordX, "0", "tix"); - } - *texCoordX = "tix"; - out << "int wrapT = (samplerMetadata[samplerIndex].wrapModes >> 2) & 0x3;\n"; - if (textureFunction.offset) - { - OutputIntTexCoordWrap(out, "wrapT", "height", *texCoordY, "offset.y", "tiy"); - } - else - { - OutputIntTexCoordWrap(out, "wrapT", "height", *texCoordY, "0", "tiy"); - } - *texCoordY = "tiy"; - - if (IsSamplerArray(textureFunction.sampler)) - { - *texCoordZ = "int(max(0, min(layers - 1, floor(0.5 + t.z))))"; - } - else if (!IsSamplerCube(textureFunction.sampler) && !IsSampler2D(textureFunction.sampler)) - { - out << "int wrapR = (samplerMetadata[samplerIndex].wrapModes >> 4) & 0x3;\n"; - if (textureFunction.offset) - { - OutputIntTexCoordWrap(out, "wrapR", "depth", *texCoordZ, "offset.z", "tiz"); - } - else - { - OutputIntTexCoordWrap(out, "wrapR", "depth", *texCoordZ, "0", "tiz"); - } - *texCoordZ = "tiz"; - } -} - -void OutputHLSL4SampleFunctionPrefix(TInfoSinkBase &out, - const TextureFunctionHLSL::TextureFunction &textureFunction, - const TString &textureReference, - const TString &samplerReference) -{ - out << textureReference; - if (IsIntegerSampler(textureFunction.sampler) || - textureFunction.method == TextureFunctionHLSL::TextureFunction::FETCH) - { - out << ".Load("; - return; - } - - if (IsShadowSampler(textureFunction.sampler)) - { - switch (textureFunction.method) - { - case TextureFunctionHLSL::TextureFunction::IMPLICIT: - case TextureFunctionHLSL::TextureFunction::BIAS: - case TextureFunctionHLSL::TextureFunction::LOD: - out << ".SampleCmp("; - break; - case TextureFunctionHLSL::TextureFunction::LOD0: - case TextureFunctionHLSL::TextureFunction::LOD0BIAS: - case TextureFunctionHLSL::TextureFunction::GRAD: - out << ".SampleCmpLevelZero("; - break; - default: - UNREACHABLE(); - } - } - else - { - switch (textureFunction.method) - { - case TextureFunctionHLSL::TextureFunction::IMPLICIT: - out << ".Sample("; - break; - case TextureFunctionHLSL::TextureFunction::BIAS: - out << ".SampleBias("; - break; - case TextureFunctionHLSL::TextureFunction::LOD: - case TextureFunctionHLSL::TextureFunction::LOD0: - case TextureFunctionHLSL::TextureFunction::LOD0BIAS: - out << ".SampleLevel("; - break; - case TextureFunctionHLSL::TextureFunction::GRAD: - out << ".SampleGrad("; - break; - default: - UNREACHABLE(); - } - } - out << samplerReference << ", "; -} - -const char *GetSamplerCoordinateTypeString( - const TextureFunctionHLSL::TextureFunction &textureFunction, - int hlslCoords) -{ - if (IsIntegerSampler(textureFunction.sampler) || - textureFunction.method == TextureFunctionHLSL::TextureFunction::FETCH) - { - switch (hlslCoords) - { - case 2: - if (textureFunction.sampler == EbtSampler2DMS || - textureFunction.sampler == EbtISampler2DMS || - textureFunction.sampler == EbtUSampler2DMS) - return "int2"; - else - return "int3"; - case 3: - return "int4"; - default: - UNREACHABLE(); - } - } - else - { - switch (hlslCoords) - { - case 2: - return "float2"; - case 3: - return "float3"; - case 4: - return "float4"; - default: - UNREACHABLE(); - } - } - return ""; -} - -int GetHLSLCoordCount(const TextureFunctionHLSL::TextureFunction &textureFunction, - ShShaderOutput outputType) -{ - if (outputType == SH_HLSL_3_0_OUTPUT) - { - int hlslCoords = 2; - switch (textureFunction.sampler) - { - case EbtSampler2D: - case EbtSamplerExternalOES: - case EbtSampler2DMS: - hlslCoords = 2; - break; - case EbtSamplerCube: - hlslCoords = 3; - break; - default: - UNREACHABLE(); - } - - switch (textureFunction.method) - { - case TextureFunctionHLSL::TextureFunction::IMPLICIT: - case TextureFunctionHLSL::TextureFunction::GRAD: - return hlslCoords; - case TextureFunctionHLSL::TextureFunction::BIAS: - case TextureFunctionHLSL::TextureFunction::LOD: - case TextureFunctionHLSL::TextureFunction::LOD0: - case TextureFunctionHLSL::TextureFunction::LOD0BIAS: - return 4; - default: - UNREACHABLE(); - } - } - else - { - switch (textureFunction.sampler) - { - case EbtSampler2D: - return 2; - case EbtSampler2DMS: - return 2; - case EbtSampler3D: - return 3; - case EbtSamplerCube: - return 3; - case EbtSampler2DArray: - return 3; - case EbtSamplerExternalOES: - return 2; - case EbtISampler2D: - return 2; - case EbtISampler2DMS: - return 2; - case EbtISampler3D: - return 3; - case EbtISamplerCube: - return 3; - case EbtISampler2DArray: - return 3; - case EbtUSampler2D: - return 2; - case EbtUSampler2DMS: - return 2; - case EbtUSampler3D: - return 3; - case EbtUSamplerCube: - return 3; - case EbtUSampler2DArray: - return 3; - case EbtSampler2DShadow: - return 2; - case EbtSamplerCubeShadow: - return 3; - case EbtSampler2DArrayShadow: - return 3; - default: - UNREACHABLE(); - } - } - return 0; -} - -void OutputTextureFunctionArgumentList(TInfoSinkBase &out, - const TextureFunctionHLSL::TextureFunction &textureFunction, - const ShShaderOutput outputType) -{ - if (outputType == SH_HLSL_3_0_OUTPUT) - { - switch (textureFunction.sampler) - { - case EbtSampler2D: - case EbtSamplerExternalOES: - out << "sampler2D s"; - break; - case EbtSamplerCube: - out << "samplerCUBE s"; - break; - default: - UNREACHABLE(); - } - } - else - { - if (outputType == SH_HLSL_4_0_FL9_3_OUTPUT) - { - out << TextureString(textureFunction.sampler) << " x, " - << SamplerString(textureFunction.sampler) << " s"; - } - else - { - ASSERT(outputType == SH_HLSL_4_1_OUTPUT); - // A bug in the D3D compiler causes some nested sampling operations to fail. - // See http://anglebug.com/1923 - // TODO(jmadill): Reinstate the const keyword when possible. - out << /*"const"*/ "uint samplerIndex"; - } - } - - if (textureFunction.method == - TextureFunctionHLSL::TextureFunction::FETCH) // Integer coordinates - { - switch (textureFunction.coords) - { - case 2: - out << ", int2 t"; - break; - case 3: - out << ", int3 t"; - break; - default: - UNREACHABLE(); - } - } - else // Floating-point coordinates (except textureSize) - { - switch (textureFunction.coords) - { - case 0: - break; // textureSize(gSampler2DMS sampler) - case 1: - out << ", int lod"; - break; // textureSize() - case 2: - out << ", float2 t"; - break; - case 3: - out << ", float3 t"; - break; - case 4: - out << ", float4 t"; - break; - default: - UNREACHABLE(); - } - } - - if (textureFunction.method == TextureFunctionHLSL::TextureFunction::GRAD) - { - switch (textureFunction.sampler) - { - case EbtSampler2D: - case EbtISampler2D: - case EbtUSampler2D: - case EbtSampler2DArray: - case EbtISampler2DArray: - case EbtUSampler2DArray: - case EbtSampler2DShadow: - case EbtSampler2DArrayShadow: - case EbtSamplerExternalOES: - out << ", float2 ddx, float2 ddy"; - break; - case EbtSampler3D: - case EbtISampler3D: - case EbtUSampler3D: - case EbtSamplerCube: - case EbtISamplerCube: - case EbtUSamplerCube: - case EbtSamplerCubeShadow: - out << ", float3 ddx, float3 ddy"; - break; - default: - UNREACHABLE(); - } - } - - switch (textureFunction.method) - { - case TextureFunctionHLSL::TextureFunction::IMPLICIT: - break; - case TextureFunctionHLSL::TextureFunction::BIAS: - break; // Comes after the offset parameter - case TextureFunctionHLSL::TextureFunction::LOD: - out << ", float lod"; - break; - case TextureFunctionHLSL::TextureFunction::LOD0: - break; - case TextureFunctionHLSL::TextureFunction::LOD0BIAS: - break; // Comes after the offset parameter - case TextureFunctionHLSL::TextureFunction::SIZE: - break; - case TextureFunctionHLSL::TextureFunction::FETCH: - if (textureFunction.sampler == EbtSampler2DMS || - textureFunction.sampler == EbtISampler2DMS || - textureFunction.sampler == EbtUSampler2DMS) - out << ", int index"; - else - out << ", int mip"; - break; - case TextureFunctionHLSL::TextureFunction::GRAD: - break; - default: - UNREACHABLE(); - } - - if (textureFunction.offset) - { - switch (textureFunction.sampler) - { - case EbtSampler3D: - case EbtISampler3D: - case EbtUSampler3D: - out << ", int3 offset"; - break; - case EbtSampler2D: - case EbtSampler2DArray: - case EbtISampler2D: - case EbtISampler2DArray: - case EbtUSampler2D: - case EbtUSampler2DArray: - case EbtSampler2DShadow: - case EbtSampler2DArrayShadow: - case EbtSampler2DMS: - case EbtISampler2DMS: - case EbtUSampler2DMS: - case EbtSamplerExternalOES: - out << ", int2 offset"; - break; - default: - UNREACHABLE(); - } - } - - if (textureFunction.method == TextureFunctionHLSL::TextureFunction::BIAS || - textureFunction.method == TextureFunctionHLSL::TextureFunction::LOD0BIAS) - { - out << ", float bias"; - } -} - -void GetTextureReference(TInfoSinkBase &out, - const TextureFunctionHLSL::TextureFunction &textureFunction, - const ShShaderOutput outputType, - TString *textureReference, - TString *samplerReference) -{ - if (outputType == SH_HLSL_4_1_OUTPUT) - { - TString suffix = TextureGroupSuffix(textureFunction.sampler); - if (TextureGroup(textureFunction.sampler) == HLSL_TEXTURE_2D) - { - *textureReference = TString("textures") + suffix + "[samplerIndex]"; - *samplerReference = TString("samplers") + suffix + "[samplerIndex]"; - } - else - { - out << " const uint textureIndex = samplerIndex - textureIndexOffset" << suffix - << ";\n"; - *textureReference = TString("textures") + suffix + "[textureIndex]"; - out << " const uint samplerArrayIndex = samplerIndex - samplerIndexOffset" << suffix - << ";\n"; - *samplerReference = TString("samplers") + suffix + "[samplerArrayIndex]"; - } - } - else - { - *textureReference = "x"; - *samplerReference = "s"; - } -} - -void OutputTextureSizeFunctionBody(TInfoSinkBase &out, - const TextureFunctionHLSL::TextureFunction &textureFunction, - const TString &textureReference, - bool getDimensionsIgnoresBaseLevel) -{ - if (IsSampler2DMS(textureFunction.sampler)) - { - out << " uint width; uint height; uint samples;\n" - << " " << textureReference << ".GetDimensions(width, height, samples);\n"; - } - else - { - if (getDimensionsIgnoresBaseLevel) - { - out << " int baseLevel = samplerMetadata[samplerIndex].baseLevel;\n"; - } - else - { - out << " int baseLevel = 0;\n"; - } - - if (IsSampler3D(textureFunction.sampler) || IsSamplerArray(textureFunction.sampler) || - (IsIntegerSampler(textureFunction.sampler) && IsSamplerCube(textureFunction.sampler))) - { - // "depth" stores either the number of layers in an array texture or 3D depth - out << " uint width; uint height; uint depth; uint numberOfLevels;\n" - << " " << textureReference - << ".GetDimensions(baseLevel, width, height, depth, numberOfLevels);\n" - << " width = max(width >> lod, 1);\n" - << " height = max(height >> lod, 1);\n"; - - if (!IsSamplerArray(textureFunction.sampler)) - { - out << " depth = max(depth >> lod, 1);\n"; - } - } - else if (IsSampler2D(textureFunction.sampler) || IsSamplerCube(textureFunction.sampler)) - { - out << " uint width; uint height; uint numberOfLevels;\n" - << " " << textureReference - << ".GetDimensions(baseLevel, width, height, numberOfLevels);\n" - << " width = max(width >> lod, 1);\n" - << " height = max(height >> lod, 1);\n"; - } - else - UNREACHABLE(); - } - - if (strcmp(textureFunction.getReturnType(), "int3") == 0) - { - out << " return int3(width, height, depth);\n"; - } - else - { - out << " return int2(width, height);\n"; - } -} - -void ProjectTextureCoordinates(const TextureFunctionHLSL::TextureFunction &textureFunction, - TString *texCoordX, - TString *texCoordY, - TString *texCoordZ) -{ - if (textureFunction.proj) - { - TString proj(""); - switch (textureFunction.coords) - { - case 3: - proj = " / t.z"; - break; - case 4: - proj = " / t.w"; - break; - default: - UNREACHABLE(); - } - *texCoordX = "(" + *texCoordX + proj + ")"; - *texCoordY = "(" + *texCoordY + proj + ")"; - *texCoordZ = "(" + *texCoordZ + proj + ")"; - } -} - -void OutputIntegerTextureSampleFunctionComputations( - TInfoSinkBase &out, - const TextureFunctionHLSL::TextureFunction &textureFunction, - const ShShaderOutput outputType, - const TString &textureReference, - TString *texCoordX, - TString *texCoordY, - TString *texCoordZ) -{ - if (!IsIntegerSampler(textureFunction.sampler)) - { - return; - } - if (IsSamplerCube(textureFunction.sampler)) - { - out << " float width; float height; float layers; float levels;\n"; - - out << " uint mip = 0;\n"; - - out << " " << textureReference - << ".GetDimensions(mip, width, height, layers, levels);\n"; - - out << " bool xMajor = abs(t.x) > abs(t.y) && abs(t.x) > abs(t.z);\n"; - out << " bool yMajor = abs(t.y) > abs(t.z) && abs(t.y) > abs(t.x);\n"; - out << " bool zMajor = abs(t.z) > abs(t.x) && abs(t.z) > abs(t.y);\n"; - out << " bool negative = (xMajor && t.x < 0.0f) || (yMajor && t.y < 0.0f) || " - "(zMajor && t.z < 0.0f);\n"; - - // FACE_POSITIVE_X = 000b - // FACE_NEGATIVE_X = 001b - // FACE_POSITIVE_Y = 010b - // FACE_NEGATIVE_Y = 011b - // FACE_POSITIVE_Z = 100b - // FACE_NEGATIVE_Z = 101b - out << " int face = (int)negative + (int)yMajor * 2 + (int)zMajor * 4;\n"; - - out << " float u = xMajor ? -t.z : (yMajor && t.y < 0.0f ? -t.x : t.x);\n"; - out << " float v = yMajor ? t.z : (negative ? t.y : -t.y);\n"; - out << " float m = xMajor ? t.x : (yMajor ? t.y : t.z);\n"; - - out << " t.x = (u * 0.5f / m) + 0.5f;\n"; - out << " t.y = (v * 0.5f / m) + 0.5f;\n"; - - // Mip level computation. - if (textureFunction.method == TextureFunctionHLSL::TextureFunction::IMPLICIT || - textureFunction.method == TextureFunctionHLSL::TextureFunction::LOD || - textureFunction.method == TextureFunctionHLSL::TextureFunction::GRAD) - { - if (textureFunction.method == TextureFunctionHLSL::TextureFunction::IMPLICIT) - { - out << " float2 tSized = float2(t.x * width, t.y * height);\n" - " float2 dx = ddx(tSized);\n" - " float2 dy = ddy(tSized);\n" - " float lod = 0.5f * log2(max(dot(dx, dx), dot(dy, dy)));\n"; - } - else if (textureFunction.method == TextureFunctionHLSL::TextureFunction::GRAD) - { - // ESSL 3.00.6 spec section 8.8: "For the cube version, the partial - // derivatives of P are assumed to be in the coordinate system used before - // texture coordinates are projected onto the appropriate cube face." - // ddx[0] and ddy[0] are the derivatives of t.x passed into the function - // ddx[1] and ddy[1] are the derivatives of t.y passed into the function - // ddx[2] and ddy[2] are the derivatives of t.z passed into the function - // Determine the derivatives of u, v and m - out << " float dudx = xMajor ? ddx[2] : (yMajor && t.y < 0.0f ? -ddx[0] " - ": ddx[0]);\n" - " float dudy = xMajor ? ddy[2] : (yMajor && t.y < 0.0f ? -ddy[0] " - ": ddy[0]);\n" - " float dvdx = yMajor ? ddx[2] : (negative ? ddx[1] : -ddx[1]);\n" - " float dvdy = yMajor ? ddy[2] : (negative ? ddy[1] : -ddy[1]);\n" - " float dmdx = xMajor ? ddx[0] : (yMajor ? ddx[1] : ddx[2]);\n" - " float dmdy = xMajor ? ddy[0] : (yMajor ? ddy[1] : ddy[2]);\n"; - // Now determine the derivatives of the face coordinates, using the - // derivatives calculated above. - // d / dx (u(x) * 0.5 / m(x) + 0.5) - // = 0.5 * (m(x) * u'(x) - u(x) * m'(x)) / m(x)^2 - out << " float dfacexdx = 0.5f * (m * dudx - u * dmdx) / (m * m);\n" - " float dfaceydx = 0.5f * (m * dvdx - v * dmdx) / (m * m);\n" - " float dfacexdy = 0.5f * (m * dudy - u * dmdy) / (m * m);\n" - " float dfaceydy = 0.5f * (m * dvdy - v * dmdy) / (m * m);\n" - " float2 sizeVec = float2(width, height);\n" - " float2 faceddx = float2(dfacexdx, dfaceydx) * sizeVec;\n" - " float2 faceddy = float2(dfacexdy, dfaceydy) * sizeVec;\n"; - // Optimization: instead of: log2(max(length(faceddx), length(faceddy))) - // we compute: log2(max(length(faceddx)^2, length(faceddy)^2)) / 2 - out << " float lengthfaceddx2 = dot(faceddx, faceddx);\n" - " float lengthfaceddy2 = dot(faceddy, faceddy);\n" - " float lod = log2(max(lengthfaceddx2, lengthfaceddy2)) * 0.5f;\n"; - } - out << " mip = uint(min(max(round(lod), 0), levels - 1));\n" - << " " << textureReference - << ".GetDimensions(mip, width, height, layers, levels);\n"; - } - - // Convert from normalized floating-point to integer - *texCoordX = "int(floor(width * frac(" + *texCoordX + ")))"; - *texCoordY = "int(floor(height * frac(" + *texCoordY + ")))"; - *texCoordZ = "face"; - } - else if (textureFunction.method != TextureFunctionHLSL::TextureFunction::FETCH) - { - if (IsSampler2D(textureFunction.sampler)) - { - if (IsSamplerArray(textureFunction.sampler)) - { - out << " float width; float height; float layers; float levels;\n"; - - if (textureFunction.method == TextureFunctionHLSL::TextureFunction::LOD0) - { - out << " uint mip = 0;\n"; - } - else if (textureFunction.method == TextureFunctionHLSL::TextureFunction::LOD0BIAS) - { - out << " uint mip = bias;\n"; - } - else - { - - out << " " << textureReference - << ".GetDimensions(0, width, height, layers, levels);\n"; - if (textureFunction.method == TextureFunctionHLSL::TextureFunction::IMPLICIT || - textureFunction.method == TextureFunctionHLSL::TextureFunction::BIAS) - { - out << " float2 tSized = float2(t.x * width, t.y * height);\n" - " float dx = length(ddx(tSized));\n" - " float dy = length(ddy(tSized));\n" - " float lod = log2(max(dx, dy));\n"; - - if (textureFunction.method == TextureFunctionHLSL::TextureFunction::BIAS) - { - out << " lod += bias;\n"; - } - } - else if (textureFunction.method == TextureFunctionHLSL::TextureFunction::GRAD) - { - out << " float2 sizeVec = float2(width, height);\n" - " float2 sizeDdx = ddx * sizeVec;\n" - " float2 sizeDdy = ddy * sizeVec;\n" - " float lod = log2(max(dot(sizeDdx, sizeDdx), " - "dot(sizeDdy, sizeDdy))) * 0.5f;\n"; - } - - out << " uint mip = uint(min(max(round(lod), 0), levels - 1));\n"; - } - - out << " " << textureReference - << ".GetDimensions(mip, width, height, layers, levels);\n"; - } - else - { - out << " float width; float height; float levels;\n"; - - if (textureFunction.method == TextureFunctionHLSL::TextureFunction::LOD0) - { - out << " uint mip = 0;\n"; - } - else if (textureFunction.method == TextureFunctionHLSL::TextureFunction::LOD0BIAS) - { - out << " uint mip = bias;\n"; - } - else - { - out << " " << textureReference - << ".GetDimensions(0, width, height, levels);\n"; - - if (textureFunction.method == TextureFunctionHLSL::TextureFunction::IMPLICIT || - textureFunction.method == TextureFunctionHLSL::TextureFunction::BIAS) - { - out << " float2 tSized = float2(t.x * width, t.y * height);\n" - " float dx = length(ddx(tSized));\n" - " float dy = length(ddy(tSized));\n" - " float lod = log2(max(dx, dy));\n"; - - if (textureFunction.method == TextureFunctionHLSL::TextureFunction::BIAS) - { - out << " lod += bias;\n"; - } - } - else if (textureFunction.method == TextureFunctionHLSL::TextureFunction::GRAD) - { - out << " float2 sizeVec = float2(width, height);\n" - " float2 sizeDdx = ddx * sizeVec;\n" - " float2 sizeDdy = ddy * sizeVec;\n" - " float lod = log2(max(dot(sizeDdx, sizeDdx), " - "dot(sizeDdy, sizeDdy))) * 0.5f;\n"; - } - - out << " uint mip = uint(min(max(round(lod), 0), levels - 1));\n"; - } - - out << " " << textureReference - << ".GetDimensions(mip, width, height, levels);\n"; - } - } - else if (IsSampler3D(textureFunction.sampler)) - { - out << " float width; float height; float depth; float levels;\n"; - - if (textureFunction.method == TextureFunctionHLSL::TextureFunction::LOD0) - { - out << " uint mip = 0;\n"; - } - else if (textureFunction.method == TextureFunctionHLSL::TextureFunction::LOD0BIAS) - { - out << " uint mip = bias;\n"; - } - else - { - out << " " << textureReference - << ".GetDimensions(0, width, height, depth, levels);\n"; - - if (textureFunction.method == TextureFunctionHLSL::TextureFunction::IMPLICIT || - textureFunction.method == TextureFunctionHLSL::TextureFunction::BIAS) - { - out << " float3 tSized = float3(t.x * width, t.y * height, t.z * depth);\n" - " float dx = length(ddx(tSized));\n" - " float dy = length(ddy(tSized));\n" - " float lod = log2(max(dx, dy));\n"; - - if (textureFunction.method == TextureFunctionHLSL::TextureFunction::BIAS) - { - out << " lod += bias;\n"; - } - } - else if (textureFunction.method == TextureFunctionHLSL::TextureFunction::GRAD) - { - out << " float3 sizeVec = float3(width, height, depth);\n" - " float3 sizeDdx = ddx * sizeVec;\n" - " float3 sizeDdy = ddy * sizeVec;\n" - " float lod = log2(max(dot(sizeDdx, sizeDdx), dot(sizeDdy, " - "sizeDdy))) * 0.5f;\n"; - } - - out << " uint mip = uint(min(max(round(lod), 0), levels - 1));\n"; - } - - out << " " << textureReference - << ".GetDimensions(mip, width, height, depth, levels);\n"; - } - else - UNREACHABLE(); - - OutputIntTexCoordWraps(out, textureFunction, texCoordX, texCoordY, texCoordZ); - } -} - -void OutputTextureSampleFunctionReturnStatement( - TInfoSinkBase &out, - const TextureFunctionHLSL::TextureFunction &textureFunction, - const ShShaderOutput outputType, - const TString &textureReference, - const TString &samplerReference, - const TString &texCoordX, - const TString &texCoordY, - const TString &texCoordZ) -{ - out << " return "; - - // HLSL intrinsic - if (outputType == SH_HLSL_3_0_OUTPUT) - { - switch (textureFunction.sampler) - { - case EbtSampler2D: - case EbtSamplerExternalOES: - out << "tex2D"; - break; - case EbtSamplerCube: - out << "texCUBE"; - break; - default: - UNREACHABLE(); - } - - switch (textureFunction.method) - { - case TextureFunctionHLSL::TextureFunction::IMPLICIT: - out << "(" << samplerReference << ", "; - break; - case TextureFunctionHLSL::TextureFunction::BIAS: - out << "bias(" << samplerReference << ", "; - break; - case TextureFunctionHLSL::TextureFunction::LOD: - out << "lod(" << samplerReference << ", "; - break; - case TextureFunctionHLSL::TextureFunction::LOD0: - out << "lod(" << samplerReference << ", "; - break; - case TextureFunctionHLSL::TextureFunction::LOD0BIAS: - out << "lod(" << samplerReference << ", "; - break; - case TextureFunctionHLSL::TextureFunction::GRAD: - out << "grad(" << samplerReference << ", "; - break; - default: - UNREACHABLE(); - } - } - else if (outputType == SH_HLSL_4_1_OUTPUT || outputType == SH_HLSL_4_0_FL9_3_OUTPUT) - { - OutputHLSL4SampleFunctionPrefix(out, textureFunction, textureReference, samplerReference); - } - else - UNREACHABLE(); - - const int hlslCoords = GetHLSLCoordCount(textureFunction, outputType); - - out << GetSamplerCoordinateTypeString(textureFunction, hlslCoords) << "(" << texCoordX << ", " - << texCoordY; - - if (outputType == SH_HLSL_3_0_OUTPUT) - { - if (hlslCoords >= 3) - { - if (textureFunction.coords < 3) - { - out << ", 0"; - } - else - { - out << ", " << texCoordZ; - } - } - - if (hlslCoords == 4) - { - switch (textureFunction.method) - { - case TextureFunctionHLSL::TextureFunction::BIAS: - out << ", bias"; - break; - case TextureFunctionHLSL::TextureFunction::LOD: - out << ", lod"; - break; - case TextureFunctionHLSL::TextureFunction::LOD0: - out << ", 0"; - break; - case TextureFunctionHLSL::TextureFunction::LOD0BIAS: - out << ", bias"; - break; - default: - UNREACHABLE(); - } - } - - out << ")"; - } - else if (outputType == SH_HLSL_4_1_OUTPUT || outputType == SH_HLSL_4_0_FL9_3_OUTPUT) - { - if (hlslCoords >= 3) - { - ASSERT(!IsIntegerSampler(textureFunction.sampler) || - !IsSamplerCube(textureFunction.sampler) || texCoordZ == "face"); - out << ", " << texCoordZ; - } - - if (textureFunction.method == TextureFunctionHLSL::TextureFunction::GRAD) - { - if (IsIntegerSampler(textureFunction.sampler)) - { - out << ", mip)"; - } - else if (IsShadowSampler(textureFunction.sampler)) - { - // Compare value - if (textureFunction.proj) - { - // According to ESSL 3.00.4 sec 8.8 p95 on textureProj: - // The resulting third component of P' in the shadow forms is used as - // Dref - out << "), " << texCoordZ; - } - else - { - switch (textureFunction.coords) - { - case 3: - out << "), t.z"; - break; - case 4: - out << "), t.w"; - break; - default: - UNREACHABLE(); - } - } - } - else - { - out << "), ddx, ddy"; - } - } - else if (IsIntegerSampler(textureFunction.sampler) || - textureFunction.method == TextureFunctionHLSL::TextureFunction::FETCH) - { - if (textureFunction.sampler == EbtSampler2DMS || - textureFunction.sampler == EbtISampler2DMS || - textureFunction.sampler == EbtUSampler2DMS) - out << "), index"; - else - out << ", mip)"; - } - else if (IsShadowSampler(textureFunction.sampler)) - { - // Compare value - if (textureFunction.proj) - { - // According to ESSL 3.00.4 sec 8.8 p95 on textureProj: - // The resulting third component of P' in the shadow forms is used as Dref - out << "), " << texCoordZ; - } - else - { - switch (textureFunction.coords) - { - case 3: - out << "), t.z"; - break; - case 4: - out << "), t.w"; - break; - default: - UNREACHABLE(); - } - } - } - else - { - switch (textureFunction.method) - { - case TextureFunctionHLSL::TextureFunction::IMPLICIT: - out << ")"; - break; - case TextureFunctionHLSL::TextureFunction::BIAS: - out << "), bias"; - break; - case TextureFunctionHLSL::TextureFunction::LOD: - out << "), lod"; - break; - case TextureFunctionHLSL::TextureFunction::LOD0: - out << "), 0"; - break; - case TextureFunctionHLSL::TextureFunction::LOD0BIAS: - out << "), bias"; - break; - default: - UNREACHABLE(); - } - } - - if (textureFunction.offset && - (!IsIntegerSampler(textureFunction.sampler) || - textureFunction.method == TextureFunctionHLSL::TextureFunction::FETCH)) - { - out << ", offset"; - } - } - else - UNREACHABLE(); - - out << ");\n"; // Close the sample function call and return statement -} - -} // Anonymous namespace - -TString TextureFunctionHLSL::TextureFunction::name() const -{ - TString name = "gl_texture"; - - // We need to include full the sampler type in the function name to make the signature unique - // on D3D11, where samplers are passed to texture functions as indices. - name += TextureTypeSuffix(this->sampler); - - if (proj) - { - name += "Proj"; - } - - if (offset) - { - name += "Offset"; - } - - switch (method) - { - case IMPLICIT: - break; - case BIAS: - break; // Extra parameter makes the signature unique - case LOD: - name += "Lod"; - break; - case LOD0: - name += "Lod0"; - break; - case LOD0BIAS: - name += "Lod0"; - break; // Extra parameter makes the signature unique - case SIZE: - name += "Size"; - break; - case FETCH: - name += "Fetch"; - break; - case GRAD: - name += "Grad"; - break; - default: - UNREACHABLE(); - } - - return name; -} - -const char *TextureFunctionHLSL::TextureFunction::getReturnType() const -{ - if (method == TextureFunction::SIZE) - { - switch (sampler) - { - case EbtSampler2D: - case EbtISampler2D: - case EbtUSampler2D: - case EbtSampler2DShadow: - case EbtSamplerCube: - case EbtISamplerCube: - case EbtUSamplerCube: - case EbtSamplerCubeShadow: - case EbtSamplerExternalOES: - case EbtSampler2DMS: - case EbtISampler2DMS: - case EbtUSampler2DMS: - return "int2"; - case EbtSampler3D: - case EbtISampler3D: - case EbtUSampler3D: - case EbtSampler2DArray: - case EbtISampler2DArray: - case EbtUSampler2DArray: - case EbtSampler2DArrayShadow: - return "int3"; - default: - UNREACHABLE(); - } - } - else // Sampling function - { - switch (sampler) - { - case EbtSampler2D: - case EbtSampler2DMS: - case EbtSampler3D: - case EbtSamplerCube: - case EbtSampler2DArray: - case EbtSamplerExternalOES: - return "float4"; - case EbtISampler2D: - case EbtISampler2DMS: - case EbtISampler3D: - case EbtISamplerCube: - case EbtISampler2DArray: - return "int4"; - case EbtUSampler2D: - case EbtUSampler2DMS: - case EbtUSampler3D: - case EbtUSamplerCube: - case EbtUSampler2DArray: - return "uint4"; - case EbtSampler2DShadow: - case EbtSamplerCubeShadow: - case EbtSampler2DArrayShadow: - return "float"; - default: - UNREACHABLE(); - } - } - return ""; -} - -bool TextureFunctionHLSL::TextureFunction::operator<(const TextureFunction &rhs) const -{ - return std::tie(sampler, coords, proj, offset, method) < - std::tie(rhs.sampler, rhs.coords, rhs.proj, rhs.offset, rhs.method); -} - -TString TextureFunctionHLSL::useTextureFunction(const TString &name, - TBasicType samplerType, - int coords, - size_t argumentCount, - bool lod0, - sh::GLenum shaderType) -{ - TextureFunction textureFunction; - textureFunction.sampler = samplerType; - textureFunction.coords = coords; - textureFunction.method = TextureFunction::IMPLICIT; - textureFunction.proj = false; - textureFunction.offset = false; - - if (name == "texture2D" || name == "textureCube" || name == "texture") - { - textureFunction.method = TextureFunction::IMPLICIT; - } - else if (name == "texture2DProj" || name == "textureProj") - { - textureFunction.method = TextureFunction::IMPLICIT; - textureFunction.proj = true; - } - else if (name == "texture2DLod" || name == "textureCubeLod" || name == "textureLod" || - name == "texture2DLodEXT" || name == "textureCubeLodEXT") - { - textureFunction.method = TextureFunction::LOD; - } - else if (name == "texture2DProjLod" || name == "textureProjLod" || - name == "texture2DProjLodEXT") - { - textureFunction.method = TextureFunction::LOD; - textureFunction.proj = true; - } - else if (name == "textureSize") - { - textureFunction.method = TextureFunction::SIZE; - } - else if (name == "textureOffset") - { - textureFunction.method = TextureFunction::IMPLICIT; - textureFunction.offset = true; - } - else if (name == "textureProjOffset") - { - textureFunction.method = TextureFunction::IMPLICIT; - textureFunction.offset = true; - textureFunction.proj = true; - } - else if (name == "textureLodOffset") - { - textureFunction.method = TextureFunction::LOD; - textureFunction.offset = true; - } - else if (name == "textureProjLodOffset") - { - textureFunction.method = TextureFunction::LOD; - textureFunction.proj = true; - textureFunction.offset = true; - } - else if (name == "texelFetch") - { - textureFunction.method = TextureFunction::FETCH; - } - else if (name == "texelFetchOffset") - { - textureFunction.method = TextureFunction::FETCH; - textureFunction.offset = true; - } - else if (name == "textureGrad" || name == "texture2DGradEXT") - { - textureFunction.method = TextureFunction::GRAD; - } - else if (name == "textureGradOffset") - { - textureFunction.method = TextureFunction::GRAD; - textureFunction.offset = true; - } - else if (name == "textureProjGrad" || name == "texture2DProjGradEXT" || - name == "textureCubeGradEXT") - { - textureFunction.method = TextureFunction::GRAD; - textureFunction.proj = true; - } - else if (name == "textureProjGradOffset") - { - textureFunction.method = TextureFunction::GRAD; - textureFunction.proj = true; - textureFunction.offset = true; - } - else - UNREACHABLE(); - - if (textureFunction.method == - TextureFunction::IMPLICIT) // Could require lod 0 or have a bias argument - { - size_t mandatoryArgumentCount = 2; // All functions have sampler and coordinate arguments - - if (textureFunction.offset) - { - mandatoryArgumentCount++; - } - - bool bias = (argumentCount > mandatoryArgumentCount); // Bias argument is optional - - if (lod0 || shaderType == GL_VERTEX_SHADER) - { - if (bias) - { - textureFunction.method = TextureFunction::LOD0BIAS; - } - else - { - textureFunction.method = TextureFunction::LOD0; - } - } - else if (bias) - { - textureFunction.method = TextureFunction::BIAS; - } - } - - mUsesTexture.insert(textureFunction); - return textureFunction.name(); -} - -void TextureFunctionHLSL::textureFunctionHeader(TInfoSinkBase &out, - const ShShaderOutput outputType, - bool getDimensionsIgnoresBaseLevel) -{ - for (const TextureFunction &textureFunction : mUsesTexture) - { - // Function header - out << textureFunction.getReturnType() << " " << textureFunction.name() << "("; - - OutputTextureFunctionArgumentList(out, textureFunction, outputType); - - out << ")\n" - "{\n"; - - // In some cases we use a variable to store the texture/sampler objects, but to work around - // a D3D11 compiler bug related to discard inside a loop that is conditional on texture - // sampling we need to call the function directly on references to the texture and sampler - // arrays. The bug was found using dEQP-GLES3.functional.shaders.discard*loop_texture* - // tests. - TString textureReference; - TString samplerReference; - GetTextureReference(out, textureFunction, outputType, &textureReference, &samplerReference); - - if (textureFunction.method == TextureFunction::SIZE) - { - OutputTextureSizeFunctionBody(out, textureFunction, textureReference, - getDimensionsIgnoresBaseLevel); - } - else - { - TString texCoordX("t.x"); - TString texCoordY("t.y"); - TString texCoordZ("t.z"); - ProjectTextureCoordinates(textureFunction, &texCoordX, &texCoordY, &texCoordZ); - OutputIntegerTextureSampleFunctionComputations(out, textureFunction, outputType, - textureReference, &texCoordX, &texCoordY, - &texCoordZ); - OutputTextureSampleFunctionReturnStatement(out, textureFunction, outputType, - textureReference, samplerReference, - texCoordX, texCoordY, texCoordZ); - } - - out << "}\n" - "\n"; - } -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/TextureFunctionHLSL.h b/src/3rdparty/angle/src/compiler/translator/TextureFunctionHLSL.h deleted file mode 100644 index 68bf8c0898..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/TextureFunctionHLSL.h +++ /dev/null @@ -1,76 +0,0 @@ -// -// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// TextureFunctionHLSL: Class for writing implementations of ESSL texture functions into HLSL -// output. Some of the implementations are straightforward and just call the HLSL equivalent of the -// ESSL texture function, others do more work to emulate ESSL texture sampling or size query -// behavior. -// - -#ifndef COMPILER_TRANSLATOR_TEXTUREFUNCTIONHLSL_H_ -#define COMPILER_TRANSLATOR_TEXTUREFUNCTIONHLSL_H_ - -#include - -#include "compiler/translator/BaseTypes.h" -#include "compiler/translator/Common.h" -#include "compiler/translator/InfoSink.h" -#include "GLSLANG/ShaderLang.h" - -namespace sh -{ - -class TextureFunctionHLSL final : angle::NonCopyable -{ - public: - struct TextureFunction - { - // See ESSL 3.00.6 section 8.8 for reference about what the different methods below do. - enum Method - { - IMPLICIT, // Mipmap LOD determined implicitly (standard lookup) - BIAS, - LOD, - LOD0, - LOD0BIAS, - SIZE, // textureSize() - FETCH, - GRAD - }; - - TString name() const; - - bool operator<(const TextureFunction &rhs) const; - - const char *getReturnType() const; - - TBasicType sampler; - int coords; - bool proj; - bool offset; - Method method; - }; - - // Returns the name of the texture function implementation to call. - // The name that's passed in is the name of the GLSL texture function that it should implement. - TString useTextureFunction(const TString &name, - TBasicType samplerType, - int coords, - size_t argumentCount, - bool lod0, - sh::GLenum shaderType); - - void textureFunctionHeader(TInfoSinkBase &out, - const ShShaderOutput outputType, - bool getDimensionsIgnoresBaseLevel); - - private: - typedef std::set TextureFunctionSet; - TextureFunctionSet mUsesTexture; -}; - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_TEXTUREFUNCTIONHLSL_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/TranslatorESSL.cpp b/src/3rdparty/angle/src/compiler/translator/TranslatorESSL.cpp deleted file mode 100644 index 23c967f944..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/TranslatorESSL.cpp +++ /dev/null @@ -1,184 +0,0 @@ -// -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/translator/TranslatorESSL.h" - -#include "compiler/translator/BuiltInFunctionEmulatorGLSL.h" -#include "compiler/translator/EmulatePrecision.h" -#include "compiler/translator/RecordConstantPrecision.h" -#include "compiler/translator/OutputESSL.h" -#include "angle_gl.h" - -namespace sh -{ - -TranslatorESSL::TranslatorESSL(sh::GLenum type, ShShaderSpec spec) - : TCompiler(type, spec, SH_ESSL_OUTPUT) -{ -} - -void TranslatorESSL::initBuiltInFunctionEmulator(BuiltInFunctionEmulator *emu, - ShCompileOptions compileOptions) -{ - if (compileOptions & SH_EMULATE_ATAN2_FLOAT_FUNCTION) - { - InitBuiltInAtanFunctionEmulatorForGLSLWorkarounds(emu); - } -} - -void TranslatorESSL::translate(TIntermBlock *root, - ShCompileOptions compileOptions, - PerformanceDiagnostics * /*perfDiagnostics*/) -{ - TInfoSinkBase &sink = getInfoSink().obj; - - int shaderVer = getShaderVersion(); - if (shaderVer > 100) - { - sink << "#version " << shaderVer << " es\n"; - } - - // Write built-in extension behaviors. - writeExtensionBehavior(compileOptions); - - // Write pragmas after extensions because some drivers consider pragmas - // like non-preprocessor tokens. - writePragma(compileOptions); - - bool precisionEmulation = - getResources().WEBGL_debug_shader_precision && getPragma().debugShaderPrecision; - - if (precisionEmulation) - { - EmulatePrecision emulatePrecision(&getSymbolTable(), shaderVer); - root->traverse(&emulatePrecision); - emulatePrecision.updateTree(); - emulatePrecision.writeEmulationHelpers(sink, shaderVer, SH_ESSL_OUTPUT); - } - - RecordConstantPrecision(root, &getSymbolTable()); - - // Write emulated built-in functions if needed. - if (!getBuiltInFunctionEmulator().isOutputEmpty()) - { - sink << "// BEGIN: Generated code for built-in function emulation\n\n"; - if (getShaderType() == GL_FRAGMENT_SHADER) - { - sink << "#if defined(GL_FRAGMENT_PRECISION_HIGH)\n" - << "#define emu_precision highp\n" - << "#else\n" - << "#define emu_precision mediump\n" - << "#endif\n\n"; - } - else - { - sink << "#define emu_precision highp\n"; - } - - getBuiltInFunctionEmulator().outputEmulatedFunctions(sink); - sink << "// END: Generated code for built-in function emulation\n\n"; - } - - // Write array bounds clamping emulation if needed. - getArrayBoundsClamper().OutputClampingFunctionDefinition(sink); - - if (getShaderType() == GL_COMPUTE_SHADER && isComputeShaderLocalSizeDeclared()) - { - const sh::WorkGroupSize &localSize = getComputeShaderLocalSize(); - sink << "layout (local_size_x=" << localSize[0] << ", local_size_y=" << localSize[1] - << ", local_size_z=" << localSize[2] << ") in;\n"; - } - - if (getShaderType() == GL_GEOMETRY_SHADER_OES) - { - WriteGeometryShaderLayoutQualifiers( - sink, getGeometryShaderInputPrimitiveType(), getGeometryShaderInvocations(), - getGeometryShaderOutputPrimitiveType(), getGeometryShaderMaxVertices()); - } - - // Write translated shader. - TOutputESSL outputESSL(sink, getArrayIndexClampingStrategy(), getHashFunction(), getNameMap(), - &getSymbolTable(), getShaderType(), shaderVer, precisionEmulation, - compileOptions); - - if (compileOptions & SH_TRANSLATE_VIEWID_OVR_TO_UNIFORM) - { - TName uniformName(TString("ViewID_OVR")); - uniformName.setInternal(true); - sink << "highp uniform int " << outputESSL.hashName(uniformName) << ";\n"; - } - - root->traverse(&outputESSL); -} - -bool TranslatorESSL::shouldFlattenPragmaStdglInvariantAll() -{ - // Not necessary when translating to ESSL. - return false; -} - -void TranslatorESSL::writeExtensionBehavior(ShCompileOptions compileOptions) -{ - TInfoSinkBase &sink = getInfoSink().obj; - const TExtensionBehavior &extBehavior = getExtensionBehavior(); - const bool isMultiviewExtEmulated = - (compileOptions & - (SH_TRANSLATE_VIEWID_OVR_TO_UNIFORM | SH_INITIALIZE_BUILTINS_FOR_INSTANCED_MULTIVIEW | - SH_SELECT_VIEW_IN_NV_GLSL_VERTEX_SHADER)) != 0u; - for (TExtensionBehavior::const_iterator iter = extBehavior.begin(); iter != extBehavior.end(); - ++iter) - { - if (iter->second != EBhUndefined) - { - const bool isMultiview = (iter->first == TExtension::OVR_multiview); - if (getResources().NV_shader_framebuffer_fetch && - iter->first == TExtension::EXT_shader_framebuffer_fetch) - { - sink << "#extension GL_NV_shader_framebuffer_fetch : " - << GetBehaviorString(iter->second) << "\n"; - } - else if (getResources().NV_draw_buffers && iter->first == TExtension::EXT_draw_buffers) - { - sink << "#extension GL_NV_draw_buffers : " << GetBehaviorString(iter->second) - << "\n"; - } - else if (isMultiview && isMultiviewExtEmulated) - { - if (getShaderType() == GL_VERTEX_SHADER && - (compileOptions & SH_SELECT_VIEW_IN_NV_GLSL_VERTEX_SHADER) != 0u) - { - // Emit the NV_viewport_array2 extension in a vertex shader if the - // SH_SELECT_VIEW_IN_NV_GLSL_VERTEX_SHADER option is set and the - // OVR_multiview(2) extension is requested. - sink << "#extension GL_NV_viewport_array2 : require\n"; - } - } - else if (iter->first == TExtension::OES_geometry_shader) - { - sink << "#ifdef GL_OES_geometry_shader\n" - << "#extension GL_OES_geometry_shader : " << GetBehaviorString(iter->second) - << "\n" - << "#elif defined GL_EXT_geometry_shader\n" - << "#extension GL_EXT_geometry_shader : " << GetBehaviorString(iter->second) - << "\n"; - if (iter->second == EBhRequire) - { - sink << "#else\n" - << "#error \"No geometry shader extensions available.\" // Only generate " - "this if the extension is \"required\"\n"; - } - sink << "#endif\n"; - } - else - { - sink << "#extension " << GetExtensionNameString(iter->first) << " : " - << GetBehaviorString(iter->second) << "\n"; - } - } - } -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/TranslatorESSL.h b/src/3rdparty/angle/src/compiler/translator/TranslatorESSL.h deleted file mode 100644 index 24dc738513..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/TranslatorESSL.h +++ /dev/null @@ -1,35 +0,0 @@ -// -// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_TRANSLATOR_TRANSLATORESSL_H_ -#define COMPILER_TRANSLATOR_TRANSLATORESSL_H_ - -#include "compiler/translator/Compiler.h" - -namespace sh -{ - -class TranslatorESSL : public TCompiler -{ - public: - TranslatorESSL(sh::GLenum type, ShShaderSpec spec); - - protected: - void initBuiltInFunctionEmulator(BuiltInFunctionEmulator *emu, - ShCompileOptions compileOptions) override; - - void translate(TIntermBlock *root, - ShCompileOptions compileOptions, - PerformanceDiagnostics *perfDiagnostics) override; - bool shouldFlattenPragmaStdglInvariantAll() override; - - private: - void writeExtensionBehavior(ShCompileOptions compileOptions); -}; - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_TRANSLATORESSL_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.cpp b/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.cpp deleted file mode 100644 index a14e69e5d5..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.cpp +++ /dev/null @@ -1,339 +0,0 @@ -// -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/translator/TranslatorGLSL.h" - -#include "angle_gl.h" -#include "compiler/translator/BuiltInFunctionEmulatorGLSL.h" -#include "compiler/translator/EmulatePrecision.h" -#include "compiler/translator/ExtensionGLSL.h" -#include "compiler/translator/OutputGLSL.h" -#include "compiler/translator/RewriteTexelFetchOffset.h" -#include "compiler/translator/RewriteUnaryMinusOperatorFloat.h" -#include "compiler/translator/VersionGLSL.h" - -namespace sh -{ - -TranslatorGLSL::TranslatorGLSL(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output) - : TCompiler(type, spec, output) -{ -} - -void TranslatorGLSL::initBuiltInFunctionEmulator(BuiltInFunctionEmulator *emu, - ShCompileOptions compileOptions) -{ - if (compileOptions & SH_EMULATE_ABS_INT_FUNCTION) - { - InitBuiltInAbsFunctionEmulatorForGLSLWorkarounds(emu, getShaderType()); - } - - if (compileOptions & SH_EMULATE_ISNAN_FLOAT_FUNCTION) - { - InitBuiltInIsnanFunctionEmulatorForGLSLWorkarounds(emu, getShaderVersion()); - } - - if (compileOptions & SH_EMULATE_ATAN2_FLOAT_FUNCTION) - { - InitBuiltInAtanFunctionEmulatorForGLSLWorkarounds(emu); - } - - int targetGLSLVersion = ShaderOutputTypeToGLSLVersion(getOutputType()); - InitBuiltInFunctionEmulatorForGLSLMissingFunctions(emu, getShaderType(), targetGLSLVersion); -} - -void TranslatorGLSL::translate(TIntermBlock *root, - ShCompileOptions compileOptions, - PerformanceDiagnostics * /*perfDiagnostics*/) -{ - TInfoSinkBase &sink = getInfoSink().obj; - - // Write GLSL version. - writeVersion(root); - - // Write extension behaviour as needed - writeExtensionBehavior(root, compileOptions); - - // Write pragmas after extensions because some drivers consider pragmas - // like non-preprocessor tokens. - writePragma(compileOptions); - - // If flattening the global invariant pragma, write invariant declarations for built-in - // variables. It should be harmless to do this twice in the case that the shader also explicitly - // did this. However, it's important to emit invariant qualifiers only for those built-in - // variables that are actually used, to avoid affecting the behavior of the shader. - if ((compileOptions & SH_FLATTEN_PRAGMA_STDGL_INVARIANT_ALL) != 0 && - getPragma().stdgl.invariantAll && - !sh::RemoveInvariant(getShaderType(), getShaderVersion(), getOutputType(), compileOptions)) - { - ASSERT(wereVariablesCollected()); - - switch (getShaderType()) - { - case GL_VERTEX_SHADER: - sink << "invariant gl_Position;\n"; - - // gl_PointSize should be declared invariant in both ESSL 1.00 and 3.00 fragment - // shaders if it's statically referenced. - conditionallyOutputInvariantDeclaration("gl_PointSize"); - break; - case GL_FRAGMENT_SHADER: - // The preprocessor will reject this pragma if it's used in ESSL 3.00 fragment - // shaders, so we can use simple logic to determine whether to declare these - // variables invariant. - conditionallyOutputInvariantDeclaration("gl_FragCoord"); - conditionallyOutputInvariantDeclaration("gl_PointCoord"); - break; - default: - // Currently not reached, but leave this in for future expansion. - ASSERT(false); - break; - } - } - - if ((compileOptions & SH_REWRITE_TEXELFETCHOFFSET_TO_TEXELFETCH) != 0) - { - sh::RewriteTexelFetchOffset(root, getSymbolTable(), getShaderVersion()); - } - - if ((compileOptions & SH_REWRITE_FLOAT_UNARY_MINUS_OPERATOR) != 0) - { - sh::RewriteUnaryMinusOperatorFloat(root); - } - - bool precisionEmulation = - getResources().WEBGL_debug_shader_precision && getPragma().debugShaderPrecision; - - if (precisionEmulation) - { - EmulatePrecision emulatePrecision(&getSymbolTable(), getShaderVersion()); - root->traverse(&emulatePrecision); - emulatePrecision.updateTree(); - emulatePrecision.writeEmulationHelpers(sink, getShaderVersion(), getOutputType()); - } - - // Write emulated built-in functions if needed. - if (!getBuiltInFunctionEmulator().isOutputEmpty()) - { - sink << "// BEGIN: Generated code for built-in function emulation\n\n"; - sink << "#define emu_precision\n\n"; - getBuiltInFunctionEmulator().outputEmulatedFunctions(sink); - sink << "// END: Generated code for built-in function emulation\n\n"; - } - - // Write array bounds clamping emulation if needed. - getArrayBoundsClamper().OutputClampingFunctionDefinition(sink); - - // Declare gl_FragColor and glFragData as webgl_FragColor and webgl_FragData - // if it's core profile shaders and they are used. - if (getShaderType() == GL_FRAGMENT_SHADER) - { - const bool mayHaveESSL1SecondaryOutputs = - IsExtensionEnabled(getExtensionBehavior(), TExtension::EXT_blend_func_extended) && - getShaderVersion() == 100; - const bool declareGLFragmentOutputs = IsGLSL130OrNewer(getOutputType()); - - bool hasGLFragColor = false; - bool hasGLFragData = false; - bool hasGLSecondaryFragColor = false; - bool hasGLSecondaryFragData = false; - - for (const auto &outputVar : outputVariables) - { - if (declareGLFragmentOutputs) - { - if (outputVar.name == "gl_FragColor") - { - ASSERT(!hasGLFragColor); - hasGLFragColor = true; - continue; - } - else if (outputVar.name == "gl_FragData") - { - ASSERT(!hasGLFragData); - hasGLFragData = true; - continue; - } - } - if (mayHaveESSL1SecondaryOutputs) - { - if (outputVar.name == "gl_SecondaryFragColorEXT") - { - ASSERT(!hasGLSecondaryFragColor); - hasGLSecondaryFragColor = true; - continue; - } - else if (outputVar.name == "gl_SecondaryFragDataEXT") - { - ASSERT(!hasGLSecondaryFragData); - hasGLSecondaryFragData = true; - continue; - } - } - } - ASSERT(!((hasGLFragColor || hasGLSecondaryFragColor) && - (hasGLFragData || hasGLSecondaryFragData))); - if (hasGLFragColor) - { - sink << "out vec4 webgl_FragColor;\n"; - } - if (hasGLFragData) - { - sink << "out vec4 webgl_FragData[gl_MaxDrawBuffers];\n"; - } - if (hasGLSecondaryFragColor) - { - sink << "out vec4 angle_SecondaryFragColor;\n"; - } - if (hasGLSecondaryFragData) - { - sink << "out vec4 angle_SecondaryFragData[" << getResources().MaxDualSourceDrawBuffers - << "];\n"; - } - } - - if (getShaderType() == GL_COMPUTE_SHADER && isComputeShaderLocalSizeDeclared()) - { - const sh::WorkGroupSize &localSize = getComputeShaderLocalSize(); - sink << "layout (local_size_x=" << localSize[0] << ", local_size_y=" << localSize[1] - << ", local_size_z=" << localSize[2] << ") in;\n"; - } - - if (getShaderType() == GL_GEOMETRY_SHADER_OES) - { - WriteGeometryShaderLayoutQualifiers( - sink, getGeometryShaderInputPrimitiveType(), getGeometryShaderInvocations(), - getGeometryShaderOutputPrimitiveType(), getGeometryShaderMaxVertices()); - } - - // Write translated shader. - TOutputGLSL outputGLSL(sink, getArrayIndexClampingStrategy(), getHashFunction(), getNameMap(), - &getSymbolTable(), getShaderType(), getShaderVersion(), getOutputType(), - compileOptions); - - if (compileOptions & SH_TRANSLATE_VIEWID_OVR_TO_UNIFORM) - { - TName uniformName(TString("ViewID_OVR")); - uniformName.setInternal(true); - sink << "uniform int " << outputGLSL.hashName(uniformName) << ";\n"; - } - - root->traverse(&outputGLSL); -} - -bool TranslatorGLSL::shouldFlattenPragmaStdglInvariantAll() -{ - // Required when outputting to any GLSL version greater than 1.20, but since ANGLE doesn't - // translate to that version, return true for the next higher version. - return IsGLSL130OrNewer(getOutputType()); -} - -bool TranslatorGLSL::shouldCollectVariables(ShCompileOptions compileOptions) -{ - return (compileOptions & SH_FLATTEN_PRAGMA_STDGL_INVARIANT_ALL) || - TCompiler::shouldCollectVariables(compileOptions); -} - -void TranslatorGLSL::writeVersion(TIntermNode *root) -{ - TVersionGLSL versionGLSL(getShaderType(), getPragma(), getOutputType()); - root->traverse(&versionGLSL); - int version = versionGLSL.getVersion(); - // We need to write version directive only if it is greater than 110. - // If there is no version directive in the shader, 110 is implied. - if (version > 110) - { - TInfoSinkBase &sink = getInfoSink().obj; - sink << "#version " << version << "\n"; - } -} - -void TranslatorGLSL::writeExtensionBehavior(TIntermNode *root, ShCompileOptions compileOptions) -{ - TInfoSinkBase &sink = getInfoSink().obj; - const TExtensionBehavior &extBehavior = getExtensionBehavior(); - for (const auto &iter : extBehavior) - { - if (iter.second == EBhUndefined) - { - continue; - } - - if (getOutputType() == SH_GLSL_COMPATIBILITY_OUTPUT) - { - // For GLSL output, we don't need to emit most extensions explicitly, - // but some we need to translate in GL compatibility profile. - if (iter.first == TExtension::EXT_shader_texture_lod) - { - sink << "#extension GL_ARB_shader_texture_lod : " << GetBehaviorString(iter.second) - << "\n"; - } - - if (iter.first == TExtension::EXT_draw_buffers) - { - sink << "#extension GL_ARB_draw_buffers : " << GetBehaviorString(iter.second) - << "\n"; - } - - if (iter.first == TExtension::OES_geometry_shader) - { - sink << "#extension GL_ARB_geometry_shader4 : " << GetBehaviorString(iter.second) - << "\n"; - } - } - - const bool isMultiview = (iter.first == TExtension::OVR_multiview); - if (isMultiview && getShaderType() == GL_VERTEX_SHADER && - (compileOptions & SH_SELECT_VIEW_IN_NV_GLSL_VERTEX_SHADER) != 0u) - { - // Emit the NV_viewport_array2 extension in a vertex shader if the - // SH_SELECT_VIEW_IN_NV_GLSL_VERTEX_SHADER option is set and the OVR_multiview(2) - // extension is requested. - sink << "#extension GL_NV_viewport_array2 : require\n"; - } - } - - // GLSL ES 3 explicit location qualifiers need to use an extension before GLSL 330 - if (getShaderVersion() >= 300 && getOutputType() < SH_GLSL_330_CORE_OUTPUT && - getShaderType() != GL_COMPUTE_SHADER) - { - sink << "#extension GL_ARB_explicit_attrib_location : require\n"; - } - - // Need to enable gpu_shader5 to have index constant sampler array indexing - if (getOutputType() != SH_ESSL_OUTPUT && getOutputType() < SH_GLSL_400_CORE_OUTPUT && - getShaderVersion() == 100) - { - // Don't use "require" on to avoid breaking WebGL 1 on drivers that silently - // support index constant sampler array indexing, but don't have the extension or - // on drivers that don't have the extension at all as it would break WebGL 1 for - // some users. - sink << "#extension GL_ARB_gpu_shader5 : enable\n"; - } - - TExtensionGLSL extensionGLSL(getOutputType()); - root->traverse(&extensionGLSL); - - for (const auto &ext : extensionGLSL.getEnabledExtensions()) - { - sink << "#extension " << ext << " : enable\n"; - } - for (const auto &ext : extensionGLSL.getRequiredExtensions()) - { - sink << "#extension " << ext << " : require\n"; - } -} - -void TranslatorGLSL::conditionallyOutputInvariantDeclaration(const char *builtinVaryingName) -{ - if (isVaryingDefined(builtinVaryingName)) - { - TInfoSinkBase &sink = getInfoSink().obj; - sink << "invariant " << builtinVaryingName << ";\n"; - } -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.h b/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.h deleted file mode 100644 index 982d0e5ddc..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.h +++ /dev/null @@ -1,38 +0,0 @@ -// -// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_TRANSLATOR_TRANSLATORGLSL_H_ -#define COMPILER_TRANSLATOR_TRANSLATORGLSL_H_ - -#include "compiler/translator/Compiler.h" - -namespace sh -{ - -class TranslatorGLSL : public TCompiler -{ - public: - TranslatorGLSL(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output); - - protected: - void initBuiltInFunctionEmulator(BuiltInFunctionEmulator *emu, - ShCompileOptions compileOptions) override; - - void translate(TIntermBlock *root, - ShCompileOptions compileOptions, - PerformanceDiagnostics *perfDiagnostics) override; - bool shouldFlattenPragmaStdglInvariantAll() override; - bool shouldCollectVariables(ShCompileOptions compileOptions) override; - - private: - void writeVersion(TIntermNode *root); - void writeExtensionBehavior(TIntermNode *root, ShCompileOptions compileOptions); - void conditionallyOutputInvariantDeclaration(const char *builtinVaryingName); -}; - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_TRANSLATORGLSL_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.cpp b/src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.cpp deleted file mode 100644 index 091a649cfc..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.cpp +++ /dev/null @@ -1,161 +0,0 @@ -// -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/translator/TranslatorHLSL.h" - -#include "compiler/translator/AddDefaultReturnStatements.h" -#include "compiler/translator/ArrayReturnValueToOutParameter.h" -#include "compiler/translator/BreakVariableAliasingInInnerLoops.h" -#include "compiler/translator/EmulatePrecision.h" -#include "compiler/translator/ExpandIntegerPowExpressions.h" -#include "compiler/translator/IntermNodePatternMatcher.h" -#include "compiler/translator/OutputHLSL.h" -#include "compiler/translator/RemoveDynamicIndexing.h" -#include "compiler/translator/RemoveNoOpCasesFromEndOfSwitchStatements.h" -#include "compiler/translator/RewriteElseBlocks.h" -#include "compiler/translator/RewriteTexelFetchOffset.h" -#include "compiler/translator/RewriteUnaryMinusOperatorInt.h" -#include "compiler/translator/SeparateArrayInitialization.h" -#include "compiler/translator/SeparateDeclarations.h" -#include "compiler/translator/SeparateExpressionsReturningArrays.h" -#include "compiler/translator/SimplifyLoopConditions.h" -#include "compiler/translator/SplitSequenceOperator.h" -#include "compiler/translator/UnfoldShortCircuitToIf.h" -#include "compiler/translator/WrapSwitchStatementsInBlocks.h" - -namespace sh -{ - -TranslatorHLSL::TranslatorHLSL(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output) - : TCompiler(type, spec, output) -{ -} - -void TranslatorHLSL::translate(TIntermBlock *root, - ShCompileOptions compileOptions, - PerformanceDiagnostics *perfDiagnostics) -{ - const ShBuiltInResources &resources = getResources(); - int numRenderTargets = resources.EXT_draw_buffers ? resources.MaxDrawBuffers : 1; - - sh::AddDefaultReturnStatements(root); - - // Note that SimplifyLoopConditions needs to be run before any other AST transformations that - // may need to generate new statements from loop conditions or loop expressions. - // Note that SeparateDeclarations has already been run in TCompiler::compileTreeImpl(). - SimplifyLoopConditions(root, - IntermNodePatternMatcher::kExpressionReturningArray | - IntermNodePatternMatcher::kUnfoldedShortCircuitExpression | - IntermNodePatternMatcher::kDynamicIndexingOfVectorOrMatrixInLValue, - &getSymbolTable(), getShaderVersion()); - - SplitSequenceOperator(root, - IntermNodePatternMatcher::kExpressionReturningArray | - IntermNodePatternMatcher::kUnfoldedShortCircuitExpression | - IntermNodePatternMatcher::kDynamicIndexingOfVectorOrMatrixInLValue, - &getSymbolTable(), getShaderVersion()); - - // Note that SeparateDeclarations needs to be run before UnfoldShortCircuitToIf. - UnfoldShortCircuitToIf(root, &getSymbolTable()); - - SeparateExpressionsReturningArrays(root, &getSymbolTable()); - - // Note that SeparateDeclarations needs to be run before SeparateArrayInitialization. - SeparateArrayInitialization(root); - - // HLSL doesn't support arrays as return values, we'll need to make functions that have an array - // as a return value to use an out parameter to transfer the array data instead. - ArrayReturnValueToOutParameter(root, &getSymbolTable()); - - if (!shouldRunLoopAndIndexingValidation(compileOptions)) - { - // HLSL doesn't support dynamic indexing of vectors and matrices. - RemoveDynamicIndexing(root, &getSymbolTable(), getShaderVersion(), perfDiagnostics); - } - - // Work around D3D9 bug that would manifest in vertex shaders with selection blocks which - // use a vertex attribute as a condition, and some related computation in the else block. - if (getOutputType() == SH_HLSL_3_0_OUTPUT && getShaderType() == GL_VERTEX_SHADER) - { - sh::RewriteElseBlocks(root, &getSymbolTable()); - } - - // Work around an HLSL compiler frontend aliasing optimization bug. - // TODO(cwallez) The date is 2016-08-25, Microsoft said the bug would be fixed - // in the next release of d3dcompiler.dll, it would be nice to detect the DLL - // version and only apply the workaround if it is too old. - sh::BreakVariableAliasingInInnerLoops(root); - - // WrapSwitchStatementsInBlocks should be called after any AST transformations that might - // introduce variable declarations inside the main scope of any switch statement. - if (WrapSwitchStatementsInBlocks(root)) - { - // The WrapSwitchStatementsInBlocks step might introduce new no-op cases to the end of - // switch statements, so make sure to clean up the AST. - RemoveNoOpCasesFromEndOfSwitchStatements(root, &getSymbolTable()); - } - - bool precisionEmulation = - getResources().WEBGL_debug_shader_precision && getPragma().debugShaderPrecision; - - if (precisionEmulation) - { - EmulatePrecision emulatePrecision(&getSymbolTable(), getShaderVersion()); - root->traverse(&emulatePrecision); - emulatePrecision.updateTree(); - emulatePrecision.writeEmulationHelpers(getInfoSink().obj, getShaderVersion(), - getOutputType()); - } - - if ((compileOptions & SH_EXPAND_SELECT_HLSL_INTEGER_POW_EXPRESSIONS) != 0) - { - sh::ExpandIntegerPowExpressions(root, &getSymbolTable()); - } - - if ((compileOptions & SH_REWRITE_TEXELFETCHOFFSET_TO_TEXELFETCH) != 0) - { - sh::RewriteTexelFetchOffset(root, getSymbolTable(), getShaderVersion()); - } - - if (((compileOptions & SH_REWRITE_INTEGER_UNARY_MINUS_OPERATOR) != 0) && - getShaderType() == GL_VERTEX_SHADER) - { - sh::RewriteUnaryMinusOperatorInt(root); - } - - sh::OutputHLSL outputHLSL(getShaderType(), getShaderVersion(), getExtensionBehavior(), - getSourcePath(), getOutputType(), numRenderTargets, getUniforms(), - compileOptions, &getSymbolTable(), perfDiagnostics); - - outputHLSL.output(root, getInfoSink().obj); - - mUniformBlockRegisterMap = outputHLSL.getUniformBlockRegisterMap(); - mUniformRegisterMap = outputHLSL.getUniformRegisterMap(); -} - -bool TranslatorHLSL::shouldFlattenPragmaStdglInvariantAll() -{ - // Not necessary when translating to HLSL. - return false; -} - -bool TranslatorHLSL::hasUniformBlock(const std::string &uniformBlockName) const -{ - return (mUniformBlockRegisterMap.count(uniformBlockName) > 0); -} - -unsigned int TranslatorHLSL::getUniformBlockRegister(const std::string &uniformBlockName) const -{ - ASSERT(hasUniformBlock(uniformBlockName)); - return mUniformBlockRegisterMap.find(uniformBlockName)->second; -} - -const std::map *TranslatorHLSL::getUniformRegisterMap() const -{ - return &mUniformRegisterMap; -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.h b/src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.h deleted file mode 100644 index d7005a603c..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.h +++ /dev/null @@ -1,41 +0,0 @@ -// -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_TRANSLATOR_TRANSLATORHLSL_H_ -#define COMPILER_TRANSLATOR_TRANSLATORHLSL_H_ - -#include "compiler/translator/Compiler.h" - -namespace sh -{ - -class TranslatorHLSL : public TCompiler -{ - public: - TranslatorHLSL(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output); - TranslatorHLSL *getAsTranslatorHLSL() override { return this; } - - bool hasUniformBlock(const std::string &interfaceBlockName) const; - unsigned int getUniformBlockRegister(const std::string &interfaceBlockName) const; - - const std::map *getUniformRegisterMap() const; - - protected: - void translate(TIntermBlock *root, - ShCompileOptions compileOptions, - PerformanceDiagnostics *perfDiagnostics) override; - bool shouldFlattenPragmaStdglInvariantAll() override; - - // collectVariables needs to be run always so registers can be assigned. - bool shouldCollectVariables(ShCompileOptions compileOptions) override { return true; } - - std::map mUniformBlockRegisterMap; - std::map mUniformRegisterMap; -}; - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_TRANSLATORHLSL_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/TranslatorVulkan.cpp b/src/3rdparty/angle/src/compiler/translator/TranslatorVulkan.cpp deleted file mode 100644 index 0fe2a21f90..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/TranslatorVulkan.cpp +++ /dev/null @@ -1,173 +0,0 @@ -// -// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// TranslatorVulkan: -// A GLSL-based translator that outputs shaders that fit GL_KHR_vulkan_glsl. -// The shaders are then fed into glslang to spit out SPIR-V (libANGLE-side). -// See: https://www.khronos.org/registry/vulkan/specs/misc/GL_KHR_vulkan_glsl.txt -// - -#include "compiler/translator/TranslatorVulkan.h" - -#include "angle_gl.h" -#include "common/utilities.h" -#include "compiler/translator/OutputVulkanGLSL.h" -#include "compiler/translator/util.h" - -namespace sh -{ - -class DeclareDefaultUniformsTraverser : public TIntermTraverser -{ - public: - DeclareDefaultUniformsTraverser(TInfoSinkBase *sink, - ShHashFunction64 hashFunction, - NameMap *nameMap) - : TIntermTraverser(true, true, true), - mSink(sink), - mHashFunction(hashFunction), - mNameMap(nameMap), - mInDefaultUniform(false) - { - } - - bool visitDeclaration(Visit visit, TIntermDeclaration *node) override - { - const TIntermSequence &sequence = *(node->getSequence()); - - // TODO(jmadill): Compound declarations. - ASSERT(sequence.size() == 1); - - TIntermTyped *variable = sequence.front()->getAsTyped(); - const TType &type = variable->getType(); - bool isUniform = (type.getQualifier() == EvqUniform) && !IsOpaqueType(type.getBasicType()); - - if (visit == PreVisit) - { - if (isUniform) - { - (*mSink) << " " << GetTypeName(type, mHashFunction, mNameMap) << " "; - mInDefaultUniform = true; - } - } - else if (visit == InVisit) - { - mInDefaultUniform = isUniform; - } - else if (visit == PostVisit) - { - if (isUniform) - { - (*mSink) << ";\n"; - - // Remove the uniform declaration from the tree so it isn't parsed again. - TIntermSequence emptyReplacement; - mMultiReplacements.push_back(NodeReplaceWithMultipleEntry( - getParentNode()->getAsBlock(), node, emptyReplacement)); - } - - mInDefaultUniform = false; - } - return true; - } - - void visitSymbol(TIntermSymbol *symbol) override - { - if (mInDefaultUniform) - { - const TName &name = symbol->getName(); - ASSERT(name.getString().substr(0, 3) != "gl_"); - (*mSink) << HashName(name, mHashFunction, mNameMap); - } - } - - private: - TInfoSinkBase *mSink; - ShHashFunction64 mHashFunction; - NameMap *mNameMap; - bool mInDefaultUniform; -}; - -TranslatorVulkan::TranslatorVulkan(sh::GLenum type, ShShaderSpec spec) - : TCompiler(type, spec, SH_GLSL_450_CORE_OUTPUT) -{ -} - -void TranslatorVulkan::translate(TIntermBlock *root, - ShCompileOptions compileOptions, - PerformanceDiagnostics * /*perfDiagnostics*/) -{ - TInfoSinkBase &sink = getInfoSink().obj; - - sink << "#version 450 core\n"; - - // Write out default uniforms into a uniform block assigned to a specific set/binding. - int defaultUniformCount = 0; - for (const auto &uniform : getUniforms()) - { - if (!uniform.isBuiltIn() && uniform.staticUse && !gl::IsOpaqueType(uniform.type)) - { - ++defaultUniformCount; - } - } - - if (defaultUniformCount > 0) - { - sink << "\nlayout(@@ DEFAULT-UNIFORMS-SET-BINDING @@) uniform defaultUniforms\n{\n"; - - DeclareDefaultUniformsTraverser defaultTraverser(&sink, getHashFunction(), &getNameMap()); - root->traverse(&defaultTraverser); - defaultTraverser.updateTree(); - - sink << "};\n"; - } - - // Declare gl_FragColor and glFragData as webgl_FragColor and webgl_FragData - // if it's core profile shaders and they are used. - if (getShaderType() == GL_FRAGMENT_SHADER) - { - bool hasGLFragColor = false; - bool hasGLFragData = false; - - for (const auto &outputVar : outputVariables) - { - if (outputVar.name == "gl_FragColor") - { - ASSERT(!hasGLFragColor); - hasGLFragColor = true; - continue; - } - else if (outputVar.name == "gl_FragData") - { - ASSERT(!hasGLFragData); - hasGLFragData = true; - continue; - } - } - ASSERT(!(hasGLFragColor && hasGLFragData)); - if (hasGLFragColor) - { - sink << "layout(location = 0) out vec4 webgl_FragColor;\n"; - } - if (hasGLFragData) - { - sink << "layout(location = 0) out vec4 webgl_FragData[gl_MaxDrawBuffers];\n"; - } - } - - // Write translated shader. - TOutputVulkanGLSL outputGLSL(sink, getArrayIndexClampingStrategy(), getHashFunction(), - getNameMap(), &getSymbolTable(), getShaderType(), - getShaderVersion(), getOutputType(), compileOptions); - root->traverse(&outputGLSL); -} - -bool TranslatorVulkan::shouldFlattenPragmaStdglInvariantAll() -{ - // Not necessary. - return false; -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/TranslatorVulkan.h b/src/3rdparty/angle/src/compiler/translator/TranslatorVulkan.h deleted file mode 100644 index ef67b15ae1..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/TranslatorVulkan.h +++ /dev/null @@ -1,34 +0,0 @@ -// -// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// TranslatorVulkan: -// A GLSL-based translator that outputs shaders that fit GL_KHR_vulkan_glsl. -// The shaders are then fed into glslang to spit out SPIR-V (libANGLE-side). -// See: https://www.khronos.org/registry/vulkan/specs/misc/GL_KHR_vulkan_glsl.txt -// - -#ifndef COMPILER_TRANSLATOR_TRANSLATORVULKAN_H_ -#define COMPILER_TRANSLATOR_TRANSLATORVULKAN_H_ - -#include "compiler/translator/Compiler.h" - -namespace sh -{ - -class TranslatorVulkan : public TCompiler -{ - public: - TranslatorVulkan(sh::GLenum type, ShShaderSpec spec); - - protected: - void translate(TIntermBlock *root, - ShCompileOptions compileOptions, - PerformanceDiagnostics *perfDiagnostics) override; - bool shouldFlattenPragmaStdglInvariantAll() override; -}; - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_TRANSLATORVULKAN_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/Types.cpp b/src/3rdparty/angle/src/compiler/translator/Types.cpp deleted file mode 100644 index 530ffe3aeb..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/Types.cpp +++ /dev/null @@ -1,1072 +0,0 @@ -// -// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#if defined(_MSC_VER) -#pragma warning(disable : 4718) -#endif - -#include "compiler/translator/Types.h" -#include "compiler/translator/InfoSink.h" -#include "compiler/translator/IntermNode.h" -#include "compiler/translator/SymbolTable.h" - -#include -#include - -namespace sh -{ - -const char *getBasicString(TBasicType t) -{ - switch (t) - { - case EbtVoid: - return "void"; - case EbtFloat: - return "float"; - case EbtInt: - return "int"; - case EbtUInt: - return "uint"; - case EbtBool: - return "bool"; - case EbtYuvCscStandardEXT: - return "yuvCscStandardEXT"; - case EbtSampler2D: - return "sampler2D"; - case EbtSampler3D: - return "sampler3D"; - case EbtSamplerCube: - return "samplerCube"; - case EbtSamplerExternalOES: - return "samplerExternalOES"; - case EbtSamplerExternal2DY2YEXT: - return "__samplerExternal2DY2YEXT"; - case EbtSampler2DRect: - return "sampler2DRect"; - case EbtSampler2DArray: - return "sampler2DArray"; - case EbtSampler2DMS: - return "sampler2DMS"; - case EbtISampler2D: - return "isampler2D"; - case EbtISampler3D: - return "isampler3D"; - case EbtISamplerCube: - return "isamplerCube"; - case EbtISampler2DArray: - return "isampler2DArray"; - case EbtISampler2DMS: - return "isampler2DMS"; - case EbtUSampler2D: - return "usampler2D"; - case EbtUSampler3D: - return "usampler3D"; - case EbtUSamplerCube: - return "usamplerCube"; - case EbtUSampler2DArray: - return "usampler2DArray"; - case EbtUSampler2DMS: - return "usampler2DMS"; - case EbtSampler2DShadow: - return "sampler2DShadow"; - case EbtSamplerCubeShadow: - return "samplerCubeShadow"; - case EbtSampler2DArrayShadow: - return "sampler2DArrayShadow"; - case EbtStruct: - return "structure"; - case EbtInterfaceBlock: - return "interface block"; - case EbtImage2D: - return "image2D"; - case EbtIImage2D: - return "iimage2D"; - case EbtUImage2D: - return "uimage2D"; - case EbtImage3D: - return "image3D"; - case EbtIImage3D: - return "iimage3D"; - case EbtUImage3D: - return "uimage3D"; - case EbtImage2DArray: - return "image2DArray"; - case EbtIImage2DArray: - return "iimage2DArray"; - case EbtUImage2DArray: - return "uimage2DArray"; - case EbtImageCube: - return "imageCube"; - case EbtIImageCube: - return "iimageCube"; - case EbtUImageCube: - return "uimageCube"; - case EbtAtomicCounter: - return "atomic_uint"; - default: - UNREACHABLE(); - return "unknown type"; - } -} - -// TType implementation. -TType::TType() - : type(EbtVoid), - precision(EbpUndefined), - qualifier(EvqGlobal), - invariant(false), - memoryQualifier(TMemoryQualifier::Create()), - layoutQualifier(TLayoutQualifier::Create()), - primarySize(0), - secondarySize(0), - mArraySizes(nullptr), - mInterfaceBlock(nullptr), - mStructure(nullptr), - mIsStructSpecifier(false), - mMangledName(nullptr) -{ -} - -TType::TType(TBasicType t, unsigned char ps, unsigned char ss) - : type(t), - precision(EbpUndefined), - qualifier(EvqGlobal), - invariant(false), - memoryQualifier(TMemoryQualifier::Create()), - layoutQualifier(TLayoutQualifier::Create()), - primarySize(ps), - secondarySize(ss), - mArraySizes(nullptr), - mInterfaceBlock(nullptr), - mStructure(nullptr), - mIsStructSpecifier(false), - mMangledName(nullptr) -{ -} - -TType::TType(TBasicType t, TPrecision p, TQualifier q, unsigned char ps, unsigned char ss) - : type(t), - precision(p), - qualifier(q), - invariant(false), - memoryQualifier(TMemoryQualifier::Create()), - layoutQualifier(TLayoutQualifier::Create()), - primarySize(ps), - secondarySize(ss), - mArraySizes(nullptr), - mInterfaceBlock(nullptr), - mStructure(nullptr), - mIsStructSpecifier(false), - mMangledName(nullptr) -{ -} - -TType::TType(const TPublicType &p) - : type(p.getBasicType()), - precision(p.precision), - qualifier(p.qualifier), - invariant(p.invariant), - memoryQualifier(p.memoryQualifier), - layoutQualifier(p.layoutQualifier), - primarySize(p.getPrimarySize()), - secondarySize(p.getSecondarySize()), - mArraySizes(nullptr), - mInterfaceBlock(nullptr), - mStructure(nullptr), - mIsStructSpecifier(false), - mMangledName(nullptr) -{ - ASSERT(primarySize <= 4); - ASSERT(secondarySize <= 4); - if (p.isArray()) - { - mArraySizes = new TVector(*p.arraySizes); - } - if (p.getUserDef()) - { - mStructure = p.getUserDef(); - mIsStructSpecifier = p.isStructSpecifier(); - } -} - -TType::TType(TStructure *userDef) - : type(EbtStruct), - precision(EbpUndefined), - qualifier(EvqTemporary), - invariant(false), - memoryQualifier(TMemoryQualifier::Create()), - layoutQualifier(TLayoutQualifier::Create()), - primarySize(1), - secondarySize(1), - mArraySizes(nullptr), - mInterfaceBlock(nullptr), - mStructure(userDef), - mIsStructSpecifier(false), - mMangledName(nullptr) -{ -} - -TType::TType(TInterfaceBlock *interfaceBlockIn, - TQualifier qualifierIn, - TLayoutQualifier layoutQualifierIn) - : type(EbtInterfaceBlock), - precision(EbpUndefined), - qualifier(qualifierIn), - invariant(false), - memoryQualifier(TMemoryQualifier::Create()), - layoutQualifier(layoutQualifierIn), - primarySize(1), - secondarySize(1), - mArraySizes(nullptr), - mInterfaceBlock(interfaceBlockIn), - mStructure(0), - mIsStructSpecifier(false), - mMangledName(nullptr) -{ -} - -TType::TType(const TType &t) - : type(t.type), - precision(t.precision), - qualifier(t.qualifier), - invariant(t.invariant), - memoryQualifier(t.memoryQualifier), - layoutQualifier(t.layoutQualifier), - primarySize(t.primarySize), - secondarySize(t.secondarySize), - mArraySizes(t.mArraySizes ? new TVector(*t.mArraySizes) : nullptr), - mInterfaceBlock(t.mInterfaceBlock), - mStructure(t.mStructure), - mIsStructSpecifier(t.mIsStructSpecifier), - mMangledName(t.mMangledName) -{ -} - -TType &TType::operator=(const TType &t) -{ - type = t.type; - precision = t.precision; - qualifier = t.qualifier; - invariant = t.invariant; - memoryQualifier = t.memoryQualifier; - layoutQualifier = t.layoutQualifier; - primarySize = t.primarySize; - secondarySize = t.secondarySize; - mArraySizes = t.mArraySizes ? new TVector(*t.mArraySizes) : nullptr; - mInterfaceBlock = t.mInterfaceBlock; - mStructure = t.mStructure; - mIsStructSpecifier = t.mIsStructSpecifier; - mMangledName = t.mMangledName; - return *this; -} - -bool TType::canBeConstructed() const -{ - switch (type) - { - case EbtFloat: - case EbtInt: - case EbtUInt: - case EbtBool: - case EbtStruct: - return true; - default: - return false; - } -} - -const char *TType::getBuiltInTypeNameString() const -{ - if (isMatrix()) - { - switch (getCols()) - { - case 2: - switch (getRows()) - { - case 2: - return "mat2"; - case 3: - return "mat2x3"; - case 4: - return "mat2x4"; - default: - UNREACHABLE(); - return nullptr; - } - case 3: - switch (getRows()) - { - case 2: - return "mat3x2"; - case 3: - return "mat3"; - case 4: - return "mat3x4"; - default: - UNREACHABLE(); - return nullptr; - } - case 4: - switch (getRows()) - { - case 2: - return "mat4x2"; - case 3: - return "mat4x3"; - case 4: - return "mat4"; - default: - UNREACHABLE(); - return nullptr; - } - default: - UNREACHABLE(); - return nullptr; - } - } - if (isVector()) - { - switch (getBasicType()) - { - case EbtFloat: - switch (getNominalSize()) - { - case 2: - return "vec2"; - case 3: - return "vec3"; - case 4: - return "vec4"; - default: - UNREACHABLE(); - return nullptr; - } - case EbtInt: - switch (getNominalSize()) - { - case 2: - return "ivec2"; - case 3: - return "ivec3"; - case 4: - return "ivec4"; - default: - UNREACHABLE(); - return nullptr; - } - case EbtBool: - switch (getNominalSize()) - { - case 2: - return "bvec2"; - case 3: - return "bvec3"; - case 4: - return "bvec4"; - default: - UNREACHABLE(); - return nullptr; - } - case EbtUInt: - switch (getNominalSize()) - { - case 2: - return "uvec2"; - case 3: - return "uvec3"; - case 4: - return "uvec4"; - default: - UNREACHABLE(); - return nullptr; - } - default: - UNREACHABLE(); - return nullptr; - } - } - ASSERT(getBasicType() != EbtStruct); - ASSERT(getBasicType() != EbtInterfaceBlock); - return getBasicString(); -} - -TString TType::getCompleteString() const -{ - TStringStream stream; - - if (invariant) - stream << "invariant "; - if (qualifier != EvqTemporary && qualifier != EvqGlobal) - stream << getQualifierString() << " "; - if (precision != EbpUndefined) - stream << getPrecisionString() << " "; - if (mArraySizes) - { - for (auto arraySizeIter = mArraySizes->rbegin(); arraySizeIter != mArraySizes->rend(); - ++arraySizeIter) - { - stream << "array[" << (*arraySizeIter) << "] of "; - } - } - if (isMatrix()) - stream << getCols() << "X" << getRows() << " matrix of "; - else if (isVector()) - stream << getNominalSize() << "-component vector of "; - - stream << getBasicString(); - return stream.str(); -} - -// -// Recursively generate mangled names. -// -const char *TType::buildMangledName() const -{ - TString mangledName; - if (isMatrix()) - mangledName += 'm'; - else if (isVector()) - mangledName += 'v'; - - switch (type) - { - case EbtFloat: - mangledName += 'f'; - break; - case EbtInt: - mangledName += 'i'; - break; - case EbtUInt: - mangledName += 'u'; - break; - case EbtBool: - mangledName += 'b'; - break; - case EbtYuvCscStandardEXT: - mangledName += "ycs"; - break; - case EbtSampler2D: - mangledName += "s2"; - break; - case EbtSampler3D: - mangledName += "s3"; - break; - case EbtSamplerCube: - mangledName += "sC"; - break; - case EbtSampler2DArray: - mangledName += "s2a"; - break; - case EbtSamplerExternalOES: - mangledName += "sext"; - break; - case EbtSamplerExternal2DY2YEXT: - mangledName += "sext2y2y"; - break; - case EbtSampler2DRect: - mangledName += "s2r"; - break; - case EbtSampler2DMS: - mangledName += "s2ms"; - break; - case EbtISampler2D: - mangledName += "is2"; - break; - case EbtISampler3D: - mangledName += "is3"; - break; - case EbtISamplerCube: - mangledName += "isC"; - break; - case EbtISampler2DArray: - mangledName += "is2a"; - break; - case EbtISampler2DMS: - mangledName += "is2ms"; - break; - case EbtUSampler2D: - mangledName += "us2"; - break; - case EbtUSampler3D: - mangledName += "us3"; - break; - case EbtUSamplerCube: - mangledName += "usC"; - break; - case EbtUSampler2DArray: - mangledName += "us2a"; - break; - case EbtUSampler2DMS: - mangledName += "us2ms"; - break; - case EbtSampler2DShadow: - mangledName += "s2s"; - break; - case EbtSamplerCubeShadow: - mangledName += "sCs"; - break; - case EbtSampler2DArrayShadow: - mangledName += "s2as"; - break; - case EbtImage2D: - mangledName += "im2"; - break; - case EbtIImage2D: - mangledName += "iim2"; - break; - case EbtUImage2D: - mangledName += "uim2"; - break; - case EbtImage3D: - mangledName += "im3"; - break; - case EbtIImage3D: - mangledName += "iim3"; - break; - case EbtUImage3D: - mangledName += "uim3"; - break; - case EbtImage2DArray: - mangledName += "im2a"; - break; - case EbtIImage2DArray: - mangledName += "iim2a"; - break; - case EbtUImage2DArray: - mangledName += "uim2a"; - break; - case EbtImageCube: - mangledName += "imc"; - break; - case EbtIImageCube: - mangledName += "iimc"; - break; - case EbtUImageCube: - mangledName += "uimc"; - break; - case EbtAtomicCounter: - mangledName += "ac"; - break; - case EbtStruct: - mangledName += mStructure->mangledName(); - break; - case EbtInterfaceBlock: - mangledName += mInterfaceBlock->mangledName(); - break; - default: - // EbtVoid, EbtAddress and non types - break; - } - - if (isMatrix()) - { - mangledName += static_cast('0' + getCols()); - mangledName += static_cast('x'); - mangledName += static_cast('0' + getRows()); - } - else - { - mangledName += static_cast('0' + getNominalSize()); - } - - if (mArraySizes) - { - for (unsigned int arraySize : *mArraySizes) - { - char buf[20]; - snprintf(buf, sizeof(buf), "%d", arraySize); - mangledName += '['; - mangledName += buf; - mangledName += ']'; - } - } - - mangledName += ';'; - - // Copy string contents into a pool-allocated buffer, so we never need to call delete. - size_t requiredSize = mangledName.size() + 1; - char *buffer = reinterpret_cast(GetGlobalPoolAllocator()->allocate(requiredSize)); - memcpy(buffer, mangledName.c_str(), requiredSize); - return buffer; -} - -size_t TType::getObjectSize() const -{ - size_t totalSize; - - if (getBasicType() == EbtStruct) - totalSize = mStructure->objectSize(); - else - totalSize = primarySize * secondarySize; - - if (totalSize == 0) - return 0; - - if (mArraySizes) - { - for (size_t arraySize : *mArraySizes) - { - if (arraySize > INT_MAX / totalSize) - totalSize = INT_MAX; - else - totalSize *= arraySize; - } - } - - return totalSize; -} - -int TType::getLocationCount() const -{ - int count = 1; - - if (getBasicType() == EbtStruct) - { - count = mStructure->getLocationCount(); - } - - if (count == 0) - { - return 0; - } - - if (mArraySizes) - { - for (unsigned int arraySize : *mArraySizes) - { - if (arraySize > static_cast(std::numeric_limits::max() / count)) - { - count = std::numeric_limits::max(); - } - else - { - count *= static_cast(arraySize); - } - } - } - - return count; -} - -unsigned int TType::getArraySizeProduct() const -{ - if (!mArraySizes) - return 1u; - - unsigned int product = 1u; - - for (unsigned int arraySize : *mArraySizes) - { - product *= arraySize; - } - return product; -} - -bool TType::isUnsizedArray() const -{ - if (!mArraySizes) - return false; - - for (unsigned int arraySize : *mArraySizes) - { - if (arraySize == 0u) - { - return true; - } - } - return false; -} - -bool TType::sameNonArrayType(const TType &right) const -{ - return (type == right.type && primarySize == right.primarySize && - secondarySize == right.secondarySize && mStructure == right.mStructure); -} - -bool TType::isElementTypeOf(const TType &arrayType) const -{ - if (!sameNonArrayType(arrayType)) - { - return false; - } - if (arrayType.getNumArraySizes() != getNumArraySizes() + 1u) - { - return false; - } - if (isArray()) - { - for (size_t i = 0; i < mArraySizes->size(); ++i) - { - if ((*mArraySizes)[i] != (*arrayType.mArraySizes)[i]) - { - return false; - } - } - } - return true; -} - -void TType::sizeUnsizedArrays(const TVector *newArraySizes) -{ - size_t newArraySizesSize = newArraySizes ? newArraySizes->size() : 0; - for (size_t i = 0u; i < getNumArraySizes(); ++i) - { - if ((*mArraySizes)[i] == 0) - { - if (i < newArraySizesSize) - { - ASSERT(newArraySizes != nullptr); - (*mArraySizes)[i] = (*newArraySizes)[i]; - } - else - { - (*mArraySizes)[i] = 1u; - } - } - } - invalidateMangledName(); -} - -void TType::sizeOutermostUnsizedArray(unsigned int arraySize) -{ - ASSERT(isArray()); - ASSERT(mArraySizes->back() == 0u); - mArraySizes->back() = arraySize; -} - -void TType::setBasicType(TBasicType t) -{ - if (type != t) - { - type = t; - invalidateMangledName(); - } -} - -void TType::setPrimarySize(unsigned char ps) -{ - if (primarySize != ps) - { - ASSERT(ps <= 4); - primarySize = ps; - invalidateMangledName(); - } -} - -void TType::setSecondarySize(unsigned char ss) -{ - if (secondarySize != ss) - { - ASSERT(ss <= 4); - secondarySize = ss; - invalidateMangledName(); - } -} - -void TType::makeArray(unsigned int s) -{ - if (!mArraySizes) - mArraySizes = new TVector(); - - mArraySizes->push_back(s); - invalidateMangledName(); -} - -void TType::makeArrays(const TVector &sizes) -{ - if (!mArraySizes) - mArraySizes = new TVector(); - - mArraySizes->insert(mArraySizes->end(), sizes.begin(), sizes.end()); - invalidateMangledName(); -} - -void TType::setArraySize(size_t arrayDimension, unsigned int s) -{ - ASSERT(mArraySizes != nullptr); - ASSERT(arrayDimension < mArraySizes->size()); - if (mArraySizes->at(arrayDimension) != s) - { - (*mArraySizes)[arrayDimension] = s; - invalidateMangledName(); - } -} - -void TType::toArrayElementType() -{ - ASSERT(mArraySizes != nullptr); - if (mArraySizes->size() > 0) - { - mArraySizes->pop_back(); - invalidateMangledName(); - } -} - -void TType::setInterfaceBlock(TInterfaceBlock *interfaceBlockIn) -{ - if (mInterfaceBlock != interfaceBlockIn) - { - mInterfaceBlock = interfaceBlockIn; - invalidateMangledName(); - } -} - -void TType::setStruct(TStructure *s) -{ - if (mStructure != s) - { - mStructure = s; - invalidateMangledName(); - } -} - -const char *TType::getMangledName() const -{ - if (mMangledName == nullptr) - { - mMangledName = buildMangledName(); - } - - return mMangledName; -} - -void TType::realize() -{ - getMangledName(); -} - -void TType::invalidateMangledName() -{ - mMangledName = nullptr; -} - -// TStructure implementation. -TStructure::TStructure(TSymbolTable *symbolTable, const TString *name, TFieldList *fields) - : TFieldListCollection(name, fields), - mDeepestNesting(0), - mUniqueId(symbolTable->nextUniqueId()), - mAtGlobalScope(false) -{ -} - -bool TStructure::equals(const TStructure &other) const -{ - return (uniqueId() == other.uniqueId()); -} - -bool TStructure::containsArrays() const -{ - for (size_t i = 0; i < mFields->size(); ++i) - { - const TType *fieldType = (*mFields)[i]->type(); - if (fieldType->isArray() || fieldType->isStructureContainingArrays()) - return true; - } - return false; -} - -bool TStructure::containsType(TBasicType type) const -{ - for (size_t i = 0; i < mFields->size(); ++i) - { - const TType *fieldType = (*mFields)[i]->type(); - if (fieldType->getBasicType() == type || fieldType->isStructureContainingType(type)) - return true; - } - return false; -} - -bool TStructure::containsSamplers() const -{ - for (size_t i = 0; i < mFields->size(); ++i) - { - const TType *fieldType = (*mFields)[i]->type(); - if (IsSampler(fieldType->getBasicType()) || fieldType->isStructureContainingSamplers()) - return true; - } - return false; -} - -void TType::createSamplerSymbols(const TString &namePrefix, - const TString &apiNamePrefix, - TVector *outputSymbols, - TMap *outputSymbolsToAPINames, - TSymbolTable *symbolTable) const -{ - if (isStructureContainingSamplers()) - { - if (isArray()) - { - TType elementType(*this); - elementType.toArrayElementType(); - for (unsigned int arrayIndex = 0u; arrayIndex < getOutermostArraySize(); ++arrayIndex) - { - TStringStream elementName; - elementName << namePrefix << "_" << arrayIndex; - TStringStream elementApiName; - elementApiName << apiNamePrefix << "[" << arrayIndex << "]"; - elementType.createSamplerSymbols(elementName.str(), elementApiName.str(), - outputSymbols, outputSymbolsToAPINames, - symbolTable); - } - } - else - { - mStructure->createSamplerSymbols(namePrefix, apiNamePrefix, outputSymbols, - outputSymbolsToAPINames, symbolTable); - } - return; - } - - ASSERT(IsSampler(type)); - TIntermSymbol *symbol = new TIntermSymbol(symbolTable->nextUniqueId(), namePrefix, *this); - outputSymbols->push_back(symbol); - if (outputSymbolsToAPINames) - { - (*outputSymbolsToAPINames)[symbol] = apiNamePrefix; - } -} - -void TStructure::createSamplerSymbols(const TString &namePrefix, - const TString &apiNamePrefix, - TVector *outputSymbols, - TMap *outputSymbolsToAPINames, - TSymbolTable *symbolTable) const -{ - ASSERT(containsSamplers()); - for (auto &field : *mFields) - { - const TType *fieldType = field->type(); - if (IsSampler(fieldType->getBasicType()) || fieldType->isStructureContainingSamplers()) - { - TString fieldName = namePrefix + "_" + field->name(); - TString fieldApiName = apiNamePrefix + "." + field->name(); - fieldType->createSamplerSymbols(fieldName, fieldApiName, outputSymbols, - outputSymbolsToAPINames, symbolTable); - } - } -} - -TString TFieldListCollection::buildMangledName(const TString &mangledNamePrefix) const -{ - TString mangledName(mangledNamePrefix); - mangledName += *mName; - for (size_t i = 0; i < mFields->size(); ++i) - { - mangledName += '-'; - mangledName += (*mFields)[i]->type()->getMangledName(); - } - return mangledName; -} - -size_t TFieldListCollection::calculateObjectSize() const -{ - size_t size = 0; - for (const TField *field : *mFields) - { - size_t fieldSize = field->type()->getObjectSize(); - if (fieldSize > INT_MAX - size) - size = INT_MAX; - else - size += fieldSize; - } - return size; -} - -int TFieldListCollection::getLocationCount() const -{ - int count = 0; - for (const TField *field : *mFields) - { - int fieldCount = field->type()->getLocationCount(); - if (fieldCount > std::numeric_limits::max() - count) - { - count = std::numeric_limits::max(); - } - else - { - count += fieldCount; - } - } - return count; -} - -int TStructure::calculateDeepestNesting() const -{ - int maxNesting = 0; - for (size_t i = 0; i < mFields->size(); ++i) - maxNesting = std::max(maxNesting, (*mFields)[i]->type()->getDeepestStructNesting()); - return 1 + maxNesting; -} - -// TPublicType implementation. -void TPublicType::initialize(const TTypeSpecifierNonArray &typeSpecifier, TQualifier q) -{ - typeSpecifierNonArray = typeSpecifier; - layoutQualifier = TLayoutQualifier::Create(); - memoryQualifier = TMemoryQualifier::Create(); - qualifier = q; - invariant = false; - precision = EbpUndefined; - arraySizes = nullptr; -} - -void TPublicType::initializeBasicType(TBasicType basicType) -{ - typeSpecifierNonArray.type = basicType; - typeSpecifierNonArray.primarySize = 1; - typeSpecifierNonArray.secondarySize = 1; - layoutQualifier = TLayoutQualifier::Create(); - memoryQualifier = TMemoryQualifier::Create(); - qualifier = EvqTemporary; - invariant = false; - precision = EbpUndefined; - arraySizes = nullptr; -} - -bool TPublicType::isStructureContainingArrays() const -{ - if (!typeSpecifierNonArray.userDef) - { - return false; - } - - return typeSpecifierNonArray.userDef->containsArrays(); -} - -bool TPublicType::isStructureContainingType(TBasicType t) const -{ - if (!typeSpecifierNonArray.userDef) - { - return false; - } - - return typeSpecifierNonArray.userDef->containsType(t); -} - -void TPublicType::setArraySizes(TVector *sizes) -{ - arraySizes = sizes; -} - -bool TPublicType::isArray() const -{ - return arraySizes && !arraySizes->empty(); -} - -void TPublicType::clearArrayness() -{ - arraySizes = nullptr; -} - -bool TPublicType::isAggregate() const -{ - return isArray() || typeSpecifierNonArray.isMatrix() || typeSpecifierNonArray.isVector(); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/Types.h b/src/3rdparty/angle/src/compiler/translator/Types.h deleted file mode 100644 index 7dc84c5b1c..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/Types.h +++ /dev/null @@ -1,509 +0,0 @@ -// -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_TRANSLATOR_TYPES_H_ -#define COMPILER_TRANSLATOR_TYPES_H_ - -#include "common/angleutils.h" -#include "common/debug.h" - -#include "compiler/translator/BaseTypes.h" -#include "compiler/translator/Common.h" -#include "compiler/translator/SymbolUniqueId.h" - -namespace sh -{ - -struct TPublicType; -class TType; -class TSymbol; -class TIntermSymbol; -class TSymbolTable; - -class TField : angle::NonCopyable -{ - public: - POOL_ALLOCATOR_NEW_DELETE(); - TField(TType *type, TString *name, const TSourceLoc &line) - : mType(type), mName(name), mLine(line) - { - } - - // TODO(alokp): We should only return const type. - // Fix it by tweaking grammar. - TType *type() { return mType; } - const TType *type() const { return mType; } - - const TString &name() const { return *mName; } - const TSourceLoc &line() const { return mLine; } - - private: - TType *mType; - TString *mName; - TSourceLoc mLine; -}; - -typedef TVector TFieldList; -inline TFieldList *NewPoolTFieldList() -{ - void *memory = GetGlobalPoolAllocator()->allocate(sizeof(TFieldList)); - return new (memory) TFieldList; -} - -class TFieldListCollection : angle::NonCopyable -{ - public: - const TString &name() const { return *mName; } - const TFieldList &fields() const { return *mFields; } - - size_t objectSize() const - { - if (mObjectSize == 0) - mObjectSize = calculateObjectSize(); - return mObjectSize; - } - - // How many locations the field list consumes as a uniform. - int getLocationCount() const; - - protected: - TFieldListCollection(const TString *name, TFieldList *fields) - : mName(name), mFields(fields), mObjectSize(0) - { - } - TString buildMangledName(const TString &mangledNamePrefix) const; - size_t calculateObjectSize() const; - - const TString *mName; - TFieldList *mFields; - - mutable TString mMangledName; - mutable size_t mObjectSize; -}; - -// May also represent interface blocks -class TStructure : public TFieldListCollection -{ - public: - POOL_ALLOCATOR_NEW_DELETE(); - TStructure(TSymbolTable *symbolTable, const TString *name, TFieldList *fields); - - int deepestNesting() const - { - if (mDeepestNesting == 0) - mDeepestNesting = calculateDeepestNesting(); - return mDeepestNesting; - } - bool containsArrays() const; - bool containsType(TBasicType t) const; - bool containsSamplers() const; - - void createSamplerSymbols(const TString &namePrefix, - const TString &apiNamePrefix, - TVector *outputSymbols, - TMap *outputSymbolsToAPINames, - TSymbolTable *symbolTable) const; - - bool equals(const TStructure &other) const; - - int uniqueId() const { return mUniqueId.get(); } - - void setAtGlobalScope(bool atGlobalScope) { mAtGlobalScope = atGlobalScope; } - - bool atGlobalScope() const { return mAtGlobalScope; } - - const TString &mangledName() const - { - if (mMangledName.empty()) - mMangledName = buildMangledName("struct-"); - return mMangledName; - } - - private: - // TODO(zmo): Find a way to get rid of the const_cast in function - // setName(). At the moment keep this function private so only - // friend class RegenerateStructNames may call it. - friend class RegenerateStructNames; - void setName(const TString &name) - { - TString *mutableName = const_cast(mName); - *mutableName = name; - } - - int calculateDeepestNesting() const; - - mutable int mDeepestNesting; - const TSymbolUniqueId mUniqueId; - bool mAtGlobalScope; -}; - -class TInterfaceBlock : public TFieldListCollection -{ - public: - POOL_ALLOCATOR_NEW_DELETE(); - TInterfaceBlock(const TString *name, - TFieldList *fields, - const TString *instanceName, - const TLayoutQualifier &layoutQualifier) - : TFieldListCollection(name, fields), - mInstanceName(instanceName), - mBlockStorage(layoutQualifier.blockStorage), - mMatrixPacking(layoutQualifier.matrixPacking), - mBinding(layoutQualifier.binding) - { - } - - const TString &instanceName() const { return *mInstanceName; } - bool hasInstanceName() const { return mInstanceName != nullptr; } - TLayoutBlockStorage blockStorage() const { return mBlockStorage; } - TLayoutMatrixPacking matrixPacking() const { return mMatrixPacking; } - int blockBinding() const { return mBinding; } - const TString &mangledName() const - { - if (mMangledName.empty()) - mMangledName = buildMangledName("iblock-"); - return mMangledName; - } - - private: - const TString *mInstanceName; // for interface block instance names - TLayoutBlockStorage mBlockStorage; - TLayoutMatrixPacking mMatrixPacking; - int mBinding; -}; - -// -// Base class for things that have a type. -// -class TType -{ - public: - POOL_ALLOCATOR_NEW_DELETE(); - TType(); - explicit TType(TBasicType t, unsigned char ps = 1, unsigned char ss = 1); - TType(TBasicType t, - TPrecision p, - TQualifier q = EvqTemporary, - unsigned char ps = 1, - unsigned char ss = 1); - explicit TType(const TPublicType &p); - explicit TType(TStructure *userDef); - TType(TInterfaceBlock *interfaceBlockIn, - TQualifier qualifierIn, - TLayoutQualifier layoutQualifierIn); - TType(const TType &t); - TType &operator=(const TType &t); - - TBasicType getBasicType() const { return type; } - void setBasicType(TBasicType t); - - TPrecision getPrecision() const { return precision; } - void setPrecision(TPrecision p) { precision = p; } - - TQualifier getQualifier() const { return qualifier; } - void setQualifier(TQualifier q) { qualifier = q; } - - bool isInvariant() const { return invariant; } - - void setInvariant(bool i) { invariant = i; } - - TMemoryQualifier getMemoryQualifier() const { return memoryQualifier; } - void setMemoryQualifier(const TMemoryQualifier &mq) { memoryQualifier = mq; } - - TLayoutQualifier getLayoutQualifier() const { return layoutQualifier; } - void setLayoutQualifier(TLayoutQualifier lq) { layoutQualifier = lq; } - - int getNominalSize() const { return primarySize; } - int getSecondarySize() const { return secondarySize; } - int getCols() const - { - ASSERT(isMatrix()); - return primarySize; - } - int getRows() const - { - ASSERT(isMatrix()); - return secondarySize; - } - void setPrimarySize(unsigned char ps); - void setSecondarySize(unsigned char ss); - - // Full size of single instance of type - size_t getObjectSize() const; - - // Get how many locations this type consumes as a uniform. - int getLocationCount() const; - - bool isMatrix() const { return primarySize > 1 && secondarySize > 1; } - bool isNonSquareMatrix() const { return isMatrix() && primarySize != secondarySize; } - bool isArray() const { return mArraySizes != nullptr && !mArraySizes->empty(); } - bool isArrayOfArrays() const { return isArray() && mArraySizes->size() > 1u; } - size_t getNumArraySizes() const { return isArray() ? mArraySizes->size() : 0; } - const TVector *getArraySizes() const { return mArraySizes; } - unsigned int getArraySizeProduct() const; - bool isUnsizedArray() const; - unsigned int getOutermostArraySize() const { - ASSERT(isArray()); - return mArraySizes->back(); - } - void makeArray(unsigned int s); - - // sizes contain new outermost array sizes. - void makeArrays(const TVector &sizes); - // Here, the array dimension value 0 corresponds to the innermost array. - void setArraySize(size_t arrayDimension, unsigned int s); - - // Will set unsized array sizes according to newArraySizes. In case there are more - // unsized arrays than there are sizes in newArraySizes, defaults to setting any - // remaining array sizes to 1. - void sizeUnsizedArrays(const TVector *newArraySizes); - - // Will size the outermost array according to arraySize. - void sizeOutermostUnsizedArray(unsigned int arraySize); - - // Note that the array element type might still be an array type in GLSL ES version >= 3.10. - void toArrayElementType(); - - TInterfaceBlock *getInterfaceBlock() const { return mInterfaceBlock; } - void setInterfaceBlock(TInterfaceBlock *interfaceBlockIn); - bool isInterfaceBlock() const { return type == EbtInterfaceBlock; } - - bool isVector() const { return primarySize > 1 && secondarySize == 1; } - bool isScalar() const - { - return primarySize == 1 && secondarySize == 1 && !mStructure && !isArray(); - } - bool isScalarFloat() const { return isScalar() && type == EbtFloat; } - bool isScalarInt() const { return isScalar() && (type == EbtInt || type == EbtUInt); } - - bool canBeConstructed() const; - - TStructure *getStruct() { return mStructure; } - const TStructure *getStruct() const { return mStructure; } - void setStruct(TStructure *s); - - const char *getMangledName() const; - - bool sameNonArrayType(const TType &right) const; - - // Returns true if arrayType is an array made of this type. - bool isElementTypeOf(const TType &arrayType) const; - - bool operator==(const TType &right) const - { - size_t numArraySizesL = getNumArraySizes(); - size_t numArraySizesR = right.getNumArraySizes(); - bool arraySizesEqual = numArraySizesL == numArraySizesR && - (numArraySizesL == 0 || *mArraySizes == *right.mArraySizes); - return type == right.type && primarySize == right.primarySize && - secondarySize == right.secondarySize && arraySizesEqual && - mStructure == right.mStructure; - // don't check the qualifier, it's not ever what's being sought after - } - bool operator!=(const TType &right) const { return !operator==(right); } - bool operator<(const TType &right) const - { - if (type != right.type) - return type < right.type; - if (primarySize != right.primarySize) - return primarySize < right.primarySize; - if (secondarySize != right.secondarySize) - return secondarySize < right.secondarySize; - size_t numArraySizesL = getNumArraySizes(); - size_t numArraySizesR = right.getNumArraySizes(); - if (numArraySizesL != numArraySizesR) - return numArraySizesL < numArraySizesR; - for (size_t i = 0; i < numArraySizesL; ++i) - { - if ((*mArraySizes)[i] != (*right.mArraySizes)[i]) - return (*mArraySizes)[i] < (*right.mArraySizes)[i]; - } - if (mStructure != right.mStructure) - return mStructure < right.mStructure; - - return false; - } - - const char *getBasicString() const { return sh::getBasicString(type); } - - const char *getPrecisionString() const { return sh::getPrecisionString(precision); } - const char *getQualifierString() const { return sh::getQualifierString(qualifier); } - - const char *getBuiltInTypeNameString() const; - - TString getCompleteString() const; - - // If this type is a struct, returns the deepest struct nesting of - // any field in the struct. For example: - // struct nesting1 { - // vec4 position; - // }; - // struct nesting2 { - // nesting1 field1; - // vec4 field2; - // }; - // For type "nesting2", this method would return 2 -- the number - // of structures through which indirection must occur to reach the - // deepest field (nesting2.field1.position). - int getDeepestStructNesting() const { return mStructure ? mStructure->deepestNesting() : 0; } - - bool isNamelessStruct() const { return mStructure && mStructure->name() == ""; } - - bool isStructureContainingArrays() const - { - return mStructure ? mStructure->containsArrays() : false; - } - - bool isStructureContainingType(TBasicType t) const - { - return mStructure ? mStructure->containsType(t) : false; - } - - bool isStructureContainingSamplers() const - { - return mStructure ? mStructure->containsSamplers() : false; - } - - bool isStructSpecifier() const { return mIsStructSpecifier; } - - void createSamplerSymbols(const TString &namePrefix, - const TString &apiNamePrefix, - TVector *outputSymbols, - TMap *outputSymbolsToAPINames, - TSymbolTable *symbolTable) const; - - // Initializes all lazily-initialized members. - void realize(); - - private: - void invalidateMangledName(); - const char *buildMangledName() const; - - TBasicType type; - TPrecision precision; - TQualifier qualifier; - bool invariant; - TMemoryQualifier memoryQualifier; - TLayoutQualifier layoutQualifier; - unsigned char primarySize; // size of vector or cols matrix - unsigned char secondarySize; // rows of a matrix - - // Used to make an array type. Outermost array size is stored at the end of the vector. Having 0 - // in this vector means an unsized array. - TVector *mArraySizes; - - // This is set only in the following two cases: - // 1) Represents an interface block. - // 2) Represents the member variable of an unnamed interface block. - // It's nullptr also for members of named interface blocks. - TInterfaceBlock *mInterfaceBlock; - - // 0 unless this is a struct - TStructure *mStructure; - bool mIsStructSpecifier; - - mutable const char *mMangledName; -}; - -// TTypeSpecifierNonArray stores all of the necessary fields for type_specifier_nonarray from the -// grammar -struct TTypeSpecifierNonArray -{ - TBasicType type; - unsigned char primarySize; // size of vector or cols of matrix - unsigned char secondarySize; // rows of matrix - TStructure *userDef; - TSourceLoc line; - - // true if the type was defined by a struct specifier rather than a reference to a type name. - bool isStructSpecifier; - - void initialize(TBasicType aType, const TSourceLoc &aLine) - { - ASSERT(aType != EbtStruct); - type = aType; - primarySize = 1; - secondarySize = 1; - userDef = nullptr; - line = aLine; - isStructSpecifier = false; - } - - void initializeStruct(TStructure *aUserDef, bool aIsStructSpecifier, const TSourceLoc &aLine) - { - type = EbtStruct; - primarySize = 1; - secondarySize = 1; - userDef = aUserDef; - line = aLine; - isStructSpecifier = aIsStructSpecifier; - } - - void setAggregate(unsigned char size) { primarySize = size; } - - void setMatrix(unsigned char columns, unsigned char rows) - { - ASSERT(columns > 1 && rows > 1 && columns <= 4 && rows <= 4); - primarySize = columns; - secondarySize = rows; - } - - bool isMatrix() const { return primarySize > 1 && secondarySize > 1; } - - bool isVector() const { return primarySize > 1 && secondarySize == 1; } -}; - -// -// This is a workaround for a problem with the yacc 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. Pointers -// could be used, but also trying to avoid lots of memory management overhead. -// -// Not as bad as it looks, there is no actual assumption that the fields -// match up or are name the same or anything like that. -// -struct TPublicType -{ - // Must have a trivial default constructor since it is used in YYSTYPE. - TPublicType() = default; - - void initialize(const TTypeSpecifierNonArray &typeSpecifier, TQualifier q); - void initializeBasicType(TBasicType basicType); - - TBasicType getBasicType() const { return typeSpecifierNonArray.type; } - void setBasicType(TBasicType basicType) { typeSpecifierNonArray.type = basicType; } - - unsigned char getPrimarySize() const { return typeSpecifierNonArray.primarySize; } - unsigned char getSecondarySize() const { return typeSpecifierNonArray.secondarySize; } - - TStructure *getUserDef() const { return typeSpecifierNonArray.userDef; } - const TSourceLoc &getLine() const { return typeSpecifierNonArray.line; } - - bool isStructSpecifier() const { return typeSpecifierNonArray.isStructSpecifier; } - - bool isStructureContainingArrays() const; - bool isStructureContainingType(TBasicType t) const; - void setArraySizes(TVector *sizes); - bool isArray() const; - void clearArrayness(); - bool isAggregate() const; - - TTypeSpecifierNonArray typeSpecifierNonArray; - TLayoutQualifier layoutQualifier; - TMemoryQualifier memoryQualifier; - TQualifier qualifier; - bool invariant; - TPrecision precision; - - // Either nullptr or empty in case the type is not an array. The last element is the outermost - // array size. Note that due to bison restrictions, copies of the public type created by the - // copy constructor share the same arraySizes pointer. - const TVector *arraySizes; -}; - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_TYPES_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitAST.cpp b/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitAST.cpp deleted file mode 100644 index 4e4653bbe5..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitAST.cpp +++ /dev/null @@ -1,59 +0,0 @@ -// -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/translator/UnfoldShortCircuitAST.h" - -namespace sh -{ - -namespace -{ - -// "x || y" is equivalent to "x ? true : y". -TIntermTernary *UnfoldOR(TIntermTyped *x, TIntermTyped *y) -{ - TConstantUnion *u = new TConstantUnion; - u->setBConst(true); - TIntermConstantUnion *trueNode = - new TIntermConstantUnion(u, TType(EbtBool, EbpUndefined, EvqConst, 1)); - return new TIntermTernary(x, trueNode, y); -} - -// "x && y" is equivalent to "x ? y : false". -TIntermTernary *UnfoldAND(TIntermTyped *x, TIntermTyped *y) -{ - TConstantUnion *u = new TConstantUnion; - u->setBConst(false); - TIntermConstantUnion *falseNode = - new TIntermConstantUnion(u, TType(EbtBool, EbpUndefined, EvqConst, 1)); - return new TIntermTernary(x, y, falseNode); -} - -} // namespace anonymous - -bool UnfoldShortCircuitAST::visitBinary(Visit visit, TIntermBinary *node) -{ - TIntermTernary *replacement = nullptr; - - switch (node->getOp()) - { - case EOpLogicalOr: - replacement = UnfoldOR(node->getLeft(), node->getRight()); - break; - case EOpLogicalAnd: - replacement = UnfoldAND(node->getLeft(), node->getRight()); - break; - default: - break; - } - if (replacement) - { - queueReplacement(replacement, OriginalNode::IS_DROPPED); - } - return true; -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitAST.h b/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitAST.h deleted file mode 100644 index 7f377e6f15..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitAST.h +++ /dev/null @@ -1,33 +0,0 @@ -// -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// UnfoldShortCircuitAST is an AST traverser to replace short-circuiting -// operations with ternary operations. -// - -#ifndef COMPILER_TRANSLATOR_UNFOLDSHORTCIRCUITAST_H_ -#define COMPILER_TRANSLATOR_UNFOLDSHORTCIRCUITAST_H_ - -#include "common/angleutils.h" -#include "compiler/translator/IntermTraverse.h" - -namespace sh -{ - -// This traverser identifies all the short circuit binary nodes that need to -// be replaced, and creates the corresponding replacement nodes. However, -// the actual replacements happen after the traverse through updateTree(). - -class UnfoldShortCircuitAST : public TIntermTraverser -{ - public: - UnfoldShortCircuitAST() : TIntermTraverser(true, false, false) {} - - bool visitBinary(Visit visit, TIntermBinary *) override; -}; - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_UNFOLDSHORTCIRCUITAST_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitToIf.cpp b/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitToIf.cpp deleted file mode 100644 index 774f1fc704..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitToIf.cpp +++ /dev/null @@ -1,186 +0,0 @@ -// -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// UnfoldShortCircuitToIf is an AST traverser to convert short-circuiting operators to if-else -// statements. -// The results are assigned to s# temporaries, which are used by the main translator instead of -// the original expression. -// - -#include "compiler/translator/UnfoldShortCircuitToIf.h" - -#include "compiler/translator/IntermNodePatternMatcher.h" -#include "compiler/translator/IntermTraverse.h" - -namespace sh -{ - -namespace -{ - -// Traverser that unfolds one short-circuiting operation at a time. -class UnfoldShortCircuitTraverser : public TIntermTraverser -{ - public: - UnfoldShortCircuitTraverser(TSymbolTable *symbolTable); - - bool visitBinary(Visit visit, TIntermBinary *node) override; - bool visitTernary(Visit visit, TIntermTernary *node) override; - - void nextIteration(); - bool foundShortCircuit() const { return mFoundShortCircuit; } - - protected: - // Marked to true once an operation that needs to be unfolded has been found. - // After that, no more unfolding is performed on that traversal. - bool mFoundShortCircuit; - - IntermNodePatternMatcher mPatternToUnfoldMatcher; -}; - -UnfoldShortCircuitTraverser::UnfoldShortCircuitTraverser(TSymbolTable *symbolTable) - : TIntermTraverser(true, false, true, symbolTable), - mFoundShortCircuit(false), - mPatternToUnfoldMatcher(IntermNodePatternMatcher::kUnfoldedShortCircuitExpression) -{ -} - -bool UnfoldShortCircuitTraverser::visitBinary(Visit visit, TIntermBinary *node) -{ - if (mFoundShortCircuit) - return false; - - if (visit != PreVisit) - return true; - - if (!mPatternToUnfoldMatcher.match(node, getParentNode())) - return true; - - // If our right node doesn't have side effects, we know we don't need to unfold this - // expression: there will be no short-circuiting side effects to avoid - // (note: unfolding doesn't depend on the left node -- it will always be evaluated) - ASSERT(node->getRight()->hasSideEffects()); - - mFoundShortCircuit = true; - - switch (node->getOp()) - { - case EOpLogicalOr: - { - // "x || y" is equivalent to "x ? true : y", which unfolds to "bool s; if(x) s = true; - // else s = y;", - // and then further simplifies down to "bool s = x; if(!s) s = y;". - - TIntermSequence insertions; - TType boolType(EbtBool, EbpUndefined, EvqTemporary); - - ASSERT(node->getLeft()->getType() == boolType); - insertions.push_back(createTempInitDeclaration(node->getLeft())); - - TIntermBlock *assignRightBlock = new TIntermBlock(); - ASSERT(node->getRight()->getType() == boolType); - assignRightBlock->getSequence()->push_back(createTempAssignment(node->getRight())); - - TIntermUnary *notTempSymbol = - new TIntermUnary(EOpLogicalNot, createTempSymbol(boolType)); - TIntermIfElse *ifNode = new TIntermIfElse(notTempSymbol, assignRightBlock, nullptr); - insertions.push_back(ifNode); - - insertStatementsInParentBlock(insertions); - - queueReplacement(createTempSymbol(boolType), OriginalNode::IS_DROPPED); - return false; - } - case EOpLogicalAnd: - { - // "x && y" is equivalent to "x ? y : false", which unfolds to "bool s; if(x) s = y; - // else s = false;", - // and then further simplifies down to "bool s = x; if(s) s = y;". - TIntermSequence insertions; - TType boolType(EbtBool, EbpUndefined, EvqTemporary); - - ASSERT(node->getLeft()->getType() == boolType); - insertions.push_back(createTempInitDeclaration(node->getLeft())); - - TIntermBlock *assignRightBlock = new TIntermBlock(); - ASSERT(node->getRight()->getType() == boolType); - assignRightBlock->getSequence()->push_back(createTempAssignment(node->getRight())); - - TIntermIfElse *ifNode = - new TIntermIfElse(createTempSymbol(boolType), assignRightBlock, nullptr); - insertions.push_back(ifNode); - - insertStatementsInParentBlock(insertions); - - queueReplacement(createTempSymbol(boolType), OriginalNode::IS_DROPPED); - return false; - } - default: - UNREACHABLE(); - return true; - } -} - -bool UnfoldShortCircuitTraverser::visitTernary(Visit visit, TIntermTernary *node) -{ - if (mFoundShortCircuit) - return false; - - if (visit != PreVisit) - return true; - - if (!mPatternToUnfoldMatcher.match(node)) - return true; - - mFoundShortCircuit = true; - - // Unfold "b ? x : y" into "type s; if(b) s = x; else s = y;" - TIntermSequence insertions; - - TIntermDeclaration *tempDeclaration = createTempDeclaration(node->getType()); - insertions.push_back(tempDeclaration); - - TIntermBlock *trueBlock = new TIntermBlock(); - TIntermBinary *trueAssignment = createTempAssignment(node->getTrueExpression()); - trueBlock->getSequence()->push_back(trueAssignment); - - TIntermBlock *falseBlock = new TIntermBlock(); - TIntermBinary *falseAssignment = createTempAssignment(node->getFalseExpression()); - falseBlock->getSequence()->push_back(falseAssignment); - - TIntermIfElse *ifNode = - new TIntermIfElse(node->getCondition()->getAsTyped(), trueBlock, falseBlock); - insertions.push_back(ifNode); - - insertStatementsInParentBlock(insertions); - - TIntermSymbol *ternaryResult = createTempSymbol(node->getType()); - queueReplacement(ternaryResult, OriginalNode::IS_DROPPED); - - return false; -} - -void UnfoldShortCircuitTraverser::nextIteration() -{ - mFoundShortCircuit = false; - nextTemporaryId(); -} - -} // namespace - -void UnfoldShortCircuitToIf(TIntermNode *root, TSymbolTable *symbolTable) -{ - UnfoldShortCircuitTraverser traverser(symbolTable); - // Unfold one operator at a time, and reset the traverser between iterations. - do - { - traverser.nextIteration(); - root->traverse(&traverser); - if (traverser.foundShortCircuit()) - traverser.updateTree(); - } while (traverser.foundShortCircuit()); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitToIf.h b/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitToIf.h deleted file mode 100644 index 37dd83a8cf..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitToIf.h +++ /dev/null @@ -1,25 +0,0 @@ -// -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// UnfoldShortCircuitToIf is an AST traverser to convert short-circuiting operators to if-else -// statements. -// The results are assigned to s# temporaries, which are used by the main translator instead of -// the original expression. -// - -#ifndef COMPILER_TRANSLATOR_UNFOLDSHORTCIRCUIT_H_ -#define COMPILER_TRANSLATOR_UNFOLDSHORTCIRCUIT_H_ - -namespace sh -{ - -class TIntermNode; -class TSymbolTable; - -void UnfoldShortCircuitToIf(TIntermNode *root, TSymbolTable *symbolTable); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_UNFOLDSHORTCIRCUIT_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/UniformHLSL.cpp b/src/3rdparty/angle/src/compiler/translator/UniformHLSL.cpp deleted file mode 100644 index 9f18509438..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/UniformHLSL.cpp +++ /dev/null @@ -1,600 +0,0 @@ -// -// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// UniformHLSL.cpp: -// Methods for GLSL to HLSL translation for uniforms and uniform blocks. -// - -#include "compiler/translator/UniformHLSL.h" - -#include "common/utilities.h" -#include "compiler/translator/StructureHLSL.h" -#include "compiler/translator/UtilsHLSL.h" -#include "compiler/translator/blocklayoutHLSL.h" -#include "compiler/translator/util.h" - -namespace sh -{ - -namespace -{ - -static const char *UniformRegisterPrefix(const TType &type) -{ - if (IsSampler(type.getBasicType())) - { - return "s"; - } - else - { - return "c"; - } -} - -static TString InterfaceBlockFieldTypeString(const TField &field, TLayoutBlockStorage blockStorage) -{ - const TType &fieldType = *field.type(); - const TLayoutMatrixPacking matrixPacking = fieldType.getLayoutQualifier().matrixPacking; - ASSERT(matrixPacking != EmpUnspecified); - const TStructure *structure = fieldType.getStruct(); - - if (fieldType.isMatrix()) - { - // Use HLSL row-major packing for GLSL column-major matrices - const TString &matrixPackString = - (matrixPacking == EmpRowMajor ? "column_major" : "row_major"); - return matrixPackString + " " + TypeString(fieldType); - } - else if (structure) - { - // Use HLSL row-major packing for GLSL column-major matrices - return QualifiedStructNameString(*structure, matrixPacking == EmpColumnMajor, - blockStorage == EbsStd140); - } - else - { - return TypeString(fieldType); - } -} - -static TString InterfaceBlockStructName(const TInterfaceBlock &interfaceBlock) -{ - return DecoratePrivate(interfaceBlock.name()) + "_type"; -} - -void OutputSamplerIndexArrayInitializer(TInfoSinkBase &out, - const TType &type, - unsigned int startIndex) -{ - out << "{"; - TType elementType(type); - elementType.toArrayElementType(); - for (unsigned int i = 0u; i < type.getOutermostArraySize(); ++i) - { - if (i > 0u) - { - out << ", "; - } - if (elementType.isArray()) - { - OutputSamplerIndexArrayInitializer(out, elementType, - startIndex + i * elementType.getArraySizeProduct()); - } - else - { - out << (startIndex + i); - } - } - out << "}"; -} - -} // anonymous namespace - -UniformHLSL::UniformHLSL(sh::GLenum shaderType, - StructureHLSL *structureHLSL, - ShShaderOutput outputType, - const std::vector &uniforms) - : mUniformRegister(0), - mUniformBlockRegister(0), - mTextureRegister(0), - mRWTextureRegister(0), - mSamplerCount(0), - mShaderType(shaderType), - mStructureHLSL(structureHLSL), - mOutputType(outputType), - mUniforms(uniforms) -{ -} - -void UniformHLSL::reserveUniformRegisters(unsigned int registerCount) -{ - mUniformRegister = registerCount; -} - -void UniformHLSL::reserveUniformBlockRegisters(unsigned int registerCount) -{ - mUniformBlockRegister = registerCount; -} - -const Uniform *UniformHLSL::findUniformByName(const TString &name) const -{ - for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); ++uniformIndex) - { - if (mUniforms[uniformIndex].name == name.c_str()) - { - return &mUniforms[uniformIndex]; - } - } - - return nullptr; -} - -unsigned int UniformHLSL::assignUniformRegister(const TType &type, - const TString &name, - unsigned int *outRegisterCount) -{ - unsigned int registerIndex; - const Uniform *uniform = findUniformByName(name); - ASSERT(uniform); - - if (IsSampler(type.getBasicType()) || - (IsImage(type.getBasicType()) && type.getMemoryQualifier().readonly)) - { - registerIndex = mTextureRegister; - } - else if (IsImage(type.getBasicType())) - { - registerIndex = mRWTextureRegister; - } - else - { - registerIndex = mUniformRegister; - } - - mUniformRegisterMap[uniform->name] = registerIndex; - - unsigned int registerCount = HLSLVariableRegisterCount(*uniform, mOutputType); - - if (IsSampler(type.getBasicType()) || - (IsImage(type.getBasicType()) && type.getMemoryQualifier().readonly)) - { - mTextureRegister += registerCount; - } - else if (IsImage(type.getBasicType())) - { - mRWTextureRegister += registerCount; - } - else - { - mUniformRegister += registerCount; - } - if (outRegisterCount) - { - *outRegisterCount = registerCount; - } - return registerIndex; -} - -unsigned int UniformHLSL::assignSamplerInStructUniformRegister(const TType &type, - const TString &name, - unsigned int *outRegisterCount) -{ - // Sampler that is a field of a uniform structure. - ASSERT(IsSampler(type.getBasicType())); - unsigned int registerIndex = mTextureRegister; - mUniformRegisterMap[std::string(name.c_str())] = registerIndex; - unsigned int registerCount = type.isArray() ? type.getArraySizeProduct() : 1u; - mTextureRegister += registerCount; - if (outRegisterCount) - { - *outRegisterCount = registerCount; - } - return registerIndex; -} - -void UniformHLSL::outputHLSLSamplerUniformGroup( - TInfoSinkBase &out, - const HLSLTextureGroup textureGroup, - const TVector &group, - const TMap &samplerInStructSymbolsToAPINames, - unsigned int *groupTextureRegisterIndex) -{ - if (group.empty()) - { - return; - } - unsigned int groupRegisterCount = 0; - for (const TIntermSymbol *uniform : group) - { - const TType &type = uniform->getType(); - const TString &name = uniform->getSymbol(); - unsigned int registerCount; - - // The uniform might be just a regular sampler or one extracted from a struct. - unsigned int samplerArrayIndex = 0u; - const Uniform *uniformByName = findUniformByName(name); - if (uniformByName) - { - samplerArrayIndex = assignUniformRegister(type, name, ®isterCount); - } - else - { - ASSERT(samplerInStructSymbolsToAPINames.find(uniform) != - samplerInStructSymbolsToAPINames.end()); - samplerArrayIndex = assignSamplerInStructUniformRegister( - type, samplerInStructSymbolsToAPINames.at(uniform), ®isterCount); - } - groupRegisterCount += registerCount; - - if (type.isArray()) - { - out << "static const uint " << DecorateVariableIfNeeded(uniform->getName()) - << ArrayString(type) << " = "; - OutputSamplerIndexArrayInitializer(out, type, samplerArrayIndex); - out << ";\n"; - } - else - { - out << "static const uint " << DecorateVariableIfNeeded(uniform->getName()) << " = " - << samplerArrayIndex << ";\n"; - } - } - TString suffix = TextureGroupSuffix(textureGroup); - // Since HLSL_TEXTURE_2D is the first group, it has a fixed offset of zero. - if (textureGroup != HLSL_TEXTURE_2D) - { - out << "static const uint textureIndexOffset" << suffix << " = " - << (*groupTextureRegisterIndex) << ";\n"; - out << "static const uint samplerIndexOffset" << suffix << " = " - << (*groupTextureRegisterIndex) << ";\n"; - } - out << "uniform " << TextureString(textureGroup) << " textures" << suffix << "[" - << groupRegisterCount << "]" - << " : register(t" << (*groupTextureRegisterIndex) << ");\n"; - out << "uniform " << SamplerString(textureGroup) << " samplers" << suffix << "[" - << groupRegisterCount << "]" - << " : register(s" << (*groupTextureRegisterIndex) << ");\n"; - *groupTextureRegisterIndex += groupRegisterCount; -} - -void UniformHLSL::outputHLSL4_0_FL9_3Sampler(TInfoSinkBase &out, - const TType &type, - const TName &name, - const unsigned int registerIndex) -{ - out << "uniform " << SamplerString(type.getBasicType()) << " sampler_" - << DecorateVariableIfNeeded(name) << ArrayString(type) << " : register(s" - << str(registerIndex) << ");\n"; - out << "uniform " << TextureString(type.getBasicType()) << " texture_" - << DecorateVariableIfNeeded(name) << ArrayString(type) << " : register(t" - << str(registerIndex) << ");\n"; -} - -void UniformHLSL::outputHLSL4_1_FL11Texture(TInfoSinkBase &out, - const TType &type, - const TName &name, - const unsigned int registerIndex) -{ - // TODO(xinghua.cao@intel.com): if image2D variable is bound on one layer of Texture3D or - // Texture2DArray. Translate this variable to HLSL Texture3D object or HLSL Texture2DArray - // object, or create a temporary Texture2D to save content of the layer and bind the - // temporary Texture2D to image2D variable. - out << "uniform " - << TextureString(type.getBasicType(), type.getLayoutQualifier().imageInternalFormat) << " " - << DecorateVariableIfNeeded(name) << ArrayString(type) << " : register(t" - << str(registerIndex) << ");\n"; - return; -} - -void UniformHLSL::outputHLSL4_1_FL11RWTexture(TInfoSinkBase &out, - const TType &type, - const TName &name, - const unsigned int registerIndex) -{ - // TODO(xinghua.cao@intel.com): if image2D variable is bound on one layer of Texture3D or - // Texture2DArray. Translate this variable to HLSL RWTexture3D object or HLSL RWTexture2DArray - // object, or create a temporary Texture2D to save content of the layer and bind the - // temporary Texture2D to image2D variable. - if (mShaderType == GL_COMPUTE_SHADER) - { - out << "uniform " - << RWTextureString(type.getBasicType(), type.getLayoutQualifier().imageInternalFormat) - << " " << DecorateVariableIfNeeded(name) << ArrayString(type) << " : register(u" - << str(registerIndex) << ");\n"; - } - else - { - // TODO(xinghua.cao@intel.com): Support images in vertex shader and fragment shader, - // which are needed to sync binding value when linking program. - } - return; -} - -void UniformHLSL::outputUniform(TInfoSinkBase &out, - const TType &type, - const TName &name, - const unsigned int registerIndex) -{ - const TStructure *structure = type.getStruct(); - // If this is a nameless struct, we need to use its full definition, rather than its (empty) - // name. - // TypeString() will invoke defineNameless in this case; qualifier prefixes are unnecessary for - // nameless structs in ES, as nameless structs cannot be used anywhere that layout qualifiers - // are permitted. - const TString &typeName = ((structure && !structure->name().empty()) - ? QualifiedStructNameString(*structure, false, false) - : TypeString(type)); - - const TString ®isterString = - TString("register(") + UniformRegisterPrefix(type) + str(registerIndex) + ")"; - - out << "uniform " << typeName << " "; - - out << DecorateVariableIfNeeded(name); - - out << ArrayString(type) << " : " << registerString << ";\n"; -} - -void UniformHLSL::uniformsHeader(TInfoSinkBase &out, - ShShaderOutput outputType, - const ReferencedSymbols &referencedUniforms, - TSymbolTable *symbolTable) -{ - if (!referencedUniforms.empty()) - { - out << "// Uniforms\n\n"; - } - // In the case of HLSL 4, sampler uniforms need to be grouped by type before the code is - // written. They are grouped based on the combination of the HLSL texture type and - // HLSL sampler type, enumerated in HLSLTextureSamplerGroup. - TVector> groupedSamplerUniforms(HLSL_TEXTURE_MAX + 1); - TMap samplerInStructSymbolsToAPINames; - TVector imageUniformsHLSL41Output; - for (auto &uniformIt : referencedUniforms) - { - // Output regular uniforms. Group sampler uniforms by type. - const TIntermSymbol &uniform = *uniformIt.second; - const TType &type = uniform.getType(); - const TName &name = uniform.getName(); - - if (outputType == SH_HLSL_4_1_OUTPUT && IsSampler(type.getBasicType())) - { - HLSLTextureGroup group = TextureGroup(type.getBasicType()); - groupedSamplerUniforms[group].push_back(&uniform); - } - else if (outputType == SH_HLSL_4_0_FL9_3_OUTPUT && IsSampler(type.getBasicType())) - { - unsigned int registerIndex = assignUniformRegister(type, name.getString(), nullptr); - outputHLSL4_0_FL9_3Sampler(out, type, name, registerIndex); - } - else if (outputType == SH_HLSL_4_1_OUTPUT && IsImage(type.getBasicType())) - { - imageUniformsHLSL41Output.push_back(&uniform); - } - else - { - if (type.isStructureContainingSamplers()) - { - TVector samplerSymbols; - TMap symbolsToAPINames; - type.createSamplerSymbols("angle_" + name.getString(), name.getString(), - &samplerSymbols, &symbolsToAPINames, symbolTable); - for (TIntermSymbol *sampler : samplerSymbols) - { - const TType &samplerType = sampler->getType(); - - // Will use angle_ prefix instead of regular prefix. - sampler->setInternal(true); - const TName &samplerName = sampler->getName(); - - if (outputType == SH_HLSL_4_1_OUTPUT) - { - HLSLTextureGroup group = TextureGroup(samplerType.getBasicType()); - groupedSamplerUniforms[group].push_back(sampler); - samplerInStructSymbolsToAPINames[sampler] = symbolsToAPINames[sampler]; - } - else if (outputType == SH_HLSL_4_0_FL9_3_OUTPUT) - { - unsigned int registerIndex = assignSamplerInStructUniformRegister( - samplerType, symbolsToAPINames[sampler], nullptr); - outputHLSL4_0_FL9_3Sampler(out, samplerType, samplerName, registerIndex); - } - else - { - ASSERT(outputType == SH_HLSL_3_0_OUTPUT); - unsigned int registerIndex = assignSamplerInStructUniformRegister( - samplerType, symbolsToAPINames[sampler], nullptr); - outputUniform(out, samplerType, samplerName, registerIndex); - } - } - } - unsigned int registerIndex = assignUniformRegister(type, name.getString(), nullptr); - outputUniform(out, type, name, registerIndex); - } - } - - if (outputType == SH_HLSL_4_1_OUTPUT) - { - unsigned int groupTextureRegisterIndex = 0; - // TEXTURE_2D is special, index offset is assumed to be 0 and omitted in that case. - ASSERT(HLSL_TEXTURE_MIN == HLSL_TEXTURE_2D); - for (int groupId = HLSL_TEXTURE_MIN; groupId < HLSL_TEXTURE_MAX; ++groupId) - { - outputHLSLSamplerUniformGroup( - out, HLSLTextureGroup(groupId), groupedSamplerUniforms[groupId], - samplerInStructSymbolsToAPINames, &groupTextureRegisterIndex); - } - mSamplerCount = groupTextureRegisterIndex; - - for (const TIntermSymbol *image : imageUniformsHLSL41Output) - { - const TType &type = image->getType(); - const TName &name = image->getName(); - unsigned int registerIndex = assignUniformRegister(type, name.getString(), nullptr); - if (type.getMemoryQualifier().readonly) - { - outputHLSL4_1_FL11Texture(out, type, name, registerIndex); - } - else - { - outputHLSL4_1_FL11RWTexture(out, type, name, registerIndex); - } - } - } -} - -void UniformHLSL::samplerMetadataUniforms(TInfoSinkBase &out, const char *reg) -{ - // If mSamplerCount is 0 the shader doesn't use any textures for samplers. - if (mSamplerCount > 0) - { - out << " struct SamplerMetadata\n" - " {\n" - " int baseLevel;\n" - " int internalFormatBits;\n" - " int wrapModes;\n" - " int padding;\n" - " };\n" - " SamplerMetadata samplerMetadata[" - << mSamplerCount << "] : packoffset(" << reg << ");\n"; - } -} - -TString UniformHLSL::uniformBlocksHeader(const ReferencedSymbols &referencedInterfaceBlocks) -{ - TString interfaceBlocks; - - for (ReferencedSymbols::const_iterator interfaceBlockIt = referencedInterfaceBlocks.begin(); - interfaceBlockIt != referencedInterfaceBlocks.end(); interfaceBlockIt++) - { - const TType &nodeType = interfaceBlockIt->second->getType(); - const TInterfaceBlock &interfaceBlock = *nodeType.getInterfaceBlock(); - - // nodeType.isInterfaceBlock() == false means the node is a field of a uniform block which - // doesn't have instance name, so this block cannot be an array. - unsigned int interfaceBlockArraySize = 0u; - if (nodeType.isInterfaceBlock() && nodeType.isArray()) - { - interfaceBlockArraySize = nodeType.getOutermostArraySize(); - } - unsigned int activeRegister = mUniformBlockRegister; - - mUniformBlockRegisterMap[interfaceBlock.name().c_str()] = activeRegister; - mUniformBlockRegister += std::max(1u, interfaceBlockArraySize); - - // FIXME: interface block field names - - if (interfaceBlock.hasInstanceName()) - { - interfaceBlocks += uniformBlockStructString(interfaceBlock); - } - - if (interfaceBlockArraySize > 0) - { - for (unsigned int arrayIndex = 0; arrayIndex < interfaceBlockArraySize; arrayIndex++) - { - interfaceBlocks += - uniformBlockString(interfaceBlock, activeRegister + arrayIndex, arrayIndex); - } - } - else - { - interfaceBlocks += uniformBlockString(interfaceBlock, activeRegister, GL_INVALID_INDEX); - } - } - - return (interfaceBlocks.empty() ? "" : ("// Uniform Blocks\n\n" + interfaceBlocks)); -} - -TString UniformHLSL::uniformBlockString(const TInterfaceBlock &interfaceBlock, - unsigned int registerIndex, - unsigned int arrayIndex) -{ - const TString &arrayIndexString = - (arrayIndex != GL_INVALID_INDEX ? Decorate(str(arrayIndex)) : ""); - const TString &blockName = interfaceBlock.name() + arrayIndexString; - TString hlsl; - - hlsl += "cbuffer " + blockName + " : register(b" + str(registerIndex) + - ")\n" - "{\n"; - - if (interfaceBlock.hasInstanceName()) - { - hlsl += " " + InterfaceBlockStructName(interfaceBlock) + " " + - uniformBlockInstanceString(interfaceBlock, arrayIndex) + ";\n"; - } - else - { - const TLayoutBlockStorage blockStorage = interfaceBlock.blockStorage(); - hlsl += uniformBlockMembersString(interfaceBlock, blockStorage); - } - - hlsl += "};\n\n"; - - return hlsl; -} - -TString UniformHLSL::uniformBlockInstanceString(const TInterfaceBlock &interfaceBlock, - unsigned int arrayIndex) -{ - if (!interfaceBlock.hasInstanceName()) - { - return ""; - } - else if (arrayIndex != GL_INVALID_INDEX) - { - return DecoratePrivate(interfaceBlock.instanceName()) + "_" + str(arrayIndex); - } - else - { - return Decorate(interfaceBlock.instanceName()); - } -} - -TString UniformHLSL::uniformBlockMembersString(const TInterfaceBlock &interfaceBlock, - TLayoutBlockStorage blockStorage) -{ - TString hlsl; - - Std140PaddingHelper padHelper = mStructureHLSL->getPaddingHelper(); - - for (unsigned int typeIndex = 0; typeIndex < interfaceBlock.fields().size(); typeIndex++) - { - const TField &field = *interfaceBlock.fields()[typeIndex]; - const TType &fieldType = *field.type(); - - if (blockStorage == EbsStd140) - { - // 2 and 3 component vector types in some cases need pre-padding - hlsl += padHelper.prePaddingString(fieldType); - } - - hlsl += " " + InterfaceBlockFieldTypeString(field, blockStorage) + " " + - Decorate(field.name()) + ArrayString(fieldType) + ";\n"; - - // must pad out after matrices and arrays, where HLSL usually allows itself room to pack - // stuff - if (blockStorage == EbsStd140) - { - const bool useHLSLRowMajorPacking = - (fieldType.getLayoutQualifier().matrixPacking == EmpColumnMajor); - hlsl += padHelper.postPaddingString(fieldType, useHLSLRowMajorPacking); - } - } - - return hlsl; -} - -TString UniformHLSL::uniformBlockStructString(const TInterfaceBlock &interfaceBlock) -{ - const TLayoutBlockStorage blockStorage = interfaceBlock.blockStorage(); - - return "struct " + InterfaceBlockStructName(interfaceBlock) + - "\n" - "{\n" + - uniformBlockMembersString(interfaceBlock, blockStorage) + "};\n\n"; -} -} diff --git a/src/3rdparty/angle/src/compiler/translator/UniformHLSL.h b/src/3rdparty/angle/src/compiler/translator/UniformHLSL.h deleted file mode 100644 index 8784e50533..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/UniformHLSL.h +++ /dev/null @@ -1,110 +0,0 @@ -// -// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// UniformHLSL.h: -// Methods for GLSL to HLSL translation for uniforms and uniform blocks. -// - -#ifndef COMPILER_TRANSLATOR_UNIFORMHLSL_H_ -#define COMPILER_TRANSLATOR_UNIFORMHLSL_H_ - -#include "compiler/translator/OutputHLSL.h" -#include "compiler/translator/UtilsHLSL.h" - -namespace sh -{ -class StructureHLSL; -class TSymbolTable; - -class UniformHLSL : angle::NonCopyable -{ - public: - UniformHLSL(sh::GLenum shaderType, - StructureHLSL *structureHLSL, - ShShaderOutput outputType, - const std::vector &uniforms); - - void reserveUniformRegisters(unsigned int registerCount); - void reserveUniformBlockRegisters(unsigned int registerCount); - void uniformsHeader(TInfoSinkBase &out, - ShShaderOutput outputType, - const ReferencedSymbols &referencedUniforms, - TSymbolTable *symbolTable); - - // Must be called after uniformsHeader - void samplerMetadataUniforms(TInfoSinkBase &out, const char *reg); - - TString uniformBlocksHeader(const ReferencedSymbols &referencedInterfaceBlocks); - - // Used for direct index references - static TString uniformBlockInstanceString(const TInterfaceBlock &interfaceBlock, - unsigned int arrayIndex); - - const std::map &getUniformBlockRegisterMap() const - { - return mUniformBlockRegisterMap; - } - const std::map &getUniformRegisterMap() const - { - return mUniformRegisterMap; - } - - private: - TString uniformBlockString(const TInterfaceBlock &interfaceBlock, - unsigned int registerIndex, - unsigned int arrayIndex); - TString uniformBlockMembersString(const TInterfaceBlock &interfaceBlock, - TLayoutBlockStorage blockStorage); - TString uniformBlockStructString(const TInterfaceBlock &interfaceBlock); - const Uniform *findUniformByName(const TString &name) const; - - void outputHLSL4_0_FL9_3Sampler(TInfoSinkBase &out, - const TType &type, - const TName &name, - const unsigned int registerIndex); - void outputHLSL4_1_FL11Texture(TInfoSinkBase &out, - const TType &type, - const TName &name, - const unsigned int registerIndex); - void outputHLSL4_1_FL11RWTexture(TInfoSinkBase &out, - const TType &type, - const TName &name, - const unsigned int registerIndex); - void outputUniform(TInfoSinkBase &out, - const TType &type, - const TName &name, - const unsigned int registerIndex); - - // Returns the uniform's register index - unsigned int assignUniformRegister(const TType &type, - const TString &name, - unsigned int *outRegisterCount); - unsigned int assignSamplerInStructUniformRegister(const TType &type, - const TString &name, - unsigned int *outRegisterCount); - - void outputHLSLSamplerUniformGroup( - TInfoSinkBase &out, - const HLSLTextureGroup textureGroup, - const TVector &group, - const TMap &samplerInStructSymbolsToAPINames, - unsigned int *groupTextureRegisterIndex); - - unsigned int mUniformRegister; - unsigned int mUniformBlockRegister; - unsigned int mTextureRegister; - unsigned int mRWTextureRegister; - unsigned int mSamplerCount; - sh::GLenum mShaderType; - StructureHLSL *mStructureHLSL; - ShShaderOutput mOutputType; - - const std::vector &mUniforms; - std::map mUniformBlockRegisterMap; - std::map mUniformRegisterMap; -}; -} - -#endif // COMPILER_TRANSLATOR_UNIFORMHLSL_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/UseInterfaceBlockFields.cpp b/src/3rdparty/angle/src/compiler/translator/UseInterfaceBlockFields.cpp deleted file mode 100644 index 40bd42afad..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/UseInterfaceBlockFields.cpp +++ /dev/null @@ -1,105 +0,0 @@ -// -// Copyright 2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// UseInterfaceBlockFields.cpp: insert statements to reference all members in InterfaceBlock list at -// the beginning of main. This is to work around a Mac driver that treats unused standard/shared -// uniform blocks as inactive. - -#include "compiler/translator/UseInterfaceBlockFields.h" - -#include "compiler/translator/FindMain.h" -#include "compiler/translator/IntermNode.h" -#include "compiler/translator/IntermNode_util.h" -#include "compiler/translator/SymbolTable.h" -#include "compiler/translator/util.h" - -namespace sh -{ - -namespace -{ - -void AddNodeUseStatements(TIntermTyped *node, TIntermSequence *sequence) -{ - if (node->isArray()) - { - for (unsigned int i = 0u; i < node->getOutermostArraySize(); ++i) - { - TIntermBinary *element = - new TIntermBinary(EOpIndexDirect, node->deepCopy(), CreateIndexNode(i)); - AddNodeUseStatements(element, sequence); - } - } - else - { - sequence->insert(sequence->begin(), node); - } -} - -void AddFieldUseStatements(const ShaderVariable &var, - TIntermSequence *sequence, - const TSymbolTable &symbolTable) -{ - TString name = TString(var.name.c_str()); - ASSERT(name.find_last_of('[') == TString::npos); - TIntermSymbol *symbol = ReferenceGlobalVariable(name, symbolTable); - AddNodeUseStatements(symbol, sequence); -} - -void InsertUseCode(const InterfaceBlock &block, TIntermTyped *blockNode, TIntermSequence *sequence) -{ - for (unsigned int i = 0; i < block.fields.size(); ++i) - { - TIntermBinary *element = new TIntermBinary(EOpIndexDirectInterfaceBlock, - blockNode->deepCopy(), CreateIndexNode(i)); - sequence->insert(sequence->begin(), element); - } -} - -void InsertUseCode(TIntermSequence *sequence, - const InterfaceBlockList &blocks, - const TSymbolTable &symbolTable) -{ - for (const auto &block : blocks) - { - if (block.instanceName.empty()) - { - for (const auto &var : block.fields) - { - AddFieldUseStatements(var, sequence, symbolTable); - } - } - else if (block.arraySize > 0u) - { - TString name(block.instanceName.c_str()); - TIntermSymbol *arraySymbol = ReferenceGlobalVariable(name, symbolTable); - for (unsigned int i = 0u; i < block.arraySize; ++i) - { - TIntermBinary *elementSymbol = - new TIntermBinary(EOpIndexDirect, arraySymbol->deepCopy(), CreateIndexNode(i)); - InsertUseCode(block, elementSymbol, sequence); - } - } - else - { - TString name(block.instanceName.c_str()); - TIntermSymbol *blockSymbol = ReferenceGlobalVariable(name, symbolTable); - InsertUseCode(block, blockSymbol, sequence); - } - } -} - -} // namespace anonymous - -void UseInterfaceBlockFields(TIntermBlock *root, - const InterfaceBlockList &blocks, - const TSymbolTable &symbolTable) -{ - TIntermBlock *mainBody = FindMainBody(root); - InsertUseCode(mainBody->getSequence(), blocks, symbolTable); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/UseInterfaceBlockFields.h b/src/3rdparty/angle/src/compiler/translator/UseInterfaceBlockFields.h deleted file mode 100644 index 3e2a4815d4..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/UseInterfaceBlockFields.h +++ /dev/null @@ -1,30 +0,0 @@ -// -// Copyright 2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// UseInterfaceBlockFields.h: insert statements to reference all members in InterfaceBlock list at -// the beginning of main. This is to work around a Mac driver that treats unused standard/shared -// uniform blocks as inactive. - -#ifndef COMPILER_TRANSLATOR_USEINTERFACEBLOCKFIELDS_H_ -#define COMPILER_TRANSLATOR_USEINTERFACEBLOCKFIELDS_H_ - -#include - -namespace sh -{ - -class TIntermBlock; -class TSymbolTable; - -using InterfaceBlockList = std::vector; - -void UseInterfaceBlockFields(TIntermBlock *root, - const InterfaceBlockList &blocks, - const TSymbolTable &symbolTable); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_USEINTERFACEBLOCKFIELDS_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/UtilsHLSL.cpp b/src/3rdparty/angle/src/compiler/translator/UtilsHLSL.cpp deleted file mode 100644 index 8a77f0049a..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/UtilsHLSL.cpp +++ /dev/null @@ -1,970 +0,0 @@ -// -// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// UtilsHLSL.cpp: -// Utility methods for GLSL to HLSL translation. -// - -#include "compiler/translator/UtilsHLSL.h" -#include "compiler/translator/IntermNode.h" -#include "compiler/translator/StructureHLSL.h" -#include "compiler/translator/SymbolTable.h" - -namespace sh -{ - -TString SamplerString(const TBasicType type) -{ - if (IsShadowSampler(type)) - { - return "SamplerComparisonState"; - } - else - { - return "SamplerState"; - } -} - -TString SamplerString(HLSLTextureGroup type) -{ - if (type >= HLSL_COMPARISON_SAMPLER_GROUP_BEGIN && type <= HLSL_COMPARISON_SAMPLER_GROUP_END) - { - return "SamplerComparisonState"; - } - else - { - return "SamplerState"; - } -} - -HLSLTextureGroup TextureGroup(const TBasicType type, TLayoutImageInternalFormat imageInternalFormat) - -{ - switch (type) - { - case EbtSampler2D: - return HLSL_TEXTURE_2D; - case EbtSamplerCube: - return HLSL_TEXTURE_CUBE; - case EbtSamplerExternalOES: - return HLSL_TEXTURE_2D; - case EbtSampler2DArray: - return HLSL_TEXTURE_2D_ARRAY; - case EbtSampler3D: - return HLSL_TEXTURE_3D; - case EbtSampler2DMS: - return HLSL_TEXTURE_2D_MS; - case EbtISampler2D: - return HLSL_TEXTURE_2D_INT4; - case EbtISampler3D: - return HLSL_TEXTURE_3D_INT4; - case EbtISamplerCube: - return HLSL_TEXTURE_2D_ARRAY_INT4; - case EbtISampler2DArray: - return HLSL_TEXTURE_2D_ARRAY_INT4; - case EbtISampler2DMS: - return HLSL_TEXTURE_2D_MS_INT4; - case EbtUSampler2D: - return HLSL_TEXTURE_2D_UINT4; - case EbtUSampler3D: - return HLSL_TEXTURE_3D_UINT4; - case EbtUSamplerCube: - return HLSL_TEXTURE_2D_ARRAY_UINT4; - case EbtUSampler2DArray: - return HLSL_TEXTURE_2D_ARRAY_UINT4; - case EbtUSampler2DMS: - return HLSL_TEXTURE_2D_MS_UINT4; - case EbtSampler2DShadow: - return HLSL_TEXTURE_2D_COMPARISON; - case EbtSamplerCubeShadow: - return HLSL_TEXTURE_CUBE_COMPARISON; - case EbtSampler2DArrayShadow: - return HLSL_TEXTURE_2D_ARRAY_COMPARISON; - case EbtImage2D: - { - switch (imageInternalFormat) - { - case EiifRGBA32F: - case EiifRGBA16F: - case EiifR32F: - return HLSL_TEXTURE_2D; - case EiifRGBA8: - return HLSL_TEXTURE_2D_UNORM; - case EiifRGBA8_SNORM: - return HLSL_TEXTURE_2D_SNORM; - default: - UNREACHABLE(); - } - } - case EbtIImage2D: - { - switch (imageInternalFormat) - { - case EiifRGBA32I: - case EiifRGBA16I: - case EiifRGBA8I: - case EiifR32I: - return HLSL_TEXTURE_2D_INT4; - default: - UNREACHABLE(); - } - } - case EbtUImage2D: - { - switch (imageInternalFormat) - { - - case EiifRGBA32UI: - case EiifRGBA16UI: - case EiifRGBA8UI: - case EiifR32UI: - return HLSL_TEXTURE_2D_UINT4; - default: - UNREACHABLE(); - } - } - case EbtImage3D: - { - switch (imageInternalFormat) - { - case EiifRGBA32F: - case EiifRGBA16F: - case EiifR32F: - return HLSL_TEXTURE_3D; - case EiifRGBA8: - return HLSL_TEXTURE_3D_UNORM; - case EiifRGBA8_SNORM: - return HLSL_TEXTURE_3D_SNORM; - default: - UNREACHABLE(); - } - } - case EbtIImage3D: - { - switch (imageInternalFormat) - { - case EiifRGBA32I: - case EiifRGBA16I: - case EiifRGBA8I: - case EiifR32I: - return HLSL_TEXTURE_3D_INT4; - default: - UNREACHABLE(); - } - } - case EbtUImage3D: - { - switch (imageInternalFormat) - { - case EiifRGBA32UI: - case EiifRGBA16UI: - case EiifRGBA8UI: - case EiifR32UI: - return HLSL_TEXTURE_3D_UINT4; - default: - UNREACHABLE(); - } - } - case EbtImage2DArray: - case EbtImageCube: - { - switch (imageInternalFormat) - { - case EiifRGBA32F: - case EiifRGBA16F: - case EiifR32F: - return HLSL_TEXTURE_2D_ARRAY; - case EiifRGBA8: - return HLSL_TEXTURE_2D_ARRAY_UNORN; - case EiifRGBA8_SNORM: - return HLSL_TEXTURE_2D_ARRAY_SNORM; - default: - UNREACHABLE(); - } - } - case EbtIImage2DArray: - case EbtIImageCube: - { - switch (imageInternalFormat) - { - case EiifRGBA32I: - case EiifRGBA16I: - case EiifRGBA8I: - case EiifR32I: - return HLSL_TEXTURE_2D_ARRAY_INT4; - default: - UNREACHABLE(); - } - } - case EbtUImage2DArray: - case EbtUImageCube: - { - switch (imageInternalFormat) - { - case EiifRGBA32UI: - case EiifRGBA16UI: - case EiifRGBA8UI: - case EiifR32UI: - return HLSL_TEXTURE_2D_ARRAY_UINT4; - default: - UNREACHABLE(); - } - } - default: - UNREACHABLE(); - } - return HLSL_TEXTURE_UNKNOWN; -} - -TString TextureString(const HLSLTextureGroup textureGroup) -{ - switch (textureGroup) - { - case HLSL_TEXTURE_2D: - return "Texture2D"; - case HLSL_TEXTURE_CUBE: - return "TextureCube"; - case HLSL_TEXTURE_2D_ARRAY: - return "Texture2DArray"; - case HLSL_TEXTURE_3D: - return "Texture3D"; - case HLSL_TEXTURE_2D_UNORM: - return "Texture2D"; - case HLSL_TEXTURE_CUBE_UNORM: - return "TextureCube"; - case HLSL_TEXTURE_2D_ARRAY_UNORN: - return "Texture2DArray"; - case HLSL_TEXTURE_3D_UNORM: - return "Texture3D"; - case HLSL_TEXTURE_2D_SNORM: - return "Texture2D"; - case HLSL_TEXTURE_CUBE_SNORM: - return "TextureCube"; - case HLSL_TEXTURE_2D_ARRAY_SNORM: - return "Texture2DArray"; - case HLSL_TEXTURE_3D_SNORM: - return "Texture3D"; - case HLSL_TEXTURE_2D_MS: - return "Texture2DMS"; - case HLSL_TEXTURE_2D_INT4: - return "Texture2D"; - case HLSL_TEXTURE_3D_INT4: - return "Texture3D"; - case HLSL_TEXTURE_2D_ARRAY_INT4: - return "Texture2DArray"; - case HLSL_TEXTURE_2D_MS_INT4: - return "Texture2DMS"; - case HLSL_TEXTURE_2D_UINT4: - return "Texture2D"; - case HLSL_TEXTURE_3D_UINT4: - return "Texture3D"; - case HLSL_TEXTURE_2D_ARRAY_UINT4: - return "Texture2DArray"; - case HLSL_TEXTURE_2D_MS_UINT4: - return "Texture2DMS"; - case HLSL_TEXTURE_2D_COMPARISON: - return "Texture2D"; - case HLSL_TEXTURE_CUBE_COMPARISON: - return "TextureCube"; - case HLSL_TEXTURE_2D_ARRAY_COMPARISON: - return "Texture2DArray"; - default: - UNREACHABLE(); - } - - return ""; -} - -TString TextureString(const TBasicType type, TLayoutImageInternalFormat imageInternalFormat) -{ - return TextureString(TextureGroup(type, imageInternalFormat)); -} - -TString TextureGroupSuffix(const HLSLTextureGroup type) -{ - switch (type) - { - case HLSL_TEXTURE_2D: - return "2D"; - case HLSL_TEXTURE_CUBE: - return "Cube"; - case HLSL_TEXTURE_2D_ARRAY: - return "2DArray"; - case HLSL_TEXTURE_3D: - return "3D"; - case HLSL_TEXTURE_2D_UNORM: - return "2D_unorm_float4_"; - case HLSL_TEXTURE_CUBE_UNORM: - return "Cube_unorm_float4_"; - case HLSL_TEXTURE_2D_ARRAY_UNORN: - return "2DArray_unorm_float4_"; - case HLSL_TEXTURE_3D_UNORM: - return "3D_unorm_float4_"; - case HLSL_TEXTURE_2D_SNORM: - return "2D_snorm_float4_"; - case HLSL_TEXTURE_CUBE_SNORM: - return "Cube_snorm_float4_"; - case HLSL_TEXTURE_2D_ARRAY_SNORM: - return "2DArray_snorm_float4_"; - case HLSL_TEXTURE_3D_SNORM: - return "3D_snorm_float4_"; - case HLSL_TEXTURE_2D_MS: - return "2DMS"; - case HLSL_TEXTURE_2D_INT4: - return "2D_int4_"; - case HLSL_TEXTURE_3D_INT4: - return "3D_int4_"; - case HLSL_TEXTURE_2D_ARRAY_INT4: - return "2DArray_int4_"; - case HLSL_TEXTURE_2D_MS_INT4: - return "2DMS_int4_"; - case HLSL_TEXTURE_2D_UINT4: - return "2D_uint4_"; - case HLSL_TEXTURE_3D_UINT4: - return "3D_uint4_"; - case HLSL_TEXTURE_2D_ARRAY_UINT4: - return "2DArray_uint4_"; - case HLSL_TEXTURE_2D_MS_UINT4: - return "2DMS_uint4_"; - case HLSL_TEXTURE_2D_COMPARISON: - return "2D_comparison"; - case HLSL_TEXTURE_CUBE_COMPARISON: - return "Cube_comparison"; - case HLSL_TEXTURE_2D_ARRAY_COMPARISON: - return "2DArray_comparison"; - default: - UNREACHABLE(); - } - - return ""; -} - -TString TextureGroupSuffix(const TBasicType type, TLayoutImageInternalFormat imageInternalFormat) -{ - return TextureGroupSuffix(TextureGroup(type, imageInternalFormat)); -} - -TString TextureTypeSuffix(const TBasicType type, TLayoutImageInternalFormat imageInternalFormat) -{ - switch (type) - { - case EbtISamplerCube: - return "Cube_int4_"; - case EbtUSamplerCube: - return "Cube_uint4_"; - case EbtSamplerExternalOES: - return "_External"; - case EbtImageCube: - { - switch (imageInternalFormat) - { - case EiifRGBA32F: - case EiifRGBA16F: - case EiifR32F: - return "Cube_float4_"; - case EiifRGBA8: - return "Cube_unorm_float4_"; - case EiifRGBA8_SNORM: - return "Cube_snorm_float4_"; - default: - UNREACHABLE(); - } - } - case EbtIImageCube: - { - switch (imageInternalFormat) - { - case EiifRGBA32I: - case EiifRGBA16I: - case EiifRGBA8I: - case EiifR32I: - return "Cube_int4_"; - default: - UNREACHABLE(); - } - } - case EbtUImageCube: - { - switch (imageInternalFormat) - { - case EiifRGBA32UI: - case EiifRGBA16UI: - case EiifRGBA8UI: - case EiifR32UI: - return "Cube_uint4_"; - default: - UNREACHABLE(); - } - } - default: - // All other types are identified by their group suffix - return TextureGroupSuffix(type, imageInternalFormat); - } -} - -HLSLRWTextureGroup RWTextureGroup(const TBasicType type, - TLayoutImageInternalFormat imageInternalFormat) - -{ - switch (type) - { - case EbtImage2D: - { - switch (imageInternalFormat) - { - case EiifRGBA32F: - case EiifRGBA16F: - case EiifR32F: - return HLSL_RWTEXTURE_2D_FLOAT4; - case EiifRGBA8: - return HLSL_RWTEXTURE_2D_UNORM; - case EiifRGBA8_SNORM: - return HLSL_RWTEXTURE_2D_SNORM; - default: - UNREACHABLE(); - } - } - case EbtIImage2D: - { - switch (imageInternalFormat) - { - case EiifRGBA32I: - case EiifRGBA16I: - case EiifRGBA8I: - case EiifR32I: - return HLSL_RWTEXTURE_2D_INT4; - default: - UNREACHABLE(); - } - } - case EbtUImage2D: - { - switch (imageInternalFormat) - { - - case EiifRGBA32UI: - case EiifRGBA16UI: - case EiifRGBA8UI: - case EiifR32UI: - return HLSL_RWTEXTURE_2D_UINT4; - default: - UNREACHABLE(); - } - } - case EbtImage3D: - { - switch (imageInternalFormat) - { - case EiifRGBA32F: - case EiifRGBA16F: - case EiifR32F: - return HLSL_RWTEXTURE_3D_FLOAT4; - case EiifRGBA8: - return HLSL_RWTEXTURE_3D_UNORM; - case EiifRGBA8_SNORM: - return HLSL_RWTEXTURE_3D_SNORM; - default: - UNREACHABLE(); - } - } - case EbtIImage3D: - { - switch (imageInternalFormat) - { - case EiifRGBA32I: - case EiifRGBA16I: - case EiifRGBA8I: - case EiifR32I: - return HLSL_RWTEXTURE_3D_INT4; - default: - UNREACHABLE(); - } - } - case EbtUImage3D: - { - switch (imageInternalFormat) - { - case EiifRGBA32UI: - case EiifRGBA16UI: - case EiifRGBA8UI: - case EiifR32UI: - return HLSL_RWTEXTURE_3D_UINT4; - default: - UNREACHABLE(); - } - } - case EbtImage2DArray: - case EbtImageCube: - { - switch (imageInternalFormat) - { - case EiifRGBA32F: - case EiifRGBA16F: - case EiifR32F: - return HLSL_RWTEXTURE_2D_ARRAY_FLOAT4; - case EiifRGBA8: - return HLSL_RWTEXTURE_2D_ARRAY_UNORN; - case EiifRGBA8_SNORM: - return HLSL_RWTEXTURE_2D_ARRAY_SNORM; - default: - UNREACHABLE(); - } - } - case EbtIImage2DArray: - case EbtIImageCube: - { - switch (imageInternalFormat) - { - case EiifRGBA32I: - case EiifRGBA16I: - case EiifRGBA8I: - case EiifR32I: - return HLSL_RWTEXTURE_2D_ARRAY_INT4; - default: - UNREACHABLE(); - } - } - case EbtUImage2DArray: - case EbtUImageCube: - { - switch (imageInternalFormat) - { - case EiifRGBA32UI: - case EiifRGBA16UI: - case EiifRGBA8UI: - case EiifR32UI: - return HLSL_RWTEXTURE_2D_ARRAY_UINT4; - default: - UNREACHABLE(); - } - } - default: - UNREACHABLE(); - } - return HLSL_RWTEXTURE_UNKNOWN; -} - -TString RWTextureString(const HLSLRWTextureGroup RWTextureGroup) -{ - switch (RWTextureGroup) - { - case HLSL_RWTEXTURE_2D_FLOAT4: - return "RWTexture2D"; - case HLSL_RWTEXTURE_2D_ARRAY_FLOAT4: - return "RWTexture2DArray"; - case HLSL_RWTEXTURE_3D_FLOAT4: - return "RWTexture3D"; - case HLSL_RWTEXTURE_2D_UNORM: - return "RWTexture2D"; - case HLSL_RWTEXTURE_2D_ARRAY_UNORN: - return "RWTexture2DArray"; - case HLSL_RWTEXTURE_3D_UNORM: - return "RWTexture3D"; - case HLSL_RWTEXTURE_2D_SNORM: - return "RWTexture2D"; - case HLSL_RWTEXTURE_2D_ARRAY_SNORM: - return "RWTexture2DArray"; - case HLSL_RWTEXTURE_3D_SNORM: - return "RWTexture3D"; - case HLSL_RWTEXTURE_2D_UINT4: - return "RWTexture2D"; - case HLSL_RWTEXTURE_2D_ARRAY_UINT4: - return "RWTexture2DArray"; - case HLSL_RWTEXTURE_3D_UINT4: - return "RWTexture3D"; - case HLSL_RWTEXTURE_2D_INT4: - return "RWTexture2D"; - case HLSL_RWTEXTURE_2D_ARRAY_INT4: - return "RWTexture2DArray"; - case HLSL_RWTEXTURE_3D_INT4: - return "RWTexture3D"; - default: - UNREACHABLE(); - } - - return ""; -} - -TString RWTextureString(const TBasicType type, TLayoutImageInternalFormat imageInternalFormat) -{ - return RWTextureString(RWTextureGroup(type, imageInternalFormat)); -} - -TString RWTextureGroupSuffix(const HLSLRWTextureGroup type) -{ - switch (type) - { - case HLSL_RWTEXTURE_2D_FLOAT4: - return "RW2D_float4_"; - case HLSL_RWTEXTURE_2D_ARRAY_FLOAT4: - return "RW2DArray_float4_"; - case HLSL_RWTEXTURE_3D_FLOAT4: - return "RW3D_float4_"; - case HLSL_RWTEXTURE_2D_UNORM: - return "RW2D_unorm_float4_"; - case HLSL_RWTEXTURE_2D_ARRAY_UNORN: - return "RW2DArray_unorm_float4_"; - case HLSL_RWTEXTURE_3D_UNORM: - return "RW3D_unorm_float4_"; - case HLSL_RWTEXTURE_2D_SNORM: - return "RW2D_snorm_float4_"; - case HLSL_RWTEXTURE_2D_ARRAY_SNORM: - return "RW2DArray_snorm_float4_"; - case HLSL_RWTEXTURE_3D_SNORM: - return "RW3D_snorm_float4_"; - case HLSL_RWTEXTURE_2D_UINT4: - return "RW2D_uint4_"; - case HLSL_RWTEXTURE_2D_ARRAY_UINT4: - return "RW2DArray_uint4_"; - case HLSL_RWTEXTURE_3D_UINT4: - return "RW3D_uint4_"; - case HLSL_RWTEXTURE_2D_INT4: - return "RW2D_int4_"; - case HLSL_RWTEXTURE_2D_ARRAY_INT4: - return "RW2DArray_int4_"; - case HLSL_RWTEXTURE_3D_INT4: - return "RW3D_int4_"; - default: - UNREACHABLE(); - } - - return ""; -} - -TString RWTextureGroupSuffix(const TBasicType type, TLayoutImageInternalFormat imageInternalFormat) -{ - return RWTextureGroupSuffix(RWTextureGroup(type, imageInternalFormat)); -} - -TString RWTextureTypeSuffix(const TBasicType type, TLayoutImageInternalFormat imageInternalFormat) -{ - switch (type) - { - case EbtImageCube: - { - switch (imageInternalFormat) - { - case EiifRGBA32F: - case EiifRGBA16F: - case EiifR32F: - return "RWCube_float4_"; - case EiifRGBA8: - return "RWCube_unorm_float4_"; - case EiifRGBA8_SNORM: - return "RWCube_unorm_float4_"; - default: - UNREACHABLE(); - } - } - case EbtIImageCube: - { - switch (imageInternalFormat) - { - case EiifRGBA32I: - case EiifRGBA16I: - case EiifRGBA8I: - case EiifR32I: - return "RWCube_int4_"; - default: - UNREACHABLE(); - } - } - case EbtUImageCube: - { - switch (imageInternalFormat) - { - case EiifRGBA32UI: - case EiifRGBA16UI: - case EiifRGBA8UI: - case EiifR32UI: - return "RWCube_uint4_"; - default: - UNREACHABLE(); - } - } - default: - // All other types are identified by their group suffix - return TextureGroupSuffix(type, imageInternalFormat); - } -} - -TString DecorateField(const TString &string, const TStructure &structure) -{ - if (structure.name().compare(0, 3, "gl_") != 0) - { - return Decorate(string); - } - - return string; -} - -TString DecoratePrivate(const TString &privateText) -{ - return "dx_" + privateText; -} - -TString Decorate(const TString &string) -{ - if (string.compare(0, 3, "gl_") != 0) - { - return "_" + string; - } - - return string; -} - -TString DecorateVariableIfNeeded(const TName &name) -{ - if (name.isInternal()) - { - // The name should not have a prefix reserved for user-defined variables or functions. - ASSERT(name.getString().compare(0, 2, "f_") != 0); - ASSERT(name.getString().compare(0, 1, "_") != 0); - return name.getString(); - } - else - { - return Decorate(name.getString()); - } -} - -TString DecorateFunctionIfNeeded(const TName &name) -{ - if (name.isInternal()) - { - // The name should not have a prefix reserved for user-defined variables or functions. - ASSERT(name.getString().compare(0, 2, "f_") != 0); - ASSERT(name.getString().compare(0, 1, "_") != 0); - return name.getString(); - } - ASSERT(name.getString().compare(0, 3, "gl_") != 0); - // Add an additional f prefix to functions so that they're always disambiguated from variables. - // This is necessary in the corner case where a variable declaration hides a function that it - // uses in its initializer. - return "f_" + name.getString(); -} - -TString TypeString(const TType &type) -{ - const TStructure *structure = type.getStruct(); - if (structure) - { - const TString &typeName = structure->name(); - if (typeName != "") - { - return StructNameString(*structure); - } - else // Nameless structure, define in place - { - return StructureHLSL::defineNameless(*structure); - } - } - else if (type.isMatrix()) - { - int cols = type.getCols(); - int rows = type.getRows(); - return "float" + str(cols) + "x" + str(rows); - } - else - { - switch (type.getBasicType()) - { - case EbtFloat: - switch (type.getNominalSize()) - { - case 1: - return "float"; - case 2: - return "float2"; - case 3: - return "float3"; - case 4: - return "float4"; - } - case EbtInt: - switch (type.getNominalSize()) - { - case 1: - return "int"; - case 2: - return "int2"; - case 3: - return "int3"; - case 4: - return "int4"; - } - case EbtUInt: - switch (type.getNominalSize()) - { - case 1: - return "uint"; - case 2: - return "uint2"; - case 3: - return "uint3"; - case 4: - return "uint4"; - } - case EbtBool: - switch (type.getNominalSize()) - { - case 1: - return "bool"; - case 2: - return "bool2"; - case 3: - return "bool3"; - case 4: - return "bool4"; - } - case EbtVoid: - return "void"; - case EbtSampler2D: - case EbtISampler2D: - case EbtUSampler2D: - case EbtSampler2DArray: - case EbtISampler2DArray: - case EbtUSampler2DArray: - return "sampler2D"; - case EbtSamplerCube: - case EbtISamplerCube: - case EbtUSamplerCube: - return "samplerCUBE"; - case EbtSamplerExternalOES: - return "sampler2D"; - case EbtAtomicCounter: - return "atomic_uint"; - default: - break; - } - } - - UNREACHABLE(); - return ""; -} - -TString StructNameString(const TStructure &structure) -{ - if (structure.name().empty()) - { - return ""; - } - - // For structures at global scope we use a consistent - // translation so that we can link between shader stages. - if (structure.atGlobalScope()) - { - return Decorate(structure.name()); - } - - return "ss" + str(structure.uniqueId()) + "_" + structure.name(); -} - -TString QualifiedStructNameString(const TStructure &structure, - bool useHLSLRowMajorPacking, - bool useStd140Packing) -{ - if (structure.name() == "") - { - return ""; - } - - TString prefix = ""; - - // Structs packed with row-major matrices in HLSL are prefixed with "rm" - // GLSL column-major maps to HLSL row-major, and the converse is true - - if (useStd140Packing) - { - prefix += "std_"; - } - - if (useHLSLRowMajorPacking) - { - prefix += "rm_"; - } - - return prefix + StructNameString(structure); -} - -TString InterpolationString(TQualifier qualifier) -{ - switch (qualifier) - { - case EvqVaryingIn: - return ""; - case EvqFragmentIn: - return ""; - case EvqSmoothIn: - return "linear"; - case EvqFlatIn: - return "nointerpolation"; - case EvqCentroidIn: - return "centroid"; - case EvqVaryingOut: - return ""; - case EvqVertexOut: - return ""; - case EvqSmoothOut: - return "linear"; - case EvqFlatOut: - return "nointerpolation"; - case EvqCentroidOut: - return "centroid"; - default: - UNREACHABLE(); - } - - return ""; -} - -TString QualifierString(TQualifier qualifier) -{ - switch (qualifier) - { - case EvqIn: - return "in"; - case EvqOut: - return "inout"; // 'out' results in an HLSL error if not all fields are written, for - // GLSL it's undefined - case EvqInOut: - return "inout"; - case EvqConstReadOnly: - return "const"; - default: - UNREACHABLE(); - } - - return ""; -} - -TString DisambiguateFunctionName(const TIntermSequence *parameters) -{ - TString disambiguatingString; - for (auto parameter : *parameters) - { - const TType ¶mType = parameter->getAsTyped()->getType(); - // Parameter types are only added to function names if they are ambiguous according to the - // native HLSL compiler. Other parameter types are not added to function names to avoid - // making function names longer. - if (paramType.getObjectSize() == 4 && paramType.getBasicType() == EbtFloat) - { - // Disambiguation is needed for float2x2 and float4 parameters. These are the only - // built-in types that HLSL thinks are identical. float2x3 and float3x2 are different - // types, for example. - disambiguatingString += "_" + TypeString(paramType); - } - else if (paramType.getBasicType() == EbtStruct) - { - // Disambiguation is needed for struct parameters, since HLSL thinks that structs with - // the same fields but a different name are identical. - ASSERT(paramType.getStruct()->name() != ""); - disambiguatingString += "_" + TypeString(paramType); - } - } - return disambiguatingString; -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/UtilsHLSL.h b/src/3rdparty/angle/src/compiler/translator/UtilsHLSL.h deleted file mode 100644 index daeec8de41..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/UtilsHLSL.h +++ /dev/null @@ -1,129 +0,0 @@ -// -// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// UtilsHLSL.h: -// Utility methods for GLSL to HLSL translation. -// - -#ifndef COMPILER_TRANSLATOR_UTILSHLSL_H_ -#define COMPILER_TRANSLATOR_UTILSHLSL_H_ - -#include -#include "compiler/translator/IntermNode.h" -#include "compiler/translator/Types.h" - -#include "angle_gl.h" - -class TName; - -namespace sh -{ - -// HLSL Texture type for GLSL sampler type and readonly image type. -enum HLSLTextureGroup -{ - // read resources - HLSL_TEXTURE_2D, - HLSL_TEXTURE_MIN = HLSL_TEXTURE_2D, - - HLSL_TEXTURE_CUBE, - HLSL_TEXTURE_2D_ARRAY, - HLSL_TEXTURE_3D, - HLSL_TEXTURE_2D_UNORM, - HLSL_TEXTURE_CUBE_UNORM, - HLSL_TEXTURE_2D_ARRAY_UNORN, - HLSL_TEXTURE_3D_UNORM, - HLSL_TEXTURE_2D_SNORM, - HLSL_TEXTURE_CUBE_SNORM, - HLSL_TEXTURE_2D_ARRAY_SNORM, - HLSL_TEXTURE_3D_SNORM, - HLSL_TEXTURE_2D_MS, - HLSL_TEXTURE_2D_INT4, - HLSL_TEXTURE_3D_INT4, - HLSL_TEXTURE_2D_ARRAY_INT4, - HLSL_TEXTURE_2D_MS_INT4, - HLSL_TEXTURE_2D_UINT4, - HLSL_TEXTURE_3D_UINT4, - HLSL_TEXTURE_2D_ARRAY_UINT4, - HLSL_TEXTURE_2D_MS_UINT4, - - // Comparison samplers - - HLSL_TEXTURE_2D_COMPARISON, - HLSL_TEXTURE_CUBE_COMPARISON, - HLSL_TEXTURE_2D_ARRAY_COMPARISON, - - HLSL_COMPARISON_SAMPLER_GROUP_BEGIN = HLSL_TEXTURE_2D_COMPARISON, - HLSL_COMPARISON_SAMPLER_GROUP_END = HLSL_TEXTURE_2D_ARRAY_COMPARISON, - - HLSL_TEXTURE_UNKNOWN, - HLSL_TEXTURE_MAX = HLSL_TEXTURE_UNKNOWN -}; - -// HLSL RWTexture type for GLSL read and write image type. -enum HLSLRWTextureGroup -{ - // read/write resource - HLSL_RWTEXTURE_2D_FLOAT4, - HLSL_RWTEXTURE_MIN = HLSL_RWTEXTURE_2D_FLOAT4, - HLSL_RWTEXTURE_2D_ARRAY_FLOAT4, - HLSL_RWTEXTURE_3D_FLOAT4, - HLSL_RWTEXTURE_2D_UNORM, - HLSL_RWTEXTURE_2D_ARRAY_UNORN, - HLSL_RWTEXTURE_3D_UNORM, - HLSL_RWTEXTURE_2D_SNORM, - HLSL_RWTEXTURE_2D_ARRAY_SNORM, - HLSL_RWTEXTURE_3D_SNORM, - HLSL_RWTEXTURE_2D_UINT4, - HLSL_RWTEXTURE_2D_ARRAY_UINT4, - HLSL_RWTEXTURE_3D_UINT4, - HLSL_RWTEXTURE_2D_INT4, - HLSL_RWTEXTURE_2D_ARRAY_INT4, - HLSL_RWTEXTURE_3D_INT4, - - HLSL_RWTEXTURE_UNKNOWN, - HLSL_RWTEXTURE_MAX = HLSL_RWTEXTURE_UNKNOWN -}; - -HLSLTextureGroup TextureGroup(const TBasicType type, - TLayoutImageInternalFormat imageInternalFormat = EiifUnspecified); -TString TextureString(const HLSLTextureGroup textureGroup); -TString TextureString(const TBasicType type, - TLayoutImageInternalFormat imageInternalFormat = EiifUnspecified); -TString TextureGroupSuffix(const HLSLTextureGroup type); -TString TextureGroupSuffix(const TBasicType type, - TLayoutImageInternalFormat imageInternalFormat = EiifUnspecified); -TString TextureTypeSuffix(const TBasicType type, - TLayoutImageInternalFormat imageInternalFormat = EiifUnspecified); -HLSLRWTextureGroup RWTextureGroup(const TBasicType type, - TLayoutImageInternalFormat imageInternalFormat); -TString RWTextureString(const HLSLRWTextureGroup textureGroup); -TString RWTextureString(const TBasicType type, TLayoutImageInternalFormat imageInternalFormat); -TString RWTextureGroupSuffix(const HLSLRWTextureGroup type); -TString RWTextureGroupSuffix(const TBasicType type, TLayoutImageInternalFormat imageInternalFormat); -TString RWTextureTypeSuffix(const TBasicType type, TLayoutImageInternalFormat imageInternalFormat); - -TString SamplerString(const TBasicType type); -TString SamplerString(HLSLTextureGroup type); - -// Adds a prefix to user-defined names to avoid naming clashes. -TString Decorate(const TString &string); -TString DecorateVariableIfNeeded(const TName &name); -TString DecorateFunctionIfNeeded(const TName &name); -TString DecorateField(const TString &string, const TStructure &structure); -TString DecoratePrivate(const TString &privateText); -TString TypeString(const TType &type); -TString StructNameString(const TStructure &structure); -TString QualifiedStructNameString(const TStructure &structure, - bool useHLSLRowMajorPacking, - bool useStd140Packing); -TString InterpolationString(TQualifier qualifier); -TString QualifierString(TQualifier qualifier); -// Parameters may need to be included in function names to disambiguate between overloaded -// functions. -TString DisambiguateFunctionName(const TIntermSequence *parameters); -} - -#endif // COMPILER_TRANSLATOR_UTILSHLSL_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/ValidateGlobalInitializer.cpp b/src/3rdparty/angle/src/compiler/translator/ValidateGlobalInitializer.cpp deleted file mode 100644 index 492972b60d..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/ValidateGlobalInitializer.cpp +++ /dev/null @@ -1,120 +0,0 @@ -// -// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/translator/ValidateGlobalInitializer.h" - -#include "compiler/translator/IntermTraverse.h" -#include "compiler/translator/ParseContext.h" - -namespace sh -{ - -namespace -{ - -class ValidateGlobalInitializerTraverser : public TIntermTraverser -{ - public: - ValidateGlobalInitializerTraverser(const TParseContext *context); - - void visitSymbol(TIntermSymbol *node) override; - bool visitAggregate(Visit visit, TIntermAggregate *node) override; - bool visitBinary(Visit visit, TIntermBinary *node) override; - bool visitUnary(Visit visit, TIntermUnary *node) override; - - bool isValid() const { return mIsValid; } - bool issueWarning() const { return mIssueWarning; } - - private: - const TParseContext *mContext; - bool mIsValid; - bool mIssueWarning; -}; - -void ValidateGlobalInitializerTraverser::visitSymbol(TIntermSymbol *node) -{ - const TSymbol *sym = - mContext->symbolTable.find(node->getSymbol(), mContext->getShaderVersion()); - if (sym->isVariable()) - { - // ESSL 1.00 section 4.3 (or ESSL 3.00 section 4.3): - // Global initializers must be constant expressions. - const TVariable *var = static_cast(sym); - switch (var->getType().getQualifier()) - { - case EvqConst: - break; - case EvqGlobal: - case EvqTemporary: - case EvqUniform: - // We allow these cases to be compatible with legacy ESSL 1.00 content. - // Implement stricter rules for ESSL 3.00 since there's no legacy content to deal - // with. - if (mContext->getShaderVersion() >= 300) - { - mIsValid = false; - } - else - { - mIssueWarning = true; - } - break; - default: - mIsValid = false; - } - } -} - -bool ValidateGlobalInitializerTraverser::visitAggregate(Visit visit, TIntermAggregate *node) -{ - // Disallow calls to user-defined functions and texture lookup functions in global variable - // initializers. - // This is done simply by disabling all function calls - built-in math functions don't use - // the function call ops. - if (node->isFunctionCall()) - { - mIsValid = false; - } - return true; -} - -bool ValidateGlobalInitializerTraverser::visitBinary(Visit visit, TIntermBinary *node) -{ - if (node->isAssignment()) - { - mIsValid = false; - } - return true; -} - -bool ValidateGlobalInitializerTraverser::visitUnary(Visit visit, TIntermUnary *node) -{ - if (node->isAssignment()) - { - mIsValid = false; - } - return true; -} - -ValidateGlobalInitializerTraverser::ValidateGlobalInitializerTraverser(const TParseContext *context) - : TIntermTraverser(true, false, false), mContext(context), mIsValid(true), mIssueWarning(false) -{ -} - -} // namespace - -bool ValidateGlobalInitializer(TIntermTyped *initializer, - const TParseContext *context, - bool *warning) -{ - ValidateGlobalInitializerTraverser validate(context); - initializer->traverse(&validate); - ASSERT(warning != nullptr); - *warning = validate.issueWarning(); - return validate.isValid(); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/ValidateGlobalInitializer.h b/src/3rdparty/angle/src/compiler/translator/ValidateGlobalInitializer.h deleted file mode 100644 index 2e7570667a..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/ValidateGlobalInitializer.h +++ /dev/null @@ -1,23 +0,0 @@ -// -// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_TRANSLATOR_VALIDATEGLOBALINITIALIZER_H_ -#define COMPILER_TRANSLATOR_VALIDATEGLOBALINITIALIZER_H_ - -namespace sh -{ - -class TIntermTyped; -class TParseContext; - -// Returns true if the initializer is valid. -bool ValidateGlobalInitializer(TIntermTyped *initializer, - const TParseContext *context, - bool *warning); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_VALIDATEGLOBALINITIALIZER_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/ValidateLimitations.cpp b/src/3rdparty/angle/src/compiler/translator/ValidateLimitations.cpp deleted file mode 100644 index 941f79ae51..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/ValidateLimitations.cpp +++ /dev/null @@ -1,444 +0,0 @@ -// -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/translator/ValidateLimitations.h" - -#include "angle_gl.h" -#include "compiler/translator/Diagnostics.h" -#include "compiler/translator/IntermTraverse.h" -#include "compiler/translator/ParseContext.h" - -namespace sh -{ - -namespace -{ - -int GetLoopSymbolId(TIntermLoop *loop) -{ - // Here we assume all the operations are valid, because the loop node is - // already validated before this call. - TIntermSequence *declSeq = loop->getInit()->getAsDeclarationNode()->getSequence(); - TIntermBinary *declInit = (*declSeq)[0]->getAsBinaryNode(); - TIntermSymbol *symbol = declInit->getLeft()->getAsSymbolNode(); - - return symbol->getId(); -} - -// Traverses a node to check if it represents a constant index expression. -// Definition: -// constant-index-expressions are a superset of constant-expressions. -// Constant-index-expressions can include loop indices as defined in -// GLSL ES 1.0 spec, Appendix A, section 4. -// The following are constant-index-expressions: -// - Constant expressions -// - Loop indices as defined in section 4 -// - Expressions composed of both of the above -class ValidateConstIndexExpr : public TIntermTraverser -{ - public: - ValidateConstIndexExpr(const std::vector &loopSymbols) - : TIntermTraverser(true, false, false), mValid(true), mLoopSymbolIds(loopSymbols) - { - } - - // Returns true if the parsed node represents a constant index expression. - bool isValid() const { return mValid; } - - void visitSymbol(TIntermSymbol *symbol) override - { - // Only constants and loop indices are allowed in a - // constant index expression. - if (mValid) - { - bool isLoopSymbol = std::find(mLoopSymbolIds.begin(), mLoopSymbolIds.end(), - symbol->getId()) != mLoopSymbolIds.end(); - mValid = (symbol->getQualifier() == EvqConst) || isLoopSymbol; - } - } - - private: - bool mValid; - const std::vector mLoopSymbolIds; -}; - -// Traverses intermediate tree to ensure that the shader does not exceed the -// minimum functionality mandated in GLSL 1.0 spec, Appendix A. -class ValidateLimitationsTraverser : public TLValueTrackingTraverser -{ - public: - ValidateLimitationsTraverser(sh::GLenum shaderType, - TSymbolTable *symbolTable, - int shaderVersion, - TDiagnostics *diagnostics); - - void visitSymbol(TIntermSymbol *node) override; - bool visitBinary(Visit, TIntermBinary *) override; - bool visitLoop(Visit, TIntermLoop *) override; - - private: - void error(TSourceLoc loc, const char *reason, const char *token); - - bool withinLoopBody() const; - bool isLoopIndex(TIntermSymbol *symbol); - bool validateLoopType(TIntermLoop *node); - - bool validateForLoopHeader(TIntermLoop *node); - // If valid, return the index symbol id; Otherwise, return -1. - int validateForLoopInit(TIntermLoop *node); - bool validateForLoopCond(TIntermLoop *node, int indexSymbolId); - bool validateForLoopExpr(TIntermLoop *node, int indexSymbolId); - - // Returns true if indexing does not exceed the minimum functionality - // mandated in GLSL 1.0 spec, Appendix A, Section 5. - bool isConstExpr(TIntermNode *node); - bool isConstIndexExpr(TIntermNode *node); - bool validateIndexing(TIntermBinary *node); - - sh::GLenum mShaderType; - TDiagnostics *mDiagnostics; - std::vector mLoopSymbolIds; -}; - -ValidateLimitationsTraverser::ValidateLimitationsTraverser(sh::GLenum shaderType, - TSymbolTable *symbolTable, - int shaderVersion, - TDiagnostics *diagnostics) - : TLValueTrackingTraverser(true, false, false, symbolTable, shaderVersion), - mShaderType(shaderType), - mDiagnostics(diagnostics) -{ - ASSERT(diagnostics); -} - -void ValidateLimitationsTraverser::visitSymbol(TIntermSymbol *node) -{ - if (isLoopIndex(node) && isLValueRequiredHere()) - { - error(node->getLine(), - "Loop index cannot be statically assigned to within the body of the loop", - node->getSymbol().c_str()); - } -} - -bool ValidateLimitationsTraverser::visitBinary(Visit, TIntermBinary *node) -{ - // Check indexing. - switch (node->getOp()) - { - case EOpIndexDirect: - case EOpIndexIndirect: - validateIndexing(node); - break; - default: - break; - } - return true; -} - -bool ValidateLimitationsTraverser::visitLoop(Visit, TIntermLoop *node) -{ - if (!validateLoopType(node)) - return false; - - if (!validateForLoopHeader(node)) - return false; - - TIntermNode *body = node->getBody(); - if (body != nullptr) - { - mLoopSymbolIds.push_back(GetLoopSymbolId(node)); - body->traverse(this); - mLoopSymbolIds.pop_back(); - } - - // The loop is fully processed - no need to visit children. - return false; -} - -void ValidateLimitationsTraverser::error(TSourceLoc loc, const char *reason, const char *token) -{ - mDiagnostics->error(loc, reason, token); -} - -bool ValidateLimitationsTraverser::withinLoopBody() const -{ - return !mLoopSymbolIds.empty(); -} - -bool ValidateLimitationsTraverser::isLoopIndex(TIntermSymbol *symbol) -{ - return std::find(mLoopSymbolIds.begin(), mLoopSymbolIds.end(), symbol->getId()) != - mLoopSymbolIds.end(); -} - -bool ValidateLimitationsTraverser::validateLoopType(TIntermLoop *node) -{ - TLoopType type = node->getType(); - if (type == ELoopFor) - return true; - - // Reject while and do-while loops. - error(node->getLine(), "This type of loop is not allowed", type == ELoopWhile ? "while" : "do"); - return false; -} - -bool ValidateLimitationsTraverser::validateForLoopHeader(TIntermLoop *node) -{ - ASSERT(node->getType() == ELoopFor); - - // - // The for statement has the form: - // for ( init-declaration ; condition ; expression ) statement - // - int indexSymbolId = validateForLoopInit(node); - if (indexSymbolId < 0) - return false; - if (!validateForLoopCond(node, indexSymbolId)) - return false; - if (!validateForLoopExpr(node, indexSymbolId)) - return false; - - return true; -} - -int ValidateLimitationsTraverser::validateForLoopInit(TIntermLoop *node) -{ - TIntermNode *init = node->getInit(); - if (init == nullptr) - { - error(node->getLine(), "Missing init declaration", "for"); - return -1; - } - - // - // init-declaration has the form: - // type-specifier identifier = constant-expression - // - TIntermDeclaration *decl = init->getAsDeclarationNode(); - if (decl == nullptr) - { - error(init->getLine(), "Invalid init declaration", "for"); - return -1; - } - // To keep things simple do not allow declaration list. - TIntermSequence *declSeq = decl->getSequence(); - if (declSeq->size() != 1) - { - error(decl->getLine(), "Invalid init declaration", "for"); - return -1; - } - TIntermBinary *declInit = (*declSeq)[0]->getAsBinaryNode(); - if ((declInit == nullptr) || (declInit->getOp() != EOpInitialize)) - { - error(decl->getLine(), "Invalid init declaration", "for"); - return -1; - } - TIntermSymbol *symbol = declInit->getLeft()->getAsSymbolNode(); - if (symbol == nullptr) - { - error(declInit->getLine(), "Invalid init declaration", "for"); - return -1; - } - // The loop index has type int or float. - TBasicType type = symbol->getBasicType(); - if ((type != EbtInt) && (type != EbtUInt) && (type != EbtFloat)) - { - error(symbol->getLine(), "Invalid type for loop index", getBasicString(type)); - return -1; - } - // The loop index is initialized with constant expression. - if (!isConstExpr(declInit->getRight())) - { - error(declInit->getLine(), "Loop index cannot be initialized with non-constant expression", - symbol->getSymbol().c_str()); - return -1; - } - - return symbol->getId(); -} - -bool ValidateLimitationsTraverser::validateForLoopCond(TIntermLoop *node, int indexSymbolId) -{ - TIntermNode *cond = node->getCondition(); - if (cond == nullptr) - { - error(node->getLine(), "Missing condition", "for"); - return false; - } - // - // condition has the form: - // loop_index relational_operator constant_expression - // - TIntermBinary *binOp = cond->getAsBinaryNode(); - if (binOp == nullptr) - { - error(node->getLine(), "Invalid condition", "for"); - return false; - } - // Loop index should be to the left of relational operator. - TIntermSymbol *symbol = binOp->getLeft()->getAsSymbolNode(); - if (symbol == nullptr) - { - error(binOp->getLine(), "Invalid condition", "for"); - return false; - } - if (symbol->getId() != indexSymbolId) - { - error(symbol->getLine(), "Expected loop index", symbol->getSymbol().c_str()); - return false; - } - // Relational operator is one of: > >= < <= == or !=. - switch (binOp->getOp()) - { - case EOpEqual: - case EOpNotEqual: - case EOpLessThan: - case EOpGreaterThan: - case EOpLessThanEqual: - case EOpGreaterThanEqual: - break; - default: - error(binOp->getLine(), "Invalid relational operator", - GetOperatorString(binOp->getOp())); - break; - } - // Loop index must be compared with a constant. - if (!isConstExpr(binOp->getRight())) - { - error(binOp->getLine(), "Loop index cannot be compared with non-constant expression", - symbol->getSymbol().c_str()); - return false; - } - - return true; -} - -bool ValidateLimitationsTraverser::validateForLoopExpr(TIntermLoop *node, int indexSymbolId) -{ - TIntermNode *expr = node->getExpression(); - if (expr == nullptr) - { - error(node->getLine(), "Missing expression", "for"); - return false; - } - - // for expression has one of the following forms: - // loop_index++ - // loop_index-- - // loop_index += constant_expression - // loop_index -= constant_expression - // ++loop_index - // --loop_index - // The last two forms are not specified in the spec, but I am assuming - // its an oversight. - TIntermUnary *unOp = expr->getAsUnaryNode(); - TIntermBinary *binOp = unOp ? nullptr : expr->getAsBinaryNode(); - - TOperator op = EOpNull; - TIntermSymbol *symbol = nullptr; - if (unOp != nullptr) - { - op = unOp->getOp(); - symbol = unOp->getOperand()->getAsSymbolNode(); - } - else if (binOp != nullptr) - { - op = binOp->getOp(); - symbol = binOp->getLeft()->getAsSymbolNode(); - } - - // The operand must be loop index. - if (symbol == nullptr) - { - error(expr->getLine(), "Invalid expression", "for"); - return false; - } - if (symbol->getId() != indexSymbolId) - { - error(symbol->getLine(), "Expected loop index", symbol->getSymbol().c_str()); - return false; - } - - // The operator is one of: ++ -- += -=. - switch (op) - { - case EOpPostIncrement: - case EOpPostDecrement: - case EOpPreIncrement: - case EOpPreDecrement: - ASSERT((unOp != nullptr) && (binOp == nullptr)); - break; - case EOpAddAssign: - case EOpSubAssign: - ASSERT((unOp == nullptr) && (binOp != nullptr)); - break; - default: - error(expr->getLine(), "Invalid operator", GetOperatorString(op)); - return false; - } - - // Loop index must be incremented/decremented with a constant. - if (binOp != nullptr) - { - if (!isConstExpr(binOp->getRight())) - { - error(binOp->getLine(), "Loop index cannot be modified by non-constant expression", - symbol->getSymbol().c_str()); - return false; - } - } - - return true; -} - -bool ValidateLimitationsTraverser::isConstExpr(TIntermNode *node) -{ - ASSERT(node != nullptr); - return node->getAsConstantUnion() != nullptr && node->getAsTyped()->getQualifier() == EvqConst; -} - -bool ValidateLimitationsTraverser::isConstIndexExpr(TIntermNode *node) -{ - ASSERT(node != nullptr); - - ValidateConstIndexExpr validate(mLoopSymbolIds); - node->traverse(&validate); - return validate.isValid(); -} - -bool ValidateLimitationsTraverser::validateIndexing(TIntermBinary *node) -{ - ASSERT((node->getOp() == EOpIndexDirect) || (node->getOp() == EOpIndexIndirect)); - - bool valid = true; - TIntermTyped *index = node->getRight(); - // The index expession must be a constant-index-expression unless - // the operand is a uniform in a vertex shader. - TIntermTyped *operand = node->getLeft(); - bool skip = (mShaderType == GL_VERTEX_SHADER) && (operand->getQualifier() == EvqUniform); - if (!skip && !isConstIndexExpr(index)) - { - error(index->getLine(), "Index expression must be constant", "[]"); - valid = false; - } - return valid; -} - -} // namespace anonymous - -bool ValidateLimitations(TIntermNode *root, - GLenum shaderType, - TSymbolTable *symbolTable, - int shaderVersion, - TDiagnostics *diagnostics) -{ - ValidateLimitationsTraverser validate(shaderType, symbolTable, shaderVersion, diagnostics); - root->traverse(&validate); - return diagnostics->numErrors() == 0; -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/ValidateLimitations.h b/src/3rdparty/angle/src/compiler/translator/ValidateLimitations.h deleted file mode 100644 index 9149b8c216..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/ValidateLimitations.h +++ /dev/null @@ -1,27 +0,0 @@ -// -// Copyright (c) 2010 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_TRANSLATOR_VALIDATELIMITATIONS_H_ -#define COMPILER_TRANSLATOR_VALIDATELIMITATIONS_H_ - -#include "compiler/translator/IntermNode.h" - -namespace sh -{ - -class TDiagnostics; - -// Returns true if the given shader does not exceed the minimum functionality mandated in GLSL ES -// 1.00 spec Appendix A. -bool ValidateLimitations(TIntermNode *root, - GLenum shaderType, - TSymbolTable *symbolTable, - int shaderVersion, - TDiagnostics *diagnostics); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_VALIDATELIMITATIONS_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/ValidateMaxParameters.cpp b/src/3rdparty/angle/src/compiler/translator/ValidateMaxParameters.cpp deleted file mode 100644 index 9dccbf413f..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/ValidateMaxParameters.cpp +++ /dev/null @@ -1,29 +0,0 @@ -// -// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// ValidateMaxParameters checks if function definitions have more than a set number of parameters. - -#include "compiler/translator/ValidateMaxParameters.h" - -#include "compiler/translator/IntermNode.h" - -namespace sh -{ - -bool ValidateMaxParameters(TIntermBlock *root, unsigned int maxParameters) -{ - for (TIntermNode *node : *root->getSequence()) - { - TIntermFunctionDefinition *definition = node->getAsFunctionDefinition(); - if (definition != nullptr && - definition->getFunctionPrototype()->getSequence()->size() > maxParameters) - { - return false; - } - } - return true; -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/ValidateMaxParameters.h b/src/3rdparty/angle/src/compiler/translator/ValidateMaxParameters.h deleted file mode 100644 index dec7597da4..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/ValidateMaxParameters.h +++ /dev/null @@ -1,21 +0,0 @@ -// -// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// ValidateMaxParameters checks if function definitions have more than a set number of parameters. - -#ifndef COMPILER_TRANSLATOR_VALIDATEMAXPARAMETERS_H_ -#define COMPILER_TRANSLATOR_VALIDATEMAXPARAMETERS_H_ - -namespace sh -{ - -class TIntermBlock; - -// Return true if valid. -bool ValidateMaxParameters(TIntermBlock *root, unsigned int maxParameters); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_VALIDATEMAXPARAMETERS_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/ValidateOutputs.cpp b/src/3rdparty/angle/src/compiler/translator/ValidateOutputs.cpp deleted file mode 100644 index 26f0e81ba7..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/ValidateOutputs.cpp +++ /dev/null @@ -1,174 +0,0 @@ -// -// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// ValidateOutputs validates fragment shader outputs. It checks for conflicting locations, -// out-of-range locations, that locations are specified when using multiple outputs, and YUV output -// validity. - -#include "compiler/translator/ValidateOutputs.h" - -#include - -#include "compiler/translator/InfoSink.h" -#include "compiler/translator/IntermTraverse.h" -#include "compiler/translator/ParseContext.h" - -namespace sh -{ - -namespace -{ -void error(const TIntermSymbol &symbol, const char *reason, TDiagnostics *diagnostics) -{ - diagnostics->error(symbol.getLine(), reason, symbol.getSymbol().c_str()); -} - -class ValidateOutputsTraverser : public TIntermTraverser -{ - public: - ValidateOutputsTraverser(const TExtensionBehavior &extBehavior, int maxDrawBuffers); - - void validate(TDiagnostics *diagnostics) const; - - void visitSymbol(TIntermSymbol *) override; - - private: - int mMaxDrawBuffers; - bool mAllowUnspecifiedOutputLocationResolution; - bool mUsesFragDepth; - - typedef std::vector OutputVector; - OutputVector mOutputs; - OutputVector mUnspecifiedLocationOutputs; - OutputVector mYuvOutputs; - std::set mVisitedSymbols; -}; - -ValidateOutputsTraverser::ValidateOutputsTraverser(const TExtensionBehavior &extBehavior, - int maxDrawBuffers) - : TIntermTraverser(true, false, false), - mMaxDrawBuffers(maxDrawBuffers), - mAllowUnspecifiedOutputLocationResolution( - IsExtensionEnabled(extBehavior, TExtension::EXT_blend_func_extended)), - mUsesFragDepth(false) -{ -} - -void ValidateOutputsTraverser::visitSymbol(TIntermSymbol *symbol) -{ - TString name = symbol->getSymbol(); - TQualifier qualifier = symbol->getQualifier(); - - if (mVisitedSymbols.count(name.c_str()) == 1) - return; - - mVisitedSymbols.insert(name.c_str()); - - if (qualifier == EvqFragmentOut) - { - if (symbol->getType().getLayoutQualifier().location != -1) - { - mOutputs.push_back(symbol); - } - else if (symbol->getType().getLayoutQualifier().yuv == true) - { - mYuvOutputs.push_back(symbol); - } - else - { - mUnspecifiedLocationOutputs.push_back(symbol); - } - } - else if (qualifier == EvqFragDepth || qualifier == EvqFragDepthEXT) - { - mUsesFragDepth = true; - } -} - -void ValidateOutputsTraverser::validate(TDiagnostics *diagnostics) const -{ - ASSERT(diagnostics); - OutputVector validOutputs(mMaxDrawBuffers); - - for (const auto &symbol : mOutputs) - { - const TType &type = symbol->getType(); - ASSERT(!type.isArrayOfArrays()); // Disallowed in GLSL ES 3.10 section 4.3.6. - const size_t elementCount = - static_cast(type.isArray() ? type.getOutermostArraySize() : 1u); - const size_t location = static_cast(type.getLayoutQualifier().location); - - ASSERT(type.getLayoutQualifier().location != -1); - - if (location + elementCount <= validOutputs.size()) - { - for (size_t elementIndex = 0; elementIndex < elementCount; elementIndex++) - { - const size_t offsetLocation = location + elementIndex; - if (validOutputs[offsetLocation]) - { - std::stringstream strstr; - strstr << "conflicting output locations with previously defined output '" - << validOutputs[offsetLocation]->getSymbol() << "'"; - error(*symbol, strstr.str().c_str(), diagnostics); - } - else - { - validOutputs[offsetLocation] = symbol; - } - } - } - else - { - if (elementCount > 0) - { - error(*symbol, - elementCount > 1 ? "output array locations would exceed MAX_DRAW_BUFFERS" - : "output location must be < MAX_DRAW_BUFFERS", - diagnostics); - } - } - } - - if (!mAllowUnspecifiedOutputLocationResolution && - ((!mOutputs.empty() && !mUnspecifiedLocationOutputs.empty()) || - mUnspecifiedLocationOutputs.size() > 1)) - { - for (const auto &symbol : mUnspecifiedLocationOutputs) - { - error(*symbol, - "must explicitly specify all locations when using multiple fragment outputs", - diagnostics); - } - } - - if (!mYuvOutputs.empty() && (mYuvOutputs.size() > 1 || mUsesFragDepth || !mOutputs.empty() || - !mUnspecifiedLocationOutputs.empty())) - { - for (const auto &symbol : mYuvOutputs) - { - error(*symbol, - "not allowed to specify yuv qualifier when using depth or multiple color " - "fragment outputs", - diagnostics); - } - } -} - -} // anonymous namespace - -bool ValidateOutputs(TIntermBlock *root, - const TExtensionBehavior &extBehavior, - int maxDrawBuffers, - TDiagnostics *diagnostics) -{ - ValidateOutputsTraverser validateOutputs(extBehavior, maxDrawBuffers); - root->traverse(&validateOutputs); - int numErrorsBefore = diagnostics->numErrors(); - validateOutputs.validate(diagnostics); - return (diagnostics->numErrors() == numErrorsBefore); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/ValidateOutputs.h b/src/3rdparty/angle/src/compiler/translator/ValidateOutputs.h deleted file mode 100644 index e41ccd990c..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/ValidateOutputs.h +++ /dev/null @@ -1,30 +0,0 @@ -// -// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// ValidateOutputs validates fragment shader outputs. It checks for conflicting locations, -// out-of-range locations, that locations are specified when using multiple outputs, and YUV output -// validity. -// - -#ifndef COMPILER_TRANSLATOR_VALIDATEOUTPUTS_H_ -#define COMPILER_TRANSLATOR_VALIDATEOUTPUTS_H_ - -#include "compiler/translator/ExtensionBehavior.h" - -namespace sh -{ - -class TIntermBlock; -class TDiagnostics; - -// Returns true if the shader has no conflicting or otherwise erroneous fragment outputs. -bool ValidateOutputs(TIntermBlock *root, - const TExtensionBehavior &extBehavior, - int maxDrawBuffers, - TDiagnostics *diagnostics); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_VALIDATEOUTPUTS_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/ValidateSwitch.cpp b/src/3rdparty/angle/src/compiler/translator/ValidateSwitch.cpp deleted file mode 100644 index 9f7a264e58..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/ValidateSwitch.cpp +++ /dev/null @@ -1,319 +0,0 @@ -// -// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/translator/ValidateSwitch.h" - -#include "compiler/translator/Diagnostics.h" -#include "compiler/translator/IntermTraverse.h" - -namespace sh -{ - -namespace -{ - -class ValidateSwitch : public TIntermTraverser -{ - public: - static bool validate(TBasicType switchType, - int shaderVersion, - TDiagnostics *diagnostics, - TIntermBlock *statementList, - const TSourceLoc &loc); - - void visitSymbol(TIntermSymbol *) override; - void visitConstantUnion(TIntermConstantUnion *) override; - bool visitDeclaration(Visit, TIntermDeclaration *) override; - bool visitBlock(Visit, TIntermBlock *) override; - bool visitBinary(Visit, TIntermBinary *) override; - bool visitUnary(Visit, TIntermUnary *) override; - bool visitTernary(Visit, TIntermTernary *) override; - bool visitSwizzle(Visit, TIntermSwizzle *) override; - bool visitIfElse(Visit visit, TIntermIfElse *) override; - bool visitSwitch(Visit, TIntermSwitch *) override; - bool visitCase(Visit, TIntermCase *node) override; - bool visitAggregate(Visit, TIntermAggregate *) override; - bool visitLoop(Visit visit, TIntermLoop *) override; - bool visitBranch(Visit, TIntermBranch *) override; - - private: - ValidateSwitch(TBasicType switchType, int shaderVersion, TDiagnostics *context); - - bool validateInternal(const TSourceLoc &loc); - - TBasicType mSwitchType; - int mShaderVersion; - TDiagnostics *mDiagnostics; - bool mCaseTypeMismatch; - bool mFirstCaseFound; - bool mStatementBeforeCase; - bool mLastStatementWasCase; - int mControlFlowDepth; - bool mCaseInsideControlFlow; - int mDefaultCount; - std::set mCasesSigned; - std::set mCasesUnsigned; - bool mDuplicateCases; -}; - -bool ValidateSwitch::validate(TBasicType switchType, - int shaderVersion, - TDiagnostics *diagnostics, - TIntermBlock *statementList, - const TSourceLoc &loc) -{ - ValidateSwitch validate(switchType, shaderVersion, diagnostics); - ASSERT(statementList); - statementList->traverse(&validate); - return validate.validateInternal(loc); -} - -ValidateSwitch::ValidateSwitch(TBasicType switchType, int shaderVersion, TDiagnostics *diagnostics) - : TIntermTraverser(true, false, true), - mSwitchType(switchType), - mShaderVersion(shaderVersion), - mDiagnostics(diagnostics), - mCaseTypeMismatch(false), - mFirstCaseFound(false), - mStatementBeforeCase(false), - mLastStatementWasCase(false), - mControlFlowDepth(0), - mCaseInsideControlFlow(false), - mDefaultCount(0), - mDuplicateCases(false) -{ -} - -void ValidateSwitch::visitSymbol(TIntermSymbol *) -{ - if (!mFirstCaseFound) - mStatementBeforeCase = true; - mLastStatementWasCase = false; -} - -void ValidateSwitch::visitConstantUnion(TIntermConstantUnion *) -{ - // Conditions of case labels are not traversed, so this is some other constant - // Could be just a statement like "0;" - if (!mFirstCaseFound) - mStatementBeforeCase = true; - mLastStatementWasCase = false; -} - -bool ValidateSwitch::visitDeclaration(Visit, TIntermDeclaration *) -{ - if (!mFirstCaseFound) - mStatementBeforeCase = true; - mLastStatementWasCase = false; - return true; -} - -bool ValidateSwitch::visitBlock(Visit, TIntermBlock *) -{ - if (getParentNode() != nullptr) - { - if (!mFirstCaseFound) - mStatementBeforeCase = true; - mLastStatementWasCase = false; - } - return true; -} - -bool ValidateSwitch::visitBinary(Visit, TIntermBinary *) -{ - if (!mFirstCaseFound) - mStatementBeforeCase = true; - mLastStatementWasCase = false; - return true; -} - -bool ValidateSwitch::visitUnary(Visit, TIntermUnary *) -{ - if (!mFirstCaseFound) - mStatementBeforeCase = true; - mLastStatementWasCase = false; - return true; -} - -bool ValidateSwitch::visitTernary(Visit, TIntermTernary *) -{ - if (!mFirstCaseFound) - mStatementBeforeCase = true; - mLastStatementWasCase = false; - return true; -} - -bool ValidateSwitch::visitSwizzle(Visit, TIntermSwizzle *) -{ - if (!mFirstCaseFound) - mStatementBeforeCase = true; - mLastStatementWasCase = false; - return true; -} - -bool ValidateSwitch::visitIfElse(Visit visit, TIntermIfElse *) -{ - if (visit == PreVisit) - ++mControlFlowDepth; - if (visit == PostVisit) - --mControlFlowDepth; - if (!mFirstCaseFound) - mStatementBeforeCase = true; - mLastStatementWasCase = false; - return true; -} - -bool ValidateSwitch::visitSwitch(Visit, TIntermSwitch *) -{ - if (!mFirstCaseFound) - mStatementBeforeCase = true; - mLastStatementWasCase = false; - // Don't go into nested switch statements - return false; -} - -bool ValidateSwitch::visitCase(Visit, TIntermCase *node) -{ - const char *nodeStr = node->hasCondition() ? "case" : "default"; - if (mControlFlowDepth > 0) - { - mDiagnostics->error(node->getLine(), "label statement nested inside control flow", nodeStr); - mCaseInsideControlFlow = true; - } - mFirstCaseFound = true; - mLastStatementWasCase = true; - if (!node->hasCondition()) - { - ++mDefaultCount; - if (mDefaultCount > 1) - { - mDiagnostics->error(node->getLine(), "duplicate default label", nodeStr); - } - } - else - { - TIntermConstantUnion *condition = node->getCondition()->getAsConstantUnion(); - if (condition == nullptr) - { - // This can happen in error cases. - return false; - } - TBasicType conditionType = condition->getBasicType(); - if (conditionType != mSwitchType) - { - mDiagnostics->error(condition->getLine(), - "case label type does not match switch init-expression type", - nodeStr); - mCaseTypeMismatch = true; - } - - if (conditionType == EbtInt) - { - int iConst = condition->getIConst(0); - if (mCasesSigned.find(iConst) != mCasesSigned.end()) - { - mDiagnostics->error(condition->getLine(), "duplicate case label", nodeStr); - mDuplicateCases = true; - } - else - { - mCasesSigned.insert(iConst); - } - } - else if (conditionType == EbtUInt) - { - unsigned int uConst = condition->getUConst(0); - if (mCasesUnsigned.find(uConst) != mCasesUnsigned.end()) - { - mDiagnostics->error(condition->getLine(), "duplicate case label", nodeStr); - mDuplicateCases = true; - } - else - { - mCasesUnsigned.insert(uConst); - } - } - // Other types are possible only in error cases, where the error has already been generated - // when parsing the case statement. - } - // Don't traverse the condition of the case statement - return false; -} - -bool ValidateSwitch::visitAggregate(Visit visit, TIntermAggregate *) -{ - if (getParentNode() != nullptr) - { - // This is not the statementList node, but some other node. - if (!mFirstCaseFound) - mStatementBeforeCase = true; - mLastStatementWasCase = false; - } - return true; -} - -bool ValidateSwitch::visitLoop(Visit visit, TIntermLoop *) -{ - if (visit == PreVisit) - ++mControlFlowDepth; - if (visit == PostVisit) - --mControlFlowDepth; - if (!mFirstCaseFound) - mStatementBeforeCase = true; - mLastStatementWasCase = false; - return true; -} - -bool ValidateSwitch::visitBranch(Visit, TIntermBranch *) -{ - if (!mFirstCaseFound) - mStatementBeforeCase = true; - mLastStatementWasCase = false; - return true; -} - -bool ValidateSwitch::validateInternal(const TSourceLoc &loc) -{ - if (mStatementBeforeCase) - { - mDiagnostics->error(loc, "statement before the first label", "switch"); - } - bool lastStatementWasCaseError = false; - if (mLastStatementWasCase) - { - if (mShaderVersion == 300) - { - lastStatementWasCaseError = true; - // This error has been proposed to be made optional in GLSL ES 3.00, but dEQP tests - // still require it. - mDiagnostics->error( - loc, "no statement between the last label and the end of the switch statement", - "switch"); - } - else - { - // The error has been removed from GLSL ES 3.10. - mDiagnostics->warning( - loc, "no statement between the last label and the end of the switch statement", - "switch"); - } - } - return !mStatementBeforeCase && !lastStatementWasCaseError && !mCaseInsideControlFlow && - !mCaseTypeMismatch && mDefaultCount <= 1 && !mDuplicateCases; -} - -} // anonymous namespace - -bool ValidateSwitchStatementList(TBasicType switchType, - int shaderVersion, - TDiagnostics *diagnostics, - TIntermBlock *statementList, - const TSourceLoc &loc) -{ - return ValidateSwitch::validate(switchType, shaderVersion, diagnostics, statementList, loc); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/ValidateSwitch.h b/src/3rdparty/angle/src/compiler/translator/ValidateSwitch.h deleted file mode 100644 index 2d2dd70f78..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/ValidateSwitch.h +++ /dev/null @@ -1,28 +0,0 @@ -// -// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_TRANSLATOR_VALIDATESWITCH_H_ -#define COMPILER_TRANSLATOR_VALIDATESWITCH_H_ - -#include "compiler/translator/BaseTypes.h" -#include "compiler/translator/Common.h" - -namespace sh -{ -class TDiagnostics; -class TIntermBlock; - -// Check for errors and output error messages on the context. -// Returns true if there are no errors. -bool ValidateSwitchStatementList(TBasicType switchType, - int shaderVersion, - TDiagnostics *diagnostics, - TIntermBlock *statementList, - const TSourceLoc &loc); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_VALIDATESWITCH_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/ValidateVaryingLocations.cpp b/src/3rdparty/angle/src/compiler/translator/ValidateVaryingLocations.cpp deleted file mode 100644 index 9c36fcea78..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/ValidateVaryingLocations.cpp +++ /dev/null @@ -1,174 +0,0 @@ -// -// Copyright (c) 2002-2017 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// The ValidateVaryingLocations function checks if there exists location conflicts on shader -// varyings. -// - -#include "ValidateVaryingLocations.h" - -#include "compiler/translator/Diagnostics.h" -#include "compiler/translator/IntermTraverse.h" -#include "compiler/translator/util.h" - -namespace sh -{ - -namespace -{ - -void error(const TIntermSymbol &symbol, const char *reason, TDiagnostics *diagnostics) -{ - diagnostics->error(symbol.getLine(), reason, symbol.getSymbol().c_str()); -} - -int GetLocationCount(const TIntermSymbol *varying, bool ignoreVaryingArraySize) -{ - const auto &varyingType = varying->getType(); - if (varyingType.getStruct() != nullptr) - { - ASSERT(!varyingType.isArray()); - int totalLocation = 0; - for (const auto *field : varyingType.getStruct()->fields()) - { - const auto *fieldType = field->type(); - ASSERT(fieldType->getStruct() == nullptr && !fieldType->isArray()); - - totalLocation += fieldType->getSecondarySize(); - } - return totalLocation; - } - // [GL_OES_shader_io_blocks SPEC Chapter 4.4.1] - // Geometry shader inputs, tessellation control shader inputs and outputs, and tessellation - // evaluation inputs all have an additional level of arrayness relative to other shader inputs - // and outputs. This outer array level is removed from the type before considering how many - // locations the type consumes. - else if (ignoreVaryingArraySize) - { - // Array-of-arrays cannot be inputs or outputs of a geometry shader. - // (GL_OES_geometry_shader SPEC issues(5)) - ASSERT(!varyingType.isArrayOfArrays()); - return varyingType.getSecondarySize(); - } - else - { - return varyingType.getSecondarySize() * static_cast(varyingType.getArraySizeProduct()); - } -} - -using VaryingVector = std::vector; - -void ValidateShaderInterface(TDiagnostics *diagnostics, - VaryingVector &varyingVector, - bool ignoreVaryingArraySize) -{ - // Location conflicts can only happen when there are two or more varyings in varyingVector. - if (varyingVector.size() <= 1) - { - return; - } - - std::map locationMap; - for (const TIntermSymbol *varying : varyingVector) - { - const int location = varying->getType().getLayoutQualifier().location; - ASSERT(location >= 0); - - const int elementCount = GetLocationCount(varying, ignoreVaryingArraySize); - for (int elementIndex = 0; elementIndex < elementCount; ++elementIndex) - { - const int offsetLocation = location + elementIndex; - if (locationMap.find(offsetLocation) != locationMap.end()) - { - std::stringstream strstr; - strstr << "'" << varying->getSymbol() - << "' conflicting location with previously defined '" - << locationMap[offsetLocation]->getSymbol() << "'"; - error(*varying, strstr.str().c_str(), diagnostics); - } - else - { - locationMap[offsetLocation] = varying; - } - } - } -} - -class ValidateVaryingLocationsTraverser : public TIntermTraverser -{ - public: - ValidateVaryingLocationsTraverser(GLenum shaderType); - void validate(TDiagnostics *diagnostics); - - private: - bool visitDeclaration(Visit visit, TIntermDeclaration *node) override; - bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override; - - VaryingVector mInputVaryingsWithLocation; - VaryingVector mOutputVaryingsWithLocation; - GLenum mShaderType; -}; - -ValidateVaryingLocationsTraverser::ValidateVaryingLocationsTraverser(GLenum shaderType) - : TIntermTraverser(true, false, false), mShaderType(shaderType) -{ -} - -bool ValidateVaryingLocationsTraverser::visitDeclaration(Visit visit, TIntermDeclaration *node) -{ - const TIntermSequence &sequence = *(node->getSequence()); - ASSERT(!sequence.empty()); - - const TIntermSymbol *symbol = sequence.front()->getAsSymbolNode(); - if (symbol == nullptr) - { - return false; - } - - // Collect varyings that have explicit 'location' qualifiers. - const TQualifier qualifier = symbol->getQualifier(); - if (symbol->getType().getLayoutQualifier().location != -1) - { - if (IsVaryingIn(qualifier)) - { - mInputVaryingsWithLocation.push_back(symbol); - } - else if (IsVaryingOut(qualifier)) - { - mOutputVaryingsWithLocation.push_back(symbol); - } - } - - return false; -} - -bool ValidateVaryingLocationsTraverser::visitFunctionDefinition(Visit visit, - TIntermFunctionDefinition *node) -{ - // We stop traversing function definitions because varyings cannot be defined in a function. - return false; -} - -void ValidateVaryingLocationsTraverser::validate(TDiagnostics *diagnostics) -{ - ASSERT(diagnostics); - - ValidateShaderInterface(diagnostics, mInputVaryingsWithLocation, - mShaderType == GL_GEOMETRY_SHADER_OES); - ValidateShaderInterface(diagnostics, mOutputVaryingsWithLocation, false); -} - -} // anonymous namespace - -bool ValidateVaryingLocations(TIntermBlock *root, TDiagnostics *diagnostics, GLenum shaderType) -{ - ValidateVaryingLocationsTraverser varyingValidator(shaderType); - root->traverse(&varyingValidator); - int numErrorsBefore = diagnostics->numErrors(); - varyingValidator.validate(diagnostics); - return (diagnostics->numErrors() == numErrorsBefore); -} - -} // namespace sh \ No newline at end of file diff --git a/src/3rdparty/angle/src/compiler/translator/ValidateVaryingLocations.h b/src/3rdparty/angle/src/compiler/translator/ValidateVaryingLocations.h deleted file mode 100644 index 1e53977c68..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/ValidateVaryingLocations.h +++ /dev/null @@ -1,25 +0,0 @@ -// -// Copyright (c) 2002-2017 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// The ValidateVaryingLocations function checks if there exists location conflicts on shader -// varyings. -// - -#ifndef COMPILER_TRANSLATOR_VALIDATEVARYINGLOCATIONS_H_ -#define COMPILER_TRANSLATOR_VALIDATEVARYINGLOCATIONS_H_ - -#include "GLSLANG/ShaderVars.h" - -namespace sh -{ - -class TIntermBlock; -class TDiagnostics; - -bool ValidateVaryingLocations(TIntermBlock *root, TDiagnostics *diagnostics, GLenum shaderType); - -} // namespace sh - -#endif \ No newline at end of file diff --git a/src/3rdparty/angle/src/compiler/translator/VariablePacker.cpp b/src/3rdparty/angle/src/compiler/translator/VariablePacker.cpp deleted file mode 100644 index 6dd396ff02..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/VariablePacker.cpp +++ /dev/null @@ -1,413 +0,0 @@ -// -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// Check whether variables fit within packing limits according to the packing rules from the GLSL ES -// 1.00.17 spec, Appendix A, section 7. - -#include - -#include "angle_gl.h" - -#include "compiler/translator/VariablePacker.h" -#include "common/utilities.h" - -namespace sh -{ - -namespace -{ - -// Expand the variable so that struct variables are split into their individual fields. -// Will not set the mappedName or staticUse fields on the expanded variables. -void ExpandVariable(const ShaderVariable &variable, - const std::string &name, - std::vector *expanded); - -void ExpandStructVariable(const ShaderVariable &variable, - const std::string &name, - std::vector *expanded) -{ - ASSERT(variable.isStruct()); - - const std::vector &fields = variable.fields; - - for (size_t fieldIndex = 0; fieldIndex < fields.size(); fieldIndex++) - { - const ShaderVariable &field = fields[fieldIndex]; - ExpandVariable(field, name + "." + field.name, expanded); - } -} - -void ExpandStructArrayVariable(const ShaderVariable &variable, - unsigned int arrayNestingIndex, - const std::string &name, - std::vector *expanded) -{ - // Nested arrays are processed starting from outermost (arrayNestingIndex 0u) and ending at the - // innermost. - const unsigned int currentArraySize = variable.getNestedArraySize(arrayNestingIndex); - for (unsigned int arrayElement = 0u; arrayElement < currentArraySize; ++arrayElement) - { - const std::string elementName = name + ArrayString(arrayElement); - if (arrayNestingIndex + 1u < variable.arraySizes.size()) - { - ExpandStructArrayVariable(variable, arrayNestingIndex + 1u, elementName, expanded); - } - else - { - ExpandStructVariable(variable, elementName, expanded); - } - } -} - -void ExpandVariable(const ShaderVariable &variable, - const std::string &name, - std::vector *expanded) -{ - if (variable.isStruct()) - { - if (variable.isArray()) - { - ExpandStructArrayVariable(variable, 0u, name, expanded); - } - else - { - ExpandStructVariable(variable, name, expanded); - } - } - else - { - ShaderVariable expandedVar = variable; - expandedVar.name = name; - - expanded->push_back(expandedVar); - } -} - -int GetVariablePackingRows(const ShaderVariable &variable) -{ - return GetTypePackingRows(variable.type) * variable.getArraySizeProduct(); -} - -class VariablePacker -{ - public: - bool checkExpandedVariablesWithinPackingLimits(unsigned int maxVectors, - std::vector *variables); - - private: - static const int kNumColumns = 4; - static const unsigned kColumnMask = (1 << kNumColumns) - 1; - - unsigned makeColumnFlags(int column, int numComponentsPerRow); - void fillColumns(int topRow, int numRows, int column, int numComponentsPerRow); - bool searchColumn(int column, int numRows, int *destRow, int *destSize); - - int topNonFullRow_; - int bottomNonFullRow_; - int maxRows_; - std::vector rows_; -}; - -struct TVariableInfoComparer -{ - bool operator()(const sh::ShaderVariable &lhs, const sh::ShaderVariable &rhs) const - { - int lhsSortOrder = gl::VariableSortOrder(lhs.type); - int rhsSortOrder = gl::VariableSortOrder(rhs.type); - if (lhsSortOrder != rhsSortOrder) - { - return lhsSortOrder < rhsSortOrder; - } - // Sort by largest first. - return lhs.getArraySizeProduct() > rhs.getArraySizeProduct(); - } -}; - -unsigned VariablePacker::makeColumnFlags(int column, int numComponentsPerRow) -{ - return ((kColumnMask << (kNumColumns - numComponentsPerRow)) & kColumnMask) >> column; -} - -void VariablePacker::fillColumns(int topRow, int numRows, int column, int numComponentsPerRow) -{ - unsigned columnFlags = makeColumnFlags(column, numComponentsPerRow); - for (int r = 0; r < numRows; ++r) - { - int row = topRow + r; - ASSERT((rows_[row] & columnFlags) == 0); - rows_[row] |= columnFlags; - } -} - -bool VariablePacker::searchColumn(int column, int numRows, int *destRow, int *destSize) -{ - ASSERT(destRow); - - for (; topNonFullRow_ < maxRows_ && rows_[topNonFullRow_] == kColumnMask; ++topNonFullRow_) - { - } - - for (; bottomNonFullRow_ >= 0 && rows_[bottomNonFullRow_] == kColumnMask; --bottomNonFullRow_) - { - } - - if (bottomNonFullRow_ - topNonFullRow_ + 1 < numRows) - { - return false; - } - - unsigned columnFlags = makeColumnFlags(column, 1); - int topGoodRow = 0; - int smallestGoodTop = -1; - int smallestGoodSize = maxRows_ + 1; - int bottomRow = bottomNonFullRow_ + 1; - bool found = false; - for (int row = topNonFullRow_; row <= bottomRow; ++row) - { - bool rowEmpty = row < bottomRow ? ((rows_[row] & columnFlags) == 0) : false; - if (rowEmpty) - { - if (!found) - { - topGoodRow = row; - found = true; - } - } - else - { - if (found) - { - int size = row - topGoodRow; - if (size >= numRows && size < smallestGoodSize) - { - smallestGoodSize = size; - smallestGoodTop = topGoodRow; - } - } - found = false; - } - } - if (smallestGoodTop < 0) - { - return false; - } - - *destRow = smallestGoodTop; - if (destSize) - { - *destSize = smallestGoodSize; - } - return true; -} - -bool VariablePacker::checkExpandedVariablesWithinPackingLimits( - unsigned int maxVectors, - std::vector *variables) -{ - ASSERT(maxVectors > 0); - maxRows_ = maxVectors; - topNonFullRow_ = 0; - bottomNonFullRow_ = maxRows_ - 1; - - // Check whether each variable fits in the available vectors. - for (const sh::ShaderVariable &variable : *variables) - { - // Structs should have been expanded before reaching here. - ASSERT(!variable.isStruct()); - if (variable.getArraySizeProduct() > maxVectors / GetTypePackingRows(variable.type)) - { - return false; - } - } - - // As per GLSL 1.017 Appendix A, Section 7 variables are packed in specific - // order by type, then by size of array, largest first. - std::sort(variables->begin(), variables->end(), TVariableInfoComparer()); - rows_.clear(); - rows_.resize(maxVectors, 0); - - // Packs the 4 column variables. - size_t ii = 0; - for (; ii < variables->size(); ++ii) - { - const sh::ShaderVariable &variable = (*variables)[ii]; - if (GetTypePackingComponentsPerRow(variable.type) != 4) - { - break; - } - topNonFullRow_ += GetVariablePackingRows(variable); - } - - if (topNonFullRow_ > maxRows_) - { - return false; - } - - // Packs the 3 column variables. - int num3ColumnRows = 0; - for (; ii < variables->size(); ++ii) - { - const sh::ShaderVariable &variable = (*variables)[ii]; - if (GetTypePackingComponentsPerRow(variable.type) != 3) - { - break; - } - num3ColumnRows += GetVariablePackingRows(variable); - } - - if (topNonFullRow_ + num3ColumnRows > maxRows_) - { - return false; - } - - fillColumns(topNonFullRow_, num3ColumnRows, 0, 3); - - // Packs the 2 column variables. - int top2ColumnRow = topNonFullRow_ + num3ColumnRows; - int twoColumnRowsAvailable = maxRows_ - top2ColumnRow; - int rowsAvailableInColumns01 = twoColumnRowsAvailable; - int rowsAvailableInColumns23 = twoColumnRowsAvailable; - for (; ii < variables->size(); ++ii) - { - const sh::ShaderVariable &variable = (*variables)[ii]; - if (GetTypePackingComponentsPerRow(variable.type) != 2) - { - break; - } - int numRows = GetVariablePackingRows(variable); - if (numRows <= rowsAvailableInColumns01) - { - rowsAvailableInColumns01 -= numRows; - } - else if (numRows <= rowsAvailableInColumns23) - { - rowsAvailableInColumns23 -= numRows; - } - else - { - return false; - } - } - - int numRowsUsedInColumns01 = twoColumnRowsAvailable - rowsAvailableInColumns01; - int numRowsUsedInColumns23 = twoColumnRowsAvailable - rowsAvailableInColumns23; - fillColumns(top2ColumnRow, numRowsUsedInColumns01, 0, 2); - fillColumns(maxRows_ - numRowsUsedInColumns23, numRowsUsedInColumns23, 2, 2); - - // Packs the 1 column variables. - for (; ii < variables->size(); ++ii) - { - const sh::ShaderVariable &variable = (*variables)[ii]; - ASSERT(1 == GetTypePackingComponentsPerRow(variable.type)); - int numRows = GetVariablePackingRows(variable); - int smallestColumn = -1; - int smallestSize = maxRows_ + 1; - int topRow = -1; - for (int column = 0; column < kNumColumns; ++column) - { - int row = 0; - int size = 0; - if (searchColumn(column, numRows, &row, &size)) - { - if (size < smallestSize) - { - smallestSize = size; - smallestColumn = column; - topRow = row; - } - } - } - - if (smallestColumn < 0) - { - return false; - } - - fillColumns(topRow, numRows, smallestColumn, 1); - } - - ASSERT(variables->size() == ii); - - return true; -} - -} // anonymous namespace - -int GetTypePackingComponentsPerRow(sh::GLenum type) -{ - switch (type) - { - case GL_FLOAT_MAT4: - case GL_FLOAT_MAT2: - case GL_FLOAT_MAT2x4: - case GL_FLOAT_MAT3x4: - case GL_FLOAT_MAT4x2: - case GL_FLOAT_MAT4x3: - case GL_FLOAT_VEC4: - case GL_INT_VEC4: - case GL_BOOL_VEC4: - case GL_UNSIGNED_INT_VEC4: - return 4; - case GL_FLOAT_MAT3: - case GL_FLOAT_MAT2x3: - case GL_FLOAT_MAT3x2: - case GL_FLOAT_VEC3: - case GL_INT_VEC3: - case GL_BOOL_VEC3: - case GL_UNSIGNED_INT_VEC3: - return 3; - case GL_FLOAT_VEC2: - case GL_INT_VEC2: - case GL_BOOL_VEC2: - case GL_UNSIGNED_INT_VEC2: - return 2; - default: - ASSERT(gl::VariableComponentCount(type) == 1); - return 1; - } -} - -int GetTypePackingRows(sh::GLenum type) -{ - switch (type) - { - case GL_FLOAT_MAT4: - case GL_FLOAT_MAT2x4: - case GL_FLOAT_MAT3x4: - case GL_FLOAT_MAT4x3: - case GL_FLOAT_MAT4x2: - return 4; - case GL_FLOAT_MAT3: - case GL_FLOAT_MAT2x3: - case GL_FLOAT_MAT3x2: - return 3; - case GL_FLOAT_MAT2: - return 2; - default: - ASSERT(gl::VariableRowCount(type) == 1); - return 1; - } -} - -template -bool CheckVariablesInPackingLimits(unsigned int maxVectors, const std::vector &variables) -{ - VariablePacker packer; - std::vector expandedVariables; - for (const ShaderVariable &variable : variables) - { - ExpandVariable(variable, variable.name, &expandedVariables); - } - return packer.checkExpandedVariablesWithinPackingLimits(maxVectors, &expandedVariables); -} - -template bool CheckVariablesInPackingLimits( - unsigned int maxVectors, - const std::vector &variables); -template bool CheckVariablesInPackingLimits(unsigned int maxVectors, - const std::vector &variables); - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/VariablePacker.h b/src/3rdparty/angle/src/compiler/translator/VariablePacker.h deleted file mode 100644 index 36b2104cd0..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/VariablePacker.h +++ /dev/null @@ -1,32 +0,0 @@ -// -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// Check whether variables fit within packing limits according to the packing rules from the GLSL ES -// 1.00.17 spec, Appendix A, section 7. - -#ifndef COMPILER_TRANSLATOR_VARIABLEPACKER_H_ -#define COMPILER_TRANSLATOR_VARIABLEPACKER_H_ - -#include - -#include - -namespace sh -{ - -// Gets how many components in a row a data type takes. -int GetTypePackingComponentsPerRow(sh::GLenum type); - -// Gets how many rows a data type takes. -int GetTypePackingRows(sh::GLenum type); - -// Returns true if the passed in variables pack in maxVectors. -// T should be ShaderVariable or one of the subclasses of ShaderVariable. -template -bool CheckVariablesInPackingLimits(unsigned int maxVectors, const std::vector &variables); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_VARIABLEPACKER_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/VectorizeVectorScalarArithmetic.cpp b/src/3rdparty/angle/src/compiler/translator/VectorizeVectorScalarArithmetic.cpp deleted file mode 100644 index 1e79a60991..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/VectorizeVectorScalarArithmetic.cpp +++ /dev/null @@ -1,284 +0,0 @@ -// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// VectorizeVectorScalarArithmetic.cpp: Turn some arithmetic operations that operate on a float -// vector-scalar pair into vector-vector operations. This is done recursively. Some scalar binary -// operations inside vector constructors are also turned into vector operations. -// -// This is targeted to work around a bug in NVIDIA OpenGL drivers that was reproducible on NVIDIA -// driver version 387.92. It works around the most common occurrences of the bug. - -#include "compiler/translator/VectorizeVectorScalarArithmetic.h" - -#include - -#include "compiler/translator/IntermNode.h" -#include "compiler/translator/IntermTraverse.h" - -namespace sh -{ - -namespace -{ - -class VectorizeVectorScalarArithmeticTraverser : public TIntermTraverser -{ - public: - VectorizeVectorScalarArithmeticTraverser(TSymbolTable *symbolTable) - : TIntermTraverser(true, false, false, symbolTable), mReplaced(false) - { - } - - bool didReplaceScalarsWithVectors() { return mReplaced; } - void nextIteration() - { - mReplaced = false; - mModifiedBlocks.clear(); - } - - protected: - bool visitBinary(Visit visit, TIntermBinary *node) override; - bool visitAggregate(Visit visit, TIntermAggregate *node) override; - - private: - // These helpers should only be called from visitAggregate when visiting a constructor. - // argBinary is the only argument of the constructor. - void replaceMathInsideConstructor(TIntermAggregate *node, TIntermBinary *argBinary); - void replaceAssignInsideConstructor(const TIntermAggregate *node, - const TIntermBinary *argBinary); - - static TIntermTyped *Vectorize(TIntermTyped *node, - TType vectorType, - TIntermTraverser::OriginalNode *originalNodeFate); - - bool mReplaced; - std::set mModifiedBlocks; -}; - -TIntermTyped *VectorizeVectorScalarArithmeticTraverser::Vectorize( - TIntermTyped *node, - TType vectorType, - TIntermTraverser::OriginalNode *originalNodeFate) -{ - ASSERT(node->isScalar()); - vectorType.setQualifier(EvqTemporary); - TIntermSequence vectorConstructorArgs; - vectorConstructorArgs.push_back(node); - TIntermAggregate *vectorized = - TIntermAggregate::CreateConstructor(vectorType, &vectorConstructorArgs); - TIntermTyped *vectorizedFolded = vectorized->fold(nullptr); - if (originalNodeFate != nullptr) - { - if (vectorizedFolded != vectorized) - { - *originalNodeFate = OriginalNode::IS_DROPPED; - } - else - { - *originalNodeFate = OriginalNode::BECOMES_CHILD; - } - } - return vectorizedFolded; -} - -bool VectorizeVectorScalarArithmeticTraverser::visitBinary(Visit /*visit*/, TIntermBinary *node) -{ - TIntermTyped *left = node->getLeft(); - TIntermTyped *right = node->getRight(); - ASSERT(left); - ASSERT(right); - switch (node->getOp()) - { - case EOpAdd: - case EOpAddAssign: - // Only these specific ops are necessary to turn into vector ops. - break; - default: - return true; - } - if (node->getBasicType() != EbtFloat) - { - // Only float ops have reproduced the bug. - return true; - } - if (left->isScalar() && right->isVector()) - { - ASSERT(!node->isAssignment()); - ASSERT(!right->isArray()); - OriginalNode originalNodeFate; - TIntermTyped *leftVectorized = Vectorize(left, right->getType(), &originalNodeFate); - queueReplacementWithParent(node, left, leftVectorized, originalNodeFate); - mReplaced = true; - // Don't replace more nodes in the same subtree on this traversal. However, nodes elsewhere - // in the tree may still be replaced. - return false; - } - else if (left->isVector() && right->isScalar()) - { - OriginalNode originalNodeFate; - TIntermTyped *rightVectorized = Vectorize(right, left->getType(), &originalNodeFate); - queueReplacementWithParent(node, right, rightVectorized, originalNodeFate); - mReplaced = true; - // Don't replace more nodes in the same subtree on this traversal. However, nodes elsewhere - // in the tree may still be replaced. - return false; - } - return true; -} - -void VectorizeVectorScalarArithmeticTraverser::replaceMathInsideConstructor( - TIntermAggregate *node, - TIntermBinary *argBinary) -{ - // Turn: - // a * b - // into: - // gvec(a) * gvec(b) - - TIntermTyped *left = argBinary->getLeft(); - TIntermTyped *right = argBinary->getRight(); - ASSERT(left->isScalar() && right->isScalar()); - - TType leftVectorizedType = left->getType(); - leftVectorizedType.setPrimarySize(static_cast(node->getType().getNominalSize())); - TIntermTyped *leftVectorized = Vectorize(left, leftVectorizedType, nullptr); - TType rightVectorizedType = right->getType(); - rightVectorizedType.setPrimarySize( - static_cast(node->getType().getNominalSize())); - TIntermTyped *rightVectorized = Vectorize(right, rightVectorizedType, nullptr); - - TIntermBinary *newArg = new TIntermBinary(argBinary->getOp(), leftVectorized, rightVectorized); - queueReplacementWithParent(node, argBinary, newArg, OriginalNode::IS_DROPPED); -} - -void VectorizeVectorScalarArithmeticTraverser::replaceAssignInsideConstructor( - const TIntermAggregate *node, - const TIntermBinary *argBinary) -{ - // Turn: - // gvec(a *= b); - // into: - // // This is inserted into the parent block: - // gvec s0 = gvec(a); - // - // // This goes where the gvec constructor used to be: - // ((s0 *= b, a = s0.x), s0); - - TIntermTyped *left = argBinary->getLeft(); - TIntermTyped *right = argBinary->getRight(); - ASSERT(left->isScalar() && right->isScalar()); - ASSERT(!left->hasSideEffects()); - - TType vecType = node->getType(); - vecType.setQualifier(EvqTemporary); - - nextTemporaryId(); - // gvec s0 = gvec(a); - // s0 is called "tempAssignmentTarget" below. - TIntermTyped *tempAssignmentTargetInitializer = Vectorize(left->deepCopy(), vecType, nullptr); - TIntermDeclaration *tempAssignmentTargetDeclaration = - createTempInitDeclaration(tempAssignmentTargetInitializer); - - // s0 *= b - TOperator compoundAssignmentOp = argBinary->getOp(); - if (compoundAssignmentOp == EOpMulAssign) - { - compoundAssignmentOp = EOpVectorTimesScalarAssign; - } - TIntermBinary *replacementCompoundAssignment = - new TIntermBinary(compoundAssignmentOp, createTempSymbol(vecType), right->deepCopy()); - - // s0.x - TVector swizzleXOffset; - swizzleXOffset.push_back(0); - TIntermSwizzle *tempAssignmentTargetX = - new TIntermSwizzle(createTempSymbol(vecType), swizzleXOffset); - // a = s0.x - TIntermBinary *replacementAssignBackToTarget = - new TIntermBinary(EOpAssign, left->deepCopy(), tempAssignmentTargetX); - - // s0 *= b, a = s0.x - TIntermBinary *replacementSequenceLeft = - new TIntermBinary(EOpComma, replacementCompoundAssignment, replacementAssignBackToTarget); - // (s0 *= b, a = s0.x), s0 - TIntermBinary *replacementSequence = - new TIntermBinary(EOpComma, replacementSequenceLeft, createTempSymbol(vecType)); - - insertStatementInParentBlock(tempAssignmentTargetDeclaration); - queueReplacement(replacementSequence, OriginalNode::IS_DROPPED); -} - -bool VectorizeVectorScalarArithmeticTraverser::visitAggregate(Visit /*visit*/, - TIntermAggregate *node) -{ - // Transform scalar binary expressions inside vector constructors. - if (!node->isConstructor() || !node->isVector() || node->getSequence()->size() != 1) - { - return true; - } - TIntermTyped *argument = node->getSequence()->back()->getAsTyped(); - ASSERT(argument); - if (!argument->isScalar() || argument->getBasicType() != EbtFloat) - { - return true; - } - TIntermBinary *argBinary = argument->getAsBinaryNode(); - if (!argBinary) - { - return true; - } - - // Only specific ops are necessary to change. - switch (argBinary->getOp()) - { - case EOpMul: - case EOpDiv: - { - replaceMathInsideConstructor(node, argBinary); - mReplaced = true; - // Don't replace more nodes in the same subtree on this traversal. However, nodes - // elsewhere in the tree may still be replaced. - return false; - } - case EOpMulAssign: - case EOpDivAssign: - { - // The case where the left side has side effects is too complicated to deal with, so we - // leave that be. - if (!argBinary->getLeft()->hasSideEffects()) - { - const TIntermBlock *parentBlock = getParentBlock(); - // We can't do more than one insertion to the same block on the same traversal. - if (mModifiedBlocks.find(parentBlock) == mModifiedBlocks.end()) - { - replaceAssignInsideConstructor(node, argBinary); - mModifiedBlocks.insert(parentBlock); - mReplaced = true; - // Don't replace more nodes in the same subtree on this traversal. - // However, nodes elsewhere in the tree may still be replaced. - return false; - } - } - break; - } - default: - return true; - } - return true; -} - -} // anonymous namespace - -void VectorizeVectorScalarArithmetic(TIntermBlock *root, TSymbolTable *symbolTable) -{ - VectorizeVectorScalarArithmeticTraverser traverser(symbolTable); - do - { - traverser.nextIteration(); - root->traverse(&traverser); - traverser.updateTree(); - } while (traverser.didReplaceScalarsWithVectors()); -} - -} // namespace sh \ No newline at end of file diff --git a/src/3rdparty/angle/src/compiler/translator/VectorizeVectorScalarArithmetic.h b/src/3rdparty/angle/src/compiler/translator/VectorizeVectorScalarArithmetic.h deleted file mode 100644 index 69f092e039..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/VectorizeVectorScalarArithmetic.h +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// VectorizeVectorScalarArithmetic.h: Turn some arithmetic operations that operate on a float -// vector-scalar pair into vector-vector operations. This is done recursively. Some scalar binary -// operations inside vector constructors are also turned into vector operations. -// -// This is targeted to work around a bug in NVIDIA OpenGL drivers that was reproducible on NVIDIA -// driver version 387.92. It works around the most common occurrences of the bug. - -#ifndef COMPILER_TRANSLATOR_VECTORIZEVECTORSCALARARITHMETIC_H_ -#define COMPILER_TRANSLATOR_VECTORIZEVECTORSCALARARITHMETIC_H_ - -namespace sh -{ - -class TIntermBlock; -class TSymbolTable; - -void VectorizeVectorScalarArithmetic(TIntermBlock *root, TSymbolTable *symbolTable); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_VECTORIZEVECTORSCALARARITHMETIC_H_ \ No newline at end of file diff --git a/src/3rdparty/angle/src/compiler/translator/VersionGLSL.cpp b/src/3rdparty/angle/src/compiler/translator/VersionGLSL.cpp deleted file mode 100644 index 81688765b8..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/VersionGLSL.cpp +++ /dev/null @@ -1,143 +0,0 @@ -// -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/translator/VersionGLSL.h" - -#include "angle_gl.h" - -namespace sh -{ - -int ShaderOutputTypeToGLSLVersion(ShShaderOutput output) -{ - switch (output) - { - case SH_GLSL_130_OUTPUT: - return GLSL_VERSION_130; - case SH_GLSL_140_OUTPUT: - return GLSL_VERSION_140; - case SH_GLSL_150_CORE_OUTPUT: - return GLSL_VERSION_150; - case SH_GLSL_330_CORE_OUTPUT: - return GLSL_VERSION_330; - case SH_GLSL_400_CORE_OUTPUT: - return GLSL_VERSION_400; - case SH_GLSL_410_CORE_OUTPUT: - return GLSL_VERSION_410; - case SH_GLSL_420_CORE_OUTPUT: - return GLSL_VERSION_420; - case SH_GLSL_430_CORE_OUTPUT: - return GLSL_VERSION_430; - case SH_GLSL_440_CORE_OUTPUT: - return GLSL_VERSION_440; - case SH_GLSL_450_CORE_OUTPUT: - return GLSL_VERSION_450; - case SH_GLSL_COMPATIBILITY_OUTPUT: - return GLSL_VERSION_110; - default: - UNREACHABLE(); - return 0; - } -} - -// We need to scan for the following: -// 1. "invariant" keyword: This can occur in both - vertex and fragment shaders -// but only at the global scope. -// 2. "gl_PointCoord" built-in variable: This can only occur in fragment shader -// but inside any scope. -// 3. Call to a matrix constructor with another matrix as argument. -// (These constructors were reserved in GLSL version 1.10.) -// 4. Arrays as "out" function parameters. -// GLSL spec section 6.1.1: "When calling a function, expressions that do -// not evaluate to l-values cannot be passed to parameters declared as -// out or inout." -// GLSL 1.1 section 5.8: "Other binary or unary expressions, -// non-dereferenced arrays, function names, swizzles with repeated fields, -// and constants cannot be l-values." -// GLSL 1.2 relaxed the restriction on arrays, section 5.8: "Variables that -// are built-in types, entire structures or arrays... are all l-values." -// -TVersionGLSL::TVersionGLSL(sh::GLenum type, const TPragma &pragma, ShShaderOutput output) - : TIntermTraverser(true, false, false) -{ - mVersion = ShaderOutputTypeToGLSLVersion(output); - if (pragma.stdgl.invariantAll) - { - ensureVersionIsAtLeast(GLSL_VERSION_120); - } - if (type == GL_COMPUTE_SHADER) - { - ensureVersionIsAtLeast(GLSL_VERSION_430); - } -} - -void TVersionGLSL::visitSymbol(TIntermSymbol *node) -{ - if (node->getSymbol() == "gl_PointCoord") - { - ensureVersionIsAtLeast(GLSL_VERSION_120); - } -} - -bool TVersionGLSL::visitDeclaration(Visit, TIntermDeclaration *node) -{ - const TIntermSequence &sequence = *(node->getSequence()); - if (sequence.front()->getAsTyped()->getType().isInvariant()) - { - ensureVersionIsAtLeast(GLSL_VERSION_120); - } - return true; -} - -bool TVersionGLSL::visitInvariantDeclaration(Visit, TIntermInvariantDeclaration *node) -{ - ensureVersionIsAtLeast(GLSL_VERSION_120); - return true; -} - -bool TVersionGLSL::visitFunctionPrototype(Visit, TIntermFunctionPrototype *node) -{ - const TIntermSequence ¶ms = *(node->getSequence()); - for (TIntermSequence::const_iterator iter = params.begin(); iter != params.end(); ++iter) - { - const TIntermTyped *param = (*iter)->getAsTyped(); - if (param->isArray()) - { - TQualifier qualifier = param->getQualifier(); - if ((qualifier == EvqOut) || (qualifier == EvqInOut)) - { - ensureVersionIsAtLeast(GLSL_VERSION_120); - break; - } - } - } - // Fully processed. No need to visit children. - return false; -} - -bool TVersionGLSL::visitAggregate(Visit, TIntermAggregate *node) -{ - if (node->getOp() == EOpConstruct && node->getType().isMatrix()) - { - const TIntermSequence &sequence = *(node->getSequence()); - if (sequence.size() == 1) - { - TIntermTyped *typed = sequence.front()->getAsTyped(); - if (typed && typed->isMatrix()) - { - ensureVersionIsAtLeast(GLSL_VERSION_120); - } - } - } - return true; -} - -void TVersionGLSL::ensureVersionIsAtLeast(int version) -{ - mVersion = std::max(version, mVersion); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/VersionGLSL.h b/src/3rdparty/angle/src/compiler/translator/VersionGLSL.h deleted file mode 100644 index 8b82eb9615..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/VersionGLSL.h +++ /dev/null @@ -1,76 +0,0 @@ -// -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_TRANSLATOR_VERSIONGLSL_H_ -#define COMPILER_TRANSLATOR_VERSIONGLSL_H_ - -#include "compiler/translator/IntermTraverse.h" - -#include "compiler/translator/Pragma.h" - -namespace sh -{ - -static const int GLSL_VERSION_110 = 110; -static const int GLSL_VERSION_120 = 120; -static const int GLSL_VERSION_130 = 130; -static const int GLSL_VERSION_140 = 140; -static const int GLSL_VERSION_150 = 150; -static const int GLSL_VERSION_330 = 330; -static const int GLSL_VERSION_400 = 400; -static const int GLSL_VERSION_410 = 410; -static const int GLSL_VERSION_420 = 420; -static const int GLSL_VERSION_430 = 430; -static const int GLSL_VERSION_440 = 440; -static const int GLSL_VERSION_450 = 450; - -int ShaderOutputTypeToGLSLVersion(ShShaderOutput output); - -// Traverses the intermediate tree to return the minimum GLSL version -// required to legally access all built-in features used in the shader. -// GLSL 1.1 which is mandated by OpenGL 2.0 provides: -// - #version and #extension to declare version and extensions. -// - built-in functions refract, exp, and log. -// - updated step() to compare x < edge instead of x <= edge. -// GLSL 1.2 which is mandated by OpenGL 2.1 provides: -// - many changes to reduce differences when compared to the ES specification. -// - invariant keyword and its support. -// - c++ style name hiding rules. -// - built-in variable gl_PointCoord for fragment shaders. -// - matrix constructors taking matrix as argument. -// - array as "out" function parameters -// -// TODO: ES3 equivalent versions of GLSL -class TVersionGLSL : public TIntermTraverser -{ - public: - TVersionGLSL(sh::GLenum type, const TPragma &pragma, ShShaderOutput output); - - // If output is core profile, returns 150. - // If output is legacy profile, - // Returns 120 if the following is used the shader: - // - "invariant", - // - "gl_PointCoord", - // - matrix/matrix constructors - // - array "out" parameters - // Else 110 is returned. - int getVersion() const { return mVersion; } - - void visitSymbol(TIntermSymbol *node) override; - bool visitAggregate(Visit, TIntermAggregate *node) override; - bool visitInvariantDeclaration(Visit, TIntermInvariantDeclaration *node) override; - bool visitFunctionPrototype(Visit, TIntermFunctionPrototype *node) override; - bool visitDeclaration(Visit, TIntermDeclaration *node) override; - - private: - void ensureVersionIsAtLeast(int version); - - int mVersion; -}; - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_VERSIONGLSL_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/WrapSwitchStatementsInBlocks.cpp b/src/3rdparty/angle/src/compiler/translator/WrapSwitchStatementsInBlocks.cpp deleted file mode 100644 index 85a11c998d..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/WrapSwitchStatementsInBlocks.cpp +++ /dev/null @@ -1,132 +0,0 @@ -// -// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// WrapSwitchStatementsInBlocks.cpp: Wrap switch statements in blocks and declare all switch-scoped -// variables there to make the AST compatible with HLSL output. -// -// switch (init) -// { -// case 0: -// float f; -// default: -// f = 1.0; -// } -// -// becomes -// -// { -// float f; -// switch (init) -// { -// case 0: -// default: -// f = 1.0; -// } -// } - -#include "compiler/translator/WrapSwitchStatementsInBlocks.h" - -#include "compiler/translator/IntermNode.h" -#include "compiler/translator/IntermTraverse.h" - -namespace sh -{ - -namespace -{ - -class WrapSwitchStatementsInBlocksTraverser : public TIntermTraverser -{ - public: - WrapSwitchStatementsInBlocksTraverser() : TIntermTraverser(true, false, false), mDidWrap(false) - { - } - - bool visitSwitch(Visit visit, TIntermSwitch *node) override; - - bool didWrap() const { return mDidWrap; } - - private: - bool mDidWrap; -}; - -bool WrapSwitchStatementsInBlocksTraverser::visitSwitch(Visit, TIntermSwitch *node) -{ - std::vector declarations; - TIntermSequence *statementList = node->getStatementList()->getSequence(); - for (TIntermNode *statement : *statementList) - { - TIntermDeclaration *asDeclaration = statement->getAsDeclarationNode(); - if (asDeclaration) - { - declarations.push_back(asDeclaration); - } - } - if (declarations.empty()) - { - // We don't need to wrap the switch if it doesn't contain declarations as its direct - // descendants. - return true; - } - - TIntermBlock *wrapperBlock = new TIntermBlock(); - for (TIntermDeclaration *declaration : declarations) - { - // SeparateDeclarations should have already been run. - ASSERT(declaration->getSequence()->size() == 1); - - TIntermDeclaration *declarationInBlock = new TIntermDeclaration(); - TIntermSymbol *declaratorAsSymbol = declaration->getSequence()->at(0)->getAsSymbolNode(); - if (declaratorAsSymbol) - { - // This is a simple declaration like: "float f;" - // Remove the declaration from inside the switch and put it in the wrapping block. - TIntermSequence emptyReplacement; - mMultiReplacements.push_back(NodeReplaceWithMultipleEntry( - node->getStatementList(), declaration, emptyReplacement)); - - declarationInBlock->appendDeclarator(declaratorAsSymbol->deepCopy()); - } - else - { - // This is an init declaration like: "float f = 0.0;" - // Change the init declaration inside the switch into an assignment and put a plain - // declaration in the wrapping block. - TIntermBinary *declaratorAsBinary = - declaration->getSequence()->at(0)->getAsBinaryNode(); - ASSERT(declaratorAsBinary); - - TIntermBinary *initAssignment = new TIntermBinary( - EOpAssign, declaratorAsBinary->getLeft(), declaratorAsBinary->getRight()); - - queueReplacementWithParent(node->getStatementList(), declaration, initAssignment, - OriginalNode::IS_DROPPED); - - declarationInBlock->appendDeclarator(declaratorAsBinary->getLeft()->deepCopy()); - } - wrapperBlock->appendStatement(declarationInBlock); - } - - wrapperBlock->appendStatement(node); - queueReplacement(wrapperBlock, OriginalNode::BECOMES_CHILD); - mDidWrap = true; - - // Should be fine to process multiple switch statements, even nesting ones in the same - // traversal. - return true; -} - -} // anonymous namespace - -// Wrap switch statements in the AST into blocks when needed. -bool WrapSwitchStatementsInBlocks(TIntermBlock *root) -{ - WrapSwitchStatementsInBlocksTraverser traverser; - root->traverse(&traverser); - traverser.updateTree(); - return traverser.didWrap(); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/WrapSwitchStatementsInBlocks.h b/src/3rdparty/angle/src/compiler/translator/WrapSwitchStatementsInBlocks.h deleted file mode 100644 index bc0179926d..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/WrapSwitchStatementsInBlocks.h +++ /dev/null @@ -1,22 +0,0 @@ -// -// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// WrapSwitchStatementsInBlocks.h: Wrap switch statements in blocks and declare all switch-scoped -// variables there to make the AST compatible with HLSL output. - -#ifndef COMPILER_TRANSLATOR_WRAPSWITCHSTATEMENTSINBLOCKS_H_ -#define COMPILER_TRANSLATOR_WRAPSWITCHSTATEMENTSINBLOCKS_H_ - -namespace sh -{ - -class TIntermBlock; - -// Wrap switch statements in the AST into blocks when needed. Returns true if the AST was changed. -bool WrapSwitchStatementsInBlocks(TIntermBlock *root); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_WRAPSWITCHSTATEMENTSINBLOCKS_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/blocklayout.cpp b/src/3rdparty/angle/src/compiler/translator/blocklayout.cpp deleted file mode 100644 index fd8c450c20..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/blocklayout.cpp +++ /dev/null @@ -1,281 +0,0 @@ -// -// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// blocklayout.cpp: -// Implementation for block layout classes and methods. -// - -#include "compiler/translator/blocklayout.h" - -#include "common/mathutil.h" -#include "common/utilities.h" - -namespace sh -{ - -namespace -{ -bool IsRowMajorLayout(const InterfaceBlockField &var) -{ - return var.isRowMajorLayout; -} - -bool IsRowMajorLayout(const ShaderVariable &var) -{ - return false; -} - -template -void GetUniformBlockStructMemberInfo(const std::vector &fields, - const std::string &fieldName, - sh::BlockLayoutEncoder *encoder, - bool inRowMajorLayout, - BlockLayoutMap *blockInfoOut) -{ - encoder->enterAggregateType(); - GetUniformBlockInfo(fields, fieldName, encoder, inRowMajorLayout, blockInfoOut); - encoder->exitAggregateType(); -} - -template -void GetUniformBlockStructArrayMemberInfo(const VarT &field, - unsigned int arrayNestingIndex, - const std::string &arrayName, - sh::BlockLayoutEncoder *encoder, - bool inRowMajorLayout, - BlockLayoutMap *blockInfoOut) -{ - // Nested arrays are processed starting from outermost (arrayNestingIndex 0u) and ending at the - // innermost. - const unsigned int currentArraySize = field.getNestedArraySize(arrayNestingIndex); - for (unsigned int arrayElement = 0u; arrayElement < currentArraySize; ++arrayElement) - { - const std::string elementName = arrayName + ArrayString(arrayElement); - if (arrayNestingIndex + 1u < field.arraySizes.size()) - { - GetUniformBlockStructArrayMemberInfo(field, arrayNestingIndex + 1u, elementName, - encoder, inRowMajorLayout, blockInfoOut); - } - else - { - GetUniformBlockStructMemberInfo(field.fields, elementName, encoder, inRowMajorLayout, - blockInfoOut); - } - } -} - -template -void GetUniformBlockArrayOfArraysMemberInfo(const VarT &field, - unsigned int arrayNestingIndex, - const std::string &arrayName, - sh::BlockLayoutEncoder *encoder, - bool inRowMajorLayout, - BlockLayoutMap *blockInfoOut) -{ - const unsigned int currentArraySize = field.getNestedArraySize(arrayNestingIndex); - for (unsigned int arrayElement = 0u; arrayElement < currentArraySize; ++arrayElement) - { - const std::string elementName = arrayName + ArrayString(arrayElement); - if (arrayNestingIndex + 2u < field.arraySizes.size()) - { - GetUniformBlockArrayOfArraysMemberInfo(field, arrayNestingIndex + 1u, elementName, - encoder, inRowMajorLayout, blockInfoOut); - } - else - { - std::vector innermostArraySize( - 1u, field.getNestedArraySize(arrayNestingIndex + 1u)); - (*blockInfoOut)[elementName] = - encoder->encodeType(field.type, innermostArraySize, inRowMajorLayout); - } - } -} - -} // anonymous namespace - -BlockLayoutEncoder::BlockLayoutEncoder() : mCurrentOffset(0) -{ -} - -BlockMemberInfo BlockLayoutEncoder::encodeType(GLenum type, - const std::vector &arraySizes, - bool isRowMajorMatrix) -{ - int arrayStride; - int matrixStride; - - getBlockLayoutInfo(type, arraySizes, isRowMajorMatrix, &arrayStride, &matrixStride); - - const BlockMemberInfo memberInfo(static_cast(mCurrentOffset * BytesPerComponent), - static_cast(arrayStride * BytesPerComponent), - static_cast(matrixStride * BytesPerComponent), - isRowMajorMatrix); - - advanceOffset(type, arraySizes, isRowMajorMatrix, arrayStride, matrixStride); - - return memberInfo; -} - -// static -size_t BlockLayoutEncoder::getBlockRegister(const BlockMemberInfo &info) -{ - return (info.offset / BytesPerComponent) / ComponentsPerRegister; -} - -// static -size_t BlockLayoutEncoder::getBlockRegisterElement(const BlockMemberInfo &info) -{ - return (info.offset / BytesPerComponent) % ComponentsPerRegister; -} - -void BlockLayoutEncoder::nextRegister() -{ - mCurrentOffset = rx::roundUp(mCurrentOffset, ComponentsPerRegister); -} - -Std140BlockEncoder::Std140BlockEncoder() -{ -} - -void Std140BlockEncoder::enterAggregateType() -{ - nextRegister(); -} - -void Std140BlockEncoder::exitAggregateType() -{ - nextRegister(); -} - -void Std140BlockEncoder::getBlockLayoutInfo(GLenum type, - const std::vector &arraySizes, - bool isRowMajorMatrix, - int *arrayStrideOut, - int *matrixStrideOut) -{ - // We assume we are only dealing with 4 byte components (no doubles or half-words currently) - ASSERT(gl::VariableComponentSize(gl::VariableComponentType(type)) == BytesPerComponent); - - size_t baseAlignment = 0; - int matrixStride = 0; - int arrayStride = 0; - - if (gl::IsMatrixType(type)) - { - baseAlignment = ComponentsPerRegister; - matrixStride = ComponentsPerRegister; - - if (!arraySizes.empty()) - { - const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix); - arrayStride = ComponentsPerRegister * numRegisters; - } - } - else if (!arraySizes.empty()) - { - baseAlignment = ComponentsPerRegister; - arrayStride = ComponentsPerRegister; - } - else - { - const int numComponents = gl::VariableComponentCount(type); - baseAlignment = (numComponents == 3 ? 4u : static_cast(numComponents)); - } - - mCurrentOffset = rx::roundUp(mCurrentOffset, baseAlignment); - - *matrixStrideOut = matrixStride; - *arrayStrideOut = arrayStride; -} - -void Std140BlockEncoder::advanceOffset(GLenum type, - const std::vector &arraySizes, - bool isRowMajorMatrix, - int arrayStride, - int matrixStride) -{ - if (!arraySizes.empty()) - { - mCurrentOffset += arrayStride * gl::ArraySizeProduct(arraySizes); - } - else if (gl::IsMatrixType(type)) - { - ASSERT(matrixStride == ComponentsPerRegister); - const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix); - mCurrentOffset += ComponentsPerRegister * numRegisters; - } - else - { - mCurrentOffset += gl::VariableComponentCount(type); - } -} - -template -void GetUniformBlockInfo(const std::vector &fields, - const std::string &prefix, - sh::BlockLayoutEncoder *encoder, - bool inRowMajorLayout, - BlockLayoutMap *blockInfoOut) -{ - for (const VarT &field : fields) - { - // Skip samplers. On Vulkan we use this for the default uniform block, so samplers may be - // included. - if (gl::IsSamplerType(field.type)) - { - continue; - } - - const std::string &fieldName = (prefix.empty() ? field.name : prefix + "." + field.name); - - if (field.isStruct()) - { - bool rowMajorLayout = (inRowMajorLayout || IsRowMajorLayout(field)); - - if (field.isArray()) - { - GetUniformBlockStructArrayMemberInfo(field, 0u, fieldName, encoder, rowMajorLayout, - blockInfoOut); - } - else - { - GetUniformBlockStructMemberInfo(field.fields, fieldName, encoder, rowMajorLayout, - blockInfoOut); - } - } - else if (field.isArrayOfArrays()) - { - bool isRowMajorMatrix = (gl::IsMatrixType(field.type) && inRowMajorLayout); - GetUniformBlockArrayOfArraysMemberInfo(field, 0u, fieldName, encoder, isRowMajorMatrix, - blockInfoOut); - } - else - { - bool isRowMajorMatrix = (gl::IsMatrixType(field.type) && inRowMajorLayout); - (*blockInfoOut)[fieldName] = - encoder->encodeType(field.type, field.arraySizes, isRowMajorMatrix); - } - } -} - -template void GetUniformBlockInfo(const std::vector &, - const std::string &, - sh::BlockLayoutEncoder *, - bool, - BlockLayoutMap *); - -template void GetUniformBlockInfo(const std::vector &, - const std::string &, - sh::BlockLayoutEncoder *, - bool, - BlockLayoutMap *); - -template void GetUniformBlockInfo(const std::vector &, - const std::string &, - sh::BlockLayoutEncoder *, - bool, - BlockLayoutMap *); - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/blocklayout.h b/src/3rdparty/angle/src/compiler/translator/blocklayout.h deleted file mode 100644 index 2b7acf4e60..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/blocklayout.h +++ /dev/null @@ -1,144 +0,0 @@ -// -// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// blocklayout.h: -// Methods and classes related to uniform layout and packing in GLSL and HLSL. -// - -#ifndef COMMON_BLOCKLAYOUT_H_ -#define COMMON_BLOCKLAYOUT_H_ - -#include -#include -#include - -#include "angle_gl.h" -#include - -namespace sh -{ -struct ShaderVariable; -struct InterfaceBlockField; -struct Uniform; -struct Varying; -struct InterfaceBlock; - -struct BlockMemberInfo -{ - BlockMemberInfo() - : offset(-1), - arrayStride(-1), - matrixStride(-1), - isRowMajorMatrix(false), - topLevelArrayStride(-1) - { - } - - BlockMemberInfo(int offset, int arrayStride, int matrixStride, bool isRowMajorMatrix) - : offset(offset), - arrayStride(arrayStride), - matrixStride(matrixStride), - isRowMajorMatrix(isRowMajorMatrix), - topLevelArrayStride(-1) - { - } - - BlockMemberInfo(int offset, - int arrayStride, - int matrixStride, - bool isRowMajorMatrix, - int topLevelArrayStride) - : offset(offset), - arrayStride(arrayStride), - matrixStride(matrixStride), - isRowMajorMatrix(isRowMajorMatrix), - topLevelArrayStride(topLevelArrayStride) - { - } - - static BlockMemberInfo getDefaultBlockInfo() { return BlockMemberInfo(-1, -1, -1, false, -1); } - - int offset; - int arrayStride; - int matrixStride; - bool isRowMajorMatrix; - int topLevelArrayStride; // Only used for shader storage block members. -}; - -class BlockLayoutEncoder -{ - public: - BlockLayoutEncoder(); - virtual ~BlockLayoutEncoder() {} - - BlockMemberInfo encodeType(GLenum type, - const std::vector &arraySizes, - bool isRowMajorMatrix); - - size_t getBlockSize() const { return mCurrentOffset * BytesPerComponent; } - - virtual void enterAggregateType() = 0; - virtual void exitAggregateType() = 0; - - static const size_t BytesPerComponent = 4u; - static const unsigned int ComponentsPerRegister = 4u; - - static size_t getBlockRegister(const BlockMemberInfo &info); - static size_t getBlockRegisterElement(const BlockMemberInfo &info); - - protected: - size_t mCurrentOffset; - - void nextRegister(); - - virtual void getBlockLayoutInfo(GLenum type, - const std::vector &arraySizes, - bool isRowMajorMatrix, - int *arrayStrideOut, - int *matrixStrideOut) = 0; - virtual void advanceOffset(GLenum type, - const std::vector &arraySizes, - bool isRowMajorMatrix, - int arrayStride, - int matrixStride) = 0; -}; - -// Block layout according to the std140 block layout -// See "Standard Uniform Block Layout" in Section 2.11.6 of the OpenGL ES 3.0 specification - -class Std140BlockEncoder : public BlockLayoutEncoder -{ - public: - Std140BlockEncoder(); - - void enterAggregateType() override; - void exitAggregateType() override; - - protected: - void getBlockLayoutInfo(GLenum type, - const std::vector &arraySizes, - bool isRowMajorMatrix, - int *arrayStrideOut, - int *matrixStrideOut) override; - void advanceOffset(GLenum type, - const std::vector &arraySizes, - bool isRowMajorMatrix, - int arrayStride, - int matrixStride) override; -}; - -using BlockLayoutMap = std::map; - -// Only valid to call with ShaderVariable, InterfaceBlockField and Uniform. -template -void GetUniformBlockInfo(const std::vector &fields, - const std::string &prefix, - sh::BlockLayoutEncoder *encoder, - bool inRowMajorLayout, - BlockLayoutMap *blockLayoutMap); - -} // namespace sh - -#endif // COMMON_BLOCKLAYOUT_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/blocklayoutHLSL.cpp b/src/3rdparty/angle/src/compiler/translator/blocklayoutHLSL.cpp deleted file mode 100644 index 867821f1ea..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/blocklayoutHLSL.cpp +++ /dev/null @@ -1,166 +0,0 @@ -// -// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// blocklayout.cpp: -// Implementation for block layout classes and methods. -// - -#include "compiler/translator/blocklayoutHLSL.h" - -#include "common/mathutil.h" -#include "common/utilities.h" - -namespace sh -{ - -HLSLBlockEncoder::HLSLBlockEncoder(HLSLBlockEncoderStrategy strategy, bool transposeMatrices) - : mEncoderStrategy(strategy), mTransposeMatrices(transposeMatrices) -{ -} - -void HLSLBlockEncoder::enterAggregateType() -{ - nextRegister(); -} - -void HLSLBlockEncoder::exitAggregateType() -{ -} - -void HLSLBlockEncoder::getBlockLayoutInfo(GLenum typeIn, - const std::vector &arraySizes, - bool isRowMajorMatrix, - int *arrayStrideOut, - int *matrixStrideOut) -{ - GLenum type = (mTransposeMatrices ? gl::TransposeMatrixType(typeIn) : typeIn); - - // We assume we are only dealing with 4 byte components (no doubles or half-words currently) - ASSERT(gl::VariableComponentSize(gl::VariableComponentType(type)) == BytesPerComponent); - - int matrixStride = 0; - int arrayStride = 0; - - // if variables are not to be packed, or we're about to - // pack a matrix or array, skip to the start of the next - // register - if (!isPacked() || gl::IsMatrixType(type) || !arraySizes.empty()) - { - nextRegister(); - } - - if (gl::IsMatrixType(type)) - { - matrixStride = ComponentsPerRegister; - - if (!arraySizes.empty()) - { - const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix); - arrayStride = ComponentsPerRegister * numRegisters; - } - } - else if (!arraySizes.empty()) - { - arrayStride = ComponentsPerRegister; - } - else if (isPacked()) - { - int numComponents = gl::VariableComponentCount(type); - if ((numComponents + (mCurrentOffset % ComponentsPerRegister)) > ComponentsPerRegister) - { - nextRegister(); - } - } - - *matrixStrideOut = matrixStride; - *arrayStrideOut = arrayStride; -} - -void HLSLBlockEncoder::advanceOffset(GLenum typeIn, - const std::vector &arraySizes, - bool isRowMajorMatrix, - int arrayStride, - int matrixStride) -{ - GLenum type = (mTransposeMatrices ? gl::TransposeMatrixType(typeIn) : typeIn); - - if (!arraySizes.empty()) - { - mCurrentOffset += arrayStride * (gl::ArraySizeProduct(arraySizes) - 1); - } - - if (gl::IsMatrixType(type)) - { - ASSERT(matrixStride == ComponentsPerRegister); - const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix); - const int numComponents = gl::MatrixComponentCount(type, isRowMajorMatrix); - mCurrentOffset += ComponentsPerRegister * (numRegisters - 1); - mCurrentOffset += numComponents; - } - else if (isPacked()) - { - mCurrentOffset += gl::VariableComponentCount(type); - } - else - { - mCurrentOffset += ComponentsPerRegister; - } -} - -void HLSLBlockEncoder::skipRegisters(unsigned int numRegisters) -{ - mCurrentOffset += (numRegisters * ComponentsPerRegister); -} - -HLSLBlockEncoder::HLSLBlockEncoderStrategy HLSLBlockEncoder::GetStrategyFor( - ShShaderOutput outputType) -{ - switch (outputType) - { - case SH_HLSL_3_0_OUTPUT: - return ENCODE_LOOSE; - case SH_HLSL_4_1_OUTPUT: - case SH_HLSL_4_0_FL9_3_OUTPUT: - return ENCODE_PACKED; - default: - UNREACHABLE(); - return ENCODE_PACKED; - } -} - -template -void HLSLVariableRegisterCount(const ShaderVarType &variable, HLSLBlockEncoder *encoder) -{ - if (variable.isStruct()) - { - for (size_t arrayElement = 0; arrayElement < variable.getArraySizeProduct(); arrayElement++) - { - encoder->enterAggregateType(); - - for (size_t fieldIndex = 0; fieldIndex < variable.fields.size(); fieldIndex++) - { - HLSLVariableRegisterCount(variable.fields[fieldIndex], encoder); - } - - encoder->exitAggregateType(); - } - } - else - { - // We operate only on varyings and uniforms, which do not have matrix layout qualifiers - encoder->encodeType(variable.type, variable.arraySizes, false); - } -} - -unsigned int HLSLVariableRegisterCount(const Uniform &variable, ShShaderOutput outputType) -{ - HLSLBlockEncoder encoder(HLSLBlockEncoder::GetStrategyFor(outputType), true); - HLSLVariableRegisterCount(variable, &encoder); - - const size_t registerBytes = (encoder.BytesPerComponent * encoder.ComponentsPerRegister); - return static_cast(rx::roundUp(encoder.getBlockSize(), registerBytes) / - registerBytes); -} -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/blocklayoutHLSL.h b/src/3rdparty/angle/src/compiler/translator/blocklayoutHLSL.h deleted file mode 100644 index 8f4a51a906..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/blocklayoutHLSL.h +++ /dev/null @@ -1,68 +0,0 @@ -// -// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// blocklayout.h: -// Methods and classes related to uniform layout and packing in GLSL and HLSL. -// - -#ifndef COMMON_BLOCKLAYOUTHLSL_H_ -#define COMMON_BLOCKLAYOUTHLSL_H_ - -#include -#include - -#include "angle_gl.h" -#include "blocklayout.h" -#include - -namespace sh -{ -// Block layout packed according to the D3D9 or default D3D10+ register packing rules -// See http://msdn.microsoft.com/en-us/library/windows/desktop/bb509632(v=vs.85).aspx -// The strategy should be ENCODE_LOOSE for D3D9 constant blocks, and ENCODE_PACKED -// for everything else (D3D10+ constant blocks and all attributes/varyings). - -class HLSLBlockEncoder : public BlockLayoutEncoder -{ - public: - enum HLSLBlockEncoderStrategy - { - ENCODE_PACKED, - ENCODE_LOOSE - }; - - HLSLBlockEncoder(HLSLBlockEncoderStrategy strategy, bool transposeMatrices); - - void enterAggregateType() override; - void exitAggregateType() override; - void skipRegisters(unsigned int numRegisters); - - bool isPacked() const { return mEncoderStrategy == ENCODE_PACKED; } - - static HLSLBlockEncoderStrategy GetStrategyFor(ShShaderOutput outputType); - - protected: - void getBlockLayoutInfo(GLenum type, - const std::vector &arraySizes, - bool isRowMajorMatrix, - int *arrayStrideOut, - int *matrixStrideOut) override; - void advanceOffset(GLenum type, - const std::vector &arraySizes, - bool isRowMajorMatrix, - int arrayStride, - int matrixStride) override; - - HLSLBlockEncoderStrategy mEncoderStrategy; - bool mTransposeMatrices; -}; - -// This method returns the number of used registers for a ShaderVariable. It is dependent on the -// HLSLBlockEncoder class to count the number of used registers in a struct (which are individually -// packed according to the same rules). -unsigned int HLSLVariableRegisterCount(const Uniform &variable, ShShaderOutput outputType); -} - -#endif // COMMON_BLOCKLAYOUTHLSL_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/emulated_builtin_function_data_hlsl.json b/src/3rdparty/angle/src/compiler/translator/emulated_builtin_function_data_hlsl.json deleted file mode 100644 index 32e500fe67..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/emulated_builtin_function_data_hlsl.json +++ /dev/null @@ -1,1382 +0,0 @@ -[ - { - "op":"mod", - "return_type":"float", - "args":[ - "float x", - "float y" - ], - "body":[ - "return x - y * floor(x / y);" - ] - }, - { - "op":"mod", - "return_type":"float2", - "args":[ - "float2 x", - "float2 y" - ], - "body":[ - "return x - y * floor(x / y);" - ] - }, - { - "op":"mod", - "return_type":"float2", - "args":[ - "float2 x", - "float y" - ], - "body":[ - "return x - y * floor(x / y);" - ] - }, - { - "op":"mod", - "return_type":"float3", - "args":[ - "float3 x", - "float3 y" - ], - "body":[ - "return x - y * floor(x / y);" - ] - }, - { - "op":"mod", - "return_type":"float3", - "args":[ - "float3 x", - "float y" - ], - "body":[ - "return x - y * floor(x / y);" - ] - }, - { - "op":"mod", - "return_type":"float4", - "args":[ - "float4 x", - "float4 y" - ], - "body":[ - "return x - y * floor(x / y);" - ] - }, - { - "op":"mod", - "return_type":"float4", - "args":[ - "float4 x", - "float y" - ], - "body":[ - "return x - y * floor(x / y);" - ] - }, - { - "op":"frexp", - "return_type":"float", - "args":[ - "float x", - "out int exp" - ], - "body":[ - "float fexp;", - "float mantissa = frexp(abs(x), fexp) * sign(x);", - "exp = int(fexp);", - "return mantissa;" - ] - }, - { - "op":"frexp", - "return_type":"float2", - "args":[ - "float2 x", - "out int2 exp" - ], - "body":[ - "float2 fexp;", - "float2 mantissa = frexp(abs(x), fexp) * sign(x);", - "exp = int2(fexp);", - "return mantissa;" - ] - }, - { - "op":"frexp", - "return_type":"float3", - "args":[ - "float3 x", - "out int3 exp" - ], - "body":[ - "float3 fexp;", - "float3 mantissa = frexp(abs(x), fexp) * sign(x);", - "exp = int3(fexp);", - "return mantissa;" - ] - }, - { - "op":"frexp", - "return_type":"float4", - "args":[ - "float4 x", - "out int4 exp" - ], - "body":[ - "float4 fexp;", - "float4 mantissa = frexp(abs(x), fexp) * sign(x);", - "exp = int4(fexp);", - "return mantissa;" - ] - }, - { - "op":"ldexp", - "return_type":"float", - "args":[ - "float x", - "int exp" - ], - "body":[ - "return ldexp(x, float(exp));" - ] - }, - { - "op":"ldexp", - "return_type":"float2", - "args":[ - "float2 x", - "int2 exp" - ], - "body":[ - "return ldexp(x, float2(exp));" - ] - }, - { - "op":"ldexp", - "return_type":"float3", - "args":[ - "float3 x", - "int3 exp" - ], - "body":[ - "return ldexp(x, float3(exp));" - ] - }, - { - "op":"ldexp", - "return_type":"float4", - "args":[ - "float4 x", - "int4 exp" - ], - "body":[ - "return ldexp(x, float4(exp));" - ] - }, - { - "op":"faceforward", - "return_type":"float", - "args":[ - "float N", - "float I", - "float Nref" - ], - "body":[ - "if(dot(Nref, I) >= 0)", - "{", - " return -N;", - "}", - "else", - "{", - " return N;", - "}" - ] - }, - { - "op":"faceforward", - "return_type":"float2", - "args":[ - "float2 N", - "float2 I", - "float2 Nref" - ], - "body":[ - "if(dot(Nref, I) >= 0)", - "{", - " return -N;", - "}", - "else", - "{", - " return N;", - "}" - ] - }, - { - "op":"faceforward", - "return_type":"float3", - "args":[ - "float3 N", - "float3 I", - "float3 Nref" - ], - "body":[ - "if(dot(Nref, I) >= 0)", - "{", - " return -N;", - "}", - "else", - "{", - " return N;", - "}" - ] - }, - { - "op":"faceforward", - "return_type":"float4", - "args":[ - "float4 N", - "float4 I", - "float4 Nref" - ], - "body":[ - "if(dot(Nref, I) >= 0)", - "{", - " return -N;", - "}", - "else", - "{", - " return N;", - "}" - ] - }, - { - "op":"atan", - "return_type":"float", - "args":[ - "float y", - "float x" - ], - "body":[ - "if(x == 0 && y == 0) x = 1;", - "return atan2(y, x);" - ] - }, - { - "op":"atan", - "return_type":"float2", - "args":[ - "float2 y", - "float2 x" - ], - "body":[ - "if(x[0] == 0 && y[0] == 0) x[0] = 1;", - "if(x[1] == 0 && y[1] == 0) x[1] = 1;", - "return float2(atan2(y[0], x[0]), atan2(y[1], x[1]));" - ] - }, - { - "op":"atan", - "return_type":"float3", - "args":[ - "float3 y", - "float3 x" - ], - "body":[ - "if(x[0] == 0 && y[0] == 0) x[0] = 1;", - "if(x[1] == 0 && y[1] == 0) x[1] = 1;", - "if(x[2] == 0 && y[2] == 0) x[2] = 1;", - "return float3(atan2(y[0], x[0]), atan2(y[1], x[1]), atan2(y[2], x[2]));" - ] - }, - { - "op":"atan", - "return_type":"float4", - "args":[ - "float4 y", - "float4 x" - ], - "body":[ - "if(x[0] == 0 && y[0] == 0) x[0] = 1;", - "if(x[1] == 0 && y[1] == 0) x[1] = 1;", - "if(x[2] == 0 && y[2] == 0) x[2] = 1;", - "if(x[3] == 0 && y[3] == 0) x[3] = 1;", - "return float4(atan2(y[0], x[0]), atan2(y[1], x[1]), atan2(y[2], ", - "x[2]), atan2(y[3], x[3]));" - ] - }, - { - "op":"asinh", - "return_type":"float", - "args":[ - "in float x" - ], - "body":[ - "return log(x + sqrt(pow(x, 2.0) + 1.0));" - ] - }, - { - "op":"asinh", - "return_type":"float2", - "args":[ - "in float2 x" - ], - "body":[ - "return log(x + sqrt(pow(x, 2.0) + 1.0));" - ] - }, - { - "op":"asinh", - "return_type":"float3", - "args":[ - "in float3 x" - ], - "body":[ - "return log(x + sqrt(pow(x, 2.0) + 1.0));" - ] - }, - { - "op":"asinh", - "return_type":"float4", - "args":[ - "in float4 x" - ], - "body":[ - "return log(x + sqrt(pow(x, 2.0) + 1.0));" - ] - }, - { - "op":"acosh", - "return_type":"float", - "args":[ - "in float x" - ], - "body":[ - "return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));" - ] - }, - { - "op":"acosh", - "return_type":"float2", - "args":[ - "in float2 x" - ], - "body":[ - "return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));" - ] - }, - { - "op":"acosh", - "return_type":"float3", - "args":[ - "in float3 x" - ], - "body":[ - "return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));" - ] - }, - { - "op":"acosh", - "return_type":"float4", - "args":[ - "in float4 x" - ], - "body":[ - "return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));" - ] - }, - { - "op":"atanh", - "return_type":"float", - "args":[ - "in float x" - ], - "body":[ - "return 0.5 * log((1.0 + x) / (1.0 - x));" - ] - }, - { - "op":"atanh", - "return_type":"float2", - "args":[ - "in float2 x" - ], - "body":[ - "return 0.5 * log((1.0 + x) / (1.0 - x));" - ] - }, - { - "op":"atanh", - "return_type":"float3", - "args":[ - "in float3 x" - ], - "body":[ - "return 0.5 * log((1.0 + x) / (1.0 - x));" - ] - }, - { - "op":"atanh", - "return_type":"float4", - "args":[ - "in float4 x" - ], - "body":[ - "return 0.5 * log((1.0 + x) / (1.0 - x));" - ] - }, - { - "op":"roundEven", - "return_type":"float", - "args":[ - "in float x" - ], - "body":[ - "return (frac(x) == 0.5 && trunc(x) % 2.0 == 0.0) ? trunc(x) : round(x);" - ] - }, - { - "op":"roundEven", - "return_type":"float2", - "args":[ - "in float2 x" - ], - "body":[ - "float2 v;", - "v[0] = (frac(x[0]) == 0.5 && trunc(x[0]) % 2.0 == 0.0) ? trunc(x[0]) : round(x[0]);", - "v[1] = (frac(x[1]) == 0.5 && trunc(x[1]) % 2.0 == 0.0) ? trunc(x[1]) : round(x[1]);", - "return v;" - ] - }, - { - "op":"roundEven", - "return_type":"float3", - "args":[ - "in float3 x" - ], - "body":[ - "float3 v;", - "v[0] = (frac(x[0]) == 0.5 && trunc(x[0]) % 2.0 == 0.0) ? trunc(x[0]) : round(x[0]);", - "v[1] = (frac(x[1]) == 0.5 && trunc(x[1]) % 2.0 == 0.0) ? trunc(x[1]) : round(x[1]);", - "v[2] = (frac(x[2]) == 0.5 && trunc(x[2]) % 2.0 == 0.0) ? trunc(x[2]) : round(x[2]);", - "return v;" - ] - }, - { - "op":"roundEven", - "return_type":"float4", - "args":[ - "in float4 x" - ], - "body":[ - "float4 v;", - "v[0] = (frac(x[0]) == 0.5 && trunc(x[0]) % 2.0 == 0.0) ? trunc(x[0]) : round(x[0]);", - "v[1] = (frac(x[1]) == 0.5 && trunc(x[1]) % 2.0 == 0.0) ? trunc(x[1]) : round(x[1]);", - "v[2] = (frac(x[2]) == 0.5 && trunc(x[2]) % 2.0 == 0.0) ? trunc(x[2]) : round(x[2]);", - "v[3] = (frac(x[3]) == 0.5 && trunc(x[3]) % 2.0 == 0.0) ? trunc(x[3]) : round(x[3]);", - "return v;" - ] - }, - { - "op":"packSnorm2x16", - "return_type":"uint", - "args":[ - "in float2 v" - ], - "helper":[ - "int webgl_toSnorm16(in float x) {", - " return int(round(clamp(x, -1.0, 1.0) * 32767.0));", - "}" - ], - "body":[ - "int x = webgl_toSnorm16(v.x);", - "int y = webgl_toSnorm16(v.y);", - "return (asuint(y) << 16) | (asuint(x) & 0xffffu);" - ] - }, - { - "op":"packUnorm2x16", - "return_type":"uint", - "args":[ - "in float2 v" - ], - "helper":[ - "uint webgl_toUnorm16(in float x) {", - " return uint(round(clamp(x, 0.0, 1.0) * 65535.0));", - "}" - ], - "body":[ - "uint x = webgl_toUnorm16(v.x);", - "uint y = webgl_toUnorm16(v.y);", - "return (y << 16) | x;" - ] - }, - { - "op":"packHalf2x16", - "return_type":"uint", - "args":[ - "in float2 v" - ], - "body":[ - "uint x = f32tof16(v.x);", - "uint y = f32tof16(v.y);", - "return (y << 16) | x;" - ] - }, - { - "op":"unpackSnorm2x16", - "return_type":"float2", - "args":[ - "in uint u" - ], - "helper":[ - "float webgl_fromSnorm16(in uint x) {", - " int xi = asint(x & 0x7fffu) - asint(x & 0x8000u);", - " return clamp(float(xi) / 32767.0, -1.0, 1.0);", - "}" - ], - "body":[ - "uint y = (u >> 16);", - "uint x = u;", - "return float2(webgl_fromSnorm16(x), webgl_fromSnorm16(y));" - ] - }, - { - "op":"unpackUnorm2x16", - "return_type":"float2", - "args":[ - "in uint u" - ], - "helper":[ - "float webgl_fromUnorm16(in uint x) {", - " return float(x) / 65535.0;", - "}" - ], - "body":[ - "uint y = (u >> 16);", - "uint x = u & 0xffffu;", - "return float2(webgl_fromUnorm16(x), webgl_fromUnorm16(y));" - ] - }, - { - "op":"unpackHalf2x16", - "return_type":"float2", - "args":[ - "in uint u" - ], - "body":[ - "uint y = (u >> 16);", - "uint x = u & 0xffffu;", - "return float2(f16tof32(x), f16tof32(y));" - ] - }, - { - "op":"packSnorm4x8", - "return_type":"uint", - "args":[ - "in float4 v" - ], - "helper":[ - "int webgl_toSnorm8(in float x) {", - " return int(round(clamp(x, -1.0, 1.0) * 127.0));", - "}" - ], - "body":[ - "int x = webgl_toSnorm8(v.x);", - "int y = webgl_toSnorm8(v.y);", - "int z = webgl_toSnorm8(v.z);", - "int w = webgl_toSnorm8(v.w);", - "return ((asuint(w) & 0xffu) << 24) | ((asuint(z) & 0xffu) << 16) ", - "| ((asuint(y) & 0xffu) << 8) | (asuint(x) & 0xffu);" - ] - }, - { - "op":"packUnorm4x8", - "return_type":"uint", - "args":[ - "in float4 v" - ], - "helper":[ - "uint webgl_toUnorm8(in float x) {", - " return uint(round(clamp(x, 0.0, 1.0) * 255.0));", - "}" - ], - "body":[ - "uint x = webgl_toUnorm8(v.x);", - "uint y = webgl_toUnorm8(v.y);", - "uint z = webgl_toUnorm8(v.z);", - "uint w = webgl_toUnorm8(v.w);", - "return (w << 24) | (z << 16) | (y << 8) | x;" - ] - }, - { - "op":"unpackSnorm4x8", - "return_type":"float4", - "args":[ - "in uint u" - ], - "helper":[ - "float webgl_fromSnorm8(in uint x) {", - " int xi = asint(x & 0x7fu) - asint(x & 0x80u);", - " return clamp(float(xi) / 127.0, -1.0, 1.0);", - "}" - ], - "body":[ - "uint w = (u >> 24);", - "uint z = (u >> 16);", - "uint y = (u >> 8);", - "uint x = u;", - "return float4(webgl_fromSnorm8(x), webgl_fromSnorm8(y), ", - "webgl_fromSnorm8(z), webgl_fromSnorm8(w));" - ] - }, - { - "op":"unpackUnorm4x8", - "return_type":"float4", - "args":[ - "in uint u" - ], - "helper":[ - "float webgl_fromUnorm8(in uint x) {", - " return float(x) / 255.0;", - "}" - ], - "body":[ - "uint w = (u >> 24) & 0xffu;", - "uint z = (u >> 16) & 0xffu;", - "uint y = (u >> 8) & 0xffu;", - "uint x = u & 0xffu;", - "return float4(webgl_fromUnorm8(x), webgl_fromUnorm8(y), ", - "webgl_fromUnorm8(z), webgl_fromUnorm8(w));" - ] - }, - { - "comment":[ - "The matrix resulting from outer product needs to be transposed", - "(matrices are stored as transposed to simplify element access in HLSL).", - "So the function should return transpose(c * r) where c is a column vector", - "and r is a row vector. This can be simplified by using the following", - "formula:", - "transpose(c * r) = transpose(r) * transpose(c)", - "transpose(r) and transpose(c) are in a sense free, since to get the", - "transpose of r, we simply can build a column matrix out of the original", - "vector instead of a row matrix." - ], - "op":"outerProduct", - "return_type":"float2x2", - "args":[ - "in float2 c", - "in float2 r" - ], - "body":[ - "return mul(float2x1(r), float1x2(c));" - ] - }, - { - "op":"outerProduct", - "return_type":"float3x3", - "args":[ - "in float3 c", - "in float3 r" - ], - "body":[ - "return mul(float3x1(r), float1x3(c));" - ] - }, - { - "op":"outerProduct", - "return_type":"float4x4", - "args":[ - "in float4 c", - "in float4 r" - ], - "body":[ - "return mul(float4x1(r), float1x4(c));" - ] - }, - { - "op":"outerProduct", - "return_type":"float2x3", - "args":[ - "in float3 c", - "in float2 r" - ], - "body":[ - "return mul(float2x1(r), float1x3(c));" - ] - }, - { - "op":"outerProduct", - "return_type":"float3x2", - "args":[ - "in float2 c", - "in float3 r" - ], - "body":[ - "return mul(float3x1(r), float1x2(c));" - ] - }, - { - "op":"outerProduct", - "return_type":"float2x4", - "args":[ - "in float4 c", - "in float2 r" - ], - "body":[ - "return mul(float2x1(r), float1x4(c));" - ] - }, - { - "op":"outerProduct", - "return_type":"float4x2", - "args":[ - "in float2 c", - "in float4 r" - ], - "body":[ - "return mul(float4x1(r), float1x2(c));" - ] - }, - { - "op":"outerProduct", - "return_type":"float3x4", - "args":[ - "in float4 c", - "in float3 r" - ], - "body":[ - "return mul(float3x1(r), float1x4(c));" - ] - }, - { - "op":"outerProduct", - "return_type":"float4x3", - "args":[ - "in float3 c", - "in float4 r" - ], - "body":[ - "return mul(float4x1(r), float1x3(c));" - ] - }, - { - "comment":[ - "Remember here that the parameter matrix is actually the transpose", - "of the matrix that we're trying to invert, and the resulting matrix", - "should also be the transpose of the inverse.", - "When accessing the parameter matrix with m[a][b] it can be thought of so", - "that a is the column and b is the row of the matrix that we're inverting.", - "We calculate the inverse as the adjugate matrix divided by the", - "determinant of the matrix being inverted. However, as the result needs", - "to be transposed, we actually use of the transpose of the adjugate matrix", - "which happens to be the cofactor matrix. That's stored in 'cof'.", - "We don't need to care about divide-by-zero since results are undefined", - "for singular or poorly-conditioned matrices." - ], - "op":"inverse", - "return_type":"float2x2", - "args":[ - "in float2x2 m" - ], - "body":[ - "float2x2 cof = { m[1][1], -m[0][1], -m[1][0], m[0][0] };", - "return cof / determinant(transpose(m));" - ] - }, - { - "comment":[ - "cofAB is the cofactor for column A and row B." - ], - "op":"inverse", - "return_type":"float3x3", - "args":[ - "in float3x3 m" - ], - "body":[ - "float cof00 = m[1][1] * m[2][2] - m[2][1] * m[1][2];", - "float cof01 = -(m[1][0] * m[2][2] - m[2][0] * m[1][2]);", - "float cof02 = m[1][0] * m[2][1] - m[2][0] * m[1][1];", - "float cof10 = -(m[0][1] * m[2][2] - m[2][1] * m[0][2]);", - "float cof11 = m[0][0] * m[2][2] - m[2][0] * m[0][2];", - "float cof12 = -(m[0][0] * m[2][1] - m[2][0] * m[0][1]);", - "float cof20 = m[0][1] * m[1][2] - m[1][1] * m[0][2];", - "float cof21 = -(m[0][0] * m[1][2] - m[1][0] * m[0][2]);", - "float cof22 = m[0][0] * m[1][1] - m[1][0] * m[0][1];", - "float3x3 cof = { cof00, cof10, cof20, cof01, cof11, cof21, cof02, cof12, cof22 };", - "return cof / determinant(transpose(m));" - ] - }, - { - "op":"inverse", - "return_type":"float4x4", - "args":[ - "in float4x4 m" - ], - "body":[ - "float cof00 = m[1][1] * m[2][2] * m[3][3] + m[2][1] * m[3][2] * m[1][3] + m[3][1] * ", - "m[1][2] * m[2][3]", - " - m[1][1] * m[3][2] * m[2][3] - m[2][1] * m[1][2] * m[3][3] - m[3][1] * m[2][2] * ", - "m[1][3];", - "float cof01 = -(m[1][0] * m[2][2] * m[3][3] + m[2][0] * m[3][2] * m[1][3] + m[3][0] * ", - "m[1][2] * m[2][3]", - " - m[1][0] * m[3][2] * m[2][3] - m[2][0] * m[1][2] * m[3][3] - m[3][0] * m[2][2] * ", - "m[1][3]);", - "float cof02 = m[1][0] * m[2][1] * m[3][3] + m[2][0] * m[3][1] * m[1][3] + m[3][0] * ", - "m[1][1] * m[2][3]", - " - m[1][0] * m[3][1] * m[2][3] - m[2][0] * m[1][1] * m[3][3] - m[3][0] * m[2][1] * ", - "m[1][3];", - "float cof03 = -(m[1][0] * m[2][1] * m[3][2] + m[2][0] * m[3][1] * m[1][2] + m[3][0] * ", - "m[1][1] * m[2][2]", - " - m[1][0] * m[3][1] * m[2][2] - m[2][0] * m[1][1] * m[3][2] - m[3][0] * m[2][1] * ", - "m[1][2]);", - "float cof10 = -(m[0][1] * m[2][2] * m[3][3] + m[2][1] * m[3][2] * m[0][3] + m[3][1] * ", - "m[0][2] * m[2][3]", - " - m[0][1] * m[3][2] * m[2][3] - m[2][1] * m[0][2] * m[3][3] - m[3][1] * m[2][2] * ", - "m[0][3]);", - "float cof11 = m[0][0] * m[2][2] * m[3][3] + m[2][0] * m[3][2] * m[0][3] + m[3][0] * ", - "m[0][2] * m[2][3]", - " - m[0][0] * m[3][2] * m[2][3] - m[2][0] * m[0][2] * m[3][3] - m[3][0] * m[2][2] * ", - "m[0][3];", - "float cof12 = -(m[0][0] * m[2][1] * m[3][3] + m[2][0] * m[3][1] * m[0][3] + m[3][0] * ", - "m[0][1] * m[2][3]", - " - m[0][0] * m[3][1] * m[2][3] - m[2][0] * m[0][1] * m[3][3] - m[3][0] * m[2][1] * ", - "m[0][3]);", - "float cof13 = m[0][0] * m[2][1] * m[3][2] + m[2][0] * m[3][1] * m[0][2] + m[3][0] * ", - "m[0][1] * m[2][2]", - " - m[0][0] * m[3][1] * m[2][2] - m[2][0] * m[0][1] * m[3][2] - m[3][0] * m[2][1] * ", - "m[0][2];", - "float cof20 = m[0][1] * m[1][2] * m[3][3] + m[1][1] * m[3][2] * m[0][3] + m[3][1] * ", - "m[0][2] * m[1][3]", - " - m[0][1] * m[3][2] * m[1][3] - m[1][1] * m[0][2] * m[3][3] - m[3][1] * m[1][2] * ", - "m[0][3];", - "float cof21 = -(m[0][0] * m[1][2] * m[3][3] + m[1][0] * m[3][2] * m[0][3] + m[3][0] * ", - "m[0][2] * m[1][3]", - " - m[0][0] * m[3][2] * m[1][3] - m[1][0] * m[0][2] * m[3][3] - m[3][0] * m[1][2] * ", - "m[0][3]);", - "float cof22 = m[0][0] * m[1][1] * m[3][3] + m[1][0] * m[3][1] * m[0][3] + m[3][0] * ", - "m[0][1] * m[1][3]", - " - m[0][0] * m[3][1] * m[1][3] - m[1][0] * m[0][1] * m[3][3] - m[3][0] * m[1][1] * ", - "m[0][3];", - "float cof23 = -(m[0][0] * m[1][1] * m[3][2] + m[1][0] * m[3][1] * m[0][2] + m[3][0] * ", - "m[0][1] * m[1][2]", - " - m[0][0] * m[3][1] * m[1][2] - m[1][0] * m[0][1] * m[3][2] - m[3][0] * m[1][1] * ", - "m[0][2]);", - "float cof30 = -(m[0][1] * m[1][2] * m[2][3] + m[1][1] * m[2][2] * m[0][3] + m[2][1] * ", - "m[0][2] * m[1][3]", - " - m[0][1] * m[2][2] * m[1][3] - m[1][1] * m[0][2] * m[2][3] - m[2][1] * m[1][2] * ", - "m[0][3]);", - "float cof31 = m[0][0] * m[1][2] * m[2][3] + m[1][0] * m[2][2] * m[0][3] + m[2][0] * ", - "m[0][2] * m[1][3]", - " - m[0][0] * m[2][2] * m[1][3] - m[1][0] * m[0][2] * m[2][3] - m[2][0] * m[1][2] * ", - "m[0][3];", - "float cof32 = -(m[0][0] * m[1][1] * m[2][3] + m[1][0] * m[2][1] * m[0][3] + m[2][0] * ", - "m[0][1] * m[1][3]", - " - m[0][0] * m[2][1] * m[1][3] - m[1][0] * m[0][1] * m[2][3] - m[2][0] * m[1][1] * ", - "m[0][3]);", - "float cof33 = m[0][0] * m[1][1] * m[2][2] + m[1][0] * m[2][1] * m[0][2] + m[2][0] * ", - "m[0][1] * m[1][2]", - " - m[0][0] * m[2][1] * m[1][2] - m[1][0] * m[0][1] * m[2][2] - m[2][0] * m[1][1] * ", - "m[0][2];", - "float4x4 cof = { cof00, cof10, cof20, cof30, cof01, cof11, cof21, cof31,", - " cof02, cof12, cof22, cof32, cof03, cof13, cof23, cof33 };", - "return cof / determinant(transpose(m));" - ] - }, - { - "comment":[ - "Emulate ESSL3 variant of mix that takes last argument as boolean vector.", - "genType mix(genType x, genType y, genBType a): Selects which vector each returned component", - "comes from. For a component of 'a' that is false, the corresponding component of 'x' is", - "returned. For a component of 'a' that is true, the corresponding component of 'y' is returned." - ], - "op":"mix", - "return_type":"float", - "args":[ - "float x", - "float y", - "bool a" - ], - "body":[ - "return a ? y : x;" - ] - }, - { - "op":"mix", - "return_type":"float2", - "args":[ - "float2 x", - "float2 y", - "bool2 a" - ], - "body":[ - "return a ? y : x;" - ] - }, - { - "op":"mix", - "return_type":"float3", - "args":[ - "float3 x", - "float3 y", - "bool3 a" - ], - "body":[ - "return a ? y : x;" - ] - }, - { - "op":"mix", - "return_type":"float4", - "args":[ - "float4 x", - "float4 y", - "bool4 a" - ], - "body":[ - "return a ? y : x;" - ] - }, - { - "op":"bitfieldExtract", - "return_type":"uint", - "args":[ - "uint value", - "int offset", - "int bits" - ], - "body":[ - "if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)", - "{", - " return 0u;", - "}", - "uint maskMsb = (1u << (bits - 1));", - "uint mask = ((maskMsb - 1u) | maskMsb) << offset;", - "return (value & mask) >> offset;" - ] - }, - { - "op":"bitfieldExtract", - "return_type":"uint2", - "args":[ - "uint2 value", - "int offset", - "int bits" - ], - "body":[ - "if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)", - "{", - " return uint2(0u, 0u);", - "}", - "uint maskMsb = (1u << (bits - 1));", - "uint mask = ((maskMsb - 1u) | maskMsb) << offset;", - "return (value & mask) >> offset;" - ] - }, - { - "op":"bitfieldExtract", - "return_type":"uint3", - "args":[ - "uint3 value", - "int offset", - "int bits" - ], - "body":[ - "if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)", - "{", - " return uint3(0u, 0u, 0u);", - "}", - "uint maskMsb = (1u << (bits - 1));", - "uint mask = ((maskMsb - 1u) | maskMsb) << offset;", - "return (value & mask) >> offset;" - ] - }, - { - "op":"bitfieldExtract", - "return_type":"uint4", - "args":[ - "uint4 value", - "int offset", - "int bits" - ], - "body":[ - "if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)", - "{", - " return uint4(0u, 0u, 0u, 0u);", - "}", - "uint maskMsb = (1u << (bits - 1));", - "uint mask = ((maskMsb - 1u) | maskMsb) << offset;", - "return (value & mask) >> offset;" - ] - }, - { - "op":"bitfieldExtract", - "return_type":"int", - "args":[ - "int value", - "int offset", - "int bits" - ], - "body":[ - "if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)", - "{", - " return 0;", - "}", - "uint maskMsb = (1u << (bits - 1));", - "uint mask = ((maskMsb - 1u) | maskMsb) << offset;", - "uint resultUnsigned = (asuint(value) & mask) >> offset;", - "if (bits != 32 && (resultUnsigned & maskMsb) != 0)", - "{", - " uint higherBitsMask = ((1u << (32 - bits)) - 1u) << bits;", - " resultUnsigned |= higherBitsMask;", - "}", - "return asint(resultUnsigned);" - ] - }, - { - "op":"bitfieldExtract", - "return_type":"int2", - "args":[ - "int2 value", - "int offset", - "int bits" - ], - "body":[ - "if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)", - "{", - " return int2(0, 0);", - "}", - "uint maskMsb = (1u << (bits - 1));", - "uint mask = ((maskMsb - 1u) | maskMsb) << offset;", - "uint2 resultUnsigned = (asuint(value) & mask) >> offset;", - "if (bits != 32)", - "{", - " uint higherBitsMask = ((1u << (32 - bits)) - 1u) << bits;", - " resultUnsigned |= ((resultUnsigned & maskMsb) >> (bits - 1)) * higherBitsMask;", - "}", - "return asint(resultUnsigned);" - ] - }, - { - "op":"bitfieldExtract", - "return_type":"int3", - "args":[ - "int3 value", - "int offset", - "int bits" - ], - "body":[ - "if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)", - "{", - " return int3(0, 0, 0);", - "}", - "uint maskMsb = (1u << (bits - 1));", - "uint mask = ((maskMsb - 1u) | maskMsb) << offset;", - "uint3 resultUnsigned = (asuint(value) & mask) >> offset;", - "if (bits != 32)", - "{", - " uint higherBitsMask = ((1u << (32 - bits)) - 1u) << bits;", - " resultUnsigned |= ((resultUnsigned & maskMsb) >> (bits - 1)) * higherBitsMask;", - "}", - "return asint(resultUnsigned);" - ] - }, - { - "op":"bitfieldExtract", - "return_type":"int4", - "args":[ - "int4 value", - "int offset", - "int bits" - ], - "body":[ - "if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)", - "{", - " return int4(0, 0, 0, 0);", - "}", - "uint maskMsb = (1u << (bits - 1));", - "uint mask = ((maskMsb - 1u) | maskMsb) << offset;", - "uint4 resultUnsigned = (asuint(value) & mask) >> offset;", - "if (bits != 32)", - "{", - " uint higherBitsMask = ((1u << (32 - bits)) - 1u) << bits;", - " resultUnsigned |= ((resultUnsigned & maskMsb) >> (bits - 1)) * higherBitsMask;", - "}", - "return asint(resultUnsigned);" - ] - }, - { - "op":"bitfieldInsert", - "return_type":"uint", - "args":[ - "uint base", - "uint insert", - "int offset", - "int bits" - ], - "body":[ - "if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)", - "{", - " return base;", - "}", - "uint maskMsb = (1u << (bits - 1));", - "uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;", - "uint baseMask = ~insertMask;", - "return (base & baseMask) | ((insert << offset) & insertMask);" - ] - }, - { - "op":"bitfieldInsert", - "return_type":"uint2", - "args":[ - "uint2 base", - "uint2 insert", - "int offset", - "int bits" - ], - "body":[ - "if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)", - "{", - " return base;", - "}", - "uint maskMsb = (1u << (bits - 1));", - "uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;", - "uint baseMask = ~insertMask;", - "return (base & baseMask) | ((insert << offset) & insertMask);" - ] - }, - { - "op":"bitfieldInsert", - "return_type":"uint3", - "args":[ - "uint3 base", - "uint3 insert", - "int offset", - "int bits" - ], - "body":[ - "if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)", - "{", - " return base;", - "}", - "uint maskMsb = (1u << (bits - 1));", - "uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;", - "uint baseMask = ~insertMask;", - "return (base & baseMask) | ((insert << offset) & insertMask);" - ] - }, - { - "op":"bitfieldInsert", - "return_type":"uint4", - "args":[ - "uint4 base", - "uint4 insert", - "int offset", - "int bits" - ], - "body":[ - "if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)", - "{", - " return base;", - "}", - "uint maskMsb = (1u << (bits - 1));", - "uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;", - "uint baseMask = ~insertMask;", - "return (base & baseMask) | ((insert << offset) & insertMask);" - ] - }, - { - "op":"bitfieldInsert", - "return_type":"int", - "args":[ - "int base", - "int insert", - "int offset", - "int bits" - ], - "body":[ - "if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)", - "{", - " return base;", - "}", - "uint maskMsb = (1u << (bits - 1));", - "uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;", - "uint baseMask = ~insertMask;", - "uint resultUnsigned = (asuint(base) & baseMask) | ((asuint(insert) << offset) & ", - " insertMask);", - "return asint(resultUnsigned);" - ] - }, - { - "op":"bitfieldInsert", - "return_type":"int2", - "args":[ - "int2 base", - "int2 insert", - "int offset", - "int bits" - ], - "body":[ - "if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)", - "{", - " return base;", - "}", - "uint maskMsb = (1u << (bits - 1));", - "uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;", - "uint baseMask = ~insertMask;", - "uint2 resultUnsigned = (asuint(base) & baseMask) | ((asuint(insert) << offset) & ", - " insertMask);", - "return asint(resultUnsigned);" - ] - }, - { - "op":"bitfieldInsert", - "return_type":"int3", - "args":[ - "int3 base", - "int3 insert", - "int offset", - "int bits" - ], - "body":[ - "if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)", - "{", - " return base;", - "}", - "uint maskMsb = (1u << (bits - 1));", - "uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;", - "uint baseMask = ~insertMask;", - "uint3 resultUnsigned = (asuint(base) & baseMask) | ((asuint(insert) << offset) & ", - " insertMask);", - "return asint(resultUnsigned);" - ] - }, - { - "op":"bitfieldInsert", - "return_type":"int4", - "args":[ - "int4 base", - "int4 insert", - "int offset", - "int bits" - ], - "body":[ - "if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)", - "{", - " return base;", - "}", - "uint maskMsb = (1u << (bits - 1));", - "uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;", - "uint baseMask = ~insertMask;", - "uint4 resultUnsigned = (asuint(base) & baseMask) | ((asuint(insert) << offset) & ", - "insertMask);", - "return asint(resultUnsigned);" - ] - }, - { - "op":"uaddCarry", - "return_type":"uint", - "args":[ - "uint x", - "uint y", - "out uint carry" - ], - "body":[ - "carry = uint(x > (0xffffffffu - y));", - "return x + y;" - ] - }, - { - "op":"uaddCarry", - "return_type":"uint2", - "args":[ - "uint2 x", - "uint2 y", - "out uint2 carry" - ], - "body":[ - "carry = uint2(x > (0xffffffffu - y));", - "return x + y;" - ] - }, - { - "op":"uaddCarry", - "return_type":"uint3", - "args":[ - "uint3 x", - "uint3 y", - "out uint3 carry" - ], - "body":[ - "carry = uint3(x > (0xffffffffu - y));", - "return x + y;" - ] - }, - { - "op":"uaddCarry", - "return_type":"uint4", - "args":[ - "uint4 x", - "uint4 y", - "out uint4 carry" - ], - "body":[ - "carry = uint4(x > (0xffffffffu - y));", - "return x + y;" - ] - }, - { - "op":"usubBorrow", - "return_type":"uint", - "args":[ - "uint x", - "uint y", - "out uint borrow" - ], - "body":[ - "borrow = uint(x < y);", - "return x - y;" - ] - }, - { - "op":"usubBorrow", - "return_type":"uint2", - "args":[ - "uint2 x", - "uint2 y", - "out uint2 borrow" - ], - "body":[ - "borrow = uint2(x < y);", - "return x - y;" - ] - }, - { - "op":"usubBorrow", - "return_type":"uint3", - "args":[ - "uint3 x", - "uint3 y", - "out uint3 borrow" - ], - "body":[ - "borrow = uint3(x < y);", - "return x - y;" - ] - }, - { - "op":"usubBorrow", - "return_type":"uint4", - "args":[ - "uint4 x", - "uint4 y", - "out uint4 borrow" - ], - "body":[ - "borrow = uint4(x < y);", - "return x - y;" - ] - } -] diff --git a/src/3rdparty/angle/src/compiler/translator/emulated_builtin_functions_hlsl_autogen.cpp b/src/3rdparty/angle/src/compiler/translator/emulated_builtin_functions_hlsl_autogen.cpp deleted file mode 100644 index 288da5e0f5..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/emulated_builtin_functions_hlsl_autogen.cpp +++ /dev/null @@ -1,859 +0,0 @@ -// GENERATED FILE - DO NOT EDIT. -// Generated by gen_emulated_builtin_function_tables.py using data from -// emulated_builtin_function_data_hlsl.json. -// -// Copyright 2017 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// emulated_builtin_functions_hlsl: -// HLSL code for emulating GLSL builtin functions not present in HLSL. - -#include "compiler/translator/BuiltInFunctionEmulator.h" - -namespace sh -{ - -namespace -{ - -struct FunctionPair -{ - constexpr FunctionPair(const MiniFunctionId &idIn, const char *bodyIn) : id(idIn), body(bodyIn) - { - } - - MiniFunctionId id; - const char *body; -}; - -constexpr FunctionPair g_hlslFunctions[] = { - {{EOpMod, ParamType::Float1, ParamType::Float1}, - "float mod_emu(float x, float y)\n" - "{\n" - " return x - y * floor(x / y);\n" - "}\n"}, - {{EOpMod, ParamType::Float2, ParamType::Float2}, - "float2 mod_emu(float2 x, float2 y)\n" - "{\n" - " return x - y * floor(x / y);\n" - "}\n"}, - {{EOpMod, ParamType::Float2, ParamType::Float1}, - "float2 mod_emu(float2 x, float y)\n" - "{\n" - " return x - y * floor(x / y);\n" - "}\n"}, - {{EOpMod, ParamType::Float3, ParamType::Float3}, - "float3 mod_emu(float3 x, float3 y)\n" - "{\n" - " return x - y * floor(x / y);\n" - "}\n"}, - {{EOpMod, ParamType::Float3, ParamType::Float1}, - "float3 mod_emu(float3 x, float y)\n" - "{\n" - " return x - y * floor(x / y);\n" - "}\n"}, - {{EOpMod, ParamType::Float4, ParamType::Float4}, - "float4 mod_emu(float4 x, float4 y)\n" - "{\n" - " return x - y * floor(x / y);\n" - "}\n"}, - {{EOpMod, ParamType::Float4, ParamType::Float1}, - "float4 mod_emu(float4 x, float y)\n" - "{\n" - " return x - y * floor(x / y);\n" - "}\n"}, - {{EOpFrexp, ParamType::Float1, ParamType::Int1}, - "float frexp_emu(float x, out int exp)\n" - "{\n" - " float fexp;\n" - " float mantissa = frexp(abs(x), fexp) * sign(x);\n" - " exp = int(fexp);\n" - " return mantissa;\n" - "}\n"}, - {{EOpFrexp, ParamType::Float2, ParamType::Int2}, - "float2 frexp_emu(float2 x, out int2 exp)\n" - "{\n" - " float2 fexp;\n" - " float2 mantissa = frexp(abs(x), fexp) * sign(x);\n" - " exp = int2(fexp);\n" - " return mantissa;\n" - "}\n"}, - {{EOpFrexp, ParamType::Float3, ParamType::Int3}, - "float3 frexp_emu(float3 x, out int3 exp)\n" - "{\n" - " float3 fexp;\n" - " float3 mantissa = frexp(abs(x), fexp) * sign(x);\n" - " exp = int3(fexp);\n" - " return mantissa;\n" - "}\n"}, - {{EOpFrexp, ParamType::Float4, ParamType::Int4}, - "float4 frexp_emu(float4 x, out int4 exp)\n" - "{\n" - " float4 fexp;\n" - " float4 mantissa = frexp(abs(x), fexp) * sign(x);\n" - " exp = int4(fexp);\n" - " return mantissa;\n" - "}\n"}, - {{EOpLdexp, ParamType::Float1, ParamType::Int1}, - "float ldexp_emu(float x, int exp)\n" - "{\n" - " return ldexp(x, float(exp));\n" - "}\n"}, - {{EOpLdexp, ParamType::Float2, ParamType::Int2}, - "float2 ldexp_emu(float2 x, int2 exp)\n" - "{\n" - " return ldexp(x, float2(exp));\n" - "}\n"}, - {{EOpLdexp, ParamType::Float3, ParamType::Int3}, - "float3 ldexp_emu(float3 x, int3 exp)\n" - "{\n" - " return ldexp(x, float3(exp));\n" - "}\n"}, - {{EOpLdexp, ParamType::Float4, ParamType::Int4}, - "float4 ldexp_emu(float4 x, int4 exp)\n" - "{\n" - " return ldexp(x, float4(exp));\n" - "}\n"}, - {{EOpFaceforward, ParamType::Float1, ParamType::Float1, ParamType::Float1}, - "float faceforward_emu(float N, float I, float Nref)\n" - "{\n" - " if(dot(Nref, I) >= 0)\n" - " {\n" - " return -N;\n" - " }\n" - " else\n" - " {\n" - " return N;\n" - " }\n" - "}\n"}, - {{EOpFaceforward, ParamType::Float2, ParamType::Float2, ParamType::Float2}, - "float2 faceforward_emu(float2 N, float2 I, float2 Nref)\n" - "{\n" - " if(dot(Nref, I) >= 0)\n" - " {\n" - " return -N;\n" - " }\n" - " else\n" - " {\n" - " return N;\n" - " }\n" - "}\n"}, - {{EOpFaceforward, ParamType::Float3, ParamType::Float3, ParamType::Float3}, - "float3 faceforward_emu(float3 N, float3 I, float3 Nref)\n" - "{\n" - " if(dot(Nref, I) >= 0)\n" - " {\n" - " return -N;\n" - " }\n" - " else\n" - " {\n" - " return N;\n" - " }\n" - "}\n"}, - {{EOpFaceforward, ParamType::Float4, ParamType::Float4, ParamType::Float4}, - "float4 faceforward_emu(float4 N, float4 I, float4 Nref)\n" - "{\n" - " if(dot(Nref, I) >= 0)\n" - " {\n" - " return -N;\n" - " }\n" - " else\n" - " {\n" - " return N;\n" - " }\n" - "}\n"}, - {{EOpAtan, ParamType::Float1, ParamType::Float1}, - "float atan_emu(float y, float x)\n" - "{\n" - " if(x == 0 && y == 0) x = 1;\n" - " return atan2(y, x);\n" - "}\n"}, - {{EOpAtan, ParamType::Float2, ParamType::Float2}, - "float2 atan_emu(float2 y, float2 x)\n" - "{\n" - " if(x[0] == 0 && y[0] == 0) x[0] = 1;\n" - " if(x[1] == 0 && y[1] == 0) x[1] = 1;\n" - " return float2(atan2(y[0], x[0]), atan2(y[1], x[1]));\n" - "}\n"}, - {{EOpAtan, ParamType::Float3, ParamType::Float3}, - "float3 atan_emu(float3 y, float3 x)\n" - "{\n" - " if(x[0] == 0 && y[0] == 0) x[0] = 1;\n" - " if(x[1] == 0 && y[1] == 0) x[1] = 1;\n" - " if(x[2] == 0 && y[2] == 0) x[2] = 1;\n" - " return float3(atan2(y[0], x[0]), atan2(y[1], x[1]), atan2(y[2], x[2]));\n" - "}\n"}, - {{EOpAtan, ParamType::Float4, ParamType::Float4}, - "float4 atan_emu(float4 y, float4 x)\n" - "{\n" - " if(x[0] == 0 && y[0] == 0) x[0] = 1;\n" - " if(x[1] == 0 && y[1] == 0) x[1] = 1;\n" - " if(x[2] == 0 && y[2] == 0) x[2] = 1;\n" - " if(x[3] == 0 && y[3] == 0) x[3] = 1;\n" - " return float4(atan2(y[0], x[0]), atan2(y[1], x[1]), atan2(y[2], \n" - " x[2]), atan2(y[3], x[3]));\n" - "}\n"}, - {{EOpAsinh, ParamType::Float1}, - "float asinh_emu(in float x)\n" - "{\n" - " return log(x + sqrt(pow(x, 2.0) + 1.0));\n" - "}\n"}, - {{EOpAsinh, ParamType::Float2}, - "float2 asinh_emu(in float2 x)\n" - "{\n" - " return log(x + sqrt(pow(x, 2.0) + 1.0));\n" - "}\n"}, - {{EOpAsinh, ParamType::Float3}, - "float3 asinh_emu(in float3 x)\n" - "{\n" - " return log(x + sqrt(pow(x, 2.0) + 1.0));\n" - "}\n"}, - {{EOpAsinh, ParamType::Float4}, - "float4 asinh_emu(in float4 x)\n" - "{\n" - " return log(x + sqrt(pow(x, 2.0) + 1.0));\n" - "}\n"}, - {{EOpAcosh, ParamType::Float1}, - "float acosh_emu(in float x)\n" - "{\n" - " return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));\n" - "}\n"}, - {{EOpAcosh, ParamType::Float2}, - "float2 acosh_emu(in float2 x)\n" - "{\n" - " return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));\n" - "}\n"}, - {{EOpAcosh, ParamType::Float3}, - "float3 acosh_emu(in float3 x)\n" - "{\n" - " return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));\n" - "}\n"}, - {{EOpAcosh, ParamType::Float4}, - "float4 acosh_emu(in float4 x)\n" - "{\n" - " return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));\n" - "}\n"}, - {{EOpAtanh, ParamType::Float1}, - "float atanh_emu(in float x)\n" - "{\n" - " return 0.5 * log((1.0 + x) / (1.0 - x));\n" - "}\n"}, - {{EOpAtanh, ParamType::Float2}, - "float2 atanh_emu(in float2 x)\n" - "{\n" - " return 0.5 * log((1.0 + x) / (1.0 - x));\n" - "}\n"}, - {{EOpAtanh, ParamType::Float3}, - "float3 atanh_emu(in float3 x)\n" - "{\n" - " return 0.5 * log((1.0 + x) / (1.0 - x));\n" - "}\n"}, - {{EOpAtanh, ParamType::Float4}, - "float4 atanh_emu(in float4 x)\n" - "{\n" - " return 0.5 * log((1.0 + x) / (1.0 - x));\n" - "}\n"}, - {{EOpRoundEven, ParamType::Float1}, - "float roundEven_emu(in float x)\n" - "{\n" - " return (frac(x) == 0.5 && trunc(x) % 2.0 == 0.0) ? trunc(x) : round(x);\n" - "}\n"}, - {{EOpRoundEven, ParamType::Float2}, - "float2 roundEven_emu(in float2 x)\n" - "{\n" - " float2 v;\n" - " v[0] = (frac(x[0]) == 0.5 && trunc(x[0]) % 2.0 == 0.0) ? trunc(x[0]) : round(x[0]);\n" - " v[1] = (frac(x[1]) == 0.5 && trunc(x[1]) % 2.0 == 0.0) ? trunc(x[1]) : round(x[1]);\n" - " return v;\n" - "}\n"}, - {{EOpRoundEven, ParamType::Float3}, - "float3 roundEven_emu(in float3 x)\n" - "{\n" - " float3 v;\n" - " v[0] = (frac(x[0]) == 0.5 && trunc(x[0]) % 2.0 == 0.0) ? trunc(x[0]) : round(x[0]);\n" - " v[1] = (frac(x[1]) == 0.5 && trunc(x[1]) % 2.0 == 0.0) ? trunc(x[1]) : round(x[1]);\n" - " v[2] = (frac(x[2]) == 0.5 && trunc(x[2]) % 2.0 == 0.0) ? trunc(x[2]) : round(x[2]);\n" - " return v;\n" - "}\n"}, - {{EOpRoundEven, ParamType::Float4}, - "float4 roundEven_emu(in float4 x)\n" - "{\n" - " float4 v;\n" - " v[0] = (frac(x[0]) == 0.5 && trunc(x[0]) % 2.0 == 0.0) ? trunc(x[0]) : round(x[0]);\n" - " v[1] = (frac(x[1]) == 0.5 && trunc(x[1]) % 2.0 == 0.0) ? trunc(x[1]) : round(x[1]);\n" - " v[2] = (frac(x[2]) == 0.5 && trunc(x[2]) % 2.0 == 0.0) ? trunc(x[2]) : round(x[2]);\n" - " v[3] = (frac(x[3]) == 0.5 && trunc(x[3]) % 2.0 == 0.0) ? trunc(x[3]) : round(x[3]);\n" - " return v;\n" - "}\n"}, - {{EOpPackSnorm2x16, ParamType::Float2}, - "int webgl_toSnorm16(in float x) {\n" - " return int(round(clamp(x, -1.0, 1.0) * 32767.0));\n" - "}\n" - "uint packSnorm2x16_emu(in float2 v)\n" - "{\n" - " int x = webgl_toSnorm16(v.x);\n" - " int y = webgl_toSnorm16(v.y);\n" - " return (asuint(y) << 16) | (asuint(x) & 0xffffu);\n" - "}\n"}, - {{EOpPackUnorm2x16, ParamType::Float2}, - "uint webgl_toUnorm16(in float x) {\n" - " return uint(round(clamp(x, 0.0, 1.0) * 65535.0));\n" - "}\n" - "uint packUnorm2x16_emu(in float2 v)\n" - "{\n" - " uint x = webgl_toUnorm16(v.x);\n" - " uint y = webgl_toUnorm16(v.y);\n" - " return (y << 16) | x;\n" - "}\n"}, - {{EOpPackHalf2x16, ParamType::Float2}, - "uint packHalf2x16_emu(in float2 v)\n" - "{\n" - " uint x = f32tof16(v.x);\n" - " uint y = f32tof16(v.y);\n" - " return (y << 16) | x;\n" - "}\n"}, - {{EOpUnpackSnorm2x16, ParamType::Uint1}, - "float webgl_fromSnorm16(in uint x) {\n" - " int xi = asint(x & 0x7fffu) - asint(x & 0x8000u);\n" - " return clamp(float(xi) / 32767.0, -1.0, 1.0);\n" - "}\n" - "float2 unpackSnorm2x16_emu(in uint u)\n" - "{\n" - " uint y = (u >> 16);\n" - " uint x = u;\n" - " return float2(webgl_fromSnorm16(x), webgl_fromSnorm16(y));\n" - "}\n"}, - {{EOpUnpackUnorm2x16, ParamType::Uint1}, - "float webgl_fromUnorm16(in uint x) {\n" - " return float(x) / 65535.0;\n" - "}\n" - "float2 unpackUnorm2x16_emu(in uint u)\n" - "{\n" - " uint y = (u >> 16);\n" - " uint x = u & 0xffffu;\n" - " return float2(webgl_fromUnorm16(x), webgl_fromUnorm16(y));\n" - "}\n"}, - {{EOpUnpackHalf2x16, ParamType::Uint1}, - "float2 unpackHalf2x16_emu(in uint u)\n" - "{\n" - " uint y = (u >> 16);\n" - " uint x = u & 0xffffu;\n" - " return float2(f16tof32(x), f16tof32(y));\n" - "}\n"}, - {{EOpPackSnorm4x8, ParamType::Float4}, - "int webgl_toSnorm8(in float x) {\n" - " return int(round(clamp(x, -1.0, 1.0) * 127.0));\n" - "}\n" - "uint packSnorm4x8_emu(in float4 v)\n" - "{\n" - " int x = webgl_toSnorm8(v.x);\n" - " int y = webgl_toSnorm8(v.y);\n" - " int z = webgl_toSnorm8(v.z);\n" - " int w = webgl_toSnorm8(v.w);\n" - " return ((asuint(w) & 0xffu) << 24) | ((asuint(z) & 0xffu) << 16) \n" - " | ((asuint(y) & 0xffu) << 8) | (asuint(x) & 0xffu);\n" - "}\n"}, - {{EOpPackUnorm4x8, ParamType::Float4}, - "uint webgl_toUnorm8(in float x) {\n" - " return uint(round(clamp(x, 0.0, 1.0) * 255.0));\n" - "}\n" - "uint packUnorm4x8_emu(in float4 v)\n" - "{\n" - " uint x = webgl_toUnorm8(v.x);\n" - " uint y = webgl_toUnorm8(v.y);\n" - " uint z = webgl_toUnorm8(v.z);\n" - " uint w = webgl_toUnorm8(v.w);\n" - " return (w << 24) | (z << 16) | (y << 8) | x;\n" - "}\n"}, - {{EOpUnpackSnorm4x8, ParamType::Uint1}, - "float webgl_fromSnorm8(in uint x) {\n" - " int xi = asint(x & 0x7fu) - asint(x & 0x80u);\n" - " return clamp(float(xi) / 127.0, -1.0, 1.0);\n" - "}\n" - "float4 unpackSnorm4x8_emu(in uint u)\n" - "{\n" - " uint w = (u >> 24);\n" - " uint z = (u >> 16);\n" - " uint y = (u >> 8);\n" - " uint x = u;\n" - " return float4(webgl_fromSnorm8(x), webgl_fromSnorm8(y), \n" - " webgl_fromSnorm8(z), webgl_fromSnorm8(w));\n" - "}\n"}, - {{EOpUnpackUnorm4x8, ParamType::Uint1}, - "float webgl_fromUnorm8(in uint x) {\n" - " return float(x) / 255.0;\n" - "}\n" - "float4 unpackUnorm4x8_emu(in uint u)\n" - "{\n" - " uint w = (u >> 24) & 0xffu;\n" - " uint z = (u >> 16) & 0xffu;\n" - " uint y = (u >> 8) & 0xffu;\n" - " uint x = u & 0xffu;\n" - " return float4(webgl_fromUnorm8(x), webgl_fromUnorm8(y), \n" - " webgl_fromUnorm8(z), webgl_fromUnorm8(w));\n" - "}\n"}, - // The matrix resulting from outer product needs to be transposed - // (matrices are stored as transposed to simplify element access in HLSL). - // So the function should return transpose(c * r) where c is a column vector - // and r is a row vector. This can be simplified by using the following - // formula: - // transpose(c * r) = transpose(r) * transpose(c) - // transpose(r) and transpose(c) are in a sense free, since to get the - // transpose of r, we simply can build a column matrix out of the original - // vector instead of a row matrix. - {{EOpOuterProduct, ParamType::Float2, ParamType::Float2}, - "float2x2 outerProduct_emu(in float2 c, in float2 r)\n" - "{\n" - " return mul(float2x1(r), float1x2(c));\n" - "}\n"}, - {{EOpOuterProduct, ParamType::Float3, ParamType::Float3}, - "float3x3 outerProduct_emu(in float3 c, in float3 r)\n" - "{\n" - " return mul(float3x1(r), float1x3(c));\n" - "}\n"}, - {{EOpOuterProduct, ParamType::Float4, ParamType::Float4}, - "float4x4 outerProduct_emu(in float4 c, in float4 r)\n" - "{\n" - " return mul(float4x1(r), float1x4(c));\n" - "}\n"}, - {{EOpOuterProduct, ParamType::Float3, ParamType::Float2}, - "float2x3 outerProduct_emu(in float3 c, in float2 r)\n" - "{\n" - " return mul(float2x1(r), float1x3(c));\n" - "}\n"}, - {{EOpOuterProduct, ParamType::Float2, ParamType::Float3}, - "float3x2 outerProduct_emu(in float2 c, in float3 r)\n" - "{\n" - " return mul(float3x1(r), float1x2(c));\n" - "}\n"}, - {{EOpOuterProduct, ParamType::Float4, ParamType::Float2}, - "float2x4 outerProduct_emu(in float4 c, in float2 r)\n" - "{\n" - " return mul(float2x1(r), float1x4(c));\n" - "}\n"}, - {{EOpOuterProduct, ParamType::Float2, ParamType::Float4}, - "float4x2 outerProduct_emu(in float2 c, in float4 r)\n" - "{\n" - " return mul(float4x1(r), float1x2(c));\n" - "}\n"}, - {{EOpOuterProduct, ParamType::Float4, ParamType::Float3}, - "float3x4 outerProduct_emu(in float4 c, in float3 r)\n" - "{\n" - " return mul(float3x1(r), float1x4(c));\n" - "}\n"}, - {{EOpOuterProduct, ParamType::Float3, ParamType::Float4}, - "float4x3 outerProduct_emu(in float3 c, in float4 r)\n" - "{\n" - " return mul(float4x1(r), float1x3(c));\n" - "}\n"}, - // Remember here that the parameter matrix is actually the transpose - // of the matrix that we're trying to invert, and the resulting matrix - // should also be the transpose of the inverse. - // When accessing the parameter matrix with m[a][b] it can be thought of so - // that a is the column and b is the row of the matrix that we're inverting. - // We calculate the inverse as the adjugate matrix divided by the - // determinant of the matrix being inverted. However, as the result needs - // to be transposed, we actually use of the transpose of the adjugate matrix - // which happens to be the cofactor matrix. That's stored in 'cof'. - // We don't need to care about divide-by-zero since results are undefined - // for singular or poorly-conditioned matrices. - {{EOpInverse, ParamType::Mat2}, - "float2x2 inverse_emu(in float2x2 m)\n" - "{\n" - " float2x2 cof = { m[1][1], -m[0][1], -m[1][0], m[0][0] };\n" - " return cof / determinant(transpose(m));\n" - "}\n"}, - // cofAB is the cofactor for column A and row B. - {{EOpInverse, ParamType::Mat3}, - "float3x3 inverse_emu(in float3x3 m)\n" - "{\n" - " float cof00 = m[1][1] * m[2][2] - m[2][1] * m[1][2];\n" - " float cof01 = -(m[1][0] * m[2][2] - m[2][0] * m[1][2]);\n" - " float cof02 = m[1][0] * m[2][1] - m[2][0] * m[1][1];\n" - " float cof10 = -(m[0][1] * m[2][2] - m[2][1] * m[0][2]);\n" - " float cof11 = m[0][0] * m[2][2] - m[2][0] * m[0][2];\n" - " float cof12 = -(m[0][0] * m[2][1] - m[2][0] * m[0][1]);\n" - " float cof20 = m[0][1] * m[1][2] - m[1][1] * m[0][2];\n" - " float cof21 = -(m[0][0] * m[1][2] - m[1][0] * m[0][2]);\n" - " float cof22 = m[0][0] * m[1][1] - m[1][0] * m[0][1];\n" - " float3x3 cof = { cof00, cof10, cof20, cof01, cof11, cof21, cof02, cof12, cof22 };\n" - " return cof / determinant(transpose(m));\n" - "}\n"}, - {{EOpInverse, ParamType::Mat4}, - "float4x4 inverse_emu(in float4x4 m)\n" - "{\n" - " float cof00 = m[1][1] * m[2][2] * m[3][3] + m[2][1] * m[3][2] * m[1][3] + m[3][1] * \n" - " m[1][2] * m[2][3]\n" - " - m[1][1] * m[3][2] * m[2][3] - m[2][1] * m[1][2] * m[3][3] - m[3][1] * m[2][2] * \n" - " m[1][3];\n" - " float cof01 = -(m[1][0] * m[2][2] * m[3][3] + m[2][0] * m[3][2] * m[1][3] + m[3][0] * \n" - " m[1][2] * m[2][3]\n" - " - m[1][0] * m[3][2] * m[2][3] - m[2][0] * m[1][2] * m[3][3] - m[3][0] * m[2][2] * \n" - " m[1][3]);\n" - " float cof02 = m[1][0] * m[2][1] * m[3][3] + m[2][0] * m[3][1] * m[1][3] + m[3][0] * \n" - " m[1][1] * m[2][3]\n" - " - m[1][0] * m[3][1] * m[2][3] - m[2][0] * m[1][1] * m[3][3] - m[3][0] * m[2][1] * \n" - " m[1][3];\n" - " float cof03 = -(m[1][0] * m[2][1] * m[3][2] + m[2][0] * m[3][1] * m[1][2] + m[3][0] * \n" - " m[1][1] * m[2][2]\n" - " - m[1][0] * m[3][1] * m[2][2] - m[2][0] * m[1][1] * m[3][2] - m[3][0] * m[2][1] * \n" - " m[1][2]);\n" - " float cof10 = -(m[0][1] * m[2][2] * m[3][3] + m[2][1] * m[3][2] * m[0][3] + m[3][1] * \n" - " m[0][2] * m[2][3]\n" - " - m[0][1] * m[3][2] * m[2][3] - m[2][1] * m[0][2] * m[3][3] - m[3][1] * m[2][2] * \n" - " m[0][3]);\n" - " float cof11 = m[0][0] * m[2][2] * m[3][3] + m[2][0] * m[3][2] * m[0][3] + m[3][0] * \n" - " m[0][2] * m[2][3]\n" - " - m[0][0] * m[3][2] * m[2][3] - m[2][0] * m[0][2] * m[3][3] - m[3][0] * m[2][2] * \n" - " m[0][3];\n" - " float cof12 = -(m[0][0] * m[2][1] * m[3][3] + m[2][0] * m[3][1] * m[0][3] + m[3][0] * \n" - " m[0][1] * m[2][3]\n" - " - m[0][0] * m[3][1] * m[2][3] - m[2][0] * m[0][1] * m[3][3] - m[3][0] * m[2][1] * \n" - " m[0][3]);\n" - " float cof13 = m[0][0] * m[2][1] * m[3][2] + m[2][0] * m[3][1] * m[0][2] + m[3][0] * \n" - " m[0][1] * m[2][2]\n" - " - m[0][0] * m[3][1] * m[2][2] - m[2][0] * m[0][1] * m[3][2] - m[3][0] * m[2][1] * \n" - " m[0][2];\n" - " float cof20 = m[0][1] * m[1][2] * m[3][3] + m[1][1] * m[3][2] * m[0][3] + m[3][1] * \n" - " m[0][2] * m[1][3]\n" - " - m[0][1] * m[3][2] * m[1][3] - m[1][1] * m[0][2] * m[3][3] - m[3][1] * m[1][2] * \n" - " m[0][3];\n" - " float cof21 = -(m[0][0] * m[1][2] * m[3][3] + m[1][0] * m[3][2] * m[0][3] + m[3][0] * \n" - " m[0][2] * m[1][3]\n" - " - m[0][0] * m[3][2] * m[1][3] - m[1][0] * m[0][2] * m[3][3] - m[3][0] * m[1][2] * \n" - " m[0][3]);\n" - " float cof22 = m[0][0] * m[1][1] * m[3][3] + m[1][0] * m[3][1] * m[0][3] + m[3][0] * \n" - " m[0][1] * m[1][3]\n" - " - m[0][0] * m[3][1] * m[1][3] - m[1][0] * m[0][1] * m[3][3] - m[3][0] * m[1][1] * \n" - " m[0][3];\n" - " float cof23 = -(m[0][0] * m[1][1] * m[3][2] + m[1][0] * m[3][1] * m[0][2] + m[3][0] * \n" - " m[0][1] * m[1][2]\n" - " - m[0][0] * m[3][1] * m[1][2] - m[1][0] * m[0][1] * m[3][2] - m[3][0] * m[1][1] * \n" - " m[0][2]);\n" - " float cof30 = -(m[0][1] * m[1][2] * m[2][3] + m[1][1] * m[2][2] * m[0][3] + m[2][1] * \n" - " m[0][2] * m[1][3]\n" - " - m[0][1] * m[2][2] * m[1][3] - m[1][1] * m[0][2] * m[2][3] - m[2][1] * m[1][2] * \n" - " m[0][3]);\n" - " float cof31 = m[0][0] * m[1][2] * m[2][3] + m[1][0] * m[2][2] * m[0][3] + m[2][0] * \n" - " m[0][2] * m[1][3]\n" - " - m[0][0] * m[2][2] * m[1][3] - m[1][0] * m[0][2] * m[2][3] - m[2][0] * m[1][2] * \n" - " m[0][3];\n" - " float cof32 = -(m[0][0] * m[1][1] * m[2][3] + m[1][0] * m[2][1] * m[0][3] + m[2][0] * \n" - " m[0][1] * m[1][3]\n" - " - m[0][0] * m[2][1] * m[1][3] - m[1][0] * m[0][1] * m[2][3] - m[2][0] * m[1][1] * \n" - " m[0][3]);\n" - " float cof33 = m[0][0] * m[1][1] * m[2][2] + m[1][0] * m[2][1] * m[0][2] + m[2][0] * \n" - " m[0][1] * m[1][2]\n" - " - m[0][0] * m[2][1] * m[1][2] - m[1][0] * m[0][1] * m[2][2] - m[2][0] * m[1][1] * \n" - " m[0][2];\n" - " float4x4 cof = { cof00, cof10, cof20, cof30, cof01, cof11, cof21, cof31,\n" - " cof02, cof12, cof22, cof32, cof03, cof13, cof23, cof33 };\n" - " return cof / determinant(transpose(m));\n" - "}\n"}, - // Emulate ESSL3 variant of mix that takes last argument as boolean vector. - // genType mix(genType x, genType y, genBType a): Selects which vector each returned component - // comes from. For a component of 'a' that is false, the corresponding component of 'x' is - // returned. For a component of 'a' that is true, the corresponding component of 'y' is - // returned. - {{EOpMix, ParamType::Float1, ParamType::Float1, ParamType::Bool1}, - "float mix_emu(float x, float y, bool a)\n" - "{\n" - " return a ? y : x;\n" - "}\n"}, - {{EOpMix, ParamType::Float2, ParamType::Float2, ParamType::Bool2}, - "float2 mix_emu(float2 x, float2 y, bool2 a)\n" - "{\n" - " return a ? y : x;\n" - "}\n"}, - {{EOpMix, ParamType::Float3, ParamType::Float3, ParamType::Bool3}, - "float3 mix_emu(float3 x, float3 y, bool3 a)\n" - "{\n" - " return a ? y : x;\n" - "}\n"}, - {{EOpMix, ParamType::Float4, ParamType::Float4, ParamType::Bool4}, - "float4 mix_emu(float4 x, float4 y, bool4 a)\n" - "{\n" - " return a ? y : x;\n" - "}\n"}, - {{EOpBitfieldExtract, ParamType::Uint1, ParamType::Int1, ParamType::Int1}, - "uint bitfieldExtract_emu(uint value, int offset, int bits)\n" - "{\n" - " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n" - " {\n" - " return 0u;\n" - " }\n" - " uint maskMsb = (1u << (bits - 1));\n" - " uint mask = ((maskMsb - 1u) | maskMsb) << offset;\n" - " return (value & mask) >> offset;\n" - "}\n"}, - {{EOpBitfieldExtract, ParamType::Uint2, ParamType::Int1, ParamType::Int1}, - "uint2 bitfieldExtract_emu(uint2 value, int offset, int bits)\n" - "{\n" - " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n" - " {\n" - " return uint2(0u, 0u);\n" - " }\n" - " uint maskMsb = (1u << (bits - 1));\n" - " uint mask = ((maskMsb - 1u) | maskMsb) << offset;\n" - " return (value & mask) >> offset;\n" - "}\n"}, - {{EOpBitfieldExtract, ParamType::Uint3, ParamType::Int1, ParamType::Int1}, - "uint3 bitfieldExtract_emu(uint3 value, int offset, int bits)\n" - "{\n" - " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n" - " {\n" - " return uint3(0u, 0u, 0u);\n" - " }\n" - " uint maskMsb = (1u << (bits - 1));\n" - " uint mask = ((maskMsb - 1u) | maskMsb) << offset;\n" - " return (value & mask) >> offset;\n" - "}\n"}, - {{EOpBitfieldExtract, ParamType::Uint4, ParamType::Int1, ParamType::Int1}, - "uint4 bitfieldExtract_emu(uint4 value, int offset, int bits)\n" - "{\n" - " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n" - " {\n" - " return uint4(0u, 0u, 0u, 0u);\n" - " }\n" - " uint maskMsb = (1u << (bits - 1));\n" - " uint mask = ((maskMsb - 1u) | maskMsb) << offset;\n" - " return (value & mask) >> offset;\n" - "}\n"}, - {{EOpBitfieldExtract, ParamType::Int1, ParamType::Int1, ParamType::Int1}, - "int bitfieldExtract_emu(int value, int offset, int bits)\n" - "{\n" - " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n" - " {\n" - " return 0;\n" - " }\n" - " uint maskMsb = (1u << (bits - 1));\n" - " uint mask = ((maskMsb - 1u) | maskMsb) << offset;\n" - " uint resultUnsigned = (asuint(value) & mask) >> offset;\n" - " if (bits != 32 && (resultUnsigned & maskMsb) != 0)\n" - " {\n" - " uint higherBitsMask = ((1u << (32 - bits)) - 1u) << bits;\n" - " resultUnsigned |= higherBitsMask;\n" - " }\n" - " return asint(resultUnsigned);\n" - "}\n"}, - {{EOpBitfieldExtract, ParamType::Int2, ParamType::Int1, ParamType::Int1}, - "int2 bitfieldExtract_emu(int2 value, int offset, int bits)\n" - "{\n" - " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n" - " {\n" - " return int2(0, 0);\n" - " }\n" - " uint maskMsb = (1u << (bits - 1));\n" - " uint mask = ((maskMsb - 1u) | maskMsb) << offset;\n" - " uint2 resultUnsigned = (asuint(value) & mask) >> offset;\n" - " if (bits != 32)\n" - " {\n" - " uint higherBitsMask = ((1u << (32 - bits)) - 1u) << bits;\n" - " resultUnsigned |= ((resultUnsigned & maskMsb) >> (bits - 1)) * higherBitsMask;\n" - " }\n" - " return asint(resultUnsigned);\n" - "}\n"}, - {{EOpBitfieldExtract, ParamType::Int3, ParamType::Int1, ParamType::Int1}, - "int3 bitfieldExtract_emu(int3 value, int offset, int bits)\n" - "{\n" - " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n" - " {\n" - " return int3(0, 0, 0);\n" - " }\n" - " uint maskMsb = (1u << (bits - 1));\n" - " uint mask = ((maskMsb - 1u) | maskMsb) << offset;\n" - " uint3 resultUnsigned = (asuint(value) & mask) >> offset;\n" - " if (bits != 32)\n" - " {\n" - " uint higherBitsMask = ((1u << (32 - bits)) - 1u) << bits;\n" - " resultUnsigned |= ((resultUnsigned & maskMsb) >> (bits - 1)) * higherBitsMask;\n" - " }\n" - " return asint(resultUnsigned);\n" - "}\n"}, - {{EOpBitfieldExtract, ParamType::Int4, ParamType::Int1, ParamType::Int1}, - "int4 bitfieldExtract_emu(int4 value, int offset, int bits)\n" - "{\n" - " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n" - " {\n" - " return int4(0, 0, 0, 0);\n" - " }\n" - " uint maskMsb = (1u << (bits - 1));\n" - " uint mask = ((maskMsb - 1u) | maskMsb) << offset;\n" - " uint4 resultUnsigned = (asuint(value) & mask) >> offset;\n" - " if (bits != 32)\n" - " {\n" - " uint higherBitsMask = ((1u << (32 - bits)) - 1u) << bits;\n" - " resultUnsigned |= ((resultUnsigned & maskMsb) >> (bits - 1)) * higherBitsMask;\n" - " }\n" - " return asint(resultUnsigned);\n" - "}\n"}, - {{EOpBitfieldInsert, ParamType::Uint1, ParamType::Uint1, ParamType::Int1, ParamType::Int1}, - "uint bitfieldInsert_emu(uint base, uint insert, int offset, int bits)\n" - "{\n" - " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n" - " {\n" - " return base;\n" - " }\n" - " uint maskMsb = (1u << (bits - 1));\n" - " uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;\n" - " uint baseMask = ~insertMask;\n" - " return (base & baseMask) | ((insert << offset) & insertMask);\n" - "}\n"}, - {{EOpBitfieldInsert, ParamType::Uint2, ParamType::Uint2, ParamType::Int1, ParamType::Int1}, - "uint2 bitfieldInsert_emu(uint2 base, uint2 insert, int offset, int bits)\n" - "{\n" - " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n" - " {\n" - " return base;\n" - " }\n" - " uint maskMsb = (1u << (bits - 1));\n" - " uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;\n" - " uint baseMask = ~insertMask;\n" - " return (base & baseMask) | ((insert << offset) & insertMask);\n" - "}\n"}, - {{EOpBitfieldInsert, ParamType::Uint3, ParamType::Uint3, ParamType::Int1, ParamType::Int1}, - "uint3 bitfieldInsert_emu(uint3 base, uint3 insert, int offset, int bits)\n" - "{\n" - " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n" - " {\n" - " return base;\n" - " }\n" - " uint maskMsb = (1u << (bits - 1));\n" - " uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;\n" - " uint baseMask = ~insertMask;\n" - " return (base & baseMask) | ((insert << offset) & insertMask);\n" - "}\n"}, - {{EOpBitfieldInsert, ParamType::Uint4, ParamType::Uint4, ParamType::Int1, ParamType::Int1}, - "uint4 bitfieldInsert_emu(uint4 base, uint4 insert, int offset, int bits)\n" - "{\n" - " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n" - " {\n" - " return base;\n" - " }\n" - " uint maskMsb = (1u << (bits - 1));\n" - " uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;\n" - " uint baseMask = ~insertMask;\n" - " return (base & baseMask) | ((insert << offset) & insertMask);\n" - "}\n"}, - {{EOpBitfieldInsert, ParamType::Int1, ParamType::Int1, ParamType::Int1, ParamType::Int1}, - "int bitfieldInsert_emu(int base, int insert, int offset, int bits)\n" - "{\n" - " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n" - " {\n" - " return base;\n" - " }\n" - " uint maskMsb = (1u << (bits - 1));\n" - " uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;\n" - " uint baseMask = ~insertMask;\n" - " uint resultUnsigned = (asuint(base) & baseMask) | ((asuint(insert) << offset) & \n" - " insertMask);\n" - " return asint(resultUnsigned);\n" - "}\n"}, - {{EOpBitfieldInsert, ParamType::Int2, ParamType::Int2, ParamType::Int1, ParamType::Int1}, - "int2 bitfieldInsert_emu(int2 base, int2 insert, int offset, int bits)\n" - "{\n" - " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n" - " {\n" - " return base;\n" - " }\n" - " uint maskMsb = (1u << (bits - 1));\n" - " uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;\n" - " uint baseMask = ~insertMask;\n" - " uint2 resultUnsigned = (asuint(base) & baseMask) | ((asuint(insert) << offset) & \n" - " insertMask);\n" - " return asint(resultUnsigned);\n" - "}\n"}, - {{EOpBitfieldInsert, ParamType::Int3, ParamType::Int3, ParamType::Int1, ParamType::Int1}, - "int3 bitfieldInsert_emu(int3 base, int3 insert, int offset, int bits)\n" - "{\n" - " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n" - " {\n" - " return base;\n" - " }\n" - " uint maskMsb = (1u << (bits - 1));\n" - " uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;\n" - " uint baseMask = ~insertMask;\n" - " uint3 resultUnsigned = (asuint(base) & baseMask) | ((asuint(insert) << offset) & \n" - " insertMask);\n" - " return asint(resultUnsigned);\n" - "}\n"}, - {{EOpBitfieldInsert, ParamType::Int4, ParamType::Int4, ParamType::Int1, ParamType::Int1}, - "int4 bitfieldInsert_emu(int4 base, int4 insert, int offset, int bits)\n" - "{\n" - " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n" - " {\n" - " return base;\n" - " }\n" - " uint maskMsb = (1u << (bits - 1));\n" - " uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;\n" - " uint baseMask = ~insertMask;\n" - " uint4 resultUnsigned = (asuint(base) & baseMask) | ((asuint(insert) << offset) & \n" - " insertMask);\n" - " return asint(resultUnsigned);\n" - "}\n"}, - {{EOpUaddCarry, ParamType::Uint1, ParamType::Uint1, ParamType::Uint1}, - "uint uaddCarry_emu(uint x, uint y, out uint carry)\n" - "{\n" - " carry = uint(x > (0xffffffffu - y));\n" - " return x + y;\n" - "}\n"}, - {{EOpUaddCarry, ParamType::Uint2, ParamType::Uint2, ParamType::Uint2}, - "uint2 uaddCarry_emu(uint2 x, uint2 y, out uint2 carry)\n" - "{\n" - " carry = uint2(x > (0xffffffffu - y));\n" - " return x + y;\n" - "}\n"}, - {{EOpUaddCarry, ParamType::Uint3, ParamType::Uint3, ParamType::Uint3}, - "uint3 uaddCarry_emu(uint3 x, uint3 y, out uint3 carry)\n" - "{\n" - " carry = uint3(x > (0xffffffffu - y));\n" - " return x + y;\n" - "}\n"}, - {{EOpUaddCarry, ParamType::Uint4, ParamType::Uint4, ParamType::Uint4}, - "uint4 uaddCarry_emu(uint4 x, uint4 y, out uint4 carry)\n" - "{\n" - " carry = uint4(x > (0xffffffffu - y));\n" - " return x + y;\n" - "}\n"}, - {{EOpUsubBorrow, ParamType::Uint1, ParamType::Uint1, ParamType::Uint1}, - "uint usubBorrow_emu(uint x, uint y, out uint borrow)\n" - "{\n" - " borrow = uint(x < y);\n" - " return x - y;\n" - "}\n"}, - {{EOpUsubBorrow, ParamType::Uint2, ParamType::Uint2, ParamType::Uint2}, - "uint2 usubBorrow_emu(uint2 x, uint2 y, out uint2 borrow)\n" - "{\n" - " borrow = uint2(x < y);\n" - " return x - y;\n" - "}\n"}, - {{EOpUsubBorrow, ParamType::Uint3, ParamType::Uint3, ParamType::Uint3}, - "uint3 usubBorrow_emu(uint3 x, uint3 y, out uint3 borrow)\n" - "{\n" - " borrow = uint3(x < y);\n" - " return x - y;\n" - "}\n"}, - {{EOpUsubBorrow, ParamType::Uint4, ParamType::Uint4, ParamType::Uint4}, - "uint4 usubBorrow_emu(uint4 x, uint4 y, out uint4 borrow)\n" - "{\n" - " borrow = uint4(x < y);\n" - " return x - y;\n" - "}\n"}, -}; -} // anonymous namespace - -const char *FindHLSLFunction(const FunctionId &functionID) -{ - for (size_t index = 0; index < ArraySize(g_hlslFunctions); ++index) - { - const auto &function = g_hlslFunctions[index]; - if (function.id == functionID) - { - return function.body; - } - } - - return nullptr; -} -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/glslang.h b/src/3rdparty/angle/src/compiler/translator/glslang.h deleted file mode 100644 index e54c31ba3e..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/glslang.h +++ /dev/null @@ -1,24 +0,0 @@ -// -// Copyright (c) 2010 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_TRANSLATOR_GLSLANG_H_ -#define COMPILER_TRANSLATOR_GLSLANG_H_ - -namespace sh -{ -class TParseContext; -} - -extern int glslang_initialize(sh::TParseContext *context); -extern int glslang_finalize(sh::TParseContext *context); - -extern int glslang_scan(size_t count, - const char *const string[], - const int length[], - sh::TParseContext *context); -extern int glslang_parse(sh::TParseContext *context); - -#endif // COMPILER_TRANSLATOR_GLSLANG_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/glslang.l b/src/3rdparty/angle/src/compiler/translator/glslang.l deleted file mode 100644 index 858ffd96bb..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/glslang.l +++ /dev/null @@ -1,697 +0,0 @@ -/* -// -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -This file contains the Lex specification for GLSL ES. -Based on ANSI C grammar, Lex specification: -http://www.lysator.liu.se/c/ANSI-C-grammar-l.html - -IF YOU MODIFY THIS FILE YOU ALSO NEED TO RUN generate_parser.sh, -WHICH GENERATES THE GLSL ES LEXER (glslang_lex.cpp). -*/ - -%top{ -// -// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// This file is auto-generated by generate_parser.sh. DO NOT EDIT! - -/* clang-format off */ - -// Ignore errors in auto-generated code. -#if defined(__GNUC__) -#pragma GCC diagnostic ignored "-Wunused-function" -#pragma GCC diagnostic ignored "-Wunused-variable" -#pragma GCC diagnostic ignored "-Wswitch-enum" -#elif defined(_MSC_VER) -#pragma warning(disable: 4005) -#pragma warning(disable: 4065) -#pragma warning(disable: 4189) -#pragma warning(disable: 4244) -#pragma warning(disable: 4505) -#pragma warning(disable: 4701) -#pragma warning(disable: 4702) -#endif -} - -%{ -#include "compiler/translator/glslang.h" -#include "compiler/translator/ParseContext.h" -#include "compiler/preprocessor/Token.h" -#include "compiler/translator/util.h" -#include "compiler/translator/length_limits.h" - -using namespace sh; - -#include "glslang_tab.h" - -/* windows only pragma */ -#ifdef _MSC_VER -#pragma warning(disable : 4102) -#endif - -// Workaround for flex using the register keyword, deprecated in C++11. -#ifdef __cplusplus -#if __cplusplus > 199711L -#define register -#endif -#endif - -#define YY_USER_ACTION \ - yylloc->first_file = yylloc->last_file = yycolumn; \ - yylloc->first_line = yylloc->last_line = yylineno; - -#define YY_INPUT(buf, result, max_size) \ - result = string_input(buf, max_size, yyscanner); - -static yy_size_t string_input(char* buf, yy_size_t max_size, yyscan_t yyscanner); -static int check_type(yyscan_t yyscanner); -static int reserved_word(yyscan_t yyscanner); -static int ES2_reserved_ES3_keyword(TParseContext *context, int token); -static int ES2_keyword_ES3_reserved(TParseContext *context, int token); -static int ES2_ident_ES3_keyword(TParseContext *context, int token); -static int ES2_ident_ES3_keyword_multiview_keyword(TParseContext *context, int token); -static int ES2_ident_ES3_reserved_ES3_1_keyword(TParseContext *context, int token); -static int ES2_and_ES3_reserved_ES3_1_keyword(TParseContext *context, int token); -static int ES2_and_ES3_ident_ES3_1_keyword(TParseContext *context, int token); -static int ES3_extension_keyword_else_ident(TParseContext *context, TExtension extension, int token); -static int uint_constant(TParseContext *context); -static int int_constant(TParseContext *context); -static int float_constant(yyscan_t yyscanner); -static int floatsuffix_check(TParseContext* context); -static int yuvcscstandardext_constant(TParseContext *context); -%} - -%option noyywrap nounput never-interactive -%option yylineno reentrant bison-bridge bison-locations -%option extra-type="TParseContext*" -%x FIELDS - -D [0-9] -L [a-zA-Z_] -H [a-fA-F0-9] -E [Ee][+-]?{D}+ -O [0-7] - -%% - -%{ - TParseContext* context = yyextra; -%} - -"invariant" { return INVARIANT; } -"highp" { return HIGH_PRECISION; } -"mediump" { return MEDIUM_PRECISION; } -"lowp" { return LOW_PRECISION; } -"precision" { return PRECISION; } - -"attribute" { return ES2_keyword_ES3_reserved(context, ATTRIBUTE); } -"const" { return CONST_QUAL; } -"uniform" { return UNIFORM; } -"buffer" { return ES2_and_ES3_ident_ES3_1_keyword(context, BUFFER); } -"varying" { return ES2_keyword_ES3_reserved(context, VARYING); } - -"break" { return BREAK; } -"continue" { return CONTINUE; } -"do" { return DO; } -"for" { return FOR; } -"while" { return WHILE; } - -"if" { return IF; } -"else" { return ELSE; } -"switch" { return ES2_reserved_ES3_keyword(context, SWITCH); } -"case" { return ES2_ident_ES3_keyword(context, CASE); } -"default" { return ES2_reserved_ES3_keyword(context, DEFAULT); } - -"centroid" { return ES2_ident_ES3_keyword(context, CENTROID); } -"flat" { return ES2_reserved_ES3_keyword(context, FLAT); } -"smooth" { return ES2_ident_ES3_keyword(context, SMOOTH); } - -"in" { return IN_QUAL; } -"out" { return OUT_QUAL; } -"inout" { return INOUT_QUAL; } -"shared" { return ES2_and_ES3_ident_ES3_1_keyword(context, SHARED); } - -"float" { return FLOAT_TYPE; } -"int" { return INT_TYPE; } -"uint" { return ES2_ident_ES3_keyword(context, UINT_TYPE); } -"void" { return VOID_TYPE; } -"bool" { return BOOL_TYPE; } -"true" { yylval->lex.b = true; return BOOLCONSTANT; } -"false" { yylval->lex.b = false; return BOOLCONSTANT; } - -"discard" { return DISCARD; } -"return" { return RETURN; } - -"mat2" { return MATRIX2; } -"mat3" { return MATRIX3; } -"mat4" { return MATRIX4; } - -"mat2x2" { return ES2_ident_ES3_keyword(context, MATRIX2); } -"mat3x3" { return ES2_ident_ES3_keyword(context, MATRIX3); } -"mat4x4" { return ES2_ident_ES3_keyword(context, MATRIX4); } - -"mat2x3" { return ES2_ident_ES3_keyword(context, MATRIX2x3); } -"mat3x2" { return ES2_ident_ES3_keyword(context, MATRIX3x2); } -"mat2x4" { return ES2_ident_ES3_keyword(context, MATRIX2x4); } -"mat4x2" { return ES2_ident_ES3_keyword(context, MATRIX4x2); } -"mat3x4" { return ES2_ident_ES3_keyword(context, MATRIX3x4); } -"mat4x3" { return ES2_ident_ES3_keyword(context, MATRIX4x3); } - -"vec2" { return VEC2; } -"vec3" { return VEC3; } -"vec4" { return VEC4; } -"ivec2" { return IVEC2; } -"ivec3" { return IVEC3; } -"ivec4" { return IVEC4; } -"bvec2" { return BVEC2; } -"bvec3" { return BVEC3; } -"bvec4" { return BVEC4; } -"uvec2" { return ES2_ident_ES3_keyword(context, UVEC2); } -"uvec3" { return ES2_ident_ES3_keyword(context, UVEC3); } -"uvec4" { return ES2_ident_ES3_keyword(context, UVEC4); } - -"sampler2D" { return SAMPLER2D; } -"samplerCube" { return SAMPLERCUBE; } -"samplerExternalOES" { return SAMPLER_EXTERNAL_OES; } -"sampler3D" { return ES2_reserved_ES3_keyword(context, SAMPLER3D); } -"sampler3DRect" { return ES2_reserved_ES3_keyword(context, SAMPLER3DRECT); } -"sampler2DRect" { return SAMPLER2DRECT; } -"sampler2DArray" { return ES2_ident_ES3_keyword(context, SAMPLER2DARRAY); } -"sampler2DMS" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, SAMPLER2DMS); } -"isampler2D" { return ES2_ident_ES3_keyword(context, ISAMPLER2D); } -"isampler3D" { return ES2_ident_ES3_keyword(context, ISAMPLER3D); } -"isamplerCube" { return ES2_ident_ES3_keyword(context, ISAMPLERCUBE); } -"isampler2DArray" { return ES2_ident_ES3_keyword(context, ISAMPLER2DARRAY); } -"isampler2DMS" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, ISAMPLER2DMS); } -"usampler2D" { return ES2_ident_ES3_keyword(context, USAMPLER2D); } -"usampler3D" { return ES2_ident_ES3_keyword(context, USAMPLER3D); } -"usamplerCube" { return ES2_ident_ES3_keyword(context, USAMPLERCUBE); } -"usampler2DArray" { return ES2_ident_ES3_keyword(context, USAMPLER2DARRAY); } -"usampler2DMS" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, USAMPLER2DMS); } -"sampler2DShadow" { return ES2_reserved_ES3_keyword(context, SAMPLER2DSHADOW); } -"samplerCubeShadow" { return ES2_ident_ES3_keyword(context, SAMPLERCUBESHADOW); } -"sampler2DArrayShadow" { return ES2_ident_ES3_keyword(context, SAMPLER2DARRAYSHADOW); } -"__samplerExternal2DY2YEXT" { return ES3_extension_keyword_else_ident(context, TExtension::EXT_YUV_target, SAMPLEREXTERNAL2DY2YEXT); } - -"struct" { return STRUCT; } - -"layout" { return ES2_ident_ES3_keyword_multiview_keyword(context, LAYOUT); } - -"yuvCscStandardEXT" { return ES3_extension_keyword_else_ident(context, TExtension::EXT_YUV_target, YUVCSCSTANDARDEXT); } -"itu_601" { return yuvcscstandardext_constant(context); } -"itu_601_full_range" { return yuvcscstandardext_constant(context); } -"itu_709" { return yuvcscstandardext_constant(context); } - -"image2D" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, IMAGE2D); } -"iimage2D" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, IIMAGE2D); } -"uimage2D" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, UIMAGE2D); } -"image2DArray" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, IMAGE2DARRAY); } -"iimage2DArray" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, IIMAGE2DARRAY); } -"uimage2DArray" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, UIMAGE2DARRAY); } -"image3D" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, IMAGE3D); } -"uimage3D" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, UIMAGE3D); } -"iimage3D" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, IIMAGE3D); } -"iimageCube" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, IIMAGECUBE); } -"uimageCube" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, UIMAGECUBE); } -"imageCube" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, IMAGECUBE); } -"readonly" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, READONLY); } -"writeonly" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, WRITEONLY); } -"coherent" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, COHERENT); } -"restrict" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, RESTRICT); } -"volatile" { return ES2_and_ES3_reserved_ES3_1_keyword(context, VOLATILE); } -"atomic_uint" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, ATOMICUINT); } - - /* Reserved keywords for GLSL ES 3.00 that are not reserved for GLSL ES 1.00 */ -"resource" | -"noperspective" | -"patch" | -"sample" | -"subroutine" | -"common" | -"partition" | -"active" | - -"filter" | -"image1D" | -"iimage1D" | -"uimage1D" | -"image1DArray" | -"iimage1DArray" | -"uimage1DArray" | -"image1DShadow" | -"image2DShadow" | -"image1DArrayShadow" | -"image2DArrayShadow" | -"imageBuffer" | -"iimageBuffer" | -"uimageBuffer" | - -"sampler1DArray" | -"sampler1DArrayShadow" | -"isampler1D" | -"isampler1DArray" | -"usampler1D" | -"usampler1DArray" | -"isampler2DRect" | -"usampler2DRect" | -"samplerBuffer" | -"isamplerBuffer" | -"usamplerBuffer" | -"sampler2DMSArray" | -"isampler2DMSArray" | -"usampler2DMSArray" { - if (context->getShaderVersion() < 300) { - yylval->lex.string = NewPoolTString(yytext); - return check_type(yyscanner); - } - return reserved_word(yyscanner); -} - - /* Reserved keywords in GLSL ES 1.00 that are not reserved in GLSL ES 3.00 */ -"packed" { - if (context->getShaderVersion() >= 300) - { - yylval->lex.string = NewPoolTString(yytext); - return check_type(yyscanner); - } - - return reserved_word(yyscanner); -} - - /* Reserved keywords */ -"asm" | - -"class" | -"union" | -"enum" | -"typedef" | -"template" | -"this" | - -"goto" | - -"inline" | -"noinline" | -"public" | -"static" | -"extern" | -"external" | -"interface" | - -"long" | -"short" | -"double" | -"half" | -"fixed" | -"unsigned" | -"superp" | - -"input" | -"output" | - -"hvec2" | -"hvec3" | -"hvec4" | -"dvec2" | -"dvec3" | -"dvec4" | -"fvec2" | -"fvec3" | -"fvec4" | - -"sampler1D" | -"sampler1DShadow" | -"sampler2DRectShadow" | - -"sizeof" | -"cast" | - -"namespace" | -"using" { return reserved_word(yyscanner); } - -{L}({L}|{D})* { - yylval->lex.string = NewPoolTString(yytext); - return check_type(yyscanner); -} - -0[xX]{H}+ { return int_constant(context); } -0{O}+ { return int_constant(context); } -{D}+ { return int_constant(context); } - -0[xX]{H}+[uU] { return uint_constant(context); } -0{O}+[uU] { return uint_constant(context); } -{D}+[uU] { return uint_constant(context); } - -{D}+{E} { return float_constant(yyscanner); } -{D}+"."{D}*({E})? { return float_constant(yyscanner); } -"."{D}+({E})? { return float_constant(yyscanner); } - -{D}+{E}[fF] { return floatsuffix_check(context); } -{D}+"."{D}*({E})?[fF] { return floatsuffix_check(context); } -"."{D}+({E})?[fF] { return floatsuffix_check(context); } - -"+=" { return ADD_ASSIGN; } -"-=" { return SUB_ASSIGN; } -"*=" { return MUL_ASSIGN; } -"/=" { return DIV_ASSIGN; } -"%=" { return MOD_ASSIGN; } -"<<=" { return LEFT_ASSIGN; } -">>=" { return RIGHT_ASSIGN; } -"&=" { return AND_ASSIGN; } -"^=" { return XOR_ASSIGN; } -"|=" { return OR_ASSIGN; } - -"++" { return INC_OP; } -"--" { return DEC_OP; } -"&&" { return AND_OP; } -"||" { return OR_OP; } -"^^" { return XOR_OP; } -"<=" { return LE_OP; } -">=" { return GE_OP; } -"==" { return EQ_OP; } -"!=" { return NE_OP; } -"<<" { return LEFT_OP; } -">>" { return RIGHT_OP; } -";" { return SEMICOLON; } -("{"|"<%") { return LEFT_BRACE; } -("}"|"%>") { return RIGHT_BRACE; } -"," { return COMMA; } -":" { return COLON; } -"=" { return EQUAL; } -"(" { return LEFT_PAREN; } -")" { return RIGHT_PAREN; } -("["|"<:") { return LEFT_BRACKET; } -("]"|":>") { return RIGHT_BRACKET; } -"." { BEGIN(FIELDS); return DOT; } -"!" { return BANG; } -"-" { return DASH; } -"~" { return TILDE; } -"+" { return PLUS; } -"*" { return STAR; } -"/" { return SLASH; } -"%" { return PERCENT; } -"<" { return LEFT_ANGLE; } -">" { return RIGHT_ANGLE; } -"|" { return VERTICAL_BAR; } -"^" { return CARET; } -"&" { return AMPERSAND; } -"?" { return QUESTION; } - -{L}({L}|{D})* { - BEGIN(INITIAL); - yylval->lex.string = NewPoolTString(yytext); - return FIELD_SELECTION; -} -[ \t\v\f\r] {} -. { - yyextra->error(*yylloc, "Illegal character at fieldname start", yytext); - return 0; -} - -[ \t\v\n\f\r] { } -<*><> { yyterminate(); } -<*>. { assert(false); return 0; } - -%% - -yy_size_t string_input(char* buf, yy_size_t max_size, yyscan_t yyscanner) { - pp::Token token; - yyget_extra(yyscanner)->getPreprocessor().lex(&token); - yy_size_t len = token.type == pp::Token::LAST ? 0 : token.text.size(); - if (len < max_size) - memcpy(buf, token.text.c_str(), len); - yyset_column(token.location.file, yyscanner); - yyset_lineno(token.location.line, yyscanner); - - if (len >= max_size) - YY_FATAL_ERROR("Input buffer overflow"); - else if (len > 0) - buf[len++] = ' '; - return len; -} - -int check_type(yyscan_t yyscanner) { - struct yyguts_t* yyg = (struct yyguts_t*) yyscanner; - - int token = IDENTIFIER; - TSymbol* symbol = yyextra->symbolTable.find(yytext, yyextra->getShaderVersion()); - if (symbol && symbol->isVariable()) { - TVariable* variable = static_cast(symbol); - if (variable->isUserType()) { - token = TYPE_NAME; - } - } - yylval->lex.symbol = symbol; - return token; -} - -int reserved_word(yyscan_t yyscanner) { - struct yyguts_t* yyg = (struct yyguts_t*) yyscanner; - - yyextra->error(*yylloc, "Illegal use of reserved word", yytext); - return 0; -} - -int ES2_reserved_ES3_keyword(TParseContext *context, int token) -{ - yyscan_t yyscanner = (yyscan_t) context->getScanner(); - - if (context->getShaderVersion() < 300) - { - return reserved_word(yyscanner); - } - - return token; -} - -int ES2_keyword_ES3_reserved(TParseContext *context, int token) -{ - yyscan_t yyscanner = (yyscan_t) context->getScanner(); - - if (context->getShaderVersion() >= 300) - { - return reserved_word(yyscanner); - } - - return token; -} - -int ES2_ident_ES3_reserved_ES3_1_keyword(TParseContext *context, int token) -{ - struct yyguts_t* yyg = (struct yyguts_t*) context->getScanner(); - yyscan_t yyscanner = (yyscan_t) context->getScanner(); - - if (context->getShaderVersion() < 300) - { - yylval->lex.string = NewPoolTString(yytext); - return check_type(yyscanner); - } - else if (context->getShaderVersion() == 300) - { - return reserved_word(yyscanner); - } - - return token; -} - -int ES2_ident_ES3_keyword(TParseContext *context, int token) -{ - struct yyguts_t* yyg = (struct yyguts_t*) context->getScanner(); - yyscan_t yyscanner = (yyscan_t) context->getScanner(); - - // not a reserved word in GLSL ES 1.00, so could be used as an identifier/type name - if (context->getShaderVersion() < 300) - { - yylval->lex.string = NewPoolTString(yytext); - return check_type(yyscanner); - } - - return token; -} - -int ES2_ident_ES3_keyword_multiview_keyword(TParseContext *context, int token) -{ - struct yyguts_t* yyg = (struct yyguts_t*) context->getScanner(); - yyscan_t yyscanner = (yyscan_t) context->getScanner(); - - // not a reserved word in GLSL ES 1.00, so could be used as an identifier/type name - // except when multiview extension is enabled - if (context->getShaderVersion() < 300 && !context->isExtensionEnabled(TExtension::OVR_multiview)) - { - yylval->lex.string = NewPoolTString(yytext); - return check_type(yyscanner); - } - - return token; -} - -int ES2_and_ES3_reserved_ES3_1_keyword(TParseContext *context, int token) -{ - yyscan_t yyscanner = (yyscan_t) context->getScanner(); - - if (context->getShaderVersion() < 310) - { - return reserved_word(yyscanner); - } - - return token; -} - -int ES2_and_ES3_ident_ES3_1_keyword(TParseContext *context, int token) -{ - struct yyguts_t* yyg = (struct yyguts_t*) context->getScanner(); - yyscan_t yyscanner = (yyscan_t) context->getScanner(); - - // not a reserved word in GLSL ES 1.00 and GLSL ES 3.00, so could be used as an identifier/type name - if (context->getShaderVersion() < 310) - { - yylval->lex.string = NewPoolTString(yytext); - return check_type(yyscanner); - } - - return token; -} - -int ES3_extension_keyword_else_ident(TParseContext *context, TExtension extension, int token) -{ - struct yyguts_t* yyg = (struct yyguts_t*) context->getScanner(); - yyscan_t yyscanner = (yyscan_t) context->getScanner(); - - // a reserved word in GLSL ES 3.00 with enabled extension, otherwise could be used as an identifier/type name - if (context->getShaderVersion() >= 300 && context->isExtensionEnabled(extension)) - { - return token; - } - - yylval->lex.string = NewPoolTString(yytext); - return check_type(yyscanner); -} - -int uint_constant(TParseContext *context) -{ - struct yyguts_t* yyg = (struct yyguts_t*) context->getScanner(); - - if (context->getShaderVersion() < 300) - { - context->error(*yylloc, "Unsigned integers are unsupported prior to GLSL ES 3.00", yytext); - return 0; - } - - if (!atoi_clamp(yytext, &(yylval->lex.u))) - yyextra->error(*yylloc, "Integer overflow", yytext); - - return UINTCONSTANT; -} - -int floatsuffix_check(TParseContext* context) -{ - struct yyguts_t* yyg = (struct yyguts_t*) context->getScanner(); - - if (context->getShaderVersion() < 300) - { - context->error(*yylloc, "Floating-point suffix unsupported prior to GLSL ES 3.00", yytext); - return 0; - } - - std::string text = yytext; - text.resize(text.size() - 1); - if (!strtof_clamp(text, &(yylval->lex.f))) - yyextra->warning(*yylloc, "Float overflow", yytext); - - return(FLOATCONSTANT); -} - -void yyerror(YYLTYPE* lloc, TParseContext* context, void *scanner, const char* reason) { - context->error(*lloc, reason, yyget_text(scanner)); -} - -int int_constant(TParseContext *context) { - struct yyguts_t* yyg = (struct yyguts_t*) context->getScanner(); - - unsigned int u; - if (!atoi_clamp(yytext, &u)) - { - if (context->getShaderVersion() >= 300) - yyextra->error(*yylloc, "Integer overflow", yytext); - else - yyextra->warning(*yylloc, "Integer overflow", yytext); - } - yylval->lex.i = static_cast(u); - return INTCONSTANT; -} - -int float_constant(yyscan_t yyscanner) { - struct yyguts_t* yyg = (struct yyguts_t*) yyscanner; - - if (!strtof_clamp(yytext, &(yylval->lex.f))) - yyextra->warning(*yylloc, "Float overflow", yytext); - return FLOATCONSTANT; -} - -int yuvcscstandardext_constant(TParseContext *context) -{ - struct yyguts_t* yyg = (struct yyguts_t*) context->getScanner(); - yyscan_t yyscanner = (yyscan_t) context->getScanner(); - - // a reserved word in GLSL ES 3.00 with enabled extension, otherwise could be used as an identifier/type name - if (context->getShaderVersion() >= 300 && context->isExtensionEnabled(TExtension::EXT_YUV_target)) - { - yylval->lex.string = NewPoolTString(yytext); - return YUVCSCSTANDARDEXTCONSTANT; - } - - yylval->lex.string = NewPoolTString(yytext); - return check_type(yyscanner); -} - -int glslang_initialize(TParseContext* context) { - yyscan_t scanner = NULL; - if (yylex_init_extra(context, &scanner)) - return 1; - - context->setScanner(scanner); - return 0; -} - -int glslang_finalize(TParseContext* context) { - yyscan_t scanner = context->getScanner(); - if (scanner == NULL) return 0; - - context->setScanner(NULL); - yylex_destroy(scanner); - - return 0; -} - -int glslang_scan(size_t count, const char* const string[], const int length[], - TParseContext* context) { - yyrestart(NULL, context->getScanner()); - yyset_column(0, context->getScanner()); - yyset_lineno(1, context->getScanner()); - - // Initialize preprocessor. - pp::Preprocessor *preprocessor = &context->getPreprocessor(); - - if (!preprocessor->init(count, string, length)) - return 1; - - // Define extension macros. - const TExtensionBehavior& extBehavior = context->extensionBehavior(); - for (TExtensionBehavior::const_iterator iter = extBehavior.begin(); - iter != extBehavior.end(); ++iter) { - preprocessor->predefineMacro(GetExtensionNameString(iter->first), 1); - } - if (context->getFragmentPrecisionHigh()) - preprocessor->predefineMacro("GL_FRAGMENT_PRECISION_HIGH", 1); - - preprocessor->setMaxTokenSize(sh::GetGlobalMaxTokenSize(context->getShaderSpec())); - - return 0; -} diff --git a/src/3rdparty/angle/src/compiler/translator/glslang.y b/src/3rdparty/angle/src/compiler/translator/glslang.y deleted file mode 100644 index 3e506caac8..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/glslang.y +++ /dev/null @@ -1,1468 +0,0 @@ -/* -// -// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -This file contains the Yacc grammar for GLSL ES. -Based on ANSI C Yacc grammar: -http://www.lysator.liu.se/c/ANSI-C-grammar-y.html - -IF YOU MODIFY THIS FILE YOU ALSO NEED TO RUN generate_parser.sh, -WHICH GENERATES THE GLSL ES PARSER (glslang_tab.cpp AND glslang_tab.h). -*/ - -%{ -// -// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// This file is auto-generated by generate_parser.sh. DO NOT EDIT! - -// clang-format off - -// Ignore errors in auto-generated code. -#if defined(__GNUC__) -#pragma GCC diagnostic ignored "-Wunused-function" -#pragma GCC diagnostic ignored "-Wunused-variable" -#pragma GCC diagnostic ignored "-Wswitch-enum" -#elif defined(_MSC_VER) -#pragma warning(disable: 4065) -#pragma warning(disable: 4189) -#pragma warning(disable: 4244) -#pragma warning(disable: 4505) -#pragma warning(disable: 4701) -#pragma warning(disable: 4702) -#endif - -#include "angle_gl.h" -#include "compiler/translator/Cache.h" -#include "compiler/translator/SymbolTable.h" -#include "compiler/translator/ParseContext.h" -#include "GLSLANG/ShaderLang.h" - -#define YYENABLE_NLS 0 - -using namespace sh; - -%} -%expect 1 /* One shift reduce conflict because of if | else */ -%parse-param {TParseContext* context} -%param {void *scanner} -%define api.pure full -%locations - -%code requires { -#define YYLTYPE TSourceLoc -#define YYLTYPE_IS_DECLARED 1 -} - -%union { - struct { - union { - TString *string; - float f; - int i; - unsigned int u; - bool b; - }; - TSymbol* symbol; - } lex; - struct { - TOperator op; - union { - TIntermNode *intermNode; - TIntermNodePair nodePair; - TIntermFunctionCallOrMethod callOrMethodPair; - TIntermTyped *intermTypedNode; - TIntermAggregate *intermAggregate; - TIntermBlock *intermBlock; - TIntermDeclaration *intermDeclaration; - TIntermFunctionPrototype *intermFunctionPrototype; - TIntermSwitch *intermSwitch; - TIntermCase *intermCase; - }; - union { - TVector *arraySizes; - TTypeSpecifierNonArray typeSpecifierNonArray; - TPublicType type; - TPrecision precision; - TLayoutQualifier layoutQualifier; - TQualifier qualifier; - TFunction *function; - TParameter param; - TField *field; - TFieldList *fieldList; - TQualifierWrapperBase *qualifierWrapper; - TTypeQualifierBuilder *typeQualifierBuilder; - }; - } interm; -} - -%{ -extern int yylex(YYSTYPE* yylval, YYLTYPE* yylloc, void* yyscanner); -extern void yyerror(YYLTYPE* yylloc, TParseContext* context, void *scanner, const char* reason); - -#define YYLLOC_DEFAULT(Current, Rhs, N) \ - do { \ - if (N) { \ - (Current).first_file = YYRHSLOC(Rhs, 1).first_file; \ - (Current).first_line = YYRHSLOC(Rhs, 1).first_line; \ - (Current).last_file = YYRHSLOC(Rhs, N).last_file; \ - (Current).last_line = YYRHSLOC(Rhs, N).last_line; \ - } \ - else { \ - (Current).first_file = YYRHSLOC(Rhs, 0).last_file; \ - (Current).first_line = YYRHSLOC(Rhs, 0).last_line; \ - (Current).last_file = YYRHSLOC(Rhs, 0).last_file; \ - (Current).last_line = YYRHSLOC(Rhs, 0).last_line; \ - } \ - } while (0) - -#define VERTEX_ONLY(S, L) { \ - if (context->getShaderType() != GL_VERTEX_SHADER) { \ - context->error(L, " supported in vertex shaders only", S); \ - } \ -} - -#define COMPUTE_ONLY(S, L) { \ - if (context->getShaderType() != GL_COMPUTE_SHADER) { \ - context->error(L, " supported in compute shaders only", S); \ - } \ -} - -#define ES2_ONLY(S, L) { \ - if (context->getShaderVersion() != 100) { \ - context->error(L, " supported in GLSL ES 1.00 only", S); \ - } \ -} - -#define ES3_OR_NEWER(TOKEN, LINE, REASON) { \ - if (context->getShaderVersion() < 300) { \ - context->error(LINE, REASON " supported in GLSL ES 3.00 and above only", TOKEN); \ - } \ -} - -#define ES3_OR_NEWER_OR_MULTIVIEW(TOKEN, LINE, REASON) { \ - if (context->getShaderVersion() < 300 && !context->isExtensionEnabled(TExtension::OVR_multiview)) { \ - context->error(LINE, REASON " supported in GLSL ES 3.00 and above only", TOKEN); \ - } \ -} - -#define ES3_1_ONLY(TOKEN, LINE, REASON) { \ - if (context->getShaderVersion() != 310) { \ - context->error(LINE, REASON " supported in GLSL ES 3.10 only", TOKEN); \ - } \ -} -%} - -%token INVARIANT HIGH_PRECISION MEDIUM_PRECISION LOW_PRECISION PRECISION -%token ATTRIBUTE CONST_QUAL BOOL_TYPE FLOAT_TYPE INT_TYPE UINT_TYPE -%token BREAK CONTINUE DO ELSE FOR IF DISCARD RETURN SWITCH CASE DEFAULT -%token BVEC2 BVEC3 BVEC4 IVEC2 IVEC3 IVEC4 VEC2 VEC3 VEC4 UVEC2 UVEC3 UVEC4 -%token MATRIX2 MATRIX3 MATRIX4 IN_QUAL OUT_QUAL INOUT_QUAL UNIFORM BUFFER VARYING -%token MATRIX2x3 MATRIX3x2 MATRIX2x4 MATRIX4x2 MATRIX3x4 MATRIX4x3 -%token CENTROID FLAT SMOOTH -%token READONLY WRITEONLY COHERENT RESTRICT VOLATILE SHARED -%token STRUCT VOID_TYPE WHILE -%token SAMPLER2D SAMPLERCUBE SAMPLER_EXTERNAL_OES SAMPLER2DRECT SAMPLER2DARRAY -%token ISAMPLER2D ISAMPLER3D ISAMPLERCUBE ISAMPLER2DARRAY -%token USAMPLER2D USAMPLER3D USAMPLERCUBE USAMPLER2DARRAY -%token SAMPLER2DMS ISAMPLER2DMS USAMPLER2DMS -%token SAMPLER3D SAMPLER3DRECT SAMPLER2DSHADOW SAMPLERCUBESHADOW SAMPLER2DARRAYSHADOW -%token SAMPLEREXTERNAL2DY2YEXT -%token IMAGE2D IIMAGE2D UIMAGE2D IMAGE3D IIMAGE3D UIMAGE3D IMAGE2DARRAY IIMAGE2DARRAY UIMAGE2DARRAY -%token IMAGECUBE IIMAGECUBE UIMAGECUBE -%token ATOMICUINT -%token LAYOUT -%token YUVCSCSTANDARDEXT YUVCSCSTANDARDEXTCONSTANT - -%token IDENTIFIER TYPE_NAME FLOATCONSTANT INTCONSTANT UINTCONSTANT BOOLCONSTANT -%token FIELD_SELECTION -%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 - -%type identifier -%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 - -%type condition conditionopt -%type translation_unit -%type function_definition statement simple_statement -%type statement_list compound_statement_with_scope compound_statement_no_new_scope -%type declaration_statement selection_statement expression_statement -%type declaration external_declaration -%type for_init_statement -%type selection_rest_statement for_rest_statement -%type switch_statement -%type case_label -%type iteration_statement jump_statement statement_no_new_scope statement_with_scope -%type single_declaration init_declarator_list - -%type parameter_declaration parameter_declarator parameter_type_specifier -%type layout_qualifier_id_list layout_qualifier_id - -// Note: array_specifier guaranteed to be non-null. -%type array_specifier - -%type fully_specified_type type_specifier - -%type precision_qualifier -%type layout_qualifier -%type interpolation_qualifier -%type storage_qualifier single_type_qualifier invariant_qualifier -%type type_qualifier - -%type type_specifier_nonarray struct_specifier -%type type_specifier_no_prec -%type struct_declarator -%type struct_declarator_list struct_declaration struct_declaration_list -%type function_header function_declarator function_identifier -%type function_header_with_parameters function_call_header -%type function_call_header_with_parameters function_call_header_no_parameters function_call_generic function_prototype -%type function_call_or_method - -%type enter_struct - -%start translation_unit -%% - -identifier - : IDENTIFIER - | TYPE_NAME - -variable_identifier - : IDENTIFIER { - // The symbol table search was done in the lexical phase - $$ = context->parseVariableIdentifier(@1, $1.string, $1.symbol); - - // don't delete $1.string, it's used by error recovery, and the pool - // pop will reclaim the memory - } - ; - -primary_expression - : variable_identifier { - $$ = $1; - } - | INTCONSTANT { - TConstantUnion *unionArray = new TConstantUnion[1]; - unionArray->setIConst($1.i); - $$ = context->addScalarLiteral(unionArray, @1); - } - | UINTCONSTANT { - TConstantUnion *unionArray = new TConstantUnion[1]; - unionArray->setUConst($1.u); - $$ = context->addScalarLiteral(unionArray, @1); - } - | FLOATCONSTANT { - TConstantUnion *unionArray = new TConstantUnion[1]; - unionArray->setFConst($1.f); - $$ = context->addScalarLiteral(unionArray, @1); - } - | BOOLCONSTANT { - TConstantUnion *unionArray = new TConstantUnion[1]; - unionArray->setBConst($1.b); - $$ = context->addScalarLiteral(unionArray, @1); - } - | YUVCSCSTANDARDEXTCONSTANT { - if (!context->checkCanUseExtension(@1, TExtension::EXT_YUV_target)) - { - context->error(@1, "unsupported value", $1.string->c_str()); - } - TConstantUnion *unionArray = new TConstantUnion[1]; - unionArray->setYuvCscStandardEXTConst(getYuvCscStandardEXT($1.string->c_str())); - $$ = context->addScalarLiteral(unionArray, @1); - } - | LEFT_PAREN expression RIGHT_PAREN { - $$ = $2; - } - ; - -postfix_expression - : primary_expression { - $$ = $1; - } - | postfix_expression LEFT_BRACKET integer_expression RIGHT_BRACKET { - $$ = context->addIndexExpression($1, @2, $3); - } - | function_call { - $$ = $1; - } - | postfix_expression DOT FIELD_SELECTION { - $$ = context->addFieldSelectionExpression($1, @2, *$3.string, @3); - } - | postfix_expression INC_OP { - $$ = context->addUnaryMathLValue(EOpPostIncrement, $1, @2); - } - | postfix_expression DEC_OP { - $$ = context->addUnaryMathLValue(EOpPostDecrement, $1, @2); - } - ; - -integer_expression - : expression { - context->checkIsScalarInteger($1, "[]"); - $$ = $1; - } - ; - -function_call - : function_call_or_method { - $$ = context->addFunctionCallOrMethod($1.function, $1.callOrMethodPair.arguments, $1.callOrMethodPair.thisNode, @1); - } - ; - -function_call_or_method - : function_call_generic { - $$ = $1; - $$.callOrMethodPair.thisNode = nullptr; - } - | postfix_expression DOT function_call_generic { - ES3_OR_NEWER("", @3, "methods"); - $$ = $3; - $$.callOrMethodPair.thisNode = $1; - } - ; - -function_call_generic - : function_call_header_with_parameters RIGHT_PAREN { - $$ = $1; - } - | function_call_header_no_parameters RIGHT_PAREN { - $$ = $1; - } - ; - -function_call_header_no_parameters - : function_call_header VOID_TYPE { - $$.function = $1; - $$.callOrMethodPair.arguments = context->createEmptyArgumentsList(); - } - | function_call_header { - $$.function = $1; - $$.callOrMethodPair.arguments = context->createEmptyArgumentsList(); - } - ; - -function_call_header_with_parameters - : function_call_header assignment_expression { - $$.callOrMethodPair.arguments = context->createEmptyArgumentsList(); - $$.function = $1; - $$.callOrMethodPair.arguments->push_back($2); - } - | function_call_header_with_parameters COMMA assignment_expression { - $$.function = $1.function; - $$.callOrMethodPair.arguments->push_back($3); - } - ; - -function_call_header - : function_identifier LEFT_PAREN { - $$ = $1; - } - ; - -// Grammar Note: Constructors look like functions, but are recognized as types. - -function_identifier - : type_specifier_no_prec { - $$ = context->addConstructorFunc($1); - } - | IDENTIFIER { - $$ = context->addNonConstructorFunc($1.string, @1); - } - | FIELD_SELECTION { - $$ = context->addNonConstructorFunc($1.string, @1); - } - ; - -unary_expression - : postfix_expression { - $$ = $1; - } - | INC_OP unary_expression { - $$ = context->addUnaryMathLValue(EOpPreIncrement, $2, @1); - } - | DEC_OP unary_expression { - $$ = context->addUnaryMathLValue(EOpPreDecrement, $2, @1); - } - | unary_operator unary_expression { - $$ = context->addUnaryMath($1, $2, @1); - } - ; -// Grammar Note: No traditional style type casts. - -unary_operator - : PLUS { $$ = EOpPositive; } - | DASH { $$ = EOpNegative; } - | BANG { $$ = EOpLogicalNot; } - | TILDE { - ES3_OR_NEWER("~", @$, "bit-wise operator"); - $$ = EOpBitwiseNot; - } - ; -// Grammar Note: No '*' or '&' unary ops. Pointers are not supported. - -multiplicative_expression - : unary_expression { $$ = $1; } - | multiplicative_expression STAR unary_expression { - $$ = context->addBinaryMath(EOpMul, $1, $3, @2); - } - | multiplicative_expression SLASH unary_expression { - $$ = context->addBinaryMath(EOpDiv, $1, $3, @2); - } - | multiplicative_expression PERCENT unary_expression { - ES3_OR_NEWER("%", @2, "integer modulus operator"); - $$ = context->addBinaryMath(EOpIMod, $1, $3, @2); - } - ; - -additive_expression - : multiplicative_expression { $$ = $1; } - | additive_expression PLUS multiplicative_expression { - $$ = context->addBinaryMath(EOpAdd, $1, $3, @2); - } - | additive_expression DASH multiplicative_expression { - $$ = context->addBinaryMath(EOpSub, $1, $3, @2); - } - ; - -shift_expression - : additive_expression { $$ = $1; } - | shift_expression LEFT_OP additive_expression { - ES3_OR_NEWER("<<", @2, "bit-wise operator"); - $$ = context->addBinaryMath(EOpBitShiftLeft, $1, $3, @2); - } - | shift_expression RIGHT_OP additive_expression { - ES3_OR_NEWER(">>", @2, "bit-wise operator"); - $$ = context->addBinaryMath(EOpBitShiftRight, $1, $3, @2); - } - ; - -relational_expression - : shift_expression { $$ = $1; } - | relational_expression LEFT_ANGLE shift_expression { - $$ = context->addBinaryMathBooleanResult(EOpLessThan, $1, $3, @2); - } - | relational_expression RIGHT_ANGLE shift_expression { - $$ = context->addBinaryMathBooleanResult(EOpGreaterThan, $1, $3, @2); - } - | relational_expression LE_OP shift_expression { - $$ = context->addBinaryMathBooleanResult(EOpLessThanEqual, $1, $3, @2); - } - | relational_expression GE_OP shift_expression { - $$ = context->addBinaryMathBooleanResult(EOpGreaterThanEqual, $1, $3, @2); - } - ; - -equality_expression - : relational_expression { $$ = $1; } - | equality_expression EQ_OP relational_expression { - $$ = context->addBinaryMathBooleanResult(EOpEqual, $1, $3, @2); - } - | equality_expression NE_OP relational_expression { - $$ = context->addBinaryMathBooleanResult(EOpNotEqual, $1, $3, @2); - } - ; - -and_expression - : equality_expression { $$ = $1; } - | and_expression AMPERSAND equality_expression { - ES3_OR_NEWER("&", @2, "bit-wise operator"); - $$ = context->addBinaryMath(EOpBitwiseAnd, $1, $3, @2); - } - ; - -exclusive_or_expression - : and_expression { $$ = $1; } - | exclusive_or_expression CARET and_expression { - ES3_OR_NEWER("^", @2, "bit-wise operator"); - $$ = context->addBinaryMath(EOpBitwiseXor, $1, $3, @2); - } - ; - -inclusive_or_expression - : exclusive_or_expression { $$ = $1; } - | inclusive_or_expression VERTICAL_BAR exclusive_or_expression { - ES3_OR_NEWER("|", @2, "bit-wise operator"); - $$ = context->addBinaryMath(EOpBitwiseOr, $1, $3, @2); - } - ; - -logical_and_expression - : inclusive_or_expression { $$ = $1; } - | logical_and_expression AND_OP inclusive_or_expression { - $$ = context->addBinaryMathBooleanResult(EOpLogicalAnd, $1, $3, @2); - } - ; - -logical_xor_expression - : logical_and_expression { $$ = $1; } - | logical_xor_expression XOR_OP logical_and_expression { - $$ = context->addBinaryMathBooleanResult(EOpLogicalXor, $1, $3, @2); - } - ; - -logical_or_expression - : logical_xor_expression { $$ = $1; } - | logical_or_expression OR_OP logical_xor_expression { - $$ = context->addBinaryMathBooleanResult(EOpLogicalOr, $1, $3, @2); - } - ; - -conditional_expression - : logical_or_expression { $$ = $1; } - | logical_or_expression QUESTION expression COLON assignment_expression { - $$ = context->addTernarySelection($1, $3, $5, @2); - } - ; - -assignment_expression - : conditional_expression { $$ = $1; } - | unary_expression assignment_operator assignment_expression { - $$ = context->addAssign($2, $1, $3, @2); - } - ; - -assignment_operator - : EQUAL { $$ = EOpAssign; } - | MUL_ASSIGN { $$ = EOpMulAssign; } - | DIV_ASSIGN { $$ = EOpDivAssign; } - | MOD_ASSIGN { - ES3_OR_NEWER("%=", @$, "integer modulus operator"); - $$ = EOpIModAssign; - } - | ADD_ASSIGN { $$ = EOpAddAssign; } - | SUB_ASSIGN { $$ = EOpSubAssign; } - | LEFT_ASSIGN { - ES3_OR_NEWER("<<=", @$, "bit-wise operator"); - $$ = EOpBitShiftLeftAssign; - } - | RIGHT_ASSIGN { - ES3_OR_NEWER(">>=", @$, "bit-wise operator"); - $$ = EOpBitShiftRightAssign; - } - | AND_ASSIGN { - ES3_OR_NEWER("&=", @$, "bit-wise operator"); - $$ = EOpBitwiseAndAssign; - } - | XOR_ASSIGN { - ES3_OR_NEWER("^=", @$, "bit-wise operator"); - $$ = EOpBitwiseXorAssign; - } - | OR_ASSIGN { - ES3_OR_NEWER("|=", @$, "bit-wise operator"); - $$ = EOpBitwiseOrAssign; - } - ; - -expression - : assignment_expression { - $$ = $1; - } - | expression COMMA assignment_expression { - $$ = context->addComma($1, $3, @2); - } - ; - -constant_expression - : conditional_expression { - context->checkIsConst($1); - $$ = $1; - } - ; - -enter_struct - : IDENTIFIER LEFT_BRACE { - context->enterStructDeclaration(@1, *$1.string); - $$ = $1; - } - ; - -declaration - : function_prototype SEMICOLON { - $$ = context->addFunctionPrototypeDeclaration(*($1.function), @1); - } - | init_declarator_list SEMICOLON { - $$ = $1.intermDeclaration; - } - | PRECISION precision_qualifier type_specifier_no_prec SEMICOLON { - context->parseDefaultPrecisionQualifier($2, $3, @1); - $$ = nullptr; - } - | type_qualifier enter_struct struct_declaration_list RIGHT_BRACE SEMICOLON { - ES3_OR_NEWER($2.string->c_str(), @1, "interface blocks"); - $$ = context->addInterfaceBlock(*$1, @2, *$2.string, $3, NULL, @$, NULL, @$); - } - | type_qualifier enter_struct struct_declaration_list RIGHT_BRACE IDENTIFIER SEMICOLON { - ES3_OR_NEWER($2.string->c_str(), @1, "interface blocks"); - $$ = context->addInterfaceBlock(*$1, @2, *$2.string, $3, $5.string, @5, NULL, @$); - } - | type_qualifier enter_struct struct_declaration_list RIGHT_BRACE IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET SEMICOLON { - ES3_OR_NEWER($2.string->c_str(), @1, "interface blocks"); - $$ = context->addInterfaceBlock(*$1, @2, *$2.string, $3, $5.string, @5, $7, @6); - } - | type_qualifier SEMICOLON { - context->parseGlobalLayoutQualifier(*$1); - $$ = nullptr; - } - | type_qualifier IDENTIFIER SEMICOLON // e.g. to qualify an existing variable as invariant - { - $$ = context->parseInvariantDeclaration(*$1, @2, $2.string, $2.symbol); - } - ; - -function_prototype - : function_declarator RIGHT_PAREN { - $$.function = context->parseFunctionDeclarator(@2, $1); - context->exitFunctionDeclaration(); - } - ; - -function_declarator - : function_header { - $$ = $1; - } - | function_header_with_parameters { - $$ = $1; - } - ; - - -function_header_with_parameters - : function_header parameter_declaration { - // Add the parameter - $$ = $1; - if ($2.type->getBasicType() != EbtVoid) - { - $1->addParameter($2.turnToConst()); - } - } - | function_header_with_parameters COMMA parameter_declaration { - $$ = $1; - // 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.type->getBasicType() == EbtVoid) - { - // This parameter > first is void - context->error(@2, "cannot be a parameter type except for '(void)'", "void"); - } - else - { - $1->addParameter($3.turnToConst()); - } - } - ; - -function_header - : fully_specified_type IDENTIFIER LEFT_PAREN { - $$ = context->parseFunctionHeader($1, $2.string, @2); - - context->symbolTable.push(); - context->enterFunctionDeclaration(); - } - ; - -parameter_declarator - // Type + name - : type_specifier identifier { - $$ = context->parseParameterDeclarator($1, $2.string, @2); - } - | type_specifier identifier array_specifier { - $$ = context->parseParameterArrayDeclarator($2.string, @2, *($3), @3, &$1); - } - ; - -parameter_declaration - : type_qualifier parameter_declarator { - $$ = $2; - context->checkIsParameterQualifierValid(@2, *$1, $2.type); - } - | parameter_declarator { - $$ = $1; - $$.type->setQualifier(EvqIn); - } - | type_qualifier parameter_type_specifier { - $$ = $2; - context->checkIsParameterQualifierValid(@2, *$1, $2.type); - } - | parameter_type_specifier { - $$ = $1; - $$.type->setQualifier(EvqIn); - } - ; - -parameter_type_specifier - : type_specifier { - TParameter param = { 0, new TType($1) }; - $$ = param; - } - ; - -init_declarator_list - : single_declaration { - $$ = $1; - } - | init_declarator_list COMMA identifier { - $$ = $1; - context->parseDeclarator($$.type, @3, *$3.string, $$.intermDeclaration); - } - | init_declarator_list COMMA identifier array_specifier { - $$ = $1; - context->parseArrayDeclarator($$.type, @3, *$3.string, @4, *($4), $$.intermDeclaration); - } - | init_declarator_list COMMA identifier array_specifier EQUAL initializer { - ES3_OR_NEWER("=", @5, "first-class arrays (array initializer)"); - $$ = $1; - context->parseArrayInitDeclarator($$.type, @3, *$3.string, @4, *($4), @5, $6, $$.intermDeclaration); - } - | init_declarator_list COMMA identifier EQUAL initializer { - $$ = $1; - context->parseInitDeclarator($$.type, @3, *$3.string, @4, $5, $$.intermDeclaration); - } - ; - -single_declaration - : fully_specified_type { - $$.type = $1; - $$.intermDeclaration = context->parseSingleDeclaration($$.type, @1, ""); - } - | fully_specified_type identifier { - $$.type = $1; - $$.intermDeclaration = context->parseSingleDeclaration($$.type, @2, *$2.string); - } - | fully_specified_type identifier array_specifier { - $$.type = $1; - $$.intermDeclaration = context->parseSingleArrayDeclaration($$.type, @2, *$2.string, @3, *($3)); - } - | fully_specified_type identifier array_specifier EQUAL initializer { - ES3_OR_NEWER("[]", @3, "first-class arrays (array initializer)"); - $$.type = $1; - $$.intermDeclaration = context->parseSingleArrayInitDeclaration($$.type, @2, *$2.string, @3, *($3), @4, $5); - } - | fully_specified_type identifier EQUAL initializer { - $$.type = $1; - $$.intermDeclaration = context->parseSingleInitDeclaration($$.type, @2, *$2.string, @3, $4); - } - ; - -fully_specified_type - : type_specifier { - context->addFullySpecifiedType(&$1); - $$ = $1; - } - | type_qualifier type_specifier { - $$ = context->addFullySpecifiedType(*$1, $2); - } - ; - -interpolation_qualifier - : SMOOTH { - $$ = EvqSmooth; - } - | FLAT { - $$ = EvqFlat; - } - ; - -type_qualifier - : single_type_qualifier { - $$ = context->createTypeQualifierBuilder(@1); - $$->appendQualifier($1); - } - | type_qualifier single_type_qualifier { - $$ = $1; - $$->appendQualifier($2); - } - ; - -invariant_qualifier - : INVARIANT { - // empty - } - ; - -single_type_qualifier - : storage_qualifier { - context->checkLocalVariableConstStorageQualifier(*$1); - $$ = $1; - } - | layout_qualifier { - context->checkIsAtGlobalLevel(@1, "layout"); - $$ = new TLayoutQualifierWrapper($1, @1); - } - | precision_qualifier { - $$ = new TPrecisionQualifierWrapper($1, @1); - } - | interpolation_qualifier { - $$ = new TInterpolationQualifierWrapper($1, @1); - } - | invariant_qualifier { - context->checkIsAtGlobalLevel(@1, "invariant"); - $$ = new TInvariantQualifierWrapper(@1); - } - ; - - -storage_qualifier - : - ATTRIBUTE { - VERTEX_ONLY("attribute", @1); - ES2_ONLY("attribute", @1); - $$ = context->parseGlobalStorageQualifier(EvqAttribute, @1); - } - | VARYING { - ES2_ONLY("varying", @1); - $$ = context->parseVaryingQualifier(@1); - } - | CONST_QUAL { - $$ = new TStorageQualifierWrapper(EvqConst, @1); - } - | IN_QUAL { - $$ = context->parseInQualifier(@1); - } - | OUT_QUAL { - $$ = context->parseOutQualifier(@1); - } - | INOUT_QUAL { - $$ = context->parseInOutQualifier(@1); - } - | CENTROID { - ES3_OR_NEWER("centroid", @1, "storage qualifier"); - $$ = new TStorageQualifierWrapper(EvqCentroid, @1); - } - | UNIFORM { - $$ = context->parseGlobalStorageQualifier(EvqUniform, @1); - } - | BUFFER { - ES3_1_ONLY("buffer", @1, "storage qualifier"); - $$ = context->parseGlobalStorageQualifier(EvqBuffer, @1); - } - | READONLY { - $$ = new TMemoryQualifierWrapper(EvqReadOnly, @1); - } - | WRITEONLY { - $$ = new TMemoryQualifierWrapper(EvqWriteOnly, @1); - } - | COHERENT { - $$ = new TMemoryQualifierWrapper(EvqCoherent, @1); - } - | RESTRICT { - $$ = new TMemoryQualifierWrapper(EvqRestrict, @1); - } - | VOLATILE { - $$ = new TMemoryQualifierWrapper(EvqVolatile, @1); - } - | SHARED { - COMPUTE_ONLY("shared", @1); - $$ = context->parseGlobalStorageQualifier(EvqShared, @1); - } - ; - -type_specifier - : type_specifier_no_prec { - $$ = $1; - $$.precision = context->symbolTable.getDefaultPrecision($1.getBasicType()); - } - ; - -precision_qualifier - : HIGH_PRECISION { - $$ = EbpHigh; - } - | MEDIUM_PRECISION { - $$ = EbpMedium; - } - | LOW_PRECISION { - $$ = EbpLow; - } - ; - -layout_qualifier - : LAYOUT LEFT_PAREN layout_qualifier_id_list RIGHT_PAREN { - ES3_OR_NEWER_OR_MULTIVIEW("layout", @1, "qualifier"); - $$ = $3; - } - ; - -layout_qualifier_id_list - : layout_qualifier_id { - $$ = $1; - } - | layout_qualifier_id_list COMMA layout_qualifier_id { - $$ = context->joinLayoutQualifiers($1, $3, @3); - } - ; - -layout_qualifier_id - : IDENTIFIER { - $$ = context->parseLayoutQualifier(*$1.string, @1); - } - | IDENTIFIER EQUAL INTCONSTANT { - $$ = context->parseLayoutQualifier(*$1.string, @1, $3.i, @3); - } - | IDENTIFIER EQUAL UINTCONSTANT { - $$ = context->parseLayoutQualifier(*$1.string, @1, $3.i, @3); - } - | SHARED { - $$ = context->parseLayoutQualifier("shared", @1); - } - ; - -type_specifier_no_prec - : type_specifier_nonarray { - $$.initialize($1, (context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary)); - } - | type_specifier_nonarray array_specifier { - $$.initialize($1, (context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary)); - $$.setArraySizes($2); - } - ; - -array_specifier - : LEFT_BRACKET RIGHT_BRACKET { - ES3_OR_NEWER("[]", @1, "implicitly sized array"); - $$ = new TVector(); - $$->push_back(0u); - } - | LEFT_BRACKET constant_expression RIGHT_BRACKET { - $$ = new TVector(); - unsigned int size = context->checkIsValidArraySize(@1, $2); - // Make the type an array even if size check failed. - // This ensures useless error messages regarding a variable's non-arrayness won't follow. - $$->push_back(size); - } - | array_specifier LEFT_BRACKET RIGHT_BRACKET { - ES3_1_ONLY("[]", @2, "arrays of arrays"); - $$ = $1; - $$->insert($$->begin(), 0u); - } - | array_specifier LEFT_BRACKET constant_expression RIGHT_BRACKET { - ES3_1_ONLY("[]", @2, "arrays of arrays"); - $$ = $1; - unsigned int size = context->checkIsValidArraySize(@2, $3); - // Make the type an array even if size check failed. - // This ensures useless error messages regarding a variable's non-arrayness won't follow. - $$->insert($$->begin(), size); - } - ; - -type_specifier_nonarray - : VOID_TYPE { - $$.initialize(EbtVoid, @1); - } - | FLOAT_TYPE { - $$.initialize(EbtFloat, @1); - } - | INT_TYPE { - $$.initialize(EbtInt, @1); - } - | UINT_TYPE { - $$.initialize(EbtUInt, @1); - } - | BOOL_TYPE { - $$.initialize(EbtBool, @1); - } - | VEC2 { - $$.initialize(EbtFloat, @1); - $$.setAggregate(2); - } - | VEC3 { - $$.initialize(EbtFloat, @1); - $$.setAggregate(3); - } - | VEC4 { - $$.initialize(EbtFloat, @1); - $$.setAggregate(4); - } - | BVEC2 { - $$.initialize(EbtBool, @1); - $$.setAggregate(2); - } - | BVEC3 { - $$.initialize(EbtBool, @1); - $$.setAggregate(3); - } - | BVEC4 { - $$.initialize(EbtBool, @1); - $$.setAggregate(4); - } - | IVEC2 { - $$.initialize(EbtInt, @1); - $$.setAggregate(2); - } - | IVEC3 { - $$.initialize(EbtInt, @1); - $$.setAggregate(3); - } - | IVEC4 { - $$.initialize(EbtInt, @1); - $$.setAggregate(4); - } - | UVEC2 { - $$.initialize(EbtUInt, @1); - $$.setAggregate(2); - } - | UVEC3 { - $$.initialize(EbtUInt, @1); - $$.setAggregate(3); - } - | UVEC4 { - $$.initialize(EbtUInt, @1); - $$.setAggregate(4); - } - | MATRIX2 { - $$.initialize(EbtFloat, @1); - $$.setMatrix(2, 2); - } - | MATRIX3 { - $$.initialize(EbtFloat, @1); - $$.setMatrix(3, 3); - } - | MATRIX4 { - $$.initialize(EbtFloat, @1); - $$.setMatrix(4, 4); - } - | MATRIX2x3 { - $$.initialize(EbtFloat, @1); - $$.setMatrix(2, 3); - } - | MATRIX3x2 { - $$.initialize(EbtFloat, @1); - $$.setMatrix(3, 2); - } - | MATRIX2x4 { - $$.initialize(EbtFloat, @1); - $$.setMatrix(2, 4); - } - | MATRIX4x2 { - $$.initialize(EbtFloat, @1); - $$.setMatrix(4, 2); - } - | MATRIX3x4 { - $$.initialize(EbtFloat, @1); - $$.setMatrix(3, 4); - } - | MATRIX4x3 { - $$.initialize(EbtFloat, @1); - $$.setMatrix(4, 3); - } - | YUVCSCSTANDARDEXT { - if (!context->checkCanUseExtension(@1, TExtension::EXT_YUV_target)) - { - context->error(@1, "unsupported type", "yuvCscStandardEXT"); - } - $$.initialize(EbtYuvCscStandardEXT, @1); - } - | SAMPLER2D { - $$.initialize(EbtSampler2D, @1); - } - | SAMPLER3D { - $$.initialize(EbtSampler3D, @1); - } - | SAMPLERCUBE { - $$.initialize(EbtSamplerCube, @1); - } - | SAMPLER2DARRAY { - $$.initialize(EbtSampler2DArray, @1); - } - | SAMPLER2DMS { - $$.initialize(EbtSampler2DMS, @1); - } - | ISAMPLER2D { - $$.initialize(EbtISampler2D, @1); - } - | ISAMPLER3D { - $$.initialize(EbtISampler3D, @1); - } - | ISAMPLERCUBE { - $$.initialize(EbtISamplerCube, @1); - } - | ISAMPLER2DARRAY { - $$.initialize(EbtISampler2DArray, @1); - } - | ISAMPLER2DMS { - $$.initialize(EbtISampler2DMS, @1); - } - | USAMPLER2D { - $$.initialize(EbtUSampler2D, @1); - } - | USAMPLER3D { - $$.initialize(EbtUSampler3D, @1); - } - | USAMPLERCUBE { - $$.initialize(EbtUSamplerCube, @1); - } - | USAMPLER2DARRAY { - $$.initialize(EbtUSampler2DArray, @1); - } - | USAMPLER2DMS { - $$.initialize(EbtUSampler2DMS, @1); - } - | SAMPLER2DSHADOW { - $$.initialize(EbtSampler2DShadow, @1); - } - | SAMPLERCUBESHADOW { - $$.initialize(EbtSamplerCubeShadow, @1); - } - | SAMPLER2DARRAYSHADOW { - $$.initialize(EbtSampler2DArrayShadow, @1); - } - | SAMPLER_EXTERNAL_OES { - constexpr std::array extensions{ { TExtension::NV_EGL_stream_consumer_external, - TExtension::OES_EGL_image_external_essl3, - TExtension::OES_EGL_image_external } }; - if (!context->checkCanUseOneOfExtensions(@1, extensions)) - { - context->error(@1, "unsupported type", "samplerExternalOES"); - } - $$.initialize(EbtSamplerExternalOES, @1); - } - | SAMPLEREXTERNAL2DY2YEXT { - if (!context->checkCanUseExtension(@1, TExtension::EXT_YUV_target)) - { - context->error(@1, "unsupported type", "__samplerExternal2DY2YEXT"); - } - $$.initialize(EbtSamplerExternal2DY2YEXT, @1); - } - | SAMPLER2DRECT { - if (!context->checkCanUseExtension(@1, TExtension::ARB_texture_rectangle)) - { - context->error(@1, "unsupported type", "sampler2DRect"); - } - $$.initialize(EbtSampler2DRect, @1); - } - | struct_specifier { - $$ = $1; - } - | IMAGE2D { - $$.initialize(EbtImage2D, @1); - } - | IIMAGE2D { - $$.initialize(EbtIImage2D, @1); - } - | UIMAGE2D { - $$.initialize(EbtUImage2D, @1); - } - | IMAGE3D { - $$.initialize(EbtImage3D, @1); - } - | IIMAGE3D { - $$.initialize(EbtIImage3D, @1); - } - | UIMAGE3D { - $$.initialize(EbtUImage3D, @1); - } - | IMAGE2DARRAY { - $$.initialize(EbtImage2DArray, @1); - } - | IIMAGE2DARRAY { - $$.initialize(EbtIImage2DArray, @1); - } - | UIMAGE2DARRAY { - $$.initialize(EbtUImage2DArray, @1); - } - | IMAGECUBE { - $$.initialize(EbtImageCube, @1); - } - | IIMAGECUBE { - $$.initialize(EbtIImageCube, @1); - } - | UIMAGECUBE { - $$.initialize(EbtUImageCube, @1); - } - | ATOMICUINT { - $$.initialize(EbtAtomicCounter, @1); - } - | TYPE_NAME { - // This is for user defined type names. The lexical phase looked up the type. - TType& structure = static_cast($1.symbol)->getType(); - $$.initializeStruct(structure.getStruct(), false, @1); - } - ; - -struct_specifier - : STRUCT identifier LEFT_BRACE { context->enterStructDeclaration(@2, *$2.string); } struct_declaration_list RIGHT_BRACE { - $$ = context->addStructure(@1, @2, $2.string, $5); - } - | STRUCT LEFT_BRACE { context->enterStructDeclaration(@2, *$2.string); } struct_declaration_list RIGHT_BRACE { - $$ = context->addStructure(@1, @$, NewPoolTString(""), $4); - } - ; - -struct_declaration_list - : struct_declaration { - $$ = context->addStructFieldList($1, @1); - } - | struct_declaration_list struct_declaration { - $$ = context->combineStructFieldLists($1, $2, @2); - } - ; - -struct_declaration - : type_specifier struct_declarator_list SEMICOLON { - $$ = context->addStructDeclaratorList($1, $2); - } - | type_qualifier type_specifier struct_declarator_list SEMICOLON { - // ES3 Only, but errors should be handled elsewhere - $$ = context->addStructDeclaratorListWithQualifiers(*$1, &$2, $3); - } - ; - -struct_declarator_list - : struct_declarator { - $$ = NewPoolTFieldList(); - $$->push_back($1); - } - | struct_declarator_list COMMA struct_declarator { - $$->push_back($3); - } - ; - -struct_declarator - : identifier { - $$ = context->parseStructDeclarator($1.string, @1); - } - | identifier array_specifier { - $$ = context->parseStructArrayDeclarator($1.string, @1, *($2), @2); - } - ; - -initializer - : assignment_expression { $$ = $1; } - ; - -declaration_statement - : declaration { $$ = $1; } - ; - -statement - : compound_statement_with_scope { $$ = $1; } - | simple_statement { $$ = $1; } - ; - -// Grammar Note: Labeled statements for SWITCH 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_with_scope - : LEFT_BRACE RIGHT_BRACE { - $$ = new TIntermBlock(); - $$->setLine(@$); - } - | LEFT_BRACE { context->symbolTable.push(); } statement_list { context->symbolTable.pop(); } RIGHT_BRACE { - $3->setLine(@$); - $$ = $3; - } - ; - -statement_no_new_scope - : compound_statement_no_new_scope { $$ = $1; } - | simple_statement { $$ = $1; } - ; - -statement_with_scope - : { context->symbolTable.push(); } compound_statement_no_new_scope { context->symbolTable.pop(); $$ = $2; } - | { context->symbolTable.push(); } simple_statement { context->symbolTable.pop(); $$ = $2; } - ; - -compound_statement_no_new_scope - // Statement that doesn't create a new scope for iteration_statement, function definition (scope is created for parameters) - : LEFT_BRACE RIGHT_BRACE { - $$ = new TIntermBlock(); - $$->setLine(@$); - } - | LEFT_BRACE statement_list RIGHT_BRACE { - $2->setLine(@$); - $$ = $2; - } - ; - -statement_list - : statement { - $$ = new TIntermBlock(); - $$->appendStatement($1); - } - | statement_list statement { - $$ = $1; - $$->appendStatement($2); - } - ; - -expression_statement - : SEMICOLON { $$ = context->addEmptyStatement(@$); } - | expression SEMICOLON { $$ = $1; } - ; - -selection_statement - : IF LEFT_PAREN expression RIGHT_PAREN selection_rest_statement { - $$ = context->addIfElse($3, $5, @1); - } - ; - -selection_rest_statement - : statement_with_scope ELSE statement_with_scope { - $$.node1 = $1; - $$.node2 = $3; - } - | statement_with_scope { - $$.node1 = $1; - $$.node2 = nullptr; - } - ; - -// Note that we've diverged from the spec grammar here a bit for the sake of simplicity. -// We're reusing compound_statement_with_scope instead of having separate rules for switch. -switch_statement - : SWITCH LEFT_PAREN expression RIGHT_PAREN { context->incrSwitchNestingLevel(); } compound_statement_with_scope { - $$ = context->addSwitch($3, $6, @1); - context->decrSwitchNestingLevel(); - } - ; - -case_label - : CASE constant_expression COLON { - $$ = context->addCase($2, @1); - } - | DEFAULT COLON { - $$ = context->addDefault(@1); - } - ; - -condition - : expression { - $$ = $1; - context->checkIsScalarBool($1->getLine(), $1); - } - | fully_specified_type identifier EQUAL initializer { - $$ = context->addConditionInitializer($1, *$2.string, $4, @2); - } - ; - -iteration_statement - : WHILE LEFT_PAREN { context->symbolTable.push(); context->incrLoopNestingLevel(); } condition RIGHT_PAREN statement_no_new_scope { - context->symbolTable.pop(); - $$ = context->addLoop(ELoopWhile, 0, $4, 0, $6, @1); - context->decrLoopNestingLevel(); - } - | DO { context->incrLoopNestingLevel(); } statement_with_scope WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON { - $$ = context->addLoop(ELoopDoWhile, 0, $6, 0, $3, @4); - context->decrLoopNestingLevel(); - } - | FOR LEFT_PAREN { context->symbolTable.push(); context->incrLoopNestingLevel(); } for_init_statement for_rest_statement RIGHT_PAREN statement_no_new_scope { - context->symbolTable.pop(); - $$ = context->addLoop(ELoopFor, $4, $5.node1, reinterpret_cast($5.node2), $7, @1); - context->decrLoopNestingLevel(); - } - ; - -for_init_statement - : expression_statement { - $$ = $1; - } - | declaration_statement { - $$ = $1; - } - ; - -conditionopt - : condition { - $$ = $1; - } - | /* May be null */ { - $$ = nullptr; - } - ; - -for_rest_statement - : conditionopt SEMICOLON { - $$.node1 = $1; - $$.node2 = 0; - } - | conditionopt SEMICOLON expression { - $$.node1 = $1; - $$.node2 = $3; - } - ; - -jump_statement - : CONTINUE SEMICOLON { - $$ = context->addBranch(EOpContinue, @1); - } - | BREAK SEMICOLON { - $$ = context->addBranch(EOpBreak, @1); - } - | RETURN SEMICOLON { - $$ = context->addBranch(EOpReturn, @1); - } - | RETURN expression SEMICOLON { - $$ = context->addBranch(EOpReturn, $2, @1); - } - | DISCARD SEMICOLON { - $$ = context->addBranch(EOpKill, @1); - } - ; - -// Grammar Note: No 'goto'. Gotos are not supported. - -translation_unit - : external_declaration { - $$ = new TIntermBlock(); - $$->setLine(@$); - $$->appendStatement($1); - context->setTreeRoot($$); - } - | translation_unit external_declaration { - $$->appendStatement($2); - } - ; - -external_declaration - : function_definition { - $$ = $1; - } - | declaration { - $$ = $1; - } - ; - -function_definition - : function_prototype { - context->parseFunctionDefinitionHeader(@1, &($1.function), &($1.intermFunctionPrototype)); - } - compound_statement_no_new_scope { - $$ = context->addFunctionDefinition($1.intermFunctionPrototype, $3, @1); - } - ; - -%% - -int glslang_parse(TParseContext* context) { - return yyparse(context, context->getScanner()); -} diff --git a/src/3rdparty/angle/src/compiler/translator/length_limits.h b/src/3rdparty/angle/src/compiler/translator/length_limits.h deleted file mode 100644 index fcda639d71..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/length_limits.h +++ /dev/null @@ -1,26 +0,0 @@ -// -// Copyright (c) 2011-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// -// length_limits.h -// - -#ifndef COMPILER_TRANSLATOR_LENGTHLIMITS_H_ -#define COMPILER_TRANSLATOR_LENGTHLIMITS_H_ - -#include "GLSLANG/ShaderLang.h" - -// These constants are factored out from the rest of the headers to -// make it easier to reference them from the compiler sources. - -namespace sh -{ - -size_t GetGlobalMaxTokenSize(ShShaderSpec spec); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_LENGTHLIMITS_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/util.cpp b/src/3rdparty/angle/src/compiler/translator/util.cpp deleted file mode 100644 index 9738370c47..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/util.cpp +++ /dev/null @@ -1,714 +0,0 @@ -// -// Copyright (c) 2010 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/translator/util.h" - -#include - -#include "common/utilities.h" -#include "compiler/preprocessor/numeric_lex.h" -#include "compiler/translator/SymbolTable.h" - -bool atoi_clamp(const char *str, unsigned int *value) -{ - bool success = pp::numeric_lex_int(str, value); - if (!success) - *value = std::numeric_limits::max(); - return success; -} - -namespace sh -{ - -namespace -{ - -bool IsInterpolationIn(TQualifier qualifier) -{ - switch (qualifier) - { - case EvqSmoothIn: - case EvqFlatIn: - case EvqCentroidIn: - return true; - default: - return false; - } -} - -} // anonymous namespace - -float NumericLexFloat32OutOfRangeToInfinity(const std::string &str) -{ - // Parses a decimal string using scientific notation into a floating point number. - // Out-of-range values are converted to infinity. Values that are too small to be - // represented are converted to zero. - - // The mantissa in decimal scientific notation. The magnitude of the mantissa integer does not - // matter. - unsigned int decimalMantissa = 0; - size_t i = 0; - bool decimalPointSeen = false; - bool nonZeroSeenInMantissa = false; - - // The exponent offset reflects the position of the decimal point. - int exponentOffset = -1; - while (i < str.length()) - { - const char c = str[i]; - if (c == 'e' || c == 'E') - { - break; - } - if (c == '.') - { - decimalPointSeen = true; - ++i; - continue; - } - - unsigned int digit = static_cast(c - '0'); - ASSERT(digit < 10u); - if (digit != 0u) - { - nonZeroSeenInMantissa = true; - } - if (nonZeroSeenInMantissa) - { - // Add bits to the mantissa until space runs out in 32-bit int. This should be - // enough precision to make the resulting binary mantissa accurate to 1 ULP. - if (decimalMantissa <= (std::numeric_limits::max() - 9u) / 10u) - { - decimalMantissa = decimalMantissa * 10u + digit; - } - if (!decimalPointSeen) - { - ++exponentOffset; - } - } - else if (decimalPointSeen) - { - --exponentOffset; - } - ++i; - } - if (decimalMantissa == 0) - { - return 0.0f; - } - int exponent = 0; - if (i < str.length()) - { - ASSERT(str[i] == 'e' || str[i] == 'E'); - ++i; - bool exponentOutOfRange = false; - bool negativeExponent = false; - if (str[i] == '-') - { - negativeExponent = true; - ++i; - } - else if (str[i] == '+') - { - ++i; - } - while (i < str.length()) - { - const char c = str[i]; - unsigned int digit = static_cast(c - '0'); - ASSERT(digit < 10u); - if (exponent <= (std::numeric_limits::max() - 9) / 10) - { - exponent = exponent * 10 + digit; - } - else - { - exponentOutOfRange = true; - } - ++i; - } - if (negativeExponent) - { - exponent = -exponent; - } - if (exponentOutOfRange) - { - if (negativeExponent) - { - return 0.0f; - } - else - { - return std::numeric_limits::infinity(); - } - } - } - // Do the calculation in 64-bit to avoid overflow. - long long exponentLong = - static_cast(exponent) + static_cast(exponentOffset); - if (exponentLong > std::numeric_limits::max_exponent10) - { - return std::numeric_limits::infinity(); - } - else if (exponentLong < std::numeric_limits::min_exponent10) - { - return 0.0f; - } - // The exponent is in range, so we need to actually evaluate the float. - exponent = static_cast(exponentLong); - double value = decimalMantissa; - - // Calculate the exponent offset to normalize the mantissa. - int normalizationExponentOffset = 0; - while (decimalMantissa >= 10u) - { - --normalizationExponentOffset; - decimalMantissa /= 10u; - } - // Apply the exponent. - value *= std::pow(10.0, static_cast(exponent + normalizationExponentOffset)); - if (value > static_cast(std::numeric_limits::max())) - { - return std::numeric_limits::infinity(); - } - if (value < static_cast(std::numeric_limits::min())) - { - return 0.0f; - } - return static_cast(value); -} - -bool strtof_clamp(const std::string &str, float *value) -{ - // Try the standard float parsing path first. - bool success = pp::numeric_lex_float(str, value); - - // If the standard path doesn't succeed, take the path that can handle the following corner - // cases: - // 1. The decimal mantissa is very small but the exponent is very large, putting the resulting - // number inside the float range. - // 2. The decimal mantissa is very large but the exponent is very small, putting the resulting - // number inside the float range. - // 3. The value is out-of-range and should be evaluated as infinity. - // 4. The value is too small and should be evaluated as zero. - // See ESSL 3.00.6 section 4.1.4 for the relevant specification. - if (!success) - *value = NumericLexFloat32OutOfRangeToInfinity(str); - return !gl::isInf(*value); -} - -GLenum GLVariableType(const TType &type) -{ - if (type.getBasicType() == EbtFloat) - { - if (type.isVector()) - { - switch (type.getNominalSize()) - { - case 2: - return GL_FLOAT_VEC2; - case 3: - return GL_FLOAT_VEC3; - case 4: - return GL_FLOAT_VEC4; - default: - UNREACHABLE(); - } - } - else if (type.isMatrix()) - { - switch (type.getCols()) - { - case 2: - switch (type.getRows()) - { - case 2: - return GL_FLOAT_MAT2; - case 3: - return GL_FLOAT_MAT2x3; - case 4: - return GL_FLOAT_MAT2x4; - default: - UNREACHABLE(); - } - - case 3: - switch (type.getRows()) - { - case 2: - return GL_FLOAT_MAT3x2; - case 3: - return GL_FLOAT_MAT3; - case 4: - return GL_FLOAT_MAT3x4; - default: - UNREACHABLE(); - } - - case 4: - switch (type.getRows()) - { - case 2: - return GL_FLOAT_MAT4x2; - case 3: - return GL_FLOAT_MAT4x3; - case 4: - return GL_FLOAT_MAT4; - default: - UNREACHABLE(); - } - - default: - UNREACHABLE(); - } - } - else - { - return GL_FLOAT; - } - } - else if (type.getBasicType() == EbtInt) - { - if (type.isVector()) - { - switch (type.getNominalSize()) - { - case 2: - return GL_INT_VEC2; - case 3: - return GL_INT_VEC3; - case 4: - return GL_INT_VEC4; - default: - UNREACHABLE(); - } - } - else - { - ASSERT(!type.isMatrix()); - return GL_INT; - } - } - else if (type.getBasicType() == EbtUInt) - { - if (type.isVector()) - { - switch (type.getNominalSize()) - { - case 2: - return GL_UNSIGNED_INT_VEC2; - case 3: - return GL_UNSIGNED_INT_VEC3; - case 4: - return GL_UNSIGNED_INT_VEC4; - default: - UNREACHABLE(); - } - } - else - { - ASSERT(!type.isMatrix()); - return GL_UNSIGNED_INT; - } - } - else if (type.getBasicType() == EbtBool) - { - if (type.isVector()) - { - switch (type.getNominalSize()) - { - case 2: - return GL_BOOL_VEC2; - case 3: - return GL_BOOL_VEC3; - case 4: - return GL_BOOL_VEC4; - default: - UNREACHABLE(); - } - } - else - { - ASSERT(!type.isMatrix()); - return GL_BOOL; - } - } - - switch (type.getBasicType()) - { - case EbtSampler2D: - return GL_SAMPLER_2D; - case EbtSampler3D: - return GL_SAMPLER_3D; - case EbtSamplerCube: - return GL_SAMPLER_CUBE; - case EbtSamplerExternalOES: - return GL_SAMPLER_EXTERNAL_OES; - case EbtSamplerExternal2DY2YEXT: - return GL_SAMPLER_EXTERNAL_2D_Y2Y_EXT; - case EbtSampler2DRect: - return GL_SAMPLER_2D_RECT_ANGLE; - case EbtSampler2DArray: - return GL_SAMPLER_2D_ARRAY; - case EbtSampler2DMS: - return GL_SAMPLER_2D_MULTISAMPLE; - case EbtISampler2D: - return GL_INT_SAMPLER_2D; - case EbtISampler3D: - return GL_INT_SAMPLER_3D; - case EbtISamplerCube: - return GL_INT_SAMPLER_CUBE; - case EbtISampler2DArray: - return GL_INT_SAMPLER_2D_ARRAY; - case EbtISampler2DMS: - return GL_INT_SAMPLER_2D_MULTISAMPLE; - case EbtUSampler2D: - return GL_UNSIGNED_INT_SAMPLER_2D; - case EbtUSampler3D: - return GL_UNSIGNED_INT_SAMPLER_3D; - case EbtUSamplerCube: - return GL_UNSIGNED_INT_SAMPLER_CUBE; - case EbtUSampler2DArray: - return GL_UNSIGNED_INT_SAMPLER_2D_ARRAY; - case EbtUSampler2DMS: - return GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE; - case EbtSampler2DShadow: - return GL_SAMPLER_2D_SHADOW; - case EbtSamplerCubeShadow: - return GL_SAMPLER_CUBE_SHADOW; - case EbtSampler2DArrayShadow: - return GL_SAMPLER_2D_ARRAY_SHADOW; - case EbtImage2D: - return GL_IMAGE_2D; - case EbtIImage2D: - return GL_INT_IMAGE_2D; - case EbtUImage2D: - return GL_UNSIGNED_INT_IMAGE_2D; - case EbtImage2DArray: - return GL_IMAGE_2D_ARRAY; - case EbtIImage2DArray: - return GL_INT_IMAGE_2D_ARRAY; - case EbtUImage2DArray: - return GL_UNSIGNED_INT_IMAGE_2D_ARRAY; - case EbtImage3D: - return GL_IMAGE_3D; - case EbtIImage3D: - return GL_INT_IMAGE_3D; - case EbtUImage3D: - return GL_UNSIGNED_INT_IMAGE_3D; - case EbtImageCube: - return GL_IMAGE_CUBE; - case EbtIImageCube: - return GL_INT_IMAGE_CUBE; - case EbtUImageCube: - return GL_UNSIGNED_INT_IMAGE_CUBE; - case EbtAtomicCounter: - return GL_UNSIGNED_INT_ATOMIC_COUNTER; - default: - UNREACHABLE(); - } - - return GL_NONE; -} - -GLenum GLVariablePrecision(const TType &type) -{ - if (type.getBasicType() == EbtFloat) - { - switch (type.getPrecision()) - { - case EbpHigh: - return GL_HIGH_FLOAT; - case EbpMedium: - return GL_MEDIUM_FLOAT; - case EbpLow: - return GL_LOW_FLOAT; - case EbpUndefined: - // Should be defined as the default precision by the parser - default: - UNREACHABLE(); - } - } - else if (type.getBasicType() == EbtInt || type.getBasicType() == EbtUInt) - { - switch (type.getPrecision()) - { - case EbpHigh: - return GL_HIGH_INT; - case EbpMedium: - return GL_MEDIUM_INT; - case EbpLow: - return GL_LOW_INT; - case EbpUndefined: - // Should be defined as the default precision by the parser - default: - UNREACHABLE(); - } - } - - // Other types (boolean, sampler) don't have a precision - return GL_NONE; -} - -TString ArrayString(const TType &type) -{ - TStringStream arrayString; - if (!type.isArray()) - return arrayString.str(); - - const TVector &arraySizes = *type.getArraySizes(); - for (auto arraySizeIter = arraySizes.rbegin(); arraySizeIter != arraySizes.rend(); - ++arraySizeIter) - { - arrayString << "["; - if (*arraySizeIter > 0) - { - arrayString << (*arraySizeIter); - } - arrayString << "]"; - } - return arrayString.str(); -} - -TString GetTypeName(const TType &type, ShHashFunction64 hashFunction, NameMap *nameMap) -{ - if (type.getBasicType() == EbtStruct) - return HashName(TName(type.getStruct()->name()), hashFunction, nameMap); - else - return type.getBuiltInTypeNameString(); -} - -bool IsVaryingOut(TQualifier qualifier) -{ - switch (qualifier) - { - case EvqVaryingOut: - case EvqSmoothOut: - case EvqFlatOut: - case EvqCentroidOut: - case EvqVertexOut: - case EvqGeometryOut: - return true; - - default: - break; - } - - return false; -} - -bool IsVaryingIn(TQualifier qualifier) -{ - switch (qualifier) - { - case EvqVaryingIn: - case EvqSmoothIn: - case EvqFlatIn: - case EvqCentroidIn: - case EvqFragmentIn: - case EvqGeometryIn: - return true; - - default: - break; - } - - return false; -} - -bool IsVarying(TQualifier qualifier) -{ - return IsVaryingIn(qualifier) || IsVaryingOut(qualifier); -} - -bool IsGeometryShaderInput(GLenum shaderType, TQualifier qualifier) -{ - return (qualifier == EvqGeometryIn) || - ((shaderType == GL_GEOMETRY_SHADER_OES) && IsInterpolationIn(qualifier)); -} - -InterpolationType GetInterpolationType(TQualifier qualifier) -{ - switch (qualifier) - { - case EvqFlatIn: - case EvqFlatOut: - return INTERPOLATION_FLAT; - - case EvqSmoothIn: - case EvqSmoothOut: - case EvqVertexOut: - case EvqFragmentIn: - case EvqVaryingIn: - case EvqVaryingOut: - case EvqGeometryIn: - case EvqGeometryOut: - return INTERPOLATION_SMOOTH; - - case EvqCentroidIn: - case EvqCentroidOut: - return INTERPOLATION_CENTROID; - - default: - UNREACHABLE(); - return INTERPOLATION_SMOOTH; - } -} - -TType GetShaderVariableBasicType(const sh::ShaderVariable &var) -{ - switch (var.type) - { - case GL_BOOL: - return TType(EbtBool); - case GL_BOOL_VEC2: - return TType(EbtBool, 2); - case GL_BOOL_VEC3: - return TType(EbtBool, 3); - case GL_BOOL_VEC4: - return TType(EbtBool, 4); - case GL_FLOAT: - return TType(EbtFloat); - case GL_FLOAT_VEC2: - return TType(EbtFloat, 2); - case GL_FLOAT_VEC3: - return TType(EbtFloat, 3); - case GL_FLOAT_VEC4: - return TType(EbtFloat, 4); - case GL_FLOAT_MAT2: - return TType(EbtFloat, 2, 2); - case GL_FLOAT_MAT3: - return TType(EbtFloat, 3, 3); - case GL_FLOAT_MAT4: - return TType(EbtFloat, 4, 4); - case GL_FLOAT_MAT2x3: - return TType(EbtFloat, 2, 3); - case GL_FLOAT_MAT2x4: - return TType(EbtFloat, 2, 4); - case GL_FLOAT_MAT3x2: - return TType(EbtFloat, 3, 2); - case GL_FLOAT_MAT3x4: - return TType(EbtFloat, 3, 4); - case GL_FLOAT_MAT4x2: - return TType(EbtFloat, 4, 2); - case GL_FLOAT_MAT4x3: - return TType(EbtFloat, 4, 3); - case GL_INT: - return TType(EbtInt); - case GL_INT_VEC2: - return TType(EbtInt, 2); - case GL_INT_VEC3: - return TType(EbtInt, 3); - case GL_INT_VEC4: - return TType(EbtInt, 4); - case GL_UNSIGNED_INT: - return TType(EbtUInt); - case GL_UNSIGNED_INT_VEC2: - return TType(EbtUInt, 2); - case GL_UNSIGNED_INT_VEC3: - return TType(EbtUInt, 3); - case GL_UNSIGNED_INT_VEC4: - return TType(EbtUInt, 4); - default: - UNREACHABLE(); - return TType(); - } -} - -// GLSL ES 1.0.17 4.6.1 The Invariant Qualifier -bool CanBeInvariantESSL1(TQualifier qualifier) -{ - return IsVaryingIn(qualifier) || IsVaryingOut(qualifier) || - IsBuiltinOutputVariable(qualifier) || - (IsBuiltinFragmentInputVariable(qualifier) && qualifier != EvqFrontFacing); -} - -// GLSL ES 3.00 Revision 6, 4.6.1 The Invariant Qualifier -// GLSL ES 3.10 Revision 4, 4.8.1 The Invariant Qualifier -bool CanBeInvariantESSL3OrGreater(TQualifier qualifier) -{ - return IsVaryingOut(qualifier) || qualifier == EvqFragmentOut || - IsBuiltinOutputVariable(qualifier); -} - -bool IsBuiltinOutputVariable(TQualifier qualifier) -{ - switch (qualifier) - { - case EvqPosition: - case EvqPointSize: - case EvqFragDepth: - case EvqFragDepthEXT: - case EvqFragColor: - case EvqSecondaryFragColorEXT: - case EvqFragData: - case EvqSecondaryFragDataEXT: - return true; - default: - break; - } - return false; -} - -bool IsBuiltinFragmentInputVariable(TQualifier qualifier) -{ - switch (qualifier) - { - case EvqFragCoord: - case EvqPointCoord: - case EvqFrontFacing: - return true; - default: - break; - } - return false; -} - -bool IsOutputESSL(ShShaderOutput output) -{ - return output == SH_ESSL_OUTPUT; -} - -bool IsOutputGLSL(ShShaderOutput output) -{ - switch (output) - { - case SH_GLSL_130_OUTPUT: - case SH_GLSL_140_OUTPUT: - case SH_GLSL_150_CORE_OUTPUT: - case SH_GLSL_330_CORE_OUTPUT: - case SH_GLSL_400_CORE_OUTPUT: - case SH_GLSL_410_CORE_OUTPUT: - case SH_GLSL_420_CORE_OUTPUT: - case SH_GLSL_430_CORE_OUTPUT: - case SH_GLSL_440_CORE_OUTPUT: - case SH_GLSL_450_CORE_OUTPUT: - case SH_GLSL_COMPATIBILITY_OUTPUT: - return true; - default: - break; - } - return false; -} -bool IsOutputHLSL(ShShaderOutput output) -{ - switch (output) - { - case SH_HLSL_3_0_OUTPUT: - case SH_HLSL_4_1_OUTPUT: - case SH_HLSL_4_0_FL9_3_OUTPUT: - return true; - default: - break; - } - return false; -} -bool IsOutputVulkan(ShShaderOutput output) -{ - return output == SH_GLSL_VULKAN_OUTPUT; -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/util.h b/src/3rdparty/angle/src/compiler/translator/util.h deleted file mode 100644 index 6d6dc95b3b..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/util.h +++ /dev/null @@ -1,63 +0,0 @@ -// -// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_TRANSLATOR_UTIL_H_ -#define COMPILER_TRANSLATOR_UTIL_H_ - -#include - -#include "angle_gl.h" -#include - -#include "compiler/translator/HashNames.h" -#include "compiler/translator/Operator.h" -#include "compiler/translator/Types.h" - -// If overflow happens, clamp the value to UINT_MIN or UINT_MAX. -// Return false if overflow happens. -bool atoi_clamp(const char *str, unsigned int *value); - -namespace sh -{ -class TSymbolTable; - -float NumericLexFloat32OutOfRangeToInfinity(const std::string &str); - -// strtof_clamp is like strtof but -// 1. it forces C locale, i.e. forcing '.' as decimal point. -// 2. it sets the value to infinity if overflow happens. -// 3. str should be guaranteed to be in the valid format for a floating point number as defined -// by the grammar in the ESSL 3.00.6 spec section 4.1.4. -// Return false if overflow happens. -bool strtof_clamp(const std::string &str, float *value); - -GLenum GLVariableType(const TType &type); -GLenum GLVariablePrecision(const TType &type); -bool IsVaryingIn(TQualifier qualifier); -bool IsVaryingOut(TQualifier qualifier); -bool IsVarying(TQualifier qualifier); -bool IsGeometryShaderInput(GLenum shaderType, TQualifier qualifier); -InterpolationType GetInterpolationType(TQualifier qualifier); - -// Returns array brackets including size with outermost array size first, as specified in GLSL ES -// 3.10 section 4.1.9. -TString ArrayString(const TType &type); - -TString GetTypeName(const TType &type, ShHashFunction64 hashFunction, NameMap *nameMap); - -TType GetShaderVariableBasicType(const sh::ShaderVariable &var); - -bool IsBuiltinOutputVariable(TQualifier qualifier); -bool IsBuiltinFragmentInputVariable(TQualifier qualifier); -bool CanBeInvariantESSL1(TQualifier qualifier); -bool CanBeInvariantESSL3OrGreater(TQualifier qualifier); -bool IsOutputESSL(ShShaderOutput output); -bool IsOutputGLSL(ShShaderOutput output); -bool IsOutputHLSL(ShShaderOutput output); -bool IsOutputVulkan(ShShaderOutput output); -} // namespace sh - -#endif // COMPILER_TRANSLATOR_UTIL_H_ -- cgit v1.2.3