1 //
2 // Copyright 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 // ShaderCompileTreeTest.cpp:
7 // Test that shader validation results in the correct compile status.
8 //
9
10 #include "tests/test_utils/ShaderCompileTreeTest.h"
11
12 #include "compiler/translator/TranslatorESSL.h"
13 #include "compiler/translator/tree_util/IntermTraverse.h"
14
15 namespace sh
16 {
17
18 namespace
19 {
20
21 // Checks that the node traversed is a zero node. It can be made out of multiple constructors and
22 // constant union nodes as long as there's no arithmetic involved and all constants are zero.
23 class OnlyContainsZeroConstantsTraverser final : public TIntermTraverser
24 {
25 public:
OnlyContainsZeroConstantsTraverser()26 OnlyContainsZeroConstantsTraverser()
27 : TIntermTraverser(true, false, false), mOnlyContainsConstantZeros(true)
28 {}
29
visitUnary(Visit,TIntermUnary * node)30 bool visitUnary(Visit, TIntermUnary *node) override
31 {
32 mOnlyContainsConstantZeros = false;
33 return false;
34 }
35
visitBinary(Visit,TIntermBinary * node)36 bool visitBinary(Visit, TIntermBinary *node) override
37 {
38 mOnlyContainsConstantZeros = false;
39 return false;
40 }
41
visitTernary(Visit,TIntermTernary * node)42 bool visitTernary(Visit, TIntermTernary *node) override
43 {
44 mOnlyContainsConstantZeros = false;
45 return false;
46 }
47
visitSwizzle(Visit,TIntermSwizzle * node)48 bool visitSwizzle(Visit, TIntermSwizzle *node) override
49 {
50 mOnlyContainsConstantZeros = false;
51 return false;
52 }
53
visitAggregate(Visit,TIntermAggregate * node)54 bool visitAggregate(Visit, TIntermAggregate *node) override
55 {
56 if (node->getOp() != EOpConstruct)
57 {
58 mOnlyContainsConstantZeros = false;
59 return false;
60 }
61 return true;
62 }
63
visitSymbol(TIntermSymbol * node)64 void visitSymbol(TIntermSymbol *node) override { mOnlyContainsConstantZeros = false; }
65
visitConstantUnion(TIntermConstantUnion * node)66 void visitConstantUnion(TIntermConstantUnion *node) override
67 {
68 if (!mOnlyContainsConstantZeros)
69 {
70 return;
71 }
72
73 const TType &type = node->getType();
74 size_t objectSize = type.getObjectSize();
75 for (size_t i = 0u; i < objectSize && mOnlyContainsConstantZeros; ++i)
76 {
77 bool isZero = false;
78 switch (type.getBasicType())
79 {
80 case EbtFloat:
81 isZero = (node->getFConst(i) == 0.0f);
82 break;
83 case EbtInt:
84 isZero = (node->getIConst(i) == 0);
85 break;
86 case EbtUInt:
87 isZero = (node->getUConst(i) == 0u);
88 break;
89 case EbtBool:
90 isZero = (node->getBConst(i) == false);
91 break;
92 default:
93 // Cannot handle.
94 break;
95 }
96 if (!isZero)
97 {
98 mOnlyContainsConstantZeros = false;
99 return;
100 }
101 }
102 }
103
onlyContainsConstantZeros() const104 bool onlyContainsConstantZeros() const { return mOnlyContainsConstantZeros; }
105
106 private:
107 bool mOnlyContainsConstantZeros;
108 };
109
110 } // anonymous namespace
111
SetUp()112 void ShaderCompileTreeTest::SetUp()
113 {
114 mAllocator.push();
115 SetGlobalPoolAllocator(&mAllocator);
116
117 ShBuiltInResources resources;
118 sh::InitBuiltInResources(&resources);
119
120 initResources(&resources);
121
122 mTranslator = new TranslatorESSL(getShaderType(), getShaderSpec());
123 ASSERT_TRUE(mTranslator->Init(resources));
124 }
125
TearDown()126 void ShaderCompileTreeTest::TearDown()
127 {
128 delete mTranslator;
129
130 SetGlobalPoolAllocator(nullptr);
131 mAllocator.pop();
132 }
133
compile(const std::string & shaderString)134 bool ShaderCompileTreeTest::compile(const std::string &shaderString)
135 {
136 const char *shaderStrings[] = {shaderString.c_str()};
137 mASTRoot = mTranslator->compileTreeForTesting(shaderStrings, 1, mExtraCompileOptions);
138 TInfoSink &infoSink = mTranslator->getInfoSink();
139 mInfoLog = infoSink.info.c_str();
140 return mASTRoot != nullptr;
141 }
142
compileAssumeSuccess(const std::string & shaderString)143 void ShaderCompileTreeTest::compileAssumeSuccess(const std::string &shaderString)
144 {
145 if (!compile(shaderString))
146 {
147 FAIL() << "Shader compilation into ESSL failed, log:\n" << mInfoLog;
148 }
149 }
150
hasWarning() const151 bool ShaderCompileTreeTest::hasWarning() const
152 {
153 return mInfoLog.find("WARNING: ") != std::string::npos;
154 }
155
getUniforms() const156 const std::vector<sh::ShaderVariable> &ShaderCompileTreeTest::getUniforms() const
157 {
158 ASSERT(mExtraCompileOptions & SH_VARIABLES);
159 return mTranslator->getUniforms();
160 }
161
getAttributes() const162 const std::vector<sh::ShaderVariable> &ShaderCompileTreeTest::getAttributes() const
163 {
164 ASSERT(mExtraCompileOptions & SH_VARIABLES);
165 return mTranslator->getAttributes();
166 }
167
IsZero(TIntermNode * node)168 bool IsZero(TIntermNode *node)
169 {
170 if (!node->getAsTyped())
171 {
172 return false;
173 }
174 OnlyContainsZeroConstantsTraverser traverser;
175 node->traverse(&traverser);
176 return traverser.onlyContainsConstantZeros();
177 }
178
179 } // namespace sh
180