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