• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2020 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 // Implementation of InterpolateAtOffset viewport transformation.
7 // See header for more info.
8 
9 #include "compiler/translator/tree_ops/vulkan/RewriteInterpolateAtOffset.h"
10 
11 #include "common/angleutils.h"
12 #include "compiler/translator/StaticType.h"
13 #include "compiler/translator/SymbolTable.h"
14 #include "compiler/translator/TranslatorVulkan.h"
15 #include "compiler/translator/tree_util/DriverUniform.h"
16 #include "compiler/translator/tree_util/IntermNode_util.h"
17 #include "compiler/translator/tree_util/IntermTraverse.h"
18 #include "compiler/translator/tree_util/SpecializationConstant.h"
19 
20 namespace sh
21 {
22 
23 namespace
24 {
25 
26 class Traverser : public TIntermTraverser
27 {
28   public:
29     ANGLE_NO_DISCARD static bool Apply(TCompiler *compiler,
30                                        ShCompileOptions compileOptions,
31                                        TIntermNode *root,
32                                        const TSymbolTable &symbolTable,
33                                        int ShaderVersion,
34                                        SpecConst *specConst,
35                                        const DriverUniform *driverUniforms);
36 
37   private:
38     Traverser(TSymbolTable *symbolTable,
39               ShCompileOptions compileOptions,
40               int shaderVersion,
41               SpecConst *specConst,
42               const DriverUniform *driverUniforms);
43     bool visitAggregate(Visit visit, TIntermAggregate *node) override;
44 
45     const TSymbolTable *symbolTable = nullptr;
46     const int shaderVersion;
47     SpecConst *mRotationSpecConst        = nullptr;
48     const DriverUniform *mDriverUniforms = nullptr;
49     bool mUsePreRotation                 = false;
50 };
51 
Traverser(TSymbolTable * symbolTable,ShCompileOptions compileOptions,int shaderVersion,SpecConst * specConst,const DriverUniform * driverUniforms)52 Traverser::Traverser(TSymbolTable *symbolTable,
53                      ShCompileOptions compileOptions,
54                      int shaderVersion,
55                      SpecConst *specConst,
56                      const DriverUniform *driverUniforms)
57     : TIntermTraverser(true, false, false, symbolTable),
58       symbolTable(symbolTable),
59       shaderVersion(shaderVersion),
60       mRotationSpecConst(specConst),
61       mDriverUniforms(driverUniforms),
62       mUsePreRotation((compileOptions & SH_ADD_PRE_ROTATION) != 0)
63 {}
64 
65 // static
Apply(TCompiler * compiler,ShCompileOptions compileOptions,TIntermNode * root,const TSymbolTable & symbolTable,int shaderVersion,SpecConst * specConst,const DriverUniform * driverUniforms)66 bool Traverser::Apply(TCompiler *compiler,
67                       ShCompileOptions compileOptions,
68                       TIntermNode *root,
69                       const TSymbolTable &symbolTable,
70                       int shaderVersion,
71                       SpecConst *specConst,
72                       const DriverUniform *driverUniforms)
73 {
74     TSymbolTable *pSymbolTable = const_cast<TSymbolTable *>(&symbolTable);
75     Traverser traverser(pSymbolTable, compileOptions, shaderVersion, specConst, driverUniforms);
76     root->traverse(&traverser);
77     return traverser.updateTree(compiler, root);
78 }
79 
visitAggregate(Visit visit,TIntermAggregate * node)80 bool Traverser::visitAggregate(Visit visit, TIntermAggregate *node)
81 {
82     // Decide if the node represents the call of texelFetchOffset.
83     if (!BuiltInGroup::IsBuiltIn(node->getOp()))
84     {
85         return true;
86     }
87 
88     ASSERT(node->getFunction()->symbolType() == SymbolType::BuiltIn);
89     if (node->getFunction()->name() != "interpolateAtOffset")
90     {
91         return true;
92     }
93 
94     const TIntermSequence *sequence = node->getSequence();
95     ASSERT(sequence->size() == 2u);
96 
97     TIntermSequence interpolateAtOffsetArguments;
98     // interpolant node
99     interpolateAtOffsetArguments.push_back(sequence->at(0));
100     // offset
101     TIntermTyped *offsetNode = sequence->at(1)->getAsTyped();
102     ASSERT(offsetNode->getType() == *(StaticType::GetBasic<EbtFloat, 2>()));
103 
104     // If pre-rotation is enabled apply the transformation else just flip the Y-coordinate
105     TIntermTyped *rotatedXY;
106     if (mUsePreRotation)
107     {
108         rotatedXY = mRotationSpecConst->getFragRotationMultiplyFlipXY();
109         if (!rotatedXY)
110         {
111             TIntermTyped *flipXY       = mDriverUniforms->getFlipXYRef();
112             TIntermTyped *fragRotation = mDriverUniforms->getFragRotationMatrixRef();
113             rotatedXY = new TIntermBinary(EOpMatrixTimesVector, fragRotation, flipXY);
114         }
115     }
116     else
117     {
118         rotatedXY = mRotationSpecConst->getFlipXY();
119         if (!rotatedXY)
120         {
121             rotatedXY = mDriverUniforms->getFlipXYRef();
122         }
123     }
124 
125     TIntermBinary *correctedOffset = new TIntermBinary(EOpMul, offsetNode, rotatedXY);
126     correctedOffset->setLine(offsetNode->getLine());
127     interpolateAtOffsetArguments.push_back(correctedOffset);
128 
129     TIntermTyped *interpolateAtOffsetNode = CreateBuiltInFunctionCallNode(
130         "interpolateAtOffset", &interpolateAtOffsetArguments, *symbolTable, shaderVersion);
131     interpolateAtOffsetNode->setLine(node->getLine());
132 
133     // Replace the old node by this new node.
134     queueReplacement(interpolateAtOffsetNode, OriginalNode::IS_DROPPED);
135 
136     return true;
137 }
138 
139 }  // anonymous namespace
140 
RewriteInterpolateAtOffset(TCompiler * compiler,ShCompileOptions compileOptions,TIntermNode * root,const TSymbolTable & symbolTable,int shaderVersion,SpecConst * specConst,const DriverUniform * driverUniforms)141 bool RewriteInterpolateAtOffset(TCompiler *compiler,
142                                 ShCompileOptions compileOptions,
143                                 TIntermNode *root,
144                                 const TSymbolTable &symbolTable,
145                                 int shaderVersion,
146                                 SpecConst *specConst,
147                                 const DriverUniform *driverUniforms)
148 {
149     // interpolateAtOffset is only valid in GLSL 3.0 and later.
150     if (shaderVersion < 300)
151     {
152         return true;
153     }
154 
155     return Traverser::Apply(compiler, compileOptions, root, symbolTable, shaderVersion, specConst,
156                             driverUniforms);
157 }
158 
159 }  // namespace sh
160