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