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