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