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