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, deUint32 features); 942 UniformCase (Context& context, const char* name, const char* description, deUint32 seed); // \note Randomizes caseType, uniformCollection and features. 943 virtual ~UniformCase (void); 944 945 virtual void init (void); 946 virtual void deinit (void); 947 948 IterateResult iterate (void); 949 950 protected: 951 // A basic uniform is a uniform (possibly struct or array member) whose type is a basic type (e.g. float, ivec4, sampler2d). 952 struct BasicUniform 953 { 954 string name; 955 glu::DataType type; 956 bool isUsedInShader; 957 VarValue finalValue; //!< The value we ultimately want to set for this uniform. 958 959 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. 960 int elemNdx; //!< If this is a member of a basic-typed array, elemNdx is the index in that array. Otherwise -1. 961 int rootSize; //!< If this is a member of a basic-typed array, rootSize is the size of that array. Otherwise 1. 962 963 BasicUniform (const char* const name_, 964 const glu::DataType type_, 965 const bool isUsedInShader_, 966 const VarValue& finalValue_, 967 const char* const rootName_ = DE_NULL, 968 const int elemNdx_ = -1, 969 const int rootSize_ = 1) 970 : name (name_) 971 , type (type_) 972 , isUsedInShader (isUsedInShader_) 973 , finalValue (finalValue_) 974 , rootName (rootName_ == DE_NULL ? name_ : rootName_) 975 , elemNdx (elemNdx_) 976 , rootSize (rootSize_) 977 { 978 } 979 980 static vector<BasicUniform>::const_iterator findWithName (const vector<BasicUniform>& vec, const char* const name) 981 { 982 for (vector<BasicUniform>::const_iterator it = vec.begin(); it != vec.end(); it++) 983 { 984 if (it->name == name) 985 return it; 986 } 987 return vec.end(); 988 } 989 }; 990 991 // Reference values for info that is expected to be reported by glGetActiveUniform() or glGetActiveUniformsiv(). 992 struct BasicUniformReportRef 993 { 994 string name; 995 // \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. 996 int minSize; 997 int maxSize; 998 glu::DataType type; 999 bool isUsedInShader; 1000 1001 BasicUniformReportRef (const char* const name_, const int minS, const int maxS, const glu::DataType type_, const bool used) 1002 : name(name_), minSize(minS), maxSize(maxS), type(type_), isUsedInShader(used) { DE_ASSERT(minSize <= maxSize); } 1003 BasicUniformReportRef (const char* const name_, const glu::DataType type_, const bool used) 1004 : name(name_), minSize(1), maxSize(1), type(type_), isUsedInShader(used) {} 1005 }; 1006 1007 // Info that is actually reported by glGetActiveUniform() or glGetActiveUniformsiv(). 1008 struct BasicUniformReportGL 1009 { 1010 string name; 1011 int nameLength; // \note Whether this includes the null byte depends on whether it was queried with glGetActiveUniform() or glGetActiveUniformsiv(). 1012 int size; 1013 glu::DataType type; 1014 1015 int index; 1016 1017 BasicUniformReportGL (const char* const name_, const int nameLength_, const int size_, const glu::DataType type_, const int index_) 1018 : name(name_), nameLength(nameLength_), size(size_), type(type_), index(index_) {} 1019 1020 static vector<BasicUniformReportGL>::const_iterator findWithName (const vector<BasicUniformReportGL>& vec, const char* const name) 1021 { 1022 for (vector<BasicUniformReportGL>::const_iterator it = vec.begin(); it != vec.end(); it++) 1023 { 1024 if (it->name == name) 1025 return it; 1026 } 1027 return vec.end(); 1028 } 1029 }; 1030 1031 // Query info with glGetActiveUniform() and check validity. 1032 bool getActiveUniforms (vector<BasicUniformReportGL>& dst, const vector<BasicUniformReportRef>& ref, deUint32 programGL); 1033 // Query info with glGetUniformIndices() + glGetActiveUniformsiv() and check validity. 1034 bool getActiveUniformsiv (vector<BasicUniformReportGL>& dst, const vector<BasicUniformReportRef>& ref, deUint32 programGL); 1035 // Compare infos returned by glGetActiveUniform() and glGetUniformIndices() + glGetActiveUniformsiv(). 1036 bool uniformVsUniformsivComparison (const vector<BasicUniformReportGL>& uniformsResult, const vector<BasicUniformReportGL>& uniformsivResult); 1037 // Get uniform values with glGetUniform*() and put to valuesDst. Uniforms that get -1 from glGetUniformLocation() get glu::TYPE_INVALID. 1038 bool getUniforms (vector<VarValue>& valuesDst, const vector<BasicUniform>& basicUniforms, deUint32 programGL); 1039 // Check that every uniform has the default (zero) value. 1040 bool checkUniformDefaultValues (const vector<VarValue>& values, const vector<BasicUniform>& basicUniforms); 1041 // Assign the basicUniforms[].finalValue values for uniforms. \note rnd parameter is for booleans (true can be any nonzero value). 1042 void assignUniforms (const vector<BasicUniform>& basicUniforms, deUint32 programGL, Random& rnd); 1043 // Compare the uniform values given in values (obtained with glGetUniform*()) with the basicUniform.finalValue values. 1044 bool compareUniformValues (const vector<VarValue>& values, const vector<BasicUniform>& basicUniforms); 1045 // Render and check that all pixels are white (i.e. all uniform comparisons passed). 1046 bool renderTest (const vector<BasicUniform>& basicUniforms, const ShaderProgram& program, Random& rnd); 1047 1048 virtual bool test (const vector<BasicUniform>& basicUniforms, const vector<BasicUniformReportRef>& basicUniformReportsRef, const ShaderProgram& program, Random& rnd) = 0; 1049 1050 const deUint32 m_features; 1051 const SharedPtr<const UniformCollection> m_uniformCollection; 1052 1053 private: 1054 static deUint32 randomFeatures (deUint32 seed); 1055 1056 // Generates the basic uniforms, based on the uniform with name varName and type varType, in the same manner as are expected 1057 // to be returned by glGetActiveUniform(), e.g. generates a name like var[0] for arrays, and recursively generates struct member names. 1058 void generateBasicUniforms (vector<BasicUniform>& basicUniformsDst, 1059 vector<BasicUniformReportRef>& basicUniformReportsDst, 1060 const glu::VarType& varType, 1061 const char* varName, 1062 bool isParentActive, 1063 int& samplerUnitCounter, 1064 Random& rnd) const; 1065 1066 void writeUniformDefinitions (std::ostringstream& dst) const; 1067 void writeUniformCompareExpr (std::ostringstream& dst, const BasicUniform& uniform) const; 1068 void writeUniformComparisons (std::ostringstream& dst, const vector<BasicUniform>& basicUniforms, const char* variableName) const; 1069 1070 string generateVertexSource (const vector<BasicUniform>& basicUniforms) const; 1071 string generateFragmentSource (const vector<BasicUniform>& basicUniforms) const; 1072 1073 void setupTexture (const VarValue& value); 1074 1075 const CaseShaderType m_caseShaderType; 1076 1077 vector<glu::Texture2D*> m_textures2d; 1078 vector<glu::TextureCube*> m_texturesCube; 1079 vector<deUint32> m_filledTextureUnits; 1080 }; 1081 1082 deUint32 UniformCase::randomFeatures (const deUint32 seed) 1083 { 1084 static const deUint32 arrayUsageChoices[] = { 0, FEATURE_ARRAYUSAGE_ONLY_MIDDLE_INDEX }; 1085 static const deUint32 uniformFuncChoices[] = { 0, FEATURE_UNIFORMFUNC_VALUE }; 1086 static const deUint32 matrixModeChoices[] = { 0, FEATURE_MATRIXMODE_ROWMAJOR }; 1087 static const deUint32 arrayAssignChoices[] = { 0, FEATURE_ARRAYASSIGN_FULL, FEATURE_ARRAYASSIGN_BLOCKS_OF_TWO }; 1088 static const deUint32 uniformUsageChoices[] = { 0, FEATURE_UNIFORMUSAGE_EVERY_OTHER }; 1089 static const deUint32 booleanApiTypeChoices[] = { 0, FEATURE_BOOLEANAPITYPE_INT, FEATURE_BOOLEANAPITYPE_UINT }; 1090 static const deUint32 uniformValueChoices[] = { 0, FEATURE_UNIFORMVALUE_ZERO }; 1091 1092 Random rnd(seed); 1093 1094 deUint32 result = 0; 1095 1096 #define ARRAY_CHOICE(ARR) ((ARR)[rnd.getInt(0, DE_LENGTH_OF_ARRAY(ARR)-1)]) 1097 1098 result |= ARRAY_CHOICE(arrayUsageChoices); 1099 result |= ARRAY_CHOICE(uniformFuncChoices); 1100 result |= ARRAY_CHOICE(matrixModeChoices); 1101 result |= ARRAY_CHOICE(arrayAssignChoices); 1102 result |= ARRAY_CHOICE(uniformUsageChoices); 1103 result |= ARRAY_CHOICE(booleanApiTypeChoices); 1104 result |= ARRAY_CHOICE(uniformValueChoices); 1105 1106 #undef ARRAY_CHOICE 1107 1108 return result; 1109 } 1110 1111 UniformCase::UniformCase (Context& context, const char* const name, const char* const description, const CaseShaderType caseShaderType, const SharedPtr<const UniformCollection>& uniformCollection, const deUint32 features) 1112 : TestCase (context, name, description) 1113 , CallLogWrapper (context.getRenderContext().getFunctions(), m_testCtx.getLog()) 1114 , m_features (features) 1115 , m_uniformCollection (uniformCollection) 1116 , m_caseShaderType (caseShaderType) 1117 { 1118 } 1119 1120 UniformCase::UniformCase (Context& context, const char* name, const char* description, const deUint32 seed) 1121 : TestCase (context, name, description) 1122 , CallLogWrapper (context.getRenderContext().getFunctions(), m_testCtx.getLog()) 1123 , m_features (randomFeatures(seed)) 1124 , m_uniformCollection (UniformCollection::random(seed)) 1125 , m_caseShaderType (randomCaseShaderType(seed)) 1126 { 1127 } 1128 1129 void UniformCase::init (void) 1130 { 1131 { 1132 const glw::Functions& funcs = m_context.getRenderContext().getFunctions(); 1133 const int numSamplerUniforms = m_uniformCollection->getNumSamplers(); 1134 const int vertexTexUnitsRequired = m_caseShaderType != CASESHADERTYPE_FRAGMENT ? numSamplerUniforms : 0; 1135 const int fragmentTexUnitsRequired = m_caseShaderType != CASESHADERTYPE_VERTEX ? numSamplerUniforms : 0; 1136 const int combinedTexUnitsRequired = vertexTexUnitsRequired + fragmentTexUnitsRequired; 1137 const int vertexTexUnitsSupported = getGLInt(funcs, GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS); 1138 const int fragmentTexUnitsSupported = getGLInt(funcs, GL_MAX_TEXTURE_IMAGE_UNITS); 1139 const int combinedTexUnitsSupported = getGLInt(funcs, GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS); 1140 1141 DE_ASSERT(numSamplerUniforms <= MAX_NUM_SAMPLER_UNIFORMS); 1142 1143 if (vertexTexUnitsRequired > vertexTexUnitsSupported) 1144 throw tcu::NotSupportedError(de::toString(vertexTexUnitsRequired) + " vertex texture units required, " + de::toString(vertexTexUnitsSupported) + " supported"); 1145 if (fragmentTexUnitsRequired > fragmentTexUnitsSupported) 1146 throw tcu::NotSupportedError(de::toString(fragmentTexUnitsRequired) + " fragment texture units required, " + de::toString(fragmentTexUnitsSupported) + " supported"); 1147 if (combinedTexUnitsRequired > combinedTexUnitsSupported) 1148 throw tcu::NotSupportedError(de::toString(combinedTexUnitsRequired) + " combined texture units required, " + de::toString(combinedTexUnitsSupported) + " supported"); 1149 } 1150 1151 enableLogging(true); 1152 } 1153 1154 void UniformCase::deinit (void) 1155 { 1156 for (int i = 0; i < (int)m_textures2d.size(); i++) 1157 delete m_textures2d[i]; 1158 m_textures2d.clear(); 1159 1160 for (int i = 0; i < (int)m_texturesCube.size(); i++) 1161 delete m_texturesCube[i]; 1162 m_texturesCube.clear(); 1163 1164 m_filledTextureUnits.clear(); 1165 } 1166 1167 UniformCase::~UniformCase (void) 1168 { 1169 UniformCase::deinit(); 1170 } 1171 1172 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 1173 { 1174 if (varType.isBasicType()) 1175 { 1176 const bool isActive = isParentActive && (m_features & FEATURE_UNIFORMUSAGE_EVERY_OTHER ? basicUniformsDst.size() % 2 == 0 : true); 1177 const glu::DataType type = varType.getBasicType(); 1178 const VarValue value = m_features & FEATURE_UNIFORMVALUE_ZERO ? generateZeroVarValue(type) 1179 : glu::isDataTypeSampler(type) ? generateRandomVarValue(type, rnd, samplerUnitCounter++) 1180 : generateRandomVarValue(varType.getBasicType(), rnd); 1181 1182 basicUniformsDst.push_back(BasicUniform(varName, varType.getBasicType(), isActive, value)); 1183 basicUniformReportsDst.push_back(BasicUniformReportRef(varName, varType.getBasicType(), isActive)); 1184 } 1185 else if (varType.isArrayType()) 1186 { 1187 const int size = varType.getArraySize(); 1188 const string arrayRootName = string("") + varName + "[0]"; 1189 vector<bool> isElemActive; 1190 1191 for (int elemNdx = 0; elemNdx < varType.getArraySize(); elemNdx++) 1192 { 1193 const string indexedName = string("") + varName + "[" + de::toString(elemNdx) + "]"; 1194 const bool isCurElemActive = isParentActive && 1195 (m_features & FEATURE_UNIFORMUSAGE_EVERY_OTHER ? basicUniformsDst.size() % 2 == 0 : true) && 1196 (m_features & FEATURE_ARRAYUSAGE_ONLY_MIDDLE_INDEX ? elemNdx == size/2 : true); 1197 1198 isElemActive.push_back(isCurElemActive); 1199 1200 if (varType.getElementType().isBasicType()) 1201 { 1202 // \note We don't want separate entries in basicUniformReportsDst for elements of basic-type arrays. 1203 const glu::DataType elemBasicType = varType.getElementType().getBasicType(); 1204 const VarValue value = m_features & FEATURE_UNIFORMVALUE_ZERO ? generateZeroVarValue(elemBasicType) 1205 : glu::isDataTypeSampler(elemBasicType) ? generateRandomVarValue(elemBasicType, rnd, samplerUnitCounter++) 1206 : generateRandomVarValue(elemBasicType, rnd); 1207 1208 basicUniformsDst.push_back(BasicUniform(indexedName.c_str(), elemBasicType, isCurElemActive, value, arrayRootName.c_str(), elemNdx, size)); 1209 } 1210 else 1211 generateBasicUniforms(basicUniformsDst, basicUniformReportsDst, varType.getElementType(), indexedName.c_str(), isCurElemActive, samplerUnitCounter, rnd); 1212 } 1213 1214 if (varType.getElementType().isBasicType()) 1215 { 1216 int minSize; 1217 for (minSize = varType.getArraySize(); minSize > 0 && !isElemActive[minSize-1]; minSize--); 1218 1219 basicUniformReportsDst.push_back(BasicUniformReportRef(arrayRootName.c_str(), minSize, size, varType.getElementType().getBasicType(), isParentActive && minSize > 0)); 1220 } 1221 } 1222 else 1223 { 1224 DE_ASSERT(varType.isStructType()); 1225 1226 const StructType& structType = *varType.getStructPtr(); 1227 1228 for (int i = 0; i < structType.getNumMembers(); i++) 1229 { 1230 const glu::StructMember& member = structType.getMember(i); 1231 const string memberFullName = string("") + varName + "." + member.getName(); 1232 1233 generateBasicUniforms(basicUniformsDst, basicUniformReportsDst, member.getType(), memberFullName.c_str(), isParentActive, samplerUnitCounter, rnd); 1234 } 1235 } 1236 } 1237 1238 void UniformCase::writeUniformDefinitions (std::ostringstream& dst) const 1239 { 1240 for (int i = 0; i < (int)m_uniformCollection->getNumStructTypes(); i++) 1241 dst << glu::declare(m_uniformCollection->getStructType(i)) << ";\n"; 1242 1243 for (int i = 0; i < (int)m_uniformCollection->getNumUniforms(); i++) 1244 dst << "uniform " << glu::declare(m_uniformCollection->getUniform(i).type, m_uniformCollection->getUniform(i).name.c_str()) << ";\n"; 1245 1246 dst << "\n"; 1247 1248 { 1249 static const struct 1250 { 1251 dataTypePredicate requiringTypes[2]; 1252 const char* definition; 1253 } compareFuncs[] = 1254 { 1255 { { glu::isDataTypeFloatOrVec, glu::isDataTypeMatrix }, "mediump float compare_float (mediump float a, mediump float b) { return abs(a - b) < 0.05 ? 1.0 : 0.0; }" }, 1256 { { 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); }" }, 1257 { { 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); }" }, 1258 { { 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); }" }, 1259 { { 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]); }" }, 1260 { { 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]); }" }, 1261 { { 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]); }" }, 1262 { { 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]); }" }, 1263 { { 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]); }" }, 1264 { { 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]); }" }, 1265 { { 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]); }" }, 1266 { { 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]); }" }, 1267 { { 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]); }" }, 1268 { { 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; }" }, 1269 { { 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; }" }, 1270 { { 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; }" }, 1271 { { 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; }" }, 1272 { { 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; }" }, 1273 { { 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; }" }, 1274 { { 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; }" }, 1275 { { 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; }" }, 1276 { { dataTypeEquals<glu::TYPE_BOOL>, dataTypeEquals<glu::TYPE_INVALID> }, "mediump float compare_bool (bool a, bool b) { return a == b ? 1.0 : 0.0; }" }, 1277 { { dataTypeEquals<glu::TYPE_BOOL_VEC2>, dataTypeEquals<glu::TYPE_INVALID> }, "mediump float compare_bvec2 (bvec2 a, bvec2 b) { return a == b ? 1.0 : 0.0; }" }, 1278 { { dataTypeEquals<glu::TYPE_BOOL_VEC3>, dataTypeEquals<glu::TYPE_INVALID> }, "mediump float compare_bvec3 (bvec3 a, bvec3 b) { return a == b ? 1.0 : 0.0; }" }, 1279 { { dataTypeEquals<glu::TYPE_BOOL_VEC4>, dataTypeEquals<glu::TYPE_INVALID> }, "mediump float compare_bvec4 (bvec4 a, bvec4 b) { return a == b ? 1.0 : 0.0; }" } 1280 }; 1281 1282 const vector<glu::DataType> samplerTypes = m_uniformCollection->getSamplerTypes(); 1283 1284 for (int compFuncNdx = 0; compFuncNdx < DE_LENGTH_OF_ARRAY(compareFuncs); compFuncNdx++) 1285 { 1286 const dataTypePredicate (&typeReq)[2] = compareFuncs[compFuncNdx].requiringTypes; 1287 bool containsTypeSampler = false; 1288 1289 for (int i = 0; i < (int)samplerTypes.size(); i++) 1290 { 1291 if (glu::isDataTypeSampler(samplerTypes[i])) 1292 { 1293 const glu::DataType retType = getSamplerLookupReturnType(samplerTypes[i]); 1294 if (typeReq[0](retType) || typeReq[1](retType)) 1295 { 1296 containsTypeSampler = true; 1297 break; 1298 } 1299 } 1300 } 1301 1302 if (containsTypeSampler || m_uniformCollection->containsMatchingBasicType(typeReq[0]) || m_uniformCollection->containsMatchingBasicType(typeReq[1])) 1303 dst << compareFuncs[compFuncNdx].definition << "\n"; 1304 } 1305 } 1306 } 1307 1308 void UniformCase::writeUniformCompareExpr (std::ostringstream& dst, const BasicUniform& uniform) const 1309 { 1310 if (glu::isDataTypeSampler(uniform.type)) 1311 dst << "compare_" << glu::getDataTypeName(getSamplerLookupReturnType(uniform.type)) << "(texture(" << uniform.name << ", vec" << getSamplerNumLookupDimensions(uniform.type) << "(0.0))"; 1312 else 1313 dst << "compare_" << glu::getDataTypeName(uniform.type) << "(" << uniform.name; 1314 1315 dst << ", " << shaderVarValueStr(uniform.finalValue) << ")"; 1316 } 1317 1318 void UniformCase::writeUniformComparisons (std::ostringstream& dst, const vector<BasicUniform>& basicUniforms, const char* const variableName) const 1319 { 1320 for (int i = 0; i < (int)basicUniforms.size(); i++) 1321 { 1322 const BasicUniform& unif = basicUniforms[i]; 1323 1324 if (unif.isUsedInShader) 1325 { 1326 dst << "\t" << variableName << " *= "; 1327 writeUniformCompareExpr(dst, basicUniforms[i]); 1328 dst << ";\n"; 1329 } 1330 else 1331 dst << "\t// UNUSED: " << basicUniforms[i].name << "\n"; 1332 } 1333 } 1334 1335 string UniformCase::generateVertexSource (const vector<BasicUniform>& basicUniforms) const 1336 { 1337 const bool isVertexCase = m_caseShaderType == CASESHADERTYPE_VERTEX || m_caseShaderType == CASESHADERTYPE_BOTH; 1338 std::ostringstream result; 1339 1340 result << "#version 300 es\n" 1341 "in highp vec4 a_position;\n" 1342 "out mediump float v_vtxOut;\n" 1343 "\n"; 1344 1345 if (isVertexCase) 1346 writeUniformDefinitions(result); 1347 1348 result << "\n" 1349 "void main (void)\n" 1350 "{\n" 1351 " gl_Position = a_position;\n" 1352 " v_vtxOut = 1.0;\n"; 1353 1354 if (isVertexCase) 1355 writeUniformComparisons(result, basicUniforms, "v_vtxOut"); 1356 1357 result << "}\n"; 1358 1359 return result.str(); 1360 } 1361 1362 string UniformCase::generateFragmentSource (const vector<BasicUniform>& basicUniforms) const 1363 { 1364 const bool isFragmentCase = m_caseShaderType == CASESHADERTYPE_FRAGMENT || m_caseShaderType == CASESHADERTYPE_BOTH; 1365 std::ostringstream result; 1366 1367 result << "#version 300 es\n" 1368 "in mediump float v_vtxOut;\n" 1369 "\n"; 1370 1371 if (isFragmentCase) 1372 writeUniformDefinitions(result); 1373 1374 result << "\n" 1375 "layout(location = 0) out mediump vec4 dEQP_FragColor;\n" 1376 "\n" 1377 "void main (void)\n" 1378 "{\n" 1379 " mediump float result = v_vtxOut;\n"; 1380 1381 if (isFragmentCase) 1382 writeUniformComparisons(result, basicUniforms, "result"); 1383 1384 result << " dEQP_FragColor = vec4(result, result, result, 1.0);\n" 1385 "}\n"; 1386 1387 return result.str(); 1388 } 1389 1390 void UniformCase::setupTexture (const VarValue& value) 1391 { 1392 // \note No handling for samplers other than 2D or cube. 1393 1394 enableLogging(false); 1395 1396 DE_ASSERT(getSamplerLookupReturnType(value.type) == glu::TYPE_FLOAT_VEC4); 1397 1398 const int width = 32; 1399 const int height = 32; 1400 const tcu::Vec4 color = vec4FromPtr(&value.val.samplerV.fillColor.floatV[0]); 1401 1402 if (value.type == glu::TYPE_SAMPLER_2D) 1403 { 1404 glu::Texture2D* texture = new glu::Texture2D(m_context.getRenderContext(), GL_RGBA, GL_UNSIGNED_BYTE, width, height); 1405 tcu::Texture2D& refTexture = texture->getRefTexture(); 1406 m_textures2d.push_back(texture); 1407 1408 refTexture.allocLevel(0); 1409 fillWithColor(refTexture.getLevel(0), color); 1410 1411 GLU_CHECK_CALL(glActiveTexture(GL_TEXTURE0 + value.val.samplerV.unit)); 1412 m_filledTextureUnits.push_back(value.val.samplerV.unit); 1413 texture->upload(); 1414 GLU_CHECK_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)); 1415 GLU_CHECK_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)); 1416 GLU_CHECK_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)); 1417 GLU_CHECK_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)); 1418 } 1419 else if (value.type == glu::TYPE_SAMPLER_CUBE) 1420 { 1421 DE_ASSERT(width == height); 1422 1423 glu::TextureCube* texture = new glu::TextureCube(m_context.getRenderContext(), GL_RGBA, GL_UNSIGNED_BYTE, width); 1424 tcu::TextureCube& refTexture = texture->getRefTexture(); 1425 m_texturesCube.push_back(texture); 1426 1427 for (int face = 0; face < (int)tcu::CUBEFACE_LAST; face++) 1428 { 1429 refTexture.allocLevel((tcu::CubeFace)face, 0); 1430 fillWithColor(refTexture.getLevelFace(0, (tcu::CubeFace)face), color); 1431 } 1432 1433 GLU_CHECK_CALL(glActiveTexture(GL_TEXTURE0 + value.val.samplerV.unit)); 1434 m_filledTextureUnits.push_back(value.val.samplerV.unit); 1435 texture->upload(); 1436 GLU_CHECK_CALL(glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)); 1437 GLU_CHECK_CALL(glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)); 1438 GLU_CHECK_CALL(glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST)); 1439 GLU_CHECK_CALL(glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST)); 1440 1441 } 1442 else 1443 DE_ASSERT(false); 1444 1445 enableLogging(true); 1446 } 1447 1448 bool UniformCase::getActiveUniforms (vector<BasicUniformReportGL>& basicUniformReportsDst, const vector<BasicUniformReportRef>& basicUniformReportsRef, const deUint32 programGL) 1449 { 1450 TestLog& log = m_testCtx.getLog(); 1451 GLint numActiveUniforms = 0; 1452 GLint uniformMaxNameLength = 0; 1453 vector<char> nameBuffer; 1454 bool success = true; 1455 1456 GLU_CHECK_CALL(glGetProgramiv(programGL, GL_ACTIVE_UNIFORMS, &numActiveUniforms)); 1457 log << TestLog::Message << "// Number of active uniforms reported: " << numActiveUniforms << TestLog::EndMessage; 1458 GLU_CHECK_CALL(glGetProgramiv(programGL, GL_ACTIVE_UNIFORM_MAX_LENGTH, &uniformMaxNameLength)); 1459 log << TestLog::Message << "// Maximum uniform name length reported: " << uniformMaxNameLength << TestLog::EndMessage; 1460 nameBuffer.resize(uniformMaxNameLength); 1461 1462 for (int unifNdx = 0; unifNdx < numActiveUniforms; unifNdx++) 1463 { 1464 GLsizei reportedNameLength = 0; 1465 GLint reportedSize = -1; 1466 GLenum reportedTypeGL = GL_NONE; 1467 1468 GLU_CHECK_CALL(glGetActiveUniform(programGL, (GLuint)unifNdx, (GLsizei)uniformMaxNameLength, &reportedNameLength, &reportedSize, &reportedTypeGL, &nameBuffer[0])); 1469 1470 const glu::DataType reportedType = glu::getDataTypeFromGLType(reportedTypeGL); 1471 const string reportedNameStr (&nameBuffer[0]); 1472 1473 TCU_CHECK_MSG(reportedType != glu::TYPE_LAST, "Invalid uniform type"); 1474 1475 log << TestLog::Message << "// Got name = " << reportedNameStr << ", name length = " << reportedNameLength << ", size = " << reportedSize << ", type = " << glu::getDataTypeName(reportedType) << TestLog::EndMessage; 1476 1477 if ((GLsizei)reportedNameStr.length() != reportedNameLength) 1478 { 1479 log << TestLog::Message << "// FAILURE: wrong name length reported, should be " << reportedNameStr.length() << TestLog::EndMessage; 1480 success = false; 1481 } 1482 1483 if (!deStringBeginsWith(reportedNameStr.c_str(), "gl_")) // Ignore built-in uniforms. 1484 { 1485 int referenceNdx; 1486 for (referenceNdx = 0; referenceNdx < (int)basicUniformReportsRef.size(); referenceNdx++) 1487 { 1488 if (basicUniformReportsRef[referenceNdx].name == reportedNameStr) 1489 break; 1490 } 1491 1492 if (referenceNdx >= (int)basicUniformReportsRef.size()) 1493 { 1494 log << TestLog::Message << "// FAILURE: invalid non-built-in uniform name reported" << TestLog::EndMessage; 1495 success = false; 1496 } 1497 else 1498 { 1499 const BasicUniformReportRef& reference = basicUniformReportsRef[referenceNdx]; 1500 1501 DE_ASSERT(reference.type != glu::TYPE_LAST); 1502 DE_ASSERT(reference.minSize >= 1 || (reference.minSize == 0 && !reference.isUsedInShader)); 1503 DE_ASSERT(reference.minSize <= reference.maxSize); 1504 1505 if (BasicUniformReportGL::findWithName(basicUniformReportsDst, reportedNameStr.c_str()) != basicUniformReportsDst.end()) 1506 { 1507 log << TestLog::Message << "// FAILURE: same uniform name reported twice" << TestLog::EndMessage; 1508 success = false; 1509 } 1510 1511 basicUniformReportsDst.push_back(BasicUniformReportGL(reportedNameStr.c_str(), reportedNameLength, reportedSize, reportedType, unifNdx)); 1512 1513 if (reportedType != reference.type) 1514 { 1515 log << TestLog::Message << "// FAILURE: wrong type reported, should be " << glu::getDataTypeName(reference.type) << TestLog::EndMessage; 1516 success = false; 1517 } 1518 if (reportedSize < reference.minSize || reportedSize > reference.maxSize) 1519 { 1520 log << TestLog::Message 1521 << "// FAILURE: wrong size reported, should be " 1522 << (reference.minSize == reference.maxSize ? de::toString(reference.minSize) : "in the range [" + de::toString(reference.minSize) + ", " + de::toString(reference.maxSize) + "]") 1523 << TestLog::EndMessage; 1524 1525 success = false; 1526 } 1527 } 1528 } 1529 } 1530 1531 for (int i = 0; i < (int)basicUniformReportsRef.size(); i++) 1532 { 1533 const BasicUniformReportRef& expected = basicUniformReportsRef[i]; 1534 if (expected.isUsedInShader && BasicUniformReportGL::findWithName(basicUniformReportsDst, expected.name.c_str()) == basicUniformReportsDst.end()) 1535 { 1536 log << TestLog::Message << "// FAILURE: uniform with name " << expected.name << " was not reported by GL" << TestLog::EndMessage; 1537 success = false; 1538 } 1539 } 1540 1541 return success; 1542 } 1543 1544 bool UniformCase::getActiveUniformsiv (vector<BasicUniformReportGL>& basicUniformReportsDst, const vector<BasicUniformReportRef>& basicUniformReportsRef, const deUint32 programGL) 1545 { 1546 TestLog& log = m_testCtx.getLog(); 1547 vector<string> queryNames (basicUniformReportsRef.size()); 1548 vector<const char*> queryNamesC (basicUniformReportsRef.size()); 1549 vector<GLuint> uniformIndices (basicUniformReportsRef.size()); 1550 vector<deUint32> validUniformIndices; // This shall have the same contents, and in same order, as uniformIndices, but with GL_INVALID_INDEX entries removed. 1551 bool success = true; 1552 1553 for (int i = 0; i < (int)basicUniformReportsRef.size(); i++) 1554 { 1555 const string& name = basicUniformReportsRef[i].name; 1556 queryNames[i] = m_features & FEATURE_ARRAY_FIRST_ELEM_NAME_NO_INDEX && name[name.size()-1] == ']' ? beforeLast(name, '[') : name; 1557 queryNamesC[i] = queryNames[i].c_str(); 1558 } 1559 1560 GLU_CHECK_CALL(glGetUniformIndices(programGL, (GLsizei)basicUniformReportsRef.size(), &queryNamesC[0], &uniformIndices[0])); 1561 1562 for (int i = 0; i < (int)uniformIndices.size(); i++) 1563 { 1564 if (uniformIndices[i] != GL_INVALID_INDEX) 1565 validUniformIndices.push_back(uniformIndices[i]); 1566 else 1567 { 1568 if (basicUniformReportsRef[i].isUsedInShader) 1569 { 1570 log << TestLog::Message << "// FAILURE: uniform with name " << basicUniformReportsRef[i].name << " received GL_INVALID_INDEX" << TestLog::EndMessage; 1571 success = false; 1572 } 1573 } 1574 } 1575 1576 if (!validUniformIndices.empty()) 1577 { 1578 vector<GLint> uniformNameLengthBuf (validUniformIndices.size()); 1579 vector<GLint> uniformSizeBuf (validUniformIndices.size()); 1580 vector<GLint> uniformTypeBuf (validUniformIndices.size()); 1581 1582 GLU_CHECK_CALL(glGetActiveUniformsiv(programGL, (GLsizei)validUniformIndices.size(), &validUniformIndices[0], GL_UNIFORM_NAME_LENGTH, &uniformNameLengthBuf[0])); 1583 GLU_CHECK_CALL(glGetActiveUniformsiv(programGL, (GLsizei)validUniformIndices.size(), &validUniformIndices[0], GL_UNIFORM_SIZE, &uniformSizeBuf[0])); 1584 GLU_CHECK_CALL(glGetActiveUniformsiv(programGL, (GLsizei)validUniformIndices.size(), &validUniformIndices[0], GL_UNIFORM_TYPE, &uniformTypeBuf[0])); 1585 1586 { 1587 int validNdx = -1; // Keeps the corresponding index to validUniformIndices while unifNdx is the index to uniformIndices. 1588 for (int unifNdx = 0; unifNdx < (int)uniformIndices.size(); unifNdx++) 1589 { 1590 if (uniformIndices[unifNdx] == GL_INVALID_INDEX) 1591 continue; 1592 1593 validNdx++; 1594 1595 const BasicUniformReportRef& reference = basicUniformReportsRef[unifNdx]; 1596 const int reportedIndex = validUniformIndices[validNdx]; 1597 const int reportedNameLength = (int)uniformNameLengthBuf[validNdx]; 1598 const int reportedSize = (int)uniformSizeBuf[validNdx]; 1599 const glu::DataType reportedType = glu::getDataTypeFromGLType((deUint32)uniformTypeBuf[validNdx]); 1600 1601 TCU_CHECK_MSG(reportedType != glu::TYPE_LAST, "Invalid uniform type"); 1602 1603 log << TestLog::Message 1604 << "// Got name length = " << reportedNameLength 1605 << ", size = " << reportedSize 1606 << ", type = " << glu::getDataTypeName(reportedType) 1607 << " for the uniform at index " << reportedIndex << " (" << reference.name << ")" 1608 << TestLog::EndMessage; 1609 1610 DE_ASSERT(reference.type != glu::TYPE_LAST); 1611 DE_ASSERT(reference.minSize >= 1 || (reference.minSize == 0 && !reference.isUsedInShader)); 1612 DE_ASSERT(reference.minSize <= reference.maxSize); 1613 basicUniformReportsDst.push_back(BasicUniformReportGL(reference.name.c_str(), reportedNameLength, reportedSize, reportedType, reportedIndex)); 1614 1615 if (reportedNameLength != (int)reference.name.length() + 1) 1616 { 1617 log << TestLog::Message << "// FAILURE: wrong name length reported, should be " << reference.name.length() + 1 << TestLog::EndMessage; 1618 success = false; 1619 } 1620 1621 if (reportedType != reference.type) 1622 { 1623 log << TestLog::Message << "// FAILURE: wrong type reported, should be " << glu::getDataTypeName(reference.type) << TestLog::EndMessage; 1624 success = false; 1625 } 1626 1627 if (reportedSize < reference.minSize || reportedSize > reference.maxSize) 1628 { 1629 log << TestLog::Message 1630 << "// FAILURE: wrong size reported, should be " 1631 << (reference.minSize == reference.maxSize ? de::toString(reference.minSize) : "in the range [" + de::toString(reference.minSize) + ", " + de::toString(reference.maxSize) + "]") 1632 << TestLog::EndMessage; 1633 1634 success = false; 1635 } 1636 } 1637 } 1638 } 1639 1640 return success; 1641 } 1642 1643 bool UniformCase::uniformVsUniformsivComparison (const vector<BasicUniformReportGL>& uniformResults, const vector<BasicUniformReportGL>& uniformsivResults) 1644 { 1645 TestLog& log = m_testCtx.getLog(); 1646 bool success = true; 1647 1648 for (int uniformResultNdx = 0; uniformResultNdx < (int)uniformResults.size(); uniformResultNdx++) 1649 { 1650 const BasicUniformReportGL& uniformResult = uniformResults[uniformResultNdx]; 1651 const string& uniformName = uniformResult.name; 1652 const vector<BasicUniformReportGL>::const_iterator uniformsivResultIt = BasicUniformReportGL::findWithName(uniformsivResults, uniformName.c_str()); 1653 1654 if (uniformsivResultIt != uniformsivResults.end()) 1655 { 1656 const BasicUniformReportGL& uniformsivResult = *uniformsivResultIt; 1657 1658 log << TestLog::Message << "// Checking uniform " << uniformName << TestLog::EndMessage; 1659 1660 if (uniformResult.index != uniformsivResult.index) 1661 { 1662 log << TestLog::Message << "// FAILURE: glGetActiveUniform() and glGetUniformIndices() gave different indices for uniform " << uniformName << TestLog::EndMessage; 1663 success = false; 1664 } 1665 if (uniformResult.nameLength + 1 != uniformsivResult.nameLength) 1666 { 1667 log << TestLog::Message << "// FAILURE: glGetActiveUniform() and glGetActiveUniformsiv() gave incompatible name lengths for uniform " << uniformName << TestLog::EndMessage; 1668 success = false; 1669 } 1670 if (uniformResult.size != uniformsivResult.size) 1671 { 1672 log << TestLog::Message << "// FAILURE: glGetActiveUniform() and glGetActiveUniformsiv() gave different sizes for uniform " << uniformName << TestLog::EndMessage; 1673 success = false; 1674 } 1675 if (uniformResult.type != uniformsivResult.type) 1676 { 1677 log << TestLog::Message << "// FAILURE: glGetActiveUniform() and glGetActiveUniformsiv() gave different types for uniform " << uniformName << TestLog::EndMessage; 1678 success = false; 1679 } 1680 } 1681 else 1682 { 1683 log << TestLog::Message << "// FAILURE: uniform " << uniformName << " was reported active by glGetActiveUniform() but not by glGetUniformIndices()" << TestLog::EndMessage; 1684 success = false; 1685 } 1686 } 1687 1688 for (int uniformsivResultNdx = 0; uniformsivResultNdx < (int)uniformsivResults.size(); uniformsivResultNdx++) 1689 { 1690 const BasicUniformReportGL& uniformsivResult = uniformsivResults[uniformsivResultNdx]; 1691 const string& uniformsivName = uniformsivResult.name; 1692 const vector<BasicUniformReportGL>::const_iterator uniformsResultIt = BasicUniformReportGL::findWithName(uniformsivResults, uniformsivName.c_str()); 1693 1694 if (uniformsResultIt == uniformsivResults.end()) 1695 { 1696 log << TestLog::Message << "// FAILURE: uniform " << uniformsivName << " was reported active by glGetUniformIndices() but not by glGetActiveUniform()" << TestLog::EndMessage; 1697 success = false; 1698 } 1699 } 1700 1701 return success; 1702 } 1703 1704 bool UniformCase::getUniforms (vector<VarValue>& valuesDst, const vector<BasicUniform>& basicUniforms, const deUint32 programGL) 1705 { 1706 TestLog& log = m_testCtx.getLog(); 1707 bool success = true; 1708 1709 for (int unifNdx = 0; unifNdx < (int)basicUniforms.size(); unifNdx++) 1710 { 1711 const BasicUniform& uniform = basicUniforms[unifNdx]; 1712 const string queryName = m_features & FEATURE_ARRAY_FIRST_ELEM_NAME_NO_INDEX && uniform.elemNdx == 0 ? beforeLast(uniform.name, '[') : uniform.name; 1713 const int location = glGetUniformLocation(programGL, queryName.c_str()); 1714 const int size = glu::getDataTypeScalarSize(uniform.type); 1715 VarValue value; 1716 1717 deMemset(&value, 0xcd, sizeof(value)); // Initialize to known garbage. 1718 1719 if (location == -1) 1720 { 1721 value.type = glu::TYPE_INVALID; 1722 valuesDst.push_back(value); 1723 if (uniform.isUsedInShader) 1724 { 1725 log << TestLog::Message << "// FAILURE: " << uniform.name << " was used in shader, but has location -1" << TestLog::EndMessage; 1726 success = false; 1727 } 1728 continue; 1729 } 1730 1731 value.type = uniform.type; 1732 1733 DE_STATIC_ASSERT(sizeof(GLint) == sizeof(value.val.intV[0])); 1734 DE_STATIC_ASSERT(sizeof(GLuint) == sizeof(value.val.uintV[0])); 1735 DE_STATIC_ASSERT(sizeof(GLfloat) == sizeof(value.val.floatV[0])); 1736 1737 if (glu::isDataTypeFloatOrVec(uniform.type) || glu::isDataTypeMatrix(uniform.type)) 1738 GLU_CHECK_CALL(glGetUniformfv(programGL, location, &value.val.floatV[0])); 1739 else if (glu::isDataTypeIntOrIVec(uniform.type)) 1740 GLU_CHECK_CALL(glGetUniformiv(programGL, location, &value.val.intV[0])); 1741 else if (glu::isDataTypeUintOrUVec(uniform.type)) 1742 GLU_CHECK_CALL(glGetUniformuiv(programGL, location, &value.val.uintV[0])); 1743 else if (glu::isDataTypeBoolOrBVec(uniform.type)) 1744 { 1745 if (m_features & FEATURE_BOOLEANAPITYPE_INT) 1746 { 1747 GLU_CHECK_CALL(glGetUniformiv(programGL, location, &value.val.intV[0])); 1748 for (int i = 0; i < size; i++) 1749 value.val.boolV[i] = value.val.intV[i] != 0; 1750 } 1751 else if (m_features & FEATURE_BOOLEANAPITYPE_UINT) 1752 { 1753 GLU_CHECK_CALL(glGetUniformuiv(programGL, location, &value.val.uintV[0])); 1754 for (int i = 0; i < size; i++) 1755 value.val.boolV[i] = value.val.uintV[i] != 0; 1756 } 1757 else // Default: use float. 1758 { 1759 GLU_CHECK_CALL(glGetUniformfv(programGL, location, &value.val.floatV[0])); 1760 for (int i = 0; i < size; i++) 1761 value.val.boolV[i] = value.val.floatV[i] != 0.0f; 1762 } 1763 } 1764 else if (glu::isDataTypeSampler(uniform.type)) 1765 { 1766 GLint unit = -1; 1767 GLU_CHECK_CALL(glGetUniformiv(programGL, location, &unit)); 1768 value.val.samplerV.unit = unit; 1769 } 1770 else 1771 DE_ASSERT(false); 1772 1773 valuesDst.push_back(value); 1774 1775 log << TestLog::Message << "// Got " << uniform.name << " value " << apiVarValueStr(value) << TestLog::EndMessage; 1776 } 1777 1778 return success; 1779 } 1780 1781 bool UniformCase::checkUniformDefaultValues (const vector<VarValue>& values, const vector<BasicUniform>& basicUniforms) 1782 { 1783 TestLog& log = m_testCtx.getLog(); 1784 bool success = true; 1785 1786 DE_ASSERT(values.size() == basicUniforms.size()); 1787 1788 for (int unifNdx = 0; unifNdx < (int)basicUniforms.size(); unifNdx++) 1789 { 1790 const BasicUniform& uniform = basicUniforms[unifNdx]; 1791 const VarValue& unifValue = values[unifNdx]; 1792 const int valSize = glu::getDataTypeScalarSize(uniform.type); 1793 1794 log << TestLog::Message << "// Checking uniform " << uniform.name << TestLog::EndMessage; 1795 1796 if (unifValue.type == glu::TYPE_INVALID) // This happens when glGetUniformLocation() returned -1. 1797 continue; 1798 1799 #define CHECK_UNIFORM(VAR_VALUE_MEMBER, ZERO) \ 1800 do \ 1801 { \ 1802 for (int i = 0; i < valSize; i++) \ 1803 { \ 1804 if (unifValue.val.VAR_VALUE_MEMBER[i] != (ZERO)) \ 1805 { \ 1806 log << TestLog::Message << "// FAILURE: uniform " << uniform.name << " has non-zero initial value" << TestLog::EndMessage; \ 1807 success = false; \ 1808 } \ 1809 } \ 1810 } while (false) 1811 1812 if (glu::isDataTypeFloatOrVec(uniform.type) || glu::isDataTypeMatrix(uniform.type)) 1813 CHECK_UNIFORM(floatV, 0.0f); 1814 else if (glu::isDataTypeIntOrIVec(uniform.type)) 1815 CHECK_UNIFORM(intV, 0); 1816 else if (glu::isDataTypeUintOrUVec(uniform.type)) 1817 CHECK_UNIFORM(uintV, 0); 1818 else if (glu::isDataTypeBoolOrBVec(uniform.type)) 1819 CHECK_UNIFORM(boolV, false); 1820 else if (glu::isDataTypeSampler(uniform.type)) 1821 { 1822 if (unifValue.val.samplerV.unit != 0) 1823 { 1824 log << TestLog::Message << "// FAILURE: uniform " << uniform.name << " has non-zero initial value" << TestLog::EndMessage; 1825 success = false; 1826 } 1827 } 1828 else 1829 DE_ASSERT(false); 1830 1831 #undef CHECK_UNIFORM 1832 } 1833 1834 return success; 1835 } 1836 1837 void UniformCase::assignUniforms (const vector<BasicUniform>& basicUniforms, deUint32 programGL, Random& rnd) 1838 { 1839 TestLog& log = m_testCtx.getLog(); 1840 const bool transpose = (m_features & FEATURE_MATRIXMODE_ROWMAJOR) != 0; 1841 const GLboolean transposeGL = transpose ? GL_TRUE : GL_FALSE; 1842 const glu::DataType boolApiType = m_features & FEATURE_BOOLEANAPITYPE_INT ? glu::TYPE_INT 1843 : m_features & FEATURE_BOOLEANAPITYPE_UINT ? glu::TYPE_UINT 1844 : glu::TYPE_FLOAT; 1845 1846 for (int unifNdx = 0; unifNdx < (int)basicUniforms.size(); unifNdx++) 1847 { 1848 const BasicUniform& uniform = basicUniforms[unifNdx]; 1849 const bool isArrayMember = uniform.elemNdx >= 0; 1850 const string queryName = m_features & FEATURE_ARRAY_FIRST_ELEM_NAME_NO_INDEX && uniform.elemNdx == 0 ? beforeLast(uniform.name, '[') : uniform.name; 1851 const int numValuesToAssign = !isArrayMember ? 1 1852 : m_features & FEATURE_ARRAYASSIGN_FULL ? (uniform.elemNdx == 0 ? uniform.rootSize : 0) 1853 : m_features & FEATURE_ARRAYASSIGN_BLOCKS_OF_TWO ? (uniform.elemNdx % 2 == 0 ? 2 : 0) 1854 : /* Default: assign array elements separately */ 1; 1855 1856 DE_ASSERT(numValuesToAssign >= 0); 1857 DE_ASSERT(numValuesToAssign == 1 || isArrayMember); 1858 1859 if (numValuesToAssign == 0) 1860 { 1861 log << TestLog::Message << "// Uniform " << uniform.name << " is covered by another glUniform*v() call to the same array" << TestLog::EndMessage; 1862 continue; 1863 } 1864 1865 const int location = glGetUniformLocation(programGL, queryName.c_str()); 1866 const int typeSize = glu::getDataTypeScalarSize(uniform.type); 1867 const bool assignByValue = m_features & FEATURE_UNIFORMFUNC_VALUE && !glu::isDataTypeMatrix(uniform.type) && numValuesToAssign == 1; 1868 vector<VarValue> valuesToAssign; 1869 1870 for (int i = 0; i < numValuesToAssign; i++) 1871 { 1872 const string curName = isArrayMember ? beforeLast(uniform.rootName, '[') + "[" + de::toString(uniform.elemNdx+i) + "]" : uniform.name; 1873 VarValue unifValue; 1874 1875 if (isArrayMember) 1876 { 1877 const vector<BasicUniform>::const_iterator elemUnif = BasicUniform::findWithName(basicUniforms, curName.c_str()); 1878 if (elemUnif == basicUniforms.end()) 1879 continue; 1880 unifValue = elemUnif->finalValue; 1881 } 1882 else 1883 unifValue = uniform.finalValue; 1884 1885 const VarValue apiValue = glu::isDataTypeBoolOrBVec(unifValue.type) ? getRandomBoolRepresentation(unifValue, boolApiType, rnd) 1886 : glu::isDataTypeSampler(unifValue.type) ? getSamplerUnitValue(unifValue) 1887 : unifValue; 1888 1889 valuesToAssign.push_back(glu::isDataTypeMatrix(apiValue.type) && transpose ? getTransposeMatrix(apiValue) : apiValue); 1890 1891 if (glu::isDataTypeBoolOrBVec(uniform.type)) 1892 log << TestLog::Message << "// Using type " << glu::getDataTypeName(boolApiType) << " to set boolean value " << apiVarValueStr(unifValue) << " for " << curName << TestLog::EndMessage; 1893 else if (glu::isDataTypeSampler(uniform.type)) 1894 log << TestLog::Message << "// Texture for the sampler uniform " << curName << " will be filled with color " << apiVarValueStr(getSamplerFillValue(uniform.finalValue)) << TestLog::EndMessage; 1895 } 1896 1897 DE_ASSERT(!valuesToAssign.empty()); 1898 1899 if (glu::isDataTypeFloatOrVec(valuesToAssign[0].type)) 1900 { 1901 if (assignByValue) 1902 { 1903 const float* const ptr = &valuesToAssign[0].val.floatV[0]; 1904 1905 switch (typeSize) 1906 { 1907 case 1: GLU_CHECK_CALL(glUniform1f(location, ptr[0])); break; 1908 case 2: GLU_CHECK_CALL(glUniform2f(location, ptr[0], ptr[1])); break; 1909 case 3: GLU_CHECK_CALL(glUniform3f(location, ptr[0], ptr[1], ptr[2])); break; 1910 case 4: GLU_CHECK_CALL(glUniform4f(location, ptr[0], ptr[1], ptr[2], ptr[3])); break; 1911 default: 1912 DE_ASSERT(false); 1913 } 1914 } 1915 else 1916 { 1917 vector<float> buffer(valuesToAssign.size() * typeSize); 1918 for (int i = 0; i < (int)buffer.size(); i++) 1919 buffer[i] = valuesToAssign[i / typeSize].val.floatV[i % typeSize]; 1920 1921 DE_STATIC_ASSERT(sizeof(GLfloat) == sizeof(buffer[0])); 1922 switch (typeSize) 1923 { 1924 case 1: GLU_CHECK_CALL(glUniform1fv(location, (GLsizei)valuesToAssign.size(), &buffer[0])); break; 1925 case 2: GLU_CHECK_CALL(glUniform2fv(location, (GLsizei)valuesToAssign.size(), &buffer[0])); break; 1926 case 3: GLU_CHECK_CALL(glUniform3fv(location, (GLsizei)valuesToAssign.size(), &buffer[0])); break; 1927 case 4: GLU_CHECK_CALL(glUniform4fv(location, (GLsizei)valuesToAssign.size(), &buffer[0])); break; 1928 default: 1929 DE_ASSERT(false); 1930 } 1931 } 1932 } 1933 else if (glu::isDataTypeMatrix(valuesToAssign[0].type)) 1934 { 1935 DE_ASSERT(!assignByValue); 1936 1937 vector<float> buffer(valuesToAssign.size() * typeSize); 1938 for (int i = 0; i < (int)buffer.size(); i++) 1939 buffer[i] = valuesToAssign[i / typeSize].val.floatV[i % typeSize]; 1940 1941 DE_STATIC_ASSERT(sizeof(GLfloat) == sizeof(buffer[0])); 1942 switch (uniform.type) 1943 { 1944 case glu::TYPE_FLOAT_MAT2: GLU_CHECK_CALL(glUniformMatrix2fv (location, (GLsizei)valuesToAssign.size(), transposeGL, &buffer[0])); break; 1945 case glu::TYPE_FLOAT_MAT3: GLU_CHECK_CALL(glUniformMatrix3fv (location, (GLsizei)valuesToAssign.size(), transposeGL, &buffer[0])); break; 1946 case glu::TYPE_FLOAT_MAT4: GLU_CHECK_CALL(glUniformMatrix4fv (location, (GLsizei)valuesToAssign.size(), transposeGL, &buffer[0])); break; 1947 case glu::TYPE_FLOAT_MAT2X3: GLU_CHECK_CALL(glUniformMatrix2x3fv (location, (GLsizei)valuesToAssign.size(), transposeGL, &buffer[0])); break; 1948 case glu::TYPE_FLOAT_MAT2X4: GLU_CHECK_CALL(glUniformMatrix2x4fv (location, (GLsizei)valuesToAssign.size(), transposeGL, &buffer[0])); break; 1949 case glu::TYPE_FLOAT_MAT3X2: GLU_CHECK_CALL(glUniformMatrix3x2fv (location, (GLsizei)valuesToAssign.size(), transposeGL, &buffer[0])); break; 1950 case glu::TYPE_FLOAT_MAT3X4: GLU_CHECK_CALL(glUniformMatrix3x4fv (location, (GLsizei)valuesToAssign.size(), transposeGL, &buffer[0])); break; 1951 case glu::TYPE_FLOAT_MAT4X2: GLU_CHECK_CALL(glUniformMatrix4x2fv (location, (GLsizei)valuesToAssign.size(), transposeGL, &buffer[0])); break; 1952 case glu::TYPE_FLOAT_MAT4X3: GLU_CHECK_CALL(glUniformMatrix4x3fv (location, (GLsizei)valuesToAssign.size(), transposeGL, &buffer[0])); break; 1953 default: 1954 DE_ASSERT(false); 1955 } 1956 } 1957 else if (glu::isDataTypeIntOrIVec(valuesToAssign[0].type)) 1958 { 1959 if (assignByValue) 1960 { 1961 const deInt32* const ptr = &valuesToAssign[0].val.intV[0]; 1962 1963 switch (typeSize) 1964 { 1965 case 1: GLU_CHECK_CALL(glUniform1i(location, ptr[0])); break; 1966 case 2: GLU_CHECK_CALL(glUniform2i(location, ptr[0], ptr[1])); break; 1967 case 3: GLU_CHECK_CALL(glUniform3i(location, ptr[0], ptr[1], ptr[2])); break; 1968 case 4: GLU_CHECK_CALL(glUniform4i(location, ptr[0], ptr[1], ptr[2], ptr[3])); break; 1969 default: 1970 DE_ASSERT(false); 1971 } 1972 } 1973 else 1974 { 1975 vector<deInt32> buffer(valuesToAssign.size() * typeSize); 1976 for (int i = 0; i < (int)buffer.size(); i++) 1977 buffer[i] = valuesToAssign[i / typeSize].val.intV[i % typeSize]; 1978 1979 DE_STATIC_ASSERT(sizeof(GLint) == sizeof(buffer[0])); 1980 switch (typeSize) 1981 { 1982 case 1: GLU_CHECK_CALL(glUniform1iv(location, (GLsizei)valuesToAssign.size(), &buffer[0])); break; 1983 case 2: GLU_CHECK_CALL(glUniform2iv(location, (GLsizei)valuesToAssign.size(), &buffer[0])); break; 1984 case 3: GLU_CHECK_CALL(glUniform3iv(location, (GLsizei)valuesToAssign.size(), &buffer[0])); break; 1985 case 4: GLU_CHECK_CALL(glUniform4iv(location, (GLsizei)valuesToAssign.size(), &buffer[0])); break; 1986 default: 1987 DE_ASSERT(false); 1988 } 1989 } 1990 } 1991 else if (glu::isDataTypeUintOrUVec(valuesToAssign[0].type)) 1992 { 1993 if (assignByValue) 1994 { 1995 const deUint32* const ptr = &valuesToAssign[0].val.uintV[0]; 1996 1997 switch (typeSize) 1998 { 1999 case 1: GLU_CHECK_CALL(glUniform1ui(location, ptr[0])); break; 2000 case 2: GLU_CHECK_CALL(glUniform2ui(location, ptr[0], ptr[1])); break; 2001 case 3: GLU_CHECK_CALL(glUniform3ui(location, ptr[0], ptr[1], ptr[2])); break; 2002 case 4: GLU_CHECK_CALL(glUniform4ui(location, ptr[0], ptr[1], ptr[2], ptr[3])); break; 2003 default: 2004 DE_ASSERT(false); 2005 } 2006 } 2007 else 2008 { 2009 vector<deUint32> buffer(valuesToAssign.size() * typeSize); 2010 for (int i = 0; i < (int)buffer.size(); i++) 2011 buffer[i] = valuesToAssign[i / typeSize].val.intV[i % typeSize]; 2012 2013 DE_STATIC_ASSERT(sizeof(GLuint) == sizeof(buffer[0])); 2014 switch (typeSize) 2015 { 2016 case 1: GLU_CHECK_CALL(glUniform1uiv(location, (GLsizei)valuesToAssign.size(), &buffer[0])); break; 2017 case 2: GLU_CHECK_CALL(glUniform2uiv(location, (GLsizei)valuesToAssign.size(), &buffer[0])); break; 2018 case 3: GLU_CHECK_CALL(glUniform3uiv(location, (GLsizei)valuesToAssign.size(), &buffer[0])); break; 2019 case 4: GLU_CHECK_CALL(glUniform4uiv(location, (GLsizei)valuesToAssign.size(), &buffer[0])); break; 2020 default: 2021 DE_ASSERT(false); 2022 } 2023 } 2024 } 2025 else if (glu::isDataTypeSampler(valuesToAssign[0].type)) 2026 { 2027 if (assignByValue) 2028 GLU_CHECK_CALL(glUniform1i(location, uniform.finalValue.val.samplerV.unit)); 2029 else 2030 { 2031 const GLint unit = uniform.finalValue.val.samplerV.unit; 2032 GLU_CHECK_CALL(glUniform1iv(location, (GLsizei)valuesToAssign.size(), &unit)); 2033 } 2034 } 2035 else 2036 DE_ASSERT(false); 2037 } 2038 } 2039 2040 bool UniformCase::compareUniformValues (const vector<VarValue>& values, const vector<BasicUniform>& basicUniforms) 2041 { 2042 TestLog& log = m_testCtx.getLog(); 2043 bool success = true; 2044 2045 for (int unifNdx = 0; unifNdx < (int)basicUniforms.size(); unifNdx++) 2046 { 2047 const BasicUniform& uniform = basicUniforms[unifNdx]; 2048 const VarValue& unifValue = values[unifNdx]; 2049 2050 log << TestLog::Message << "// Checking uniform " << uniform.name << TestLog::EndMessage; 2051 2052 if (unifValue.type == glu::TYPE_INVALID) // This happens when glGetUniformLocation() returned -1. 2053 continue; 2054 2055 if (!apiVarValueEquals(unifValue, uniform.finalValue)) 2056 { 2057 log << TestLog::Message << "// FAILURE: value obtained with glGetUniform*() for uniform " << uniform.name << " differs from value set with glUniform*()" << TestLog::EndMessage; 2058 success = false; 2059 } 2060 } 2061 2062 return success; 2063 } 2064 2065 bool UniformCase::renderTest (const vector<BasicUniform>& basicUniforms, const ShaderProgram& program, Random& rnd) 2066 { 2067 TestLog& log = m_testCtx.getLog(); 2068 const tcu::RenderTarget& renderTarget = m_context.getRenderTarget(); 2069 const int viewportW = de::min(renderTarget.getWidth(), MAX_RENDER_WIDTH); 2070 const int viewportH = de::min(renderTarget.getHeight(), MAX_RENDER_HEIGHT); 2071 const int viewportX = rnd.getInt(0, renderTarget.getWidth() - viewportW); 2072 const int viewportY = rnd.getInt(0, renderTarget.getHeight() - viewportH); 2073 tcu::Surface renderedImg (viewportW, viewportH); 2074 2075 // Assert that no two samplers of different types have the same texture unit - this is an error in GL. 2076 for (int i = 0; i < (int)basicUniforms.size(); i++) 2077 { 2078 if (glu::isDataTypeSampler(basicUniforms[i].type)) 2079 { 2080 for (int j = 0; j < i; j++) 2081 { 2082 if (glu::isDataTypeSampler(basicUniforms[j].type) && basicUniforms[i].type != basicUniforms[j].type) 2083 DE_ASSERT(basicUniforms[i].finalValue.val.samplerV.unit != basicUniforms[j].finalValue.val.samplerV.unit); 2084 } 2085 } 2086 } 2087 2088 for (int i = 0; i < (int)basicUniforms.size(); i++) 2089 { 2090 if (glu::isDataTypeSampler(basicUniforms[i].type) && std::find(m_filledTextureUnits.begin(), m_filledTextureUnits.end(), basicUniforms[i].finalValue.val.samplerV.unit) == m_filledTextureUnits.end()) 2091 { 2092 log << TestLog::Message << "// Filling texture at unit " << apiVarValueStr(basicUniforms[i].finalValue) << " with color " << shaderVarValueStr(basicUniforms[i].finalValue) << TestLog::EndMessage; 2093 setupTexture(basicUniforms[i].finalValue); 2094 } 2095 } 2096 2097 GLU_CHECK_CALL(glViewport(viewportX, viewportY, viewportW, viewportH)); 2098 2099 { 2100 static const float position[] = 2101 { 2102 -1.0f, -1.0f, 0.0f, 1.0f, 2103 -1.0f, +1.0f, 0.0f, 1.0f, 2104 +1.0f, -1.0f, 0.0f, 1.0f, 2105 +1.0f, +1.0f, 0.0f, 1.0f 2106 }; 2107 static const deUint16 indices[] = { 0, 1, 2, 2, 1, 3 }; 2108 2109 const int posLoc = glGetAttribLocation(program.getProgram(), "a_position"); 2110 glEnableVertexAttribArray(posLoc); 2111 glVertexAttribPointer(posLoc, 4, GL_FLOAT, GL_FALSE, 0, &position[0]); 2112 GLU_CHECK_CALL(glDrawElements(GL_TRIANGLES, DE_LENGTH_OF_ARRAY(indices), GL_UNSIGNED_SHORT, &indices[0])); 2113 } 2114 2115 glu::readPixels(m_context.getRenderContext(), viewportX, viewportY, renderedImg.getAccess()); 2116 2117 int numFailedPixels = 0; 2118 for (int y = 0; y < renderedImg.getHeight(); y++) 2119 { 2120 for (int x = 0; x < renderedImg.getWidth(); x++) 2121 { 2122 if (renderedImg.getPixel(x, y) != tcu::RGBA::white()) 2123 numFailedPixels += 1; 2124 } 2125 } 2126 2127 if (numFailedPixels > 0) 2128 { 2129 log << TestLog::Image("RenderedImage", "Rendered image", renderedImg); 2130 log << TestLog::Message << "FAILURE: image comparison failed, got " << numFailedPixels << " non-white pixels" << TestLog::EndMessage; 2131 return false; 2132 } 2133 else 2134 { 2135 log << TestLog::Message << "Success: got all-white pixels (all uniforms have correct values)" << TestLog::EndMessage; 2136 return true; 2137 } 2138 } 2139 2140 UniformCase::IterateResult UniformCase::iterate (void) 2141 { 2142 Random rnd (deStringHash(getName()) ^ (deUint32)m_context.getTestContext().getCommandLine().getBaseSeed()); 2143 TestLog& log = m_testCtx.getLog(); 2144 vector<BasicUniform> basicUniforms; 2145 vector<BasicUniformReportRef> basicUniformReportsRef; 2146 2147 { 2148 int samplerUnitCounter = 0; 2149 for (int i = 0; i < (int)m_uniformCollection->getNumUniforms(); i++) 2150 generateBasicUniforms(basicUniforms, basicUniformReportsRef, m_uniformCollection->getUniform(i).type, m_uniformCollection->getUniform(i).name.c_str(), true, samplerUnitCounter, rnd); 2151 } 2152 2153 const string vertexSource = generateVertexSource(basicUniforms); 2154 const string fragmentSource = generateFragmentSource(basicUniforms); 2155 const ShaderProgram program (m_context.getRenderContext(), glu::makeVtxFragSources(vertexSource, fragmentSource)); 2156 2157 log << program; 2158 2159 if (!program.isOk()) 2160 { 2161 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Compile failed"); 2162 return STOP; 2163 } 2164 2165 GLU_CHECK_CALL(glUseProgram(program.getProgram())); 2166 2167 const bool success = test(basicUniforms, basicUniformReportsRef, program, rnd); 2168 m_testCtx.setTestResult(success ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, 2169 success ? "Passed" : "Failed"); 2170 2171 return STOP; 2172 } 2173 2174 class UniformInfoQueryCase : public UniformCase 2175 { 2176 public: 2177 enum CaseType 2178 { 2179 CASETYPE_UNIFORM = 0, //!< Check info returned by glGetActiveUniform(). 2180 CASETYPE_INDICES_UNIFORMSIV, //!< Check info returned by glGetUniformIndices() + glGetActiveUniformsiv(). 2181 CASETYPE_CONSISTENCY, //!< Query info with both above methods, and check consistency. 2182 2183 CASETYPE_LAST 2184 }; 2185 2186 UniformInfoQueryCase (Context& context, const char* name, const char* description, CaseShaderType shaderType, const SharedPtr<const UniformCollection>& uniformCollection, CaseType caseType, deUint32 additionalFeatures = 0); 2187 bool test (const vector<BasicUniform>& basicUniforms, const vector<BasicUniformReportRef>& basicUniformReportsRef, const ShaderProgram& program, Random& rnd); 2188 2189 static const char* getCaseTypeName (CaseType caseType); 2190 static const char* getCaseTypeDescription (CaseType caseType); 2191 2192 private: 2193 const CaseType m_caseType; 2194 }; 2195 2196 const char* UniformInfoQueryCase::getCaseTypeName (const CaseType caseType) 2197 { 2198 switch (caseType) 2199 { 2200 case CASETYPE_UNIFORM: return "active_uniform"; 2201 case CASETYPE_INDICES_UNIFORMSIV: return "indices_active_uniformsiv"; 2202 case CASETYPE_CONSISTENCY: return "consistency"; 2203 default: 2204 DE_ASSERT(false); 2205 return DE_NULL; 2206 } 2207 } 2208 2209 const char* UniformInfoQueryCase::getCaseTypeDescription (const CaseType caseType) 2210 { 2211 switch (caseType) 2212 { 2213 case CASETYPE_UNIFORM: return "Test glGetActiveUniform()"; 2214 case CASETYPE_INDICES_UNIFORMSIV: return "Test glGetUniformIndices() along with glGetActiveUniformsiv()"; 2215 case CASETYPE_CONSISTENCY: return "Check consistency between results from glGetActiveUniform() and glGetUniformIndices() + glGetActiveUniformsiv()"; 2216 default: 2217 DE_ASSERT(false); 2218 return DE_NULL; 2219 } 2220 } 2221 2222 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) 2223 : UniformCase (context, name, description, shaderType, uniformCollection, additionalFeatures) 2224 , m_caseType (caseType) 2225 { 2226 } 2227 2228 bool UniformInfoQueryCase::test (const vector<BasicUniform>& basicUniforms, const vector<BasicUniformReportRef>& basicUniformReportsRef, const ShaderProgram& program, Random& rnd) 2229 { 2230 DE_UNREF(basicUniforms); 2231 DE_UNREF(rnd); 2232 2233 const deUint32 programGL = program.getProgram(); 2234 TestLog& log = m_testCtx.getLog(); 2235 vector<BasicUniformReportGL> basicUniformReportsUniform; 2236 vector<BasicUniformReportGL> basicUniformReportsUniformsiv; 2237 2238 if (m_caseType == CASETYPE_UNIFORM || m_caseType == CASETYPE_CONSISTENCY) 2239 { 2240 bool success = false; 2241 2242 { 2243 const ScopedLogSection section(log, "InfoGetActiveUniform", "Uniform information queries with glGetActiveUniform()"); 2244 success = getActiveUniforms(basicUniformReportsUniform, basicUniformReportsRef, programGL); 2245 } 2246 2247 if (!success) 2248 { 2249 if (m_caseType == CASETYPE_UNIFORM) 2250 return false; 2251 else 2252 { 2253 DE_ASSERT(m_caseType == CASETYPE_CONSISTENCY); 2254 log << TestLog::Message << "// Note: this is a consistency case, so ignoring above failure(s)" << TestLog::EndMessage; 2255 } 2256 } 2257 } 2258 2259 if (m_caseType == CASETYPE_INDICES_UNIFORMSIV || m_caseType == CASETYPE_CONSISTENCY) 2260 { 2261 bool success = false; 2262 2263 { 2264 const ScopedLogSection section(log, "InfoGetActiveUniformsiv", "Uniform information queries with glGetUniformIndices() and glGetActiveUniformsiv()"); 2265 success = getActiveUniformsiv(basicUniformReportsUniformsiv, basicUniformReportsRef, programGL); 2266 } 2267 2268 if (!success) 2269 { 2270 if (m_caseType == CASETYPE_INDICES_UNIFORMSIV) 2271 return false; 2272 else 2273 { 2274 DE_ASSERT(m_caseType == CASETYPE_CONSISTENCY); 2275 log << TestLog::Message << "// Note: this is a consistency case, so ignoring above failure(s)" << TestLog::EndMessage; 2276 } 2277 } 2278 } 2279 2280 if (m_caseType == CASETYPE_CONSISTENCY) 2281 { 2282 bool success = false; 2283 2284 { 2285 const ScopedLogSection section(log, "CompareUniformVsUniformsiv", "Comparison of results from glGetActiveUniform() and glGetActiveUniformsiv()"); 2286 success = uniformVsUniformsivComparison(basicUniformReportsUniform, basicUniformReportsUniformsiv); 2287 } 2288 2289 if (!success) 2290 return false; 2291 } 2292 2293 return true; 2294 } 2295 2296 class UniformValueCase : public UniformCase 2297 { 2298 public: 2299 enum ValueToCheck 2300 { 2301 VALUETOCHECK_INITIAL = 0, //!< Verify the initial values of the uniforms (i.e. check that they're zero). 2302 VALUETOCHECK_ASSIGNED, //!< Assign values to uniforms with glUniform*(), and check those. 2303 2304 VALUETOCHECK_LAST 2305 }; 2306 enum CheckMethod 2307 { 2308 CHECKMETHOD_GET_UNIFORM = 0, //!< Check values with glGetUniform*(). 2309 CHECKMETHOD_RENDER, //!< Check values by rendering with the value-checking shader. 2310 2311 CHECKMETHOD_LAST 2312 }; 2313 enum AssignMethod 2314 { 2315 ASSIGNMETHOD_POINTER = 0, 2316 ASSIGNMETHOD_VALUE, 2317 2318 ASSIGNMETHOD_LAST 2319 }; 2320 2321 UniformValueCase (Context& context, 2322 const char* name, 2323 const char* description, 2324 CaseShaderType shaderType, 2325 const SharedPtr<const UniformCollection>& uniformCollection, 2326 ValueToCheck valueToCheck, 2327 CheckMethod checkMethod, 2328 AssignMethod assignMethod, 2329 deUint32 additionalFeatures = 0); 2330 2331 bool test (const vector<BasicUniform>& basicUniforms, const vector<BasicUniformReportRef>& basicUniformReportsRef, const ShaderProgram& program, Random& rnd); 2332 2333 static const char* getValueToCheckName (ValueToCheck valueToCheck); 2334 static const char* getValueToCheckDescription (ValueToCheck valueToCheck); 2335 static const char* getCheckMethodName (CheckMethod checkMethod); 2336 static const char* getCheckMethodDescription (CheckMethod checkMethod); 2337 static const char* getAssignMethodName (AssignMethod checkMethod); 2338 static const char* getAssignMethodDescription (AssignMethod checkMethod); 2339 2340 private: 2341 const ValueToCheck m_valueToCheck; 2342 const CheckMethod m_checkMethod; 2343 }; 2344 2345 const char* UniformValueCase::getValueToCheckName (const ValueToCheck valueToCheck) 2346 { 2347 switch (valueToCheck) 2348 { 2349 case VALUETOCHECK_INITIAL: return "initial"; 2350 case VALUETOCHECK_ASSIGNED: return "assigned"; 2351 default: DE_ASSERT(false); return DE_NULL; 2352 } 2353 } 2354 2355 const char* UniformValueCase::getValueToCheckDescription (const ValueToCheck valueToCheck) 2356 { 2357 switch (valueToCheck) 2358 { 2359 case VALUETOCHECK_INITIAL: return "Check initial uniform values (zeros)"; 2360 case VALUETOCHECK_ASSIGNED: return "Check assigned uniform values"; 2361 default: DE_ASSERT(false); return DE_NULL; 2362 } 2363 } 2364 2365 const char* UniformValueCase::getCheckMethodName (const CheckMethod checkMethod) 2366 { 2367 switch (checkMethod) 2368 { 2369 case CHECKMETHOD_GET_UNIFORM: return "get_uniform"; 2370 case CHECKMETHOD_RENDER: return "render"; 2371 default: DE_ASSERT(false); return DE_NULL; 2372 } 2373 } 2374 2375 const char* UniformValueCase::getCheckMethodDescription (const CheckMethod checkMethod) 2376 { 2377 switch (checkMethod) 2378 { 2379 case CHECKMETHOD_GET_UNIFORM: return "Verify values with glGetUniform*()"; 2380 case CHECKMETHOD_RENDER: return "Verify values by rendering"; 2381 default: DE_ASSERT(false); return DE_NULL; 2382 } 2383 } 2384 2385 const char* UniformValueCase::getAssignMethodName (const AssignMethod assignMethod) 2386 { 2387 switch (assignMethod) 2388 { 2389 case ASSIGNMETHOD_POINTER: return "by_pointer"; 2390 case ASSIGNMETHOD_VALUE: return "by_value"; 2391 default: DE_ASSERT(false); return DE_NULL; 2392 } 2393 } 2394 2395 const char* UniformValueCase::getAssignMethodDescription (const AssignMethod assignMethod) 2396 { 2397 switch (assignMethod) 2398 { 2399 case ASSIGNMETHOD_POINTER: return "Assign values by-pointer"; 2400 case ASSIGNMETHOD_VALUE: return "Assign values by-value"; 2401 default: DE_ASSERT(false); return DE_NULL; 2402 } 2403 } 2404 2405 UniformValueCase::UniformValueCase (Context& context, 2406 const char* const name, 2407 const char* const description, 2408 const CaseShaderType shaderType, 2409 const SharedPtr<const UniformCollection>& uniformCollection, 2410 const ValueToCheck valueToCheck, 2411 const CheckMethod checkMethod, 2412 const AssignMethod assignMethod, 2413 const deUint32 additionalFeatures) 2414 : UniformCase (context, name, description, shaderType, uniformCollection, 2415 (valueToCheck == VALUETOCHECK_INITIAL ? FEATURE_UNIFORMVALUE_ZERO : 0) | (assignMethod == ASSIGNMETHOD_VALUE ? FEATURE_UNIFORMFUNC_VALUE : 0) | additionalFeatures) 2416 , m_valueToCheck (valueToCheck) 2417 , m_checkMethod (checkMethod) 2418 { 2419 DE_ASSERT(!(assignMethod == ASSIGNMETHOD_LAST && valueToCheck == VALUETOCHECK_ASSIGNED)); 2420 } 2421 2422 bool UniformValueCase::test (const vector<BasicUniform>& basicUniforms, const vector<BasicUniformReportRef>& basicUniformReportsRef, const ShaderProgram& program, Random& rnd) 2423 { 2424 DE_UNREF(basicUniformReportsRef); 2425 2426 const deUint32 programGL = program.getProgram(); 2427 TestLog& log = m_testCtx.getLog(); 2428 2429 if (m_valueToCheck == VALUETOCHECK_ASSIGNED) 2430 { 2431 const ScopedLogSection section(log, "UniformAssign", "Uniform value assignments"); 2432 assignUniforms(basicUniforms, programGL, rnd); 2433 } 2434 else 2435 DE_ASSERT(m_valueToCheck == VALUETOCHECK_INITIAL); 2436 2437 if (m_checkMethod == CHECKMETHOD_GET_UNIFORM) 2438 { 2439 vector<VarValue> values; 2440 2441 { 2442 const ScopedLogSection section(log, "GetUniforms", "Uniform value query"); 2443 const bool success = getUniforms(values, basicUniforms, program.getProgram()); 2444 2445 if (!success) 2446 return false; 2447 } 2448 2449 if (m_valueToCheck == VALUETOCHECK_ASSIGNED) 2450 { 2451 const ScopedLogSection section(log, "ValueCheck", "Verify that the reported values match the assigned values"); 2452 const bool success = compareUniformValues(values, basicUniforms); 2453 2454 if (!success) 2455 return false; 2456 } 2457 else 2458 { 2459 DE_ASSERT(m_valueToCheck == VALUETOCHECK_INITIAL); 2460 2461 const ScopedLogSection section(log, "ValueCheck", "Verify that the uniforms have correct initial values (zeros)"); 2462 const bool success = checkUniformDefaultValues(values, basicUniforms); 2463 2464 if (!success) 2465 return false; 2466 } 2467 } 2468 else 2469 { 2470 DE_ASSERT(m_checkMethod == CHECKMETHOD_RENDER); 2471 2472 const ScopedLogSection section(log, "RenderTest", "Render test"); 2473 const bool success = renderTest(basicUniforms, program, rnd); 2474 2475 if (!success) 2476 return false; 2477 } 2478 2479 return true; 2480 } 2481 2482 class RandomUniformCase : public UniformCase 2483 { 2484 public: 2485 RandomUniformCase (Context& m_context, const char* name, const char* description, deUint32 seed); 2486 2487 bool test (const vector<BasicUniform>& basicUniforms, const vector<BasicUniformReportRef>& basicUniformReportsRef, const ShaderProgram& program, Random& rnd); 2488 }; 2489 2490 RandomUniformCase::RandomUniformCase (Context& context, const char* const name, const char* const description, const deUint32 seed) 2491 : UniformCase (context, name, description, seed ^ (deUint32)context.getTestContext().getCommandLine().getBaseSeed()) 2492 { 2493 } 2494 2495 bool RandomUniformCase::test (const vector<BasicUniform>& basicUniforms, const vector<BasicUniformReportRef>& basicUniformReportsRef, const ShaderProgram& program, Random& rnd) 2496 { 2497 // \note Different sampler types may not be bound to same unit when rendering. 2498 const bool renderingPossible = (m_features & FEATURE_UNIFORMVALUE_ZERO) == 0 || !m_uniformCollection->containsSeveralSamplerTypes(); 2499 2500 bool performGetActiveUniforms = rnd.getBool(); 2501 const bool performGetActiveUniformsiv = rnd.getBool(); 2502 const bool performUniformVsUniformsivComparison = performGetActiveUniforms && performGetActiveUniformsiv && rnd.getBool(); 2503 const bool performGetUniforms = rnd.getBool(); 2504 const bool performCheckUniformDefaultValues = performGetUniforms && rnd.getBool(); 2505 const bool performAssignUniforms = rnd.getBool(); 2506 const bool performCompareUniformValues = performGetUniforms && performAssignUniforms && rnd.getBool(); 2507 const bool performRenderTest = renderingPossible && performAssignUniforms && rnd.getBool(); 2508 const deUint32 programGL = program.getProgram(); 2509 TestLog& log = m_testCtx.getLog(); 2510 2511 if (!(performGetActiveUniforms || performGetActiveUniformsiv || performUniformVsUniformsivComparison || performGetUniforms || performCheckUniformDefaultValues || performAssignUniforms || performCompareUniformValues || performRenderTest)) 2512 performGetActiveUniforms = true; // Do something at least. 2513 2514 #define PERFORM_AND_CHECK(CALL, SECTION_NAME, SECTION_DESCRIPTION) \ 2515 do \ 2516 { \ 2517 const ScopedLogSection section(log, (SECTION_NAME), (SECTION_DESCRIPTION)); \ 2518 const bool success = (CALL); \ 2519 if (!success) \ 2520 return false; \ 2521 } while (false) 2522 2523 { 2524 vector<BasicUniformReportGL> reportsUniform; 2525 vector<BasicUniformReportGL> reportsUniformsiv; 2526 2527 if (performGetActiveUniforms) 2528 PERFORM_AND_CHECK(getActiveUniforms(reportsUniform, basicUniformReportsRef, programGL), "InfoGetActiveUniform", "Uniform information queries with glGetActiveUniform()"); 2529 if (performGetActiveUniformsiv) 2530 PERFORM_AND_CHECK(getActiveUniformsiv(reportsUniformsiv, basicUniformReportsRef, programGL), "InfoGetActiveUniformsiv", "Uniform information queries with glGetIndices() and glGetActiveUniformsiv()"); 2531 if (performUniformVsUniformsivComparison) 2532 PERFORM_AND_CHECK(uniformVsUniformsivComparison(reportsUniform, reportsUniformsiv), "CompareUniformVsUniformsiv", "Comparison of results from glGetActiveUniform() and glGetActiveUniformsiv()"); 2533 } 2534 2535 { 2536 vector<VarValue> uniformDefaultValues; 2537 2538 if (performGetUniforms) 2539 PERFORM_AND_CHECK(getUniforms(uniformDefaultValues, basicUniforms, programGL), "GetUniformDefaults", "Uniform default value query"); 2540 if (performCheckUniformDefaultValues) 2541 PERFORM_AND_CHECK(checkUniformDefaultValues(uniformDefaultValues, basicUniforms), "DefaultValueCheck", "Verify that the uniforms have correct initial values (zeros)"); 2542 } 2543 2544 { 2545 vector<VarValue> uniformValues; 2546 2547 if (performAssignUniforms) 2548 { 2549 const ScopedLogSection section(log, "UniformAssign", "Uniform value assignments"); 2550 assignUniforms(basicUniforms, programGL, rnd); 2551 } 2552 if (performCompareUniformValues) 2553 { 2554 PERFORM_AND_CHECK(getUniforms(uniformValues, basicUniforms, programGL), "GetUniforms", "Uniform value query"); 2555 PERFORM_AND_CHECK(compareUniformValues(uniformValues, basicUniforms), "ValueCheck", "Verify that the reported values match the assigned values"); 2556 } 2557 } 2558 2559 if (performRenderTest) 2560 PERFORM_AND_CHECK(renderTest(basicUniforms, program, rnd), "RenderTest", "Render test"); 2561 2562 #undef PERFORM_AND_CHECK 2563 2564 return true; 2565 } 2566 2567 UniformApiTests::UniformApiTests (Context& context) 2568 : TestCaseGroup(context, "uniform_api", "Uniform API Tests") 2569 { 2570 } 2571 2572 UniformApiTests::~UniformApiTests (void) 2573 { 2574 } 2575 2576 namespace 2577 { 2578 2579 // \note Although this is only used in UniformApiTest::init, it needs to be defined here as it's used as a template argument. 2580 struct UniformCollectionCase 2581 { 2582 string namePrefix; 2583 SharedPtr<const UniformCollection> uniformCollection; 2584 2585 UniformCollectionCase (const char* const name, const UniformCollection* uniformCollection_) 2586 : namePrefix (name ? name + string("_") : "") 2587 , uniformCollection (uniformCollection_) 2588 { 2589 } 2590 }; 2591 2592 } // anonymous 2593 2594 void UniformApiTests::init (void) 2595 { 2596 // Generate sets of UniformCollections that are used by several cases. 2597 2598 enum 2599 { 2600 UNIFORMCOLLECTIONS_BASIC = 0, 2601 UNIFORMCOLLECTIONS_BASIC_ARRAY, 2602 UNIFORMCOLLECTIONS_BASIC_STRUCT, 2603 UNIFORMCOLLECTIONS_STRUCT_IN_ARRAY, 2604 UNIFORMCOLLECTIONS_ARRAY_IN_STRUCT, 2605 UNIFORMCOLLECTIONS_NESTED_STRUCTS_ARRAYS, 2606 UNIFORMCOLLECTIONS_MULTIPLE_BASIC, 2607 UNIFORMCOLLECTIONS_MULTIPLE_BASIC_ARRAY, 2608 UNIFORMCOLLECTIONS_MULTIPLE_NESTED_STRUCTS_ARRAYS, 2609 2610 UNIFORMCOLLECTIONS_LAST 2611 }; 2612 2613 struct UniformCollectionGroup 2614 { 2615 string name; 2616 vector<UniformCollectionCase> cases; 2617 } defaultUniformCollections[UNIFORMCOLLECTIONS_LAST]; 2618 2619 defaultUniformCollections[UNIFORMCOLLECTIONS_BASIC].name = "basic"; 2620 defaultUniformCollections[UNIFORMCOLLECTIONS_BASIC_ARRAY].name = "basic_array"; 2621 defaultUniformCollections[UNIFORMCOLLECTIONS_BASIC_STRUCT].name = "basic_struct"; 2622 defaultUniformCollections[UNIFORMCOLLECTIONS_STRUCT_IN_ARRAY].name = "struct_in_array"; 2623 defaultUniformCollections[UNIFORMCOLLECTIONS_ARRAY_IN_STRUCT].name = "array_in_struct"; 2624 defaultUniformCollections[UNIFORMCOLLECTIONS_NESTED_STRUCTS_ARRAYS].name = "nested_structs_arrays"; 2625 defaultUniformCollections[UNIFORMCOLLECTIONS_MULTIPLE_BASIC].name = "multiple_basic"; 2626 defaultUniformCollections[UNIFORMCOLLECTIONS_MULTIPLE_BASIC_ARRAY].name = "multiple_basic_array"; 2627 defaultUniformCollections[UNIFORMCOLLECTIONS_MULTIPLE_NESTED_STRUCTS_ARRAYS].name = "multiple_nested_structs_arrays"; 2628 2629 for (int dataTypeNdx = 0; dataTypeNdx < DE_LENGTH_OF_ARRAY(s_testDataTypes); dataTypeNdx++) 2630 { 2631 const glu::DataType dataType = s_testDataTypes[dataTypeNdx]; 2632 const char* const typeName = glu::getDataTypeName(dataType); 2633 2634 defaultUniformCollections[UNIFORMCOLLECTIONS_BASIC].cases.push_back(UniformCollectionCase(typeName, UniformCollection::basic(dataType))); 2635 2636 if (glu::isDataTypeScalar(dataType) || 2637 (glu::isDataTypeVector(dataType) && glu::getDataTypeScalarSize(dataType) == 4) || 2638 dataType == glu::TYPE_FLOAT_MAT4 || 2639 dataType == glu::TYPE_SAMPLER_2D) 2640 defaultUniformCollections[UNIFORMCOLLECTIONS_BASIC_ARRAY].cases.push_back(UniformCollectionCase(typeName, UniformCollection::basicArray(dataType))); 2641 2642 if (glu::isDataTypeScalar(dataType) || 2643 dataType == glu::TYPE_FLOAT_MAT4 || 2644 dataType == glu::TYPE_SAMPLER_2D) 2645 { 2646 const glu::DataType secondDataType = glu::isDataTypeScalar(dataType) ? glu::getDataTypeVector(dataType, 4) 2647 : dataType == glu::TYPE_FLOAT_MAT4 ? glu::TYPE_FLOAT_MAT2 2648 : dataType == glu::TYPE_SAMPLER_2D ? glu::TYPE_SAMPLER_CUBE 2649 : glu::TYPE_LAST; 2650 DE_ASSERT(secondDataType != glu::TYPE_LAST); 2651 const char* const secondTypeName = glu::getDataTypeName(secondDataType); 2652 const string name = string("") + typeName + "_" + secondTypeName; 2653 2654 defaultUniformCollections[UNIFORMCOLLECTIONS_BASIC_STRUCT].cases.push_back (UniformCollectionCase(name.c_str(), UniformCollection::basicStruct(dataType, secondDataType, false))); 2655 defaultUniformCollections[UNIFORMCOLLECTIONS_ARRAY_IN_STRUCT].cases.push_back (UniformCollectionCase(name.c_str(), UniformCollection::basicStruct(dataType, secondDataType, true))); 2656 defaultUniformCollections[UNIFORMCOLLECTIONS_STRUCT_IN_ARRAY].cases.push_back (UniformCollectionCase(name.c_str(), UniformCollection::structInArray(dataType, secondDataType, false))); 2657 defaultUniformCollections[UNIFORMCOLLECTIONS_NESTED_STRUCTS_ARRAYS].cases.push_back (UniformCollectionCase(name.c_str(), UniformCollection::nestedArraysStructs(dataType, secondDataType))); 2658 } 2659 } 2660 defaultUniformCollections[UNIFORMCOLLECTIONS_MULTIPLE_BASIC].cases.push_back (UniformCollectionCase(DE_NULL, UniformCollection::multipleBasic())); 2661 defaultUniformCollections[UNIFORMCOLLECTIONS_MULTIPLE_BASIC_ARRAY].cases.push_back (UniformCollectionCase(DE_NULL, UniformCollection::multipleBasicArray())); 2662 defaultUniformCollections[UNIFORMCOLLECTIONS_MULTIPLE_NESTED_STRUCTS_ARRAYS].cases.push_back (UniformCollectionCase(DE_NULL, UniformCollection::multipleNestedArraysStructs())); 2663 2664 // Info-query cases (check info returned by e.g. glGetActiveUniforms()). 2665 2666 { 2667 TestCaseGroup* const infoQueryGroup = new TestCaseGroup(m_context, "info_query", "Test uniform info querying functions"); 2668 addChild(infoQueryGroup); 2669 for (int caseTypeI = 0; caseTypeI < (int)UniformInfoQueryCase::CASETYPE_LAST; caseTypeI++) 2670 { 2671 const UniformInfoQueryCase::CaseType caseType = (UniformInfoQueryCase::CaseType)caseTypeI; 2672 TestCaseGroup* const caseTypeGroup = new TestCaseGroup(m_context, UniformInfoQueryCase::getCaseTypeName(caseType), UniformInfoQueryCase::getCaseTypeDescription(caseType)); 2673 infoQueryGroup->addChild(caseTypeGroup); 2674 2675 for (int collectionGroupNdx = 0; collectionGroupNdx < (int)UNIFORMCOLLECTIONS_LAST; collectionGroupNdx++) 2676 { 2677 const int numArrayFirstElemNameCases = caseType == UniformInfoQueryCase::CASETYPE_INDICES_UNIFORMSIV && collectionGroupNdx == UNIFORMCOLLECTIONS_BASIC_ARRAY ? 2 : 1; 2678 2679 for (int referToFirstArrayElemWithoutIndexI = 0; referToFirstArrayElemWithoutIndexI < numArrayFirstElemNameCases; referToFirstArrayElemWithoutIndexI++) 2680 { 2681 const UniformCollectionGroup& collectionGroup = defaultUniformCollections[collectionGroupNdx]; 2682 const string collectionGroupName = collectionGroup.name + (referToFirstArrayElemWithoutIndexI == 0 ? "" : "_first_elem_without_brackets"); 2683 TestCaseGroup* const collectionTestGroup = new TestCaseGroup(m_context, collectionGroupName.c_str(), ""); 2684 caseTypeGroup->addChild(collectionTestGroup); 2685 2686 for (int collectionNdx = 0; collectionNdx < (int)collectionGroup.cases.size(); collectionNdx++) 2687 { 2688 const UniformCollectionCase& collectionCase = collectionGroup.cases[collectionNdx]; 2689 2690 for (int shaderType = 0; shaderType < (int)CASESHADERTYPE_LAST; shaderType++) 2691 { 2692 const string name = collectionCase.namePrefix + getCaseShaderTypeName((CaseShaderType)shaderType); 2693 const SharedPtr<const UniformCollection>& uniformCollection = collectionCase.uniformCollection; 2694 2695 collectionTestGroup->addChild(new UniformInfoQueryCase(m_context, name.c_str(), "", (CaseShaderType)shaderType, uniformCollection, (UniformInfoQueryCase::CaseType)caseType, 2696 referToFirstArrayElemWithoutIndexI == 0 ? 0 : UniformCase::FEATURE_ARRAY_FIRST_ELEM_NAME_NO_INDEX)); 2697 } 2698 } 2699 } 2700 } 2701 2702 // Info-querying cases when unused uniforms are present. 2703 2704 { 2705 TestCaseGroup* const unusedUniformsGroup = new TestCaseGroup(m_context, "unused_uniforms", "Test with unused uniforms"); 2706 caseTypeGroup->addChild(unusedUniformsGroup); 2707 2708 const UniformCollectionGroup& collectionGroup = defaultUniformCollections[UNIFORMCOLLECTIONS_ARRAY_IN_STRUCT]; 2709 2710 for (int collectionNdx = 0; collectionNdx < (int)collectionGroup.cases.size(); collectionNdx++) 2711 { 2712 const UniformCollectionCase& collectionCase = collectionGroup.cases[collectionNdx]; 2713 const string collName = collectionCase.namePrefix; 2714 const SharedPtr<const UniformCollection>& uniformCollection = collectionCase.uniformCollection; 2715 2716 for (int shaderType = 0; shaderType < (int)CASESHADERTYPE_LAST; shaderType++) 2717 { 2718 const string name = collName + getCaseShaderTypeName((CaseShaderType)shaderType); 2719 unusedUniformsGroup->addChild(new UniformInfoQueryCase(m_context, name.c_str(), "", (CaseShaderType)shaderType, uniformCollection, (UniformInfoQueryCase::CaseType)caseType, 2720 UniformCase::FEATURE_UNIFORMUSAGE_EVERY_OTHER | UniformCase::FEATURE_ARRAYUSAGE_ONLY_MIDDLE_INDEX)); 2721 } 2722 } 2723 } 2724 } 2725 } 2726 2727 // Cases testing uniform values. 2728 2729 { 2730 TestCaseGroup* const valueGroup = new TestCaseGroup(m_context, "value", "Uniform value tests"); 2731 addChild(valueGroup); 2732 2733 // Cases checking uniforms' initial values (all must be zeros), with glGetUniform*() or by rendering. 2734 2735 { 2736 TestCaseGroup* const initialValuesGroup = new TestCaseGroup(m_context, 2737 UniformValueCase::getValueToCheckName(UniformValueCase::VALUETOCHECK_INITIAL), 2738 UniformValueCase::getValueToCheckDescription(UniformValueCase::VALUETOCHECK_INITIAL)); 2739 valueGroup->addChild(initialValuesGroup); 2740 2741 for (int checkMethodI = 0; checkMethodI < (int)UniformValueCase::CHECKMETHOD_LAST; checkMethodI++) 2742 { 2743 const UniformValueCase::CheckMethod checkMethod = (UniformValueCase::CheckMethod)checkMethodI; 2744 TestCaseGroup* const checkMethodGroup = new TestCaseGroup(m_context, UniformValueCase::getCheckMethodName(checkMethod), UniformValueCase::getCheckMethodDescription(checkMethod)); 2745 initialValuesGroup->addChild(checkMethodGroup); 2746 2747 for (int collectionGroupNdx = 0; collectionGroupNdx < (int)UNIFORMCOLLECTIONS_LAST; collectionGroupNdx++) 2748 { 2749 const UniformCollectionGroup& collectionGroup = defaultUniformCollections[collectionGroupNdx]; 2750 TestCaseGroup* const collectionTestGroup = new TestCaseGroup(m_context, collectionGroup.name.c_str(), ""); 2751 checkMethodGroup->addChild(collectionTestGroup); 2752 2753 for (int collectionNdx = 0; collectionNdx < (int)collectionGroup.cases.size(); collectionNdx++) 2754 { 2755 const UniformCollectionCase& collectionCase = collectionGroup.cases[collectionNdx]; 2756 const string collName = collectionCase.namePrefix; 2757 const SharedPtr<const UniformCollection>& uniformCollection = collectionCase.uniformCollection; 2758 const bool containsBooleans = uniformCollection->containsMatchingBasicType(glu::isDataTypeBoolOrBVec); 2759 const bool varyBoolApiType = checkMethod == UniformValueCase::CHECKMETHOD_GET_UNIFORM && containsBooleans && 2760 (collectionGroupNdx == UNIFORMCOLLECTIONS_BASIC || collectionGroupNdx == UNIFORMCOLLECTIONS_BASIC_ARRAY); 2761 const int numBoolVariations = varyBoolApiType ? 3 : 1; 2762 2763 if (checkMethod == UniformValueCase::CHECKMETHOD_RENDER && uniformCollection->containsSeveralSamplerTypes()) 2764 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. 2765 2766 for (int booleanTypeI = 0; booleanTypeI < numBoolVariations; booleanTypeI++) 2767 { 2768 const deUint32 booleanTypeFeat = booleanTypeI == 1 ? UniformCase::FEATURE_BOOLEANAPITYPE_INT 2769 : booleanTypeI == 2 ? UniformCase::FEATURE_BOOLEANAPITYPE_UINT 2770 : 0; 2771 const char* const booleanTypeName = booleanTypeI == 1 ? "int" 2772 : booleanTypeI == 2 ? "uint" 2773 : "float"; 2774 const string nameWithApiType = varyBoolApiType ? collName + "api_" + booleanTypeName + "_" : collName; 2775 2776 for (int shaderType = 0; shaderType < (int)CASESHADERTYPE_LAST; shaderType++) 2777 { 2778 const string name = nameWithApiType + getCaseShaderTypeName((CaseShaderType)shaderType); 2779 collectionTestGroup->addChild(new UniformValueCase(m_context, name.c_str(), "", (CaseShaderType)shaderType, uniformCollection, 2780 UniformValueCase::VALUETOCHECK_INITIAL, checkMethod, UniformValueCase::ASSIGNMETHOD_LAST, booleanTypeFeat)); 2781 } 2782 } 2783 } 2784 } 2785 } 2786 } 2787 2788 // Cases that first assign values to each uniform, then check the values with glGetUniform*() or by rendering. 2789 2790 { 2791 TestCaseGroup* const assignedValuesGroup = new TestCaseGroup(m_context, 2792 UniformValueCase::getValueToCheckName(UniformValueCase::VALUETOCHECK_ASSIGNED), 2793 UniformValueCase::getValueToCheckDescription(UniformValueCase::VALUETOCHECK_ASSIGNED)); 2794 valueGroup->addChild(assignedValuesGroup); 2795 2796 for (int assignMethodI = 0; assignMethodI < (int)UniformValueCase::ASSIGNMETHOD_LAST; assignMethodI++) 2797 { 2798 const UniformValueCase::AssignMethod assignMethod = (UniformValueCase::AssignMethod)assignMethodI; 2799 TestCaseGroup* const assignMethodGroup = new TestCaseGroup(m_context, UniformValueCase::getAssignMethodName(assignMethod), UniformValueCase::getAssignMethodDescription(assignMethod)); 2800 assignedValuesGroup->addChild(assignMethodGroup); 2801 2802 for (int checkMethodI = 0; checkMethodI < (int)UniformValueCase::CHECKMETHOD_LAST; checkMethodI++) 2803 { 2804 const UniformValueCase::CheckMethod checkMethod = (UniformValueCase::CheckMethod)checkMethodI; 2805 TestCaseGroup* const checkMethodGroup = new TestCaseGroup(m_context, UniformValueCase::getCheckMethodName(checkMethod), UniformValueCase::getCheckMethodDescription(checkMethod)); 2806 assignMethodGroup->addChild(checkMethodGroup); 2807 2808 for (int collectionGroupNdx = 0; collectionGroupNdx < (int)UNIFORMCOLLECTIONS_LAST; collectionGroupNdx++) 2809 { 2810 const int numArrayFirstElemNameCases = checkMethod == UniformValueCase::CHECKMETHOD_GET_UNIFORM && collectionGroupNdx == UNIFORMCOLLECTIONS_BASIC_ARRAY ? 2 : 1; 2811 2812 for (int referToFirstArrayElemWithoutIndexI = 0; referToFirstArrayElemWithoutIndexI < numArrayFirstElemNameCases; referToFirstArrayElemWithoutIndexI++) 2813 { 2814 const UniformCollectionGroup& collectionGroup = defaultUniformCollections[collectionGroupNdx]; 2815 const string collectionGroupName = collectionGroup.name + (referToFirstArrayElemWithoutIndexI == 0 ? "" : "_first_elem_without_brackets"); 2816 TestCaseGroup* collectionTestGroup = DE_NULL; 2817 2818 for (int collectionNdx = 0; collectionNdx < (int)collectionGroup.cases.size(); collectionNdx++) 2819 { 2820 const UniformCollectionCase& collectionCase = collectionGroup.cases[collectionNdx]; 2821 const string collName = collectionCase.namePrefix; 2822 const SharedPtr<const UniformCollection>& uniformCollection = collectionCase.uniformCollection; 2823 const bool containsBooleans = uniformCollection->containsMatchingBasicType(glu::isDataTypeBoolOrBVec); 2824 const bool varyBoolApiType = checkMethod == UniformValueCase::CHECKMETHOD_GET_UNIFORM && containsBooleans && 2825 (collectionGroupNdx == UNIFORMCOLLECTIONS_BASIC || collectionGroupNdx == UNIFORMCOLLECTIONS_BASIC_ARRAY); 2826 const int numBoolVariations = varyBoolApiType ? 3 : 1; 2827 const bool containsMatrices = uniformCollection->containsMatchingBasicType(glu::isDataTypeMatrix); 2828 const bool varyMatrixMode = containsMatrices && 2829 (collectionGroupNdx == UNIFORMCOLLECTIONS_BASIC || collectionGroupNdx == UNIFORMCOLLECTIONS_BASIC_ARRAY); 2830 const int numMatVariations = varyMatrixMode ? 2 : 1; 2831 2832 if (containsMatrices && assignMethod != UniformValueCase::ASSIGNMETHOD_POINTER) 2833 continue; 2834 2835 for (int booleanTypeI = 0; booleanTypeI < numBoolVariations; booleanTypeI++) 2836 { 2837 const deUint32 booleanTypeFeat = booleanTypeI == 1 ? UniformCase::FEATURE_BOOLEANAPITYPE_INT 2838 : booleanTypeI == 2 ? UniformCase::FEATURE_BOOLEANAPITYPE_UINT 2839 : 0; 2840 const char* const booleanTypeName = booleanTypeI == 1 ? "int" 2841 : booleanTypeI == 2 ? "uint" 2842 : "float"; 2843 const string nameWithBoolType = varyBoolApiType ? collName + "api_" + booleanTypeName + "_" : collName; 2844 2845 for (int matrixTypeI = 0; matrixTypeI < numMatVariations; matrixTypeI++) 2846 { 2847 const string nameWithMatrixType = nameWithBoolType + (matrixTypeI == 1 ? "row_major_" : ""); 2848 2849 for (int shaderType = 0; shaderType < (int)CASESHADERTYPE_LAST; shaderType++) 2850 { 2851 const string name = nameWithMatrixType + getCaseShaderTypeName((CaseShaderType)shaderType); 2852 const deUint32 arrayFirstElemNameNoIndexFeat = referToFirstArrayElemWithoutIndexI == 0 ? 0 : UniformCase::FEATURE_ARRAY_FIRST_ELEM_NAME_NO_INDEX; 2853 2854 // skip empty groups by creating groups on demand 2855 if (!collectionTestGroup) 2856 { 2857 collectionTestGroup = new TestCaseGroup(m_context, collectionGroupName.c_str(), ""); 2858 checkMethodGroup->addChild(collectionTestGroup); 2859 } 2860 2861 collectionTestGroup->addChild(new UniformValueCase(m_context, name.c_str(), "", (CaseShaderType)shaderType, uniformCollection, 2862 UniformValueCase::VALUETOCHECK_ASSIGNED, checkMethod, assignMethod, 2863 booleanTypeFeat | arrayFirstElemNameNoIndexFeat | (matrixTypeI == 1 ? UniformCase::FEATURE_MATRIXMODE_ROWMAJOR : 0))); 2864 } 2865 } 2866 } 2867 } 2868 } 2869 } 2870 } 2871 } 2872 2873 // Cases assign multiple basic-array elements with one glUniform*v() (i.e. the count parameter is bigger than 1). 2874 2875 { 2876 static const struct 2877 { 2878 UniformCase::Feature arrayAssignMode; 2879 const char* name; 2880 const char* description; 2881 } arrayAssignGroups[] = 2882 { 2883 { UniformCase::FEATURE_ARRAYASSIGN_FULL, "basic_array_assign_full", "Assign entire basic-type arrays per glUniform*v() call" }, 2884 { UniformCase::FEATURE_ARRAYASSIGN_BLOCKS_OF_TWO, "basic_array_assign_partial", "Assign two elements of a basic-type array per glUniform*v() call" } 2885 }; 2886 2887 for (int arrayAssignGroupNdx = 0; arrayAssignGroupNdx < DE_LENGTH_OF_ARRAY(arrayAssignGroups); arrayAssignGroupNdx++) 2888 { 2889 UniformCase::Feature arrayAssignMode = arrayAssignGroups[arrayAssignGroupNdx].arrayAssignMode; 2890 const char* const groupName = arrayAssignGroups[arrayAssignGroupNdx].name; 2891 const char* const groupDesc = arrayAssignGroups[arrayAssignGroupNdx].description; 2892 2893 TestCaseGroup* const curArrayAssignGroup = new TestCaseGroup(m_context, groupName, groupDesc); 2894 assignedValuesGroup->addChild(curArrayAssignGroup); 2895 2896 static const int basicArrayCollectionGroups[] = { UNIFORMCOLLECTIONS_BASIC_ARRAY, UNIFORMCOLLECTIONS_ARRAY_IN_STRUCT, UNIFORMCOLLECTIONS_MULTIPLE_BASIC_ARRAY }; 2897 2898 for (int collectionGroupNdx = 0; collectionGroupNdx < DE_LENGTH_OF_ARRAY(basicArrayCollectionGroups); collectionGroupNdx++) 2899 { 2900 const UniformCollectionGroup& collectionGroup = defaultUniformCollections[basicArrayCollectionGroups[collectionGroupNdx]]; 2901 TestCaseGroup* const collectionTestGroup = new TestCaseGroup(m_context, collectionGroup.name.c_str(), ""); 2902 curArrayAssignGroup->addChild(collectionTestGroup); 2903 2904 for (int collectionNdx = 0; collectionNdx < (int)collectionGroup.cases.size(); collectionNdx++) 2905 { 2906 const UniformCollectionCase& collectionCase = collectionGroup.cases[collectionNdx]; 2907 const string collName = collectionCase.namePrefix; 2908 const SharedPtr<const UniformCollection>& uniformCollection = collectionCase.uniformCollection; 2909 2910 for (int shaderType = 0; shaderType < (int)CASESHADERTYPE_LAST; shaderType++) 2911 { 2912 const string name = collName + getCaseShaderTypeName((CaseShaderType)shaderType); 2913 collectionTestGroup->addChild(new UniformValueCase(m_context, name.c_str(), "", (CaseShaderType)shaderType, uniformCollection, 2914 UniformValueCase::VALUETOCHECK_ASSIGNED, UniformValueCase::CHECKMETHOD_GET_UNIFORM, UniformValueCase::ASSIGNMETHOD_POINTER, 2915 arrayAssignMode)); 2916 } 2917 } 2918 } 2919 } 2920 } 2921 2922 // Value checking cases when unused uniforms are present. 2923 2924 { 2925 TestCaseGroup* const unusedUniformsGroup = new TestCaseGroup(m_context, "unused_uniforms", "Test with unused uniforms"); 2926 assignedValuesGroup->addChild(unusedUniformsGroup); 2927 2928 const UniformCollectionGroup& collectionGroup = defaultUniformCollections[UNIFORMCOLLECTIONS_ARRAY_IN_STRUCT]; 2929 2930 for (int collectionNdx = 0; collectionNdx < (int)collectionGroup.cases.size(); collectionNdx++) 2931 { 2932 const UniformCollectionCase& collectionCase = collectionGroup.cases[collectionNdx]; 2933 const string collName = collectionCase.namePrefix; 2934 const SharedPtr<const UniformCollection>& uniformCollection = collectionCase.uniformCollection; 2935 2936 for (int shaderType = 0; shaderType < (int)CASESHADERTYPE_LAST; shaderType++) 2937 { 2938 const string name = collName + getCaseShaderTypeName((CaseShaderType)shaderType); 2939 unusedUniformsGroup->addChild(new UniformValueCase(m_context, name.c_str(), "", (CaseShaderType)shaderType, uniformCollection, 2940 UniformValueCase::VALUETOCHECK_ASSIGNED, UniformValueCase::CHECKMETHOD_GET_UNIFORM, UniformValueCase::ASSIGNMETHOD_POINTER, 2941 UniformCase::FEATURE_ARRAYUSAGE_ONLY_MIDDLE_INDEX | UniformCase::FEATURE_UNIFORMUSAGE_EVERY_OTHER)); 2942 } 2943 } 2944 } 2945 } 2946 } 2947 2948 // Random cases. 2949 2950 { 2951 const int numRandomCases = 100; 2952 TestCaseGroup* const randomGroup = new TestCaseGroup(m_context, "random", "Random cases"); 2953 addChild(randomGroup); 2954 2955 for (int ndx = 0; ndx < numRandomCases; ndx++) 2956 randomGroup->addChild(new RandomUniformCase(m_context, de::toString(ndx).c_str(), "", (deUint32)ndx)); 2957 } 2958 } 2959 2960 } // Functional 2961 } // gles3 2962 } // deqp 2963