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