• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2015 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 
7 // DebugTest.cpp : Tests of the GL_KHR_debug extension
8 
9 #include "common/debug.h"
10 #include "test_utils/ANGLETest.h"
11 #include "test_utils/gl_raii.h"
12 
13 namespace angle
14 {
15 constexpr char kBufferObjLabel[]          = "buffer";
16 constexpr char kShaderObjLabel[]          = "shader";
17 constexpr char kProgramObjLabel[]         = "program";
18 constexpr char kVertexArrayObjLabel[]     = "vertexarray";
19 constexpr char kQueryObjLabel[]           = "query";
20 constexpr char kProgramPipelineObjLabel[] = "programpipeline";
21 constexpr GLenum kObjectTypes[]           = {GL_BUFFER_OBJECT_EXT,           GL_SHADER_OBJECT_EXT,
22                                    GL_PROGRAM_OBJECT_EXT,          GL_QUERY_OBJECT_EXT,
23                                    GL_PROGRAM_PIPELINE_OBJECT_EXT, GL_VERTEX_ARRAY_OBJECT_EXT};
24 
25 class DebugTest : public ANGLETest
26 {
27   protected:
DebugTest()28     DebugTest() : mDebugExtensionAvailable(false)
29     {
30         setWindowWidth(128);
31         setWindowHeight(128);
32         setConfigRedBits(8);
33         setConfigGreenBits(8);
34         setConfigBlueBits(8);
35         setConfigAlphaBits(8);
36         setConfigDepthBits(24);
37         setDebugEnabled(true);
38     }
39 
testSetUp()40     void testSetUp() override
41     {
42         mDebugExtensionAvailable = IsGLExtensionEnabled("GL_KHR_debug");
43         if (mDebugExtensionAvailable)
44         {
45             glEnable(GL_DEBUG_OUTPUT);
46         }
47     }
48 
49     bool mDebugExtensionAvailable;
50 };
51 
createGLObjectAndLabel(GLenum identifier,GLuint & object,const char ** label)52 void createGLObjectAndLabel(GLenum identifier, GLuint &object, const char **label)
53 {
54     switch (identifier)
55     {
56         case GL_BUFFER_OBJECT_EXT:
57             glGenBuffers(1, &object);
58             glBindBuffer(GL_ARRAY_BUFFER, object);
59             *label = kBufferObjLabel;
60             break;
61         case GL_SHADER_OBJECT_EXT:
62             object = glCreateShader(GL_VERTEX_SHADER);
63             *label = kShaderObjLabel;
64             break;
65         case GL_PROGRAM_OBJECT_EXT:
66             object = glCreateProgram();
67             *label = kProgramObjLabel;
68             break;
69         case GL_VERTEX_ARRAY_OBJECT_EXT:
70             glGenVertexArrays(1, &object);
71             glBindVertexArray(object);
72             *label = kVertexArrayObjLabel;
73             break;
74         case GL_QUERY_OBJECT_EXT:
75             glGenQueries(1, &object);
76             glBeginQuery(GL_ANY_SAMPLES_PASSED, object);
77             *label = kQueryObjLabel;
78             break;
79         case GL_PROGRAM_PIPELINE_OBJECT_EXT:
80             glGenProgramPipelines(1, &object);
81             glBindProgramPipeline(object);
82             *label = kProgramPipelineObjLabel;
83             break;
84         default:
85             UNREACHABLE();
86             break;
87     }
88 }
89 
deleteGLObject(GLenum identifier,GLuint & object)90 void deleteGLObject(GLenum identifier, GLuint &object)
91 {
92     switch (identifier)
93     {
94         case GL_BUFFER_OBJECT_EXT:
95             glDeleteBuffers(1, &object);
96             break;
97         case GL_SHADER_OBJECT_EXT:
98             glDeleteShader(object);
99             break;
100         case GL_PROGRAM_OBJECT_EXT:
101             glDeleteProgram(object);
102             break;
103         case GL_VERTEX_ARRAY_OBJECT_EXT:
104             glDeleteVertexArrays(1, &object);
105             break;
106         case GL_QUERY_OBJECT_EXT:
107             glEndQuery(GL_ANY_SAMPLES_PASSED);
108             glDeleteQueries(1, &object);
109             break;
110         case GL_PROGRAM_PIPELINE_OBJECT_EXT:
111             glDeleteProgramPipelines(1, &object);
112             break;
113         default:
114             UNREACHABLE();
115             break;
116     }
117 }
118 
119 // Test basic usage of setting and getting labels using GL_EXT_debug_label
TEST_P(DebugTest,ObjectLabelsEXT)120 TEST_P(DebugTest, ObjectLabelsEXT)
121 {
122     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_debug_label"));
123 
124     for (const GLenum identifier : kObjectTypes)
125     {
126         bool skip = false;
127         switch (identifier)
128         {
129             case GL_PROGRAM_PIPELINE_OBJECT_EXT:
130                 if (!(getClientMajorVersion() >= 3 && getClientMinorVersion() >= 1) ||
131                     !IsGLExtensionEnabled("GL_EXT_separate_shader_objects"))
132                 {
133                     skip = true;
134                 }
135                 break;
136             case GL_QUERY_OBJECT_EXT:
137                 // GLES3 context is required for glGenQueries()
138                 if (getClientMajorVersion() < 3 ||
139                     !IsGLExtensionEnabled("GL_EXT_occlusion_query_boolean"))
140                 {
141                     skip = true;
142                 }
143                 break;
144             case GL_VERTEX_ARRAY_OBJECT_EXT:
145                 if (getClientMajorVersion() < 3)
146                 {
147                     skip = true;
148                 }
149                 break;
150             default:
151                 break;
152         }
153 
154         // if object enum is not supported, move on to the next object type
155         if (skip)
156         {
157             continue;
158         }
159 
160         GLuint object;
161         const char *label;
162         createGLObjectAndLabel(identifier, object, &label);
163 
164         glLabelObjectEXT(identifier, object, 0, label);
165         ASSERT_GL_NO_ERROR();
166 
167         std::vector<char> labelBuf(strlen(label) + 1);
168         GLsizei labelLengthBuf = 0;
169         glGetObjectLabelEXT(identifier, object, static_cast<GLsizei>(labelBuf.size()),
170                             &labelLengthBuf, labelBuf.data());
171         ASSERT_GL_NO_ERROR();
172 
173         EXPECT_EQ(static_cast<GLsizei>(strlen(label)), labelLengthBuf);
174         EXPECT_STREQ(label, labelBuf.data());
175 
176         ASSERT_GL_NO_ERROR();
177 
178         deleteGLObject(identifier, object);
179 
180         glLabelObjectEXT(identifier, object, 0, label);
181         EXPECT_GL_ERROR(GL_INVALID_OPERATION);
182 
183         glGetObjectLabelEXT(identifier, object, static_cast<GLsizei>(labelBuf.size()),
184                             &labelLengthBuf, labelBuf.data());
185         EXPECT_GL_ERROR(GL_INVALID_OPERATION);
186     }
187 }
188 
189 class DebugTestES3 : public DebugTest
190 {};
191 
192 struct Message
193 {
194     GLenum source;
195     GLenum type;
196     GLuint id;
197     GLenum severity;
198     std::string message;
199     const void *userParam;
200 };
201 
Callback(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar * message,const void * userParam)202 static void GL_APIENTRY Callback(GLenum source,
203                                  GLenum type,
204                                  GLuint id,
205                                  GLenum severity,
206                                  GLsizei length,
207                                  const GLchar *message,
208                                  const void *userParam)
209 {
210     Message m{source, type, id, severity, std::string(message, length), userParam};
211     std::vector<Message> *messages =
212         static_cast<std::vector<Message> *>(const_cast<void *>(userParam));
213     messages->push_back(m);
214 }
215 
216 // Test that all ANGLE back-ends have GL_KHR_debug enabled
TEST_P(DebugTestES3,Enabled)217 TEST_P(DebugTestES3, Enabled)
218 {
219     ASSERT_TRUE(mDebugExtensionAvailable);
220 }
221 
222 // Test that when debug output is disabled, no message are outputted
TEST_P(DebugTestES3,DisabledOutput)223 TEST_P(DebugTestES3, DisabledOutput)
224 {
225     ANGLE_SKIP_TEST_IF(!mDebugExtensionAvailable);
226 
227     glDisable(GL_DEBUG_OUTPUT);
228 
229     glDebugMessageInsertKHR(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_OTHER, 1,
230                             GL_DEBUG_SEVERITY_NOTIFICATION, -1, "discarded");
231 
232     GLint numMessages = 0;
233     glGetIntegerv(GL_DEBUG_LOGGED_MESSAGES, &numMessages);
234     ASSERT_EQ(0, numMessages);
235 
236     std::vector<Message> messages;
237     glDebugMessageCallbackKHR(Callback, &messages);
238     glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
239 
240     ASSERT_EQ(0u, messages.size());
241 }
242 
243 // Test a basic flow of inserting a message and reading it back
TEST_P(DebugTestES3,InsertMessage)244 TEST_P(DebugTestES3, InsertMessage)
245 {
246     ANGLE_SKIP_TEST_IF(!mDebugExtensionAvailable);
247 
248     const GLenum source       = GL_DEBUG_SOURCE_APPLICATION;
249     const GLenum type         = GL_DEBUG_TYPE_OTHER;
250     const GLuint id           = 1;
251     const GLenum severity     = GL_DEBUG_SEVERITY_NOTIFICATION;
252     const std::string message = "Message";
253 
254     glDebugMessageInsertKHR(source, type, id, severity, -1, message.c_str());
255 
256     GLint numMessages = 0;
257     glGetIntegerv(GL_DEBUG_LOGGED_MESSAGES, &numMessages);
258     ASSERT_EQ(1, numMessages);
259 
260     GLint messageLength = 0;
261     glGetIntegerv(GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH, &messageLength);
262     EXPECT_EQ(static_cast<GLint>(message.length()) + 1, messageLength);
263 
264     GLenum sourceBuf   = 0;
265     GLenum typeBuf     = 0;
266     GLenum idBuf       = 0;
267     GLenum severityBuf = 0;
268     GLsizei lengthBuf  = 0;
269     std::vector<char> messageBuf(messageLength);
270     GLuint ret =
271         glGetDebugMessageLogKHR(1, static_cast<GLsizei>(messageBuf.size()), &sourceBuf, &typeBuf,
272                                 &idBuf, &severityBuf, &lengthBuf, messageBuf.data());
273     EXPECT_EQ(1u, ret);
274     EXPECT_EQ(source, sourceBuf);
275     EXPECT_EQ(type, typeBuf);
276     EXPECT_EQ(id, idBuf);
277     EXPECT_EQ(severity, severityBuf);
278     EXPECT_EQ(lengthBuf, messageLength);
279     EXPECT_STREQ(message.c_str(), messageBuf.data());
280 
281     glGetIntegerv(GL_DEBUG_LOGGED_MESSAGES, &numMessages);
282     EXPECT_EQ(0, numMessages);
283 
284     ASSERT_GL_NO_ERROR();
285 }
286 
287 // Test inserting multiple messages
TEST_P(DebugTestES3,InsertMessageMultiple)288 TEST_P(DebugTestES3, InsertMessageMultiple)
289 {
290     ANGLE_SKIP_TEST_IF(!mDebugExtensionAvailable);
291 
292     const GLenum source          = GL_DEBUG_SOURCE_APPLICATION;
293     const GLenum type            = GL_DEBUG_TYPE_OTHER;
294     const GLuint startID         = 1;
295     const GLenum severity        = GL_DEBUG_SEVERITY_NOTIFICATION;
296     const char messageRepeatChar = 'm';
297     const size_t messageCount    = 32;
298 
299     for (size_t i = 0; i < messageCount; i++)
300     {
301         std::string message(i + 1, messageRepeatChar);
302         glDebugMessageInsertKHR(source, type, startID + static_cast<GLuint>(i), severity, -1,
303                                 message.c_str());
304     }
305 
306     GLint numMessages = 0;
307     glGetIntegerv(GL_DEBUG_LOGGED_MESSAGES, &numMessages);
308     ASSERT_EQ(static_cast<GLint>(messageCount), numMessages);
309 
310     for (size_t i = 0; i < messageCount; i++)
311     {
312         glGetIntegerv(GL_DEBUG_LOGGED_MESSAGES, &numMessages);
313         EXPECT_EQ(static_cast<GLint>(messageCount - i), numMessages);
314 
315         std::string expectedMessage(i + 1, messageRepeatChar);
316 
317         GLint messageLength = 0;
318         glGetIntegerv(GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH, &messageLength);
319         EXPECT_EQ(static_cast<GLint>(expectedMessage.length()) + 1, messageLength);
320 
321         GLenum sourceBuf   = 0;
322         GLenum typeBuf     = 0;
323         GLenum idBuf       = 0;
324         GLenum severityBuf = 0;
325         GLsizei lengthBuf  = 0;
326         std::vector<char> messageBuf(messageLength);
327         GLuint ret =
328             glGetDebugMessageLogKHR(1, static_cast<GLsizei>(messageBuf.size()), &sourceBuf,
329                                     &typeBuf, &idBuf, &severityBuf, &lengthBuf, messageBuf.data());
330         EXPECT_EQ(1u, ret);
331         EXPECT_EQ(source, sourceBuf);
332         EXPECT_EQ(type, typeBuf);
333         EXPECT_EQ(startID + i, idBuf);
334         EXPECT_EQ(severity, severityBuf);
335         EXPECT_EQ(lengthBuf, messageLength);
336         EXPECT_STREQ(expectedMessage.c_str(), messageBuf.data());
337     }
338 
339     glGetIntegerv(GL_DEBUG_LOGGED_MESSAGES, &numMessages);
340     EXPECT_EQ(0, numMessages);
341 
342     ASSERT_GL_NO_ERROR();
343 }
344 
345 // Test using a debug callback
TEST_P(DebugTestES3,DebugCallback)346 TEST_P(DebugTestES3, DebugCallback)
347 {
348     ANGLE_SKIP_TEST_IF(!mDebugExtensionAvailable);
349 
350     std::vector<Message> messages;
351 
352     glDebugMessageCallbackKHR(Callback, &messages);
353     glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
354 
355     const GLenum source       = GL_DEBUG_SOURCE_APPLICATION;
356     const GLenum type         = GL_DEBUG_TYPE_OTHER;
357     const GLuint id           = 1;
358     const GLenum severity     = GL_DEBUG_SEVERITY_NOTIFICATION;
359     const std::string message = "Message";
360 
361     glDebugMessageInsertKHR(source, type, id, severity, -1, message.c_str());
362 
363     GLint numMessages = 0;
364     glGetIntegerv(GL_DEBUG_LOGGED_MESSAGES, &numMessages);
365     EXPECT_EQ(0, numMessages);
366 
367     ASSERT_EQ(1u, messages.size());
368 
369     const Message &m = messages.front();
370     EXPECT_EQ(source, m.source);
371     EXPECT_EQ(type, m.type);
372     EXPECT_EQ(id, m.id);
373     EXPECT_EQ(severity, m.severity);
374     EXPECT_EQ(message, m.message);
375 
376     ASSERT_GL_NO_ERROR();
377 }
378 
379 // Test the glGetPointervKHR entry point
TEST_P(DebugTestES3,GetPointer)380 TEST_P(DebugTestES3, GetPointer)
381 {
382     ANGLE_SKIP_TEST_IF(!mDebugExtensionAvailable);
383 
384     std::vector<Message> messages;
385 
386     glDebugMessageCallbackKHR(Callback, &messages);
387 
388     void *callback = nullptr;
389     glGetPointervKHR(GL_DEBUG_CALLBACK_FUNCTION, &callback);
390     EXPECT_EQ(reinterpret_cast<void *>(Callback), callback);
391 
392     void *userData = nullptr;
393     glGetPointervKHR(GL_DEBUG_CALLBACK_USER_PARAM, &userData);
394     EXPECT_EQ(static_cast<void *>(&messages), userData);
395 }
396 
397 // Test usage of message control.  Example taken from GL_KHR_debug spec.
TEST_P(DebugTestES3,MessageControl1)398 TEST_P(DebugTestES3, MessageControl1)
399 {
400     ANGLE_SKIP_TEST_IF(!mDebugExtensionAvailable);
401 
402     std::vector<Message> messages;
403 
404     glDebugMessageCallbackKHR(Callback, &messages);
405     glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
406 
407     // Setup of the default active debug group: Filter everything in
408     glDebugMessageControlKHR(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, nullptr, GL_TRUE);
409 
410     // Generate a debug marker debug output message
411     glDebugMessageInsertKHR(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_MARKER, 100,
412                             GL_DEBUG_SEVERITY_NOTIFICATION, -1, "Message 1");
413 
414     // Push debug group 1
415     glPushDebugGroupKHR(GL_DEBUG_SOURCE_APPLICATION, 1, -1, "Message 2");
416 
417     // Setup of the debug group 1: Filter everything out
418     glDebugMessageControlKHR(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, nullptr, GL_FALSE);
419 
420     // This message won't appear in the debug output log of
421     glDebugMessageInsertKHR(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_MARKER, 100,
422                             GL_DEBUG_SEVERITY_NOTIFICATION, -1, "Message 3");
423 
424     // Pop debug group 1, restore the volume control of the default debug group.
425     glPopDebugGroupKHR();
426 
427     // Generate a debug marker debug output message
428     glDebugMessageInsertKHR(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_MARKER, 100,
429                             GL_DEBUG_SEVERITY_NOTIFICATION, -1, "Message 5");
430 
431     // Expected debug output from the GL implementation
432     // Message 1
433     // Message 2
434     // Message 2
435     // Message 5
436     EXPECT_EQ(4u, messages.size());
437     EXPECT_STREQ(messages[0].message.c_str(), "Message 1");
438     EXPECT_STREQ(messages[1].message.c_str(), "Message 2");
439     EXPECT_STREQ(messages[2].message.c_str(), "Message 2");
440     EXPECT_STREQ(messages[3].message.c_str(), "Message 5");
441 
442     ASSERT_GL_NO_ERROR();
443 }
444 
445 // Test usage of message control.  Example taken from GL_KHR_debug spec.
TEST_P(DebugTestES3,MessageControl2)446 TEST_P(DebugTestES3, MessageControl2)
447 {
448     ANGLE_SKIP_TEST_IF(!mDebugExtensionAvailable);
449 
450     std::vector<Message> messages;
451 
452     glDebugMessageCallbackKHR(Callback, &messages);
453     glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
454 
455     // Setup the control of de debug output for the default debug group
456     glDebugMessageControlKHR(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, nullptr, GL_FALSE);
457     glDebugMessageControlKHR(GL_DEBUG_SOURCE_THIRD_PARTY, GL_DONT_CARE, GL_DONT_CARE, 0, nullptr,
458                              GL_FALSE);
459     std::vector<GLuint> ids0 = {1234, 2345, 3456, 4567};
460     glDebugMessageControlKHR(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_OTHER, GL_DONT_CARE,
461                              static_cast<GLuint>(ids0.size()), ids0.data(), GL_FALSE);
462     glDebugMessageControlKHR(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, GL_DONT_CARE,
463                              static_cast<GLuint>(ids0.size()), ids0.data(), GL_FALSE);
464 
465     // Push debug group 1
466     // Inherit of the default debug group debug output volume control
467     // Filtered out by glDebugMessageControl
468     glPushDebugGroupKHR(GL_DEBUG_SOURCE_APPLICATION, 1, -1, "Message 1");
469 
470     // In this section of the code, we are interested in performances.
471     glDebugMessageControlKHR(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PERFORMANCE, GL_DONT_CARE,
472                              0, nullptr, GL_TRUE);
473     // But we already identify that some messages are not really useful for us.
474     std::vector<GLuint> ids1 = {5678, 6789};
475     glDebugMessageControlKHR(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_OTHER, GL_DONT_CARE,
476                              static_cast<GLuint>(ids1.size()), ids1.data(), GL_FALSE);
477 
478     glDebugMessageInsertKHR(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PERFORMANCE, 1357,
479                             GL_DEBUG_SEVERITY_MEDIUM, -1, "Message 2");
480     glDebugMessageInsertKHR(GL_DEBUG_SOURCE_THIRD_PARTY,  // We still filter out these messages.
481                             GL_DEBUG_TYPE_OTHER, 3579, GL_DEBUG_SEVERITY_MEDIUM, -1, "Message 3");
482 
483     glPopDebugGroupKHR();
484 
485     // Expected debug output from the GL implementation
486     // Message 2
487     EXPECT_EQ(1u, messages.size());
488     EXPECT_STREQ(messages[0].message.c_str(), "Message 2");
489 
490     ASSERT_GL_NO_ERROR();
491 }
492 
493 // Test basic usage of setting and getting labels
TEST_P(DebugTestES3,ObjectLabels)494 TEST_P(DebugTestES3, ObjectLabels)
495 {
496     ANGLE_SKIP_TEST_IF(!mDebugExtensionAvailable);
497 
498     GLuint renderbuffer = 0;
499     glGenRenderbuffers(1, &renderbuffer);
500     glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
501 
502     const std::string &label = "renderbuffer";
503     glObjectLabelKHR(GL_RENDERBUFFER, renderbuffer, -1, label.c_str());
504 
505     std::vector<char> labelBuf(label.length() + 1);
506     GLsizei labelLengthBuf = 0;
507     glGetObjectLabelKHR(GL_RENDERBUFFER, renderbuffer, static_cast<GLsizei>(labelBuf.size()),
508                         &labelLengthBuf, labelBuf.data());
509 
510     EXPECT_EQ(static_cast<GLsizei>(label.length()), labelLengthBuf);
511     EXPECT_STREQ(label.c_str(), labelBuf.data());
512 
513     ASSERT_GL_NO_ERROR();
514 
515     glDeleteRenderbuffers(1, &renderbuffer);
516 
517     glObjectLabelKHR(GL_RENDERBUFFER, renderbuffer, -1, label.c_str());
518     EXPECT_GL_ERROR(GL_INVALID_VALUE);
519 
520     glGetObjectLabelKHR(GL_RENDERBUFFER, renderbuffer, static_cast<GLsizei>(labelBuf.size()),
521                         &labelLengthBuf, labelBuf.data());
522     EXPECT_GL_ERROR(GL_INVALID_VALUE);
523 }
524 
525 // Test basic usage of setting and getting labels
TEST_P(DebugTestES3,ObjectPtrLabels)526 TEST_P(DebugTestES3, ObjectPtrLabels)
527 {
528     ANGLE_SKIP_TEST_IF(!mDebugExtensionAvailable);
529 
530     GLsync sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
531 
532     const std::string &label = "sync";
533     glObjectPtrLabelKHR(sync, -1, label.c_str());
534 
535     std::vector<char> labelBuf(label.length() + 1);
536     GLsizei labelLengthBuf = 0;
537     glGetObjectPtrLabelKHR(sync, static_cast<GLsizei>(labelBuf.size()), &labelLengthBuf,
538                            labelBuf.data());
539 
540     EXPECT_EQ(static_cast<GLsizei>(label.length()), labelLengthBuf);
541     EXPECT_STREQ(label.c_str(), labelBuf.data());
542 
543     ASSERT_GL_NO_ERROR();
544 
545     glDeleteSync(sync);
546 
547     glObjectPtrLabelKHR(sync, -1, label.c_str());
548     EXPECT_GL_ERROR(GL_INVALID_VALUE);
549 
550     glGetObjectPtrLabelKHR(sync, static_cast<GLsizei>(labelBuf.size()), &labelLengthBuf,
551                            labelBuf.data());
552     EXPECT_GL_ERROR(GL_INVALID_VALUE);
553 }
554 
555 // Test setting labels before, during and after rendering.  The debug markers can be validated by
556 // capturing this test under a graphics debugger.
TEST_P(DebugTestES3,Rendering)557 TEST_P(DebugTestES3, Rendering)
558 {
559     ANGLE_SKIP_TEST_IF(!mDebugExtensionAvailable);
560 
561     // The test produces the following hierarchy:
562     //
563     // Group: Before Draw
564     // Message: Before Draw Marker
565     //   Message: In Group 1 Marker
566     //   glDrawArrays
567     //   Group: After Draw 1
568     //      glDrawArrays
569     //      Message: In Group 2 Marker
570     //
571     //      glCopyTexImage <-- this breaks the render pass
572     //
573     //      glDrawArrays
574     //   End Group
575     //
576     //   glCopyTexImage <-- this breaks the render pass
577     //
578     //   Group: After Draw 2
579     //      glDrawArrays
580     //
581     //      glCopyTexImage <-- this breaks the render pass
582     //
583     //      Message: In Group 3 Marker
584     //   End Group
585     //   Message: After Draw Marker
586     // End Group
587     const std::string beforeDrawGroup = "Before Draw";
588     const std::string drawGroup1      = "Group 1";
589     const std::string drawGroup2      = "Group 2";
590 
591     const std::string beforeDrawMarker = "Before Draw Marker";
592     const std::string inGroup1Marker   = "In Group 1 Marker";
593     const std::string inGroup2Marker   = "In Group 2 Marker";
594     const std::string inGroup3Marker   = "In Group 3 Marker";
595     const std::string afterDrawMarker  = "After Draw Marker";
596 
597     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
598     glUseProgram(program);
599 
600     glPushDebugGroupKHR(GL_DEBUG_SOURCE_THIRD_PARTY, 0, -1, beforeDrawGroup.c_str());
601     glDebugMessageInsertKHR(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PERFORMANCE, 0,
602                             GL_DEBUG_SEVERITY_NOTIFICATION, -1, beforeDrawMarker.c_str());
603     {
604         glDebugMessageInsertKHR(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_MARKER, 0,
605                                 GL_DEBUG_SEVERITY_LOW, -1, inGroup1Marker.c_str());
606 
607         glDrawArrays(GL_TRIANGLES, 0, 6);
608 
609         glPushDebugGroupKHR(GL_DEBUG_SOURCE_APPLICATION, 0, -1, drawGroup1.c_str());
610         {
611             glDrawArrays(GL_TRIANGLES, 0, 6);
612 
613             glDebugMessageInsertKHR(GL_DEBUG_SOURCE_THIRD_PARTY, GL_DEBUG_TYPE_PORTABILITY, 0,
614                                     GL_DEBUG_SEVERITY_MEDIUM, -1, inGroup2Marker.c_str());
615 
616             GLTexture texture;
617             glBindTexture(GL_TEXTURE_2D, texture);
618             glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, 1, 1, 0);
619 
620             glDrawArrays(GL_TRIANGLES, 0, 6);
621         }
622         glPopDebugGroupKHR();
623 
624         glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, 2, 2, 0);
625 
626         glPushDebugGroupKHR(GL_DEBUG_SOURCE_THIRD_PARTY, 0, -1, drawGroup2.c_str());
627         {
628             glDrawArrays(GL_TRIANGLES, 0, 6);
629 
630             glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, 3, 3, 0);
631 
632             glDebugMessageInsertKHR(GL_DEBUG_SOURCE_THIRD_PARTY, GL_DEBUG_TYPE_OTHER, 0,
633                                     GL_DEBUG_SEVERITY_HIGH, -1, inGroup3Marker.c_str());
634         }
635         glPopGroupMarkerEXT();
636 
637         glDebugMessageInsertKHR(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0,
638                                 GL_DEBUG_SEVERITY_HIGH, -1, afterDrawMarker.c_str());
639     }
640     glPopGroupMarkerEXT();
641 
642     ASSERT_GL_NO_ERROR();
643 }
644 
645 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DebugTestES3);
646 ANGLE_INSTANTIATE_TEST_ES3(DebugTestES3);
647 
648 ANGLE_INSTANTIATE_TEST(DebugTest,
649                        ANGLE_ALL_TEST_PLATFORMS_ES1,
650                        ANGLE_ALL_TEST_PLATFORMS_ES2,
651                        ANGLE_ALL_TEST_PLATFORMS_ES3,
652                        ANGLE_ALL_TEST_PLATFORMS_ES31);
653 }  // namespace angle
654