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
7 #include "compiler/translator/tree_ops/ForcePrecisionQualifier.h"
8 #include "angle_gl.h"
9 #include "common/debug.h"
10 #include "compiler/translator/Compiler.h"
11 #include "compiler/translator/tree_util/IntermTraverse.h"
12 #include "compiler/translator/util.h"
13
14 namespace sh
15 {
16
17 namespace
18 {
19 class TPrecisionTraverser : public TIntermTraverser
20 {
21 public:
22 TPrecisionTraverser(TSymbolTable *symbolTable);
23
24 protected:
25 bool visitDeclaration(Visit visit, TIntermDeclaration *node) override;
26
27 void overwriteVariablePrecision(TType *type) const;
28 };
29
TPrecisionTraverser(TSymbolTable * symbolTable)30 TPrecisionTraverser::TPrecisionTraverser(TSymbolTable *symbolTable)
31 : TIntermTraverser(true, true, true, symbolTable)
32 {}
33
overwriteVariablePrecision(TType * type) const34 void TPrecisionTraverser::overwriteVariablePrecision(TType *type) const
35 {
36 if (type->getPrecision() == EbpHigh)
37 {
38 type->setPrecision(EbpMedium);
39 }
40 }
41
visitDeclaration(Visit visit,TIntermDeclaration * node)42 bool TPrecisionTraverser::visitDeclaration(Visit visit, TIntermDeclaration *node)
43 {
44 // Variable declaration.
45 if (visit == PreVisit)
46 {
47 const TIntermSequence &sequence = *(node->getSequence());
48 TIntermTyped *variable = sequence.front()->getAsTyped();
49 const TType &type = variable->getType();
50 TQualifier qualifier = variable->getQualifier();
51
52 // Don't modify uniform since it might be shared between vertex and fragment shader
53 if (qualifier == EvqUniform)
54 {
55 return true;
56 }
57
58 // Visit the struct.
59 if (type.isStructSpecifier())
60 {
61 const TStructure *structure = type.getStruct();
62 const TFieldList &fields = structure->fields();
63 for (size_t i = 0; i < fields.size(); ++i)
64 {
65 const TField *field = fields[i];
66 const TType *fieldType = field->type();
67 overwriteVariablePrecision((TType *)fieldType);
68 }
69 }
70 else if (type.getBasicType() == EbtInterfaceBlock)
71 {
72 const TInterfaceBlock *interfaceBlock = type.getInterfaceBlock();
73 const TFieldList &fields = interfaceBlock->fields();
74 for (const TField *field : fields)
75 {
76 const TType *fieldType = field->type();
77 overwriteVariablePrecision((TType *)fieldType);
78 }
79 }
80 else
81 {
82 overwriteVariablePrecision((TType *)&type);
83 }
84 }
85 return true;
86 }
87 } // namespace
88
ForceShaderPrecisionToMediump(TIntermNode * root,TSymbolTable * symbolTable,GLenum shaderType)89 bool ForceShaderPrecisionToMediump(TIntermNode *root, TSymbolTable *symbolTable, GLenum shaderType)
90 {
91 if (shaderType != GL_FRAGMENT_SHADER)
92 {
93 return true;
94 }
95
96 TPrecisionTraverser traverser(symbolTable);
97 root->traverse(&traverser);
98 return true;
99 }
100
101 } // namespace sh
102