1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES 3.1 Module
3 * -------------------------------------------------
4 *
5 * Copyright 2018 The Android Open Source Project
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 *//*!
20 * \file
21 * \brief Built-in function tests for uniform constants.
22 *//*--------------------------------------------------------------------*/
23
24 #include "es31fShaderUniformIntegerFunctionTests.hpp"
25 #include "glsShaderExecUtil.hpp"
26 #include "glwFunctions.hpp"
27 #include "tcuTestLog.hpp"
28 #include <iostream>
29
30 namespace deqp
31 {
32 namespace gles31
33 {
34 namespace Functional
35 {
36
37 using std::string;
38 using std::vector;
39 using tcu::TestLog;
40 using namespace gls::ShaderExecUtil;
41
42 class UniformIntegerFunctionCase : public TestCase
43 {
44 public:
45 UniformIntegerFunctionCase(Context &context, const char *description, int inputValue, glu::Precision precision,
46 glu::ShaderType shaderType);
47 ~UniformIntegerFunctionCase(void);
48
49 void init(void);
50 void deinit(void);
51 IterateResult iterate(void);
52 virtual const char *getFunctionName() = 0;
53 virtual int computeExpectedResult(int32_t value) = 0;
54
55 protected:
56 UniformIntegerFunctionCase(const UniformIntegerFunctionCase &other);
57 UniformIntegerFunctionCase &operator=(const UniformIntegerFunctionCase &other);
58
59 private:
60 ShaderSpec m_spec;
61 glu::ShaderType m_shaderType;
62 int m_input;
63 int m_value;
64 ShaderExecutor *m_executor;
65 };
66
67 static std::string getCaseName(glu::Precision precision, glu::ShaderType shaderType);
68
UniformIntegerFunctionCase(Context & context,const char * description,int inputValue,glu::Precision precision,glu::ShaderType shaderType)69 UniformIntegerFunctionCase::UniformIntegerFunctionCase(Context &context, const char *description, int inputValue,
70 glu::Precision precision, glu::ShaderType shaderType)
71 : TestCase(context, getCaseName(precision, shaderType).c_str(), description)
72 , m_shaderType(shaderType)
73 , m_input(inputValue)
74 , m_value(0)
75 , m_executor(DE_NULL)
76 {
77 m_spec.version = glu::GLSL_VERSION_310_ES;
78
79 std::ostringstream oss;
80 glu::VarType varType(glu::TYPE_INT, precision);
81 oss << "uniform " << glu::declare(varType, "value", 0) << ";\n";
82 m_spec.globalDeclarations = oss.str();
83 m_spec.outputs.push_back(Symbol("result", glu::VarType(glu::TYPE_INT, glu::PRECISION_LOWP)));
84 m_spec.outputs.push_back(Symbol("comparison", glu::VarType(glu::TYPE_BOOL, glu::PRECISION_LAST)));
85 }
86
~UniformIntegerFunctionCase(void)87 UniformIntegerFunctionCase::~UniformIntegerFunctionCase(void)
88 {
89 UniformIntegerFunctionCase::deinit();
90 }
91
deinit(void)92 void UniformIntegerFunctionCase::deinit(void)
93 {
94 delete m_executor;
95 m_executor = DE_NULL;
96 }
97
init(void)98 void UniformIntegerFunctionCase::init(void)
99 {
100 std::ostringstream oss;
101 oss << "result = " << getFunctionName() << "(value);\n"
102 << "comparison = (" << getFunctionName() << "(value) == " << computeExpectedResult(m_input) << ");\n";
103 m_spec.source = oss.str();
104
105 DE_ASSERT(!m_executor);
106 m_executor = createExecutor(m_context.getRenderContext(), m_shaderType, m_spec);
107 m_testCtx.getLog() << m_executor;
108
109 if (!m_executor->isOk())
110 throw tcu::TestError("Compile failed");
111
112 m_value = m_context.getRenderContext().getFunctions().getUniformLocation(m_executor->getProgram(), "value");
113 }
114
iterate(void)115 tcu::TestNode::IterateResult UniformIntegerFunctionCase::iterate(void)
116 {
117 int32_t result;
118 int32_t comparison; // A bool in the shader, but we must use a 32-bit type to copy out into.
119 vector<void *> outputPointers(2);
120
121 outputPointers[0] = &result;
122 outputPointers[1] = &comparison;
123
124 m_executor->useProgram();
125 m_context.getRenderContext().getFunctions().uniform1i(m_value, m_input);
126 m_executor->execute(1, DE_NULL, &outputPointers[0]);
127
128 int expectedResult = computeExpectedResult(m_input);
129 if (result != expectedResult)
130 {
131 m_testCtx.getLog() << TestLog::Message << "ERROR: comparison failed for " << getFunctionName() << "(" << m_input
132 << ") == " << expectedResult << TestLog::EndMessage;
133 m_testCtx.getLog() << TestLog::Message << "input: " << m_input << TestLog::EndMessage;
134 m_testCtx.getLog() << TestLog::Message << "result: " << result << TestLog::EndMessage;
135 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Result comparison failed");
136 return STOP;
137 }
138 else if (!comparison)
139 {
140 m_testCtx.getLog() << TestLog::Message
141 << "ERROR: result is as expected, but not when use in condition statement ("
142 << getFunctionName() << "(" << m_input << ") == " << expectedResult << ") == true"
143 << TestLog::EndMessage;
144 m_testCtx.getLog() << TestLog::Message << "input:" << m_input << TestLog::EndMessage;
145 m_testCtx.getLog() << TestLog::Message << "result: " << result << TestLog::EndMessage;
146 m_testCtx.getLog() << TestLog::Message << "comparison: " << comparison << TestLog::EndMessage;
147 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Result comparison failed");
148 return STOP;
149 }
150 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
151 return STOP;
152 }
153
getCaseName(glu::Precision precision,glu::ShaderType shaderType)154 static std::string getCaseName(glu::Precision precision, glu::ShaderType shaderType)
155 {
156 return string(getPrecisionName(precision)) + getShaderTypePostfix(shaderType);
157 }
158
159 class FindMSBEdgeCase : public UniformIntegerFunctionCase
160 {
161 public:
FindMSBEdgeCase(Context & context,int inputValue,glu::Precision precision,glu::ShaderType shaderType)162 FindMSBEdgeCase(Context &context, int inputValue, glu::Precision precision, glu::ShaderType shaderType)
163 : UniformIntegerFunctionCase(context, "findMSB", inputValue, precision, shaderType)
164 {
165 }
166
167 protected:
getFunctionName()168 const char *getFunctionName()
169 {
170 return "findMSB";
171 }
172
computeExpectedResult(int32_t input)173 int computeExpectedResult(int32_t input)
174 {
175 return de::findMSB(input);
176 }
177 };
178
179 class FindLSBEdgeCase : public UniformIntegerFunctionCase
180 {
181 public:
FindLSBEdgeCase(Context & context,int inputValue,glu::Precision precision,glu::ShaderType shaderType)182 FindLSBEdgeCase(Context &context, int inputValue, glu::Precision precision, glu::ShaderType shaderType)
183 : UniformIntegerFunctionCase(context, "findLSB", inputValue, precision, shaderType)
184 {
185 }
186
187 protected:
getFunctionName()188 const char *getFunctionName()
189 {
190 return "findLSB";
191 }
192
computeExpectedResult(int32_t input)193 int computeExpectedResult(int32_t input)
194 {
195 return de::findLSB(input);
196 }
197 };
198
199 template <class TestClass>
addFunctionCases(TestCaseGroup * parent,const char * functionName,int input)200 static void addFunctionCases(TestCaseGroup *parent, const char *functionName, int input)
201 {
202 tcu::TestCaseGroup *group = new tcu::TestCaseGroup(parent->getTestContext(), functionName, functionName);
203 parent->addChild(group);
204 for (int prec = glu::PRECISION_LOWP; prec <= glu::PRECISION_HIGHP; prec++)
205 {
206 for (int shaderTypeNdx = 0; shaderTypeNdx < glu::SHADERTYPE_LAST; shaderTypeNdx++)
207 {
208 if (executorSupported(glu::ShaderType(shaderTypeNdx)))
209 {
210 group->addChild(
211 new TestClass(parent->getContext(), input, glu::Precision(prec), glu::ShaderType(shaderTypeNdx)));
212 }
213 }
214 }
215 }
216
ShaderUniformIntegerFunctionTests(Context & context)217 ShaderUniformIntegerFunctionTests::ShaderUniformIntegerFunctionTests(Context &context)
218 : TestCaseGroup(context, "uniform", "Function on uniform")
219 {
220 }
221
~ShaderUniformIntegerFunctionTests()222 ShaderUniformIntegerFunctionTests::~ShaderUniformIntegerFunctionTests()
223 {
224 }
init()225 void ShaderUniformIntegerFunctionTests::init()
226 {
227 addFunctionCases<FindMSBEdgeCase>(this, "findMSBZero", 0);
228 addFunctionCases<FindMSBEdgeCase>(this, "findMSBMinusOne", -1);
229 addFunctionCases<FindLSBEdgeCase>(this, "findLSBZero", 0);
230 addFunctionCases<FindLSBEdgeCase>(this, "findLSBMinusOne", -1);
231 }
232
233 } // namespace Functional
234 } // namespace gles31
235 } // namespace deqp
236