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