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