1 //
2 // Copyright 2018 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 // DepthStencilTest:
7 // Tests covering depth- or stencil-only rendering to make sure the other non-existing aspect is
8 // not affecting the results (since the format may be emulated with one that has both aspects).
9 //
10
11 #include "test_utils/ANGLETest.h"
12
13 #include "platform/FeaturesVk.h"
14 #include "test_utils/gl_raii.h"
15
16 using namespace angle;
17
18 namespace
19 {
20
21 class DepthStencilTest : public ANGLETest
22 {
23 protected:
DepthStencilTest()24 DepthStencilTest()
25 {
26 setWindowWidth(128);
27 setWindowHeight(128);
28 setConfigRedBits(8);
29 setConfigGreenBits(8);
30 setConfigBlueBits(8);
31 setConfigAlphaBits(8);
32 setConfigDepthBits(24);
33 setConfigStencilBits(8);
34 }
35
testSetUp()36 void testSetUp() override
37 {
38 glBindTexture(GL_TEXTURE_2D, mColorTexture);
39 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
40 GL_UNSIGNED_BYTE, nullptr);
41
42 // Setup Color/Stencil FBO with a stencil format that's emulated with packed depth/stencil.
43 glBindFramebuffer(GL_FRAMEBUFFER, mColorStencilFBO);
44
45 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mColorTexture,
46 0);
47 glBindRenderbuffer(GL_RENDERBUFFER, mStencilTexture);
48 glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, getWindowWidth(),
49 getWindowHeight());
50 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
51 mStencilTexture);
52
53 ASSERT_GL_NO_ERROR();
54
55 // Note: GL_DEPTH_COMPONENT24 is allowed in GLES2 with GL_OES_depth24 extension.
56 if (getClientMajorVersion() >= 3 || IsGLExtensionEnabled("GL_OES_depth24"))
57 {
58 // Setup Color/Depth FBO with a depth format that's emulated with packed depth/stencil.
59 glBindFramebuffer(GL_FRAMEBUFFER, mColorDepthFBO);
60
61 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
62 mColorTexture, 0);
63 glBindRenderbuffer(GL_RENDERBUFFER, mDepthTexture);
64 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, getWindowWidth(),
65 getWindowHeight());
66 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER,
67 mDepthTexture);
68 }
69
70 ASSERT_GL_NO_ERROR();
71 }
72
bindColorStencilFBO()73 void bindColorStencilFBO()
74 {
75 glBindFramebuffer(GL_FRAMEBUFFER, mColorStencilFBO);
76 mHasDepth = false;
77 }
78
bindColorDepthFBO()79 void bindColorDepthFBO()
80 {
81 glBindFramebuffer(GL_FRAMEBUFFER, mColorDepthFBO);
82 mHasStencil = false;
83 }
84
85 // Override a feature to force emulation of stencil-only and depth-only formats with a packed
86 // depth/stencil format
overrideFeaturesVk(FeaturesVk * featuresVk)87 void overrideFeaturesVk(FeaturesVk *featuresVk) override
88 {
89 featuresVk->overrideFeatures({"force_fallback_format"}, true);
90 }
91
92 void prepareSingleEmulatedWithPacked();
93 void ensureColor(GLColor color);
94 void ensureDepthUnaffected();
95 void ensureStencilUnaffected();
96
97 private:
98 GLFramebuffer mColorStencilFBO;
99 GLFramebuffer mColorDepthFBO;
100 GLTexture mColorTexture;
101 GLRenderbuffer mDepthTexture;
102 GLRenderbuffer mStencilTexture;
103
104 bool mHasDepth = true;
105 bool mHasStencil = true;
106 };
107
108 class DepthStencilTestES3 : public DepthStencilTest
109 {
110 protected:
111 void compareDepth(uint32_t expected);
112 void clearAndCompareDepth(GLfloat depth, uint32_t expected);
113 void drawAndCompareDepth(GLProgram &program, GLfloat depth, uint32_t expected);
114 };
115
ensureColor(GLColor color)116 void DepthStencilTest::ensureColor(GLColor color)
117 {
118 const int width = getWindowWidth();
119 const int height = getWindowHeight();
120
121 std::vector<GLColor> pixelData(width * height);
122 glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixelData.data());
123
124 for (int i = 0; i < width * height; i += 16)
125 {
126 GLColor actualColor = pixelData[i];
127 EXPECT_NEAR(color.R, actualColor.R, 1);
128 EXPECT_NEAR(color.G, actualColor.G, 1);
129 EXPECT_NEAR(color.B, actualColor.B, 1);
130 EXPECT_NEAR(color.A, actualColor.A, 1);
131
132 if (i % width == 0)
133 i += 16 * width;
134 }
135 }
136
ensureDepthUnaffected()137 void DepthStencilTest::ensureDepthUnaffected()
138 {
139 ANGLE_GL_PROGRAM(depthTestProgram, essl1_shaders::vs::Passthrough(), essl1_shaders::fs::Blue());
140 glEnable(GL_DEPTH_TEST);
141 glDepthFunc(GL_EQUAL);
142 drawQuad(depthTestProgram, essl1_shaders::PositionAttrib(), 0.123f);
143 glDisable(GL_DEPTH_TEST);
144 ASSERT_GL_NO_ERROR();
145
146 // Since depth shouldn't exist, the drawQuad above should succeed in turning the whole image
147 // blue.
148 ensureColor(GLColor::blue);
149 }
150
ensureStencilUnaffected()151 void DepthStencilTest::ensureStencilUnaffected()
152 {
153 ANGLE_GL_PROGRAM(stencilTestProgram, essl1_shaders::vs::Passthrough(),
154 essl1_shaders::fs::Green());
155 glEnable(GL_STENCIL_TEST);
156 glStencilFunc(GL_EQUAL, 0x1B, 0xFF);
157 drawQuad(stencilTestProgram, essl1_shaders::PositionAttrib(), 0.0f);
158 glDisable(GL_STENCIL_TEST);
159 ASSERT_GL_NO_ERROR();
160
161 // Since stencil shouldn't exist, the drawQuad above should succeed in turning the whole image
162 // green.
163 ensureColor(GLColor::green);
164 }
165
prepareSingleEmulatedWithPacked()166 void DepthStencilTest::prepareSingleEmulatedWithPacked()
167 {
168 const int w = getWindowWidth();
169 const int h = getWindowHeight();
170 const int whalf = w >> 1;
171 const int hhalf = h >> 1;
172
173 // Clear to a random color, 0.75 depth and 0x36 stencil
174 Vector4 color1(0.1f, 0.2f, 0.3f, 0.4f);
175 GLColor color1RGB(color1);
176
177 glClearColor(color1[0], color1[1], color1[2], color1[3]);
178 glClearDepthf(0.75f);
179 glClearStencil(0x36);
180 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
181 ASSERT_GL_NO_ERROR();
182
183 // Verify color was cleared correctly.
184 EXPECT_PIXEL_COLOR_NEAR(0, 0, color1RGB, 1);
185
186 // Use masked color to clear two channels of the image to a second color, 0.25 depth and 0x59
187 // stencil.
188 Vector4 color2(0.2f, 0.4f, 0.6f, 0.8f);
189 glClearColor(color2[0], color2[1], color2[2], color2[3]);
190 glClearDepthf(0.25f);
191 glClearStencil(0x59);
192 glColorMask(GL_TRUE, GL_FALSE, GL_TRUE, GL_FALSE);
193 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
194 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
195 ASSERT_GL_NO_ERROR();
196
197 GLColor color2RGB(Vector4(color2[0], color1[1], color2[2], color1[3]));
198
199 EXPECT_PIXEL_COLOR_NEAR(whalf, hhalf, color2RGB, 1);
200
201 EXPECT_PIXEL_COLOR_NEAR(0, 0, color2RGB, 1);
202 EXPECT_PIXEL_COLOR_NEAR(w - 1, 0, color2RGB, 1);
203 EXPECT_PIXEL_COLOR_NEAR(0, h - 1, color2RGB, 1);
204 EXPECT_PIXEL_COLOR_NEAR(w - 1, h - 1, color2RGB, 1);
205
206 // Use scissor to clear the center to a third color, 0.5 depth and 0xA9 stencil.
207 glEnable(GL_SCISSOR_TEST);
208 glScissor(whalf / 2, hhalf / 2, whalf, hhalf);
209
210 Vector4 color3(0.3f, 0.5f, 0.7f, 0.9f);
211 GLColor color3RGB(color3);
212 glClearColor(color3[0], color3[1], color3[2], color3[3]);
213 glClearDepthf(0.5f);
214 glClearStencil(0xA9);
215 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
216 glDisable(GL_SCISSOR_TEST);
217 ASSERT_GL_NO_ERROR();
218
219 EXPECT_PIXEL_COLOR_NEAR(whalf, hhalf, color3RGB, 1);
220
221 EXPECT_PIXEL_COLOR_NEAR(0, 0, color2RGB, 1);
222 EXPECT_PIXEL_COLOR_NEAR(w - 1, 0, color2RGB, 1);
223 EXPECT_PIXEL_COLOR_NEAR(0, h - 1, color2RGB, 1);
224 EXPECT_PIXEL_COLOR_NEAR(w - 1, h - 1, color2RGB, 1);
225
226 // Use scissor to draw to the right half of the image with a fourth color, 0.6 depth and 0x84
227 // stencil.
228 glEnable(GL_SCISSOR_TEST);
229 glScissor(whalf, 0, whalf, h);
230
231 ANGLE_GL_PROGRAM(redProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
232 glEnable(GL_STENCIL_TEST);
233 glStencilFunc(GL_ALWAYS, 0x84, 0xFF);
234 glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
235 glStencilMask(0xFF);
236 drawQuad(redProgram, essl1_shaders::PositionAttrib(), 0.2f);
237
238 glDisable(GL_STENCIL_TEST);
239 glDisable(GL_SCISSOR_TEST);
240 }
241
242 // Tests that clearing or rendering into a depth-only format doesn't affect stencil.
TEST_P(DepthStencilTest,DepthOnlyEmulatedWithPacked)243 TEST_P(DepthStencilTest, DepthOnlyEmulatedWithPacked)
244 {
245 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 && !IsGLExtensionEnabled("GL_OES_depth24"));
246
247 bindColorDepthFBO();
248 prepareSingleEmulatedWithPacked();
249 ensureStencilUnaffected();
250 }
251
252 // Tests that clearing or rendering into a stencil-only format doesn't affect depth.
TEST_P(DepthStencilTest,StencilOnlyEmulatedWithPacked)253 TEST_P(DepthStencilTest, StencilOnlyEmulatedWithPacked)
254 {
255 // http://anglebug.com/4092
256 ANGLE_SKIP_TEST_IF(IsWindows() && IsD3D9());
257 bindColorStencilFBO();
258 prepareSingleEmulatedWithPacked();
259 ensureDepthUnaffected();
260 }
261
262 // Tests that clearing depth/stencil followed by draw works when the depth/stencil attachment is a
263 // texture.
TEST_P(DepthStencilTestES3,ClearThenDraw)264 TEST_P(DepthStencilTestES3, ClearThenDraw)
265 {
266 GLFramebuffer FBO;
267 glBindFramebuffer(GL_FRAMEBUFFER, FBO);
268
269 constexpr GLsizei kSize = 6;
270
271 // Create framebuffer to draw into, with both color and depth attachments.
272 GLTexture color;
273 glBindTexture(GL_TEXTURE_2D, color);
274 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
275
276 GLTexture depth;
277 glBindTexture(GL_TEXTURE_2D, depth);
278 glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, kSize, kSize, 0, GL_DEPTH_STENCIL,
279 GL_UNSIGNED_INT_24_8_OES, nullptr);
280
281 GLFramebuffer fbo;
282 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
283 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
284 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, depth, 0);
285 ASSERT_GL_NO_ERROR();
286
287 // Set viewport and clear depth/stencil
288 glViewport(0, 0, kSize, kSize);
289 glClearDepthf(1);
290 glClearStencil(0x55);
291 glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
292
293 // If depth is not cleared to 1, rendering would fail.
294 glEnable(GL_DEPTH_TEST);
295 glDepthFunc(GL_LESS);
296
297 // If stencil is not clear to 0x55, rendering would fail.
298 glEnable(GL_STENCIL_TEST);
299 glStencilFunc(GL_EQUAL, 0x55, 0xFF);
300 glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
301 glStencilMask(0xFF);
302
303 // Set up program
304 ANGLE_GL_PROGRAM(drawRed, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
305
306 // Draw red
307 drawQuad(drawRed, essl1_shaders::PositionAttrib(), 0.0f);
308 ASSERT_GL_NO_ERROR();
309
310 // Verify.
311 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
312 EXPECT_PIXEL_COLOR_EQ(kSize - 1, 0, GLColor::red);
313 EXPECT_PIXEL_COLOR_EQ(0, kSize - 1, GLColor::red);
314 EXPECT_PIXEL_COLOR_EQ(kSize - 1, kSize - 1, GLColor::red);
315 }
316
compareDepth(uint32_t expected)317 void DepthStencilTestES3::compareDepth(uint32_t expected)
318 {
319 uint32_t pixel;
320 glReadPixels(0, 0, 1, 1, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, &pixel);
321 ASSERT_GL_NO_ERROR();
322
323 // Right shift by 8 bits to only compare 24 depth bits
324 // and ignore 8 undefined bits.
325 pixel = pixel >> 8;
326
327 EXPECT_NEAR(pixel, expected, 1);
328 }
329
clearAndCompareDepth(GLfloat depth,uint32_t expected)330 void DepthStencilTestES3::clearAndCompareDepth(GLfloat depth, uint32_t expected)
331 {
332 glClearDepthf(depth);
333 glClear(GL_DEPTH_BUFFER_BIT);
334 compareDepth(expected);
335 }
336
drawAndCompareDepth(GLProgram & program,GLfloat positionZ,uint32_t expected)337 void DepthStencilTestES3::drawAndCompareDepth(GLProgram &program,
338 GLfloat positionZ,
339 uint32_t expected)
340 {
341 glEnable(GL_DEPTH_TEST);
342 glDepthFunc(GL_ALWAYS);
343 drawQuad(program, essl3_shaders::PositionAttrib(), positionZ, 1.0f);
344 glDisable(GL_DEPTH_TEST);
345 compareDepth(expected);
346 }
347
TEST_P(DepthStencilTestES3,ReadPixelsDepth24)348 TEST_P(DepthStencilTestES3, ReadPixelsDepth24)
349 {
350 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_depth24") ||
351 !IsGLExtensionEnabled("GL_NV_read_depth"));
352
353 // The test fails on native GLES on Android in glReadPixels
354 // with GL_INVALID_OPERATION due to the format/type combination
355 // not being supported.
356 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
357
358 // Create GL_DEPTH_COMPONENT24 texture
359 GLTexture depthTexture;
360 glBindTexture(GL_TEXTURE_2D, depthTexture);
361 glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, getWindowWidth(), getWindowHeight(), 0,
362 GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, nullptr);
363
364 // Set up framebuffer
365 GLFramebuffer depthFBO;
366 GLRenderbuffer depthRenderbuffer;
367
368 glBindFramebuffer(GL_FRAMEBUFFER, depthFBO);
369
370 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTexture, 0);
371 glBindRenderbuffer(GL_RENDERBUFFER, depthRenderbuffer);
372 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, getWindowWidth(),
373 getWindowHeight());
374 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER,
375 depthRenderbuffer);
376
377 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
378 ASSERT_GL_NO_ERROR();
379
380 // Test clear
381 clearAndCompareDepth(0.0f, 0x0);
382 clearAndCompareDepth(0.125f, 0x200000);
383 clearAndCompareDepth(0.5f, 0x800000);
384 clearAndCompareDepth(1.0f, 0xffffff);
385
386 // Test draw
387 ANGLE_GL_PROGRAM(depthTestProgram, essl3_shaders::vs::Simple(), essl3_shaders::fs::Green());
388 drawAndCompareDepth(depthTestProgram, 0.0f, 0x800000);
389 drawAndCompareDepth(depthTestProgram, 0.125f, 0x8fffff);
390 drawAndCompareDepth(depthTestProgram, 0.5f, 0xbfffff);
391 drawAndCompareDepth(depthTestProgram, 1.0f, 0xffffff);
392
393 ASSERT_GL_NO_ERROR();
394 }
395
396 // Tests that the stencil test is correctly handled when a framebuffer is cleared before that
397 // framebuffer's stencil attachment has been configured.
TEST_P(DepthStencilTestES3,FramebufferClearThenStencilAttachedThenStencilTestState)398 TEST_P(DepthStencilTestES3, FramebufferClearThenStencilAttachedThenStencilTestState)
399 {
400 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_NV_read_stencil"));
401
402 GLFramebuffer fbo;
403 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
404
405 GLRenderbuffer colorRbo;
406 glBindRenderbuffer(GL_RENDERBUFFER, colorRbo);
407 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, getWindowWidth(), getWindowHeight());
408 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorRbo);
409 glClearColor(0.f, 0.f, 0.f, 0.f);
410 glClear(GL_COLOR_BUFFER_BIT);
411
412 GLRenderbuffer stencilRbo;
413 glBindRenderbuffer(GL_RENDERBUFFER, stencilRbo);
414 glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, getWindowWidth(), getWindowHeight());
415 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, stencilRbo);
416 glClearStencil(2);
417 glClear(GL_STENCIL_BUFFER_BIT);
418
419 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
420 ASSERT_GL_NO_ERROR();
421
422 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
423 EXPECT_PIXEL_STENCIL_EQ(0, 0, 2);
424
425 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
426
427 GLint colorLocation = glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
428 ASSERT_NE(-1, colorLocation);
429
430 glUseProgram(program);
431 glUniform4f(colorLocation, 1.0f, 0.0f, 0.0f, 1.0f);
432
433 glEnable(GL_STENCIL_TEST);
434 glStencilFunc(GL_ALWAYS, 0, 0xFF);
435 glStencilOp(GL_KEEP, GL_INCR, GL_INCR);
436 drawQuad(program, "a_position", 0.5f);
437
438 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
439 EXPECT_PIXEL_STENCIL_EQ(0, 0, 3);
440 }
441
442 // Tests that the stencil test is correctly handled when both the stencil test state is configured
443 // and a framebuffer is cleared before that framebuffer's stencil attachment has been configured.
TEST_P(DepthStencilTestES3,StencilTestStateThenFramebufferClearThenStencilAttached)444 TEST_P(DepthStencilTestES3, StencilTestStateThenFramebufferClearThenStencilAttached)
445 {
446 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_NV_read_stencil"));
447
448 glEnable(GL_STENCIL_TEST);
449 glStencilFunc(GL_ALWAYS, 0, 0xFF);
450 glStencilOp(GL_KEEP, GL_INCR, GL_INCR);
451
452 GLFramebuffer fbo;
453 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
454
455 GLRenderbuffer colorRbo;
456 glBindRenderbuffer(GL_RENDERBUFFER, colorRbo);
457 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, getWindowWidth(), getWindowHeight());
458 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorRbo);
459 glClearColor(0.f, 0.f, 0.f, 0.f);
460 glClear(GL_COLOR_BUFFER_BIT);
461
462 GLRenderbuffer stencilRbo;
463 glBindRenderbuffer(GL_RENDERBUFFER, stencilRbo);
464 glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, getWindowWidth(), getWindowHeight());
465 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, stencilRbo);
466 glClearStencil(2);
467 glClear(GL_STENCIL_BUFFER_BIT);
468
469 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
470 ASSERT_GL_NO_ERROR();
471
472 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
473 EXPECT_PIXEL_STENCIL_EQ(0, 0, 2);
474
475 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
476
477 GLint colorLocation = glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
478 ASSERT_NE(-1, colorLocation);
479
480 glUseProgram(program);
481 glUniform4f(colorLocation, 1.0f, 0.0f, 0.0f, 1.0f);
482
483 drawQuad(program, "a_position", 0.5f);
484
485 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
486 EXPECT_PIXEL_STENCIL_EQ(0, 0, 3);
487 }
488
489 // Tests that the stencil test is correctly handled when a framebuffer is cleared before that
490 // framebuffer's stencil attachment has been configured and the stencil test state is configured
491 // during framebuffer setup.
TEST_P(DepthStencilTestES3,FramebufferClearThenStencilTestStateThenStencilAttached)492 TEST_P(DepthStencilTestES3, FramebufferClearThenStencilTestStateThenStencilAttached)
493 {
494 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_NV_read_stencil"));
495
496 GLFramebuffer fbo;
497 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
498
499 GLRenderbuffer colorRbo;
500 glBindRenderbuffer(GL_RENDERBUFFER, colorRbo);
501 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, getWindowWidth(), getWindowHeight());
502 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorRbo);
503 glClearColor(0.f, 0.f, 0.f, 0.f);
504 glClear(GL_COLOR_BUFFER_BIT);
505
506 glEnable(GL_STENCIL_TEST);
507 glStencilFunc(GL_ALWAYS, 0, 0xFF);
508 glStencilOp(GL_KEEP, GL_INCR, GL_INCR);
509
510 GLRenderbuffer stencilRbo;
511 glBindRenderbuffer(GL_RENDERBUFFER, stencilRbo);
512 glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, getWindowWidth(), getWindowHeight());
513 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, stencilRbo);
514 glClearStencil(2);
515 glClear(GL_STENCIL_BUFFER_BIT);
516
517 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
518 ASSERT_GL_NO_ERROR();
519
520 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
521 EXPECT_PIXEL_STENCIL_EQ(0, 0, 2);
522
523 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
524
525 GLint colorLocation = glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
526 ASSERT_NE(-1, colorLocation);
527
528 glUseProgram(program);
529 glUniform4f(colorLocation, 1.0f, 0.0f, 0.0f, 1.0f);
530
531 drawQuad(program, "a_position", 0.5f);
532
533 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
534 EXPECT_PIXEL_STENCIL_EQ(0, 0, 3);
535 }
536
537 // Tests that drawing with read-only depth/stencil followed by depth/stencil output (in two render
538 // passes) works. Regression test for a synchronization bug in the Vulkan backend, caught by
539 // syncval VVL.
TEST_P(DepthStencilTestES3,ReadOnlyDepthStencilThenOutputDepthStencil)540 TEST_P(DepthStencilTestES3, ReadOnlyDepthStencilThenOutputDepthStencil)
541 {
542 constexpr GLsizei kSize = 64;
543
544 // Create FBO with color, depth and stencil
545 GLTexture texture;
546 glBindTexture(GL_TEXTURE_2D, texture);
547 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
548
549 GLRenderbuffer renderbuffer;
550 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
551 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, kSize, kSize);
552
553 GLFramebuffer framebuffer;
554 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
555 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
556 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
557 renderbuffer);
558 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
559 ASSERT_GL_NO_ERROR();
560
561 // Initialize depth/stencil
562 glEnable(GL_DEPTH_TEST);
563 glDepthFunc(GL_ALWAYS);
564
565 glEnable(GL_STENCIL_TEST);
566 glStencilFunc(GL_ALWAYS, 0xAA, 0xFF);
567 glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
568 glStencilMask(0xFF);
569
570 ANGLE_GL_PROGRAM(drawColor, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
571 glUseProgram(drawColor);
572 GLint colorUniformLocation =
573 glGetUniformLocation(drawColor, angle::essl1_shaders::ColorUniform());
574 ASSERT_NE(colorUniformLocation, -1);
575
576 // Draw red with depth = 1 and stencil = 0xAA
577 glUniform4f(colorUniformLocation, 1.0f, 0.0f, 0.0f, 1.0f);
578 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 1);
579 ASSERT_GL_NO_ERROR();
580
581 // Break the render pass by making a copy of the color texture.
582 GLTexture copyTex;
583 glBindTexture(GL_TEXTURE_2D, copyTex);
584 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
585 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, kSize / 2, kSize / 2);
586 ASSERT_GL_NO_ERROR();
587
588 // Disable depth/stencil output and issue a draw call that's expected to pass depth/stencil.
589 glDepthFunc(GL_LESS);
590 glDepthMask(GL_FALSE);
591 glStencilFunc(GL_EQUAL, 0xAA, 0xFF);
592 glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
593
594 // Draw green
595 glUniform4f(colorUniformLocation, 0.0f, 1.0f, 0.0f, 1.0f);
596 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.95);
597 ASSERT_GL_NO_ERROR();
598
599 // Break the render pass
600 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, kSize / 2, 0, 0, 0, kSize / 2, kSize / 2);
601 ASSERT_GL_NO_ERROR();
602
603 // Draw again to start another render pass still with depth/stencil read-only
604 glUniform4f(colorUniformLocation, 0.0f, 0.0f, 1.0f, 1.0f);
605 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.95);
606 ASSERT_GL_NO_ERROR();
607
608 // Break the render pass
609 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, kSize / 2, 0, 0, kSize / 2, kSize / 2);
610 ASSERT_GL_NO_ERROR();
611
612 // Re-enable depth/stencil output and issue a draw call that's expected to pass depth/stencil.
613 glDepthMask(GL_TRUE);
614 glStencilFunc(GL_EQUAL, 0xAB, 0xF0);
615 glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
616
617 // Draw yellow
618 glUniform4f(colorUniformLocation, 1.0f, 1.0f, 0.0f, 1.0f);
619 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.95);
620 ASSERT_GL_NO_ERROR();
621
622 // Break the render pass
623 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, kSize / 2, kSize / 2, 0, 0, kSize / 2, kSize / 2);
624 ASSERT_GL_NO_ERROR();
625
626 GLFramebuffer readFramebuffer;
627 glBindFramebuffer(GL_READ_FRAMEBUFFER, readFramebuffer);
628 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, copyTex, 0);
629 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
630 EXPECT_PIXEL_COLOR_EQ(kSize / 2, 0, GLColor::green);
631 EXPECT_PIXEL_COLOR_EQ(0, kSize / 2, GLColor::blue);
632 EXPECT_PIXEL_COLOR_EQ(kSize / 2, kSize / 2, GLColor::yellow);
633 }
634
635 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(DepthStencilTest);
636
637 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DepthStencilTestES3);
638 ANGLE_INSTANTIATE_TEST_ES3(DepthStencilTestES3);
639
640 } // anonymous namespace
641