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