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