1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES 3.1 Module
3 * -------------------------------------------------
5 * Copyright 2014 The Android Open Source Project
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
21 * \brief Debug output (KHR_debug) tests
22 *//*--------------------------------------------------------------------*/
24 #include "es31fDebugTests.hpp"
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 "es31fNegativePreciseTests.hpp"
38 #include "es31fNegativeAdvancedBlendEquationTests.hpp"
40 #include "deUniquePtr.hpp"
41 #include "deRandom.hpp"
42 #include "deStringUtil.hpp"
43 #include "deSTLUtil.hpp"
44 #include "deMutex.hpp"
47 #include "gluRenderContext.hpp"
48 #include "gluContextInfo.hpp"
49 #include "gluCallLogWrapper.hpp"
50 #include "gluStrUtil.hpp"
52 #include "glwDefs.hpp"
53 #include "glwEnums.hpp"
54 #include "glwFunctions.hpp"
56 #include "tes31Context.hpp"
57 #include "tcuTestContext.hpp"
58 #include "tcuCommandLine.hpp"
59 #include "tcuResultCollector.hpp"
61 #include "glsStateQueryUtil.hpp"
79 using tcu::ResultCollector;
81 using glu::CallLogWrapper;
83 using NegativeTestShared::NegativeTestContext;
85 static const GLenum s_debugTypes[] =
88 GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR,
89 GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR,
90 GL_DEBUG_TYPE_PORTABILITY,
91 GL_DEBUG_TYPE_PERFORMANCE,
94 GL_DEBUG_TYPE_PUSH_GROUP,
95 GL_DEBUG_TYPE_POP_GROUP,
98 static const GLenum s_debugSeverities[] =
100 GL_DEBUG_SEVERITY_HIGH,
101 GL_DEBUG_SEVERITY_MEDIUM,
102 GL_DEBUG_SEVERITY_LOW,
103 GL_DEBUG_SEVERITY_NOTIFICATION,
106 static bool isKHRDebugSupported (Context& ctx)
108 const bool isES32 = glu::contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2));
109 return isES32 || ctx.getContextInfo().isExtensionSupported("GL_KHR_debug");
114 class DebugMessageTestContext : public NegativeTestContext
117 DebugMessageTestContext (BaseCase& host,
118 glu::RenderContext& renderCtx,
119 const glu::ContextInfo& ctxInfo,
121 tcu::ResultCollector& results,
123 ~DebugMessageTestContext (void);
125 void expectMessage (GLenum source, GLenum type);
128 BaseCase& m_debugHost;
131 class TestFunctionWrapper
134 typedef void (*CoreTestFunc)(NegativeTestContext& ctx);
135 typedef void (*DebugTestFunc)(DebugMessageTestContext& ctx);
137 TestFunctionWrapper (void);
138 explicit TestFunctionWrapper (CoreTestFunc func);
139 explicit TestFunctionWrapper (DebugTestFunc func);
141 void call (DebugMessageTestContext& ctx) const;
155 DebugTestFunc debugFn;
159 TestFunctionWrapper::TestFunctionWrapper (void)
164 TestFunctionWrapper::TestFunctionWrapper (CoreTestFunc func)
167 m_func.coreFn = func;
170 TestFunctionWrapper::TestFunctionWrapper (DebugTestFunc func)
173 m_func.debugFn = func;
176 void TestFunctionWrapper::call (DebugMessageTestContext& ctx) const
178 if (m_type == TYPE_CORE)
179 m_func.coreFn(static_cast<NegativeTestContext&>(ctx));
180 else if (m_type == TYPE_DEBUG)
186 void emitMessages (DebugMessageTestContext& ctx, GLenum source)
188 for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(s_debugTypes); typeNdx++)
190 for (int severityNdx = 0; severityNdx < DE_LENGTH_OF_ARRAY(s_debugSeverities); severityNdx++)
192 const GLenum type = s_debugTypes[typeNdx];
193 const GLenum severity = s_debugSeverities[severityNdx];
194 const string msg = string("Application generated message with type ") + glu::getDebugMessageTypeName(type)
195 + " and severity " + glu::getDebugMessageSeverityName(severity);
197 // Use severity as ID, guaranteed unique
198 ctx.glDebugMessageInsert(source, type, severity, severity, -1, msg.c_str());
199 ctx.expectMessage(source, type);
204 void application_messages (DebugMessageTestContext& ctx)
206 ctx.beginSection("Messages with source of GL_DEBUG_SOURCE_APPLICATION");
207 emitMessages(ctx, GL_DEBUG_SOURCE_APPLICATION);
211 void thirdparty_messages (DebugMessageTestContext& ctx)
213 ctx.beginSection("Messages with source of GL_DEBUG_SOURCE_THIRD_PARTY");
214 emitMessages(ctx, GL_DEBUG_SOURCE_THIRD_PARTY);
218 void push_pop_messages (DebugMessageTestContext& ctx)
220 ctx.beginSection("Push/Pop Debug Group");
222 ctx.glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 1, -1, "Application group 1");
223 ctx.expectMessage(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PUSH_GROUP);
224 ctx.glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 2, -1, "Application group 1-1");
225 ctx.expectMessage(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PUSH_GROUP);
226 ctx.glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 3, -1, "Application group 1-1-1");
227 ctx.expectMessage(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PUSH_GROUP);
228 ctx.glPopDebugGroup();
229 ctx.expectMessage(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_POP_GROUP);
230 ctx.glPopDebugGroup();
231 ctx.expectMessage(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_POP_GROUP);
233 ctx.glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 4, -1, "Application group 1-2");
234 ctx.expectMessage(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PUSH_GROUP);
235 ctx.glPopDebugGroup();
236 ctx.expectMessage(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_POP_GROUP);
238 ctx.glPushDebugGroup(GL_DEBUG_SOURCE_THIRD_PARTY, 4, -1, "3rd Party group 1-3");
239 ctx.expectMessage(GL_DEBUG_SOURCE_THIRD_PARTY, GL_DEBUG_TYPE_PUSH_GROUP);
240 ctx.glPopDebugGroup();
241 ctx.expectMessage(GL_DEBUG_SOURCE_THIRD_PARTY, GL_DEBUG_TYPE_POP_GROUP);
242 ctx.glPopDebugGroup();
243 ctx.expectMessage(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_POP_GROUP);
245 ctx.glPushDebugGroup(GL_DEBUG_SOURCE_THIRD_PARTY, 4, -1, "3rd Party group 2");
246 ctx.expectMessage(GL_DEBUG_SOURCE_THIRD_PARTY, GL_DEBUG_TYPE_PUSH_GROUP);
247 ctx.glPopDebugGroup();
248 ctx.expectMessage(GL_DEBUG_SOURCE_THIRD_PARTY, GL_DEBUG_TYPE_POP_GROUP);
253 struct FunctionContainer
255 TestFunctionWrapper function;
260 vector<FunctionContainer> getUserMessageFuncs (void)
262 FunctionContainer funcs[] =
264 { TestFunctionWrapper(application_messages), "application_messages", "Externally generated messages from the application" },
265 { TestFunctionWrapper(thirdparty_messages), "third_party_messages", "Externally generated messages from a third party" },
266 { TestFunctionWrapper(push_pop_messages), "push_pop_stack", "Messages from pushing/popping debug groups" },
269 return std::vector<FunctionContainer>(DE_ARRAY_BEGIN(funcs), DE_ARRAY_END(funcs));
272 // Data required to uniquely identify a debug message
279 MessageID (void) : source(GL_NONE), type(GL_NONE), id(0) {}
280 MessageID (GLenum source_, GLenum type_, GLuint id_) : source(source_), type(type_), id(id_) {}
282 bool operator== (const MessageID& rhs) const { return source == rhs.source && type == rhs.type && id == rhs.id;}
283 bool operator!= (const MessageID& rhs) const { return source != rhs.source || type != rhs.type || id != rhs.id;}
284 bool operator< (const MessageID& rhs) const
286 return source < rhs.source || (source == rhs.source && (type < rhs.type || (type == rhs.type && id < rhs.id)));
290 std::ostream& operator<< (std::ostream& str, const MessageID &id)
292 return str << glu::getDebugMessageSourceStr(id.source) << ", " << glu::getDebugMessageTypeStr(id.type) << ", " << id.id;
295 // All info from a single debug message
302 MessageData (void) : id(MessageID()), severity(GL_NONE) {}
303 MessageData (const MessageID& id_, GLenum severity_, const string& message_) : id(id_) , severity(severity_) , message(message_) {}
306 extern "C" typedef void GLW_APIENTRY DebugCallbackFunc(GLenum, GLenum, GLuint, GLenum, GLsizei, const char*, void*);
309 class BaseCase : public NegativeTestShared::ErrorCase
312 BaseCase (Context& ctx,
315 virtual ~BaseCase (void) {}
317 virtual IterateResult iterate (void) = 0;
319 virtual void expectMessage (GLenum source, GLenum type);
320 virtual void expectError (GLenum error0, GLenum error1);
323 struct VerificationResult {
324 const qpTestResult result;
325 const string resultMessage;
326 const string logMessage;
328 VerificationResult (qpTestResult result_, const string& resultMessage_, const string& logMessage_)
329 : result(result_), resultMessage(resultMessage_), logMessage(logMessage_) {}
332 static DebugCallbackFunc callbackHandle;
333 virtual void callback (GLenum source, GLenum type, GLuint id, GLenum severity, const std::string& message);
336 VerificationResult verifyMessageCount (const MessageID& id, GLenum severity, int refCount, int resCount, bool messageEnabled) const;
338 // Verify a single message instance against expected attributes
339 void verifyMessage (const MessageData& message, GLenum source, GLenum type, GLuint id, GLenum severity);
340 void verifyMessage (const MessageData& message, GLenum source, GLenum type);
342 bool verifyMessageExists (const MessageData& message, GLenum source, GLenum type);
343 void verifyMessageGroup (const MessageData& message, GLenum source, GLenum type);
344 void verifyMessageString (const MessageData& message);
346 bool isDebugContext (void) const;
348 tcu::ResultCollector m_results;
351 void BaseCase::callbackHandle (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const char* message, void* userParam)
353 static_cast<BaseCase*>(userParam)->callback(source, type, id, severity, string(message, &message[length]));
356 BaseCase::BaseCase (Context& ctx, const char* name, const char* desc)
357 : ErrorCase(ctx, name, desc)
361 void BaseCase::expectMessage (GLenum source, GLenum type)
367 void BaseCase::expectError (GLenum error0, GLenum error1)
369 if (error0 != GL_NO_ERROR || error1 != GL_NO_ERROR)
370 expectMessage(GL_DEBUG_SOURCE_API, GL_DEBUG_TYPE_ERROR);
372 expectMessage(GL_DONT_CARE, GL_DONT_CARE);
375 void BaseCase::callback (GLenum source, GLenum type, GLuint id, GLenum severity, const string& message)
384 BaseCase::VerificationResult BaseCase::verifyMessageCount (const MessageID& id, GLenum severity, int refCount, int resCount, bool messageEnabled) const
386 std::stringstream log;
388 // This message should not be filtered out
391 if (resCount != refCount)
394 * Technically nothing requires the implementation to be consistent in terms
395 * of the messages it produces in most situations, allowing the set of messages
396 * produced to vary between executions. This function splits messages
397 * into deterministic and non-deterministic to facilitate handling of such messages.
399 * Non-deterministic messages that are present in differing quantities in filtered and
400 * unfiltered runs will not fail the test case unless in direct violation of a filter:
401 * the implementation may produce an arbitrary number of such messages when they are
402 * not filtered out and none when they are filtered.
404 * A list of error source/type combinations with their assumed behaviour and
405 * the rationale for expecting such behaviour follows
407 * For API/shader messages we assume that the following types are deterministic:
408 * DEBUG_TYPE_ERROR Errors specified by spec and should always be produced
410 * For API messages the following types are assumed to be non-deterministic
411 * and treated as quality warnings since the underlying reported issue does not change between calls:
412 * DEBUG_TYPE_DEPRECATED_BEHAVIOR Reasonable to only report first instance
413 * DEBUG_TYPE_UNDEFINED_BEHAVIOR Reasonable to only report first instance
414 * DEBUG_TYPE_PORTABILITY Reasonable to only report first instance
416 * For API messages the following types are assumed to be non-deterministic
417 * and do not affect test results.
418 * DEBUG_TYPE_PERFORMANCE May be tied to arbitrary factors, reasonable to report only first instance
419 * DEBUG_TYPE_OTHER Definition allows arbitrary contents
421 * For 3rd party and application messages the following types are deterministic:
422 * DEBUG_TYPE_MARKER Only generated by test
423 * DEBUG_TYPE_PUSH_GROUP Only generated by test
424 * DEBUG_TYPE_POP_GROUP Only generated by test
425 * All others Only generated by test
427 * All messages with category of window system or other are treated as non-deterministic
428 * and do not effect test results since they can be assumed to be outside control of
429 * both the implementation and test case
433 const bool isDeterministic = id.source == GL_DEBUG_SOURCE_APPLICATION ||
434 id.source == GL_DEBUG_SOURCE_THIRD_PARTY ||
435 ((id.source == GL_DEBUG_SOURCE_API || id.source == GL_DEBUG_SOURCE_SHADER_COMPILER) && id.type == GL_DEBUG_TYPE_ERROR);
437 const bool canIgnore = id.source == GL_DEBUG_SOURCE_WINDOW_SYSTEM || id.source == GL_DEBUG_SOURCE_OTHER;
441 if (resCount > refCount)
443 log << "Extra instances of message were found: (" << id << ") with "
444 << glu::getDebugMessageSeverityStr(severity)
445 << " (got " << resCount << ", expected " << refCount << ")";
446 return VerificationResult(QP_TEST_RESULT_FAIL, "Extra instances of a deterministic message were present", log.str());
450 log << "Instances of message were missing: (" << id << ") with "
451 << glu::getDebugMessageSeverityStr(severity)
452 << " (got " << resCount << ", expected " << refCount << ")";
453 return VerificationResult(QP_TEST_RESULT_FAIL, "Message missing", log.str());
458 if (resCount > refCount)
460 log << "Extra instances of message were found but the message is non-deterministic(warning): (" << id << ") with "
461 << glu::getDebugMessageSeverityStr(severity)
462 << " (got " << resCount << ", expected " << refCount << ")";
463 return VerificationResult(QP_TEST_RESULT_QUALITY_WARNING, "Extra instances of a message were present", log.str());
467 log << "Instances of message were missing but the message is non-deterministic(warning): (" << id << ") with "
468 << glu::getDebugMessageSeverityStr(severity)
469 << " (got " << resCount << ", expected " << refCount << ")";
470 return VerificationResult(QP_TEST_RESULT_QUALITY_WARNING, "Message missing", log.str());
475 if (resCount > refCount)
477 log << "Extra instances of message were found but the message is non-deterministic(ignored): (" << id << ") with "
478 << glu::getDebugMessageSeverityStr(severity)
479 << " (got " << resCount << ", expected " << refCount << ")";
480 return VerificationResult(QP_TEST_RESULT_PASS, "", log.str());
484 log << "Instances of message were missing but the message is non-deterministic(ignored): (" << id << ") with "
485 << glu::getDebugMessageSeverityStr(severity)
486 << " (got " << resCount << ", expected " << refCount << ")";
487 return VerificationResult(QP_TEST_RESULT_PASS, "", log.str());
491 else // Passed as appropriate
493 log << "Message was found when expected: ("<< id << ") with "
494 << glu::getDebugMessageSeverityStr(severity);
495 return VerificationResult(QP_TEST_RESULT_PASS, "", log.str());
498 // Message should be filtered out
504 log << "Message was excluded correctly: (" << id << ") with "
505 << glu::getDebugMessageSeverityStr(severity);
506 return VerificationResult(QP_TEST_RESULT_PASS, "", log.str());
508 // Only present in filtered run (ERROR)
509 else if (resCount > 0 && refCount == 0)
511 log << "A message was not excluded as it should have been: (" << id << ") with "
512 << glu::getDebugMessageSeverityStr(severity)
513 << ". This message was not present in the reference run";
514 return VerificationResult(QP_TEST_RESULT_FAIL, "A message was not filtered out", log.str());
516 // Present in both runs (ERROR)
519 log << "A message was not excluded as it should have been: (" << id << ") with "
520 << glu::getDebugMessageSeverityStr(severity);
521 return VerificationResult(QP_TEST_RESULT_FAIL, "A message was not filtered out", log.str());
526 // Return true if message needs further verification
527 bool BaseCase::verifyMessageExists (const MessageData& message, GLenum source, GLenum type)
529 TestLog& log = m_testCtx.getLog();
531 if (source == GL_DONT_CARE || type == GL_DONT_CARE)
533 else if (message.id.source == GL_NONE || message.id.type == GL_NONE)
535 if (isDebugContext())
537 m_results.addResult(QP_TEST_RESULT_FAIL, "Message was not reported as expected");
538 log << TestLog::Message << "A message was expected but none was reported" << TestLog::EndMessage;
542 m_results.addResult(QP_TEST_RESULT_QUALITY_WARNING, "Verification accuracy is lacking without a debug context");
543 log << TestLog::Message << "A message was expected but none was reported. Running without a debug context" << TestLog::EndMessage;
551 void BaseCase::verifyMessageGroup (const MessageData& message, GLenum source, GLenum type)
553 TestLog& log = m_testCtx.getLog();
555 if (message.id.source != source)
557 m_results.addResult(QP_TEST_RESULT_FAIL, "Incorrect message source");
558 log << TestLog::Message << "Message source was " << glu::getDebugMessageSourceStr(message.id.source)
559 << " when it should have been " << glu::getDebugMessageSourceStr(source) << TestLog::EndMessage;
562 if (message.id.type != type)
564 m_results.addResult(QP_TEST_RESULT_FAIL, "Incorrect message type");
565 log << TestLog::Message << "Message type was " << glu::getDebugMessageTypeStr(message.id.type)
566 << " when it should have been " << glu::getDebugMessageTypeStr(type) << TestLog::EndMessage;
570 void BaseCase::verifyMessageString (const MessageData& message)
572 TestLog& log = m_testCtx.getLog();
574 log << TestLog::Message << "Driver says: \"" << message.message << "\"" << TestLog::EndMessage;
576 if (message.message.empty())
578 m_results.addResult(QP_TEST_RESULT_QUALITY_WARNING, "Empty message");
579 log << TestLog::Message << "Message message was empty" << TestLog::EndMessage;
583 void BaseCase::verifyMessage (const MessageData& message, GLenum source, GLenum type)
585 if (verifyMessageExists(message, source, type))
587 verifyMessageString(message);
588 verifyMessageGroup(message, source, type);
592 void BaseCase::verifyMessage (const MessageData& message, GLenum source, GLenum type, GLuint id, GLenum severity)
594 TestLog& log = m_testCtx.getLog();
596 if (verifyMessageExists(message, source, type))
598 verifyMessageString(message);
599 verifyMessageGroup(message, source, type);
601 if (message.id.id != id)
603 m_results.addResult(QP_TEST_RESULT_FAIL, "Incorrect message id");
604 log << TestLog::Message << "Message id was " << message.id.id
605 << " when it should have been " << id << TestLog::EndMessage;
608 if (message.severity != severity)
610 m_results.addResult(QP_TEST_RESULT_FAIL, "Incorrect message severity");
611 log << TestLog::Message << "Message severity was " << glu::getDebugMessageSeverityStr(message.severity)
612 << " when it should have been " << glu::getDebugMessageSeverityStr(severity) << TestLog::EndMessage;
617 bool BaseCase::isDebugContext (void) const
619 return (m_context.getRenderContext().getType().getFlags() & glu::CONTEXT_DEBUG) != 0;
622 // Generate errors, verify that each error results in a callback call
623 class CallbackErrorCase : public BaseCase
626 CallbackErrorCase (Context& ctx,
629 TestFunctionWrapper errorFunc);
630 virtual ~CallbackErrorCase (void) {}
632 virtual IterateResult iterate (void);
634 virtual void expectMessage (GLenum source, GLenum type);
637 virtual void callback (GLenum source, GLenum type, GLuint id, GLenum severity, const string& message);
639 const TestFunctionWrapper m_errorFunc;
640 MessageData m_lastMessage;
643 CallbackErrorCase::CallbackErrorCase (Context& ctx,
646 TestFunctionWrapper errorFunc)
647 : BaseCase (ctx, name, desc)
648 , m_errorFunc (errorFunc)
652 CallbackErrorCase::IterateResult CallbackErrorCase::iterate (void)
654 TCU_CHECK_AND_THROW(NotSupportedError, isKHRDebugSupported(m_context), "GL_KHR_debug is not supported");
656 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
657 tcu::TestLog& log = m_testCtx.getLog();
658 DebugMessageTestContext context = DebugMessageTestContext(*this, m_context.getRenderContext(), m_context.getContextInfo(), log, m_results, true);
660 gl.enable(GL_DEBUG_OUTPUT);
661 gl.enable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
662 gl.debugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, DE_NULL, false); // disable all
663 gl.debugMessageControl(GL_DEBUG_SOURCE_API, GL_DEBUG_TYPE_ERROR, GL_DONT_CARE, 0, DE_NULL, true); // enable API errors
664 gl.debugMessageControl(GL_DEBUG_SOURCE_APPLICATION, GL_DONT_CARE, GL_DONT_CARE, 0, DE_NULL, true); // enable application messages
665 gl.debugMessageControl(GL_DEBUG_SOURCE_THIRD_PARTY, GL_DONT_CARE, GL_DONT_CARE, 0, DE_NULL, true); // enable third party messages
666 gl.debugMessageCallback(callbackHandle, this);
668 m_errorFunc.call(context);
670 gl.debugMessageCallback(DE_NULL, DE_NULL);
671 gl.disable(GL_DEBUG_OUTPUT);
673 m_results.setTestContextResult(m_testCtx);
678 void CallbackErrorCase::expectMessage (GLenum source, GLenum type)
680 verifyMessage(m_lastMessage, source, type);
681 m_lastMessage = MessageData();
683 // Reset error so that code afterwards (such as glu::ShaderProgram) doesn't break because of
684 // lingering error state.
685 m_context.getRenderContext().getFunctions().getError();
688 void CallbackErrorCase::callback (GLenum source, GLenum type, GLuint id, GLenum severity, const string& message)
690 m_lastMessage = MessageData(MessageID(source, type, id), severity, message);
693 // Generate errors, verify that each error results in a log entry
694 class LogErrorCase : public BaseCase
697 LogErrorCase (Context& context,
700 TestFunctionWrapper errorFunc);
701 virtual ~LogErrorCase (void) {}
703 virtual IterateResult iterate (void);
705 virtual void expectMessage (GLenum source, GLenum type);
708 const TestFunctionWrapper m_errorFunc;
709 MessageData m_lastMessage;
712 LogErrorCase::LogErrorCase (Context& ctx,
715 TestFunctionWrapper errorFunc)
716 : BaseCase (ctx, name, desc)
717 , m_errorFunc (errorFunc)
721 LogErrorCase::IterateResult LogErrorCase::iterate (void)
723 TCU_CHECK_AND_THROW(NotSupportedError, isKHRDebugSupported(m_context), "GL_KHR_debug is not supported");
725 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
726 tcu::TestLog& log = m_testCtx.getLog();
727 DebugMessageTestContext context = DebugMessageTestContext(*this, m_context.getRenderContext(), m_context.getContextInfo(), log, m_results, true);
730 gl.enable(GL_DEBUG_OUTPUT);
731 gl.enable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
732 gl.debugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, DE_NULL, false); // disable all
733 gl.debugMessageControl(GL_DEBUG_SOURCE_API, GL_DEBUG_TYPE_ERROR, GL_DONT_CARE, 0, DE_NULL, true); // enable API errors
734 gl.debugMessageCallback(DE_NULL, DE_NULL); // enable logging
735 gl.getIntegerv(GL_DEBUG_LOGGED_MESSAGES, &numMsg);
736 gl.getDebugMessageLog(numMsg, 0, DE_NULL, DE_NULL, DE_NULL, DE_NULL, DE_NULL, DE_NULL); // clear log
738 m_errorFunc.call(context);
740 gl.disable(GL_DEBUG_OUTPUT);
741 m_results.setTestContextResult(m_testCtx);
746 void LogErrorCase::expectMessage (GLenum source, GLenum type)
748 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
750 TestLog& log = m_testCtx.getLog();
753 if (source == GL_DONT_CARE || type == GL_DONT_CARE)
756 gl.getIntegerv(GL_DEBUG_LOGGED_MESSAGES, &numMsg);
760 if (isDebugContext())
762 m_results.addResult(QP_TEST_RESULT_FAIL, "Error was not reported as expected");
763 log << TestLog::Message << "A message was expected but none was reported (empty message log)" << TestLog::EndMessage;
767 m_results.addResult(QP_TEST_RESULT_QUALITY_WARNING, "Verification accuracy is lacking without a debug context");
768 log << TestLog::Message << "A message was expected but none was reported (empty message log). Running without a debug context" << TestLog::EndMessage;
773 // There may be messages other than the error we are looking for in the log.
774 // Strictly nothing prevents the implementation from producing more than the
775 // required error from an API call with a defined error. however we assume that
776 // since calls that produce an error should not change GL state the implementation
777 // should have nothing else to report.
779 gl.getDebugMessageLog(numMsg-1, 0, DE_NULL, DE_NULL, DE_NULL, DE_NULL, DE_NULL, DE_NULL); // Clear all but last
783 gl.getIntegerv(GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH, &msgLen);
785 TCU_CHECK_MSG(msgLen >= 0, "Negative message length");
786 TCU_CHECK_MSG(msgLen < 100000, "Excessively long message");
788 lastMsg.message.resize(msgLen);
789 gl.getDebugMessageLog(1, msgLen, &lastMsg.id.source, &lastMsg.id.type, &lastMsg.id.id, &lastMsg.severity, &msgLen, &lastMsg.message[0]);
792 log << TestLog::Message << "Driver says: \"" << lastMsg.message << "\"" << TestLog::EndMessage;
794 verifyMessage(lastMsg, source, type);
796 // Reset error so that code afterwards (such as glu::ShaderProgram) doesn't break because of
797 // lingering error state.
798 m_context.getRenderContext().getFunctions().getError();
801 // Generate errors, verify that calling glGetError afterwards produces desired result
802 class GetErrorCase : public BaseCase
805 GetErrorCase (Context& ctx,
808 TestFunctionWrapper errorFunc);
809 virtual ~GetErrorCase (void) {}
811 virtual IterateResult iterate (void);
813 virtual void expectMessage (GLenum source, GLenum type);
814 virtual void expectError (glw::GLenum error0, glw::GLenum error1);
817 const TestFunctionWrapper m_errorFunc;
820 GetErrorCase::GetErrorCase (Context& ctx,
823 TestFunctionWrapper errorFunc)
824 : BaseCase (ctx, name, desc)
825 , m_errorFunc (errorFunc)
829 GetErrorCase::IterateResult GetErrorCase::iterate (void)
831 tcu::TestLog& log = m_testCtx.getLog();
832 DebugMessageTestContext context = DebugMessageTestContext(*this, m_context.getRenderContext(), m_context.getContextInfo(), log, m_results, true);
834 m_errorFunc.call(context);
836 m_results.setTestContextResult(m_testCtx);
841 void GetErrorCase::expectMessage (GLenum source, GLenum type)
845 DE_FATAL("GetErrorCase cannot handle anything other than error codes");
848 void GetErrorCase::expectError (glw::GLenum error0, glw::GLenum error1)
850 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
851 TestLog& log = m_testCtx.getLog();
853 const GLenum result = gl.getError();
855 if (result != error0 && result != error1)
857 m_results.addResult(QP_TEST_RESULT_FAIL, "Incorrect error was reported");
858 if (error0 == error1)
859 log << TestLog::Message
860 << glu::getErrorStr(error0) << " was expected but got "
861 << glu::getErrorStr(result)
862 << TestLog::EndMessage;
864 log << TestLog::Message
865 << glu::getErrorStr(error0) << " or "
866 << glu::getErrorStr(error1) << " was expected but got "
867 << glu::getErrorStr(result)
868 << TestLog::EndMessage;
873 // Generate errors, log the types, disable some, regenerate errors, verify correct errors (not)reported
874 class FilterCase : public BaseCase
877 FilterCase (Context& ctx,
880 const vector<TestFunctionWrapper>& errorFuncs);
881 virtual ~FilterCase (void) {}
883 virtual IterateResult iterate (void);
885 virtual void expectMessage (GLenum source, GLenum type);
890 MessageFilter() : source(GL_DONT_CARE), type(GL_DONT_CARE), severity(GL_DONT_CARE), enabled(true) {} // Default to enable all
891 MessageFilter(GLenum source_, GLenum type_, GLenum severity_, const vector<GLuint>& ids_, bool enabled_) : source(source_), type(type_), severity(severity_), ids(ids_), enabled(enabled_) {}
900 virtual void callback (GLenum source, GLenum type, GLuint id, GLenum severity, const string& message);
902 vector<MessageData> genMessages (bool uselog, const string& desc);
904 vector<MessageFilter> genFilters (const vector<MessageData>& messages, const vector<MessageFilter>& initial, deUint32 seed, int iterations) const;
905 void applyFilters (const vector<MessageFilter>& filters) const;
906 bool isEnabled (const vector<MessageFilter>& filters, const MessageData& message) const;
908 void verify (const vector<MessageData>& refMessages,
909 const vector<MessageData>& filteredMessages,
910 const vector<MessageFilter>& filters);
912 const vector<TestFunctionWrapper> m_errorFuncs;
914 vector<MessageData>* m_currentErrors;
917 FilterCase::FilterCase (Context& ctx,
920 const vector<TestFunctionWrapper>& errorFuncs)
921 : BaseCase (ctx, name, desc)
922 , m_errorFuncs (errorFuncs)
923 , m_currentErrors (DE_NULL)
927 FilterCase::IterateResult FilterCase::iterate (void)
929 TCU_CHECK_AND_THROW(NotSupportedError, isKHRDebugSupported(m_context), "GL_KHR_debug is not supported");
931 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
933 gl.enable(GL_DEBUG_OUTPUT);
934 gl.enable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
935 gl.debugMessageCallback(callbackHandle, this);
939 gl.debugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, DE_NULL, true);
942 const vector<MessageData> refMessages = genMessages(true, "Reference run");
943 const MessageFilter baseFilter (GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, vector<GLuint>(), true);
944 const deUint32 baseSeed = deStringHash(getName()) ^ m_testCtx.getCommandLine().getBaseSeed();
945 const vector<MessageFilter> filters = genFilters(refMessages, vector<MessageFilter>(1, baseFilter), baseSeed, 4);
946 vector<MessageData> filteredMessages;
948 applyFilters(filters);
951 filteredMessages = genMessages(false, "Filtered run");
954 verify(refMessages, filteredMessages, filters);
956 if (!isDebugContext() && refMessages.empty())
957 m_results.addResult(QP_TEST_RESULT_QUALITY_WARNING, "Verification accuracy is lacking without a debug context");
962 gl.disable(GL_DEBUG_OUTPUT);
963 gl.debugMessageCallback(DE_NULL, DE_NULL);
967 gl.disable(GL_DEBUG_OUTPUT);
968 gl.debugMessageCallback(DE_NULL, DE_NULL);
969 m_results.setTestContextResult(m_testCtx);
974 void FilterCase::expectMessage (GLenum source, GLenum type)
980 void FilterCase::callback (GLenum source, GLenum type, GLuint id, GLenum severity, const string& message)
983 m_currentErrors->push_back(MessageData(MessageID(source, type, id), severity, message));
986 vector<MessageData> FilterCase::genMessages (bool uselog, const string& desc)
988 tcu::TestLog& log = m_testCtx.getLog();
989 DebugMessageTestContext context = DebugMessageTestContext(*this, m_context.getRenderContext(), m_context.getContextInfo(), log, m_results, uselog);
990 tcu::ScopedLogSection section (log, "message gen", desc);
991 vector<MessageData> messages;
993 m_currentErrors = &messages;
995 for (int ndx = 0; ndx < int(m_errorFuncs.size()); ndx++)
996 m_errorFuncs[ndx].call(context);
998 m_currentErrors = DE_NULL;
1003 vector<FilterCase::MessageFilter> FilterCase::genFilters (const vector<MessageData>& messages, const vector<MessageFilter>& initial, deUint32 seed, int iterations) const
1005 de::Random rng (seed ^ deInt32Hash(deStringHash(getName())));
1007 set<MessageID> tempMessageIds;
1008 set<GLenum> tempSources;
1009 set<GLenum> tempTypes;
1010 set<GLenum> tempSeverities;
1012 if (messages.empty())
1015 for (int ndx = 0; ndx < int(messages.size()); ndx++)
1017 const MessageData& msg = messages[ndx];
1019 tempMessageIds.insert(msg.id);
1020 tempSources.insert(msg.id.source);
1021 tempTypes.insert(msg.id.type);
1022 tempSeverities.insert(msg.severity);
1026 // Fetchable by index
1027 const vector<MessageID> messageIds (tempMessageIds.begin(), tempMessageIds.end());
1028 const vector<GLenum> sources (tempSources.begin(), tempSources.end());
1029 const vector<GLenum> types (tempTypes.begin(), tempTypes.end());
1030 const vector<GLenum> severities (tempSeverities.begin(), tempSeverities.end());
1032 vector<MessageFilter> filters = initial;
1034 for (int iteration = 0; iteration < iterations; iteration++)
1036 switch(rng.getInt(0, 8)) // Distribute so that per-message randomization (the default branch) is prevalent
1040 const GLenum source = sources[rng.getInt(0, int(sources.size()-1))];
1041 const bool enabled = rng.getBool();
1043 filters.push_back(MessageFilter(source, GL_DONT_CARE, GL_DONT_CARE, vector<GLuint>(), enabled));
1049 const GLenum type = types[rng.getUint32()%types.size()];
1050 const bool enabled = rng.getBool();
1052 filters.push_back(MessageFilter(GL_DONT_CARE, type, GL_DONT_CARE, vector<GLuint>(), enabled));
1058 const GLenum severity = severities[rng.getUint32()%severities.size()];
1059 const bool enabled = rng.getBool();
1061 filters.push_back(MessageFilter(GL_DONT_CARE, GL_DONT_CARE, severity, vector<GLuint>(), enabled));
1067 const int start = rng.getInt(0, int(messageIds.size()));
1069 for (int itr = 0; itr < 4; itr++)
1071 const MessageID& id = messageIds[(start+itr)%messageIds.size()];
1072 const bool enabled = rng.getBool();
1074 filters.push_back(MessageFilter(id.source, id.type, GL_DONT_CARE, vector<GLuint>(1, id.id), enabled));
1084 void FilterCase::applyFilters (const vector<MessageFilter>& filters) const
1086 TestLog& log = m_testCtx.getLog();
1087 const tcu::ScopedLogSection section (log, "", "Setting message filters");
1088 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1090 for (size_t filterNdx = 0; filterNdx < filters.size(); filterNdx++)
1092 const MessageFilter& filter = filters[filterNdx];
1094 if (filter.ids.empty())
1095 log << TestLog::Message << "Setting messages with"
1096 << " source " << glu::getDebugMessageSourceStr(filter.source)
1097 << ", type " << glu::getDebugMessageTypeStr(filter.type)
1098 << " and severity " << glu::getDebugMessageSeverityStr(filter.severity)
1099 << (filter.enabled ? " to enabled" : " to disabled")
1100 << TestLog::EndMessage;
1103 for (size_t ndx = 0; ndx < filter.ids.size(); ndx++)
1104 log << TestLog::Message << "Setting message (" << MessageID(filter.source, filter.type, filter.ids[ndx]) << ") to " << (filter.enabled ? "enabled" : "disabled") << TestLog::EndMessage;
1107 gl.debugMessageControl(filter.source, filter.type, filter.severity, GLsizei(filter.ids.size()), filter.ids.empty() ? DE_NULL : &filter.ids[0], filter.enabled);
1111 bool FilterCase::isEnabled (const vector<MessageFilter>& filters, const MessageData& message) const
1115 for (size_t filterNdx = 0; filterNdx < filters.size(); filterNdx++)
1117 const MessageFilter& filter = filters[filterNdx];
1119 if (filter.ids.empty())
1121 if (filter.source != GL_DONT_CARE && filter.source != message.id.source)
1124 if (filter.type != GL_DONT_CARE && filter.type != message.id.type)
1127 if (filter.severity != GL_DONT_CARE && filter.severity != message.severity)
1132 DE_ASSERT(filter.source != GL_DONT_CARE);
1133 DE_ASSERT(filter.type != GL_DONT_CARE);
1134 DE_ASSERT(filter.severity == GL_DONT_CARE);
1136 if (filter.source != message.id.source || filter.type != message.id.type)
1139 if (!de::contains(filter.ids.begin(), filter.ids.end(), message.id.id))
1143 retval = filter.enabled;
1155 MessageMeta (void) : refCount(0), resCount(0), severity(GL_NONE) {}
1158 void FilterCase::verify (const vector<MessageData>& refMessages, const vector<MessageData>& resMessages, const vector<MessageFilter>& filters)
1160 TestLog& log = m_testCtx.getLog();
1161 map<MessageID, MessageMeta> counts;
1163 log << TestLog::Section("verification", "Verifying");
1165 // Gather message counts & severities, report severity mismatches if found
1166 for (size_t refNdx = 0; refNdx < refMessages.size(); refNdx++)
1168 const MessageData& msg = refMessages[refNdx];
1169 MessageMeta& meta = counts[msg.id];
1171 if (meta.severity != GL_NONE && meta.severity != msg.severity)
1173 log << TestLog::Message << "A message has variable severity between instances: (" << msg.id << ") with severity "
1174 << glu::getDebugMessageSeverityStr(meta.severity) << " and " << glu::getDebugMessageSeverityStr(msg.severity) << TestLog::EndMessage;
1175 m_results.addResult(QP_TEST_RESULT_FAIL, "Message severity changed between instances of the same message");
1179 meta.severity = msg.severity;
1182 for (size_t resNdx = 0; resNdx < resMessages.size(); resNdx++)
1184 const MessageData& msg = resMessages[resNdx];
1185 MessageMeta& meta = counts[msg.id];
1187 if (meta.severity != GL_NONE && meta.severity != msg.severity)
1189 log << TestLog::Message << "A message has variable severity between instances: (" << msg.id << ") with severity "
1190 << glu::getDebugMessageSeverityStr(meta.severity) << " and " << glu::getDebugMessageSeverityStr(msg.severity) << TestLog::EndMessage;
1191 m_results.addResult(QP_TEST_RESULT_FAIL, "Message severity changed between instances of the same message");
1195 meta.severity = msg.severity;
1198 for (map<MessageID, MessageMeta>::const_iterator itr = counts.begin(); itr != counts.end(); itr++)
1200 const MessageID& id = itr->first;
1201 const GLenum severity = itr->second.severity;
1203 const int refCount = itr->second.refCount;
1204 const int resCount = itr->second.resCount;
1205 const bool enabled = isEnabled(filters, MessageData(id, severity, ""));
1207 VerificationResult result = verifyMessageCount(id, severity, refCount, resCount, enabled);
1209 log << TestLog::Message << result.logMessage << TestLog::EndMessage;
1211 if (result.result != QP_TEST_RESULT_PASS)
1212 m_results.addResult(result.result, result.resultMessage);
1215 log << TestLog::EndSection;
1218 // Filter case that uses debug groups
1219 class GroupFilterCase : public FilterCase
1222 GroupFilterCase (Context& ctx,
1225 const vector<TestFunctionWrapper>& errorFuncs);
1226 virtual ~GroupFilterCase (void) {}
1228 virtual IterateResult iterate (void);
1231 GroupFilterCase::GroupFilterCase (Context& ctx,
1234 const vector<TestFunctionWrapper>& errorFuncs)
1235 : FilterCase(ctx, name, desc, errorFuncs)
1239 template<typename T>
1240 vector<T> join(const vector<T>& a, const vector<T>&b)
1244 retval.reserve(a.size()+b.size());
1245 retval.insert(retval.end(), a.begin(), a.end());
1246 retval.insert(retval.end(), b.begin(), b.end());
1250 GroupFilterCase::IterateResult GroupFilterCase::iterate (void)
1252 TCU_CHECK_AND_THROW(NotSupportedError, isKHRDebugSupported(m_context), "GL_KHR_debug is not supported");
1254 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1255 tcu::TestLog& log = m_testCtx.getLog();
1257 gl.enable(GL_DEBUG_OUTPUT);
1258 gl.enable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
1259 gl.debugMessageCallback(callbackHandle, this);
1263 gl.debugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, DE_NULL, true);
1267 // Generate reference (all errors)
1268 const vector<MessageData> refMessages = genMessages(true, "Reference run");
1269 const deUint32 baseSeed = deStringHash(getName()) ^ m_testCtx.getCommandLine().getBaseSeed();
1270 const MessageFilter baseFilter (GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, vector<GLuint>(), true);
1271 const vector<MessageFilter> filter0 = genFilters(refMessages, vector<MessageFilter>(1, baseFilter), baseSeed, 4);
1272 vector<MessageData> resMessages0;
1274 applyFilters(filter0);
1276 resMessages0 = genMessages(false, "Filtered run, default debug group");
1278 // Initial verification
1279 verify(refMessages, resMessages0, filter0);
1282 // Generate reference (filters inherited from parent)
1283 const vector<MessageFilter> filter1base = genFilters(refMessages, vector<MessageFilter>(), baseSeed ^ 0xDEADBEEF, 4);
1284 const vector<MessageFilter> filter1full = join(filter0, filter1base);
1285 tcu::ScopedLogSection section1 (log, "", "Pushing Debug Group");
1286 vector<MessageData> resMessages1;
1288 gl.pushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 1, -1, "Test Group");
1289 applyFilters(filter1base);
1291 // First nested verification
1292 resMessages1 = genMessages(false, "Filtered run, pushed one debug group");
1293 verify(refMessages, resMessages1, filter1full);
1296 // Generate reference (filters iherited again)
1297 const vector<MessageFilter> filter2base = genFilters(refMessages, vector<MessageFilter>(), baseSeed ^ 0x43211234, 4);
1298 const vector<MessageFilter> filter2full = join(filter1full, filter2base);
1299 tcu::ScopedLogSection section2 (log, "", "Pushing Debug Group");
1300 vector<MessageData> resMessages2;
1302 gl.pushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 1, -1, "Nested Test Group");
1303 applyFilters(filter2base);
1305 // Second nested verification
1306 resMessages2 = genMessages(false, "Filtered run, pushed two debug groups");
1307 verify(refMessages, resMessages2, filter2full);
1312 // First restore verification
1313 resMessages1 = genMessages(false, "Filtered run, popped second debug group");
1314 verify(refMessages, resMessages1, filter1full);
1319 // restore verification
1320 resMessages0 = genMessages(false, "Filtered run, popped first debug group");
1321 verify(refMessages, resMessages0, filter0);
1323 if (!isDebugContext() && refMessages.empty())
1324 m_results.addResult(QP_TEST_RESULT_QUALITY_WARNING, "Verification accuracy is lacking without a debug context");
1329 gl.disable(GL_DEBUG_OUTPUT);
1330 gl.debugMessageCallback(DE_NULL, DE_NULL);
1334 gl.disable(GL_DEBUG_OUTPUT);
1335 gl.debugMessageCallback(DE_NULL, DE_NULL);
1336 m_results.setTestContextResult(m_testCtx);
1340 // Basic grouping functionality
1341 class GroupCase : public BaseCase
1344 GroupCase (Context& ctx,
1347 virtual ~GroupCase () {}
1349 virtual IterateResult iterate (void);
1352 virtual void callback (GLenum source, GLenum type, GLuint id, GLenum severity, const string& message);
1354 MessageData m_lastMessage;
1357 GroupCase::GroupCase (Context& ctx,
1360 : BaseCase(ctx, name, desc)
1364 GroupCase::IterateResult GroupCase::iterate (void)
1366 TCU_CHECK_AND_THROW(NotSupportedError, isKHRDebugSupported(m_context), "GL_KHR_debug is not supported");
1368 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1369 tcu::TestLog& log = m_testCtx.getLog();
1370 glu::CallLogWrapper wrapper (gl, log);
1372 gl.enable(GL_DEBUG_OUTPUT);
1373 gl.enable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
1374 gl.debugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, DE_NULL, false); // disable all
1375 gl.debugMessageControl(GL_DEBUG_SOURCE_API, GL_DEBUG_TYPE_ERROR, GL_DONT_CARE, 0, DE_NULL, true); // enable API errors
1376 gl.debugMessageControl(GL_DEBUG_SOURCE_APPLICATION, GL_DONT_CARE, GL_DONT_CARE, 0, DE_NULL, true); // enable application messages
1377 gl.debugMessageControl(GL_DEBUG_SOURCE_THIRD_PARTY, GL_DONT_CARE, GL_DONT_CARE, 0, DE_NULL, true); // enable third party messages
1378 gl.debugMessageCallback(callbackHandle, this);
1380 wrapper.enableLogging(true);
1381 wrapper.glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 1234, -1, "Pushed debug stack");
1382 verifyMessage(m_lastMessage, GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PUSH_GROUP, 1234, GL_DEBUG_SEVERITY_NOTIFICATION);
1383 wrapper.glPopDebugGroup();
1384 verifyMessage(m_lastMessage, GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_POP_GROUP, 1234, GL_DEBUG_SEVERITY_NOTIFICATION);
1386 wrapper.glPushDebugGroup(GL_DEBUG_SOURCE_THIRD_PARTY, 4231, -1, "Pushed debug stack");
1387 verifyMessage(m_lastMessage, GL_DEBUG_SOURCE_THIRD_PARTY, GL_DEBUG_TYPE_PUSH_GROUP, 4231, GL_DEBUG_SEVERITY_NOTIFICATION);
1388 wrapper.glPopDebugGroup();
1389 verifyMessage(m_lastMessage, GL_DEBUG_SOURCE_THIRD_PARTY, GL_DEBUG_TYPE_POP_GROUP, 4231, GL_DEBUG_SEVERITY_NOTIFICATION);
1391 gl.debugMessageCallback(DE_NULL, DE_NULL);
1392 gl.disable(GL_DEBUG_OUTPUT);
1394 m_results.setTestContextResult(m_testCtx);
1399 void GroupCase::callback (GLenum source, GLenum type, GLuint id, GLenum severity, const string& message)
1401 m_lastMessage = MessageData(MessageID(source, type, id), severity, message);
1404 // Asynchronous debug output
1405 class AsyncCase : public BaseCase
1408 AsyncCase (Context& ctx,
1411 const vector<TestFunctionWrapper>& errorFuncs,
1413 virtual ~AsyncCase (void) {}
1415 virtual IterateResult iterate (void);
1417 virtual void expectMessage (glw::GLenum source, glw::GLenum type);
1425 MessageCount(void) : received(0), expected(0) {}
1427 typedef map<MessageID, MessageCount> MessageCounter;
1438 virtual void callback (glw::GLenum source, glw::GLenum type, glw::GLuint id, glw::GLenum severity, const std::string& message);
1439 VerifyState verify (bool uselog);
1440 void fetchLogMessages (void);
1442 const vector<TestFunctionWrapper> m_errorFuncs;
1443 const bool m_useCallbacks;
1445 MessageCounter m_counts;
1450 AsyncCase::AsyncCase (Context& ctx,
1453 const vector<TestFunctionWrapper>& errorFuncs,
1455 : BaseCase (ctx, name, desc)
1456 , m_errorFuncs (errorFuncs)
1457 , m_useCallbacks (useCallbacks)
1461 AsyncCase::IterateResult AsyncCase::iterate (void)
1463 TCU_CHECK_AND_THROW(NotSupportedError, isKHRDebugSupported(m_context), "GL_KHR_debug is not supported");
1465 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1466 tcu::TestLog& log = m_testCtx.getLog();
1467 DebugMessageTestContext context = DebugMessageTestContext(*this, m_context.getRenderContext(), m_context.getContextInfo(), log, m_results, true);
1468 const int maxWait = 10000; // ms
1469 const int warnWait = 100;
1471 // Clear log from earlier messages
1473 GLint numMessages = 0;
1474 gl.getIntegerv(GL_DEBUG_LOGGED_MESSAGES, &numMessages);
1475 gl.getDebugMessageLog(numMessages, 0, DE_NULL, DE_NULL, DE_NULL, DE_NULL, DE_NULL, DE_NULL);
1478 gl.enable(GL_DEBUG_OUTPUT);
1479 gl.enable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
1480 gl.debugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, DE_NULL, false);
1482 // Some messages could be dependent on the value of DEBUG_OUTPUT_SYNCHRONOUS so only use API errors which should be generated in all cases
1483 gl.debugMessageControl(GL_DEBUG_SOURCE_API, GL_DEBUG_TYPE_ERROR, GL_DONT_CARE, 0, DE_NULL, true);
1485 if (m_useCallbacks) // will use log otherwise
1486 gl.debugMessageCallback(callbackHandle, this);
1488 gl.debugMessageCallback(DE_NULL, DE_NULL);
1490 // Reference run (synchoronous)
1492 tcu::ScopedLogSection section(log, "reference run", "Reference run (synchronous)");
1494 for (int ndx = 0; ndx < int(m_errorFuncs.size()); ndx++)
1495 m_errorFuncs[ndx].call(context);
1498 if (m_counts.empty())
1500 if (!isDebugContext())
1501 m_results.addResult(QP_TEST_RESULT_QUALITY_WARNING, "Need debug context to guarantee implementation behaviour (see command line options)");
1503 log << TestLog::Message << "Reference run produced no messages, nothing to verify" << TestLog::EndMessage;
1505 gl.debugMessageCallback(DE_NULL, DE_NULL);
1506 gl.disable(GL_DEBUG_OUTPUT);
1508 m_results.setTestContextResult(m_testCtx);
1512 for (MessageCounter::iterator itr = m_counts.begin(); itr != m_counts.end(); itr++)
1514 itr->second.expected = itr->second.received;
1515 itr->second.received = 0;
1518 gl.disable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
1520 // Result run (async)
1521 for (int ndx = 0; ndx < int(m_errorFuncs.size()); ndx++)
1522 m_errorFuncs[ndx].call(context);
1524 // Repatedly try verification, new results may be added to m_receivedMessages at any time
1526 tcu::ScopedLogSection section (log, "result run", "Result run (asynchronous)");
1527 VerifyState lastTimelyState = VERIFY_FAIL;
1529 for (int waited = 0;;)
1531 const VerifyState pass = verify(false);
1532 const int wait = de::max(50, waited>>2);
1534 // Pass (possibly due to time limit)
1535 if (pass == VERIFY_PASS || (pass == VERIFY_MINIMUM && waited >= maxWait))
1537 verify(true); // log
1539 // State changed late
1540 if (waited >= warnWait && lastTimelyState != pass)
1541 m_results.addResult(QP_TEST_RESULT_QUALITY_WARNING, "Async messages were returned to application somewhat slowly");
1543 log << TestLog::Message << "Passed after ~" << waited << "ms of waiting" << TestLog::EndMessage;
1547 else if (waited >= maxWait)
1549 verify(true); // log
1551 log << TestLog::Message << "Waited for ~" << waited << "ms without getting all expected messages" << TestLog::EndMessage;
1552 m_results.addResult(QP_TEST_RESULT_FAIL, "Async messages were not returned to application within a reasonable timeframe");
1556 if (waited < warnWait)
1557 lastTimelyState = pass;
1562 if (!m_useCallbacks)
1567 gl.debugMessageCallback(DE_NULL, DE_NULL);
1569 gl.disable(GL_DEBUG_OUTPUT);
1570 m_results.setTestContextResult(m_testCtx);
1575 void AsyncCase::expectMessage (GLenum source, GLenum type)
1577 // Good time to clean up the queue as this should be called after most messages are generated
1578 if (!m_useCallbacks)
1585 void AsyncCase::callback (GLenum source, GLenum type, GLuint id, GLenum severity, const string& message)
1587 DE_ASSERT(m_useCallbacks);
1591 de::ScopedLock lock(m_mutex);
1593 m_counts[MessageID(source, type, id)].received++;
1596 // 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
1597 void AsyncCase::fetchLogMessages (void)
1599 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1602 gl.getIntegerv(GL_DEBUG_LOGGED_MESSAGES, &numMsg);
1604 for(int msgNdx = 0; msgNdx < numMsg; msgNdx++)
1609 gl.getIntegerv(GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH, &msgLen);
1611 TCU_CHECK_MSG(msgLen >= 0, "Negative message length");
1612 TCU_CHECK_MSG(msgLen < 100000, "Excessively long message");
1614 msg.message.resize(msgLen);
1615 gl.getDebugMessageLog(1, msgLen, &msg.id.source, &msg.id.type, &msg.id.id, &msg.severity, &msgLen, &msg.message[0]);
1618 const de::ScopedLock lock(m_mutex); // Don't block during API call
1620 m_counts[MessageID(msg.id)].received++;
1625 AsyncCase::VerifyState AsyncCase::verify (bool uselog)
1629 VerifyState retval = VERIFY_PASS;
1630 TestLog& log = m_testCtx.getLog();
1632 const de::ScopedLock lock(m_mutex);
1634 for (map<MessageID, MessageCount>::const_iterator itr = m_counts.begin(); itr != m_counts.end(); itr++)
1636 const MessageID& id = itr->first;
1638 const int refCount = itr->second.expected;
1639 const int resCount = itr->second.received;
1640 const bool enabled = true;
1642 VerificationResult result = verifyMessageCount(id, GL_DONT_CARE, refCount, resCount, enabled);
1645 log << TestLog::Message << result.logMessage << TestLog::EndMessage;
1647 if (result.result == QP_TEST_RESULT_FAIL)
1648 retval = VERIFY_FAIL;
1649 else if (result.result != QP_TEST_RESULT_PASS && retval == VERIFY_PASS)
1650 retval = VERIFY_MINIMUM;
1656 // Tests debug labels
1657 class LabelCase : public TestCase
1660 LabelCase (Context& ctx,
1664 virtual ~LabelCase (void) {}
1666 virtual IterateResult iterate (void);
1669 GLenum m_identifier;
1672 LabelCase::LabelCase (Context& ctx,
1676 : TestCase (ctx, name, desc)
1677 , m_identifier (identifier)
1681 LabelCase::IterateResult LabelCase::iterate (void)
1683 TCU_CHECK_AND_THROW(NotSupportedError, isKHRDebugSupported(m_context), "GL_KHR_debug is not supported");
1685 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1686 const char* const msg = "This is a debug label";
1691 switch(m_identifier)
1694 gl.genBuffers(1, &object);
1695 gl.bindBuffer(GL_ARRAY_BUFFER, object);
1696 gl.bindBuffer(GL_ARRAY_BUFFER, 0);
1700 object = gl.createShader(GL_FRAGMENT_SHADER);
1704 object = gl.createProgram();
1708 gl.genQueries(1, &object);
1709 gl.beginQuery(GL_ANY_SAMPLES_PASSED, object); // Create
1710 gl.endQuery(GL_ANY_SAMPLES_PASSED); // Cleanup
1713 case GL_PROGRAM_PIPELINE:
1714 gl.genProgramPipelines(1, &object);
1715 gl.bindProgramPipeline(object); // Create
1716 gl.bindProgramPipeline(0); // Cleanup
1719 case GL_TRANSFORM_FEEDBACK:
1720 gl.genTransformFeedbacks(1, &object);
1721 gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, object);
1722 gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);
1726 gl.genSamplers(1, &object);
1727 gl.bindSampler(0, object);
1728 gl.bindSampler(0, 0);
1732 gl.genTextures(1, &object);
1733 gl.bindTexture(GL_TEXTURE_2D, object);
1734 gl.bindTexture(GL_TEXTURE_2D, 0);
1737 case GL_RENDERBUFFER:
1738 gl.genRenderbuffers(1, &object);
1739 gl.bindRenderbuffer(GL_RENDERBUFFER, object);
1740 gl.bindRenderbuffer(GL_RENDERBUFFER, 0);
1743 case GL_FRAMEBUFFER:
1744 gl.genFramebuffers(1, &object);
1745 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, object);
1746 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_context.getRenderContext().getDefaultFramebuffer());
1750 DE_FATAL("Invalid identifier");
1753 gl.objectLabel(m_identifier, object, -1, msg);
1755 deMemset(buffer, 'X', sizeof(buffer));
1756 gl.getObjectLabel(m_identifier, object, sizeof(buffer), &outlen, buffer);
1759 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Failed to query debug label from object");
1760 else if (deStringEqual(msg, buffer))
1762 m_testCtx.getLog() << TestLog::Message << "Query returned string: \"" << buffer << "\"" << TestLog::EndMessage;
1763 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1767 buffer[63] = '\0'; // make sure buffer is null terminated before printing
1768 m_testCtx.getLog() << TestLog::Message << "Query returned wrong string: expected \"" << msg << "\" but got \"" << buffer << "\"" << TestLog::EndMessage;
1769 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Query returned wrong label");
1772 switch(m_identifier)
1774 case GL_BUFFER: gl.deleteBuffers(1, &object); break;
1775 case GL_SHADER: gl.deleteShader(object); break;
1776 case GL_PROGRAM: gl.deleteProgram(object); break;
1777 case GL_QUERY: gl.deleteQueries(1, &object); break;
1778 case GL_PROGRAM_PIPELINE: gl.deleteProgramPipelines(1, &object); break;
1779 case GL_TRANSFORM_FEEDBACK: gl.deleteTransformFeedbacks(1, &object); break;
1780 case GL_SAMPLER: gl.deleteSamplers(1, &object); break;
1781 case GL_TEXTURE: gl.deleteTextures(1, &object); break;
1782 case GL_RENDERBUFFER: gl.deleteRenderbuffers(1, &object); break;
1783 case GL_FRAMEBUFFER: gl.deleteFramebuffers(1, &object); break;
1786 DE_FATAL("Invalid identifier");
1793 DebugMessageTestContext::DebugMessageTestContext (BaseCase& host,
1794 glu::RenderContext& renderCtx,
1795 const glu::ContextInfo& ctxInfo,
1797 tcu::ResultCollector& results,
1799 : NegativeTestContext (host, renderCtx, ctxInfo, log, results, enableLog)
1800 , m_debugHost (host)
1804 DebugMessageTestContext::~DebugMessageTestContext (void)
1808 void DebugMessageTestContext::expectMessage (GLenum source, GLenum type)
1810 m_debugHost.expectMessage(source, type);
1813 class SyncLabelCase : public TestCase
1816 SyncLabelCase (Context& ctx, const char* name, const char* desc);
1817 virtual IterateResult iterate (void);
1820 SyncLabelCase::SyncLabelCase (Context& ctx, const char* name, const char* desc)
1821 : TestCase(ctx, name, desc)
1825 SyncLabelCase::IterateResult SyncLabelCase::iterate (void)
1827 TCU_CHECK_AND_THROW(NotSupportedError, isKHRDebugSupported(m_context), "GL_KHR_debug is not supported");
1829 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1830 const char* const msg = "This is a debug label";
1834 glw::GLsync sync = gl.fenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
1835 GLU_EXPECT_NO_ERROR(gl.getError(), "fenceSync");
1837 gl.objectPtrLabel(sync, -1, msg);
1839 deMemset(buffer, 'X', sizeof(buffer));
1840 gl.getObjectPtrLabel(sync, sizeof(buffer), &outlen, buffer);
1843 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Failed to query debug label from object");
1844 else if (deStringEqual(msg, buffer))
1846 m_testCtx.getLog() << TestLog::Message << "Query returned string: \"" << buffer << "\"" << TestLog::EndMessage;
1847 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1851 buffer[63] = '\0'; // make sure buffer is null terminated before printing
1852 m_testCtx.getLog() << TestLog::Message << "Query returned wrong string: expected \"" << msg << "\" but got \"" << buffer << "\"" << TestLog::EndMessage;
1853 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Query returned wrong label");
1856 gl.deleteSync(sync);
1861 class InitialLabelCase : public TestCase
1864 InitialLabelCase (Context& ctx, const char* name, const char* desc);
1865 virtual IterateResult iterate (void);
1868 InitialLabelCase::InitialLabelCase (Context& ctx, const char* name, const char* desc)
1869 : TestCase(ctx, name, desc)
1873 InitialLabelCase::IterateResult InitialLabelCase::iterate (void)
1875 TCU_CHECK_AND_THROW(NotSupportedError, isKHRDebugSupported(m_context), "GL_KHR_debug is not supported");
1877 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1878 tcu::ResultCollector result (m_testCtx.getLog(), " // ERROR: ");
1884 sync = gl.fenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
1885 GLS_COLLECT_GL_ERROR(result, gl.getError(), "fenceSync");
1887 shader = gl.createShader(GL_FRAGMENT_SHADER);
1888 GLS_COLLECT_GL_ERROR(result, gl.getError(), "createShader");
1891 const tcu::ScopedLogSection section(m_testCtx.getLog(), "Shader", "Shader object");
1892 m_testCtx.getLog() << TestLog::Message << "Querying initial value" << TestLog::EndMessage;
1896 gl.getObjectLabel(GL_SHADER, shader, sizeof(buffer), &outlen, buffer);
1897 GLS_COLLECT_GL_ERROR(result, gl.getError(), "getObjectLabel");
1900 result.fail("'length' was not zero, got " + de::toString(outlen));
1901 else if (buffer[0] != '\0')
1902 result.fail("label was not null terminated");
1904 m_testCtx.getLog() << TestLog::Message << "Got 0-sized null-terminated string." << TestLog::EndMessage;
1908 const tcu::ScopedLogSection section(m_testCtx.getLog(), "Sync", "Sync object");
1909 m_testCtx.getLog() << TestLog::Message << "Querying initial value" << TestLog::EndMessage;
1913 gl.getObjectPtrLabel(sync, sizeof(buffer), &outlen, buffer);
1914 GLS_COLLECT_GL_ERROR(result, gl.getError(), "getObjectPtrLabel");
1917 result.fail("'length' was not zero, got " + de::toString(outlen));
1918 else if (buffer[0] != '\0')
1919 result.fail("label was not null terminated");
1921 m_testCtx.getLog() << TestLog::Message << "Got 0-sized null-terminated string." << TestLog::EndMessage;
1924 gl.deleteShader(shader);
1925 gl.deleteSync(sync);
1927 result.setTestContextResult(m_testCtx);
1931 class ClearLabelCase : public TestCase
1934 ClearLabelCase (Context& ctx, const char* name, const char* desc);
1935 virtual IterateResult iterate (void);
1938 ClearLabelCase::ClearLabelCase (Context& ctx, const char* name, const char* desc)
1939 : TestCase(ctx, name, desc)
1943 ClearLabelCase::IterateResult ClearLabelCase::iterate (void)
1945 TCU_CHECK_AND_THROW(NotSupportedError, isKHRDebugSupported(m_context), "GL_KHR_debug is not supported");
1949 const char* description;
1951 } s_clearMethods[] =
1953 { " with NULL label and 0 length", 0 },
1954 { " with NULL label and 1 length", 1 },
1955 { " with NULL label and negative length", -1 },
1958 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1959 tcu::ResultCollector result (m_testCtx.getLog(), " // ERROR: ");
1960 const char* const msg = "This is a debug label";
1966 sync = gl.fenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
1967 GLS_COLLECT_GL_ERROR(result, gl.getError(), "fenceSync");
1969 shader = gl.createShader(GL_FRAGMENT_SHADER);
1970 GLS_COLLECT_GL_ERROR(result, gl.getError(), "createShader");
1973 const tcu::ScopedLogSection section(m_testCtx.getLog(), "Shader", "Shader object");
1975 for (int methodNdx = 0; methodNdx < DE_LENGTH_OF_ARRAY(s_clearMethods); ++methodNdx)
1977 m_testCtx.getLog() << TestLog::Message << "Setting label to string: \"" << msg << "\"" << TestLog::EndMessage;
1978 gl.objectLabel(GL_SHADER, shader, -2, msg);
1979 GLS_COLLECT_GL_ERROR(result, gl.getError(), "objectLabel");
1981 m_testCtx.getLog() << TestLog::Message << "Clearing label " << s_clearMethods[methodNdx].description << TestLog::EndMessage;
1982 gl.objectLabel(GL_SHADER, shader, s_clearMethods[methodNdx].length, DE_NULL);
1983 GLS_COLLECT_GL_ERROR(result, gl.getError(), "objectLabel");
1985 m_testCtx.getLog() << TestLog::Message << "Querying label" << TestLog::EndMessage;
1988 gl.getObjectLabel(GL_SHADER, shader, sizeof(buffer), &outlen, buffer);
1989 GLS_COLLECT_GL_ERROR(result, gl.getError(), "getObjectLabel");
1992 result.fail("'length' was not zero, got " + de::toString(outlen));
1993 else if (buffer[0] != '\0')
1994 result.fail("label was not null terminated");
1996 m_testCtx.getLog() << TestLog::Message << "Got 0-sized null-terminated string." << TestLog::EndMessage;
2001 const tcu::ScopedLogSection section(m_testCtx.getLog(), "Sync", "Sync object");
2003 for (int methodNdx = 0; methodNdx < DE_LENGTH_OF_ARRAY(s_clearMethods); ++methodNdx)
2005 m_testCtx.getLog() << TestLog::Message << "Setting label to string: \"" << msg << "\"" << TestLog::EndMessage;
2006 gl.objectPtrLabel(sync, -2, msg);
2007 GLS_COLLECT_GL_ERROR(result, gl.getError(), "objectPtrLabel");
2009 m_testCtx.getLog() << TestLog::Message << "Clearing label " << s_clearMethods[methodNdx].description << TestLog::EndMessage;
2010 gl.objectPtrLabel(sync, s_clearMethods[methodNdx].length, DE_NULL);
2011 GLS_COLLECT_GL_ERROR(result, gl.getError(), "objectPtrLabel");
2013 m_testCtx.getLog() << TestLog::Message << "Querying label" << TestLog::EndMessage;
2016 gl.getObjectPtrLabel(sync, sizeof(buffer), &outlen, buffer);
2017 GLS_COLLECT_GL_ERROR(result, gl.getError(), "getObjectPtrLabel");
2020 result.fail("'length' was not zero, got " + de::toString(outlen));
2021 else if (buffer[0] != '\0')
2022 result.fail("label was not null terminated");
2024 m_testCtx.getLog() << TestLog::Message << "Got 0-sized null-terminated string." << TestLog::EndMessage;
2028 gl.deleteShader(shader);
2029 gl.deleteSync(sync);
2031 result.setTestContextResult(m_testCtx);
2035 class SpecifyWithLengthCase : public TestCase
2038 SpecifyWithLengthCase (Context& ctx, const char* name, const char* desc);
2039 virtual IterateResult iterate (void);
2042 SpecifyWithLengthCase::SpecifyWithLengthCase (Context& ctx, const char* name, const char* desc)
2043 : TestCase(ctx, name, desc)
2047 SpecifyWithLengthCase::IterateResult SpecifyWithLengthCase::iterate (void)
2049 TCU_CHECK_AND_THROW(NotSupportedError, isKHRDebugSupported(m_context), "GL_KHR_debug is not supported");
2051 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2052 tcu::ResultCollector result (m_testCtx.getLog(), " // ERROR: ");
2053 const char* const msg = "This is a debug label";
2054 const char* const clipMsg = "This is a de";
2060 sync = gl.fenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
2061 GLS_COLLECT_GL_ERROR(result, gl.getError(), "fenceSync");
2063 shader = gl.createShader(GL_FRAGMENT_SHADER);
2064 GLS_COLLECT_GL_ERROR(result, gl.getError(), "createShader");
2067 const tcu::ScopedLogSection section(m_testCtx.getLog(), "Shader", "Shader object");
2069 m_testCtx.getLog() << TestLog::Message << "Setting label to string: \"" << msg << "\" with length 12" << TestLog::EndMessage;
2070 gl.objectLabel(GL_SHADER, shader, 12, msg);
2071 GLS_COLLECT_GL_ERROR(result, gl.getError(), "objectLabel");
2073 m_testCtx.getLog() << TestLog::Message << "Querying label" << TestLog::EndMessage;
2074 deMemset(buffer, 'X', sizeof(buffer));
2075 gl.getObjectLabel(GL_SHADER, shader, sizeof(buffer), &outlen, buffer);
2076 GLS_COLLECT_GL_ERROR(result, gl.getError(), "getObjectLabel");
2079 result.fail("'length' was not 12, got " + de::toString(outlen));
2080 else if (deStringEqual(clipMsg, buffer))
2082 m_testCtx.getLog() << TestLog::Message << "Query returned string: \"" << buffer << "\"" << TestLog::EndMessage;
2086 buffer[63] = '\0'; // make sure buffer is null terminated before printing
2087 m_testCtx.getLog() << TestLog::Message << "Query returned wrong string: expected \"" << clipMsg << "\" but got \"" << buffer << "\"" << TestLog::EndMessage;
2088 result.fail("Query returned wrong label");
2093 const tcu::ScopedLogSection section(m_testCtx.getLog(), "Sync", "Sync object");
2095 m_testCtx.getLog() << TestLog::Message << "Setting label to string: \"" << msg << "\" with length 12" << TestLog::EndMessage;
2096 gl.objectPtrLabel(sync, 12, msg);
2097 GLS_COLLECT_GL_ERROR(result, gl.getError(), "objectPtrLabel");
2099 m_testCtx.getLog() << TestLog::Message << "Querying label" << TestLog::EndMessage;
2100 deMemset(buffer, 'X', sizeof(buffer));
2101 gl.getObjectPtrLabel(sync, sizeof(buffer), &outlen, buffer);
2102 GLS_COLLECT_GL_ERROR(result, gl.getError(), "getObjectPtrLabel");
2105 result.fail("'length' was not 12, got " + de::toString(outlen));
2106 else if (deStringEqual(clipMsg, buffer))
2108 m_testCtx.getLog() << TestLog::Message << "Query returned string: \"" << buffer << "\"" << TestLog::EndMessage;
2112 buffer[63] = '\0'; // make sure buffer is null terminated before printing
2113 m_testCtx.getLog() << TestLog::Message << "Query returned wrong string: expected \"" << clipMsg << "\" but got \"" << buffer << "\"" << TestLog::EndMessage;
2114 result.fail("Query returned wrong label");
2119 const tcu::ScopedLogSection section(m_testCtx.getLog(), "ZeroSized", "ZeroSized");
2121 m_testCtx.getLog() << TestLog::Message << "Setting label to string: \"" << msg << "\" with length 0" << TestLog::EndMessage;
2122 gl.objectLabel(GL_SHADER, shader, 0, msg);
2123 GLS_COLLECT_GL_ERROR(result, gl.getError(), "objectLabel");
2125 m_testCtx.getLog() << TestLog::Message << "Querying label" << TestLog::EndMessage;
2126 deMemset(buffer, 'X', sizeof(buffer));
2127 gl.getObjectLabel(GL_SHADER, shader, sizeof(buffer), &outlen, buffer);
2128 GLS_COLLECT_GL_ERROR(result, gl.getError(), "getObjectLabel");
2131 result.fail("'length' was not zero, got " + de::toString(outlen));
2132 else if (buffer[0] != '\0')
2133 result.fail("label was not null terminated");
2135 m_testCtx.getLog() << TestLog::Message << "Got 0-sized null-terminated string." << TestLog::EndMessage;
2138 gl.deleteShader(shader);
2139 gl.deleteSync(sync);
2141 result.setTestContextResult(m_testCtx);
2145 class BufferLimitedLabelCase : public TestCase
2148 BufferLimitedLabelCase (Context& ctx, const char* name, const char* desc);
2149 virtual IterateResult iterate (void);
2152 BufferLimitedLabelCase::BufferLimitedLabelCase (Context& ctx, const char* name, const char* desc)
2153 : TestCase(ctx, name, desc)
2157 BufferLimitedLabelCase::IterateResult BufferLimitedLabelCase::iterate (void)
2159 TCU_CHECK_AND_THROW(NotSupportedError, isKHRDebugSupported(m_context), "GL_KHR_debug is not supported");
2161 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2162 tcu::ResultCollector result (m_testCtx.getLog(), " // ERROR: ");
2163 const char* const msg = "This is a debug label";
2169 sync = gl.fenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
2170 GLS_COLLECT_GL_ERROR(result, gl.getError(), "fenceSync");
2172 shader = gl.createShader(GL_FRAGMENT_SHADER);
2173 GLS_COLLECT_GL_ERROR(result, gl.getError(), "createShader");
2176 const tcu::ScopedLogSection superSection(m_testCtx.getLog(), "Shader", "Shader object");
2178 m_testCtx.getLog() << TestLog::Message << "Setting label to string: \"" << msg << "\"" << TestLog::EndMessage;
2179 gl.objectLabel(GL_SHADER, shader, -1, msg);
2180 GLS_COLLECT_GL_ERROR(result, gl.getError(), "objectLabel");
2183 const tcu::ScopedLogSection section(m_testCtx.getLog(), "QueryAll", "Query All");
2185 m_testCtx.getLog() << TestLog::Message << "Querying whole label, buffer size = 22" << TestLog::EndMessage;
2186 deMemset(buffer, 'X', sizeof(buffer));
2187 gl.getObjectLabel(GL_SHADER, shader, 22, &outlen, buffer);
2188 GLS_COLLECT_GL_ERROR(result, gl.getError(), "getObjectLabel");
2191 result.fail("'length' was not 21, got " + de::toString(outlen));
2192 else if (buffer[outlen] != '\0')
2193 result.fail("Buffer was not null-terminated");
2194 else if (buffer[outlen+1] != 'X')
2195 result.fail("Query wrote over buffer bound");
2196 else if (!deStringEqual(msg, buffer))
2198 buffer[63] = '\0'; // make sure buffer is null terminated before printing
2199 m_testCtx.getLog() << TestLog::Message << "Query returned string: \"" << buffer << "\"" << TestLog::EndMessage;
2200 result.fail("Query returned wrong label");
2203 m_testCtx.getLog() << TestLog::Message << "Query returned string: \"" << buffer << "\"" << TestLog::EndMessage;
2206 const tcu::ScopedLogSection section(m_testCtx.getLog(), "QueryAllNoSize", "Query all without size");
2208 m_testCtx.getLog() << TestLog::Message << "Querying whole label, buffer size = 22" << TestLog::EndMessage;
2209 deMemset(buffer, 'X', sizeof(buffer));
2210 gl.getObjectLabel(GL_SHADER, shader, 22, DE_NULL, buffer);
2211 GLS_COLLECT_GL_ERROR(result, gl.getError(), "getObjectLabel");
2213 buffer[63] = '\0'; // make sure buffer is null terminated before strlen
2215 if (strlen(buffer) != 21)
2216 result.fail("Buffer length was not 21");
2217 else if (buffer[21] != '\0')
2218 result.fail("Buffer was not null-terminated");
2219 else if (buffer[22] != 'X')
2220 result.fail("Query wrote over buffer bound");
2221 else if (!deStringEqual(msg, buffer))
2223 m_testCtx.getLog() << TestLog::Message << "Query returned string: \"" << buffer << "\"" << TestLog::EndMessage;
2224 result.fail("Query returned wrong label");
2227 m_testCtx.getLog() << TestLog::Message << "Query returned string: \"" << buffer << "\"" << TestLog::EndMessage;
2230 const tcu::ScopedLogSection section(m_testCtx.getLog(), "QueryLess", "Query substring");
2232 m_testCtx.getLog() << TestLog::Message << "Querying whole label, buffer size = 2" << TestLog::EndMessage;
2233 deMemset(buffer, 'X', sizeof(buffer));
2234 gl.getObjectLabel(GL_SHADER, shader, 2, &outlen, buffer);
2235 GLS_COLLECT_GL_ERROR(result, gl.getError(), "getObjectLabel");
2238 result.fail("'length' was not 1, got " + de::toString(outlen));
2239 else if (buffer[outlen] != '\0')
2240 result.fail("Buffer was not null-terminated");
2241 else if (buffer[outlen+1] != 'X')
2242 result.fail("Query wrote over buffer bound");
2243 else if (!deStringBeginsWith(msg, buffer))
2245 buffer[63] = '\0'; // make sure buffer is null terminated before printing
2246 m_testCtx.getLog() << TestLog::Message << "Query returned string: \"" << buffer << "\"" << TestLog::EndMessage;
2247 result.fail("Query returned wrong label");
2250 m_testCtx.getLog() << TestLog::Message << "Query returned string: \"" << buffer << "\"" << TestLog::EndMessage;
2253 const tcu::ScopedLogSection section(m_testCtx.getLog(), "QueryNone", "Query one character");
2255 m_testCtx.getLog() << TestLog::Message << "Querying whole label, buffer size = 1" << TestLog::EndMessage;
2256 deMemset(buffer, 'X', sizeof(buffer));
2257 gl.getObjectLabel(GL_SHADER, shader, 1, &outlen, buffer);
2258 GLS_COLLECT_GL_ERROR(result, gl.getError(), "getObjectLabel");
2261 result.fail("'length' was not 0, got " + de::toString(outlen));
2262 else if (buffer[outlen] != '\0')
2263 result.fail("Buffer was not null-terminated");
2264 else if (buffer[outlen+1] != 'X')
2265 result.fail("Query wrote over buffer bound");
2267 m_testCtx.getLog() << TestLog::Message << "Query returned zero-sized null-terminated string" << TestLog::EndMessage;
2272 const tcu::ScopedLogSection superSection(m_testCtx.getLog(), "Sync", "Sync object");
2274 m_testCtx.getLog() << TestLog::Message << "Setting label to string: \"" << msg << "\"" << TestLog::EndMessage;
2275 gl.objectPtrLabel(sync, -1, msg);
2276 GLS_COLLECT_GL_ERROR(result, gl.getError(), "objectPtrLabel");
2279 const tcu::ScopedLogSection section(m_testCtx.getLog(), "QueryAll", "Query All");
2281 m_testCtx.getLog() << TestLog::Message << "Querying whole label, buffer size = 22" << TestLog::EndMessage;
2282 deMemset(buffer, 'X', sizeof(buffer));
2283 gl.getObjectPtrLabel(sync, 22, &outlen, buffer);
2284 GLS_COLLECT_GL_ERROR(result, gl.getError(), "getObjectPtrLabel");
2287 result.fail("'length' was not 21, got " + de::toString(outlen));
2288 else if (buffer[outlen] != '\0')
2289 result.fail("Buffer was not null-terminated");
2290 else if (buffer[outlen+1] != 'X')
2291 result.fail("Query wrote over buffer bound");
2292 else if (!deStringEqual(msg, buffer))
2294 buffer[63] = '\0'; // make sure buffer is null terminated before printing
2295 m_testCtx.getLog() << TestLog::Message << "Query returned string: \"" << buffer << "\"" << TestLog::EndMessage;
2296 result.fail("Query returned wrong label");
2299 m_testCtx.getLog() << TestLog::Message << "Query returned string: \"" << buffer << "\"" << TestLog::EndMessage;
2302 const tcu::ScopedLogSection section(m_testCtx.getLog(), "QueryAllNoSize", "Query all without size");
2304 m_testCtx.getLog() << TestLog::Message << "Querying whole label, buffer size = 22" << TestLog::EndMessage;
2305 deMemset(buffer, 'X', sizeof(buffer));
2306 gl.getObjectPtrLabel(sync, 22, DE_NULL, buffer);
2307 GLS_COLLECT_GL_ERROR(result, gl.getError(), "getObjectPtrLabel");
2309 buffer[63] = '\0'; // make sure buffer is null terminated before strlen
2311 if (strlen(buffer) != 21)
2312 result.fail("Buffer length was not 21");
2313 else if (buffer[21] != '\0')
2314 result.fail("Buffer was not null-terminated");
2315 else if (buffer[22] != 'X')
2316 result.fail("Query wrote over buffer bound");
2317 else if (!deStringEqual(msg, buffer))
2319 m_testCtx.getLog() << TestLog::Message << "Query returned string: \"" << buffer << "\"" << TestLog::EndMessage;
2320 result.fail("Query returned wrong label");
2323 m_testCtx.getLog() << TestLog::Message << "Query returned string: \"" << buffer << "\"" << TestLog::EndMessage;
2326 const tcu::ScopedLogSection section(m_testCtx.getLog(), "QueryLess", "Query substring");
2328 m_testCtx.getLog() << TestLog::Message << "Querying whole label, buffer size = 2" << TestLog::EndMessage;
2329 deMemset(buffer, 'X', sizeof(buffer));
2330 gl.getObjectPtrLabel(sync, 2, &outlen, buffer);
2331 GLS_COLLECT_GL_ERROR(result, gl.getError(), "getObjectPtrLabel");
2334 result.fail("'length' was not 1, got " + de::toString(outlen));
2335 else if (buffer[outlen] != '\0')
2336 result.fail("Buffer was not null-terminated");
2337 else if (buffer[outlen+1] != 'X')
2338 result.fail("Query wrote over buffer bound");
2339 else if (!deStringBeginsWith(msg, buffer))
2341 buffer[63] = '\0'; // make sure buffer is null terminated before printing
2342 m_testCtx.getLog() << TestLog::Message << "Query returned string: \"" << buffer << "\"" << TestLog::EndMessage;
2343 result.fail("Query returned wrong label");
2346 m_testCtx.getLog() << TestLog::Message << "Query returned string: \"" << buffer << "\"" << TestLog::EndMessage;
2349 const tcu::ScopedLogSection section(m_testCtx.getLog(), "QueryNone", "Query one character");
2351 m_testCtx.getLog() << TestLog::Message << "Querying whole label, buffer size = 1" << TestLog::EndMessage;
2352 deMemset(buffer, 'X', sizeof(buffer));
2353 gl.getObjectPtrLabel(sync, 1, &outlen, buffer);
2354 GLS_COLLECT_GL_ERROR(result, gl.getError(), "getObjectPtrLabel");
2357 result.fail("'length' was not 0, got " + de::toString(outlen));
2358 else if (buffer[outlen] != '\0')
2359 result.fail("Buffer was not null-terminated");
2360 else if (buffer[outlen+1] != 'X')
2361 result.fail("Query wrote over buffer bound");
2363 m_testCtx.getLog() << TestLog::Message << "Query returned zero-sized null-terminated string" << TestLog::EndMessage;
2367 gl.deleteShader(shader);
2368 gl.deleteSync(sync);
2370 result.setTestContextResult(m_testCtx);
2374 class LabelMaxSizeCase : public TestCase
2377 LabelMaxSizeCase (Context& ctx, const char* name, const char* desc);
2378 virtual IterateResult iterate (void);
2381 LabelMaxSizeCase::LabelMaxSizeCase (Context& ctx, const char* name, const char* desc)
2382 : TestCase(ctx, name, desc)
2386 LabelMaxSizeCase::IterateResult LabelMaxSizeCase::iterate (void)
2388 TCU_CHECK_AND_THROW(NotSupportedError, isKHRDebugSupported(m_context), "GL_KHR_debug is not supported");
2390 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2391 tcu::ResultCollector result (m_testCtx.getLog(), " // ERROR: ");
2392 int maxLabelLen = -1;
2397 gl.getIntegerv(GL_MAX_LABEL_LENGTH, &maxLabelLen);
2398 GLS_COLLECT_GL_ERROR(result, gl.getError(), "GL_MAX_LABEL_LENGTH");
2400 m_testCtx.getLog() << TestLog::Message << "GL_MAX_LABEL_LENGTH = " << maxLabelLen << TestLog::EndMessage;
2402 if (maxLabelLen < 256)
2403 throw tcu::TestError("maxLabelLen was less than required (256)");
2404 if (maxLabelLen > 8192)
2408 << "GL_MAX_LABEL_LENGTH is very large. Application having larger labels is unlikely, skipping test."
2409 << TestLog::EndMessage;
2410 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2414 sync = gl.fenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
2415 GLS_COLLECT_GL_ERROR(result, gl.getError(), "fenceSync");
2417 shader = gl.createShader(GL_FRAGMENT_SHADER);
2418 GLS_COLLECT_GL_ERROR(result, gl.getError(), "createShader");
2421 const tcu::ScopedLogSection section (m_testCtx.getLog(), "Shader", "Shader object");
2422 std::vector<char> buffer (maxLabelLen, 'X');
2423 std::vector<char> readBuffer (maxLabelLen, 'X');
2425 buffer[maxLabelLen-1] = '\0';
2427 m_testCtx.getLog() << TestLog::Message << "Setting max length label, with implicit size. (length = -1)" << TestLog::EndMessage;
2428 gl.objectLabel(GL_SHADER, shader, -1, &buffer[0]);
2429 GLS_COLLECT_GL_ERROR(result, gl.getError(), "objectLabel");
2431 m_testCtx.getLog() << TestLog::Message << "Querying label back" << TestLog::EndMessage;
2433 gl.getObjectLabel(GL_SHADER, shader, maxLabelLen, &outlen, &readBuffer[0]);
2434 GLS_COLLECT_GL_ERROR(result, gl.getError(), "getObjectLabel");
2436 if (outlen != maxLabelLen-1)
2437 result.fail("'length' was not " + de::toString(maxLabelLen-1) + ", got " + de::toString(outlen));
2438 else if (readBuffer[outlen] != '\0')
2439 result.fail("Buffer was not null-terminated");
2441 m_testCtx.getLog() << TestLog::Message << "Setting max length label, with explicit size. (length = " << (maxLabelLen-1) << ")" << TestLog::EndMessage;
2442 gl.objectLabel(GL_SHADER, shader, maxLabelLen-1, &buffer[0]);
2443 GLS_COLLECT_GL_ERROR(result, gl.getError(), "objectLabel");
2445 m_testCtx.getLog() << TestLog::Message << "Querying label back" << TestLog::EndMessage;
2447 readBuffer[maxLabelLen-1] = 'X';
2448 gl.getObjectLabel(GL_SHADER, shader, maxLabelLen, &outlen, &readBuffer[0]);
2449 GLS_COLLECT_GL_ERROR(result, gl.getError(), "getObjectLabel");
2451 if (outlen != maxLabelLen-1)
2452 result.fail("'length' was not " + de::toString(maxLabelLen-1) + ", got " + de::toString(outlen));
2453 else if (readBuffer[outlen] != '\0')
2454 result.fail("Buffer was not null-terminated");
2458 const tcu::ScopedLogSection section (m_testCtx.getLog(), "Sync", "Sync object");
2459 std::vector<char> buffer (maxLabelLen, 'X');
2460 std::vector<char> readBuffer (maxLabelLen, 'X');
2462 buffer[maxLabelLen-1] = '\0';
2464 m_testCtx.getLog() << TestLog::Message << "Setting max length label, with implicit size. (length = -1)" << TestLog::EndMessage;
2465 gl.objectPtrLabel(sync, -1, &buffer[0]);
2466 GLS_COLLECT_GL_ERROR(result, gl.getError(), "objectPtrLabel");
2468 m_testCtx.getLog() << TestLog::Message << "Querying label back" << TestLog::EndMessage;
2470 gl.getObjectPtrLabel(sync, maxLabelLen, &outlen, &readBuffer[0]);
2471 GLS_COLLECT_GL_ERROR(result, gl.getError(), "getObjectPtrLabel");
2473 if (outlen != maxLabelLen-1)
2474 result.fail("'length' was not " + de::toString(maxLabelLen-1) + ", got " + de::toString(outlen));
2475 else if (readBuffer[outlen] != '\0')
2476 result.fail("Buffer was not null-terminated");
2478 m_testCtx.getLog() << TestLog::Message << "Setting max length label, with explicit size. (length = " << (maxLabelLen-1) << ")" << TestLog::EndMessage;
2479 gl.objectPtrLabel(sync, maxLabelLen-1, &buffer[0]);
2480 GLS_COLLECT_GL_ERROR(result, gl.getError(), "objectPtrLabel");
2482 m_testCtx.getLog() << TestLog::Message << "Querying label back" << TestLog::EndMessage;
2484 readBuffer[maxLabelLen-1] = 'X';
2485 gl.getObjectPtrLabel(sync, maxLabelLen, &outlen, &readBuffer[0]);
2486 GLS_COLLECT_GL_ERROR(result, gl.getError(), "getObjectPtrLabel");
2488 if (outlen != maxLabelLen-1)
2489 result.fail("'length' was not " + de::toString(maxLabelLen-1) + ", got " + de::toString(outlen));
2490 else if (readBuffer[outlen] != '\0')
2491 result.fail("Buffer was not null-terminated");
2494 gl.deleteShader(shader);
2495 gl.deleteSync(sync);
2497 result.setTestContextResult(m_testCtx);
2501 class LabelLengthCase : public TestCase
2504 LabelLengthCase (Context& ctx, const char* name, const char* desc);
2505 virtual IterateResult iterate (void);
2508 LabelLengthCase::LabelLengthCase (Context& ctx, const char* name, const char* desc)
2509 : TestCase(ctx, name, desc)
2513 LabelLengthCase::IterateResult LabelLengthCase::iterate (void)
2515 TCU_CHECK_AND_THROW(NotSupportedError, isKHRDebugSupported(m_context), "GL_KHR_debug is not supported");
2517 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2518 tcu::ResultCollector result (m_testCtx.getLog(), " // ERROR: ");
2519 const char* const msg = "This is a debug label";
2524 sync = gl.fenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
2525 GLS_COLLECT_GL_ERROR(result, gl.getError(), "fenceSync");
2527 shader = gl.createShader(GL_FRAGMENT_SHADER);
2528 GLS_COLLECT_GL_ERROR(result, gl.getError(), "createShader");
2531 const tcu::ScopedLogSection section(m_testCtx.getLog(), "Shader", "Shader object");
2533 m_testCtx.getLog() << TestLog::Message << "Querying label length" << TestLog::EndMessage;
2535 gl.getObjectLabel(GL_SHADER, shader, 0, &outlen, DE_NULL);
2536 GLS_COLLECT_GL_ERROR(result, gl.getError(), "getObjectLabel");
2539 result.fail("'length' was not 0, got " + de::toString(outlen));
2541 m_testCtx.getLog() << TestLog::Message << "Query returned length: " << outlen << TestLog::EndMessage;
2543 m_testCtx.getLog() << TestLog::Message << "Setting label to string: \"" << msg << "\"" << TestLog::EndMessage;
2544 gl.objectLabel(GL_SHADER, shader, -1, msg);
2545 GLS_COLLECT_GL_ERROR(result, gl.getError(), "objectLabel");
2547 m_testCtx.getLog() << TestLog::Message << "Querying label length" << TestLog::EndMessage;
2549 gl.getObjectLabel(GL_SHADER, shader, 0, &outlen, DE_NULL);
2550 GLS_COLLECT_GL_ERROR(result, gl.getError(), "getObjectLabel");
2553 result.fail("'length' was not 21, got " + de::toString(outlen));
2555 m_testCtx.getLog() << TestLog::Message << "Query returned length: " << outlen << TestLog::EndMessage;
2559 const tcu::ScopedLogSection section(m_testCtx.getLog(), "Sync", "Sync object");
2561 m_testCtx.getLog() << TestLog::Message << "Querying label length" << TestLog::EndMessage;
2563 gl.getObjectPtrLabel(sync, 0, &outlen, DE_NULL);
2564 GLS_COLLECT_GL_ERROR(result, gl.getError(), "getObjectPtrLabel");
2567 result.fail("'length' was not 0, got " + de::toString(outlen));
2569 m_testCtx.getLog() << TestLog::Message << "Query returned length: " << outlen << TestLog::EndMessage;
2571 m_testCtx.getLog() << TestLog::Message << "Setting label to string: \"" << msg << "\"" << TestLog::EndMessage;
2572 gl.objectPtrLabel(sync, -1, msg);
2573 GLS_COLLECT_GL_ERROR(result, gl.getError(), "objectPtrLabel");
2575 m_testCtx.getLog() << TestLog::Message << "Querying label length" << TestLog::EndMessage;
2577 gl.getObjectPtrLabel(sync, 0, &outlen, DE_NULL);
2578 GLS_COLLECT_GL_ERROR(result, gl.getError(), "getObjectPtrLabel");
2581 result.fail("'length' was not 21, got " + de::toString(outlen));
2583 m_testCtx.getLog() << TestLog::Message << "Query returned length: " << outlen << TestLog::EndMessage;
2586 gl.deleteShader(shader);
2587 gl.deleteSync(sync);
2589 result.setTestContextResult(m_testCtx);
2593 class LimitQueryCase : public TestCase
2596 LimitQueryCase (Context& context,
2598 const char* description,
2601 gls::StateQueryUtil::QueryType type);
2603 IterateResult iterate (void);
2605 const gls::StateQueryUtil::QueryType m_type;
2607 const glw::GLenum m_target;
2610 LimitQueryCase::LimitQueryCase (Context& context,
2612 const char* description,
2615 gls::StateQueryUtil::QueryType type)
2616 : TestCase (context, name, description)
2623 LimitQueryCase::IterateResult LimitQueryCase::iterate (void)
2625 TCU_CHECK_AND_THROW(NotSupportedError, isKHRDebugSupported(m_context), "GL_KHR_debug is not supported");
2627 glu::CallLogWrapper gl (m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
2628 tcu::ResultCollector result (m_testCtx.getLog(), " // ERROR: ");
2630 gl.enableLogging(true);
2631 gls::StateQueryUtil::verifyStateIntegerMin(result, gl, m_target, m_limit, m_type);
2633 result.setTestContextResult(m_testCtx);
2637 class IsEnabledCase : public TestCase
2642 INITIAL_CTX_IS_DEBUG = 0,
2646 IsEnabledCase (Context& context,
2648 const char* description,
2650 InitialValue initial,
2651 gls::StateQueryUtil::QueryType type);
2653 IterateResult iterate (void);
2655 const gls::StateQueryUtil::QueryType m_type;
2656 const glw::GLenum m_target;
2657 const InitialValue m_initial;
2660 IsEnabledCase::IsEnabledCase (Context& context,
2662 const char* description,
2664 InitialValue initial,
2665 gls::StateQueryUtil::QueryType type)
2666 : TestCase (context, name, description)
2669 , m_initial (initial)
2673 IsEnabledCase::IterateResult IsEnabledCase::iterate (void)
2675 TCU_CHECK_AND_THROW(NotSupportedError, isKHRDebugSupported(m_context), "GL_KHR_debug is not supported");
2677 glu::CallLogWrapper gl (m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
2678 tcu::ResultCollector result (m_testCtx.getLog(), " // ERROR: ");
2681 gl.enableLogging(true);
2683 if (m_initial == INITIAL_FALSE)
2687 DE_ASSERT(m_initial == INITIAL_CTX_IS_DEBUG);
2688 initial = (m_context.getRenderContext().getType().getFlags() & glu::CONTEXT_DEBUG) != 0;
2691 // check inital value
2692 gls::StateQueryUtil::verifyStateBoolean(result, gl, m_target, initial, m_type);
2696 gl.glEnable(m_target);
2697 GLS_COLLECT_GL_ERROR(result, gl.glGetError(), "glEnable");
2699 gls::StateQueryUtil::verifyStateBoolean(result, gl, m_target, true, m_type);
2701 gl.glDisable(m_target);
2702 GLS_COLLECT_GL_ERROR(result, gl.glGetError(), "glDisable");
2704 gls::StateQueryUtil::verifyStateBoolean(result, gl, m_target, false, m_type);
2706 result.setTestContextResult(m_testCtx);
2710 class PositiveIntegerCase : public TestCase
2713 PositiveIntegerCase (Context& context,
2715 const char* description,
2717 gls::StateQueryUtil::QueryType type);
2719 IterateResult iterate (void);
2721 const gls::StateQueryUtil::QueryType m_type;
2722 const glw::GLenum m_target;
2725 PositiveIntegerCase::PositiveIntegerCase (Context& context,
2727 const char* description,
2729 gls::StateQueryUtil::QueryType type)
2730 : TestCase (context, name, description)
2736 PositiveIntegerCase::IterateResult PositiveIntegerCase::iterate (void)
2738 TCU_CHECK_AND_THROW(NotSupportedError, isKHRDebugSupported(m_context), "GL_KHR_debug is not supported");
2740 glu::CallLogWrapper gl (m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
2741 tcu::ResultCollector result (m_testCtx.getLog(), " // ERROR: ");
2743 gl.enableLogging(true);
2744 gls::StateQueryUtil::verifyStateIntegerMin(result, gl, m_target, 0, m_type);
2746 result.setTestContextResult(m_testCtx);
2750 class GroupStackDepthQueryCase : public TestCase
2753 GroupStackDepthQueryCase (Context& context,
2755 const char* description,
2756 gls::StateQueryUtil::QueryType type);
2758 IterateResult iterate (void);
2760 const gls::StateQueryUtil::QueryType m_type;
2763 GroupStackDepthQueryCase::GroupStackDepthQueryCase (Context& context,
2765 const char* description,
2766 gls::StateQueryUtil::QueryType type)
2767 : TestCase (context, name, description)
2772 GroupStackDepthQueryCase::IterateResult GroupStackDepthQueryCase::iterate (void)
2774 TCU_CHECK_AND_THROW(NotSupportedError, isKHRDebugSupported(m_context), "GL_KHR_debug is not supported");
2776 glu::CallLogWrapper gl (m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
2777 tcu::ResultCollector result (m_testCtx.getLog(), " // ERROR: ");
2779 gl.enableLogging(true);
2782 const tcu::ScopedLogSection section(m_testCtx.getLog(), "Initial", "Initial");
2784 gls::StateQueryUtil::verifyStateInteger(result, gl, GL_DEBUG_GROUP_STACK_DEPTH, 1, m_type);
2788 const tcu::ScopedLogSection section(m_testCtx.getLog(), "Scoped", "Scoped");
2790 gl.glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 1, -1, "Application group 1");
2791 gls::StateQueryUtil::verifyStateInteger(result, gl, GL_DEBUG_GROUP_STACK_DEPTH, 2, m_type);
2792 gl.glPopDebugGroup();
2795 result.setTestContextResult(m_testCtx);
2799 extern "C" void GLW_APIENTRY dummyCallback(GLenum, GLenum, GLuint, GLenum, GLsizei, const char*, void*)
2804 class DebugCallbackFunctionCase : public TestCase
2807 DebugCallbackFunctionCase (Context& context, const char* name, const char* description);
2808 IterateResult iterate (void);
2811 DebugCallbackFunctionCase::DebugCallbackFunctionCase (Context& context, const char* name, const char* description)
2812 : TestCase (context, name, description)
2816 DebugCallbackFunctionCase::IterateResult DebugCallbackFunctionCase::iterate (void)
2818 using namespace gls::StateQueryUtil;
2819 TCU_CHECK_AND_THROW(NotSupportedError, isKHRDebugSupported(m_context), "GL_KHR_debug is not supported");
2821 glu::CallLogWrapper gl (m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
2822 tcu::ResultCollector result (m_testCtx.getLog(), " // ERROR: ");
2824 gl.enableLogging(true);
2827 const tcu::ScopedLogSection section(m_testCtx.getLog(), "Initial", "Initial");
2829 verifyStatePointer(result, gl, GL_DEBUG_CALLBACK_FUNCTION, 0, QUERY_POINTER);
2833 const tcu::ScopedLogSection section(m_testCtx.getLog(), "Set", "Set");
2835 gl.glDebugMessageCallback(dummyCallback, DE_NULL);
2836 verifyStatePointer(result, gl, GL_DEBUG_CALLBACK_FUNCTION, (const void*)dummyCallback, QUERY_POINTER);
2839 result.setTestContextResult(m_testCtx);
2843 class DebugCallbackUserParamCase : public TestCase
2846 DebugCallbackUserParamCase (Context& context, const char* name, const char* description);
2847 IterateResult iterate (void);
2850 DebugCallbackUserParamCase::DebugCallbackUserParamCase (Context& context, const char* name, const char* description)
2851 : TestCase (context, name, description)
2855 DebugCallbackUserParamCase::IterateResult DebugCallbackUserParamCase::iterate (void)
2857 using namespace gls::StateQueryUtil;
2859 TCU_CHECK_AND_THROW(NotSupportedError, isKHRDebugSupported(m_context), "GL_KHR_debug is not supported");
2861 glu::CallLogWrapper gl (m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
2862 tcu::ResultCollector result (m_testCtx.getLog(), " // ERROR: ");
2864 gl.enableLogging(true);
2867 const tcu::ScopedLogSection section(m_testCtx.getLog(), "Initial", "Initial");
2869 verifyStatePointer(result, gl, GL_DEBUG_CALLBACK_USER_PARAM, 0, QUERY_POINTER);
2873 const tcu::ScopedLogSection section (m_testCtx.getLog(), "Set", "Set");
2874 const void* param = (void*)(int*)0x123;
2876 gl.glDebugMessageCallback(dummyCallback, param);
2877 verifyStatePointer(result, gl, GL_DEBUG_CALLBACK_USER_PARAM, param, QUERY_POINTER);
2880 result.setTestContextResult(m_testCtx);
2886 DebugTests::DebugTests (Context& context)
2887 : TestCaseGroup(context, "debug", "Debug tests")
2893 CASETYPE_CALLBACK = 0,
2900 tcu::TestNode* createCase (CaseType type, Context& ctx, const char* name, const char* desc, TestFunctionWrapper function)
2904 case CASETYPE_CALLBACK: return new CallbackErrorCase(ctx, name, desc, function);
2905 case CASETYPE_LOG: return new LogErrorCase(ctx, name, desc, function);
2906 case CASETYPE_GETERROR: return new GetErrorCase(ctx, name, desc, function);
2909 DE_FATAL("Invalid type");
2915 tcu::TestCaseGroup* createChildCases (CaseType type, Context& ctx, const char* name, const char* desc, const vector<FunctionContainer>& funcs)
2917 tcu::TestCaseGroup* host = new tcu::TestCaseGroup(ctx.getTestContext(), name, desc);
2919 for (size_t ndx = 0; ndx < funcs.size(); ndx++)
2920 host->addChild(createCase(type, ctx, funcs[ndx].name, funcs[ndx].desc, funcs[ndx].function));
2925 vector<FunctionContainer> wrapCoreFunctions (const vector<NegativeTestShared::FunctionContainer>& fns)
2927 vector<FunctionContainer> retVal;
2929 retVal.resize(fns.size());
2930 for (int ndx = 0; ndx < (int)fns.size(); ++ndx)
2932 retVal[ndx].function = TestFunctionWrapper(fns[ndx].function);
2933 retVal[ndx].name = fns[ndx].name;
2934 retVal[ndx].desc = fns[ndx].desc;
2940 void DebugTests::init (void)
2942 const vector<FunctionContainer> bufferFuncs = wrapCoreFunctions(NegativeTestShared::getNegativeBufferApiTestFunctions());
2943 const vector<FunctionContainer> textureFuncs = wrapCoreFunctions(NegativeTestShared::getNegativeTextureApiTestFunctions());
2944 const vector<FunctionContainer> shaderFuncs = wrapCoreFunctions(NegativeTestShared::getNegativeShaderApiTestFunctions());
2945 const vector<FunctionContainer> fragmentFuncs = wrapCoreFunctions(NegativeTestShared::getNegativeFragmentApiTestFunctions());
2946 const vector<FunctionContainer> vaFuncs = wrapCoreFunctions(NegativeTestShared::getNegativeVertexArrayApiTestFunctions());
2947 const vector<FunctionContainer> stateFuncs = wrapCoreFunctions(NegativeTestShared::getNegativeStateApiTestFunctions());
2948 const vector<FunctionContainer> atomicCounterFuncs = wrapCoreFunctions(NegativeTestShared::getNegativeAtomicCounterTestFunctions());
2949 const vector<FunctionContainer> imageLoadFuncs = wrapCoreFunctions(NegativeTestShared::getNegativeShaderImageLoadTestFunctions());
2950 const vector<FunctionContainer> imageStoreFuncs = wrapCoreFunctions(NegativeTestShared::getNegativeShaderImageStoreTestFunctions());
2951 const vector<FunctionContainer> imageAtomicFuncs = wrapCoreFunctions(NegativeTestShared::getNegativeShaderImageAtomicTestFunctions());
2952 const vector<FunctionContainer> imageAtomicExchangeFuncs = wrapCoreFunctions(NegativeTestShared::getNegativeShaderImageAtomicExchangeTestFunctions());
2953 const vector<FunctionContainer> shaderFunctionFuncs = wrapCoreFunctions(NegativeTestShared::getNegativeShaderFunctionTestFunctions());
2954 const vector<FunctionContainer> shaderDirectiveFuncs = wrapCoreFunctions(NegativeTestShared::getNegativeShaderDirectiveTestFunctions());
2955 const vector<FunctionContainer> preciseFuncs = wrapCoreFunctions(NegativeTestShared::getNegativePreciseTestFunctions());
2956 const vector<FunctionContainer> advancedBlendFuncs = wrapCoreFunctions(NegativeTestShared::getNegativeAdvancedBlendEquationTestFunctions());
2957 const vector<FunctionContainer> externalFuncs = getUserMessageFuncs();
2960 using namespace gls::StateQueryUtil;
2962 tcu::TestCaseGroup* const queries = new tcu::TestCaseGroup(m_testCtx, "state_query", "State query");
2967 const char* targetName;
2972 { "max_debug_message_length", "MAX_DEBUG_MESSAGE_LENGTH", GL_MAX_DEBUG_MESSAGE_LENGTH, 1 },
2973 { "max_debug_logged_messages", "MAX_DEBUG_LOGGED_MESSAGES", GL_MAX_DEBUG_LOGGED_MESSAGES, 1 },
2974 { "max_debug_group_stack_depth", "MAX_DEBUG_GROUP_STACK_DEPTH", GL_MAX_DEBUG_GROUP_STACK_DEPTH, 64 },
2975 { "max_label_length", "MAX_LABEL_LENGTH", GL_MAX_LABEL_LENGTH, 256 },
2980 #define FOR_ALL_TYPES(X) \
2984 const char* const postfix = "_getboolean"; \
2985 const QueryType queryType = QUERY_BOOLEAN; \
2989 const char* const postfix = "_getinteger"; \
2990 const QueryType queryType = QUERY_INTEGER; \
2994 const char* const postfix = "_getinteger64"; \
2995 const QueryType queryType = QUERY_INTEGER64; \
2999 const char* const postfix = "_getfloat"; \
3000 const QueryType queryType = QUERY_FLOAT; \
3004 while (deGetFalse())
3005 #define FOR_ALL_ENABLE_TYPES(X) \
3009 const char* const postfix = "_isenabled"; \
3010 const QueryType queryType = QUERY_ISENABLED; \
3015 while (deGetFalse())
3017 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(limits); ++ndx)
3019 FOR_ALL_TYPES(queries->addChild(new LimitQueryCase(m_context,
3020 (std::string(limits[ndx].name) + postfix).c_str(),
3021 (std::string("Test ") + limits[ndx].targetName).c_str(),
3022 limits[ndx].target, limits[ndx].limit, queryType)));
3025 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)));
3026 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)));
3028 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)));
3029 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)));
3030 FOR_ALL_TYPES(queries->addChild(new GroupStackDepthQueryCase(m_context, (std::string("debug_group_stack_depth") + postfix).c_str(), "Test DEBUG_GROUP_STACK_DEPTH", queryType)));
3032 queries->addChild(new DebugCallbackFunctionCase (m_context, "debug_callback_function_getpointer", "Test DEBUG_CALLBACK_FUNCTION"));
3033 queries->addChild(new DebugCallbackUserParamCase(m_context, "debug_callback_user_param_getpointer", "Test DEBUG_CALLBACK_USER_PARAM"));
3035 #undef FOR_ALL_TYPES
3036 #undef FOR_ALL_ENABLE_TYPES
3040 tcu::TestCaseGroup* const negative = new tcu::TestCaseGroup(m_testCtx, "negative_coverage", "API error coverage with various reporting methods");
3044 tcu::TestCaseGroup* const host = new tcu::TestCaseGroup(m_testCtx, "callbacks", "Reporting of standard API errors via callback");
3046 negative->addChild(host);
3047 host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "buffer", "Negative Buffer API Cases", bufferFuncs));
3048 host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "texture", "Negative Texture API Cases", textureFuncs));
3049 host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "shader", "Negative Shader API Cases", shaderFuncs));
3050 host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "fragment", "Negative Fragment API Cases", fragmentFuncs));
3051 host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "vertex_array", "Negative Vertex Array API Cases", vaFuncs));
3052 host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "state", "Negative GL State API Cases", stateFuncs));
3053 host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "atomic_counter", "Negative Atomic Counter API Cases", atomicCounterFuncs));
3054 host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "shader_image_load", "Negative Shader Image Load API Cases", imageLoadFuncs));
3055 host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "shader_image_store", "Negative Shader Image Store API Cases", imageStoreFuncs));
3056 host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "shader_image_atomic", "Negative Shader Image Atomic API Cases", imageAtomicFuncs));
3057 host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "shader_image_exchange", "Negative Shader Image Atomic Exchange API Cases", imageAtomicExchangeFuncs));
3058 host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "shader_function", "Negative Shader Function Cases", shaderFunctionFuncs));
3059 host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "shader_directive", "Negative Shader Directive Cases", shaderDirectiveFuncs));
3060 host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "precise", "Negative Precise Cases", preciseFuncs));
3061 host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "advanced_blend", "Negative Advanced Blend Equation Cases", advancedBlendFuncs));
3065 tcu::TestCaseGroup* const host = new tcu::TestCaseGroup(m_testCtx, "log", "Reporting of standard API errors via log");
3067 negative->addChild(host);
3069 host->addChild(createChildCases(CASETYPE_LOG, m_context, "buffer", "Negative Buffer API Cases", bufferFuncs));
3070 host->addChild(createChildCases(CASETYPE_LOG, m_context, "texture", "Negative Texture API Cases", textureFuncs));
3071 host->addChild(createChildCases(CASETYPE_LOG, m_context, "shader", "Negative Shader API Cases", shaderFuncs));
3072 host->addChild(createChildCases(CASETYPE_LOG, m_context, "fragment", "Negative Fragment API Cases", fragmentFuncs));
3073 host->addChild(createChildCases(CASETYPE_LOG, m_context, "vertex_array", "Negative Vertex Array API Cases", vaFuncs));
3074 host->addChild(createChildCases(CASETYPE_LOG, m_context, "state", "Negative GL State API Cases", stateFuncs));
3075 host->addChild(createChildCases(CASETYPE_LOG, m_context, "atomic_counter", "Negative Atomic Counter API Cases", atomicCounterFuncs));
3076 host->addChild(createChildCases(CASETYPE_LOG, m_context, "shader_image_load", "Negative Shader Image Load API Cases", imageLoadFuncs));
3077 host->addChild(createChildCases(CASETYPE_LOG, m_context, "shader_image_store", "Negative Shader Image Store API Cases", imageStoreFuncs));
3078 host->addChild(createChildCases(CASETYPE_LOG, m_context, "shader_image_atomic", "Negative Shader Image Atomic API Cases", imageAtomicFuncs));
3079 host->addChild(createChildCases(CASETYPE_LOG, m_context, "shader_image_exchange", "Negative Shader Image Atomic Exchange API Cases", imageAtomicExchangeFuncs));
3080 host->addChild(createChildCases(CASETYPE_LOG, m_context, "shader_function", "Negative Shader Function Cases", shaderFunctionFuncs));
3081 host->addChild(createChildCases(CASETYPE_LOG, m_context, "shader_directive", "Negative Shader Directive Cases", shaderDirectiveFuncs));
3082 host->addChild(createChildCases(CASETYPE_LOG, m_context, "precise", "Negative Precise Cases", preciseFuncs));
3083 host->addChild(createChildCases(CASETYPE_LOG, m_context, "advanced_blend", "Negative Advanced Blend Equation Cases", advancedBlendFuncs));
3087 tcu::TestCaseGroup* const host = new tcu::TestCaseGroup(m_testCtx, "get_error", "Reporting of standard API errors via glGetError");
3089 negative->addChild(host);
3091 host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "buffer", "Negative Buffer API Cases", bufferFuncs));
3092 host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "texture", "Negative Texture API Cases", textureFuncs));
3093 host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "shader", "Negative Shader API Cases", shaderFuncs));
3094 host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "fragment", "Negative Fragment API Cases", fragmentFuncs));
3095 host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "vertex_array", "Negative Vertex Array API Cases", vaFuncs));
3096 host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "state", "Negative GL State API Cases", stateFuncs));
3097 host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "atomic_counter", "Negative Atomic Counter API Cases", atomicCounterFuncs));
3098 host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "shader_image_load", "Negative Shader Image Load API Cases", imageLoadFuncs));
3099 host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "shader_image_store", "Negative Shader Image Store API Cases", imageStoreFuncs));
3100 host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "shader_image_atomic", "Negative Shader Image Atomic API Cases", imageAtomicFuncs));
3101 host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "shader_image_exchange", "Negative Shader Image Atomic Exchange API Cases", imageAtomicExchangeFuncs));
3102 host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "shader_function", "Negative Shader Function Cases", shaderFunctionFuncs));
3103 host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "shader_directive", "Negative Shader Directive Cases", shaderDirectiveFuncs));
3104 host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "precise", "Negative Precise Cases", preciseFuncs));
3105 host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "advanced_blend", "Negative Advanced Blend Equation Cases", advancedBlendFuncs));
3110 tcu::TestCaseGroup* const host = createChildCases(CASETYPE_CALLBACK, m_context, "externally_generated", "Externally Generated Messages", externalFuncs);
3112 host->addChild(new GroupCase(m_context, "push_pop_consistency", "Push/pop message generation with full message output checking"));
3118 vector<FunctionContainer> containers;
3119 vector<TestFunctionWrapper> allFuncs;
3121 de::Random rng (0x53941903 ^ m_context.getTestContext().getCommandLine().getBaseSeed());
3123 containers.insert(containers.end(), bufferFuncs.begin(), bufferFuncs.end());
3124 containers.insert(containers.end(), textureFuncs.begin(), textureFuncs.end());
3125 containers.insert(containers.end(), externalFuncs.begin(), externalFuncs.end());
3127 for (size_t ndx = 0; ndx < containers.size(); ndx++)
3128 allFuncs.push_back(containers[ndx].function);
3130 rng.shuffle(allFuncs.begin(), allFuncs.end());
3133 tcu::TestCaseGroup* const filtering = new tcu::TestCaseGroup(m_testCtx, "error_filters", "Filtering of reported errors");
3134 const int errorFuncsPerCase = 4;
3135 const int maxFilteringCaseCount = 32;
3136 const int caseCount = (int(allFuncs.size()) + errorFuncsPerCase-1) / errorFuncsPerCase;
3138 addChild(filtering);
3140 for (int caseNdx = 0; caseNdx < de::min(caseCount, maxFilteringCaseCount); caseNdx++)
3142 const int start = caseNdx*errorFuncsPerCase;
3143 const int end = de::min((caseNdx+1)*errorFuncsPerCase, int(allFuncs.size()));
3144 const string name = "case_" + de::toString(caseNdx);
3145 vector<TestFunctionWrapper> funcs (allFuncs.begin()+start, allFuncs.begin()+end);
3147 // These produce lots of different message types, thus always include at least one when testing filtering
3148 funcs.insert(funcs.end(), externalFuncs[caseNdx%externalFuncs.size()].function);
3150 filtering->addChild(new FilterCase(m_context, name.c_str(), "DebugMessageControl usage", funcs));
3155 tcu::TestCaseGroup* const groups = new tcu::TestCaseGroup(m_testCtx, "error_groups", "Filtering of reported errors with use of Error Groups");
3156 const int errorFuncsPerCase = 4;
3157 const int maxFilteringCaseCount = 16;
3158 const int caseCount = (int(allFuncs.size()) + errorFuncsPerCase-1) / errorFuncsPerCase;
3162 for (int caseNdx = 0; caseNdx < caseCount && caseNdx < maxFilteringCaseCount; caseNdx++)
3164 const int start = caseNdx*errorFuncsPerCase;
3165 const int end = de::min((caseNdx+1)*errorFuncsPerCase, int(allFuncs.size()));
3166 const string name = ("case_" + de::toString(caseNdx)).c_str();
3167 vector<TestFunctionWrapper> funcs (&allFuncs[0]+start, &allFuncs[0]+end);
3169 // These produce lots of different message types, thus always include at least one when testing filtering
3170 funcs.insert(funcs.end(), externalFuncs[caseNdx%externalFuncs.size()].function);
3172 groups->addChild(new GroupFilterCase(m_context, name.c_str(), "Debug Group usage", funcs));
3177 tcu::TestCaseGroup* const async = new tcu::TestCaseGroup(m_testCtx, "async", "Asynchronous message generation");
3178 const int errorFuncsPerCase = 2;
3179 const int maxAsyncCaseCount = 16;
3180 const int caseCount = (int(allFuncs.size()) + errorFuncsPerCase-1) / errorFuncsPerCase;
3184 for (int caseNdx = 0; caseNdx < caseCount && caseNdx < maxAsyncCaseCount; caseNdx++)
3186 const int start = caseNdx*errorFuncsPerCase;
3187 const int end = de::min((caseNdx+1)*errorFuncsPerCase, int(allFuncs.size()));
3188 const string name = ("case_" + de::toString(caseNdx)).c_str();
3189 vector<TestFunctionWrapper> funcs (&allFuncs[0]+start, &allFuncs[0]+end);
3192 async->addChild(new AsyncCase(m_context, (name+"_callback").c_str(), "Async message generation", funcs, true));
3194 async->addChild(new AsyncCase(m_context, (name+"_log").c_str(), "Async message generation", funcs, false));
3200 tcu::TestCaseGroup* const labels = new tcu::TestCaseGroup(m_testCtx, "object_labels", "Labeling objects");
3209 { GL_BUFFER, "buffer", "Debug label on a buffer object" },
3210 { GL_SHADER, "shader", "Debug label on a shader object" },
3211 { GL_PROGRAM, "program", "Debug label on a program object" },
3212 { GL_QUERY, "query", "Debug label on a query object" },
3213 { GL_PROGRAM_PIPELINE, "program_pipeline", "Debug label on a program pipeline object" },
3214 { GL_TRANSFORM_FEEDBACK, "transform_feedback", "Debug label on a transform feedback object" },
3215 { GL_SAMPLER, "sampler", "Debug label on a sampler object" },
3216 { GL_TEXTURE, "texture", "Debug label on a texture object" },
3217 { GL_RENDERBUFFER, "renderbuffer", "Debug label on a renderbuffer object" },
3218 { GL_FRAMEBUFFER, "framebuffer", "Debug label on a framebuffer object" },
3223 labels->addChild(new InitialLabelCase (m_context, "initial", "Debug label initial value"));
3224 labels->addChild(new ClearLabelCase (m_context, "clearing", "Debug label clearing"));
3225 labels->addChild(new SpecifyWithLengthCase (m_context, "specify_with_length", "Debug label specified with length"));
3226 labels->addChild(new BufferLimitedLabelCase (m_context, "buffer_limited_query", "Debug label query to too short buffer"));
3227 labels->addChild(new LabelMaxSizeCase (m_context, "max_label_length", "Max sized debug label"));
3228 labels->addChild(new LabelLengthCase (m_context, "query_length_only", "Query debug label length"));
3230 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(cases); ndx++)
3231 labels->addChild(new LabelCase(m_context, cases[ndx].name, cases[ndx].desc, cases[ndx].identifier));
3232 labels->addChild(new SyncLabelCase(m_context, "sync", "Debug label on a sync object"));