• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 tcu::Vec2;
48 using tcu::Vec3;
49 using tcu::Vec4;
50 using tcu::TestLog;
51 using std::string;
52 using std::vector;
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(deUint32 func,T a,T b)74 static inline bool compare(deUint32 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(DE_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, deUint32 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 	deUint32		  m_compareFunc;
123 };
124 
FragDepthCompareCase(Context & context,const char * name,const char * desc,glu::GLSLVersion glslVersion,const char * fragSrc,EvalFragDepthFunc evalFunc,deUint32 compareFunc)125 FragDepthCompareCase::FragDepthCompareCase(Context& context, const char* name, const char* desc,
126 										   glu::GLSLVersion glslVersion, const char* fragSrc,
127 										   EvalFragDepthFunc evalFunc, deUint32 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 deUint16 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), m_glslVersion(glslVersion), m_fragSrc(fragSrc), m_evalFunc(evalFunc)
286 {
287 }
288 
~FragDepthWriteCase(void)289 FragDepthWriteCase::~FragDepthWriteCase(void)
290 {
291 }
292 
iterate(void)293 FragDepthWriteCase::IterateResult FragDepthWriteCase::iterate(void)
294 {
295 	TestLog&				 log = m_testCtx.getLog();
296 	const glw::Functions&	gl  = m_context.getRenderContext().getFunctions();
297 	de::Random				 rnd(deStringHash(getName()));
298 	const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget();
299 	int						 viewportW	= de::min(128, renderTarget.getWidth());
300 	int						 viewportH	= de::min(128, renderTarget.getHeight());
301 	int						 viewportX	= rnd.getInt(0, renderTarget.getWidth() - viewportW);
302 	int						 viewportY	= rnd.getInt(0, renderTarget.getHeight() - viewportH);
303 	tcu::Surface			 renderedFrame(viewportW, viewportH);
304 	tcu::Surface			 referenceFrame(viewportW, viewportH);
305 	const int				 numDepthSteps = 16;
306 	const float				 depthStep	 = 1.0f / (float)(numDepthSteps - 1);
307 
308 	if (renderTarget.getDepthBits() == 0)
309 		throw tcu::NotSupportedError("Depth buffer is required", "", __FILE__, __LINE__);
310 
311 	gl.viewport(viewportX, viewportY, viewportW, viewportH);
312 	gl.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
313 	gl.enable(GL_DEPTH_TEST);
314 	gl.depthFunc(GL_LESS);
315 
316 	static const deUint16 quadIndices[] = { 0, 1, 2, 2, 1, 3 };
317 
318 	// Render with given shader.
319 	{
320 		glu::ShaderProgram program(m_context.getRenderContext(),
321 								   glu::makeVtxFragSources(specializeVersion(s_vertexShaderSrc, m_glslVersion).c_str(),
322 														   specializeVersion(m_fragSrc, m_glslVersion).c_str()));
323 		log << program;
324 
325 		if (!program.isOk())
326 			TCU_FAIL("Compile failed");
327 
328 		const float coord[]	= { 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f };
329 		const float position[] = { -1.0f, -1.0f, +1.0f, 1.0f, -1.0f, +1.0f, 0.0f,  1.0f,
330 								   +1.0f, -1.0f, 0.0f,  1.0f, +1.0f, +1.0f, -1.0f, 1.0f };
331 
332 		gl.useProgram(program.getProgram());
333 		gl.uniform4f(gl.getUniformLocation(program.getProgram(), "u_color"), 0.0f, 1.0f, 0.0f, 1.0f);
334 
335 		// Setup default helper uniforms.
336 		setupDefaultUniforms(m_context.getRenderContext(), program.getProgram());
337 
338 		{
339 			glu::VertexArrayBinding vertexArrays[] = { glu::va::Float("a_position", 4, 4, 0, &position[0]),
340 													   glu::va::Float("a_coord", 2, 4, 0, &coord[0]) };
341 			glu::draw(m_context.getRenderContext(), program.getProgram(), DE_LENGTH_OF_ARRAY(vertexArrays),
342 					  &vertexArrays[0], glu::pr::Triangles(DE_LENGTH_OF_ARRAY(quadIndices), &quadIndices[0]));
343 		}
344 
345 		GLU_EXPECT_NO_ERROR(gl.getError(), "Draw test quad");
346 	}
347 
348 	// Visualize by rendering full-screen quads with increasing depth and color.
349 	{
350 		glu::ShaderProgram program(
351 			m_context.getRenderContext(),
352 			glu::makeVtxFragSources(specializeVersion(s_vertexShaderSrc, m_glslVersion).c_str(),
353 									specializeVersion(s_defaultFragmentShaderSrc, m_glslVersion).c_str()));
354 		if (!program.isOk())
355 		{
356 			log << program;
357 			TCU_FAIL("Compile failed");
358 		}
359 
360 		int posLoc   = gl.getAttribLocation(program.getProgram(), "a_position");
361 		int colorLoc = gl.getUniformLocation(program.getProgram(), "u_color");
362 
363 		gl.useProgram(program.getProgram());
364 		gl.depthMask(GL_FALSE);
365 
366 		for (int stepNdx = 0; stepNdx < numDepthSteps; stepNdx++)
367 		{
368 			float f		= (float)stepNdx * depthStep;
369 			float depth = f * 2.0f - 1.0f;
370 			Vec4  color = Vec4(f, f, f, 1.0f);
371 
372 			const float position[] = { -1.0f, -1.0f, depth, 1.0f, -1.0f, +1.0f, depth, 1.0f,
373 									   +1.0f, -1.0f, depth, 1.0f, +1.0f, +1.0f, depth, 1.0f };
374 			glu::VertexArrayBinding posBinding = glu::va::Float(posLoc, 4, 4, 0, &position[0]);
375 
376 			gl.uniform4fv(colorLoc, 1, color.getPtr());
377 			glu::draw(m_context.getRenderContext(), program.getProgram(), 1, &posBinding,
378 					  glu::pr::Triangles(DE_LENGTH_OF_ARRAY(quadIndices), &quadIndices[0]));
379 		}
380 
381 		GLU_EXPECT_NO_ERROR(gl.getError(), "Visualization draw");
382 	}
383 
384 	glu::readPixels(m_context.getRenderContext(), viewportX, viewportY, renderedFrame.getAccess());
385 
386 	// Render reference.
387 	for (int y = 0; y < referenceFrame.getHeight(); y++)
388 	{
389 		for (int x = 0; x < referenceFrame.getWidth(); x++)
390 		{
391 			float xf   = ((float)x + 0.5f) / (float)referenceFrame.getWidth();
392 			float yf   = ((float)y + 0.5f) / (float)referenceFrame.getHeight();
393 			float d	= m_evalFunc(Vec2(xf, yf));
394 			int   step = (int)deFloatFloor(d / depthStep);
395 			int   col  = de::clamp(deRoundFloatToInt32((float)step * depthStep * 255.0f), 0, 255);
396 
397 			referenceFrame.setPixel(x, y, tcu::RGBA(col, col, col, 0xff));
398 		}
399 	}
400 
401 	bool isOk = tcu::fuzzyCompare(log, "Result", "Image comparison result", referenceFrame, renderedFrame, 0.05f,
402 								  tcu::COMPARE_LOG_RESULT);
403 	m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, isOk ? "Pass" : "Fail");
404 	return STOP;
405 }
406 
FragDepthTests(Context & context,glu::GLSLVersion glslVersion)407 FragDepthTests::FragDepthTests(Context& context, glu::GLSLVersion glslVersion)
408 	: TestCaseGroup(context, "fragdepth", "gl_FragDepth tests"), m_glslVersion(glslVersion)
409 {
410 }
411 
~FragDepthTests(void)412 FragDepthTests::~FragDepthTests(void)
413 {
414 }
415 
evalConstDepth(const Vec2 & coord)416 static float evalConstDepth(const Vec2& coord)
417 {
418 	DE_UNREF(coord);
419 	return 0.5f;
420 }
evalDynamicDepth(const Vec2 & coord)421 static float evalDynamicDepth(const Vec2& coord)
422 {
423 	return (coord.x() + coord.y()) * 0.5f;
424 }
evalNoWrite(const Vec2 & coord)425 static float evalNoWrite(const Vec2& coord)
426 {
427 	return 1.0f - (coord.x() + coord.y()) * 0.5f;
428 }
429 
evalDynamicConditionalDepth(const Vec2 & coord)430 static float evalDynamicConditionalDepth(const Vec2& coord)
431 {
432 	float d = (coord.x() + coord.y()) * 0.5f;
433 	if (coord.y() < 0.5f)
434 		return d;
435 	else
436 		return 1.0f - d;
437 }
438 
init(void)439 void FragDepthTests::init(void)
440 {
441 	static const struct
442 	{
443 		const char*		  name;
444 		const char*		  desc;
445 		EvalFragDepthFunc evalFunc;
446 		const char*		  fragSrc;
447 	} cases[] = {
448 		{ "no_write", "No gl_FragDepth write", evalNoWrite, "${VERSION_DECL}\n"
449 															"uniform highp vec4 u_color;\n"
450 															"layout(location = 0) out mediump vec4 o_color;\n"
451 															"void main (void)\n"
452 															"{\n"
453 															"   o_color = u_color;\n"
454 															"}\n" },
455 		{ "const", "Const depth write", evalConstDepth, "${VERSION_DECL}\n"
456 														"uniform highp vec4 u_color;\n"
457 														"layout(location = 0) out mediump vec4 o_color;\n"
458 														"void main (void)\n"
459 														"{\n"
460 														"   o_color = u_color;\n"
461 														"   gl_FragDepth = 0.5;\n"
462 														"}\n" },
463 		{ "uniform", "Uniform depth write", evalConstDepth, "${VERSION_DECL}\n"
464 															"uniform highp vec4 u_color;\n"
465 															"uniform highp float uf_half;\n"
466 															"layout(location = 0) out mediump vec4 o_color;\n"
467 															"void main (void)\n"
468 															"{\n"
469 															"   o_color = u_color;\n"
470 															"   gl_FragDepth = uf_half;\n"
471 															"}\n" },
472 		{ "dynamic", "Dynamic depth write", evalDynamicDepth, "${VERSION_DECL}\n"
473 															  "uniform highp vec4 u_color;\n"
474 															  "in highp vec2 v_coord;\n"
475 															  "layout(location = 0) out mediump vec4 o_color;\n"
476 															  "void main (void)\n"
477 															  "{\n"
478 															  "   o_color = u_color;\n"
479 															  "   gl_FragDepth = (v_coord.x+v_coord.y)*0.5;\n"
480 															  "}\n" },
481 		{ "fragcoord_z", "gl_FragDepth write from gl_FragCoord.z", evalNoWrite,
482 		  "${VERSION_DECL}\n"
483 		  "uniform highp vec4 u_color;\n"
484 		  "layout(location = 0) out mediump vec4 o_color;\n"
485 		  "void main (void)\n"
486 		  "{\n"
487 		  "   o_color = u_color;\n"
488 		  "   gl_FragDepth = gl_FragCoord.z;\n"
489 		  "}\n" },
490 		{ "uniform_conditional_write", "Uniform conditional write", evalDynamicDepth,
491 		  "${VERSION_DECL}\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 		  "   if (ub_true)\n"
500 		  "       gl_FragDepth = (v_coord.x+v_coord.y)*0.5;\n"
501 		  "}\n" },
502 		{ "dynamic_conditional_write", "Uniform conditional write", evalDynamicConditionalDepth,
503 		  "${VERSION_DECL}\n"
504 		  "uniform highp vec4 u_color;\n"
505 		  "uniform bool ub_true;\n"
506 		  "in highp vec2 v_coord;\n"
507 		  "layout(location = 0) out mediump vec4 o_color;\n"
508 		  "void main (void)\n"
509 		  "{\n"
510 		  "   o_color = u_color;\n"
511 		  "   mediump float d = (v_coord.x+v_coord.y)*0.5f;\n"
512 		  "   if (v_coord.y < 0.5)\n"
513 		  "       gl_FragDepth = d;\n"
514 		  "   else\n"
515 		  "       gl_FragDepth = 1.0 - d;\n"
516 		  "}\n" },
517 		{ "uniform_loop_write", "Uniform loop write", evalConstDepth, "${VERSION_DECL}\n"
518 																	  "uniform highp vec4 u_color;\n"
519 																	  "uniform int ui_two;\n"
520 																	  "uniform highp float uf_fourth;\n"
521 																	  "in highp vec2 v_coord;\n"
522 																	  "layout(location = 0) out mediump vec4 o_color;\n"
523 																	  "void main (void)\n"
524 																	  "{\n"
525 																	  "   o_color = u_color;\n"
526 																	  "   gl_FragDepth = 0.0;\n"
527 																	  "   for (int i = 0; i < ui_two; i++)\n"
528 																	  "       gl_FragDepth += uf_fourth;\n"
529 																	  "}\n" },
530 		{ "write_in_function", "Uniform loop write", evalDynamicDepth,
531 		  "${VERSION_DECL}\n"
532 		  "uniform highp vec4 u_color;\n"
533 		  "uniform highp float uf_half;\n"
534 		  "in highp vec2 v_coord;\n"
535 		  "layout(location = 0) out mediump vec4 o_color;\n"
536 		  "void myfunc (highp vec2 coord)\n"
537 		  "{\n"
538 		  "   gl_FragDepth = (coord.x+coord.y)*0.5;\n"
539 		  "}\n"
540 		  "void main (void)\n"
541 		  "{\n"
542 		  "   o_color = u_color;\n"
543 		  "   myfunc(v_coord);\n"
544 		  "}\n" }
545 	};
546 
547 	// .write
548 	tcu::TestCaseGroup* writeGroup = new tcu::TestCaseGroup(m_testCtx, "write", "gl_FragDepth write tests");
549 	addChild(writeGroup);
550 	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(cases); ndx++)
551 		writeGroup->addChild(new FragDepthWriteCase(m_context, cases[ndx].name, cases[ndx].desc, m_glslVersion,
552 													cases[ndx].fragSrc, cases[ndx].evalFunc));
553 
554 	// .compare
555 	tcu::TestCaseGroup* compareGroup =
556 		new tcu::TestCaseGroup(m_testCtx, "compare", "gl_FragDepth used with depth comparison");
557 	addChild(compareGroup);
558 	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(cases); ndx++)
559 		compareGroup->addChild(new FragDepthCompareCase(m_context, cases[ndx].name, cases[ndx].desc, m_glslVersion,
560 														cases[ndx].fragSrc, cases[ndx].evalFunc, GL_LESS));
561 }
562 
563 } // deqp
564