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