xref: /aosp_15_r20/external/deqp/external/openglcts/modules/common/glcFragDepthTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1 /*-------------------------------------------------------------------------
2  * OpenGL Conformance Test Suite
3  * -----------------------------
4  *
5  * Copyright (c) 2016 Google Inc.
6  * Copyright (c) 2016 The Khronos Group Inc.
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */ /*!
21  * \file
22  * \brief gl_FragDepth tests.
23  */ /*-------------------------------------------------------------------*/
24 
25 #include "glcFragDepthTests.hpp"
26 #include "deMath.h"
27 #include "deRandom.hpp"
28 #include "deString.h"
29 #include "gluDrawUtil.hpp"
30 #include "gluPixelTransfer.hpp"
31 #include "gluShaderProgram.hpp"
32 #include "glwEnums.hpp"
33 #include "glwFunctions.hpp"
34 #include "tcuImageCompare.hpp"
35 #include "tcuRenderTarget.hpp"
36 #include "tcuStringTemplate.hpp"
37 #include "tcuSurface.hpp"
38 #include "tcuTestLog.hpp"
39 #include "tcuVector.hpp"
40 
41 // For setupDefaultUniforms()
42 #include "glcShaderRenderCase.hpp"
43 
44 namespace deqp
45 {
46 
47 using std::string;
48 using std::vector;
49 using tcu::TestLog;
50 using tcu::Vec2;
51 using tcu::Vec3;
52 using tcu::Vec4;
53 
54 typedef float (*EvalFragDepthFunc)(const Vec2 &coord);
55 
56 static const char *s_vertexShaderSrc          = "${VERSION_DECL}\n"
57                                                 "in highp vec4 a_position;\n"
58                                                 "in highp vec2 a_coord;\n"
59                                                 "out highp vec2 v_coord;\n"
60                                                 "void main (void)\n"
61                                                 "{\n"
62                                                 "   gl_Position = a_position;\n"
63                                                 "   v_coord = a_coord;\n"
64                                                 "}\n";
65 static const char *s_defaultFragmentShaderSrc = "${VERSION_DECL}\n"
66                                                 "uniform highp vec4 u_color;\n"
67                                                 "layout(location = 0) out mediump vec4 o_color;\n"
68                                                 "void main (void)\n"
69                                                 "{\n"
70                                                 "   o_color = u_color;\n"
71                                                 "}\n";
72 
73 template <typename T>
compare(uint32_t func,T a,T b)74 static inline bool compare(uint32_t func, T a, T b)
75 {
76     switch (func)
77     {
78     case GL_NEVER:
79         return false;
80     case GL_ALWAYS:
81         return true;
82     case GL_LESS:
83         return a < b;
84     case GL_LEQUAL:
85         return a <= b;
86     case GL_EQUAL:
87         return a == b;
88     case GL_NOTEQUAL:
89         return a != b;
90     case GL_GEQUAL:
91         return a >= b;
92     case GL_GREATER:
93         return a > b;
94     default:
95         DE_ASSERT(false);
96         return false;
97     }
98 }
99 
specializeVersion(const std::string & source,glu::GLSLVersion version)100 static std::string specializeVersion(const std::string &source, glu::GLSLVersion version)
101 {
102     DE_ASSERT(version == glu::GLSL_VERSION_300_ES || version == glu::GLSL_VERSION_310_ES ||
103               version >= glu::GLSL_VERSION_330);
104     std::map<std::string, std::string> args;
105     args["VERSION_DECL"] = glu::getGLSLVersionDeclaration(version);
106     return tcu::StringTemplate(source.c_str()).specialize(args);
107 }
108 
109 class FragDepthCompareCase : public TestCase
110 {
111 public:
112     FragDepthCompareCase(Context &context, const char *name, const char *desc, glu::GLSLVersion glslVersion,
113                          const char *fragSrc, EvalFragDepthFunc evalFunc, uint32_t compareFunc);
114     ~FragDepthCompareCase(void);
115 
116     IterateResult iterate(void);
117 
118 private:
119     glu::GLSLVersion m_glslVersion;
120     string m_fragSrc;
121     EvalFragDepthFunc m_evalFunc;
122     uint32_t m_compareFunc;
123 };
124 
FragDepthCompareCase(Context & context,const char * name,const char * desc,glu::GLSLVersion glslVersion,const char * fragSrc,EvalFragDepthFunc evalFunc,uint32_t compareFunc)125 FragDepthCompareCase::FragDepthCompareCase(Context &context, const char *name, const char *desc,
126                                            glu::GLSLVersion glslVersion, const char *fragSrc,
127                                            EvalFragDepthFunc evalFunc, uint32_t compareFunc)
128     : TestCase(context, name, desc)
129     , m_glslVersion(glslVersion)
130     , m_fragSrc(fragSrc)
131     , m_evalFunc(evalFunc)
132     , m_compareFunc(compareFunc)
133 {
134 }
135 
~FragDepthCompareCase(void)136 FragDepthCompareCase::~FragDepthCompareCase(void)
137 {
138 }
139 
iterate(void)140 FragDepthCompareCase::IterateResult FragDepthCompareCase::iterate(void)
141 {
142     TestLog &log             = m_testCtx.getLog();
143     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
144     de::Random rnd(deStringHash(getName()));
145     const tcu::RenderTarget &renderTarget = m_context.getRenderContext().getRenderTarget();
146     int viewportW                         = de::min(128, renderTarget.getWidth());
147     int viewportH                         = de::min(128, renderTarget.getHeight());
148     int viewportX                         = rnd.getInt(0, renderTarget.getWidth() - viewportW);
149     int viewportY                         = rnd.getInt(0, renderTarget.getHeight() - viewportH);
150     tcu::Surface renderedFrame(viewportW, viewportH);
151     tcu::Surface referenceFrame(viewportW, viewportH);
152     const float constDepth = 0.1f;
153 
154     if (renderTarget.getDepthBits() == 0)
155         throw tcu::NotSupportedError("Depth buffer is required", "", __FILE__, __LINE__);
156 
157     gl.viewport(viewportX, viewportY, viewportW, viewportH);
158     gl.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
159     gl.enable(GL_DEPTH_TEST);
160 
161     static const uint16_t quadIndices[] = {0, 1, 2, 2, 1, 3};
162 
163     // Fill viewport with 2 quads - one with constant depth and another with d = [-1..1]
164     {
165         glu::ShaderProgram basicQuadProgram(
166             m_context.getRenderContext(),
167             glu::makeVtxFragSources(specializeVersion(s_vertexShaderSrc, m_glslVersion).c_str(),
168                                     specializeVersion(s_defaultFragmentShaderSrc, m_glslVersion).c_str()));
169 
170         if (!basicQuadProgram.isOk())
171         {
172             log << basicQuadProgram;
173             TCU_FAIL("Compile failed");
174         }
175 
176         const float constDepthCoord[]   = {-1.0f, -1.0f, constDepth, 1.0f, -1.0f, +1.0f, constDepth, 1.0f,
177                                            0.0f,  -1.0f, constDepth, 1.0f, 0.0f,  +1.0f, constDepth, 1.0f};
178         const float varyingDepthCoord[] = {0.0f,  -1.0f, +1.0f, 1.0f, 0.0f,  +1.0f, 0.0f,  1.0f,
179                                            +1.0f, -1.0f, 0.0f,  1.0f, +1.0f, +1.0f, -1.0f, 1.0f};
180 
181         gl.useProgram(basicQuadProgram.getProgram());
182         gl.uniform4f(gl.getUniformLocation(basicQuadProgram.getProgram(), "u_color"), 0.0f, 0.0f, 1.0f, 1.0f);
183         gl.depthFunc(GL_ALWAYS);
184 
185         {
186             glu::VertexArrayBinding posBinding = glu::va::Float("a_position", 4, 4, 0, &constDepthCoord[0]);
187             glu::draw(m_context.getRenderContext(), basicQuadProgram.getProgram(), 1, &posBinding,
188                       glu::pr::Triangles(DE_LENGTH_OF_ARRAY(quadIndices), &quadIndices[0]));
189         }
190 
191         {
192             glu::VertexArrayBinding posBinding = glu::va::Float("a_position", 4, 4, 0, &varyingDepthCoord[0]);
193             glu::draw(m_context.getRenderContext(), basicQuadProgram.getProgram(), 1, &posBinding,
194                       glu::pr::Triangles(DE_LENGTH_OF_ARRAY(quadIndices), &quadIndices[0]));
195         }
196 
197         GLU_EXPECT_NO_ERROR(gl.getError(), "Draw base quads");
198     }
199 
200     // Render with depth test.
201     {
202         glu::ShaderProgram program(m_context.getRenderContext(),
203                                    glu::makeVtxFragSources(specializeVersion(s_vertexShaderSrc, m_glslVersion).c_str(),
204                                                            specializeVersion(m_fragSrc, m_glslVersion).c_str()));
205         log << program;
206 
207         if (!program.isOk())
208             TCU_FAIL("Compile failed");
209 
210         const float coord[]    = {0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f};
211         const float position[] = {-1.0f, -1.0f, +1.0f, 1.0f, -1.0f, +1.0f, 0.0f,  1.0f,
212                                   +1.0f, -1.0f, 0.0f,  1.0f, +1.0f, +1.0f, -1.0f, 1.0f};
213 
214         gl.useProgram(program.getProgram());
215         gl.depthFunc(m_compareFunc);
216         gl.uniform4f(gl.getUniformLocation(program.getProgram(), "u_color"), 0.0f, 1.0f, 0.0f, 1.0f);
217 
218         // Setup default helper uniforms.
219         setupDefaultUniforms(m_context.getRenderContext(), program.getProgram());
220 
221         {
222             glu::VertexArrayBinding vertexArrays[] = {glu::va::Float("a_position", 4, 4, 0, &position[0]),
223                                                       glu::va::Float("a_coord", 2, 4, 0, &coord[0])};
224             glu::draw(m_context.getRenderContext(), program.getProgram(), DE_LENGTH_OF_ARRAY(vertexArrays),
225                       &vertexArrays[0], glu::pr::Triangles(DE_LENGTH_OF_ARRAY(quadIndices), &quadIndices[0]));
226         }
227 
228         GLU_EXPECT_NO_ERROR(gl.getError(), "Draw test quad");
229     }
230 
231     glu::readPixels(m_context.getRenderContext(), viewportX, viewportY, renderedFrame.getAccess());
232 
233     // Render reference.
234     for (int y = 0; y < referenceFrame.getHeight(); y++)
235     {
236         float yf = ((float)y + 0.5f) / (float)referenceFrame.getHeight();
237         int half = de::clamp((int)((float)referenceFrame.getWidth() * 0.5f + 0.5f), 0, referenceFrame.getWidth());
238 
239         // Fill left half - comparison to constant 0.5
240         for (int x = 0; x < half; x++)
241         {
242             float xf   = ((float)x + 0.5f) / (float)referenceFrame.getWidth();
243             float d    = m_evalFunc(Vec2(xf, yf));
244             bool dpass = compare(m_compareFunc, d, constDepth * 0.5f + 0.5f);
245 
246             referenceFrame.setPixel(x, y, dpass ? tcu::RGBA::green() : tcu::RGBA::blue());
247         }
248 
249         // Fill right half - comparison to interpolated depth
250         for (int x = half; x < referenceFrame.getWidth(); x++)
251         {
252             float xf   = ((float)x + 0.5f) / (float)referenceFrame.getWidth();
253             float xh   = ((float)x - (float)half + 0.5f) / (float)(referenceFrame.getWidth() - half);
254             float rd   = 1.0f - (xh + yf) * 0.5f;
255             float d    = m_evalFunc(Vec2(xf, yf));
256             bool dpass = compare(m_compareFunc, d, rd);
257 
258             referenceFrame.setPixel(x, y, dpass ? tcu::RGBA::green() : tcu::RGBA::blue());
259         }
260     }
261 
262     bool isOk = tcu::fuzzyCompare(log, "Result", "Image comparison result", referenceFrame, renderedFrame, 0.05f,
263                                   tcu::COMPARE_LOG_RESULT);
264     m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, isOk ? "Pass" : "Fail");
265     return STOP;
266 }
267 
268 class FragDepthWriteCase : public TestCase
269 {
270 public:
271     FragDepthWriteCase(Context &context, const char *name, const char *desc, glu::GLSLVersion glslVersion,
272                        const char *fragSrc, EvalFragDepthFunc evalFunc);
273     ~FragDepthWriteCase(void);
274 
275     IterateResult iterate(void);
276 
277 private:
278     glu::GLSLVersion m_glslVersion;
279     string m_fragSrc;
280     EvalFragDepthFunc m_evalFunc;
281 };
282 
FragDepthWriteCase(Context & context,const char * name,const char * desc,glu::GLSLVersion glslVersion,const char * fragSrc,EvalFragDepthFunc evalFunc)283 FragDepthWriteCase::FragDepthWriteCase(Context &context, const char *name, const char *desc,
284                                        glu::GLSLVersion glslVersion, const char *fragSrc, EvalFragDepthFunc evalFunc)
285     : TestCase(context, name, desc)
286     , m_glslVersion(glslVersion)
287     , m_fragSrc(fragSrc)
288     , m_evalFunc(evalFunc)
289 {
290 }
291 
~FragDepthWriteCase(void)292 FragDepthWriteCase::~FragDepthWriteCase(void)
293 {
294 }
295 
iterate(void)296 FragDepthWriteCase::IterateResult FragDepthWriteCase::iterate(void)
297 {
298     TestLog &log             = m_testCtx.getLog();
299     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
300     de::Random rnd(deStringHash(getName()));
301     const tcu::RenderTarget &renderTarget = m_context.getRenderContext().getRenderTarget();
302     int viewportW                         = de::min(128, renderTarget.getWidth());
303     int viewportH                         = de::min(128, renderTarget.getHeight());
304     int viewportX                         = rnd.getInt(0, renderTarget.getWidth() - viewportW);
305     int viewportY                         = rnd.getInt(0, renderTarget.getHeight() - viewportH);
306     tcu::Surface renderedFrame(viewportW, viewportH);
307     tcu::Surface referenceFrame(viewportW, viewportH);
308     const int numDepthSteps = 16;
309     const float depthStep   = 1.0f / (float)(numDepthSteps - 1);
310 
311     if (renderTarget.getDepthBits() == 0)
312         throw tcu::NotSupportedError("Depth buffer is required", "", __FILE__, __LINE__);
313 
314     gl.viewport(viewportX, viewportY, viewportW, viewportH);
315     gl.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
316     gl.enable(GL_DEPTH_TEST);
317     gl.depthFunc(GL_LESS);
318 
319     static const uint16_t quadIndices[] = {0, 1, 2, 2, 1, 3};
320 
321     // Render with given shader.
322     {
323         glu::ShaderProgram program(m_context.getRenderContext(),
324                                    glu::makeVtxFragSources(specializeVersion(s_vertexShaderSrc, m_glslVersion).c_str(),
325                                                            specializeVersion(m_fragSrc, m_glslVersion).c_str()));
326         log << program;
327 
328         if (!program.isOk())
329             TCU_FAIL("Compile failed");
330 
331         const float coord[]    = {0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f};
332         const float position[] = {-1.0f, -1.0f, +1.0f, 1.0f, -1.0f, +1.0f, 0.0f,  1.0f,
333                                   +1.0f, -1.0f, 0.0f,  1.0f, +1.0f, +1.0f, -1.0f, 1.0f};
334 
335         gl.useProgram(program.getProgram());
336         gl.uniform4f(gl.getUniformLocation(program.getProgram(), "u_color"), 0.0f, 1.0f, 0.0f, 1.0f);
337 
338         // Setup default helper uniforms.
339         setupDefaultUniforms(m_context.getRenderContext(), program.getProgram());
340 
341         {
342             glu::VertexArrayBinding vertexArrays[] = {glu::va::Float("a_position", 4, 4, 0, &position[0]),
343                                                       glu::va::Float("a_coord", 2, 4, 0, &coord[0])};
344             glu::draw(m_context.getRenderContext(), program.getProgram(), DE_LENGTH_OF_ARRAY(vertexArrays),
345                       &vertexArrays[0], glu::pr::Triangles(DE_LENGTH_OF_ARRAY(quadIndices), &quadIndices[0]));
346         }
347 
348         GLU_EXPECT_NO_ERROR(gl.getError(), "Draw test quad");
349     }
350 
351     // Visualize by rendering full-screen quads with increasing depth and color.
352     {
353         glu::ShaderProgram program(
354             m_context.getRenderContext(),
355             glu::makeVtxFragSources(specializeVersion(s_vertexShaderSrc, m_glslVersion).c_str(),
356                                     specializeVersion(s_defaultFragmentShaderSrc, m_glslVersion).c_str()));
357         if (!program.isOk())
358         {
359             log << program;
360             TCU_FAIL("Compile failed");
361         }
362 
363         int posLoc   = gl.getAttribLocation(program.getProgram(), "a_position");
364         int colorLoc = gl.getUniformLocation(program.getProgram(), "u_color");
365 
366         gl.useProgram(program.getProgram());
367         gl.depthMask(GL_FALSE);
368 
369         for (int stepNdx = 0; stepNdx < numDepthSteps; stepNdx++)
370         {
371             float f     = (float)stepNdx * depthStep;
372             float depth = f * 2.0f - 1.0f;
373             Vec4 color  = Vec4(f, f, f, 1.0f);
374 
375             const float position[]             = {-1.0f, -1.0f, depth, 1.0f, -1.0f, +1.0f, depth, 1.0f,
376                                                   +1.0f, -1.0f, depth, 1.0f, +1.0f, +1.0f, depth, 1.0f};
377             glu::VertexArrayBinding posBinding = glu::va::Float(posLoc, 4, 4, 0, &position[0]);
378 
379             gl.uniform4fv(colorLoc, 1, color.getPtr());
380             glu::draw(m_context.getRenderContext(), program.getProgram(), 1, &posBinding,
381                       glu::pr::Triangles(DE_LENGTH_OF_ARRAY(quadIndices), &quadIndices[0]));
382         }
383 
384         GLU_EXPECT_NO_ERROR(gl.getError(), "Visualization draw");
385     }
386 
387     glu::readPixels(m_context.getRenderContext(), viewportX, viewportY, renderedFrame.getAccess());
388 
389     // Render reference.
390     for (int y = 0; y < referenceFrame.getHeight(); y++)
391     {
392         for (int x = 0; x < referenceFrame.getWidth(); x++)
393         {
394             float xf = ((float)x + 0.5f) / (float)referenceFrame.getWidth();
395             float yf = ((float)y + 0.5f) / (float)referenceFrame.getHeight();
396             float d  = m_evalFunc(Vec2(xf, yf));
397             int step = (int)deFloatFloor(d / depthStep);
398             int col  = de::clamp(deRoundFloatToInt32((float)step * depthStep * 255.0f), 0, 255);
399 
400             referenceFrame.setPixel(x, y, tcu::RGBA(col, col, col, 0xff));
401         }
402     }
403 
404     bool isOk = tcu::fuzzyCompare(log, "Result", "Image comparison result", referenceFrame, renderedFrame, 0.05f,
405                                   tcu::COMPARE_LOG_RESULT);
406     m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, isOk ? "Pass" : "Fail");
407     return STOP;
408 }
409 
FragDepthTests(Context & context,glu::GLSLVersion glslVersion)410 FragDepthTests::FragDepthTests(Context &context, glu::GLSLVersion glslVersion)
411     : TestCaseGroup(context, "fragdepth", "gl_FragDepth tests")
412     , m_glslVersion(glslVersion)
413 {
414 }
415 
~FragDepthTests(void)416 FragDepthTests::~FragDepthTests(void)
417 {
418 }
419 
evalConstDepth(const Vec2 & coord)420 static float evalConstDepth(const Vec2 &coord)
421 {
422     DE_UNREF(coord);
423     return 0.5f;
424 }
evalDynamicDepth(const Vec2 & coord)425 static float evalDynamicDepth(const Vec2 &coord)
426 {
427     return (coord.x() + coord.y()) * 0.5f;
428 }
evalNoWrite(const Vec2 & coord)429 static float evalNoWrite(const Vec2 &coord)
430 {
431     return 1.0f - (coord.x() + coord.y()) * 0.5f;
432 }
433 
evalDynamicConditionalDepth(const Vec2 & coord)434 static float evalDynamicConditionalDepth(const Vec2 &coord)
435 {
436     float d = (coord.x() + coord.y()) * 0.5f;
437     if (coord.y() < 0.5f)
438         return d;
439     else
440         return 1.0f - d;
441 }
442 
init(void)443 void FragDepthTests::init(void)
444 {
445     static const struct
446     {
447         const char *name;
448         const char *desc;
449         EvalFragDepthFunc evalFunc;
450         const char *fragSrc;
451     } cases[] = {{"no_write", "No gl_FragDepth write", evalNoWrite,
452                   "${VERSION_DECL}\n"
453                   "uniform highp vec4 u_color;\n"
454                   "layout(location = 0) out mediump vec4 o_color;\n"
455                   "void main (void)\n"
456                   "{\n"
457                   "   o_color = u_color;\n"
458                   "}\n"},
459                  {"const", "Const depth write", evalConstDepth,
460                   "${VERSION_DECL}\n"
461                   "uniform highp vec4 u_color;\n"
462                   "layout(location = 0) out mediump vec4 o_color;\n"
463                   "void main (void)\n"
464                   "{\n"
465                   "   o_color = u_color;\n"
466                   "   gl_FragDepth = 0.5;\n"
467                   "}\n"},
468                  {"uniform", "Uniform depth write", evalConstDepth,
469                   "${VERSION_DECL}\n"
470                   "uniform highp vec4 u_color;\n"
471                   "uniform highp float uf_half;\n"
472                   "layout(location = 0) out mediump vec4 o_color;\n"
473                   "void main (void)\n"
474                   "{\n"
475                   "   o_color = u_color;\n"
476                   "   gl_FragDepth = uf_half;\n"
477                   "}\n"},
478                  {"dynamic", "Dynamic depth write", evalDynamicDepth,
479                   "${VERSION_DECL}\n"
480                   "uniform highp vec4 u_color;\n"
481                   "in highp vec2 v_coord;\n"
482                   "layout(location = 0) out mediump vec4 o_color;\n"
483                   "void main (void)\n"
484                   "{\n"
485                   "   o_color = u_color;\n"
486                   "   gl_FragDepth = (v_coord.x+v_coord.y)*0.5;\n"
487                   "}\n"},
488                  {"fragcoord_z", "gl_FragDepth write from gl_FragCoord.z", evalNoWrite,
489                   "${VERSION_DECL}\n"
490                   "uniform highp vec4 u_color;\n"
491                   "layout(location = 0) out mediump vec4 o_color;\n"
492                   "void main (void)\n"
493                   "{\n"
494                   "   o_color = u_color;\n"
495                   "   gl_FragDepth = gl_FragCoord.z;\n"
496                   "}\n"},
497                  {"uniform_conditional_write", "Uniform conditional write", evalDynamicDepth,
498                   "${VERSION_DECL}\n"
499                   "uniform highp vec4 u_color;\n"
500                   "uniform bool ub_true;\n"
501                   "in highp vec2 v_coord;\n"
502                   "layout(location = 0) out mediump vec4 o_color;\n"
503                   "void main (void)\n"
504                   "{\n"
505                   "   o_color = u_color;\n"
506                   "   if (ub_true)\n"
507                   "       gl_FragDepth = (v_coord.x+v_coord.y)*0.5;\n"
508                   "}\n"},
509                  {"dynamic_conditional_write", "Uniform conditional write", evalDynamicConditionalDepth,
510                   "${VERSION_DECL}\n"
511                   "uniform highp vec4 u_color;\n"
512                   "uniform bool ub_true;\n"
513                   "in highp vec2 v_coord;\n"
514                   "layout(location = 0) out mediump vec4 o_color;\n"
515                   "void main (void)\n"
516                   "{\n"
517                   "   o_color = u_color;\n"
518                   "   mediump float d = (v_coord.x+v_coord.y)*0.5f;\n"
519                   "   if (v_coord.y < 0.5)\n"
520                   "       gl_FragDepth = d;\n"
521                   "   else\n"
522                   "       gl_FragDepth = 1.0 - d;\n"
523                   "}\n"},
524                  {"uniform_loop_write", "Uniform loop write", evalConstDepth,
525                   "${VERSION_DECL}\n"
526                   "uniform highp vec4 u_color;\n"
527                   "uniform int ui_two;\n"
528                   "uniform highp float uf_fourth;\n"
529                   "in highp vec2 v_coord;\n"
530                   "layout(location = 0) out mediump vec4 o_color;\n"
531                   "void main (void)\n"
532                   "{\n"
533                   "   o_color = u_color;\n"
534                   "   gl_FragDepth = 0.0;\n"
535                   "   for (int i = 0; i < ui_two; i++)\n"
536                   "       gl_FragDepth += uf_fourth;\n"
537                   "}\n"},
538                  {"write_in_function", "Uniform loop write", evalDynamicDepth,
539                   "${VERSION_DECL}\n"
540                   "uniform highp vec4 u_color;\n"
541                   "uniform highp float uf_half;\n"
542                   "in highp vec2 v_coord;\n"
543                   "layout(location = 0) out mediump vec4 o_color;\n"
544                   "void myfunc (highp vec2 coord)\n"
545                   "{\n"
546                   "   gl_FragDepth = (coord.x+coord.y)*0.5;\n"
547                   "}\n"
548                   "void main (void)\n"
549                   "{\n"
550                   "   o_color = u_color;\n"
551                   "   myfunc(v_coord);\n"
552                   "}\n"}};
553 
554     // .write
555     tcu::TestCaseGroup *writeGroup = new tcu::TestCaseGroup(m_testCtx, "write", "gl_FragDepth write tests");
556     addChild(writeGroup);
557     for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(cases); ndx++)
558         writeGroup->addChild(new FragDepthWriteCase(m_context, cases[ndx].name, cases[ndx].desc, m_glslVersion,
559                                                     cases[ndx].fragSrc, cases[ndx].evalFunc));
560 
561     // .compare
562     tcu::TestCaseGroup *compareGroup =
563         new tcu::TestCaseGroup(m_testCtx, "compare", "gl_FragDepth used with depth comparison");
564     addChild(compareGroup);
565     for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(cases); ndx++)
566         compareGroup->addChild(new FragDepthCompareCase(m_context, cases[ndx].name, cases[ndx].desc, m_glslVersion,
567                                                         cases[ndx].fragSrc, cases[ndx].evalFunc, GL_LESS));
568 }
569 
570 } // namespace deqp
571