Skip OOB SSBO fragment tests for ES3.1 GPUs am: 66241e9dbb
[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                                                                                         generateSources(m_shaderType, m_spec, programCollection);
325                                                                                 }
326
327         virtual TestInstance*                           createInstance                  (Context& context) const = 0;
328
329 protected:
330                                                                                 IntegerFunctionCase             (const IntegerFunctionCase& other);
331         IntegerFunctionCase&                            operator=                               (const IntegerFunctionCase& other);
332
333         const glu::ShaderType                           m_shaderType;
334
335         ShaderSpec                                                      m_spec;
336
337         const int                                                       m_numValues;
338 };
339
340 IntegerFunctionCase::IntegerFunctionCase (tcu::TestContext& testCtx, const char* name, const char* description, glu::ShaderType shaderType)
341         : TestCase              (testCtx, name, description)
342         , m_shaderType  (shaderType)
343         , m_numValues   (100)
344 {
345 }
346
347 IntegerFunctionCase::~IntegerFunctionCase (void)
348 {
349 }
350
351 // IntegerFunctionTestInstance
352
353 class IntegerFunctionTestInstance : public TestInstance
354 {
355 public:
356                                                                 IntegerFunctionTestInstance             (Context& context, glu::ShaderType shaderType, const ShaderSpec& spec, int numValues, const char* name)
357                                                                         : TestInstance  (context)
358                                                                         , m_shaderType  (shaderType)
359                                                                         , m_spec                (spec)
360                                                                         , m_numValues   (numValues)
361                                                                         , m_name                (name)
362                                                                         , m_executor    (createExecutor(context, m_shaderType, m_spec))
363                                                                 {
364                                                                 }
365         virtual tcu::TestStatus         iterate                                                 (void);
366 protected:
367         virtual bool                                            compare                                 (const void* const* inputs, const void* const* outputs) = 0;
368
369         virtual void                                            getInputValues                  (int numValues, void* const* values) const = 0;
370
371         const glu::ShaderType                           m_shaderType;
372
373         ShaderSpec                                                      m_spec;
374
375         const int                                                       m_numValues;
376
377         const char*                                                     m_name;
378
379         std::ostringstream                                      m_failMsg;                              //!< Comparison failure help message.
380
381         de::UniquePtr<ShaderExecutor>           m_executor;
382 };
383
384 tcu::TestStatus IntegerFunctionTestInstance::iterate (void)
385 {
386         const int                               numInputScalars                 = computeTotalScalarSize(m_spec.inputs);
387         const int                               numOutputScalars                = computeTotalScalarSize(m_spec.outputs);
388         vector<deUint32>                inputData                               (numInputScalars * m_numValues);
389         vector<deUint32>                outputData                              (numOutputScalars * m_numValues);
390         const vector<void*>             inputPointers                   = getInputOutputPointers(m_spec.inputs, inputData, m_numValues);
391         const vector<void*>             outputPointers                  = getInputOutputPointers(m_spec.outputs, outputData, m_numValues);
392
393         // Initialize input data.
394         getInputValues(m_numValues, &inputPointers[0]);
395
396         // Execute shader.
397         m_executor->execute(m_numValues, &inputPointers[0], &outputPointers[0]);
398
399         // Compare results.
400         {
401                 const vector<int>               inScalarSizes           = getScalarSizes(m_spec.inputs);
402                 const vector<int>               outScalarSizes          = getScalarSizes(m_spec.outputs);
403                 vector<void*>                   curInputPtr                     (inputPointers.size());
404                 vector<void*>                   curOutputPtr            (outputPointers.size());
405                 int                                             numFailed                       = 0;
406                 tcu::TestContext&               testCtx                         = m_context.getTestContext();
407                 for (int valNdx = 0; valNdx < m_numValues; valNdx++)
408                 {
409                         // Set up pointers for comparison.
410                         for (int inNdx = 0; inNdx < (int)curInputPtr.size(); ++inNdx)
411                                 curInputPtr[inNdx] = (deUint32*)inputPointers[inNdx] + inScalarSizes[inNdx]*valNdx;
412
413                         for (int outNdx = 0; outNdx < (int)curOutputPtr.size(); ++outNdx)
414                                 curOutputPtr[outNdx] = (deUint32*)outputPointers[outNdx] + outScalarSizes[outNdx]*valNdx;
415
416                         if (!compare(&curInputPtr[0], &curOutputPtr[0]))
417                         {
418                                 // \todo [2013-08-08 pyry] We probably want to log reference value as well?
419
420                                 testCtx.getLog() << TestLog::Message << "ERROR: comparison failed for value " << valNdx << ":\n  " << m_failMsg.str() << TestLog::EndMessage;
421
422                                 testCtx.getLog() << TestLog::Message << "  inputs:" << TestLog::EndMessage;
423                                 for (int inNdx = 0; inNdx < (int)curInputPtr.size(); inNdx++)
424                                         testCtx.getLog() << TestLog::Message << "    " << m_spec.inputs[inNdx].name << " = "
425                                                                                                                    << VarValue(m_spec.inputs[inNdx].varType, curInputPtr[inNdx])
426                                                                            << TestLog::EndMessage;
427
428                                 testCtx.getLog() << TestLog::Message << "  outputs:" << TestLog::EndMessage;
429                                 for (int outNdx = 0; outNdx < (int)curOutputPtr.size(); outNdx++)
430                                         testCtx.getLog() << TestLog::Message << "    " << m_spec.outputs[outNdx].name << " = "
431                                                                                                                    << VarValue(m_spec.outputs[outNdx].varType, curOutputPtr[outNdx])
432                                                                            << TestLog::EndMessage;
433
434                                 m_failMsg.str("");
435                                 m_failMsg.clear();
436                                 numFailed += 1;
437                         }
438                 }
439
440                 testCtx.getLog() << TestLog::Message << (m_numValues - numFailed) << " / " << m_numValues << " values passed" << TestLog::EndMessage;
441
442                 if (numFailed == 0)
443                         return tcu::TestStatus::pass("Pass");
444                 else
445                         return tcu::TestStatus::fail("Result comparison failed");
446         }
447 }
448
449 // Test cases
450
451 class UaddCarryCaseInstance : public IntegerFunctionTestInstance
452 {
453 public:
454         UaddCarryCaseInstance (Context& context, glu::ShaderType shaderType, const ShaderSpec& spec, int numValues, const char* name)
455                 : IntegerFunctionTestInstance   (context, shaderType, spec, numValues, name)
456         {
457         }
458
459         void getInputValues (int numValues, void* const* values) const
460         {
461                 de::Random                              rnd                             (deStringHash(m_name) ^ 0x235facu);
462                 const glu::DataType             type                    = m_spec.inputs[0].varType.getBasicType();
463                 const glu::Precision    precision               = m_spec.inputs[0].varType.getPrecision();
464                 const int                               scalarSize              = glu::getDataTypeScalarSize(type);
465                 const int                               integerLength   = getShaderUintBitCount(m_shaderType, precision);
466                 const deUint32                  integerMask             = getLowBitMask(integerLength);
467                 const bool                              isSigned                = glu::isDataTypeIntOrIVec(type);
468                 deUint32*                               in0                             = (deUint32*)values[0];
469                 deUint32*                               in1                             = (deUint32*)values[1];
470
471                 const struct
472                 {
473                         deUint32        x;
474                         deUint32        y;
475                 } easyCases[] =
476                 {
477                         { 0x00000000u,  0x00000000u },
478                         { 0xfffffffeu,  0x00000001u },
479                         { 0x00000001u,  0xfffffffeu },
480                         { 0xffffffffu,  0x00000001u },
481                         { 0x00000001u,  0xffffffffu },
482                         { 0xfffffffeu,  0x00000002u },
483                         { 0x00000002u,  0xfffffffeu },
484                         { 0xffffffffu,  0xffffffffu }
485                 };
486
487                 // generate integers with proper bit count
488                 for (int easyCaseNdx = 0; easyCaseNdx < DE_LENGTH_OF_ARRAY(easyCases); easyCaseNdx++)
489                 {
490                         for (int compNdx = 0; compNdx < scalarSize; compNdx++)
491                         {
492                                 in0[easyCaseNdx*scalarSize + compNdx] = easyCases[easyCaseNdx].x & integerMask;
493                                 in1[easyCaseNdx*scalarSize + compNdx] = easyCases[easyCaseNdx].y & integerMask;
494                         }
495                 }
496
497                 // convert to signed
498                 if (isSigned)
499                 {
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] = extendSignTo32(in0[easyCaseNdx*scalarSize + compNdx], integerLength);
505                                         in1[easyCaseNdx*scalarSize + compNdx] = extendSignTo32(in1[easyCaseNdx*scalarSize + compNdx], integerLength);
506                                 }
507                         }
508                 }
509
510                 generateRandomInputData(rnd, m_shaderType, type, precision, in0, numValues - DE_LENGTH_OF_ARRAY(easyCases));
511                 generateRandomInputData(rnd, m_shaderType, type, precision, in1, numValues - DE_LENGTH_OF_ARRAY(easyCases));
512         }
513
514         bool compare (const void* const* inputs, const void* const* outputs)
515         {
516                 const glu::DataType             type                    = m_spec.inputs[0].varType.getBasicType();
517                 const glu::Precision    precision               = m_spec.inputs[0].varType.getPrecision();
518                 const int                               scalarSize              = glu::getDataTypeScalarSize(type);
519                 const int                               integerLength   = getShaderUintBitCount(m_shaderType, precision);
520                 const deUint32                  mask0                   = getLowBitMask(integerLength);
521
522                 for (int compNdx = 0; compNdx < scalarSize; compNdx++)
523                 {
524                         const deUint32  in0             = ((const deUint32*)inputs[0])[compNdx];
525                         const deUint32  in1             = ((const deUint32*)inputs[1])[compNdx];
526                         const deUint32  out0    = ((const deUint32*)outputs[0])[compNdx];
527                         const deUint32  out1    = ((const deUint32*)outputs[1])[compNdx];
528                         const deUint32  ref0    = in0+in1;
529                         const deUint32  ref1    = (deUint64(in0)+deUint64(in1)) > 0xffffffffu ? 1u : 0u;
530
531                         if (((out0&mask0) != (ref0&mask0)) || out1 != ref1)
532                         {
533                                 m_failMsg << "Expected [" << compNdx << "] = " << tcu::toHex(ref0) << ", " << tcu::toHex(ref1);
534                                 return false;
535                         }
536                 }
537
538                 return true;
539         }
540 };
541
542 class UaddCarryCase : public IntegerFunctionCase
543 {
544 public:
545         UaddCarryCase (tcu::TestContext& testCtx, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
546                 : IntegerFunctionCase   (testCtx, getIntegerFuncCaseName(baseType, precision, shaderType).c_str(), "uaddCarry", shaderType)
547         {
548                 m_spec.inputs.push_back(Symbol("x", glu::VarType(baseType, precision)));
549                 m_spec.inputs.push_back(Symbol("y", glu::VarType(baseType, precision)));
550                 m_spec.outputs.push_back(Symbol("sum", glu::VarType(baseType, precision)));
551                 m_spec.outputs.push_back(Symbol("carry", glu::VarType(baseType, glu::PRECISION_LOWP)));
552                 m_spec.source = "sum = uaddCarry(x, y, carry);";
553         }
554
555         TestInstance* createInstance (Context& ctx) const
556         {
557                 return new UaddCarryCaseInstance(ctx, m_shaderType, m_spec, m_numValues, getName());
558         }
559 };
560
561 class UsubBorrowCaseInstance : public IntegerFunctionTestInstance
562 {
563 public:
564         UsubBorrowCaseInstance (Context& context, glu::ShaderType shaderType, const ShaderSpec& spec, int numValues, const char* name)
565                 : IntegerFunctionTestInstance   (context, shaderType, spec, numValues, name)
566         {
567         }
568
569         void getInputValues (int numValues, void* const* values) const
570         {
571                 de::Random                              rnd                             (deStringHash(m_name) ^ 0x235facu);
572                 const glu::DataType             type                    = m_spec.inputs[0].varType.getBasicType();
573                 const glu::Precision    precision               = m_spec.inputs[0].varType.getPrecision();
574                 const int                               scalarSize              = glu::getDataTypeScalarSize(type);
575                 const int                               integerLength   = getShaderUintBitCount(m_shaderType, precision);
576                 const deUint32                  integerMask             = getLowBitMask(integerLength);
577                 const bool                              isSigned                = glu::isDataTypeIntOrIVec(type);
578                 deUint32*                               in0                             = (deUint32*)values[0];
579                 deUint32*                               in1                             = (deUint32*)values[1];
580
581                 const struct
582                 {
583                         deUint32        x;
584                         deUint32        y;
585                 } easyCases[] =
586                 {
587                         { 0x00000000u,  0x00000000u },
588                         { 0x00000001u,  0x00000001u },
589                         { 0x00000001u,  0x00000002u },
590                         { 0x00000001u,  0xffffffffu },
591                         { 0xfffffffeu,  0xffffffffu },
592                         { 0xffffffffu,  0xffffffffu },
593                 };
594
595                 // generate integers with proper bit count
596                 for (int easyCaseNdx = 0; easyCaseNdx < DE_LENGTH_OF_ARRAY(easyCases); easyCaseNdx++)
597                 {
598                         for (int compNdx = 0; compNdx < scalarSize; compNdx++)
599                         {
600                                 in0[easyCaseNdx*scalarSize + compNdx] = easyCases[easyCaseNdx].x & integerMask;
601                                 in1[easyCaseNdx*scalarSize + compNdx] = easyCases[easyCaseNdx].y & integerMask;
602                         }
603                 }
604
605                 // convert to signed
606                 if (isSigned)
607                 {
608                         for (int easyCaseNdx = 0; easyCaseNdx < DE_LENGTH_OF_ARRAY(easyCases); easyCaseNdx++)
609                         {
610                                 for (int compNdx = 0; compNdx < scalarSize; compNdx++)
611                                 {
612                                         in0[easyCaseNdx*scalarSize + compNdx] = extendSignTo32(in0[easyCaseNdx*scalarSize + compNdx], integerLength);
613                                         in1[easyCaseNdx*scalarSize + compNdx] = extendSignTo32(in1[easyCaseNdx*scalarSize + compNdx], integerLength);
614                                 }
615                         }
616                 }
617
618                 generateRandomInputData(rnd, m_shaderType, type, precision, in0, numValues - DE_LENGTH_OF_ARRAY(easyCases));
619                 generateRandomInputData(rnd, m_shaderType, type, precision, in1, numValues - DE_LENGTH_OF_ARRAY(easyCases));
620         }
621
622         bool compare (const void* const* inputs, const void* const* outputs)
623         {
624                 const glu::DataType             type                    = m_spec.inputs[0].varType.getBasicType();
625                 const glu::Precision    precision               = m_spec.inputs[0].varType.getPrecision();
626                 const int                               scalarSize              = glu::getDataTypeScalarSize(type);
627                 const int                               integerLength   = getShaderUintBitCount(m_shaderType, precision);
628                 const deUint32                  mask0                   = getLowBitMask(integerLength);
629
630                 for (int compNdx = 0; compNdx < scalarSize; compNdx++)
631                 {
632                         const deUint32  in0             = ((const deUint32*)inputs[0])[compNdx];
633                         const deUint32  in1             = ((const deUint32*)inputs[1])[compNdx];
634                         const deUint32  out0    = ((const deUint32*)outputs[0])[compNdx];
635                         const deUint32  out1    = ((const deUint32*)outputs[1])[compNdx];
636                         const deUint32  ref0    = in0-in1;
637                         const deUint32  ref1    = in0 >= in1 ? 0u : 1u;
638
639                         if (((out0&mask0) != (ref0&mask0)) || out1 != ref1)
640                         {
641                                 m_failMsg << "Expected [" << compNdx << "] = " << tcu::toHex(ref0) << ", " << tcu::toHex(ref1);
642                                 return false;
643                         }
644                 }
645
646                 return true;
647         }
648 };
649
650 class UsubBorrowCase : public IntegerFunctionCase
651 {
652 public:
653         UsubBorrowCase (tcu::TestContext& testCtx, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
654                 : IntegerFunctionCase   (testCtx, getIntegerFuncCaseName(baseType, precision, shaderType).c_str(), "usubBorrow", shaderType)
655         {
656                 m_spec.inputs.push_back(Symbol("x", glu::VarType(baseType, precision)));
657                 m_spec.inputs.push_back(Symbol("y", glu::VarType(baseType, precision)));
658                 m_spec.outputs.push_back(Symbol("diff", glu::VarType(baseType, precision)));
659                 m_spec.outputs.push_back(Symbol("carry", glu::VarType(baseType, glu::PRECISION_LOWP)));
660                 m_spec.source = "diff = usubBorrow(x, y, carry);";
661         }
662
663         TestInstance* createInstance (Context& ctx) const
664         {
665                 return new UsubBorrowCaseInstance(ctx, m_shaderType, m_spec, m_numValues, getName());
666         }
667 };
668
669 class UmulExtendedCaseInstance : public IntegerFunctionTestInstance
670 {
671 public:
672         UmulExtendedCaseInstance (Context& context, glu::ShaderType shaderType, const ShaderSpec& spec, int numValues, const char* name)
673                 : IntegerFunctionTestInstance   (context, shaderType, spec, numValues, name)
674         {
675         }
676
677         void getInputValues (int numValues, void* const* values) const
678         {
679                 de::Random                              rnd                     (deStringHash(m_name) ^ 0x235facu);
680                 const glu::DataType             type            = m_spec.inputs[0].varType.getBasicType();
681 //              const glu::Precision    precision       = m_spec.inputs[0].varType.getPrecision();
682                 const int                               scalarSize      = glu::getDataTypeScalarSize(type);
683                 deUint32*                               in0                     = (deUint32*)values[0];
684                 deUint32*                               in1                     = (deUint32*)values[1];
685                 int                                             valueNdx        = 0;
686
687                 const struct
688                 {
689                         deUint32        x;
690                         deUint32        y;
691                 } easyCases[] =
692                 {
693                         { 0x00000000u,  0x00000000u },
694                         { 0xffffffffu,  0x00000001u },
695                         { 0xffffffffu,  0x00000002u },
696                         { 0x00000001u,  0xffffffffu },
697                         { 0x00000002u,  0xffffffffu },
698                         { 0xffffffffu,  0xffffffffu },
699                 };
700
701                 for (int easyCaseNdx = 0; easyCaseNdx < DE_LENGTH_OF_ARRAY(easyCases); easyCaseNdx++)
702                 {
703                         for (int compNdx = 0; compNdx < scalarSize; compNdx++)
704                         {
705                                 in0[valueNdx*scalarSize + compNdx] = easyCases[easyCaseNdx].x;
706                                 in1[valueNdx*scalarSize + compNdx] = easyCases[easyCaseNdx].y;
707                         }
708
709                         valueNdx += 1;
710                 }
711
712                 while (valueNdx < numValues)
713                 {
714                         for (int compNdx = 0; compNdx < scalarSize; compNdx++)
715                         {
716                                 const deUint32  base0   = rnd.getUint32();
717                                 const deUint32  base1   = rnd.getUint32();
718                                 const int               adj0    = rnd.getInt(0, 20);
719                                 const int               adj1    = rnd.getInt(0, 20);
720                                 in0[valueNdx*scalarSize + compNdx] = base0 >> adj0;
721                                 in1[valueNdx*scalarSize + compNdx] = base1 >> adj1;
722                         }
723
724                         valueNdx += 1;
725                 }
726         }
727
728         bool compare (const void* const* inputs, const void* const* outputs)
729         {
730                 const glu::DataType             type                    = m_spec.inputs[0].varType.getBasicType();
731                 const int                               scalarSize              = glu::getDataTypeScalarSize(type);
732
733                 for (int compNdx = 0; compNdx < scalarSize; compNdx++)
734                 {
735                         const deUint32  in0             = ((const deUint32*)inputs[0])[compNdx];
736                         const deUint32  in1             = ((const deUint32*)inputs[1])[compNdx];
737                         const deUint32  out0    = ((const deUint32*)outputs[0])[compNdx];
738                         const deUint32  out1    = ((const deUint32*)outputs[1])[compNdx];
739                         const deUint64  mul64   = deUint64(in0)*deUint64(in1);
740                         const deUint32  ref0    = deUint32(mul64 >> 32);
741                         const deUint32  ref1    = deUint32(mul64 & 0xffffffffu);
742
743                         if (out0 != ref0 || out1 != ref1)
744                         {
745                                 m_failMsg << "Expected [" << compNdx << "] = " << tcu::toHex(ref0) << ", " << tcu::toHex(ref1);
746                                 return false;
747                         }
748                 }
749
750                 return true;
751         }
752 };
753
754 class UmulExtendedCase : public IntegerFunctionCase
755 {
756 public:
757         UmulExtendedCase (tcu::TestContext& testCtx, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
758                 : IntegerFunctionCase   (testCtx, getIntegerFuncCaseName(baseType, precision, shaderType).c_str(), "umulExtended", shaderType)
759         {
760                 m_spec.inputs.push_back(Symbol("x", glu::VarType(baseType, precision)));
761                 m_spec.inputs.push_back(Symbol("y", glu::VarType(baseType, precision)));
762                 m_spec.outputs.push_back(Symbol("msb", glu::VarType(baseType, precision)));
763                 m_spec.outputs.push_back(Symbol("lsb", glu::VarType(baseType, precision)));
764                 m_spec.source = "umulExtended(x, y, msb, lsb);";
765         }
766
767         TestInstance* createInstance (Context& ctx) const
768         {
769                 return new UmulExtendedCaseInstance(ctx, m_shaderType, m_spec, m_numValues, getName());
770         }
771 };
772
773 class ImulExtendedCaseInstance : public IntegerFunctionTestInstance
774 {
775 public:
776         ImulExtendedCaseInstance (Context& context, glu::ShaderType shaderType, const ShaderSpec& spec, int numValues, const char* name)
777                 : IntegerFunctionTestInstance   (context, shaderType, spec, numValues, name)
778         {
779         }
780
781         void getInputValues (int numValues, void* const* values) const
782         {
783                 de::Random                              rnd                     (deStringHash(m_name) ^ 0x224fa1u);
784                 const glu::DataType             type            = m_spec.inputs[0].varType.getBasicType();
785 //              const glu::Precision    precision       = m_spec.inputs[0].varType.getPrecision();
786                 const int                               scalarSize      = glu::getDataTypeScalarSize(type);
787                 deUint32*                               in0                     = (deUint32*)values[0];
788                 deUint32*                               in1                     = (deUint32*)values[1];
789                 int                                             valueNdx        = 0;
790
791                 const struct
792                 {
793                         deUint32        x;
794                         deUint32        y;
795                 } easyCases[] =
796                 {
797                         { 0x00000000u,  0x00000000u },
798                         { 0xffffffffu,  0x00000002u },
799                         { 0x7fffffffu,  0x00000001u },
800                         { 0x7fffffffu,  0x00000002u },
801                         { 0x7fffffffu,  0x7fffffffu },
802                         { 0xffffffffu,  0xffffffffu },
803                         { 0x7fffffffu,  0xfffffffeu },
804                 };
805
806                 for (int easyCaseNdx = 0; easyCaseNdx < DE_LENGTH_OF_ARRAY(easyCases); easyCaseNdx++)
807                 {
808                         for (int compNdx = 0; compNdx < scalarSize; compNdx++)
809                         {
810                                 in0[valueNdx*scalarSize + compNdx] = (deInt32)easyCases[easyCaseNdx].x;
811                                 in1[valueNdx*scalarSize + compNdx] = (deInt32)easyCases[easyCaseNdx].y;
812                         }
813
814                         valueNdx += 1;
815                 }
816
817                 while (valueNdx < numValues)
818                 {
819                         for (int compNdx = 0; compNdx < scalarSize; compNdx++)
820                         {
821                                 const deInt32   base0   = (deInt32)rnd.getUint32();
822                                 const deInt32   base1   = (deInt32)rnd.getUint32();
823                                 const int               adj0    = rnd.getInt(0, 20);
824                                 const int               adj1    = rnd.getInt(0, 20);
825                                 in0[valueNdx*scalarSize + compNdx] = base0 >> adj0;
826                                 in1[valueNdx*scalarSize + compNdx] = base1 >> adj1;
827                         }
828
829                         valueNdx += 1;
830                 }
831         }
832
833         bool compare (const void* const* inputs, const void* const* outputs)
834         {
835                 const glu::DataType             type                    = m_spec.inputs[0].varType.getBasicType();
836                 const int                               scalarSize              = glu::getDataTypeScalarSize(type);
837
838                 for (int compNdx = 0; compNdx < scalarSize; compNdx++)
839                 {
840                         const deInt32   in0             = ((const deInt32*)inputs[0])[compNdx];
841                         const deInt32   in1             = ((const deInt32*)inputs[1])[compNdx];
842                         const deInt32   out0    = ((const deInt32*)outputs[0])[compNdx];
843                         const deInt32   out1    = ((const deInt32*)outputs[1])[compNdx];
844                         const deInt64   mul64   = deInt64(in0)*deInt64(in1);
845                         const deInt32   ref0    = deInt32(mul64 >> 32);
846                         const deInt32   ref1    = deInt32(mul64 & 0xffffffffu);
847
848                         if (out0 != ref0 || out1 != ref1)
849                         {
850                                 m_failMsg << "Expected [" << compNdx << "] = " << tcu::toHex(ref0) << ", " << tcu::toHex(ref1);
851                                 return false;
852                         }
853                 }
854
855                 return true;
856         }
857 };
858
859 class ImulExtendedCase : public IntegerFunctionCase
860 {
861 public:
862         ImulExtendedCase (tcu::TestContext& testCtx, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
863                 : IntegerFunctionCase   (testCtx, getIntegerFuncCaseName(baseType, precision, shaderType).c_str(), "imulExtended", shaderType)
864         {
865                 m_spec.inputs.push_back(Symbol("x", glu::VarType(baseType, precision)));
866                 m_spec.inputs.push_back(Symbol("y", glu::VarType(baseType, precision)));
867                 m_spec.outputs.push_back(Symbol("msb", glu::VarType(baseType, precision)));
868                 m_spec.outputs.push_back(Symbol("lsb", glu::VarType(baseType, precision)));
869                 m_spec.source = "imulExtended(x, y, msb, lsb);";
870         }
871
872         TestInstance* createInstance (Context& ctx) const
873         {
874                 return new ImulExtendedCaseInstance(ctx, m_shaderType, m_spec, m_numValues, getName());
875         }
876 };
877
878 class BitfieldExtractCaseInstance : public IntegerFunctionTestInstance
879 {
880 public:
881         BitfieldExtractCaseInstance (Context& context, glu::ShaderType shaderType, const ShaderSpec& spec, int numValues, const char* name)
882                 : IntegerFunctionTestInstance   (context, shaderType, spec, numValues, name)
883         {
884         }
885
886         void getInputValues (int numValues, void* const* values) const
887         {
888                 de::Random                              rnd                     (deStringHash(m_name) ^ 0xa113fca2u);
889                 const glu::DataType             type            = m_spec.inputs[0].varType.getBasicType();
890                 const glu::Precision    precision       = m_spec.inputs[0].varType.getPrecision();
891                 const bool                              ignoreSign      = precision != glu::PRECISION_HIGHP && glu::isDataTypeIntOrIVec(type);
892                 const int                               numBits         = getShaderUintBitCount(m_shaderType, precision) - (ignoreSign ? 1 : 0);
893                 deUint32*                               inValue         = (deUint32*)values[0];
894                 int*                                    inOffset        = (int*)values[1];
895                 int*                                    inBits          = (int*)values[2];
896
897                 for (int valueNdx = 0; valueNdx < numValues; ++valueNdx)
898                 {
899                         const int               bits    = rnd.getInt(0, numBits);
900                         const int               offset  = rnd.getInt(0, numBits-bits);
901
902                         inOffset[valueNdx]      = offset;
903                         inBits[valueNdx]        = bits;
904                 }
905
906                 generateRandomInputData(rnd, m_shaderType, type, precision, inValue, numValues);
907         }
908
909         bool compare (const void* const* inputs, const void* const* outputs)
910         {
911                 const glu::DataType             type                    = m_spec.inputs[0].varType.getBasicType();
912                 const bool                              isSigned                = glu::isDataTypeIntOrIVec(type);
913                 const int                               scalarSize              = glu::getDataTypeScalarSize(type);
914                 const int                               offset                  = *((const int*)inputs[1]);
915                 const int                               bits                    = *((const int*)inputs[2]);
916
917                 for (int compNdx = 0; compNdx < scalarSize; compNdx++)
918                 {
919                         const deUint32  value   = ((const deUint32*)inputs[0])[compNdx];
920                         const deUint32  out             = ((const deUint32*)outputs[0])[compNdx];
921                         const deUint32  valMask = (bits == 32 ? ~0u : ((1u<<bits)-1u));
922                         const deUint32  baseVal = (offset == 32) ? (0) : ((value >> offset) & valMask);
923                         const deUint32  ref             = baseVal | ((isSigned && (baseVal & (1<<(bits-1)))) ? ~valMask : 0u);
924
925                         if (out != ref)
926                         {
927                                 m_failMsg << "Expected [" << compNdx << "] = " << tcu::toHex(ref);
928                                 return false;
929                         }
930                 }
931
932                 return true;
933         }
934 };
935
936 class BitfieldExtractCase : public IntegerFunctionCase
937 {
938 public:
939         BitfieldExtractCase (tcu::TestContext& testCtx, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
940                 : IntegerFunctionCase   (testCtx, getIntegerFuncCaseName(baseType, precision, shaderType).c_str(), "bitfieldExtract", shaderType)
941         {
942                 m_spec.inputs.push_back(Symbol("value", glu::VarType(baseType, precision)));
943                 m_spec.inputs.push_back(Symbol("offset", glu::VarType(glu::TYPE_INT, precision)));
944                 m_spec.inputs.push_back(Symbol("bits", glu::VarType(glu::TYPE_INT, precision)));
945                 m_spec.outputs.push_back(Symbol("extracted", glu::VarType(baseType, precision)));
946                 m_spec.source = "extracted = bitfieldExtract(value, offset, bits);";
947         }
948
949         TestInstance* createInstance (Context& ctx) const
950         {
951                 return new BitfieldExtractCaseInstance(ctx, m_shaderType, m_spec, m_numValues, getName());
952         }
953 };
954
955 class BitfieldInsertCaseInstance : public IntegerFunctionTestInstance
956 {
957 public:
958         BitfieldInsertCaseInstance (Context& context, glu::ShaderType shaderType, const ShaderSpec& spec, int numValues, const char* name)
959                 : IntegerFunctionTestInstance   (context, shaderType, spec, numValues, name)
960         {
961         }
962
963         void getInputValues (int numValues, void* const* values) const
964         {
965                 de::Random                              rnd                     (deStringHash(m_name) ^ 0x12c2acff);
966                 const glu::DataType             type            = m_spec.inputs[0].varType.getBasicType();
967                 const glu::Precision    precision       = m_spec.inputs[0].varType.getPrecision();
968                 const int                               numBits         = getShaderUintBitCount(m_shaderType, precision);
969                 deUint32*                               inBase          = (deUint32*)values[0];
970                 deUint32*                               inInsert        = (deUint32*)values[1];
971                 int*                                    inOffset        = (int*)values[2];
972                 int*                                    inBits          = (int*)values[3];
973
974                 for (int valueNdx = 0; valueNdx < numValues; ++valueNdx)
975                 {
976                         const int bits          = rnd.getInt(0, numBits);
977                         const int offset        = rnd.getInt(0, numBits-bits);
978
979                         inOffset[valueNdx]      = offset;
980                         inBits[valueNdx]        = bits;
981                 }
982
983                 generateRandomInputData(rnd, m_shaderType, type, precision, inBase, numValues);
984                 generateRandomInputData(rnd, m_shaderType, type, precision, inInsert, numValues);
985         }
986
987         bool compare (const void* const* inputs, const void* const* outputs)
988         {
989                 const glu::DataType             type                    = m_spec.inputs[0].varType.getBasicType();
990                 const glu::Precision    precision               = m_spec.inputs[0].varType.getPrecision();
991                 const int                               scalarSize              = glu::getDataTypeScalarSize(type);
992                 const int                               integerLength   = getShaderUintBitCount(m_shaderType, precision);
993                 const deUint32                  cmpMask                 = getLowBitMask(integerLength);
994                 const int                               offset                  = *((const int*)inputs[2]);
995                 const int                               bits                    = *((const int*)inputs[3]);
996
997                 for (int compNdx = 0; compNdx < scalarSize; compNdx++)
998                 {
999                         const deUint32  base    = ((const deUint32*)inputs[0])[compNdx];
1000                         const deUint32  insert  = ((const deUint32*)inputs[1])[compNdx];
1001                         const deInt32   out             = ((const deUint32*)outputs[0])[compNdx];
1002
1003                         const deUint32  mask    = bits == 32 ? ~0u : (1u<<bits)-1;
1004                         const deUint32  ref             = (base & ~(mask<<offset)) | ((insert & mask)<<offset);
1005
1006                         if ((out&cmpMask) != (ref&cmpMask))
1007                         {
1008                                 m_failMsg << "Expected [" << compNdx << "] = " << tcu::toHex(ref);
1009                                 return false;
1010                         }
1011                 }
1012
1013                 return true;
1014         }
1015 };
1016
1017 class BitfieldInsertCase : public IntegerFunctionCase
1018 {
1019 public:
1020         BitfieldInsertCase (tcu::TestContext& testCtx, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
1021                 : IntegerFunctionCase   (testCtx, getIntegerFuncCaseName(baseType, precision, shaderType).c_str(), "bitfieldInsert", shaderType)
1022         {
1023                 m_spec.inputs.push_back(Symbol("base", glu::VarType(baseType, precision)));
1024                 m_spec.inputs.push_back(Symbol("insert", glu::VarType(baseType, precision)));
1025                 m_spec.inputs.push_back(Symbol("offset", glu::VarType(glu::TYPE_INT, precision)));
1026                 m_spec.inputs.push_back(Symbol("bits", glu::VarType(glu::TYPE_INT, precision)));
1027                 m_spec.outputs.push_back(Symbol("result", glu::VarType(baseType, precision)));
1028                 m_spec.source = "result = bitfieldInsert(base, insert, offset, bits);";
1029         }
1030
1031         TestInstance* createInstance (Context& ctx) const
1032         {
1033                 return new BitfieldInsertCaseInstance(ctx, m_shaderType, m_spec, m_numValues, getName());
1034         }
1035 };
1036
1037 class BitfieldReverseCaseInstance : public IntegerFunctionTestInstance
1038 {
1039 public:
1040         BitfieldReverseCaseInstance (Context& context, glu::ShaderType shaderType, const ShaderSpec& spec, int numValues, const char* name)
1041                 : IntegerFunctionTestInstance   (context, shaderType, spec, numValues, name)
1042         {
1043         }
1044
1045         void getInputValues (int numValues, void* const* values) const
1046         {
1047                 de::Random                              rnd                     (deStringHash(m_name) ^ 0xff23a4);
1048                 const glu::DataType             type            = m_spec.inputs[0].varType.getBasicType();
1049                 const glu::Precision    precision       = m_spec.inputs[0].varType.getPrecision();
1050                 deUint32*                               inValue         = (deUint32*)values[0];
1051
1052                 generateRandomInputData(rnd, m_shaderType, type, precision, inValue, numValues);
1053         }
1054
1055         bool compare (const void* const* inputs, const void* const* outputs)
1056         {
1057                 const glu::DataType             type                    = m_spec.inputs[0].varType.getBasicType();
1058                 const glu::Precision    precision               = m_spec.inputs[0].varType.getPrecision();
1059                 const int                               integerLength   = getShaderUintBitCount(m_shaderType, precision);
1060                 const int                               scalarSize              = glu::getDataTypeScalarSize(type);
1061                 const deUint32                  cmpMask                 = reverseBits(getLowBitMask(integerLength));
1062
1063                 for (int compNdx = 0; compNdx < scalarSize; compNdx++)
1064                 {
1065                         const deUint32  value   = ((const deUint32*)inputs[0])[compNdx];
1066                         const deInt32   out             = ((const deUint32*)outputs[0])[compNdx];
1067                         const deUint32  ref             = reverseBits(value);
1068
1069                         if ((out&cmpMask) != (ref&cmpMask))
1070                         {
1071                                 m_failMsg << "Expected [" << compNdx << "] = " << tcu::toHex(ref);
1072                                 return false;
1073                         }
1074                 }
1075
1076                 return true;
1077         }
1078 };
1079
1080 class BitfieldReverseCase : public IntegerFunctionCase
1081 {
1082 public:
1083         BitfieldReverseCase (tcu::TestContext& testCtx, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
1084                 : IntegerFunctionCase   (testCtx, getIntegerFuncCaseName(baseType, precision, shaderType).c_str(), "bitfieldReverse", shaderType)
1085         {
1086                 m_spec.inputs.push_back(Symbol("value", glu::VarType(baseType, precision)));
1087                 m_spec.outputs.push_back(Symbol("result", glu::VarType(baseType, glu::PRECISION_HIGHP)));
1088                 m_spec.source = "result = bitfieldReverse(value);";
1089         }
1090
1091         TestInstance* createInstance (Context& ctx) const
1092         {
1093                 return new BitfieldReverseCaseInstance(ctx, m_shaderType, m_spec, m_numValues, getName());
1094         }
1095 };
1096
1097 class BitCountCaseInstance : public IntegerFunctionTestInstance
1098 {
1099 public:
1100         BitCountCaseInstance (Context& context, glu::ShaderType shaderType, const ShaderSpec& spec, int numValues, const char* name)
1101                 : IntegerFunctionTestInstance   (context, shaderType, spec, numValues, name)
1102         {
1103         }
1104
1105         void getInputValues (int numValues, void* const* values) const
1106         {
1107                 de::Random                              rnd                     (deStringHash(m_name) ^ 0xab2cca4);
1108                 const glu::DataType             type            = m_spec.inputs[0].varType.getBasicType();
1109                 const glu::Precision    precision       = m_spec.inputs[0].varType.getPrecision();
1110                 deUint32*                               inValue         = (deUint32*)values[0];
1111
1112                 generateRandomInputData(rnd, m_shaderType, type, precision, inValue, numValues);
1113         }
1114
1115         bool compare (const void* const* inputs, const void* const* outputs)
1116         {
1117                 const glu::DataType             type                    = m_spec.inputs[0].varType.getBasicType();
1118                 const glu::Precision    precision               = m_spec.inputs[0].varType.getPrecision();
1119                 const int                               integerLength   = getShaderUintBitCount(m_shaderType, precision);
1120                 const int                               scalarSize              = glu::getDataTypeScalarSize(type);
1121                 const deUint32                  countMask               = getLowBitMask(integerLength);
1122
1123                 for (int compNdx = 0; compNdx < scalarSize; compNdx++)
1124                 {
1125                         const deUint32  value   = ((const deUint32*)inputs[0])[compNdx];
1126                         const int               out             = ((const int*)outputs[0])[compNdx];
1127                         const int               minRef  = dePop32(value&countMask);
1128                         const int               maxRef  = dePop32(value);
1129
1130                         if (!de::inRange(out, minRef, maxRef))
1131                         {
1132                                 m_failMsg << "Expected [" << compNdx << "] in range [" << minRef << ", " << maxRef << "]";
1133                                 return false;
1134                         }
1135                 }
1136
1137                 return true;
1138         }
1139 };
1140
1141 class BitCountCase : public IntegerFunctionCase
1142 {
1143 public:
1144         BitCountCase (tcu::TestContext& testCtx, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
1145                 : IntegerFunctionCase   (testCtx, getIntegerFuncCaseName(baseType, precision, shaderType).c_str(), "bitCount", shaderType)
1146         {
1147                 const int                       vecSize         = glu::getDataTypeScalarSize(baseType);
1148                 const glu::DataType     intType         = vecSize == 1 ? glu::TYPE_INT : glu::getDataTypeIntVec(vecSize);
1149
1150                 m_spec.inputs.push_back(Symbol("value", glu::VarType(baseType, precision)));
1151                 m_spec.outputs.push_back(Symbol("count", glu::VarType(intType, glu::PRECISION_MEDIUMP)));
1152                 m_spec.source = "count = bitCount(value);";
1153         }
1154
1155         TestInstance* createInstance (Context& ctx) const
1156         {
1157                 return new BitCountCaseInstance(ctx, m_shaderType, m_spec, m_numValues, getName());
1158         }
1159 };
1160
1161 class FindLSBCaseInstance : public IntegerFunctionTestInstance
1162 {
1163 public:
1164         FindLSBCaseInstance (Context& context, glu::ShaderType shaderType, const ShaderSpec& spec, int numValues, const char* name)
1165                 : IntegerFunctionTestInstance   (context, shaderType, spec, numValues, name)
1166         {
1167         }
1168
1169         void getInputValues (int numValues, void* const* values) const
1170         {
1171                 de::Random                              rnd                     (deStringHash(m_name) ^ 0x9923c2af);
1172                 const glu::DataType             type            = m_spec.inputs[0].varType.getBasicType();
1173                 const glu::Precision    precision       = m_spec.inputs[0].varType.getPrecision();
1174                 deUint32*                               inValue         = (deUint32*)values[0];
1175
1176                 generateRandomInputData(rnd, m_shaderType, type, precision, inValue, numValues);
1177         }
1178
1179         bool compare (const void* const* inputs, const void* const* outputs)
1180         {
1181                 const glu::DataType             type                    = m_spec.inputs[0].varType.getBasicType();
1182                 const glu::Precision    precision               = m_spec.inputs[0].varType.getPrecision();
1183                 const int                               scalarSize              = glu::getDataTypeScalarSize(type);
1184                 const int                               integerLength   = getShaderUintBitCount(m_shaderType, precision);
1185                 const deUint32                  mask                    = getLowBitMask(integerLength);
1186
1187                 for (int compNdx = 0; compNdx < scalarSize; compNdx++)
1188                 {
1189                         const deUint32  value   = ((const deUint32*)inputs[0])[compNdx];
1190                         const int               out             = ((const int*)outputs[0])[compNdx];
1191                         const int               minRef  = findLSB(value&mask);
1192                         const int               maxRef  = findLSB(value);
1193
1194                         if (!de::inRange(out, minRef, maxRef))
1195                         {
1196                                 m_failMsg << "Expected [" << compNdx << "] in range [" << minRef << ", " << maxRef << "]";
1197                                 return false;
1198                         }
1199                 }
1200
1201                 return true;
1202         }
1203 };
1204
1205 class FindLSBCase : public IntegerFunctionCase
1206 {
1207 public:
1208         FindLSBCase (tcu::TestContext& testCtx, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
1209                 : IntegerFunctionCase   (testCtx, getIntegerFuncCaseName(baseType, precision, shaderType).c_str(), "findLSB", shaderType)
1210         {
1211                 const int                       vecSize         = glu::getDataTypeScalarSize(baseType);
1212                 const glu::DataType     intType         = vecSize == 1 ? glu::TYPE_INT : glu::getDataTypeIntVec(vecSize);
1213
1214                 m_spec.inputs.push_back(Symbol("value", glu::VarType(baseType, precision)));
1215                 m_spec.outputs.push_back(Symbol("lsb", glu::VarType(intType, glu::PRECISION_LOWP)));
1216                 m_spec.source = "lsb = findLSB(value);";
1217         }
1218
1219         TestInstance* createInstance (Context& ctx) const
1220         {
1221                 return new FindLSBCaseInstance(ctx, m_shaderType, m_spec, m_numValues, getName());
1222         }
1223 };
1224
1225 class findMSBCaseInstance : public IntegerFunctionTestInstance
1226 {
1227 public:
1228         findMSBCaseInstance (Context& context, glu::ShaderType shaderType, const ShaderSpec& spec, int numValues, const char* name)
1229                 : IntegerFunctionTestInstance   (context, shaderType, spec, numValues, name)
1230         {
1231         }
1232
1233         void getInputValues (int numValues, void* const* values) const
1234         {
1235                 de::Random                              rnd                     (deStringHash(m_name) ^ 0x742ac4e);
1236                 const glu::DataType             type            = m_spec.inputs[0].varType.getBasicType();
1237                 const glu::Precision    precision       = m_spec.inputs[0].varType.getPrecision();
1238                 deUint32*                               inValue         = (deUint32*)values[0];
1239
1240                 generateRandomInputData(rnd, m_shaderType, type, precision, inValue, numValues);
1241         }
1242
1243         bool compare (const void* const* inputs, const void* const* outputs)
1244         {
1245                 const glu::DataType             type                    = m_spec.inputs[0].varType.getBasicType();
1246                 const glu::Precision    precision               = m_spec.inputs[0].varType.getPrecision();
1247                 const bool                              isSigned                = glu::isDataTypeIntOrIVec(type);
1248                 const int                               scalarSize              = glu::getDataTypeScalarSize(type);
1249                 const int                               integerLength   = getShaderUintBitCount(m_shaderType, precision);
1250
1251                 for (int compNdx = 0; compNdx < scalarSize; compNdx++)
1252                 {
1253                         const deUint32  value   = ((const deUint32*)inputs[0])[compNdx];
1254                         const int               out             = ((const deInt32*)outputs[0])[compNdx];
1255                         const int               minRef  = isSigned ? findMSB(toPrecision(deInt32(value), integerLength))        : findMSB(toPrecision(value, integerLength));
1256                         const int               maxRef  = isSigned ? findMSB(deInt32(value))                                                            : findMSB(value);
1257
1258                         if (!de::inRange(out, minRef, maxRef))
1259                         {
1260                                 m_failMsg << "Expected [" << compNdx << "] in range [" << minRef << ", " << maxRef << "]";
1261                                 return false;
1262                         }
1263                 }
1264
1265                 return true;
1266         }
1267 };
1268
1269 class findMSBCase : public IntegerFunctionCase
1270 {
1271 public:
1272         findMSBCase (tcu::TestContext& testCtx, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
1273                 : IntegerFunctionCase   (testCtx, getIntegerFuncCaseName(baseType, precision, shaderType).c_str(), "findMSB", shaderType)
1274         {
1275                 const int                       vecSize         = glu::getDataTypeScalarSize(baseType);
1276                 const glu::DataType     intType         = vecSize == 1 ? glu::TYPE_INT : glu::getDataTypeIntVec(vecSize);
1277
1278                 m_spec.inputs.push_back(Symbol("value", glu::VarType(baseType, precision)));
1279                 m_spec.outputs.push_back(Symbol("msb", glu::VarType(intType, glu::PRECISION_LOWP)));
1280                 m_spec.source = "msb = findMSB(value);";
1281         }
1282
1283         TestInstance* createInstance (Context& ctx) const
1284         {
1285                 return new findMSBCaseInstance(ctx, m_shaderType, m_spec, m_numValues, getName());
1286         }
1287 };
1288
1289 ShaderIntegerFunctionTests::ShaderIntegerFunctionTests (tcu::TestContext& testCtx)
1290         : tcu::TestCaseGroup    (testCtx, "integer", "Integer function tests")
1291 {
1292 }
1293
1294 ShaderIntegerFunctionTests::~ShaderIntegerFunctionTests (void)
1295 {
1296 }
1297
1298 void ShaderIntegerFunctionTests::init (void)
1299 {
1300         enum
1301         {
1302                 VS = (1<<glu::SHADERTYPE_VERTEX),
1303                 FS = (1<<glu::SHADERTYPE_FRAGMENT),
1304                 CS = (1<<glu::SHADERTYPE_COMPUTE),
1305                 GS = (1<<glu::SHADERTYPE_GEOMETRY),
1306                 TC = (1<<glu::SHADERTYPE_TESSELLATION_CONTROL),
1307                 TE = (1<<glu::SHADERTYPE_TESSELLATION_EVALUATION),
1308
1309                 ALL_SHADERS = VS|TC|TE|GS|FS|CS
1310         };
1311
1312         //                                                                                                                                              Int?    Uint?   AllPrec?        Shaders
1313         addFunctionCases<UaddCarryCase>                         (this,  "uaddcarry",            false,  true,   true,           ALL_SHADERS);
1314         addFunctionCases<UsubBorrowCase>                        (this,  "usubborrow",           false,  true,   true,           ALL_SHADERS);
1315         addFunctionCases<UmulExtendedCase>                      (this,  "umulextended",         false,  true,   false,          ALL_SHADERS);
1316         addFunctionCases<ImulExtendedCase>                      (this,  "imulextended",         true,   false,  false,          ALL_SHADERS);
1317         addFunctionCases<BitfieldExtractCase>           (this,  "bitfieldextract",      true,   true,   true,           ALL_SHADERS);
1318         addFunctionCases<BitfieldInsertCase>            (this,  "bitfieldinsert",       true,   true,   true,           ALL_SHADERS);
1319         addFunctionCases<BitfieldReverseCase>           (this,  "bitfieldreverse",      true,   true,   true,           ALL_SHADERS);
1320         addFunctionCases<BitCountCase>                          (this,  "bitcount",                     true,   true,   true,           ALL_SHADERS);
1321         addFunctionCases<FindLSBCase>                           (this,  "findlsb",                      true,   true,   true,           ALL_SHADERS);
1322         addFunctionCases<findMSBCase>                           (this,  "findMSB",                      true,   true,   true,           ALL_SHADERS);
1323 }
1324
1325 } // shaderexecutor
1326 } // vkt