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 #include "test_utils/ANGLETest.h"
8 #include "test_utils/gl_raii.h"
9 #include "util/EGLWindow.h"
10 #include "util/random_utils.h"
11 #include "util/test_utils.h"
12
13 using namespace angle;
14
15 class OcclusionQueriesTest : public ANGLETest<>
16 {
17 protected:
OcclusionQueriesTest()18 OcclusionQueriesTest() : mProgram(0), mRNG(1)
19 {
20 setWindowWidth(128);
21 setWindowHeight(128);
22 setConfigRedBits(8);
23 setConfigGreenBits(8);
24 setConfigBlueBits(8);
25 setConfigAlphaBits(8);
26 setConfigDepthBits(24);
27 }
28
testSetUp()29 void testSetUp() override
30 {
31 mProgram = CompileProgram(essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
32 ASSERT_NE(0u, mProgram);
33 }
34
testTearDown()35 void testTearDown() override { glDeleteProgram(mProgram); }
36
37 GLuint mProgram;
38 RNG mRNG;
39 };
40
41 class OcclusionQueriesTestES3 : public OcclusionQueriesTest
42 {};
43
TEST_P(OcclusionQueriesTest,IsOccluded)44 TEST_P(OcclusionQueriesTest, IsOccluded)
45 {
46 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 &&
47 !IsGLExtensionEnabled("GL_EXT_occlusion_query_boolean"));
48
49 glDepthMask(GL_TRUE);
50 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
51
52 // draw a quad at depth 0.3
53 glEnable(GL_DEPTH_TEST);
54 glUseProgram(mProgram);
55 drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.3f);
56 glUseProgram(0);
57
58 EXPECT_GL_NO_ERROR();
59
60 GLQueryEXT query;
61 glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, query);
62 drawQuad(mProgram, essl1_shaders::PositionAttrib(),
63 0.8f); // this quad should be occluded by first quad
64 glEndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT);
65
66 EXPECT_GL_NO_ERROR();
67
68 swapBuffers();
69
70 GLuint ready = GL_FALSE;
71 while (ready == GL_FALSE)
72 {
73 angle::Sleep(0);
74 glGetQueryObjectuivEXT(query, GL_QUERY_RESULT_AVAILABLE_EXT, &ready);
75 }
76
77 GLuint result = GL_TRUE;
78 glGetQueryObjectuivEXT(query, GL_QUERY_RESULT_EXT, &result);
79
80 EXPECT_GL_NO_ERROR();
81
82 EXPECT_GL_FALSE(result);
83 }
84
TEST_P(OcclusionQueriesTest,IsNotOccluded)85 TEST_P(OcclusionQueriesTest, IsNotOccluded)
86 {
87 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 &&
88 !IsGLExtensionEnabled("GL_EXT_occlusion_query_boolean"));
89
90 glDepthMask(GL_TRUE);
91 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
92
93 EXPECT_GL_NO_ERROR();
94
95 GLQueryEXT query;
96 glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, query);
97 drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.8f); // this quad should not be occluded
98 glEndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT);
99
100 EXPECT_GL_NO_ERROR();
101
102 swapBuffers();
103
104 GLuint result = GL_TRUE;
105 glGetQueryObjectuivEXT(query, GL_QUERY_RESULT_EXT, &result); // will block waiting for result
106
107 EXPECT_GL_NO_ERROR();
108
109 EXPECT_GL_TRUE(result);
110 }
111
112 // Test that glClear should not be counted by occlusion query.
TEST_P(OcclusionQueriesTest,ClearNotCounted)113 TEST_P(OcclusionQueriesTest, ClearNotCounted)
114 {
115 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 &&
116 !IsGLExtensionEnabled("GL_EXT_occlusion_query_boolean"));
117
118 // http://anglebug.com/42263499
119 ANGLE_SKIP_TEST_IF(IsD3D11());
120
121 glDepthMask(GL_TRUE);
122 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
123
124 EXPECT_GL_NO_ERROR();
125
126 GLQueryEXT query[2];
127
128 // First query
129 glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, query[0]);
130 // Full screen clear
131 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
132
133 // View port clear
134 glViewport(0, 0, getWindowWidth() / 2, getWindowHeight());
135 glScissor(0, 0, getWindowWidth() / 2, getWindowHeight());
136 glEnable(GL_SCISSOR_TEST);
137 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
138
139 glEndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT);
140
141 EXPECT_GL_NO_ERROR();
142
143 // Second query
144 glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, query[1]);
145
146 // View port clear
147 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
148
149 // View port clear
150 glViewport(0, 0, getWindowWidth() / 2, getWindowHeight());
151 glScissor(0, 0, getWindowWidth() / 2, getWindowHeight());
152 glEnable(GL_SCISSOR_TEST);
153 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
154
155 // this quad should not be occluded
156 drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.8f, 0.5f);
157
158 // Clear again
159 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
160
161 // this quad should not be occluded
162 drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.8f, 1.0);
163
164 glEndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT);
165
166 EXPECT_GL_NO_ERROR();
167
168 swapBuffers();
169
170 GLuint result[2] = {GL_TRUE, GL_TRUE};
171 glGetQueryObjectuivEXT(query[0], GL_QUERY_RESULT_EXT,
172 &result[0]); // will block waiting for result
173 glGetQueryObjectuivEXT(query[1], GL_QUERY_RESULT_EXT,
174 &result[1]); // will block waiting for result
175 EXPECT_GL_NO_ERROR();
176
177 EXPECT_GL_FALSE(result[0]);
178 EXPECT_GL_TRUE(result[1]);
179 }
180
181 // Test that masked glClear should not be counted by occlusion query.
TEST_P(OcclusionQueriesTest,MaskedClearNotCounted)182 TEST_P(OcclusionQueriesTest, MaskedClearNotCounted)
183 {
184 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 &&
185 !IsGLExtensionEnabled("GL_EXT_occlusion_query_boolean"));
186
187 // http://anglebug.com/42263499
188 ANGLE_SKIP_TEST_IF(IsD3D());
189
190 GLQueryEXT query;
191
192 // Masked clear
193 glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, query);
194 glColorMask(GL_TRUE, GL_FALSE, GL_TRUE, GL_TRUE);
195 glClear(GL_COLOR_BUFFER_BIT);
196 glEndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT);
197 EXPECT_GL_NO_ERROR();
198
199 swapBuffers();
200
201 GLuint result = GL_TRUE;
202 glGetQueryObjectuivEXT(query, GL_QUERY_RESULT_EXT,
203 &result); // will block waiting for result
204 EXPECT_GL_NO_ERROR();
205
206 EXPECT_GL_FALSE(result);
207 }
208
209 // Test that copies should not be counted by occlusion query.
TEST_P(OcclusionQueriesTest,CopyNotCounted)210 TEST_P(OcclusionQueriesTest, CopyNotCounted)
211 {
212 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 &&
213 !IsGLExtensionEnabled("GL_EXT_occlusion_query_boolean"));
214
215 // http://anglebug.com/42263499
216 ANGLE_SKIP_TEST_IF(IsD3D());
217
218 GLQueryEXT query;
219
220 // Unrelated draw before the query starts.
221 drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.8f, 0.5f);
222
223 // Copy to a texture with a different format from backbuffer
224 glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, query);
225 GLTexture tex;
226 glBindTexture(GL_TEXTURE_2D, tex);
227 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, getWindowWidth(), getWindowHeight(), 0);
228 glEndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT);
229 EXPECT_GL_NO_ERROR();
230
231 swapBuffers();
232
233 GLuint result = GL_TRUE;
234 glGetQueryObjectuivEXT(query, GL_QUERY_RESULT_EXT,
235 &result); // will block waiting for result
236 EXPECT_GL_NO_ERROR();
237
238 EXPECT_GL_FALSE(result);
239 }
240
241 // Test that blit should not be counted by occlusion query.
TEST_P(OcclusionQueriesTestES3,BlitNotCounted)242 TEST_P(OcclusionQueriesTestES3, BlitNotCounted)
243 {
244 // http://anglebug.com/42263499
245 ANGLE_SKIP_TEST_IF(IsD3D11());
246
247 // http://anglebug.com/42263669
248 ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsVulkan());
249
250 constexpr GLuint kSize = 64;
251
252 GLFramebuffer srcFbo;
253 glBindFramebuffer(GL_FRAMEBUFFER, srcFbo);
254
255 GLTexture srcTex;
256 glBindTexture(GL_TEXTURE_2D, srcTex);
257 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
258 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, srcTex, 0);
259
260 GLFramebuffer dstFbo;
261 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, dstFbo);
262
263 GLTexture dstTex;
264 glBindTexture(GL_TEXTURE_2D, dstTex);
265 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, kSize, kSize, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
266 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, dstTex, 0);
267
268 GLQueryEXT query;
269
270 // Unrelated draw before the query starts.
271 drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.8f, 0.5f);
272
273 // Blit flipped and with different formats.
274 glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, query);
275 glBlitFramebuffer(0, 0, 64, 64, 64, 64, 0, 0, GL_COLOR_BUFFER_BIT, GL_LINEAR);
276 glEndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT);
277 EXPECT_GL_NO_ERROR();
278
279 swapBuffers();
280
281 GLuint result = GL_TRUE;
282 glGetQueryObjectuivEXT(query, GL_QUERY_RESULT_EXT,
283 &result); // will block waiting for result
284 EXPECT_GL_NO_ERROR();
285
286 EXPECT_GL_FALSE(result);
287 }
288
289 // Test that multisampled-render-to-texture unresolve should not be counted by occlusion query.
TEST_P(OcclusionQueriesTestES3,UnresolveNotCounted)290 TEST_P(OcclusionQueriesTestES3, UnresolveNotCounted)
291 {
292 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture"));
293
294 constexpr GLuint kSize = 64;
295
296 GLFramebuffer fboMS;
297 glBindFramebuffer(GL_FRAMEBUFFER, fboMS);
298
299 // Create multisampled framebuffer to draw into
300 GLTexture textureMS;
301 glBindTexture(GL_TEXTURE_2D, textureMS);
302 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
303 glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
304 textureMS, 0, 4);
305
306 GLRenderbuffer depthMS;
307 glBindRenderbuffer(GL_RENDERBUFFER, depthMS);
308 glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_DEPTH_COMPONENT16, kSize, kSize);
309 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthMS);
310
311 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
312
313 // Draw red into the multisampled color buffer.
314 drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.5f);
315 ASSERT_GL_NO_ERROR();
316
317 // Create a texture and copy into it, forcing a resolve of the color buffer.
318 GLTexture texture;
319 glBindTexture(GL_TEXTURE_2D, texture);
320 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, kSize, kSize, 0);
321
322 GLQueryEXT query;
323
324 // Make a draw call that will fail the depth test, and therefore shouldn't contribute to
325 // occlusion query.
326 glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, query);
327 glEnable(GL_DEPTH_TEST);
328 glDepthFunc(GL_NEVER);
329 drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.8f, 0.5f);
330 glEndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT);
331 EXPECT_GL_NO_ERROR();
332
333 swapBuffers();
334
335 GLuint result = GL_TRUE;
336 glGetQueryObjectuivEXT(query, GL_QUERY_RESULT_EXT,
337 &result); // will block waiting for result
338 EXPECT_GL_NO_ERROR();
339
340 EXPECT_GL_FALSE(result);
341 }
342
343 // Test that reusing a query should reset its value to zero if no draw calls are emitted in the
344 // second pass.
TEST_P(OcclusionQueriesTest,RewriteDrawNoDrawToZero)345 TEST_P(OcclusionQueriesTest, RewriteDrawNoDrawToZero)
346 {
347 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 &&
348 !IsGLExtensionEnabled("GL_EXT_occlusion_query_boolean"));
349
350 GLQueryEXT query;
351 glDepthMask(GL_TRUE);
352 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
353
354 // draw a quad at depth 0.3
355 glEnable(GL_DEPTH_TEST);
356 glUseProgram(mProgram);
357 glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, query);
358 drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.3f);
359 glEndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT);
360 glUseProgram(0);
361
362 EXPECT_GL_NO_ERROR();
363
364 glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, query);
365 glEndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT);
366
367 EXPECT_GL_NO_ERROR();
368
369 swapBuffers();
370
371 GLuint ready = GL_FALSE;
372 while (ready == GL_FALSE)
373 {
374 angle::Sleep(0);
375 glGetQueryObjectuivEXT(query, GL_QUERY_RESULT_AVAILABLE_EXT, &ready);
376 }
377
378 GLuint result = GL_TRUE;
379 glGetQueryObjectuivEXT(query, GL_QUERY_RESULT_EXT, &result);
380
381 EXPECT_GL_NO_ERROR();
382
383 EXPECT_GL_FALSE(result);
384 }
385
386 // Test that changing framebuffers work
TEST_P(OcclusionQueriesTest,FramebufferBindingChange)387 TEST_P(OcclusionQueriesTest, FramebufferBindingChange)
388 {
389 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 &&
390 !IsGLExtensionEnabled("GL_EXT_occlusion_query_boolean"));
391
392 constexpr GLsizei kSize = 4;
393
394 // Create two framebuffers, and make sure they are synced.
395 GLFramebuffer fbo[2];
396 GLTexture color[2];
397
398 for (size_t index = 0; index < 2; ++index)
399 {
400 glBindTexture(GL_TEXTURE_2D, color[index]);
401 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
402 nullptr);
403
404 glBindFramebuffer(GL_FRAMEBUFFER, fbo[index]);
405 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color[index],
406 0);
407
408 glClearColor(0, index, 1 - index, 1);
409 glClear(GL_COLOR_BUFFER_BIT);
410
411 EXPECT_PIXEL_COLOR_EQ(0, 0, index ? GLColor::green : GLColor::blue);
412 }
413 EXPECT_GL_NO_ERROR();
414
415 glViewport(0, 0, kSize, kSize);
416
417 // Start an occlusion query and issue a draw call to each framebuffer.
418 GLQueryEXT query;
419
420 glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, query);
421
422 for (size_t index = 0; index < 2; ++index)
423 {
424 glBindFramebuffer(GL_FRAMEBUFFER, fbo[index]);
425 drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.5f);
426 }
427
428 glEndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT);
429 EXPECT_GL_NO_ERROR();
430
431 GLuint result = GL_FALSE;
432 glGetQueryObjectuivEXT(query, GL_QUERY_RESULT_EXT, &result);
433 EXPECT_GL_NO_ERROR();
434
435 EXPECT_GL_TRUE(result);
436 }
437
438 // Test that switching framebuffers without actually drawing, then issuing a masked clear while a
439 // query is active works.
TEST_P(OcclusionQueriesTestES3,SwitchFramebuffersThenMaskedClear)440 TEST_P(OcclusionQueriesTestES3, SwitchFramebuffersThenMaskedClear)
441 {
442 constexpr GLint kSize = 10;
443
444 GLFramebuffer fbo1, fbo2;
445 GLRenderbuffer rbo1, rbo2;
446
447 // Set up two framebuffers
448 glBindRenderbuffer(GL_RENDERBUFFER, rbo1);
449 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8_OES, kSize, kSize);
450
451 glBindFramebuffer(GL_FRAMEBUFFER, fbo1);
452 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo1);
453
454 glBindRenderbuffer(GL_RENDERBUFFER, rbo2);
455 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8_OES, kSize, kSize);
456
457 glBindFramebuffer(GL_FRAMEBUFFER, fbo2);
458 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo2);
459
460 // Start render pass on fbo1
461 glBindFramebuffer(GL_FRAMEBUFFER, fbo1);
462 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
463 drawQuad(program, essl1_shaders::PositionAttrib(), 0);
464
465 // Begin a query
466 GLQuery query;
467 glBeginQuery(GL_ANY_SAMPLES_PASSED, query);
468
469 // Switch to another render pass and clear. In the Vulkan backend, this clear is deferred, so
470 // while the framebuffer binding is synced, the previous render pass is not necessarily closed.
471 glBindFramebuffer(GL_FRAMEBUFFER, fbo2);
472 glClear(GL_STENCIL_BUFFER_BIT);
473
474 // Switch back to the original render pass and issue a masked stencil clear. In the Vulkan
475 // backend, this is done with a draw call.
476 glBindFramebuffer(GL_FRAMEBUFFER, fbo1);
477 glStencilMask(0xAA);
478 glClearStencil(0xF4);
479 glClear(GL_STENCIL_BUFFER_BIT);
480
481 // Verify the clear worked.
482 GLRenderbuffer color;
483 glBindRenderbuffer(GL_RENDERBUFFER, color);
484 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, kSize, kSize);
485 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, color);
486
487 glEnable(GL_STENCIL_TEST);
488 glStencilFunc(GL_ALWAYS, 0xA4, 0xFF);
489 glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
490 glStencilMask(0xFF);
491
492 glClear(GL_COLOR_BUFFER_BIT);
493 drawQuad(program, essl1_shaders::PositionAttrib(), 0);
494
495 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
496 ASSERT_GL_NO_ERROR();
497 }
498
499 // Test that an empty query after a positive query returns false
TEST_P(OcclusionQueriesTest,EmptyQueryAfterCompletedQuery)500 TEST_P(OcclusionQueriesTest, EmptyQueryAfterCompletedQuery)
501 {
502 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 &&
503 !IsGLExtensionEnabled("GL_EXT_occlusion_query_boolean"));
504
505 GLQueryEXT query;
506
507 glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, query);
508 drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.5f);
509 glEndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT);
510 ASSERT_GL_NO_ERROR();
511
512 GLuint result = GL_FALSE;
513 glGetQueryObjectuivEXT(query, GL_QUERY_RESULT_EXT, &result);
514 ASSERT_GL_NO_ERROR();
515 EXPECT_TRUE(result);
516
517 glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, query);
518 glEndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT);
519 ASSERT_GL_NO_ERROR();
520
521 result = GL_FALSE;
522 glGetQueryObjectuivEXT(query, GL_QUERY_RESULT_EXT, &result);
523 ASSERT_GL_NO_ERROR();
524 EXPECT_FALSE(result);
525 }
526
527 // Some Metal drivers do not automatically clear visibility buffer
528 // at the beginning of a render pass. This test makes two queries
529 // that would use the same internal visibility buffer at the same
530 // offset and checks the query results.
TEST_P(OcclusionQueriesTest,EmptyQueryAfterCompletedQueryInterleaved)531 TEST_P(OcclusionQueriesTest, EmptyQueryAfterCompletedQueryInterleaved)
532 {
533 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 &&
534 !IsGLExtensionEnabled("GL_EXT_occlusion_query_boolean"));
535
536 GLQueryEXT query;
537
538 // Make a draw call to start a new render pass
539 drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.0f);
540
541 // Begin a query and make another draw call
542 glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, query);
543 drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.0f);
544 glEndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT);
545
546 // Check the query result to end command encoding
547 GLuint result = GL_FALSE;
548 glGetQueryObjectuivEXT(query, GL_QUERY_RESULT_EXT, &result);
549 EXPECT_TRUE(result);
550 ASSERT_GL_NO_ERROR();
551
552 // Make a draw call to start a new render pass
553 drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.0f);
554
555 // Begin and immediately resolve a new query; it must return false
556 result = GL_FALSE;
557 glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, query);
558 glEndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT);
559 glGetQueryObjectuivEXT(query, GL_QUERY_RESULT_EXT, &result);
560 EXPECT_FALSE(result);
561 ASSERT_GL_NO_ERROR();
562 }
563
564 // Test multiple occlusion queries.
TEST_P(OcclusionQueriesTest,MultiQueries)565 TEST_P(OcclusionQueriesTest, MultiQueries)
566 {
567 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 &&
568 !IsGLExtensionEnabled("GL_EXT_occlusion_query_boolean"));
569
570 // http://anglebug.com/42263499
571 ANGLE_SKIP_TEST_IF(IsOpenGL() || IsD3D11());
572
573 // TODO(anglebug.com/40096747): Failing on ARM-based Apple DTKs.
574 ANGLE_SKIP_TEST_IF(IsMac() && IsARM64() && IsDesktopOpenGL());
575
576 GLQueryEXT query[5];
577
578 // First query
579 glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, query[0]);
580
581 EXPECT_GL_NO_ERROR();
582
583 glEnable(GL_DEPTH_TEST);
584 glDepthMask(GL_TRUE);
585 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
586
587 EXPECT_GL_NO_ERROR();
588
589 drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.8f); // this quad should not be occluded
590
591 EXPECT_GL_NO_ERROR();
592
593 // Due to implementation might skip in-renderpass flush, we are using glFinish here to force a
594 // flush. A flush shound't clear the query result.
595 glFinish();
596
597 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
598 drawQuad(mProgram, essl1_shaders::PositionAttrib(), -2, 0.25f); // this quad should be occluded
599 glEndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT);
600 // First query ends
601
602 drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.8f,
603 0.25f); // this quad should not be occluded
604
605 // Second query
606 glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, query[1]);
607 drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.9f,
608 0.25f); // this quad should be occluded
609 glEndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT);
610
611 // Third query
612 glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, query[2]);
613 drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.9f,
614 0.5f); // this quad should not be occluded
615 glEndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT);
616 // ------------
617 glFinish();
618
619 glViewport(0, 0, getWindowWidth() / 2, getWindowHeight());
620 glScissor(0, 0, getWindowWidth() / 2, getWindowHeight());
621 glEnable(GL_SCISSOR_TEST);
622 drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.9f,
623 0.5f); // this quad should not be occluded
624
625 // Fourth query: begin query then end then begin again
626 glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, query[3]);
627 drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.9f,
628 1); // this quad should not be occluded
629 glEndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT);
630 glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, query[3]);
631 EXPECT_GL_NO_ERROR();
632 // glClear should not be counted toward query);
633 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
634 glEndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT);
635
636 // Fifth query spans across frames
637 glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, query[4]);
638 drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.8f,
639 0.25f); // this quad should not be occluded
640
641 swapBuffers();
642
643 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
644
645 drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.9f,
646 0.5f); // this quad should not be occluded
647 glEndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT);
648
649 GLuint result = GL_TRUE;
650 glGetQueryObjectuivEXT(query[0], GL_QUERY_RESULT_EXT,
651 &result); // will block waiting for result
652 EXPECT_GL_NO_ERROR();
653 EXPECT_GL_TRUE(result);
654
655 glGetQueryObjectuivEXT(query[1], GL_QUERY_RESULT_EXT,
656 &result); // will block waiting for result
657 EXPECT_GL_NO_ERROR();
658 EXPECT_GL_FALSE(result);
659
660 glGetQueryObjectuivEXT(query[2], GL_QUERY_RESULT_EXT,
661 &result); // will block waiting for result
662 EXPECT_GL_NO_ERROR();
663 EXPECT_GL_TRUE(result);
664
665 glGetQueryObjectuivEXT(query[3], GL_QUERY_RESULT_EXT,
666 &result); // will block waiting for result
667 EXPECT_GL_NO_ERROR();
668 EXPECT_GL_FALSE(result);
669
670 glGetQueryObjectuivEXT(query[4], GL_QUERY_RESULT_EXT,
671 &result); // will block waiting for result
672 EXPECT_GL_NO_ERROR();
673 EXPECT_GL_TRUE(result);
674 }
675
TEST_P(OcclusionQueriesTest,Errors)676 TEST_P(OcclusionQueriesTest, Errors)
677 {
678 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 &&
679 !IsGLExtensionEnabled("GL_EXT_occlusion_query_boolean"));
680
681 glDepthMask(GL_TRUE);
682 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
683
684 EXPECT_GL_NO_ERROR();
685
686 GLuint query = 0;
687 GLuint query2 = 0;
688 glGenQueriesEXT(1, &query);
689
690 EXPECT_GL_FALSE(glIsQueryEXT(query));
691 EXPECT_GL_FALSE(glIsQueryEXT(query2));
692
693 glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, 0); // can't pass 0 as query id
694 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
695
696 glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, query);
697 glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
698 query2); // can't initiate a query while one's already active
699 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
700
701 EXPECT_GL_TRUE(glIsQueryEXT(query));
702 EXPECT_GL_FALSE(glIsQueryEXT(query2)); // have not called begin
703
704 drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.8f); // this quad should not be occluded
705 glEndQueryEXT(GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT); // no active query for this target
706 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
707 glEndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT);
708
709 glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
710 query); // can't begin a query as a different type than previously used
711 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
712
713 glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
714 query2); // have to call genqueries first
715 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
716
717 glGenQueriesEXT(1, &query2);
718 glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, query2); // should be ok now
719 EXPECT_GL_TRUE(glIsQueryEXT(query2));
720
721 drawQuad(mProgram, essl1_shaders::PositionAttrib(),
722 0.3f); // this should draw in front of other quad
723 glDeleteQueriesEXT(1, &query2); // should delete when query becomes inactive
724 glEndQueryEXT(GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT); // should not incur error; should delete
725 // query + 1 at end of execution.
726 EXPECT_GL_NO_ERROR();
727
728 swapBuffers();
729
730 EXPECT_GL_NO_ERROR();
731
732 GLuint ready = GL_FALSE;
733 glGetQueryObjectuivEXT(query2, GL_QUERY_RESULT_AVAILABLE_EXT,
734 &ready); // this query is now deleted
735 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
736
737 EXPECT_GL_NO_ERROR();
738 }
739
740 // Test that running multiple simultaneous queries from multiple EGL contexts returns the correct
741 // result for each query. Helps expose bugs in ANGLE's virtual contexts.
TEST_P(OcclusionQueriesTest,MultiContext)742 TEST_P(OcclusionQueriesTest, MultiContext)
743 {
744 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 &&
745 !IsGLExtensionEnabled("GL_EXT_occlusion_query_boolean"));
746
747 // TODO([email protected]): Suppression for http://anglebug.com/42261759
748 ANGLE_SKIP_TEST_IF(IsWindows() && IsNVIDIA() && IsVulkan());
749
750 // Test skipped because the D3D backends cannot support simultaneous queries on multiple
751 // contexts yet.
752 ANGLE_SKIP_TEST_IF(GetParam() == ES2_D3D9() || GetParam() == ES2_D3D11() ||
753 GetParam() == ES3_D3D11());
754
755 glDepthMask(GL_TRUE);
756 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
757
758 // draw a quad at depth 0.5
759 glEnable(GL_DEPTH_TEST);
760 drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.5f);
761
762 EGLWindow *window = getEGLWindow();
763
764 EGLDisplay display = window->getDisplay();
765 EGLConfig config = window->getConfig();
766 EGLSurface surface = window->getSurface();
767
768 EGLint contextAttributes[] = {
769 EGL_CONTEXT_MAJOR_VERSION_KHR,
770 GetParam().majorVersion,
771 EGL_CONTEXT_MINOR_VERSION_KHR,
772 GetParam().minorVersion,
773 EGL_NONE,
774 };
775
776 const size_t passCount = 5;
777 struct ContextInfo
778 {
779 EGLContext context;
780 GLuint program;
781 GLuint query;
782 bool visiblePasses[passCount];
783 bool shouldPass;
784 };
785
786 ContextInfo contexts[] = {
787 {
788 EGL_NO_CONTEXT,
789 0,
790 0,
791 {false, false, false, false, false},
792 false,
793 },
794 {
795 EGL_NO_CONTEXT,
796 0,
797 0,
798 {false, true, false, true, false},
799 true,
800 },
801 {
802 EGL_NO_CONTEXT,
803 0,
804 0,
805 {false, false, false, false, false},
806 false,
807 },
808 {
809 EGL_NO_CONTEXT,
810 0,
811 0,
812 {true, true, false, true, true},
813 true,
814 },
815 {
816 EGL_NO_CONTEXT,
817 0,
818 0,
819 {false, true, true, true, true},
820 true,
821 },
822 {
823 EGL_NO_CONTEXT,
824 0,
825 0,
826 {true, false, false, true, false},
827 true,
828 },
829 {
830 EGL_NO_CONTEXT,
831 0,
832 0,
833 {false, false, false, false, false},
834 false,
835 },
836 {
837 EGL_NO_CONTEXT,
838 0,
839 0,
840 {false, false, false, false, false},
841 false,
842 },
843 };
844
845 for (auto &context : contexts)
846 {
847 context.context = eglCreateContext(display, config, EGL_NO_CONTEXT, contextAttributes);
848 ASSERT_NE(context.context, EGL_NO_CONTEXT);
849
850 eglMakeCurrent(display, surface, surface, context.context);
851
852 context.program = CompileProgram(essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
853 ASSERT_NE(context.program, 0u);
854
855 glDepthMask(GL_FALSE);
856 glEnable(GL_DEPTH_TEST);
857
858 glGenQueriesEXT(1, &context.query);
859 glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, context.query);
860
861 ASSERT_GL_NO_ERROR();
862 }
863
864 for (size_t pass = 0; pass < passCount; pass++)
865 {
866 for (const auto &context : contexts)
867 {
868 eglMakeCurrent(display, surface, surface, context.context);
869
870 float depth = context.visiblePasses[pass] ? mRNG.randomFloatBetween(0.0f, 0.4f)
871 : mRNG.randomFloatBetween(0.6f, 1.0f);
872 drawQuad(context.program, essl1_shaders::PositionAttrib(), depth);
873
874 EXPECT_GL_NO_ERROR();
875 }
876 }
877
878 for (const auto &context : contexts)
879 {
880 eglMakeCurrent(display, surface, surface, context.context);
881 glEndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT);
882
883 GLuint result = GL_TRUE;
884 glGetQueryObjectuivEXT(context.query, GL_QUERY_RESULT_EXT, &result);
885
886 EXPECT_GL_NO_ERROR();
887
888 GLuint expectation = context.shouldPass ? GL_TRUE : GL_FALSE;
889 EXPECT_EQ(expectation, result);
890 }
891
892 eglMakeCurrent(display, surface, surface, window->getContext());
893
894 for (auto &context : contexts)
895 {
896 eglDestroyContext(display, context.context);
897 context.context = EGL_NO_CONTEXT;
898 }
899 }
900
901 // Test multiple occlusion queries in flight. This test provoked a bug in the Metal backend that
902 // resulted in an infinite loop when trying to flush the command buffer when the maximum number of
903 // inflight render passes was reached.
TEST_P(OcclusionQueriesTest,ManyQueriesInFlight)904 TEST_P(OcclusionQueriesTest, ManyQueriesInFlight)
905 {
906 constexpr int kManyQueryCount = 100;
907
908 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 &&
909 !IsGLExtensionEnabled("GL_EXT_occlusion_query_boolean"));
910
911 // http://anglebug.com/42263499
912 ANGLE_SKIP_TEST_IF(IsOpenGL() || IsD3D11());
913
914 GLQueryEXT query;
915
916 glEnable(GL_DEPTH_TEST);
917 glDepthMask(GL_TRUE);
918 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
919
920 GLRenderbuffer rbo[2];
921 glBindRenderbuffer(GL_RENDERBUFFER, rbo[0]);
922 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 32, 32);
923 glBindRenderbuffer(GL_RENDERBUFFER, rbo[1]);
924 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, 32, 32);
925
926 GLFramebuffer fbo;
927 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
928 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo[0]);
929 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rbo[1]);
930
931 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
932
933 EXPECT_GL_NO_ERROR();
934
935 glBindFramebuffer(GL_FRAMEBUFFER, 0);
936
937 for (int i = 0; i < kManyQueryCount; i++)
938 {
939 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
940 glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, query);
941 drawQuad(mProgram, essl1_shaders::PositionAttrib(), 1.0f - 2.0f * i / kManyQueryCount);
942 glEndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT);
943
944 glBindFramebuffer(GL_FRAMEBUFFER, 0);
945 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
946 drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.8f);
947 }
948
949 glFinish();
950
951 EXPECT_GL_NO_ERROR();
952 }
953
954 class OcclusionQueriesNoSurfaceTestES3 : public ANGLETestBase,
955 public ::testing::TestWithParam<angle::PlatformParameters>
956 {
957 protected:
OcclusionQueriesNoSurfaceTestES3()958 OcclusionQueriesNoSurfaceTestES3()
959 : ANGLETestBase(GetParam()), mUnusedConfig(0), mUnusedDisplay(nullptr)
960 {
961 setWindowWidth(kWidth);
962 setWindowHeight(kHeight);
963 setConfigRedBits(8);
964 setConfigGreenBits(8);
965 setConfigBlueBits(8);
966 setConfigAlphaBits(8);
967 setDeferContextInit(true);
968 }
969
970 static constexpr int kWidth = 300;
971 static constexpr int kHeight = 300;
972
SetUp()973 void SetUp() override { ANGLETestBase::ANGLETestSetUp(); }
TearDown()974 void TearDown() override { ANGLETestBase::ANGLETestTearDown(); }
975
swapBuffers()976 void swapBuffers() override {}
977
978 EGLConfig mUnusedConfig;
979 EGLDisplay mUnusedDisplay;
980 };
981
982 // This test provked a bug in the Metal backend that only happened
983 // when there was no surfaces on the EGLContext and a query had
984 // just ended after a draw and then switching to a different
985 // context.
TEST_P(OcclusionQueriesNoSurfaceTestES3,SwitchingContextsWithQuery)986 TEST_P(OcclusionQueriesNoSurfaceTestES3, SwitchingContextsWithQuery)
987 {
988 EGLWindow *window = getEGLWindow();
989
990 EGLDisplay display = window->getDisplay();
991 EGLConfig config = window->getConfig();
992
993 EGLint contextAttributes[] = {
994 EGL_CONTEXT_MAJOR_VERSION_KHR,
995 GetParam().majorVersion,
996 EGL_CONTEXT_MINOR_VERSION_KHR,
997 GetParam().minorVersion,
998 EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE,
999 EGL_TRUE,
1000 EGL_NONE,
1001 };
1002
1003 // The following GL objects are implicitly deleted in
1004 // ContextInfo's destructor before the EGLContext is manually destroyed
1005 struct ContextInfo
1006 {
1007 EGLContext context;
1008 GLBuffer buf;
1009 GLProgram program;
1010 GLFramebuffer fb;
1011 GLTexture tex;
1012 GLQuery query;
1013 };
1014
1015 // ContextInfo contains objects that clean themselves on destruction.
1016 // We want these objects to stick around until the test ends.
1017 std::vector<ContextInfo *> pairs;
1018
1019 for (size_t i = 0; i < 2; ++i)
1020 {
1021 ContextInfo *infos[] = {
1022 new ContextInfo(),
1023 new ContextInfo(),
1024 };
1025
1026 for (ContextInfo *pinfo : infos)
1027 {
1028 pairs.push_back(pinfo);
1029 ContextInfo &info = *pinfo;
1030
1031 info.context = eglCreateContext(display, config, EGL_NO_CONTEXT, contextAttributes);
1032 ASSERT_NE(info.context, EGL_NO_CONTEXT);
1033
1034 // Make context current context with no draw and read surface.
1035 ASSERT_EGL_TRUE(eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, info.context));
1036
1037 // Create something to draw to.
1038 glBindFramebuffer(GL_FRAMEBUFFER, info.fb);
1039 glBindTexture(GL_TEXTURE_2D, info.tex);
1040 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1);
1041 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, info.tex,
1042 0);
1043 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1044
1045 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1046 EXPECT_GL_NO_ERROR();
1047 glFlush();
1048 }
1049
1050 // Setup an shader and quad buffer
1051 for (ContextInfo *pinfo : infos)
1052 {
1053 ContextInfo &info = *pinfo;
1054 ASSERT_EGL_TRUE(eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, info.context));
1055
1056 constexpr char kVS[] = R"(
1057 attribute vec4 position;
1058 void main() {
1059 gl_Position = position;
1060 }
1061 )";
1062
1063 constexpr char kFS[] = R"(
1064 precision mediump float;
1065 void main() {
1066 gl_FragColor = vec4(1, 0, 0, 1);
1067 }
1068 )";
1069
1070 info.program.makeRaster(kVS, kFS);
1071 glUseProgram(info.program);
1072
1073 constexpr float vertices[] = {
1074 -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f,
1075 };
1076 glBindBuffer(GL_ARRAY_BUFFER, info.buf);
1077 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
1078 glEnableVertexAttribArray(0);
1079 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
1080 EXPECT_GL_NO_ERROR();
1081 }
1082
1083 ContextInfo &info1 = *infos[0];
1084 ContextInfo &info2 = *infos[1];
1085
1086 ASSERT_EGL_TRUE(eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, info1.context));
1087
1088 glBeginQuery(GL_ANY_SAMPLES_PASSED_CONSERVATIVE, info1.query);
1089 glFlush();
1090
1091 ASSERT_EGL_TRUE(eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, info2.context));
1092 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1093 ASSERT_EGL_TRUE(eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, info1.context));
1094
1095 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1096
1097 glEndQuery(GL_ANY_SAMPLES_PASSED_CONSERVATIVE);
1098 EXPECT_GL_NO_ERROR();
1099
1100 ASSERT_EGL_TRUE(eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, info2.context));
1101 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1102 ASSERT_EGL_TRUE(eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, info1.context));
1103 ASSERT_EGL_TRUE(eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, info2.context));
1104 ASSERT_EGL_TRUE(eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, info1.context));
1105 }
1106
1107 // destroy GL objects on the correct context.
1108 for (ContextInfo *pinfo : pairs)
1109 {
1110 EGLContext context = pinfo->context;
1111 ASSERT_EGL_TRUE(eglMakeCurrent(display, nullptr, nullptr, context));
1112 EXPECT_GL_NO_ERROR();
1113 delete pinfo;
1114 ASSERT_EGL_TRUE(eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
1115 ASSERT_EGL_TRUE(eglDestroyContext(display, context));
1116 EXPECT_EGL_SUCCESS();
1117 }
1118 }
1119
1120 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(OcclusionQueriesTest);
1121
1122 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(OcclusionQueriesTestES3);
1123 ANGLE_INSTANTIATE_TEST_ES3_AND(
1124 OcclusionQueriesTestES3,
1125 ES3_VULKAN().enable(Feature::PreferSubmitOnAnySamplesPassedQueryEnd));
1126
1127 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(OcclusionQueriesNoSurfaceTestES3);
1128 ANGLE_INSTANTIATE_TEST_ES3(OcclusionQueriesNoSurfaceTestES3);
1129