1 /*------------------------------------------------------------------------- 2 * drawElements Quality Program OpenGL ES 3.1 Module 3 * ------------------------------------------------- 4 * 5 * Copyright 2014 The Android Open Source Project 6 * 7 * Licensed under the Apache License, Version 2.0 (the "License"); 8 * you may not use this file except in compliance with the License. 9 * You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, software 14 * distributed under the License is distributed on an "AS IS" BASIS, 15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 * See the License for the specific language governing permissions and 17 * limitations under the License. 18 * 19 *//*! 20 * \file 21 * \brief Debug output (KHR_debug) tests 22 *//*--------------------------------------------------------------------*/ 23 24 #include "es31fDebugTests.hpp" 25 26 #include "es31fNegativeTestShared.hpp" 27 #include "es31fNegativeBufferApiTests.hpp" 28 #include "es31fNegativeTextureApiTests.hpp" 29 #include "es31fNegativeShaderApiTests.hpp" 30 #include "es31fNegativeFragmentApiTests.hpp" 31 #include "es31fNegativeVertexArrayApiTests.hpp" 32 #include "es31fNegativeStateApiTests.hpp" 33 #include "es31fNegativeAtomicCounterTests.hpp" 34 #include "es31fNegativeShaderImageLoadStoreTests.hpp" 35 #include "es31fNegativeShaderFunctionTests.hpp" 36 #include "es31fNegativeShaderDirectiveTests.hpp" 37 #include "es31fNegativeSSBOBlockTests.hpp" 38 #include "es31fNegativePreciseTests.hpp" 39 #include "es31fNegativeAdvancedBlendEquationTests.hpp" 40 #include "es31fNegativeShaderStorageTests.hpp" 41 #include "es31fNegativeTessellationTests.hpp" 42 #include "es31fNegativeComputeTests.hpp" 43 #include "es31fNegativeSampleVariablesTests.hpp" 44 #include "es31fNegativeShaderFramebufferFetchTests.hpp" 45 46 #include "deUniquePtr.hpp" 47 #include "deRandom.hpp" 48 #include "deStringUtil.hpp" 49 #include "deSTLUtil.hpp" 50 #include "deMutex.hpp" 51 #include "deThread.h" 52 53 #include "gluRenderContext.hpp" 54 #include "gluContextInfo.hpp" 55 #include "gluCallLogWrapper.hpp" 56 #include "gluStrUtil.hpp" 57 58 #include "glwDefs.hpp" 59 #include "glwEnums.hpp" 60 #include "glwFunctions.hpp" 61 62 #include "tes31Context.hpp" 63 #include "tcuTestContext.hpp" 64 #include "tcuCommandLine.hpp" 65 #include "tcuResultCollector.hpp" 66 67 #include "glsStateQueryUtil.hpp" 68 69 namespace deqp 70 { 71 namespace gles31 72 { 73 namespace Functional 74 { 75 namespace 76 { 77 using namespace glw; 78 79 using std::string; 80 using std::vector; 81 using std::set; 82 using std::map; 83 using de::MovePtr; 84 85 using tcu::ResultCollector; 86 using tcu::TestLog; 87 using glu::CallLogWrapper; 88 89 using NegativeTestShared::NegativeTestContext; 90 91 static const GLenum s_debugTypes[] = 92 { 93 GL_DEBUG_TYPE_ERROR, 94 GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR, 95 GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR, 96 GL_DEBUG_TYPE_PORTABILITY, 97 GL_DEBUG_TYPE_PERFORMANCE, 98 GL_DEBUG_TYPE_OTHER, 99 GL_DEBUG_TYPE_MARKER, 100 GL_DEBUG_TYPE_PUSH_GROUP, 101 GL_DEBUG_TYPE_POP_GROUP, 102 }; 103 104 static const GLenum s_debugSeverities[] = 105 { 106 GL_DEBUG_SEVERITY_HIGH, 107 GL_DEBUG_SEVERITY_MEDIUM, 108 GL_DEBUG_SEVERITY_LOW, 109 GL_DEBUG_SEVERITY_NOTIFICATION, 110 }; 111 112 static bool isKHRDebugSupported (Context& ctx) 113 { 114 const bool supportsES32 = glu::contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2)); 115 return supportsES32 || ctx.getContextInfo().isExtensionSupported("GL_KHR_debug"); 116 } 117 118 class BaseCase; 119 120 class DebugMessageTestContext : public NegativeTestContext 121 { 122 public: 123 DebugMessageTestContext (BaseCase& host, 124 glu::RenderContext& renderCtx, 125 const glu::ContextInfo& ctxInfo, 126 tcu::TestLog& log, 127 tcu::ResultCollector& results, 128 bool enableLog); 129 ~DebugMessageTestContext (void); 130 131 void expectMessage (GLenum source, GLenum type); 132 133 private: 134 BaseCase& m_debugHost; 135 }; 136 137 class TestFunctionWrapper 138 { 139 public: 140 typedef void (*CoreTestFunc)(NegativeTestContext& ctx); 141 typedef void (*DebugTestFunc)(DebugMessageTestContext& ctx); 142 143 TestFunctionWrapper (void); 144 explicit TestFunctionWrapper (CoreTestFunc func); 145 explicit TestFunctionWrapper (DebugTestFunc func); 146 147 void call (DebugMessageTestContext& ctx) const; 148 149 private: 150 enum FuncType 151 { 152 TYPE_NULL = 0, 153 TYPE_CORE, 154 TYPE_DEBUG, 155 }; 156 FuncType m_type; 157 158 union 159 { 160 CoreTestFunc coreFn; 161 DebugTestFunc debugFn; 162 } m_func; 163 }; 164 165 TestFunctionWrapper::TestFunctionWrapper (void) 166 : m_type(TYPE_NULL) 167 { 168 } 169 170 TestFunctionWrapper::TestFunctionWrapper (CoreTestFunc func) 171 : m_type(TYPE_CORE) 172 { 173 m_func.coreFn = func; 174 } 175 176 TestFunctionWrapper::TestFunctionWrapper (DebugTestFunc func) 177 : m_type(TYPE_DEBUG) 178 { 179 m_func.debugFn = func; 180 } 181 182 void TestFunctionWrapper::call (DebugMessageTestContext& ctx) const 183 { 184 if (m_type == TYPE_CORE) 185 m_func.coreFn(static_cast<NegativeTestContext&>(ctx)); 186 else if (m_type == TYPE_DEBUG) 187 m_func.debugFn(ctx); 188 else 189 DE_ASSERT(false); 190 } 191 192 void emitMessages (DebugMessageTestContext& ctx, GLenum source) 193 { 194 for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(s_debugTypes); typeNdx++) 195 { 196 for (int severityNdx = 0; severityNdx < DE_LENGTH_OF_ARRAY(s_debugSeverities); severityNdx++) 197 { 198 const GLenum type = s_debugTypes[typeNdx]; 199 const GLenum severity = s_debugSeverities[severityNdx]; 200 const string msg = string("Application generated message with type ") + glu::getDebugMessageTypeName(type) 201 + " and severity " + glu::getDebugMessageSeverityName(severity); 202 203 // Use severity as ID, guaranteed unique 204 ctx.glDebugMessageInsert(source, type, severity, severity, -1, msg.c_str()); 205 ctx.expectMessage(source, type); 206 } 207 } 208 } 209 210 void application_messages (DebugMessageTestContext& ctx) 211 { 212 ctx.beginSection("Messages with source of GL_DEBUG_SOURCE_APPLICATION"); 213 emitMessages(ctx, GL_DEBUG_SOURCE_APPLICATION); 214 ctx.endSection(); 215 } 216 217 void thirdparty_messages (DebugMessageTestContext& ctx) 218 { 219 ctx.beginSection("Messages with source of GL_DEBUG_SOURCE_THIRD_PARTY"); 220 emitMessages(ctx, GL_DEBUG_SOURCE_THIRD_PARTY); 221 ctx.endSection(); 222 } 223 224 void push_pop_messages (DebugMessageTestContext& ctx) 225 { 226 ctx.beginSection("Push/Pop Debug Group"); 227 228 ctx.glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 1, -1, "Application group 1"); 229 ctx.expectMessage(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PUSH_GROUP); 230 ctx.glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 2, -1, "Application group 1-1"); 231 ctx.expectMessage(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PUSH_GROUP); 232 ctx.glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 3, -1, "Application group 1-1-1"); 233 ctx.expectMessage(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PUSH_GROUP); 234 ctx.glPopDebugGroup(); 235 ctx.expectMessage(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_POP_GROUP); 236 ctx.glPopDebugGroup(); 237 ctx.expectMessage(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_POP_GROUP); 238 239 ctx.glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 4, -1, "Application group 1-2"); 240 ctx.expectMessage(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PUSH_GROUP); 241 ctx.glPopDebugGroup(); 242 ctx.expectMessage(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_POP_GROUP); 243 244 ctx.glPushDebugGroup(GL_DEBUG_SOURCE_THIRD_PARTY, 4, -1, "3rd Party group 1-3"); 245 ctx.expectMessage(GL_DEBUG_SOURCE_THIRD_PARTY, GL_DEBUG_TYPE_PUSH_GROUP); 246 ctx.glPopDebugGroup(); 247 ctx.expectMessage(GL_DEBUG_SOURCE_THIRD_PARTY, GL_DEBUG_TYPE_POP_GROUP); 248 ctx.glPopDebugGroup(); 249 ctx.expectMessage(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_POP_GROUP); 250 251 ctx.glPushDebugGroup(GL_DEBUG_SOURCE_THIRD_PARTY, 4, -1, "3rd Party group 2"); 252 ctx.expectMessage(GL_DEBUG_SOURCE_THIRD_PARTY, GL_DEBUG_TYPE_PUSH_GROUP); 253 ctx.glPopDebugGroup(); 254 ctx.expectMessage(GL_DEBUG_SOURCE_THIRD_PARTY, GL_DEBUG_TYPE_POP_GROUP); 255 256 ctx.endSection(); 257 } 258 259 struct FunctionContainer 260 { 261 TestFunctionWrapper function; 262 const char* name; 263 const char* desc; 264 }; 265 266 vector<FunctionContainer> getUserMessageFuncs (void) 267 { 268 FunctionContainer funcs[] = 269 { 270 { TestFunctionWrapper(application_messages), "application_messages", "Externally generated messages from the application" }, 271 { TestFunctionWrapper(thirdparty_messages), "third_party_messages", "Externally generated messages from a third party" }, 272 { TestFunctionWrapper(push_pop_messages), "push_pop_stack", "Messages from pushing/popping debug groups" }, 273 }; 274 275 return std::vector<FunctionContainer>(DE_ARRAY_BEGIN(funcs), DE_ARRAY_END(funcs)); 276 } 277 278 // Data required to uniquely identify a debug message 279 struct MessageID 280 { 281 GLenum source; 282 GLenum type; 283 GLuint id; 284 285 MessageID (void) : source(GL_NONE), type(GL_NONE), id(0) {} 286 MessageID (GLenum source_, GLenum type_, GLuint id_) : source(source_), type(type_), id(id_) {} 287 288 bool operator== (const MessageID& rhs) const { return source == rhs.source && type == rhs.type && id == rhs.id;} 289 bool operator!= (const MessageID& rhs) const { return source != rhs.source || type != rhs.type || id != rhs.id;} 290 bool operator< (const MessageID& rhs) const 291 { 292 return source < rhs.source || (source == rhs.source && (type < rhs.type || (type == rhs.type && id < rhs.id))); 293 } 294 }; 295 296 std::ostream& operator<< (std::ostream& str, const MessageID &id) 297 { 298 return str << glu::getDebugMessageSourceStr(id.source) << ", " << glu::getDebugMessageTypeStr(id.type) << ", " << id.id; 299 } 300 301 // All info from a single debug message 302 struct MessageData 303 { 304 MessageID id; 305 GLenum severity; 306 string message; 307 308 MessageData (void) : id(MessageID()), severity(GL_NONE) {} 309 MessageData (const MessageID& id_, GLenum severity_, const string& message_) : id(id_) , severity(severity_) , message(message_) {} 310 }; 311 312 extern "C" typedef void GLW_APIENTRY DebugCallbackFunc(GLenum, GLenum, GLuint, GLenum, GLsizei, const char*, const void*); 313 314 // Base class 315 class BaseCase : public NegativeTestShared::ErrorCase 316 { 317 public: 318 BaseCase (Context& ctx, 319 const char* name, 320 const char* desc); 321 virtual ~BaseCase (void) {} 322 323 virtual IterateResult iterate (void) = 0; 324 325 virtual void expectMessage (GLenum source, GLenum type); 326 virtual void expectError (GLenum error0, GLenum error1); 327 328 protected: 329 struct VerificationResult 330 { 331 const qpTestResult result; 332 const string resultMessage; 333 const string logMessage; 334 335 VerificationResult (qpTestResult result_, const string& resultMessage_, const string& logMessage_) 336 : result(result_), resultMessage(resultMessage_), logMessage(logMessage_) {} 337 }; 338 339 static DebugCallbackFunc callbackHandle; 340 virtual void callback (GLenum source, GLenum type, GLuint id, GLenum severity, const std::string& message); 341 342 343 VerificationResult verifyMessageCount (const MessageID& id, GLenum severity, int refCount, int resCount, bool messageEnabled) const; 344 345 // Verify a single message instance against expected attributes 346 void verifyMessage (const MessageData& message, GLenum source, GLenum type, GLuint id, GLenum severity); 347 void verifyMessage (const MessageData& message, GLenum source, GLenum type); 348 349 bool verifyMessageExists (const MessageData& message, GLenum source, GLenum type); 350 void verifyMessageGroup (const MessageData& message, GLenum source, GLenum type); 351 void verifyMessageString (const MessageData& message); 352 353 bool isDebugContext (void) const; 354 355 tcu::ResultCollector m_results; 356 }; 357 358 void BaseCase::callbackHandle (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const char* message, const void* userParam) 359 { 360 static_cast<BaseCase*>(const_cast<void*>(userParam))->callback(source, type, id, severity, string(message, &message[length])); 361 } 362 363 BaseCase::BaseCase (Context& ctx, const char* name, const char* desc) 364 : ErrorCase(ctx, name, desc) 365 { 366 } 367 368 void BaseCase::expectMessage (GLenum source, GLenum type) 369 { 370 DE_UNREF(source); 371 DE_UNREF(type); 372 } 373 374 void BaseCase::expectError (GLenum error0, GLenum error1) 375 { 376 if (error0 != GL_NO_ERROR || error1 != GL_NO_ERROR) 377 expectMessage(GL_DEBUG_SOURCE_API, GL_DEBUG_TYPE_ERROR); 378 else 379 expectMessage(GL_DONT_CARE, GL_DONT_CARE); 380 } 381 382 void BaseCase::callback (GLenum source, GLenum type, GLuint id, GLenum severity, const string& message) 383 { 384 DE_UNREF(source); 385 DE_UNREF(type); 386 DE_UNREF(id); 387 DE_UNREF(severity); 388 DE_UNREF(message); 389 } 390 391 BaseCase::VerificationResult BaseCase::verifyMessageCount (const MessageID& id, GLenum severity, int refCount, int resCount, bool messageEnabled) const 392 { 393 std::stringstream log; 394 395 // This message should not be filtered out 396 if (messageEnabled) 397 { 398 if (resCount != refCount) 399 { 400 /* 401 * Technically nothing requires the implementation to be consistent in terms 402 * of the messages it produces in most situations, allowing the set of messages 403 * produced to vary between executions. This function splits messages 404 * into deterministic and non-deterministic to facilitate handling of such messages. 405 * 406 * Non-deterministic messages that are present in differing quantities in filtered and 407 * unfiltered runs will not fail the test case unless in direct violation of a filter: 408 * the implementation may produce an arbitrary number of such messages when they are 409 * not filtered out and none when they are filtered. 410 * 411 * A list of error source/type combinations with their assumed behaviour and 412 * the rationale for expecting such behaviour follows 413 * 414 * For API/shader messages we assume that the following types are deterministic: 415 * DEBUG_TYPE_ERROR Errors specified by spec and should always be produced 416 * 417 * For API messages the following types are assumed to be non-deterministic 418 * and treated as quality warnings since the underlying reported issue does not change between calls: 419 * DEBUG_TYPE_DEPRECATED_BEHAVIOR Reasonable to only report first instance 420 * DEBUG_TYPE_UNDEFINED_BEHAVIOR Reasonable to only report first instance 421 * DEBUG_TYPE_PORTABILITY Reasonable to only report first instance 422 * 423 * For API messages the following types are assumed to be non-deterministic 424 * and do not affect test results. 425 * DEBUG_TYPE_PERFORMANCE May be tied to arbitrary factors, reasonable to report only first instance 426 * DEBUG_TYPE_OTHER Definition allows arbitrary contents 427 * 428 * For 3rd party and application messages the following types are deterministic: 429 * DEBUG_TYPE_MARKER Only generated by test 430 * DEBUG_TYPE_PUSH_GROUP Only generated by test 431 * DEBUG_TYPE_POP_GROUP Only generated by test 432 * All others Only generated by test 433 * 434 * All messages with category of window system or other are treated as non-deterministic 435 * and do not effect test results since they can be assumed to be outside control of 436 * both the implementation and test case 437 * 438 */ 439 440 const bool isDeterministic = id.source == GL_DEBUG_SOURCE_APPLICATION || 441 id.source == GL_DEBUG_SOURCE_THIRD_PARTY || 442 ((id.source == GL_DEBUG_SOURCE_API || id.source == GL_DEBUG_SOURCE_SHADER_COMPILER) && id.type == GL_DEBUG_TYPE_ERROR); 443 444 const bool canIgnore = id.source == GL_DEBUG_SOURCE_WINDOW_SYSTEM || id.source == GL_DEBUG_SOURCE_OTHER; 445 446 if (isDeterministic) 447 { 448 if (resCount > refCount) 449 { 450 log << "Extra instances of message were found: (" << id << ") with " 451 << glu::getDebugMessageSeverityStr(severity) 452 << " (got " << resCount << ", expected " << refCount << ")"; 453 return VerificationResult(QP_TEST_RESULT_FAIL, "Extra instances of a deterministic message were present", log.str()); 454 } 455 else 456 { 457 log << "Instances of message were missing: (" << id << ") with " 458 << glu::getDebugMessageSeverityStr(severity) 459 << " (got " << resCount << ", expected " << refCount << ")"; 460 return VerificationResult(QP_TEST_RESULT_FAIL, "Message missing", log.str()); 461 } 462 } 463 else if(!canIgnore) 464 { 465 if (resCount > refCount) 466 { 467 log << "Extra instances of message were found but the message is non-deterministic(warning): (" << id << ") with " 468 << glu::getDebugMessageSeverityStr(severity) 469 << " (got " << resCount << ", expected " << refCount << ")"; 470 return VerificationResult(QP_TEST_RESULT_QUALITY_WARNING, "Extra instances of a message were present", log.str()); 471 } 472 else 473 { 474 log << "Instances of message were missing but the message is non-deterministic(warning): (" << id << ") with " 475 << glu::getDebugMessageSeverityStr(severity) 476 << " (got " << resCount << ", expected " << refCount << ")"; 477 return VerificationResult(QP_TEST_RESULT_QUALITY_WARNING, "Message missing", log.str()); 478 } 479 } 480 else 481 { 482 if (resCount > refCount) 483 { 484 log << "Extra instances of message were found but the message is non-deterministic(ignored): (" << id << ") with " 485 << glu::getDebugMessageSeverityStr(severity) 486 << " (got " << resCount << ", expected " << refCount << ")"; 487 return VerificationResult(QP_TEST_RESULT_PASS, "", log.str()); 488 } 489 else 490 { 491 log << "Instances of message were missing but the message is non-deterministic(ignored): (" << id << ") with " 492 << glu::getDebugMessageSeverityStr(severity) 493 << " (got " << resCount << ", expected " << refCount << ")"; 494 return VerificationResult(QP_TEST_RESULT_PASS, "", log.str()); 495 } 496 } 497 } 498 else // Passed as appropriate 499 { 500 log << "Message was found when expected: ("<< id << ") with " 501 << glu::getDebugMessageSeverityStr(severity); 502 return VerificationResult(QP_TEST_RESULT_PASS, "", log.str()); 503 } 504 } 505 // Message should be filtered out 506 else 507 { 508 // Filtered out 509 if (resCount == 0) 510 { 511 log << "Message was excluded correctly: (" << id << ") with " 512 << glu::getDebugMessageSeverityStr(severity); 513 return VerificationResult(QP_TEST_RESULT_PASS, "", log.str()); 514 } 515 // Only present in filtered run (ERROR) 516 else if (resCount > 0 && refCount == 0) 517 { 518 log << "A message was not excluded as it should have been: (" << id << ") with " 519 << glu::getDebugMessageSeverityStr(severity) 520 << ". This message was not present in the reference run"; 521 return VerificationResult(QP_TEST_RESULT_FAIL, "A message was not filtered out", log.str()); 522 } 523 // Present in both runs (ERROR) 524 else 525 { 526 log << "A message was not excluded as it should have been: (" << id << ") with " 527 << glu::getDebugMessageSeverityStr(severity); 528 return VerificationResult(QP_TEST_RESULT_FAIL, "A message was not filtered out", log.str()); 529 } 530 } 531 } 532 533 // Return true if message needs further verification 534 bool BaseCase::verifyMessageExists (const MessageData& message, GLenum source, GLenum type) 535 { 536 TestLog& log = m_testCtx.getLog(); 537 538 if (source == GL_DONT_CARE || type == GL_DONT_CARE) 539 return false; 540 else if (message.id.source == GL_NONE || message.id.type == GL_NONE) 541 { 542 if (isDebugContext()) 543 { 544 m_results.addResult(QP_TEST_RESULT_FAIL, "Message was not reported as expected"); 545 log << TestLog::Message << "A message was expected but none was reported" << TestLog::EndMessage; 546 } 547 else 548 { 549 m_results.addResult(QP_TEST_RESULT_QUALITY_WARNING, "Verification accuracy is lacking without a debug context"); 550 log << TestLog::Message << "A message was expected but none was reported. Running without a debug context" << TestLog::EndMessage; 551 } 552 return false; 553 } 554 else 555 return true; 556 } 557 558 void BaseCase::verifyMessageGroup (const MessageData& message, GLenum source, GLenum type) 559 { 560 TestLog& log = m_testCtx.getLog(); 561 562 if (message.id.source != source) 563 { 564 m_results.addResult(QP_TEST_RESULT_FAIL, "Incorrect message source"); 565 log << TestLog::Message << "Message source was " << glu::getDebugMessageSourceStr(message.id.source) 566 << " when it should have been " << glu::getDebugMessageSourceStr(source) << TestLog::EndMessage; 567 } 568 569 if (message.id.type != type) 570 { 571 m_results.addResult(QP_TEST_RESULT_FAIL, "Incorrect message type"); 572 log << TestLog::Message << "Message type was " << glu::getDebugMessageTypeStr(message.id.type) 573 << " when it should have been " << glu::getDebugMessageTypeStr(type) << TestLog::EndMessage; 574 } 575 } 576 577 void BaseCase::verifyMessageString (const MessageData& message) 578 { 579 TestLog& log = m_testCtx.getLog(); 580 581 log << TestLog::Message << "Driver says: \"" << message.message << "\"" << TestLog::EndMessage; 582 583 if (message.message.empty()) 584 { 585 m_results.addResult(QP_TEST_RESULT_QUALITY_WARNING, "Empty message"); 586 log << TestLog::Message << "Message message was empty" << TestLog::EndMessage; 587 } 588 } 589 590 void BaseCase::verifyMessage (const MessageData& message, GLenum source, GLenum type) 591 { 592 if (verifyMessageExists(message, source, type)) 593 { 594 verifyMessageString(message); 595 verifyMessageGroup(message, source, type); 596 } 597 } 598 599 void BaseCase::verifyMessage (const MessageData& message, GLenum source, GLenum type, GLuint id, GLenum severity) 600 { 601 TestLog& log = m_testCtx.getLog(); 602 603 if (verifyMessageExists(message, source, type)) 604 { 605 verifyMessageString(message); 606 verifyMessageGroup(message, source, type); 607 608 if (message.id.id != id) 609 { 610 m_results.addResult(QP_TEST_RESULT_FAIL, "Incorrect message id"); 611 log << TestLog::Message << "Message id was " << message.id.id 612 << " when it should have been " << id << TestLog::EndMessage; 613 } 614 615 if (message.severity != severity) 616 { 617 m_results.addResult(QP_TEST_RESULT_FAIL, "Incorrect message severity"); 618 log << TestLog::Message << "Message severity was " << glu::getDebugMessageSeverityStr(message.severity) 619 << " when it should have been " << glu::getDebugMessageSeverityStr(severity) << TestLog::EndMessage; 620 } 621 } 622 } 623 624 bool BaseCase::isDebugContext (void) const 625 { 626 return (m_context.getRenderContext().getType().getFlags() & glu::CONTEXT_DEBUG) != 0; 627 } 628 629 // Generate errors, verify that each error results in a callback call 630 class CallbackErrorCase : public BaseCase 631 { 632 public: 633 CallbackErrorCase (Context& ctx, 634 const char* name, 635 const char* desc, 636 TestFunctionWrapper errorFunc); 637 virtual ~CallbackErrorCase (void) {} 638 639 virtual IterateResult iterate (void); 640 641 virtual void expectMessage (GLenum source, GLenum type); 642 643 private: 644 virtual void callback (GLenum source, GLenum type, GLuint id, GLenum severity, const string& message); 645 646 const TestFunctionWrapper m_errorFunc; 647 MessageData m_lastMessage; 648 }; 649 650 CallbackErrorCase::CallbackErrorCase (Context& ctx, 651 const char* name, 652 const char* desc, 653 TestFunctionWrapper errorFunc) 654 : BaseCase (ctx, name, desc) 655 , m_errorFunc (errorFunc) 656 { 657 } 658 659 CallbackErrorCase::IterateResult CallbackErrorCase::iterate (void) 660 { 661 TCU_CHECK_AND_THROW(NotSupportedError, isKHRDebugSupported(m_context), "GL_KHR_debug is not supported"); 662 663 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 664 tcu::TestLog& log = m_testCtx.getLog(); 665 DebugMessageTestContext context = DebugMessageTestContext(*this, m_context.getRenderContext(), m_context.getContextInfo(), log, m_results, true); 666 667 gl.enable(GL_DEBUG_OUTPUT); 668 gl.enable(GL_DEBUG_OUTPUT_SYNCHRONOUS); 669 gl.debugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, DE_NULL, false); // disable all 670 gl.debugMessageControl(GL_DEBUG_SOURCE_API, GL_DEBUG_TYPE_ERROR, GL_DONT_CARE, 0, DE_NULL, true); // enable API errors 671 gl.debugMessageControl(GL_DEBUG_SOURCE_APPLICATION, GL_DONT_CARE, GL_DONT_CARE, 0, DE_NULL, true); // enable application messages 672 gl.debugMessageControl(GL_DEBUG_SOURCE_THIRD_PARTY, GL_DONT_CARE, GL_DONT_CARE, 0, DE_NULL, true); // enable third party messages 673 gl.debugMessageCallback(callbackHandle, this); 674 675 m_errorFunc.call(context); 676 677 gl.debugMessageCallback(DE_NULL, DE_NULL); 678 gl.disable(GL_DEBUG_OUTPUT); 679 680 m_results.setTestContextResult(m_testCtx); 681 682 return STOP; 683 } 684 685 void CallbackErrorCase::expectMessage (GLenum source, GLenum type) 686 { 687 verifyMessage(m_lastMessage, source, type); 688 m_lastMessage = MessageData(); 689 690 // Reset error so that code afterwards (such as glu::ShaderProgram) doesn't break because of 691 // lingering error state. 692 m_context.getRenderContext().getFunctions().getError(); 693 } 694 695 void CallbackErrorCase::callback (GLenum source, GLenum type, GLuint id, GLenum severity, const string& message) 696 { 697 m_lastMessage = MessageData(MessageID(source, type, id), severity, message); 698 } 699 700 // Generate errors, verify that each error results in a log entry 701 class LogErrorCase : public BaseCase 702 { 703 public: 704 LogErrorCase (Context& context, 705 const char* name, 706 const char* desc, 707 TestFunctionWrapper errorFunc); 708 virtual ~LogErrorCase (void) {} 709 710 virtual IterateResult iterate (void); 711 712 virtual void expectMessage (GLenum source, GLenum type); 713 714 private: 715 const TestFunctionWrapper m_errorFunc; 716 MessageData m_lastMessage; 717 }; 718 719 LogErrorCase::LogErrorCase (Context& ctx, 720 const char* name, 721 const char* desc, 722 TestFunctionWrapper errorFunc) 723 : BaseCase (ctx, name, desc) 724 , m_errorFunc (errorFunc) 725 { 726 } 727 728 LogErrorCase::IterateResult LogErrorCase::iterate (void) 729 { 730 TCU_CHECK_AND_THROW(NotSupportedError, isKHRDebugSupported(m_context), "GL_KHR_debug is not supported"); 731 732 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 733 tcu::TestLog& log = m_testCtx.getLog(); 734 DebugMessageTestContext context = DebugMessageTestContext(*this, m_context.getRenderContext(), m_context.getContextInfo(), log, m_results, true); 735 GLint numMsg = 0; 736 737 gl.enable(GL_DEBUG_OUTPUT); 738 gl.enable(GL_DEBUG_OUTPUT_SYNCHRONOUS); 739 gl.debugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, DE_NULL, false); // disable all 740 gl.debugMessageControl(GL_DEBUG_SOURCE_API, GL_DEBUG_TYPE_ERROR, GL_DONT_CARE, 0, DE_NULL, true); // enable API errors 741 gl.debugMessageCallback(DE_NULL, DE_NULL); // enable logging 742 gl.getIntegerv(GL_DEBUG_LOGGED_MESSAGES, &numMsg); 743 gl.getDebugMessageLog(numMsg, 0, DE_NULL, DE_NULL, DE_NULL, DE_NULL, DE_NULL, DE_NULL); // clear log 744 745 m_errorFunc.call(context); 746 747 gl.disable(GL_DEBUG_OUTPUT); 748 m_results.setTestContextResult(m_testCtx); 749 750 return STOP; 751 } 752 753 void LogErrorCase::expectMessage (GLenum source, GLenum type) 754 { 755 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 756 int numMsg = 0; 757 TestLog& log = m_testCtx.getLog(); 758 MessageData lastMsg; 759 760 if (source == GL_DONT_CARE || type == GL_DONT_CARE) 761 return; 762 763 gl.getIntegerv(GL_DEBUG_LOGGED_MESSAGES, &numMsg); 764 765 if (numMsg == 0) 766 { 767 if (isDebugContext()) 768 { 769 m_results.addResult(QP_TEST_RESULT_FAIL, "Error was not reported as expected"); 770 log << TestLog::Message << "A message was expected but none was reported (empty message log)" << TestLog::EndMessage; 771 } 772 else 773 { 774 m_results.addResult(QP_TEST_RESULT_QUALITY_WARNING, "Verification accuracy is lacking without a debug context"); 775 log << TestLog::Message << "A message was expected but none was reported (empty message log). Running without a debug context" << TestLog::EndMessage; 776 } 777 return; 778 } 779 780 // There may be messages other than the error we are looking for in the log. 781 // Strictly nothing prevents the implementation from producing more than the 782 // required error from an API call with a defined error. however we assume that 783 // since calls that produce an error should not change GL state the implementation 784 // should have nothing else to report. 785 if (numMsg > 1) 786 gl.getDebugMessageLog(numMsg-1, 0, DE_NULL, DE_NULL, DE_NULL, DE_NULL, DE_NULL, DE_NULL); // Clear all but last 787 788 { 789 int msgLen = 0; 790 gl.getIntegerv(GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH, &msgLen); 791 792 TCU_CHECK_MSG(msgLen >= 0, "Negative message length"); 793 TCU_CHECK_MSG(msgLen < 100000, "Excessively long message"); 794 795 lastMsg.message.resize(msgLen); 796 gl.getDebugMessageLog(1, msgLen, &lastMsg.id.source, &lastMsg.id.type, &lastMsg.id.id, &lastMsg.severity, &msgLen, &lastMsg.message[0]); 797 } 798 799 log << TestLog::Message << "Driver says: \"" << lastMsg.message << "\"" << TestLog::EndMessage; 800 801 verifyMessage(lastMsg, source, type); 802 803 // Reset error so that code afterwards (such as glu::ShaderProgram) doesn't break because of 804 // lingering error state. 805 m_context.getRenderContext().getFunctions().getError(); 806 } 807 808 // Generate errors, verify that calling glGetError afterwards produces desired result 809 class GetErrorCase : public BaseCase 810 { 811 public: 812 GetErrorCase (Context& ctx, 813 const char* name, 814 const char* desc, 815 TestFunctionWrapper errorFunc); 816 virtual ~GetErrorCase (void) {} 817 818 virtual IterateResult iterate (void); 819 820 virtual void expectMessage (GLenum source, GLenum type); 821 virtual void expectError (glw::GLenum error0, glw::GLenum error1); 822 823 private: 824 const TestFunctionWrapper m_errorFunc; 825 }; 826 827 GetErrorCase::GetErrorCase (Context& ctx, 828 const char* name, 829 const char* desc, 830 TestFunctionWrapper errorFunc) 831 : BaseCase (ctx, name, desc) 832 , m_errorFunc (errorFunc) 833 { 834 } 835 836 GetErrorCase::IterateResult GetErrorCase::iterate (void) 837 { 838 tcu::TestLog& log = m_testCtx.getLog(); 839 DebugMessageTestContext context = DebugMessageTestContext(*this, m_context.getRenderContext(), m_context.getContextInfo(), log, m_results, true); 840 841 m_errorFunc.call(context); 842 843 m_results.setTestContextResult(m_testCtx); 844 845 return STOP; 846 } 847 848 void GetErrorCase::expectMessage (GLenum source, GLenum type) 849 { 850 DE_UNREF(source); 851 DE_UNREF(type); 852 DE_FATAL("GetErrorCase cannot handle anything other than error codes"); 853 } 854 855 void GetErrorCase::expectError (glw::GLenum error0, glw::GLenum error1) 856 { 857 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 858 TestLog& log = m_testCtx.getLog(); 859 860 const GLenum result = gl.getError(); 861 862 if (result != error0 && result != error1) 863 { 864 m_results.addResult(QP_TEST_RESULT_FAIL, "Incorrect error was reported"); 865 if (error0 == error1) 866 log << TestLog::Message 867 << glu::getErrorStr(error0) << " was expected but got " 868 << glu::getErrorStr(result) 869 << TestLog::EndMessage; 870 else 871 log << TestLog::Message 872 << glu::getErrorStr(error0) << " or " 873 << glu::getErrorStr(error1) << " was expected but got " 874 << glu::getErrorStr(result) 875 << TestLog::EndMessage; 876 return; 877 } 878 } 879 880 // Generate errors, log the types, disable some, regenerate errors, verify correct errors (not)reported 881 class FilterCase : public BaseCase 882 { 883 public: 884 FilterCase (Context& ctx, 885 const char* name, 886 const char* desc, 887 const vector<TestFunctionWrapper>& errorFuncs); 888 virtual ~FilterCase (void) {} 889 890 virtual IterateResult iterate (void); 891 892 virtual void expectMessage (GLenum source, GLenum type); 893 894 protected: 895 struct MessageFilter 896 { 897 MessageFilter() : source(GL_DONT_CARE), type(GL_DONT_CARE), severity(GL_DONT_CARE), enabled(true) {} // Default to enable all 898 MessageFilter(GLenum source_, GLenum type_, GLenum severity_, const vector<GLuint>& ids_, bool enabled_) : source(source_), type(type_), severity(severity_), ids(ids_), enabled(enabled_) {} 899 900 GLenum source; 901 GLenum type; 902 GLenum severity; 903 vector<GLuint> ids; 904 bool enabled; 905 }; 906 907 virtual void callback (GLenum source, GLenum type, GLuint id, GLenum severity, const string& message); 908 909 vector<MessageData> genMessages (bool uselog, const string& desc); 910 911 vector<MessageFilter> genFilters (const vector<MessageData>& messages, const vector<MessageFilter>& initial, deUint32 seed, int iterations) const; 912 void applyFilters (const vector<MessageFilter>& filters) const; 913 bool isEnabled (const vector<MessageFilter>& filters, const MessageData& message) const; 914 915 void verify (const vector<MessageData>& refMessages, 916 const vector<MessageData>& filteredMessages, 917 const vector<MessageFilter>& filters); 918 919 const vector<TestFunctionWrapper> m_errorFuncs; 920 921 vector<MessageData>* m_currentErrors; 922 }; 923 924 FilterCase::FilterCase (Context& ctx, 925 const char* name, 926 const char* desc, 927 const vector<TestFunctionWrapper>& errorFuncs) 928 : BaseCase (ctx, name, desc) 929 , m_errorFuncs (errorFuncs) 930 , m_currentErrors (DE_NULL) 931 { 932 } 933 934 FilterCase::IterateResult FilterCase::iterate (void) 935 { 936 TCU_CHECK_AND_THROW(NotSupportedError, isKHRDebugSupported(m_context), "GL_KHR_debug is not supported"); 937 938 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 939 940 gl.enable(GL_DEBUG_OUTPUT); 941 gl.enable(GL_DEBUG_OUTPUT_SYNCHRONOUS); 942 gl.debugMessageCallback(callbackHandle, this); 943 944 try 945 { 946 gl.debugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, DE_NULL, true); 947 948 { 949 const vector<MessageData> refMessages = genMessages(true, "Reference run"); 950 const MessageFilter baseFilter (GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, vector<GLuint>(), true); 951 const deUint32 baseSeed = deStringHash(getName()) ^ m_testCtx.getCommandLine().getBaseSeed(); 952 const vector<MessageFilter> filters = genFilters(refMessages, vector<MessageFilter>(1, baseFilter), baseSeed, 4); 953 vector<MessageData> filteredMessages; 954 955 applyFilters(filters); 956 957 // Generate errors 958 filteredMessages = genMessages(false, "Filtered run"); 959 960 // Verify 961 verify(refMessages, filteredMessages, filters); 962 963 if (!isDebugContext() && refMessages.empty()) 964 m_results.addResult(QP_TEST_RESULT_QUALITY_WARNING, "Verification accuracy is lacking without a debug context"); 965 } 966 } 967 catch (...) 968 { 969 gl.disable(GL_DEBUG_OUTPUT); 970 gl.debugMessageCallback(DE_NULL, DE_NULL); 971 throw; 972 } 973 974 gl.disable(GL_DEBUG_OUTPUT); 975 gl.debugMessageCallback(DE_NULL, DE_NULL); 976 m_results.setTestContextResult(m_testCtx); 977 978 return STOP; 979 } 980 981 void FilterCase::expectMessage (GLenum source, GLenum type) 982 { 983 DE_UNREF(source); 984 DE_UNREF(type); 985 } 986 987 void FilterCase::callback (GLenum source, GLenum type, GLuint id, GLenum severity, const string& message) 988 { 989 if (m_currentErrors) 990 m_currentErrors->push_back(MessageData(MessageID(source, type, id), severity, message)); 991 } 992 993 vector<MessageData> FilterCase::genMessages (bool uselog, const string& desc) 994 { 995 tcu::TestLog& log = m_testCtx.getLog(); 996 DebugMessageTestContext context = DebugMessageTestContext(*this, m_context.getRenderContext(), m_context.getContextInfo(), log, m_results, uselog); 997 tcu::ScopedLogSection section (log, "message gen", desc); 998 vector<MessageData> messages; 999 1000 m_currentErrors = &messages; 1001 1002 for (int ndx = 0; ndx < int(m_errorFuncs.size()); ndx++) 1003 m_errorFuncs[ndx].call(context); 1004 1005 m_currentErrors = DE_NULL; 1006 1007 return messages; 1008 } 1009 1010 vector<FilterCase::MessageFilter> FilterCase::genFilters (const vector<MessageData>& messages, const vector<MessageFilter>& initial, deUint32 seed, int iterations) const 1011 { 1012 de::Random rng (seed ^ deInt32Hash(deStringHash(getName()))); 1013 1014 set<MessageID> tempMessageIds; 1015 set<GLenum> tempSources; 1016 set<GLenum> tempTypes; 1017 set<GLenum> tempSeverities; 1018 1019 if (messages.empty()) 1020 return initial; 1021 1022 for (int ndx = 0; ndx < int(messages.size()); ndx++) 1023 { 1024 const MessageData& msg = messages[ndx]; 1025 1026 tempMessageIds.insert(msg.id); 1027 tempSources.insert(msg.id.source); 1028 tempTypes.insert(msg.id.type); 1029 tempSeverities.insert(msg.severity); 1030 } 1031 1032 { 1033 // Fetchable by index 1034 const vector<MessageID> messageIds (tempMessageIds.begin(), tempMessageIds.end()); 1035 const vector<GLenum> sources (tempSources.begin(), tempSources.end()); 1036 const vector<GLenum> types (tempTypes.begin(), tempTypes.end()); 1037 const vector<GLenum> severities (tempSeverities.begin(), tempSeverities.end()); 1038 1039 vector<MessageFilter> filters = initial; 1040 1041 for (int iteration = 0; iteration < iterations; iteration++) 1042 { 1043 switch(rng.getInt(0, 8)) // Distribute so that per-message randomization (the default branch) is prevalent 1044 { 1045 case 0: 1046 { 1047 const GLenum source = sources[rng.getInt(0, int(sources.size()-1))]; 1048 const bool enabled = rng.getBool(); 1049 1050 filters.push_back(MessageFilter(source, GL_DONT_CARE, GL_DONT_CARE, vector<GLuint>(), enabled)); 1051 break; 1052 } 1053 1054 case 1: 1055 { 1056 const GLenum type = types[rng.getUint32()%types.size()]; 1057 const bool enabled = rng.getBool(); 1058 1059 filters.push_back(MessageFilter(GL_DONT_CARE, type, GL_DONT_CARE, vector<GLuint>(), enabled)); 1060 break; 1061 } 1062 1063 case 2: 1064 { 1065 const GLenum severity = severities[rng.getUint32()%severities.size()]; 1066 const bool enabled = rng.getBool(); 1067 1068 filters.push_back(MessageFilter(GL_DONT_CARE, GL_DONT_CARE, severity, vector<GLuint>(), enabled)); 1069 break; 1070 } 1071 1072 default: 1073 { 1074 const int start = rng.getInt(0, int(messageIds.size())); 1075 1076 for (int itr = 0; itr < 4; itr++) 1077 { 1078 const MessageID& id = messageIds[(start+itr)%messageIds.size()]; 1079 const bool enabled = rng.getBool(); 1080 1081 filters.push_back(MessageFilter(id.source, id.type, GL_DONT_CARE, vector<GLuint>(1, id.id), enabled)); 1082 } 1083 } 1084 } 1085 } 1086 1087 return filters; 1088 } 1089 } 1090 1091 void FilterCase::applyFilters (const vector<MessageFilter>& filters) const 1092 { 1093 TestLog& log = m_testCtx.getLog(); 1094 const tcu::ScopedLogSection section (log, "", "Setting message filters"); 1095 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1096 1097 for (size_t filterNdx = 0; filterNdx < filters.size(); filterNdx++) 1098 { 1099 const MessageFilter& filter = filters[filterNdx]; 1100 1101 if (filter.ids.empty()) 1102 log << TestLog::Message << "Setting messages with" 1103 << " source " << glu::getDebugMessageSourceStr(filter.source) 1104 << ", type " << glu::getDebugMessageTypeStr(filter.type) 1105 << " and severity " << glu::getDebugMessageSeverityStr(filter.severity) 1106 << (filter.enabled ? " to enabled" : " to disabled") 1107 << TestLog::EndMessage; 1108 else 1109 { 1110 for (size_t ndx = 0; ndx < filter.ids.size(); ndx++) 1111 log << TestLog::Message << "Setting message (" << MessageID(filter.source, filter.type, filter.ids[ndx]) << ") to " << (filter.enabled ? "enabled" : "disabled") << TestLog::EndMessage; 1112 } 1113 1114 gl.debugMessageControl(filter.source, filter.type, filter.severity, GLsizei(filter.ids.size()), filter.ids.empty() ? DE_NULL : &filter.ids[0], filter.enabled); 1115 } 1116 } 1117 1118 bool FilterCase::isEnabled (const vector<MessageFilter>& filters, const MessageData& message) const 1119 { 1120 bool retval = true; 1121 1122 for (size_t filterNdx = 0; filterNdx < filters.size(); filterNdx++) 1123 { 1124 const MessageFilter& filter = filters[filterNdx]; 1125 1126 if (filter.ids.empty()) 1127 { 1128 if (filter.source != GL_DONT_CARE && filter.source != message.id.source) 1129 continue; 1130 1131 if (filter.type != GL_DONT_CARE && filter.type != message.id.type) 1132 continue; 1133 1134 if (filter.severity != GL_DONT_CARE && filter.severity != message.severity) 1135 continue; 1136 } 1137 else 1138 { 1139 DE_ASSERT(filter.source != GL_DONT_CARE); 1140 DE_ASSERT(filter.type != GL_DONT_CARE); 1141 DE_ASSERT(filter.severity == GL_DONT_CARE); 1142 1143 if (filter.source != message.id.source || filter.type != message.id.type) 1144 continue; 1145 1146 if (!de::contains(filter.ids.begin(), filter.ids.end(), message.id.id)) 1147 continue; 1148 } 1149 1150 retval = filter.enabled; 1151 } 1152 1153 return retval; 1154 } 1155 1156 struct MessageMeta 1157 { 1158 int refCount; 1159 int resCount; 1160 GLenum severity; 1161 1162 MessageMeta (void) : refCount(0), resCount(0), severity(GL_NONE) {} 1163 }; 1164 1165 void FilterCase::verify (const vector<MessageData>& refMessages, const vector<MessageData>& resMessages, const vector<MessageFilter>& filters) 1166 { 1167 TestLog& log = m_testCtx.getLog(); 1168 map<MessageID, MessageMeta> counts; 1169 1170 log << TestLog::Section("verification", "Verifying"); 1171 1172 // Gather message counts & severities, report severity mismatches if found 1173 for (size_t refNdx = 0; refNdx < refMessages.size(); refNdx++) 1174 { 1175 const MessageData& msg = refMessages[refNdx]; 1176 MessageMeta& meta = counts[msg.id]; 1177 1178 if (meta.severity != GL_NONE && meta.severity != msg.severity) 1179 { 1180 log << TestLog::Message << "A message has variable severity between instances: (" << msg.id << ") with severity " 1181 << glu::getDebugMessageSeverityStr(meta.severity) << " and " << glu::getDebugMessageSeverityStr(msg.severity) << TestLog::EndMessage; 1182 m_results.addResult(QP_TEST_RESULT_FAIL, "Message severity changed between instances of the same message"); 1183 } 1184 1185 meta.refCount++; 1186 meta.severity = msg.severity; 1187 } 1188 1189 for (size_t resNdx = 0; resNdx < resMessages.size(); resNdx++) 1190 { 1191 const MessageData& msg = resMessages[resNdx]; 1192 MessageMeta& meta = counts[msg.id]; 1193 1194 if (meta.severity != GL_NONE && meta.severity != msg.severity) 1195 { 1196 log << TestLog::Message << "A message has variable severity between instances: (" << msg.id << ") with severity " 1197 << glu::getDebugMessageSeverityStr(meta.severity) << " and " << glu::getDebugMessageSeverityStr(msg.severity) << TestLog::EndMessage; 1198 m_results.addResult(QP_TEST_RESULT_FAIL, "Message severity changed between instances of the same message"); 1199 } 1200 1201 meta.resCount++; 1202 meta.severity = msg.severity; 1203 } 1204 1205 for (map<MessageID, MessageMeta>::const_iterator itr = counts.begin(); itr != counts.end(); itr++) 1206 { 1207 const MessageID& id = itr->first; 1208 const GLenum severity = itr->second.severity; 1209 1210 const int refCount = itr->second.refCount; 1211 const int resCount = itr->second.resCount; 1212 const bool enabled = isEnabled(filters, MessageData(id, severity, "")); 1213 1214 VerificationResult result = verifyMessageCount(id, severity, refCount, resCount, enabled); 1215 1216 log << TestLog::Message << result.logMessage << TestLog::EndMessage; 1217 1218 if (result.result != QP_TEST_RESULT_PASS) 1219 m_results.addResult(result.result, result.resultMessage); 1220 } 1221 1222 log << TestLog::EndSection; 1223 } 1224 1225 // Filter case that uses debug groups 1226 class GroupFilterCase : public FilterCase 1227 { 1228 public: 1229 GroupFilterCase (Context& ctx, 1230 const char* name, 1231 const char* desc, 1232 const vector<TestFunctionWrapper>& errorFuncs); 1233 virtual ~GroupFilterCase (void) {} 1234 1235 virtual IterateResult iterate (void); 1236 }; 1237 1238 GroupFilterCase::GroupFilterCase (Context& ctx, 1239 const char* name, 1240 const char* desc, 1241 const vector<TestFunctionWrapper>& errorFuncs) 1242 : FilterCase(ctx, name, desc, errorFuncs) 1243 { 1244 } 1245 1246 template<typename T> 1247 vector<T> join(const vector<T>& a, const vector<T>&b) 1248 { 1249 vector<T> retval; 1250 1251 retval.reserve(a.size()+b.size()); 1252 retval.insert(retval.end(), a.begin(), a.end()); 1253 retval.insert(retval.end(), b.begin(), b.end()); 1254 return retval; 1255 } 1256 1257 GroupFilterCase::IterateResult GroupFilterCase::iterate (void) 1258 { 1259 TCU_CHECK_AND_THROW(NotSupportedError, isKHRDebugSupported(m_context), "GL_KHR_debug is not supported"); 1260 1261 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1262 tcu::TestLog& log = m_testCtx.getLog(); 1263 1264 gl.enable(GL_DEBUG_OUTPUT); 1265 gl.enable(GL_DEBUG_OUTPUT_SYNCHRONOUS); 1266 gl.debugMessageCallback(callbackHandle, this); 1267 1268 try 1269 { 1270 gl.debugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, DE_NULL, true); 1271 1272 { 1273 1274 // Generate reference (all errors) 1275 const vector<MessageData> refMessages = genMessages(true, "Reference run"); 1276 const deUint32 baseSeed = deStringHash(getName()) ^ m_testCtx.getCommandLine().getBaseSeed(); 1277 const MessageFilter baseFilter (GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, vector<GLuint>(), true); 1278 const vector<MessageFilter> filter0 = genFilters(refMessages, vector<MessageFilter>(1, baseFilter), baseSeed, 4); 1279 vector<MessageData> resMessages0; 1280 1281 applyFilters(filter0); 1282 1283 resMessages0 = genMessages(false, "Filtered run, default debug group"); 1284 1285 // Initial verification 1286 verify(refMessages, resMessages0, filter0); 1287 1288 { 1289 // Generate reference (filters inherited from parent) 1290 const vector<MessageFilter> filter1base = genFilters(refMessages, vector<MessageFilter>(), baseSeed ^ 0xDEADBEEF, 4); 1291 const vector<MessageFilter> filter1full = join(filter0, filter1base); 1292 tcu::ScopedLogSection section1 (log, "", "Pushing Debug Group"); 1293 vector<MessageData> resMessages1; 1294 1295 gl.pushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 1, -1, "Test Group"); 1296 applyFilters(filter1base); 1297 1298 // First nested verification 1299 resMessages1 = genMessages(false, "Filtered run, pushed one debug group"); 1300 verify(refMessages, resMessages1, filter1full); 1301 1302 { 1303 // Generate reference (filters iherited again) 1304 const vector<MessageFilter> filter2base = genFilters(refMessages, vector<MessageFilter>(), baseSeed ^ 0x43211234, 4); 1305 const vector<MessageFilter> filter2full = join(filter1full, filter2base); 1306 tcu::ScopedLogSection section2 (log, "", "Pushing Debug Group"); 1307 vector<MessageData> resMessages2; 1308 1309 gl.pushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 1, -1, "Nested Test Group"); 1310 applyFilters(filter2base); 1311 1312 // Second nested verification 1313 resMessages2 = genMessages(false, "Filtered run, pushed two debug groups"); 1314 verify(refMessages, resMessages2, filter2full); 1315 1316 gl.popDebugGroup(); 1317 } 1318 1319 // First restore verification 1320 resMessages1 = genMessages(false, "Filtered run, popped second debug group"); 1321 verify(refMessages, resMessages1, filter1full); 1322 1323 gl.popDebugGroup(); 1324 } 1325 1326 // restore verification 1327 resMessages0 = genMessages(false, "Filtered run, popped first debug group"); 1328 verify(refMessages, resMessages0, filter0); 1329 1330 if (!isDebugContext() && refMessages.empty()) 1331 m_results.addResult(QP_TEST_RESULT_QUALITY_WARNING, "Verification accuracy is lacking without a debug context"); 1332 } 1333 } 1334 catch (...) 1335 { 1336 gl.disable(GL_DEBUG_OUTPUT); 1337 gl.debugMessageCallback(DE_NULL, DE_NULL); 1338 throw; 1339 } 1340 1341 gl.disable(GL_DEBUG_OUTPUT); 1342 gl.debugMessageCallback(DE_NULL, DE_NULL); 1343 m_results.setTestContextResult(m_testCtx); 1344 return STOP; 1345 } 1346 1347 // Basic grouping functionality 1348 class GroupCase : public BaseCase 1349 { 1350 public: 1351 GroupCase (Context& ctx, 1352 const char* name, 1353 const char* desc); 1354 virtual ~GroupCase () {} 1355 1356 virtual IterateResult iterate (void); 1357 1358 private: 1359 virtual void callback (GLenum source, GLenum type, GLuint id, GLenum severity, const string& message); 1360 1361 MessageData m_lastMessage; 1362 }; 1363 1364 GroupCase::GroupCase (Context& ctx, 1365 const char* name, 1366 const char* desc) 1367 : BaseCase(ctx, name, desc) 1368 { 1369 } 1370 1371 GroupCase::IterateResult GroupCase::iterate (void) 1372 { 1373 TCU_CHECK_AND_THROW(NotSupportedError, isKHRDebugSupported(m_context), "GL_KHR_debug is not supported"); 1374 1375 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1376 tcu::TestLog& log = m_testCtx.getLog(); 1377 glu::CallLogWrapper wrapper (gl, log); 1378 1379 gl.enable(GL_DEBUG_OUTPUT); 1380 gl.enable(GL_DEBUG_OUTPUT_SYNCHRONOUS); 1381 gl.debugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, DE_NULL, false); // disable all 1382 gl.debugMessageControl(GL_DEBUG_SOURCE_API, GL_DEBUG_TYPE_ERROR, GL_DONT_CARE, 0, DE_NULL, true); // enable API errors 1383 gl.debugMessageControl(GL_DEBUG_SOURCE_APPLICATION, GL_DONT_CARE, GL_DONT_CARE, 0, DE_NULL, true); // enable application messages 1384 gl.debugMessageControl(GL_DEBUG_SOURCE_THIRD_PARTY, GL_DONT_CARE, GL_DONT_CARE, 0, DE_NULL, true); // enable third party messages 1385 gl.debugMessageCallback(callbackHandle, this); 1386 1387 wrapper.enableLogging(true); 1388 wrapper.glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 1234, -1, "Pushed debug stack"); 1389 verifyMessage(m_lastMessage, GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PUSH_GROUP, 1234, GL_DEBUG_SEVERITY_NOTIFICATION); 1390 wrapper.glPopDebugGroup(); 1391 verifyMessage(m_lastMessage, GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_POP_GROUP, 1234, GL_DEBUG_SEVERITY_NOTIFICATION); 1392 1393 wrapper.glPushDebugGroup(GL_DEBUG_SOURCE_THIRD_PARTY, 4231, -1, "Pushed debug stack"); 1394 verifyMessage(m_lastMessage, GL_DEBUG_SOURCE_THIRD_PARTY, GL_DEBUG_TYPE_PUSH_GROUP, 4231, GL_DEBUG_SEVERITY_NOTIFICATION); 1395 wrapper.glPopDebugGroup(); 1396 verifyMessage(m_lastMessage, GL_DEBUG_SOURCE_THIRD_PARTY, GL_DEBUG_TYPE_POP_GROUP, 4231, GL_DEBUG_SEVERITY_NOTIFICATION); 1397 1398 gl.debugMessageCallback(DE_NULL, DE_NULL); 1399 gl.disable(GL_DEBUG_OUTPUT); 1400 1401 m_results.setTestContextResult(m_testCtx); 1402 1403 return STOP; 1404 } 1405 1406 void GroupCase::callback (GLenum source, GLenum type, GLuint id, GLenum severity, const string& message) 1407 { 1408 m_lastMessage = MessageData(MessageID(source, type, id), severity, message); 1409 } 1410 1411 // Asynchronous debug output 1412 class AsyncCase : public BaseCase 1413 { 1414 public: 1415 AsyncCase (Context& ctx, 1416 const char* name, 1417 const char* desc, 1418 const vector<TestFunctionWrapper>& errorFuncs, 1419 bool useCallbacks); 1420 virtual ~AsyncCase (void) {} 1421 1422 virtual IterateResult iterate (void); 1423 1424 virtual void expectMessage (glw::GLenum source, glw::GLenum type); 1425 1426 private: 1427 struct MessageCount 1428 { 1429 int received; 1430 int expected; 1431 1432 MessageCount(void) : received(0), expected(0) {} 1433 }; 1434 typedef map<MessageID, MessageCount> MessageCounter; 1435 1436 enum VerifyState 1437 { 1438 VERIFY_PASS = 0, 1439 VERIFY_MINIMUM, 1440 VERIFY_FAIL, 1441 1442 VERIFY_LAST 1443 }; 1444 1445 virtual void callback (glw::GLenum source, glw::GLenum type, glw::GLuint id, glw::GLenum severity, const std::string& message); 1446 VerifyState verify (bool uselog); 1447 void fetchLogMessages (void); 1448 1449 const vector<TestFunctionWrapper> m_errorFuncs; 1450 const bool m_useCallbacks; 1451 1452 MessageCounter m_counts; 1453 1454 de::Mutex m_mutex; 1455 }; 1456 1457 AsyncCase::AsyncCase (Context& ctx, 1458 const char* name, 1459 const char* desc, 1460 const vector<TestFunctionWrapper>& errorFuncs, 1461 bool useCallbacks) 1462 : BaseCase (ctx, name, desc) 1463 , m_errorFuncs (errorFuncs) 1464 , m_useCallbacks (useCallbacks) 1465 { 1466 } 1467 1468 AsyncCase::IterateResult AsyncCase::iterate (void) 1469 { 1470 TCU_CHECK_AND_THROW(NotSupportedError, isKHRDebugSupported(m_context), "GL_KHR_debug is not supported"); 1471 1472 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1473 tcu::TestLog& log = m_testCtx.getLog(); 1474 DebugMessageTestContext context = DebugMessageTestContext(*this, m_context.getRenderContext(), m_context.getContextInfo(), log, m_results, true); 1475 const int maxWait = 10000; // ms 1476 const int warnWait = 100; 1477 1478 // Clear log from earlier messages 1479 { 1480 GLint numMessages = 0; 1481 gl.getIntegerv(GL_DEBUG_LOGGED_MESSAGES, &numMessages); 1482 gl.getDebugMessageLog(numMessages, 0, DE_NULL, DE_NULL, DE_NULL, DE_NULL, DE_NULL, DE_NULL); 1483 } 1484 1485 gl.enable(GL_DEBUG_OUTPUT); 1486 gl.enable(GL_DEBUG_OUTPUT_SYNCHRONOUS); 1487 gl.debugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, DE_NULL, false); 1488 1489 // Some messages could be dependent on the value of DEBUG_OUTPUT_SYNCHRONOUS so only use API errors which should be generated in all cases 1490 gl.debugMessageControl(GL_DEBUG_SOURCE_API, GL_DEBUG_TYPE_ERROR, GL_DONT_CARE, 0, DE_NULL, true); 1491 1492 if (m_useCallbacks) // will use log otherwise 1493 gl.debugMessageCallback(callbackHandle, this); 1494 else 1495 gl.debugMessageCallback(DE_NULL, DE_NULL); 1496 1497 // Reference run (synchoronous) 1498 { 1499 tcu::ScopedLogSection section(log, "reference run", "Reference run (synchronous)"); 1500 1501 for (int ndx = 0; ndx < int(m_errorFuncs.size()); ndx++) 1502 m_errorFuncs[ndx].call(context); 1503 } 1504 1505 if (m_counts.empty()) 1506 { 1507 if (!isDebugContext()) 1508 m_results.addResult(QP_TEST_RESULT_QUALITY_WARNING, "Need debug context to guarantee implementation behaviour (see command line options)"); 1509 1510 log << TestLog::Message << "Reference run produced no messages, nothing to verify" << TestLog::EndMessage; 1511 1512 gl.debugMessageCallback(DE_NULL, DE_NULL); 1513 gl.disable(GL_DEBUG_OUTPUT); 1514 1515 m_results.setTestContextResult(m_testCtx); 1516 return STOP; 1517 } 1518 1519 for (MessageCounter::iterator itr = m_counts.begin(); itr != m_counts.end(); itr++) 1520 { 1521 itr->second.expected = itr->second.received; 1522 itr->second.received = 0; 1523 } 1524 1525 gl.disable(GL_DEBUG_OUTPUT_SYNCHRONOUS); 1526 1527 // Result run (async) 1528 for (int ndx = 0; ndx < int(m_errorFuncs.size()); ndx++) 1529 m_errorFuncs[ndx].call(context); 1530 1531 // Repatedly try verification, new results may be added to m_receivedMessages at any time 1532 { 1533 tcu::ScopedLogSection section (log, "result run", "Result run (asynchronous)"); 1534 VerifyState lastTimelyState = VERIFY_FAIL; 1535 1536 for (int waited = 0;;) 1537 { 1538 const VerifyState pass = verify(false); 1539 const int wait = de::max(50, waited>>2); 1540 1541 // Pass (possibly due to time limit) 1542 if (pass == VERIFY_PASS || (pass == VERIFY_MINIMUM && waited >= maxWait)) 1543 { 1544 verify(true); // log 1545 1546 // State changed late 1547 if (waited >= warnWait && lastTimelyState != pass) 1548 m_results.addResult(QP_TEST_RESULT_QUALITY_WARNING, "Async messages were returned to application somewhat slowly"); 1549 1550 log << TestLog::Message << "Passed after ~" << waited << "ms of waiting" << TestLog::EndMessage; 1551 break; 1552 } 1553 // fail 1554 else if (waited >= maxWait) 1555 { 1556 verify(true); // log 1557 1558 log << TestLog::Message << "Waited for ~" << waited << "ms without getting all expected messages" << TestLog::EndMessage; 1559 m_results.addResult(QP_TEST_RESULT_FAIL, "Async messages were not returned to application within a reasonable timeframe"); 1560 break; 1561 } 1562 1563 if (waited < warnWait) 1564 lastTimelyState = pass; 1565 1566 deSleep(wait); 1567 waited += wait; 1568 1569 if (!m_useCallbacks) 1570 fetchLogMessages(); 1571 } 1572 } 1573 1574 gl.debugMessageCallback(DE_NULL, DE_NULL); 1575 1576 gl.disable(GL_DEBUG_OUTPUT); 1577 m_results.setTestContextResult(m_testCtx); 1578 1579 return STOP; 1580 } 1581 1582 void AsyncCase::expectMessage (GLenum source, GLenum type) 1583 { 1584 // Good time to clean up the queue as this should be called after most messages are generated 1585 if (!m_useCallbacks) 1586 fetchLogMessages(); 1587 1588 DE_UNREF(source); 1589 DE_UNREF(type); 1590 } 1591 1592 void AsyncCase::callback (GLenum source, GLenum type, GLuint id, GLenum severity, const string& message) 1593 { 1594 DE_ASSERT(m_useCallbacks); 1595 DE_UNREF(severity); 1596 DE_UNREF(message); 1597 1598 de::ScopedLock lock(m_mutex); 1599 1600 m_counts[MessageID(source, type, id)].received++; 1601 } 1602 1603 // Note that we can never guarantee getting all messages back when using logs/fetching as the GL may create more than its log size limit during an arbitrary period of time 1604 void AsyncCase::fetchLogMessages (void) 1605 { 1606 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1607 GLint numMsg = 0; 1608 1609 gl.getIntegerv(GL_DEBUG_LOGGED_MESSAGES, &numMsg); 1610 1611 for(int msgNdx = 0; msgNdx < numMsg; msgNdx++) 1612 { 1613 int msgLen = 0; 1614 MessageData msg; 1615 1616 gl.getIntegerv(GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH, &msgLen); 1617 1618 TCU_CHECK_MSG(msgLen >= 0, "Negative message length"); 1619 TCU_CHECK_MSG(msgLen < 100000, "Excessively long message"); 1620 1621 msg.message.resize(msgLen); 1622 gl.getDebugMessageLog(1, msgLen, &msg.id.source, &msg.id.type, &msg.id.id, &msg.severity, &msgLen, &msg.message[0]); 1623 1624 { 1625 const de::ScopedLock lock(m_mutex); // Don't block during API call 1626 1627 m_counts[MessageID(msg.id)].received++; 1628 } 1629 } 1630 } 1631 1632 AsyncCase::VerifyState AsyncCase::verify (bool uselog) 1633 { 1634 using std::map; 1635 1636 VerifyState retval = VERIFY_PASS; 1637 TestLog& log = m_testCtx.getLog(); 1638 1639 const de::ScopedLock lock(m_mutex); 1640 1641 for (map<MessageID, MessageCount>::const_iterator itr = m_counts.begin(); itr != m_counts.end(); itr++) 1642 { 1643 const MessageID& id = itr->first; 1644 1645 const int refCount = itr->second.expected; 1646 const int resCount = itr->second.received; 1647 const bool enabled = true; 1648 1649 VerificationResult result = verifyMessageCount(id, GL_DONT_CARE, refCount, resCount, enabled); 1650 1651 if (uselog) 1652 log << TestLog::Message << result.logMessage << TestLog::EndMessage; 1653 1654 if (result.result == QP_TEST_RESULT_FAIL) 1655 retval = VERIFY_FAIL; 1656 else if (result.result != QP_TEST_RESULT_PASS && retval == VERIFY_PASS) 1657 retval = VERIFY_MINIMUM; 1658 } 1659 1660 return retval; 1661 } 1662 1663 // Tests debug labels 1664 class LabelCase : public TestCase 1665 { 1666 public: 1667 LabelCase (Context& ctx, 1668 const char* name, 1669 const char* desc, 1670 GLenum identifier); 1671 virtual ~LabelCase (void) {} 1672 1673 virtual IterateResult iterate (void); 1674 1675 private: 1676 GLenum m_identifier; 1677 }; 1678 1679 LabelCase::LabelCase (Context& ctx, 1680 const char* name, 1681 const char* desc, 1682 GLenum identifier) 1683 : TestCase (ctx, name, desc) 1684 , m_identifier (identifier) 1685 { 1686 } 1687 1688 LabelCase::IterateResult LabelCase::iterate (void) 1689 { 1690 TCU_CHECK_AND_THROW(NotSupportedError, isKHRDebugSupported(m_context), "GL_KHR_debug is not supported"); 1691 1692 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1693 const char* const msg = "This is a debug label"; 1694 GLuint object = 0; 1695 int outlen = -1; 1696 char buffer[64]; 1697 1698 switch(m_identifier) 1699 { 1700 case GL_BUFFER: 1701 gl.genBuffers(1, &object); 1702 gl.bindBuffer(GL_ARRAY_BUFFER, object); 1703 gl.bindBuffer(GL_ARRAY_BUFFER, 0); 1704 break; 1705 1706 case GL_SHADER: 1707 object = gl.createShader(GL_FRAGMENT_SHADER); 1708 break; 1709 1710 case GL_PROGRAM: 1711 object = gl.createProgram(); 1712 break; 1713 1714 case GL_QUERY: 1715 gl.genQueries(1, &object); 1716 gl.beginQuery(GL_ANY_SAMPLES_PASSED, object); // Create 1717 gl.endQuery(GL_ANY_SAMPLES_PASSED); // Cleanup 1718 break; 1719 1720 case GL_PROGRAM_PIPELINE: 1721 gl.genProgramPipelines(1, &object); 1722 gl.bindProgramPipeline(object); // Create 1723 gl.bindProgramPipeline(0); // Cleanup 1724 break; 1725 1726 case GL_TRANSFORM_FEEDBACK: 1727 gl.genTransformFeedbacks(1, &object); 1728 gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, object); 1729 gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0); 1730 break; 1731 1732 case GL_SAMPLER: 1733 gl.genSamplers(1, &object); 1734 gl.bindSampler(0, object); 1735 gl.bindSampler(0, 0); 1736 break; 1737 1738 case GL_TEXTURE: 1739 gl.genTextures(1, &object); 1740 gl.bindTexture(GL_TEXTURE_2D, object); 1741 gl.bindTexture(GL_TEXTURE_2D, 0); 1742 break; 1743 1744 case GL_RENDERBUFFER: 1745 gl.genRenderbuffers(1, &object); 1746 gl.bindRenderbuffer(GL_RENDERBUFFER, object); 1747 gl.bindRenderbuffer(GL_RENDERBUFFER, 0); 1748 break; 1749 1750 case GL_FRAMEBUFFER: 1751 gl.genFramebuffers(1, &object); 1752 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, object); 1753 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_context.getRenderContext().getDefaultFramebuffer()); 1754 break; 1755 1756 default: 1757 DE_FATAL("Invalid identifier"); 1758 } 1759 1760 gl.objectLabel(m_identifier, object, -1, msg); 1761 1762 deMemset(buffer, 'X', sizeof(buffer)); 1763 gl.getObjectLabel(m_identifier, object, sizeof(buffer), &outlen, buffer); 1764 1765 if (outlen == 0) 1766 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Failed to query debug label from object"); 1767 else if (deStringEqual(msg, buffer)) 1768 { 1769 m_testCtx.getLog() << TestLog::Message << "Query returned string: \"" << buffer << "\"" << TestLog::EndMessage; 1770 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 1771 } 1772 else 1773 { 1774 buffer[63] = '\0'; // make sure buffer is null terminated before printing 1775 m_testCtx.getLog() << TestLog::Message << "Query returned wrong string: expected \"" << msg << "\" but got \"" << buffer << "\"" << TestLog::EndMessage; 1776 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Query returned wrong label"); 1777 } 1778 1779 switch(m_identifier) 1780 { 1781 case GL_BUFFER: gl.deleteBuffers(1, &object); break; 1782 case GL_SHADER: gl.deleteShader(object); break; 1783 case GL_PROGRAM: gl.deleteProgram(object); break; 1784 case GL_QUERY: gl.deleteQueries(1, &object); break; 1785 case GL_PROGRAM_PIPELINE: gl.deleteProgramPipelines(1, &object); break; 1786 case GL_TRANSFORM_FEEDBACK: gl.deleteTransformFeedbacks(1, &object); break; 1787 case GL_SAMPLER: gl.deleteSamplers(1, &object); break; 1788 case GL_TEXTURE: gl.deleteTextures(1, &object); break; 1789 case GL_RENDERBUFFER: gl.deleteRenderbuffers(1, &object); break; 1790 case GL_FRAMEBUFFER: gl.deleteFramebuffers(1, &object); break; 1791 1792 default: 1793 DE_FATAL("Invalid identifier"); 1794 } 1795 1796 return STOP; 1797 } 1798 1799 1800 DebugMessageTestContext::DebugMessageTestContext (BaseCase& host, 1801 glu::RenderContext& renderCtx, 1802 const glu::ContextInfo& ctxInfo, 1803 tcu::TestLog& log, 1804 tcu::ResultCollector& results, 1805 bool enableLog) 1806 : NegativeTestContext (host, renderCtx, ctxInfo, log, results, enableLog) 1807 , m_debugHost (host) 1808 { 1809 } 1810 1811 DebugMessageTestContext::~DebugMessageTestContext (void) 1812 { 1813 } 1814 1815 void DebugMessageTestContext::expectMessage (GLenum source, GLenum type) 1816 { 1817 m_debugHost.expectMessage(source, type); 1818 } 1819 1820 class SyncLabelCase : public TestCase 1821 { 1822 public: 1823 SyncLabelCase (Context& ctx, const char* name, const char* desc); 1824 virtual IterateResult iterate (void); 1825 }; 1826 1827 SyncLabelCase::SyncLabelCase (Context& ctx, const char* name, const char* desc) 1828 : TestCase(ctx, name, desc) 1829 { 1830 } 1831 1832 SyncLabelCase::IterateResult SyncLabelCase::iterate (void) 1833 { 1834 TCU_CHECK_AND_THROW(NotSupportedError, isKHRDebugSupported(m_context), "GL_KHR_debug is not supported"); 1835 1836 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1837 const char* const msg = "This is a debug label"; 1838 int outlen = -1; 1839 char buffer[64]; 1840 1841 glw::GLsync sync = gl.fenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); 1842 GLU_EXPECT_NO_ERROR(gl.getError(), "fenceSync"); 1843 1844 gl.objectPtrLabel(sync, -1, msg); 1845 1846 deMemset(buffer, 'X', sizeof(buffer)); 1847 gl.getObjectPtrLabel(sync, sizeof(buffer), &outlen, buffer); 1848 1849 if (outlen == 0) 1850 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Failed to query debug label from object"); 1851 else if (deStringEqual(msg, buffer)) 1852 { 1853 m_testCtx.getLog() << TestLog::Message << "Query returned string: \"" << buffer << "\"" << TestLog::EndMessage; 1854 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 1855 } 1856 else 1857 { 1858 buffer[63] = '\0'; // make sure buffer is null terminated before printing 1859 m_testCtx.getLog() << TestLog::Message << "Query returned wrong string: expected \"" << msg << "\" but got \"" << buffer << "\"" << TestLog::EndMessage; 1860 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Query returned wrong label"); 1861 } 1862 1863 gl.deleteSync(sync); 1864 1865 return STOP; 1866 } 1867 1868 class InitialLabelCase : public TestCase 1869 { 1870 public: 1871 InitialLabelCase (Context& ctx, const char* name, const char* desc); 1872 virtual IterateResult iterate (void); 1873 }; 1874 1875 InitialLabelCase::InitialLabelCase (Context& ctx, const char* name, const char* desc) 1876 : TestCase(ctx, name, desc) 1877 { 1878 } 1879 1880 InitialLabelCase::IterateResult InitialLabelCase::iterate (void) 1881 { 1882 TCU_CHECK_AND_THROW(NotSupportedError, isKHRDebugSupported(m_context), "GL_KHR_debug is not supported"); 1883 1884 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1885 tcu::ResultCollector result (m_testCtx.getLog(), " // ERROR: "); 1886 int outlen = -1; 1887 GLuint shader; 1888 glw::GLsync sync; 1889 char buffer[64]; 1890 1891 sync = gl.fenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); 1892 GLS_COLLECT_GL_ERROR(result, gl.getError(), "fenceSync"); 1893 1894 shader = gl.createShader(GL_FRAGMENT_SHADER); 1895 GLS_COLLECT_GL_ERROR(result, gl.getError(), "createShader"); 1896 1897 { 1898 const tcu::ScopedLogSection section(m_testCtx.getLog(), "Shader", "Shader object"); 1899 m_testCtx.getLog() << TestLog::Message << "Querying initial value" << TestLog::EndMessage; 1900 1901 buffer[0] = 'X'; 1902 outlen = -1; 1903 gl.getObjectLabel(GL_SHADER, shader, sizeof(buffer), &outlen, buffer); 1904 GLS_COLLECT_GL_ERROR(result, gl.getError(), "getObjectLabel"); 1905 1906 if (outlen != 0) 1907 result.fail("'length' was not zero, got " + de::toString(outlen)); 1908 else if (buffer[0] != '\0') 1909 result.fail("label was not null terminated"); 1910 else 1911 m_testCtx.getLog() << TestLog::Message << "Got 0-sized null-terminated string." << TestLog::EndMessage; 1912 } 1913 1914 { 1915 const tcu::ScopedLogSection section(m_testCtx.getLog(), "Sync", "Sync object"); 1916 m_testCtx.getLog() << TestLog::Message << "Querying initial value" << TestLog::EndMessage; 1917 1918 buffer[0] = 'X'; 1919 outlen = -1; 1920 gl.getObjectPtrLabel(sync, sizeof(buffer), &outlen, buffer); 1921 GLS_COLLECT_GL_ERROR(result, gl.getError(), "getObjectPtrLabel"); 1922 1923 if (outlen != 0) 1924 result.fail("'length' was not zero, got " + de::toString(outlen)); 1925 else if (buffer[0] != '\0') 1926 result.fail("label was not null terminated"); 1927 else 1928 m_testCtx.getLog() << TestLog::Message << "Got 0-sized null-terminated string." << TestLog::EndMessage; 1929 } 1930 1931 gl.deleteShader(shader); 1932 gl.deleteSync(sync); 1933 1934 result.setTestContextResult(m_testCtx); 1935 return STOP; 1936 } 1937 1938 class ClearLabelCase : public TestCase 1939 { 1940 public: 1941 ClearLabelCase (Context& ctx, const char* name, const char* desc); 1942 virtual IterateResult iterate (void); 1943 }; 1944 1945 ClearLabelCase::ClearLabelCase (Context& ctx, const char* name, const char* desc) 1946 : TestCase(ctx, name, desc) 1947 { 1948 } 1949 1950 ClearLabelCase::IterateResult ClearLabelCase::iterate (void) 1951 { 1952 TCU_CHECK_AND_THROW(NotSupportedError, isKHRDebugSupported(m_context), "GL_KHR_debug is not supported"); 1953 1954 static const struct 1955 { 1956 const char* description; 1957 int length; 1958 } s_clearMethods[] = 1959 { 1960 { " with NULL label and 0 length", 0 }, 1961 { " with NULL label and 1 length", 1 }, 1962 { " with NULL label and negative length", -1 }, 1963 }; 1964 1965 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1966 tcu::ResultCollector result (m_testCtx.getLog(), " // ERROR: "); 1967 const char* const msg = "This is a debug label"; 1968 int outlen = -1; 1969 GLuint shader; 1970 glw::GLsync sync; 1971 char buffer[64]; 1972 1973 sync = gl.fenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); 1974 GLS_COLLECT_GL_ERROR(result, gl.getError(), "fenceSync"); 1975 1976 shader = gl.createShader(GL_FRAGMENT_SHADER); 1977 GLS_COLLECT_GL_ERROR(result, gl.getError(), "createShader"); 1978 1979 { 1980 const tcu::ScopedLogSection section(m_testCtx.getLog(), "Shader", "Shader object"); 1981 1982 for (int methodNdx = 0; methodNdx < DE_LENGTH_OF_ARRAY(s_clearMethods); ++methodNdx) 1983 { 1984 m_testCtx.getLog() << TestLog::Message << "Setting label to string: \"" << msg << "\"" << TestLog::EndMessage; 1985 gl.objectLabel(GL_SHADER, shader, -2, msg); 1986 GLS_COLLECT_GL_ERROR(result, gl.getError(), "objectLabel"); 1987 1988 m_testCtx.getLog() << TestLog::Message << "Clearing label " << s_clearMethods[methodNdx].description << TestLog::EndMessage; 1989 gl.objectLabel(GL_SHADER, shader, s_clearMethods[methodNdx].length, DE_NULL); 1990 GLS_COLLECT_GL_ERROR(result, gl.getError(), "objectLabel"); 1991 1992 m_testCtx.getLog() << TestLog::Message << "Querying label" << TestLog::EndMessage; 1993 buffer[0] = 'X'; 1994 outlen = -1; 1995 gl.getObjectLabel(GL_SHADER, shader, sizeof(buffer), &outlen, buffer); 1996 GLS_COLLECT_GL_ERROR(result, gl.getError(), "getObjectLabel"); 1997 1998 if (outlen != 0) 1999 result.fail("'length' was not zero, got " + de::toString(outlen)); 2000 else if (buffer[0] != '\0') 2001 result.fail("label was not null terminated"); 2002 else 2003 m_testCtx.getLog() << TestLog::Message << "Got 0-sized null-terminated string." << TestLog::EndMessage; 2004 } 2005 } 2006 2007 { 2008 const tcu::ScopedLogSection section(m_testCtx.getLog(), "Sync", "Sync object"); 2009 2010 for (int methodNdx = 0; methodNdx < DE_LENGTH_OF_ARRAY(s_clearMethods); ++methodNdx) 2011 { 2012 m_testCtx.getLog() << TestLog::Message << "Setting label to string: \"" << msg << "\"" << TestLog::EndMessage; 2013 gl.objectPtrLabel(sync, -2, msg); 2014 GLS_COLLECT_GL_ERROR(result, gl.getError(), "objectPtrLabel"); 2015 2016 m_testCtx.getLog() << TestLog::Message << "Clearing label " << s_clearMethods[methodNdx].description << TestLog::EndMessage; 2017 gl.objectPtrLabel(sync, s_clearMethods[methodNdx].length, DE_NULL); 2018 GLS_COLLECT_GL_ERROR(result, gl.getError(), "objectPtrLabel"); 2019 2020 m_testCtx.getLog() << TestLog::Message << "Querying label" << TestLog::EndMessage; 2021 buffer[0] = 'X'; 2022 outlen = -1; 2023 gl.getObjectPtrLabel(sync, sizeof(buffer), &outlen, buffer); 2024 GLS_COLLECT_GL_ERROR(result, gl.getError(), "getObjectPtrLabel"); 2025 2026 if (outlen != 0) 2027 result.fail("'length' was not zero, got " + de::toString(outlen)); 2028 else if (buffer[0] != '\0') 2029 result.fail("label was not null terminated"); 2030 else 2031 m_testCtx.getLog() << TestLog::Message << "Got 0-sized null-terminated string." << TestLog::EndMessage; 2032 } 2033 } 2034 2035 gl.deleteShader(shader); 2036 gl.deleteSync(sync); 2037 2038 result.setTestContextResult(m_testCtx); 2039 return STOP; 2040 } 2041 2042 class SpecifyWithLengthCase : public TestCase 2043 { 2044 public: 2045 SpecifyWithLengthCase (Context& ctx, const char* name, const char* desc); 2046 virtual IterateResult iterate (void); 2047 }; 2048 2049 SpecifyWithLengthCase::SpecifyWithLengthCase (Context& ctx, const char* name, const char* desc) 2050 : TestCase(ctx, name, desc) 2051 { 2052 } 2053 2054 SpecifyWithLengthCase::IterateResult SpecifyWithLengthCase::iterate (void) 2055 { 2056 TCU_CHECK_AND_THROW(NotSupportedError, isKHRDebugSupported(m_context), "GL_KHR_debug is not supported"); 2057 2058 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2059 tcu::ResultCollector result (m_testCtx.getLog(), " // ERROR: "); 2060 const char* const msg = "This is a debug label"; 2061 const char* const clipMsg = "This is a de"; 2062 int outlen = -1; 2063 GLuint shader; 2064 glw::GLsync sync; 2065 char buffer[64]; 2066 2067 sync = gl.fenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); 2068 GLS_COLLECT_GL_ERROR(result, gl.getError(), "fenceSync"); 2069 2070 shader = gl.createShader(GL_FRAGMENT_SHADER); 2071 GLS_COLLECT_GL_ERROR(result, gl.getError(), "createShader"); 2072 2073 { 2074 const tcu::ScopedLogSection section(m_testCtx.getLog(), "Shader", "Shader object"); 2075 2076 m_testCtx.getLog() << TestLog::Message << "Setting label to string: \"" << msg << "\" with length 12" << TestLog::EndMessage; 2077 gl.objectLabel(GL_SHADER, shader, 12, msg); 2078 GLS_COLLECT_GL_ERROR(result, gl.getError(), "objectLabel"); 2079 2080 m_testCtx.getLog() << TestLog::Message << "Querying label" << TestLog::EndMessage; 2081 deMemset(buffer, 'X', sizeof(buffer)); 2082 gl.getObjectLabel(GL_SHADER, shader, sizeof(buffer), &outlen, buffer); 2083 GLS_COLLECT_GL_ERROR(result, gl.getError(), "getObjectLabel"); 2084 2085 if (outlen != 12) 2086 result.fail("'length' was not 12, got " + de::toString(outlen)); 2087 else if (deStringEqual(clipMsg, buffer)) 2088 { 2089 m_testCtx.getLog() << TestLog::Message << "Query returned string: \"" << buffer << "\"" << TestLog::EndMessage; 2090 } 2091 else 2092 { 2093 buffer[63] = '\0'; // make sure buffer is null terminated before printing 2094 m_testCtx.getLog() << TestLog::Message << "Query returned wrong string: expected \"" << clipMsg << "\" but got \"" << buffer << "\"" << TestLog::EndMessage; 2095 result.fail("Query returned wrong label"); 2096 } 2097 } 2098 2099 { 2100 const tcu::ScopedLogSection section(m_testCtx.getLog(), "Sync", "Sync object"); 2101 2102 m_testCtx.getLog() << TestLog::Message << "Setting label to string: \"" << msg << "\" with length 12" << TestLog::EndMessage; 2103 gl.objectPtrLabel(sync, 12, msg); 2104 GLS_COLLECT_GL_ERROR(result, gl.getError(), "objectPtrLabel"); 2105 2106 m_testCtx.getLog() << TestLog::Message << "Querying label" << TestLog::EndMessage; 2107 deMemset(buffer, 'X', sizeof(buffer)); 2108 gl.getObjectPtrLabel(sync, sizeof(buffer), &outlen, buffer); 2109 GLS_COLLECT_GL_ERROR(result, gl.getError(), "getObjectPtrLabel"); 2110 2111 if (outlen != 12) 2112 result.fail("'length' was not 12, got " + de::toString(outlen)); 2113 else if (deStringEqual(clipMsg, buffer)) 2114 { 2115 m_testCtx.getLog() << TestLog::Message << "Query returned string: \"" << buffer << "\"" << TestLog::EndMessage; 2116 } 2117 else 2118 { 2119 buffer[63] = '\0'; // make sure buffer is null terminated before printing 2120 m_testCtx.getLog() << TestLog::Message << "Query returned wrong string: expected \"" << clipMsg << "\" but got \"" << buffer << "\"" << TestLog::EndMessage; 2121 result.fail("Query returned wrong label"); 2122 } 2123 } 2124 2125 { 2126 const tcu::ScopedLogSection section(m_testCtx.getLog(), "ZeroSized", "ZeroSized"); 2127 2128 m_testCtx.getLog() << TestLog::Message << "Setting label to string: \"" << msg << "\" with length 0" << TestLog::EndMessage; 2129 gl.objectLabel(GL_SHADER, shader, 0, msg); 2130 GLS_COLLECT_GL_ERROR(result, gl.getError(), "objectLabel"); 2131 2132 m_testCtx.getLog() << TestLog::Message << "Querying label" << TestLog::EndMessage; 2133 deMemset(buffer, 'X', sizeof(buffer)); 2134 gl.getObjectLabel(GL_SHADER, shader, sizeof(buffer), &outlen, buffer); 2135 GLS_COLLECT_GL_ERROR(result, gl.getError(), "getObjectLabel"); 2136 2137 if (outlen != 0) 2138 result.fail("'length' was not zero, got " + de::toString(outlen)); 2139 else if (buffer[0] != '\0') 2140 result.fail("label was not null terminated"); 2141 else 2142 m_testCtx.getLog() << TestLog::Message << "Got 0-sized null-terminated string." << TestLog::EndMessage; 2143 } 2144 2145 gl.deleteShader(shader); 2146 gl.deleteSync(sync); 2147 2148 result.setTestContextResult(m_testCtx); 2149 return STOP; 2150 } 2151 2152 class BufferLimitedLabelCase : public TestCase 2153 { 2154 public: 2155 BufferLimitedLabelCase (Context& ctx, const char* name, const char* desc); 2156 virtual IterateResult iterate (void); 2157 }; 2158 2159 BufferLimitedLabelCase::BufferLimitedLabelCase (Context& ctx, const char* name, const char* desc) 2160 : TestCase(ctx, name, desc) 2161 { 2162 } 2163 2164 BufferLimitedLabelCase::IterateResult BufferLimitedLabelCase::iterate (void) 2165 { 2166 TCU_CHECK_AND_THROW(NotSupportedError, isKHRDebugSupported(m_context), "GL_KHR_debug is not supported"); 2167 2168 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2169 tcu::ResultCollector result (m_testCtx.getLog(), " // ERROR: "); 2170 const char* const msg = "This is a debug label"; 2171 int outlen = -1; 2172 GLuint shader; 2173 glw::GLsync sync; 2174 char buffer[64]; 2175 2176 sync = gl.fenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); 2177 GLS_COLLECT_GL_ERROR(result, gl.getError(), "fenceSync"); 2178 2179 shader = gl.createShader(GL_FRAGMENT_SHADER); 2180 GLS_COLLECT_GL_ERROR(result, gl.getError(), "createShader"); 2181 2182 { 2183 const tcu::ScopedLogSection superSection(m_testCtx.getLog(), "Shader", "Shader object"); 2184 2185 m_testCtx.getLog() << TestLog::Message << "Setting label to string: \"" << msg << "\"" << TestLog::EndMessage; 2186 gl.objectLabel(GL_SHADER, shader, -1, msg); 2187 GLS_COLLECT_GL_ERROR(result, gl.getError(), "objectLabel"); 2188 2189 { 2190 const tcu::ScopedLogSection section(m_testCtx.getLog(), "QueryAll", "Query All"); 2191 2192 m_testCtx.getLog() << TestLog::Message << "Querying whole label, buffer size = 22" << TestLog::EndMessage; 2193 deMemset(buffer, 'X', sizeof(buffer)); 2194 gl.getObjectLabel(GL_SHADER, shader, 22, &outlen, buffer); 2195 GLS_COLLECT_GL_ERROR(result, gl.getError(), "getObjectLabel"); 2196 2197 if (outlen != 21) 2198 result.fail("'length' was not 21, got " + de::toString(outlen)); 2199 else if (buffer[outlen] != '\0') 2200 result.fail("Buffer was not null-terminated"); 2201 else if (buffer[outlen+1] != 'X') 2202 result.fail("Query wrote over buffer bound"); 2203 else if (!deStringEqual(msg, buffer)) 2204 { 2205 buffer[63] = '\0'; // make sure buffer is null terminated before printing 2206 m_testCtx.getLog() << TestLog::Message << "Query returned string: \"" << buffer << "\"" << TestLog::EndMessage; 2207 result.fail("Query returned wrong label"); 2208 } 2209 else 2210 m_testCtx.getLog() << TestLog::Message << "Query returned string: \"" << buffer << "\"" << TestLog::EndMessage; 2211 } 2212 { 2213 const tcu::ScopedLogSection section(m_testCtx.getLog(), "QueryAllNoSize", "Query all without size"); 2214 2215 m_testCtx.getLog() << TestLog::Message << "Querying whole label, buffer size = 22" << TestLog::EndMessage; 2216 deMemset(buffer, 'X', sizeof(buffer)); 2217 gl.getObjectLabel(GL_SHADER, shader, 22, DE_NULL, buffer); 2218 GLS_COLLECT_GL_ERROR(result, gl.getError(), "getObjectLabel"); 2219 2220 buffer[63] = '\0'; // make sure buffer is null terminated before strlen 2221 2222 if (strlen(buffer) != 21) 2223 result.fail("Buffer length was not 21"); 2224 else if (buffer[21] != '\0') 2225 result.fail("Buffer was not null-terminated"); 2226 else if (buffer[22] != 'X') 2227 result.fail("Query wrote over buffer bound"); 2228 else if (!deStringEqual(msg, buffer)) 2229 { 2230 m_testCtx.getLog() << TestLog::Message << "Query returned string: \"" << buffer << "\"" << TestLog::EndMessage; 2231 result.fail("Query returned wrong label"); 2232 } 2233 else 2234 m_testCtx.getLog() << TestLog::Message << "Query returned string: \"" << buffer << "\"" << TestLog::EndMessage; 2235 } 2236 { 2237 const tcu::ScopedLogSection section(m_testCtx.getLog(), "QueryLess", "Query substring"); 2238 2239 m_testCtx.getLog() << TestLog::Message << "Querying whole label, buffer size = 2" << TestLog::EndMessage; 2240 deMemset(buffer, 'X', sizeof(buffer)); 2241 gl.getObjectLabel(GL_SHADER, shader, 2, &outlen, buffer); 2242 GLS_COLLECT_GL_ERROR(result, gl.getError(), "getObjectLabel"); 2243 2244 if (outlen != 1) 2245 result.fail("'length' was not 1, got " + de::toString(outlen)); 2246 else if (buffer[outlen] != '\0') 2247 result.fail("Buffer was not null-terminated"); 2248 else if (buffer[outlen+1] != 'X') 2249 result.fail("Query wrote over buffer bound"); 2250 else if (!deStringBeginsWith(msg, buffer)) 2251 { 2252 buffer[63] = '\0'; // make sure buffer is null terminated before printing 2253 m_testCtx.getLog() << TestLog::Message << "Query returned string: \"" << buffer << "\"" << TestLog::EndMessage; 2254 result.fail("Query returned wrong label"); 2255 } 2256 else 2257 m_testCtx.getLog() << TestLog::Message << "Query returned string: \"" << buffer << "\"" << TestLog::EndMessage; 2258 } 2259 { 2260 const tcu::ScopedLogSection section(m_testCtx.getLog(), "QueryNone", "Query one character"); 2261 2262 m_testCtx.getLog() << TestLog::Message << "Querying whole label, buffer size = 1" << TestLog::EndMessage; 2263 deMemset(buffer, 'X', sizeof(buffer)); 2264 gl.getObjectLabel(GL_SHADER, shader, 1, &outlen, buffer); 2265 GLS_COLLECT_GL_ERROR(result, gl.getError(), "getObjectLabel"); 2266 2267 if (outlen != 0) 2268 result.fail("'length' was not 0, got " + de::toString(outlen)); 2269 else if (buffer[outlen] != '\0') 2270 result.fail("Buffer was not null-terminated"); 2271 else if (buffer[outlen+1] != 'X') 2272 result.fail("Query wrote over buffer bound"); 2273 else 2274 m_testCtx.getLog() << TestLog::Message << "Query returned zero-sized null-terminated string" << TestLog::EndMessage; 2275 } 2276 } 2277 2278 { 2279 const tcu::ScopedLogSection superSection(m_testCtx.getLog(), "Sync", "Sync object"); 2280 2281 m_testCtx.getLog() << TestLog::Message << "Setting label to string: \"" << msg << "\"" << TestLog::EndMessage; 2282 gl.objectPtrLabel(sync, -1, msg); 2283 GLS_COLLECT_GL_ERROR(result, gl.getError(), "objectPtrLabel"); 2284 2285 { 2286 const tcu::ScopedLogSection section(m_testCtx.getLog(), "QueryAll", "Query All"); 2287 2288 m_testCtx.getLog() << TestLog::Message << "Querying whole label, buffer size = 22" << TestLog::EndMessage; 2289 deMemset(buffer, 'X', sizeof(buffer)); 2290 gl.getObjectPtrLabel(sync, 22, &outlen, buffer); 2291 GLS_COLLECT_GL_ERROR(result, gl.getError(), "getObjectPtrLabel"); 2292 2293 if (outlen != 21) 2294 result.fail("'length' was not 21, got " + de::toString(outlen)); 2295 else if (buffer[outlen] != '\0') 2296 result.fail("Buffer was not null-terminated"); 2297 else if (buffer[outlen+1] != 'X') 2298 result.fail("Query wrote over buffer bound"); 2299 else if (!deStringEqual(msg, buffer)) 2300 { 2301 buffer[63] = '\0'; // make sure buffer is null terminated before printing 2302 m_testCtx.getLog() << TestLog::Message << "Query returned string: \"" << buffer << "\"" << TestLog::EndMessage; 2303 result.fail("Query returned wrong label"); 2304 } 2305 else 2306 m_testCtx.getLog() << TestLog::Message << "Query returned string: \"" << buffer << "\"" << TestLog::EndMessage; 2307 } 2308 { 2309 const tcu::ScopedLogSection section(m_testCtx.getLog(), "QueryAllNoSize", "Query all without size"); 2310 2311 m_testCtx.getLog() << TestLog::Message << "Querying whole label, buffer size = 22" << TestLog::EndMessage; 2312 deMemset(buffer, 'X', sizeof(buffer)); 2313 gl.getObjectPtrLabel(sync, 22, DE_NULL, buffer); 2314 GLS_COLLECT_GL_ERROR(result, gl.getError(), "getObjectPtrLabel"); 2315 2316 buffer[63] = '\0'; // make sure buffer is null terminated before strlen 2317 2318 if (strlen(buffer) != 21) 2319 result.fail("Buffer length was not 21"); 2320 else if (buffer[21] != '\0') 2321 result.fail("Buffer was not null-terminated"); 2322 else if (buffer[22] != 'X') 2323 result.fail("Query wrote over buffer bound"); 2324 else if (!deStringEqual(msg, buffer)) 2325 { 2326 m_testCtx.getLog() << TestLog::Message << "Query returned string: \"" << buffer << "\"" << TestLog::EndMessage; 2327 result.fail("Query returned wrong label"); 2328 } 2329 else 2330 m_testCtx.getLog() << TestLog::Message << "Query returned string: \"" << buffer << "\"" << TestLog::EndMessage; 2331 } 2332 { 2333 const tcu::ScopedLogSection section(m_testCtx.getLog(), "QueryLess", "Query substring"); 2334 2335 m_testCtx.getLog() << TestLog::Message << "Querying whole label, buffer size = 2" << TestLog::EndMessage; 2336 deMemset(buffer, 'X', sizeof(buffer)); 2337 gl.getObjectPtrLabel(sync, 2, &outlen, buffer); 2338 GLS_COLLECT_GL_ERROR(result, gl.getError(), "getObjectPtrLabel"); 2339 2340 if (outlen != 1) 2341 result.fail("'length' was not 1, got " + de::toString(outlen)); 2342 else if (buffer[outlen] != '\0') 2343 result.fail("Buffer was not null-terminated"); 2344 else if (buffer[outlen+1] != 'X') 2345 result.fail("Query wrote over buffer bound"); 2346 else if (!deStringBeginsWith(msg, buffer)) 2347 { 2348 buffer[63] = '\0'; // make sure buffer is null terminated before printing 2349 m_testCtx.getLog() << TestLog::Message << "Query returned string: \"" << buffer << "\"" << TestLog::EndMessage; 2350 result.fail("Query returned wrong label"); 2351 } 2352 else 2353 m_testCtx.getLog() << TestLog::Message << "Query returned string: \"" << buffer << "\"" << TestLog::EndMessage; 2354 } 2355 { 2356 const tcu::ScopedLogSection section(m_testCtx.getLog(), "QueryNone", "Query one character"); 2357 2358 m_testCtx.getLog() << TestLog::Message << "Querying whole label, buffer size = 1" << TestLog::EndMessage; 2359 deMemset(buffer, 'X', sizeof(buffer)); 2360 gl.getObjectPtrLabel(sync, 1, &outlen, buffer); 2361 GLS_COLLECT_GL_ERROR(result, gl.getError(), "getObjectPtrLabel"); 2362 2363 if (outlen != 0) 2364 result.fail("'length' was not 0, got " + de::toString(outlen)); 2365 else if (buffer[outlen] != '\0') 2366 result.fail("Buffer was not null-terminated"); 2367 else if (buffer[outlen+1] != 'X') 2368 result.fail("Query wrote over buffer bound"); 2369 else 2370 m_testCtx.getLog() << TestLog::Message << "Query returned zero-sized null-terminated string" << TestLog::EndMessage; 2371 } 2372 } 2373 2374 gl.deleteShader(shader); 2375 gl.deleteSync(sync); 2376 2377 result.setTestContextResult(m_testCtx); 2378 return STOP; 2379 } 2380 2381 class LabelMaxSizeCase : public TestCase 2382 { 2383 public: 2384 LabelMaxSizeCase (Context& ctx, const char* name, const char* desc); 2385 virtual IterateResult iterate (void); 2386 }; 2387 2388 LabelMaxSizeCase::LabelMaxSizeCase (Context& ctx, const char* name, const char* desc) 2389 : TestCase(ctx, name, desc) 2390 { 2391 } 2392 2393 LabelMaxSizeCase::IterateResult LabelMaxSizeCase::iterate (void) 2394 { 2395 TCU_CHECK_AND_THROW(NotSupportedError, isKHRDebugSupported(m_context), "GL_KHR_debug is not supported"); 2396 2397 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2398 tcu::ResultCollector result (m_testCtx.getLog(), " // ERROR: "); 2399 int maxLabelLen = -1; 2400 int outlen = -1; 2401 GLuint shader; 2402 glw::GLsync sync; 2403 2404 gl.getIntegerv(GL_MAX_LABEL_LENGTH, &maxLabelLen); 2405 GLS_COLLECT_GL_ERROR(result, gl.getError(), "GL_MAX_LABEL_LENGTH"); 2406 2407 m_testCtx.getLog() << TestLog::Message << "GL_MAX_LABEL_LENGTH = " << maxLabelLen << TestLog::EndMessage; 2408 2409 if (maxLabelLen < 256) 2410 throw tcu::TestError("maxLabelLen was less than required (256)"); 2411 if (maxLabelLen > 8192) 2412 { 2413 m_testCtx.getLog() 2414 << TestLog::Message 2415 << "GL_MAX_LABEL_LENGTH is very large. Application having larger labels is unlikely, skipping test." 2416 << TestLog::EndMessage; 2417 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 2418 return STOP; 2419 } 2420 2421 sync = gl.fenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); 2422 GLS_COLLECT_GL_ERROR(result, gl.getError(), "fenceSync"); 2423 2424 shader = gl.createShader(GL_FRAGMENT_SHADER); 2425 GLS_COLLECT_GL_ERROR(result, gl.getError(), "createShader"); 2426 2427 { 2428 const tcu::ScopedLogSection section (m_testCtx.getLog(), "Shader", "Shader object"); 2429 std::vector<char> buffer (maxLabelLen, 'X'); 2430 std::vector<char> readBuffer (maxLabelLen, 'X'); 2431 2432 buffer[maxLabelLen-1] = '\0'; 2433 2434 m_testCtx.getLog() << TestLog::Message << "Setting max length label, with implicit size. (length = -1)" << TestLog::EndMessage; 2435 gl.objectLabel(GL_SHADER, shader, -1, &buffer[0]); 2436 GLS_COLLECT_GL_ERROR(result, gl.getError(), "objectLabel"); 2437 2438 m_testCtx.getLog() << TestLog::Message << "Querying label back" << TestLog::EndMessage; 2439 outlen = -1; 2440 gl.getObjectLabel(GL_SHADER, shader, maxLabelLen, &outlen, &readBuffer[0]); 2441 GLS_COLLECT_GL_ERROR(result, gl.getError(), "getObjectLabel"); 2442 2443 if (outlen != maxLabelLen-1) 2444 result.fail("'length' was not " + de::toString(maxLabelLen-1) + ", got " + de::toString(outlen)); 2445 else if (readBuffer[outlen] != '\0') 2446 result.fail("Buffer was not null-terminated"); 2447 2448 m_testCtx.getLog() << TestLog::Message << "Setting max length label, with explicit size. (length = " << (maxLabelLen-1) << ")" << TestLog::EndMessage; 2449 gl.objectLabel(GL_SHADER, shader, maxLabelLen-1, &buffer[0]); 2450 GLS_COLLECT_GL_ERROR(result, gl.getError(), "objectLabel"); 2451 2452 m_testCtx.getLog() << TestLog::Message << "Querying label back" << TestLog::EndMessage; 2453 outlen = -1; 2454 readBuffer[maxLabelLen-1] = 'X'; 2455 gl.getObjectLabel(GL_SHADER, shader, maxLabelLen, &outlen, &readBuffer[0]); 2456 GLS_COLLECT_GL_ERROR(result, gl.getError(), "getObjectLabel"); 2457 2458 if (outlen != maxLabelLen-1) 2459 result.fail("'length' was not " + de::toString(maxLabelLen-1) + ", got " + de::toString(outlen)); 2460 else if (readBuffer[outlen] != '\0') 2461 result.fail("Buffer was not null-terminated"); 2462 } 2463 2464 { 2465 const tcu::ScopedLogSection section (m_testCtx.getLog(), "Sync", "Sync object"); 2466 std::vector<char> buffer (maxLabelLen, 'X'); 2467 std::vector<char> readBuffer (maxLabelLen, 'X'); 2468 2469 buffer[maxLabelLen-1] = '\0'; 2470 2471 m_testCtx.getLog() << TestLog::Message << "Setting max length label, with implicit size. (length = -1)" << TestLog::EndMessage; 2472 gl.objectPtrLabel(sync, -1, &buffer[0]); 2473 GLS_COLLECT_GL_ERROR(result, gl.getError(), "objectPtrLabel"); 2474 2475 m_testCtx.getLog() << TestLog::Message << "Querying label back" << TestLog::EndMessage; 2476 outlen = -1; 2477 gl.getObjectPtrLabel(sync, maxLabelLen, &outlen, &readBuffer[0]); 2478 GLS_COLLECT_GL_ERROR(result, gl.getError(), "getObjectPtrLabel"); 2479 2480 if (outlen != maxLabelLen-1) 2481 result.fail("'length' was not " + de::toString(maxLabelLen-1) + ", got " + de::toString(outlen)); 2482 else if (readBuffer[outlen] != '\0') 2483 result.fail("Buffer was not null-terminated"); 2484 2485 m_testCtx.getLog() << TestLog::Message << "Setting max length label, with explicit size. (length = " << (maxLabelLen-1) << ")" << TestLog::EndMessage; 2486 gl.objectPtrLabel(sync, maxLabelLen-1, &buffer[0]); 2487 GLS_COLLECT_GL_ERROR(result, gl.getError(), "objectPtrLabel"); 2488 2489 m_testCtx.getLog() << TestLog::Message << "Querying label back" << TestLog::EndMessage; 2490 outlen = -1; 2491 readBuffer[maxLabelLen-1] = 'X'; 2492 gl.getObjectPtrLabel(sync, maxLabelLen, &outlen, &readBuffer[0]); 2493 GLS_COLLECT_GL_ERROR(result, gl.getError(), "getObjectPtrLabel"); 2494 2495 if (outlen != maxLabelLen-1) 2496 result.fail("'length' was not " + de::toString(maxLabelLen-1) + ", got " + de::toString(outlen)); 2497 else if (readBuffer[outlen] != '\0') 2498 result.fail("Buffer was not null-terminated"); 2499 } 2500 2501 gl.deleteShader(shader); 2502 gl.deleteSync(sync); 2503 2504 result.setTestContextResult(m_testCtx); 2505 return STOP; 2506 } 2507 2508 class LabelLengthCase : public TestCase 2509 { 2510 public: 2511 LabelLengthCase (Context& ctx, const char* name, const char* desc); 2512 virtual IterateResult iterate (void); 2513 }; 2514 2515 LabelLengthCase::LabelLengthCase (Context& ctx, const char* name, const char* desc) 2516 : TestCase(ctx, name, desc) 2517 { 2518 } 2519 2520 LabelLengthCase::IterateResult LabelLengthCase::iterate (void) 2521 { 2522 TCU_CHECK_AND_THROW(NotSupportedError, isKHRDebugSupported(m_context), "GL_KHR_debug is not supported"); 2523 2524 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2525 tcu::ResultCollector result (m_testCtx.getLog(), " // ERROR: "); 2526 const char* const msg = "This is a debug label"; 2527 int outlen = -1; 2528 GLuint shader; 2529 glw::GLsync sync; 2530 2531 sync = gl.fenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); 2532 GLS_COLLECT_GL_ERROR(result, gl.getError(), "fenceSync"); 2533 2534 shader = gl.createShader(GL_FRAGMENT_SHADER); 2535 GLS_COLLECT_GL_ERROR(result, gl.getError(), "createShader"); 2536 2537 { 2538 const tcu::ScopedLogSection section(m_testCtx.getLog(), "Shader", "Shader object"); 2539 2540 m_testCtx.getLog() << TestLog::Message << "Querying label length" << TestLog::EndMessage; 2541 outlen = -1; 2542 gl.getObjectLabel(GL_SHADER, shader, 0, &outlen, DE_NULL); 2543 GLS_COLLECT_GL_ERROR(result, gl.getError(), "getObjectLabel"); 2544 2545 if (outlen != 0) 2546 result.fail("'length' was not 0, got " + de::toString(outlen)); 2547 else 2548 m_testCtx.getLog() << TestLog::Message << "Query returned length: " << outlen << TestLog::EndMessage; 2549 2550 m_testCtx.getLog() << TestLog::Message << "Setting label to string: \"" << msg << "\"" << TestLog::EndMessage; 2551 gl.objectLabel(GL_SHADER, shader, -1, msg); 2552 GLS_COLLECT_GL_ERROR(result, gl.getError(), "objectLabel"); 2553 2554 m_testCtx.getLog() << TestLog::Message << "Querying label length" << TestLog::EndMessage; 2555 outlen = -1; 2556 gl.getObjectLabel(GL_SHADER, shader, 0, &outlen, DE_NULL); 2557 GLS_COLLECT_GL_ERROR(result, gl.getError(), "getObjectLabel"); 2558 2559 if (outlen != 21) 2560 result.fail("'length' was not 21, got " + de::toString(outlen)); 2561 else 2562 m_testCtx.getLog() << TestLog::Message << "Query returned length: " << outlen << TestLog::EndMessage; 2563 } 2564 2565 { 2566 const tcu::ScopedLogSection section(m_testCtx.getLog(), "Sync", "Sync object"); 2567 2568 m_testCtx.getLog() << TestLog::Message << "Querying label length" << TestLog::EndMessage; 2569 outlen = -1; 2570 gl.getObjectPtrLabel(sync, 0, &outlen, DE_NULL); 2571 GLS_COLLECT_GL_ERROR(result, gl.getError(), "getObjectPtrLabel"); 2572 2573 if (outlen != 0) 2574 result.fail("'length' was not 0, got " + de::toString(outlen)); 2575 else 2576 m_testCtx.getLog() << TestLog::Message << "Query returned length: " << outlen << TestLog::EndMessage; 2577 2578 m_testCtx.getLog() << TestLog::Message << "Setting label to string: \"" << msg << "\"" << TestLog::EndMessage; 2579 gl.objectPtrLabel(sync, -1, msg); 2580 GLS_COLLECT_GL_ERROR(result, gl.getError(), "objectPtrLabel"); 2581 2582 m_testCtx.getLog() << TestLog::Message << "Querying label length" << TestLog::EndMessage; 2583 outlen = -1; 2584 gl.getObjectPtrLabel(sync, 0, &outlen, DE_NULL); 2585 GLS_COLLECT_GL_ERROR(result, gl.getError(), "getObjectPtrLabel"); 2586 2587 if (outlen != 21) 2588 result.fail("'length' was not 21, got " + de::toString(outlen)); 2589 else 2590 m_testCtx.getLog() << TestLog::Message << "Query returned length: " << outlen << TestLog::EndMessage; 2591 } 2592 2593 gl.deleteShader(shader); 2594 gl.deleteSync(sync); 2595 2596 result.setTestContextResult(m_testCtx); 2597 return STOP; 2598 } 2599 2600 class LimitQueryCase : public TestCase 2601 { 2602 public: 2603 LimitQueryCase (Context& context, 2604 const char* name, 2605 const char* description, 2606 glw::GLenum target, 2607 int limit, 2608 gls::StateQueryUtil::QueryType type); 2609 2610 IterateResult iterate (void); 2611 private: 2612 const gls::StateQueryUtil::QueryType m_type; 2613 const int m_limit; 2614 const glw::GLenum m_target; 2615 }; 2616 2617 LimitQueryCase::LimitQueryCase (Context& context, 2618 const char* name, 2619 const char* description, 2620 glw::GLenum target, 2621 int limit, 2622 gls::StateQueryUtil::QueryType type) 2623 : TestCase (context, name, description) 2624 , m_type (type) 2625 , m_limit (limit) 2626 , m_target (target) 2627 { 2628 } 2629 2630 LimitQueryCase::IterateResult LimitQueryCase::iterate (void) 2631 { 2632 TCU_CHECK_AND_THROW(NotSupportedError, isKHRDebugSupported(m_context), "GL_KHR_debug is not supported"); 2633 2634 glu::CallLogWrapper gl (m_context.getRenderContext().getFunctions(), m_testCtx.getLog()); 2635 tcu::ResultCollector result (m_testCtx.getLog(), " // ERROR: "); 2636 2637 gl.enableLogging(true); 2638 gls::StateQueryUtil::verifyStateIntegerMin(result, gl, m_target, m_limit, m_type); 2639 2640 result.setTestContextResult(m_testCtx); 2641 return STOP; 2642 } 2643 2644 class IsEnabledCase : public TestCase 2645 { 2646 public: 2647 enum InitialValue 2648 { 2649 INITIAL_CTX_IS_DEBUG = 0, 2650 INITIAL_FALSE, 2651 }; 2652 2653 IsEnabledCase (Context& context, 2654 const char* name, 2655 const char* description, 2656 glw::GLenum target, 2657 InitialValue initial, 2658 gls::StateQueryUtil::QueryType type); 2659 2660 IterateResult iterate (void); 2661 private: 2662 const gls::StateQueryUtil::QueryType m_type; 2663 const glw::GLenum m_target; 2664 const InitialValue m_initial; 2665 }; 2666 2667 IsEnabledCase::IsEnabledCase (Context& context, 2668 const char* name, 2669 const char* description, 2670 glw::GLenum target, 2671 InitialValue initial, 2672 gls::StateQueryUtil::QueryType type) 2673 : TestCase (context, name, description) 2674 , m_type (type) 2675 , m_target (target) 2676 , m_initial (initial) 2677 { 2678 } 2679 2680 IsEnabledCase::IterateResult IsEnabledCase::iterate (void) 2681 { 2682 TCU_CHECK_AND_THROW(NotSupportedError, isKHRDebugSupported(m_context), "GL_KHR_debug is not supported"); 2683 2684 glu::CallLogWrapper gl (m_context.getRenderContext().getFunctions(), m_testCtx.getLog()); 2685 tcu::ResultCollector result (m_testCtx.getLog(), " // ERROR: "); 2686 bool initial; 2687 2688 gl.enableLogging(true); 2689 2690 if (m_initial == INITIAL_FALSE) 2691 initial = false; 2692 else 2693 { 2694 DE_ASSERT(m_initial == INITIAL_CTX_IS_DEBUG); 2695 initial = (m_context.getRenderContext().getType().getFlags() & glu::CONTEXT_DEBUG) != 0; 2696 } 2697 2698 // check inital value 2699 gls::StateQueryUtil::verifyStateBoolean(result, gl, m_target, initial, m_type); 2700 2701 // check toggle 2702 2703 gl.glEnable(m_target); 2704 GLS_COLLECT_GL_ERROR(result, gl.glGetError(), "glEnable"); 2705 2706 gls::StateQueryUtil::verifyStateBoolean(result, gl, m_target, true, m_type); 2707 2708 gl.glDisable(m_target); 2709 GLS_COLLECT_GL_ERROR(result, gl.glGetError(), "glDisable"); 2710 2711 gls::StateQueryUtil::verifyStateBoolean(result, gl, m_target, false, m_type); 2712 2713 result.setTestContextResult(m_testCtx); 2714 return STOP; 2715 } 2716 2717 class PositiveIntegerCase : public TestCase 2718 { 2719 public: 2720 PositiveIntegerCase (Context& context, 2721 const char* name, 2722 const char* description, 2723 glw::GLenum target, 2724 gls::StateQueryUtil::QueryType type); 2725 2726 IterateResult iterate (void); 2727 private: 2728 const gls::StateQueryUtil::QueryType m_type; 2729 const glw::GLenum m_target; 2730 }; 2731 2732 PositiveIntegerCase::PositiveIntegerCase (Context& context, 2733 const char* name, 2734 const char* description, 2735 glw::GLenum target, 2736 gls::StateQueryUtil::QueryType type) 2737 : TestCase (context, name, description) 2738 , m_type (type) 2739 , m_target (target) 2740 { 2741 } 2742 2743 PositiveIntegerCase::IterateResult PositiveIntegerCase::iterate (void) 2744 { 2745 TCU_CHECK_AND_THROW(NotSupportedError, isKHRDebugSupported(m_context), "GL_KHR_debug is not supported"); 2746 2747 glu::CallLogWrapper gl (m_context.getRenderContext().getFunctions(), m_testCtx.getLog()); 2748 tcu::ResultCollector result (m_testCtx.getLog(), " // ERROR: "); 2749 2750 gl.enableLogging(true); 2751 gls::StateQueryUtil::verifyStateIntegerMin(result, gl, m_target, 0, m_type); 2752 2753 result.setTestContextResult(m_testCtx); 2754 return STOP; 2755 } 2756 2757 class GroupStackDepthQueryCase : public TestCase 2758 { 2759 public: 2760 GroupStackDepthQueryCase (Context& context, 2761 const char* name, 2762 const char* description, 2763 gls::StateQueryUtil::QueryType type); 2764 2765 IterateResult iterate (void); 2766 private: 2767 const gls::StateQueryUtil::QueryType m_type; 2768 }; 2769 2770 GroupStackDepthQueryCase::GroupStackDepthQueryCase (Context& context, 2771 const char* name, 2772 const char* description, 2773 gls::StateQueryUtil::QueryType type) 2774 : TestCase (context, name, description) 2775 , m_type (type) 2776 { 2777 } 2778 2779 GroupStackDepthQueryCase::IterateResult GroupStackDepthQueryCase::iterate (void) 2780 { 2781 TCU_CHECK_AND_THROW(NotSupportedError, isKHRDebugSupported(m_context), "GL_KHR_debug is not supported"); 2782 2783 glu::CallLogWrapper gl (m_context.getRenderContext().getFunctions(), m_testCtx.getLog()); 2784 tcu::ResultCollector result (m_testCtx.getLog(), " // ERROR: "); 2785 2786 gl.enableLogging(true); 2787 2788 { 2789 const tcu::ScopedLogSection section(m_testCtx.getLog(), "Initial", "Initial"); 2790 2791 gls::StateQueryUtil::verifyStateInteger(result, gl, GL_DEBUG_GROUP_STACK_DEPTH, 1, m_type); 2792 } 2793 2794 { 2795 const tcu::ScopedLogSection section(m_testCtx.getLog(), "Scoped", "Scoped"); 2796 2797 gl.glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 1, -1, "Application group 1"); 2798 gls::StateQueryUtil::verifyStateInteger(result, gl, GL_DEBUG_GROUP_STACK_DEPTH, 2, m_type); 2799 gl.glPopDebugGroup(); 2800 } 2801 2802 result.setTestContextResult(m_testCtx); 2803 return STOP; 2804 } 2805 2806 extern "C" void GLW_APIENTRY dummyCallback(GLenum, GLenum, GLuint, GLenum, GLsizei, const char*, const void*) 2807 { 2808 // dummy 2809 } 2810 2811 class DebugCallbackFunctionCase : public TestCase 2812 { 2813 public: 2814 DebugCallbackFunctionCase (Context& context, const char* name, const char* description); 2815 IterateResult iterate (void); 2816 }; 2817 2818 DebugCallbackFunctionCase::DebugCallbackFunctionCase (Context& context, const char* name, const char* description) 2819 : TestCase (context, name, description) 2820 { 2821 } 2822 2823 DebugCallbackFunctionCase::IterateResult DebugCallbackFunctionCase::iterate (void) 2824 { 2825 using namespace gls::StateQueryUtil; 2826 TCU_CHECK_AND_THROW(NotSupportedError, isKHRDebugSupported(m_context), "GL_KHR_debug is not supported"); 2827 2828 glu::CallLogWrapper gl (m_context.getRenderContext().getFunctions(), m_testCtx.getLog()); 2829 tcu::ResultCollector result (m_testCtx.getLog(), " // ERROR: "); 2830 2831 gl.enableLogging(true); 2832 2833 { 2834 const tcu::ScopedLogSection section(m_testCtx.getLog(), "Initial", "Initial"); 2835 2836 verifyStatePointer(result, gl, GL_DEBUG_CALLBACK_FUNCTION, 0, QUERY_POINTER); 2837 } 2838 2839 { 2840 const tcu::ScopedLogSection section(m_testCtx.getLog(), "Set", "Set"); 2841 2842 gl.glDebugMessageCallback(dummyCallback, DE_NULL); 2843 verifyStatePointer(result, gl, GL_DEBUG_CALLBACK_FUNCTION, (const void*)dummyCallback, QUERY_POINTER); 2844 } 2845 2846 result.setTestContextResult(m_testCtx); 2847 return STOP; 2848 } 2849 2850 class DebugCallbackUserParamCase : public TestCase 2851 { 2852 public: 2853 DebugCallbackUserParamCase (Context& context, const char* name, const char* description); 2854 IterateResult iterate (void); 2855 }; 2856 2857 DebugCallbackUserParamCase::DebugCallbackUserParamCase (Context& context, const char* name, const char* description) 2858 : TestCase (context, name, description) 2859 { 2860 } 2861 2862 DebugCallbackUserParamCase::IterateResult DebugCallbackUserParamCase::iterate (void) 2863 { 2864 using namespace gls::StateQueryUtil; 2865 2866 TCU_CHECK_AND_THROW(NotSupportedError, isKHRDebugSupported(m_context), "GL_KHR_debug is not supported"); 2867 2868 glu::CallLogWrapper gl (m_context.getRenderContext().getFunctions(), m_testCtx.getLog()); 2869 tcu::ResultCollector result (m_testCtx.getLog(), " // ERROR: "); 2870 2871 gl.enableLogging(true); 2872 2873 { 2874 const tcu::ScopedLogSection section(m_testCtx.getLog(), "Initial", "Initial"); 2875 2876 verifyStatePointer(result, gl, GL_DEBUG_CALLBACK_USER_PARAM, 0, QUERY_POINTER); 2877 } 2878 2879 { 2880 const tcu::ScopedLogSection section (m_testCtx.getLog(), "Set", "Set"); 2881 const void* param = (void*)(int*)0x123; 2882 2883 gl.glDebugMessageCallback(dummyCallback, param); 2884 verifyStatePointer(result, gl, GL_DEBUG_CALLBACK_USER_PARAM, param, QUERY_POINTER); 2885 } 2886 2887 result.setTestContextResult(m_testCtx); 2888 return STOP; 2889 } 2890 2891 } // anonymous 2892 2893 DebugTests::DebugTests (Context& context) 2894 : TestCaseGroup(context, "debug", "Debug tests") 2895 { 2896 } 2897 2898 enum CaseType 2899 { 2900 CASETYPE_CALLBACK = 0, 2901 CASETYPE_LOG, 2902 CASETYPE_GETERROR, 2903 2904 CASETYPE_LAST 2905 }; 2906 2907 tcu::TestNode* createCase (CaseType type, Context& ctx, const char* name, const char* desc, TestFunctionWrapper function) 2908 { 2909 switch(type) 2910 { 2911 case CASETYPE_CALLBACK: return new CallbackErrorCase(ctx, name, desc, function); 2912 case CASETYPE_LOG: return new LogErrorCase(ctx, name, desc, function); 2913 case CASETYPE_GETERROR: return new GetErrorCase(ctx, name, desc, function); 2914 2915 default: 2916 DE_FATAL("Invalid type"); 2917 } 2918 2919 return DE_NULL; 2920 } 2921 2922 tcu::TestCaseGroup* createChildCases (CaseType type, Context& ctx, const char* name, const char* desc, const vector<FunctionContainer>& funcs) 2923 { 2924 tcu::TestCaseGroup* host = new tcu::TestCaseGroup(ctx.getTestContext(), name, desc); 2925 2926 for (size_t ndx = 0; ndx < funcs.size(); ndx++) 2927 host->addChild(createCase(type, ctx, funcs[ndx].name, funcs[ndx].desc, funcs[ndx].function)); 2928 2929 return host; 2930 } 2931 2932 vector<FunctionContainer> wrapCoreFunctions (const vector<NegativeTestShared::FunctionContainer>& fns) 2933 { 2934 vector<FunctionContainer> retVal; 2935 2936 retVal.resize(fns.size()); 2937 for (int ndx = 0; ndx < (int)fns.size(); ++ndx) 2938 { 2939 retVal[ndx].function = TestFunctionWrapper(fns[ndx].function); 2940 retVal[ndx].name = fns[ndx].name; 2941 retVal[ndx].desc = fns[ndx].desc; 2942 } 2943 2944 return retVal; 2945 } 2946 2947 void DebugTests::init (void) 2948 { 2949 const vector<FunctionContainer> bufferFuncs = wrapCoreFunctions(NegativeTestShared::getNegativeBufferApiTestFunctions()); 2950 const vector<FunctionContainer> textureFuncs = wrapCoreFunctions(NegativeTestShared::getNegativeTextureApiTestFunctions()); 2951 const vector<FunctionContainer> shaderFuncs = wrapCoreFunctions(NegativeTestShared::getNegativeShaderApiTestFunctions()); 2952 const vector<FunctionContainer> fragmentFuncs = wrapCoreFunctions(NegativeTestShared::getNegativeFragmentApiTestFunctions()); 2953 const vector<FunctionContainer> vaFuncs = wrapCoreFunctions(NegativeTestShared::getNegativeVertexArrayApiTestFunctions()); 2954 const vector<FunctionContainer> stateFuncs = wrapCoreFunctions(NegativeTestShared::getNegativeStateApiTestFunctions()); 2955 const vector<FunctionContainer> tessellationFuncs = wrapCoreFunctions(NegativeTestShared::getNegativeTessellationTestFunctions()); 2956 const vector<FunctionContainer> atomicCounterFuncs = wrapCoreFunctions(NegativeTestShared::getNegativeAtomicCounterTestFunctions()); 2957 const vector<FunctionContainer> imageLoadFuncs = wrapCoreFunctions(NegativeTestShared::getNegativeShaderImageLoadTestFunctions()); 2958 const vector<FunctionContainer> imageStoreFuncs = wrapCoreFunctions(NegativeTestShared::getNegativeShaderImageStoreTestFunctions()); 2959 const vector<FunctionContainer> imageAtomicFuncs = wrapCoreFunctions(NegativeTestShared::getNegativeShaderImageAtomicTestFunctions()); 2960 const vector<FunctionContainer> imageAtomicExchangeFuncs = wrapCoreFunctions(NegativeTestShared::getNegativeShaderImageAtomicExchangeTestFunctions()); 2961 const vector<FunctionContainer> shaderFunctionFuncs = wrapCoreFunctions(NegativeTestShared::getNegativeShaderFunctionTestFunctions()); 2962 const vector<FunctionContainer> shaderDirectiveFuncs = wrapCoreFunctions(NegativeTestShared::getNegativeShaderDirectiveTestFunctions()); 2963 const vector<FunctionContainer> ssboBlockFuncs = wrapCoreFunctions(NegativeTestShared::getNegativeSSBOBlockTestFunctions()); 2964 const vector<FunctionContainer> preciseFuncs = wrapCoreFunctions(NegativeTestShared::getNegativePreciseTestFunctions()); 2965 const vector<FunctionContainer> advancedBlendFuncs = wrapCoreFunctions(NegativeTestShared::getNegativeAdvancedBlendEquationTestFunctions()); 2966 const vector<FunctionContainer> shaderStorageFuncs = wrapCoreFunctions(NegativeTestShared::getNegativeShaderStorageTestFunctions()); 2967 const vector<FunctionContainer> sampleVariablesFuncs = wrapCoreFunctions(NegativeTestShared::getNegativeSampleVariablesTestFunctions()); 2968 const vector<FunctionContainer> computeFuncs = wrapCoreFunctions(NegativeTestShared::getNegativeComputeTestFunctions()); 2969 const vector<FunctionContainer> framebufferFetchFuncs = wrapCoreFunctions(NegativeTestShared::getNegativeShaderFramebufferFetchTestFunctions()); 2970 const vector<FunctionContainer> externalFuncs = getUserMessageFuncs(); 2971 2972 { 2973 using namespace gls::StateQueryUtil; 2974 2975 tcu::TestCaseGroup* const queries = new tcu::TestCaseGroup(m_testCtx, "state_query", "State query"); 2976 2977 static const struct 2978 { 2979 const char* name; 2980 const char* targetName; 2981 glw::GLenum target; 2982 int limit; 2983 } limits[] = 2984 { 2985 { "max_debug_message_length", "MAX_DEBUG_MESSAGE_LENGTH", GL_MAX_DEBUG_MESSAGE_LENGTH, 1 }, 2986 { "max_debug_logged_messages", "MAX_DEBUG_LOGGED_MESSAGES", GL_MAX_DEBUG_LOGGED_MESSAGES, 1 }, 2987 { "max_debug_group_stack_depth", "MAX_DEBUG_GROUP_STACK_DEPTH", GL_MAX_DEBUG_GROUP_STACK_DEPTH, 64 }, 2988 { "max_label_length", "MAX_LABEL_LENGTH", GL_MAX_LABEL_LENGTH, 256 }, 2989 }; 2990 2991 addChild(queries); 2992 2993 #define FOR_ALL_TYPES(X) \ 2994 do \ 2995 { \ 2996 { \ 2997 const char* const postfix = "_getboolean"; \ 2998 const QueryType queryType = QUERY_BOOLEAN; \ 2999 X; \ 3000 } \ 3001 { \ 3002 const char* const postfix = "_getinteger"; \ 3003 const QueryType queryType = QUERY_INTEGER; \ 3004 X; \ 3005 } \ 3006 { \ 3007 const char* const postfix = "_getinteger64"; \ 3008 const QueryType queryType = QUERY_INTEGER64; \ 3009 X; \ 3010 } \ 3011 { \ 3012 const char* const postfix = "_getfloat"; \ 3013 const QueryType queryType = QUERY_FLOAT; \ 3014 X; \ 3015 } \ 3016 } \ 3017 while (deGetFalse()) 3018 #define FOR_ALL_ENABLE_TYPES(X) \ 3019 do \ 3020 { \ 3021 { \ 3022 const char* const postfix = "_isenabled"; \ 3023 const QueryType queryType = QUERY_ISENABLED; \ 3024 X; \ 3025 } \ 3026 FOR_ALL_TYPES(X); \ 3027 } \ 3028 while (deGetFalse()) 3029 3030 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(limits); ++ndx) 3031 { 3032 FOR_ALL_TYPES(queries->addChild(new LimitQueryCase(m_context, 3033 (std::string(limits[ndx].name) + postfix).c_str(), 3034 (std::string("Test ") + limits[ndx].targetName).c_str(), 3035 limits[ndx].target, limits[ndx].limit, queryType))); 3036 } 3037 3038 FOR_ALL_ENABLE_TYPES(queries->addChild(new IsEnabledCase (m_context, (std::string("debug_output") + postfix).c_str(), "Test DEBUG_OUTPUT", GL_DEBUG_OUTPUT, IsEnabledCase::INITIAL_CTX_IS_DEBUG, queryType))); 3039 FOR_ALL_ENABLE_TYPES(queries->addChild(new IsEnabledCase (m_context, (std::string("debug_output_synchronous") + postfix).c_str(), "Test DEBUG_OUTPUT_SYNCHRONOUS", GL_DEBUG_OUTPUT_SYNCHRONOUS, IsEnabledCase::INITIAL_FALSE, queryType))); 3040 3041 FOR_ALL_TYPES(queries->addChild(new PositiveIntegerCase (m_context, (std::string("debug_logged_messages") + postfix).c_str(), "Test DEBUG_LOGGED_MESSAGES", GL_DEBUG_LOGGED_MESSAGES, queryType))); 3042 FOR_ALL_TYPES(queries->addChild(new PositiveIntegerCase (m_context, (std::string("debug_next_logged_message_length") + postfix).c_str(), "Test DEBUG_NEXT_LOGGED_MESSAGE_LENGTH", GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH, queryType))); 3043 FOR_ALL_TYPES(queries->addChild(new GroupStackDepthQueryCase(m_context, (std::string("debug_group_stack_depth") + postfix).c_str(), "Test DEBUG_GROUP_STACK_DEPTH", queryType))); 3044 3045 queries->addChild(new DebugCallbackFunctionCase (m_context, "debug_callback_function_getpointer", "Test DEBUG_CALLBACK_FUNCTION")); 3046 queries->addChild(new DebugCallbackUserParamCase(m_context, "debug_callback_user_param_getpointer", "Test DEBUG_CALLBACK_USER_PARAM")); 3047 3048 #undef FOR_ALL_TYPES 3049 #undef FOR_ALL_ENABLE_TYPES 3050 } 3051 3052 { 3053 tcu::TestCaseGroup* const negative = new tcu::TestCaseGroup(m_testCtx, "negative_coverage", "API error coverage with various reporting methods"); 3054 3055 addChild(negative); 3056 { 3057 tcu::TestCaseGroup* const host = new tcu::TestCaseGroup(m_testCtx, "callbacks", "Reporting of standard API errors via callback"); 3058 3059 negative->addChild(host); 3060 host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "buffer", "Negative Buffer API Cases", bufferFuncs)); 3061 host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "texture", "Negative Texture API Cases", textureFuncs)); 3062 host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "shader", "Negative Shader API Cases", shaderFuncs)); 3063 host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "fragment", "Negative Fragment API Cases", fragmentFuncs)); 3064 host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "vertex_array", "Negative Vertex Array API Cases", vaFuncs)); 3065 host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "state", "Negative GL State API Cases", stateFuncs)); 3066 host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "atomic_counter", "Negative Atomic Counter API Cases", atomicCounterFuncs)); 3067 host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "shader_image_load", "Negative Shader Image Load API Cases", imageLoadFuncs)); 3068 host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "shader_image_store", "Negative Shader Image Store API Cases", imageStoreFuncs)); 3069 host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "shader_image_atomic", "Negative Shader Image Atomic API Cases", imageAtomicFuncs)); 3070 host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "shader_image_exchange", "Negative Shader Image Atomic Exchange API Cases", imageAtomicExchangeFuncs)); 3071 host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "shader_function", "Negative Shader Function Cases", shaderFunctionFuncs)); 3072 host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "shader_directive", "Negative Shader Directive Cases", shaderDirectiveFuncs)); 3073 host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "ssbo_block", "Negative SSBO Block Cases", ssboBlockFuncs)); 3074 host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "precise", "Negative Precise Cases", preciseFuncs)); 3075 host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "advanced_blend", "Negative Advanced Blend Equation Cases", advancedBlendFuncs)); 3076 host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "shader_storage", "Negative Shader Storage Cases", shaderStorageFuncs)); 3077 host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "tessellation", "Negative Tessellation Cases", tessellationFuncs)); 3078 host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "oes_sample_variables", "Negative Sample Variables Cases", sampleVariablesFuncs)); 3079 host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "compute", "Negative Compute Cases", computeFuncs)); 3080 host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "framebuffer_fetch", "Negative Framebuffer Fetch Cases", framebufferFetchFuncs)); 3081 } 3082 3083 { 3084 tcu::TestCaseGroup* const host = new tcu::TestCaseGroup(m_testCtx, "log", "Reporting of standard API errors via log"); 3085 3086 negative->addChild(host); 3087 3088 host->addChild(createChildCases(CASETYPE_LOG, m_context, "buffer", "Negative Buffer API Cases", bufferFuncs)); 3089 host->addChild(createChildCases(CASETYPE_LOG, m_context, "texture", "Negative Texture API Cases", textureFuncs)); 3090 host->addChild(createChildCases(CASETYPE_LOG, m_context, "shader", "Negative Shader API Cases", shaderFuncs)); 3091 host->addChild(createChildCases(CASETYPE_LOG, m_context, "fragment", "Negative Fragment API Cases", fragmentFuncs)); 3092 host->addChild(createChildCases(CASETYPE_LOG, m_context, "vertex_array", "Negative Vertex Array API Cases", vaFuncs)); 3093 host->addChild(createChildCases(CASETYPE_LOG, m_context, "state", "Negative GL State API Cases", stateFuncs)); 3094 host->addChild(createChildCases(CASETYPE_LOG, m_context, "atomic_counter", "Negative Atomic Counter API Cases", atomicCounterFuncs)); 3095 host->addChild(createChildCases(CASETYPE_LOG, m_context, "shader_image_load", "Negative Shader Image Load API Cases", imageLoadFuncs)); 3096 host->addChild(createChildCases(CASETYPE_LOG, m_context, "shader_image_store", "Negative Shader Image Store API Cases", imageStoreFuncs)); 3097 host->addChild(createChildCases(CASETYPE_LOG, m_context, "shader_image_atomic", "Negative Shader Image Atomic API Cases", imageAtomicFuncs)); 3098 host->addChild(createChildCases(CASETYPE_LOG, m_context, "shader_image_exchange", "Negative Shader Image Atomic Exchange API Cases", imageAtomicExchangeFuncs)); 3099 host->addChild(createChildCases(CASETYPE_LOG, m_context, "shader_function", "Negative Shader Function Cases", shaderFunctionFuncs)); 3100 host->addChild(createChildCases(CASETYPE_LOG, m_context, "shader_directive", "Negative Shader Directive Cases", shaderDirectiveFuncs)); 3101 host->addChild(createChildCases(CASETYPE_LOG, m_context, "ssbo_block", "Negative SSBO Block Cases", ssboBlockFuncs)); 3102 host->addChild(createChildCases(CASETYPE_LOG, m_context, "precise", "Negative Precise Cases", preciseFuncs)); 3103 host->addChild(createChildCases(CASETYPE_LOG, m_context, "advanced_blend", "Negative Advanced Blend Equation Cases", advancedBlendFuncs)); 3104 host->addChild(createChildCases(CASETYPE_LOG, m_context, "shader_storage", "Negative Shader Storage Cases", shaderStorageFuncs)); 3105 host->addChild(createChildCases(CASETYPE_LOG, m_context, "tessellation", "Negative Tessellation Cases", tessellationFuncs)); 3106 host->addChild(createChildCases(CASETYPE_LOG, m_context, "oes_sample_variables", "Negative Sample Variables Cases", sampleVariablesFuncs)); 3107 host->addChild(createChildCases(CASETYPE_LOG, m_context, "compute", "Negative Compute Cases", computeFuncs)); 3108 host->addChild(createChildCases(CASETYPE_LOG, m_context, "framebuffer_fetch", "Negative Framebuffer Fetch Cases", framebufferFetchFuncs)); 3109 } 3110 3111 { 3112 tcu::TestCaseGroup* const host = new tcu::TestCaseGroup(m_testCtx, "get_error", "Reporting of standard API errors via glGetError"); 3113 3114 negative->addChild(host); 3115 3116 host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "buffer", "Negative Buffer API Cases", bufferFuncs)); 3117 host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "texture", "Negative Texture API Cases", textureFuncs)); 3118 host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "shader", "Negative Shader API Cases", shaderFuncs)); 3119 host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "fragment", "Negative Fragment API Cases", fragmentFuncs)); 3120 host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "vertex_array", "Negative Vertex Array API Cases", vaFuncs)); 3121 host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "state", "Negative GL State API Cases", stateFuncs)); 3122 host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "atomic_counter", "Negative Atomic Counter API Cases", atomicCounterFuncs)); 3123 host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "shader_image_load", "Negative Shader Image Load API Cases", imageLoadFuncs)); 3124 host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "shader_image_store", "Negative Shader Image Store API Cases", imageStoreFuncs)); 3125 host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "shader_image_atomic", "Negative Shader Image Atomic API Cases", imageAtomicFuncs)); 3126 host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "shader_image_exchange", "Negative Shader Image Atomic Exchange API Cases", imageAtomicExchangeFuncs)); 3127 host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "shader_function", "Negative Shader Function Cases", shaderFunctionFuncs)); 3128 host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "shader_directive", "Negative Shader Directive Cases", shaderDirectiveFuncs)); 3129 host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "ssbo_block", "Negative SSBO Block Cases", ssboBlockFuncs)); 3130 host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "precise", "Negative Precise Cases", preciseFuncs)); 3131 host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "advanced_blend", "Negative Advanced Blend Equation Cases", advancedBlendFuncs)); 3132 host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "shader_storage", "Negative Shader Storage Cases", shaderStorageFuncs)); 3133 host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "tessellation", "Negative Tessellation Cases", tessellationFuncs)); 3134 host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "oes_sample_variables", "Negative Sample Variables Cases", sampleVariablesFuncs)); 3135 host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "compute", "Negative Compute Cases", computeFuncs)); 3136 host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "framebuffer_fetch", "Negative Framebuffer Fetch Cases", framebufferFetchFuncs)); 3137 } 3138 } 3139 3140 { 3141 tcu::TestCaseGroup* const host = createChildCases(CASETYPE_CALLBACK, m_context, "externally_generated", "Externally Generated Messages", externalFuncs); 3142 3143 host->addChild(new GroupCase(m_context, "push_pop_consistency", "Push/pop message generation with full message output checking")); 3144 3145 addChild(host); 3146 } 3147 3148 { 3149 vector<FunctionContainer> containers; 3150 vector<TestFunctionWrapper> allFuncs; 3151 3152 de::Random rng (0x53941903 ^ m_context.getTestContext().getCommandLine().getBaseSeed()); 3153 3154 containers.insert(containers.end(), bufferFuncs.begin(), bufferFuncs.end()); 3155 containers.insert(containers.end(), textureFuncs.begin(), textureFuncs.end()); 3156 containers.insert(containers.end(), externalFuncs.begin(), externalFuncs.end()); 3157 3158 for (size_t ndx = 0; ndx < containers.size(); ndx++) 3159 allFuncs.push_back(containers[ndx].function); 3160 3161 rng.shuffle(allFuncs.begin(), allFuncs.end()); 3162 3163 { 3164 tcu::TestCaseGroup* const filtering = new tcu::TestCaseGroup(m_testCtx, "error_filters", "Filtering of reported errors"); 3165 const int errorFuncsPerCase = 4; 3166 const int maxFilteringCaseCount = 32; 3167 const int caseCount = (int(allFuncs.size()) + errorFuncsPerCase-1) / errorFuncsPerCase; 3168 3169 addChild(filtering); 3170 3171 for (int caseNdx = 0; caseNdx < de::min(caseCount, maxFilteringCaseCount); caseNdx++) 3172 { 3173 const int start = caseNdx*errorFuncsPerCase; 3174 const int end = de::min((caseNdx+1)*errorFuncsPerCase, int(allFuncs.size())); 3175 const string name = "case_" + de::toString(caseNdx); 3176 vector<TestFunctionWrapper> funcs (allFuncs.begin()+start, allFuncs.begin()+end); 3177 3178 // These produce lots of different message types, thus always include at least one when testing filtering 3179 funcs.insert(funcs.end(), externalFuncs[caseNdx%externalFuncs.size()].function); 3180 3181 filtering->addChild(new FilterCase(m_context, name.c_str(), "DebugMessageControl usage", funcs)); 3182 } 3183 } 3184 3185 { 3186 tcu::TestCaseGroup* const groups = new tcu::TestCaseGroup(m_testCtx, "error_groups", "Filtering of reported errors with use of Error Groups"); 3187 const int errorFuncsPerCase = 4; 3188 const int maxFilteringCaseCount = 16; 3189 const int caseCount = (int(allFuncs.size()) + errorFuncsPerCase-1) / errorFuncsPerCase; 3190 3191 addChild(groups); 3192 3193 for (int caseNdx = 0; caseNdx < caseCount && caseNdx < maxFilteringCaseCount; caseNdx++) 3194 { 3195 const int start = caseNdx*errorFuncsPerCase; 3196 const int end = de::min((caseNdx+1)*errorFuncsPerCase, int(allFuncs.size())); 3197 const string name = ("case_" + de::toString(caseNdx)).c_str(); 3198 vector<TestFunctionWrapper> funcs (&allFuncs[0]+start, &allFuncs[0]+end); 3199 3200 // These produce lots of different message types, thus always include at least one when testing filtering 3201 funcs.insert(funcs.end(), externalFuncs[caseNdx%externalFuncs.size()].function); 3202 3203 groups->addChild(new GroupFilterCase(m_context, name.c_str(), "Debug Group usage", funcs)); 3204 } 3205 } 3206 3207 { 3208 tcu::TestCaseGroup* const async = new tcu::TestCaseGroup(m_testCtx, "async", "Asynchronous message generation"); 3209 const int errorFuncsPerCase = 2; 3210 const int maxAsyncCaseCount = 16; 3211 const int caseCount = (int(allFuncs.size()) + errorFuncsPerCase-1) / errorFuncsPerCase; 3212 3213 addChild(async); 3214 3215 for (int caseNdx = 0; caseNdx < caseCount && caseNdx < maxAsyncCaseCount; caseNdx++) 3216 { 3217 const int start = caseNdx*errorFuncsPerCase; 3218 const int end = de::min((caseNdx+1)*errorFuncsPerCase, int(allFuncs.size())); 3219 const string name = ("case_" + de::toString(caseNdx)).c_str(); 3220 vector<TestFunctionWrapper> funcs (&allFuncs[0]+start, &allFuncs[0]+end); 3221 3222 if (caseNdx&0x1) 3223 async->addChild(new AsyncCase(m_context, (name+"_callback").c_str(), "Async message generation", funcs, true)); 3224 else 3225 async->addChild(new AsyncCase(m_context, (name+"_log").c_str(), "Async message generation", funcs, false)); 3226 } 3227 } 3228 } 3229 3230 { 3231 tcu::TestCaseGroup* const labels = new tcu::TestCaseGroup(m_testCtx, "object_labels", "Labeling objects"); 3232 3233 const struct 3234 { 3235 GLenum identifier; 3236 const char* name; 3237 const char* desc; 3238 } cases[] = 3239 { 3240 { GL_BUFFER, "buffer", "Debug label on a buffer object" }, 3241 { GL_SHADER, "shader", "Debug label on a shader object" }, 3242 { GL_PROGRAM, "program", "Debug label on a program object" }, 3243 { GL_QUERY, "query", "Debug label on a query object" }, 3244 { GL_PROGRAM_PIPELINE, "program_pipeline", "Debug label on a program pipeline object" }, 3245 { GL_TRANSFORM_FEEDBACK, "transform_feedback", "Debug label on a transform feedback object" }, 3246 { GL_SAMPLER, "sampler", "Debug label on a sampler object" }, 3247 { GL_TEXTURE, "texture", "Debug label on a texture object" }, 3248 { GL_RENDERBUFFER, "renderbuffer", "Debug label on a renderbuffer object" }, 3249 { GL_FRAMEBUFFER, "framebuffer", "Debug label on a framebuffer object" }, 3250 }; 3251 3252 addChild(labels); 3253 3254 labels->addChild(new InitialLabelCase (m_context, "initial", "Debug label initial value")); 3255 labels->addChild(new ClearLabelCase (m_context, "clearing", "Debug label clearing")); 3256 labels->addChild(new SpecifyWithLengthCase (m_context, "specify_with_length", "Debug label specified with length")); 3257 labels->addChild(new BufferLimitedLabelCase (m_context, "buffer_limited_query", "Debug label query to too short buffer")); 3258 labels->addChild(new LabelMaxSizeCase (m_context, "max_label_length", "Max sized debug label")); 3259 labels->addChild(new LabelLengthCase (m_context, "query_length_only", "Query debug label length")); 3260 3261 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(cases); ndx++) 3262 labels->addChild(new LabelCase(m_context, cases[ndx].name, cases[ndx].desc, cases[ndx].identifier)); 3263 labels->addChild(new SyncLabelCase(m_context, "sync", "Debug label on a sync object")); 3264 } 3265 } 3266 3267 } // Functional 3268 } // gles31 3269 } // deqp 3270