• 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/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, 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     ShCompileOptions mCompileOptions;
34 
35     bool isBaseInstanceDeclared = false;
36 };
37 
TBuiltinsWorkaroundGLSL(TSymbolTable * symbolTable,ShCompileOptions options)38 TBuiltinsWorkaroundGLSL::TBuiltinsWorkaroundGLSL(TSymbolTable *symbolTable,
39                                                  ShCompileOptions options)
40     : TIntermTraverser(true, false, false, symbolTable), mCompileOptions(options)
41 {}
42 
visitSymbol(TIntermSymbol * node)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 
visitDeclaration(Visit,TIntermDeclaration * node)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 
ShaderBuiltinsWorkaround(TCompiler * compiler,TIntermBlock * root,TSymbolTable * symbolTable,ShCompileOptions compileOptions)95 ANGLE_NO_DISCARD bool ShaderBuiltinsWorkaround(TCompiler *compiler,
96                                                TIntermBlock *root,
97                                                TSymbolTable *symbolTable,
98                                                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
110