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