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"
38 #include "deUniquePtr.hpp"
39 #include "deRandom.hpp"
40 #include "deStringUtil.hpp"
41 #include "deSTLUtil.hpp"
42 #include "deMutex.hpp"
45 #include "gluRenderContext.hpp"
46 #include "gluContextInfo.hpp"
47 #include "gluCallLogWrapper.hpp"
48 #include "gluStrUtil.hpp"
50 #include "glwDefs.hpp"
51 #include "glwEnums.hpp"
52 #include "glwFunctions.hpp"
54 #include "tes31Context.hpp"
55 #include "tcuTestContext.hpp"
56 #include "tcuCommandLine.hpp"
57 #include "tcuResultCollector.hpp"
59 #include "glsStateQueryUtil.hpp"
77 using tcu::ResultCollector;
79 using glu::CallLogWrapper;
81 using NegativeTestShared::NegativeTestContext;
83 static const GLenum s_debugTypes[] =
86 GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR,
87 GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR,
88 GL_DEBUG_TYPE_PORTABILITY,
89 GL_DEBUG_TYPE_PERFORMANCE,
92 GL_DEBUG_TYPE_PUSH_GROUP,
93 GL_DEBUG_TYPE_POP_GROUP,
96 static const GLenum s_debugSeverities[] =
98 GL_DEBUG_SEVERITY_HIGH,
99 GL_DEBUG_SEVERITY_MEDIUM,
100 GL_DEBUG_SEVERITY_LOW,
101 GL_DEBUG_SEVERITY_NOTIFICATION,
104 static bool isKHRDebugSupported (Context& ctx)
106 const bool isES32 = glu::contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2));
107 return isES32 || ctx.getContextInfo().isExtensionSupported("GL_KHR_debug");
112 class DebugMessageTestContext : public NegativeTestContext
115 DebugMessageTestContext (BaseCase& host,
116 glu::RenderContext& renderCtx,
117 const glu::ContextInfo& ctxInfo,
119 tcu::ResultCollector& results,
121 ~DebugMessageTestContext (void);
123 void expectMessage (GLenum source, GLenum type);
126 BaseCase& m_debugHost;
129 class TestFunctionWrapper
132 typedef void (*CoreTestFunc)(NegativeTestContext& ctx);
133 typedef void (*DebugTestFunc)(DebugMessageTestContext& ctx);
135 TestFunctionWrapper (void);
136 explicit TestFunctionWrapper (CoreTestFunc func);
137 explicit TestFunctionWrapper (DebugTestFunc func);
139 void call (DebugMessageTestContext& ctx) const;
153 DebugTestFunc debugFn;
157 TestFunctionWrapper::TestFunctionWrapper (void)
162 TestFunctionWrapper::TestFunctionWrapper (CoreTestFunc func)
165 m_func.coreFn = func;
168 TestFunctionWrapper::TestFunctionWrapper (DebugTestFunc func)
171 m_func.debugFn = func;
174 void TestFunctionWrapper::call (DebugMessageTestContext& ctx) const
176 if (m_type == TYPE_CORE)
177 m_func.coreFn(static_cast<NegativeTestContext&>(ctx));
178 else if (m_type == TYPE_DEBUG)
184 void emitMessages (DebugMessageTestContext& ctx, GLenum source)
186 for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(s_debugTypes); typeNdx++)
188 for (int severityNdx = 0; severityNdx < DE_LENGTH_OF_ARRAY(s_debugSeverities); severityNdx++)
190 const GLenum type = s_debugTypes[typeNdx];
191 const GLenum severity = s_debugSeverities[severityNdx];
192 const string msg = string("Application generated message with type ") + glu::getDebugMessageTypeName(type)
193 + " and severity " + glu::getDebugMessageSeverityName(severity);
195 // Use severity as ID, guaranteed unique
196 ctx.glDebugMessageInsert(source, type, severity, severity, -1, msg.c_str());
197 ctx.expectMessage(source, type);
202 void application_messages (DebugMessageTestContext& ctx)
204 ctx.beginSection("Messages with source of GL_DEBUG_SOURCE_APPLICATION");
205 emitMessages(ctx, GL_DEBUG_SOURCE_APPLICATION);
209 void thirdparty_messages (DebugMessageTestContext& ctx)
211 ctx.beginSection("Messages with source of GL_DEBUG_SOURCE_THIRD_PARTY");
212 emitMessages(ctx, GL_DEBUG_SOURCE_THIRD_PARTY);
216 void push_pop_messages (DebugMessageTestContext& ctx)
218 ctx.beginSection("Push/Pop Debug Group");
220 ctx.glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 1, -1, "Application group 1");
221 ctx.expectMessage(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PUSH_GROUP);
222 ctx.glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 2, -1, "Application group 1-1");
223 ctx.expectMessage(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PUSH_GROUP);
224 ctx.glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 3, -1, "Application group 1-1-1");
225 ctx.expectMessage(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PUSH_GROUP);
226 ctx.glPopDebugGroup();
227 ctx.expectMessage(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_POP_GROUP);
228 ctx.glPopDebugGroup();
229 ctx.expectMessage(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_POP_GROUP);
231 ctx.glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 4, -1, "Application group 1-2");
232 ctx.expectMessage(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PUSH_GROUP);
233 ctx.glPopDebugGroup();
234 ctx.expectMessage(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_POP_GROUP);
236 ctx.glPushDebugGroup(GL_DEBUG_SOURCE_THIRD_PARTY, 4, -1, "3rd Party group 1-3");
237 ctx.expectMessage(GL_DEBUG_SOURCE_THIRD_PARTY, GL_DEBUG_TYPE_PUSH_GROUP);
238 ctx.glPopDebugGroup();
239 ctx.expectMessage(GL_DEBUG_SOURCE_THIRD_PARTY, GL_DEBUG_TYPE_POP_GROUP);
240 ctx.glPopDebugGroup();
241 ctx.expectMessage(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_POP_GROUP);
243 ctx.glPushDebugGroup(GL_DEBUG_SOURCE_THIRD_PARTY, 4, -1, "3rd Party group 2");
244 ctx.expectMessage(GL_DEBUG_SOURCE_THIRD_PARTY, GL_DEBUG_TYPE_PUSH_GROUP);
245 ctx.glPopDebugGroup();
246 ctx.expectMessage(GL_DEBUG_SOURCE_THIRD_PARTY, GL_DEBUG_TYPE_POP_GROUP);
251 struct FunctionContainer
253 TestFunctionWrapper function;
258 vector<FunctionContainer> getUserMessageFuncs (void)
260 FunctionContainer funcs[] =
262 { TestFunctionWrapper(application_messages), "application_messages", "Externally generated messages from the application" },
263 { TestFunctionWrapper(thirdparty_messages), "third_party_messages", "Externally generated messages from a third party" },
264 { TestFunctionWrapper(push_pop_messages), "push_pop_stack", "Messages from pushing/popping debug groups" },
267 return std::vector<FunctionContainer>(DE_ARRAY_BEGIN(funcs), DE_ARRAY_END(funcs));
270 // Data required to uniquely identify a debug message
277 MessageID (void) : source(GL_NONE), type(GL_NONE), id(0) {}
278 MessageID (GLenum source_, GLenum type_, GLuint id_) : source(source_), type(type_), id(id_) {}
280 bool operator== (const MessageID& rhs) const { return source == rhs.source && type == rhs.type && id == rhs.id;}
281 bool operator!= (const MessageID& rhs) const { return source != rhs.source || type != rhs.type || id != rhs.id;}
282 bool operator< (const MessageID& rhs) const
284 return source < rhs.source || (source == rhs.source && (type < rhs.type || (type == rhs.type && id < rhs.id)));
288 std::ostream& operator<< (std::ostream& str, const MessageID &id)
290 return str << glu::getDebugMessageSourceStr(id.source) << ", " << glu::getDebugMessageTypeStr(id.type) << ", " << id.id;
293 // All info from a single debug message
300 MessageData (void) : id(MessageID()), severity(GL_NONE) {}
301 MessageData (const MessageID& id_, GLenum severity_, const string& message_) : id(id_) , severity(severity_) , message(message_) {}
304 extern "C" typedef void GLW_APIENTRY DebugCallbackFunc(GLenum, GLenum, GLuint, GLenum, GLsizei, const char*, void*);
307 class BaseCase : public NegativeTestShared::ErrorCase
310 BaseCase (Context& ctx,
313 virtual ~BaseCase (void) {}
315 virtual IterateResult iterate (void) = 0;
317 virtual void expectMessage (GLenum source, GLenum type);
318 virtual void expectError (GLenum error0, GLenum error1);
321 struct VerificationResult {
322 const qpTestResult result;
323 const string resultMessage;
324 const string logMessage;
326 VerificationResult (qpTestResult result_, const string& resultMessage_, const string& logMessage_)
327 : result(result_), resultMessage(resultMessage_), logMessage(logMessage_) {}
330 static DebugCallbackFunc callbackHandle;
331 virtual void callback (GLenum source, GLenum type, GLuint id, GLenum severity, const std::string& message);
334 VerificationResult verifyMessageCount (const MessageID& id, GLenum severity, int refCount, int resCount, bool messageEnabled) const;
336 // Verify a single message instance against expected attributes
337 void verifyMessage (const MessageData& message, GLenum source, GLenum type, GLuint id, GLenum severity);
338 void verifyMessage (const MessageData& message, GLenum source, GLenum type);
340 bool verifyMessageExists (const MessageData& message, GLenum source, GLenum type);
341 void verifyMessageGroup (const MessageData& message, GLenum source, GLenum type);
342 void verifyMessageString (const MessageData& message);
344 bool isDebugContext (void) const;
346 tcu::ResultCollector m_results;
349 void BaseCase::callbackHandle (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const char* message, void* userParam)
351 static_cast<BaseCase*>(userParam)->callback(source, type, id, severity, string(message, &message[length]));
354 BaseCase::BaseCase (Context& ctx, const char* name, const char* desc)
355 : ErrorCase(ctx, name, desc)
359 void BaseCase::expectMessage (GLenum source, GLenum type)
365 void BaseCase::expectError (GLenum error0, GLenum error1)
367 if (error0 != GL_NO_ERROR || error1 != GL_NO_ERROR)
368 expectMessage(GL_DEBUG_SOURCE_API, GL_DEBUG_TYPE_ERROR);
370 expectMessage(GL_DONT_CARE, GL_DONT_CARE);
373 void BaseCase::callback (GLenum source, GLenum type, GLuint id, GLenum severity, const string& message)
382 BaseCase::VerificationResult BaseCase::verifyMessageCount (const MessageID& id, GLenum severity, int refCount, int resCount, bool messageEnabled) const
384 std::stringstream log;
386 // This message should not be filtered out
389 if (resCount != refCount)
392 * Technically nothing requires the implementation to be consistent in terms
393 * of the messages it produces in most situations, allowing the set of messages
394 * produced to vary between executions. This function splits messages
395 * into deterministic and non-deterministic to facilitate handling of such messages.
397 * Non-deterministic messages that are present in differing quantities in filtered and
398 * unfiltered runs will not fail the test case unless in direct violation of a filter:
399 * the implementation may produce an arbitrary number of such messages when they are
400 * not filtered out and none when they are filtered.
402 * A list of error source/type combinations with their assumed behaviour and
403 * the rationale for expecting such behaviour follows
405 * For API/shader messages we assume that the following types are deterministic:
406 * DEBUG_TYPE_ERROR Errors specified by spec and should always be produced
408 * For API messages the following types are assumed to be non-deterministic
409 * and treated as quality warnings since the underlying reported issue does not change between calls:
410 * DEBUG_TYPE_DEPRECATED_BEHAVIOR Reasonable to only report first instance
411 * DEBUG_TYPE_UNDEFINED_BEHAVIOR Reasonable to only report first instance
412 * DEBUG_TYPE_PORTABILITY Reasonable to only report first instance
414 * For API messages the following types are assumed to be non-deterministic
415 * and do not affect test results.
416 * DEBUG_TYPE_PERFORMANCE May be tied to arbitrary factors, reasonable to report only first instance
417 * DEBUG_TYPE_OTHER Definition allows arbitrary contents
419 * For 3rd party and application messages the following types are deterministic:
420 * DEBUG_TYPE_MARKER Only generated by test
421 * DEBUG_TYPE_PUSH_GROUP Only generated by test
422 * DEBUG_TYPE_POP_GROUP Only generated by test
423 * All others Only generated by test
425 * All messages with category of window system or other are treated as non-deterministic
426 * and do not effect test results since they can be assumed to be outside control of
427 * both the implementation and test case
431 const bool isDeterministic = id.source == GL_DEBUG_SOURCE_APPLICATION ||
432 id.source == GL_DEBUG_SOURCE_THIRD_PARTY ||
433 ((id.source == GL_DEBUG_SOURCE_API || id.source == GL_DEBUG_SOURCE_SHADER_COMPILER) && id.type == GL_DEBUG_TYPE_ERROR);
435 const bool canIgnore = id.source == GL_DEBUG_SOURCE_WINDOW_SYSTEM || id.source == GL_DEBUG_SOURCE_OTHER;
439 if (resCount > refCount)
441 log << "Extra instances of message were found: (" << id << ") with "
442 << glu::getDebugMessageSeverityStr(severity)
443 << " (got " << resCount << ", expected " << refCount << ")";
444 return VerificationResult(QP_TEST_RESULT_FAIL, "Extra instances of a deterministic message were present", log.str());
448 log << "Instances of message were missing: (" << id << ") with "
449 << glu::getDebugMessageSeverityStr(severity)
450 << " (got " << resCount << ", expected " << refCount << ")";
451 return VerificationResult(QP_TEST_RESULT_FAIL, "Message missing", log.str());
456 if (resCount > refCount)
458 log << "Extra instances of message were found but the message is non-deterministic(warning): (" << id << ") with "
459 << glu::getDebugMessageSeverityStr(severity)
460 << " (got " << resCount << ", expected " << refCount << ")";
461 return VerificationResult(QP_TEST_RESULT_QUALITY_WARNING, "Extra instances of a message were present", log.str());
465 log << "Instances of message were missing but the message is non-deterministic(warning): (" << id << ") with "
466 << glu::getDebugMessageSeverityStr(severity)
467 << " (got " << resCount << ", expected " << refCount << ")";
468 return VerificationResult(QP_TEST_RESULT_QUALITY_WARNING, "Message missing", log.str());
473 if (resCount > refCount)
475 log << "Extra instances of message were found but the message is non-deterministic(ignored): (" << id << ") with "
476 << glu::getDebugMessageSeverityStr(severity)
477 << " (got " << resCount << ", expected " << refCount << ")";
478 return VerificationResult(QP_TEST_RESULT_PASS, "", log.str());
482 log << "Instances of message were missing but the message is non-deterministic(ignored): (" << id << ") with "
483 << glu::getDebugMessageSeverityStr(severity)
484 << " (got " << resCount << ", expected " << refCount << ")";
485 return VerificationResult(QP_TEST_RESULT_PASS, "", log.str());
489 else // Passed as appropriate
491 log << "Message was found when expected: ("<< id << ") with "
492 << glu::getDebugMessageSeverityStr(severity);
493 return VerificationResult(QP_TEST_RESULT_PASS, "", log.str());
496 // Message should be filtered out
502 log << "Message was excluded correctly: (" << id << ") with "
503 << glu::getDebugMessageSeverityStr(severity);
504 return VerificationResult(QP_TEST_RESULT_PASS, "", log.str());
506 // Only present in filtered run (ERROR)
507 else if (resCount > 0 && refCount == 0)
509 log << "A message was not excluded as it should have been: (" << id << ") with "
510 << glu::getDebugMessageSeverityStr(severity)
511 << ". This message was not present in the reference run";
512 return VerificationResult(QP_TEST_RESULT_FAIL, "A message was not filtered out", log.str());
514 // Present in both runs (ERROR)
517 log << "A message was not excluded as it should have been: (" << id << ") with "
518 << glu::getDebugMessageSeverityStr(severity);
519 return VerificationResult(QP_TEST_RESULT_FAIL, "A message was not filtered out", log.str());
524 // Return true if message needs further verification
525 bool BaseCase::verifyMessageExists (const MessageData& message, GLenum source, GLenum type)
527 TestLog& log = m_testCtx.getLog();
529 if (source == GL_DONT_CARE || type == GL_DONT_CARE)
531 else if (message.id.source == GL_NONE || message.id.type == GL_NONE)
533 if (isDebugContext())
535 m_results.addResult(QP_TEST_RESULT_FAIL, "Message was not reported as expected");
536 log << TestLog::Message << "A message was expected but none was reported" << TestLog::EndMessage;
540 m_results.addResult(QP_TEST_RESULT_QUALITY_WARNING, "Verification accuracy is lacking without a debug context");
541 log << TestLog::Message << "A message was expected but none was reported. Running without a debug context" << TestLog::EndMessage;
549 void BaseCase::verifyMessageGroup (const MessageData& message, GLenum source, GLenum type)
551 TestLog& log = m_testCtx.getLog();
553 if (message.id.source != source)
555 m_results.addResult(QP_TEST_RESULT_FAIL, "Incorrect message source");
556 log << TestLog::Message << "Message source was " << glu::getDebugMessageSourceStr(message.id.source)
557 << " when it should have been " << glu::getDebugMessageSourceStr(source) << TestLog::EndMessage;
560 if (message.id.type != type)
562 m_results.addResult(QP_TEST_RESULT_FAIL, "Incorrect message type");
563 log << TestLog::Message << "Message type was " << glu::getDebugMessageTypeStr(message.id.type)
564 << " when it should have been " << glu::getDebugMessageTypeStr(type) << TestLog::EndMessage;
568 void BaseCase::verifyMessageString (const MessageData& message)
570 TestLog& log = m_testCtx.getLog();
572 log << TestLog::Message << "Driver says: \"" << message.message << "\"" << TestLog::EndMessage;
574 if (message.message.empty())
576 m_results.addResult(QP_TEST_RESULT_QUALITY_WARNING, "Empty message");
577 log << TestLog::Message << "Message message was empty" << TestLog::EndMessage;
581 void BaseCase::verifyMessage (const MessageData& message, GLenum source, GLenum type)
583 if (verifyMessageExists(message, source, type))
585 verifyMessageString(message);
586 verifyMessageGroup(message, source, type);
590 void BaseCase::verifyMessage (const MessageData& message, GLenum source, GLenum type, GLuint id, GLenum severity)
592 TestLog& log = m_testCtx.getLog();
594 if (verifyMessageExists(message, source, type))
596 verifyMessageString(message);
597 verifyMessageGroup(message, source, type);
599 if (message.id.id != id)
601 m_results.addResult(QP_TEST_RESULT_FAIL, "Incorrect message id");
602 log << TestLog::Message << "Message id was " << message.id.id
603 << " when it should have been " << id << TestLog::EndMessage;
606 if (message.severity != severity)
608 m_results.addResult(QP_TEST_RESULT_FAIL, "Incorrect message severity");
609 log << TestLog::Message << "Message severity was " << glu::getDebugMessageSeverityStr(message.severity)
610 << " when it should have been " << glu::getDebugMessageSeverityStr(severity) << TestLog::EndMessage;
615 bool BaseCase::isDebugContext (void) const
617 return (m_context.getRenderContext().getType().getFlags() & glu::CONTEXT_DEBUG) != 0;
620 // Generate errors, verify that each error results in a callback call
621 class CallbackErrorCase : public BaseCase
624 CallbackErrorCase (Context& ctx,
627 TestFunctionWrapper errorFunc);
628 virtual ~CallbackErrorCase (void) {}
630 virtual IterateResult iterate (void);
632 virtual void expectMessage (GLenum source, GLenum type);
635 virtual void callback (GLenum source, GLenum type, GLuint id, GLenum severity, const string& message);
637 const TestFunctionWrapper m_errorFunc;
638 MessageData m_lastMessage;
641 CallbackErrorCase::CallbackErrorCase (Context& ctx,
644 TestFunctionWrapper errorFunc)
645 : BaseCase (ctx, name, desc)
646 , m_errorFunc (errorFunc)
650 CallbackErrorCase::IterateResult CallbackErrorCase::iterate (void)
652 TCU_CHECK_AND_THROW(NotSupportedError, isKHRDebugSupported(m_context), "GL_KHR_debug is not supported");
654 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
655 tcu::TestLog& log = m_testCtx.getLog();
656 DebugMessageTestContext context = DebugMessageTestContext(*this, m_context.getRenderContext(), m_context.getContextInfo(), log, m_results, true);
658 gl.enable(GL_DEBUG_OUTPUT);
659 gl.enable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
660 gl.debugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, DE_NULL, false); // disable all
661 gl.debugMessageControl(GL_DEBUG_SOURCE_API, GL_DEBUG_TYPE_ERROR, GL_DONT_CARE, 0, DE_NULL, true); // enable API errors
662 gl.debugMessageControl(GL_DEBUG_SOURCE_APPLICATION, GL_DONT_CARE, GL_DONT_CARE, 0, DE_NULL, true); // enable application messages
663 gl.debugMessageControl(GL_DEBUG_SOURCE_THIRD_PARTY, GL_DONT_CARE, GL_DONT_CARE, 0, DE_NULL, true); // enable third party messages
664 gl.debugMessageCallback(callbackHandle, this);
666 m_errorFunc.call(context);
668 gl.debugMessageCallback(DE_NULL, DE_NULL);
669 gl.disable(GL_DEBUG_OUTPUT);
671 m_results.setTestContextResult(m_testCtx);
676 void CallbackErrorCase::expectMessage (GLenum source, GLenum type)
678 verifyMessage(m_lastMessage, source, type);
679 m_lastMessage = MessageData();
681 // Reset error so that code afterwards (such as glu::ShaderProgram) doesn't break because of
682 // lingering error state.
683 m_context.getRenderContext().getFunctions().getError();
686 void CallbackErrorCase::callback (GLenum source, GLenum type, GLuint id, GLenum severity, const string& message)
688 m_lastMessage = MessageData(MessageID(source, type, id), severity, message);
691 // Generate errors, verify that each error results in a log entry
692 class LogErrorCase : public BaseCase
695 LogErrorCase (Context& context,
698 TestFunctionWrapper errorFunc);
699 virtual ~LogErrorCase (void) {}
701 virtual IterateResult iterate (void);
703 virtual void expectMessage (GLenum source, GLenum type);
706 const TestFunctionWrapper m_errorFunc;
707 MessageData m_lastMessage;
710 LogErrorCase::LogErrorCase (Context& ctx,
713 TestFunctionWrapper errorFunc)
714 : BaseCase (ctx, name, desc)
715 , m_errorFunc (errorFunc)
719 LogErrorCase::IterateResult LogErrorCase::iterate (void)
721 TCU_CHECK_AND_THROW(NotSupportedError, isKHRDebugSupported(m_context), "GL_KHR_debug is not supported");
723 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
724 tcu::TestLog& log = m_testCtx.getLog();
725 DebugMessageTestContext context = DebugMessageTestContext(*this, m_context.getRenderContext(), m_context.getContextInfo(), log, m_results, true);
728 gl.enable(GL_DEBUG_OUTPUT);
729 gl.enable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
730 gl.debugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, DE_NULL, false); // disable all
731 gl.debugMessageControl(GL_DEBUG_SOURCE_API, GL_DEBUG_TYPE_ERROR, GL_DONT_CARE, 0, DE_NULL, true); // enable API errors
732 gl.debugMessageCallback(DE_NULL, DE_NULL); // enable logging
733 gl.getIntegerv(GL_DEBUG_LOGGED_MESSAGES, &numMsg);
734 gl.getDebugMessageLog(numMsg, 0, DE_NULL, DE_NULL, DE_NULL, DE_NULL, DE_NULL, DE_NULL); // clear log
736 m_errorFunc.call(context);
738 gl.disable(GL_DEBUG_OUTPUT);
739 m_results.setTestContextResult(m_testCtx);
744 void LogErrorCase::expectMessage (GLenum source, GLenum type)
746 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
748 TestLog& log = m_testCtx.getLog();
751 if (source == GL_DONT_CARE || type == GL_DONT_CARE)
754 gl.getIntegerv(GL_DEBUG_LOGGED_MESSAGES, &numMsg);
758 if (isDebugContext())
760 m_results.addResult(QP_TEST_RESULT_FAIL, "Error was not reported as expected");
761 log << TestLog::Message << "A message was expected but none was reported (empty message log)" << TestLog::EndMessage;
765 m_results.addResult(QP_TEST_RESULT_QUALITY_WARNING, "Verification accuracy is lacking without a debug context");
766 log << TestLog::Message << "A message was expected but none was reported (empty message log). Running without a debug context" << TestLog::EndMessage;
771 // There may be messages other than the error we are looking for in the log.
772 // Strictly nothing prevents the implementation from producing more than the
773 // required error from an API call with a defined error. however we assume that
774 // since calls that produce an error should not change GL state the implementation
775 // should have nothing else to report.
777 gl.getDebugMessageLog(numMsg-1, 0, DE_NULL, DE_NULL, DE_NULL, DE_NULL, DE_NULL, DE_NULL); // Clear all but last
781 gl.getIntegerv(GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH, &msgLen);
783 TCU_CHECK_MSG(msgLen >= 0, "Negative message length");
784 TCU_CHECK_MSG(msgLen < 100000, "Excessively long message");
786 lastMsg.message.resize(msgLen);
787 gl.getDebugMessageLog(1, msgLen, &lastMsg.id.source, &lastMsg.id.type, &lastMsg.id.id, &lastMsg.severity, &msgLen, &lastMsg.message[0]);
790 log << TestLog::Message << "Driver says: \"" << lastMsg.message << "\"" << TestLog::EndMessage;
792 verifyMessage(lastMsg, source, type);
794 // Reset error so that code afterwards (such as glu::ShaderProgram) doesn't break because of
795 // lingering error state.
796 m_context.getRenderContext().getFunctions().getError();
799 // Generate errors, verify that calling glGetError afterwards produces desired result
800 class GetErrorCase : public BaseCase
803 GetErrorCase (Context& ctx,
806 TestFunctionWrapper errorFunc);
807 virtual ~GetErrorCase (void) {}
809 virtual IterateResult iterate (void);
811 virtual void expectMessage (GLenum source, GLenum type);
812 virtual void expectError (glw::GLenum error0, glw::GLenum error1);
815 const TestFunctionWrapper m_errorFunc;
818 GetErrorCase::GetErrorCase (Context& ctx,
821 TestFunctionWrapper errorFunc)
822 : BaseCase (ctx, name, desc)
823 , m_errorFunc (errorFunc)
827 GetErrorCase::IterateResult GetErrorCase::iterate (void)
829 tcu::TestLog& log = m_testCtx.getLog();
830 DebugMessageTestContext context = DebugMessageTestContext(*this, m_context.getRenderContext(), m_context.getContextInfo(), log, m_results, true);
832 m_errorFunc.call(context);
834 m_results.setTestContextResult(m_testCtx);
839 void GetErrorCase::expectMessage (GLenum source, GLenum type)
843 DE_FATAL("GetErrorCase cannot handle anything other than error codes");
846 void GetErrorCase::expectError (glw::GLenum error0, glw::GLenum error1)
848 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
849 TestLog& log = m_testCtx.getLog();
851 const GLenum result = gl.getError();
853 if (result != error0 && result != error1)
855 m_results.addResult(QP_TEST_RESULT_FAIL, "Incorrect error was reported");
856 if (error0 == error1)
857 log << TestLog::Message
858 << glu::getErrorStr(error0) << " was expected but got "
859 << glu::getErrorStr(result)
860 << TestLog::EndMessage;
862 log << TestLog::Message
863 << glu::getErrorStr(error0) << " or "
864 << glu::getErrorStr(error1) << " was expected but got "
865 << glu::getErrorStr(result)
866 << TestLog::EndMessage;
871 // Generate errors, log the types, disable some, regenerate errors, verify correct errors (not)reported
872 class FilterCase : public BaseCase
875 FilterCase (Context& ctx,
878 const vector<TestFunctionWrapper>& errorFuncs);
879 virtual ~FilterCase (void) {}
881 virtual IterateResult iterate (void);
883 virtual void expectMessage (GLenum source, GLenum type);
888 MessageFilter() : source(GL_DONT_CARE), type(GL_DONT_CARE), severity(GL_DONT_CARE), enabled(true) {} // Default to enable all
889 MessageFilter(GLenum source_, GLenum type_, GLenum severity_, const vector<GLuint>& ids_, bool enabled_) : source(source_), type(type_), severity(severity_), ids(ids_), enabled(enabled_) {}
898 virtual void callback (GLenum source, GLenum type, GLuint id, GLenum severity, const string& message);
900 vector<MessageData> genMessages (bool uselog, const string& desc);
902 vector<MessageFilter> genFilters (const vector<MessageData>& messages, const vector<MessageFilter>& initial, deUint32 seed, int iterations) const;
903 void applyFilters (const vector<MessageFilter>& filters) const;
904 bool isEnabled (const vector<MessageFilter>& filters, const MessageData& message) const;
906 void verify (const vector<MessageData>& refMessages,
907 const vector<MessageData>& filteredMessages,
908 const vector<MessageFilter>& filters);
910 const vector<TestFunctionWrapper> m_errorFuncs;
912 vector<MessageData>* m_currentErrors;
915 FilterCase::FilterCase (Context& ctx,
918 const vector<TestFunctionWrapper>& errorFuncs)
919 : BaseCase (ctx, name, desc)
920 , m_errorFuncs (errorFuncs)
921 , m_currentErrors (DE_NULL)
925 FilterCase::IterateResult FilterCase::iterate (void)
927 TCU_CHECK_AND_THROW(NotSupportedError, isKHRDebugSupported(m_context), "GL_KHR_debug is not supported");
929 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
931 gl.enable(GL_DEBUG_OUTPUT);
932 gl.enable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
933 gl.debugMessageCallback(callbackHandle, this);
934 gl.debugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, DE_NULL, true);
937 const vector<MessageData> refMessages = genMessages(true, "Reference run");
938 const MessageFilter baseFilter (GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, vector<GLuint>(), true);
939 const deUint32 baseSeed = deStringHash(getName()) ^ m_testCtx.getCommandLine().getBaseSeed();
940 const vector<MessageFilter> filters = genFilters(refMessages, vector<MessageFilter>(1, baseFilter), baseSeed, 4);
941 vector<MessageData> filteredMessages;
943 applyFilters(filters);
946 filteredMessages = genMessages(false, "Filtered run");
949 verify(refMessages, filteredMessages, filters);
951 if (!isDebugContext() && refMessages.empty())
952 m_results.addResult(QP_TEST_RESULT_QUALITY_WARNING, "Verification accuracy is lacking without a debug context");
955 gl.disable(GL_DEBUG_OUTPUT);
956 m_results.setTestContextResult(m_testCtx);
961 void FilterCase::expectMessage (GLenum source, GLenum type)
967 void FilterCase::callback (GLenum source, GLenum type, GLuint id, GLenum severity, const string& message)
970 m_currentErrors->push_back(MessageData(MessageID(source, type, id), severity, message));
973 vector<MessageData> FilterCase::genMessages (bool uselog, const string& desc)
975 tcu::TestLog& log = m_testCtx.getLog();
976 DebugMessageTestContext context = DebugMessageTestContext(*this, m_context.getRenderContext(), m_context.getContextInfo(), log, m_results, uselog);
977 tcu::ScopedLogSection section (log, "message gen", desc);
978 vector<MessageData> messages;
980 m_currentErrors = &messages;
982 for (int ndx = 0; ndx < int(m_errorFuncs.size()); ndx++)
983 m_errorFuncs[ndx].call(context);
985 m_currentErrors = DE_NULL;
990 vector<FilterCase::MessageFilter> FilterCase::genFilters (const vector<MessageData>& messages, const vector<MessageFilter>& initial, deUint32 seed, int iterations) const
992 de::Random rng (seed ^ deInt32Hash(deStringHash(getName())));
994 set<MessageID> tempMessageIds;
995 set<GLenum> tempSources;
996 set<GLenum> tempTypes;
997 set<GLenum> tempSeverities;
999 if (messages.empty())
1002 for (int ndx = 0; ndx < int(messages.size()); ndx++)
1004 const MessageData& msg = messages[ndx];
1006 tempMessageIds.insert(msg.id);
1007 tempSources.insert(msg.id.source);
1008 tempTypes.insert(msg.id.type);
1009 tempSeverities.insert(msg.severity);
1013 // Fetchable by index
1014 const vector<MessageID> messageIds (tempMessageIds.begin(), tempMessageIds.end());
1015 const vector<GLenum> sources (tempSources.begin(), tempSources.end());
1016 const vector<GLenum> types (tempTypes.begin(), tempTypes.end());
1017 const vector<GLenum> severities (tempSeverities.begin(), tempSeverities.end());
1019 vector<MessageFilter> filters = initial;
1021 for (int iteration = 0; iteration < iterations; iteration++)
1023 switch(rng.getInt(0, 8)) // Distribute so that per-message randomization (the default branch) is prevalent
1027 const GLenum source = sources[rng.getInt(0, int(sources.size()-1))];
1028 const bool enabled = rng.getBool();
1030 filters.push_back(MessageFilter(source, GL_DONT_CARE, GL_DONT_CARE, vector<GLuint>(), enabled));
1036 const GLenum type = types[rng.getUint32()%types.size()];
1037 const bool enabled = rng.getBool();
1039 filters.push_back(MessageFilter(GL_DONT_CARE, type, GL_DONT_CARE, vector<GLuint>(), enabled));
1045 const GLenum severity = severities[rng.getUint32()%severities.size()];
1046 const bool enabled = rng.getBool();
1048 filters.push_back(MessageFilter(GL_DONT_CARE, GL_DONT_CARE, severity, vector<GLuint>(), enabled));
1054 const int start = rng.getInt(0, int(messageIds.size()));
1056 for (int itr = 0; itr < 4; itr++)
1058 const MessageID& id = messageIds[(start+itr)%messageIds.size()];
1059 const bool enabled = rng.getBool();
1061 filters.push_back(MessageFilter(id.source, id.type, GL_DONT_CARE, vector<GLuint>(1, id.id), enabled));
1071 void FilterCase::applyFilters (const vector<MessageFilter>& filters) const
1073 TestLog& log = m_testCtx.getLog();
1074 const tcu::ScopedLogSection section (log, "", "Setting message filters");
1075 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1077 for (size_t filterNdx = 0; filterNdx < filters.size(); filterNdx++)
1079 const MessageFilter& filter = filters[filterNdx];
1081 if (filter.ids.empty())
1082 log << TestLog::Message << "Setting messages with"
1083 << " source " << glu::getDebugMessageSourceStr(filter.source)
1084 << ", type " << glu::getDebugMessageTypeStr(filter.type)
1085 << " and severity " << glu::getDebugMessageSeverityStr(filter.severity)
1086 << (filter.enabled ? " to enabled" : " to disabled")
1087 << TestLog::EndMessage;
1090 for (size_t ndx = 0; ndx < filter.ids.size(); ndx++)
1091 log << TestLog::Message << "Setting message (" << MessageID(filter.source, filter.type, filter.ids[ndx]) << ") to " << (filter.enabled ? "enabled" : "disabled") << TestLog::EndMessage;
1094 gl.debugMessageControl(filter.source, filter.type, filter.severity, GLsizei(filter.ids.size()), filter.ids.empty() ? DE_NULL : &filter.ids[0], filter.enabled);
1098 bool FilterCase::isEnabled (const vector<MessageFilter>& filters, const MessageData& message) const
1102 for (size_t filterNdx = 0; filterNdx < filters.size(); filterNdx++)
1104 const MessageFilter& filter = filters[filterNdx];
1106 if (filter.ids.empty())
1108 if (filter.source != GL_DONT_CARE && filter.source != message.id.source)
1111 if (filter.type != GL_DONT_CARE && filter.type != message.id.type)
1114 if (filter.severity != GL_DONT_CARE && filter.severity != message.severity)
1119 DE_ASSERT(filter.source != GL_DONT_CARE);
1120 DE_ASSERT(filter.type != GL_DONT_CARE);
1121 DE_ASSERT(filter.severity == GL_DONT_CARE);
1123 if (filter.source != message.id.source || filter.type != message.id.type)
1126 if (!de::contains(filter.ids.begin(), filter.ids.end(), message.id.id))
1130 retval = filter.enabled;
1142 MessageMeta (void) : refCount(0), resCount(0), severity(GL_NONE) {}
1145 void FilterCase::verify (const vector<MessageData>& refMessages, const vector<MessageData>& resMessages, const vector<MessageFilter>& filters)
1147 TestLog& log = m_testCtx.getLog();
1148 map<MessageID, MessageMeta> counts;
1150 log << TestLog::Section("verification", "Verifying");
1152 // Gather message counts & severities, report severity mismatches if found
1153 for (size_t refNdx = 0; refNdx < refMessages.size(); refNdx++)
1155 const MessageData& msg = refMessages[refNdx];
1156 MessageMeta& meta = counts[msg.id];
1158 if (meta.severity != GL_NONE && meta.severity != msg.severity)
1160 log << TestLog::Message << "A message has variable severity between instances: (" << msg.id << ") with severity "
1161 << glu::getDebugMessageSeverityStr(meta.severity) << " and " << glu::getDebugMessageSeverityStr(msg.severity) << TestLog::EndMessage;
1162 m_results.addResult(QP_TEST_RESULT_FAIL, "Message severity changed between instances of the same message");
1166 meta.severity = msg.severity;
1169 for (size_t resNdx = 0; resNdx < resMessages.size(); resNdx++)
1171 const MessageData& msg = resMessages[resNdx];
1172 MessageMeta& meta = counts[msg.id];
1174 if (meta.severity != GL_NONE && meta.severity != msg.severity)
1176 log << TestLog::Message << "A message has variable severity between instances: (" << msg.id << ") with severity "
1177 << glu::getDebugMessageSeverityStr(meta.severity) << " and " << glu::getDebugMessageSeverityStr(msg.severity) << TestLog::EndMessage;
1178 m_results.addResult(QP_TEST_RESULT_FAIL, "Message severity changed between instances of the same message");
1182 meta.severity = msg.severity;
1185 for (map<MessageID, MessageMeta>::const_iterator itr = counts.begin(); itr != counts.end(); itr++)
1187 const MessageID& id = itr->first;
1188 const GLenum severity = itr->second.severity;
1190 const int refCount = itr->second.refCount;
1191 const int resCount = itr->second.resCount;
1192 const bool enabled = isEnabled(filters, MessageData(id, severity, ""));
1194 VerificationResult result = verifyMessageCount(id, severity, refCount, resCount, enabled);
1196 log << TestLog::Message << result.logMessage << TestLog::EndMessage;
1198 if (result.result != QP_TEST_RESULT_PASS)
1199 m_results.addResult(result.result, result.resultMessage);
1202 log << TestLog::EndSection;
1205 // Filter case that uses debug groups
1206 class GroupFilterCase : public FilterCase
1209 GroupFilterCase (Context& ctx,
1212 const vector<TestFunctionWrapper>& errorFuncs);
1213 virtual ~GroupFilterCase (void) {}
1215 virtual IterateResult iterate (void);
1218 GroupFilterCase::GroupFilterCase (Context& ctx,
1221 const vector<TestFunctionWrapper>& errorFuncs)
1222 : FilterCase(ctx, name, desc, errorFuncs)
1226 template<typename T>
1227 vector<T> join(const vector<T>& a, const vector<T>&b)
1231 retval.reserve(a.size()+b.size());
1232 retval.insert(retval.end(), a.begin(), a.end());
1233 retval.insert(retval.end(), b.begin(), b.end());
1237 GroupFilterCase::IterateResult GroupFilterCase::iterate (void)
1239 TCU_CHECK_AND_THROW(NotSupportedError, isKHRDebugSupported(m_context), "GL_KHR_debug is not supported");
1241 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1242 tcu::TestLog& log = m_testCtx.getLog();
1244 gl.enable(GL_DEBUG_OUTPUT);
1245 gl.enable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
1246 gl.debugMessageCallback(callbackHandle, this);
1247 gl.debugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, DE_NULL, true);
1251 // Generate reference (all errors)
1252 const vector<MessageData> refMessages = genMessages(true, "Reference run");
1253 const deUint32 baseSeed = deStringHash(getName()) ^ m_testCtx.getCommandLine().getBaseSeed();
1254 const MessageFilter baseFilter (GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, vector<GLuint>(), true);
1255 const vector<MessageFilter> filter0 = genFilters(refMessages, vector<MessageFilter>(1, baseFilter), baseSeed, 4);
1256 vector<MessageData> resMessages0;
1258 applyFilters(filter0);
1260 resMessages0 = genMessages(false, "Filtered run, default debug group");
1262 // Initial verification
1263 verify(refMessages, resMessages0, filter0);
1266 // Generate reference (filters inherited from parent)
1267 const vector<MessageFilter> filter1base = genFilters(refMessages, vector<MessageFilter>(), baseSeed ^ 0xDEADBEEF, 4);
1268 const vector<MessageFilter> filter1full = join(filter0, filter1base);
1269 tcu::ScopedLogSection section1 (log, "", "Pushing Debug Group");
1270 vector<MessageData> resMessages1;
1272 gl.pushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 1, -1, "Test Group");
1273 applyFilters(filter1base);
1275 // First nested verification
1276 resMessages1 = genMessages(false, "Filtered run, pushed one debug group");
1277 verify(refMessages, resMessages1, filter1full);
1280 // Generate reference (filters iherited again)
1281 const vector<MessageFilter> filter2base = genFilters(refMessages, vector<MessageFilter>(), baseSeed ^ 0x43211234, 4);
1282 const vector<MessageFilter> filter2full = join(filter1full, filter2base);
1283 tcu::ScopedLogSection section2 (log, "", "Pushing Debug Group");
1284 vector<MessageData> resMessages2;
1286 gl.pushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 1, -1, "Nested Test Group");
1287 applyFilters(filter2base);
1289 // Second nested verification
1290 resMessages2 = genMessages(false, "Filtered run, pushed two debug groups");
1291 verify(refMessages, resMessages2, filter2full);
1296 // First restore verification
1297 resMessages1 = genMessages(false, "Filtered run, popped second debug group");
1298 verify(refMessages, resMessages1, filter1full);
1303 // restore verification
1304 resMessages0 = genMessages(false, "Filtered run, popped first debug group");
1305 verify(refMessages, resMessages0, filter0);
1307 if (!isDebugContext() && refMessages.empty())
1308 m_results.addResult(QP_TEST_RESULT_QUALITY_WARNING, "Verification accuracy is lacking without a debug context");
1311 gl.disable(GL_DEBUG_OUTPUT);
1312 m_results.setTestContextResult(m_testCtx);
1316 // Basic grouping functionality
1317 class GroupCase : public BaseCase
1320 GroupCase (Context& ctx,
1323 virtual ~GroupCase () {}
1325 virtual IterateResult iterate (void);
1328 virtual void callback (GLenum source, GLenum type, GLuint id, GLenum severity, const string& message);
1330 MessageData m_lastMessage;
1333 GroupCase::GroupCase (Context& ctx,
1336 : BaseCase(ctx, name, desc)
1340 GroupCase::IterateResult GroupCase::iterate (void)
1342 TCU_CHECK_AND_THROW(NotSupportedError, isKHRDebugSupported(m_context), "GL_KHR_debug is not supported");
1344 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1345 tcu::TestLog& log = m_testCtx.getLog();
1346 glu::CallLogWrapper wrapper (gl, log);
1348 gl.enable(GL_DEBUG_OUTPUT);
1349 gl.enable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
1350 gl.debugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, DE_NULL, false); // disable all
1351 gl.debugMessageControl(GL_DEBUG_SOURCE_API, GL_DEBUG_TYPE_ERROR, GL_DONT_CARE, 0, DE_NULL, true); // enable API errors
1352 gl.debugMessageControl(GL_DEBUG_SOURCE_APPLICATION, GL_DONT_CARE, GL_DONT_CARE, 0, DE_NULL, true); // enable application messages
1353 gl.debugMessageControl(GL_DEBUG_SOURCE_THIRD_PARTY, GL_DONT_CARE, GL_DONT_CARE, 0, DE_NULL, true); // enable third party messages
1354 gl.debugMessageCallback(callbackHandle, this);
1356 wrapper.enableLogging(true);
1357 wrapper.glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 1234, -1, "Pushed debug stack");
1358 verifyMessage(m_lastMessage, GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PUSH_GROUP, 1234, GL_DEBUG_SEVERITY_NOTIFICATION);
1359 wrapper.glPopDebugGroup();
1360 verifyMessage(m_lastMessage, GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_POP_GROUP, 1234, GL_DEBUG_SEVERITY_NOTIFICATION);
1362 wrapper.glPushDebugGroup(GL_DEBUG_SOURCE_THIRD_PARTY, 4231, -1, "Pushed debug stack");
1363 verifyMessage(m_lastMessage, GL_DEBUG_SOURCE_THIRD_PARTY, GL_DEBUG_TYPE_PUSH_GROUP, 4231, GL_DEBUG_SEVERITY_NOTIFICATION);
1364 wrapper.glPopDebugGroup();
1365 verifyMessage(m_lastMessage, GL_DEBUG_SOURCE_THIRD_PARTY, GL_DEBUG_TYPE_POP_GROUP, 4231, GL_DEBUG_SEVERITY_NOTIFICATION);
1367 gl.debugMessageCallback(DE_NULL, DE_NULL);
1368 gl.disable(GL_DEBUG_OUTPUT);
1370 m_results.setTestContextResult(m_testCtx);
1375 void GroupCase::callback (GLenum source, GLenum type, GLuint id, GLenum severity, const string& message)
1377 m_lastMessage = MessageData(MessageID(source, type, id), severity, message);
1380 // Asynchronous debug output
1381 class AsyncCase : public BaseCase
1384 AsyncCase (Context& ctx,
1387 const vector<TestFunctionWrapper>& errorFuncs,
1389 virtual ~AsyncCase (void) {}
1391 virtual IterateResult iterate (void);
1393 virtual void expectMessage (glw::GLenum source, glw::GLenum type);
1401 MessageCount(void) : received(0), expected(0) {}
1403 typedef map<MessageID, MessageCount> MessageCounter;
1414 virtual void callback (glw::GLenum source, glw::GLenum type, glw::GLuint id, glw::GLenum severity, const std::string& message);
1415 VerifyState verify (bool uselog);
1416 void fetchLogMessages (void);
1418 const vector<TestFunctionWrapper> m_errorFuncs;
1419 const bool m_useCallbacks;
1421 MessageCounter m_counts;
1426 AsyncCase::AsyncCase (Context& ctx,
1429 const vector<TestFunctionWrapper>& errorFuncs,
1431 : BaseCase (ctx, name, desc)
1432 , m_errorFuncs (errorFuncs)
1433 , m_useCallbacks (useCallbacks)
1437 AsyncCase::IterateResult AsyncCase::iterate (void)
1439 TCU_CHECK_AND_THROW(NotSupportedError, isKHRDebugSupported(m_context), "GL_KHR_debug is not supported");
1441 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1442 tcu::TestLog& log = m_testCtx.getLog();
1443 DebugMessageTestContext context = DebugMessageTestContext(*this, m_context.getRenderContext(), m_context.getContextInfo(), log, m_results, true);
1444 const int maxWait = 10000; // ms
1445 const int warnWait = 100;
1447 gl.enable(GL_DEBUG_OUTPUT);
1448 gl.enable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
1449 gl.debugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, DE_NULL, false);
1451 // Some messages could be dependent on the value of DEBUG_OUTPUT_SYNCHRONOUS so only use API errors which should be generated in all cases
1452 gl.debugMessageControl(GL_DEBUG_SOURCE_API, GL_DEBUG_TYPE_ERROR, GL_DONT_CARE, 0, DE_NULL, true);
1454 if (m_useCallbacks) // will use log otherwise
1455 gl.debugMessageCallback(callbackHandle, this);
1457 gl.debugMessageCallback(DE_NULL, DE_NULL);
1459 // Reference run (synchoronous)
1461 tcu::ScopedLogSection section(log, "reference run", "Reference run (synchronous)");
1463 for (int ndx = 0; ndx < int(m_errorFuncs.size()); ndx++)
1464 m_errorFuncs[ndx].call(context);
1467 if (m_counts.empty())
1469 if (!isDebugContext())
1470 m_results.addResult(QP_TEST_RESULT_QUALITY_WARNING, "Need debug context to guarantee implementation behaviour (see command line options)");
1472 log << TestLog::Message << "Reference run produced no messages, nothing to verify" << TestLog::EndMessage;
1474 gl.debugMessageCallback(DE_NULL, DE_NULL);
1475 gl.disable(GL_DEBUG_OUTPUT);
1477 m_results.setTestContextResult(m_testCtx);
1481 for (MessageCounter::iterator itr = m_counts.begin(); itr != m_counts.end(); itr++)
1483 itr->second.expected = itr->second.received;
1484 itr->second.received = 0;
1487 gl.disable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
1489 // Result run (async)
1490 for (int ndx = 0; ndx < int(m_errorFuncs.size()); ndx++)
1491 m_errorFuncs[ndx].call(context);
1493 // Repatedly try verification, new results may be added to m_receivedMessages at any time
1495 tcu::ScopedLogSection section (log, "result run", "Result run (asynchronous)");
1496 VerifyState lastTimelyState = VERIFY_FAIL;
1498 for (int waited = 0;;)
1500 const VerifyState pass = verify(false);
1501 const int wait = de::max(50, waited>>2);
1503 // Pass (possibly due to time limit)
1504 if (pass == VERIFY_PASS || (pass == VERIFY_MINIMUM && waited >= maxWait))
1506 verify(true); // log
1508 // State changed late
1509 if (waited >= warnWait && lastTimelyState != pass)
1510 m_results.addResult(QP_TEST_RESULT_QUALITY_WARNING, "Async messages were returned to application somewhat slowly");
1512 log << TestLog::Message << "Passed after ~" << waited << "ms of waiting" << TestLog::EndMessage;
1516 else if (waited >= maxWait)
1518 verify(true); // log
1520 log << TestLog::Message << "Waited for ~" << waited << "ms without getting all expected messages" << TestLog::EndMessage;
1521 m_results.addResult(QP_TEST_RESULT_FAIL, "Async messages were not returned to application within a reasonable timeframe");
1525 if (waited < warnWait)
1526 lastTimelyState = pass;
1531 if (!m_useCallbacks)
1536 gl.debugMessageCallback(DE_NULL, DE_NULL);
1538 gl.disable(GL_DEBUG_OUTPUT);
1539 m_results.setTestContextResult(m_testCtx);
1544 void AsyncCase::expectMessage (GLenum source, GLenum type)
1546 // Good time to clean up the queue as this should be called after most messages are generated
1547 if (!m_useCallbacks)
1554 void AsyncCase::callback (GLenum source, GLenum type, GLuint id, GLenum severity, const string& message)
1556 DE_ASSERT(m_useCallbacks);
1560 de::ScopedLock lock(m_mutex);
1562 m_counts[MessageID(source, type, id)].received++;
1565 // 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
1566 void AsyncCase::fetchLogMessages (void)
1568 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1571 gl.getIntegerv(GL_DEBUG_LOGGED_MESSAGES, &numMsg);
1573 for(int msgNdx = 0; msgNdx < numMsg; msgNdx++)
1578 gl.getIntegerv(GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH, &msgLen);
1580 TCU_CHECK_MSG(msgLen >= 0, "Negative message length");
1581 TCU_CHECK_MSG(msgLen < 100000, "Excessively long message");
1583 msg.message.resize(msgLen);
1584 gl.getDebugMessageLog(1, msgLen, &msg.id.source, &msg.id.type, &msg.id.id, &msg.severity, &msgLen, &msg.message[0]);
1587 const de::ScopedLock lock(m_mutex); // Don't block during API call
1589 m_counts[MessageID(msg.id)].received++;
1594 AsyncCase::VerifyState AsyncCase::verify (bool uselog)
1598 VerifyState retval = VERIFY_PASS;
1599 TestLog& log = m_testCtx.getLog();
1601 const de::ScopedLock lock(m_mutex);
1603 for (map<MessageID, MessageCount>::const_iterator itr = m_counts.begin(); itr != m_counts.end(); itr++)
1605 const MessageID& id = itr->first;
1607 const int refCount = itr->second.expected;
1608 const int resCount = itr->second.received;
1609 const bool enabled = true;
1611 VerificationResult result = verifyMessageCount(id, GL_DONT_CARE, refCount, resCount, enabled);
1614 log << TestLog::Message << result.logMessage << TestLog::EndMessage;
1616 if (result.result == QP_TEST_RESULT_FAIL)
1617 retval = VERIFY_FAIL;
1618 else if (result.result != QP_TEST_RESULT_PASS && retval == VERIFY_PASS)
1619 retval = VERIFY_MINIMUM;
1625 // Tests debug labels
1626 class LabelCase : public TestCase
1629 LabelCase (Context& ctx,
1633 virtual ~LabelCase (void) {}
1635 virtual IterateResult iterate (void);
1638 GLenum m_identifier;
1641 LabelCase::LabelCase (Context& ctx,
1645 : TestCase (ctx, name, desc)
1646 , m_identifier (identifier)
1650 LabelCase::IterateResult LabelCase::iterate (void)
1652 TCU_CHECK_AND_THROW(NotSupportedError, isKHRDebugSupported(m_context), "GL_KHR_debug is not supported");
1654 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1655 const char* const msg = "This is a debug label";
1660 switch(m_identifier)
1663 gl.genBuffers(1, &object);
1664 gl.bindBuffer(GL_ARRAY_BUFFER, object);
1665 gl.bindBuffer(GL_ARRAY_BUFFER, 0);
1669 object = gl.createShader(GL_FRAGMENT_SHADER);
1673 object = gl.createProgram();
1677 gl.genQueries(1, &object);
1678 gl.beginQuery(GL_ANY_SAMPLES_PASSED, object); // Create
1679 gl.endQuery(GL_ANY_SAMPLES_PASSED); // Cleanup
1682 case GL_PROGRAM_PIPELINE:
1683 gl.genProgramPipelines(1, &object);
1684 gl.bindProgramPipeline(object); // Create
1685 gl.bindProgramPipeline(0); // Cleanup
1688 case GL_TRANSFORM_FEEDBACK:
1689 gl.genTransformFeedbacks(1, &object);
1690 gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, object);
1691 gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);
1695 gl.genSamplers(1, &object);
1696 gl.bindSampler(0, object);
1697 gl.bindSampler(0, 0);
1701 gl.genTextures(1, &object);
1702 gl.bindTexture(GL_TEXTURE_2D, object);
1703 gl.bindTexture(GL_TEXTURE_2D, 0);
1706 case GL_RENDERBUFFER:
1707 gl.genRenderbuffers(1, &object);
1708 gl.bindRenderbuffer(GL_RENDERBUFFER, object);
1709 gl.bindRenderbuffer(GL_RENDERBUFFER, 0);
1712 case GL_FRAMEBUFFER:
1713 gl.genFramebuffers(1, &object);
1714 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, object);
1715 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_context.getRenderContext().getDefaultFramebuffer());
1719 DE_FATAL("Invalid identifier");
1722 gl.objectLabel(m_identifier, object, -1, msg);
1724 deMemset(buffer, 'X', sizeof(buffer));
1725 gl.getObjectLabel(m_identifier, object, sizeof(buffer), &outlen, buffer);
1728 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Failed to query debug label from object");
1729 else if (deStringEqual(msg, buffer))
1731 m_testCtx.getLog() << TestLog::Message << "Query returned string: \"" << buffer << "\"" << TestLog::EndMessage;
1732 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1736 buffer[63] = '\0'; // make sure buffer is null terminated before printing
1737 m_testCtx.getLog() << TestLog::Message << "Query returned wrong string: expected \"" << msg << "\" but got \"" << buffer << "\"" << TestLog::EndMessage;
1738 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Query returned wrong label");
1741 switch(m_identifier)
1743 case GL_BUFFER: gl.deleteBuffers(1, &object); break;
1744 case GL_SHADER: gl.deleteShader(object); break;
1745 case GL_PROGRAM: gl.deleteProgram(object); break;
1746 case GL_QUERY: gl.deleteQueries(1, &object); break;
1747 case GL_PROGRAM_PIPELINE: gl.deleteProgramPipelines(1, &object); break;
1748 case GL_TRANSFORM_FEEDBACK: gl.deleteTransformFeedbacks(1, &object); break;
1749 case GL_SAMPLER: gl.deleteSamplers(1, &object); break;
1750 case GL_TEXTURE: gl.deleteTextures(1, &object); break;
1751 case GL_RENDERBUFFER: gl.deleteRenderbuffers(1, &object); break;
1752 case GL_FRAMEBUFFER: gl.deleteFramebuffers(1, &object); break;
1755 DE_FATAL("Invalid identifier");
1762 DebugMessageTestContext::DebugMessageTestContext (BaseCase& host,
1763 glu::RenderContext& renderCtx,
1764 const glu::ContextInfo& ctxInfo,
1766 tcu::ResultCollector& results,
1768 : NegativeTestContext (host, renderCtx, ctxInfo, log, results, enableLog)
1769 , m_debugHost (host)
1773 DebugMessageTestContext::~DebugMessageTestContext (void)
1777 void DebugMessageTestContext::expectMessage (GLenum source, GLenum type)
1779 m_debugHost.expectMessage(source, type);
1782 class SyncLabelCase : public TestCase
1785 SyncLabelCase (Context& ctx, const char* name, const char* desc);
1786 virtual IterateResult iterate (void);
1789 SyncLabelCase::SyncLabelCase (Context& ctx, const char* name, const char* desc)
1790 : TestCase(ctx, name, desc)
1794 SyncLabelCase::IterateResult SyncLabelCase::iterate (void)
1796 TCU_CHECK_AND_THROW(NotSupportedError, isKHRDebugSupported(m_context), "GL_KHR_debug is not supported");
1798 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1799 const char* const msg = "This is a debug label";
1803 glw::GLsync sync = gl.fenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
1804 GLU_EXPECT_NO_ERROR(gl.getError(), "fenceSync");
1806 gl.objectPtrLabel(sync, -1, msg);
1808 deMemset(buffer, 'X', sizeof(buffer));
1809 gl.getObjectPtrLabel(sync, sizeof(buffer), &outlen, buffer);
1812 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Failed to query debug label from object");
1813 else if (deStringEqual(msg, buffer))
1815 m_testCtx.getLog() << TestLog::Message << "Query returned string: \"" << buffer << "\"" << TestLog::EndMessage;
1816 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1820 buffer[63] = '\0'; // make sure buffer is null terminated before printing
1821 m_testCtx.getLog() << TestLog::Message << "Query returned wrong string: expected \"" << msg << "\" but got \"" << buffer << "\"" << TestLog::EndMessage;
1822 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Query returned wrong label");
1825 gl.deleteSync(sync);
1830 class InitialLabelCase : public TestCase
1833 InitialLabelCase (Context& ctx, const char* name, const char* desc);
1834 virtual IterateResult iterate (void);
1837 InitialLabelCase::InitialLabelCase (Context& ctx, const char* name, const char* desc)
1838 : TestCase(ctx, name, desc)
1842 InitialLabelCase::IterateResult InitialLabelCase::iterate (void)
1844 TCU_CHECK_AND_THROW(NotSupportedError, isKHRDebugSupported(m_context), "GL_KHR_debug is not supported");
1846 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1847 tcu::ResultCollector result (m_testCtx.getLog(), " // ERROR: ");
1853 sync = gl.fenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
1854 GLS_COLLECT_GL_ERROR(result, gl.getError(), "fenceSync");
1856 shader = gl.createShader(GL_FRAGMENT_SHADER);
1857 GLS_COLLECT_GL_ERROR(result, gl.getError(), "createShader");
1860 const tcu::ScopedLogSection section(m_testCtx.getLog(), "Shader", "Shader object");
1861 m_testCtx.getLog() << TestLog::Message << "Querying initial value" << TestLog::EndMessage;
1865 gl.getObjectLabel(GL_SHADER, shader, sizeof(buffer), &outlen, buffer);
1866 GLS_COLLECT_GL_ERROR(result, gl.getError(), "getObjectLabel");
1869 result.fail("'length' was not zero, got " + de::toString(outlen));
1870 else if (buffer[0] != '\0')
1871 result.fail("label was not null terminated");
1873 m_testCtx.getLog() << TestLog::Message << "Got 0-sized null-terminated string." << TestLog::EndMessage;
1877 const tcu::ScopedLogSection section(m_testCtx.getLog(), "Sync", "Sync object");
1878 m_testCtx.getLog() << TestLog::Message << "Querying initial value" << TestLog::EndMessage;
1882 gl.getObjectPtrLabel(sync, sizeof(buffer), &outlen, buffer);
1883 GLS_COLLECT_GL_ERROR(result, gl.getError(), "getObjectPtrLabel");
1886 result.fail("'length' was not zero, got " + de::toString(outlen));
1887 else if (buffer[0] != '\0')
1888 result.fail("label was not null terminated");
1890 m_testCtx.getLog() << TestLog::Message << "Got 0-sized null-terminated string." << TestLog::EndMessage;
1893 gl.deleteShader(shader);
1894 gl.deleteSync(sync);
1896 result.setTestContextResult(m_testCtx);
1900 class ClearLabelCase : public TestCase
1903 ClearLabelCase (Context& ctx, const char* name, const char* desc);
1904 virtual IterateResult iterate (void);
1907 ClearLabelCase::ClearLabelCase (Context& ctx, const char* name, const char* desc)
1908 : TestCase(ctx, name, desc)
1912 ClearLabelCase::IterateResult ClearLabelCase::iterate (void)
1914 TCU_CHECK_AND_THROW(NotSupportedError, isKHRDebugSupported(m_context), "GL_KHR_debug is not supported");
1918 const char* description;
1920 } s_clearMethods[] =
1922 { " with NULL label and 0 length", 0 },
1923 { " with NULL label and 1 length", 1 },
1924 { " with NULL label and negative length", -1 },
1927 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1928 tcu::ResultCollector result (m_testCtx.getLog(), " // ERROR: ");
1929 const char* const msg = "This is a debug label";
1935 sync = gl.fenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
1936 GLS_COLLECT_GL_ERROR(result, gl.getError(), "fenceSync");
1938 shader = gl.createShader(GL_FRAGMENT_SHADER);
1939 GLS_COLLECT_GL_ERROR(result, gl.getError(), "createShader");
1942 const tcu::ScopedLogSection section(m_testCtx.getLog(), "Shader", "Shader object");
1944 for (int methodNdx = 0; methodNdx < DE_LENGTH_OF_ARRAY(s_clearMethods); ++methodNdx)
1946 m_testCtx.getLog() << TestLog::Message << "Setting label to string: \"" << msg << "\"" << TestLog::EndMessage;
1947 gl.objectLabel(GL_SHADER, shader, -2, msg);
1948 GLS_COLLECT_GL_ERROR(result, gl.getError(), "objectLabel");
1950 m_testCtx.getLog() << TestLog::Message << "Clearing label " << s_clearMethods[methodNdx].description << TestLog::EndMessage;
1951 gl.objectLabel(GL_SHADER, shader, s_clearMethods[methodNdx].length, DE_NULL);
1952 GLS_COLLECT_GL_ERROR(result, gl.getError(), "objectLabel");
1954 m_testCtx.getLog() << TestLog::Message << "Querying label" << TestLog::EndMessage;
1957 gl.getObjectLabel(GL_SHADER, shader, sizeof(buffer), &outlen, buffer);
1958 GLS_COLLECT_GL_ERROR(result, gl.getError(), "getObjectLabel");
1961 result.fail("'length' was not zero, got " + de::toString(outlen));
1962 else if (buffer[0] != '\0')
1963 result.fail("label was not null terminated");
1965 m_testCtx.getLog() << TestLog::Message << "Got 0-sized null-terminated string." << TestLog::EndMessage;
1970 const tcu::ScopedLogSection section(m_testCtx.getLog(), "Sync", "Sync object");
1972 for (int methodNdx = 0; methodNdx < DE_LENGTH_OF_ARRAY(s_clearMethods); ++methodNdx)
1974 m_testCtx.getLog() << TestLog::Message << "Setting label to string: \"" << msg << "\"" << TestLog::EndMessage;
1975 gl.objectPtrLabel(sync, -2, msg);
1976 GLS_COLLECT_GL_ERROR(result, gl.getError(), "objectPtrLabel");
1978 m_testCtx.getLog() << TestLog::Message << "Clearing label " << s_clearMethods[methodNdx].description << TestLog::EndMessage;
1979 gl.objectPtrLabel(sync, s_clearMethods[methodNdx].length, DE_NULL);
1980 GLS_COLLECT_GL_ERROR(result, gl.getError(), "objectPtrLabel");
1982 m_testCtx.getLog() << TestLog::Message << "Querying label" << TestLog::EndMessage;
1985 gl.getObjectPtrLabel(sync, sizeof(buffer), &outlen, buffer);
1986 GLS_COLLECT_GL_ERROR(result, gl.getError(), "getObjectPtrLabel");
1989 result.fail("'length' was not zero, got " + de::toString(outlen));
1990 else if (buffer[0] != '\0')
1991 result.fail("label was not null terminated");
1993 m_testCtx.getLog() << TestLog::Message << "Got 0-sized null-terminated string." << TestLog::EndMessage;
1997 gl.deleteShader(shader);
1998 gl.deleteSync(sync);
2000 result.setTestContextResult(m_testCtx);
2004 class SpecifyWithLengthCase : public TestCase
2007 SpecifyWithLengthCase (Context& ctx, const char* name, const char* desc);
2008 virtual IterateResult iterate (void);
2011 SpecifyWithLengthCase::SpecifyWithLengthCase (Context& ctx, const char* name, const char* desc)
2012 : TestCase(ctx, name, desc)
2016 SpecifyWithLengthCase::IterateResult SpecifyWithLengthCase::iterate (void)
2018 TCU_CHECK_AND_THROW(NotSupportedError, isKHRDebugSupported(m_context), "GL_KHR_debug is not supported");
2020 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2021 tcu::ResultCollector result (m_testCtx.getLog(), " // ERROR: ");
2022 const char* const msg = "This is a debug label";
2023 const char* const clipMsg = "This is a de";
2029 sync = gl.fenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
2030 GLS_COLLECT_GL_ERROR(result, gl.getError(), "fenceSync");
2032 shader = gl.createShader(GL_FRAGMENT_SHADER);
2033 GLS_COLLECT_GL_ERROR(result, gl.getError(), "createShader");
2036 const tcu::ScopedLogSection section(m_testCtx.getLog(), "Shader", "Shader object");
2038 m_testCtx.getLog() << TestLog::Message << "Setting label to string: \"" << msg << "\" with length 12" << TestLog::EndMessage;
2039 gl.objectLabel(GL_SHADER, shader, 12, msg);
2040 GLS_COLLECT_GL_ERROR(result, gl.getError(), "objectLabel");
2042 m_testCtx.getLog() << TestLog::Message << "Querying label" << TestLog::EndMessage;
2043 deMemset(buffer, 'X', sizeof(buffer));
2044 gl.getObjectLabel(GL_SHADER, shader, sizeof(buffer), &outlen, buffer);
2045 GLS_COLLECT_GL_ERROR(result, gl.getError(), "getObjectLabel");
2048 result.fail("'length' was not 12, got " + de::toString(outlen));
2049 else if (deStringEqual(clipMsg, buffer))
2051 m_testCtx.getLog() << TestLog::Message << "Query returned string: \"" << buffer << "\"" << TestLog::EndMessage;
2055 buffer[63] = '\0'; // make sure buffer is null terminated before printing
2056 m_testCtx.getLog() << TestLog::Message << "Query returned wrong string: expected \"" << clipMsg << "\" but got \"" << buffer << "\"" << TestLog::EndMessage;
2057 result.fail("Query returned wrong label");
2062 const tcu::ScopedLogSection section(m_testCtx.getLog(), "Sync", "Sync object");
2064 m_testCtx.getLog() << TestLog::Message << "Setting label to string: \"" << msg << "\" with length 12" << TestLog::EndMessage;
2065 gl.objectPtrLabel(sync, 12, msg);
2066 GLS_COLLECT_GL_ERROR(result, gl.getError(), "objectPtrLabel");
2068 m_testCtx.getLog() << TestLog::Message << "Querying label" << TestLog::EndMessage;
2069 deMemset(buffer, 'X', sizeof(buffer));
2070 gl.getObjectPtrLabel(sync, sizeof(buffer), &outlen, buffer);
2071 GLS_COLLECT_GL_ERROR(result, gl.getError(), "getObjectPtrLabel");
2074 result.fail("'length' was not 12, got " + de::toString(outlen));
2075 else if (deStringEqual(clipMsg, buffer))
2077 m_testCtx.getLog() << TestLog::Message << "Query returned string: \"" << buffer << "\"" << TestLog::EndMessage;
2081 buffer[63] = '\0'; // make sure buffer is null terminated before printing
2082 m_testCtx.getLog() << TestLog::Message << "Query returned wrong string: expected \"" << clipMsg << "\" but got \"" << buffer << "\"" << TestLog::EndMessage;
2083 result.fail("Query returned wrong label");
2088 const tcu::ScopedLogSection section(m_testCtx.getLog(), "ZeroSized", "ZeroSized");
2090 m_testCtx.getLog() << TestLog::Message << "Setting label to string: \"" << msg << "\" with length 0" << TestLog::EndMessage;
2091 gl.objectLabel(GL_SHADER, shader, 0, msg);
2092 GLS_COLLECT_GL_ERROR(result, gl.getError(), "objectLabel");
2094 m_testCtx.getLog() << TestLog::Message << "Querying label" << TestLog::EndMessage;
2095 deMemset(buffer, 'X', sizeof(buffer));
2096 gl.getObjectLabel(GL_SHADER, shader, sizeof(buffer), &outlen, buffer);
2097 GLS_COLLECT_GL_ERROR(result, gl.getError(), "getObjectLabel");
2100 result.fail("'length' was not zero, got " + de::toString(outlen));
2101 else if (buffer[0] != '\0')
2102 result.fail("label was not null terminated");
2104 m_testCtx.getLog() << TestLog::Message << "Got 0-sized null-terminated string." << TestLog::EndMessage;
2107 gl.deleteShader(shader);
2108 gl.deleteSync(sync);
2110 result.setTestContextResult(m_testCtx);
2114 class BufferLimitedLabelCase : public TestCase
2117 BufferLimitedLabelCase (Context& ctx, const char* name, const char* desc);
2118 virtual IterateResult iterate (void);
2121 BufferLimitedLabelCase::BufferLimitedLabelCase (Context& ctx, const char* name, const char* desc)
2122 : TestCase(ctx, name, desc)
2126 BufferLimitedLabelCase::IterateResult BufferLimitedLabelCase::iterate (void)
2128 TCU_CHECK_AND_THROW(NotSupportedError, isKHRDebugSupported(m_context), "GL_KHR_debug is not supported");
2130 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2131 tcu::ResultCollector result (m_testCtx.getLog(), " // ERROR: ");
2132 const char* const msg = "This is a debug label";
2138 sync = gl.fenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
2139 GLS_COLLECT_GL_ERROR(result, gl.getError(), "fenceSync");
2141 shader = gl.createShader(GL_FRAGMENT_SHADER);
2142 GLS_COLLECT_GL_ERROR(result, gl.getError(), "createShader");
2145 const tcu::ScopedLogSection superSection(m_testCtx.getLog(), "Shader", "Shader object");
2147 m_testCtx.getLog() << TestLog::Message << "Setting label to string: \"" << msg << "\"" << TestLog::EndMessage;
2148 gl.objectLabel(GL_SHADER, shader, -1, msg);
2149 GLS_COLLECT_GL_ERROR(result, gl.getError(), "objectLabel");
2152 const tcu::ScopedLogSection section(m_testCtx.getLog(), "QueryAll", "Query All");
2154 m_testCtx.getLog() << TestLog::Message << "Querying whole label, buffer size = 22" << TestLog::EndMessage;
2155 deMemset(buffer, 'X', sizeof(buffer));
2156 gl.getObjectLabel(GL_SHADER, shader, 22, &outlen, buffer);
2157 GLS_COLLECT_GL_ERROR(result, gl.getError(), "getObjectLabel");
2160 result.fail("'length' was not 21, got " + de::toString(outlen));
2161 else if (buffer[outlen] != '\0')
2162 result.fail("Buffer was not null-terminated");
2163 else if (buffer[outlen+1] != 'X')
2164 result.fail("Query wrote over buffer bound");
2165 else if (!deStringEqual(msg, buffer))
2167 buffer[63] = '\0'; // make sure buffer is null terminated before printing
2168 m_testCtx.getLog() << TestLog::Message << "Query returned string: \"" << buffer << "\"" << TestLog::EndMessage;
2169 result.fail("Query returned wrong label");
2172 m_testCtx.getLog() << TestLog::Message << "Query returned string: \"" << buffer << "\"" << TestLog::EndMessage;
2175 const tcu::ScopedLogSection section(m_testCtx.getLog(), "QueryAllNoSize", "Query all without size");
2177 m_testCtx.getLog() << TestLog::Message << "Querying whole label, buffer size = 22" << TestLog::EndMessage;
2178 deMemset(buffer, 'X', sizeof(buffer));
2179 gl.getObjectLabel(GL_SHADER, shader, 22, DE_NULL, buffer);
2180 GLS_COLLECT_GL_ERROR(result, gl.getError(), "getObjectLabel");
2182 buffer[63] = '\0'; // make sure buffer is null terminated before strlen
2184 if (strlen(buffer) != 21)
2185 result.fail("Buffer length was not 21");
2186 else if (buffer[21] != '\0')
2187 result.fail("Buffer was not null-terminated");
2188 else if (buffer[22] != 'X')
2189 result.fail("Query wrote over buffer bound");
2190 else if (!deStringEqual(msg, buffer))
2192 m_testCtx.getLog() << TestLog::Message << "Query returned string: \"" << buffer << "\"" << TestLog::EndMessage;
2193 result.fail("Query returned wrong label");
2196 m_testCtx.getLog() << TestLog::Message << "Query returned string: \"" << buffer << "\"" << TestLog::EndMessage;
2199 const tcu::ScopedLogSection section(m_testCtx.getLog(), "QueryLess", "Query substring");
2201 m_testCtx.getLog() << TestLog::Message << "Querying whole label, buffer size = 2" << TestLog::EndMessage;
2202 deMemset(buffer, 'X', sizeof(buffer));
2203 gl.getObjectLabel(GL_SHADER, shader, 2, &outlen, buffer);
2204 GLS_COLLECT_GL_ERROR(result, gl.getError(), "getObjectLabel");
2207 result.fail("'length' was not 1, got " + de::toString(outlen));
2208 else if (buffer[outlen] != '\0')
2209 result.fail("Buffer was not null-terminated");
2210 else if (buffer[outlen+1] != 'X')
2211 result.fail("Query wrote over buffer bound");
2212 else if (!deStringBeginsWith(msg, buffer))
2214 buffer[63] = '\0'; // make sure buffer is null terminated before printing
2215 m_testCtx.getLog() << TestLog::Message << "Query returned string: \"" << buffer << "\"" << TestLog::EndMessage;
2216 result.fail("Query returned wrong label");
2219 m_testCtx.getLog() << TestLog::Message << "Query returned string: \"" << buffer << "\"" << TestLog::EndMessage;
2222 const tcu::ScopedLogSection section(m_testCtx.getLog(), "QueryNone", "Query one character");
2224 m_testCtx.getLog() << TestLog::Message << "Querying whole label, buffer size = 1" << TestLog::EndMessage;
2225 deMemset(buffer, 'X', sizeof(buffer));
2226 gl.getObjectLabel(GL_SHADER, shader, 1, &outlen, buffer);
2227 GLS_COLLECT_GL_ERROR(result, gl.getError(), "getObjectLabel");
2230 result.fail("'length' was not 0, got " + de::toString(outlen));
2231 else if (buffer[outlen] != '\0')
2232 result.fail("Buffer was not null-terminated");
2233 else if (buffer[outlen+1] != 'X')
2234 result.fail("Query wrote over buffer bound");
2236 m_testCtx.getLog() << TestLog::Message << "Query returned zero-sized null-terminated string" << TestLog::EndMessage;
2241 const tcu::ScopedLogSection superSection(m_testCtx.getLog(), "Sync", "Sync object");
2243 m_testCtx.getLog() << TestLog::Message << "Setting label to string: \"" << msg << "\"" << TestLog::EndMessage;
2244 gl.objectPtrLabel(sync, -1, msg);
2245 GLS_COLLECT_GL_ERROR(result, gl.getError(), "objectPtrLabel");
2248 const tcu::ScopedLogSection section(m_testCtx.getLog(), "QueryAll", "Query All");
2250 m_testCtx.getLog() << TestLog::Message << "Querying whole label, buffer size = 22" << TestLog::EndMessage;
2251 deMemset(buffer, 'X', sizeof(buffer));
2252 gl.getObjectPtrLabel(sync, 22, &outlen, buffer);
2253 GLS_COLLECT_GL_ERROR(result, gl.getError(), "getObjectPtrLabel");
2256 result.fail("'length' was not 21, got " + de::toString(outlen));
2257 else if (buffer[outlen] != '\0')
2258 result.fail("Buffer was not null-terminated");
2259 else if (buffer[outlen+1] != 'X')
2260 result.fail("Query wrote over buffer bound");
2261 else if (!deStringEqual(msg, buffer))
2263 buffer[63] = '\0'; // make sure buffer is null terminated before printing
2264 m_testCtx.getLog() << TestLog::Message << "Query returned string: \"" << buffer << "\"" << TestLog::EndMessage;
2265 result.fail("Query returned wrong label");
2268 m_testCtx.getLog() << TestLog::Message << "Query returned string: \"" << buffer << "\"" << TestLog::EndMessage;
2271 const tcu::ScopedLogSection section(m_testCtx.getLog(), "QueryAllNoSize", "Query all without size");
2273 m_testCtx.getLog() << TestLog::Message << "Querying whole label, buffer size = 22" << TestLog::EndMessage;
2274 deMemset(buffer, 'X', sizeof(buffer));
2275 gl.getObjectPtrLabel(sync, 22, DE_NULL, buffer);
2276 GLS_COLLECT_GL_ERROR(result, gl.getError(), "getObjectPtrLabel");
2278 buffer[63] = '\0'; // make sure buffer is null terminated before strlen
2280 if (strlen(buffer) != 21)
2281 result.fail("Buffer length was not 21");
2282 else if (buffer[21] != '\0')
2283 result.fail("Buffer was not null-terminated");
2284 else if (buffer[22] != 'X')
2285 result.fail("Query wrote over buffer bound");
2286 else if (!deStringEqual(msg, buffer))
2288 m_testCtx.getLog() << TestLog::Message << "Query returned string: \"" << buffer << "\"" << TestLog::EndMessage;
2289 result.fail("Query returned wrong label");
2292 m_testCtx.getLog() << TestLog::Message << "Query returned string: \"" << buffer << "\"" << TestLog::EndMessage;
2295 const tcu::ScopedLogSection section(m_testCtx.getLog(), "QueryLess", "Query substring");
2297 m_testCtx.getLog() << TestLog::Message << "Querying whole label, buffer size = 2" << TestLog::EndMessage;
2298 deMemset(buffer, 'X', sizeof(buffer));
2299 gl.getObjectPtrLabel(sync, 2, &outlen, buffer);
2300 GLS_COLLECT_GL_ERROR(result, gl.getError(), "getObjectPtrLabel");
2303 result.fail("'length' was not 1, got " + de::toString(outlen));
2304 else if (buffer[outlen] != '\0')
2305 result.fail("Buffer was not null-terminated");
2306 else if (buffer[outlen+1] != 'X')
2307 result.fail("Query wrote over buffer bound");
2308 else if (!deStringBeginsWith(msg, buffer))
2310 buffer[63] = '\0'; // make sure buffer is null terminated before printing
2311 m_testCtx.getLog() << TestLog::Message << "Query returned string: \"" << buffer << "\"" << TestLog::EndMessage;
2312 result.fail("Query returned wrong label");
2315 m_testCtx.getLog() << TestLog::Message << "Query returned string: \"" << buffer << "\"" << TestLog::EndMessage;
2318 const tcu::ScopedLogSection section(m_testCtx.getLog(), "QueryNone", "Query one character");
2320 m_testCtx.getLog() << TestLog::Message << "Querying whole label, buffer size = 1" << TestLog::EndMessage;
2321 deMemset(buffer, 'X', sizeof(buffer));
2322 gl.getObjectPtrLabel(sync, 1, &outlen, buffer);
2323 GLS_COLLECT_GL_ERROR(result, gl.getError(), "getObjectPtrLabel");
2326 result.fail("'length' was not 0, got " + de::toString(outlen));
2327 else if (buffer[outlen] != '\0')
2328 result.fail("Buffer was not null-terminated");
2329 else if (buffer[outlen+1] != 'X')
2330 result.fail("Query wrote over buffer bound");
2332 m_testCtx.getLog() << TestLog::Message << "Query returned zero-sized null-terminated string" << TestLog::EndMessage;
2336 gl.deleteShader(shader);
2337 gl.deleteSync(sync);
2339 result.setTestContextResult(m_testCtx);
2343 class LabelMaxSizeCase : public TestCase
2346 LabelMaxSizeCase (Context& ctx, const char* name, const char* desc);
2347 virtual IterateResult iterate (void);
2350 LabelMaxSizeCase::LabelMaxSizeCase (Context& ctx, const char* name, const char* desc)
2351 : TestCase(ctx, name, desc)
2355 LabelMaxSizeCase::IterateResult LabelMaxSizeCase::iterate (void)
2357 TCU_CHECK_AND_THROW(NotSupportedError, isKHRDebugSupported(m_context), "GL_KHR_debug is not supported");
2359 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2360 tcu::ResultCollector result (m_testCtx.getLog(), " // ERROR: ");
2361 int maxLabelLen = -1;
2366 gl.getIntegerv(GL_MAX_LABEL_LENGTH, &maxLabelLen);
2367 GLS_COLLECT_GL_ERROR(result, gl.getError(), "GL_MAX_LABEL_LENGTH");
2369 m_testCtx.getLog() << TestLog::Message << "GL_MAX_LABEL_LENGTH = " << maxLabelLen << TestLog::EndMessage;
2371 if (maxLabelLen < 256)
2372 throw tcu::TestError("maxLabelLen was less than required (256)");
2373 if (maxLabelLen > 8192)
2377 << "GL_MAX_LABEL_LENGTH is very large. Application having larger labels is unlikely, skipping test."
2378 << TestLog::EndMessage;
2379 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2383 sync = gl.fenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
2384 GLS_COLLECT_GL_ERROR(result, gl.getError(), "fenceSync");
2386 shader = gl.createShader(GL_FRAGMENT_SHADER);
2387 GLS_COLLECT_GL_ERROR(result, gl.getError(), "createShader");
2390 const tcu::ScopedLogSection section (m_testCtx.getLog(), "Shader", "Shader object");
2391 std::vector<char> buffer (maxLabelLen, 'X');
2392 std::vector<char> readBuffer (maxLabelLen, 'X');
2394 buffer[maxLabelLen-1] = '\0';
2396 m_testCtx.getLog() << TestLog::Message << "Setting max length label, with implicit size. (length = -1)" << TestLog::EndMessage;
2397 gl.objectLabel(GL_SHADER, shader, -1, &buffer[0]);
2398 GLS_COLLECT_GL_ERROR(result, gl.getError(), "objectLabel");
2400 m_testCtx.getLog() << TestLog::Message << "Querying label back" << TestLog::EndMessage;
2402 gl.getObjectLabel(GL_SHADER, shader, maxLabelLen, &outlen, &readBuffer[0]);
2403 GLS_COLLECT_GL_ERROR(result, gl.getError(), "getObjectLabel");
2405 if (outlen != maxLabelLen-1)
2406 result.fail("'length' was not " + de::toString(maxLabelLen-1) + ", got " + de::toString(outlen));
2407 else if (readBuffer[outlen] != '\0')
2408 result.fail("Buffer was not null-terminated");
2410 m_testCtx.getLog() << TestLog::Message << "Setting max length label, with explicit size. (length = " << (maxLabelLen-1) << ")" << TestLog::EndMessage;
2411 gl.objectLabel(GL_SHADER, shader, maxLabelLen-1, &buffer[0]);
2412 GLS_COLLECT_GL_ERROR(result, gl.getError(), "objectLabel");
2414 m_testCtx.getLog() << TestLog::Message << "Querying label back" << TestLog::EndMessage;
2416 readBuffer[maxLabelLen-1] = 'X';
2417 gl.getObjectLabel(GL_SHADER, shader, maxLabelLen, &outlen, &readBuffer[0]);
2418 GLS_COLLECT_GL_ERROR(result, gl.getError(), "getObjectLabel");
2420 if (outlen != maxLabelLen-1)
2421 result.fail("'length' was not " + de::toString(maxLabelLen-1) + ", got " + de::toString(outlen));
2422 else if (readBuffer[outlen] != '\0')
2423 result.fail("Buffer was not null-terminated");
2427 const tcu::ScopedLogSection section (m_testCtx.getLog(), "Sync", "Sync object");
2428 std::vector<char> buffer (maxLabelLen, 'X');
2429 std::vector<char> readBuffer (maxLabelLen, 'X');
2431 buffer[maxLabelLen-1] = '\0';
2433 m_testCtx.getLog() << TestLog::Message << "Setting max length label, with implicit size. (length = -1)" << TestLog::EndMessage;
2434 gl.objectPtrLabel(sync, -1, &buffer[0]);
2435 GLS_COLLECT_GL_ERROR(result, gl.getError(), "objectPtrLabel");
2437 m_testCtx.getLog() << TestLog::Message << "Querying label back" << TestLog::EndMessage;
2439 gl.getObjectPtrLabel(sync, maxLabelLen, &outlen, &readBuffer[0]);
2440 GLS_COLLECT_GL_ERROR(result, gl.getError(), "getObjectPtrLabel");
2442 if (outlen != maxLabelLen-1)
2443 result.fail("'length' was not " + de::toString(maxLabelLen-1) + ", got " + de::toString(outlen));
2444 else if (readBuffer[outlen] != '\0')
2445 result.fail("Buffer was not null-terminated");
2447 m_testCtx.getLog() << TestLog::Message << "Setting max length label, with explicit size. (length = " << (maxLabelLen-1) << ")" << TestLog::EndMessage;
2448 gl.objectPtrLabel(sync, maxLabelLen-1, &buffer[0]);
2449 GLS_COLLECT_GL_ERROR(result, gl.getError(), "objectPtrLabel");
2451 m_testCtx.getLog() << TestLog::Message << "Querying label back" << TestLog::EndMessage;
2453 readBuffer[maxLabelLen-1] = 'X';
2454 gl.getObjectPtrLabel(sync, maxLabelLen, &outlen, &readBuffer[0]);
2455 GLS_COLLECT_GL_ERROR(result, gl.getError(), "getObjectPtrLabel");
2457 if (outlen != maxLabelLen-1)
2458 result.fail("'length' was not " + de::toString(maxLabelLen-1) + ", got " + de::toString(outlen));
2459 else if (readBuffer[outlen] != '\0')
2460 result.fail("Buffer was not null-terminated");
2463 gl.deleteShader(shader);
2464 gl.deleteSync(sync);
2466 result.setTestContextResult(m_testCtx);
2470 class LabelLengthCase : public TestCase
2473 LabelLengthCase (Context& ctx, const char* name, const char* desc);
2474 virtual IterateResult iterate (void);
2477 LabelLengthCase::LabelLengthCase (Context& ctx, const char* name, const char* desc)
2478 : TestCase(ctx, name, desc)
2482 LabelLengthCase::IterateResult LabelLengthCase::iterate (void)
2484 TCU_CHECK_AND_THROW(NotSupportedError, isKHRDebugSupported(m_context), "GL_KHR_debug is not supported");
2486 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2487 tcu::ResultCollector result (m_testCtx.getLog(), " // ERROR: ");
2488 const char* const msg = "This is a debug label";
2493 sync = gl.fenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
2494 GLS_COLLECT_GL_ERROR(result, gl.getError(), "fenceSync");
2496 shader = gl.createShader(GL_FRAGMENT_SHADER);
2497 GLS_COLLECT_GL_ERROR(result, gl.getError(), "createShader");
2500 const tcu::ScopedLogSection section(m_testCtx.getLog(), "Shader", "Shader object");
2502 m_testCtx.getLog() << TestLog::Message << "Querying label length" << TestLog::EndMessage;
2504 gl.getObjectLabel(GL_SHADER, shader, 0, &outlen, DE_NULL);
2505 GLS_COLLECT_GL_ERROR(result, gl.getError(), "getObjectLabel");
2508 result.fail("'length' was not 0, got " + de::toString(outlen));
2510 m_testCtx.getLog() << TestLog::Message << "Query returned length: " << outlen << TestLog::EndMessage;
2512 m_testCtx.getLog() << TestLog::Message << "Setting label to string: \"" << msg << "\"" << TestLog::EndMessage;
2513 gl.objectLabel(GL_SHADER, shader, -1, msg);
2514 GLS_COLLECT_GL_ERROR(result, gl.getError(), "objectLabel");
2516 m_testCtx.getLog() << TestLog::Message << "Querying label length" << TestLog::EndMessage;
2518 gl.getObjectLabel(GL_SHADER, shader, 0, &outlen, DE_NULL);
2519 GLS_COLLECT_GL_ERROR(result, gl.getError(), "getObjectLabel");
2522 result.fail("'length' was not 21, got " + de::toString(outlen));
2524 m_testCtx.getLog() << TestLog::Message << "Query returned length: " << outlen << TestLog::EndMessage;
2528 const tcu::ScopedLogSection section(m_testCtx.getLog(), "Sync", "Sync object");
2530 m_testCtx.getLog() << TestLog::Message << "Querying label length" << TestLog::EndMessage;
2532 gl.getObjectPtrLabel(sync, 0, &outlen, DE_NULL);
2533 GLS_COLLECT_GL_ERROR(result, gl.getError(), "getObjectPtrLabel");
2536 result.fail("'length' was not 0, got " + de::toString(outlen));
2538 m_testCtx.getLog() << TestLog::Message << "Query returned length: " << outlen << TestLog::EndMessage;
2540 m_testCtx.getLog() << TestLog::Message << "Setting label to string: \"" << msg << "\"" << TestLog::EndMessage;
2541 gl.objectPtrLabel(sync, -1, msg);
2542 GLS_COLLECT_GL_ERROR(result, gl.getError(), "objectPtrLabel");
2544 m_testCtx.getLog() << TestLog::Message << "Querying label length" << TestLog::EndMessage;
2546 gl.getObjectPtrLabel(sync, 0, &outlen, DE_NULL);
2547 GLS_COLLECT_GL_ERROR(result, gl.getError(), "getObjectPtrLabel");
2550 result.fail("'length' was not 21, got " + de::toString(outlen));
2552 m_testCtx.getLog() << TestLog::Message << "Query returned length: " << outlen << TestLog::EndMessage;
2555 gl.deleteShader(shader);
2556 gl.deleteSync(sync);
2558 result.setTestContextResult(m_testCtx);
2562 class LimitQueryCase : public TestCase
2565 LimitQueryCase (Context& context,
2567 const char* description,
2570 gls::StateQueryUtil::QueryType type);
2572 IterateResult iterate (void);
2574 const gls::StateQueryUtil::QueryType m_type;
2576 const glw::GLenum m_target;
2579 LimitQueryCase::LimitQueryCase (Context& context,
2581 const char* description,
2584 gls::StateQueryUtil::QueryType type)
2585 : TestCase (context, name, description)
2592 LimitQueryCase::IterateResult LimitQueryCase::iterate (void)
2594 TCU_CHECK_AND_THROW(NotSupportedError, isKHRDebugSupported(m_context), "GL_KHR_debug is not supported");
2596 glu::CallLogWrapper gl (m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
2597 tcu::ResultCollector result (m_testCtx.getLog(), " // ERROR: ");
2599 gl.enableLogging(true);
2600 gls::StateQueryUtil::verifyStateIntegerMin(result, gl, m_target, m_limit, m_type);
2602 result.setTestContextResult(m_testCtx);
2606 class IsEnabledCase : public TestCase
2611 INITIAL_CTX_IS_DEBUG = 0,
2615 IsEnabledCase (Context& context,
2617 const char* description,
2619 InitialValue initial,
2620 gls::StateQueryUtil::QueryType type);
2622 IterateResult iterate (void);
2624 const gls::StateQueryUtil::QueryType m_type;
2625 const glw::GLenum m_target;
2626 const InitialValue m_initial;
2629 IsEnabledCase::IsEnabledCase (Context& context,
2631 const char* description,
2633 InitialValue initial,
2634 gls::StateQueryUtil::QueryType type)
2635 : TestCase (context, name, description)
2638 , m_initial (initial)
2642 IsEnabledCase::IterateResult IsEnabledCase::iterate (void)
2644 TCU_CHECK_AND_THROW(NotSupportedError, isKHRDebugSupported(m_context), "GL_KHR_debug is not supported");
2646 glu::CallLogWrapper gl (m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
2647 tcu::ResultCollector result (m_testCtx.getLog(), " // ERROR: ");
2650 gl.enableLogging(true);
2652 if (m_initial == INITIAL_FALSE)
2656 DE_ASSERT(m_initial == INITIAL_CTX_IS_DEBUG);
2657 initial = (m_context.getRenderContext().getType().getFlags() & glu::CONTEXT_DEBUG) != 0;
2660 // check inital value
2661 gls::StateQueryUtil::verifyStateBoolean(result, gl, m_target, initial, m_type);
2665 gl.glEnable(m_target);
2666 GLS_COLLECT_GL_ERROR(result, gl.glGetError(), "glEnable");
2668 gls::StateQueryUtil::verifyStateBoolean(result, gl, m_target, true, m_type);
2670 gl.glDisable(m_target);
2671 GLS_COLLECT_GL_ERROR(result, gl.glGetError(), "glDisable");
2673 gls::StateQueryUtil::verifyStateBoolean(result, gl, m_target, false, m_type);
2675 result.setTestContextResult(m_testCtx);
2679 class PositiveIntegerCase : public TestCase
2682 PositiveIntegerCase (Context& context,
2684 const char* description,
2686 gls::StateQueryUtil::QueryType type);
2688 IterateResult iterate (void);
2690 const gls::StateQueryUtil::QueryType m_type;
2691 const glw::GLenum m_target;
2694 PositiveIntegerCase::PositiveIntegerCase (Context& context,
2696 const char* description,
2698 gls::StateQueryUtil::QueryType type)
2699 : TestCase (context, name, description)
2705 PositiveIntegerCase::IterateResult PositiveIntegerCase::iterate (void)
2707 TCU_CHECK_AND_THROW(NotSupportedError, isKHRDebugSupported(m_context), "GL_KHR_debug is not supported");
2709 glu::CallLogWrapper gl (m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
2710 tcu::ResultCollector result (m_testCtx.getLog(), " // ERROR: ");
2712 gl.enableLogging(true);
2713 gls::StateQueryUtil::verifyStateIntegerMin(result, gl, m_target, 0, m_type);
2715 result.setTestContextResult(m_testCtx);
2719 class GroupStackDepthQueryCase : public TestCase
2722 GroupStackDepthQueryCase (Context& context,
2724 const char* description,
2725 gls::StateQueryUtil::QueryType type);
2727 IterateResult iterate (void);
2729 const gls::StateQueryUtil::QueryType m_type;
2732 GroupStackDepthQueryCase::GroupStackDepthQueryCase (Context& context,
2734 const char* description,
2735 gls::StateQueryUtil::QueryType type)
2736 : TestCase (context, name, description)
2741 GroupStackDepthQueryCase::IterateResult GroupStackDepthQueryCase::iterate (void)
2743 TCU_CHECK_AND_THROW(NotSupportedError, isKHRDebugSupported(m_context), "GL_KHR_debug is not supported");
2745 glu::CallLogWrapper gl (m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
2746 tcu::ResultCollector result (m_testCtx.getLog(), " // ERROR: ");
2748 gl.enableLogging(true);
2751 const tcu::ScopedLogSection section(m_testCtx.getLog(), "Initial", "Initial");
2753 gls::StateQueryUtil::verifyStateInteger(result, gl, GL_DEBUG_GROUP_STACK_DEPTH, 1, m_type);
2757 const tcu::ScopedLogSection section(m_testCtx.getLog(), "Scoped", "Scoped");
2759 gl.glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 1, -1, "Application group 1");
2760 gls::StateQueryUtil::verifyStateInteger(result, gl, GL_DEBUG_GROUP_STACK_DEPTH, 2, m_type);
2761 gl.glPopDebugGroup();
2764 result.setTestContextResult(m_testCtx);
2768 extern "C" void GLW_APIENTRY dummyCallback(GLenum, GLenum, GLuint, GLenum, GLsizei, const char*, void*)
2773 class DebugCallbackFunctionCase : public TestCase
2776 DebugCallbackFunctionCase (Context& context, const char* name, const char* description);
2777 IterateResult iterate (void);
2780 DebugCallbackFunctionCase::DebugCallbackFunctionCase (Context& context, const char* name, const char* description)
2781 : TestCase (context, name, description)
2785 DebugCallbackFunctionCase::IterateResult DebugCallbackFunctionCase::iterate (void)
2787 using namespace gls::StateQueryUtil;
2788 TCU_CHECK_AND_THROW(NotSupportedError, isKHRDebugSupported(m_context), "GL_KHR_debug is not supported");
2790 glu::CallLogWrapper gl (m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
2791 tcu::ResultCollector result (m_testCtx.getLog(), " // ERROR: ");
2793 gl.enableLogging(true);
2796 const tcu::ScopedLogSection section(m_testCtx.getLog(), "Initial", "Initial");
2798 verifyStatePointer(result, gl, GL_DEBUG_CALLBACK_FUNCTION, 0, QUERY_POINTER);
2802 const tcu::ScopedLogSection section(m_testCtx.getLog(), "Set", "Set");
2804 gl.glDebugMessageCallback(dummyCallback, DE_NULL);
2805 verifyStatePointer(result, gl, GL_DEBUG_CALLBACK_FUNCTION, (const void*)dummyCallback, QUERY_POINTER);
2808 result.setTestContextResult(m_testCtx);
2812 class DebugCallbackUserParamCase : public TestCase
2815 DebugCallbackUserParamCase (Context& context, const char* name, const char* description);
2816 IterateResult iterate (void);
2819 DebugCallbackUserParamCase::DebugCallbackUserParamCase (Context& context, const char* name, const char* description)
2820 : TestCase (context, name, description)
2824 DebugCallbackUserParamCase::IterateResult DebugCallbackUserParamCase::iterate (void)
2826 using namespace gls::StateQueryUtil;
2828 TCU_CHECK_AND_THROW(NotSupportedError, isKHRDebugSupported(m_context), "GL_KHR_debug is not supported");
2830 glu::CallLogWrapper gl (m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
2831 tcu::ResultCollector result (m_testCtx.getLog(), " // ERROR: ");
2833 gl.enableLogging(true);
2836 const tcu::ScopedLogSection section(m_testCtx.getLog(), "Initial", "Initial");
2838 verifyStatePointer(result, gl, GL_DEBUG_CALLBACK_USER_PARAM, 0, QUERY_POINTER);
2842 const tcu::ScopedLogSection section (m_testCtx.getLog(), "Set", "Set");
2843 const void* param = (void*)(int*)0x123;
2845 gl.glDebugMessageCallback(dummyCallback, param);
2846 verifyStatePointer(result, gl, GL_DEBUG_CALLBACK_USER_PARAM, param, QUERY_POINTER);
2849 result.setTestContextResult(m_testCtx);
2855 DebugTests::DebugTests (Context& context)
2856 : TestCaseGroup(context, "debug", "Debug tests")
2862 CASETYPE_CALLBACK = 0,
2869 tcu::TestNode* createCase (CaseType type, Context& ctx, const char* name, const char* desc, TestFunctionWrapper function)
2873 case CASETYPE_CALLBACK: return new CallbackErrorCase(ctx, name, desc, function);
2874 case CASETYPE_LOG: return new LogErrorCase(ctx, name, desc, function);
2875 case CASETYPE_GETERROR: return new GetErrorCase(ctx, name, desc, function);
2878 DE_FATAL("Invalid type");
2884 tcu::TestCaseGroup* createChildCases (CaseType type, Context& ctx, const char* name, const char* desc, const vector<FunctionContainer>& funcs)
2886 tcu::TestCaseGroup* host = new tcu::TestCaseGroup(ctx.getTestContext(), name, desc);
2888 for (size_t ndx = 0; ndx < funcs.size(); ndx++)
2889 host->addChild(createCase(type, ctx, funcs[ndx].name, funcs[ndx].desc, funcs[ndx].function));
2894 vector<FunctionContainer> wrapCoreFunctions (const vector<NegativeTestShared::FunctionContainer>& fns)
2896 vector<FunctionContainer> retVal;
2898 retVal.resize(fns.size());
2899 for (int ndx = 0; ndx < (int)fns.size(); ++ndx)
2901 retVal[ndx].function = TestFunctionWrapper(fns[ndx].function);
2902 retVal[ndx].name = fns[ndx].name;
2903 retVal[ndx].desc = fns[ndx].desc;
2909 void DebugTests::init (void)
2911 const vector<FunctionContainer> bufferFuncs = wrapCoreFunctions(NegativeTestShared::getNegativeBufferApiTestFunctions());
2912 const vector<FunctionContainer> textureFuncs = wrapCoreFunctions(NegativeTestShared::getNegativeTextureApiTestFunctions());
2913 const vector<FunctionContainer> shaderFuncs = wrapCoreFunctions(NegativeTestShared::getNegativeShaderApiTestFunctions());
2914 const vector<FunctionContainer> fragmentFuncs = wrapCoreFunctions(NegativeTestShared::getNegativeFragmentApiTestFunctions());
2915 const vector<FunctionContainer> vaFuncs = wrapCoreFunctions(NegativeTestShared::getNegativeVertexArrayApiTestFunctions());
2916 const vector<FunctionContainer> stateFuncs = wrapCoreFunctions(NegativeTestShared::getNegativeStateApiTestFunctions());
2917 const vector<FunctionContainer> atomicCounterFuncs = wrapCoreFunctions(NegativeTestShared::getNegativeAtomicCounterTestFunctions());
2918 const vector<FunctionContainer> shaderImageLoadStoreFuncs = wrapCoreFunctions(NegativeTestShared::getNegativeShaderImageLoadStoreTestFunctions());
2919 const vector<FunctionContainer> shaderFunctionFuncs = wrapCoreFunctions(NegativeTestShared::getNegativeShaderFunctionTestFunctions());
2920 const vector<FunctionContainer> shaderDirectiveFuncs = wrapCoreFunctions(NegativeTestShared::getNegativeShaderDirectiveTestFunctions());
2921 const vector<FunctionContainer> externalFuncs = getUserMessageFuncs();
2924 using namespace gls::StateQueryUtil;
2926 tcu::TestCaseGroup* const queries = new tcu::TestCaseGroup(m_testCtx, "state_query", "State query");
2931 const char* targetName;
2936 { "max_debug_message_length", "MAX_DEBUG_MESSAGE_LENGTH", GL_MAX_DEBUG_MESSAGE_LENGTH, 1 },
2937 { "max_debug_logged_messages", "MAX_DEBUG_LOGGED_MESSAGES", GL_MAX_DEBUG_LOGGED_MESSAGES, 1 },
2938 { "max_debug_group_stack_depth", "MAX_DEBUG_GROUP_STACK_DEPTH", GL_MAX_DEBUG_GROUP_STACK_DEPTH, 64 },
2939 { "max_label_length", "MAX_LABEL_LENGTH", GL_MAX_LABEL_LENGTH, 256 },
2944 #define FOR_ALL_TYPES(X) \
2948 const char* const postfix = "_getboolean"; \
2949 const QueryType queryType = QUERY_BOOLEAN; \
2953 const char* const postfix = "_getinteger"; \
2954 const QueryType queryType = QUERY_INTEGER; \
2958 const char* const postfix = "_getinteger64"; \
2959 const QueryType queryType = QUERY_INTEGER64; \
2963 const char* const postfix = "_getfloat"; \
2964 const QueryType queryType = QUERY_FLOAT; \
2968 while (deGetFalse())
2969 #define FOR_ALL_ENABLE_TYPES(X) \
2973 const char* const postfix = "_isenabled"; \
2974 const QueryType queryType = QUERY_ISENABLED; \
2979 while (deGetFalse())
2981 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(limits); ++ndx)
2983 FOR_ALL_TYPES(queries->addChild(new LimitQueryCase(m_context,
2984 (std::string(limits[ndx].name) + postfix).c_str(),
2985 (std::string("Test ") + limits[ndx].targetName).c_str(),
2986 limits[ndx].target, limits[ndx].limit, queryType)));
2989 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)));
2990 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)));
2992 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)));
2993 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)));
2994 FOR_ALL_TYPES(queries->addChild(new GroupStackDepthQueryCase(m_context, (std::string("debug_group_stack_depth") + postfix).c_str(), "Test DEBUG_GROUP_STACK_DEPTH", queryType)));
2996 queries->addChild(new DebugCallbackFunctionCase (m_context, "debug_callback_function_getpointer", "Test DEBUG_CALLBACK_FUNCTION"));
2997 queries->addChild(new DebugCallbackUserParamCase(m_context, "debug_callback_user_param_getpointer", "Test DEBUG_CALLBACK_USER_PARAM"));
2999 #undef FOR_ALL_TYPES
3000 #undef FOR_ALL_ENABLE_TYPES
3004 tcu::TestCaseGroup* const negative = new tcu::TestCaseGroup(m_testCtx, "negative_coverage", "API error coverage with various reporting methods");
3009 tcu::TestCaseGroup* const host = new tcu::TestCaseGroup(m_testCtx, "callbacks", "Reporting of standard API errors via callback");
3011 negative->addChild(host);
3012 host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "buffer", "Negative Buffer API Cases", bufferFuncs));
3013 host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "texture", "Negative Texture API Cases", textureFuncs));
3014 host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "shader", "Negative Shader API Cases", shaderFuncs));
3015 host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "fragment", "Negative Fragment API Cases", fragmentFuncs));
3016 host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "vertex_array", "Negative Vertex Array API Cases", vaFuncs));
3017 host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "state", "Negative GL State API Cases", stateFuncs));
3018 host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "atomic_counter", "Negative Atomic Counter API Cases", atomicCounterFuncs));
3019 host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "shader_image_load_store", "Negative Shader Image Load and Store API Cases", shaderImageLoadStoreFuncs));
3020 host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "shader_function", "Negative Shader Function Cases", shaderFunctionFuncs));
3021 host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "shader_directive", "Negative Shader Directive Cases", shaderDirectiveFuncs));
3025 tcu::TestCaseGroup* const host = new tcu::TestCaseGroup(m_testCtx, "log", "Reporting of standard API errors via log");
3027 negative->addChild(host);
3029 host->addChild(createChildCases(CASETYPE_LOG, m_context, "buffer", "Negative Buffer API Cases", bufferFuncs));
3030 host->addChild(createChildCases(CASETYPE_LOG, m_context, "texture", "Negative Texture API Cases", textureFuncs));
3031 host->addChild(createChildCases(CASETYPE_LOG, m_context, "shader", "Negative Shader API Cases", shaderFuncs));
3032 host->addChild(createChildCases(CASETYPE_LOG, m_context, "fragment", "Negative Fragment API Cases", fragmentFuncs));
3033 host->addChild(createChildCases(CASETYPE_LOG, m_context, "vertex_array", "Negative Vertex Array API Cases", vaFuncs));
3034 host->addChild(createChildCases(CASETYPE_LOG, m_context, "state", "Negative GL State API Cases", stateFuncs));
3035 host->addChild(createChildCases(CASETYPE_LOG, m_context, "atomic_counter", "Negative Atomic Counter API Cases", atomicCounterFuncs));
3036 host->addChild(createChildCases(CASETYPE_LOG, m_context, "shader_image_load_store", "Negative Shader Image Load and Store API Cases", shaderImageLoadStoreFuncs));
3037 host->addChild(createChildCases(CASETYPE_LOG, m_context, "shader_function", "Negative Shader Function Cases", shaderFunctionFuncs));
3038 host->addChild(createChildCases(CASETYPE_LOG, m_context, "shader_directive", "Negative Shader Directive Cases", shaderDirectiveFuncs));
3042 tcu::TestCaseGroup* const host = new tcu::TestCaseGroup(m_testCtx, "get_error", "Reporting of standard API errors via glGetError");
3044 negative->addChild(host);
3046 host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "buffer", "Negative Buffer API Cases", bufferFuncs));
3047 host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "texture", "Negative Texture API Cases", textureFuncs));
3048 host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "shader", "Negative Shader API Cases", shaderFuncs));
3049 host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "fragment", "Negative Fragment API Cases", fragmentFuncs));
3050 host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "vertex_array", "Negative Vertex Array API Cases", vaFuncs));
3051 host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "state", "Negative GL State API Cases", stateFuncs));
3052 host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "atomic_counter", "Negative Atomic Counter API Cases", atomicCounterFuncs));
3053 host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "shader_image_load_store", "Negative Shader Image Load and Store API Cases", shaderImageLoadStoreFuncs));
3054 host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "shader_function", "Negative Shader Function Cases", shaderFunctionFuncs));
3055 host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "shader_directive", "Negative Shader Directive Cases", shaderDirectiveFuncs));
3060 tcu::TestCaseGroup* const host = createChildCases(CASETYPE_CALLBACK, m_context, "externally_generated", "Externally Generated Messages", externalFuncs);
3062 host->addChild(new GroupCase(m_context, "push_pop_consistency", "Push/pop message generation with full message output checking"));
3068 vector<FunctionContainer> containers;
3069 vector<TestFunctionWrapper> allFuncs;
3071 de::Random rng (0x53941903 ^ m_context.getTestContext().getCommandLine().getBaseSeed());
3073 containers.insert(containers.end(), bufferFuncs.begin(), bufferFuncs.end());
3074 containers.insert(containers.end(), textureFuncs.begin(), textureFuncs.end());
3075 containers.insert(containers.end(), externalFuncs.begin(), externalFuncs.end());
3077 for (size_t ndx = 0; ndx < containers.size(); ndx++)
3078 allFuncs.push_back(containers[ndx].function);
3080 rng.shuffle(allFuncs.begin(), allFuncs.end());
3083 tcu::TestCaseGroup* const filtering = new tcu::TestCaseGroup(m_testCtx, "error_filters", "Filtering of reported errors");
3084 const int errorFuncsPerCase = 4;
3085 const int maxFilteringCaseCount = 32;
3086 const int caseCount = (int(allFuncs.size()) + errorFuncsPerCase-1) / errorFuncsPerCase;
3088 addChild(filtering);
3090 for (int caseNdx = 0; caseNdx < de::min(caseCount, maxFilteringCaseCount); caseNdx++)
3092 const int start = caseNdx*errorFuncsPerCase;
3093 const int end = de::min((caseNdx+1)*errorFuncsPerCase, int(allFuncs.size()));
3094 const string name = "case_" + de::toString(caseNdx);
3095 vector<TestFunctionWrapper> funcs (allFuncs.begin()+start, allFuncs.begin()+end);
3097 // These produce lots of different message types, thus always include at least one when testing filtering
3098 funcs.insert(funcs.end(), externalFuncs[caseNdx%externalFuncs.size()].function);
3100 filtering->addChild(new FilterCase(m_context, name.c_str(), "DebugMessageControl usage", funcs));
3105 tcu::TestCaseGroup* const groups = new tcu::TestCaseGroup(m_testCtx, "error_groups", "Filtering of reported errors with use of Error Groups");
3106 const int errorFuncsPerCase = 4;
3107 const int maxFilteringCaseCount = 16;
3108 const int caseCount = (int(allFuncs.size()) + errorFuncsPerCase-1) / errorFuncsPerCase;
3112 for (int caseNdx = 0; caseNdx < caseCount && caseNdx < maxFilteringCaseCount; caseNdx++)
3114 const int start = caseNdx*errorFuncsPerCase;
3115 const int end = de::min((caseNdx+1)*errorFuncsPerCase, int(allFuncs.size()));
3116 const string name = ("case_" + de::toString(caseNdx)).c_str();
3117 vector<TestFunctionWrapper> funcs (&allFuncs[0]+start, &allFuncs[0]+end);
3119 // These produce lots of different message types, thus always include at least one when testing filtering
3120 funcs.insert(funcs.end(), externalFuncs[caseNdx%externalFuncs.size()].function);
3122 groups->addChild(new GroupFilterCase(m_context, name.c_str(), "Debug Group usage", funcs));
3127 tcu::TestCaseGroup* const async = new tcu::TestCaseGroup(m_testCtx, "async", "Asynchronous message generation");
3128 const int errorFuncsPerCase = 2;
3129 const int maxAsyncCaseCount = 16;
3130 const int caseCount = (int(allFuncs.size()) + errorFuncsPerCase-1) / errorFuncsPerCase;
3134 for (int caseNdx = 0; caseNdx < caseCount && caseNdx < maxAsyncCaseCount; caseNdx++)
3136 const int start = caseNdx*errorFuncsPerCase;
3137 const int end = de::min((caseNdx+1)*errorFuncsPerCase, int(allFuncs.size()));
3138 const string name = ("case_" + de::toString(caseNdx)).c_str();
3139 vector<TestFunctionWrapper> funcs (&allFuncs[0]+start, &allFuncs[0]+end);
3142 async->addChild(new AsyncCase(m_context, (name+"_callback").c_str(), "Async message generation", funcs, true));
3144 async->addChild(new AsyncCase(m_context, (name+"_log").c_str(), "Async message generation", funcs, false));
3150 tcu::TestCaseGroup* const labels = new tcu::TestCaseGroup(m_testCtx, "object_labels", "Labeling objects");
3159 { GL_BUFFER, "buffer", "Debug label on a buffer object" },
3160 { GL_SHADER, "shader", "Debug label on a shader object" },
3161 { GL_PROGRAM, "program", "Debug label on a program object" },
3162 { GL_QUERY, "query", "Debug label on a query object" },
3163 { GL_PROGRAM_PIPELINE, "program_pipeline", "Debug label on a program pipeline object" },
3164 { GL_TRANSFORM_FEEDBACK, "transform_feedback", "Debug label on a transform feedback object" },
3165 { GL_SAMPLER, "sampler", "Debug label on a sampler object" },
3166 { GL_TEXTURE, "texture", "Debug label on a texture object" },
3167 { GL_RENDERBUFFER, "renderbuffer", "Debug label on a renderbuffer object" },
3168 { GL_FRAMEBUFFER, "framebuffer", "Debug label on a framebuffer object" },
3173 labels->addChild(new InitialLabelCase (m_context, "initial", "Debug label initial value"));
3174 labels->addChild(new ClearLabelCase (m_context, "clearing", "Debug label clearing"));
3175 labels->addChild(new SpecifyWithLengthCase (m_context, "specify_with_length", "Debug label specified with length"));
3176 labels->addChild(new BufferLimitedLabelCase (m_context, "buffer_limited_query", "Debug label query to too short buffer"));
3177 labels->addChild(new LabelMaxSizeCase (m_context, "max_label_length", "Max sized debug label"));
3178 labels->addChild(new LabelLengthCase (m_context, "query_length_only", "Query debug label length"));
3180 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(cases); ndx++)
3181 labels->addChild(new LabelCase(m_context, cases[ndx].name, cases[ndx].desc, cases[ndx].identifier));
3182 labels->addChild(new SyncLabelCase(m_context, "sync", "Debug label on a sync object"));