xref: /aosp_15_r20/external/angle/src/tests/gl_tests/DebugTest.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
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 class DebugTestES32 : public DebugTestES3
193 {
testSetUp()194     void testSetUp() override { ; }
195 };
196 
197 struct Message
198 {
199     GLenum source;
200     GLenum type;
201     GLuint id;
202     GLenum severity;
203     std::string message;
204     const void *userParam;
205 };
206 
Callback(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar * message,const void * userParam)207 static void GL_APIENTRY Callback(GLenum source,
208                                  GLenum type,
209                                  GLuint id,
210                                  GLenum severity,
211                                  GLsizei length,
212                                  const GLchar *message,
213                                  const void *userParam)
214 {
215     Message m{source, type, id, severity, std::string(message, length), userParam};
216     std::vector<Message> *messages =
217         static_cast<std::vector<Message> *>(const_cast<void *>(userParam));
218     messages->push_back(m);
219 }
220 
221 // Test that all ANGLE back-ends have GL_KHR_debug enabled
TEST_P(DebugTestES3,Enabled)222 TEST_P(DebugTestES3, Enabled)
223 {
224     ASSERT_TRUE(mDebugExtensionAvailable);
225 }
226 
227 // Test that when debug output is disabled, no message are outputted
TEST_P(DebugTestES3,DisabledOutput)228 TEST_P(DebugTestES3, DisabledOutput)
229 {
230     ANGLE_SKIP_TEST_IF(!mDebugExtensionAvailable);
231 
232     glDisable(GL_DEBUG_OUTPUT);
233 
234     glDebugMessageInsertKHR(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_OTHER, 1,
235                             GL_DEBUG_SEVERITY_NOTIFICATION, -1, "discarded");
236 
237     GLint numMessages = 0;
238     glGetIntegerv(GL_DEBUG_LOGGED_MESSAGES, &numMessages);
239     ASSERT_EQ(0, numMessages);
240 
241     std::vector<Message> messages;
242     glDebugMessageCallbackKHR(Callback, &messages);
243     glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
244 
245     ASSERT_EQ(0u, messages.size());
246 }
247 
248 // Test a basic flow of inserting a message and reading it back
TEST_P(DebugTestES3,InsertMessage)249 TEST_P(DebugTestES3, InsertMessage)
250 {
251     ANGLE_SKIP_TEST_IF(!mDebugExtensionAvailable);
252 
253     const GLenum source       = GL_DEBUG_SOURCE_APPLICATION;
254     const GLenum type         = GL_DEBUG_TYPE_OTHER;
255     const GLuint id           = 1;
256     const GLenum severity     = GL_DEBUG_SEVERITY_NOTIFICATION;
257     const std::string message = "Message";
258 
259     glDebugMessageInsertKHR(source, type, id, severity, -1, message.c_str());
260 
261     GLint numMessages = 0;
262     glGetIntegerv(GL_DEBUG_LOGGED_MESSAGES, &numMessages);
263     ASSERT_EQ(1, numMessages);
264 
265     GLint messageLength = 0;
266     glGetIntegerv(GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH, &messageLength);
267     EXPECT_EQ(static_cast<GLint>(message.length()) + 1, messageLength);
268 
269     GLenum sourceBuf   = 0;
270     GLenum typeBuf     = 0;
271     GLenum idBuf       = 0;
272     GLenum severityBuf = 0;
273     GLsizei lengthBuf  = 0;
274     std::vector<char> messageBuf(messageLength);
275     GLuint ret =
276         glGetDebugMessageLogKHR(1, static_cast<GLsizei>(messageBuf.size()), &sourceBuf, &typeBuf,
277                                 &idBuf, &severityBuf, &lengthBuf, messageBuf.data());
278     EXPECT_EQ(1u, ret);
279     EXPECT_EQ(source, sourceBuf);
280     EXPECT_EQ(type, typeBuf);
281     EXPECT_EQ(id, idBuf);
282     EXPECT_EQ(severity, severityBuf);
283     EXPECT_EQ(lengthBuf, messageLength);
284     EXPECT_STREQ(message.c_str(), messageBuf.data());
285 
286     glGetIntegerv(GL_DEBUG_LOGGED_MESSAGES, &numMessages);
287     EXPECT_EQ(0, numMessages);
288 
289     ASSERT_GL_NO_ERROR();
290 }
291 
292 // Test inserting multiple messages
TEST_P(DebugTestES3,InsertMessageMultiple)293 TEST_P(DebugTestES3, InsertMessageMultiple)
294 {
295     ANGLE_SKIP_TEST_IF(!mDebugExtensionAvailable);
296 
297     const GLenum source          = GL_DEBUG_SOURCE_APPLICATION;
298     const GLenum type            = GL_DEBUG_TYPE_OTHER;
299     const GLuint startID         = 1;
300     const GLenum severity        = GL_DEBUG_SEVERITY_NOTIFICATION;
301     const char messageRepeatChar = 'm';
302     const size_t messageCount    = 32;
303 
304     for (size_t i = 0; i < messageCount; i++)
305     {
306         std::string message(i + 1, messageRepeatChar);
307         glDebugMessageInsertKHR(source, type, startID + static_cast<GLuint>(i), severity, -1,
308                                 message.c_str());
309     }
310 
311     GLint numMessages = 0;
312     glGetIntegerv(GL_DEBUG_LOGGED_MESSAGES, &numMessages);
313     ASSERT_EQ(static_cast<GLint>(messageCount), numMessages);
314 
315     for (size_t i = 0; i < messageCount; i++)
316     {
317         glGetIntegerv(GL_DEBUG_LOGGED_MESSAGES, &numMessages);
318         EXPECT_EQ(static_cast<GLint>(messageCount - i), numMessages);
319 
320         std::string expectedMessage(i + 1, messageRepeatChar);
321 
322         GLint messageLength = 0;
323         glGetIntegerv(GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH, &messageLength);
324         EXPECT_EQ(static_cast<GLint>(expectedMessage.length()) + 1, messageLength);
325 
326         GLenum sourceBuf   = 0;
327         GLenum typeBuf     = 0;
328         GLenum idBuf       = 0;
329         GLenum severityBuf = 0;
330         GLsizei lengthBuf  = 0;
331         std::vector<char> messageBuf(messageLength);
332         GLuint ret =
333             glGetDebugMessageLogKHR(1, static_cast<GLsizei>(messageBuf.size()), &sourceBuf,
334                                     &typeBuf, &idBuf, &severityBuf, &lengthBuf, messageBuf.data());
335         EXPECT_EQ(1u, ret);
336         EXPECT_EQ(source, sourceBuf);
337         EXPECT_EQ(type, typeBuf);
338         EXPECT_EQ(startID + i, idBuf);
339         EXPECT_EQ(severity, severityBuf);
340         EXPECT_EQ(lengthBuf, messageLength);
341         EXPECT_STREQ(expectedMessage.c_str(), messageBuf.data());
342     }
343 
344     glGetIntegerv(GL_DEBUG_LOGGED_MESSAGES, &numMessages);
345     EXPECT_EQ(0, numMessages);
346 
347     ASSERT_GL_NO_ERROR();
348 }
349 
350 // Test using a debug callback
TEST_P(DebugTestES3,DebugCallback)351 TEST_P(DebugTestES3, DebugCallback)
352 {
353     ANGLE_SKIP_TEST_IF(!mDebugExtensionAvailable);
354 
355     std::vector<Message> messages;
356 
357     glDebugMessageCallbackKHR(Callback, &messages);
358     glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
359 
360     const GLenum source       = GL_DEBUG_SOURCE_APPLICATION;
361     const GLenum type         = GL_DEBUG_TYPE_OTHER;
362     const GLuint id           = 1;
363     const GLenum severity     = GL_DEBUG_SEVERITY_NOTIFICATION;
364     const std::string message = "Message";
365 
366     glDebugMessageInsertKHR(source, type, id, severity, -1, message.c_str());
367 
368     GLint numMessages = 0;
369     glGetIntegerv(GL_DEBUG_LOGGED_MESSAGES, &numMessages);
370     EXPECT_EQ(0, numMessages);
371 
372     ASSERT_EQ(1u, messages.size());
373 
374     const Message &m = messages.front();
375     EXPECT_EQ(source, m.source);
376     EXPECT_EQ(type, m.type);
377     EXPECT_EQ(id, m.id);
378     EXPECT_EQ(severity, m.severity);
379     EXPECT_EQ(message, m.message);
380 
381     ASSERT_GL_NO_ERROR();
382 }
383 
384 // Test the glGetPointervKHR entry point
TEST_P(DebugTestES3,GetPointer)385 TEST_P(DebugTestES3, GetPointer)
386 {
387     ANGLE_SKIP_TEST_IF(!mDebugExtensionAvailable);
388 
389     std::vector<Message> messages;
390 
391     glDebugMessageCallbackKHR(Callback, &messages);
392 
393     void *callback = nullptr;
394     glGetPointervKHR(GL_DEBUG_CALLBACK_FUNCTION, &callback);
395     EXPECT_EQ(reinterpret_cast<void *>(Callback), callback);
396 
397     void *userData = nullptr;
398     glGetPointervKHR(GL_DEBUG_CALLBACK_USER_PARAM, &userData);
399     EXPECT_EQ(static_cast<void *>(&messages), userData);
400 }
401 
402 // Test usage of message control.  Example taken from GL_KHR_debug spec.
TEST_P(DebugTestES3,MessageControl1)403 TEST_P(DebugTestES3, MessageControl1)
404 {
405     ANGLE_SKIP_TEST_IF(!mDebugExtensionAvailable);
406 
407     std::vector<Message> messages;
408 
409     glDebugMessageCallbackKHR(Callback, &messages);
410     glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
411 
412     // Setup of the default active debug group: Filter everything in
413     glDebugMessageControlKHR(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, nullptr, GL_TRUE);
414 
415     // Generate a debug marker debug output message
416     glDebugMessageInsertKHR(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_MARKER, 100,
417                             GL_DEBUG_SEVERITY_NOTIFICATION, -1, "Message 1");
418 
419     // Push debug group 1
420     glPushDebugGroupKHR(GL_DEBUG_SOURCE_APPLICATION, 1, -1, "Message 2");
421 
422     // Setup of the debug group 1: Filter everything out
423     glDebugMessageControlKHR(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, nullptr, GL_FALSE);
424 
425     // This message won't appear in the debug output log of
426     glDebugMessageInsertKHR(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_MARKER, 100,
427                             GL_DEBUG_SEVERITY_NOTIFICATION, -1, "Message 3");
428 
429     // Pop debug group 1, restore the volume control of the default debug group.
430     glPopDebugGroupKHR();
431 
432     // Generate a debug marker debug output message
433     glDebugMessageInsertKHR(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_MARKER, 100,
434                             GL_DEBUG_SEVERITY_NOTIFICATION, -1, "Message 5");
435 
436     // Expected debug output from the GL implementation
437     // Message 1
438     // Message 2
439     // Message 2
440     // Message 5
441     EXPECT_EQ(4u, messages.size());
442     EXPECT_STREQ(messages[0].message.c_str(), "Message 1");
443     EXPECT_STREQ(messages[1].message.c_str(), "Message 2");
444     EXPECT_STREQ(messages[2].message.c_str(), "Message 2");
445     EXPECT_STREQ(messages[3].message.c_str(), "Message 5");
446 
447     ASSERT_GL_NO_ERROR();
448 }
449 
450 // Test usage of message control.  Example taken from GL_KHR_debug spec.
TEST_P(DebugTestES3,MessageControl2)451 TEST_P(DebugTestES3, MessageControl2)
452 {
453     ANGLE_SKIP_TEST_IF(!mDebugExtensionAvailable);
454 
455     std::vector<Message> messages;
456 
457     glDebugMessageCallbackKHR(Callback, &messages);
458     glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
459 
460     // Setup the control of de debug output for the default debug group
461     glDebugMessageControlKHR(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, nullptr, GL_FALSE);
462     glDebugMessageControlKHR(GL_DEBUG_SOURCE_THIRD_PARTY, GL_DONT_CARE, GL_DONT_CARE, 0, nullptr,
463                              GL_FALSE);
464     std::vector<GLuint> ids0 = {1234, 2345, 3456, 4567};
465     glDebugMessageControlKHR(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_OTHER, GL_DONT_CARE,
466                              static_cast<GLuint>(ids0.size()), ids0.data(), GL_FALSE);
467     glDebugMessageControlKHR(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, GL_DONT_CARE,
468                              static_cast<GLuint>(ids0.size()), ids0.data(), GL_FALSE);
469 
470     // Push debug group 1
471     // Inherit of the default debug group debug output volume control
472     // Filtered out by glDebugMessageControl
473     glPushDebugGroupKHR(GL_DEBUG_SOURCE_APPLICATION, 1, -1, "Message 1");
474 
475     // In this section of the code, we are interested in performances.
476     glDebugMessageControlKHR(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PERFORMANCE, GL_DONT_CARE,
477                              0, nullptr, GL_TRUE);
478     // But we already identify that some messages are not really useful for us.
479     std::vector<GLuint> ids1 = {5678, 6789};
480     glDebugMessageControlKHR(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_OTHER, GL_DONT_CARE,
481                              static_cast<GLuint>(ids1.size()), ids1.data(), GL_FALSE);
482 
483     glDebugMessageInsertKHR(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PERFORMANCE, 1357,
484                             GL_DEBUG_SEVERITY_MEDIUM, -1, "Message 2");
485     glDebugMessageInsertKHR(GL_DEBUG_SOURCE_THIRD_PARTY,  // We still filter out these messages.
486                             GL_DEBUG_TYPE_OTHER, 3579, GL_DEBUG_SEVERITY_MEDIUM, -1, "Message 3");
487 
488     glPopDebugGroupKHR();
489 
490     // Expected debug output from the GL implementation
491     // Message 2
492     EXPECT_EQ(1u, messages.size());
493     EXPECT_STREQ(messages[0].message.c_str(), "Message 2");
494 
495     ASSERT_GL_NO_ERROR();
496 }
497 
498 // Test basic usage of setting and getting labels
TEST_P(DebugTestES3,ObjectLabelsKHR)499 TEST_P(DebugTestES3, ObjectLabelsKHR)
500 {
501     ANGLE_SKIP_TEST_IF(!mDebugExtensionAvailable);
502 
503     GLuint renderbuffer = 0;
504     glGenRenderbuffers(1, &renderbuffer);
505     glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
506 
507     const std::string &label = "renderbuffer";
508     glObjectLabelKHR(GL_RENDERBUFFER, renderbuffer, -1, label.c_str());
509 
510     std::vector<char> labelBuf(label.length() + 1);
511     GLsizei labelLengthBuf = 0;
512     glGetObjectLabelKHR(GL_RENDERBUFFER, renderbuffer, static_cast<GLsizei>(labelBuf.size()),
513                         &labelLengthBuf, labelBuf.data());
514 
515     EXPECT_EQ(static_cast<GLsizei>(label.length()), labelLengthBuf);
516     EXPECT_STREQ(label.c_str(), labelBuf.data());
517 
518     ASSERT_GL_NO_ERROR();
519 
520     glDeleteRenderbuffers(1, &renderbuffer);
521 
522     glObjectLabelKHR(GL_RENDERBUFFER, renderbuffer, -1, label.c_str());
523     EXPECT_GL_ERROR(GL_INVALID_VALUE);
524 
525     glGetObjectLabelKHR(GL_RENDERBUFFER, renderbuffer, static_cast<GLsizei>(labelBuf.size()),
526                         &labelLengthBuf, labelBuf.data());
527     EXPECT_GL_ERROR(GL_INVALID_VALUE);
528 }
529 
530 // Test basic usage of setting and getting labels
TEST_P(DebugTestES3,ObjectPtrLabelsKHR)531 TEST_P(DebugTestES3, ObjectPtrLabelsKHR)
532 {
533     ANGLE_SKIP_TEST_IF(!mDebugExtensionAvailable);
534 
535     GLsync sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
536 
537     const std::string &label = "sync";
538     glObjectPtrLabelKHR(sync, -1, label.c_str());
539 
540     std::vector<char> labelBuf(label.length() + 1);
541     GLsizei labelLengthBuf = 0;
542     glGetObjectPtrLabelKHR(sync, static_cast<GLsizei>(labelBuf.size()), &labelLengthBuf,
543                            labelBuf.data());
544 
545     EXPECT_EQ(static_cast<GLsizei>(label.length()), labelLengthBuf);
546     EXPECT_STREQ(label.c_str(), labelBuf.data());
547 
548     ASSERT_GL_NO_ERROR();
549 
550     glDeleteSync(sync);
551 
552     glObjectPtrLabelKHR(sync, -1, label.c_str());
553     EXPECT_GL_ERROR(GL_INVALID_VALUE);
554 
555     glGetObjectPtrLabelKHR(sync, static_cast<GLsizei>(labelBuf.size()), &labelLengthBuf,
556                            labelBuf.data());
557     EXPECT_GL_ERROR(GL_INVALID_VALUE);
558 }
559 
560 // Test setting labels before, during and after rendering.  The debug markers can be validated by
561 // capturing this test under a graphics debugger.
TEST_P(DebugTestES3,Rendering)562 TEST_P(DebugTestES3, Rendering)
563 {
564     ANGLE_SKIP_TEST_IF(!mDebugExtensionAvailable);
565 
566     // The test produces the following hierarchy:
567     //
568     // Group: Before Draw
569     // Message: Before Draw Marker
570     //   Message: In Group 1 Marker
571     //   glDrawArrays
572     //   Group: After Draw 1
573     //      glDrawArrays
574     //      Message: In Group 2 Marker
575     //
576     //      glCopyTexImage <-- this breaks the render pass
577     //
578     //      glDrawArrays
579     //   End Group
580     //
581     //   glCopyTexImage <-- this breaks the render pass
582     //
583     //   Group: After Draw 2
584     //      glDrawArrays
585     //
586     //      glCopyTexImage <-- this breaks the render pass
587     //
588     //      Message: In Group 3 Marker
589     //   End Group
590     //   Message: After Draw Marker
591     // End Group
592     const std::string beforeDrawGroup = "Before Draw";
593     const std::string drawGroup1      = "Group 1";
594     const std::string drawGroup2      = "Group 2";
595 
596     const std::string beforeDrawMarker = "Before Draw Marker";
597     const std::string inGroup1Marker   = "In Group 1 Marker";
598     const std::string inGroup2Marker   = "In Group 2 Marker";
599     const std::string inGroup3Marker   = "In Group 3 Marker";
600     const std::string afterDrawMarker  = "After Draw Marker";
601 
602     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
603     glUseProgram(program);
604 
605     glPushDebugGroupKHR(GL_DEBUG_SOURCE_THIRD_PARTY, 0, -1, beforeDrawGroup.c_str());
606     glDebugMessageInsertKHR(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PERFORMANCE, 0,
607                             GL_DEBUG_SEVERITY_NOTIFICATION, -1, beforeDrawMarker.c_str());
608     {
609         glDebugMessageInsertKHR(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_MARKER, 0,
610                                 GL_DEBUG_SEVERITY_LOW, -1, inGroup1Marker.c_str());
611 
612         glDrawArrays(GL_TRIANGLES, 0, 6);
613 
614         glPushDebugGroupKHR(GL_DEBUG_SOURCE_APPLICATION, 0, -1, drawGroup1.c_str());
615         {
616             glDrawArrays(GL_TRIANGLES, 0, 6);
617 
618             glDebugMessageInsertKHR(GL_DEBUG_SOURCE_THIRD_PARTY, GL_DEBUG_TYPE_PORTABILITY, 0,
619                                     GL_DEBUG_SEVERITY_MEDIUM, -1, inGroup2Marker.c_str());
620 
621             GLTexture texture;
622             glBindTexture(GL_TEXTURE_2D, texture);
623             glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, 1, 1, 0);
624 
625             glDrawArrays(GL_TRIANGLES, 0, 6);
626         }
627         glPopDebugGroupKHR();
628 
629         glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, 2, 2, 0);
630 
631         glPushDebugGroupKHR(GL_DEBUG_SOURCE_THIRD_PARTY, 0, -1, drawGroup2.c_str());
632         {
633             glDrawArrays(GL_TRIANGLES, 0, 6);
634 
635             glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, 3, 3, 0);
636 
637             glDebugMessageInsertKHR(GL_DEBUG_SOURCE_THIRD_PARTY, GL_DEBUG_TYPE_OTHER, 0,
638                                     GL_DEBUG_SEVERITY_HIGH, -1, inGroup3Marker.c_str());
639         }
640         glPopGroupMarkerEXT();
641 
642         glDebugMessageInsertKHR(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0,
643                                 GL_DEBUG_SEVERITY_HIGH, -1, afterDrawMarker.c_str());
644     }
645     glPopGroupMarkerEXT();
646 
647     ASSERT_GL_NO_ERROR();
648 }
649 
650 // Simple test for gl[Push, Pop]DebugGroup using ES32 core APIs
TEST_P(DebugTestES32,DebugGroup)651 TEST_P(DebugTestES32, DebugGroup)
652 {
653     const std::string testDrawGroup = "Test Draw Group";
654 
655     // Pop without a push should generate GL_STACK_UNDERFLOW error
656     glPopDebugGroup();
657     EXPECT_GL_ERROR(GL_STACK_UNDERFLOW);
658 
659     // Push a test debug group and expect no error
660     glPushDebugGroup(GL_DEBUG_SOURCE_THIRD_PARTY, 0, -1, testDrawGroup.c_str());
661     ASSERT_GL_NO_ERROR();
662 
663     // Pop the test debug group and expect no error
664     glPopDebugGroup();
665     ASSERT_GL_NO_ERROR();
666 }
667 
668 // Simple test for setting and getting labels using ES32 core APIs
TEST_P(DebugTestES32,ObjectLabels)669 TEST_P(DebugTestES32, ObjectLabels)
670 {
671     GLuint renderbuffer = 0;
672     glGenRenderbuffers(1, &renderbuffer);
673     glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
674 
675     const std::string &label = "renderbuffer";
676     glObjectLabel(GL_RENDERBUFFER, renderbuffer, -1, label.c_str());
677 
678     std::vector<char> labelBuf(label.length() + 1);
679     GLsizei labelLengthBuf = 0;
680     glGetObjectLabel(GL_RENDERBUFFER, renderbuffer, static_cast<GLsizei>(labelBuf.size()),
681                      &labelLengthBuf, labelBuf.data());
682 
683     EXPECT_EQ(static_cast<GLsizei>(label.length()), labelLengthBuf);
684     EXPECT_STREQ(label.c_str(), labelBuf.data());
685 
686     ASSERT_GL_NO_ERROR();
687 
688     glDeleteRenderbuffers(1, &renderbuffer);
689 
690     glObjectLabel(GL_RENDERBUFFER, renderbuffer, -1, label.c_str());
691     EXPECT_GL_ERROR(GL_INVALID_VALUE);
692 
693     glGetObjectLabel(GL_RENDERBUFFER, renderbuffer, static_cast<GLsizei>(labelBuf.size()),
694                      &labelLengthBuf, labelBuf.data());
695     EXPECT_GL_ERROR(GL_INVALID_VALUE);
696 }
697 
698 // Simple test for setting and getting labels using ES32 core APIs
TEST_P(DebugTestES32,ObjectPtrLabels)699 TEST_P(DebugTestES32, ObjectPtrLabels)
700 {
701     GLsync sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
702 
703     const std::string &label = "sync";
704     glObjectPtrLabel(sync, -1, label.c_str());
705 
706     std::vector<char> labelBuf(label.length() + 1);
707     GLsizei labelLengthBuf = 0;
708     glGetObjectPtrLabel(sync, static_cast<GLsizei>(labelBuf.size()), &labelLengthBuf,
709                         labelBuf.data());
710 
711     EXPECT_EQ(static_cast<GLsizei>(label.length()), labelLengthBuf);
712     EXPECT_STREQ(label.c_str(), labelBuf.data());
713 
714     ASSERT_GL_NO_ERROR();
715 
716     glDeleteSync(sync);
717 
718     glObjectPtrLabel(sync, -1, label.c_str());
719     EXPECT_GL_ERROR(GL_INVALID_VALUE);
720 
721     glGetObjectPtrLabel(sync, static_cast<GLsizei>(labelBuf.size()), &labelLengthBuf,
722                         labelBuf.data());
723     EXPECT_GL_ERROR(GL_INVALID_VALUE);
724 }
725 
726 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DebugTestES3);
727 ANGLE_INSTANTIATE_TEST_ES3(DebugTestES3);
728 
729 ANGLE_INSTANTIATE_TEST(DebugTest,
730                        ANGLE_ALL_TEST_PLATFORMS_ES1,
731                        ANGLE_ALL_TEST_PLATFORMS_ES2,
732                        ANGLE_ALL_TEST_PLATFORMS_ES3,
733                        ANGLE_ALL_TEST_PLATFORMS_ES31);
734 
735 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DebugTestES32);
736 ANGLE_INSTANTIATE_TEST_ES32(DebugTestES32);
737 }  // namespace angle
738