xref: /aosp_15_r20/external/deqp/modules/gles31/functional/es31fShaderIntegerFunctionTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1*35238bceSAndroid Build Coastguard Worker /*-------------------------------------------------------------------------
2*35238bceSAndroid Build Coastguard Worker  * drawElements Quality Program OpenGL ES 3.1 Module
3*35238bceSAndroid Build Coastguard Worker  * -------------------------------------------------
4*35238bceSAndroid Build Coastguard Worker  *
5*35238bceSAndroid Build Coastguard Worker  * Copyright 2014 The Android Open Source Project
6*35238bceSAndroid Build Coastguard Worker  *
7*35238bceSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
8*35238bceSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
9*35238bceSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
10*35238bceSAndroid Build Coastguard Worker  *
11*35238bceSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
12*35238bceSAndroid Build Coastguard Worker  *
13*35238bceSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
14*35238bceSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
15*35238bceSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16*35238bceSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
17*35238bceSAndroid Build Coastguard Worker  * limitations under the License.
18*35238bceSAndroid Build Coastguard Worker  *
19*35238bceSAndroid Build Coastguard Worker  *//*!
20*35238bceSAndroid Build Coastguard Worker  * \file
21*35238bceSAndroid Build Coastguard Worker  * \brief Integer built-in function tests.
22*35238bceSAndroid Build Coastguard Worker  *//*--------------------------------------------------------------------*/
23*35238bceSAndroid Build Coastguard Worker 
24*35238bceSAndroid Build Coastguard Worker #include "es31fShaderIntegerFunctionTests.hpp"
25*35238bceSAndroid Build Coastguard Worker #include "glsShaderExecUtil.hpp"
26*35238bceSAndroid Build Coastguard Worker #include "tcuTestLog.hpp"
27*35238bceSAndroid Build Coastguard Worker #include "tcuFormatUtil.hpp"
28*35238bceSAndroid Build Coastguard Worker #include "tcuFloat.hpp"
29*35238bceSAndroid Build Coastguard Worker #include "deRandom.hpp"
30*35238bceSAndroid Build Coastguard Worker #include "deMath.h"
31*35238bceSAndroid Build Coastguard Worker #include "deString.h"
32*35238bceSAndroid Build Coastguard Worker #include "deDefs.hpp"
33*35238bceSAndroid Build Coastguard Worker 
34*35238bceSAndroid Build Coastguard Worker namespace deqp
35*35238bceSAndroid Build Coastguard Worker {
36*35238bceSAndroid Build Coastguard Worker namespace gles31
37*35238bceSAndroid Build Coastguard Worker {
38*35238bceSAndroid Build Coastguard Worker namespace Functional
39*35238bceSAndroid Build Coastguard Worker {
40*35238bceSAndroid Build Coastguard Worker 
41*35238bceSAndroid Build Coastguard Worker using std::string;
42*35238bceSAndroid Build Coastguard Worker using std::vector;
43*35238bceSAndroid Build Coastguard Worker using tcu::TestLog;
44*35238bceSAndroid Build Coastguard Worker using namespace gls::ShaderExecUtil;
45*35238bceSAndroid Build Coastguard Worker 
46*35238bceSAndroid Build Coastguard Worker using tcu::IVec2;
47*35238bceSAndroid Build Coastguard Worker using tcu::IVec3;
48*35238bceSAndroid Build Coastguard Worker using tcu::IVec4;
49*35238bceSAndroid Build Coastguard Worker using tcu::UVec2;
50*35238bceSAndroid Build Coastguard Worker using tcu::UVec3;
51*35238bceSAndroid Build Coastguard Worker using tcu::UVec4;
52*35238bceSAndroid Build Coastguard Worker 
53*35238bceSAndroid Build Coastguard Worker // Utilities
54*35238bceSAndroid Build Coastguard Worker 
55*35238bceSAndroid Build Coastguard Worker namespace
56*35238bceSAndroid Build Coastguard Worker {
57*35238bceSAndroid Build Coastguard Worker 
58*35238bceSAndroid Build Coastguard Worker struct HexFloat
59*35238bceSAndroid Build Coastguard Worker {
60*35238bceSAndroid Build Coastguard Worker     const float value;
HexFloatdeqp::gles31::Functional::__anon94d887390111::HexFloat61*35238bceSAndroid Build Coastguard Worker     HexFloat(const float value_) : value(value_)
62*35238bceSAndroid Build Coastguard Worker     {
63*35238bceSAndroid Build Coastguard Worker     }
64*35238bceSAndroid Build Coastguard Worker };
65*35238bceSAndroid Build Coastguard Worker 
operator <<(std::ostream & str,const HexFloat & v)66*35238bceSAndroid Build Coastguard Worker std::ostream &operator<<(std::ostream &str, const HexFloat &v)
67*35238bceSAndroid Build Coastguard Worker {
68*35238bceSAndroid Build Coastguard Worker     return str << v.value << " / " << tcu::toHex(tcu::Float32(v.value).bits());
69*35238bceSAndroid Build Coastguard Worker }
70*35238bceSAndroid Build Coastguard Worker 
71*35238bceSAndroid Build Coastguard Worker struct VarValue
72*35238bceSAndroid Build Coastguard Worker {
73*35238bceSAndroid Build Coastguard Worker     const glu::VarType &type;
74*35238bceSAndroid Build Coastguard Worker     const void *value;
75*35238bceSAndroid Build Coastguard Worker 
VarValuedeqp::gles31::Functional::__anon94d887390111::VarValue76*35238bceSAndroid Build Coastguard Worker     VarValue(const glu::VarType &type_, const void *value_) : type(type_), value(value_)
77*35238bceSAndroid Build Coastguard Worker     {
78*35238bceSAndroid Build Coastguard Worker     }
79*35238bceSAndroid Build Coastguard Worker };
80*35238bceSAndroid Build Coastguard Worker 
operator <<(std::ostream & str,const VarValue & varValue)81*35238bceSAndroid Build Coastguard Worker std::ostream &operator<<(std::ostream &str, const VarValue &varValue)
82*35238bceSAndroid Build Coastguard Worker {
83*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(varValue.type.isBasicType());
84*35238bceSAndroid Build Coastguard Worker 
85*35238bceSAndroid Build Coastguard Worker     const glu::DataType basicType  = varValue.type.getBasicType();
86*35238bceSAndroid Build Coastguard Worker     const glu::DataType scalarType = glu::getDataTypeScalarType(basicType);
87*35238bceSAndroid Build Coastguard Worker     const int numComponents        = glu::getDataTypeScalarSize(basicType);
88*35238bceSAndroid Build Coastguard Worker 
89*35238bceSAndroid Build Coastguard Worker     if (numComponents > 1)
90*35238bceSAndroid Build Coastguard Worker         str << glu::getDataTypeName(basicType) << "(";
91*35238bceSAndroid Build Coastguard Worker 
92*35238bceSAndroid Build Coastguard Worker     for (int compNdx = 0; compNdx < numComponents; compNdx++)
93*35238bceSAndroid Build Coastguard Worker     {
94*35238bceSAndroid Build Coastguard Worker         if (compNdx != 0)
95*35238bceSAndroid Build Coastguard Worker             str << ", ";
96*35238bceSAndroid Build Coastguard Worker 
97*35238bceSAndroid Build Coastguard Worker         switch (scalarType)
98*35238bceSAndroid Build Coastguard Worker         {
99*35238bceSAndroid Build Coastguard Worker         case glu::TYPE_FLOAT:
100*35238bceSAndroid Build Coastguard Worker             str << HexFloat(((const float *)varValue.value)[compNdx]);
101*35238bceSAndroid Build Coastguard Worker             break;
102*35238bceSAndroid Build Coastguard Worker         case glu::TYPE_INT:
103*35238bceSAndroid Build Coastguard Worker             str << ((const int32_t *)varValue.value)[compNdx];
104*35238bceSAndroid Build Coastguard Worker             break;
105*35238bceSAndroid Build Coastguard Worker         case glu::TYPE_UINT:
106*35238bceSAndroid Build Coastguard Worker             str << tcu::toHex(((const uint32_t *)varValue.value)[compNdx]);
107*35238bceSAndroid Build Coastguard Worker             break;
108*35238bceSAndroid Build Coastguard Worker         case glu::TYPE_BOOL:
109*35238bceSAndroid Build Coastguard Worker             str << (((const uint32_t *)varValue.value)[compNdx] != 0 ? "true" : "false");
110*35238bceSAndroid Build Coastguard Worker             break;
111*35238bceSAndroid Build Coastguard Worker 
112*35238bceSAndroid Build Coastguard Worker         default:
113*35238bceSAndroid Build Coastguard Worker             DE_ASSERT(false);
114*35238bceSAndroid Build Coastguard Worker         }
115*35238bceSAndroid Build Coastguard Worker     }
116*35238bceSAndroid Build Coastguard Worker 
117*35238bceSAndroid Build Coastguard Worker     if (numComponents > 1)
118*35238bceSAndroid Build Coastguard Worker         str << ")";
119*35238bceSAndroid Build Coastguard Worker 
120*35238bceSAndroid Build Coastguard Worker     return str;
121*35238bceSAndroid Build Coastguard Worker }
122*35238bceSAndroid Build Coastguard Worker 
getShaderUintBitCount(glu::ShaderType shaderType,glu::Precision precision)123*35238bceSAndroid Build Coastguard Worker inline int getShaderUintBitCount(glu::ShaderType shaderType, glu::Precision precision)
124*35238bceSAndroid Build Coastguard Worker {
125*35238bceSAndroid Build Coastguard Worker     // \todo [2013-10-31 pyry] Query from GL for vertex and fragment shaders.
126*35238bceSAndroid Build Coastguard Worker     DE_UNREF(shaderType);
127*35238bceSAndroid Build Coastguard Worker     const int bitCounts[] = {9, 16, 32};
128*35238bceSAndroid Build Coastguard Worker     DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(bitCounts) == glu::PRECISION_LAST);
129*35238bceSAndroid Build Coastguard Worker     return bitCounts[precision];
130*35238bceSAndroid Build Coastguard Worker }
131*35238bceSAndroid Build Coastguard Worker 
extendSignTo32(uint32_t integer,uint32_t integerLength)132*35238bceSAndroid Build Coastguard Worker static inline uint32_t extendSignTo32(uint32_t integer, uint32_t integerLength)
133*35238bceSAndroid Build Coastguard Worker {
134*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(integerLength > 0 && integerLength <= 32);
135*35238bceSAndroid Build Coastguard Worker 
136*35238bceSAndroid Build Coastguard Worker     return uint32_t(0 - int32_t((integer & (1 << (integerLength - 1))) << 1)) | integer;
137*35238bceSAndroid Build Coastguard Worker }
138*35238bceSAndroid Build Coastguard Worker 
getLowBitMask(int integerLength)139*35238bceSAndroid Build Coastguard Worker static inline uint32_t getLowBitMask(int integerLength)
140*35238bceSAndroid Build Coastguard Worker {
141*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(integerLength >= 0 && integerLength <= 32);
142*35238bceSAndroid Build Coastguard Worker 
143*35238bceSAndroid Build Coastguard Worker     // \note: shifting more or equal to 32 => undefined behavior. Avoid it by shifting in two parts (1 << (num-1) << 1)
144*35238bceSAndroid Build Coastguard Worker     if (integerLength == 0u)
145*35238bceSAndroid Build Coastguard Worker         return 0u;
146*35238bceSAndroid Build Coastguard Worker     return ((1u << ((uint32_t)integerLength - 1u)) << 1u) - 1u;
147*35238bceSAndroid Build Coastguard Worker }
148*35238bceSAndroid Build Coastguard Worker 
generateRandomInputData(de::Random & rnd,glu::ShaderType shaderType,glu::DataType dataType,glu::Precision precision,uint32_t * dst,int numValues)149*35238bceSAndroid Build Coastguard Worker static void generateRandomInputData(de::Random &rnd, glu::ShaderType shaderType, glu::DataType dataType,
150*35238bceSAndroid Build Coastguard Worker                                     glu::Precision precision, uint32_t *dst, int numValues)
151*35238bceSAndroid Build Coastguard Worker {
152*35238bceSAndroid Build Coastguard Worker     const int scalarSize         = glu::getDataTypeScalarSize(dataType);
153*35238bceSAndroid Build Coastguard Worker     const uint32_t integerLength = (uint32_t)getShaderUintBitCount(shaderType, precision);
154*35238bceSAndroid Build Coastguard Worker     const uint32_t integerMask   = getLowBitMask(integerLength);
155*35238bceSAndroid Build Coastguard Worker     const bool isUnsigned        = glu::isDataTypeUintOrUVec(dataType);
156*35238bceSAndroid Build Coastguard Worker 
157*35238bceSAndroid Build Coastguard Worker     if (isUnsigned)
158*35238bceSAndroid Build Coastguard Worker     {
159*35238bceSAndroid Build Coastguard Worker         for (int valueNdx = 0; valueNdx < numValues; ++valueNdx)
160*35238bceSAndroid Build Coastguard Worker             for (int compNdx = 0; compNdx < scalarSize; compNdx++)
161*35238bceSAndroid Build Coastguard Worker                 dst[valueNdx * scalarSize + compNdx] = rnd.getUint32() & integerMask;
162*35238bceSAndroid Build Coastguard Worker     }
163*35238bceSAndroid Build Coastguard Worker     else
164*35238bceSAndroid Build Coastguard Worker     {
165*35238bceSAndroid Build Coastguard Worker         for (int valueNdx = 0; valueNdx < numValues; ++valueNdx)
166*35238bceSAndroid Build Coastguard Worker             for (int compNdx = 0; compNdx < scalarSize; compNdx++)
167*35238bceSAndroid Build Coastguard Worker                 dst[valueNdx * scalarSize + compNdx] = extendSignTo32(rnd.getUint32() & integerMask, integerLength);
168*35238bceSAndroid Build Coastguard Worker     }
169*35238bceSAndroid Build Coastguard Worker }
170*35238bceSAndroid Build Coastguard Worker 
171*35238bceSAndroid Build Coastguard Worker } // namespace
172*35238bceSAndroid Build Coastguard Worker 
173*35238bceSAndroid Build Coastguard Worker // IntegerFunctionCase
174*35238bceSAndroid Build Coastguard Worker 
175*35238bceSAndroid Build Coastguard Worker class IntegerFunctionCase : public TestCase
176*35238bceSAndroid Build Coastguard Worker {
177*35238bceSAndroid Build Coastguard Worker public:
178*35238bceSAndroid Build Coastguard Worker     IntegerFunctionCase(Context &context, const char *name, const char *description, glu::ShaderType shaderType);
179*35238bceSAndroid Build Coastguard Worker     ~IntegerFunctionCase(void);
180*35238bceSAndroid Build Coastguard Worker 
181*35238bceSAndroid Build Coastguard Worker     void init(void);
182*35238bceSAndroid Build Coastguard Worker     void deinit(void);
183*35238bceSAndroid Build Coastguard Worker     IterateResult iterate(void);
184*35238bceSAndroid Build Coastguard Worker 
185*35238bceSAndroid Build Coastguard Worker protected:
186*35238bceSAndroid Build Coastguard Worker     IntegerFunctionCase(const IntegerFunctionCase &other);
187*35238bceSAndroid Build Coastguard Worker     IntegerFunctionCase &operator=(const IntegerFunctionCase &other);
188*35238bceSAndroid Build Coastguard Worker 
189*35238bceSAndroid Build Coastguard Worker     virtual void getInputValues(int numValues, void *const *values) const       = 0;
190*35238bceSAndroid Build Coastguard Worker     virtual bool compare(const void *const *inputs, const void *const *outputs) = 0;
191*35238bceSAndroid Build Coastguard Worker 
192*35238bceSAndroid Build Coastguard Worker     glu::ShaderType m_shaderType;
193*35238bceSAndroid Build Coastguard Worker     ShaderSpec m_spec;
194*35238bceSAndroid Build Coastguard Worker     int m_numValues;
195*35238bceSAndroid Build Coastguard Worker 
196*35238bceSAndroid Build Coastguard Worker     std::ostringstream m_failMsg; //!< Comparison failure help message.
197*35238bceSAndroid Build Coastguard Worker 
198*35238bceSAndroid Build Coastguard Worker private:
199*35238bceSAndroid Build Coastguard Worker     ShaderExecutor *m_executor;
200*35238bceSAndroid Build Coastguard Worker };
201*35238bceSAndroid Build Coastguard Worker 
IntegerFunctionCase(Context & context,const char * name,const char * description,glu::ShaderType shaderType)202*35238bceSAndroid Build Coastguard Worker IntegerFunctionCase::IntegerFunctionCase(Context &context, const char *name, const char *description,
203*35238bceSAndroid Build Coastguard Worker                                          glu::ShaderType shaderType)
204*35238bceSAndroid Build Coastguard Worker     : TestCase(context, name, description)
205*35238bceSAndroid Build Coastguard Worker     , m_shaderType(shaderType)
206*35238bceSAndroid Build Coastguard Worker     , m_numValues(100)
207*35238bceSAndroid Build Coastguard Worker     , m_executor(DE_NULL)
208*35238bceSAndroid Build Coastguard Worker {
209*35238bceSAndroid Build Coastguard Worker     m_spec.version = glu::getContextTypeGLSLVersion(context.getRenderContext().getType());
210*35238bceSAndroid Build Coastguard Worker }
211*35238bceSAndroid Build Coastguard Worker 
~IntegerFunctionCase(void)212*35238bceSAndroid Build Coastguard Worker IntegerFunctionCase::~IntegerFunctionCase(void)
213*35238bceSAndroid Build Coastguard Worker {
214*35238bceSAndroid Build Coastguard Worker     IntegerFunctionCase::deinit();
215*35238bceSAndroid Build Coastguard Worker }
216*35238bceSAndroid Build Coastguard Worker 
init(void)217*35238bceSAndroid Build Coastguard Worker void IntegerFunctionCase::init(void)
218*35238bceSAndroid Build Coastguard Worker {
219*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(!m_executor);
220*35238bceSAndroid Build Coastguard Worker 
221*35238bceSAndroid Build Coastguard Worker     m_executor = createExecutor(m_context.getRenderContext(), m_shaderType, m_spec);
222*35238bceSAndroid Build Coastguard Worker     m_testCtx.getLog() << m_executor;
223*35238bceSAndroid Build Coastguard Worker 
224*35238bceSAndroid Build Coastguard Worker     if (!m_executor->isOk())
225*35238bceSAndroid Build Coastguard Worker         throw tcu::TestError("Compile failed");
226*35238bceSAndroid Build Coastguard Worker }
227*35238bceSAndroid Build Coastguard Worker 
deinit(void)228*35238bceSAndroid Build Coastguard Worker void IntegerFunctionCase::deinit(void)
229*35238bceSAndroid Build Coastguard Worker {
230*35238bceSAndroid Build Coastguard Worker     delete m_executor;
231*35238bceSAndroid Build Coastguard Worker     m_executor = DE_NULL;
232*35238bceSAndroid Build Coastguard Worker }
233*35238bceSAndroid Build Coastguard Worker 
getScalarSizes(const vector<Symbol> & symbols)234*35238bceSAndroid Build Coastguard Worker static vector<int> getScalarSizes(const vector<Symbol> &symbols)
235*35238bceSAndroid Build Coastguard Worker {
236*35238bceSAndroid Build Coastguard Worker     vector<int> sizes(symbols.size());
237*35238bceSAndroid Build Coastguard Worker     for (int ndx = 0; ndx < (int)symbols.size(); ++ndx)
238*35238bceSAndroid Build Coastguard Worker         sizes[ndx] = symbols[ndx].varType.getScalarSize();
239*35238bceSAndroid Build Coastguard Worker     return sizes;
240*35238bceSAndroid Build Coastguard Worker }
241*35238bceSAndroid Build Coastguard Worker 
computeTotalScalarSize(const vector<Symbol> & symbols)242*35238bceSAndroid Build Coastguard Worker static int computeTotalScalarSize(const vector<Symbol> &symbols)
243*35238bceSAndroid Build Coastguard Worker {
244*35238bceSAndroid Build Coastguard Worker     int totalSize = 0;
245*35238bceSAndroid Build Coastguard Worker     for (vector<Symbol>::const_iterator sym = symbols.begin(); sym != symbols.end(); ++sym)
246*35238bceSAndroid Build Coastguard Worker         totalSize += sym->varType.getScalarSize();
247*35238bceSAndroid Build Coastguard Worker     return totalSize;
248*35238bceSAndroid Build Coastguard Worker }
249*35238bceSAndroid Build Coastguard Worker 
getInputOutputPointers(const vector<Symbol> & symbols,vector<uint32_t> & data,const int numValues)250*35238bceSAndroid Build Coastguard Worker static vector<void *> getInputOutputPointers(const vector<Symbol> &symbols, vector<uint32_t> &data, const int numValues)
251*35238bceSAndroid Build Coastguard Worker {
252*35238bceSAndroid Build Coastguard Worker     vector<void *> pointers(symbols.size());
253*35238bceSAndroid Build Coastguard Worker     int curScalarOffset = 0;
254*35238bceSAndroid Build Coastguard Worker 
255*35238bceSAndroid Build Coastguard Worker     for (int varNdx = 0; varNdx < (int)symbols.size(); ++varNdx)
256*35238bceSAndroid Build Coastguard Worker     {
257*35238bceSAndroid Build Coastguard Worker         const Symbol &var    = symbols[varNdx];
258*35238bceSAndroid Build Coastguard Worker         const int scalarSize = var.varType.getScalarSize();
259*35238bceSAndroid Build Coastguard Worker 
260*35238bceSAndroid Build Coastguard Worker         // Uses planar layout as input/output specs do not support strides.
261*35238bceSAndroid Build Coastguard Worker         pointers[varNdx] = &data[curScalarOffset];
262*35238bceSAndroid Build Coastguard Worker         curScalarOffset += scalarSize * numValues;
263*35238bceSAndroid Build Coastguard Worker     }
264*35238bceSAndroid Build Coastguard Worker 
265*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(curScalarOffset == (int)data.size());
266*35238bceSAndroid Build Coastguard Worker 
267*35238bceSAndroid Build Coastguard Worker     return pointers;
268*35238bceSAndroid Build Coastguard Worker }
269*35238bceSAndroid Build Coastguard Worker 
iterate(void)270*35238bceSAndroid Build Coastguard Worker IntegerFunctionCase::IterateResult IntegerFunctionCase::iterate(void)
271*35238bceSAndroid Build Coastguard Worker {
272*35238bceSAndroid Build Coastguard Worker     const int numInputScalars  = computeTotalScalarSize(m_spec.inputs);
273*35238bceSAndroid Build Coastguard Worker     const int numOutputScalars = computeTotalScalarSize(m_spec.outputs);
274*35238bceSAndroid Build Coastguard Worker     vector<uint32_t> inputData(numInputScalars * m_numValues);
275*35238bceSAndroid Build Coastguard Worker     vector<uint32_t> outputData(numOutputScalars * m_numValues);
276*35238bceSAndroid Build Coastguard Worker     const vector<void *> inputPointers  = getInputOutputPointers(m_spec.inputs, inputData, m_numValues);
277*35238bceSAndroid Build Coastguard Worker     const vector<void *> outputPointers = getInputOutputPointers(m_spec.outputs, outputData, m_numValues);
278*35238bceSAndroid Build Coastguard Worker 
279*35238bceSAndroid Build Coastguard Worker     // Initialize input data.
280*35238bceSAndroid Build Coastguard Worker     getInputValues(m_numValues, &inputPointers[0]);
281*35238bceSAndroid Build Coastguard Worker 
282*35238bceSAndroid Build Coastguard Worker     // Execute shader.
283*35238bceSAndroid Build Coastguard Worker     m_executor->useProgram();
284*35238bceSAndroid Build Coastguard Worker     m_executor->execute(m_numValues, &inputPointers[0], &outputPointers[0]);
285*35238bceSAndroid Build Coastguard Worker 
286*35238bceSAndroid Build Coastguard Worker     // Compare results.
287*35238bceSAndroid Build Coastguard Worker     {
288*35238bceSAndroid Build Coastguard Worker         const vector<int> inScalarSizes  = getScalarSizes(m_spec.inputs);
289*35238bceSAndroid Build Coastguard Worker         const vector<int> outScalarSizes = getScalarSizes(m_spec.outputs);
290*35238bceSAndroid Build Coastguard Worker         vector<void *> curInputPtr(inputPointers.size());
291*35238bceSAndroid Build Coastguard Worker         vector<void *> curOutputPtr(outputPointers.size());
292*35238bceSAndroid Build Coastguard Worker         int numFailed = 0;
293*35238bceSAndroid Build Coastguard Worker 
294*35238bceSAndroid Build Coastguard Worker         for (int valNdx = 0; valNdx < m_numValues; valNdx++)
295*35238bceSAndroid Build Coastguard Worker         {
296*35238bceSAndroid Build Coastguard Worker             // Set up pointers for comparison.
297*35238bceSAndroid Build Coastguard Worker             for (int inNdx = 0; inNdx < (int)curInputPtr.size(); ++inNdx)
298*35238bceSAndroid Build Coastguard Worker                 curInputPtr[inNdx] = (uint32_t *)inputPointers[inNdx] + inScalarSizes[inNdx] * valNdx;
299*35238bceSAndroid Build Coastguard Worker 
300*35238bceSAndroid Build Coastguard Worker             for (int outNdx = 0; outNdx < (int)curOutputPtr.size(); ++outNdx)
301*35238bceSAndroid Build Coastguard Worker                 curOutputPtr[outNdx] = (uint32_t *)outputPointers[outNdx] + outScalarSizes[outNdx] * valNdx;
302*35238bceSAndroid Build Coastguard Worker 
303*35238bceSAndroid Build Coastguard Worker             if (!compare(&curInputPtr[0], &curOutputPtr[0]))
304*35238bceSAndroid Build Coastguard Worker             {
305*35238bceSAndroid Build Coastguard Worker                 // \todo [2013-08-08 pyry] We probably want to log reference value as well?
306*35238bceSAndroid Build Coastguard Worker 
307*35238bceSAndroid Build Coastguard Worker                 m_testCtx.getLog() << TestLog::Message << "ERROR: comparison failed for value " << valNdx << ":\n  "
308*35238bceSAndroid Build Coastguard Worker                                    << m_failMsg.str() << TestLog::EndMessage;
309*35238bceSAndroid Build Coastguard Worker 
310*35238bceSAndroid Build Coastguard Worker                 m_testCtx.getLog() << TestLog::Message << "  inputs:" << TestLog::EndMessage;
311*35238bceSAndroid Build Coastguard Worker                 for (int inNdx = 0; inNdx < (int)curInputPtr.size(); inNdx++)
312*35238bceSAndroid Build Coastguard Worker                     m_testCtx.getLog() << TestLog::Message << "    " << m_spec.inputs[inNdx].name << " = "
313*35238bceSAndroid Build Coastguard Worker                                        << VarValue(m_spec.inputs[inNdx].varType, curInputPtr[inNdx])
314*35238bceSAndroid Build Coastguard Worker                                        << TestLog::EndMessage;
315*35238bceSAndroid Build Coastguard Worker 
316*35238bceSAndroid Build Coastguard Worker                 m_testCtx.getLog() << TestLog::Message << "  outputs:" << TestLog::EndMessage;
317*35238bceSAndroid Build Coastguard Worker                 for (int outNdx = 0; outNdx < (int)curOutputPtr.size(); outNdx++)
318*35238bceSAndroid Build Coastguard Worker                     m_testCtx.getLog() << TestLog::Message << "    " << m_spec.outputs[outNdx].name << " = "
319*35238bceSAndroid Build Coastguard Worker                                        << VarValue(m_spec.outputs[outNdx].varType, curOutputPtr[outNdx])
320*35238bceSAndroid Build Coastguard Worker                                        << TestLog::EndMessage;
321*35238bceSAndroid Build Coastguard Worker 
322*35238bceSAndroid Build Coastguard Worker                 m_failMsg.str("");
323*35238bceSAndroid Build Coastguard Worker                 m_failMsg.clear();
324*35238bceSAndroid Build Coastguard Worker                 numFailed += 1;
325*35238bceSAndroid Build Coastguard Worker             }
326*35238bceSAndroid Build Coastguard Worker         }
327*35238bceSAndroid Build Coastguard Worker 
328*35238bceSAndroid Build Coastguard Worker         m_testCtx.getLog() << TestLog::Message << (m_numValues - numFailed) << " / " << m_numValues << " values passed"
329*35238bceSAndroid Build Coastguard Worker                            << TestLog::EndMessage;
330*35238bceSAndroid Build Coastguard Worker 
331*35238bceSAndroid Build Coastguard Worker         m_testCtx.setTestResult(numFailed == 0 ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL,
332*35238bceSAndroid Build Coastguard Worker                                 numFailed == 0 ? "Pass" : "Result comparison failed");
333*35238bceSAndroid Build Coastguard Worker     }
334*35238bceSAndroid Build Coastguard Worker 
335*35238bceSAndroid Build Coastguard Worker     return STOP;
336*35238bceSAndroid Build Coastguard Worker }
337*35238bceSAndroid Build Coastguard Worker 
getIntegerFuncCaseName(glu::DataType baseType,glu::Precision precision,glu::ShaderType shaderType)338*35238bceSAndroid Build Coastguard Worker static std::string getIntegerFuncCaseName(glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
339*35238bceSAndroid Build Coastguard Worker {
340*35238bceSAndroid Build Coastguard Worker     return string(glu::getDataTypeName(baseType)) + getPrecisionPostfix(precision) + getShaderTypePostfix(shaderType);
341*35238bceSAndroid Build Coastguard Worker }
342*35238bceSAndroid Build Coastguard Worker 
343*35238bceSAndroid Build Coastguard Worker class UaddCarryCase : public IntegerFunctionCase
344*35238bceSAndroid Build Coastguard Worker {
345*35238bceSAndroid Build Coastguard Worker public:
UaddCarryCase(Context & context,glu::DataType baseType,glu::Precision precision,glu::ShaderType shaderType)346*35238bceSAndroid Build Coastguard Worker     UaddCarryCase(Context &context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
347*35238bceSAndroid Build Coastguard Worker         : IntegerFunctionCase(context, getIntegerFuncCaseName(baseType, precision, shaderType).c_str(), "uaddCarry",
348*35238bceSAndroid Build Coastguard Worker                               shaderType)
349*35238bceSAndroid Build Coastguard Worker     {
350*35238bceSAndroid Build Coastguard Worker         m_spec.inputs.push_back(Symbol("x", glu::VarType(baseType, precision)));
351*35238bceSAndroid Build Coastguard Worker         m_spec.inputs.push_back(Symbol("y", glu::VarType(baseType, precision)));
352*35238bceSAndroid Build Coastguard Worker         m_spec.outputs.push_back(Symbol("sum", glu::VarType(baseType, precision)));
353*35238bceSAndroid Build Coastguard Worker         m_spec.outputs.push_back(Symbol("carry", glu::VarType(baseType, glu::PRECISION_LOWP)));
354*35238bceSAndroid Build Coastguard Worker         m_spec.source = "sum = uaddCarry(x, y, carry);";
355*35238bceSAndroid Build Coastguard Worker     }
356*35238bceSAndroid Build Coastguard Worker 
getInputValues(int numValues,void * const * values) const357*35238bceSAndroid Build Coastguard Worker     void getInputValues(int numValues, void *const *values) const
358*35238bceSAndroid Build Coastguard Worker     {
359*35238bceSAndroid Build Coastguard Worker         de::Random rnd(deStringHash(getName()) ^ 0x235facu);
360*35238bceSAndroid Build Coastguard Worker         const glu::DataType type       = m_spec.inputs[0].varType.getBasicType();
361*35238bceSAndroid Build Coastguard Worker         const glu::Precision precision = m_spec.inputs[0].varType.getPrecision();
362*35238bceSAndroid Build Coastguard Worker         const int scalarSize           = glu::getDataTypeScalarSize(type);
363*35238bceSAndroid Build Coastguard Worker         const int integerLength        = getShaderUintBitCount(m_shaderType, precision);
364*35238bceSAndroid Build Coastguard Worker         const uint32_t integerMask     = getLowBitMask(integerLength);
365*35238bceSAndroid Build Coastguard Worker         const bool isSigned            = glu::isDataTypeIntOrIVec(type);
366*35238bceSAndroid Build Coastguard Worker         uint32_t *in0                  = (uint32_t *)values[0];
367*35238bceSAndroid Build Coastguard Worker         uint32_t *in1                  = (uint32_t *)values[1];
368*35238bceSAndroid Build Coastguard Worker 
369*35238bceSAndroid Build Coastguard Worker         const struct
370*35238bceSAndroid Build Coastguard Worker         {
371*35238bceSAndroid Build Coastguard Worker             uint32_t x;
372*35238bceSAndroid Build Coastguard Worker             uint32_t y;
373*35238bceSAndroid Build Coastguard Worker         } easyCases[] = {{0x00000000u, 0x00000000u}, {0xfffffffeu, 0x00000001u}, {0x00000001u, 0xfffffffeu},
374*35238bceSAndroid Build Coastguard Worker                          {0xffffffffu, 0x00000001u}, {0x00000001u, 0xffffffffu}, {0xfffffffeu, 0x00000002u},
375*35238bceSAndroid Build Coastguard Worker                          {0x00000002u, 0xfffffffeu}, {0xffffffffu, 0xffffffffu}};
376*35238bceSAndroid Build Coastguard Worker 
377*35238bceSAndroid Build Coastguard Worker         // generate integers with proper bit count
378*35238bceSAndroid Build Coastguard Worker         for (int easyCaseNdx = 0; easyCaseNdx < DE_LENGTH_OF_ARRAY(easyCases); easyCaseNdx++)
379*35238bceSAndroid Build Coastguard Worker         {
380*35238bceSAndroid Build Coastguard Worker             for (int compNdx = 0; compNdx < scalarSize; compNdx++)
381*35238bceSAndroid Build Coastguard Worker             {
382*35238bceSAndroid Build Coastguard Worker                 in0[easyCaseNdx * scalarSize + compNdx] = easyCases[easyCaseNdx].x & integerMask;
383*35238bceSAndroid Build Coastguard Worker                 in1[easyCaseNdx * scalarSize + compNdx] = easyCases[easyCaseNdx].y & integerMask;
384*35238bceSAndroid Build Coastguard Worker             }
385*35238bceSAndroid Build Coastguard Worker         }
386*35238bceSAndroid Build Coastguard Worker 
387*35238bceSAndroid Build Coastguard Worker         // convert to signed
388*35238bceSAndroid Build Coastguard Worker         if (isSigned)
389*35238bceSAndroid Build Coastguard Worker         {
390*35238bceSAndroid Build Coastguard Worker             for (int easyCaseNdx = 0; easyCaseNdx < DE_LENGTH_OF_ARRAY(easyCases); easyCaseNdx++)
391*35238bceSAndroid Build Coastguard Worker             {
392*35238bceSAndroid Build Coastguard Worker                 for (int compNdx = 0; compNdx < scalarSize; compNdx++)
393*35238bceSAndroid Build Coastguard Worker                 {
394*35238bceSAndroid Build Coastguard Worker                     in0[easyCaseNdx * scalarSize + compNdx] =
395*35238bceSAndroid Build Coastguard Worker                         extendSignTo32(in0[easyCaseNdx * scalarSize + compNdx], integerLength);
396*35238bceSAndroid Build Coastguard Worker                     in1[easyCaseNdx * scalarSize + compNdx] =
397*35238bceSAndroid Build Coastguard Worker                         extendSignTo32(in1[easyCaseNdx * scalarSize + compNdx], integerLength);
398*35238bceSAndroid Build Coastguard Worker                 }
399*35238bceSAndroid Build Coastguard Worker             }
400*35238bceSAndroid Build Coastguard Worker         }
401*35238bceSAndroid Build Coastguard Worker 
402*35238bceSAndroid Build Coastguard Worker         generateRandomInputData(rnd, m_shaderType, type, precision, in0, numValues - DE_LENGTH_OF_ARRAY(easyCases));
403*35238bceSAndroid Build Coastguard Worker         generateRandomInputData(rnd, m_shaderType, type, precision, in1, numValues - DE_LENGTH_OF_ARRAY(easyCases));
404*35238bceSAndroid Build Coastguard Worker     }
405*35238bceSAndroid Build Coastguard Worker 
compare(const void * const * inputs,const void * const * outputs)406*35238bceSAndroid Build Coastguard Worker     bool compare(const void *const *inputs, const void *const *outputs)
407*35238bceSAndroid Build Coastguard Worker     {
408*35238bceSAndroid Build Coastguard Worker         const glu::DataType type       = m_spec.inputs[0].varType.getBasicType();
409*35238bceSAndroid Build Coastguard Worker         const glu::Precision precision = m_spec.inputs[0].varType.getPrecision();
410*35238bceSAndroid Build Coastguard Worker         const int scalarSize           = glu::getDataTypeScalarSize(type);
411*35238bceSAndroid Build Coastguard Worker         const int integerLength        = getShaderUintBitCount(m_shaderType, precision);
412*35238bceSAndroid Build Coastguard Worker         const uint32_t mask0           = getLowBitMask(integerLength);
413*35238bceSAndroid Build Coastguard Worker 
414*35238bceSAndroid Build Coastguard Worker         for (int compNdx = 0; compNdx < scalarSize; compNdx++)
415*35238bceSAndroid Build Coastguard Worker         {
416*35238bceSAndroid Build Coastguard Worker             const uint32_t in0  = ((const uint32_t *)inputs[0])[compNdx];
417*35238bceSAndroid Build Coastguard Worker             const uint32_t in1  = ((const uint32_t *)inputs[1])[compNdx];
418*35238bceSAndroid Build Coastguard Worker             const uint32_t out0 = ((const uint32_t *)outputs[0])[compNdx];
419*35238bceSAndroid Build Coastguard Worker             const uint32_t out1 = ((const uint32_t *)outputs[1])[compNdx];
420*35238bceSAndroid Build Coastguard Worker             const uint32_t ref0 = in0 + in1;
421*35238bceSAndroid Build Coastguard Worker             const uint32_t ref1 = (uint64_t(in0) + uint64_t(in1)) > 0xffffffffu ? 1u : 0u;
422*35238bceSAndroid Build Coastguard Worker 
423*35238bceSAndroid Build Coastguard Worker             if (((out0 & mask0) != (ref0 & mask0)) || out1 != ref1)
424*35238bceSAndroid Build Coastguard Worker             {
425*35238bceSAndroid Build Coastguard Worker                 m_failMsg << "Expected [" << compNdx << "] = " << tcu::toHex(ref0) << ", " << tcu::toHex(ref1);
426*35238bceSAndroid Build Coastguard Worker                 return false;
427*35238bceSAndroid Build Coastguard Worker             }
428*35238bceSAndroid Build Coastguard Worker         }
429*35238bceSAndroid Build Coastguard Worker 
430*35238bceSAndroid Build Coastguard Worker         return true;
431*35238bceSAndroid Build Coastguard Worker     }
432*35238bceSAndroid Build Coastguard Worker };
433*35238bceSAndroid Build Coastguard Worker 
434*35238bceSAndroid Build Coastguard Worker class UsubBorrowCase : public IntegerFunctionCase
435*35238bceSAndroid Build Coastguard Worker {
436*35238bceSAndroid Build Coastguard Worker public:
UsubBorrowCase(Context & context,glu::DataType baseType,glu::Precision precision,glu::ShaderType shaderType)437*35238bceSAndroid Build Coastguard Worker     UsubBorrowCase(Context &context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
438*35238bceSAndroid Build Coastguard Worker         : IntegerFunctionCase(context, getIntegerFuncCaseName(baseType, precision, shaderType).c_str(), "usubBorrow",
439*35238bceSAndroid Build Coastguard Worker                               shaderType)
440*35238bceSAndroid Build Coastguard Worker     {
441*35238bceSAndroid Build Coastguard Worker         m_spec.inputs.push_back(Symbol("x", glu::VarType(baseType, precision)));
442*35238bceSAndroid Build Coastguard Worker         m_spec.inputs.push_back(Symbol("y", glu::VarType(baseType, precision)));
443*35238bceSAndroid Build Coastguard Worker         m_spec.outputs.push_back(Symbol("diff", glu::VarType(baseType, precision)));
444*35238bceSAndroid Build Coastguard Worker         m_spec.outputs.push_back(Symbol("carry", glu::VarType(baseType, glu::PRECISION_LOWP)));
445*35238bceSAndroid Build Coastguard Worker         m_spec.source = "diff = usubBorrow(x, y, carry);";
446*35238bceSAndroid Build Coastguard Worker     }
447*35238bceSAndroid Build Coastguard Worker 
getInputValues(int numValues,void * const * values) const448*35238bceSAndroid Build Coastguard Worker     void getInputValues(int numValues, void *const *values) const
449*35238bceSAndroid Build Coastguard Worker     {
450*35238bceSAndroid Build Coastguard Worker         de::Random rnd(deStringHash(getName()) ^ 0x235facu);
451*35238bceSAndroid Build Coastguard Worker         const glu::DataType type       = m_spec.inputs[0].varType.getBasicType();
452*35238bceSAndroid Build Coastguard Worker         const glu::Precision precision = m_spec.inputs[0].varType.getPrecision();
453*35238bceSAndroid Build Coastguard Worker         const int scalarSize           = glu::getDataTypeScalarSize(type);
454*35238bceSAndroid Build Coastguard Worker         const int integerLength        = getShaderUintBitCount(m_shaderType, precision);
455*35238bceSAndroid Build Coastguard Worker         const uint32_t integerMask     = getLowBitMask(integerLength);
456*35238bceSAndroid Build Coastguard Worker         const bool isSigned            = glu::isDataTypeIntOrIVec(type);
457*35238bceSAndroid Build Coastguard Worker         uint32_t *in0                  = (uint32_t *)values[0];
458*35238bceSAndroid Build Coastguard Worker         uint32_t *in1                  = (uint32_t *)values[1];
459*35238bceSAndroid Build Coastguard Worker 
460*35238bceSAndroid Build Coastguard Worker         const struct
461*35238bceSAndroid Build Coastguard Worker         {
462*35238bceSAndroid Build Coastguard Worker             uint32_t x;
463*35238bceSAndroid Build Coastguard Worker             uint32_t y;
464*35238bceSAndroid Build Coastguard Worker         } easyCases[] = {
465*35238bceSAndroid Build Coastguard Worker             {0x00000000u, 0x00000000u}, {0x00000001u, 0x00000001u}, {0x00000001u, 0x00000002u},
466*35238bceSAndroid Build Coastguard Worker             {0x00000001u, 0xffffffffu}, {0xfffffffeu, 0xffffffffu}, {0xffffffffu, 0xffffffffu},
467*35238bceSAndroid Build Coastguard Worker         };
468*35238bceSAndroid Build Coastguard Worker 
469*35238bceSAndroid Build Coastguard Worker         // generate integers with proper bit count
470*35238bceSAndroid Build Coastguard Worker         for (int easyCaseNdx = 0; easyCaseNdx < DE_LENGTH_OF_ARRAY(easyCases); easyCaseNdx++)
471*35238bceSAndroid Build Coastguard Worker         {
472*35238bceSAndroid Build Coastguard Worker             for (int compNdx = 0; compNdx < scalarSize; compNdx++)
473*35238bceSAndroid Build Coastguard Worker             {
474*35238bceSAndroid Build Coastguard Worker                 in0[easyCaseNdx * scalarSize + compNdx] = easyCases[easyCaseNdx].x & integerMask;
475*35238bceSAndroid Build Coastguard Worker                 in1[easyCaseNdx * scalarSize + compNdx] = easyCases[easyCaseNdx].y & integerMask;
476*35238bceSAndroid Build Coastguard Worker             }
477*35238bceSAndroid Build Coastguard Worker         }
478*35238bceSAndroid Build Coastguard Worker 
479*35238bceSAndroid Build Coastguard Worker         // convert to signed
480*35238bceSAndroid Build Coastguard Worker         if (isSigned)
481*35238bceSAndroid Build Coastguard Worker         {
482*35238bceSAndroid Build Coastguard Worker             for (int easyCaseNdx = 0; easyCaseNdx < DE_LENGTH_OF_ARRAY(easyCases); easyCaseNdx++)
483*35238bceSAndroid Build Coastguard Worker             {
484*35238bceSAndroid Build Coastguard Worker                 for (int compNdx = 0; compNdx < scalarSize; compNdx++)
485*35238bceSAndroid Build Coastguard Worker                 {
486*35238bceSAndroid Build Coastguard Worker                     in0[easyCaseNdx * scalarSize + compNdx] =
487*35238bceSAndroid Build Coastguard Worker                         extendSignTo32(in0[easyCaseNdx * scalarSize + compNdx], integerLength);
488*35238bceSAndroid Build Coastguard Worker                     in1[easyCaseNdx * scalarSize + compNdx] =
489*35238bceSAndroid Build Coastguard Worker                         extendSignTo32(in1[easyCaseNdx * scalarSize + compNdx], integerLength);
490*35238bceSAndroid Build Coastguard Worker                 }
491*35238bceSAndroid Build Coastguard Worker             }
492*35238bceSAndroid Build Coastguard Worker         }
493*35238bceSAndroid Build Coastguard Worker 
494*35238bceSAndroid Build Coastguard Worker         generateRandomInputData(rnd, m_shaderType, type, precision, in0, numValues - DE_LENGTH_OF_ARRAY(easyCases));
495*35238bceSAndroid Build Coastguard Worker         generateRandomInputData(rnd, m_shaderType, type, precision, in1, numValues - DE_LENGTH_OF_ARRAY(easyCases));
496*35238bceSAndroid Build Coastguard Worker     }
497*35238bceSAndroid Build Coastguard Worker 
compare(const void * const * inputs,const void * const * outputs)498*35238bceSAndroid Build Coastguard Worker     bool compare(const void *const *inputs, const void *const *outputs)
499*35238bceSAndroid Build Coastguard Worker     {
500*35238bceSAndroid Build Coastguard Worker         const glu::DataType type       = m_spec.inputs[0].varType.getBasicType();
501*35238bceSAndroid Build Coastguard Worker         const glu::Precision precision = m_spec.inputs[0].varType.getPrecision();
502*35238bceSAndroid Build Coastguard Worker         const int scalarSize           = glu::getDataTypeScalarSize(type);
503*35238bceSAndroid Build Coastguard Worker         const int integerLength        = getShaderUintBitCount(m_shaderType, precision);
504*35238bceSAndroid Build Coastguard Worker         const uint32_t mask0           = getLowBitMask(integerLength);
505*35238bceSAndroid Build Coastguard Worker 
506*35238bceSAndroid Build Coastguard Worker         for (int compNdx = 0; compNdx < scalarSize; compNdx++)
507*35238bceSAndroid Build Coastguard Worker         {
508*35238bceSAndroid Build Coastguard Worker             const uint32_t in0  = ((const uint32_t *)inputs[0])[compNdx];
509*35238bceSAndroid Build Coastguard Worker             const uint32_t in1  = ((const uint32_t *)inputs[1])[compNdx];
510*35238bceSAndroid Build Coastguard Worker             const uint32_t out0 = ((const uint32_t *)outputs[0])[compNdx];
511*35238bceSAndroid Build Coastguard Worker             const uint32_t out1 = ((const uint32_t *)outputs[1])[compNdx];
512*35238bceSAndroid Build Coastguard Worker             const uint32_t ref0 = in0 - in1;
513*35238bceSAndroid Build Coastguard Worker             const uint32_t ref1 = in0 >= in1 ? 0u : 1u;
514*35238bceSAndroid Build Coastguard Worker 
515*35238bceSAndroid Build Coastguard Worker             if (((out0 & mask0) != (ref0 & mask0)) || out1 != ref1)
516*35238bceSAndroid Build Coastguard Worker             {
517*35238bceSAndroid Build Coastguard Worker                 m_failMsg << "Expected [" << compNdx << "] = " << tcu::toHex(ref0) << ", " << tcu::toHex(ref1);
518*35238bceSAndroid Build Coastguard Worker                 return false;
519*35238bceSAndroid Build Coastguard Worker             }
520*35238bceSAndroid Build Coastguard Worker         }
521*35238bceSAndroid Build Coastguard Worker 
522*35238bceSAndroid Build Coastguard Worker         return true;
523*35238bceSAndroid Build Coastguard Worker     }
524*35238bceSAndroid Build Coastguard Worker };
525*35238bceSAndroid Build Coastguard Worker 
526*35238bceSAndroid Build Coastguard Worker class UmulExtendedCase : public IntegerFunctionCase
527*35238bceSAndroid Build Coastguard Worker {
528*35238bceSAndroid Build Coastguard Worker public:
UmulExtendedCase(Context & context,glu::DataType baseType,glu::Precision precision,glu::ShaderType shaderType)529*35238bceSAndroid Build Coastguard Worker     UmulExtendedCase(Context &context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
530*35238bceSAndroid Build Coastguard Worker         : IntegerFunctionCase(context, getIntegerFuncCaseName(baseType, precision, shaderType).c_str(), "umulExtended",
531*35238bceSAndroid Build Coastguard Worker                               shaderType)
532*35238bceSAndroid Build Coastguard Worker     {
533*35238bceSAndroid Build Coastguard Worker         m_spec.inputs.push_back(Symbol("x", glu::VarType(baseType, precision)));
534*35238bceSAndroid Build Coastguard Worker         m_spec.inputs.push_back(Symbol("y", glu::VarType(baseType, precision)));
535*35238bceSAndroid Build Coastguard Worker         m_spec.outputs.push_back(Symbol("msb", glu::VarType(baseType, precision)));
536*35238bceSAndroid Build Coastguard Worker         m_spec.outputs.push_back(Symbol("lsb", glu::VarType(baseType, precision)));
537*35238bceSAndroid Build Coastguard Worker         m_spec.source = "umulExtended(x, y, msb, lsb);";
538*35238bceSAndroid Build Coastguard Worker     }
539*35238bceSAndroid Build Coastguard Worker 
getInputValues(int numValues,void * const * values) const540*35238bceSAndroid Build Coastguard Worker     void getInputValues(int numValues, void *const *values) const
541*35238bceSAndroid Build Coastguard Worker     {
542*35238bceSAndroid Build Coastguard Worker         de::Random rnd(deStringHash(getName()) ^ 0x235facu);
543*35238bceSAndroid Build Coastguard Worker         const glu::DataType type = m_spec.inputs[0].varType.getBasicType();
544*35238bceSAndroid Build Coastguard Worker         // const glu::Precision precision = m_spec.inputs[0].varType.getPrecision();
545*35238bceSAndroid Build Coastguard Worker         const int scalarSize = glu::getDataTypeScalarSize(type);
546*35238bceSAndroid Build Coastguard Worker         uint32_t *in0        = (uint32_t *)values[0];
547*35238bceSAndroid Build Coastguard Worker         uint32_t *in1        = (uint32_t *)values[1];
548*35238bceSAndroid Build Coastguard Worker         int valueNdx         = 0;
549*35238bceSAndroid Build Coastguard Worker 
550*35238bceSAndroid Build Coastguard Worker         const struct
551*35238bceSAndroid Build Coastguard Worker         {
552*35238bceSAndroid Build Coastguard Worker             uint32_t x;
553*35238bceSAndroid Build Coastguard Worker             uint32_t y;
554*35238bceSAndroid Build Coastguard Worker         } easyCases[] = {
555*35238bceSAndroid Build Coastguard Worker             {0x00000000u, 0x00000000u}, {0xffffffffu, 0x00000001u}, {0xffffffffu, 0x00000002u},
556*35238bceSAndroid Build Coastguard Worker             {0x00000001u, 0xffffffffu}, {0x00000002u, 0xffffffffu}, {0xffffffffu, 0xffffffffu},
557*35238bceSAndroid Build Coastguard Worker         };
558*35238bceSAndroid Build Coastguard Worker 
559*35238bceSAndroid Build Coastguard Worker         for (int easyCaseNdx = 0; easyCaseNdx < DE_LENGTH_OF_ARRAY(easyCases); easyCaseNdx++)
560*35238bceSAndroid Build Coastguard Worker         {
561*35238bceSAndroid Build Coastguard Worker             for (int compNdx = 0; compNdx < scalarSize; compNdx++)
562*35238bceSAndroid Build Coastguard Worker             {
563*35238bceSAndroid Build Coastguard Worker                 in0[valueNdx * scalarSize + compNdx] = easyCases[easyCaseNdx].x;
564*35238bceSAndroid Build Coastguard Worker                 in1[valueNdx * scalarSize + compNdx] = easyCases[easyCaseNdx].y;
565*35238bceSAndroid Build Coastguard Worker             }
566*35238bceSAndroid Build Coastguard Worker 
567*35238bceSAndroid Build Coastguard Worker             valueNdx += 1;
568*35238bceSAndroid Build Coastguard Worker         }
569*35238bceSAndroid Build Coastguard Worker 
570*35238bceSAndroid Build Coastguard Worker         while (valueNdx < numValues)
571*35238bceSAndroid Build Coastguard Worker         {
572*35238bceSAndroid Build Coastguard Worker             for (int compNdx = 0; compNdx < scalarSize; compNdx++)
573*35238bceSAndroid Build Coastguard Worker             {
574*35238bceSAndroid Build Coastguard Worker                 const uint32_t base0                 = rnd.getUint32();
575*35238bceSAndroid Build Coastguard Worker                 const uint32_t base1                 = rnd.getUint32();
576*35238bceSAndroid Build Coastguard Worker                 const int adj0                       = rnd.getInt(0, 20);
577*35238bceSAndroid Build Coastguard Worker                 const int adj1                       = rnd.getInt(0, 20);
578*35238bceSAndroid Build Coastguard Worker                 in0[valueNdx * scalarSize + compNdx] = base0 >> adj0;
579*35238bceSAndroid Build Coastguard Worker                 in1[valueNdx * scalarSize + compNdx] = base1 >> adj1;
580*35238bceSAndroid Build Coastguard Worker             }
581*35238bceSAndroid Build Coastguard Worker 
582*35238bceSAndroid Build Coastguard Worker             valueNdx += 1;
583*35238bceSAndroid Build Coastguard Worker         }
584*35238bceSAndroid Build Coastguard Worker     }
585*35238bceSAndroid Build Coastguard Worker 
compare(const void * const * inputs,const void * const * outputs)586*35238bceSAndroid Build Coastguard Worker     bool compare(const void *const *inputs, const void *const *outputs)
587*35238bceSAndroid Build Coastguard Worker     {
588*35238bceSAndroid Build Coastguard Worker         const glu::DataType type = m_spec.inputs[0].varType.getBasicType();
589*35238bceSAndroid Build Coastguard Worker         const int scalarSize     = glu::getDataTypeScalarSize(type);
590*35238bceSAndroid Build Coastguard Worker 
591*35238bceSAndroid Build Coastguard Worker         for (int compNdx = 0; compNdx < scalarSize; compNdx++)
592*35238bceSAndroid Build Coastguard Worker         {
593*35238bceSAndroid Build Coastguard Worker             const uint32_t in0   = ((const uint32_t *)inputs[0])[compNdx];
594*35238bceSAndroid Build Coastguard Worker             const uint32_t in1   = ((const uint32_t *)inputs[1])[compNdx];
595*35238bceSAndroid Build Coastguard Worker             const uint32_t out0  = ((const uint32_t *)outputs[0])[compNdx];
596*35238bceSAndroid Build Coastguard Worker             const uint32_t out1  = ((const uint32_t *)outputs[1])[compNdx];
597*35238bceSAndroid Build Coastguard Worker             const uint64_t mul64 = uint64_t(in0) * uint64_t(in1);
598*35238bceSAndroid Build Coastguard Worker             const uint32_t ref0  = uint32_t(mul64 >> 32);
599*35238bceSAndroid Build Coastguard Worker             const uint32_t ref1  = uint32_t(mul64 & 0xffffffffu);
600*35238bceSAndroid Build Coastguard Worker 
601*35238bceSAndroid Build Coastguard Worker             if (out0 != ref0 || out1 != ref1)
602*35238bceSAndroid Build Coastguard Worker             {
603*35238bceSAndroid Build Coastguard Worker                 m_failMsg << "Expected [" << compNdx << "] = " << tcu::toHex(ref0) << ", " << tcu::toHex(ref1);
604*35238bceSAndroid Build Coastguard Worker                 return false;
605*35238bceSAndroid Build Coastguard Worker             }
606*35238bceSAndroid Build Coastguard Worker         }
607*35238bceSAndroid Build Coastguard Worker 
608*35238bceSAndroid Build Coastguard Worker         return true;
609*35238bceSAndroid Build Coastguard Worker     }
610*35238bceSAndroid Build Coastguard Worker };
611*35238bceSAndroid Build Coastguard Worker 
612*35238bceSAndroid Build Coastguard Worker class ImulExtendedCase : public IntegerFunctionCase
613*35238bceSAndroid Build Coastguard Worker {
614*35238bceSAndroid Build Coastguard Worker public:
ImulExtendedCase(Context & context,glu::DataType baseType,glu::Precision precision,glu::ShaderType shaderType)615*35238bceSAndroid Build Coastguard Worker     ImulExtendedCase(Context &context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
616*35238bceSAndroid Build Coastguard Worker         : IntegerFunctionCase(context, getIntegerFuncCaseName(baseType, precision, shaderType).c_str(), "imulExtended",
617*35238bceSAndroid Build Coastguard Worker                               shaderType)
618*35238bceSAndroid Build Coastguard Worker     {
619*35238bceSAndroid Build Coastguard Worker         m_spec.inputs.push_back(Symbol("x", glu::VarType(baseType, precision)));
620*35238bceSAndroid Build Coastguard Worker         m_spec.inputs.push_back(Symbol("y", glu::VarType(baseType, precision)));
621*35238bceSAndroid Build Coastguard Worker         m_spec.outputs.push_back(Symbol("msb", glu::VarType(baseType, precision)));
622*35238bceSAndroid Build Coastguard Worker         m_spec.outputs.push_back(Symbol("lsb", glu::VarType(baseType, precision)));
623*35238bceSAndroid Build Coastguard Worker         m_spec.source = "imulExtended(x, y, msb, lsb);";
624*35238bceSAndroid Build Coastguard Worker     }
625*35238bceSAndroid Build Coastguard Worker 
getInputValues(int numValues,void * const * values) const626*35238bceSAndroid Build Coastguard Worker     void getInputValues(int numValues, void *const *values) const
627*35238bceSAndroid Build Coastguard Worker     {
628*35238bceSAndroid Build Coastguard Worker         de::Random rnd(deStringHash(getName()) ^ 0x224fa1u);
629*35238bceSAndroid Build Coastguard Worker         const glu::DataType type = m_spec.inputs[0].varType.getBasicType();
630*35238bceSAndroid Build Coastguard Worker         // const glu::Precision precision = m_spec.inputs[0].varType.getPrecision();
631*35238bceSAndroid Build Coastguard Worker         const int scalarSize = glu::getDataTypeScalarSize(type);
632*35238bceSAndroid Build Coastguard Worker         uint32_t *in0        = (uint32_t *)values[0];
633*35238bceSAndroid Build Coastguard Worker         uint32_t *in1        = (uint32_t *)values[1];
634*35238bceSAndroid Build Coastguard Worker         int valueNdx         = 0;
635*35238bceSAndroid Build Coastguard Worker 
636*35238bceSAndroid Build Coastguard Worker         const struct
637*35238bceSAndroid Build Coastguard Worker         {
638*35238bceSAndroid Build Coastguard Worker             uint32_t x;
639*35238bceSAndroid Build Coastguard Worker             uint32_t y;
640*35238bceSAndroid Build Coastguard Worker         } easyCases[] = {
641*35238bceSAndroid Build Coastguard Worker             {0x00000000u, 0x00000000u}, {0xffffffffu, 0x00000002u}, {0x7fffffffu, 0x00000001u},
642*35238bceSAndroid Build Coastguard Worker             {0x7fffffffu, 0x00000002u}, {0x7fffffffu, 0x7fffffffu}, {0xffffffffu, 0xffffffffu},
643*35238bceSAndroid Build Coastguard Worker             {0x7fffffffu, 0xfffffffeu},
644*35238bceSAndroid Build Coastguard Worker         };
645*35238bceSAndroid Build Coastguard Worker 
646*35238bceSAndroid Build Coastguard Worker         for (int easyCaseNdx = 0; easyCaseNdx < DE_LENGTH_OF_ARRAY(easyCases); easyCaseNdx++)
647*35238bceSAndroid Build Coastguard Worker         {
648*35238bceSAndroid Build Coastguard Worker             for (int compNdx = 0; compNdx < scalarSize; compNdx++)
649*35238bceSAndroid Build Coastguard Worker             {
650*35238bceSAndroid Build Coastguard Worker                 in0[valueNdx * scalarSize + compNdx] = (int32_t)easyCases[easyCaseNdx].x;
651*35238bceSAndroid Build Coastguard Worker                 in1[valueNdx * scalarSize + compNdx] = (int32_t)easyCases[easyCaseNdx].y;
652*35238bceSAndroid Build Coastguard Worker             }
653*35238bceSAndroid Build Coastguard Worker 
654*35238bceSAndroid Build Coastguard Worker             valueNdx += 1;
655*35238bceSAndroid Build Coastguard Worker         }
656*35238bceSAndroid Build Coastguard Worker 
657*35238bceSAndroid Build Coastguard Worker         while (valueNdx < numValues)
658*35238bceSAndroid Build Coastguard Worker         {
659*35238bceSAndroid Build Coastguard Worker             for (int compNdx = 0; compNdx < scalarSize; compNdx++)
660*35238bceSAndroid Build Coastguard Worker             {
661*35238bceSAndroid Build Coastguard Worker                 const int32_t base0                  = (int32_t)rnd.getUint32();
662*35238bceSAndroid Build Coastguard Worker                 const int32_t base1                  = (int32_t)rnd.getUint32();
663*35238bceSAndroid Build Coastguard Worker                 const int adj0                       = rnd.getInt(0, 20);
664*35238bceSAndroid Build Coastguard Worker                 const int adj1                       = rnd.getInt(0, 20);
665*35238bceSAndroid Build Coastguard Worker                 in0[valueNdx * scalarSize + compNdx] = base0 >> adj0;
666*35238bceSAndroid Build Coastguard Worker                 in1[valueNdx * scalarSize + compNdx] = base1 >> adj1;
667*35238bceSAndroid Build Coastguard Worker             }
668*35238bceSAndroid Build Coastguard Worker 
669*35238bceSAndroid Build Coastguard Worker             valueNdx += 1;
670*35238bceSAndroid Build Coastguard Worker         }
671*35238bceSAndroid Build Coastguard Worker     }
672*35238bceSAndroid Build Coastguard Worker 
compare(const void * const * inputs,const void * const * outputs)673*35238bceSAndroid Build Coastguard Worker     bool compare(const void *const *inputs, const void *const *outputs)
674*35238bceSAndroid Build Coastguard Worker     {
675*35238bceSAndroid Build Coastguard Worker         const glu::DataType type = m_spec.inputs[0].varType.getBasicType();
676*35238bceSAndroid Build Coastguard Worker         const int scalarSize     = glu::getDataTypeScalarSize(type);
677*35238bceSAndroid Build Coastguard Worker 
678*35238bceSAndroid Build Coastguard Worker         for (int compNdx = 0; compNdx < scalarSize; compNdx++)
679*35238bceSAndroid Build Coastguard Worker         {
680*35238bceSAndroid Build Coastguard Worker             const int32_t in0   = ((const int32_t *)inputs[0])[compNdx];
681*35238bceSAndroid Build Coastguard Worker             const int32_t in1   = ((const int32_t *)inputs[1])[compNdx];
682*35238bceSAndroid Build Coastguard Worker             const int32_t out0  = ((const int32_t *)outputs[0])[compNdx];
683*35238bceSAndroid Build Coastguard Worker             const int32_t out1  = ((const int32_t *)outputs[1])[compNdx];
684*35238bceSAndroid Build Coastguard Worker             const int64_t mul64 = int64_t(in0) * int64_t(in1);
685*35238bceSAndroid Build Coastguard Worker             const int32_t ref0  = int32_t(mul64 >> 32);
686*35238bceSAndroid Build Coastguard Worker             const int32_t ref1  = int32_t(mul64 & 0xffffffffu);
687*35238bceSAndroid Build Coastguard Worker 
688*35238bceSAndroid Build Coastguard Worker             if (out0 != ref0 || out1 != ref1)
689*35238bceSAndroid Build Coastguard Worker             {
690*35238bceSAndroid Build Coastguard Worker                 m_failMsg << "Expected [" << compNdx << "] = " << tcu::toHex(ref0) << ", " << tcu::toHex(ref1);
691*35238bceSAndroid Build Coastguard Worker                 return false;
692*35238bceSAndroid Build Coastguard Worker             }
693*35238bceSAndroid Build Coastguard Worker         }
694*35238bceSAndroid Build Coastguard Worker 
695*35238bceSAndroid Build Coastguard Worker         return true;
696*35238bceSAndroid Build Coastguard Worker     }
697*35238bceSAndroid Build Coastguard Worker };
698*35238bceSAndroid Build Coastguard Worker 
699*35238bceSAndroid Build Coastguard Worker class BitfieldExtractCase : public IntegerFunctionCase
700*35238bceSAndroid Build Coastguard Worker {
701*35238bceSAndroid Build Coastguard Worker public:
BitfieldExtractCase(Context & context,glu::DataType baseType,glu::Precision precision,glu::ShaderType shaderType)702*35238bceSAndroid Build Coastguard Worker     BitfieldExtractCase(Context &context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
703*35238bceSAndroid Build Coastguard Worker         : IntegerFunctionCase(context, getIntegerFuncCaseName(baseType, precision, shaderType).c_str(),
704*35238bceSAndroid Build Coastguard Worker                               "bitfieldExtract", shaderType)
705*35238bceSAndroid Build Coastguard Worker     {
706*35238bceSAndroid Build Coastguard Worker         m_spec.inputs.push_back(Symbol("value", glu::VarType(baseType, precision)));
707*35238bceSAndroid Build Coastguard Worker         m_spec.inputs.push_back(Symbol("offset", glu::VarType(glu::TYPE_INT, precision)));
708*35238bceSAndroid Build Coastguard Worker         m_spec.inputs.push_back(Symbol("bits", glu::VarType(glu::TYPE_INT, precision)));
709*35238bceSAndroid Build Coastguard Worker         m_spec.outputs.push_back(Symbol("extracted", glu::VarType(baseType, precision)));
710*35238bceSAndroid Build Coastguard Worker         m_spec.source = "extracted = bitfieldExtract(value, offset, bits);";
711*35238bceSAndroid Build Coastguard Worker     }
712*35238bceSAndroid Build Coastguard Worker 
getInputValues(int numValues,void * const * values) const713*35238bceSAndroid Build Coastguard Worker     void getInputValues(int numValues, void *const *values) const
714*35238bceSAndroid Build Coastguard Worker     {
715*35238bceSAndroid Build Coastguard Worker         de::Random rnd(deStringHash(getName()) ^ 0xa113fca2u);
716*35238bceSAndroid Build Coastguard Worker         const glu::DataType type       = m_spec.inputs[0].varType.getBasicType();
717*35238bceSAndroid Build Coastguard Worker         const glu::Precision precision = m_spec.inputs[0].varType.getPrecision();
718*35238bceSAndroid Build Coastguard Worker         const bool ignoreSign          = precision != glu::PRECISION_HIGHP && glu::isDataTypeIntOrIVec(type);
719*35238bceSAndroid Build Coastguard Worker         const int numBits              = getShaderUintBitCount(m_shaderType, precision) - (ignoreSign ? 1 : 0);
720*35238bceSAndroid Build Coastguard Worker         uint32_t *inValue              = (uint32_t *)values[0];
721*35238bceSAndroid Build Coastguard Worker         int *inOffset                  = (int *)values[1];
722*35238bceSAndroid Build Coastguard Worker         int *inBits                    = (int *)values[2];
723*35238bceSAndroid Build Coastguard Worker 
724*35238bceSAndroid Build Coastguard Worker         for (int valueNdx = 0; valueNdx < numValues; ++valueNdx)
725*35238bceSAndroid Build Coastguard Worker         {
726*35238bceSAndroid Build Coastguard Worker             const int bits   = rnd.getInt(0, numBits);
727*35238bceSAndroid Build Coastguard Worker             const int offset = rnd.getInt(0, numBits - bits);
728*35238bceSAndroid Build Coastguard Worker 
729*35238bceSAndroid Build Coastguard Worker             inOffset[valueNdx] = offset;
730*35238bceSAndroid Build Coastguard Worker             inBits[valueNdx]   = bits;
731*35238bceSAndroid Build Coastguard Worker         }
732*35238bceSAndroid Build Coastguard Worker 
733*35238bceSAndroid Build Coastguard Worker         generateRandomInputData(rnd, m_shaderType, type, precision, inValue, numValues);
734*35238bceSAndroid Build Coastguard Worker     }
735*35238bceSAndroid Build Coastguard Worker 
compare(const void * const * inputs,const void * const * outputs)736*35238bceSAndroid Build Coastguard Worker     bool compare(const void *const *inputs, const void *const *outputs)
737*35238bceSAndroid Build Coastguard Worker     {
738*35238bceSAndroid Build Coastguard Worker         const glu::DataType type = m_spec.inputs[0].varType.getBasicType();
739*35238bceSAndroid Build Coastguard Worker         const bool isSigned      = glu::isDataTypeIntOrIVec(type);
740*35238bceSAndroid Build Coastguard Worker         const int scalarSize     = glu::getDataTypeScalarSize(type);
741*35238bceSAndroid Build Coastguard Worker         const int offset         = *((const int *)inputs[1]);
742*35238bceSAndroid Build Coastguard Worker         const int bits           = *((const int *)inputs[2]);
743*35238bceSAndroid Build Coastguard Worker 
744*35238bceSAndroid Build Coastguard Worker         for (int compNdx = 0; compNdx < scalarSize; compNdx++)
745*35238bceSAndroid Build Coastguard Worker         {
746*35238bceSAndroid Build Coastguard Worker             const uint32_t out = ((const uint32_t *)outputs[0])[compNdx];
747*35238bceSAndroid Build Coastguard Worker             uint32_t ref;
748*35238bceSAndroid Build Coastguard Worker 
749*35238bceSAndroid Build Coastguard Worker             // From the bitfieldExtract spec: "If bits is zero, the result will be zero.".
750*35238bceSAndroid Build Coastguard Worker             if (bits == 0)
751*35238bceSAndroid Build Coastguard Worker             {
752*35238bceSAndroid Build Coastguard Worker                 ref = 0u;
753*35238bceSAndroid Build Coastguard Worker             }
754*35238bceSAndroid Build Coastguard Worker             else
755*35238bceSAndroid Build Coastguard Worker             {
756*35238bceSAndroid Build Coastguard Worker                 const uint32_t value   = ((const uint32_t *)inputs[0])[compNdx];
757*35238bceSAndroid Build Coastguard Worker                 const uint32_t valMask = (bits == 32 ? ~0u : ((1u << bits) - 1u));
758*35238bceSAndroid Build Coastguard Worker                 const uint32_t baseVal = (offset == 32) ? (0) : ((value >> offset) & valMask);
759*35238bceSAndroid Build Coastguard Worker                 ref                    = baseVal | ((isSigned && (baseVal & (1 << (bits - 1)))) ? ~valMask : 0u);
760*35238bceSAndroid Build Coastguard Worker             }
761*35238bceSAndroid Build Coastguard Worker 
762*35238bceSAndroid Build Coastguard Worker             if (out != ref)
763*35238bceSAndroid Build Coastguard Worker             {
764*35238bceSAndroid Build Coastguard Worker                 m_failMsg << "Expected [" << compNdx << "] = " << tcu::toHex(ref);
765*35238bceSAndroid Build Coastguard Worker                 return false;
766*35238bceSAndroid Build Coastguard Worker             }
767*35238bceSAndroid Build Coastguard Worker         }
768*35238bceSAndroid Build Coastguard Worker 
769*35238bceSAndroid Build Coastguard Worker         return true;
770*35238bceSAndroid Build Coastguard Worker     }
771*35238bceSAndroid Build Coastguard Worker };
772*35238bceSAndroid Build Coastguard Worker 
773*35238bceSAndroid Build Coastguard Worker class BitfieldInsertCase : public IntegerFunctionCase
774*35238bceSAndroid Build Coastguard Worker {
775*35238bceSAndroid Build Coastguard Worker public:
BitfieldInsertCase(Context & context,glu::DataType baseType,glu::Precision precision,glu::ShaderType shaderType)776*35238bceSAndroid Build Coastguard Worker     BitfieldInsertCase(Context &context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
777*35238bceSAndroid Build Coastguard Worker         : IntegerFunctionCase(context, getIntegerFuncCaseName(baseType, precision, shaderType).c_str(),
778*35238bceSAndroid Build Coastguard Worker                               "bitfieldInsert", shaderType)
779*35238bceSAndroid Build Coastguard Worker     {
780*35238bceSAndroid Build Coastguard Worker         m_spec.inputs.push_back(Symbol("base", glu::VarType(baseType, precision)));
781*35238bceSAndroid Build Coastguard Worker         m_spec.inputs.push_back(Symbol("insert", glu::VarType(baseType, precision)));
782*35238bceSAndroid Build Coastguard Worker         m_spec.inputs.push_back(Symbol("offset", glu::VarType(glu::TYPE_INT, precision)));
783*35238bceSAndroid Build Coastguard Worker         m_spec.inputs.push_back(Symbol("bits", glu::VarType(glu::TYPE_INT, precision)));
784*35238bceSAndroid Build Coastguard Worker         m_spec.outputs.push_back(Symbol("result", glu::VarType(baseType, precision)));
785*35238bceSAndroid Build Coastguard Worker         m_spec.source = "result = bitfieldInsert(base, insert, offset, bits);";
786*35238bceSAndroid Build Coastguard Worker     }
787*35238bceSAndroid Build Coastguard Worker 
getInputValues(int numValues,void * const * values) const788*35238bceSAndroid Build Coastguard Worker     void getInputValues(int numValues, void *const *values) const
789*35238bceSAndroid Build Coastguard Worker     {
790*35238bceSAndroid Build Coastguard Worker         de::Random rnd(deStringHash(getName()) ^ 0x12c2acff);
791*35238bceSAndroid Build Coastguard Worker         const glu::DataType type       = m_spec.inputs[0].varType.getBasicType();
792*35238bceSAndroid Build Coastguard Worker         const glu::Precision precision = m_spec.inputs[0].varType.getPrecision();
793*35238bceSAndroid Build Coastguard Worker         const int numBits              = getShaderUintBitCount(m_shaderType, precision);
794*35238bceSAndroid Build Coastguard Worker         uint32_t *inBase               = (uint32_t *)values[0];
795*35238bceSAndroid Build Coastguard Worker         uint32_t *inInsert             = (uint32_t *)values[1];
796*35238bceSAndroid Build Coastguard Worker         int *inOffset                  = (int *)values[2];
797*35238bceSAndroid Build Coastguard Worker         int *inBits                    = (int *)values[3];
798*35238bceSAndroid Build Coastguard Worker 
799*35238bceSAndroid Build Coastguard Worker         for (int valueNdx = 0; valueNdx < numValues; ++valueNdx)
800*35238bceSAndroid Build Coastguard Worker         {
801*35238bceSAndroid Build Coastguard Worker             const int bits   = rnd.getInt(0, numBits);
802*35238bceSAndroid Build Coastguard Worker             const int offset = rnd.getInt(0, numBits - bits);
803*35238bceSAndroid Build Coastguard Worker 
804*35238bceSAndroid Build Coastguard Worker             inOffset[valueNdx] = offset;
805*35238bceSAndroid Build Coastguard Worker             inBits[valueNdx]   = bits;
806*35238bceSAndroid Build Coastguard Worker         }
807*35238bceSAndroid Build Coastguard Worker 
808*35238bceSAndroid Build Coastguard Worker         generateRandomInputData(rnd, m_shaderType, type, precision, inBase, numValues);
809*35238bceSAndroid Build Coastguard Worker         generateRandomInputData(rnd, m_shaderType, type, precision, inInsert, numValues);
810*35238bceSAndroid Build Coastguard Worker     }
811*35238bceSAndroid Build Coastguard Worker 
compare(const void * const * inputs,const void * const * outputs)812*35238bceSAndroid Build Coastguard Worker     bool compare(const void *const *inputs, const void *const *outputs)
813*35238bceSAndroid Build Coastguard Worker     {
814*35238bceSAndroid Build Coastguard Worker         const glu::DataType type       = m_spec.inputs[0].varType.getBasicType();
815*35238bceSAndroid Build Coastguard Worker         const glu::Precision precision = m_spec.inputs[0].varType.getPrecision();
816*35238bceSAndroid Build Coastguard Worker         const int scalarSize           = glu::getDataTypeScalarSize(type);
817*35238bceSAndroid Build Coastguard Worker         const int integerLength        = getShaderUintBitCount(m_shaderType, precision);
818*35238bceSAndroid Build Coastguard Worker         const uint32_t cmpMask         = getLowBitMask(integerLength);
819*35238bceSAndroid Build Coastguard Worker         const int offset               = *((const int *)inputs[2]);
820*35238bceSAndroid Build Coastguard Worker         const int bits                 = *((const int *)inputs[3]);
821*35238bceSAndroid Build Coastguard Worker 
822*35238bceSAndroid Build Coastguard Worker         for (int compNdx = 0; compNdx < scalarSize; compNdx++)
823*35238bceSAndroid Build Coastguard Worker         {
824*35238bceSAndroid Build Coastguard Worker             const uint32_t base   = ((const uint32_t *)inputs[0])[compNdx];
825*35238bceSAndroid Build Coastguard Worker             const uint32_t insert = ((const uint32_t *)inputs[1])[compNdx];
826*35238bceSAndroid Build Coastguard Worker             const int32_t out     = ((const uint32_t *)outputs[0])[compNdx];
827*35238bceSAndroid Build Coastguard Worker 
828*35238bceSAndroid Build Coastguard Worker             const uint32_t mask = bits == 32 ? ~0u : (1u << bits) - 1;
829*35238bceSAndroid Build Coastguard Worker             const uint32_t ref  = (base & ~(mask << offset)) | ((insert & mask) << offset);
830*35238bceSAndroid Build Coastguard Worker 
831*35238bceSAndroid Build Coastguard Worker             if ((out & cmpMask) != (ref & cmpMask))
832*35238bceSAndroid Build Coastguard Worker             {
833*35238bceSAndroid Build Coastguard Worker                 m_failMsg << "Expected [" << compNdx << "] = " << tcu::toHex(ref);
834*35238bceSAndroid Build Coastguard Worker                 return false;
835*35238bceSAndroid Build Coastguard Worker             }
836*35238bceSAndroid Build Coastguard Worker         }
837*35238bceSAndroid Build Coastguard Worker 
838*35238bceSAndroid Build Coastguard Worker         return true;
839*35238bceSAndroid Build Coastguard Worker     }
840*35238bceSAndroid Build Coastguard Worker };
841*35238bceSAndroid Build Coastguard Worker 
reverseBits(uint32_t v)842*35238bceSAndroid Build Coastguard Worker static inline uint32_t reverseBits(uint32_t v)
843*35238bceSAndroid Build Coastguard Worker {
844*35238bceSAndroid Build Coastguard Worker     v = (((v & 0xaaaaaaaa) >> 1) | ((v & 0x55555555) << 1));
845*35238bceSAndroid Build Coastguard Worker     v = (((v & 0xcccccccc) >> 2) | ((v & 0x33333333) << 2));
846*35238bceSAndroid Build Coastguard Worker     v = (((v & 0xf0f0f0f0) >> 4) | ((v & 0x0f0f0f0f) << 4));
847*35238bceSAndroid Build Coastguard Worker     v = (((v & 0xff00ff00) >> 8) | ((v & 0x00ff00ff) << 8));
848*35238bceSAndroid Build Coastguard Worker     return ((v >> 16) | (v << 16));
849*35238bceSAndroid Build Coastguard Worker }
850*35238bceSAndroid Build Coastguard Worker 
851*35238bceSAndroid Build Coastguard Worker class BitfieldReverseCase : public IntegerFunctionCase
852*35238bceSAndroid Build Coastguard Worker {
853*35238bceSAndroid Build Coastguard Worker public:
BitfieldReverseCase(Context & context,glu::DataType baseType,glu::Precision precision,glu::ShaderType shaderType)854*35238bceSAndroid Build Coastguard Worker     BitfieldReverseCase(Context &context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
855*35238bceSAndroid Build Coastguard Worker         : IntegerFunctionCase(context, getIntegerFuncCaseName(baseType, precision, shaderType).c_str(),
856*35238bceSAndroid Build Coastguard Worker                               "bitfieldReverse", shaderType)
857*35238bceSAndroid Build Coastguard Worker     {
858*35238bceSAndroid Build Coastguard Worker         m_spec.inputs.push_back(Symbol("value", glu::VarType(baseType, precision)));
859*35238bceSAndroid Build Coastguard Worker         m_spec.outputs.push_back(Symbol("result", glu::VarType(baseType, glu::PRECISION_HIGHP)));
860*35238bceSAndroid Build Coastguard Worker         m_spec.source = "result = bitfieldReverse(value);";
861*35238bceSAndroid Build Coastguard Worker     }
862*35238bceSAndroid Build Coastguard Worker 
getInputValues(int numValues,void * const * values) const863*35238bceSAndroid Build Coastguard Worker     void getInputValues(int numValues, void *const *values) const
864*35238bceSAndroid Build Coastguard Worker     {
865*35238bceSAndroid Build Coastguard Worker         de::Random rnd(deStringHash(getName()) ^ 0xff23a4);
866*35238bceSAndroid Build Coastguard Worker         const glu::DataType type       = m_spec.inputs[0].varType.getBasicType();
867*35238bceSAndroid Build Coastguard Worker         const glu::Precision precision = m_spec.inputs[0].varType.getPrecision();
868*35238bceSAndroid Build Coastguard Worker         uint32_t *inValue              = (uint32_t *)values[0];
869*35238bceSAndroid Build Coastguard Worker 
870*35238bceSAndroid Build Coastguard Worker         generateRandomInputData(rnd, m_shaderType, type, precision, inValue, numValues);
871*35238bceSAndroid Build Coastguard Worker     }
872*35238bceSAndroid Build Coastguard Worker 
compare(const void * const * inputs,const void * const * outputs)873*35238bceSAndroid Build Coastguard Worker     bool compare(const void *const *inputs, const void *const *outputs)
874*35238bceSAndroid Build Coastguard Worker     {
875*35238bceSAndroid Build Coastguard Worker         const glu::DataType type       = m_spec.inputs[0].varType.getBasicType();
876*35238bceSAndroid Build Coastguard Worker         const glu::Precision precision = m_spec.inputs[0].varType.getPrecision();
877*35238bceSAndroid Build Coastguard Worker         const int integerLength        = getShaderUintBitCount(m_shaderType, precision);
878*35238bceSAndroid Build Coastguard Worker         const int scalarSize           = glu::getDataTypeScalarSize(type);
879*35238bceSAndroid Build Coastguard Worker         const uint32_t cmpMask         = reverseBits(getLowBitMask(integerLength));
880*35238bceSAndroid Build Coastguard Worker 
881*35238bceSAndroid Build Coastguard Worker         for (int compNdx = 0; compNdx < scalarSize; compNdx++)
882*35238bceSAndroid Build Coastguard Worker         {
883*35238bceSAndroid Build Coastguard Worker             const uint32_t value = ((const uint32_t *)inputs[0])[compNdx];
884*35238bceSAndroid Build Coastguard Worker             const int32_t out    = ((const uint32_t *)outputs[0])[compNdx];
885*35238bceSAndroid Build Coastguard Worker             const uint32_t ref   = reverseBits(value);
886*35238bceSAndroid Build Coastguard Worker 
887*35238bceSAndroid Build Coastguard Worker             if ((out & cmpMask) != (ref & cmpMask))
888*35238bceSAndroid Build Coastguard Worker             {
889*35238bceSAndroid Build Coastguard Worker                 m_failMsg << "Expected [" << compNdx << "] = " << tcu::toHex(ref);
890*35238bceSAndroid Build Coastguard Worker                 return false;
891*35238bceSAndroid Build Coastguard Worker             }
892*35238bceSAndroid Build Coastguard Worker         }
893*35238bceSAndroid Build Coastguard Worker 
894*35238bceSAndroid Build Coastguard Worker         return true;
895*35238bceSAndroid Build Coastguard Worker     }
896*35238bceSAndroid Build Coastguard Worker };
897*35238bceSAndroid Build Coastguard Worker 
898*35238bceSAndroid Build Coastguard Worker class BitCountCase : public IntegerFunctionCase
899*35238bceSAndroid Build Coastguard Worker {
900*35238bceSAndroid Build Coastguard Worker public:
BitCountCase(Context & context,glu::DataType baseType,glu::Precision precision,glu::ShaderType shaderType)901*35238bceSAndroid Build Coastguard Worker     BitCountCase(Context &context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
902*35238bceSAndroid Build Coastguard Worker         : IntegerFunctionCase(context, getIntegerFuncCaseName(baseType, precision, shaderType).c_str(), "bitCount",
903*35238bceSAndroid Build Coastguard Worker                               shaderType)
904*35238bceSAndroid Build Coastguard Worker     {
905*35238bceSAndroid Build Coastguard Worker         const int vecSize           = glu::getDataTypeScalarSize(baseType);
906*35238bceSAndroid Build Coastguard Worker         const glu::DataType intType = vecSize == 1 ? glu::TYPE_INT : glu::getDataTypeIntVec(vecSize);
907*35238bceSAndroid Build Coastguard Worker 
908*35238bceSAndroid Build Coastguard Worker         m_spec.inputs.push_back(Symbol("value", glu::VarType(baseType, precision)));
909*35238bceSAndroid Build Coastguard Worker         m_spec.outputs.push_back(Symbol("count", glu::VarType(intType, glu::PRECISION_LOWP)));
910*35238bceSAndroid Build Coastguard Worker         m_spec.source = "count = bitCount(value);";
911*35238bceSAndroid Build Coastguard Worker     }
912*35238bceSAndroid Build Coastguard Worker 
getInputValues(int numValues,void * const * values) const913*35238bceSAndroid Build Coastguard Worker     void getInputValues(int numValues, void *const *values) const
914*35238bceSAndroid Build Coastguard Worker     {
915*35238bceSAndroid Build Coastguard Worker         de::Random rnd(deStringHash(getName()) ^ 0xab2cca4);
916*35238bceSAndroid Build Coastguard Worker         const glu::DataType type       = m_spec.inputs[0].varType.getBasicType();
917*35238bceSAndroid Build Coastguard Worker         const glu::Precision precision = m_spec.inputs[0].varType.getPrecision();
918*35238bceSAndroid Build Coastguard Worker         uint32_t *inValue              = (uint32_t *)values[0];
919*35238bceSAndroid Build Coastguard Worker 
920*35238bceSAndroid Build Coastguard Worker         generateRandomInputData(rnd, m_shaderType, type, precision, inValue, numValues);
921*35238bceSAndroid Build Coastguard Worker     }
922*35238bceSAndroid Build Coastguard Worker 
compare(const void * const * inputs,const void * const * outputs)923*35238bceSAndroid Build Coastguard Worker     bool compare(const void *const *inputs, const void *const *outputs)
924*35238bceSAndroid Build Coastguard Worker     {
925*35238bceSAndroid Build Coastguard Worker         const glu::DataType type       = m_spec.inputs[0].varType.getBasicType();
926*35238bceSAndroid Build Coastguard Worker         const glu::Precision precision = m_spec.inputs[0].varType.getPrecision();
927*35238bceSAndroid Build Coastguard Worker         const int integerLength        = getShaderUintBitCount(m_shaderType, precision);
928*35238bceSAndroid Build Coastguard Worker         const int scalarSize           = glu::getDataTypeScalarSize(type);
929*35238bceSAndroid Build Coastguard Worker         const uint32_t countMask       = getLowBitMask(integerLength);
930*35238bceSAndroid Build Coastguard Worker 
931*35238bceSAndroid Build Coastguard Worker         for (int compNdx = 0; compNdx < scalarSize; compNdx++)
932*35238bceSAndroid Build Coastguard Worker         {
933*35238bceSAndroid Build Coastguard Worker             const uint32_t value = ((const uint32_t *)inputs[0])[compNdx];
934*35238bceSAndroid Build Coastguard Worker             const int out        = ((const int *)outputs[0])[compNdx];
935*35238bceSAndroid Build Coastguard Worker             const int minRef     = dePop32(value & countMask);
936*35238bceSAndroid Build Coastguard Worker             const int maxRef     = dePop32(value);
937*35238bceSAndroid Build Coastguard Worker 
938*35238bceSAndroid Build Coastguard Worker             if (!de::inRange(out, minRef, maxRef))
939*35238bceSAndroid Build Coastguard Worker             {
940*35238bceSAndroid Build Coastguard Worker                 m_failMsg << "Expected [" << compNdx << "] in range [" << minRef << ", " << maxRef << "]";
941*35238bceSAndroid Build Coastguard Worker                 return false;
942*35238bceSAndroid Build Coastguard Worker             }
943*35238bceSAndroid Build Coastguard Worker         }
944*35238bceSAndroid Build Coastguard Worker 
945*35238bceSAndroid Build Coastguard Worker         return true;
946*35238bceSAndroid Build Coastguard Worker     }
947*35238bceSAndroid Build Coastguard Worker };
948*35238bceSAndroid Build Coastguard Worker 
findLSB(uint32_t value)949*35238bceSAndroid Build Coastguard Worker static int findLSB(uint32_t value)
950*35238bceSAndroid Build Coastguard Worker {
951*35238bceSAndroid Build Coastguard Worker     for (int i = 0; i < 32; i++)
952*35238bceSAndroid Build Coastguard Worker     {
953*35238bceSAndroid Build Coastguard Worker         if (value & (1u << i))
954*35238bceSAndroid Build Coastguard Worker             return i;
955*35238bceSAndroid Build Coastguard Worker     }
956*35238bceSAndroid Build Coastguard Worker     return -1;
957*35238bceSAndroid Build Coastguard Worker }
958*35238bceSAndroid Build Coastguard Worker 
959*35238bceSAndroid Build Coastguard Worker class FindLSBCase : public IntegerFunctionCase
960*35238bceSAndroid Build Coastguard Worker {
961*35238bceSAndroid Build Coastguard Worker public:
FindLSBCase(Context & context,glu::DataType baseType,glu::Precision precision,glu::ShaderType shaderType)962*35238bceSAndroid Build Coastguard Worker     FindLSBCase(Context &context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
963*35238bceSAndroid Build Coastguard Worker         : IntegerFunctionCase(context, getIntegerFuncCaseName(baseType, precision, shaderType).c_str(), "findLSB",
964*35238bceSAndroid Build Coastguard Worker                               shaderType)
965*35238bceSAndroid Build Coastguard Worker     {
966*35238bceSAndroid Build Coastguard Worker         const int vecSize           = glu::getDataTypeScalarSize(baseType);
967*35238bceSAndroid Build Coastguard Worker         const glu::DataType intType = vecSize == 1 ? glu::TYPE_INT : glu::getDataTypeIntVec(vecSize);
968*35238bceSAndroid Build Coastguard Worker 
969*35238bceSAndroid Build Coastguard Worker         m_spec.inputs.push_back(Symbol("value", glu::VarType(baseType, precision)));
970*35238bceSAndroid Build Coastguard Worker         m_spec.outputs.push_back(Symbol("lsb", glu::VarType(intType, glu::PRECISION_LOWP)));
971*35238bceSAndroid Build Coastguard Worker         m_spec.source = "lsb = findLSB(value);";
972*35238bceSAndroid Build Coastguard Worker     }
973*35238bceSAndroid Build Coastguard Worker 
getInputValues(int numValues,void * const * values) const974*35238bceSAndroid Build Coastguard Worker     void getInputValues(int numValues, void *const *values) const
975*35238bceSAndroid Build Coastguard Worker     {
976*35238bceSAndroid Build Coastguard Worker         de::Random rnd(deStringHash(getName()) ^ 0x9923c2af);
977*35238bceSAndroid Build Coastguard Worker         const glu::DataType type       = m_spec.inputs[0].varType.getBasicType();
978*35238bceSAndroid Build Coastguard Worker         const glu::Precision precision = m_spec.inputs[0].varType.getPrecision();
979*35238bceSAndroid Build Coastguard Worker         uint32_t *inValue              = (uint32_t *)values[0];
980*35238bceSAndroid Build Coastguard Worker 
981*35238bceSAndroid Build Coastguard Worker         generateRandomInputData(rnd, m_shaderType, type, precision, inValue, numValues);
982*35238bceSAndroid Build Coastguard Worker     }
983*35238bceSAndroid Build Coastguard Worker 
compare(const void * const * inputs,const void * const * outputs)984*35238bceSAndroid Build Coastguard Worker     bool compare(const void *const *inputs, const void *const *outputs)
985*35238bceSAndroid Build Coastguard Worker     {
986*35238bceSAndroid Build Coastguard Worker         const glu::DataType type       = m_spec.inputs[0].varType.getBasicType();
987*35238bceSAndroid Build Coastguard Worker         const glu::Precision precision = m_spec.inputs[0].varType.getPrecision();
988*35238bceSAndroid Build Coastguard Worker         const int scalarSize           = glu::getDataTypeScalarSize(type);
989*35238bceSAndroid Build Coastguard Worker         const int integerLength        = getShaderUintBitCount(m_shaderType, precision);
990*35238bceSAndroid Build Coastguard Worker         const uint32_t mask            = getLowBitMask(integerLength);
991*35238bceSAndroid Build Coastguard Worker 
992*35238bceSAndroid Build Coastguard Worker         for (int compNdx = 0; compNdx < scalarSize; compNdx++)
993*35238bceSAndroid Build Coastguard Worker         {
994*35238bceSAndroid Build Coastguard Worker             const uint32_t value = ((const uint32_t *)inputs[0])[compNdx];
995*35238bceSAndroid Build Coastguard Worker             const int out        = ((const int *)outputs[0])[compNdx];
996*35238bceSAndroid Build Coastguard Worker             const int minRef     = findLSB(value & mask);
997*35238bceSAndroid Build Coastguard Worker             const int maxRef     = findLSB(value);
998*35238bceSAndroid Build Coastguard Worker 
999*35238bceSAndroid Build Coastguard Worker             if (!de::inRange(out, minRef, maxRef))
1000*35238bceSAndroid Build Coastguard Worker             {
1001*35238bceSAndroid Build Coastguard Worker                 m_failMsg << "Expected [" << compNdx << "] in range [" << minRef << ", " << maxRef << "]";
1002*35238bceSAndroid Build Coastguard Worker                 return false;
1003*35238bceSAndroid Build Coastguard Worker             }
1004*35238bceSAndroid Build Coastguard Worker         }
1005*35238bceSAndroid Build Coastguard Worker 
1006*35238bceSAndroid Build Coastguard Worker         return true;
1007*35238bceSAndroid Build Coastguard Worker     }
1008*35238bceSAndroid Build Coastguard Worker };
1009*35238bceSAndroid Build Coastguard Worker 
toPrecision(uint32_t value,int numIntegerBits)1010*35238bceSAndroid Build Coastguard Worker static uint32_t toPrecision(uint32_t value, int numIntegerBits)
1011*35238bceSAndroid Build Coastguard Worker {
1012*35238bceSAndroid Build Coastguard Worker     return value & getLowBitMask(numIntegerBits);
1013*35238bceSAndroid Build Coastguard Worker }
1014*35238bceSAndroid Build Coastguard Worker 
toPrecision(int32_t value,int numIntegerBits)1015*35238bceSAndroid Build Coastguard Worker static int32_t toPrecision(int32_t value, int numIntegerBits)
1016*35238bceSAndroid Build Coastguard Worker {
1017*35238bceSAndroid Build Coastguard Worker     return (int32_t)extendSignTo32((uint32_t)value & getLowBitMask(numIntegerBits), numIntegerBits);
1018*35238bceSAndroid Build Coastguard Worker }
1019*35238bceSAndroid Build Coastguard Worker 
1020*35238bceSAndroid Build Coastguard Worker class FindMSBCase : public IntegerFunctionCase
1021*35238bceSAndroid Build Coastguard Worker {
1022*35238bceSAndroid Build Coastguard Worker public:
FindMSBCase(Context & context,glu::DataType baseType,glu::Precision precision,glu::ShaderType shaderType)1023*35238bceSAndroid Build Coastguard Worker     FindMSBCase(Context &context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
1024*35238bceSAndroid Build Coastguard Worker         : IntegerFunctionCase(context, getIntegerFuncCaseName(baseType, precision, shaderType).c_str(), "findMSB",
1025*35238bceSAndroid Build Coastguard Worker                               shaderType)
1026*35238bceSAndroid Build Coastguard Worker     {
1027*35238bceSAndroid Build Coastguard Worker         const int vecSize           = glu::getDataTypeScalarSize(baseType);
1028*35238bceSAndroid Build Coastguard Worker         const glu::DataType intType = vecSize == 1 ? glu::TYPE_INT : glu::getDataTypeIntVec(vecSize);
1029*35238bceSAndroid Build Coastguard Worker 
1030*35238bceSAndroid Build Coastguard Worker         m_spec.inputs.push_back(Symbol("value", glu::VarType(baseType, precision)));
1031*35238bceSAndroid Build Coastguard Worker         m_spec.outputs.push_back(Symbol("msb", glu::VarType(intType, glu::PRECISION_LOWP)));
1032*35238bceSAndroid Build Coastguard Worker         m_spec.source = "msb = findMSB(value);";
1033*35238bceSAndroid Build Coastguard Worker     }
1034*35238bceSAndroid Build Coastguard Worker 
getInputValues(int numValues,void * const * values) const1035*35238bceSAndroid Build Coastguard Worker     void getInputValues(int numValues, void *const *values) const
1036*35238bceSAndroid Build Coastguard Worker     {
1037*35238bceSAndroid Build Coastguard Worker         de::Random rnd(deStringHash(getName()) ^ 0x742ac4e);
1038*35238bceSAndroid Build Coastguard Worker         const glu::DataType type       = m_spec.inputs[0].varType.getBasicType();
1039*35238bceSAndroid Build Coastguard Worker         const glu::Precision precision = m_spec.inputs[0].varType.getPrecision();
1040*35238bceSAndroid Build Coastguard Worker         uint32_t *inValue              = (uint32_t *)values[0];
1041*35238bceSAndroid Build Coastguard Worker 
1042*35238bceSAndroid Build Coastguard Worker         generateRandomInputData(rnd, m_shaderType, type, precision, inValue, numValues);
1043*35238bceSAndroid Build Coastguard Worker     }
1044*35238bceSAndroid Build Coastguard Worker 
compare(const void * const * inputs,const void * const * outputs)1045*35238bceSAndroid Build Coastguard Worker     bool compare(const void *const *inputs, const void *const *outputs)
1046*35238bceSAndroid Build Coastguard Worker     {
1047*35238bceSAndroid Build Coastguard Worker         const glu::DataType type       = m_spec.inputs[0].varType.getBasicType();
1048*35238bceSAndroid Build Coastguard Worker         const glu::Precision precision = m_spec.inputs[0].varType.getPrecision();
1049*35238bceSAndroid Build Coastguard Worker         const bool isSigned            = glu::isDataTypeIntOrIVec(type);
1050*35238bceSAndroid Build Coastguard Worker         const int scalarSize           = glu::getDataTypeScalarSize(type);
1051*35238bceSAndroid Build Coastguard Worker         const int integerLength        = getShaderUintBitCount(m_shaderType, precision);
1052*35238bceSAndroid Build Coastguard Worker 
1053*35238bceSAndroid Build Coastguard Worker         for (int compNdx = 0; compNdx < scalarSize; compNdx++)
1054*35238bceSAndroid Build Coastguard Worker         {
1055*35238bceSAndroid Build Coastguard Worker             const uint32_t value = ((const uint32_t *)inputs[0])[compNdx];
1056*35238bceSAndroid Build Coastguard Worker             const int out        = ((const int32_t *)outputs[0])[compNdx];
1057*35238bceSAndroid Build Coastguard Worker             const int minRef     = isSigned ? de::findMSB(toPrecision(int32_t(value), integerLength)) :
1058*35238bceSAndroid Build Coastguard Worker                                               de::findMSB(toPrecision(value, integerLength));
1059*35238bceSAndroid Build Coastguard Worker             const int maxRef     = isSigned ? de::findMSB(int32_t(value)) : de::findMSB(value);
1060*35238bceSAndroid Build Coastguard Worker 
1061*35238bceSAndroid Build Coastguard Worker             if (!de::inRange(out, minRef, maxRef))
1062*35238bceSAndroid Build Coastguard Worker             {
1063*35238bceSAndroid Build Coastguard Worker                 m_failMsg << "Expected [" << compNdx << "] in range [" << minRef << ", " << maxRef << "]";
1064*35238bceSAndroid Build Coastguard Worker                 return false;
1065*35238bceSAndroid Build Coastguard Worker             }
1066*35238bceSAndroid Build Coastguard Worker         }
1067*35238bceSAndroid Build Coastguard Worker 
1068*35238bceSAndroid Build Coastguard Worker         return true;
1069*35238bceSAndroid Build Coastguard Worker     }
1070*35238bceSAndroid Build Coastguard Worker };
1071*35238bceSAndroid Build Coastguard Worker 
ShaderIntegerFunctionTests(Context & context)1072*35238bceSAndroid Build Coastguard Worker ShaderIntegerFunctionTests::ShaderIntegerFunctionTests(Context &context)
1073*35238bceSAndroid Build Coastguard Worker     : TestCaseGroup(context, "integer", "Integer function tests")
1074*35238bceSAndroid Build Coastguard Worker {
1075*35238bceSAndroid Build Coastguard Worker }
1076*35238bceSAndroid Build Coastguard Worker 
~ShaderIntegerFunctionTests(void)1077*35238bceSAndroid Build Coastguard Worker ShaderIntegerFunctionTests::~ShaderIntegerFunctionTests(void)
1078*35238bceSAndroid Build Coastguard Worker {
1079*35238bceSAndroid Build Coastguard Worker }
1080*35238bceSAndroid Build Coastguard Worker 
1081*35238bceSAndroid Build Coastguard Worker template <class TestClass>
addFunctionCases(TestCaseGroup * parent,const char * functionName,bool intTypes,bool uintTypes,bool allPrec,uint32_t shaderBits)1082*35238bceSAndroid Build Coastguard Worker static void addFunctionCases(TestCaseGroup *parent, const char *functionName, bool intTypes, bool uintTypes,
1083*35238bceSAndroid Build Coastguard Worker                              bool allPrec, uint32_t shaderBits)
1084*35238bceSAndroid Build Coastguard Worker {
1085*35238bceSAndroid Build Coastguard Worker     tcu::TestCaseGroup *group = new tcu::TestCaseGroup(parent->getTestContext(), functionName, functionName);
1086*35238bceSAndroid Build Coastguard Worker     parent->addChild(group);
1087*35238bceSAndroid Build Coastguard Worker 
1088*35238bceSAndroid Build Coastguard Worker     const glu::DataType scalarTypes[] = {glu::TYPE_INT, glu::TYPE_UINT};
1089*35238bceSAndroid Build Coastguard Worker 
1090*35238bceSAndroid Build Coastguard Worker     for (int scalarTypeNdx = 0; scalarTypeNdx < DE_LENGTH_OF_ARRAY(scalarTypes); scalarTypeNdx++)
1091*35238bceSAndroid Build Coastguard Worker     {
1092*35238bceSAndroid Build Coastguard Worker         const glu::DataType scalarType = scalarTypes[scalarTypeNdx];
1093*35238bceSAndroid Build Coastguard Worker 
1094*35238bceSAndroid Build Coastguard Worker         if ((!intTypes && scalarType == glu::TYPE_INT) || (!uintTypes && scalarType == glu::TYPE_UINT))
1095*35238bceSAndroid Build Coastguard Worker             continue;
1096*35238bceSAndroid Build Coastguard Worker 
1097*35238bceSAndroid Build Coastguard Worker         for (int vecSize = 1; vecSize <= 4; vecSize++)
1098*35238bceSAndroid Build Coastguard Worker         {
1099*35238bceSAndroid Build Coastguard Worker             for (int prec = glu::PRECISION_LOWP; prec <= glu::PRECISION_HIGHP; prec++)
1100*35238bceSAndroid Build Coastguard Worker             {
1101*35238bceSAndroid Build Coastguard Worker                 if (prec != glu::PRECISION_HIGHP && !allPrec)
1102*35238bceSAndroid Build Coastguard Worker                     continue;
1103*35238bceSAndroid Build Coastguard Worker 
1104*35238bceSAndroid Build Coastguard Worker                 for (int shaderTypeNdx = 0; shaderTypeNdx < glu::SHADERTYPE_LAST; shaderTypeNdx++)
1105*35238bceSAndroid Build Coastguard Worker                 {
1106*35238bceSAndroid Build Coastguard Worker                     if (shaderBits & (1 << shaderTypeNdx))
1107*35238bceSAndroid Build Coastguard Worker                         group->addChild(new TestClass(parent->getContext(), glu::DataType(scalarType + vecSize - 1),
1108*35238bceSAndroid Build Coastguard Worker                                                       glu::Precision(prec), glu::ShaderType(shaderTypeNdx)));
1109*35238bceSAndroid Build Coastguard Worker                 }
1110*35238bceSAndroid Build Coastguard Worker             }
1111*35238bceSAndroid Build Coastguard Worker         }
1112*35238bceSAndroid Build Coastguard Worker     }
1113*35238bceSAndroid Build Coastguard Worker }
1114*35238bceSAndroid Build Coastguard Worker 
init(void)1115*35238bceSAndroid Build Coastguard Worker void ShaderIntegerFunctionTests::init(void)
1116*35238bceSAndroid Build Coastguard Worker {
1117*35238bceSAndroid Build Coastguard Worker     enum
1118*35238bceSAndroid Build Coastguard Worker     {
1119*35238bceSAndroid Build Coastguard Worker         VS = (1 << glu::SHADERTYPE_VERTEX),
1120*35238bceSAndroid Build Coastguard Worker         FS = (1 << glu::SHADERTYPE_FRAGMENT),
1121*35238bceSAndroid Build Coastguard Worker         CS = (1 << glu::SHADERTYPE_COMPUTE),
1122*35238bceSAndroid Build Coastguard Worker         GS = (1 << glu::SHADERTYPE_GEOMETRY),
1123*35238bceSAndroid Build Coastguard Worker         TC = (1 << glu::SHADERTYPE_TESSELLATION_CONTROL),
1124*35238bceSAndroid Build Coastguard Worker         TE = (1 << glu::SHADERTYPE_TESSELLATION_EVALUATION),
1125*35238bceSAndroid Build Coastguard Worker 
1126*35238bceSAndroid Build Coastguard Worker         ALL_SHADERS = VS | TC | TE | GS | FS | CS
1127*35238bceSAndroid Build Coastguard Worker     };
1128*35238bceSAndroid Build Coastguard Worker 
1129*35238bceSAndroid Build Coastguard Worker     //                                                                        Int?    Uint?    AllPrec?    Shaders
1130*35238bceSAndroid Build Coastguard Worker     addFunctionCases<UaddCarryCase>(this, "uaddcarry", false, true, true, ALL_SHADERS);
1131*35238bceSAndroid Build Coastguard Worker     addFunctionCases<UsubBorrowCase>(this, "usubborrow", false, true, true, ALL_SHADERS);
1132*35238bceSAndroid Build Coastguard Worker     addFunctionCases<UmulExtendedCase>(this, "umulextended", false, true, false, ALL_SHADERS);
1133*35238bceSAndroid Build Coastguard Worker     addFunctionCases<ImulExtendedCase>(this, "imulextended", true, false, false, ALL_SHADERS);
1134*35238bceSAndroid Build Coastguard Worker     addFunctionCases<BitfieldExtractCase>(this, "bitfieldextract", true, true, true, ALL_SHADERS);
1135*35238bceSAndroid Build Coastguard Worker     addFunctionCases<BitfieldInsertCase>(this, "bitfieldinsert", true, true, true, ALL_SHADERS);
1136*35238bceSAndroid Build Coastguard Worker     addFunctionCases<BitfieldReverseCase>(this, "bitfieldreverse", true, true, true, ALL_SHADERS);
1137*35238bceSAndroid Build Coastguard Worker     addFunctionCases<BitCountCase>(this, "bitcount", true, true, true, ALL_SHADERS);
1138*35238bceSAndroid Build Coastguard Worker     addFunctionCases<FindLSBCase>(this, "findlsb", true, true, true, ALL_SHADERS);
1139*35238bceSAndroid Build Coastguard Worker     addFunctionCases<FindMSBCase>(this, "findmsb", true, true, true, ALL_SHADERS);
1140*35238bceSAndroid Build Coastguard Worker }
1141*35238bceSAndroid Build Coastguard Worker 
1142*35238bceSAndroid Build Coastguard Worker } // namespace Functional
1143*35238bceSAndroid Build Coastguard Worker } // namespace gles31
1144*35238bceSAndroid Build Coastguard Worker } // namespace deqp
1145