xref: /aosp_15_r20/external/angle/src/tests/gl_tests/TimerQueriesTest.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1 //
2 // Copyright 2016 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 // TimerQueriesTest.cpp
7 //   Various tests for EXT_disjoint_timer_query functionality and validation
8 //
9 
10 #include "test_utils/ANGLETest.h"
11 #include "test_utils/gl_raii.h"
12 #include "util/EGLWindow.h"
13 #include "util/random_utils.h"
14 #include "util/test_utils.h"
15 
16 using namespace angle;
17 
18 class TimerQueriesTest : public ANGLETest<>
19 {
20   protected:
TimerQueriesTest()21     TimerQueriesTest() : mProgram(0), mProgramCostly(0)
22     {
23         setWindowWidth(128);
24         setWindowHeight(128);
25         setConfigRedBits(8);
26         setConfigGreenBits(8);
27         setConfigBlueBits(8);
28         setConfigAlphaBits(8);
29         setConfigDepthBits(24);
30     }
31 
testSetUp()32     void testSetUp() override
33     {
34         constexpr char kCostlyVS[] =
35             "attribute highp vec4 position; varying highp vec4 testPos; void main(void)\n"
36             "{\n"
37             "    testPos     = position;\n"
38             "    gl_Position = position;\n"
39             "}\n";
40 
41         constexpr char kCostlyFS[] =
42             "precision highp float; varying highp vec4 testPos; void main(void)\n"
43             "{\n"
44             "    vec4 test = testPos;\n"
45             "    for (int i = 0; i < 500; i++)\n"
46             "    {\n"
47             "        test = sqrt(test);\n"
48             "    }\n"
49             "    gl_FragColor = test;\n"
50             "}\n";
51 
52         mProgram = CompileProgram(essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
53         ASSERT_NE(0u, mProgram) << "shader compilation failed.";
54 
55         mProgramCostly = CompileProgram(kCostlyVS, kCostlyFS);
56         ASSERT_NE(0u, mProgramCostly) << "shader compilation failed.";
57     }
58 
testTearDown()59     void testTearDown() override
60     {
61         glDeleteProgram(mProgram);
62         glDeleteProgram(mProgramCostly);
63     }
64 
65     GLuint mProgram;
66     GLuint mProgramCostly;
67 };
68 
69 // Test that all proc addresses are loadable
TEST_P(TimerQueriesTest,ProcAddresses)70 TEST_P(TimerQueriesTest, ProcAddresses)
71 {
72     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_disjoint_timer_query"));
73 
74     ASSERT_NE(nullptr, eglGetProcAddress("glGenQueriesEXT"));
75     ASSERT_NE(nullptr, eglGetProcAddress("glDeleteQueriesEXT"));
76     ASSERT_NE(nullptr, eglGetProcAddress("glIsQueryEXT"));
77     ASSERT_NE(nullptr, eglGetProcAddress("glBeginQueryEXT"));
78     ASSERT_NE(nullptr, eglGetProcAddress("glEndQueryEXT"));
79     ASSERT_NE(nullptr, eglGetProcAddress("glQueryCounterEXT"));
80     ASSERT_NE(nullptr, eglGetProcAddress("glGetQueryivEXT"));
81     ASSERT_NE(nullptr, eglGetProcAddress("glGetQueryObjectivEXT"));
82     ASSERT_NE(nullptr, eglGetProcAddress("glGetQueryObjectuivEXT"));
83     ASSERT_NE(nullptr, eglGetProcAddress("glGetQueryObjecti64vEXT"));
84     ASSERT_NE(nullptr, eglGetProcAddress("glGetQueryObjectui64vEXT"));
85 }
86 
87 // Tests the time elapsed query
TEST_P(TimerQueriesTest,TimeElapsed)88 TEST_P(TimerQueriesTest, TimeElapsed)
89 {
90     // TODO(anglebug.com/40096747): Failing on ARM-based Apple DTKs.
91     ANGLE_SKIP_TEST_IF(IsMac() && IsARM64() && IsDesktopOpenGL());
92 
93     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_disjoint_timer_query"));
94 
95     // http://anglebug.com/42263715
96     ANGLE_SKIP_TEST_IF(IsMac() && IsOpenGL());
97 
98     GLint queryTimeElapsedBits = 0;
99     glGetQueryivEXT(GL_TIME_ELAPSED_EXT, GL_QUERY_COUNTER_BITS_EXT, &queryTimeElapsedBits);
100     ASSERT_GL_NO_ERROR();
101 
102     std::cout << "Time elapsed counter bits: " << queryTimeElapsedBits << std::endl;
103 
104     // Skip test if the number of bits is 0
105     ANGLE_SKIP_TEST_IF(!queryTimeElapsedBits);
106 
107     glDepthMask(GL_TRUE);
108     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
109 
110     GLuint query1 = 0;
111     GLuint query2 = 0;
112     glGenQueriesEXT(1, &query1);
113     glGenQueriesEXT(1, &query2);
114 
115     // Test time elapsed for a single quad
116     glBeginQueryEXT(GL_TIME_ELAPSED_EXT, query1);
117     drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.8f);
118     glEndQueryEXT(GL_TIME_ELAPSED_EXT);
119     ASSERT_GL_NO_ERROR();
120 
121     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
122 
123     // Test time elapsed for costly quad
124     glBeginQueryEXT(GL_TIME_ELAPSED_EXT, query2);
125     drawQuad(mProgramCostly, "position", 0.8f);
126     glEndQueryEXT(GL_TIME_ELAPSED_EXT);
127     ASSERT_GL_NO_ERROR();
128 
129     swapBuffers();
130 
131     int timeout  = 200000;
132     GLuint ready = GL_FALSE;
133     while (ready == GL_FALSE && timeout > 0)
134     {
135         angle::Sleep(0);
136         glGetQueryObjectuivEXT(query1, GL_QUERY_RESULT_AVAILABLE_EXT, &ready);
137         timeout--;
138     }
139     ready = GL_FALSE;
140     while (ready == GL_FALSE && timeout > 0)
141     {
142         angle::Sleep(0);
143         glGetQueryObjectuivEXT(query2, GL_QUERY_RESULT_AVAILABLE_EXT, &ready);
144         timeout--;
145     }
146     ASSERT_LT(0, timeout) << "Query result available timed out" << std::endl;
147 
148     GLuint64 result1 = 0;
149     GLuint64 result2 = 0;
150     glGetQueryObjectui64vEXT(query1, GL_QUERY_RESULT_EXT, &result1);
151     glGetQueryObjectui64vEXT(query2, GL_QUERY_RESULT_EXT, &result2);
152     ASSERT_GL_NO_ERROR();
153 
154     glDeleteQueriesEXT(1, &query1);
155     glDeleteQueriesEXT(1, &query2);
156     ASSERT_GL_NO_ERROR();
157 
158     std::cout << "Elapsed time: " << result1 << " cheap quad" << std::endl;
159     std::cout << "Elapsed time: " << result2 << " costly quad" << std::endl;
160 
161     // The time elapsed should be nonzero
162     EXPECT_LT(0ul, result1);
163     EXPECT_LT(0ul, result2);
164 
165     // The time elapsed should be less than a second.  Not an actual
166     // requirement, but longer than a second to draw something basic hints at
167     // an issue with the queries themselves.
168     EXPECT_LT(result1, 1000000000ul);
169     EXPECT_LT(result2, 1000000000ul);
170 
171     // TODO(geofflang): Re-enable this check when it is non-flaky
172     // The costly quad should take longer than the cheap quad
173     // EXPECT_LT(result1, result2);
174 }
175 
176 // Tests time elapsed for a non draw call (texture upload)
TEST_P(TimerQueriesTest,TimeElapsedTextureTest)177 TEST_P(TimerQueriesTest, TimeElapsedTextureTest)
178 {
179     // OSX drivers don't seem to properly time non-draw calls so we skip the test on Mac
180     ANGLE_SKIP_TEST_IF(IsMac() && IsOpenGL());
181 
182     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_disjoint_timer_query"));
183 
184     GLint queryTimeElapsedBits = 0;
185     glGetQueryivEXT(GL_TIME_ELAPSED_EXT, GL_QUERY_COUNTER_BITS_EXT, &queryTimeElapsedBits);
186     ASSERT_GL_NO_ERROR();
187 
188     std::cout << "Time elapsed counter bits: " << queryTimeElapsedBits << std::endl;
189 
190     // Skip test if the number of bits is 0
191     ANGLE_SKIP_TEST_IF(!queryTimeElapsedBits);
192 
193     std::vector<GLColor> texData{GLColor::black, GLColor::white, GLColor::white, GLColor::black};
194 
195     // Query and texture initialization
196     GLuint texture;
197     GLuint query = 0;
198     glGenQueriesEXT(1, &query);
199     glGenTextures(1, &texture);
200 
201     // Upload a texture inside the query
202     glBeginQueryEXT(GL_TIME_ELAPSED_EXT, query);
203     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
204     glBindTexture(GL_TEXTURE_2D, texture);
205     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 2, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, texData.data());
206     glGenerateMipmap(GL_TEXTURE_2D);
207     glFinish();
208     glEndQueryEXT(GL_TIME_ELAPSED_EXT);
209     ASSERT_GL_NO_ERROR();
210 
211     int timeout  = 200000;
212     GLuint ready = GL_FALSE;
213     while (ready == GL_FALSE && timeout > 0)
214     {
215         angle::Sleep(0);
216         glGetQueryObjectuivEXT(query, GL_QUERY_RESULT_AVAILABLE_EXT, &ready);
217         timeout--;
218     }
219     ASSERT_LT(0, timeout) << "Query result available timed out" << std::endl;
220 
221     GLuint64 result = 0;
222     glGetQueryObjectui64vEXT(query, GL_QUERY_RESULT_EXT, &result);
223     ASSERT_GL_NO_ERROR();
224 
225     glDeleteTextures(1, &texture);
226     glDeleteQueriesEXT(1, &query);
227 
228     std::cout << "Elapsed time: " << result << std::endl;
229     EXPECT_LT(0ul, result);
230 
231     // an issue with the queries themselves.
232     EXPECT_LT(result, 1000000000ul);
233 }
234 
235 // Tests validation of query functions with respect to elapsed time query
TEST_P(TimerQueriesTest,TimeElapsedValidationTest)236 TEST_P(TimerQueriesTest, TimeElapsedValidationTest)
237 {
238     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_disjoint_timer_query"));
239 
240     GLint queryTimeElapsedBits = 0;
241     glGetQueryivEXT(GL_TIME_ELAPSED_EXT, GL_QUERY_COUNTER_BITS_EXT, &queryTimeElapsedBits);
242     ASSERT_GL_NO_ERROR();
243 
244     std::cout << "Time elapsed counter bits: " << queryTimeElapsedBits << std::endl;
245 
246     // Skip test if the number of bits is 0
247     ANGLE_SKIP_TEST_IF(!queryTimeElapsedBits);
248 
249     GLuint query = 0;
250     glGenQueriesEXT(-1, &query);
251     EXPECT_GL_ERROR(GL_INVALID_VALUE);
252 
253     glGenQueriesEXT(1, &query);
254     EXPECT_GL_NO_ERROR();
255 
256     glBeginQueryEXT(GL_TIMESTAMP_EXT, query);
257     EXPECT_GL_ERROR(GL_INVALID_ENUM);
258 
259     glBeginQueryEXT(GL_TIME_ELAPSED_EXT, 0);
260     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
261 
262     glEndQueryEXT(GL_TIME_ELAPSED_EXT);
263     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
264 
265     glBeginQueryEXT(GL_TIME_ELAPSED_EXT, query);
266     EXPECT_GL_NO_ERROR();
267 
268     glBeginQueryEXT(GL_TIME_ELAPSED_EXT, query);
269     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
270 
271     glEndQueryEXT(GL_TIME_ELAPSED_EXT);
272     EXPECT_GL_NO_ERROR();
273 
274     glEndQueryEXT(GL_TIME_ELAPSED_EXT);
275     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
276 }
277 
278 // Tests timer queries operating under multiple EGL contexts with mid-query switching
TEST_P(TimerQueriesTest,TimeElapsedMulticontextTest)279 TEST_P(TimerQueriesTest, TimeElapsedMulticontextTest)
280 {
281     // TODO(jmadill): Figure out why this test is flaky on AMD/OpenGL.
282     // http://anglebug.com/42260520
283     ANGLE_SKIP_TEST_IF(IsAMD() && IsOpenGL());
284 
285     // TODO(anglebug.com/40096747): Failing on ARM-based Apple DTKs.
286     ANGLE_SKIP_TEST_IF(IsMac() && IsARM64() && IsDesktopOpenGL());
287 
288     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_disjoint_timer_query"));
289 
290     // Test skipped because the Vulkan backend doesn't account for (and remove) time spent in other
291     // contexts.
292     ANGLE_SKIP_TEST_IF(IsVulkan());
293 
294     GLint queryTimeElapsedBits = 0;
295     glGetQueryivEXT(GL_TIME_ELAPSED_EXT, GL_QUERY_COUNTER_BITS_EXT, &queryTimeElapsedBits);
296     ASSERT_GL_NO_ERROR();
297 
298     std::cout << "Time elapsed counter bits: " << queryTimeElapsedBits << std::endl;
299 
300     // Skip test if the number of bits is 0
301     ANGLE_SKIP_TEST_IF(!queryTimeElapsedBits);
302 
303     // Without a glClear, the first draw call on GL takes a huge amount of time when run after the
304     // D3D test on certain NVIDIA drivers
305     glDepthMask(GL_TRUE);
306     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
307 
308     EGLint contextAttributes[] = {
309         EGL_CONTEXT_MAJOR_VERSION_KHR,
310         GetParam().majorVersion,
311         EGL_CONTEXT_MINOR_VERSION_KHR,
312         GetParam().minorVersion,
313         EGL_NONE,
314     };
315 
316     EGLWindow *window = getEGLWindow();
317 
318     EGLDisplay display = window->getDisplay();
319     EGLConfig config   = window->getConfig();
320     EGLSurface surface = window->getSurface();
321 
322     struct ContextInfo
323     {
324         EGLContext context;
325         GLuint program;
326         GLuint query;
327         EGLDisplay display;
328 
329         ContextInfo() : context(EGL_NO_CONTEXT), program(0), query(0), display(EGL_NO_DISPLAY) {}
330 
331         ~ContextInfo()
332         {
333             if (context != EGL_NO_CONTEXT && display != EGL_NO_DISPLAY)
334             {
335                 eglDestroyContext(display, context);
336             }
337         }
338     };
339     ContextInfo contexts[2];
340 
341     constexpr char kCostlyVS[] =
342         "attribute highp vec4 position; varying highp vec4 testPos; void main(void)\n"
343         "{\n"
344         "    testPos     = position;\n"
345         "    gl_Position = position;\n"
346         "}\n";
347 
348     constexpr char kCostlyFS[] =
349         "precision highp float; varying highp vec4 testPos; void main(void)\n"
350         "{\n"
351         "    vec4 test = testPos;\n"
352         "    for (int i = 0; i < 500; i++)\n"
353         "    {\n"
354         "        test = sqrt(test);\n"
355         "    }\n"
356         "    gl_FragColor = test;\n"
357         "}\n";
358 
359     // Setup the first context with a cheap shader
360     contexts[0].context = eglCreateContext(display, config, EGL_NO_CONTEXT, contextAttributes);
361     contexts[0].display = display;
362     ASSERT_NE(contexts[0].context, EGL_NO_CONTEXT);
363     eglMakeCurrent(display, surface, surface, contexts[0].context);
364     contexts[0].program = CompileProgram(essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
365     glGenQueriesEXT(1, &contexts[0].query);
366     ASSERT_GL_NO_ERROR();
367 
368     // Setup the second context with an expensive shader
369     contexts[1].context = eglCreateContext(display, config, EGL_NO_CONTEXT, contextAttributes);
370     contexts[1].display = display;
371     ASSERT_NE(contexts[1].context, EGL_NO_CONTEXT);
372     eglMakeCurrent(display, surface, surface, contexts[1].context);
373     contexts[1].program = CompileProgram(kCostlyVS, kCostlyFS);
374     glGenQueriesEXT(1, &contexts[1].query);
375     ASSERT_GL_NO_ERROR();
376 
377     // Start the query and draw a quad on the first context without ending the query
378     eglMakeCurrent(display, surface, surface, contexts[0].context);
379     glBeginQueryEXT(GL_TIME_ELAPSED_EXT, contexts[0].query);
380     drawQuad(contexts[0].program, essl1_shaders::PositionAttrib(), 0.8f);
381     ASSERT_GL_NO_ERROR();
382 
383     // Switch contexts, draw the expensive quad and end its query
384     eglMakeCurrent(display, surface, surface, contexts[1].context);
385     glBeginQueryEXT(GL_TIME_ELAPSED_EXT, contexts[1].query);
386     drawQuad(contexts[1].program, "position", 0.8f);
387     glEndQueryEXT(GL_TIME_ELAPSED_EXT);
388     ASSERT_GL_NO_ERROR();
389 
390     // Go back to the first context, end its query, and get the result
391     eglMakeCurrent(display, surface, surface, contexts[0].context);
392     glEndQueryEXT(GL_TIME_ELAPSED_EXT);
393 
394     GLuint64 result1 = 0;
395     GLuint64 result2 = 0;
396     glGetQueryObjectui64vEXT(contexts[0].query, GL_QUERY_RESULT_EXT, &result1);
397     glDeleteQueriesEXT(1, &contexts[0].query);
398     glDeleteProgram(contexts[0].program);
399     ASSERT_GL_NO_ERROR();
400 
401     // Get the 2nd context's results
402     eglMakeCurrent(display, surface, surface, contexts[1].context);
403     glGetQueryObjectui64vEXT(contexts[1].query, GL_QUERY_RESULT_EXT, &result2);
404     glDeleteQueriesEXT(1, &contexts[1].query);
405     glDeleteProgram(contexts[1].program);
406     ASSERT_GL_NO_ERROR();
407 
408     // Switch back to main context
409     eglMakeCurrent(display, surface, surface, window->getContext());
410 
411     // Compare the results. The cheap quad should be smaller than the expensive one if
412     // virtualization is working correctly
413     std::cout << "Elapsed time: " << result1 << " cheap quad" << std::endl;
414     std::cout << "Elapsed time: " << result2 << " costly quad" << std::endl;
415     EXPECT_LT(0ul, result1);
416     EXPECT_LT(0ul, result2);
417     EXPECT_LT(result1, 1000000000ul);
418     EXPECT_LT(result2, 1000000000ul);
419 
420     // This check can never really be non-flaky. http://anglebug.com/42263737
421     // EXPECT_LT(result1, result2);
422 }
423 
424 // Tests GPU timestamp functionality
TEST_P(TimerQueriesTest,Timestamp)425 TEST_P(TimerQueriesTest, Timestamp)
426 {
427     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_disjoint_timer_query"));
428 
429     GLint queryTimestampBits = 0;
430     glGetQueryivEXT(GL_TIMESTAMP_EXT, GL_QUERY_COUNTER_BITS_EXT, &queryTimestampBits);
431     ASSERT_GL_NO_ERROR();
432 
433     std::cout << "Timestamp counter bits: " << queryTimestampBits << std::endl;
434 
435     // Macs for some reason return 0 bits so skip the test for now if either are 0
436     ANGLE_SKIP_TEST_IF(!queryTimestampBits);
437 
438     glDepthMask(GL_TRUE);
439     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
440 
441     GLuint query1 = 0;
442     GLuint query2 = 0;
443     glGenQueriesEXT(1, &query1);
444     glGenQueriesEXT(1, &query2);
445     glQueryCounterEXT(query1, GL_TIMESTAMP_EXT);
446     drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.8f);
447     glQueryCounterEXT(query2, GL_TIMESTAMP_EXT);
448 
449     ASSERT_GL_NO_ERROR();
450 
451     swapBuffers();
452 
453     int timeout  = 200000;
454     GLuint ready = GL_FALSE;
455     while (ready == GL_FALSE && timeout > 0)
456     {
457         angle::Sleep(0);
458         glGetQueryObjectuivEXT(query1, GL_QUERY_RESULT_AVAILABLE_EXT, &ready);
459         timeout--;
460     }
461     ready = GL_FALSE;
462     while (ready == GL_FALSE && timeout > 0)
463     {
464         angle::Sleep(0);
465         glGetQueryObjectuivEXT(query2, GL_QUERY_RESULT_AVAILABLE_EXT, &ready);
466         timeout--;
467     }
468     ASSERT_LT(0, timeout) << "Query result available timed out" << std::endl;
469 
470     GLuint64 result1 = 0;
471     GLuint64 result2 = 0;
472     glGetQueryObjectui64vEXT(query1, GL_QUERY_RESULT_EXT, &result1);
473     glGetQueryObjectui64vEXT(query2, GL_QUERY_RESULT_EXT, &result2);
474 
475     ASSERT_GL_NO_ERROR();
476 
477     glDeleteQueriesEXT(1, &query1);
478     glDeleteQueriesEXT(1, &query2);
479 
480     std::cout << "Timestamps: " << result1 << " " << result2 << std::endl;
481     EXPECT_LT(0ul, result1);
482     EXPECT_LT(0ul, result2);
483     EXPECT_LT(result1, result2);
484 }
485 
getQueryResult(GLuint queryObjectName,GLuint64 * result)486 void getQueryResult(GLuint queryObjectName, GLuint64 *result)
487 {
488     GLuint queryResult = GL_FALSE;
489     while (queryResult != GL_TRUE)
490     {
491         glGetQueryObjectuivEXT(queryObjectName, GL_QUERY_RESULT_AVAILABLE, &queryResult);
492         ASSERT_GL_NO_ERROR();
493         angle::Sleep(50);
494     }
495     glGetQueryObjectui64vEXT(queryObjectName, GL_QUERY_RESULT_EXT, result);
496 }
497 
498 class TimerstampQueriesTest : public TimerQueriesTest
499 {};
500 
501 // Tests getting timestamps via glGetQueryObjectui64vEXT
TEST_P(TimerstampQueriesTest,TimestampBasic)502 TEST_P(TimerstampQueriesTest, TimestampBasic)
503 {
504     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_disjoint_timer_query"));
505     ANGLE_SKIP_TEST_IF(!IsD3D11() || !IsWindows());
506     GLint queryTimestampBits = 0;
507     glGetQueryivEXT(GL_TIMESTAMP_EXT, GL_QUERY_COUNTER_BITS_EXT, &queryTimestampBits);
508     ASSERT_GL_NO_ERROR();
509     std::cout << "Timestamp counter bits: " << queryTimestampBits << std::endl;
510 
511     GLQuery queryObject1, queryObject2;
512     glQueryCounterEXT(queryObject1, GL_TIMESTAMP_EXT);
513     ASSERT_GL_NO_ERROR();
514     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
515     drawQuad(mProgramCostly, "position", 0.8f);
516     glQueryCounterEXT(queryObject2, GL_TIMESTAMP_EXT);
517     ASSERT_GL_NO_ERROR();
518 
519     GLuint64 result1 = 0;
520     getQueryResult(queryObject1, &result1);
521 
522     GLuint64 result2 = 0;
523     getQueryResult(queryObject2, &result2);
524     std::cout << "Timestamps: " << result1 << " " << result2 << std::endl;
525     if (queryTimestampBits != 0)
526     {
527         ASSERT_TRUE(result1 != 0 && result2 > result1);
528     }
529 }
530 
531 class TimerQueriesTestES3 : public TimerQueriesTest
532 {};
533 
534 // Tests getting timestamps via glGetInteger64v
TEST_P(TimerQueriesTestES3,TimestampGetInteger64)535 TEST_P(TimerQueriesTestES3, TimestampGetInteger64)
536 {
537     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_disjoint_timer_query"));
538     // http://anglebug.com/40096654
539     ANGLE_SKIP_TEST_IF(IsAndroid());
540 
541     GLint queryTimestampBits = 0;
542     glGetQueryivEXT(GL_TIMESTAMP_EXT, GL_QUERY_COUNTER_BITS_EXT, &queryTimestampBits);
543     ASSERT_GL_NO_ERROR();
544 
545     std::cout << "Timestamp counter bits: " << queryTimestampBits << std::endl;
546 
547     ANGLE_SKIP_TEST_IF(!queryTimestampBits);
548 
549     glDepthMask(GL_TRUE);
550     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
551 
552     GLint64 result1 = 0;
553     GLint64 result2 = 0;
554     glGetInteger64v(GL_TIMESTAMP_EXT, &result1);
555     drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.8f);
556     glGetInteger64v(GL_TIMESTAMP_EXT, &result2);
557     ASSERT_GL_NO_ERROR();
558     std::cout << "Timestamps (getInteger64v): " << result1 << " " << result2 << std::endl;
559     EXPECT_LT(0l, result1);
560     EXPECT_LT(0l, result2);
561     EXPECT_LT(result1, result2);
562 }
563 
564 ANGLE_INSTANTIATE_TEST_ES2_AND(TimerstampQueriesTest,
565                                ES3_D3D11().disable(Feature::EnableTimestampQueries),
566                                ES3_D3D11().enable(Feature::EnableTimestampQueries));
567 
568 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TimestampQueriesTest);
569 
570 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(TimerQueriesTest);
571 
572 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TimerQueriesTestES3);
573 ANGLE_INSTANTIATE_TEST_ES3(TimerQueriesTestES3);
574