diff options
Diffstat (limited to 'gfx/angle/checkout/src/compiler/translator/tree_ops/EmulateMultiDrawShaderBuiltins.cpp')
-rw-r--r-- | gfx/angle/checkout/src/compiler/translator/tree_ops/EmulateMultiDrawShaderBuiltins.cpp | 274 |
1 files changed, 274 insertions, 0 deletions
diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/EmulateMultiDrawShaderBuiltins.cpp b/gfx/angle/checkout/src/compiler/translator/tree_ops/EmulateMultiDrawShaderBuiltins.cpp new file mode 100644 index 0000000000..dfa36ad145 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/EmulateMultiDrawShaderBuiltins.cpp @@ -0,0 +1,274 @@ +// +// Copyright 2019 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. +// +// EmulateGLDrawID is an AST traverser to convert the gl_DrawID builtin +// to a uniform int +// +// EmulateGLBaseVertex is an AST traverser to convert the gl_BaseVertex builtin +// to a uniform int +// +// EmulateGLBaseInstance is an AST traverser to convert the gl_BaseInstance builtin +// to a uniform int +// + +#include "compiler/translator/tree_ops/EmulateMultiDrawShaderBuiltins.h" + +#include "angle_gl.h" +#include "compiler/translator/StaticType.h" +#include "compiler/translator/Symbol.h" +#include "compiler/translator/SymbolTable.h" +#include "compiler/translator/tree_util/BuiltIn.h" +#include "compiler/translator/tree_util/IntermTraverse.h" +#include "compiler/translator/tree_util/ReplaceVariable.h" +#include "compiler/translator/util.h" + +namespace sh +{ + +namespace +{ + +constexpr const ImmutableString kEmulatedGLDrawIDName("angle_DrawID"); + +class FindGLDrawIDTraverser : public TIntermTraverser +{ + public: + FindGLDrawIDTraverser() : TIntermTraverser(true, false, false), mVariable(nullptr) {} + + const TVariable *getGLDrawIDBuiltinVariable() { return mVariable; } + + protected: + void visitSymbol(TIntermSymbol *node) override + { + if (&node->variable() == BuiltInVariable::gl_DrawID()) + { + mVariable = &node->variable(); + } + } + + private: + const TVariable *mVariable; +}; + +class AddBaseVertexToGLVertexIDTraverser : public TIntermTraverser +{ + public: + AddBaseVertexToGLVertexIDTraverser() : TIntermTraverser(true, false, false) {} + + protected: + void visitSymbol(TIntermSymbol *node) override + { + if (&node->variable() == BuiltInVariable::gl_VertexID()) + { + + TIntermSymbol *baseVertexRef = new TIntermSymbol(BuiltInVariable::gl_BaseVertex()); + + TIntermBinary *addBaseVertex = new TIntermBinary(EOpAdd, node, baseVertexRef); + queueReplacement(addBaseVertex, OriginalNode::BECOMES_CHILD); + } + } +}; + +constexpr const ImmutableString kEmulatedGLBaseVertexName("angle_BaseVertex"); + +class FindGLBaseVertexTraverser : public TIntermTraverser +{ + public: + FindGLBaseVertexTraverser() : TIntermTraverser(true, false, false), mVariable(nullptr) {} + + const TVariable *getGLBaseVertexBuiltinVariable() { return mVariable; } + + protected: + void visitSymbol(TIntermSymbol *node) override + { + if (&node->variable() == BuiltInVariable::gl_BaseVertex()) + { + mVariable = &node->variable(); + } + } + + private: + const TVariable *mVariable; +}; + +constexpr const ImmutableString kEmulatedGLBaseInstanceName("angle_BaseInstance"); + +class FindGLBaseInstanceTraverser : public TIntermTraverser +{ + public: + FindGLBaseInstanceTraverser() : TIntermTraverser(true, false, false), mVariable(nullptr) {} + + const TVariable *getGLBaseInstanceBuiltinVariable() { return mVariable; } + + protected: + void visitSymbol(TIntermSymbol *node) override + { + if (&node->variable() == BuiltInVariable::gl_BaseInstance()) + { + mVariable = &node->variable(); + } + } + + private: + const TVariable *mVariable; +}; + +} // namespace + +bool EmulateGLDrawID(TCompiler *compiler, + TIntermBlock *root, + TSymbolTable *symbolTable, + std::vector<sh::ShaderVariable> *uniforms, + bool shouldCollect) +{ + FindGLDrawIDTraverser traverser; + root->traverse(&traverser); + const TVariable *builtInVariable = traverser.getGLDrawIDBuiltinVariable(); + if (builtInVariable) + { + const TType *type = StaticType::Get<EbtInt, EbpHigh, EvqUniform, 1, 1>(); + const TVariable *drawID = + new TVariable(symbolTable, kEmulatedGLDrawIDName, type, SymbolType::AngleInternal); + const TIntermSymbol *drawIDSymbol = new TIntermSymbol(drawID); + + // AngleInternal variables don't get collected + if (shouldCollect) + { + ShaderVariable uniform; + uniform.name = kEmulatedGLDrawIDName.data(); + uniform.mappedName = kEmulatedGLDrawIDName.data(); + uniform.type = GLVariableType(*type); + uniform.precision = GLVariablePrecision(*type); + uniform.staticUse = symbolTable->isStaticallyUsed(*builtInVariable); + uniform.active = true; + uniform.binding = type->getLayoutQualifier().binding; + uniform.location = type->getLayoutQualifier().location; + uniform.offset = type->getLayoutQualifier().offset; + uniform.rasterOrdered = type->getLayoutQualifier().rasterOrdered; + uniform.readonly = type->getMemoryQualifier().readonly; + uniform.writeonly = type->getMemoryQualifier().writeonly; + uniforms->push_back(uniform); + } + + DeclareGlobalVariable(root, drawID); + if (!ReplaceVariableWithTyped(compiler, root, builtInVariable, drawIDSymbol)) + { + return false; + } + } + + return true; +} + +bool EmulateGLBaseVertexBaseInstance(TCompiler *compiler, + TIntermBlock *root, + TSymbolTable *symbolTable, + std::vector<sh::ShaderVariable> *uniforms, + bool shouldCollect, + bool addBaseVertexToVertexID) +{ + bool addBaseVertex = false, addBaseInstance = false; + ShaderVariable uniformBaseVertex, uniformBaseInstance; + + if (addBaseVertexToVertexID) + { + // This is a workaround for Mac AMD GPU + // Replace gl_VertexID with (gl_VertexID + gl_BaseVertex) + AddBaseVertexToGLVertexIDTraverser traverserVertexID; + root->traverse(&traverserVertexID); + if (!traverserVertexID.updateTree(compiler, root)) + { + return false; + } + } + + FindGLBaseVertexTraverser traverserBaseVertex; + root->traverse(&traverserBaseVertex); + const TVariable *builtInVariableBaseVertex = + traverserBaseVertex.getGLBaseVertexBuiltinVariable(); + + if (builtInVariableBaseVertex) + { + const TVariable *baseVertex = BuiltInVariable::angle_BaseVertex(); + const TType &type = baseVertex->getType(); + const TIntermSymbol *baseVertexSymbol = new TIntermSymbol(baseVertex); + + // AngleInternal variables don't get collected + if (shouldCollect) + { + uniformBaseVertex.name = kEmulatedGLBaseVertexName.data(); + uniformBaseVertex.mappedName = kEmulatedGLBaseVertexName.data(); + uniformBaseVertex.type = GLVariableType(type); + uniformBaseVertex.precision = GLVariablePrecision(type); + uniformBaseVertex.staticUse = symbolTable->isStaticallyUsed(*builtInVariableBaseVertex); + uniformBaseVertex.active = true; + uniformBaseVertex.binding = type.getLayoutQualifier().binding; + uniformBaseVertex.location = type.getLayoutQualifier().location; + uniformBaseVertex.offset = type.getLayoutQualifier().offset; + uniformBaseVertex.rasterOrdered = type.getLayoutQualifier().rasterOrdered; + uniformBaseVertex.readonly = type.getMemoryQualifier().readonly; + uniformBaseVertex.writeonly = type.getMemoryQualifier().writeonly; + addBaseVertex = true; + } + + DeclareGlobalVariable(root, baseVertex); + if (!ReplaceVariableWithTyped(compiler, root, builtInVariableBaseVertex, baseVertexSymbol)) + { + return false; + } + } + + FindGLBaseInstanceTraverser traverserInstance; + root->traverse(&traverserInstance); + const TVariable *builtInVariableBaseInstance = + traverserInstance.getGLBaseInstanceBuiltinVariable(); + + if (builtInVariableBaseInstance) + { + const TVariable *baseInstance = BuiltInVariable::angle_BaseInstance(); + const TType &type = baseInstance->getType(); + const TIntermSymbol *baseInstanceSymbol = new TIntermSymbol(baseInstance); + + // AngleInternal variables don't get collected + if (shouldCollect) + { + uniformBaseInstance.name = kEmulatedGLBaseInstanceName.data(); + uniformBaseInstance.mappedName = kEmulatedGLBaseInstanceName.data(); + uniformBaseInstance.type = GLVariableType(type); + uniformBaseInstance.precision = GLVariablePrecision(type); + uniformBaseInstance.staticUse = + symbolTable->isStaticallyUsed(*builtInVariableBaseInstance); + uniformBaseInstance.active = true; + uniformBaseInstance.binding = type.getLayoutQualifier().binding; + uniformBaseInstance.location = type.getLayoutQualifier().location; + uniformBaseInstance.offset = type.getLayoutQualifier().offset; + uniformBaseInstance.rasterOrdered = type.getLayoutQualifier().rasterOrdered; + uniformBaseInstance.readonly = type.getMemoryQualifier().readonly; + uniformBaseInstance.writeonly = type.getMemoryQualifier().writeonly; + addBaseInstance = true; + } + + DeclareGlobalVariable(root, baseInstance); + if (!ReplaceVariableWithTyped(compiler, root, builtInVariableBaseInstance, + baseInstanceSymbol)) + { + return false; + } + } + + // Make sure the order in uniforms is the same as the traverse order + if (addBaseInstance) + { + uniforms->push_back(uniformBaseInstance); + } + if (addBaseVertex) + { + uniforms->push_back(uniformBaseVertex); + } + + return true; +} + +} // namespace sh |