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