xref: /aosp_15_r20/external/angle/src/tests/gl_tests/FragDepthTest.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1 //
2 // Copyright 2022 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 // FragDepthTest:
7 //   Tests the correctness of gl_FragDepth usage.
8 //
9 
10 #include "test_utils/ANGLETest.h"
11 #include "test_utils/gl_raii.h"
12 
13 using namespace angle;
14 
15 class FragDepthTest : public ANGLETest<>
16 {
17   protected:
18     struct FragDepthTestResources
19     {
20         GLuint program;
21         GLint depthLocation;
22         GLTexture colorTexture;
23         GLTexture depthTexture;
24         GLFramebuffer framebuffer;
25     };
26 
setupResources(FragDepthTestResources & resources)27     void setupResources(FragDepthTestResources &resources)
28     {
29 
30         // Writes a fixed depth value and green.
31         constexpr char kFS[] =
32             R"(#version 300 es
33             precision highp float;
34             layout(location = 0) out vec4 fragColor;
35             uniform float u_depth;
36             void main(){
37                 gl_FragDepth = u_depth;
38                 fragColor = vec4(0.0, 1.0, 0.0, 1.0);
39             })";
40 
41         resources.program       = CompileProgram(essl3_shaders::vs::Simple(), kFS);
42         resources.depthLocation = glGetUniformLocation(resources.program, "u_depth");
43 
44         glBindTexture(GL_TEXTURE_2D, resources.colorTexture);
45         glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1);
46         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
47         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
48 
49         glBindTexture(GL_TEXTURE_2D, resources.depthTexture);
50         glTexStorage2D(GL_TEXTURE_2D, 1, GL_DEPTH_COMPONENT32F, 1, 1);
51         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
52         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
53 
54         glBindFramebuffer(GL_FRAMEBUFFER, resources.framebuffer);
55         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
56                                resources.colorTexture, 0);
57     }
58 
cleanupResources(FragDepthTestResources & resources)59     void cleanupResources(FragDepthTestResources &resources) { glDeleteProgram(resources.program); }
60 
checkDepthWritten(float expectedDepth,float fsDepth,bool bindDepthBuffer)61     void checkDepthWritten(float expectedDepth, float fsDepth, bool bindDepthBuffer)
62     {
63         FragDepthTestResources resources;
64         setupResources(resources);
65         ASSERT_NE(0u, resources.program);
66         ASSERT_NE(-1, resources.depthLocation);
67         ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
68         ASSERT_GL_NO_ERROR();
69 
70         glBindFramebuffer(GL_FRAMEBUFFER, resources.framebuffer);
71         if (bindDepthBuffer)
72         {
73             glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D,
74                                    resources.depthTexture, 0);
75             EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
76 
77             // Clear to the expected depth so it will be compared to the FS depth with
78             // DepthFunc(GL_EQUAL)
79             glClearDepthf(expectedDepth);
80             glDepthFunc(GL_EQUAL);
81             glEnable(GL_DEPTH_TEST);
82         }
83         else
84         {
85             glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
86             EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
87             glDisable(GL_DEPTH_TEST);
88         }
89         glUseProgram(resources.program);
90 
91         // Clear to red, the FS will write green on success
92         glClearColor(1.0f, 0.0f, 0.0f, 0.0f);
93         // Clear to the expected depth so it will be compared to the FS depth with
94         // DepthFunc(GL_EQUAL)
95 
96         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
97         glUniform1f(resources.depthLocation, fsDepth);
98 
99         drawQuad(resources.program, "a_position", 0.0f);
100         EXPECT_GL_NO_ERROR();
101 
102         EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
103         cleanupResources(resources);
104     }
105 };
106 
107 // Test that writing to gl_FragDepth works
TEST_P(FragDepthTest,DepthBufferBound)108 TEST_P(FragDepthTest, DepthBufferBound)
109 {
110     checkDepthWritten(0.5f, 0.5f, true);
111 }
112 
113 // Test that writing to gl_FragDepth with no depth buffer works.
TEST_P(FragDepthTest,DepthBufferUnbound)114 TEST_P(FragDepthTest, DepthBufferUnbound)
115 {
116     // Depth test is disabled, so the expected depth should not matter.
117     checkDepthWritten(0.f, 0.5f, false);
118 }
119 
120 // Test that fragment shader depth writes to a no-depth framebuffer do not fail
121 // after using a depth-enabled framebuffer with the same program.
TEST_P(FragDepthTest,SwitchToNoDepthFramebuffer)122 TEST_P(FragDepthTest, SwitchToNoDepthFramebuffer)
123 {
124     constexpr char kFS[] = R"(#version 300 es
125     out highp vec4 color;
126     void main() {
127       color = vec4(1.0, 0.0, 0.0, 1.0);
128       gl_FragDepth = 1.0;
129     })";
130 
131     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
132 
133     // Draw to a depth-enabled framebuffer first
134     GLFramebuffer fbo1;
135     glBindFramebuffer(GL_FRAMEBUFFER, fbo1);
136 
137     GLRenderbuffer rb10;
138     glBindRenderbuffer(GL_RENDERBUFFER, rb10);
139     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 128, 128);
140     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rb10);
141 
142     GLRenderbuffer rb1d;
143     glBindRenderbuffer(GL_RENDERBUFFER, rb1d);
144     glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT32F, 128, 128);
145     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rb1d);
146 
147     EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
148 
149     drawQuad(program, "a_position", 0.0f);
150     EXPECT_GL_NO_ERROR();
151 
152     // Draw to a no-depth framebuffer using the same program
153     GLFramebuffer fbo2;
154     glBindFramebuffer(GL_FRAMEBUFFER, fbo2);
155 
156     GLRenderbuffer rb20;
157     glBindRenderbuffer(GL_RENDERBUFFER, rb20);
158     glRenderbufferStorage(GL_RENDERBUFFER, GL_R8, 64, 64);
159     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rb20);
160 
161     EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
162 
163     drawQuad(program, "a_position", 0.0f);
164     EXPECT_GL_NO_ERROR();
165 }
166 
167 class FragDepthRedeclarationTest : public ANGLETest<>
168 {};
169 
170 // Test gl_FragDepth redeclared as vertex output
TEST_P(FragDepthRedeclarationTest,VSOutput)171 TEST_P(FragDepthRedeclarationTest, VSOutput)
172 {
173     constexpr char kVS[] = R"(#version 300 es
174 #extension GL_EXT_conservative_depth: enable
175 out highp float gl_FragDepth;
176 void main() {
177     gl_Position = vec4(0.0, 0.0, 0.0, 1.0);
178     gl_FragDepth = 1.0;
179 })";
180 
181     GLProgram prg;
182     prg.makeRaster(kVS, essl3_shaders::fs::Red());
183     EXPECT_FALSE(prg.valid());
184 }
185 
186 // Test gl_FragDepth redeclared as fragment input
TEST_P(FragDepthRedeclarationTest,FSInput)187 TEST_P(FragDepthRedeclarationTest, FSInput)
188 {
189     constexpr char kFS[] = R"(#version 300 es
190 #extension GL_EXT_conservative_depth: enable
191 out highp vec4 color;
192 in highp float gl_FragDepth;
193 void main() {
194     color = vec4(gl_FragDepth, 0.0, 0.0, 1.0);
195 })";
196 
197     GLProgram prg;
198     prg.makeRaster(essl3_shaders::vs::Simple(), kFS);
199     EXPECT_FALSE(prg.valid());
200 }
201 
202 // Test gl_FragDepth redeclaration with no layout qualifier
TEST_P(FragDepthRedeclarationTest,NoLayout)203 TEST_P(FragDepthRedeclarationTest, NoLayout)
204 {
205     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_conservative_depth"));
206 
207     constexpr char kFS[] = R"(#version 300 es
208 #extension GL_EXT_conservative_depth: require
209 out highp vec4 color;
210 out highp float gl_FragDepth;
211 void main() {
212     color = vec4(1.0, 0.0, 0.0, 1.0);
213     gl_FragDepth = 1.0;
214 })";
215 
216     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
217 }
218 
219 // Test gl_FragDepth redeclaration with depth_any layout qualifier
TEST_P(FragDepthRedeclarationTest,Any)220 TEST_P(FragDepthRedeclarationTest, Any)
221 {
222     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_conservative_depth"));
223 
224     constexpr char kFS[] = R"(#version 300 es
225 #extension GL_EXT_conservative_depth: require
226 out highp vec4 color;
227 layout (depth_any) out highp float gl_FragDepth;
228 void main() {
229     color = vec4(1.0, 0.0, 0.0, 1.0);
230     gl_FragDepth = 1.0;
231 })";
232 
233     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
234 }
235 
236 // Test gl_FragDepth redeclaration with depth_greater layout qualifier
TEST_P(FragDepthRedeclarationTest,Greater)237 TEST_P(FragDepthRedeclarationTest, Greater)
238 {
239     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_conservative_depth"));
240 
241     constexpr char kFS[] = R"(#version 300 es
242 #extension GL_EXT_conservative_depth: require
243 out highp vec4 color;
244 layout (depth_greater) out highp float gl_FragDepth;
245 void main() {
246     color = vec4(1.0, 0.0, 0.0, 1.0);
247     gl_FragDepth = 1.0;
248 })";
249 
250     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
251 }
252 
253 // Test gl_FragDepth redeclaration with depth_less layout qualifier
TEST_P(FragDepthRedeclarationTest,Less)254 TEST_P(FragDepthRedeclarationTest, Less)
255 {
256     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_conservative_depth"));
257 
258     constexpr char kFS[] = R"(#version 300 es
259 #extension GL_EXT_conservative_depth: require
260 out highp vec4 color;
261 layout (depth_less) out highp float gl_FragDepth;
262 void main() {
263     color = vec4(1.0, 0.0, 0.0, 1.0);
264     gl_FragDepth = 1.0;
265 })";
266 
267     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
268 }
269 
270 // Test gl_FragDepth redeclaration with depth_unchanged layout qualifier
TEST_P(FragDepthRedeclarationTest,Unchanged)271 TEST_P(FragDepthRedeclarationTest, Unchanged)
272 {
273     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_conservative_depth"));
274 
275     constexpr char kFS[] = R"(#version 300 es
276 #extension GL_EXT_conservative_depth: require
277 out highp vec4 color;
278 layout (depth_unchanged) out highp float gl_FragDepth;
279 void main() {
280     color = vec4(1.0, 0.0, 0.0, 1.0);
281     gl_FragDepth = 1.0;
282 })";
283 
284     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
285 }
286 
287 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(FragDepthTest);
288 ANGLE_INSTANTIATE_TEST_ES3(FragDepthTest);
289 
290 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(FragDepthRedeclarationTest);
291 ANGLE_INSTANTIATE_TEST_ES3(FragDepthRedeclarationTest);
292