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