xref: /aosp_15_r20/external/angle/src/tests/gl_tests/OcclusionQueriesTest.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
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