• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/StaticType.h"
11 #include "compiler/translator/Symbol.h"
12 #include "compiler/translator/SymbolTable.h"
13 #include "compiler/translator/tree_util/BuiltIn.h"
14 
15 namespace sh
16 {
17 
18 namespace
19 {
20 constexpr const ImmutableString kGlInstanceIDString("gl_InstanceID");
21 constexpr const ImmutableString kGlVertexIDString("gl_VertexID");
22 
23 class TBuiltinsWorkaroundGLSL : public TIntermTraverser
24 {
25   public:
26     TBuiltinsWorkaroundGLSL(TSymbolTable *symbolTable, ShCompileOptions options);
27 
28     void visitSymbol(TIntermSymbol *node) override;
29     bool visitDeclaration(Visit, TIntermDeclaration *node) override;
30 
31   private:
32     void ensureVersionIsAtLeast(int version);
33 
34     ShCompileOptions mCompileOptions;
35 
36     bool isBaseInstanceDeclared = false;
37     bool isBaseVertexDeclared   = false;
38 };
39 
TBuiltinsWorkaroundGLSL(TSymbolTable * symbolTable,ShCompileOptions options)40 TBuiltinsWorkaroundGLSL::TBuiltinsWorkaroundGLSL(TSymbolTable *symbolTable,
41                                                  ShCompileOptions options)
42     : TIntermTraverser(true, false, false, symbolTable), mCompileOptions(options)
43 {}
44 
visitSymbol(TIntermSymbol * node)45 void TBuiltinsWorkaroundGLSL::visitSymbol(TIntermSymbol *node)
46 {
47     if (node->variable().symbolType() == SymbolType::BuiltIn)
48     {
49         if (node->getName() == kGlInstanceIDString)
50         {
51             TIntermSymbol *instanceIndexRef =
52                 new TIntermSymbol(BuiltInVariable::gl_InstanceIndex());
53 
54             if (isBaseInstanceDeclared)
55             {
56                 TIntermSymbol *baseInstanceRef =
57                     new TIntermSymbol(BuiltInVariable::angle_BaseInstance());
58 
59                 TIntermBinary *subBaseInstance =
60                     new TIntermBinary(EOpSub, instanceIndexRef, baseInstanceRef);
61                 queueReplacement(subBaseInstance, OriginalNode::IS_DROPPED);
62             }
63             else
64             {
65                 queueReplacement(instanceIndexRef, OriginalNode::IS_DROPPED);
66             }
67         }
68         else if (node->getName() == kGlVertexIDString)
69         {
70             TIntermSymbol *vertexIndexRef = new TIntermSymbol(BuiltInVariable::gl_VertexIndex());
71             queueReplacement(vertexIndexRef, OriginalNode::IS_DROPPED);
72         }
73     }
74 }
75 
visitDeclaration(Visit,TIntermDeclaration * node)76 bool TBuiltinsWorkaroundGLSL::visitDeclaration(Visit, TIntermDeclaration *node)
77 {
78     const TIntermSequence &sequence = *(node->getSequence());
79     ASSERT(!sequence.empty());
80 
81     for (TIntermNode *variableNode : sequence)
82     {
83         TIntermSymbol *variable = variableNode->getAsSymbolNode();
84         if (variable && variable->variable().symbolType() == SymbolType::AngleInternal)
85         {
86             if (variable->getName() == "angle_BaseInstance")
87             {
88                 isBaseInstanceDeclared = true;
89             }
90         }
91     }
92     return true;
93 }
94 
95 }  // anonymous namespace
96 
ShaderBuiltinsWorkaround(TCompiler * compiler,TIntermBlock * root,TSymbolTable * symbolTable,ShCompileOptions compileOptions)97 ANGLE_NO_DISCARD bool ShaderBuiltinsWorkaround(TCompiler *compiler,
98                                                TIntermBlock *root,
99                                                TSymbolTable *symbolTable,
100                                                ShCompileOptions compileOptions)
101 {
102     TBuiltinsWorkaroundGLSL builtins(symbolTable, compileOptions);
103     root->traverse(&builtins);
104     if (!builtins.updateTree(compiler, root))
105     {
106         return false;
107     }
108     return true;
109 }
110 
111 }  // namespace sh
112