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