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