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