xref: /aosp_15_r20/external/angle/src/tests/gl_tests/ReadOnlyFeedbackLoopTest.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1 //
2 // Copyright 2020 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 // Test that invokes a usecase where there is a feedback loop but the framebuffer
8 // depth attachment is only read from
9 
10 #include "test_utils/ANGLETest.h"
11 #include "test_utils/gl_raii.h"
12 
13 using namespace angle;
14 
15 class ReadOnlyFeedbackLoopTest : public ANGLETest<>
16 {
17   protected:
ReadOnlyFeedbackLoopTest()18     ReadOnlyFeedbackLoopTest()
19     {
20         setWindowWidth(256);
21         setWindowHeight(256);
22         setConfigRedBits(8);
23         setConfigGreenBits(8);
24         setConfigBlueBits(8);
25         setConfigAlphaBits(8);
26     }
27 
testSetUp()28     void testSetUp() override
29     {
30         glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
31         glClearDepthf(1.0f);
32         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
33         glDepthRangef(-1.0f, 1.0f);
34 
35         glEnable(GL_BLEND);
36         glDisable(GL_DEPTH_TEST);
37 
38         ASSERT_GL_NO_ERROR();
39     }
40 };
41 
42 class ReadOnlyFeedbackLoopTestES31 : public ReadOnlyFeedbackLoopTest
43 {};
44 
45 // Fill out a depth texture to specific values and use it both as a sampler and a depth texture
46 // with depth write disabled. This is to test a "read-only feedback loop" that needs to be
47 // supported to match industry standard.
TEST_P(ReadOnlyFeedbackLoopTest,DepthFeedbackLoop)48 TEST_P(ReadOnlyFeedbackLoopTest, DepthFeedbackLoop)
49 {
50     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_read_only_depth_stencil_feedback_loops"));
51 
52     const GLuint width  = getWindowWidth();
53     const GLuint height = getWindowHeight();
54 
55     GLTexture colorTex;
56     GLTexture depthTex;
57     GLTexture finalTex;
58 
59     GLFramebuffer gbufferFbo;
60     GLFramebuffer finalFbo;
61 
62     ANGLE_GL_PROGRAM(colorFillProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
63     ANGLE_GL_PROGRAM(textureFillProgram, essl1_shaders::vs::Texture2D(),
64                      essl1_shaders::fs::Texture2D());
65 
66     glBindTexture(GL_TEXTURE_2D, colorTex);
67     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
68     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
69     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
70     EXPECT_GL_NO_ERROR();
71 
72     glBindTexture(GL_TEXTURE_2D, depthTex);
73     glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, width, height, 0, GL_DEPTH_COMPONENT,
74                  GL_UNSIGNED_INT, nullptr);
75     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
76     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
77     EXPECT_GL_NO_ERROR();
78 
79     glBindFramebuffer(GL_FRAMEBUFFER, gbufferFbo);
80     EXPECT_GL_NO_ERROR();
81 
82     // Attach a color and depth texture to the FBO
83     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTex, 0);
84     EXPECT_GL_NO_ERROR();
85     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTex, 0);
86     EXPECT_GL_NO_ERROR();
87 
88     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
89 
90     // Set the color texture to blue and depth texture to 1.0f
91     glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
92     glClearDepthf(1.0f);
93     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
94     ASSERT_GL_NO_ERROR();
95 
96     // Enable Depth test with passing always to write depth.
97     glEnable(GL_DEPTH_TEST);
98     glDepthMask(GL_TRUE);
99     glDepthFunc(GL_ALWAYS);
100 
101     // Fill the middle of the depth texture with 0.0f. while the border remains 1.0f as
102     // previously cleared.
103     const GLfloat depthValue = 0.0f;
104     drawQuad(colorFillProgram, essl1_shaders::PositionAttrib(), depthValue, 0.6f);
105 
106     EXPECT_GL_NO_ERROR();
107 
108     glBindTexture(GL_TEXTURE_2D, finalTex);
109     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
110     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
111     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
112     EXPECT_GL_NO_ERROR();
113 
114     glBindFramebuffer(GL_FRAMEBUFFER, finalFbo);
115     EXPECT_GL_NO_ERROR();
116 
117     // Enable Depth test without depth write.
118     glEnable(GL_DEPTH_TEST);
119     glDepthMask(GL_FALSE);
120     glDepthFunc(GL_GREATER);
121 
122     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, finalTex, 0);
123     EXPECT_GL_NO_ERROR();
124     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTex, 0);
125     EXPECT_GL_NO_ERROR();
126     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
127 
128     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
129 
130     glBindTexture(GL_TEXTURE_2D, depthTex);
131 
132     // Fill finalTex with values read from depthTex. This should work even though depthTex
133     // is also bound as the depth attachment, because depth write is disabled.
134     // The write to finalTex only succeeds for the middle region due to depth test.
135     drawQuad(textureFillProgram, essl1_shaders::PositionAttrib(), 0.7f, 1.0f);
136 
137     // Copy finalTex to default framebuffer for verification. Depth values written in the first
138     // draw call are expected in the middle, while the clear value in the clear before the
139     // second draw call are expected at the border.
140     glBindFramebuffer(GL_FRAMEBUFFER, 0);
141     glDisable(GL_DEPTH_TEST);
142     glDepthMask(GL_FALSE);
143     glBindTexture(GL_TEXTURE_2D, finalTex);
144     drawQuad(textureFillProgram, essl1_shaders::PositionAttrib(), 0.0f, 1.0f);
145     EXPECT_GL_NO_ERROR();
146 
147     GLint depthColorValue = (depthValue)*128 + 128;
148     EXPECT_NEAR(depthColorValue, angle::ReadColor(width / 2, height / 2).R, 1);
149     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
150 }
151 
152 // Tests that we can support a feedback loop between a depth textures and the depth buffer.
153 // The test emulates the read-only feedback loop in Manhattan.
TEST_P(ReadOnlyFeedbackLoopTest,ReadOnlyDepthFeedbackLoopSupported)154 TEST_P(ReadOnlyFeedbackLoopTest, ReadOnlyDepthFeedbackLoopSupported)
155 {
156     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_read_only_depth_stencil_feedback_loops"));
157 
158     constexpr GLuint kSize = 2;
159     glViewport(0, 0, kSize, kSize);
160 
161     constexpr char kFS[] = R"(precision mediump float;
162 varying vec2 v_texCoord;
163 uniform sampler2D depth;
164 void main()
165 {
166     if (abs(texture2D(depth, v_texCoord).x - 0.5) < 0.1)
167     {
168         gl_FragColor = vec4(0, 1, 0, 1);
169     }
170     else
171     {
172         gl_FragColor = vec4(1, 0, 0, 1);
173     }
174 })";
175 
176     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), kFS);
177 
178     GLFramebuffer framebuffer;
179     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
180 
181     GLTexture colorTexture;
182     glBindTexture(GL_TEXTURE_2D, colorTexture);
183     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
184 
185     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
186     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
187     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 0);
188 
189     GLTexture depthTexture;
190     glBindTexture(GL_TEXTURE_2D, depthTexture);
191     glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, kSize, kSize, 0, GL_DEPTH_COMPONENT,
192                  GL_UNSIGNED_INT, nullptr);
193     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
194     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
195     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTexture, 0);
196 
197     ASSERT_GL_NO_ERROR();
198     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
199 
200     // Clear depth to 0.5.
201     glClearDepthf(0.5f);
202     glClear(GL_DEPTH_BUFFER_BIT);
203 
204     // Disable depth. Although this does not remove the feedback loop as defined by the
205     // spec it mimics what gfxbench does in its rendering tests.
206     glDepthMask(false);
207     glDisable(GL_DEPTH_TEST);
208 
209     // Verify we can sample the depth texture and get 0.5.
210     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5);
211 
212     ASSERT_GL_NO_ERROR();
213     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
214 }
215 
216 // Tests corner cases with read-only depth-stencil feedback loops.
TEST_P(ReadOnlyFeedbackLoopTest,ReadOnlyDepthFeedbackLoopStateChanges)217 TEST_P(ReadOnlyFeedbackLoopTest, ReadOnlyDepthFeedbackLoopStateChanges)
218 {
219     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_read_only_depth_stencil_feedback_loops"));
220 
221     constexpr GLuint kSize = 2;
222     glViewport(0, 0, kSize, kSize);
223 
224     constexpr char kFS[] = R"(precision mediump float;
225 varying vec2 v_texCoord;
226 uniform sampler2D depth;
227 void main()
228 {
229     if (abs(texture2D(depth, v_texCoord).x - 0.5) < 0.1)
230     {
231         gl_FragColor = vec4(0, 1, 0, 1);
232     }
233     else
234     {
235         gl_FragColor = vec4(1, 0, 0, 1);
236     }
237 })";
238 
239     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), kFS);
240     glUseProgram(program);
241 
242     setupQuadVertexBuffer(0.5f, 1.0f);
243     glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
244     glEnableVertexAttribArray(0);
245 
246     GLFramebuffer framebuffer1;
247     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer1);
248 
249     GLTexture colorTexture;
250     glBindTexture(GL_TEXTURE_2D, colorTexture);
251     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
252 
253     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
254     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
255     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 0);
256 
257     GLTexture depthTexture;
258     glBindTexture(GL_TEXTURE_2D, depthTexture);
259     glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, kSize, kSize, 0, GL_DEPTH_COMPONENT,
260                  GL_UNSIGNED_INT, nullptr);
261     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
262     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
263     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTexture, 0);
264     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
265 
266     GLFramebuffer framebuffer2;
267     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer2);
268     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTexture, 0);
269     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
270 
271     ASSERT_GL_NO_ERROR();
272 
273     // Clear depth to 0.5.
274     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer1);
275     glClearDepthf(0.5f);
276     glClear(GL_DEPTH_BUFFER_BIT);
277     glFlush();
278 
279     // Disable depth. Although this does not remove the feedback loop as defined by the
280     // spec it mimics what gfxbench does in its rendering tests.
281     glDepthMask(false);
282     glDisable(GL_DEPTH_TEST);
283 
284     // Draw with loop.
285     glDrawArrays(GL_TRIANGLES, 0, 6);
286     ASSERT_GL_NO_ERROR();
287 
288     // Draw with no loop and second FBO. Starts RP in writable mode.
289     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer2);
290     glBindTexture(GL_TEXTURE_2D, 0);
291     glDrawArrays(GL_TRIANGLES, 0, 6);
292     ASSERT_GL_NO_ERROR();
293 
294     // Draw with loop, restarts RP.
295     glBindTexture(GL_TEXTURE_2D, depthTexture);
296     glDrawArrays(GL_TRIANGLES, 0, 6);
297     ASSERT_GL_NO_ERROR();
298 }
299 
300 // Tests depth/stencil clear after read-only depth/stencil feedback loop draw.
TEST_P(ReadOnlyFeedbackLoopTest,ReadOnlyDepthFeedbackLoopDrawThenDepthStencilClear)301 TEST_P(ReadOnlyFeedbackLoopTest, ReadOnlyDepthFeedbackLoopDrawThenDepthStencilClear)
302 {
303     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_read_only_depth_stencil_feedback_loops"));
304 
305     constexpr GLuint kSize = 2;
306     glViewport(0, 0, kSize, kSize);
307 
308     constexpr char kFS[] = R"(precision mediump float;
309 varying vec2 v_texCoord;
310 uniform sampler2D depth;
311 void main()
312 {
313     if (abs(texture2D(depth, v_texCoord).x - 0.5) < 0.1)
314     {
315         gl_FragColor = vec4(0, 1, 0, 1);
316     }
317     else
318     {
319         gl_FragColor = vec4(1, 0, 0, 1);
320     }
321 })";
322 
323     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), kFS);
324     glUseProgram(program);
325 
326     setupQuadVertexBuffer(0.5f, 1.0f);
327     glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
328     glEnableVertexAttribArray(0);
329 
330     GLFramebuffer framebuffer;
331     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
332 
333     GLTexture colorTexture;
334     glBindTexture(GL_TEXTURE_2D, colorTexture);
335     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
336 
337     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
338     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
339     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 0);
340 
341     GLTexture depthTexture;
342     glBindTexture(GL_TEXTURE_2D, depthTexture);
343     glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, kSize, kSize, 0, GL_DEPTH_COMPONENT,
344                  GL_UNSIGNED_INT, nullptr);
345     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
346     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
347     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTexture, 0);
348 
349     ASSERT_GL_NO_ERROR();
350     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
351 
352     // Clear depth to 0.5.
353     glClearDepthf(0.5f);
354     glClear(GL_DEPTH_BUFFER_BIT);
355 
356     // Disable depth to establish read-only depth/stencil feedback loop.
357     glDepthMask(false);
358     glDisable(GL_DEPTH_TEST);
359 
360     // Verify we can sample the depth texture and get 0.5.
361     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5);
362 
363     // Clear depth to another value
364     glDepthMask(true);
365     glClearDepthf(1.0f);
366     glClear(GL_DEPTH_BUFFER_BIT);
367     ASSERT_GL_NO_ERROR();
368 
369     // Make sure the last clear and the draw are not reordered by mistake.
370     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
371     ASSERT_GL_NO_ERROR();
372 
373     // Make sure depth is correctly cleared.
374     glEnable(GL_DEPTH_TEST);
375     glDepthFunc(GL_LESS);
376 
377     ANGLE_GL_PROGRAM(drawBlue, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
378     drawQuad(drawBlue, essl1_shaders::PositionAttrib(), 0.95f);
379 
380     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
381     ASSERT_GL_NO_ERROR();
382 }
383 
384 // Tests scissored depth/stencil clear after read-only depth/stencil feedback loop draw.
TEST_P(ReadOnlyFeedbackLoopTest,ReadOnlyDepthFeedbackLoopDrawThenScissoredDepthStencilClear)385 TEST_P(ReadOnlyFeedbackLoopTest, ReadOnlyDepthFeedbackLoopDrawThenScissoredDepthStencilClear)
386 {
387     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_read_only_depth_stencil_feedback_loops"));
388 
389     constexpr GLuint kSize = 2;
390     glViewport(0, 0, kSize, kSize);
391 
392     constexpr char kFS[] = R"(precision mediump float;
393 varying vec2 v_texCoord;
394 uniform sampler2D depth;
395 void main()
396 {
397     if (abs(texture2D(depth, v_texCoord).x - 0.5) < 0.1)
398     {
399         gl_FragColor = vec4(0, 1, 0, 1);
400     }
401     else
402     {
403         gl_FragColor = vec4(1, 0, 0, 1);
404     }
405 })";
406 
407     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), kFS);
408     glUseProgram(program);
409 
410     setupQuadVertexBuffer(0.5f, 1.0f);
411     glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
412     glEnableVertexAttribArray(0);
413 
414     GLFramebuffer framebuffer;
415     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
416 
417     GLTexture colorTexture;
418     glBindTexture(GL_TEXTURE_2D, colorTexture);
419     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
420 
421     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
422     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
423     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 0);
424 
425     GLTexture depthTexture;
426     glBindTexture(GL_TEXTURE_2D, depthTexture);
427     glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, kSize, kSize, 0, GL_DEPTH_COMPONENT,
428                  GL_UNSIGNED_INT, nullptr);
429     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
430     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
431     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTexture, 0);
432 
433     ASSERT_GL_NO_ERROR();
434     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
435 
436     // Clear depth to 0.5.
437     glClearDepthf(0.5f);
438     glClear(GL_DEPTH_BUFFER_BIT);
439 
440     // Disable depth to establish read-only depth/stencil feedback loop.
441     glDepthMask(false);
442     glDisable(GL_DEPTH_TEST);
443 
444     // Verify we can sample the depth texture and get 0.5.
445     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5);
446 
447     // Clear depth to another value in a scissor
448     glDepthMask(true);
449     glEnable(GL_SCISSOR_TEST);
450     glViewport(kSize / 2, kSize / 2, kSize / 2, kSize / 2);
451     glClearDepthf(1.0f);
452     glClear(GL_DEPTH_BUFFER_BIT);
453     ASSERT_GL_NO_ERROR();
454 
455     // Make sure the draw worked.
456     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
457     ASSERT_GL_NO_ERROR();
458 
459     // Make sure depth is correctly cleared.
460     glEnable(GL_DEPTH_TEST);
461     glDepthFunc(GL_LESS);
462 
463     ANGLE_GL_PROGRAM(drawBlue, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
464     drawQuad(drawBlue, essl1_shaders::PositionAttrib(), 0.95f);
465 
466     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
467     EXPECT_PIXEL_COLOR_EQ(kSize - 1, kSize - 1, GLColor::blue);
468     ASSERT_GL_NO_ERROR();
469 }
470 
471 // Tests depth/stencil blit after read-only depth/stencil feedback loop draw.
TEST_P(ReadOnlyFeedbackLoopTest,ReadOnlyDepthFeedbackLoopDrawThenDepthStencilBlit)472 TEST_P(ReadOnlyFeedbackLoopTest, ReadOnlyDepthFeedbackLoopDrawThenDepthStencilBlit)
473 {
474     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_read_only_depth_stencil_feedback_loops"));
475 
476     constexpr GLuint kSize = 2;
477     glViewport(0, 0, kSize, kSize);
478 
479     constexpr char kFS[] = R"(precision mediump float;
480 varying vec2 v_texCoord;
481 uniform sampler2D depth;
482 void main()
483 {
484     if (abs(texture2D(depth, v_texCoord).x - 0.5) < 0.1)
485     {
486         gl_FragColor = vec4(0, 1, 0, 1);
487     }
488     else
489     {
490         gl_FragColor = vec4(1, 0, 0, 1);
491     }
492 })";
493 
494     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), kFS);
495     glUseProgram(program);
496 
497     setupQuadVertexBuffer(0.5f, 1.0f);
498     glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
499     glEnableVertexAttribArray(0);
500 
501     GLFramebuffer framebuffer;
502     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
503 
504     GLTexture colorTexture;
505     glBindTexture(GL_TEXTURE_2D, colorTexture);
506     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
507 
508     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
509     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
510     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 0);
511 
512     GLTexture depthTexture;
513     glBindTexture(GL_TEXTURE_2D, depthTexture);
514     glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, kSize, kSize, 0, GL_DEPTH_COMPONENT,
515                  GL_UNSIGNED_INT, nullptr);
516     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
517     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
518     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTexture, 0);
519 
520     ASSERT_GL_NO_ERROR();
521     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
522 
523     // Clear depth to 0.5.
524     glClearDepthf(0.5f);
525     glClear(GL_DEPTH_BUFFER_BIT);
526 
527     // Disable depth to establish read-only depth/stencil feedback loop.
528     glDepthMask(false);
529     glDisable(GL_DEPTH_TEST);
530 
531     // Verify we can sample the depth texture and get 0.5.
532     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5);
533 
534     // Blit depth to another framebuffer.
535     GLFramebuffer framebuffer2;
536     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer2);
537 
538     GLTexture colorTexture2;
539     glBindTexture(GL_TEXTURE_2D, colorTexture2);
540     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
541     glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture2,
542                            0);
543 
544     GLTexture depthTexture2;
545     glBindTexture(GL_TEXTURE_2D, depthTexture2);
546     glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, kSize, kSize, 0, GL_DEPTH_COMPONENT,
547                  GL_UNSIGNED_INT, nullptr);
548     glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTexture2,
549                            0);
550 
551     ASSERT_GL_NO_ERROR();
552     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
553 
554     glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_DEPTH_BUFFER_BIT, GL_NEAREST);
555 
556     // Make sure the draw worked.
557     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
558     ASSERT_GL_NO_ERROR();
559 
560     // Make sure depth is correctly blitted.
561     glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer2);
562     glEnable(GL_DEPTH_TEST);
563     glDepthFunc(GL_GREATER);
564 
565     ANGLE_GL_PROGRAM(drawBlue, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
566     drawQuad(drawBlue, essl1_shaders::PositionAttrib(), 0.05f);
567 
568     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
569     ASSERT_GL_NO_ERROR();
570 
571     glDepthFunc(GL_LESS);
572     ANGLE_GL_PROGRAM(drawRed, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
573     drawQuad(drawRed, essl1_shaders::PositionAttrib(), -0.05f);
574 
575     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
576     ASSERT_GL_NO_ERROR();
577 }
578 
579 // Tests that if the framebuffer is cleared, a feedback loop between a depth textures and the depth
580 // buffer is established, and a scissored clear is issued, that the clear is not mistakenly
581 // scissored.
TEST_P(ReadOnlyFeedbackLoopTest,ReadOnlyDepthFeedbackLoopWithClearAndScissoredDraw)582 TEST_P(ReadOnlyFeedbackLoopTest, ReadOnlyDepthFeedbackLoopWithClearAndScissoredDraw)
583 {
584     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_read_only_depth_stencil_feedback_loops"));
585 
586     constexpr GLuint kSize = 16;
587     glViewport(0, 0, kSize, kSize);
588 
589     constexpr char kFS[] = R"(precision mediump float;
590 varying vec2 v_texCoord;
591 uniform sampler2D depth;
592 void main()
593 {
594     if (abs(texture2D(depth, v_texCoord).x - 0.5) < 0.1)
595     {
596         gl_FragColor = vec4(0, 1, 0, 1);
597     }
598     else
599     {
600         gl_FragColor = vec4(1, 0, 0, 1);
601     }
602 })";
603 
604     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), kFS);
605 
606     GLFramebuffer framebuffer;
607     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
608 
609     GLTexture colorTexture;
610     glBindTexture(GL_TEXTURE_2D, colorTexture);
611     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
612 
613     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
614     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
615     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 0);
616 
617     GLTexture depthTexture;
618     glBindTexture(GL_TEXTURE_2D, depthTexture);
619     glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, kSize, kSize, 0, GL_DEPTH_COMPONENT,
620                  GL_UNSIGNED_INT, nullptr);
621     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
622     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
623     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTexture, 0);
624 
625     ASSERT_GL_NO_ERROR();
626     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
627 
628     // Clear color to blue and depth to 0.5.
629     glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
630     glClearDepthf(0.5f);
631     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
632 
633     // Disable depth. Although this does not remove the feedback loop as defined by the
634     // spec it mimics what gfxbench does in its rendering tests.
635     glDepthMask(false);
636     glDisable(GL_DEPTH_TEST);
637 
638     // Verify we can sample the depth texture and get 0.5.  Use a scissor.
639     glScissor(0, 0, kSize / 2, kSize);
640     glEnable(GL_SCISSOR_TEST);
641     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5);
642     ASSERT_GL_NO_ERROR();
643 
644     // Make sure the scissored region passes the depth test and is changed to green.
645     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
646     EXPECT_PIXEL_COLOR_EQ(0, kSize - 1, GLColor::green);
647     EXPECT_PIXEL_COLOR_EQ(kSize / 2 - 1, 0, GLColor::green);
648     EXPECT_PIXEL_COLOR_EQ(kSize / 2 - 1, kSize - 1, GLColor::green);
649 
650     // Make sure the region outside the scissor is cleared to blue.
651     EXPECT_PIXEL_COLOR_EQ(kSize / 2, 0, GLColor::blue);
652     EXPECT_PIXEL_COLOR_EQ(kSize / 2, kSize - 1, GLColor::blue);
653     EXPECT_PIXEL_COLOR_EQ(kSize - 1, 0, GLColor::blue);
654     EXPECT_PIXEL_COLOR_EQ(kSize - 1, kSize - 1, GLColor::blue);
655 }
656 
657 // Tests that sampling from stencil while simultaneously bound as read-only attachment works.  Depth
658 // is being written at the same time.
TEST_P(ReadOnlyFeedbackLoopTestES31,SampleStencilWhileReadOnlyAttachment)659 TEST_P(ReadOnlyFeedbackLoopTestES31, SampleStencilWhileReadOnlyAttachment)
660 {
661     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_read_only_depth_stencil_feedback_loops"));
662 
663     constexpr GLsizei kSize = 64;
664 
665     // Create FBO with color, depth and stencil
666     GLTexture texture;
667     glBindTexture(GL_TEXTURE_2D, texture);
668     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);
669 
670     GLTexture depthStencil;
671     glBindTexture(GL_TEXTURE_2D, depthStencil);
672     glTexStorage2D(GL_TEXTURE_2D, 1, GL_DEPTH24_STENCIL8, kSize, kSize);
673 
674     GLFramebuffer framebuffer;
675     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
676     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
677     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, depthStencil,
678                            0);
679     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
680     ASSERT_GL_NO_ERROR();
681 
682     // Initialize depth/stencil
683     glEnable(GL_DEPTH_TEST);
684     glDepthFunc(GL_ALWAYS);
685 
686     glEnable(GL_STENCIL_TEST);
687     glStencilFunc(GL_ALWAYS, 0xAA, 0xFF);
688     glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
689     glStencilMask(0xFF);
690 
691     glBindTexture(GL_TEXTURE_2D, 0);
692     ANGLE_GL_PROGRAM(drawColor, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
693     glUseProgram(drawColor);
694     GLint colorUniformLocation =
695         glGetUniformLocation(drawColor, angle::essl1_shaders::ColorUniform());
696     ASSERT_NE(colorUniformLocation, -1);
697 
698     // Draw red with depth = 1 and stencil = 0xAA
699     glUniform4f(colorUniformLocation, 1.0f, 0.0f, 0.0f, 1.0f);
700     drawQuad(drawColor, essl1_shaders::PositionAttrib(), 1);
701     ASSERT_GL_NO_ERROR();
702 
703     // Break the render pass by making a copy of the color texture.
704     GLTexture copyTex;
705     glBindTexture(GL_TEXTURE_2D, copyTex);
706     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);
707     glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, kSize, kSize / 2);
708     ASSERT_GL_NO_ERROR();
709 
710     // Disable stencil output and bind stencil as sampler.
711     glDepthFunc(GL_LESS);
712     glStencilFunc(GL_EQUAL, 0xAA, 0xFF);
713     glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
714 
715     constexpr char kVS[] = R"(#version 310 es
716 precision highp float;
717 in vec4 position;
718 out vec2 texCoord;
719 
720 void main()
721 {
722     gl_Position = position;
723     texCoord = position.xy * 0.5 + vec2(0.5);
724 })";
725 
726     constexpr char kFS[] = R"(#version 310 es
727 precision mediump float;
728 precision mediump usampler2D;
729 
730 in vec2 texCoord;
731 
732 uniform usampler2D stencil;
733 
734 out vec4 color;
735 
736 void main()
737 {
738     bool stencilPass = texture(stencil, texCoord).x == 0xAAu;
739 
740     color = vec4(0, stencilPass, 0, 1);
741 }
742 )";
743 
744     ANGLE_GL_PROGRAM(validateStencil, kVS, kFS);
745 
746     glActiveTexture(GL_TEXTURE0);
747     glBindTexture(GL_TEXTURE_2D, depthStencil);
748     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
749     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
750     glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_STENCIL_TEXTURE_MODE, GL_STENCIL_INDEX);
751     ASSERT_GL_NO_ERROR();
752 
753     glUseProgram(validateStencil);
754     glUniform1i(glGetUniformLocation(validateStencil, "stencil"), 0);
755     ASSERT_GL_NO_ERROR();
756 
757     drawQuad(validateStencil, "position", 0.95);
758     ASSERT_GL_NO_ERROR();
759 
760     // Break the render pass
761     glBindTexture(GL_TEXTURE_2D, copyTex);
762     glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, kSize / 2, 0, 0, kSize, kSize / 2);
763     ASSERT_GL_NO_ERROR();
764 
765     GLFramebuffer readFramebuffer;
766     glBindFramebuffer(GL_READ_FRAMEBUFFER, readFramebuffer);
767     glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, copyTex, 0);
768     EXPECT_PIXEL_RECT_EQ(0, 0, kSize, kSize / 2, GLColor::red);
769     EXPECT_PIXEL_RECT_EQ(0, kSize / 2, kSize, kSize / 2, GLColor::green);
770 
771     // Validate that depth was overwritten in the previous render pass
772     glDepthFunc(GL_GREATER);
773     glDepthMask(GL_FALSE);
774 
775     glUseProgram(drawColor);
776     glUniform4f(colorUniformLocation, 0.0f, 0.0f, 1.0f, 1.0f);
777     drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.97);
778     ASSERT_GL_NO_ERROR();
779 
780     glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
781     EXPECT_PIXEL_RECT_EQ(0, 0, kSize, kSize, GLColor::blue);
782 }
783 
784 // Tests that sampling from depth while simultaneously bound as read-only attachment works.  Stencil
785 // is being written at the same time.
TEST_P(ReadOnlyFeedbackLoopTestES31,SampleDepthWhileReadOnlyAttachment)786 TEST_P(ReadOnlyFeedbackLoopTestES31, SampleDepthWhileReadOnlyAttachment)
787 {
788     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_read_only_depth_stencil_feedback_loops"));
789 
790     constexpr GLsizei kSize = 64;
791 
792     // Create FBO with color, depth and stencil
793     GLTexture texture;
794     glBindTexture(GL_TEXTURE_2D, texture);
795     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);
796 
797     GLTexture depthStencil;
798     glBindTexture(GL_TEXTURE_2D, depthStencil);
799     glTexStorage2D(GL_TEXTURE_2D, 1, GL_DEPTH24_STENCIL8, kSize, kSize);
800 
801     GLFramebuffer framebuffer;
802     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
803     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
804     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, depthStencil,
805                            0);
806     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
807     ASSERT_GL_NO_ERROR();
808 
809     // Initialize depth/stencil
810     glEnable(GL_DEPTH_TEST);
811     glDepthFunc(GL_ALWAYS);
812 
813     glEnable(GL_STENCIL_TEST);
814     glStencilFunc(GL_ALWAYS, 0xAA, 0xFF);
815     glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
816     glStencilMask(0xFF);
817 
818     glBindTexture(GL_TEXTURE_2D, 0);
819     ANGLE_GL_PROGRAM(drawColor, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
820     glUseProgram(drawColor);
821     GLint colorUniformLocation =
822         glGetUniformLocation(drawColor, angle::essl1_shaders::ColorUniform());
823     ASSERT_NE(colorUniformLocation, -1);
824 
825     // Draw red with depth = 1 and stencil = 0xAA
826     glUniform4f(colorUniformLocation, 1.0f, 0.0f, 0.0f, 1.0f);
827     drawQuad(drawColor, essl1_shaders::PositionAttrib(), 1);
828     ASSERT_GL_NO_ERROR();
829 
830     // Break the render pass by making a copy of the color texture.
831     GLTexture copyTex;
832     glBindTexture(GL_TEXTURE_2D, copyTex);
833     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);
834     glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, kSize, kSize / 2);
835     ASSERT_GL_NO_ERROR();
836 
837     // Disable depth output and bind depth as sampler.
838     glDepthFunc(GL_LESS);
839     glDepthMask(GL_FALSE);
840     glStencilFunc(GL_ALWAYS, 0xBB, 0xEE);
841     glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
842 
843     constexpr char kVS[] = R"(#version 310 es
844 precision highp float;
845 in vec4 position;
846 out vec2 texCoord;
847 
848 void main()
849 {
850     gl_Position = position;
851     texCoord = position.xy * 0.5 + vec2(0.5);
852 })";
853 
854     constexpr char kFS[] = R"(#version 310 es
855 precision mediump float;
856 
857 in vec2 texCoord;
858 
859 uniform sampler2D depth;
860 
861 out vec4 color;
862 
863 void main()
864 {
865     bool depthPass = abs(texture(depth, texCoord).x - 1.0) < 0.1;
866 
867     color = vec4(0, depthPass, 0, 1);
868 }
869 )";
870 
871     ANGLE_GL_PROGRAM(validateDepth, kVS, kFS);
872 
873     glActiveTexture(GL_TEXTURE0);
874     glBindTexture(GL_TEXTURE_2D, depthStencil);
875     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
876     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
877     ASSERT_GL_NO_ERROR();
878 
879     glUseProgram(validateDepth);
880     glUniform1i(glGetUniformLocation(validateDepth, "depth"), 0);
881     ASSERT_GL_NO_ERROR();
882 
883     drawQuad(validateDepth, "position", 0.95);
884     ASSERT_GL_NO_ERROR();
885 
886     // Break the render pass
887     glBindTexture(GL_TEXTURE_2D, copyTex);
888     glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, kSize / 2, 0, 0, kSize, kSize / 2);
889     ASSERT_GL_NO_ERROR();
890 
891     GLFramebuffer readFramebuffer;
892     glBindFramebuffer(GL_READ_FRAMEBUFFER, readFramebuffer);
893     glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, copyTex, 0);
894     EXPECT_PIXEL_RECT_EQ(0, 0, kSize, kSize / 2, GLColor::red);
895     EXPECT_PIXEL_RECT_EQ(0, kSize / 2, kSize, kSize / 2, GLColor::green);
896 
897     // Validate that stencil was overwritten in the previous render pass
898     glStencilFunc(GL_EQUAL, 0xBB, 0xFF);
899     glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
900 
901     glUseProgram(drawColor);
902     glUniform4f(colorUniformLocation, 0.0f, 0.0f, 1.0f, 1.0f);
903     drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.97);
904     ASSERT_GL_NO_ERROR();
905 
906     glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
907     EXPECT_PIXEL_RECT_EQ(0, 0, kSize, kSize, GLColor::blue);
908 }
909 
910 // Tests that sampling from depth and stencil while simultaneously bound as read-only attachment
911 // works.
TEST_P(ReadOnlyFeedbackLoopTestES31,SampleDepthAndStencilWhileReadOnlyAttachment)912 TEST_P(ReadOnlyFeedbackLoopTestES31, SampleDepthAndStencilWhileReadOnlyAttachment)
913 {
914     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_read_only_depth_stencil_feedback_loops"));
915 
916     constexpr GLsizei kSize = 64;
917 
918     // Create FBO with color, depth and stencil
919     GLTexture texture;
920     glBindTexture(GL_TEXTURE_2D, texture);
921     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);
922 
923     GLTexture depthStencil;
924     glBindTexture(GL_TEXTURE_2D, depthStencil);
925     glTexStorage2D(GL_TEXTURE_2D, 1, GL_DEPTH24_STENCIL8, kSize, kSize);
926 
927     GLFramebuffer framebuffer;
928     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
929     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
930     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, depthStencil,
931                            0);
932     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
933     ASSERT_GL_NO_ERROR();
934 
935     // Initialize depth/stencil
936     glEnable(GL_DEPTH_TEST);
937     glDepthFunc(GL_ALWAYS);
938 
939     glEnable(GL_STENCIL_TEST);
940     glStencilFunc(GL_ALWAYS, 0xAA, 0xFF);
941     glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
942     glStencilMask(0xFF);
943 
944     glBindTexture(GL_TEXTURE_2D, 0);
945     ANGLE_GL_PROGRAM(drawColor, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
946     glUseProgram(drawColor);
947     GLint colorUniformLocation =
948         glGetUniformLocation(drawColor, angle::essl1_shaders::ColorUniform());
949     ASSERT_NE(colorUniformLocation, -1);
950 
951     // Draw red with depth = 1 and stencil = 0xAA
952     glUniform4f(colorUniformLocation, 1.0f, 0.0f, 0.0f, 1.0f);
953     drawQuad(drawColor, essl1_shaders::PositionAttrib(), 1);
954     ASSERT_GL_NO_ERROR();
955 
956     // Break the render pass by making a copy of the color texture.
957     GLTexture copyTex;
958     glBindTexture(GL_TEXTURE_2D, copyTex);
959     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);
960     glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, kSize, kSize / 2);
961     ASSERT_GL_NO_ERROR();
962 
963     // Disable depth/stencil output and bind both depth and stencil as samplers.
964     glDepthFunc(GL_LESS);
965     glDepthMask(GL_FALSE);
966     glStencilFunc(GL_EQUAL, 0xAA, 0xFF);
967     glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
968 
969     constexpr char kVS[] = R"(#version 310 es
970 precision highp float;
971 in vec4 position;
972 out vec2 texCoord;
973 
974 void main()
975 {
976     gl_Position = position;
977     texCoord = position.xy * 0.5 + vec2(0.5);
978 })";
979 
980     constexpr char kFS[] = R"(#version 310 es
981 precision mediump float;
982 precision mediump usampler2D;
983 
984 in vec2 texCoord;
985 
986 uniform sampler2D depth;
987 uniform usampler2D stencil;
988 
989 out vec4 color;
990 
991 void main()
992 {
993     // Note: Due to GL_DEPTH_STENCIL_TEXTURE_MODE, it is not possible to read both the depth and
994     // stencil aspects correctly.  For the sake of test (reading both aspects), just make sure to
995     // sample from depth.
996     bool depthPass = !isinf(texture(depth, texCoord).x);
997     bool stencilPass = texture(stencil, texCoord).x == 0xAAu;
998 
999     color = vec4(0, depthPass, stencilPass, 1);
1000 }
1001 )";
1002 
1003     ANGLE_GL_PROGRAM(validateDepthStencil, kVS, kFS);
1004 
1005     glActiveTexture(GL_TEXTURE0);
1006     glBindTexture(GL_TEXTURE_2D, depthStencil);
1007     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1008     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1009     ASSERT_GL_NO_ERROR();
1010 
1011     glActiveTexture(GL_TEXTURE1);
1012     glBindTexture(GL_TEXTURE_2D, depthStencil);
1013     glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_STENCIL_TEXTURE_MODE, GL_STENCIL_INDEX);
1014     ASSERT_GL_NO_ERROR();
1015 
1016     glUseProgram(validateDepthStencil);
1017     glUniform1i(glGetUniformLocation(validateDepthStencil, "depth"), 0);
1018     glUniform1i(glGetUniformLocation(validateDepthStencil, "stencil"), 1);
1019     ASSERT_GL_NO_ERROR();
1020 
1021     drawQuad(validateDepthStencil, "position", 0.95);
1022     ASSERT_GL_NO_ERROR();
1023 
1024     // Break the render pass
1025     glBindTexture(GL_TEXTURE_2D, copyTex);
1026     glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, kSize / 2, 0, 0, kSize, kSize / 2);
1027     ASSERT_GL_NO_ERROR();
1028 
1029     GLFramebuffer readFramebuffer;
1030     glBindFramebuffer(GL_READ_FRAMEBUFFER, readFramebuffer);
1031     glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, copyTex, 0);
1032     EXPECT_PIXEL_RECT_EQ(0, 0, kSize, kSize / 2, GLColor::red);
1033     EXPECT_PIXEL_RECT_EQ(0, kSize / 2, kSize, kSize / 2, GLColor::cyan);
1034 }
1035 
1036 // Instantiate the test for ES3.
1037 ANGLE_INSTANTIATE_TEST_ES3(ReadOnlyFeedbackLoopTest);
1038 
1039 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ReadOnlyFeedbackLoopTestES31);
1040 ANGLE_INSTANTIATE_TEST_ES31(ReadOnlyFeedbackLoopTestES31);
1041