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