es31fDebugTests.cpp revision e4f5e0c8d113561d40edb72cb5cf3c8b0495518f
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 34#include "deUniquePtr.hpp" 35#include "deRandom.hpp" 36#include "deStringUtil.hpp" 37#include "deSTLUtil.hpp" 38#include "deMutex.hpp" 39#include "deThread.h" 40 41#include "gluRenderContext.hpp" 42#include "gluContextInfo.hpp" 43#include "gluCallLogWrapper.hpp" 44#include "gluStrUtil.hpp" 45 46#include "glwDefs.hpp" 47#include "glwEnums.hpp" 48#include "glwFunctions.hpp" 49 50#include "tes31Context.hpp" 51#include "tcuTestContext.hpp" 52#include "tcuCommandLine.hpp" 53 54namespace deqp 55{ 56namespace gles31 57{ 58namespace Functional 59{ 60namespace 61{ 62using namespace glw; 63 64using std::string; 65using std::vector; 66using std::set; 67using std::map; 68using de::MovePtr; 69 70using tcu::ResultCollector; 71using tcu::TestLog; 72using glu::CallLogWrapper; 73 74using NegativeTestShared::NegativeTestContext; 75 76static const GLenum s_debugTypes[] = 77{ 78 GL_DEBUG_TYPE_ERROR, 79 GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR, 80 GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR, 81 GL_DEBUG_TYPE_PORTABILITY, 82 GL_DEBUG_TYPE_PERFORMANCE, 83 GL_DEBUG_TYPE_OTHER, 84 GL_DEBUG_TYPE_MARKER, 85 GL_DEBUG_TYPE_PUSH_GROUP, 86 GL_DEBUG_TYPE_POP_GROUP, 87}; 88 89static const GLenum s_debugSeverities[] = 90{ 91 GL_DEBUG_SEVERITY_HIGH, 92 GL_DEBUG_SEVERITY_MEDIUM, 93 GL_DEBUG_SEVERITY_LOW, 94 GL_DEBUG_SEVERITY_NOTIFICATION, 95}; 96 97class BaseCase; 98 99class DebugMessageTestContext : public NegativeTestContext 100{ 101public: 102 DebugMessageTestContext (BaseCase& host, 103 glu::RenderContext& renderCtx, 104 const glu::ContextInfo& ctxInfo, 105 tcu::TestLog& log, 106 tcu::ResultCollector& results, 107 bool enableLog); 108 ~DebugMessageTestContext (void); 109 110 void expectMessage (GLenum source, GLenum type); 111 112private: 113 BaseCase& m_debugHost; 114}; 115 116class TestFunctionWrapper 117{ 118public: 119 typedef void (*CoreTestFunc)(NegativeTestContext& ctx); 120 typedef void (*DebugTestFunc)(DebugMessageTestContext& ctx); 121 122 TestFunctionWrapper (void); 123 explicit TestFunctionWrapper (CoreTestFunc func); 124 explicit TestFunctionWrapper (DebugTestFunc func); 125 126 void call (DebugMessageTestContext& ctx) const; 127 128private: 129 enum FuncType 130 { 131 TYPE_NULL = 0, 132 TYPE_CORE, 133 TYPE_DEBUG, 134 }; 135 FuncType m_type; 136 137 union 138 { 139 CoreTestFunc coreFn; 140 DebugTestFunc debugFn; 141 } m_func; 142}; 143 144TestFunctionWrapper::TestFunctionWrapper (void) 145 : m_type(TYPE_NULL) 146{ 147} 148 149TestFunctionWrapper::TestFunctionWrapper (CoreTestFunc func) 150 : m_type(TYPE_CORE) 151{ 152 m_func.coreFn = func; 153} 154 155TestFunctionWrapper::TestFunctionWrapper (DebugTestFunc func) 156 : m_type(TYPE_DEBUG) 157{ 158 m_func.debugFn = func; 159} 160 161void TestFunctionWrapper::call (DebugMessageTestContext& ctx) const 162{ 163 if (m_type == TYPE_CORE) 164 m_func.coreFn(static_cast<NegativeTestContext&>(ctx)); 165 else if (m_type == TYPE_DEBUG) 166 m_func.debugFn(ctx); 167 else 168 DE_ASSERT(false); 169} 170 171void emitMessages(DebugMessageTestContext& ctx, GLenum source) 172{ 173 for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(s_debugTypes); typeNdx++) 174 { 175 for (int severityNdx = 0; severityNdx < DE_LENGTH_OF_ARRAY(s_debugSeverities); severityNdx++) 176 { 177 const GLenum type = s_debugTypes[typeNdx]; 178 const GLenum severity = s_debugSeverities[severityNdx]; 179 const string msg = string("Application generated message with type ") + glu::getDebugMessageTypeName(type) 180 + " and severity " + glu::getDebugMessageSeverityName(severity); 181 182 // Use severity as ID, guaranteed unique 183 ctx.glDebugMessageInsert(source, type, severity, severity, -1, msg.c_str()); 184 ctx.expectMessage(source, type); 185 } 186 } 187} 188 189void application_messages (DebugMessageTestContext& ctx) 190{ 191 ctx.beginSection("Messages with source of GL_DEBUG_SOURCE_APPLICATION"); 192 emitMessages(ctx, GL_DEBUG_SOURCE_APPLICATION); 193 ctx.endSection(); 194} 195 196void thirdparty_messages (DebugMessageTestContext& ctx) 197{ 198 ctx.beginSection("Messages with source of GL_DEBUG_SOURCE_THIRD_PARTY"); 199 emitMessages(ctx, GL_DEBUG_SOURCE_THIRD_PARTY); 200 ctx.endSection(); 201} 202 203void push_pop_messages (DebugMessageTestContext& ctx) 204{ 205 ctx.beginSection("Push/Pop Debug Group"); 206 207 ctx.glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 1, -1, "Application group 1"); 208 ctx.expectMessage(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PUSH_GROUP); 209 ctx.glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 2, -1, "Application group 1-1"); 210 ctx.expectMessage(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PUSH_GROUP); 211 ctx.glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 3, -1, "Application group 1-1-1"); 212 ctx.expectMessage(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PUSH_GROUP); 213 ctx.glPopDebugGroup(); 214 ctx.expectMessage(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_POP_GROUP); 215 ctx.glPopDebugGroup(); 216 ctx.expectMessage(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_POP_GROUP); 217 218 ctx.glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 4, -1, "Application group 1-2"); 219 ctx.expectMessage(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PUSH_GROUP); 220 ctx.glPopDebugGroup(); 221 ctx.expectMessage(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_POP_GROUP); 222 223 ctx.glPushDebugGroup(GL_DEBUG_SOURCE_THIRD_PARTY, 4, -1, "3rd Party group 1-3"); 224 ctx.expectMessage(GL_DEBUG_SOURCE_THIRD_PARTY, GL_DEBUG_TYPE_PUSH_GROUP); 225 ctx.glPopDebugGroup(); 226 ctx.expectMessage(GL_DEBUG_SOURCE_THIRD_PARTY, GL_DEBUG_TYPE_POP_GROUP); 227 ctx.glPopDebugGroup(); 228 ctx.expectMessage(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_POP_GROUP); 229 230 ctx.glPushDebugGroup(GL_DEBUG_SOURCE_THIRD_PARTY, 4, -1, "3rd Party group 2"); 231 ctx.expectMessage(GL_DEBUG_SOURCE_THIRD_PARTY, GL_DEBUG_TYPE_PUSH_GROUP); 232 ctx.glPopDebugGroup(); 233 ctx.expectMessage(GL_DEBUG_SOURCE_THIRD_PARTY, GL_DEBUG_TYPE_POP_GROUP); 234 235 ctx.endSection(); 236} 237 238struct FunctionContainer 239{ 240 TestFunctionWrapper function; 241 const char* name; 242 const char* desc; 243}; 244 245vector<FunctionContainer> getUserMessageFuncs (void) 246{ 247 FunctionContainer funcs[] = 248 { 249 { TestFunctionWrapper(application_messages), "application_messages", "Externally generated messages from the application" }, 250 { TestFunctionWrapper(thirdparty_messages), "third_party_messages", "Externally generated messages from a third party" }, 251 { TestFunctionWrapper(push_pop_messages), "push_pop_stack", "Messages from pushing/popping debug groups" }, 252 }; 253 254 return std::vector<FunctionContainer>(DE_ARRAY_BEGIN(funcs), DE_ARRAY_END(funcs)); 255} 256 257// Data required to uniquely identify a debug message 258struct MessageID 259{ 260 GLenum source; 261 GLenum type; 262 GLuint id; 263 264 MessageID (void) : source(GL_NONE), type(GL_NONE), id(0) {} 265 MessageID (GLenum source_, GLenum type_, GLuint id_) : source(source_), type(type_), id(id_) {} 266 267 bool operator== (const MessageID& rhs) const { return source == rhs.source && type == rhs.type && id == rhs.id;} 268 bool operator!= (const MessageID& rhs) const { return source != rhs.source || type != rhs.type || id != rhs.id;} 269 bool operator< (const MessageID& rhs) const 270 { 271 return source < rhs.source || (source == rhs.source && (type < rhs.type || (type == rhs.type && id < rhs.id))); 272 } 273}; 274 275std::ostream& operator<< (std::ostream& str, const MessageID &id) 276{ 277 return str << glu::getDebugMessageSourceStr(id.source) << ", " << glu::getDebugMessageTypeStr(id.type) << ", " << id.id; 278} 279 280// All info from a single debug message 281struct MessageData 282{ 283 MessageID id; 284 GLenum severity; 285 string message; 286 287 MessageData (void) : id(MessageID()), severity(GL_NONE) {} 288 MessageData (const MessageID& id_, GLenum severity_, const string& message_) : id(id_) , severity(severity_) , message(message_) {} 289}; 290 291extern "C" typedef void GLW_APIENTRY DebugCallbackFunc(GLenum, GLenum, GLuint, GLenum, GLsizei, const char*, void*); 292 293// Base class 294class BaseCase : public NegativeTestShared::ErrorCase 295{ 296public: 297 BaseCase (Context& ctx, 298 const char* name, 299 const char* desc); 300 virtual ~BaseCase (void) {} 301 302 virtual IterateResult iterate (void) = 0; 303 304 virtual void expectMessage (GLenum source, GLenum type); 305 virtual void expectError (GLenum error0, GLenum error1); 306 307protected: 308 struct VerificationResult { 309 const qpTestResult result; 310 const string resultMessage; 311 const string logMessage; 312 313 VerificationResult (qpTestResult result_, const string& resultMessage_, const string& logMessage_) 314 : result(result_), resultMessage(resultMessage_), logMessage(logMessage_) {} 315 }; 316 317 static DebugCallbackFunc callbackHandle; 318 virtual void callback (GLenum source, GLenum type, GLuint id, GLenum severity, const std::string& message); 319 320 321 VerificationResult verifyMessageCount (const MessageID& id, GLenum severity, int refCount, int resCount, bool messageEnabled) const; 322 323 // Verify a single message instance against expected attributes 324 void verifyMessage (const MessageData& message, GLenum source, GLenum type, GLuint id, GLenum severity); 325 void verifyMessage (const MessageData& message, GLenum source, GLenum type); 326 327 bool verifyMessageExists (const MessageData& message, GLenum source, GLenum type); 328 void verifyMessageGroup (const MessageData& message, GLenum source, GLenum type); 329 void verifyMessageString (const MessageData& message); 330 331 bool isDebugContext (void) const; 332 333 tcu::ResultCollector m_results; 334}; 335 336void BaseCase::callbackHandle (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const char* message, void* userParam) 337{ 338 static_cast<BaseCase*>(userParam)->callback(source, type, id, severity, string(message, &message[length])); 339} 340 341BaseCase::BaseCase (Context& ctx, const char* name, const char* desc) 342 : ErrorCase(ctx, name, desc) 343{ 344} 345 346void BaseCase::expectMessage (GLenum source, GLenum type) 347{ 348 DE_UNREF(source); 349 DE_UNREF(type); 350} 351 352void BaseCase::expectError (GLenum error0, GLenum error1) 353{ 354 if (error0 != GL_NO_ERROR || error1 != GL_NO_ERROR) 355 expectMessage(GL_DEBUG_SOURCE_API, GL_DEBUG_TYPE_ERROR); 356 else 357 expectMessage(GL_DONT_CARE, GL_DONT_CARE); 358} 359 360void BaseCase::callback (GLenum source, GLenum type, GLuint id, GLenum severity, const string& message) 361{ 362 DE_UNREF(source); 363 DE_UNREF(type); 364 DE_UNREF(id); 365 DE_UNREF(severity); 366 DE_UNREF(message); 367} 368 369BaseCase::VerificationResult BaseCase::verifyMessageCount (const MessageID& id, GLenum severity, int refCount, int resCount, bool messageEnabled) const 370{ 371 std::stringstream log; 372 373 // This message should not be filtered out 374 if (messageEnabled) 375 { 376 if (resCount != refCount) 377 { 378 /* 379 * Technically nothing requires the implementation to be consistent in terms 380 * of the messages it produces in most situations, allowing the set of messages 381 * produced to vary between executions. This function splits messages 382 * into deterministic and non-deterministic to facilitate handling of such messages. 383 * 384 * Non-deterministic messages that are present in differing quantities in filtered and 385 * unfiltered runs will not fail the test case unless in direct violation of a filter: 386 * the implementation may produce an arbitrary number of such messages when they are 387 * not filtered out and none when they are filtered. 388 * 389 * A list of error source/type combinations with their assumed behaviour and 390 * the rationale for expecting such behaviour follows 391 * 392 * For API/shader messages we assume that the following types are deterministic: 393 * DEBUG_TYPE_ERROR Errors specified by spec and should always be produced 394 * 395 * For API messages the following types are assumed to be non-deterministic 396 * and treated as quality warnings since the underlying reported issue does not change between calls: 397 * DEBUG_TYPE_DEPRECATED_BEHAVIOR Reasonable to only report first instance 398 * DEBUG_TYPE_UNDEFINED_BEHAVIOR Reasonable to only report first instance 399 * DEBUG_TYPE_PORTABILITY Reasonable to only report first instance 400 * 401 * For API messages the following types are assumed to be non-deterministic 402 * and do not affect test results. 403 * DEBUG_TYPE_PERFORMANCE May be tied to arbitrary factors, reasonable to report only first instance 404 * DEBUG_TYPE_OTHER Definition allows arbitrary contents 405 * 406 * For 3rd party and application messages the following types are deterministic: 407 * DEBUG_TYPE_MARKER Only generated by test 408 * DEBUG_TYPE_PUSH_GROUP Only generated by test 409 * DEBUG_TYPE_POP_GROUP Only generated by test 410 * All others Only generated by test 411 * 412 * All messages with category of window system or other are treated as non-deterministic 413 * and do not effect test results since they can be assumed to be outside control of 414 * both the implementation and test case 415 * 416 */ 417 418 const bool isDeterministic = id.source == GL_DEBUG_SOURCE_APPLICATION || 419 id.source == GL_DEBUG_SOURCE_THIRD_PARTY || 420 ((id.source == GL_DEBUG_SOURCE_API || id.source == GL_DEBUG_SOURCE_SHADER_COMPILER) && id.type == GL_DEBUG_TYPE_ERROR); 421 422 const bool canIgnore = id.source == GL_DEBUG_SOURCE_WINDOW_SYSTEM || id.source == GL_DEBUG_SOURCE_OTHER; 423 424 if (isDeterministic) 425 { 426 if (resCount > refCount) 427 { 428 log << "Extra instances of message were found: (" << id << ") with " 429 << glu::getDebugMessageSeverityStr(severity) 430 << " (got " << resCount << ", expected " << refCount << ")"; 431 return VerificationResult(QP_TEST_RESULT_FAIL, "Extra instances of a deterministic message were present", log.str()); 432 } 433 else 434 { 435 log << "Instances of message were missing: (" << id << ") with " 436 << glu::getDebugMessageSeverityStr(severity) 437 << " (got " << resCount << ", expected " << refCount << ")"; 438 return VerificationResult(QP_TEST_RESULT_FAIL, "Message missing", log.str()); 439 } 440 } 441 else if(!canIgnore) 442 { 443 if (resCount > refCount) 444 { 445 log << "Extra instances of message were found but the message is non-deterministic(warning): (" << id << ") with " 446 << glu::getDebugMessageSeverityStr(severity) 447 << " (got " << resCount << ", expected " << refCount << ")"; 448 return VerificationResult(QP_TEST_RESULT_QUALITY_WARNING, "Extra instances of a message were present", log.str()); 449 } 450 else 451 { 452 log << "Instances of message were missing but the message is non-deterministic(warning): (" << id << ") with " 453 << glu::getDebugMessageSeverityStr(severity) 454 << " (got " << resCount << ", expected " << refCount << ")"; 455 return VerificationResult(QP_TEST_RESULT_QUALITY_WARNING, "Message missing", log.str()); 456 } 457 } 458 else 459 { 460 if (resCount > refCount) 461 { 462 log << "Extra instances of message were found but the message is non-deterministic(ignored): (" << id << ") with " 463 << glu::getDebugMessageSeverityStr(severity) 464 << " (got " << resCount << ", expected " << refCount << ")"; 465 return VerificationResult(QP_TEST_RESULT_PASS, "", log.str()); 466 } 467 else 468 { 469 log << "Instances of message were missing but the message is non-deterministic(ignored): (" << id << ") with " 470 << glu::getDebugMessageSeverityStr(severity) 471 << " (got " << resCount << ", expected " << refCount << ")"; 472 return VerificationResult(QP_TEST_RESULT_PASS, "", log.str()); 473 } 474 } 475 } 476 else // Passed as appropriate 477 { 478 log << "Message was found when expected: ("<< id << ") with " 479 << glu::getDebugMessageSeverityStr(severity); 480 return VerificationResult(QP_TEST_RESULT_PASS, "", log.str()); 481 } 482 } 483 // Message should be filtered out 484 else 485 { 486 // Filtered out 487 if (resCount == 0) 488 { 489 log << "Message was excluded correctly: (" << id << ") with " 490 << glu::getDebugMessageSeverityStr(severity); 491 return VerificationResult(QP_TEST_RESULT_PASS, "", log.str()); 492 } 493 // Only present in filtered run (ERROR) 494 else if (resCount > 0 && refCount == 0) 495 { 496 log << "A message was not excluded as it should have been: (" << id << ") with " 497 << glu::getDebugMessageSeverityStr(severity) 498 << ". This message was not present in the reference run"; 499 return VerificationResult(QP_TEST_RESULT_FAIL, "A message was not filtered out", log.str()); 500 } 501 // Present in both runs (ERROR) 502 else 503 { 504 log << "A message was not excluded as it should have been: (" << id << ") with " 505 << glu::getDebugMessageSeverityStr(severity); 506 return VerificationResult(QP_TEST_RESULT_FAIL, "A message was not filtered out", log.str()); 507 } 508 } 509} 510 511// Return true if message needs further verification 512bool BaseCase::verifyMessageExists (const MessageData& message, GLenum source, GLenum type) 513{ 514 TestLog& log = m_testCtx.getLog(); 515 516 if (source == GL_DONT_CARE || type == GL_DONT_CARE) 517 return false; 518 else if (message.id.source == GL_NONE || message.id.type == GL_NONE) 519 { 520 if (isDebugContext()) 521 { 522 m_results.addResult(QP_TEST_RESULT_FAIL, "Message was not reported as expected"); 523 log << TestLog::Message << "A message was expected but none was reported" << TestLog::EndMessage; 524 } 525 else 526 { 527 m_results.addResult(QP_TEST_RESULT_QUALITY_WARNING, "Verification accuracy is lacking without a debug context"); 528 log << TestLog::Message << "A message was expected but none was reported. Running without a debug context" << TestLog::EndMessage; 529 } 530 return false; 531 } 532 else 533 return true; 534} 535 536void BaseCase::verifyMessageGroup (const MessageData& message, GLenum source, GLenum type) 537{ 538 TestLog& log = m_testCtx.getLog(); 539 540 if (message.id.source != source) 541 { 542 m_results.addResult(QP_TEST_RESULT_FAIL, "Incorrect message source"); 543 log << TestLog::Message << "Message source was " << glu::getDebugMessageSourceStr(message.id.source) 544 << " when it should have been " << glu::getDebugMessageSourceStr(source) << TestLog::EndMessage; 545 } 546 547 if (message.id.type != type) 548 { 549 m_results.addResult(QP_TEST_RESULT_FAIL, "Incorrect message type"); 550 log << TestLog::Message << "Message type was " << glu::getDebugMessageTypeStr(message.id.type) 551 << " when it should have been " << glu::getDebugMessageTypeStr(type) << TestLog::EndMessage; 552 } 553} 554 555void BaseCase::verifyMessageString (const MessageData& message) 556{ 557 TestLog& log = m_testCtx.getLog(); 558 559 log << TestLog::Message << "Driver says: \"" << message.message << "\"" << TestLog::EndMessage; 560 561 if (message.message.empty()) 562 { 563 m_results.addResult(QP_TEST_RESULT_QUALITY_WARNING, "Empty message"); 564 log << TestLog::Message << "Message message was empty" << TestLog::EndMessage; 565 } 566} 567 568void BaseCase::verifyMessage (const MessageData& message, GLenum source, GLenum type) 569{ 570 if (verifyMessageExists(message, source, type)) 571 { 572 verifyMessageString(message); 573 verifyMessageGroup(message, source, type); 574 } 575} 576 577void BaseCase::verifyMessage (const MessageData& message, GLenum source, GLenum type, GLuint id, GLenum severity) 578{ 579 TestLog& log = m_testCtx.getLog(); 580 581 if (verifyMessageExists(message, source, type)) 582 { 583 verifyMessageString(message); 584 verifyMessageGroup(message, source, type); 585 586 if (message.id.id != id) 587 { 588 m_results.addResult(QP_TEST_RESULT_FAIL, "Incorrect message id"); 589 log << TestLog::Message << "Message id was " << message.id.id 590 << " when it should have been " << id << TestLog::EndMessage; 591 } 592 593 if (message.severity != severity) 594 { 595 m_results.addResult(QP_TEST_RESULT_FAIL, "Incorrect message severity"); 596 log << TestLog::Message << "Message severity was " << glu::getDebugMessageSeverityStr(message.severity) 597 << " when it should have been " << glu::getDebugMessageSeverityStr(severity) << TestLog::EndMessage; 598 } 599 } 600} 601 602bool BaseCase::isDebugContext (void) const 603{ 604 return (m_context.getRenderContext().getType().getFlags() & glu::CONTEXT_DEBUG) != 0; 605} 606 607// Generate errors, verify that each error results in a callback call 608class CallbackErrorCase : public BaseCase 609{ 610public: 611 CallbackErrorCase (Context& ctx, 612 const char* name, 613 const char* desc, 614 TestFunctionWrapper errorFunc); 615 virtual ~CallbackErrorCase (void) {} 616 617 virtual IterateResult iterate (void); 618 619 virtual void expectMessage (GLenum source, GLenum type); 620 621private: 622 virtual void callback (GLenum source, GLenum type, GLuint id, GLenum severity, const string& message); 623 624 const TestFunctionWrapper m_errorFunc; 625 MessageData m_lastMessage; 626}; 627 628CallbackErrorCase::CallbackErrorCase (Context& ctx, 629 const char* name, 630 const char* desc, 631 TestFunctionWrapper errorFunc) 632 : BaseCase (ctx, name, desc) 633 , m_errorFunc (errorFunc) 634{ 635} 636 637CallbackErrorCase::IterateResult CallbackErrorCase::iterate (void) 638{ 639 TCU_CHECK_AND_THROW(NotSupportedError, m_context.getContextInfo().isExtensionSupported("GL_KHR_debug"), "GL_KHR_debug is not supported"); 640 641 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 642 tcu::TestLog& log = m_testCtx.getLog(); 643 DebugMessageTestContext context = DebugMessageTestContext(*this, m_context.getRenderContext(), m_context.getContextInfo(), log, m_results, true); 644 645 gl.enable(GL_DEBUG_OUTPUT); 646 gl.enable(GL_DEBUG_OUTPUT_SYNCHRONOUS); 647 gl.debugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, DE_NULL, false); // disable all 648 gl.debugMessageControl(GL_DEBUG_SOURCE_API, GL_DEBUG_TYPE_ERROR, GL_DONT_CARE, 0, DE_NULL, true); // enable API errors 649 gl.debugMessageControl(GL_DEBUG_SOURCE_APPLICATION, GL_DONT_CARE, GL_DONT_CARE, 0, DE_NULL, true); // enable application messages 650 gl.debugMessageControl(GL_DEBUG_SOURCE_THIRD_PARTY, GL_DONT_CARE, GL_DONT_CARE, 0, DE_NULL, true); // enable third party messages 651 gl.debugMessageCallback(callbackHandle, this); 652 653 m_errorFunc.call(context); 654 655 gl.debugMessageCallback(DE_NULL, DE_NULL); 656 gl.disable(GL_DEBUG_OUTPUT); 657 658 m_results.setTestContextResult(m_testCtx); 659 660 return STOP; 661} 662 663void CallbackErrorCase::expectMessage (GLenum source, GLenum type) 664{ 665 verifyMessage(m_lastMessage, source, type); 666 m_lastMessage = MessageData(); 667} 668 669void CallbackErrorCase::callback (GLenum source, GLenum type, GLuint id, GLenum severity, const string& message) 670{ 671 m_lastMessage = MessageData(MessageID(source, type, id), severity, message); 672} 673 674// Generate errors, verify that each error results in a log entry 675class LogErrorCase : public BaseCase 676{ 677public: 678 LogErrorCase (Context& context, 679 const char* name, 680 const char* desc, 681 TestFunctionWrapper errorFunc); 682 virtual ~LogErrorCase (void) {} 683 684 virtual IterateResult iterate (void); 685 686 virtual void expectMessage (GLenum source, GLenum type); 687 688private: 689 const TestFunctionWrapper m_errorFunc; 690 MessageData m_lastMessage; 691}; 692 693LogErrorCase::LogErrorCase (Context& ctx, 694 const char* name, 695 const char* desc, 696 TestFunctionWrapper errorFunc) 697 : BaseCase (ctx, name, desc) 698 , m_errorFunc (errorFunc) 699{ 700} 701 702LogErrorCase::IterateResult LogErrorCase::iterate (void) 703{ 704 TCU_CHECK_AND_THROW(NotSupportedError, m_context.getContextInfo().isExtensionSupported("GL_KHR_debug"), "GL_KHR_debug is not supported"); 705 706 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 707 tcu::TestLog& log = m_testCtx.getLog(); 708 DebugMessageTestContext context = DebugMessageTestContext(*this, m_context.getRenderContext(), m_context.getContextInfo(), log, m_results, true); 709 GLint numMsg = 0; 710 711 gl.enable(GL_DEBUG_OUTPUT); 712 gl.enable(GL_DEBUG_OUTPUT_SYNCHRONOUS); 713 gl.debugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, DE_NULL, false); // disable all 714 gl.debugMessageControl(GL_DEBUG_SOURCE_API, GL_DEBUG_TYPE_ERROR, GL_DONT_CARE, 0, DE_NULL, true); // enable API errors 715 gl.debugMessageCallback(DE_NULL, DE_NULL); // enable logging 716 gl.getIntegerv(GL_DEBUG_LOGGED_MESSAGES, &numMsg); 717 gl.getDebugMessageLog(numMsg, 0, DE_NULL, DE_NULL, DE_NULL, DE_NULL, DE_NULL, DE_NULL); // clear log 718 719 m_errorFunc.call(context); 720 721 gl.disable(GL_DEBUG_OUTPUT); 722 m_results.setTestContextResult(m_testCtx); 723 724 return STOP; 725} 726 727void LogErrorCase::expectMessage (GLenum source, GLenum type) 728{ 729 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 730 int numMsg = 0; 731 TestLog& log = m_testCtx.getLog(); 732 MessageData lastMsg; 733 734 if (source == GL_DONT_CARE || type == GL_DONT_CARE) 735 return; 736 737 gl.getIntegerv(GL_DEBUG_LOGGED_MESSAGES, &numMsg); 738 739 if (numMsg == 0) 740 { 741 if (isDebugContext()) 742 { 743 m_results.addResult(QP_TEST_RESULT_FAIL, "Error was not reported as expected"); 744 log << TestLog::Message << "A message was expected but none was reported (empty message log)" << TestLog::EndMessage; 745 } 746 else 747 { 748 m_results.addResult(QP_TEST_RESULT_QUALITY_WARNING, "Verification accuracy is lacking without a debug context"); 749 log << TestLog::Message << "A message was expected but none was reported (empty message log). Running without a debug context" << TestLog::EndMessage; 750 } 751 return; 752 } 753 754 // There may be messages other than the error we are looking for in the log. 755 // Strictly nothing prevents the implementation from producing more than the 756 // required error from an API call with a defined error. however we assume that 757 // since calls that produce an error should not change GL state the implementation 758 // should have nothing else to report. 759 if (numMsg > 1) 760 gl.getDebugMessageLog(numMsg-1, 0, DE_NULL, DE_NULL, DE_NULL, DE_NULL, DE_NULL, DE_NULL); // Clear all but last 761 762 { 763 int msgLen = 0; 764 gl.getIntegerv(GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH, &msgLen); 765 766 TCU_CHECK_MSG(msgLen >= 0, "Negative message length"); 767 TCU_CHECK_MSG(msgLen < 100000, "Excessively long message"); 768 769 lastMsg.message.resize(msgLen); 770 gl.getDebugMessageLog(1, msgLen, &lastMsg.id.source, &lastMsg.id.type, &lastMsg.id.id, &lastMsg.severity, &msgLen, &lastMsg.message[0]); 771 } 772 773 log << TestLog::Message << "Driver says: \"" << lastMsg.message << "\"" << TestLog::EndMessage; 774 775 verifyMessage(lastMsg, source, type); 776} 777 778// Generate errors, verify that calling glGetError afterwards produces desired result 779class GetErrorCase : public BaseCase 780{ 781public: 782 GetErrorCase (Context& ctx, 783 const char* name, 784 const char* desc, 785 TestFunctionWrapper errorFunc); 786 virtual ~GetErrorCase (void) {} 787 788 virtual IterateResult iterate (void); 789 790 virtual void expectMessage (GLenum source, GLenum type); 791 virtual void expectError (glw::GLenum error0, glw::GLenum error1); 792 793private: 794 const TestFunctionWrapper m_errorFunc; 795}; 796 797GetErrorCase::GetErrorCase (Context& ctx, 798 const char* name, 799 const char* desc, 800 TestFunctionWrapper errorFunc) 801 : BaseCase (ctx, name, desc) 802 , m_errorFunc (errorFunc) 803{ 804} 805 806GetErrorCase::IterateResult GetErrorCase::iterate (void) 807{ 808 tcu::TestLog& log = m_testCtx.getLog(); 809 DebugMessageTestContext context = DebugMessageTestContext(*this, m_context.getRenderContext(), m_context.getContextInfo(), log, m_results, true); 810 811 m_errorFunc.call(context); 812 813 m_results.setTestContextResult(m_testCtx); 814 815 return STOP; 816} 817 818void GetErrorCase::expectMessage (GLenum source, GLenum type) 819{ 820 DE_UNREF(source); 821 DE_UNREF(type); 822 DE_ASSERT(!"GetErrorCase cannot handle anything other than error codes"); 823} 824 825void GetErrorCase::expectError (glw::GLenum error0, glw::GLenum error1) 826{ 827 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 828 TestLog& log = m_testCtx.getLog(); 829 830 const GLenum result = gl.getError(); 831 832 if (result != error0 && result != error1) 833 { 834 m_results.addResult(QP_TEST_RESULT_FAIL, "Incorrect error was reported"); 835 if (error0 == error1) 836 log << TestLog::Message 837 << glu::getErrorStr(error0) << " was expected but got " 838 << glu::getErrorStr(result) 839 << TestLog::EndMessage; 840 else 841 log << TestLog::Message 842 << glu::getErrorStr(error0) << " or " 843 << glu::getErrorStr(error1) << " was expected but got " 844 << glu::getErrorStr(result) 845 << TestLog::EndMessage; 846 return; 847 } 848} 849 850// Generate errors, log the types, disable some, regenerate errors, verify correct errors (not)reported 851class FilterCase : public BaseCase 852{ 853public: 854 FilterCase (Context& ctx, 855 const char* name, 856 const char* desc, 857 const vector<TestFunctionWrapper>& errorFuncs); 858 virtual ~FilterCase (void) {} 859 860 virtual IterateResult iterate (void); 861 862 virtual void expectMessage (GLenum source, GLenum type); 863 864protected: 865 struct MessageFilter 866 { 867 MessageFilter() : source(GL_DONT_CARE), type(GL_DONT_CARE), severity(GL_DONT_CARE), enabled(true) {} // Default to enable all 868 MessageFilter(GLenum source_, GLenum type_, GLenum severity_, const vector<GLuint>& ids_, bool enabled_) : source(source_), type(type_), severity(severity_), ids(ids_), enabled(enabled_) {} 869 870 GLenum source; 871 GLenum type; 872 GLenum severity; 873 vector<GLuint> ids; 874 bool enabled; 875 }; 876 877 virtual void callback (GLenum source, GLenum type, GLuint id, GLenum severity, const string& message); 878 879 vector<MessageData> genMessages (bool uselog, const string& desc); 880 881 vector<MessageFilter> genFilters (const vector<MessageData>& messages, const vector<MessageFilter>& initial, deUint32 seed, int iterations) const; 882 void applyFilters (const vector<MessageFilter>& filters) const; 883 bool isEnabled (const vector<MessageFilter>& filters, const MessageData& message) const; 884 885 void verify (const vector<MessageData>& refMessages, 886 const vector<MessageData>& filteredMessages, 887 const vector<MessageFilter>& filters); 888 889 const vector<TestFunctionWrapper> m_errorFuncs; 890 891 vector<MessageData>* m_currentErrors; 892}; 893 894FilterCase::FilterCase (Context& ctx, 895 const char* name, 896 const char* desc, 897 const vector<TestFunctionWrapper>& errorFuncs) 898 : BaseCase (ctx, name, desc) 899 , m_errorFuncs (errorFuncs) 900 , m_currentErrors (DE_NULL) 901{ 902} 903 904FilterCase::IterateResult FilterCase::iterate (void) 905{ 906 TCU_CHECK_AND_THROW(NotSupportedError, m_context.getContextInfo().isExtensionSupported("GL_KHR_debug"), "GL_KHR_debug is not supported"); 907 908 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 909 910 gl.enable(GL_DEBUG_OUTPUT); 911 gl.enable(GL_DEBUG_OUTPUT_SYNCHRONOUS); 912 gl.debugMessageCallback(callbackHandle, this); 913 gl.debugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, DE_NULL, true); 914 915 { 916 const vector<MessageData> refMessages = genMessages(true, "Reference run"); 917 const MessageFilter baseFilter (GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, vector<GLuint>(), true); 918 const deUint32 baseSeed = deStringHash(getName()) ^ m_testCtx.getCommandLine().getBaseSeed(); 919 const vector<MessageFilter> filters = genFilters(refMessages, vector<MessageFilter>(1, baseFilter), baseSeed, 4); 920 vector<MessageData> filteredMessages; 921 922 applyFilters(filters); 923 924 // Generate errors 925 filteredMessages = genMessages(false, "Filtered run"); 926 927 // Verify 928 verify(refMessages, filteredMessages, filters); 929 930 if (!isDebugContext() && refMessages.empty()) 931 m_results.addResult(QP_TEST_RESULT_QUALITY_WARNING, "Verification accuracy is lacking without a debug context"); 932 } 933 934 gl.disable(GL_DEBUG_OUTPUT); 935 m_results.setTestContextResult(m_testCtx); 936 937 return STOP; 938} 939 940void FilterCase::expectMessage (GLenum source, GLenum type) 941{ 942 DE_UNREF(source); 943 DE_UNREF(type); 944} 945 946void FilterCase::callback (GLenum source, GLenum type, GLuint id, GLenum severity, const string& message) 947{ 948 if (m_currentErrors) 949 m_currentErrors->push_back(MessageData(MessageID(source, type, id), severity, message)); 950} 951 952vector<MessageData> FilterCase::genMessages (bool uselog, const string& desc) 953{ 954 tcu::TestLog& log = m_testCtx.getLog(); 955 DebugMessageTestContext context = DebugMessageTestContext(*this, m_context.getRenderContext(), m_context.getContextInfo(), log, m_results, uselog); 956 tcu::ScopedLogSection section (log, "message gen", desc); 957 vector<MessageData> messages; 958 959 m_currentErrors = &messages; 960 961 for (int ndx = 0; ndx < int(m_errorFuncs.size()); ndx++) 962 m_errorFuncs[ndx].call(context); 963 964 m_currentErrors = DE_NULL; 965 966 return messages; 967} 968 969vector<FilterCase::MessageFilter> FilterCase::genFilters (const vector<MessageData>& messages, const vector<MessageFilter>& initial, deUint32 seed, int iterations) const 970{ 971 de::Random rng (seed ^ deInt32Hash(deStringHash(getName()))); 972 973 set<MessageID> tempMessageIds; 974 set<GLenum> tempSources; 975 set<GLenum> tempTypes; 976 set<GLenum> tempSeverities; 977 978 if (messages.empty()) 979 return initial; 980 981 for (int ndx = 0; ndx < int(messages.size()); ndx++) 982 { 983 const MessageData& msg = messages[ndx]; 984 985 tempMessageIds.insert(msg.id); 986 tempSources.insert(msg.id.source); 987 tempTypes.insert(msg.id.type); 988 tempSeverities.insert(msg.severity); 989 } 990 991 { 992 // Fetchable by index 993 const vector<MessageID> messageIds (tempMessageIds.begin(), tempMessageIds.end()); 994 const vector<GLenum> sources (tempSources.begin(), tempSources.end()); 995 const vector<GLenum> types (tempTypes.begin(), tempTypes.end()); 996 const vector<GLenum> severities (tempSeverities.begin(), tempSeverities.end()); 997 998 vector<MessageFilter> filters = initial; 999 1000 for (int iteration = 0; iteration < iterations; iteration++) 1001 { 1002 switch(rng.getInt(0, 8)) // Distribute so that per-message randomization (the default branch) is prevalent 1003 { 1004 case 0: 1005 { 1006 const GLenum source = sources[rng.getInt(0, int(sources.size()-1))]; 1007 const bool enabled = rng.getBool(); 1008 1009 filters.push_back(MessageFilter(source, GL_DONT_CARE, GL_DONT_CARE, vector<GLuint>(), enabled)); 1010 break; 1011 } 1012 1013 case 1: 1014 { 1015 const GLenum type = types[rng.getUint32()%types.size()]; 1016 const bool enabled = rng.getBool(); 1017 1018 filters.push_back(MessageFilter(GL_DONT_CARE, type, GL_DONT_CARE, vector<GLuint>(), enabled)); 1019 break; 1020 } 1021 1022 case 2: 1023 { 1024 const GLenum severity = severities[rng.getUint32()%severities.size()]; 1025 const bool enabled = rng.getBool(); 1026 1027 filters.push_back(MessageFilter(GL_DONT_CARE, GL_DONT_CARE, severity, vector<GLuint>(), enabled)); 1028 break; 1029 } 1030 1031 default: 1032 { 1033 const int start = rng.getInt(0, int(messageIds.size())); 1034 1035 for (int itr = 0; itr < 4; itr++) 1036 { 1037 const MessageID& id = messageIds[(start+itr)%messageIds.size()]; 1038 const bool enabled = rng.getBool(); 1039 1040 filters.push_back(MessageFilter(id.source, id.type, GL_DONT_CARE, vector<GLuint>(1, id.id), enabled)); 1041 } 1042 } 1043 } 1044 } 1045 1046 return filters; 1047 } 1048} 1049 1050void FilterCase::applyFilters (const vector<MessageFilter>& filters) const 1051{ 1052 TestLog& log = m_testCtx.getLog(); 1053 const tcu::ScopedLogSection section (log, "", "Setting message filters"); 1054 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1055 1056 for (size_t filterNdx = 0; filterNdx < filters.size(); filterNdx++) 1057 { 1058 const MessageFilter& filter = filters[filterNdx]; 1059 1060 if (filter.ids.empty()) 1061 log << TestLog::Message << "Setting messages with" 1062 << " source " << glu::getDebugMessageSourceStr(filter.source) 1063 << ", type " << glu::getDebugMessageTypeStr(filter.type) 1064 << " and severity " << glu::getDebugMessageSeverityStr(filter.severity) 1065 << (filter.enabled ? " to enabled" : " to disabled") 1066 << TestLog::EndMessage; 1067 else 1068 { 1069 for (size_t ndx = 0; ndx < filter.ids.size(); ndx++) 1070 log << TestLog::Message << "Setting message (" << MessageID(filter.source, filter.type, filter.ids[ndx]) << ") to " << (filter.enabled ? "enabled" : "disabled") << TestLog::EndMessage; 1071 } 1072 1073 gl.debugMessageControl(filter.source, filter.type, filter.severity, GLsizei(filter.ids.size()), filter.ids.empty() ? DE_NULL : &filter.ids[0], filter.enabled); 1074 } 1075} 1076 1077bool FilterCase::isEnabled (const vector<MessageFilter>& filters, const MessageData& message) const 1078{ 1079 bool retval = true; 1080 1081 for (size_t filterNdx = 0; filterNdx < filters.size(); filterNdx++) 1082 { 1083 const MessageFilter& filter = filters[filterNdx]; 1084 1085 if (filter.ids.empty()) 1086 { 1087 if (filter.source != GL_DONT_CARE && filter.source != message.id.source) 1088 continue; 1089 1090 if (filter.type != GL_DONT_CARE && filter.type != message.id.type) 1091 continue; 1092 1093 if (filter.severity != GL_DONT_CARE && filter.severity != message.severity) 1094 continue; 1095 } 1096 else 1097 { 1098 DE_ASSERT(filter.source != GL_DONT_CARE); 1099 DE_ASSERT(filter.type != GL_DONT_CARE); 1100 DE_ASSERT(filter.severity == GL_DONT_CARE); 1101 1102 if (filter.source != message.id.source || filter.type != message.id.type) 1103 continue; 1104 1105 if (!de::contains(filter.ids.begin(), filter.ids.end(), message.id.id)) 1106 continue; 1107 } 1108 1109 retval = filter.enabled; 1110 } 1111 1112 return retval; 1113} 1114 1115struct MessageMeta 1116{ 1117 int refCount; 1118 int resCount; 1119 GLenum severity; 1120 1121 MessageMeta (void) : refCount(0), resCount(0), severity(GL_NONE) {} 1122}; 1123 1124void FilterCase::verify (const vector<MessageData>& refMessages, const vector<MessageData>& resMessages, const vector<MessageFilter>& filters) 1125{ 1126 TestLog& log = m_testCtx.getLog(); 1127 map<MessageID, MessageMeta> counts; 1128 1129 log << TestLog::Section("verification", "Verifying"); 1130 1131 // Gather message counts & severities, report severity mismatches if found 1132 for (size_t refNdx = 0; refNdx < refMessages.size(); refNdx++) 1133 { 1134 const MessageData& msg = refMessages[refNdx]; 1135 MessageMeta& meta = counts[msg.id]; 1136 1137 if (meta.severity != GL_NONE && meta.severity != msg.severity) 1138 { 1139 log << TestLog::Message << "A message has variable severity between instances: (" << msg.id << ") with severity " 1140 << glu::getDebugMessageSeverityStr(meta.severity) << " and " << glu::getDebugMessageSeverityStr(msg.severity) << TestLog::EndMessage; 1141 m_results.addResult(QP_TEST_RESULT_FAIL, "Message severity changed between instances of the same message"); 1142 } 1143 1144 meta.refCount++; 1145 meta.severity = msg.severity; 1146 } 1147 1148 for (size_t resNdx = 0; resNdx < resMessages.size(); resNdx++) 1149 { 1150 const MessageData& msg = resMessages[resNdx]; 1151 MessageMeta& meta = counts[msg.id]; 1152 1153 if (meta.severity != GL_NONE && meta.severity != msg.severity) 1154 { 1155 log << TestLog::Message << "A message has variable severity between instances: (" << msg.id << ") with severity " 1156 << glu::getDebugMessageSeverityStr(meta.severity) << " and " << glu::getDebugMessageSeverityStr(msg.severity) << TestLog::EndMessage; 1157 m_results.addResult(QP_TEST_RESULT_FAIL, "Message severity changed between instances of the same message"); 1158 } 1159 1160 meta.resCount++; 1161 meta.severity = msg.severity; 1162 } 1163 1164 for (map<MessageID, MessageMeta>::const_iterator itr = counts.begin(); itr != counts.end(); itr++) 1165 { 1166 const MessageID& id = itr->first; 1167 const GLenum severity = itr->second.severity; 1168 1169 const int refCount = itr->second.refCount; 1170 const int resCount = itr->second.resCount; 1171 const bool enabled = isEnabled(filters, MessageData(id, severity, "")); 1172 1173 VerificationResult result = verifyMessageCount(id, severity, refCount, resCount, enabled); 1174 1175 log << TestLog::Message << result.logMessage << TestLog::EndMessage; 1176 1177 if (result.result != QP_TEST_RESULT_PASS) 1178 m_results.addResult(result.result, result.resultMessage); 1179 } 1180 1181 log << TestLog::EndSection; 1182} 1183 1184// Filter case that uses debug groups 1185class GroupFilterCase : public FilterCase 1186{ 1187public: 1188 GroupFilterCase (Context& ctx, 1189 const char* name, 1190 const char* desc, 1191 const vector<TestFunctionWrapper>& errorFuncs); 1192 virtual ~GroupFilterCase (void) {} 1193 1194 virtual IterateResult iterate (void); 1195}; 1196 1197GroupFilterCase::GroupFilterCase (Context& ctx, 1198 const char* name, 1199 const char* desc, 1200 const vector<TestFunctionWrapper>& errorFuncs) 1201 : FilterCase(ctx, name, desc, errorFuncs) 1202{ 1203} 1204 1205template<typename T> 1206vector<T> join(const vector<T>& a, const vector<T>&b) 1207{ 1208 vector<T> retval; 1209 1210 retval.reserve(a.size()+b.size()); 1211 retval.insert(retval.end(), a.begin(), a.end()); 1212 retval.insert(retval.end(), b.begin(), b.end()); 1213 return retval; 1214} 1215 1216GroupFilterCase::IterateResult GroupFilterCase::iterate (void) 1217{ 1218 TCU_CHECK_AND_THROW(NotSupportedError, m_context.getContextInfo().isExtensionSupported("GL_KHR_debug"), "GL_KHR_debug is not supported"); 1219 1220 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1221 tcu::TestLog& log = m_testCtx.getLog(); 1222 1223 gl.enable(GL_DEBUG_OUTPUT); 1224 gl.enable(GL_DEBUG_OUTPUT_SYNCHRONOUS); 1225 gl.debugMessageCallback(callbackHandle, this); 1226 gl.debugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, DE_NULL, true); 1227 1228 { 1229 1230 // Generate reference (all errors) 1231 const vector<MessageData> refMessages = genMessages(true, "Reference run"); 1232 const deUint32 baseSeed = deStringHash(getName()) ^ m_testCtx.getCommandLine().getBaseSeed(); 1233 const MessageFilter baseFilter (GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, vector<GLuint>(), true); 1234 const vector<MessageFilter> filter0 = genFilters(refMessages, vector<MessageFilter>(1, baseFilter), baseSeed, 4); 1235 vector<MessageData> resMessages0; 1236 1237 applyFilters(filter0); 1238 1239 resMessages0 = genMessages(false, "Filtered run, default debug group"); 1240 1241 // Initial verification 1242 verify(refMessages, resMessages0, filter0); 1243 1244 { 1245 // Generate reference (filters inherited from parent) 1246 const vector<MessageFilter> filter1base = genFilters(refMessages, vector<MessageFilter>(), baseSeed ^ 0xDEADBEEF, 4); 1247 const vector<MessageFilter> filter1full = join(filter0, filter1base); 1248 tcu::ScopedLogSection section1 (log, "", "Pushing Debug Group"); 1249 vector<MessageData> resMessages1; 1250 1251 gl.pushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 1, -1, "Test Group"); 1252 applyFilters(filter1base); 1253 1254 // First nested verification 1255 resMessages1 = genMessages(false, "Filtered run, pushed one debug group"); 1256 verify(refMessages, resMessages1, filter1full); 1257 1258 { 1259 // Generate reference (filters iherited again) 1260 const vector<MessageFilter> filter2base = genFilters(refMessages, vector<MessageFilter>(), baseSeed ^ 0x43211234, 4); 1261 const vector<MessageFilter> filter2full = join(filter1full, filter2base); 1262 tcu::ScopedLogSection section2 (log, "", "Pushing Debug Group"); 1263 vector<MessageData> resMessages2; 1264 1265 gl.pushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 1, -1, "Nested Test Group"); 1266 applyFilters(filter2base); 1267 1268 // Second nested verification 1269 resMessages2 = genMessages(false, "Filtered run, pushed two debug groups"); 1270 verify(refMessages, resMessages2, filter2full); 1271 1272 gl.popDebugGroup(); 1273 } 1274 1275 // First restore verification 1276 resMessages1 = genMessages(false, "Filtered run, popped second debug group"); 1277 verify(refMessages, resMessages1, filter1full); 1278 1279 gl.popDebugGroup(); 1280 } 1281 1282 // restore verification 1283 resMessages0 = genMessages(false, "Filtered run, popped first debug group"); 1284 verify(refMessages, resMessages0, filter0); 1285 1286 if (!isDebugContext() && refMessages.empty()) 1287 m_results.addResult(QP_TEST_RESULT_QUALITY_WARNING, "Verification accuracy is lacking without a debug context"); 1288 } 1289 1290 gl.disable(GL_DEBUG_OUTPUT); 1291 m_results.setTestContextResult(m_testCtx); 1292 return STOP; 1293} 1294 1295// Basic grouping functionality 1296class GroupCase : public BaseCase 1297{ 1298public: 1299 GroupCase (Context& ctx, 1300 const char* name, 1301 const char* desc); 1302 virtual ~GroupCase () {} 1303 1304 virtual IterateResult iterate (void); 1305 1306private: 1307 virtual void callback (GLenum source, GLenum type, GLuint id, GLenum severity, const string& message); 1308 1309 MessageData m_lastMessage; 1310}; 1311 1312GroupCase::GroupCase (Context& ctx, 1313 const char* name, 1314 const char* desc) 1315 : BaseCase(ctx, name, desc) 1316{ 1317} 1318 1319GroupCase::IterateResult GroupCase::iterate (void) 1320{ 1321 TCU_CHECK_AND_THROW(NotSupportedError, m_context.getContextInfo().isExtensionSupported("GL_KHR_debug"), "GL_KHR_debug is not supported"); 1322 1323 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1324 tcu::TestLog& log = m_testCtx.getLog(); 1325 glu::CallLogWrapper wrapper (gl, log); 1326 1327 gl.enable(GL_DEBUG_OUTPUT); 1328 gl.enable(GL_DEBUG_OUTPUT_SYNCHRONOUS); 1329 gl.debugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, DE_NULL, false); // disable all 1330 gl.debugMessageControl(GL_DEBUG_SOURCE_API, GL_DEBUG_TYPE_ERROR, GL_DONT_CARE, 0, DE_NULL, true); // enable API errors 1331 gl.debugMessageControl(GL_DEBUG_SOURCE_APPLICATION, GL_DONT_CARE, GL_DONT_CARE, 0, DE_NULL, true); // enable application messages 1332 gl.debugMessageControl(GL_DEBUG_SOURCE_THIRD_PARTY, GL_DONT_CARE, GL_DONT_CARE, 0, DE_NULL, true); // enable third party messages 1333 gl.debugMessageCallback(callbackHandle, this); 1334 1335 wrapper.enableLogging(true); 1336 wrapper.glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 1234, -1, "Pushed debug stack"); 1337 verifyMessage(m_lastMessage, GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PUSH_GROUP, 1234, GL_DEBUG_SEVERITY_NOTIFICATION); 1338 wrapper.glPopDebugGroup(); 1339 verifyMessage(m_lastMessage, GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_POP_GROUP, 1234, GL_DEBUG_SEVERITY_NOTIFICATION); 1340 1341 wrapper.glPushDebugGroup(GL_DEBUG_SOURCE_THIRD_PARTY, 4231, -1, "Pushed debug stack"); 1342 verifyMessage(m_lastMessage, GL_DEBUG_SOURCE_THIRD_PARTY, GL_DEBUG_TYPE_PUSH_GROUP, 4231, GL_DEBUG_SEVERITY_NOTIFICATION); 1343 wrapper.glPopDebugGroup(); 1344 verifyMessage(m_lastMessage, GL_DEBUG_SOURCE_THIRD_PARTY, GL_DEBUG_TYPE_POP_GROUP, 4231, GL_DEBUG_SEVERITY_NOTIFICATION); 1345 1346 gl.debugMessageCallback(DE_NULL, DE_NULL); 1347 gl.disable(GL_DEBUG_OUTPUT); 1348 1349 m_results.setTestContextResult(m_testCtx); 1350 1351 return STOP; 1352} 1353 1354void GroupCase::callback (GLenum source, GLenum type, GLuint id, GLenum severity, const string& message) 1355{ 1356 m_lastMessage = MessageData(MessageID(source, type, id), severity, message); 1357} 1358 1359// Asynchronous debug output 1360class AsyncCase : public BaseCase 1361{ 1362public: 1363 AsyncCase (Context& ctx, 1364 const char* name, 1365 const char* desc, 1366 const vector<TestFunctionWrapper>& errorFuncs, 1367 bool useCallbacks); 1368 virtual ~AsyncCase (void) {} 1369 1370 virtual IterateResult iterate (void); 1371 1372 virtual void expectMessage (glw::GLenum source, glw::GLenum type); 1373 1374private: 1375 struct MessageCount 1376 { 1377 int received; 1378 int expected; 1379 1380 MessageCount(void) : received(0), expected(0) {} 1381 }; 1382 typedef map<MessageID, MessageCount> MessageCounter; 1383 1384 enum VerifyState 1385 { 1386 VERIFY_PASS = 0, 1387 VERIFY_MINIMUM, 1388 VERIFY_FAIL, 1389 1390 VERIFY_LAST 1391 }; 1392 1393 virtual void callback (glw::GLenum source, glw::GLenum type, glw::GLuint id, glw::GLenum severity, const std::string& message); 1394 VerifyState verify (bool uselog); 1395 void fetchLogMessages (void); 1396 1397 const vector<TestFunctionWrapper> m_errorFuncs; 1398 const bool m_useCallbacks; 1399 1400 MessageCounter m_counts; 1401 1402 de::Mutex m_mutex; 1403}; 1404 1405AsyncCase::AsyncCase (Context& ctx, 1406 const char* name, 1407 const char* desc, 1408 const vector<TestFunctionWrapper>& errorFuncs, 1409 bool useCallbacks) 1410 : BaseCase (ctx, name, desc) 1411 , m_errorFuncs (errorFuncs) 1412 , m_useCallbacks (useCallbacks) 1413{ 1414} 1415 1416AsyncCase::IterateResult AsyncCase::iterate (void) 1417{ 1418 TCU_CHECK_AND_THROW(NotSupportedError, m_context.getContextInfo().isExtensionSupported("GL_KHR_debug"), "GL_KHR_debug is not supported"); 1419 1420 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1421 tcu::TestLog& log = m_testCtx.getLog(); 1422 DebugMessageTestContext context = DebugMessageTestContext(*this, m_context.getRenderContext(), m_context.getContextInfo(), log, m_results, true); 1423 const int maxWait = 10000; // ms 1424 const int warnWait = 100; 1425 1426 gl.enable(GL_DEBUG_OUTPUT); 1427 gl.enable(GL_DEBUG_OUTPUT_SYNCHRONOUS); 1428 gl.debugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, DE_NULL, false); 1429 1430 // Some messages could be dependent on the value of DEBUG_OUTPUT_SYNCHRONOUS so only use API errors which should be generated in all cases 1431 gl.debugMessageControl(GL_DEBUG_SOURCE_API, GL_DEBUG_TYPE_ERROR, GL_DONT_CARE, 0, DE_NULL, true); 1432 1433 if (m_useCallbacks) // will use log otherwise 1434 gl.debugMessageCallback(callbackHandle, this); 1435 else 1436 gl.debugMessageCallback(DE_NULL, DE_NULL); 1437 1438 // Reference run (synchoronous) 1439 { 1440 tcu::ScopedLogSection section(log, "reference run", "Reference run (synchronous)"); 1441 1442 for (int ndx = 0; ndx < int(m_errorFuncs.size()); ndx++) 1443 m_errorFuncs[ndx].call(context); 1444 } 1445 1446 if (m_counts.empty()) 1447 { 1448 if (!isDebugContext()) 1449 m_results.addResult(QP_TEST_RESULT_QUALITY_WARNING, "Need debug context to guarantee implementation behaviour (see command line options)"); 1450 1451 log << TestLog::Message << "Reference run produced no messages, nothing to verify" << TestLog::EndMessage; 1452 1453 gl.debugMessageCallback(DE_NULL, DE_NULL); 1454 gl.disable(GL_DEBUG_OUTPUT); 1455 1456 m_results.setTestContextResult(m_testCtx); 1457 return STOP; 1458 } 1459 1460 for (MessageCounter::iterator itr = m_counts.begin(); itr != m_counts.end(); itr++) 1461 { 1462 itr->second.expected = itr->second.received; 1463 itr->second.received = 0; 1464 } 1465 1466 gl.disable(GL_DEBUG_OUTPUT_SYNCHRONOUS); 1467 1468 // Result run (async) 1469 for (int ndx = 0; ndx < int(m_errorFuncs.size()); ndx++) 1470 m_errorFuncs[ndx].call(context); 1471 1472 // Repatedly try verification, new results may be added to m_receivedMessages at any time 1473 { 1474 tcu::ScopedLogSection section (log, "result run", "Result run (asynchronous)"); 1475 VerifyState lastTimelyState = VERIFY_FAIL; 1476 1477 for (int waited = 0;;) 1478 { 1479 const VerifyState pass = verify(false); 1480 const int wait = de::max(50, waited>>2); 1481 1482 // Pass (possibly due to time limit) 1483 if (pass == VERIFY_PASS || (pass == VERIFY_MINIMUM && waited >= maxWait)) 1484 { 1485 verify(true); // log 1486 1487 // State changed late 1488 if (waited >= warnWait && lastTimelyState != pass) 1489 m_results.addResult(QP_TEST_RESULT_QUALITY_WARNING, "Async messages were returned to application somewhat slowly"); 1490 1491 log << TestLog::Message << "Passed after ~" << waited << "ms of waiting" << TestLog::EndMessage; 1492 break; 1493 } 1494 // fail 1495 else if (waited >= maxWait) 1496 { 1497 verify(true); // log 1498 1499 log << TestLog::Message << "Waited for ~" << waited << "ms without getting all expected messages" << TestLog::EndMessage; 1500 m_results.addResult(QP_TEST_RESULT_FAIL, "Async messages were not returned to application within a reasonable timeframe"); 1501 break; 1502 } 1503 1504 if (waited < warnWait) 1505 lastTimelyState = pass; 1506 1507 deSleep(wait); 1508 waited += wait; 1509 1510 if (!m_useCallbacks) 1511 fetchLogMessages(); 1512 } 1513 } 1514 1515 gl.debugMessageCallback(DE_NULL, DE_NULL); 1516 1517 gl.disable(GL_DEBUG_OUTPUT); 1518 m_results.setTestContextResult(m_testCtx); 1519 1520 return STOP; 1521} 1522 1523void AsyncCase::expectMessage (GLenum source, GLenum type) 1524{ 1525 // Good time to clean up the queue as this should be called after most messages are generated 1526 if (!m_useCallbacks) 1527 fetchLogMessages(); 1528 1529 DE_UNREF(source); 1530 DE_UNREF(type); 1531} 1532 1533void AsyncCase::callback (GLenum source, GLenum type, GLuint id, GLenum severity, const string& message) 1534{ 1535 DE_ASSERT(m_useCallbacks); 1536 DE_UNREF(severity); 1537 DE_UNREF(message); 1538 1539 de::ScopedLock lock(m_mutex); 1540 1541 m_counts[MessageID(source, type, id)].received++; 1542} 1543 1544// 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 1545void AsyncCase::fetchLogMessages (void) 1546{ 1547 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1548 GLint numMsg = 0; 1549 1550 gl.getIntegerv(GL_DEBUG_LOGGED_MESSAGES, &numMsg); 1551 1552 for(int msgNdx = 0; msgNdx < numMsg; msgNdx++) 1553 { 1554 int msgLen = 0; 1555 MessageData msg; 1556 1557 gl.getIntegerv(GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH, &msgLen); 1558 1559 TCU_CHECK_MSG(msgLen >= 0, "Negative message length"); 1560 TCU_CHECK_MSG(msgLen < 100000, "Excessively long message"); 1561 1562 msg.message.resize(msgLen); 1563 gl.getDebugMessageLog(1, msgLen, &msg.id.source, &msg.id.type, &msg.id.id, &msg.severity, &msgLen, &msg.message[0]); 1564 1565 { 1566 const de::ScopedLock lock(m_mutex); // Don't block during API call 1567 1568 m_counts[MessageID(msg.id)].received++; 1569 } 1570 } 1571} 1572 1573AsyncCase::VerifyState AsyncCase::verify (bool uselog) 1574{ 1575 using std::map; 1576 1577 VerifyState retval = VERIFY_PASS; 1578 TestLog& log = m_testCtx.getLog(); 1579 1580 const de::ScopedLock lock(m_mutex); 1581 1582 for (map<MessageID, MessageCount>::const_iterator itr = m_counts.begin(); itr != m_counts.end(); itr++) 1583 { 1584 const MessageID& id = itr->first; 1585 1586 const int refCount = itr->second.expected; 1587 const int resCount = itr->second.received; 1588 const bool enabled = true; 1589 1590 VerificationResult result = verifyMessageCount(id, GL_DONT_CARE, refCount, resCount, enabled); 1591 1592 if (uselog) 1593 log << TestLog::Message << result.logMessage << TestLog::EndMessage; 1594 1595 if (result.result == QP_TEST_RESULT_FAIL) 1596 retval = VERIFY_FAIL; 1597 else if (result.result != QP_TEST_RESULT_PASS && retval == VERIFY_PASS) 1598 retval = VERIFY_MINIMUM; 1599 } 1600 1601 return retval; 1602} 1603 1604// Tests debug labels 1605class LabelCase : public TestCase 1606{ 1607public: 1608 LabelCase (Context& ctx, 1609 const char* name, 1610 const char* desc, 1611 GLenum identifier); 1612 virtual ~LabelCase (void) {} 1613 1614 virtual IterateResult iterate (void); 1615 1616private: 1617 GLenum m_identifier; 1618}; 1619 1620LabelCase::LabelCase (Context& ctx, 1621 const char* name, 1622 const char* desc, 1623 GLenum identifier) 1624 : TestCase (ctx, name, desc) 1625 , m_identifier (identifier) 1626{ 1627} 1628 1629LabelCase::IterateResult LabelCase::iterate (void) 1630{ 1631 TCU_CHECK_AND_THROW(NotSupportedError, m_context.getContextInfo().isExtensionSupported("GL_KHR_debug"), "GL_KHR_debug is not supported"); 1632 1633 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1634 const char* const msg = "This is a debug label"; 1635 GLuint object = 0; 1636 char buffer[64]; 1637 int outlen = 0; 1638 1639 switch(m_identifier) 1640 { 1641 case GL_BUFFER: 1642 gl.genBuffers(1, &object); 1643 gl.bindBuffer(GL_ARRAY_BUFFER, object); 1644 gl.bindBuffer(GL_ARRAY_BUFFER, 0); 1645 break; 1646 1647 case GL_SHADER: 1648 object = gl.createShader(GL_FRAGMENT_SHADER); 1649 break; 1650 1651 case GL_PROGRAM: 1652 object = gl.createProgram(); 1653 break; 1654 1655 case GL_QUERY: 1656 gl.genQueries(1, &object); 1657 gl.beginQuery(GL_ANY_SAMPLES_PASSED, object); // Create 1658 gl.endQuery(GL_ANY_SAMPLES_PASSED); // Cleanup 1659 break; 1660 1661 case GL_PROGRAM_PIPELINE: 1662 gl.genProgramPipelines(1, &object); 1663 gl.bindProgramPipeline(object); // Create 1664 gl.bindProgramPipeline(0); // Cleanup 1665 break; 1666 1667 case GL_TRANSFORM_FEEDBACK: 1668 gl.genTransformFeedbacks(1, &object); 1669 gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, object); 1670 gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0); 1671 break; 1672 1673 case GL_SAMPLER: 1674 gl.genSamplers(1, &object); 1675 gl.bindSampler(0, object); 1676 gl.bindSampler(0, 0); 1677 break; 1678 1679 case GL_TEXTURE: 1680 gl.genTextures(1, &object); 1681 gl.bindTexture(GL_TEXTURE_2D, object); 1682 gl.bindTexture(GL_TEXTURE_2D, 0); 1683 break; 1684 1685 case GL_RENDERBUFFER: 1686 gl.genRenderbuffers(1, &object); 1687 gl.bindRenderbuffer(GL_RENDERBUFFER, object); 1688 gl.bindRenderbuffer(GL_RENDERBUFFER, 0); 1689 break; 1690 1691 case GL_FRAMEBUFFER: 1692 gl.genFramebuffers(1, &object); 1693 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, object); 1694 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_context.getRenderContext().getDefaultFramebuffer()); 1695 break; 1696 1697 default: 1698 DE_ASSERT(!"Invalid identifier"); 1699 } 1700 1701 gl.objectLabel(m_identifier, object, -1, msg); 1702 1703 gl.getObjectLabel(m_identifier, object, sizeof(buffer), &outlen, buffer); 1704 1705 if (outlen == 0) 1706 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Failed to query debug label from object"); 1707 else if (deStringEqual(msg, buffer)) 1708 { 1709 m_testCtx.getLog() << TestLog::Message << "Query returned string: \"" << buffer << "\"" << TestLog::EndMessage; 1710 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 1711 } 1712 else 1713 { 1714 m_testCtx.getLog() << TestLog::Message << "Query returned wrong string: expected \"" << msg << "\" but got \"" << buffer << "\"" << TestLog::EndMessage; 1715 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Query returned wrong label"); 1716 } 1717 1718 switch(m_identifier) 1719 { 1720 case GL_BUFFER: gl.deleteBuffers(1, &object); break; 1721 case GL_SHADER: gl.deleteShader(object); break; 1722 case GL_PROGRAM: gl.deleteProgram(object); break; 1723 case GL_QUERY: gl.deleteQueries(1, &object); break; 1724 case GL_PROGRAM_PIPELINE: gl.deleteProgramPipelines(1, &object); break; 1725 case GL_TRANSFORM_FEEDBACK: gl.deleteTransformFeedbacks(1, &object); break; 1726 case GL_SAMPLER: gl.deleteSamplers(1, &object); break; 1727 case GL_TEXTURE: gl.deleteTextures(1, &object); break; 1728 case GL_RENDERBUFFER: gl.deleteRenderbuffers(1, &object); break; 1729 case GL_FRAMEBUFFER: gl.deleteFramebuffers(1, &object); break; 1730 1731 default: 1732 DE_ASSERT(!"Invalid identifier"); 1733 } 1734 1735 return STOP; 1736} 1737 1738 1739DebugMessageTestContext::DebugMessageTestContext (BaseCase& host, 1740 glu::RenderContext& renderCtx, 1741 const glu::ContextInfo& ctxInfo, 1742 tcu::TestLog& log, 1743 tcu::ResultCollector& results, 1744 bool enableLog) 1745 : NegativeTestContext (host, renderCtx, ctxInfo, log, results, enableLog) 1746 , m_debugHost (host) 1747{ 1748} 1749 1750DebugMessageTestContext::~DebugMessageTestContext (void) 1751{ 1752} 1753 1754void DebugMessageTestContext::expectMessage (GLenum source, GLenum type) 1755{ 1756 m_debugHost.expectMessage(source, type); 1757} 1758 1759} // anonymous 1760 1761DebugTests::DebugTests (Context& context) 1762 : TestCaseGroup(context, "debug", "Debug tests") 1763{ 1764} 1765 1766enum CaseType 1767{ 1768 CASETYPE_CALLBACK = 0, 1769 CASETYPE_LOG, 1770 CASETYPE_GETERROR, 1771 1772 CASETYPE_LAST 1773}; 1774 1775tcu::TestNode* createCase (CaseType type, Context& ctx, const char* name, const char* desc, TestFunctionWrapper function) 1776{ 1777 switch(type) 1778 { 1779 case CASETYPE_CALLBACK: return new CallbackErrorCase(ctx, name, desc, function); 1780 case CASETYPE_LOG: return new LogErrorCase(ctx, name, desc, function); 1781 case CASETYPE_GETERROR: return new GetErrorCase(ctx, name, desc, function); 1782 1783 default: 1784 DE_ASSERT(!"Invalid type"); 1785 } 1786 1787 return DE_NULL; 1788} 1789 1790tcu::TestCaseGroup* createChildCases (CaseType type, Context& ctx, const char* name, const char* desc, const vector<FunctionContainer>& funcs) 1791{ 1792 tcu::TestCaseGroup* host = new tcu::TestCaseGroup(ctx.getTestContext(), name, desc); 1793 1794 for (size_t ndx = 0; ndx < funcs.size(); ndx++) 1795 host->addChild(createCase(type, ctx, funcs[ndx].name, funcs[ndx].desc, funcs[ndx].function)); 1796 1797 return host; 1798} 1799 1800vector<FunctionContainer> wrapCoreFunctions (const vector<NegativeTestShared::FunctionContainer>& fns) 1801{ 1802 vector<FunctionContainer> retVal; 1803 1804 retVal.resize(fns.size()); 1805 for (int ndx = 0; ndx < (int)fns.size(); ++ndx) 1806 { 1807 retVal[ndx].function = TestFunctionWrapper(fns[ndx].function); 1808 retVal[ndx].name = fns[ndx].name; 1809 retVal[ndx].desc = fns[ndx].desc; 1810 } 1811 1812 return retVal; 1813} 1814 1815void DebugTests::init (void) 1816{ 1817 const vector<FunctionContainer> bufferFuncs = wrapCoreFunctions(NegativeTestShared::getNegativeBufferApiTestFunctions()); 1818 const vector<FunctionContainer> textureFuncs = wrapCoreFunctions(NegativeTestShared::getNegativeTextureApiTestFunctions()); 1819 const vector<FunctionContainer> shaderFuncs = wrapCoreFunctions(NegativeTestShared::getNegativeShaderApiTestFunctions()); 1820 const vector<FunctionContainer> fragmentFuncs = wrapCoreFunctions(NegativeTestShared::getNegativeFragmentApiTestFunctions()); 1821 const vector<FunctionContainer> vaFuncs = wrapCoreFunctions(NegativeTestShared::getNegativeVertexArrayApiTestFunctions()); 1822 const vector<FunctionContainer> stateFuncs = wrapCoreFunctions(NegativeTestShared::getNegativeStateApiTestFunctions()); 1823 const vector<FunctionContainer> externalFuncs = getUserMessageFuncs(); 1824 1825 { 1826 tcu::TestCaseGroup* const negative = new tcu::TestCaseGroup(m_testCtx, "negative_coverage", "API error coverage with various reporting methods"); 1827 1828 addChild(negative); 1829 1830 { 1831 tcu::TestCaseGroup* const host = new tcu::TestCaseGroup(m_testCtx, "callbacks", "Reporting of standard API errors via callback"); 1832 1833 negative->addChild(host); 1834 host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "buffer", "Negative Buffer API Cases", bufferFuncs)); 1835 host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "texture", "Negative Texture API Cases", textureFuncs)); 1836 host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "shader", "Negative Shader API Cases", shaderFuncs)); 1837 host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "fragment", "Negative Fragment API Cases", fragmentFuncs)); 1838 host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "vertex_array", "Negative Vertex Array API Cases", vaFuncs)); 1839 host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "state", "Negative GL State API Cases", stateFuncs)); 1840 } 1841 1842 { 1843 tcu::TestCaseGroup* const host = new tcu::TestCaseGroup(m_testCtx, "log", "Reporting of standard API errors via log"); 1844 1845 negative->addChild(host); 1846 1847 host->addChild(createChildCases(CASETYPE_LOG, m_context, "buffer", "Negative Buffer API Cases", bufferFuncs)); 1848 host->addChild(createChildCases(CASETYPE_LOG, m_context, "texture", "Negative Texture API Cases", textureFuncs)); 1849 host->addChild(createChildCases(CASETYPE_LOG, m_context, "shader", "Negative Shader API Cases", shaderFuncs)); 1850 host->addChild(createChildCases(CASETYPE_LOG, m_context, "fragment", "Negative Fragment API Cases", fragmentFuncs)); 1851 host->addChild(createChildCases(CASETYPE_LOG, m_context, "vertex_array", "Negative Vertex Array API Cases", vaFuncs)); 1852 host->addChild(createChildCases(CASETYPE_LOG, m_context, "state", "Negative GL State API Cases", stateFuncs)); 1853 } 1854 1855 { 1856 tcu::TestCaseGroup* const host = new tcu::TestCaseGroup(m_testCtx, "get_error", "Reporting of standard API errors via glGetError"); 1857 1858 negative->addChild(host); 1859 1860 host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "buffer", "Negative Buffer API Cases", bufferFuncs)); 1861 host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "texture", "Negative Texture API Cases", textureFuncs)); 1862 host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "shader", "Negative Shader API Cases", shaderFuncs)); 1863 host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "fragment", "Negative Fragment API Cases", fragmentFuncs)); 1864 host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "vertex_array", "Negative Vertex Array API Cases", vaFuncs)); 1865 host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "state", "Negative GL State API Cases", stateFuncs)); 1866 } 1867 } 1868 1869 { 1870 tcu::TestCaseGroup* const host = createChildCases(CASETYPE_CALLBACK, m_context, "externally_generated", "Externally Generated Messages", externalFuncs); 1871 1872 host->addChild(new GroupCase(m_context, "push_pop_consistency", "Push/pop message generation with full message output checking")); 1873 1874 addChild(host); 1875 } 1876 1877 { 1878 vector<FunctionContainer> containers; 1879 vector<TestFunctionWrapper> allFuncs; 1880 1881 de::Random rng (0x53941903 ^ m_context.getTestContext().getCommandLine().getBaseSeed()); 1882 1883 containers.insert(containers.end(), bufferFuncs.begin(), bufferFuncs.end()); 1884 containers.insert(containers.end(), textureFuncs.begin(), textureFuncs.end()); 1885 containers.insert(containers.end(), externalFuncs.begin(), externalFuncs.end()); 1886 1887 for (size_t ndx = 0; ndx < containers.size(); ndx++) 1888 allFuncs.push_back(containers[ndx].function); 1889 1890 rng.shuffle(allFuncs.begin(), allFuncs.end()); 1891 1892 { 1893 tcu::TestCaseGroup* const filtering = new tcu::TestCaseGroup(m_testCtx, "error_filters", "Filtering of reported errors"); 1894 const int errorFuncsPerCase = 4; 1895 const int maxFilteringCaseCount = 32; 1896 const int caseCount = (int(allFuncs.size()) + errorFuncsPerCase-1) / errorFuncsPerCase; 1897 1898 addChild(filtering); 1899 1900 for (int caseNdx = 0; caseNdx < de::min(caseCount, maxFilteringCaseCount); caseNdx++) 1901 { 1902 const int start = caseNdx*errorFuncsPerCase; 1903 const int end = de::min((caseNdx+1)*errorFuncsPerCase, int(allFuncs.size())); 1904 const string name = "case_" + de::toString(caseNdx); 1905 vector<TestFunctionWrapper> funcs (allFuncs.begin()+start, allFuncs.begin()+end); 1906 1907 // These produce lots of different message types, thus always include at least one when testing filtering 1908 funcs.insert(funcs.end(), externalFuncs[caseNdx%externalFuncs.size()].function); 1909 1910 filtering->addChild(new FilterCase(m_context, name.c_str(), "DebugMessageControl usage", funcs)); 1911 } 1912 } 1913 1914 { 1915 tcu::TestCaseGroup* const groups = new tcu::TestCaseGroup(m_testCtx, "error_groups", "Filtering of reported errors with use of Error Groups"); 1916 const int errorFuncsPerCase = 4; 1917 const int maxFilteringCaseCount = 16; 1918 const int caseCount = (int(allFuncs.size()) + errorFuncsPerCase-1) / errorFuncsPerCase; 1919 1920 addChild(groups); 1921 1922 for (int caseNdx = 0; caseNdx < caseCount && caseNdx < maxFilteringCaseCount; caseNdx++) 1923 { 1924 const int start = caseNdx*errorFuncsPerCase; 1925 const int end = de::min((caseNdx+1)*errorFuncsPerCase, int(allFuncs.size())); 1926 const string name = ("case_" + de::toString(caseNdx)).c_str(); 1927 vector<TestFunctionWrapper> funcs (&allFuncs[0]+start, &allFuncs[0]+end); 1928 1929 // These produce lots of different message types, thus always include at least one when testing filtering 1930 funcs.insert(funcs.end(), externalFuncs[caseNdx%externalFuncs.size()].function); 1931 1932 groups->addChild(new GroupFilterCase(m_context, name.c_str(), "Debug Group usage", funcs)); 1933 } 1934 } 1935 1936 { 1937 tcu::TestCaseGroup* const async = new tcu::TestCaseGroup(m_testCtx, "async", "Asynchronous message generation"); 1938 const int errorFuncsPerCase = 2; 1939 const int maxAsyncCaseCount = 16; 1940 const int caseCount = (int(allFuncs.size()) + errorFuncsPerCase-1) / errorFuncsPerCase; 1941 1942 addChild(async); 1943 1944 for (int caseNdx = 0; caseNdx < caseCount && caseNdx < maxAsyncCaseCount; caseNdx++) 1945 { 1946 const int start = caseNdx*errorFuncsPerCase; 1947 const int end = de::min((caseNdx+1)*errorFuncsPerCase, int(allFuncs.size())); 1948 const string name = ("case_" + de::toString(caseNdx)).c_str(); 1949 vector<TestFunctionWrapper> funcs (&allFuncs[0]+start, &allFuncs[0]+end); 1950 1951 if (caseNdx&0x1) 1952 async->addChild(new AsyncCase(m_context, (name+"_callback").c_str(), "Async message generation", funcs, true)); 1953 else 1954 async->addChild(new AsyncCase(m_context, (name+"_log").c_str(), "Async message generation", funcs, false)); 1955 } 1956 } 1957 } 1958 1959 { 1960 tcu::TestCaseGroup* const labels = new tcu::TestCaseGroup(m_testCtx, "object_labels", "Labeling objects"); 1961 1962 const struct 1963 { 1964 GLenum identifier; 1965 const char* name; 1966 const char* desc; 1967 } cases[] = 1968 { 1969 { GL_BUFFER, "buffer", "Debug label on a buffer object" }, 1970 { GL_SHADER, "shader", "Debug label on a shader object" }, 1971 { GL_PROGRAM, "program", "Debug label on a program object" }, 1972 { GL_QUERY, "query", "Debug label on a query object" }, 1973 { GL_PROGRAM_PIPELINE, "program_pipeline", "Debug label on a program pipeline object" }, 1974 { GL_TRANSFORM_FEEDBACK, "transform_feedback", "Debug label on a transform feedback object" }, 1975 { GL_SAMPLER, "sampler", "Debug label on a sampler object" }, 1976 { GL_TEXTURE, "texture", "Debug label on a texture object" }, 1977 { GL_RENDERBUFFER, "renderbuffer", "Debug label on a renderbuffer object" }, 1978 { GL_FRAMEBUFFER, "framebuffer", "Debug label on a framebuffer object" }, 1979 }; 1980 1981 addChild(labels); 1982 1983 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(cases); ndx++) 1984 labels->addChild(new LabelCase(m_context, cases[ndx].name, cases[ndx].desc, cases[ndx].identifier)); 1985 } 1986} 1987 1988} // Functional 1989} // gles31 1990} // deqp 1991