blob: bf89ddad1c56af283c75d20fae1035d38ad27685 [file] [log] [blame]
Shao11e43ec2016-08-11 09:54:08 +08001//
2// Copyright (c) 2016 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 texelFetchOffset translation issue workaround.
7// See header for more info.
8
9#include "compiler/translator/RewriteTexelFetchOffset.h"
10
11#include "common/angleutils.h"
12#include "compiler/translator/IntermNode.h"
13#include "compiler/translator/SymbolTable.h"
14
15namespace sh
16{
17
18namespace
19{
20
21class Traverser : public TIntermTraverser
22{
23 public:
24 static void Apply(TIntermNode *root,
Shao11e43ec2016-08-11 09:54:08 +080025 const TSymbolTable &symbolTable,
26 int shaderVersion);
27
28 private:
29 Traverser(const TSymbolTable &symbolTable, int shaderVersion);
30 bool visitAggregate(Visit visit, TIntermAggregate *node) override;
31 void nextIteration();
32
33 const TSymbolTable *symbolTable;
34 const int shaderVersion;
35 bool mFound = false;
36};
37
38Traverser::Traverser(const TSymbolTable &symbolTable, int shaderVersion)
39 : TIntermTraverser(true, false, false), symbolTable(&symbolTable), shaderVersion(shaderVersion)
40{
41}
42
43// static
44void Traverser::Apply(TIntermNode *root,
Shao11e43ec2016-08-11 09:54:08 +080045 const TSymbolTable &symbolTable,
46 int shaderVersion)
47{
48 Traverser traverser(symbolTable, shaderVersion);
Shao11e43ec2016-08-11 09:54:08 +080049 do
50 {
51 traverser.nextIteration();
52 root->traverse(&traverser);
53 if (traverser.mFound)
54 {
55 traverser.updateTree();
56 }
57 } while (traverser.mFound);
58}
59
60void Traverser::nextIteration()
61{
62 mFound = false;
Shao11e43ec2016-08-11 09:54:08 +080063}
64
65bool Traverser::visitAggregate(Visit visit, TIntermAggregate *node)
66{
67 if (mFound)
68 {
69 return false;
70 }
71
72 // Decide if the node represents the call of texelFetchOffset.
73 if (node->getOp() != EOpFunctionCall || node->isUserDefined())
74 {
75 return true;
76 }
77
78 if (node->getName().compare(0, 16, "texelFetchOffset") != 0)
79 {
80 return true;
81 }
82
83 // Potential problem case detected, apply workaround.
84 const TIntermSequence *sequence = node->getSequence();
85 ASSERT(sequence->size() == 4u);
Shao11e43ec2016-08-11 09:54:08 +080086
87 // Decide if there is a 2DArray sampler.
88 bool is2DArray = node->getName().find("s2a1") != TString::npos;
89
90 // Create new argument list from node->getName().
91 // e.g. Get "(is2a1;vi3;i1;" from "texelFetchOffset(is2a1;vi3;i1;vi2;"
92 TString newArgs = node->getName().substr(16, node->getName().length() - 20);
93 TString newName = "texelFetch" + newArgs;
94 TSymbol *texelFetchSymbol = symbolTable->findBuiltIn(newName, shaderVersion);
95 ASSERT(texelFetchSymbol);
96 int uniqueId = texelFetchSymbol->getUniqueId();
97
98 // Create new node that represents the call of function texelFetch.
Olli Etuaho6d40bbd2016-09-30 13:49:38 +010099 // Its argument list will be: texelFetch(sampler, Position+offset, lod).
Shao11e43ec2016-08-11 09:54:08 +0800100 TIntermAggregate *texelFetchNode = new TIntermAggregate(EOpFunctionCall);
101 texelFetchNode->setName(newName);
102 texelFetchNode->setFunctionId(uniqueId);
103 texelFetchNode->setType(node->getType());
104 texelFetchNode->setLine(node->getLine());
105
Shao11e43ec2016-08-11 09:54:08 +0800106 // sampler
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100107 texelFetchNode->getSequence()->push_back(sequence->at(0));
Shao11e43ec2016-08-11 09:54:08 +0800108
Shao11e43ec2016-08-11 09:54:08 +0800109 // Position
110 TIntermTyped *texCoordNode = sequence->at(1)->getAsTyped();
111 ASSERT(texCoordNode);
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100112
Shao11e43ec2016-08-11 09:54:08 +0800113 // offset
Olli Etuaho3272a6d2016-08-29 17:54:50 +0300114 TIntermTyped *offsetNode = nullptr;
Shao11e43ec2016-08-11 09:54:08 +0800115 ASSERT(sequence->at(3)->getAsTyped());
116 if (is2DArray)
117 {
118 // For 2DArray samplers, Position is ivec3 and offset is ivec2;
119 // So offset must be converted into an ivec3 before being added to Position.
120 TIntermAggregate *constructIVec3Node = new TIntermAggregate(EOpConstructIVec3);
121 constructIVec3Node->setLine(texCoordNode->getLine());
122 constructIVec3Node->setType(texCoordNode->getType());
123
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100124 constructIVec3Node->getSequence()->push_back(sequence->at(3)->getAsTyped());
Shao11e43ec2016-08-11 09:54:08 +0800125
126 TConstantUnion *zero = new TConstantUnion();
127 zero->setIConst(0);
128 TType *intType = new TType(EbtInt);
129
130 TIntermConstantUnion *zeroNode = new TIntermConstantUnion(zero, *intType);
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100131 constructIVec3Node->getSequence()->push_back(zeroNode);
Shao11e43ec2016-08-11 09:54:08 +0800132
Olli Etuaho3272a6d2016-08-29 17:54:50 +0300133 offsetNode = constructIVec3Node;
Shao11e43ec2016-08-11 09:54:08 +0800134 }
135 else
136 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +0300137 offsetNode = sequence->at(3)->getAsTyped();
Shao11e43ec2016-08-11 09:54:08 +0800138 }
Olli Etuaho3272a6d2016-08-29 17:54:50 +0300139
140 // Position+offset
141 TIntermBinary *add = new TIntermBinary(EOpAdd, texCoordNode, offsetNode);
142 add->setLine(texCoordNode->getLine());
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100143 texelFetchNode->getSequence()->push_back(add);
Shao11e43ec2016-08-11 09:54:08 +0800144
145 // lod
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100146 texelFetchNode->getSequence()->push_back(sequence->at(2));
147
148 ASSERT(texelFetchNode->getSequence()->size() == 3u);
Shao11e43ec2016-08-11 09:54:08 +0800149
150 // Replace the old node by this new node.
151 queueReplacement(node, texelFetchNode, OriginalNode::IS_DROPPED);
152 mFound = true;
153 return false;
154}
155
156} // anonymous namespace
157
158void RewriteTexelFetchOffset(TIntermNode *root,
Shao11e43ec2016-08-11 09:54:08 +0800159 const TSymbolTable &symbolTable,
160 int shaderVersion)
161{
162 // texelFetchOffset is only valid in GLSL 3.0 and later.
163 if (shaderVersion < 300)
164 return;
165
Jiawei-Shaof9795242016-09-21 15:19:00 +0800166 Traverser::Apply(root, symbolTable, shaderVersion);
Shao11e43ec2016-08-11 09:54:08 +0800167}
168
169} // namespace sh