| /*------------------------------------------------------------------------- |
| * drawElements Quality Program OpenGL ES 3.0 Module |
| * ------------------------------------------------- |
| * |
| * Copyright 2014 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| *//*! |
| * \file |
| * \brief gl_FragDepth tests. |
| *//*--------------------------------------------------------------------*/ |
| |
| #include "es3fFragDepthTests.hpp" |
| #include "tcuVector.hpp" |
| #include "tcuTestLog.hpp" |
| #include "tcuSurface.hpp" |
| #include "tcuImageCompare.hpp" |
| #include "tcuRenderTarget.hpp" |
| #include "gluPixelTransfer.hpp" |
| #include "gluShaderProgram.hpp" |
| #include "gluDrawUtil.hpp" |
| #include "deRandom.hpp" |
| #include "deMath.h" |
| #include "deString.h" |
| |
| // For setupDefaultUniforms() |
| #include "glsShaderRenderCase.hpp" |
| |
| #include "glwEnums.hpp" |
| #include "glwFunctions.hpp" |
| |
| namespace deqp |
| { |
| namespace gles3 |
| { |
| namespace Functional |
| { |
| |
| using tcu::Vec2; |
| using tcu::Vec3; |
| using tcu::Vec4; |
| using tcu::TestLog; |
| using std::string; |
| using std::vector; |
| |
| typedef float (*EvalFragDepthFunc) (const Vec2& coord); |
| |
| static const char* s_vertexShaderSrc = |
| "#version 300 es\n" |
| "in highp vec4 a_position;\n" |
| "in highp vec2 a_coord;\n" |
| "out highp vec2 v_coord;\n" |
| "void main (void)\n" |
| "{\n" |
| " gl_Position = a_position;\n" |
| " v_coord = a_coord;\n" |
| "}\n"; |
| static const char* s_defaultFragmentShaderSrc = |
| "#version 300 es\n" |
| "uniform highp vec4 u_color;\n" |
| "layout(location = 0) out mediump vec4 o_color;\n" |
| "void main (void)\n" |
| "{\n" |
| " o_color = u_color;\n" |
| "}\n"; |
| |
| template <typename T> |
| static inline bool compare (deUint32 func, T a, T b) |
| { |
| switch (func) |
| { |
| case GL_NEVER: return false; |
| case GL_ALWAYS: return true; |
| case GL_LESS: return a < b; |
| case GL_LEQUAL: return a <= b; |
| case GL_EQUAL: return a == b; |
| case GL_NOTEQUAL: return a != b; |
| case GL_GEQUAL: return a >= b; |
| case GL_GREATER: return a > b; |
| default: |
| DE_ASSERT(DE_FALSE); |
| return false; |
| } |
| } |
| |
| class FragDepthCompareCase : public TestCase |
| { |
| public: |
| FragDepthCompareCase (Context& context, const char* name, const char* desc, const char* fragSrc, EvalFragDepthFunc evalFunc, deUint32 compareFunc); |
| ~FragDepthCompareCase (void); |
| |
| IterateResult iterate (void); |
| |
| private: |
| string m_fragSrc; |
| EvalFragDepthFunc m_evalFunc; |
| deUint32 m_compareFunc; |
| }; |
| |
| FragDepthCompareCase::FragDepthCompareCase (Context& context, const char* name, const char* desc, const char* fragSrc, EvalFragDepthFunc evalFunc, deUint32 compareFunc) |
| : TestCase (context, name, desc) |
| , m_fragSrc (fragSrc) |
| , m_evalFunc (evalFunc) |
| , m_compareFunc (compareFunc) |
| { |
| } |
| |
| FragDepthCompareCase::~FragDepthCompareCase (void) |
| { |
| } |
| |
| FragDepthCompareCase::IterateResult FragDepthCompareCase::iterate (void) |
| { |
| TestLog& log = m_testCtx.getLog(); |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| de::Random rnd (deStringHash(getName())); |
| const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget(); |
| int viewportW = de::min(128, renderTarget.getWidth()); |
| int viewportH = de::min(128, renderTarget.getHeight()); |
| int viewportX = rnd.getInt(0, renderTarget.getWidth()-viewportW); |
| int viewportY = rnd.getInt(0, renderTarget.getHeight()-viewportH); |
| tcu::Surface renderedFrame (viewportW, viewportH); |
| tcu::Surface referenceFrame (viewportW, viewportH); |
| const float constDepth = 0.1f; |
| |
| if (renderTarget.getDepthBits() == 0) |
| throw tcu::NotSupportedError("Depth buffer is required", "", __FILE__, __LINE__); |
| |
| gl.viewport(viewportX, viewportY, viewportW, viewportH); |
| gl.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT); |
| gl.enable(GL_DEPTH_TEST); |
| |
| static const deUint16 quadIndices[] = { 0, 1, 2, 2, 1, 3 }; |
| |
| // Fill viewport with 2 quads - one with constant depth and another with d = [-1..1] |
| { |
| glu::ShaderProgram basicQuadProgram(m_context.getRenderContext(), glu::makeVtxFragSources(s_vertexShaderSrc, s_defaultFragmentShaderSrc)); |
| |
| if (!basicQuadProgram.isOk()) |
| { |
| log << basicQuadProgram; |
| TCU_FAIL("Compile failed"); |
| } |
| |
| const float constDepthCoord[] = |
| { |
| -1.0f, -1.0f, constDepth, 1.0f, |
| -1.0f, +1.0f, constDepth, 1.0f, |
| 0.0f, -1.0f, constDepth, 1.0f, |
| 0.0f, +1.0f, constDepth, 1.0f |
| }; |
| const float varyingDepthCoord[] = |
| { |
| 0.0f, -1.0f, +1.0f, 1.0f, |
| 0.0f, +1.0f, 0.0f, 1.0f, |
| +1.0f, -1.0f, 0.0f, 1.0f, |
| +1.0f, +1.0f, -1.0f, 1.0f |
| }; |
| |
| gl.useProgram(basicQuadProgram.getProgram()); |
| gl.uniform4f(gl.getUniformLocation(basicQuadProgram.getProgram(), "u_color"), 0.0f, 0.0f, 1.0f, 1.0f); |
| gl.depthFunc(GL_ALWAYS); |
| |
| { |
| glu::VertexArrayBinding posBinding = glu::va::Float("a_position", 4, 4, 0, &constDepthCoord[0]); |
| glu::draw(m_context.getRenderContext(), basicQuadProgram.getProgram(), 1, &posBinding, |
| glu::pr::Triangles(DE_LENGTH_OF_ARRAY(quadIndices), &quadIndices[0])); |
| } |
| |
| { |
| glu::VertexArrayBinding posBinding = glu::va::Float("a_position", 4, 4, 0, &varyingDepthCoord[0]); |
| glu::draw(m_context.getRenderContext(), basicQuadProgram.getProgram(), 1, &posBinding, |
| glu::pr::Triangles(DE_LENGTH_OF_ARRAY(quadIndices), &quadIndices[0])); |
| } |
| |
| GLU_EXPECT_NO_ERROR(gl.getError(), "Draw base quads"); |
| } |
| |
| // Render with depth test. |
| { |
| glu::ShaderProgram program(m_context.getRenderContext(), glu::makeVtxFragSources(s_vertexShaderSrc, m_fragSrc.c_str())); |
| log << program; |
| |
| if (!program.isOk()) |
| TCU_FAIL("Compile failed"); |
| |
| const float coord[] = |
| { |
| 0.0f, 0.0f, |
| 0.0f, 1.0f, |
| 1.0f, 0.0f, |
| 1.0f, 1.0f |
| }; |
| const float position[] = |
| { |
| -1.0f, -1.0f, +1.0f, 1.0f, |
| -1.0f, +1.0f, 0.0f, 1.0f, |
| +1.0f, -1.0f, 0.0f, 1.0f, |
| +1.0f, +1.0f, -1.0f, 1.0f |
| }; |
| |
| gl.useProgram(program.getProgram()); |
| gl.depthFunc(m_compareFunc); |
| gl.uniform4f(gl.getUniformLocation(program.getProgram(), "u_color"), 0.0f, 1.0f, 0.0f, 1.0f); |
| |
| // Setup default helper uniforms. |
| gls::setupDefaultUniforms(m_context.getRenderContext(), program.getProgram()); |
| |
| { |
| glu::VertexArrayBinding vertexArrays[] = |
| { |
| glu::va::Float("a_position", 4, 4, 0, &position[0]), |
| glu::va::Float("a_coord", 2, 4, 0, &coord[0]) |
| }; |
| glu::draw(m_context.getRenderContext(), program.getProgram(), DE_LENGTH_OF_ARRAY(vertexArrays), &vertexArrays[0], |
| glu::pr::Triangles(DE_LENGTH_OF_ARRAY(quadIndices), &quadIndices[0])); |
| } |
| |
| GLU_EXPECT_NO_ERROR(gl.getError(), "Draw test quad"); |
| } |
| |
| glu::readPixels(m_context.getRenderContext(), viewportX, viewportY, renderedFrame.getAccess()); |
| |
| // Render reference. |
| for (int y = 0; y < referenceFrame.getHeight(); y++) |
| { |
| float yf = ((float)y + 0.5f) / (float)referenceFrame.getHeight(); |
| int half = de::clamp((int)((float)referenceFrame.getWidth()*0.5f + 0.5f), 0, referenceFrame.getWidth()); |
| |
| // Fill left half - comparison to constant 0.5 |
| for (int x = 0; x < half; x++) |
| { |
| float xf = ((float)x + 0.5f) / (float)referenceFrame.getWidth(); |
| float d = m_evalFunc(Vec2(xf, yf)); |
| bool dpass = compare(m_compareFunc, d, constDepth*0.5f + 0.5f); |
| |
| referenceFrame.setPixel(x, y, dpass ? tcu::RGBA::green() : tcu::RGBA::blue()); |
| } |
| |
| // Fill right half - comparison to interpolated depth |
| for (int x = half; x < referenceFrame.getWidth(); x++) |
| { |
| float xf = ((float)x + 0.5f) / (float)referenceFrame.getWidth(); |
| float xh = ((float)(x - half) + 0.5f) / (float)(referenceFrame.getWidth()-half); |
| float rd = 1.0f - (xh + yf) * 0.5f; |
| float d = m_evalFunc(Vec2(xf, yf)); |
| bool dpass = compare(m_compareFunc, d, rd); |
| |
| referenceFrame.setPixel(x, y, dpass ? tcu::RGBA::green() : tcu::RGBA::blue()); |
| } |
| } |
| |
| bool isOk = tcu::fuzzyCompare(log, "Result", "Image comparison result", referenceFrame, renderedFrame, 0.05f, tcu::COMPARE_LOG_RESULT); |
| m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, |
| isOk ? "Pass" : "Fail"); |
| return STOP; |
| } |
| |
| class FragDepthWriteCase : public TestCase |
| { |
| public: |
| FragDepthWriteCase (Context& context, const char* name, const char* desc, const char* fragSrc, EvalFragDepthFunc evalFunc); |
| ~FragDepthWriteCase (void); |
| |
| IterateResult iterate (void); |
| |
| private: |
| string m_fragSrc; |
| EvalFragDepthFunc m_evalFunc; |
| }; |
| |
| FragDepthWriteCase::FragDepthWriteCase (Context& context, const char* name, const char* desc, const char* fragSrc, EvalFragDepthFunc evalFunc) |
| : TestCase (context, name, desc) |
| , m_fragSrc (fragSrc) |
| , m_evalFunc (evalFunc) |
| { |
| } |
| |
| FragDepthWriteCase::~FragDepthWriteCase (void) |
| { |
| } |
| |
| FragDepthWriteCase::IterateResult FragDepthWriteCase::iterate (void) |
| { |
| TestLog& log = m_testCtx.getLog(); |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| de::Random rnd (deStringHash(getName())); |
| const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget(); |
| int viewportW = de::min(128, renderTarget.getWidth()); |
| int viewportH = de::min(128, renderTarget.getHeight()); |
| int viewportX = rnd.getInt(0, renderTarget.getWidth()-viewportW); |
| int viewportY = rnd.getInt(0, renderTarget.getHeight()-viewportH); |
| tcu::Surface renderedFrame (viewportW, viewportH); |
| tcu::Surface referenceFrame (viewportW, viewportH); |
| const int numDepthSteps = 16; |
| const float depthStep = 1.0f/(float)(numDepthSteps-1); |
| |
| if (renderTarget.getDepthBits() == 0) |
| throw tcu::NotSupportedError("Depth buffer is required", "", __FILE__, __LINE__); |
| |
| gl.viewport(viewportX, viewportY, viewportW, viewportH); |
| gl.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT); |
| gl.enable(GL_DEPTH_TEST); |
| gl.depthFunc(GL_LESS); |
| |
| static const deUint16 quadIndices[] = { 0, 1, 2, 2, 1, 3 }; |
| |
| // Render with given shader. |
| { |
| glu::ShaderProgram program(m_context.getRenderContext(), glu::makeVtxFragSources(s_vertexShaderSrc, m_fragSrc.c_str())); |
| log << program; |
| |
| if (!program.isOk()) |
| TCU_FAIL("Compile failed"); |
| |
| const float coord[] = |
| { |
| 0.0f, 0.0f, |
| 0.0f, 1.0f, |
| 1.0f, 0.0f, |
| 1.0f, 1.0f |
| }; |
| const float position[] = |
| { |
| -1.0f, -1.0f, +1.0f, 1.0f, |
| -1.0f, +1.0f, 0.0f, 1.0f, |
| +1.0f, -1.0f, 0.0f, 1.0f, |
| +1.0f, +1.0f, -1.0f, 1.0f |
| }; |
| |
| gl.useProgram(program.getProgram()); |
| gl.uniform4f(gl.getUniformLocation(program.getProgram(), "u_color"), 0.0f, 1.0f, 0.0f, 1.0f); |
| |
| // Setup default helper uniforms. |
| gls::setupDefaultUniforms(m_context.getRenderContext(), program.getProgram()); |
| |
| { |
| glu::VertexArrayBinding vertexArrays[] = |
| { |
| glu::va::Float("a_position", 4, 4, 0, &position[0]), |
| glu::va::Float("a_coord", 2, 4, 0, &coord[0]) |
| }; |
| glu::draw(m_context.getRenderContext(), program.getProgram(), DE_LENGTH_OF_ARRAY(vertexArrays), &vertexArrays[0], |
| glu::pr::Triangles(DE_LENGTH_OF_ARRAY(quadIndices), &quadIndices[0])); |
| } |
| |
| GLU_EXPECT_NO_ERROR(gl.getError(), "Draw test quad"); |
| } |
| |
| // Visualize by rendering full-screen quads with increasing depth and color. |
| { |
| glu::ShaderProgram program (m_context.getRenderContext(), glu::makeVtxFragSources(s_vertexShaderSrc, s_defaultFragmentShaderSrc)); |
| if (!program.isOk()) |
| { |
| log << program; |
| TCU_FAIL("Compile failed"); |
| } |
| |
| int posLoc = gl.getAttribLocation(program.getProgram(), "a_position"); |
| int colorLoc = gl.getUniformLocation(program.getProgram(), "u_color"); |
| |
| gl.useProgram(program.getProgram()); |
| gl.depthMask(GL_FALSE); |
| |
| for (int stepNdx = 0; stepNdx < numDepthSteps; stepNdx++) |
| { |
| float f = (float)stepNdx*depthStep; |
| float depth = f*2.0f - 1.0f; |
| Vec4 color = Vec4(f, f, f, 1.0f); |
| |
| const float position[] = |
| { |
| -1.0f, -1.0f, depth, 1.0f, |
| -1.0f, +1.0f, depth, 1.0f, |
| +1.0f, -1.0f, depth, 1.0f, |
| +1.0f, +1.0f, depth, 1.0f |
| }; |
| glu::VertexArrayBinding posBinding = glu::va::Float(posLoc, 4, 4, 0, &position[0]); |
| |
| gl.uniform4fv(colorLoc, 1, color.getPtr()); |
| glu::draw(m_context.getRenderContext(), program.getProgram(), 1, &posBinding, |
| glu::pr::Triangles(DE_LENGTH_OF_ARRAY(quadIndices), &quadIndices[0])); |
| } |
| |
| GLU_EXPECT_NO_ERROR(gl.getError(), "Visualization draw"); |
| } |
| |
| glu::readPixels(m_context.getRenderContext(), viewportX, viewportY, renderedFrame.getAccess()); |
| |
| // Render reference. |
| for (int y = 0; y < referenceFrame.getHeight(); y++) |
| { |
| for (int x = 0; x < referenceFrame.getWidth(); x++) |
| { |
| float xf = ((float)x + 0.5f) / (float)referenceFrame.getWidth(); |
| float yf = ((float)y + 0.5f) / (float)referenceFrame.getHeight(); |
| float d = m_evalFunc(Vec2(xf, yf)); |
| int step = (int)deFloatFloor(d / depthStep); |
| int col = de::clamp(deRoundFloatToInt32((float)step*depthStep*255.0f), 0, 255); |
| |
| referenceFrame.setPixel(x, y, tcu::RGBA(col, col, col, 0xff)); |
| } |
| } |
| |
| bool isOk = tcu::fuzzyCompare(log, "Result", "Image comparison result", referenceFrame, renderedFrame, 0.05f, tcu::COMPARE_LOG_RESULT); |
| m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, |
| isOk ? "Pass" : "Fail"); |
| return STOP; |
| } |
| |
| FragDepthTests::FragDepthTests (Context& context) |
| : TestCaseGroup(context, "fragdepth", "gl_FragDepth tests") |
| { |
| } |
| |
| FragDepthTests::~FragDepthTests (void) |
| { |
| } |
| |
| static float evalConstDepth (const Vec2& coord) { DE_UNREF(coord); return 0.5f; } |
| static float evalDynamicDepth (const Vec2& coord) { return (coord.x()+coord.y())*0.5f; } |
| static float evalNoWrite (const Vec2& coord) { return 1.0f - (coord.x()+coord.y())*0.5f; } |
| |
| static float evalDynamicConditionalDepth (const Vec2& coord) |
| { |
| float d = (coord.x()+coord.y())*0.5f; |
| if (coord.y() < 0.5f) |
| return d; |
| else |
| return 1.0f - d; |
| } |
| |
| void FragDepthTests::init (void) |
| { |
| static const struct |
| { |
| const char* name; |
| const char* desc; |
| EvalFragDepthFunc evalFunc; |
| const char* fragSrc; |
| } cases[] = |
| { |
| { |
| "no_write", "No gl_FragDepth write", evalNoWrite, |
| "#version 300 es\n" |
| "uniform highp vec4 u_color;\n" |
| "layout(location = 0) out mediump vec4 o_color;\n" |
| "void main (void)\n" |
| "{\n" |
| " o_color = u_color;\n" |
| "}\n" |
| }, |
| { |
| "const", "Const depth write", evalConstDepth, |
| "#version 300 es\n" |
| "uniform highp vec4 u_color;\n" |
| "layout(location = 0) out mediump vec4 o_color;\n" |
| "void main (void)\n" |
| "{\n" |
| " o_color = u_color;\n" |
| " gl_FragDepth = 0.5;\n" |
| "}\n" |
| }, |
| { |
| "uniform", "Uniform depth write", evalConstDepth, |
| "#version 300 es\n" |
| "uniform highp vec4 u_color;\n" |
| "uniform highp float uf_half;\n" |
| "layout(location = 0) out mediump vec4 o_color;\n" |
| "void main (void)\n" |
| "{\n" |
| " o_color = u_color;\n" |
| " gl_FragDepth = uf_half;\n" |
| "}\n" |
| }, |
| { |
| "dynamic", "Dynamic depth write", evalDynamicDepth, |
| "#version 300 es\n" |
| "uniform highp vec4 u_color;\n" |
| "in highp vec2 v_coord;\n" |
| "layout(location = 0) out mediump vec4 o_color;\n" |
| "void main (void)\n" |
| "{\n" |
| " o_color = u_color;\n" |
| " gl_FragDepth = (v_coord.x+v_coord.y)*0.5;\n" |
| "}\n" |
| }, |
| { |
| "fragcoord_z", "gl_FragDepth write from gl_FragCoord.z", evalNoWrite, |
| "#version 300 es\n" |
| "uniform highp vec4 u_color;\n" |
| "layout(location = 0) out mediump vec4 o_color;\n" |
| "void main (void)\n" |
| "{\n" |
| " o_color = u_color;\n" |
| " gl_FragDepth = gl_FragCoord.z;\n" |
| "}\n" |
| }, |
| { |
| "uniform_conditional_write", "Uniform conditional write", evalDynamicDepth, |
| "#version 300 es\n" |
| "uniform highp vec4 u_color;\n" |
| "uniform bool ub_true;\n" |
| "in highp vec2 v_coord;\n" |
| "layout(location = 0) out mediump vec4 o_color;\n" |
| "void main (void)\n" |
| "{\n" |
| " o_color = u_color;\n" |
| " if (ub_true)\n" |
| " gl_FragDepth = (v_coord.x+v_coord.y)*0.5;\n" |
| "}\n" |
| }, |
| { |
| "dynamic_conditional_write", "Uniform conditional write", evalDynamicConditionalDepth, |
| "#version 300 es\n" |
| "uniform highp vec4 u_color;\n" |
| "uniform bool ub_true;\n" |
| "in highp vec2 v_coord;\n" |
| "layout(location = 0) out mediump vec4 o_color;\n" |
| "void main (void)\n" |
| "{\n" |
| " o_color = u_color;\n" |
| " mediump float d = (v_coord.x+v_coord.y)*0.5f;\n" |
| " if (v_coord.y < 0.5)\n" |
| " gl_FragDepth = d;\n" |
| " else\n" |
| " gl_FragDepth = 1.0 - d;\n" |
| "}\n" |
| }, |
| { |
| "uniform_loop_write", "Uniform loop write", evalConstDepth, |
| "#version 300 es\n" |
| "uniform highp vec4 u_color;\n" |
| "uniform int ui_two;\n" |
| "uniform highp float uf_fourth;\n" |
| "in highp vec2 v_coord;\n" |
| "layout(location = 0) out mediump vec4 o_color;\n" |
| "void main (void)\n" |
| "{\n" |
| " o_color = u_color;\n" |
| " gl_FragDepth = 0.0;\n" |
| " for (int i = 0; i < ui_two; i++)\n" |
| " gl_FragDepth += uf_fourth;\n" |
| "}\n" |
| }, |
| { |
| "write_in_function", "Uniform loop write", evalDynamicDepth, |
| "#version 300 es\n" |
| "uniform highp vec4 u_color;\n" |
| "uniform highp float uf_half;\n" |
| "in highp vec2 v_coord;\n" |
| "layout(location = 0) out mediump vec4 o_color;\n" |
| "void myfunc (highp vec2 coord)\n" |
| "{\n" |
| " gl_FragDepth = (coord.x+coord.y)*0.5;\n" |
| "}\n" |
| "void main (void)\n" |
| "{\n" |
| " o_color = u_color;\n" |
| " myfunc(v_coord);\n" |
| "}\n" |
| } |
| }; |
| |
| // .write |
| tcu::TestCaseGroup* writeGroup = new tcu::TestCaseGroup(m_testCtx, "write", "gl_FragDepth write tests"); |
| addChild(writeGroup); |
| for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(cases); ndx++) |
| writeGroup->addChild(new FragDepthWriteCase(m_context, cases[ndx].name, cases[ndx].desc, cases[ndx].fragSrc, cases[ndx].evalFunc)); |
| |
| // .compare |
| tcu::TestCaseGroup* compareGroup = new tcu::TestCaseGroup(m_testCtx, "compare", "gl_FragDepth used with depth comparison"); |
| addChild(compareGroup); |
| for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(cases); ndx++) |
| compareGroup->addChild(new FragDepthCompareCase(m_context, cases[ndx].name, cases[ndx].desc, cases[ndx].fragSrc, cases[ndx].evalFunc, GL_LESS)); |
| } |
| |
| } // Functional |
| } // gles3 |
| } // deqp |