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