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