1 /*------------------------------------------------------------------------- 2 * drawElements Quality Program OpenGL ES 3.0 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 Uniform API tests. 22 * 23 * \todo [2013-02-26 nuutti] Much duplication between this and ES2. 24 * Utilities to glshared? 25 *//*--------------------------------------------------------------------*/ 26 27 #include "es3fUniformApiTests.hpp" 28 #include "gluCallLogWrapper.hpp" 29 #include "gluShaderProgram.hpp" 30 #include "gluVarType.hpp" 31 #include "gluPixelTransfer.hpp" 32 #include "gluTextureUtil.hpp" 33 #include "gluTexture.hpp" 34 #include "tcuRenderTarget.hpp" 35 #include "tcuTestLog.hpp" 36 #include "tcuSurface.hpp" 37 #include "tcuCommandLine.hpp" 38 #include "deRandom.hpp" 39 #include "deStringUtil.hpp" 40 #include "deString.h" 41 #include "deSharedPtr.hpp" 42 #include "deMemory.h" 43 44 #include "glwEnums.hpp" 45 #include "glwFunctions.hpp" 46 47 #include <set> 48 #include <cstring> 49 50 using namespace glw; 51 52 namespace deqp 53 { 54 namespace gles3 55 { 56 namespace Functional 57 { 58 59 using std::vector; 60 using std::string; 61 using tcu::TestLog; 62 using tcu::ScopedLogSection; 63 using glu::ShaderProgram; 64 using glu::StructType; 65 using de::Random; 66 using de::SharedPtr; 67 68 typedef bool (* dataTypePredicate)(glu::DataType); 69 70 static const int MAX_RENDER_WIDTH = 32; 71 static const int MAX_RENDER_HEIGHT = 32; 72 static const int MAX_NUM_SAMPLER_UNIFORMS = 16; 73 74 static const glu::DataType s_testDataTypes[] = 75 { 76 glu::TYPE_FLOAT, 77 glu::TYPE_FLOAT_VEC2, 78 glu::TYPE_FLOAT_VEC3, 79 glu::TYPE_FLOAT_VEC4, 80 glu::TYPE_FLOAT_MAT2, 81 glu::TYPE_FLOAT_MAT2X3, 82 glu::TYPE_FLOAT_MAT2X4, 83 glu::TYPE_FLOAT_MAT3X2, 84 glu::TYPE_FLOAT_MAT3, 85 glu::TYPE_FLOAT_MAT3X4, 86 glu::TYPE_FLOAT_MAT4X2, 87 glu::TYPE_FLOAT_MAT4X3, 88 glu::TYPE_FLOAT_MAT4, 89 90 glu::TYPE_INT, 91 glu::TYPE_INT_VEC2, 92 glu::TYPE_INT_VEC3, 93 glu::TYPE_INT_VEC4, 94 95 glu::TYPE_UINT, 96 glu::TYPE_UINT_VEC2, 97 glu::TYPE_UINT_VEC3, 98 glu::TYPE_UINT_VEC4, 99 100 glu::TYPE_BOOL, 101 glu::TYPE_BOOL_VEC2, 102 glu::TYPE_BOOL_VEC3, 103 glu::TYPE_BOOL_VEC4, 104 105 glu::TYPE_SAMPLER_2D, 106 glu::TYPE_SAMPLER_CUBE 107 // \note We don't test all sampler types here. 108 }; 109 110 static inline int getGLInt (const glw::Functions& funcs, const deUint32 name) 111 { 112 int val = -1; 113 funcs.getIntegerv(name, &val); 114 return val; 115 } 116 117 static inline tcu::Vec4 vec4FromPtr (const float* const ptr) 118 { 119 tcu::Vec4 result; 120 for (int i = 0; i < 4; i++) 121 result[i] = ptr[i]; 122 return result; 123 } 124 125 static inline string beforeLast (const string& str, const char c) 126 { 127 return str.substr(0, str.find_last_of(c)); 128 } 129 130 static inline void fillWithColor (const tcu::PixelBufferAccess& access, const tcu::Vec4& color) 131 { 132 for (int z = 0; z < access.getDepth(); z++) 133 for (int y = 0; y < access.getHeight(); y++) 134 for (int x = 0; x < access.getWidth(); x++) 135 access.setPixel(color, x, y, z); 136 } 137 138 static inline int getSamplerNumLookupDimensions (const glu::DataType type) 139 { 140 switch (type) 141 { 142 case glu::TYPE_SAMPLER_2D: 143 case glu::TYPE_INT_SAMPLER_2D: 144 case glu::TYPE_UINT_SAMPLER_2D: 145 return 2; 146 147 case glu::TYPE_SAMPLER_3D: 148 case glu::TYPE_INT_SAMPLER_3D: 149 case glu::TYPE_UINT_SAMPLER_3D: 150 case glu::TYPE_SAMPLER_2D_SHADOW: 151 case glu::TYPE_SAMPLER_2D_ARRAY: 152 case glu::TYPE_INT_SAMPLER_2D_ARRAY: 153 case glu::TYPE_UINT_SAMPLER_2D_ARRAY: 154 case glu::TYPE_SAMPLER_CUBE: 155 case glu::TYPE_INT_SAMPLER_CUBE: 156 case glu::TYPE_UINT_SAMPLER_CUBE: 157 return 3; 158 159 case glu::TYPE_SAMPLER_CUBE_SHADOW: 160 case glu::TYPE_SAMPLER_2D_ARRAY_SHADOW: 161 return 4; 162 163 default: 164 DE_ASSERT(false); 165 return 0; 166 } 167 } 168 169 static inline glu::DataType getSamplerLookupReturnType (const glu::DataType type) 170 { 171 switch (type) 172 { 173 case glu::TYPE_SAMPLER_2D: 174 case glu::TYPE_SAMPLER_CUBE: 175 case glu::TYPE_SAMPLER_2D_ARRAY: 176 case glu::TYPE_SAMPLER_3D: 177 return glu::TYPE_FLOAT_VEC4; 178 179 case glu::TYPE_UINT_SAMPLER_2D: 180 case glu::TYPE_UINT_SAMPLER_CUBE: 181 case glu::TYPE_UINT_SAMPLER_2D_ARRAY: 182 case glu::TYPE_UINT_SAMPLER_3D: 183 return glu::TYPE_UINT_VEC4; 184 185 case glu::TYPE_INT_SAMPLER_2D: 186 case glu::TYPE_INT_SAMPLER_CUBE: 187 case glu::TYPE_INT_SAMPLER_2D_ARRAY: 188 case glu::TYPE_INT_SAMPLER_3D: 189 return glu::TYPE_INT_VEC4; 190 191 case glu::TYPE_SAMPLER_2D_SHADOW: 192 case glu::TYPE_SAMPLER_CUBE_SHADOW: 193 case glu::TYPE_SAMPLER_2D_ARRAY_SHADOW: 194 return glu::TYPE_FLOAT; 195 196 default: 197 DE_ASSERT(false); 198 return glu::TYPE_LAST; 199 } 200 } 201 202 template<glu::DataType T> 203 static bool dataTypeEquals (const glu::DataType t) 204 { 205 return t == T; 206 } 207 208 template<int N> 209 static bool dataTypeIsMatrixWithNRows (const glu::DataType t) 210 { 211 return glu::isDataTypeMatrix(t) && glu::getDataTypeMatrixNumRows(t) == N; 212 } 213 214 static bool typeContainsMatchingBasicType (const glu::VarType& type, const dataTypePredicate predicate) 215 { 216 if (type.isBasicType()) 217 return predicate(type.getBasicType()); 218 else if (type.isArrayType()) 219 return typeContainsMatchingBasicType(type.getElementType(), predicate); 220 else 221 { 222 DE_ASSERT(type.isStructType()); 223 const StructType& structType = *type.getStructPtr(); 224 for (int i = 0; i < structType.getNumMembers(); i++) 225 if (typeContainsMatchingBasicType(structType.getMember(i).getType(), predicate)) 226 return true; 227 return false; 228 } 229 } 230 231 static void getDistinctSamplerTypes (vector<glu::DataType>& dst, const glu::VarType& type) 232 { 233 if (type.isBasicType()) 234 { 235 const glu::DataType basicType = type.getBasicType(); 236 if (glu::isDataTypeSampler(basicType) && std::find(dst.begin(), dst.end(), basicType) == dst.end()) 237 dst.push_back(basicType); 238 } 239 else if (type.isArrayType()) 240 getDistinctSamplerTypes(dst, type.getElementType()); 241 else 242 { 243 DE_ASSERT(type.isStructType()); 244 const StructType& structType = *type.getStructPtr(); 245 for (int i = 0; i < structType.getNumMembers(); i++) 246 getDistinctSamplerTypes(dst, structType.getMember(i).getType()); 247 } 248 } 249 250 static int getNumSamplersInType (const glu::VarType& type) 251 { 252 if (type.isBasicType()) 253 return glu::isDataTypeSampler(type.getBasicType()) ? 1 : 0; 254 else if (type.isArrayType()) 255 return getNumSamplersInType(type.getElementType()) * type.getArraySize(); 256 else 257 { 258 DE_ASSERT(type.isStructType()); 259 const StructType& structType = *type.getStructPtr(); 260 int sum = 0; 261 for (int i = 0; i < structType.getNumMembers(); i++) 262 sum += getNumSamplersInType(structType.getMember(i).getType()); 263 return sum; 264 } 265 } 266 267 static glu::VarType generateRandomType (const int maxDepth, int& curStructIdx, vector<const StructType*>& structTypesDst, Random& rnd) 268 { 269 const bool isStruct = maxDepth > 0 && rnd.getFloat() < 0.2f; 270 const bool isArray = rnd.getFloat() < 0.3f; 271 272 if (isStruct) 273 { 274 const int numMembers = rnd.getInt(1, 5); 275 StructType* const structType = new StructType(("structType" + de::toString(curStructIdx++)).c_str()); 276 277 for (int i = 0; i < numMembers; i++) 278 structType->addMember(("m" + de::toString(i)).c_str(), generateRandomType(maxDepth-1, curStructIdx, structTypesDst, rnd)); 279 280 structTypesDst.push_back(structType); 281 return isArray ? glu::VarType(glu::VarType(structType), rnd.getInt(1, 5)) : glu::VarType(structType); 282 } 283 else 284 { 285 const glu::DataType basicType = (glu::DataType)s_testDataTypes[rnd.getInt(0, DE_LENGTH_OF_ARRAY(s_testDataTypes)-1)]; 286 const glu::Precision precision = glu::isDataTypeBoolOrBVec(basicType) ? glu::PRECISION_LAST : glu::PRECISION_MEDIUMP; 287 return isArray ? glu::VarType(glu::VarType(basicType, precision), rnd.getInt(1, 5)) : glu::VarType(basicType, precision); 288 } 289 } 290 291 namespace 292 { 293 294 struct VarValue 295 { 296 glu::DataType type; 297 298 union 299 { 300 float floatV[4*4]; // At most mat4. \note Matrices here are column-major. 301 deInt32 intV[4]; 302 deUint32 uintV[4]; 303 bool boolV[4]; 304 struct 305 { 306 int unit; 307 union 308 { 309 float floatV[4]; 310 deInt32 intV[4]; 311 deUint32 uintV[4]; 312 } fillColor; 313 } samplerV; 314 } val; 315 }; 316 317 enum CaseShaderType 318 { 319 CASESHADERTYPE_VERTEX = 0, 320 CASESHADERTYPE_FRAGMENT, 321 CASESHADERTYPE_BOTH, 322 323 CASESHADERTYPE_LAST 324 }; 325 326 struct Uniform 327 { 328 string name; 329 glu::VarType type; 330 331 Uniform (const char* const name_, const glu::VarType& type_) : name(name_), type(type_) {} 332 }; 333 334 // A set of uniforms, along with related struct types. 335 class UniformCollection 336 { 337 public: 338 int getNumUniforms (void) const { return (int)m_uniforms.size(); } 339 int getNumStructTypes (void) const { return (int)m_structTypes.size(); } 340 Uniform& getUniform (const int ndx) { return m_uniforms[ndx]; } 341 const Uniform& getUniform (const int ndx) const { return m_uniforms[ndx]; } 342 const StructType* getStructType (const int ndx) const { return m_structTypes[ndx]; } 343 void addUniform (const Uniform& uniform) { m_uniforms.push_back(uniform); } 344 void addStructType (const StructType* const type) { m_structTypes.push_back(type); } 345 346 UniformCollection (void) {} 347 ~UniformCollection (void) 348 { 349 for (int i = 0; i < (int)m_structTypes.size(); i++) 350 delete m_structTypes[i]; 351 } 352 353 // Add the contents of m_uniforms and m_structTypes to receiver, and remove them from this one. 354 // \note receiver takes ownership of the struct types. 355 void moveContents (UniformCollection& receiver) 356 { 357 for (int i = 0; i < (int)m_uniforms.size(); i++) 358 receiver.addUniform(m_uniforms[i]); 359 m_uniforms.clear(); 360 361 for (int i = 0; i < (int)m_structTypes.size(); i++) 362 receiver.addStructType(m_structTypes[i]); 363 m_structTypes.clear(); 364 } 365 366 bool containsMatchingBasicType (const dataTypePredicate predicate) const 367 { 368 for (int i = 0; i < (int)m_uniforms.size(); i++) 369 if (typeContainsMatchingBasicType(m_uniforms[i].type, predicate)) 370 return true; 371 return false; 372 } 373 374 vector<glu::DataType> getSamplerTypes (void) const 375 { 376 vector<glu::DataType> samplerTypes; 377 for (int i = 0; i < (int)m_uniforms.size(); i++) 378 getDistinctSamplerTypes(samplerTypes, m_uniforms[i].type); 379 return samplerTypes; 380 } 381 382 bool containsSeveralSamplerTypes (void) const 383 { 384 return getSamplerTypes().size() > 1; 385 } 386 387 int getNumSamplers (void) const 388 { 389 int sum = 0; 390 for (int i = 0; i < (int)m_uniforms.size(); i++) 391 sum += getNumSamplersInType(m_uniforms[i].type); 392 return sum; 393 } 394 395 static UniformCollection* basic (const glu::DataType type, const char* const nameSuffix = "") 396 { 397 UniformCollection* const res = new UniformCollection; 398 const glu::Precision prec = glu::isDataTypeBoolOrBVec(type) ? glu::PRECISION_LAST : glu::PRECISION_MEDIUMP; 399 res->m_uniforms.push_back(Uniform((string("u_var") + nameSuffix).c_str(), glu::VarType(type, prec))); 400 return res; 401 } 402 403 static UniformCollection* basicArray (const glu::DataType type, const char* const nameSuffix = "") 404 { 405 UniformCollection* const res = new UniformCollection; 406 const glu::Precision prec = glu::isDataTypeBoolOrBVec(type) ? glu::PRECISION_LAST : glu::PRECISION_MEDIUMP; 407 res->m_uniforms.push_back(Uniform((string("u_var") + nameSuffix).c_str(), glu::VarType(glu::VarType(type, prec), 3))); 408 return res; 409 } 410 411 static UniformCollection* basicStruct (const glu::DataType type0, const glu::DataType type1, const bool containsArrays, const char* const nameSuffix = "") 412 { 413 UniformCollection* const res = new UniformCollection; 414 const glu::Precision prec0 = glu::isDataTypeBoolOrBVec(type0) ? glu::PRECISION_LAST : glu::PRECISION_MEDIUMP; 415 const glu::Precision prec1 = glu::isDataTypeBoolOrBVec(type1) ? glu::PRECISION_LAST : glu::PRECISION_MEDIUMP; 416 417 StructType* const structType = new StructType((string("structType") + nameSuffix).c_str()); 418 structType->addMember("m0", glu::VarType(type0, prec0)); 419 structType->addMember("m1", glu::VarType(type1, prec1)); 420 if (containsArrays) 421 { 422 structType->addMember("m2", glu::VarType(glu::VarType(type0, prec0), 3)); 423 structType->addMember("m3", glu::VarType(glu::VarType(type1, prec1), 3)); 424 } 425 426 res->addStructType(structType); 427 res->addUniform(Uniform((string("u_var") + nameSuffix).c_str(), glu::VarType(structType))); 428 429 return res; 430 } 431 432 static UniformCollection* structInArray (const glu::DataType type0, const glu::DataType type1, const bool containsArrays, const char* const nameSuffix = "") 433 { 434 UniformCollection* const res = basicStruct(type0, type1, containsArrays, nameSuffix); 435 res->getUniform(0).type = glu::VarType(res->getUniform(0).type, 3); 436 return res; 437 } 438 439 static UniformCollection* nestedArraysStructs (const glu::DataType type0, const glu::DataType type1, const char* const nameSuffix = "") 440 { 441 UniformCollection* const res = new UniformCollection; 442 const glu::Precision prec0 = glu::isDataTypeBoolOrBVec(type0) ? glu::PRECISION_LAST : glu::PRECISION_MEDIUMP; 443 const glu::Precision prec1 = glu::isDataTypeBoolOrBVec(type1) ? glu::PRECISION_LAST : glu::PRECISION_MEDIUMP; 444 StructType* const structType = new StructType((string("structType") + nameSuffix).c_str()); 445 StructType* const subStructType = new StructType((string("subStructType") + nameSuffix).c_str()); 446 StructType* const subSubStructType = new StructType((string("subSubStructType") + nameSuffix).c_str()); 447 448 subSubStructType->addMember("mss0", glu::VarType(type0, prec0)); 449 subSubStructType->addMember("mss1", glu::VarType(type1, prec1)); 450 451 subStructType->addMember("ms0", glu::VarType(type1, prec1)); 452 subStructType->addMember("ms1", glu::VarType(glu::VarType(type0, prec0), 2)); 453 subStructType->addMember("ms2", glu::VarType(glu::VarType(subSubStructType), 2)); 454 455 structType->addMember("m0", glu::VarType(type0, prec0)); 456 structType->addMember("m1", glu::VarType(subStructType)); 457 structType->addMember("m2", glu::VarType(type1, prec1)); 458 459 res->addStructType(subSubStructType); 460 res->addStructType(subStructType); 461 res->addStructType(structType); 462 463 res->addUniform(Uniform((string("u_var") + nameSuffix).c_str(), glu::VarType(structType))); 464 465 return res; 466 } 467 468 static UniformCollection* multipleBasic (const char* const nameSuffix = "") 469 { 470 static const glu::DataType types[] = { glu::TYPE_FLOAT, glu::TYPE_INT_VEC3, glu::TYPE_UINT_VEC4, glu::TYPE_FLOAT_MAT3, glu::TYPE_BOOL_VEC2 }; 471 UniformCollection* const res = new UniformCollection; 472 473 for (int i = 0; i < DE_LENGTH_OF_ARRAY(types); i++) 474 { 475 UniformCollection* const sub = basic(types[i], ("_" + de::toString(i) + nameSuffix).c_str()); 476 sub->moveContents(*res); 477 delete sub; 478 } 479 480 return res; 481 } 482 483 static UniformCollection* multipleBasicArray (const char* const nameSuffix = "") 484 { 485 static const glu::DataType types[] = { glu::TYPE_FLOAT, glu::TYPE_INT_VEC3, glu::TYPE_BOOL_VEC2 }; 486 UniformCollection* const res = new UniformCollection; 487 488 for (int i = 0; i < DE_LENGTH_OF_ARRAY(types); i++) 489 { 490 UniformCollection* const sub = basicArray(types[i], ("_" + de::toString(i) + nameSuffix).c_str()); 491 sub->moveContents(*res); 492 delete sub; 493 } 494 495 return res; 496 } 497 498 static UniformCollection* multipleNestedArraysStructs (const char* const nameSuffix = "") 499 { 500 static const glu::DataType types0[] = { glu::TYPE_FLOAT, glu::TYPE_INT, glu::TYPE_BOOL_VEC4 }; 501 static const glu::DataType types1[] = { glu::TYPE_FLOAT_VEC4, glu::TYPE_INT_VEC4, glu::TYPE_BOOL }; 502 UniformCollection* const res = new UniformCollection; 503 504 DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(types0) == DE_LENGTH_OF_ARRAY(types1)); 505 506 for (int i = 0; i < DE_LENGTH_OF_ARRAY(types0); i++) 507 { 508 UniformCollection* const sub = nestedArraysStructs(types0[i], types1[i], ("_" + de::toString(i) + nameSuffix).c_str()); 509 sub->moveContents(*res); 510 delete sub; 511 } 512 513 return res; 514 } 515 516 static UniformCollection* random (const deUint32 seed) 517 { 518 Random rnd (seed); 519 const int numUniforms = rnd.getInt(1, 5); 520 int structIdx = 0; 521 UniformCollection* const res = new UniformCollection; 522 523 for (int i = 0; i < numUniforms; i++) 524 { 525 vector<const StructType*> structTypes; 526 Uniform uniform(("u_var" + de::toString(i)).c_str(), glu::VarType()); 527 528 // \note Discard uniforms that would cause number of samplers to exceed MAX_NUM_SAMPLER_UNIFORMS. 529 do 530 { 531 for (int j = 0; j < (int)structTypes.size(); j++) 532 delete structTypes[j]; 533 structTypes.clear(); 534 uniform.type = (("u_var" + de::toString(i)).c_str(), generateRandomType(3, structIdx, structTypes, rnd)); 535 } while (res->getNumSamplers() + getNumSamplersInType(uniform.type) > MAX_NUM_SAMPLER_UNIFORMS); 536 537 res->addUniform(uniform); 538 for (int j = 0; j < (int)structTypes.size(); j++) 539 res->addStructType(structTypes[j]); 540 } 541 542 return res; 543 } 544 545 private: 546 // \note Copying these would be cumbersome, since deep-copying both m_uniforms and m_structTypes 547 // would mean that we'd need to update pointers from uniforms to point to the new structTypes. 548 // When the same UniformCollection is needed in several places, a SharedPtr is used instead. 549 UniformCollection (const UniformCollection&); // Not allowed. 550 UniformCollection& operator= (const UniformCollection&); // Not allowed. 551 552 vector<Uniform> m_uniforms; 553 vector<const StructType*> m_structTypes; 554 }; 555 556 }; // anonymous 557 558 static VarValue getSamplerFillValue (const VarValue& sampler) 559 { 560 DE_ASSERT(glu::isDataTypeSampler(sampler.type)); 561 562 VarValue result; 563 result.type = getSamplerLookupReturnType(sampler.type); 564 565 switch (result.type) 566 { 567 case glu::TYPE_FLOAT_VEC4: 568 for (int i = 0; i < 4; i++) 569 result.val.floatV[i] = sampler.val.samplerV.fillColor.floatV[i]; 570 break; 571 case glu::TYPE_UINT_VEC4: 572 for (int i = 0; i < 4; i++) 573 result.val.uintV[i] = sampler.val.samplerV.fillColor.uintV[i]; 574 break; 575 case glu::TYPE_INT_VEC4: 576 for (int i = 0; i < 4; i++) 577 result.val.intV[i] = sampler.val.samplerV.fillColor.intV[i]; 578 break; 579 case glu::TYPE_FLOAT: 580 result.val.floatV[0] = sampler.val.samplerV.fillColor.floatV[0]; 581 break; 582 default: 583 DE_ASSERT(false); 584 } 585 586 return result; 587 } 588 589 static VarValue getSamplerUnitValue (const VarValue& sampler) 590 { 591 DE_ASSERT(glu::isDataTypeSampler(sampler.type)); 592 593 VarValue result; 594 result.type = glu::TYPE_INT; 595 result.val.intV[0] = sampler.val.samplerV.unit; 596 597 return result; 598 } 599 600 static glu::DataType getDataTypeTransposedMatrix (const glu::DataType original) 601 { 602 return glu::getDataTypeMatrix(glu::getDataTypeMatrixNumRows(original), glu::getDataTypeMatrixNumColumns(original)); 603 } 604 605 static VarValue getTransposeMatrix (const VarValue& original) 606 { 607 DE_ASSERT(glu::isDataTypeMatrix(original.type)); 608 609 const int rows = glu::getDataTypeMatrixNumRows(original.type); 610 const int cols = glu::getDataTypeMatrixNumColumns(original.type); 611 VarValue result; 612 result.type = getDataTypeTransposedMatrix(original.type); 613 614 for (int i = 0; i < rows; i++) 615 for (int j = 0; j < cols; j++) 616 result.val.floatV[i*cols + j] = original.val.floatV[j*rows + i]; 617 618 return result; 619 } 620 621 static string shaderVarValueStr (const VarValue& value) 622 { 623 const int numElems = glu::getDataTypeScalarSize(value.type); 624 std::ostringstream result; 625 626 if (numElems > 1) 627 result << glu::getDataTypeName(value.type) << "("; 628 629 for (int i = 0; i < numElems; i++) 630 { 631 if (i > 0) 632 result << ", "; 633 634 if (glu::isDataTypeFloatOrVec(value.type) || glu::isDataTypeMatrix(value.type)) 635 result << de::floatToString(value.val.floatV[i], 2); 636 else if (glu::isDataTypeIntOrIVec((value.type))) 637 result << de::toString(value.val.intV[i]); 638 else if (glu::isDataTypeUintOrUVec((value.type))) 639 result << de::toString(value.val.uintV[i]) << "u"; 640 else if (glu::isDataTypeBoolOrBVec((value.type))) 641 result << (value.val.boolV[i] ? "true" : "false"); 642 else if (glu::isDataTypeSampler((value.type))) 643 result << shaderVarValueStr(getSamplerFillValue(value)); 644 else 645 DE_ASSERT(false); 646 } 647 648 if (numElems > 1) 649 result << ")"; 650 651 return result.str(); 652 } 653 654 static string apiVarValueStr (const VarValue& value) 655 { 656 const int numElems = glu::getDataTypeScalarSize(value.type); 657 std::ostringstream result; 658 659 if (numElems > 1) 660 result << "("; 661 662 for (int i = 0; i < numElems; i++) 663 { 664 if (i > 0) 665 result << ", "; 666 667 if (glu::isDataTypeFloatOrVec(value.type) || glu::isDataTypeMatrix(value.type)) 668 result << de::floatToString(value.val.floatV[i], 2); 669 else if (glu::isDataTypeIntOrIVec((value.type))) 670 result << de::toString(value.val.intV[i]); 671 else if (glu::isDataTypeUintOrUVec((value.type))) 672 result << de::toString(value.val.uintV[i]); 673 else if (glu::isDataTypeBoolOrBVec((value.type))) 674 result << (value.val.boolV[i] ? "true" : "false"); 675 else if (glu::isDataTypeSampler((value.type))) 676 result << value.val.samplerV.unit; 677 else 678 DE_ASSERT(false); 679 } 680 681 if (numElems > 1) 682 result << ")"; 683 684 return result.str(); 685 } 686 687 static VarValue generateRandomVarValue (const glu::DataType type, Random& rnd, int samplerUnit = -1 /* Used if type is a sampler type. \note Samplers' unit numbers are not randomized. */) 688 { 689 const int numElems = glu::getDataTypeScalarSize(type); 690 VarValue result; 691 result.type = type; 692 693 DE_ASSERT((samplerUnit >= 0) == (glu::isDataTypeSampler(type))); 694 695 if (glu::isDataTypeFloatOrVec(type) || glu::isDataTypeMatrix(type)) 696 { 697 for (int i = 0; i < numElems; i++) 698 result.val.floatV[i] = rnd.getFloat(-10.0f, 10.0f); 699 } 700 else if (glu::isDataTypeIntOrIVec(type)) 701 { 702 for (int i = 0; i < numElems; i++) 703 result.val.intV[i] = rnd.getInt(-10, 10); 704 } 705 else if (glu::isDataTypeUintOrUVec(type)) 706 { 707 for (int i = 0; i < numElems; i++) 708 result.val.uintV[i] = (deUint32)rnd.getInt(0, 10); 709 } 710 else if (glu::isDataTypeBoolOrBVec(type)) 711 { 712 for (int i = 0; i < numElems; i++) 713 result.val.boolV[i] = rnd.getBool(); 714 } 715 else if (glu::isDataTypeSampler(type)) 716 { 717 const glu::DataType texResultType = getSamplerLookupReturnType(type); 718 const glu::DataType texResultScalarType = glu::getDataTypeScalarType(texResultType); 719 const int texResultNumDims = glu::getDataTypeScalarSize(texResultType); 720 721 result.val.samplerV.unit = samplerUnit; 722 723 for (int i = 0; i < texResultNumDims; i++) 724 { 725 switch (texResultScalarType) 726 { 727 case glu::TYPE_FLOAT: result.val.samplerV.fillColor.floatV[i] = rnd.getFloat(0.0f, 1.0f); break; 728 case glu::TYPE_INT: result.val.samplerV.fillColor.intV[i] = rnd.getInt(-10, 10); break; 729 case glu::TYPE_UINT: result.val.samplerV.fillColor.uintV[i] = (deUint32)rnd.getInt(0, 10); break; 730 default: 731 DE_ASSERT(false); 732 } 733 } 734 } 735 else 736 DE_ASSERT(false); 737 738 return result; 739 } 740 741 static VarValue generateZeroVarValue (const glu::DataType type) 742 { 743 const int numElems = glu::getDataTypeScalarSize(type); 744 VarValue result; 745 result.type = type; 746 747 if (glu::isDataTypeFloatOrVec(type) || glu::isDataTypeMatrix(type)) 748 { 749 for (int i = 0; i < numElems; i++) 750 result.val.floatV[i] = 0.0f; 751 } 752 else if (glu::isDataTypeIntOrIVec(type)) 753 { 754 for (int i = 0; i < numElems; i++) 755 result.val.intV[i] = 0; 756 } 757 else if (glu::isDataTypeUintOrUVec(type)) 758 { 759 for (int i = 0; i < numElems; i++) 760 result.val.uintV[i] = 0u; 761 } 762 else if (glu::isDataTypeBoolOrBVec(type)) 763 { 764 for (int i = 0; i < numElems; i++) 765 result.val.boolV[i] = false; 766 } 767 else if (glu::isDataTypeSampler(type)) 768 { 769 const glu::DataType texResultType = getSamplerLookupReturnType(type); 770 const glu::DataType texResultScalarType = glu::getDataTypeScalarType(texResultType); 771 const int texResultNumDims = glu::getDataTypeScalarSize(texResultType); 772 773 result.val.samplerV.unit = 0; 774 775 for (int i = 0; i < texResultNumDims; i++) 776 { 777 switch (texResultScalarType) 778 { 779 case glu::TYPE_FLOAT: result.val.samplerV.fillColor.floatV[i] = 0.12f * (float)i; break; 780 case glu::TYPE_INT: result.val.samplerV.fillColor.intV[i] = -2 + i; break; 781 case glu::TYPE_UINT: result.val.samplerV.fillColor.uintV[i] = 4 + i; break; 782 default: 783 DE_ASSERT(false); 784 } 785 } 786 } 787 else 788 DE_ASSERT(false); 789 790 return result; 791 } 792 793 static bool apiVarValueEquals (const VarValue& a, const VarValue& b) 794 { 795 const int size = glu::getDataTypeScalarSize(a.type); 796 const float floatThreshold = 0.05f; 797 798 DE_ASSERT(a.type == b.type); 799 800 if (glu::isDataTypeFloatOrVec(a.type) || glu::isDataTypeMatrix(a.type)) 801 { 802 for (int i = 0; i < size; i++) 803 if (de::abs(a.val.floatV[i] - b.val.floatV[i]) >= floatThreshold) 804 return false; 805 } 806 else if (glu::isDataTypeIntOrIVec(a.type)) 807 { 808 for (int i = 0; i < size; i++) 809 if (a.val.intV[i] != b.val.intV[i]) 810 return false; 811 } 812 else if (glu::isDataTypeUintOrUVec(a.type)) 813 { 814 for (int i = 0; i < size; i++) 815 if (a.val.uintV[i] != b.val.uintV[i]) 816 return false; 817 } 818 else if (glu::isDataTypeBoolOrBVec(a.type)) 819 { 820 for (int i = 0; i < size; i++) 821 if (a.val.boolV[i] != b.val.boolV[i]) 822 return false; 823 } 824 else if (glu::isDataTypeSampler(a.type)) 825 { 826 if (a.val.samplerV.unit != b.val.samplerV.unit) 827 return false; 828 } 829 else 830 DE_ASSERT(false); 831 832 return true; 833 } 834 835 static VarValue getRandomBoolRepresentation (const VarValue& boolValue, const glu::DataType targetScalarType, Random& rnd) 836 { 837 DE_ASSERT(glu::isDataTypeBoolOrBVec(boolValue.type)); 838 839 const int size = glu::getDataTypeScalarSize(boolValue.type); 840 const glu::DataType targetType = size == 1 ? targetScalarType : glu::getDataTypeVector(targetScalarType, size); 841 VarValue result; 842 result.type = targetType; 843 844 switch (targetScalarType) 845 { 846 case glu::TYPE_INT: 847 for (int i = 0; i < size; i++) 848 { 849 if (boolValue.val.boolV[i]) 850 { 851 result.val.intV[i] = rnd.getInt(-10, 10); 852 if (result.val.intV[i] == 0) 853 result.val.intV[i] = 1; 854 } 855 else 856 result.val.intV[i] = 0; 857 } 858 break; 859 860 case glu::TYPE_UINT: 861 for (int i = 0; i < size; i++) 862 { 863 if (boolValue.val.boolV[i]) 864 result.val.uintV[i] = rnd.getInt(1, 10); 865 else 866 result.val.uintV[i] = 0; 867 } 868 break; 869 870 case glu::TYPE_FLOAT: 871 for (int i = 0; i < size; i++) 872 { 873 if (boolValue.val.boolV[i]) 874 { 875 result.val.floatV[i] = rnd.getFloat(-10.0f, 10.0f); 876 if (result.val.floatV[i] == 0.0f) 877 result.val.floatV[i] = 1.0f; 878 } 879 else 880 result.val.floatV[i] = 0; 881 } 882 break; 883 884 default: 885 DE_ASSERT(false); 886 } 887 888 return result; 889 } 890 891 static const char* getCaseShaderTypeName (const CaseShaderType type) 892 { 893 switch (type) 894 { 895 case CASESHADERTYPE_VERTEX: return "vertex"; 896 case CASESHADERTYPE_FRAGMENT: return "fragment"; 897 case CASESHADERTYPE_BOTH: return "both"; 898 default: 899 DE_ASSERT(false); 900 return DE_NULL; 901 } 902 } 903 904 static CaseShaderType randomCaseShaderType (const deUint32 seed) 905 { 906 return (CaseShaderType)Random(seed).getInt(0, CASESHADERTYPE_LAST-1); 907 } 908 909 class UniformCase : public TestCase, protected glu::CallLogWrapper 910 { 911 public: 912 enum Feature 913 { 914 // ARRAYUSAGE_ONLY_MIDDLE_INDEX: only middle index of each array is used in shader. If not given, use all indices. 915 FEATURE_ARRAYUSAGE_ONLY_MIDDLE_INDEX = 1<<0, 916 917 // UNIFORMFUNC_VALUE: use pass-by-value versions of uniform assignment funcs, e.g. glUniform1f(), where possible. If not given, use pass-by-pointer versions. 918 FEATURE_UNIFORMFUNC_VALUE = 1<<1, 919 920 // MATRIXMODE_ROWMAJOR: pass matrices to GL in row major form. If not given, use column major. 921 FEATURE_MATRIXMODE_ROWMAJOR = 1<<2, 922 923 // ARRAYASSIGN: how basic-type arrays are assigned with glUniform*(). If none given, assign each element of an array separately. 924 FEATURE_ARRAYASSIGN_FULL = 1<<3, //!< Assign all elements of an array with one glUniform*(). 925 FEATURE_ARRAYASSIGN_BLOCKS_OF_TWO = 1<<4, //!< Assign two elements per one glUniform*(). 926 927 // UNIFORMUSAGE_EVERY_OTHER: use about half of the uniforms. If not given, use all uniforms (except that some array indices may be omitted according to ARRAYUSAGE). 928 FEATURE_UNIFORMUSAGE_EVERY_OTHER = 1<<5, 929 930 // BOOLEANAPITYPE: type used to pass booleans to and from GL api. If none given, use float. 931 FEATURE_BOOLEANAPITYPE_INT = 1<<6, 932 FEATURE_BOOLEANAPITYPE_UINT = 1<<7, 933 934 // UNIFORMVALUE_ZERO: use zero-valued uniforms. If not given, use random uniform values. 935 FEATURE_UNIFORMVALUE_ZERO = 1<<8, 936 937 // ARRAY_FIRST_ELEM_NAME_NO_INDEX: in certain API functions, when referring to the first element of an array, use just the array name without [0] at the end. 938 FEATURE_ARRAY_FIRST_ELEM_NAME_NO_INDEX = 1<<9 939 }; 940 941 UniformCase (Context& context, const char* name, const char* description, CaseShaderType caseType, const SharedPtr<const UniformCollection>& uniformCollection); 942 UniformCase (Context& context, const char* name, const char* description, CaseShaderType caseType, const SharedPtr<const UniformCollection>& uniformCollection, deUint32 features); 943 UniformCase (Context& context, const char* name, const char* description, deUint32 seed); // \note Randomizes caseType, uniformCollection and features. 944 virtual ~UniformCase (void); 945 946 virtual void init (void); 947 virtual void deinit (void); 948 949 IterateResult iterate (void); 950 951 protected: 952 // A basic uniform is a uniform (possibly struct or array member) whose type is a basic type (e.g. float, ivec4, sampler2d). 953 struct BasicUniform 954 { 955 string name; 956 glu::DataType type; 957 bool isUsedInShader; 958 VarValue finalValue; //!< The value we ultimately want to set for this uniform. 959 960 string rootName; //!< If this is a member of a basic-typed array, rootName is the name of that array with "[0]" appended. Otherwise it equals name. 961 int elemNdx; //!< If this is a member of a basic-typed array, elemNdx is the index in that array. Otherwise -1. 962 int rootSize; //!< If this is a member of a basic-typed array, rootSize is the size of that array. Otherwise 1. 963 964 BasicUniform (const char* const name_, 965 const glu::DataType type_, 966 const bool isUsedInShader_, 967 const VarValue& finalValue_, 968 const char* const rootName_ = DE_NULL, 969 const int elemNdx_ = -1, 970 const int rootSize_ = 1) 971 : name (name_) 972 , type (type_) 973 , isUsedInShader (isUsedInShader_) 974 , finalValue (finalValue_) 975 , rootName (rootName_ == DE_NULL ? name_ : rootName_) 976 , elemNdx (elemNdx_) 977 , rootSize (rootSize_) 978 { 979 } 980 981 static vector<BasicUniform>::const_iterator findWithName (const vector<BasicUniform>& vec, const char* const name) 982 { 983 for (vector<BasicUniform>::const_iterator it = vec.begin(); it != vec.end(); it++) 984 { 985 if (it->name == name) 986 return it; 987 } 988 return vec.end(); 989 } 990 }; 991 992 // Reference values for info that is expected to be reported by glGetActiveUniform() or glGetActiveUniformsiv(). 993 struct BasicUniformReportRef 994 { 995 string name; 996 // \note minSize and maxSize are for arrays and can be distinct since implementations are allowed, but not required, to trim the inactive end indices of arrays. 997 int minSize; 998 int maxSize; 999 glu::DataType type; 1000 bool isUsedInShader; 1001 1002 BasicUniformReportRef (const char* const name_, const int minS, const int maxS, const glu::DataType type_, const bool used) 1003 : name(name_), minSize(minS), maxSize(maxS), type(type_), isUsedInShader(used) { DE_ASSERT(minSize <= maxSize); } 1004 BasicUniformReportRef (const char* const name_, const glu::DataType type_, const bool used) 1005 : name(name_), minSize(1), maxSize(1), type(type_), isUsedInShader(used) {} 1006 }; 1007 1008 // Info that is actually reported by glGetActiveUniform() or glGetActiveUniformsiv(). 1009 struct BasicUniformReportGL 1010 { 1011 string name; 1012 int nameLength; // \note Whether this includes the null byte depends on whether it was queried with glGetActiveUniform() or glGetActiveUniformsiv(). 1013 int size; 1014 glu::DataType type; 1015 1016 int index; 1017 1018 BasicUniformReportGL (const char* const name_, const int nameLength_, const int size_, const glu::DataType type_, const int index_) 1019 : name(name_), nameLength(nameLength_), size(size_), type(type_), index(index_) {} 1020 1021 static vector<BasicUniformReportGL>::const_iterator findWithName (const vector<BasicUniformReportGL>& vec, const char* const name) 1022 { 1023 for (vector<BasicUniformReportGL>::const_iterator it = vec.begin(); it != vec.end(); it++) 1024 { 1025 if (it->name == name) 1026 return it; 1027 } 1028 return vec.end(); 1029 } 1030 }; 1031 1032 // Query info with glGetActiveUniform() and check validity. 1033 bool getActiveUniforms (vector<BasicUniformReportGL>& dst, const vector<BasicUniformReportRef>& ref, deUint32 programGL); 1034 // Query info with glGetUniformIndices() + glGetActiveUniformsiv() and check validity. 1035 bool getActiveUniformsiv (vector<BasicUniformReportGL>& dst, const vector<BasicUniformReportRef>& ref, deUint32 programGL); 1036 // Compare infos returned by glGetActiveUniform() and glGetUniformIndices() + glGetActiveUniformsiv(). 1037 bool uniformVsUniformsivComparison (const vector<BasicUniformReportGL>& uniformsResult, const vector<BasicUniformReportGL>& uniformsivResult); 1038 // Get uniform values with glGetUniform*() and put to valuesDst. Uniforms that get -1 from glGetUniformLocation() get glu::TYPE_INVALID. 1039 bool getUniforms (vector<VarValue>& valuesDst, const vector<BasicUniform>& basicUniforms, deUint32 programGL); 1040 // Check that every uniform has the default (zero) value. 1041 bool checkUniformDefaultValues (const vector<VarValue>& values, const vector<BasicUniform>& basicUniforms); 1042 // Assign the basicUniforms[].finalValue values for uniforms. \note rnd parameter is for booleans (true can be any nonzero value). 1043 void assignUniforms (const vector<BasicUniform>& basicUniforms, deUint32 programGL, Random& rnd); 1044 // Compare the uniform values given in values (obtained with glGetUniform*()) with the basicUniform.finalValue values. 1045 bool compareUniformValues (const vector<VarValue>& values, const vector<BasicUniform>& basicUniforms); 1046 // Render and check that all pixels are white (i.e. all uniform comparisons passed). 1047 bool renderTest (const vector<BasicUniform>& basicUniforms, const ShaderProgram& program, Random& rnd); 1048 1049 virtual bool test (const vector<BasicUniform>& basicUniforms, const vector<BasicUniformReportRef>& basicUniformReportsRef, const ShaderProgram& program, Random& rnd) = 0; 1050 1051 const deUint32 m_features; 1052 const SharedPtr<const UniformCollection> m_uniformCollection; 1053 1054 private: 1055 static deUint32 randomFeatures (deUint32 seed); 1056 1057 // Generates the basic uniforms, based on the uniform with name varName and type varType, in the same manner as are expected 1058 // to be returned by glGetActiveUniform(), e.g. generates a name like var[0] for arrays, and recursively generates struct member names. 1059 void generateBasicUniforms (vector<BasicUniform>& basicUniformsDst, 1060 vector<BasicUniformReportRef>& basicUniformReportsDst, 1061 const glu::VarType& varType, 1062 const char* varName, 1063 bool isParentActive, 1064 int& samplerUnitCounter, 1065 Random& rnd) const; 1066 1067 void writeUniformDefinitions (std::ostringstream& dst) const; 1068 void writeUniformCompareExpr (std::ostringstream& dst, const BasicUniform& uniform) const; 1069 void writeUniformComparisons (std::ostringstream& dst, const vector<BasicUniform>& basicUniforms, const char* variableName) const; 1070 1071 string generateVertexSource (const vector<BasicUniform>& basicUniforms) const; 1072 string generateFragmentSource (const vector<BasicUniform>& basicUniforms) const; 1073 1074 void setupTexture (const VarValue& value); 1075 1076 const CaseShaderType m_caseShaderType; 1077 1078 vector<glu::Texture2D*> m_textures2d; 1079 vector<glu::TextureCube*> m_texturesCube; 1080 vector<deUint32> m_filledTextureUnits; 1081 }; 1082 1083 deUint32 UniformCase::randomFeatures (const deUint32 seed) 1084 { 1085 static const deUint32 arrayUsageChoices[] = { 0, FEATURE_ARRAYUSAGE_ONLY_MIDDLE_INDEX }; 1086 static const deUint32 uniformFuncChoices[] = { 0, FEATURE_UNIFORMFUNC_VALUE }; 1087 static const deUint32 matrixModeChoices[] = { 0, FEATURE_MATRIXMODE_ROWMAJOR }; 1088 static const deUint32 arrayAssignChoices[] = { 0, FEATURE_ARRAYASSIGN_FULL, FEATURE_ARRAYASSIGN_BLOCKS_OF_TWO }; 1089 static const deUint32 uniformUsageChoices[] = { 0, FEATURE_UNIFORMUSAGE_EVERY_OTHER }; 1090 static const deUint32 booleanApiTypeChoices[] = { 0, FEATURE_BOOLEANAPITYPE_INT, FEATURE_BOOLEANAPITYPE_UINT }; 1091 static const deUint32 uniformValueChoices[] = { 0, FEATURE_UNIFORMVALUE_ZERO }; 1092 1093 Random rnd(seed); 1094 1095 deUint32 result = 0; 1096 1097 #define ARRAY_CHOICE(ARR) (ARR[rnd.getInt(0, DE_LENGTH_OF_ARRAY(ARR)-1)]) 1098 1099 result |= ARRAY_CHOICE(arrayUsageChoices); 1100 result |= ARRAY_CHOICE(uniformFuncChoices); 1101 result |= ARRAY_CHOICE(matrixModeChoices); 1102 result |= ARRAY_CHOICE(arrayAssignChoices); 1103 result |= ARRAY_CHOICE(uniformUsageChoices); 1104 result |= ARRAY_CHOICE(booleanApiTypeChoices); 1105 result |= ARRAY_CHOICE(uniformValueChoices); 1106 1107 #undef ARRAY_CHOICE 1108 1109 return result; 1110 } 1111 1112 UniformCase::UniformCase (Context& context, const char* const name, const char* const description, const CaseShaderType caseShaderType, const SharedPtr<const UniformCollection>& uniformCollection, const deUint32 features) 1113 : TestCase (context, name, description) 1114 , CallLogWrapper (context.getRenderContext().getFunctions(), m_testCtx.getLog()) 1115 , m_features (features) 1116 , m_uniformCollection (uniformCollection) 1117 , m_caseShaderType (caseShaderType) 1118 { 1119 } 1120 1121 UniformCase::UniformCase (Context& context, const char* const name, const char* const description, const CaseShaderType caseShaderType, const SharedPtr<const UniformCollection>& uniformCollection) 1122 : TestCase (context, name, description) 1123 , CallLogWrapper (context.getRenderContext().getFunctions(), m_testCtx.getLog()) 1124 , m_features (0) 1125 , m_uniformCollection (uniformCollection) 1126 , m_caseShaderType (caseShaderType) 1127 { 1128 } 1129 1130 UniformCase::UniformCase (Context& context, const char* name, const char* description, const deUint32 seed) 1131 : TestCase (context, name, description) 1132 , CallLogWrapper (context.getRenderContext().getFunctions(), m_testCtx.getLog()) 1133 , m_features (randomFeatures(seed)) 1134 , m_uniformCollection (UniformCollection::random(seed)) 1135 , m_caseShaderType (randomCaseShaderType(seed)) 1136 { 1137 } 1138 1139 void UniformCase::init (void) 1140 { 1141 { 1142 const glw::Functions& funcs = m_context.getRenderContext().getFunctions(); 1143 const int numSamplerUniforms = m_uniformCollection->getNumSamplers(); 1144 const int vertexTexUnitsRequired = m_caseShaderType != CASESHADERTYPE_FRAGMENT ? numSamplerUniforms : 0; 1145 const int fragmentTexUnitsRequired = m_caseShaderType != CASESHADERTYPE_VERTEX ? numSamplerUniforms : 0; 1146 const int combinedTexUnitsRequired = vertexTexUnitsRequired + fragmentTexUnitsRequired; 1147 const int vertexTexUnitsSupported = getGLInt(funcs, GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS); 1148 const int fragmentTexUnitsSupported = getGLInt(funcs, GL_MAX_TEXTURE_IMAGE_UNITS); 1149 const int combinedTexUnitsSupported = getGLInt(funcs, GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS); 1150 1151 DE_ASSERT(numSamplerUniforms <= MAX_NUM_SAMPLER_UNIFORMS); 1152 1153 if (vertexTexUnitsRequired > vertexTexUnitsSupported) 1154 throw tcu::NotSupportedError(de::toString(vertexTexUnitsRequired) + " vertex texture units required, " + de::toString(vertexTexUnitsSupported) + " supported"); 1155 if (fragmentTexUnitsRequired > fragmentTexUnitsSupported) 1156 throw tcu::NotSupportedError(de::toString(fragmentTexUnitsRequired) + " fragment texture units required, " + de::toString(fragmentTexUnitsSupported) + " supported"); 1157 if (combinedTexUnitsRequired > combinedTexUnitsSupported) 1158 throw tcu::NotSupportedError(de::toString(combinedTexUnitsRequired) + " combined texture units required, " + de::toString(combinedTexUnitsSupported) + " supported"); 1159 } 1160 1161 enableLogging(true); 1162 } 1163 1164 void UniformCase::deinit (void) 1165 { 1166 for (int i = 0; i < (int)m_textures2d.size(); i++) 1167 delete m_textures2d[i]; 1168 m_textures2d.clear(); 1169 1170 for (int i = 0; i < (int)m_texturesCube.size(); i++) 1171 delete m_texturesCube[i]; 1172 m_texturesCube.clear(); 1173 1174 m_filledTextureUnits.clear(); 1175 } 1176 1177 UniformCase::~UniformCase (void) 1178 { 1179 UniformCase::deinit(); 1180 } 1181 1182 void UniformCase::generateBasicUniforms (vector<BasicUniform>& basicUniformsDst, vector<BasicUniformReportRef>& basicUniformReportsDst, const glu::VarType& varType, const char* const varName, const bool isParentActive, int& samplerUnitCounter, Random& rnd) const 1183 { 1184 if (varType.isBasicType()) 1185 { 1186 const bool isActive = isParentActive && (m_features & FEATURE_UNIFORMUSAGE_EVERY_OTHER ? basicUniformsDst.size() % 2 == 0 : true); 1187 const glu::DataType type = varType.getBasicType(); 1188 const VarValue value = m_features & FEATURE_UNIFORMVALUE_ZERO ? generateZeroVarValue(type) 1189 : glu::isDataTypeSampler(type) ? generateRandomVarValue(type, rnd, samplerUnitCounter++) 1190 : generateRandomVarValue(varType.getBasicType(), rnd); 1191 1192 basicUniformsDst.push_back(BasicUniform(varName, varType.getBasicType(), isActive, value)); 1193 basicUniformReportsDst.push_back(BasicUniformReportRef(varName, varType.getBasicType(), isActive)); 1194 } 1195 else if (varType.isArrayType()) 1196 { 1197 const int size = varType.getArraySize(); 1198 const string arrayRootName = string("") + varName + "[0]"; 1199 vector<bool> isElemActive; 1200 1201 for (int elemNdx = 0; elemNdx < varType.getArraySize(); elemNdx++) 1202 { 1203 const string indexedName = string("") + varName + "[" + de::toString(elemNdx) + "]"; 1204 const bool isCurElemActive = isParentActive && 1205 (m_features & FEATURE_UNIFORMUSAGE_EVERY_OTHER ? basicUniformsDst.size() % 2 == 0 : true) && 1206 (m_features & FEATURE_ARRAYUSAGE_ONLY_MIDDLE_INDEX ? elemNdx == size/2 : true); 1207 1208 isElemActive.push_back(isCurElemActive); 1209 1210 if (varType.getElementType().isBasicType()) 1211 { 1212 // \note We don't want separate entries in basicUniformReportsDst for elements of basic-type arrays. 1213 const glu::DataType elemBasicType = varType.getElementType().getBasicType(); 1214 const VarValue value = m_features & FEATURE_UNIFORMVALUE_ZERO ? generateZeroVarValue(elemBasicType) 1215 : glu::isDataTypeSampler(elemBasicType) ? generateRandomVarValue(elemBasicType, rnd, samplerUnitCounter++) 1216 : generateRandomVarValue(elemBasicType, rnd); 1217 1218 basicUniformsDst.push_back(BasicUniform(indexedName.c_str(), elemBasicType, isCurElemActive, value, arrayRootName.c_str(), elemNdx, size)); 1219 } 1220 else 1221 generateBasicUniforms(basicUniformsDst, basicUniformReportsDst, varType.getElementType(), indexedName.c_str(), isCurElemActive, samplerUnitCounter, rnd); 1222 } 1223 1224 if (varType.getElementType().isBasicType()) 1225 { 1226 int minSize; 1227 for (minSize = varType.getArraySize(); minSize > 0 && !isElemActive[minSize-1]; minSize--); 1228 1229 basicUniformReportsDst.push_back(BasicUniformReportRef(arrayRootName.c_str(), minSize, size, varType.getElementType().getBasicType(), isParentActive && minSize > 0)); 1230 } 1231 } 1232 else 1233 { 1234 DE_ASSERT(varType.isStructType()); 1235 1236 const StructType& structType = *varType.getStructPtr(); 1237 1238 for (int i = 0; i < structType.getNumMembers(); i++) 1239 { 1240 const glu::StructMember& member = structType.getMember(i); 1241 const string memberFullName = string("") + varName + "." + member.getName(); 1242 1243 generateBasicUniforms(basicUniformsDst, basicUniformReportsDst, member.getType(), memberFullName.c_str(), isParentActive, samplerUnitCounter, rnd); 1244 } 1245 } 1246 } 1247 1248 void UniformCase::writeUniformDefinitions (std::ostringstream& dst) const 1249 { 1250 for (int i = 0; i < (int)m_uniformCollection->getNumStructTypes(); i++) 1251 dst << glu::declare(m_uniformCollection->getStructType(i)) << ";\n"; 1252 1253 for (int i = 0; i < (int)m_uniformCollection->getNumUniforms(); i++) 1254 dst << "uniform " << glu::declare(m_uniformCollection->getUniform(i).type, m_uniformCollection->getUniform(i).name.c_str()) << ";\n"; 1255 1256 dst << "\n"; 1257 1258 { 1259 static const struct 1260 { 1261 dataTypePredicate requiringTypes[2]; 1262 const char* definition; 1263 } compareFuncs[] = 1264 { 1265 { { glu::isDataTypeFloatOrVec, glu::isDataTypeMatrix }, "mediump float compare_float (mediump float a, mediump float b) { return abs(a - b) < 0.05 ? 1.0 : 0.0; }" }, 1266 { { dataTypeEquals<glu::TYPE_FLOAT_VEC2>, dataTypeIsMatrixWithNRows<2> }, "mediump float compare_vec2 (mediump vec2 a, mediump vec2 b) { return compare_float(a.x, b.x)*compare_float(a.y, b.y); }" }, 1267 { { dataTypeEquals<glu::TYPE_FLOAT_VEC3>, dataTypeIsMatrixWithNRows<3> }, "mediump float compare_vec3 (mediump vec3 a, mediump vec3 b) { return compare_float(a.x, b.x)*compare_float(a.y, b.y)*compare_float(a.z, b.z); }" }, 1268 { { dataTypeEquals<glu::TYPE_FLOAT_VEC4>, dataTypeIsMatrixWithNRows<4> }, "mediump float compare_vec4 (mediump vec4 a, mediump vec4 b) { return compare_float(a.x, b.x)*compare_float(a.y, b.y)*compare_float(a.z, b.z)*compare_float(a.w, b.w); }" }, 1269 { { dataTypeEquals<glu::TYPE_FLOAT_MAT2>, dataTypeEquals<glu::TYPE_INVALID> }, "mediump float compare_mat2 (mediump mat2 a, mediump mat2 b) { return compare_vec2(a[0], b[0])*compare_vec2(a[1], b[1]); }" }, 1270 { { dataTypeEquals<glu::TYPE_FLOAT_MAT2X3>, dataTypeEquals<glu::TYPE_INVALID> }, "mediump float compare_mat2x3 (mediump mat2x3 a, mediump mat2x3 b){ return compare_vec3(a[0], b[0])*compare_vec3(a[1], b[1]); }" }, 1271 { { dataTypeEquals<glu::TYPE_FLOAT_MAT2X4>, dataTypeEquals<glu::TYPE_INVALID> }, "mediump float compare_mat2x4 (mediump mat2x4 a, mediump mat2x4 b){ return compare_vec4(a[0], b[0])*compare_vec4(a[1], b[1]); }" }, 1272 { { dataTypeEquals<glu::TYPE_FLOAT_MAT3X2>, dataTypeEquals<glu::TYPE_INVALID> }, "mediump float compare_mat3x2 (mediump mat3x2 a, mediump mat3x2 b){ return compare_vec2(a[0], b[0])*compare_vec2(a[1], b[1])*compare_vec2(a[2], b[2]); }" }, 1273 { { dataTypeEquals<glu::TYPE_FLOAT_MAT3>, dataTypeEquals<glu::TYPE_INVALID> }, "mediump float compare_mat3 (mediump mat3 a, mediump mat3 b) { return compare_vec3(a[0], b[0])*compare_vec3(a[1], b[1])*compare_vec3(a[2], b[2]); }" }, 1274 { { dataTypeEquals<glu::TYPE_FLOAT_MAT3X4>, dataTypeEquals<glu::TYPE_INVALID> }, "mediump float compare_mat3x4 (mediump mat3x4 a, mediump mat3x4 b){ return compare_vec4(a[0], b[0])*compare_vec4(a[1], b[1])*compare_vec4(a[2], b[2]); }" }, 1275 { { dataTypeEquals<glu::TYPE_FLOAT_MAT4X2>, dataTypeEquals<glu::TYPE_INVALID> }, "mediump float compare_mat4x2 (mediump mat4x2 a, mediump mat4x2 b){ return compare_vec2(a[0], b[0])*compare_vec2(a[1], b[1])*compare_vec2(a[2], b[2])*compare_vec2(a[3], b[3]); }" }, 1276 { { dataTypeEquals<glu::TYPE_FLOAT_MAT4X3>, dataTypeEquals<glu::TYPE_INVALID> }, "mediump float compare_mat4x3 (mediump mat4x3 a, mediump mat4x3 b){ return compare_vec3(a[0], b[0])*compare_vec3(a[1], b[1])*compare_vec3(a[2], b[2])*compare_vec3(a[3], b[3]); }" }, 1277 { { dataTypeEquals<glu::TYPE_FLOAT_MAT4>, dataTypeEquals<glu::TYPE_INVALID> }, "mediump float compare_mat4 (mediump mat4 a, mediump mat4 b) { return compare_vec4(a[0], b[0])*compare_vec4(a[1], b[1])*compare_vec4(a[2], b[2])*compare_vec4(a[3], b[3]); }" }, 1278 { { dataTypeEquals<glu::TYPE_INT>, dataTypeEquals<glu::TYPE_INVALID> }, "mediump float compare_int (mediump int a, mediump int b) { return a == b ? 1.0 : 0.0; }" }, 1279 { { dataTypeEquals<glu::TYPE_INT_VEC2>, dataTypeEquals<glu::TYPE_INVALID> }, "mediump float compare_ivec2 (mediump ivec2 a, mediump ivec2 b) { return a == b ? 1.0 : 0.0; }" }, 1280 { { dataTypeEquals<glu::TYPE_INT_VEC3>, dataTypeEquals<glu::TYPE_INVALID> }, "mediump float compare_ivec3 (mediump ivec3 a, mediump ivec3 b) { return a == b ? 1.0 : 0.0; }" }, 1281 { { dataTypeEquals<glu::TYPE_INT_VEC4>, dataTypeEquals<glu::TYPE_INVALID> }, "mediump float compare_ivec4 (mediump ivec4 a, mediump ivec4 b) { return a == b ? 1.0 : 0.0; }" }, 1282 { { dataTypeEquals<glu::TYPE_UINT>, dataTypeEquals<glu::TYPE_INVALID> }, "mediump float compare_uint (mediump uint a, mediump uint b) { return a == b ? 1.0 : 0.0; }" }, 1283 { { dataTypeEquals<glu::TYPE_UINT_VEC2>, dataTypeEquals<glu::TYPE_INVALID> }, "mediump float compare_uvec2 (mediump uvec2 a, mediump uvec2 b) { return a == b ? 1.0 : 0.0; }" }, 1284 { { dataTypeEquals<glu::TYPE_UINT_VEC3>, dataTypeEquals<glu::TYPE_INVALID> }, "mediump float compare_uvec3 (mediump uvec3 a, mediump uvec3 b) { return a == b ? 1.0 : 0.0; }" }, 1285 { { dataTypeEquals<glu::TYPE_UINT_VEC4>, dataTypeEquals<glu::TYPE_INVALID> }, "mediump float compare_uvec4 (mediump uvec4 a, mediump uvec4 b) { return a == b ? 1.0 : 0.0; }" }, 1286 { { dataTypeEquals<glu::TYPE_BOOL>, dataTypeEquals<glu::TYPE_INVALID> }, "mediump float compare_bool (bool a, bool b) { return a == b ? 1.0 : 0.0; }" }, 1287 { { dataTypeEquals<glu::TYPE_BOOL_VEC2>, dataTypeEquals<glu::TYPE_INVALID> }, "mediump float compare_bvec2 (bvec2 a, bvec2 b) { return a == b ? 1.0 : 0.0; }" }, 1288 { { dataTypeEquals<glu::TYPE_BOOL_VEC3>, dataTypeEquals<glu::TYPE_INVALID> }, "mediump float compare_bvec3 (bvec3 a, bvec3 b) { return a == b ? 1.0 : 0.0; }" }, 1289 { { dataTypeEquals<glu::TYPE_BOOL_VEC4>, dataTypeEquals<glu::TYPE_INVALID> }, "mediump float compare_bvec4 (bvec4 a, bvec4 b) { return a == b ? 1.0 : 0.0; }" } 1290 }; 1291 1292 const vector<glu::DataType> samplerTypes = m_uniformCollection->getSamplerTypes(); 1293 1294 for (int compFuncNdx = 0; compFuncNdx < DE_LENGTH_OF_ARRAY(compareFuncs); compFuncNdx++) 1295 { 1296 const dataTypePredicate (&typeReq)[2] = compareFuncs[compFuncNdx].requiringTypes; 1297 bool containsTypeSampler = false; 1298 1299 for (int i = 0; i < (int)samplerTypes.size(); i++) 1300 { 1301 if (glu::isDataTypeSampler(samplerTypes[i])) 1302 { 1303 const glu::DataType retType = getSamplerLookupReturnType(samplerTypes[i]); 1304 if (typeReq[0](retType) || typeReq[1](retType)) 1305 { 1306 containsTypeSampler = true; 1307 break; 1308 } 1309 } 1310 } 1311 1312 if (containsTypeSampler || m_uniformCollection->containsMatchingBasicType(typeReq[0]) || m_uniformCollection->containsMatchingBasicType(typeReq[1])) 1313 dst << compareFuncs[compFuncNdx].definition << "\n"; 1314 } 1315 } 1316 } 1317 1318 void UniformCase::writeUniformCompareExpr (std::ostringstream& dst, const BasicUniform& uniform) const 1319 { 1320 if (glu::isDataTypeSampler(uniform.type)) 1321 dst << "compare_" << glu::getDataTypeName(getSamplerLookupReturnType(uniform.type)) << "(texture(" << uniform.name << ", vec" << getSamplerNumLookupDimensions(uniform.type) << "(0.0))"; 1322 else 1323 dst << "compare_" << glu::getDataTypeName(uniform.type) << "(" << uniform.name; 1324 1325 dst << ", " << shaderVarValueStr(uniform.finalValue) << ")"; 1326 } 1327 1328 void UniformCase::writeUniformComparisons (std::ostringstream& dst, const vector<BasicUniform>& basicUniforms, const char* const variableName) const 1329 { 1330 for (int i = 0; i < (int)basicUniforms.size(); i++) 1331 { 1332 const BasicUniform& unif = basicUniforms[i]; 1333 1334 if (unif.isUsedInShader) 1335 { 1336 dst << "\t" << variableName << " *= "; 1337 writeUniformCompareExpr(dst, basicUniforms[i]); 1338 dst << ";\n"; 1339 } 1340 else 1341 dst << "\t// UNUSED: " << basicUniforms[i].name << "\n"; 1342 } 1343 } 1344 1345 string UniformCase::generateVertexSource (const vector<BasicUniform>& basicUniforms) const 1346 { 1347 const bool isVertexCase = m_caseShaderType == CASESHADERTYPE_VERTEX || m_caseShaderType == CASESHADERTYPE_BOTH; 1348 std::ostringstream result; 1349 1350 result << "#version 300 es\n" 1351 "in highp vec4 a_position;\n" 1352 "out mediump float v_vtxOut;\n" 1353 "\n"; 1354 1355 if (isVertexCase) 1356 writeUniformDefinitions(result); 1357 1358 result << "\n" 1359 "void main (void)\n" 1360 "{\n" 1361 " gl_Position = a_position;\n" 1362 " v_vtxOut = 1.0;\n"; 1363 1364 if (isVertexCase) 1365 writeUniformComparisons(result, basicUniforms, "v_vtxOut"); 1366 1367 result << "}\n"; 1368 1369 return result.str(); 1370 } 1371 1372 string UniformCase::generateFragmentSource (const vector<BasicUniform>& basicUniforms) const 1373 { 1374 const bool isFragmentCase = m_caseShaderType == CASESHADERTYPE_FRAGMENT || m_caseShaderType == CASESHADERTYPE_BOTH; 1375 std::ostringstream result; 1376 1377 result << "#version 300 es\n" 1378 "in mediump float v_vtxOut;\n" 1379 "\n"; 1380 1381 if (isFragmentCase) 1382 writeUniformDefinitions(result); 1383 1384 result << "\n" 1385 "layout(location = 0) out mediump vec4 dEQP_FragColor;\n" 1386 "\n" 1387 "void main (void)\n" 1388 "{\n" 1389 " mediump float result = v_vtxOut;\n"; 1390 1391 if (isFragmentCase) 1392 writeUniformComparisons(result, basicUniforms, "result"); 1393 1394 result << " dEQP_FragColor = vec4(result, result, result, 1.0);\n" 1395 "}\n"; 1396 1397 return result.str(); 1398 } 1399 1400 void UniformCase::setupTexture (const VarValue& value) 1401 { 1402 // \note No handling for samplers other than 2D or cube. 1403 1404 enableLogging(false); 1405 1406 DE_ASSERT(getSamplerLookupReturnType(value.type) == glu::TYPE_FLOAT_VEC4); 1407 1408 const int width = 32; 1409 const int height = 32; 1410 const tcu::Vec4 color = vec4FromPtr(&value.val.samplerV.fillColor.floatV[0]); 1411 1412 if (value.type == glu::TYPE_SAMPLER_2D) 1413 { 1414 glu::Texture2D* texture = new glu::Texture2D(m_context.getRenderContext(), GL_RGBA, GL_UNSIGNED_BYTE, width, height); 1415 tcu::Texture2D& refTexture = texture->getRefTexture(); 1416 m_textures2d.push_back(texture); 1417 1418 refTexture.allocLevel(0); 1419 fillWithColor(refTexture.getLevel(0), color); 1420 1421 GLU_CHECK_CALL(glActiveTexture(GL_TEXTURE0 + value.val.samplerV.unit)); 1422 m_filledTextureUnits.push_back(value.val.samplerV.unit); 1423 texture->upload(); 1424 GLU_CHECK_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)); 1425 GLU_CHECK_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)); 1426 GLU_CHECK_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)); 1427 GLU_CHECK_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)); 1428 } 1429 else if (value.type == glu::TYPE_SAMPLER_CUBE) 1430 { 1431 DE_ASSERT(width == height); 1432 1433 glu::TextureCube* texture = new glu::TextureCube(m_context.getRenderContext(), GL_RGBA, GL_UNSIGNED_BYTE, width); 1434 tcu::TextureCube& refTexture = texture->getRefTexture(); 1435 m_texturesCube.push_back(texture); 1436 1437 for (int face = 0; face < (int)tcu::CUBEFACE_LAST; face++) 1438 { 1439 refTexture.allocLevel((tcu::CubeFace)face, 0); 1440 fillWithColor(refTexture.getLevelFace(0, (tcu::CubeFace)face), color); 1441 } 1442 1443 GLU_CHECK_CALL(glActiveTexture(GL_TEXTURE0 + value.val.samplerV.unit)); 1444 m_filledTextureUnits.push_back(value.val.samplerV.unit); 1445 texture->upload(); 1446 GLU_CHECK_CALL(glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)); 1447 GLU_CHECK_CALL(glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)); 1448 GLU_CHECK_CALL(glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST)); 1449 GLU_CHECK_CALL(glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST)); 1450 1451 } 1452 else 1453 DE_ASSERT(false); 1454 1455 enableLogging(true); 1456 } 1457 1458 bool UniformCase::getActiveUniforms (vector<BasicUniformReportGL>& basicUniformReportsDst, const vector<BasicUniformReportRef>& basicUniformReportsRef, const deUint32 programGL) 1459 { 1460 TestLog& log = m_testCtx.getLog(); 1461 GLint numActiveUniforms = 0; 1462 GLint uniformMaxNameLength = 0; 1463 vector<char> nameBuffer; 1464 bool success = true; 1465 1466 GLU_CHECK_CALL(glGetProgramiv(programGL, GL_ACTIVE_UNIFORMS, &numActiveUniforms)); 1467 log << TestLog::Message << "// Number of active uniforms reported: " << numActiveUniforms << TestLog::EndMessage; 1468 GLU_CHECK_CALL(glGetProgramiv(programGL, GL_ACTIVE_UNIFORM_MAX_LENGTH, &uniformMaxNameLength)); 1469 log << TestLog::Message << "// Maximum uniform name length reported: " << uniformMaxNameLength << TestLog::EndMessage; 1470 nameBuffer.resize(uniformMaxNameLength); 1471 1472 for (int unifNdx = 0; unifNdx < numActiveUniforms; unifNdx++) 1473 { 1474 GLsizei reportedNameLength = 0; 1475 GLint reportedSize = -1; 1476 GLenum reportedTypeGL = GL_NONE; 1477 1478 GLU_CHECK_CALL(glGetActiveUniform(programGL, (GLuint)unifNdx, (GLsizei)uniformMaxNameLength, &reportedNameLength, &reportedSize, &reportedTypeGL, &nameBuffer[0])); 1479 1480 const glu::DataType reportedType = glu::getDataTypeFromGLType(reportedTypeGL); 1481 const string reportedNameStr (&nameBuffer[0]); 1482 1483 TCU_CHECK_MSG(reportedType != glu::TYPE_LAST, "Invalid uniform type"); 1484 1485 log << TestLog::Message << "// Got name = " << reportedNameStr << ", name length = " << reportedNameLength << ", size = " << reportedSize << ", type = " << glu::getDataTypeName(reportedType) << TestLog::EndMessage; 1486 1487 if ((GLsizei)reportedNameStr.length() != reportedNameLength) 1488 { 1489 log << TestLog::Message << "// FAILURE: wrong name length reported, should be " << reportedNameStr.length() << TestLog::EndMessage; 1490 success = false; 1491 } 1492 1493 if (!deStringBeginsWith(reportedNameStr.c_str(), "gl_")) // Ignore built-in uniforms. 1494 { 1495 int referenceNdx; 1496 for (referenceNdx = 0; referenceNdx < (int)basicUniformReportsRef.size(); referenceNdx++) 1497 { 1498 if (basicUniformReportsRef[referenceNdx].name == reportedNameStr) 1499 break; 1500 } 1501 1502 if (referenceNdx >= (int)basicUniformReportsRef.size()) 1503 { 1504 log << TestLog::Message << "// FAILURE: invalid non-built-in uniform name reported" << TestLog::EndMessage; 1505 success = false; 1506 } 1507 else 1508 { 1509 const BasicUniformReportRef& reference = basicUniformReportsRef[referenceNdx]; 1510 1511 DE_ASSERT(reference.type != glu::TYPE_LAST); 1512 DE_ASSERT(reference.minSize >= 1 || (reference.minSize == 0 && !reference.isUsedInShader)); 1513 DE_ASSERT(reference.minSize <= reference.maxSize); 1514 1515 if (BasicUniformReportGL::findWithName(basicUniformReportsDst, reportedNameStr.c_str()) != basicUniformReportsDst.end()) 1516 { 1517 log << TestLog::Message << "// FAILURE: same uniform name reported twice" << TestLog::EndMessage; 1518 success = false; 1519 } 1520 1521 basicUniformReportsDst.push_back(BasicUniformReportGL(reportedNameStr.c_str(), reportedNameLength, reportedSize, reportedType, unifNdx)); 1522 1523 if (reportedType != reference.type) 1524 { 1525 log << TestLog::Message << "// FAILURE: wrong type reported, should be " << glu::getDataTypeName(reference.type) << TestLog::EndMessage; 1526 success = false; 1527 } 1528 if (reportedSize < reference.minSize || reportedSize > reference.maxSize) 1529 { 1530 log << TestLog::Message 1531 << "// FAILURE: wrong size reported, should be " 1532 << (reference.minSize == reference.maxSize ? de::toString(reference.minSize) : "in the range [" + de::toString(reference.minSize) + ", " + de::toString(reference.maxSize) + "]") 1533 << TestLog::EndMessage; 1534 1535 success = false; 1536 } 1537 } 1538 } 1539 } 1540 1541 for (int i = 0; i < (int)basicUniformReportsRef.size(); i++) 1542 { 1543 const BasicUniformReportRef& expected = basicUniformReportsRef[i]; 1544 if (expected.isUsedInShader && BasicUniformReportGL::findWithName(basicUniformReportsDst, expected.name.c_str()) == basicUniformReportsDst.end()) 1545 { 1546 log << TestLog::Message << "// FAILURE: uniform with name " << expected.name << " was not reported by GL" << TestLog::EndMessage; 1547 success = false; 1548 } 1549 } 1550 1551 return success; 1552 } 1553 1554 bool UniformCase::getActiveUniformsiv (vector<BasicUniformReportGL>& basicUniformReportsDst, const vector<BasicUniformReportRef>& basicUniformReportsRef, const deUint32 programGL) 1555 { 1556 TestLog& log = m_testCtx.getLog(); 1557 vector<string> queryNames (basicUniformReportsRef.size()); 1558 vector<const char*> queryNamesC (basicUniformReportsRef.size()); 1559 vector<GLuint> uniformIndices (basicUniformReportsRef.size()); 1560 vector<deUint32> validUniformIndices; // This shall have the same contents, and in same order, as uniformIndices, but with GL_INVALID_INDEX entries removed. 1561 bool success = true; 1562 1563 for (int i = 0; i < (int)basicUniformReportsRef.size(); i++) 1564 { 1565 const string& name = basicUniformReportsRef[i].name; 1566 queryNames[i] = m_features & FEATURE_ARRAY_FIRST_ELEM_NAME_NO_INDEX && name[name.size()-1] == ']' ? beforeLast(name, '[') : name; 1567 queryNamesC[i] = queryNames[i].c_str(); 1568 } 1569 1570 GLU_CHECK_CALL(glGetUniformIndices(programGL, (GLsizei)basicUniformReportsRef.size(), &queryNamesC[0], &uniformIndices[0])); 1571 1572 for (int i = 0; i < (int)uniformIndices.size(); i++) 1573 { 1574 if (uniformIndices[i] != GL_INVALID_INDEX) 1575 validUniformIndices.push_back(uniformIndices[i]); 1576 else 1577 { 1578 if (basicUniformReportsRef[i].isUsedInShader) 1579 { 1580 log << TestLog::Message << "// FAILURE: uniform with name " << basicUniformReportsRef[i].name << " received GL_INVALID_INDEX" << TestLog::EndMessage; 1581 success = false; 1582 } 1583 } 1584 } 1585 1586 if (!validUniformIndices.empty()) 1587 { 1588 vector<GLint> uniformNameLengthBuf (validUniformIndices.size()); 1589 vector<GLint> uniformSizeBuf (validUniformIndices.size()); 1590 vector<GLint> uniformTypeBuf (validUniformIndices.size()); 1591 1592 GLU_CHECK_CALL(glGetActiveUniformsiv(programGL, (GLsizei)validUniformIndices.size(), &validUniformIndices[0], GL_UNIFORM_NAME_LENGTH, &uniformNameLengthBuf[0])); 1593 GLU_CHECK_CALL(glGetActiveUniformsiv(programGL, (GLsizei)validUniformIndices.size(), &validUniformIndices[0], GL_UNIFORM_SIZE, &uniformSizeBuf[0])); 1594 GLU_CHECK_CALL(glGetActiveUniformsiv(programGL, (GLsizei)validUniformIndices.size(), &validUniformIndices[0], GL_UNIFORM_TYPE, &uniformTypeBuf[0])); 1595 1596 { 1597 int validNdx = -1; // Keeps the corresponding index to validUniformIndices while unifNdx is the index to uniformIndices. 1598 for (int unifNdx = 0; unifNdx < (int)uniformIndices.size(); unifNdx++) 1599 { 1600 if (uniformIndices[unifNdx] == GL_INVALID_INDEX) 1601 continue; 1602 1603 validNdx++; 1604 1605 const BasicUniformReportRef& reference = basicUniformReportsRef[unifNdx]; 1606 const int reportedIndex = validUniformIndices[validNdx]; 1607 const int reportedNameLength = (int)uniformNameLengthBuf[validNdx]; 1608 const int reportedSize = (int)uniformSizeBuf[validNdx]; 1609 const glu::DataType reportedType = glu::getDataTypeFromGLType((deUint32)uniformTypeBuf[validNdx]); 1610 1611 TCU_CHECK_MSG(reportedType != glu::TYPE_LAST, "Invalid uniform type"); 1612 1613 log << TestLog::Message 1614 << "// Got name length = " << reportedNameLength 1615 << ", size = " << reportedSize 1616 << ", type = " << glu::getDataTypeName(reportedType) 1617 << " for the uniform at index " << reportedIndex << " (" << reference.name << ")" 1618 << TestLog::EndMessage; 1619 1620 DE_ASSERT(reference.type != glu::TYPE_LAST); 1621 DE_ASSERT(reference.minSize >= 1 || (reference.minSize == 0 && !reference.isUsedInShader)); 1622 DE_ASSERT(reference.minSize <= reference.maxSize); 1623 basicUniformReportsDst.push_back(BasicUniformReportGL(reference.name.c_str(), reportedNameLength, reportedSize, reportedType, reportedIndex)); 1624 1625 if (reportedNameLength != (int)reference.name.length() + 1) 1626 { 1627 log << TestLog::Message << "// FAILURE: wrong name length reported, should be " << reference.name.length() + 1 << TestLog::EndMessage; 1628 success = false; 1629 } 1630 1631 if (reportedType != reference.type) 1632 { 1633 log << TestLog::Message << "// FAILURE: wrong type reported, should be " << glu::getDataTypeName(reference.type) << TestLog::EndMessage; 1634 success = false; 1635 } 1636 1637 if (reportedSize < reference.minSize || reportedSize > reference.maxSize) 1638 { 1639 log << TestLog::Message 1640 << "// FAILURE: wrong size reported, should be " 1641 << (reference.minSize == reference.maxSize ? de::toString(reference.minSize) : "in the range [" + de::toString(reference.minSize) + ", " + de::toString(reference.maxSize) + "]") 1642 << TestLog::EndMessage; 1643 1644 success = false; 1645 } 1646 } 1647 } 1648 } 1649 1650 return success; 1651 } 1652 1653 bool UniformCase::uniformVsUniformsivComparison (const vector<BasicUniformReportGL>& uniformResults, const vector<BasicUniformReportGL>& uniformsivResults) 1654 { 1655 TestLog& log = m_testCtx.getLog(); 1656 bool success = true; 1657 1658 for (int uniformResultNdx = 0; uniformResultNdx < (int)uniformResults.size(); uniformResultNdx++) 1659 { 1660 const BasicUniformReportGL& uniformResult = uniformResults[uniformResultNdx]; 1661 const string& uniformName = uniformResult.name; 1662 const vector<BasicUniformReportGL>::const_iterator uniformsivResultIt = BasicUniformReportGL::findWithName(uniformsivResults, uniformName.c_str()); 1663 1664 if (uniformsivResultIt != uniformsivResults.end()) 1665 { 1666 const BasicUniformReportGL& uniformsivResult = *uniformsivResultIt; 1667 1668 log << TestLog::Message << "// Checking uniform " << uniformName << TestLog::EndMessage; 1669 1670 if (uniformResult.index != uniformsivResult.index) 1671 { 1672 log << TestLog::Message << "// FAILURE: glGetActiveUniform() and glGetUniformIndices() gave different indices for uniform " << uniformName << TestLog::EndMessage; 1673 success = false; 1674 } 1675 if (uniformResult.nameLength + 1 != uniformsivResult.nameLength) 1676 { 1677 log << TestLog::Message << "// FAILURE: glGetActiveUniform() and glGetActiveUniformsiv() gave incompatible name lengths for uniform " << uniformName << TestLog::EndMessage; 1678 success = false; 1679 } 1680 if (uniformResult.size != uniformsivResult.size) 1681 { 1682 log << TestLog::Message << "// FAILURE: glGetActiveUniform() and glGetActiveUniformsiv() gave different sizes for uniform " << uniformName << TestLog::EndMessage; 1683 success = false; 1684 } 1685 if (uniformResult.type != uniformsivResult.type) 1686 { 1687 log << TestLog::Message << "// FAILURE: glGetActiveUniform() and glGetActiveUniformsiv() gave different types for uniform " << uniformName << TestLog::EndMessage; 1688 success = false; 1689 } 1690 } 1691 else 1692 { 1693 log << TestLog::Message << "// FAILURE: uniform " << uniformName << " was reported active by glGetActiveUniform() but not by glGetUniformIndices()" << TestLog::EndMessage; 1694 success = false; 1695 } 1696 } 1697 1698 for (int uniformsivResultNdx = 0; uniformsivResultNdx < (int)uniformsivResults.size(); uniformsivResultNdx++) 1699 { 1700 const BasicUniformReportGL& uniformsivResult = uniformsivResults[uniformsivResultNdx]; 1701 const string& uniformsivName = uniformsivResult.name; 1702 const vector<BasicUniformReportGL>::const_iterator uniformsResultIt = BasicUniformReportGL::findWithName(uniformsivResults, uniformsivName.c_str()); 1703 1704 if (uniformsResultIt == uniformsivResults.end()) 1705 { 1706 log << TestLog::Message << "// FAILURE: uniform " << uniformsivName << " was reported active by glGetUniformIndices() but not by glGetActiveUniform()" << TestLog::EndMessage; 1707 success = false; 1708 } 1709 } 1710 1711 return success; 1712 } 1713 1714 bool UniformCase::getUniforms (vector<VarValue>& valuesDst, const vector<BasicUniform>& basicUniforms, const deUint32 programGL) 1715 { 1716 TestLog& log = m_testCtx.getLog(); 1717 bool success = true; 1718 1719 for (int unifNdx = 0; unifNdx < (int)basicUniforms.size(); unifNdx++) 1720 { 1721 const BasicUniform& uniform = basicUniforms[unifNdx]; 1722 const string queryName = m_features & FEATURE_ARRAY_FIRST_ELEM_NAME_NO_INDEX && uniform.elemNdx == 0 ? beforeLast(uniform.name, '[') : uniform.name; 1723 const int location = glGetUniformLocation(programGL, queryName.c_str()); 1724 const int size = glu::getDataTypeScalarSize(uniform.type); 1725 VarValue value; 1726 1727 deMemset(&value, 0xcd, sizeof(value)); // Initialize to known garbage. 1728 1729 if (location == -1) 1730 { 1731 value.type = glu::TYPE_INVALID; 1732 valuesDst.push_back(value); 1733 if (uniform.isUsedInShader) 1734 { 1735 log << TestLog::Message << "// FAILURE: " << uniform.name << " was used in shader, but has location -1" << TestLog::EndMessage; 1736 success = false; 1737 } 1738 continue; 1739 } 1740 1741 value.type = uniform.type; 1742 1743 DE_STATIC_ASSERT(sizeof(GLint) == sizeof(value.val.intV[0])); 1744 DE_STATIC_ASSERT(sizeof(GLuint) == sizeof(value.val.uintV[0])); 1745 DE_STATIC_ASSERT(sizeof(GLfloat) == sizeof(value.val.floatV[0])); 1746 1747 if (glu::isDataTypeFloatOrVec(uniform.type) || glu::isDataTypeMatrix(uniform.type)) 1748 GLU_CHECK_CALL(glGetUniformfv(programGL, location, &value.val.floatV[0])); 1749 else if (glu::isDataTypeIntOrIVec(uniform.type)) 1750 GLU_CHECK_CALL(glGetUniformiv(programGL, location, &value.val.intV[0])); 1751 else if (glu::isDataTypeUintOrUVec(uniform.type)) 1752 GLU_CHECK_CALL(glGetUniformuiv(programGL, location, &value.val.uintV[0])); 1753 else if (glu::isDataTypeBoolOrBVec(uniform.type)) 1754 { 1755 if (m_features & FEATURE_BOOLEANAPITYPE_INT) 1756 { 1757 GLU_CHECK_CALL(glGetUniformiv(programGL, location, &value.val.intV[0])); 1758 for (int i = 0; i < size; i++) 1759 value.val.boolV[i] = value.val.intV[i] != 0; 1760 } 1761 else if (m_features & FEATURE_BOOLEANAPITYPE_UINT) 1762 { 1763 GLU_CHECK_CALL(glGetUniformuiv(programGL, location, &value.val.uintV[0])); 1764 for (int i = 0; i < size; i++) 1765 value.val.boolV[i] = value.val.uintV[i] != 0; 1766 } 1767 else // Default: use float. 1768 { 1769 GLU_CHECK_CALL(glGetUniformfv(programGL, location, &value.val.floatV[0])); 1770 for (int i = 0; i < size; i++) 1771 value.val.boolV[i] = value.val.floatV[i] != 0.0f; 1772 } 1773 } 1774 else if (glu::isDataTypeSampler(uniform.type)) 1775 { 1776 GLint unit = -1; 1777 GLU_CHECK_CALL(glGetUniformiv(programGL, location, &unit)); 1778 value.val.samplerV.unit = unit; 1779 } 1780 else 1781 DE_ASSERT(false); 1782 1783 valuesDst.push_back(value); 1784 1785 log << TestLog::Message << "// Got " << uniform.name << " value " << apiVarValueStr(value) << TestLog::EndMessage; 1786 } 1787 1788 return success; 1789 } 1790 1791 bool UniformCase::checkUniformDefaultValues (const vector<VarValue>& values, const vector<BasicUniform>& basicUniforms) 1792 { 1793 TestLog& log = m_testCtx.getLog(); 1794 bool success = true; 1795 1796 DE_ASSERT(values.size() == basicUniforms.size()); 1797 1798 for (int unifNdx = 0; unifNdx < (int)basicUniforms.size(); unifNdx++) 1799 { 1800 const BasicUniform& uniform = basicUniforms[unifNdx]; 1801 const VarValue& unifValue = values[unifNdx]; 1802 const int valSize = glu::getDataTypeScalarSize(uniform.type); 1803 1804 log << TestLog::Message << "// Checking uniform " << uniform.name << TestLog::EndMessage; 1805 1806 if (unifValue.type == glu::TYPE_INVALID) // This happens when glGetUniformLocation() returned -1. 1807 continue; 1808 1809 #define CHECK_UNIFORM(VAR_VALUE_MEMBER, ZERO) \ 1810 do \ 1811 { \ 1812 for (int i = 0; i < valSize; i++) \ 1813 { \ 1814 if (unifValue.val.VAR_VALUE_MEMBER[i] != ZERO) \ 1815 { \ 1816 log << TestLog::Message << "// FAILURE: uniform " << uniform.name << " has non-zero initial value" << TestLog::EndMessage; \ 1817 success = false; \ 1818 } \ 1819 } \ 1820 } while (false) 1821 1822 if (glu::isDataTypeFloatOrVec(uniform.type) || glu::isDataTypeMatrix(uniform.type)) 1823 CHECK_UNIFORM(floatV, 0.0f); 1824 else if (glu::isDataTypeIntOrIVec(uniform.type)) 1825 CHECK_UNIFORM(intV, 0); 1826 else if (glu::isDataTypeUintOrUVec(uniform.type)) 1827 CHECK_UNIFORM(uintV, 0); 1828 else if (glu::isDataTypeBoolOrBVec(uniform.type)) 1829 CHECK_UNIFORM(boolV, false); 1830 else if (glu::isDataTypeSampler(uniform.type)) 1831 { 1832 if (unifValue.val.samplerV.unit != 0) 1833 { 1834 log << TestLog::Message << "// FAILURE: uniform " << uniform.name << " has non-zero initial value" << TestLog::EndMessage; 1835 success = false; 1836 } 1837 } 1838 else 1839 DE_ASSERT(false); 1840 1841 #undef CHECK_UNIFORM 1842 } 1843 1844 return success; 1845 } 1846 1847 void UniformCase::assignUniforms (const vector<BasicUniform>& basicUniforms, deUint32 programGL, Random& rnd) 1848 { 1849 TestLog& log = m_testCtx.getLog(); 1850 const bool transpose = (m_features & FEATURE_MATRIXMODE_ROWMAJOR) != 0; 1851 const GLboolean transposeGL = transpose ? GL_TRUE : GL_FALSE; 1852 const glu::DataType boolApiType = m_features & FEATURE_BOOLEANAPITYPE_INT ? glu::TYPE_INT 1853 : m_features & FEATURE_BOOLEANAPITYPE_UINT ? glu::TYPE_UINT 1854 : glu::TYPE_FLOAT; 1855 1856 for (int unifNdx = 0; unifNdx < (int)basicUniforms.size(); unifNdx++) 1857 { 1858 const BasicUniform& uniform = basicUniforms[unifNdx]; 1859 const bool isArrayMember = uniform.elemNdx >= 0; 1860 const string queryName = m_features & FEATURE_ARRAY_FIRST_ELEM_NAME_NO_INDEX && uniform.elemNdx == 0 ? beforeLast(uniform.name, '[') : uniform.name; 1861 const int numValuesToAssign = !isArrayMember ? 1 1862 : m_features & FEATURE_ARRAYASSIGN_FULL ? (uniform.elemNdx == 0 ? uniform.rootSize : 0) 1863 : m_features & FEATURE_ARRAYASSIGN_BLOCKS_OF_TWO ? (uniform.elemNdx % 2 == 0 ? 2 : 0) 1864 : /* Default: assign array elements separately */ 1; 1865 1866 DE_ASSERT(numValuesToAssign >= 0); 1867 DE_ASSERT(numValuesToAssign == 1 || isArrayMember); 1868 1869 if (numValuesToAssign == 0) 1870 { 1871 log << TestLog::Message << "// Uniform " << uniform.name << " is covered by another glUniform*v() call to the same array" << TestLog::EndMessage; 1872 continue; 1873 } 1874 1875 const int location = glGetUniformLocation(programGL, queryName.c_str()); 1876 const int typeSize = glu::getDataTypeScalarSize(uniform.type); 1877 const bool assignByValue = m_features & FEATURE_UNIFORMFUNC_VALUE && !glu::isDataTypeMatrix(uniform.type) && numValuesToAssign == 1; 1878 vector<VarValue> valuesToAssign; 1879 1880 for (int i = 0; i < numValuesToAssign; i++) 1881 { 1882 const string curName = isArrayMember ? beforeLast(uniform.rootName, '[') + "[" + de::toString(uniform.elemNdx+i) + "]" : uniform.name; 1883 VarValue unifValue; 1884 1885 if (isArrayMember) 1886 { 1887 const vector<BasicUniform>::const_iterator elemUnif = BasicUniform::findWithName(basicUniforms, curName.c_str()); 1888 if (elemUnif == basicUniforms.end()) 1889 continue; 1890 unifValue = elemUnif->finalValue; 1891 } 1892 else 1893 unifValue = uniform.finalValue; 1894 1895 const VarValue apiValue = glu::isDataTypeBoolOrBVec(unifValue.type) ? getRandomBoolRepresentation(unifValue, boolApiType, rnd) 1896 : glu::isDataTypeSampler(unifValue.type) ? getSamplerUnitValue(unifValue) 1897 : unifValue; 1898 1899 valuesToAssign.push_back(glu::isDataTypeMatrix(apiValue.type) && transpose ? getTransposeMatrix(apiValue) : apiValue); 1900 1901 if (glu::isDataTypeBoolOrBVec(uniform.type)) 1902 log << TestLog::Message << "// Using type " << glu::getDataTypeName(boolApiType) << " to set boolean value " << apiVarValueStr(unifValue) << " for " << curName << TestLog::EndMessage; 1903 else if (glu::isDataTypeSampler(uniform.type)) 1904 log << TestLog::Message << "// Texture for the sampler uniform " << curName << " will be filled with color " << apiVarValueStr(getSamplerFillValue(uniform.finalValue)) << TestLog::EndMessage; 1905 } 1906 1907 DE_ASSERT(!valuesToAssign.empty()); 1908 1909 if (glu::isDataTypeFloatOrVec(valuesToAssign[0].type)) 1910 { 1911 if (assignByValue) 1912 { 1913 const float* const ptr = &valuesToAssign[0].val.floatV[0]; 1914 1915 switch (typeSize) 1916 { 1917 case 1: GLU_CHECK_CALL(glUniform1f(location, ptr[0])); break; 1918 case 2: GLU_CHECK_CALL(glUniform2f(location, ptr[0], ptr[1])); break; 1919 case 3: GLU_CHECK_CALL(glUniform3f(location, ptr[0], ptr[1], ptr[2])); break; 1920 case 4: GLU_CHECK_CALL(glUniform4f(location, ptr[0], ptr[1], ptr[2], ptr[3])); break; 1921 default: 1922 DE_ASSERT(false); 1923 } 1924 } 1925 else 1926 { 1927 vector<float> buffer(valuesToAssign.size() * typeSize); 1928 for (int i = 0; i < (int)buffer.size(); i++) 1929 buffer[i] = valuesToAssign[i / typeSize].val.floatV[i % typeSize]; 1930 1931 DE_STATIC_ASSERT(sizeof(GLfloat) == sizeof(buffer[0])); 1932 switch (typeSize) 1933 { 1934 case 1: GLU_CHECK_CALL(glUniform1fv(location, (GLsizei)valuesToAssign.size(), &buffer[0])); break; 1935 case 2: GLU_CHECK_CALL(glUniform2fv(location, (GLsizei)valuesToAssign.size(), &buffer[0])); break; 1936 case 3: GLU_CHECK_CALL(glUniform3fv(location, (GLsizei)valuesToAssign.size(), &buffer[0])); break; 1937 case 4: GLU_CHECK_CALL(glUniform4fv(location, (GLsizei)valuesToAssign.size(), &buffer[0])); break; 1938 default: 1939 DE_ASSERT(false); 1940 } 1941 } 1942 } 1943 else if (glu::isDataTypeMatrix(valuesToAssign[0].type)) 1944 { 1945 DE_ASSERT(!assignByValue); 1946 1947 vector<float> buffer(valuesToAssign.size() * typeSize); 1948 for (int i = 0; i < (int)buffer.size(); i++) 1949 buffer[i] = valuesToAssign[i / typeSize].val.floatV[i % typeSize]; 1950 1951 DE_STATIC_ASSERT(sizeof(GLfloat) == sizeof(buffer[0])); 1952 switch (uniform.type) 1953 { 1954 case glu::TYPE_FLOAT_MAT2: GLU_CHECK_CALL(glUniformMatrix2fv (location, (GLsizei)valuesToAssign.size(), transposeGL, &buffer[0])); break; 1955 case glu::TYPE_FLOAT_MAT3: GLU_CHECK_CALL(glUniformMatrix3fv (location, (GLsizei)valuesToAssign.size(), transposeGL, &buffer[0])); break; 1956 case glu::TYPE_FLOAT_MAT4: GLU_CHECK_CALL(glUniformMatrix4fv (location, (GLsizei)valuesToAssign.size(), transposeGL, &buffer[0])); break; 1957 case glu::TYPE_FLOAT_MAT2X3: GLU_CHECK_CALL(glUniformMatrix2x3fv (location, (GLsizei)valuesToAssign.size(), transposeGL, &buffer[0])); break; 1958 case glu::TYPE_FLOAT_MAT2X4: GLU_CHECK_CALL(glUniformMatrix2x4fv (location, (GLsizei)valuesToAssign.size(), transposeGL, &buffer[0])); break; 1959 case glu::TYPE_FLOAT_MAT3X2: GLU_CHECK_CALL(glUniformMatrix3x2fv (location, (GLsizei)valuesToAssign.size(), transposeGL, &buffer[0])); break; 1960 case glu::TYPE_FLOAT_MAT3X4: GLU_CHECK_CALL(glUniformMatrix3x4fv (location, (GLsizei)valuesToAssign.size(), transposeGL, &buffer[0])); break; 1961 case glu::TYPE_FLOAT_MAT4X2: GLU_CHECK_CALL(glUniformMatrix4x2fv (location, (GLsizei)valuesToAssign.size(), transposeGL, &buffer[0])); break; 1962 case glu::TYPE_FLOAT_MAT4X3: GLU_CHECK_CALL(glUniformMatrix4x3fv (location, (GLsizei)valuesToAssign.size(), transposeGL, &buffer[0])); break; 1963 default: 1964 DE_ASSERT(false); 1965 } 1966 } 1967 else if (glu::isDataTypeIntOrIVec(valuesToAssign[0].type)) 1968 { 1969 if (assignByValue) 1970 { 1971 const deInt32* const ptr = &valuesToAssign[0].val.intV[0]; 1972 1973 switch (typeSize) 1974 { 1975 case 1: GLU_CHECK_CALL(glUniform1i(location, ptr[0])); break; 1976 case 2: GLU_CHECK_CALL(glUniform2i(location, ptr[0], ptr[1])); break; 1977 case 3: GLU_CHECK_CALL(glUniform3i(location, ptr[0], ptr[1], ptr[2])); break; 1978 case 4: GLU_CHECK_CALL(glUniform4i(location, ptr[0], ptr[1], ptr[2], ptr[3])); break; 1979 default: 1980 DE_ASSERT(false); 1981 } 1982 } 1983 else 1984 { 1985 vector<deInt32> buffer(valuesToAssign.size() * typeSize); 1986 for (int i = 0; i < (int)buffer.size(); i++) 1987 buffer[i] = valuesToAssign[i / typeSize].val.intV[i % typeSize]; 1988 1989 DE_STATIC_ASSERT(sizeof(GLint) == sizeof(buffer[0])); 1990 switch (typeSize) 1991 { 1992 case 1: GLU_CHECK_CALL(glUniform1iv(location, (GLsizei)valuesToAssign.size(), &buffer[0])); break; 1993 case 2: GLU_CHECK_CALL(glUniform2iv(location, (GLsizei)valuesToAssign.size(), &buffer[0])); break; 1994 case 3: GLU_CHECK_CALL(glUniform3iv(location, (GLsizei)valuesToAssign.size(), &buffer[0])); break; 1995 case 4: GLU_CHECK_CALL(glUniform4iv(location, (GLsizei)valuesToAssign.size(), &buffer[0])); break; 1996 default: 1997 DE_ASSERT(false); 1998 } 1999 } 2000 } 2001 else if (glu::isDataTypeUintOrUVec(valuesToAssign[0].type)) 2002 { 2003 if (assignByValue) 2004 { 2005 const deUint32* const ptr = &valuesToAssign[0].val.uintV[0]; 2006 2007 switch (typeSize) 2008 { 2009 case 1: GLU_CHECK_CALL(glUniform1ui(location, ptr[0])); break; 2010 case 2: GLU_CHECK_CALL(glUniform2ui(location, ptr[0], ptr[1])); break; 2011 case 3: GLU_CHECK_CALL(glUniform3ui(location, ptr[0], ptr[1], ptr[2])); break; 2012 case 4: GLU_CHECK_CALL(glUniform4ui(location, ptr[0], ptr[1], ptr[2], ptr[3])); break; 2013 default: 2014 DE_ASSERT(false); 2015 } 2016 } 2017 else 2018 { 2019 vector<deUint32> buffer(valuesToAssign.size() * typeSize); 2020 for (int i = 0; i < (int)buffer.size(); i++) 2021 buffer[i] = valuesToAssign[i / typeSize].val.intV[i % typeSize]; 2022 2023 DE_STATIC_ASSERT(sizeof(GLuint) == sizeof(buffer[0])); 2024 switch (typeSize) 2025 { 2026 case 1: GLU_CHECK_CALL(glUniform1uiv(location, (GLsizei)valuesToAssign.size(), &buffer[0])); break; 2027 case 2: GLU_CHECK_CALL(glUniform2uiv(location, (GLsizei)valuesToAssign.size(), &buffer[0])); break; 2028 case 3: GLU_CHECK_CALL(glUniform3uiv(location, (GLsizei)valuesToAssign.size(), &buffer[0])); break; 2029 case 4: GLU_CHECK_CALL(glUniform4uiv(location, (GLsizei)valuesToAssign.size(), &buffer[0])); break; 2030 default: 2031 DE_ASSERT(false); 2032 } 2033 } 2034 } 2035 else if (glu::isDataTypeSampler(valuesToAssign[0].type)) 2036 { 2037 if (assignByValue) 2038 GLU_CHECK_CALL(glUniform1i(location, uniform.finalValue.val.samplerV.unit)); 2039 else 2040 { 2041 const GLint unit = uniform.finalValue.val.samplerV.unit; 2042 GLU_CHECK_CALL(glUniform1iv(location, (GLsizei)valuesToAssign.size(), &unit)); 2043 } 2044 } 2045 else 2046 DE_ASSERT(false); 2047 } 2048 } 2049 2050 bool UniformCase::compareUniformValues (const vector<VarValue>& values, const vector<BasicUniform>& basicUniforms) 2051 { 2052 TestLog& log = m_testCtx.getLog(); 2053 bool success = true; 2054 2055 for (int unifNdx = 0; unifNdx < (int)basicUniforms.size(); unifNdx++) 2056 { 2057 const BasicUniform& uniform = basicUniforms[unifNdx]; 2058 const VarValue& unifValue = values[unifNdx]; 2059 2060 log << TestLog::Message << "// Checking uniform " << uniform.name << TestLog::EndMessage; 2061 2062 if (unifValue.type == glu::TYPE_INVALID) // This happens when glGetUniformLocation() returned -1. 2063 continue; 2064 2065 if (!apiVarValueEquals(unifValue, uniform.finalValue)) 2066 { 2067 log << TestLog::Message << "// FAILURE: value obtained with glGetUniform*() for uniform " << uniform.name << " differs from value set with glUniform*()" << TestLog::EndMessage; 2068 success = false; 2069 } 2070 } 2071 2072 return success; 2073 } 2074 2075 bool UniformCase::renderTest (const vector<BasicUniform>& basicUniforms, const ShaderProgram& program, Random& rnd) 2076 { 2077 TestLog& log = m_testCtx.getLog(); 2078 const tcu::RenderTarget& renderTarget = m_context.getRenderTarget(); 2079 const int viewportW = de::min(renderTarget.getWidth(), MAX_RENDER_WIDTH); 2080 const int viewportH = de::min(renderTarget.getHeight(), MAX_RENDER_HEIGHT); 2081 const int viewportX = rnd.getInt(0, renderTarget.getWidth() - viewportW); 2082 const int viewportY = rnd.getInt(0, renderTarget.getHeight() - viewportH); 2083 tcu::Surface renderedImg (viewportW, viewportH); 2084 2085 // Assert that no two samplers of different types have the same texture unit - this is an error in GL. 2086 for (int i = 0; i < (int)basicUniforms.size(); i++) 2087 { 2088 if (glu::isDataTypeSampler(basicUniforms[i].type)) 2089 { 2090 for (int j = 0; j < i; j++) 2091 { 2092 if (glu::isDataTypeSampler(basicUniforms[j].type) && basicUniforms[i].type != basicUniforms[j].type) 2093 DE_ASSERT(basicUniforms[i].finalValue.val.samplerV.unit != basicUniforms[j].finalValue.val.samplerV.unit); 2094 } 2095 } 2096 } 2097 2098 for (int i = 0; i < (int)basicUniforms.size(); i++) 2099 { 2100 if (glu::isDataTypeSampler(basicUniforms[i].type) && std::find(m_filledTextureUnits.begin(), m_filledTextureUnits.end(), basicUniforms[i].finalValue.val.samplerV.unit) == m_filledTextureUnits.end()) 2101 { 2102 log << TestLog::Message << "// Filling texture at unit " << apiVarValueStr(basicUniforms[i].finalValue) << " with color " << shaderVarValueStr(basicUniforms[i].finalValue) << TestLog::EndMessage; 2103 setupTexture(basicUniforms[i].finalValue); 2104 } 2105 } 2106 2107 GLU_CHECK_CALL(glViewport(viewportX, viewportY, viewportW, viewportH)); 2108 2109 { 2110 static const float position[] = 2111 { 2112 -1.0f, -1.0f, 0.0f, 1.0f, 2113 -1.0f, +1.0f, 0.0f, 1.0f, 2114 +1.0f, -1.0f, 0.0f, 1.0f, 2115 +1.0f, +1.0f, 0.0f, 1.0f 2116 }; 2117 static const deUint16 indices[] = { 0, 1, 2, 2, 1, 3 }; 2118 2119 const int posLoc = glGetAttribLocation(program.getProgram(), "a_position"); 2120 glEnableVertexAttribArray(posLoc); 2121 glVertexAttribPointer(posLoc, 4, GL_FLOAT, GL_FALSE, 0, &position[0]); 2122 GLU_CHECK_CALL(glDrawElements(GL_TRIANGLES, DE_LENGTH_OF_ARRAY(indices), GL_UNSIGNED_SHORT, &indices[0])); 2123 } 2124 2125 glu::readPixels(m_context.getRenderContext(), viewportX, viewportY, renderedImg.getAccess()); 2126 2127 int numFailedPixels = 0; 2128 for (int y = 0; y < renderedImg.getHeight(); y++) 2129 { 2130 for (int x = 0; x < renderedImg.getWidth(); x++) 2131 { 2132 if (renderedImg.getPixel(x, y) != tcu::RGBA::white()) 2133 numFailedPixels += 1; 2134 } 2135 } 2136 2137 if (numFailedPixels > 0) 2138 { 2139 log << TestLog::Image("RenderedImage", "Rendered image", renderedImg); 2140 log << TestLog::Message << "FAILURE: image comparison failed, got " << numFailedPixels << " non-white pixels" << TestLog::EndMessage; 2141 return false; 2142 } 2143 else 2144 { 2145 log << TestLog::Message << "Success: got all-white pixels (all uniforms have correct values)" << TestLog::EndMessage; 2146 return true; 2147 } 2148 } 2149 2150 UniformCase::IterateResult UniformCase::iterate (void) 2151 { 2152 Random rnd (deStringHash(getName()) ^ (deUint32)m_context.getTestContext().getCommandLine().getBaseSeed()); 2153 TestLog& log = m_testCtx.getLog(); 2154 vector<BasicUniform> basicUniforms; 2155 vector<BasicUniformReportRef> basicUniformReportsRef; 2156 2157 { 2158 int samplerUnitCounter = 0; 2159 for (int i = 0; i < (int)m_uniformCollection->getNumUniforms(); i++) 2160 generateBasicUniforms(basicUniforms, basicUniformReportsRef, m_uniformCollection->getUniform(i).type, m_uniformCollection->getUniform(i).name.c_str(), true, samplerUnitCounter, rnd); 2161 } 2162 2163 const string vertexSource = generateVertexSource(basicUniforms); 2164 const string fragmentSource = generateFragmentSource(basicUniforms); 2165 const ShaderProgram program (m_context.getRenderContext(), glu::makeVtxFragSources(vertexSource, fragmentSource)); 2166 2167 log << program; 2168 2169 if (!program.isOk()) 2170 { 2171 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Compile failed"); 2172 return STOP; 2173 } 2174 2175 GLU_CHECK_CALL(glUseProgram(program.getProgram())); 2176 2177 const bool success = test(basicUniforms, basicUniformReportsRef, program, rnd); 2178 m_testCtx.setTestResult(success ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, 2179 success ? "Passed" : "Failed"); 2180 2181 return STOP; 2182 } 2183 2184 class UniformInfoQueryCase : public UniformCase 2185 { 2186 public: 2187 enum CaseType 2188 { 2189 CASETYPE_UNIFORM = 0, //!< Check info returned by glGetActiveUniform(). 2190 CASETYPE_INDICES_UNIFORMSIV, //!< Check info returned by glGetUniformIndices() + glGetActiveUniformsiv(). 2191 CASETYPE_CONSISTENCY, //!< Query info with both above methods, and check consistency. 2192 2193 CASETYPE_LAST 2194 }; 2195 2196 UniformInfoQueryCase (Context& context, const char* name, const char* description, CaseShaderType shaderType, const SharedPtr<const UniformCollection>& uniformCollection, CaseType caseType, deUint32 additionalFeatures = 0); 2197 bool test (const vector<BasicUniform>& basicUniforms, const vector<BasicUniformReportRef>& basicUniformReportsRef, const ShaderProgram& program, Random& rnd); 2198 2199 static const char* getCaseTypeName (CaseType caseType); 2200 static const char* getCaseTypeDescription (CaseType caseType); 2201 2202 private: 2203 const CaseType m_caseType; 2204 }; 2205 2206 const char* UniformInfoQueryCase::getCaseTypeName (const CaseType caseType) 2207 { 2208 switch (caseType) 2209 { 2210 case CASETYPE_UNIFORM: return "active_uniform"; 2211 case CASETYPE_INDICES_UNIFORMSIV: return "indices_active_uniformsiv"; 2212 case CASETYPE_CONSISTENCY: return "consistency"; 2213 default: 2214 DE_ASSERT(false); 2215 return DE_NULL; 2216 } 2217 } 2218 2219 const char* UniformInfoQueryCase::getCaseTypeDescription (const CaseType caseType) 2220 { 2221 switch (caseType) 2222 { 2223 case CASETYPE_UNIFORM: return "Test glGetActiveUniform()"; 2224 case CASETYPE_INDICES_UNIFORMSIV: return "Test glGetUniformIndices() along with glGetActiveUniformsiv()"; 2225 case CASETYPE_CONSISTENCY: return "Check consistency between results from glGetActiveUniform() and glGetUniformIndices() + glGetActiveUniformsiv()"; 2226 default: 2227 DE_ASSERT(false); 2228 return DE_NULL; 2229 } 2230 } 2231 2232 UniformInfoQueryCase::UniformInfoQueryCase (Context& context, const char* const name, const char* const description, const CaseShaderType shaderType, const SharedPtr<const UniformCollection>& uniformCollection, const CaseType caseType, const deUint32 additionalFeatures) 2233 : UniformCase (context, name, description, shaderType, uniformCollection, additionalFeatures) 2234 , m_caseType (caseType) 2235 { 2236 } 2237 2238 bool UniformInfoQueryCase::test (const vector<BasicUniform>& basicUniforms, const vector<BasicUniformReportRef>& basicUniformReportsRef, const ShaderProgram& program, Random& rnd) 2239 { 2240 DE_UNREF(basicUniforms); 2241 DE_UNREF(rnd); 2242 2243 const deUint32 programGL = program.getProgram(); 2244 TestLog& log = m_testCtx.getLog(); 2245 vector<BasicUniformReportGL> basicUniformReportsUniform; 2246 vector<BasicUniformReportGL> basicUniformReportsUniformsiv; 2247 2248 if (m_caseType == CASETYPE_UNIFORM || m_caseType == CASETYPE_CONSISTENCY) 2249 { 2250 bool success = false; 2251 2252 { 2253 const ScopedLogSection section(log, "InfoGetActiveUniform", "Uniform information queries with glGetActiveUniform()"); 2254 success = getActiveUniforms(basicUniformReportsUniform, basicUniformReportsRef, programGL); 2255 } 2256 2257 if (!success) 2258 { 2259 if (m_caseType == CASETYPE_UNIFORM) 2260 return false; 2261 else 2262 { 2263 DE_ASSERT(m_caseType == CASETYPE_CONSISTENCY); 2264 log << TestLog::Message << "// Note: this is a consistency case, so ignoring above failure(s)" << TestLog::EndMessage; 2265 } 2266 } 2267 } 2268 2269 if (m_caseType == CASETYPE_INDICES_UNIFORMSIV || m_caseType == CASETYPE_CONSISTENCY) 2270 { 2271 bool success = false; 2272 2273 { 2274 const ScopedLogSection section(log, "InfoGetActiveUniformsiv", "Uniform information queries with glGetUniformIndices() and glGetActiveUniformsiv()"); 2275 success = getActiveUniformsiv(basicUniformReportsUniformsiv, basicUniformReportsRef, programGL); 2276 } 2277 2278 if (!success) 2279 { 2280 if (m_caseType == CASETYPE_INDICES_UNIFORMSIV) 2281 return false; 2282 else 2283 { 2284 DE_ASSERT(m_caseType == CASETYPE_CONSISTENCY); 2285 log << TestLog::Message << "// Note: this is a consistency case, so ignoring above failure(s)" << TestLog::EndMessage; 2286 } 2287 } 2288 } 2289 2290 if (m_caseType == CASETYPE_CONSISTENCY) 2291 { 2292 bool success = false; 2293 2294 { 2295 const ScopedLogSection section(log, "CompareUniformVsUniformsiv", "Comparison of results from glGetActiveUniform() and glGetActiveUniformsiv()"); 2296 success = uniformVsUniformsivComparison(basicUniformReportsUniform, basicUniformReportsUniformsiv); 2297 } 2298 2299 if (!success) 2300 return false; 2301 } 2302 2303 return true; 2304 } 2305 2306 class UniformValueCase : public UniformCase 2307 { 2308 public: 2309 enum ValueToCheck 2310 { 2311 VALUETOCHECK_INITIAL = 0, //!< Verify the initial values of the uniforms (i.e. check that they're zero). 2312 VALUETOCHECK_ASSIGNED, //!< Assign values to uniforms with glUniform*(), and check those. 2313 2314 VALUETOCHECK_LAST 2315 }; 2316 enum CheckMethod 2317 { 2318 CHECKMETHOD_GET_UNIFORM = 0, //!< Check values with glGetUniform*(). 2319 CHECKMETHOD_RENDER, //!< Check values by rendering with the value-checking shader. 2320 2321 CHECKMETHOD_LAST 2322 }; 2323 enum AssignMethod 2324 { 2325 ASSIGNMETHOD_POINTER = 0, 2326 ASSIGNMETHOD_VALUE, 2327 2328 ASSIGNMETHOD_LAST 2329 }; 2330 2331 UniformValueCase (Context& context, 2332 const char* name, 2333 const char* description, 2334 CaseShaderType shaderType, 2335 const SharedPtr<const UniformCollection>& uniformCollection, 2336 ValueToCheck valueToCheck, 2337 CheckMethod checkMethod, 2338 AssignMethod assignMethod, 2339 deUint32 additionalFeatures = 0); 2340 2341 bool test (const vector<BasicUniform>& basicUniforms, const vector<BasicUniformReportRef>& basicUniformReportsRef, const ShaderProgram& program, Random& rnd); 2342 2343 static const char* getValueToCheckName (ValueToCheck valueToCheck); 2344 static const char* getValueToCheckDescription (ValueToCheck valueToCheck); 2345 static const char* getCheckMethodName (CheckMethod checkMethod); 2346 static const char* getCheckMethodDescription (CheckMethod checkMethod); 2347 static const char* getAssignMethodName (AssignMethod checkMethod); 2348 static const char* getAssignMethodDescription (AssignMethod checkMethod); 2349 2350 private: 2351 const ValueToCheck m_valueToCheck; 2352 const CheckMethod m_checkMethod; 2353 }; 2354 2355 const char* UniformValueCase::getValueToCheckName (const ValueToCheck valueToCheck) 2356 { 2357 switch (valueToCheck) 2358 { 2359 case VALUETOCHECK_INITIAL: return "initial"; 2360 case VALUETOCHECK_ASSIGNED: return "assigned"; 2361 default: DE_ASSERT(false); return DE_NULL; 2362 } 2363 } 2364 2365 const char* UniformValueCase::getValueToCheckDescription (const ValueToCheck valueToCheck) 2366 { 2367 switch (valueToCheck) 2368 { 2369 case VALUETOCHECK_INITIAL: return "Check initial uniform values (zeros)"; 2370 case VALUETOCHECK_ASSIGNED: return "Check assigned uniform values"; 2371 default: DE_ASSERT(false); return DE_NULL; 2372 } 2373 } 2374 2375 const char* UniformValueCase::getCheckMethodName (const CheckMethod checkMethod) 2376 { 2377 switch (checkMethod) 2378 { 2379 case CHECKMETHOD_GET_UNIFORM: return "get_uniform"; 2380 case CHECKMETHOD_RENDER: return "render"; 2381 default: DE_ASSERT(false); return DE_NULL; 2382 } 2383 } 2384 2385 const char* UniformValueCase::getCheckMethodDescription (const CheckMethod checkMethod) 2386 { 2387 switch (checkMethod) 2388 { 2389 case CHECKMETHOD_GET_UNIFORM: return "Verify values with glGetUniform*()"; 2390 case CHECKMETHOD_RENDER: return "Verify values by rendering"; 2391 default: DE_ASSERT(false); return DE_NULL; 2392 } 2393 } 2394 2395 const char* UniformValueCase::getAssignMethodName (const AssignMethod assignMethod) 2396 { 2397 switch (assignMethod) 2398 { 2399 case ASSIGNMETHOD_POINTER: return "by_pointer"; 2400 case ASSIGNMETHOD_VALUE: return "by_value"; 2401 default: DE_ASSERT(false); return DE_NULL; 2402 } 2403 } 2404 2405 const char* UniformValueCase::getAssignMethodDescription (const AssignMethod assignMethod) 2406 { 2407 switch (assignMethod) 2408 { 2409 case ASSIGNMETHOD_POINTER: return "Assign values by-pointer"; 2410 case ASSIGNMETHOD_VALUE: return "Assign values by-value"; 2411 default: DE_ASSERT(false); return DE_NULL; 2412 } 2413 } 2414 2415 UniformValueCase::UniformValueCase (Context& context, 2416 const char* const name, 2417 const char* const description, 2418 const CaseShaderType shaderType, 2419 const SharedPtr<const UniformCollection>& uniformCollection, 2420 const ValueToCheck valueToCheck, 2421 const CheckMethod checkMethod, 2422 const AssignMethod assignMethod, 2423 const deUint32 additionalFeatures) 2424 : UniformCase (context, name, description, shaderType, uniformCollection, 2425 (valueToCheck == VALUETOCHECK_INITIAL ? FEATURE_UNIFORMVALUE_ZERO : 0) | (assignMethod == ASSIGNMETHOD_VALUE ? FEATURE_UNIFORMFUNC_VALUE : 0) | additionalFeatures) 2426 , m_valueToCheck (valueToCheck) 2427 , m_checkMethod (checkMethod) 2428 { 2429 DE_ASSERT(!(assignMethod == ASSIGNMETHOD_LAST && valueToCheck == VALUETOCHECK_ASSIGNED)); 2430 } 2431 2432 bool UniformValueCase::test (const vector<BasicUniform>& basicUniforms, const vector<BasicUniformReportRef>& basicUniformReportsRef, const ShaderProgram& program, Random& rnd) 2433 { 2434 DE_UNREF(basicUniformReportsRef); 2435 2436 const deUint32 programGL = program.getProgram(); 2437 TestLog& log = m_testCtx.getLog(); 2438 2439 if (m_valueToCheck == VALUETOCHECK_ASSIGNED) 2440 { 2441 const ScopedLogSection section(log, "UniformAssign", "Uniform value assignments"); 2442 assignUniforms(basicUniforms, programGL, rnd); 2443 } 2444 else 2445 DE_ASSERT(m_valueToCheck == VALUETOCHECK_INITIAL); 2446 2447 if (m_checkMethod == CHECKMETHOD_GET_UNIFORM) 2448 { 2449 vector<VarValue> values; 2450 2451 { 2452 const ScopedLogSection section(log, "GetUniforms", "Uniform value query"); 2453 const bool success = getUniforms(values, basicUniforms, program.getProgram()); 2454 2455 if (!success) 2456 return false; 2457 } 2458 2459 if (m_valueToCheck == VALUETOCHECK_ASSIGNED) 2460 { 2461 const ScopedLogSection section(log, "ValueCheck", "Verify that the reported values match the assigned values"); 2462 const bool success = compareUniformValues(values, basicUniforms); 2463 2464 if (!success) 2465 return false; 2466 } 2467 else 2468 { 2469 DE_ASSERT(m_valueToCheck == VALUETOCHECK_INITIAL); 2470 2471 const ScopedLogSection section(log, "ValueCheck", "Verify that the uniforms have correct initial values (zeros)"); 2472 const bool success = checkUniformDefaultValues(values, basicUniforms); 2473 2474 if (!success) 2475 return false; 2476 } 2477 } 2478 else 2479 { 2480 DE_ASSERT(m_checkMethod == CHECKMETHOD_RENDER); 2481 2482 const ScopedLogSection section(log, "RenderTest", "Render test"); 2483 const bool success = renderTest(basicUniforms, program, rnd); 2484 2485 if (!success) 2486 return false; 2487 } 2488 2489 return true; 2490 } 2491 2492 class RandomUniformCase : public UniformCase 2493 { 2494 public: 2495 RandomUniformCase (Context& m_context, const char* name, const char* description, deUint32 seed); 2496 2497 bool test (const vector<BasicUniform>& basicUniforms, const vector<BasicUniformReportRef>& basicUniformReportsRef, const ShaderProgram& program, Random& rnd); 2498 }; 2499 2500 RandomUniformCase::RandomUniformCase (Context& context, const char* const name, const char* const description, const deUint32 seed) 2501 : UniformCase (context, name, description, seed ^ (deUint32)context.getTestContext().getCommandLine().getBaseSeed()) 2502 { 2503 } 2504 2505 bool RandomUniformCase::test (const vector<BasicUniform>& basicUniforms, const vector<BasicUniformReportRef>& basicUniformReportsRef, const ShaderProgram& program, Random& rnd) 2506 { 2507 // \note Different sampler types may not be bound to same unit when rendering. 2508 const bool renderingPossible = (m_features & FEATURE_UNIFORMVALUE_ZERO) == 0 || !m_uniformCollection->containsSeveralSamplerTypes(); 2509 2510 bool performGetActiveUniforms = rnd.getBool(); 2511 const bool performGetActiveUniformsiv = rnd.getBool(); 2512 const bool performUniformVsUniformsivComparison = performGetActiveUniforms && performGetActiveUniformsiv && rnd.getBool(); 2513 const bool performGetUniforms = rnd.getBool(); 2514 const bool performCheckUniformDefaultValues = performGetUniforms && rnd.getBool(); 2515 const bool performAssignUniforms = rnd.getBool(); 2516 const bool performCompareUniformValues = performGetUniforms && performAssignUniforms && rnd.getBool(); 2517 const bool performRenderTest = renderingPossible && performAssignUniforms && rnd.getBool(); 2518 const deUint32 programGL = program.getProgram(); 2519 TestLog& log = m_testCtx.getLog(); 2520 2521 if (!(performGetActiveUniforms || performGetActiveUniformsiv || performUniformVsUniformsivComparison || performGetUniforms || performCheckUniformDefaultValues || performAssignUniforms || performCompareUniformValues || performRenderTest)) 2522 performGetActiveUniforms = true; // Do something at least. 2523 2524 #define PERFORM_AND_CHECK(CALL, SECTION_NAME, SECTION_DESCRIPTION) \ 2525 do \ 2526 { \ 2527 const ScopedLogSection section(log, (SECTION_NAME), (SECTION_DESCRIPTION)); \ 2528 const bool success = (CALL); \ 2529 if (!success) \ 2530 return false; \ 2531 } while (false) 2532 2533 { 2534 vector<BasicUniformReportGL> reportsUniform; 2535 vector<BasicUniformReportGL> reportsUniformsiv; 2536 2537 if (performGetActiveUniforms) 2538 PERFORM_AND_CHECK(getActiveUniforms(reportsUniform, basicUniformReportsRef, programGL), "InfoGetActiveUniform", "Uniform information queries with glGetActiveUniform()"); 2539 if (performGetActiveUniformsiv) 2540 PERFORM_AND_CHECK(getActiveUniformsiv(reportsUniformsiv, basicUniformReportsRef, programGL), "InfoGetActiveUniformsiv", "Uniform information queries with glGetIndices() and glGetActiveUniformsiv()"); 2541 if (performUniformVsUniformsivComparison) 2542 PERFORM_AND_CHECK(uniformVsUniformsivComparison(reportsUniform, reportsUniformsiv), "CompareUniformVsUniformsiv", "Comparison of results from glGetActiveUniform() and glGetActiveUniformsiv()"); 2543 } 2544 2545 { 2546 vector<VarValue> uniformDefaultValues; 2547 2548 if (performGetUniforms) 2549 PERFORM_AND_CHECK(getUniforms(uniformDefaultValues, basicUniforms, programGL), "GetUniformDefaults", "Uniform default value query"); 2550 if (performCheckUniformDefaultValues) 2551 PERFORM_AND_CHECK(checkUniformDefaultValues(uniformDefaultValues, basicUniforms), "DefaultValueCheck", "Verify that the uniforms have correct initial values (zeros)"); 2552 } 2553 2554 { 2555 vector<VarValue> uniformValues; 2556 2557 if (performAssignUniforms) 2558 { 2559 const ScopedLogSection section(log, "UniformAssign", "Uniform value assignments"); 2560 assignUniforms(basicUniforms, programGL, rnd); 2561 } 2562 if (performCompareUniformValues) 2563 { 2564 PERFORM_AND_CHECK(getUniforms(uniformValues, basicUniforms, programGL), "GetUniforms", "Uniform value query"); 2565 PERFORM_AND_CHECK(compareUniformValues(uniformValues, basicUniforms), "ValueCheck", "Verify that the reported values match the assigned values"); 2566 } 2567 } 2568 2569 if (performRenderTest) 2570 PERFORM_AND_CHECK(renderTest(basicUniforms, program, rnd), "RenderTest", "Render test"); 2571 2572 #undef PERFORM_AND_CHECK 2573 2574 return true; 2575 } 2576 2577 UniformApiTests::UniformApiTests (Context& context) 2578 : TestCaseGroup(context, "uniform_api", "Uniform API Tests") 2579 { 2580 } 2581 2582 UniformApiTests::~UniformApiTests (void) 2583 { 2584 } 2585 2586 namespace 2587 { 2588 2589 // \note Although this is only used in UniformApiTest::init, it needs to be defined here as it's used as a template argument. 2590 struct UniformCollectionCase 2591 { 2592 string namePrefix; 2593 SharedPtr<const UniformCollection> uniformCollection; 2594 2595 UniformCollectionCase (const char* const name, const UniformCollection* uniformCollection_) 2596 : namePrefix (name ? name + string("_") : "") 2597 , uniformCollection (uniformCollection_) 2598 { 2599 } 2600 }; 2601 2602 } // anonymous 2603 2604 void UniformApiTests::init (void) 2605 { 2606 // Generate sets of UniformCollections that are used by several cases. 2607 2608 enum 2609 { 2610 UNIFORMCOLLECTIONS_BASIC = 0, 2611 UNIFORMCOLLECTIONS_BASIC_ARRAY, 2612 UNIFORMCOLLECTIONS_BASIC_STRUCT, 2613 UNIFORMCOLLECTIONS_STRUCT_IN_ARRAY, 2614 UNIFORMCOLLECTIONS_ARRAY_IN_STRUCT, 2615 UNIFORMCOLLECTIONS_NESTED_STRUCTS_ARRAYS, 2616 UNIFORMCOLLECTIONS_MULTIPLE_BASIC, 2617 UNIFORMCOLLECTIONS_MULTIPLE_BASIC_ARRAY, 2618 UNIFORMCOLLECTIONS_MULTIPLE_NESTED_STRUCTS_ARRAYS, 2619 2620 UNIFORMCOLLECTIONS_LAST 2621 }; 2622 2623 struct UniformCollectionGroup 2624 { 2625 string name; 2626 vector<UniformCollectionCase> cases; 2627 } defaultUniformCollections[UNIFORMCOLLECTIONS_LAST]; 2628 2629 defaultUniformCollections[UNIFORMCOLLECTIONS_BASIC].name = "basic"; 2630 defaultUniformCollections[UNIFORMCOLLECTIONS_BASIC_ARRAY].name = "basic_array"; 2631 defaultUniformCollections[UNIFORMCOLLECTIONS_BASIC_STRUCT].name = "basic_struct"; 2632 defaultUniformCollections[UNIFORMCOLLECTIONS_STRUCT_IN_ARRAY].name = "struct_in_array"; 2633 defaultUniformCollections[UNIFORMCOLLECTIONS_ARRAY_IN_STRUCT].name = "array_in_struct"; 2634 defaultUniformCollections[UNIFORMCOLLECTIONS_NESTED_STRUCTS_ARRAYS].name = "nested_structs_arrays"; 2635 defaultUniformCollections[UNIFORMCOLLECTIONS_MULTIPLE_BASIC].name = "multiple_basic"; 2636 defaultUniformCollections[UNIFORMCOLLECTIONS_MULTIPLE_BASIC_ARRAY].name = "multiple_basic_array"; 2637 defaultUniformCollections[UNIFORMCOLLECTIONS_MULTIPLE_NESTED_STRUCTS_ARRAYS].name = "multiple_nested_structs_arrays"; 2638 2639 for (int dataTypeNdx = 0; dataTypeNdx < DE_LENGTH_OF_ARRAY(s_testDataTypes); dataTypeNdx++) 2640 { 2641 const glu::DataType dataType = s_testDataTypes[dataTypeNdx]; 2642 const char* const typeName = glu::getDataTypeName(dataType); 2643 2644 defaultUniformCollections[UNIFORMCOLLECTIONS_BASIC].cases.push_back(UniformCollectionCase(typeName, UniformCollection::basic(dataType))); 2645 2646 if (glu::isDataTypeScalar(dataType) || 2647 (glu::isDataTypeVector(dataType) && glu::getDataTypeScalarSize(dataType) == 4) || 2648 dataType == glu::TYPE_FLOAT_MAT4 || 2649 dataType == glu::TYPE_SAMPLER_2D) 2650 defaultUniformCollections[UNIFORMCOLLECTIONS_BASIC_ARRAY].cases.push_back(UniformCollectionCase(typeName, UniformCollection::basicArray(dataType))); 2651 2652 if (glu::isDataTypeScalar(dataType) || 2653 dataType == glu::TYPE_FLOAT_MAT4 || 2654 dataType == glu::TYPE_SAMPLER_2D) 2655 { 2656 const glu::DataType secondDataType = glu::isDataTypeScalar(dataType) ? glu::getDataTypeVector(dataType, 4) 2657 : dataType == glu::TYPE_FLOAT_MAT4 ? glu::TYPE_FLOAT_MAT2 2658 : dataType == glu::TYPE_SAMPLER_2D ? glu::TYPE_SAMPLER_CUBE 2659 : glu::TYPE_LAST; 2660 DE_ASSERT(secondDataType != glu::TYPE_LAST); 2661 const char* const secondTypeName = glu::getDataTypeName(secondDataType); 2662 const string name = string("") + typeName + "_" + secondTypeName; 2663 2664 defaultUniformCollections[UNIFORMCOLLECTIONS_BASIC_STRUCT].cases.push_back (UniformCollectionCase(name.c_str(), UniformCollection::basicStruct(dataType, secondDataType, false))); 2665 defaultUniformCollections[UNIFORMCOLLECTIONS_ARRAY_IN_STRUCT].cases.push_back (UniformCollectionCase(name.c_str(), UniformCollection::basicStruct(dataType, secondDataType, true))); 2666 defaultUniformCollections[UNIFORMCOLLECTIONS_STRUCT_IN_ARRAY].cases.push_back (UniformCollectionCase(name.c_str(), UniformCollection::structInArray(dataType, secondDataType, false))); 2667 defaultUniformCollections[UNIFORMCOLLECTIONS_NESTED_STRUCTS_ARRAYS].cases.push_back (UniformCollectionCase(name.c_str(), UniformCollection::nestedArraysStructs(dataType, secondDataType))); 2668 } 2669 } 2670 defaultUniformCollections[UNIFORMCOLLECTIONS_MULTIPLE_BASIC].cases.push_back (UniformCollectionCase(DE_NULL, UniformCollection::multipleBasic())); 2671 defaultUniformCollections[UNIFORMCOLLECTIONS_MULTIPLE_BASIC_ARRAY].cases.push_back (UniformCollectionCase(DE_NULL, UniformCollection::multipleBasicArray())); 2672 defaultUniformCollections[UNIFORMCOLLECTIONS_MULTIPLE_NESTED_STRUCTS_ARRAYS].cases.push_back (UniformCollectionCase(DE_NULL, UniformCollection::multipleNestedArraysStructs())); 2673 2674 // Info-query cases (check info returned by e.g. glGetActiveUniforms()). 2675 2676 { 2677 TestCaseGroup* const infoQueryGroup = new TestCaseGroup(m_context, "info_query", "Test uniform info querying functions"); 2678 addChild(infoQueryGroup); 2679 for (int caseTypeI = 0; caseTypeI < (int)UniformInfoQueryCase::CASETYPE_LAST; caseTypeI++) 2680 { 2681 const UniformInfoQueryCase::CaseType caseType = (UniformInfoQueryCase::CaseType)caseTypeI; 2682 TestCaseGroup* const caseTypeGroup = new TestCaseGroup(m_context, UniformInfoQueryCase::getCaseTypeName(caseType), UniformInfoQueryCase::getCaseTypeDescription(caseType)); 2683 infoQueryGroup->addChild(caseTypeGroup); 2684 2685 for (int collectionGroupNdx = 0; collectionGroupNdx < (int)UNIFORMCOLLECTIONS_LAST; collectionGroupNdx++) 2686 { 2687 const int numArrayFirstElemNameCases = caseType == UniformInfoQueryCase::CASETYPE_INDICES_UNIFORMSIV && collectionGroupNdx == UNIFORMCOLLECTIONS_BASIC_ARRAY ? 2 : 1; 2688 2689 for (int referToFirstArrayElemWithoutIndexI = 0; referToFirstArrayElemWithoutIndexI < numArrayFirstElemNameCases; referToFirstArrayElemWithoutIndexI++) 2690 { 2691 const UniformCollectionGroup& collectionGroup = defaultUniformCollections[collectionGroupNdx]; 2692 const string collectionGroupName = collectionGroup.name + (referToFirstArrayElemWithoutIndexI == 0 ? "" : "_first_elem_without_brackets"); 2693 TestCaseGroup* const collectionTestGroup = new TestCaseGroup(m_context, collectionGroupName.c_str(), ""); 2694 caseTypeGroup->addChild(collectionTestGroup); 2695 2696 for (int collectionNdx = 0; collectionNdx < (int)collectionGroup.cases.size(); collectionNdx++) 2697 { 2698 const UniformCollectionCase& collectionCase = collectionGroup.cases[collectionNdx]; 2699 2700 for (int shaderType = 0; shaderType < (int)CASESHADERTYPE_LAST; shaderType++) 2701 { 2702 const string name = collectionCase.namePrefix + getCaseShaderTypeName((CaseShaderType)shaderType); 2703 const SharedPtr<const UniformCollection>& uniformCollection = collectionCase.uniformCollection; 2704 2705 collectionTestGroup->addChild(new UniformInfoQueryCase(m_context, name.c_str(), "", (CaseShaderType)shaderType, uniformCollection, (UniformInfoQueryCase::CaseType)caseType, 2706 referToFirstArrayElemWithoutIndexI == 0 ? 0 : UniformCase::FEATURE_ARRAY_FIRST_ELEM_NAME_NO_INDEX)); 2707 } 2708 } 2709 } 2710 } 2711 2712 // Info-querying cases when unused uniforms are present. 2713 2714 { 2715 TestCaseGroup* const unusedUniformsGroup = new TestCaseGroup(m_context, "unused_uniforms", "Test with unused uniforms"); 2716 caseTypeGroup->addChild(unusedUniformsGroup); 2717 2718 const UniformCollectionGroup& collectionGroup = defaultUniformCollections[UNIFORMCOLLECTIONS_ARRAY_IN_STRUCT]; 2719 2720 for (int collectionNdx = 0; collectionNdx < (int)collectionGroup.cases.size(); collectionNdx++) 2721 { 2722 const UniformCollectionCase& collectionCase = collectionGroup.cases[collectionNdx]; 2723 const string collName = collectionCase.namePrefix; 2724 const SharedPtr<const UniformCollection>& uniformCollection = collectionCase.uniformCollection; 2725 2726 for (int shaderType = 0; shaderType < (int)CASESHADERTYPE_LAST; shaderType++) 2727 { 2728 const string name = collName + getCaseShaderTypeName((CaseShaderType)shaderType); 2729 unusedUniformsGroup->addChild(new UniformInfoQueryCase(m_context, name.c_str(), "", (CaseShaderType)shaderType, uniformCollection, (UniformInfoQueryCase::CaseType)caseType, 2730 UniformCase::FEATURE_UNIFORMUSAGE_EVERY_OTHER | UniformCase::FEATURE_ARRAYUSAGE_ONLY_MIDDLE_INDEX)); 2731 } 2732 } 2733 } 2734 } 2735 } 2736 2737 // Cases testing uniform values. 2738 2739 { 2740 TestCaseGroup* const valueGroup = new TestCaseGroup(m_context, "value", "Uniform value tests"); 2741 addChild(valueGroup); 2742 2743 // Cases checking uniforms' initial values (all must be zeros), with glGetUniform*() or by rendering. 2744 2745 { 2746 TestCaseGroup* const initialValuesGroup = new TestCaseGroup(m_context, 2747 UniformValueCase::getValueToCheckName(UniformValueCase::VALUETOCHECK_INITIAL), 2748 UniformValueCase::getValueToCheckDescription(UniformValueCase::VALUETOCHECK_INITIAL)); 2749 valueGroup->addChild(initialValuesGroup); 2750 2751 for (int checkMethodI = 0; checkMethodI < (int)UniformValueCase::CHECKMETHOD_LAST; checkMethodI++) 2752 { 2753 const UniformValueCase::CheckMethod checkMethod = (UniformValueCase::CheckMethod)checkMethodI; 2754 TestCaseGroup* const checkMethodGroup = new TestCaseGroup(m_context, UniformValueCase::getCheckMethodName(checkMethod), UniformValueCase::getCheckMethodDescription(checkMethod)); 2755 initialValuesGroup->addChild(checkMethodGroup); 2756 2757 for (int collectionGroupNdx = 0; collectionGroupNdx < (int)UNIFORMCOLLECTIONS_LAST; collectionGroupNdx++) 2758 { 2759 const UniformCollectionGroup& collectionGroup = defaultUniformCollections[collectionGroupNdx]; 2760 TestCaseGroup* const collectionTestGroup = new TestCaseGroup(m_context, collectionGroup.name.c_str(), ""); 2761 checkMethodGroup->addChild(collectionTestGroup); 2762 2763 for (int collectionNdx = 0; collectionNdx < (int)collectionGroup.cases.size(); collectionNdx++) 2764 { 2765 const UniformCollectionCase& collectionCase = collectionGroup.cases[collectionNdx]; 2766 const string collName = collectionCase.namePrefix; 2767 const SharedPtr<const UniformCollection>& uniformCollection = collectionCase.uniformCollection; 2768 const bool containsBooleans = uniformCollection->containsMatchingBasicType(glu::isDataTypeBoolOrBVec); 2769 const bool varyBoolApiType = checkMethod == UniformValueCase::CHECKMETHOD_GET_UNIFORM && containsBooleans && 2770 (collectionGroupNdx == UNIFORMCOLLECTIONS_BASIC || collectionGroupNdx == UNIFORMCOLLECTIONS_BASIC_ARRAY); 2771 const int numBoolVariations = varyBoolApiType ? 3 : 1; 2772 2773 if (checkMethod == UniformValueCase::CHECKMETHOD_RENDER && uniformCollection->containsSeveralSamplerTypes()) 2774 continue; // \note Samplers' initial API values (i.e. their texture units) are 0, and no two samplers of different types shall have same unit when rendering. 2775 2776 for (int booleanTypeI = 0; booleanTypeI < numBoolVariations; booleanTypeI++) 2777 { 2778 const deUint32 booleanTypeFeat = booleanTypeI == 1 ? UniformCase::FEATURE_BOOLEANAPITYPE_INT 2779 : booleanTypeI == 2 ? UniformCase::FEATURE_BOOLEANAPITYPE_UINT 2780 : 0; 2781 const char* const booleanTypeName = booleanTypeI == 1 ? "int" 2782 : booleanTypeI == 2 ? "uint" 2783 : "float"; 2784 const string nameWithApiType = varyBoolApiType ? collName + "api_" + booleanTypeName + "_" : collName; 2785 2786 for (int shaderType = 0; shaderType < (int)CASESHADERTYPE_LAST; shaderType++) 2787 { 2788 const string name = nameWithApiType + getCaseShaderTypeName((CaseShaderType)shaderType); 2789 collectionTestGroup->addChild(new UniformValueCase(m_context, name.c_str(), "", (CaseShaderType)shaderType, uniformCollection, 2790 UniformValueCase::VALUETOCHECK_INITIAL, checkMethod, UniformValueCase::ASSIGNMETHOD_LAST, booleanTypeFeat)); 2791 } 2792 } 2793 } 2794 } 2795 } 2796 } 2797 2798 // Cases that first assign values to each uniform, then check the values with glGetUniform*() or by rendering. 2799 2800 { 2801 TestCaseGroup* const assignedValuesGroup = new TestCaseGroup(m_context, 2802 UniformValueCase::getValueToCheckName(UniformValueCase::VALUETOCHECK_ASSIGNED), 2803 UniformValueCase::getValueToCheckDescription(UniformValueCase::VALUETOCHECK_ASSIGNED)); 2804 valueGroup->addChild(assignedValuesGroup); 2805 2806 for (int assignMethodI = 0; assignMethodI < (int)UniformValueCase::ASSIGNMETHOD_LAST; assignMethodI++) 2807 { 2808 const UniformValueCase::AssignMethod assignMethod = (UniformValueCase::AssignMethod)assignMethodI; 2809 TestCaseGroup* const assignMethodGroup = new TestCaseGroup(m_context, UniformValueCase::getAssignMethodName(assignMethod), UniformValueCase::getAssignMethodDescription(assignMethod)); 2810 assignedValuesGroup->addChild(assignMethodGroup); 2811 2812 for (int checkMethodI = 0; checkMethodI < (int)UniformValueCase::CHECKMETHOD_LAST; checkMethodI++) 2813 { 2814 const UniformValueCase::CheckMethod checkMethod = (UniformValueCase::CheckMethod)checkMethodI; 2815 TestCaseGroup* const checkMethodGroup = new TestCaseGroup(m_context, UniformValueCase::getCheckMethodName(checkMethod), UniformValueCase::getCheckMethodDescription(checkMethod)); 2816 assignMethodGroup->addChild(checkMethodGroup); 2817 2818 for (int collectionGroupNdx = 0; collectionGroupNdx < (int)UNIFORMCOLLECTIONS_LAST; collectionGroupNdx++) 2819 { 2820 const int numArrayFirstElemNameCases = checkMethod == UniformValueCase::CHECKMETHOD_GET_UNIFORM && collectionGroupNdx == UNIFORMCOLLECTIONS_BASIC_ARRAY ? 2 : 1; 2821 2822 for (int referToFirstArrayElemWithoutIndexI = 0; referToFirstArrayElemWithoutIndexI < numArrayFirstElemNameCases; referToFirstArrayElemWithoutIndexI++) 2823 { 2824 const UniformCollectionGroup& collectionGroup = defaultUniformCollections[collectionGroupNdx]; 2825 const string collectionGroupName = collectionGroup.name + (referToFirstArrayElemWithoutIndexI == 0 ? "" : "_first_elem_without_brackets"); 2826 TestCaseGroup* collectionTestGroup = DE_NULL; 2827 2828 for (int collectionNdx = 0; collectionNdx < (int)collectionGroup.cases.size(); collectionNdx++) 2829 { 2830 const UniformCollectionCase& collectionCase = collectionGroup.cases[collectionNdx]; 2831 const string collName = collectionCase.namePrefix; 2832 const SharedPtr<const UniformCollection>& uniformCollection = collectionCase.uniformCollection; 2833 const bool containsBooleans = uniformCollection->containsMatchingBasicType(glu::isDataTypeBoolOrBVec); 2834 const bool varyBoolApiType = checkMethod == UniformValueCase::CHECKMETHOD_GET_UNIFORM && containsBooleans && 2835 (collectionGroupNdx == UNIFORMCOLLECTIONS_BASIC || collectionGroupNdx == UNIFORMCOLLECTIONS_BASIC_ARRAY); 2836 const int numBoolVariations = varyBoolApiType ? 3 : 1; 2837 const bool containsMatrices = uniformCollection->containsMatchingBasicType(glu::isDataTypeMatrix); 2838 const bool varyMatrixMode = containsMatrices && 2839 (collectionGroupNdx == UNIFORMCOLLECTIONS_BASIC || collectionGroupNdx == UNIFORMCOLLECTIONS_BASIC_ARRAY); 2840 const int numMatVariations = varyMatrixMode ? 2 : 1; 2841 2842 if (containsMatrices && assignMethod != UniformValueCase::ASSIGNMETHOD_POINTER) 2843 continue; 2844 2845 for (int booleanTypeI = 0; booleanTypeI < numBoolVariations; booleanTypeI++) 2846 { 2847 const deUint32 booleanTypeFeat = booleanTypeI == 1 ? UniformCase::FEATURE_BOOLEANAPITYPE_INT 2848 : booleanTypeI == 2 ? UniformCase::FEATURE_BOOLEANAPITYPE_UINT 2849 : 0; 2850 const char* const booleanTypeName = booleanTypeI == 1 ? "int" 2851 : booleanTypeI == 2 ? "uint" 2852 : "float"; 2853 const string nameWithBoolType = varyBoolApiType ? collName + "api_" + booleanTypeName + "_" : collName; 2854 2855 for (int matrixTypeI = 0; matrixTypeI < numMatVariations; matrixTypeI++) 2856 { 2857 const string nameWithMatrixType = nameWithBoolType + (matrixTypeI == 1 ? "row_major_" : ""); 2858 2859 for (int shaderType = 0; shaderType < (int)CASESHADERTYPE_LAST; shaderType++) 2860 { 2861 const string name = nameWithMatrixType + getCaseShaderTypeName((CaseShaderType)shaderType); 2862 const deUint32 arrayFirstElemNameNoIndexFeat = referToFirstArrayElemWithoutIndexI == 0 ? 0 : UniformCase::FEATURE_ARRAY_FIRST_ELEM_NAME_NO_INDEX; 2863 2864 // skip empty groups by creating groups on demand 2865 if (!collectionTestGroup) 2866 { 2867 collectionTestGroup = new TestCaseGroup(m_context, collectionGroupName.c_str(), ""); 2868 checkMethodGroup->addChild(collectionTestGroup); 2869 } 2870 2871 collectionTestGroup->addChild(new UniformValueCase(m_context, name.c_str(), "", (CaseShaderType)shaderType, uniformCollection, 2872 UniformValueCase::VALUETOCHECK_ASSIGNED, checkMethod, assignMethod, 2873 booleanTypeFeat | arrayFirstElemNameNoIndexFeat | (matrixTypeI == 1 ? UniformCase::FEATURE_MATRIXMODE_ROWMAJOR : 0))); 2874 } 2875 } 2876 } 2877 } 2878 } 2879 } 2880 } 2881 } 2882 2883 // Cases assign multiple basic-array elements with one glUniform*v() (i.e. the count parameter is bigger than 1). 2884 2885 { 2886 static const struct 2887 { 2888 UniformCase::Feature arrayAssignMode; 2889 const char* name; 2890 const char* description; 2891 } arrayAssignGroups[] = 2892 { 2893 { UniformCase::FEATURE_ARRAYASSIGN_FULL, "basic_array_assign_full", "Assign entire basic-type arrays per glUniform*v() call" }, 2894 { UniformCase::FEATURE_ARRAYASSIGN_BLOCKS_OF_TWO, "basic_array_assign_partial", "Assign two elements of a basic-type array per glUniform*v() call" } 2895 }; 2896 2897 for (int arrayAssignGroupNdx = 0; arrayAssignGroupNdx < DE_LENGTH_OF_ARRAY(arrayAssignGroups); arrayAssignGroupNdx++) 2898 { 2899 UniformCase::Feature arrayAssignMode = arrayAssignGroups[arrayAssignGroupNdx].arrayAssignMode; 2900 const char* const groupName = arrayAssignGroups[arrayAssignGroupNdx].name; 2901 const char* const groupDesc = arrayAssignGroups[arrayAssignGroupNdx].description; 2902 2903 TestCaseGroup* const curArrayAssignGroup = new TestCaseGroup(m_context, groupName, groupDesc); 2904 assignedValuesGroup->addChild(curArrayAssignGroup); 2905 2906 static const int basicArrayCollectionGroups[] = { UNIFORMCOLLECTIONS_BASIC_ARRAY, UNIFORMCOLLECTIONS_ARRAY_IN_STRUCT, UNIFORMCOLLECTIONS_MULTIPLE_BASIC_ARRAY }; 2907 2908 for (int collectionGroupNdx = 0; collectionGroupNdx < DE_LENGTH_OF_ARRAY(basicArrayCollectionGroups); collectionGroupNdx++) 2909 { 2910 const UniformCollectionGroup& collectionGroup = defaultUniformCollections[basicArrayCollectionGroups[collectionGroupNdx]]; 2911 TestCaseGroup* const collectionTestGroup = new TestCaseGroup(m_context, collectionGroup.name.c_str(), ""); 2912 curArrayAssignGroup->addChild(collectionTestGroup); 2913 2914 for (int collectionNdx = 0; collectionNdx < (int)collectionGroup.cases.size(); collectionNdx++) 2915 { 2916 const UniformCollectionCase& collectionCase = collectionGroup.cases[collectionNdx]; 2917 const string collName = collectionCase.namePrefix; 2918 const SharedPtr<const UniformCollection>& uniformCollection = collectionCase.uniformCollection; 2919 2920 for (int shaderType = 0; shaderType < (int)CASESHADERTYPE_LAST; shaderType++) 2921 { 2922 const string name = collName + getCaseShaderTypeName((CaseShaderType)shaderType); 2923 collectionTestGroup->addChild(new UniformValueCase(m_context, name.c_str(), "", (CaseShaderType)shaderType, uniformCollection, 2924 UniformValueCase::VALUETOCHECK_ASSIGNED, UniformValueCase::CHECKMETHOD_GET_UNIFORM, UniformValueCase::ASSIGNMETHOD_POINTER, 2925 arrayAssignMode)); 2926 } 2927 } 2928 } 2929 } 2930 } 2931 2932 // Value checking cases when unused uniforms are present. 2933 2934 { 2935 TestCaseGroup* const unusedUniformsGroup = new TestCaseGroup(m_context, "unused_uniforms", "Test with unused uniforms"); 2936 assignedValuesGroup->addChild(unusedUniformsGroup); 2937 2938 const UniformCollectionGroup& collectionGroup = defaultUniformCollections[UNIFORMCOLLECTIONS_ARRAY_IN_STRUCT]; 2939 2940 for (int collectionNdx = 0; collectionNdx < (int)collectionGroup.cases.size(); collectionNdx++) 2941 { 2942 const UniformCollectionCase& collectionCase = collectionGroup.cases[collectionNdx]; 2943 const string collName = collectionCase.namePrefix; 2944 const SharedPtr<const UniformCollection>& uniformCollection = collectionCase.uniformCollection; 2945 2946 for (int shaderType = 0; shaderType < (int)CASESHADERTYPE_LAST; shaderType++) 2947 { 2948 const string name = collName + getCaseShaderTypeName((CaseShaderType)shaderType); 2949 unusedUniformsGroup->addChild(new UniformValueCase(m_context, name.c_str(), "", (CaseShaderType)shaderType, uniformCollection, 2950 UniformValueCase::VALUETOCHECK_ASSIGNED, UniformValueCase::CHECKMETHOD_GET_UNIFORM, UniformValueCase::ASSIGNMETHOD_POINTER, 2951 UniformCase::FEATURE_ARRAYUSAGE_ONLY_MIDDLE_INDEX | UniformCase::FEATURE_UNIFORMUSAGE_EVERY_OTHER)); 2952 } 2953 } 2954 } 2955 } 2956 } 2957 2958 // Random cases. 2959 2960 { 2961 const int numRandomCases = 100; 2962 TestCaseGroup* const randomGroup = new TestCaseGroup(m_context, "random", "Random cases"); 2963 addChild(randomGroup); 2964 2965 for (int ndx = 0; ndx < numRandomCases; ndx++) 2966 randomGroup->addChild(new RandomUniformCase(m_context, de::toString(ndx).c_str(), "", (deUint32)ndx)); 2967 } 2968 } 2969 2970 } // Functional 2971 } // gles3 2972 } // deqp 2973