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