Home | History | Annotate | Download | only in common
      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>
     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 
    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 
    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 
    136 FragDepthCompareCase::~FragDepthCompareCase(void)
    137 {
    138 }
    139 
    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 
    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 
    289 FragDepthWriteCase::~FragDepthWriteCase(void)
    290 {
    291 }
    292 
    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 
    407 FragDepthTests::FragDepthTests(Context& context, glu::GLSLVersion glslVersion)
    408 	: TestCaseGroup(context, "fragdepth", "gl_FragDepth tests"), m_glslVersion(glslVersion)
    409 {
    410 }
    411 
    412 FragDepthTests::~FragDepthTests(void)
    413 {
    414 }
    415 
    416 static float evalConstDepth(const Vec2& coord)
    417 {
    418 	DE_UNREF(coord);
    419 	return 0.5f;
    420 }
    421 static float evalDynamicDepth(const Vec2& coord)
    422 {
    423 	return (coord.x() + coord.y()) * 0.5f;
    424 }
    425 static float evalNoWrite(const Vec2& coord)
    426 {
    427 	return 1.0f - (coord.x() + coord.y()) * 0.5f;
    428 }
    429 
    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 
    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