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