BuiltinsWorkaroundGLSL.cpp (3426B)
1 // 2 // Copyright 2019 The ANGLE Project Authors. All rights reserved. 3 // Use of this source code is governed by a BSD-style license that can be 4 // found in the LICENSE file. 5 // 6 7 #include "compiler/translator/BuiltinsWorkaroundGLSL.h" 8 9 #include "angle_gl.h" 10 #include "compiler/translator/Symbol.h" 11 #include "compiler/translator/SymbolTable.h" 12 #include "compiler/translator/tree_util/BuiltIn.h" 13 14 namespace sh 15 { 16 17 namespace 18 { 19 constexpr const ImmutableString kGlInstanceIDString("gl_InstanceID"); 20 constexpr const ImmutableString kGlVertexIDString("gl_VertexID"); 21 22 class TBuiltinsWorkaroundGLSL : public TIntermTraverser 23 { 24 public: 25 TBuiltinsWorkaroundGLSL(TSymbolTable *symbolTable, const ShCompileOptions &options); 26 27 void visitSymbol(TIntermSymbol *node) override; 28 bool visitDeclaration(Visit, TIntermDeclaration *node) override; 29 30 private: 31 void ensureVersionIsAtLeast(int version); 32 33 const ShCompileOptions &mCompileOptions; 34 35 bool isBaseInstanceDeclared = false; 36 }; 37 38 TBuiltinsWorkaroundGLSL::TBuiltinsWorkaroundGLSL(TSymbolTable *symbolTable, 39 const ShCompileOptions &options) 40 : TIntermTraverser(true, false, false, symbolTable), mCompileOptions(options) 41 {} 42 43 void TBuiltinsWorkaroundGLSL::visitSymbol(TIntermSymbol *node) 44 { 45 if (node->variable().symbolType() == SymbolType::BuiltIn) 46 { 47 if (node->getName() == kGlInstanceIDString) 48 { 49 TIntermSymbol *instanceIndexRef = 50 new TIntermSymbol(BuiltInVariable::gl_InstanceIndex()); 51 52 if (isBaseInstanceDeclared) 53 { 54 TIntermSymbol *baseInstanceRef = 55 new TIntermSymbol(BuiltInVariable::angle_BaseInstance()); 56 57 TIntermBinary *subBaseInstance = 58 new TIntermBinary(EOpSub, instanceIndexRef, baseInstanceRef); 59 queueReplacement(subBaseInstance, OriginalNode::IS_DROPPED); 60 } 61 else 62 { 63 queueReplacement(instanceIndexRef, OriginalNode::IS_DROPPED); 64 } 65 } 66 else if (node->getName() == kGlVertexIDString) 67 { 68 TIntermSymbol *vertexIndexRef = new TIntermSymbol(BuiltInVariable::gl_VertexIndex()); 69 queueReplacement(vertexIndexRef, OriginalNode::IS_DROPPED); 70 } 71 } 72 } 73 74 bool TBuiltinsWorkaroundGLSL::visitDeclaration(Visit, TIntermDeclaration *node) 75 { 76 const TIntermSequence &sequence = *(node->getSequence()); 77 ASSERT(!sequence.empty()); 78 79 for (TIntermNode *variableNode : sequence) 80 { 81 TIntermSymbol *variable = variableNode->getAsSymbolNode(); 82 if (variable && variable->variable().symbolType() == SymbolType::BuiltIn) 83 { 84 if (variable->getName() == "angle_BaseInstance") 85 { 86 isBaseInstanceDeclared = true; 87 } 88 } 89 } 90 return true; 91 } 92 93 } // anonymous namespace 94 95 [[nodiscard]] bool ShaderBuiltinsWorkaround(TCompiler *compiler, 96 TIntermBlock *root, 97 TSymbolTable *symbolTable, 98 const ShCompileOptions &compileOptions) 99 { 100 TBuiltinsWorkaroundGLSL builtins(symbolTable, compileOptions); 101 root->traverse(&builtins); 102 if (!builtins.updateTree(compiler, root)) 103 { 104 return false; 105 } 106 return true; 107 } 108 109 } // namespace sh