/*------------------------------------------------------------------------- * drawElements Quality Program OpenGL ES 3.1 Module * ------------------------------------------------- * * Copyright 2017 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 EXT Shader Framebuffer Fetch Tests. *//*--------------------------------------------------------------------*/ #include "es31fShaderFramebufferFetchTests.hpp" #include "es31fFboTestUtil.hpp" #include "tcuTestLog.hpp" #include "tcuSurface.hpp" #include "tcuTextureUtil.hpp" #include "tcuImageCompare.hpp" #include "tcuVectorUtil.hpp" #include "gluShaderProgram.hpp" #include "gluPixelTransfer.hpp" #include "gluTextureUtil.hpp" #include "gluContextInfo.hpp" #include "gluObjectWrapper.hpp" #include "glwFunctions.hpp" #include "glwEnums.hpp" #include "deStringUtil.hpp" #include <vector> namespace deqp { namespace gles31 { namespace Functional { namespace { using std::vector; using std::string; using tcu::TestLog; using namespace glw; using namespace FboTestUtil; static void checkExtensionSupport (Context& context, const char* extName) { if (!context.getContextInfo().isExtensionSupported(extName)) throw tcu::NotSupportedError(string(extName) + " not supported"); } static void checkFramebufferFetchSupport (Context& context) { checkExtensionSupport(context, "GL_EXT_shader_framebuffer_fetch"); } static bool isRequiredFormat (deUint32 format, glu::RenderContext& renderContext) { const bool isES32 = glu::contextSupports(renderContext.getType(), glu::ApiType::es(3, 2)); switch (format) { // Color-renderable formats case GL_RGBA32I: case GL_RGBA32UI: case GL_RGBA16I: case GL_RGBA16UI: case GL_RGBA8: case GL_RGBA8I: case GL_RGBA8UI: case GL_SRGB8_ALPHA8: case GL_RGB10_A2: case GL_RGB10_A2UI: case GL_RGBA4: case GL_RGB5_A1: case GL_RGB8: case GL_RGB565: case GL_RG32I: case GL_RG32UI: case GL_RG16I: case GL_RG16UI: case GL_RG8: case GL_RG8I: case GL_RG8UI: case GL_R32I: case GL_R32UI: case GL_R16I: case GL_R16UI: case GL_R8: case GL_R8I: case GL_R8UI: return true; // Float format case GL_RGBA32F: case GL_RGB32F: case GL_R11F_G11F_B10F: case GL_RG32F: case GL_R32F: return isES32; default: return false; } } tcu::TextureFormat getReadPixelFormat (const tcu::TextureFormat& format) { switch (tcu::getTextureChannelClass(format.type)) { case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER: return tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNSIGNED_INT32); case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER: return tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::SIGNED_INT32); case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT: case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT: return tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8); case tcu::TEXTURECHANNELCLASS_FLOATING_POINT: return tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::FLOAT); default: DE_ASSERT(false); return tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8); } } tcu::Vec4 getFixedPointFormatThreshold (const tcu::TextureFormat& sourceFormat, const tcu::TextureFormat& readPixelsFormat) { DE_ASSERT(tcu::getTextureChannelClass(sourceFormat.type) != tcu::TEXTURECHANNELCLASS_FLOATING_POINT); DE_ASSERT(tcu::getTextureChannelClass(readPixelsFormat.type) != tcu::TEXTURECHANNELCLASS_FLOATING_POINT); DE_ASSERT(tcu::getTextureChannelClass(sourceFormat.type) != tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER); DE_ASSERT(tcu::getTextureChannelClass(readPixelsFormat.type) != tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER); DE_ASSERT(tcu::getTextureChannelClass(sourceFormat.type) != tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER); DE_ASSERT(tcu::getTextureChannelClass(readPixelsFormat.type) != tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER); const tcu::IVec4 srcBits = tcu::getTextureFormatBitDepth(sourceFormat); const tcu::IVec4 readBits = tcu::getTextureFormatBitDepth(readPixelsFormat); return tcu::Vec4(3.0f) / ((tcu::Vector<deUint64, 4>(1) << (tcu::min(srcBits, readBits).cast<deUint64>())) - tcu::Vector<deUint64, 4>(1)).cast<float>(); } tcu::UVec4 getFloatULPThreshold (const tcu::TextureFormat& sourceFormat, const tcu::TextureFormat& readPixelsFormat) { const tcu::IVec4 srcMantissaBits = tcu::getTextureFormatMantissaBitDepth(sourceFormat); const tcu::IVec4 readMantissaBits = tcu::getTextureFormatMantissaBitDepth(readPixelsFormat); tcu::IVec4 ULPDiff(0); for (int i = 0; i < 4; i++) if (readMantissaBits[i] >= srcMantissaBits[i]) ULPDiff[i] = readMantissaBits[i] - srcMantissaBits[i]; return tcu::UVec4(4) * (tcu::UVec4(1) << (ULPDiff.cast<deUint32>())); } static bool isAnyExtensionSupported (Context& context, const std::vector<std::string>& requiredExts) { for (std::vector<std::string>::const_iterator iter = requiredExts.begin(); iter != requiredExts.end(); iter++) { const std::string& extension = *iter; if (context.getContextInfo().isExtensionSupported(extension.c_str())) return true; } return false; } static std::string getColorOutputType(tcu::TextureFormat format) { switch (tcu::getTextureChannelClass(format.type)) { case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER: return "uvec4"; case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER: return "ivec4"; case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT: case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT: case tcu::TEXTURECHANNELCLASS_FLOATING_POINT: return "vec4"; default: DE_FATAL("Unsupported TEXTURECHANNELCLASS"); return ""; } } static std::vector<std::string> getEnablingExtensions (deUint32 format, glu::RenderContext& renderContext) { const bool isES32 = glu::contextSupports(renderContext.getType(), glu::ApiType::es(3, 2)); std::vector<std::string> out; DE_ASSERT(!isRequiredFormat(format, renderContext)); switch (format) { case GL_RGB16F: out.push_back("GL_EXT_color_buffer_half_float"); break; case GL_RGBA16F: case GL_RG16F: case GL_R16F: out.push_back("GL_EXT_color_buffer_half_float"); // Fallthrough case GL_RGBA32F: case GL_RGB32F: case GL_R11F_G11F_B10F: case GL_RG32F: case GL_R32F: if (!isES32) out.push_back("GL_EXT_color_buffer_float"); break; default: break; } return out; } void checkFormatSupport (Context& context, deUint32 sizedFormat) { const bool isCoreFormat = isRequiredFormat(sizedFormat, context.getRenderContext()); const std::vector<std::string> requiredExts = (!isCoreFormat) ? getEnablingExtensions(sizedFormat, context.getRenderContext()) : std::vector<std::string>(); // Check that we don't try to use invalid formats. DE_ASSERT(isCoreFormat || !requiredExts.empty()); if (!requiredExts.empty() && !isAnyExtensionSupported(context, requiredExts)) throw tcu::NotSupportedError("Format not supported"); } tcu::Vec4 scaleColorValue (tcu::TextureFormat format, const tcu::Vec4& color) { const tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(format); const tcu::Vec4 cScale = fmtInfo.valueMax-fmtInfo.valueMin; const tcu::Vec4 cBias = fmtInfo.valueMin; return tcu::RGBA(color).toVec() * cScale + cBias; } // Base class for framebuffer fetch test cases class FramebufferFetchTestCase : public TestCase { public: FramebufferFetchTestCase (Context& context, const char* name, const char* desc, deUint32 format); ~FramebufferFetchTestCase (void); void init (void); void deinit (void); protected: string genPassThroughVertSource (void); virtual glu::ProgramSources genShaderSources (void); void genFramebufferWithTexture (const tcu::Vec4& color); void genAttachementTexture (const tcu::Vec4& color); void genUniformColor (const tcu::Vec4& color); void render (void); void verifyRenderbuffer (TestLog& log, const tcu::TextureFormat& format, const tcu::TextureLevel& reference, const tcu::TextureLevel& result); const glw::Functions& m_gl; const deUint32 m_format; glu::ShaderProgram* m_program; GLuint m_framebuffer; GLuint m_texColorBuffer; tcu::TextureFormat m_texFmt; glu::TransferFormat m_transferFmt; bool m_isFilterable; enum { VIEWPORT_WIDTH = 64, VIEWPORT_HEIGHT = 64, }; }; FramebufferFetchTestCase::FramebufferFetchTestCase (Context& context, const char* name, const char* desc, deUint32 format) : TestCase (context, name, desc) , m_gl (m_context.getRenderContext().getFunctions()) , m_format (format) , m_program (DE_NULL) , m_framebuffer (0) , m_texColorBuffer (0) , m_texFmt (glu::mapGLInternalFormat(m_format)) , m_transferFmt (glu::getTransferFormat(m_texFmt)) , m_isFilterable (glu::isGLInternalColorFormatFilterable(m_format)) { } FramebufferFetchTestCase::~FramebufferFetchTestCase (void) { FramebufferFetchTestCase::deinit(); } void FramebufferFetchTestCase::init (void) { checkFramebufferFetchSupport (m_context); checkFormatSupport(m_context, m_format); DE_ASSERT(!m_program); m_program = new glu::ShaderProgram(m_context.getRenderContext(), genShaderSources()); m_testCtx.getLog() << *m_program; if (!m_program->isOk()) { delete m_program; m_program = DE_NULL; TCU_FAIL("Failed to compile shader program"); } m_gl.useProgram(m_program->getProgram()); } void FramebufferFetchTestCase::deinit (void) { delete m_program; m_program = DE_NULL; if (m_framebuffer) { m_gl.bindFramebuffer(GL_FRAMEBUFFER, 0); m_gl.deleteFramebuffers(1, &m_framebuffer); m_framebuffer = 0; } if (m_texColorBuffer) { m_gl.deleteTextures(1, &m_texColorBuffer); m_texColorBuffer = 0; } } string FramebufferFetchTestCase::genPassThroughVertSource (void) { std::ostringstream vertShaderSource; vertShaderSource << "#version 310 es\n" << "in highp vec4 a_position;\n" << "\n" << "void main (void)\n" << "{\n" << " gl_Position = a_position;\n" << "}\n"; return vertShaderSource.str(); } glu::ProgramSources FramebufferFetchTestCase::genShaderSources (void) { const string vecType = getColorOutputType(m_texFmt); std::ostringstream fragShaderSource; fragShaderSource << "#version 310 es\n" << "#extension GL_EXT_shader_framebuffer_fetch : require\n" << "layout(location = 0) inout highp " << vecType << " o_color;\n" << "uniform highp " << vecType << " u_color;\n" << "\n" << "void main (void)\n" << "{\n" << " o_color += u_color;\n" << "}\n"; return glu::makeVtxFragSources(genPassThroughVertSource(), fragShaderSource.str()); } void FramebufferFetchTestCase::genFramebufferWithTexture (const tcu::Vec4& color) { m_gl.genFramebuffers(1, &m_framebuffer); m_gl.bindFramebuffer(GL_FRAMEBUFFER, m_framebuffer); genAttachementTexture(color); GLU_EXPECT_NO_ERROR(m_gl.getError(), "genAttachementTexture()"); m_gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texColorBuffer, 0); TCU_CHECK(m_gl.checkFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE); } void FramebufferFetchTestCase::genAttachementTexture (const tcu::Vec4& color) { tcu::TextureLevel data (glu::mapGLTransferFormat(m_transferFmt.format, m_transferFmt.dataType), VIEWPORT_WIDTH, VIEWPORT_HEIGHT, 1); tcu::TextureChannelClass textureChannelClass = tcu::getTextureChannelClass(m_texFmt.type); m_gl.genTextures(1, &m_texColorBuffer); m_gl.bindTexture(GL_TEXTURE_2D, m_texColorBuffer); m_gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); m_gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); m_gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); m_gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, m_isFilterable ? GL_LINEAR : GL_NEAREST); m_gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, m_isFilterable ? GL_LINEAR : GL_NEAREST); if (textureChannelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER) tcu::clear(data.getAccess(), color.asUint()); else if (textureChannelClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER) tcu::clear(data.getAccess(), color.asInt()); else tcu::clear(data.getAccess(), color); m_gl.texImage2D(GL_TEXTURE_2D, 0, m_format, VIEWPORT_WIDTH, VIEWPORT_HEIGHT, 0, m_transferFmt.format, m_transferFmt.dataType, data.getAccess().getDataPtr()); m_gl.bindTexture(GL_TEXTURE_2D, 0); } void FramebufferFetchTestCase::verifyRenderbuffer (TestLog& log, const tcu::TextureFormat& format, const tcu::TextureLevel& reference, const tcu::TextureLevel& result) { m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); switch (tcu::getTextureChannelClass(format.type)) { case tcu::TEXTURECHANNELCLASS_FLOATING_POINT: { const string name = "Renderbuffer"; const string desc = "Compare renderbuffer (floating_point)"; const tcu::UVec4 threshold = getFloatULPThreshold(format, result.getFormat()); if (!tcu::floatUlpThresholdCompare(log, name.c_str(), desc.c_str(), reference, result, threshold, tcu::COMPARE_LOG_RESULT)) m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); break; } case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER: case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER: { const string name = "Renderbuffer"; const string desc = "Compare renderbuffer (integer)"; const tcu::UVec4 threshold (1, 1, 1, 1); if (!tcu::intThresholdCompare(log, name.c_str(), desc.c_str(), reference, result, threshold, tcu::COMPARE_LOG_RESULT)) m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); break; } case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT: case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT: { const string name = "Renderbuffer"; const string desc = "Compare renderbuffer (fixed point)"; const tcu::Vec4 threshold = getFixedPointFormatThreshold(format, result.getFormat()); if (!tcu::floatThresholdCompare(log, name.c_str(), desc.c_str(), reference, result, threshold, tcu::COMPARE_LOG_RESULT)) m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); break; } default: { DE_ASSERT(DE_FALSE); m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); } } } void FramebufferFetchTestCase::genUniformColor (const tcu::Vec4& color) { const GLuint colorLocation = m_gl.getUniformLocation(m_program->getProgram(), "u_color"); switch (tcu::getTextureChannelClass(m_texFmt.type)) { case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER: { m_gl.uniform4uiv(colorLocation, 1, color.asUint().getPtr()); break; } case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER: { m_gl.uniform4iv(colorLocation, 1, color.asInt().getPtr()); break; } case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT: case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT: case tcu::TEXTURECHANNELCLASS_FLOATING_POINT: { m_gl.uniform4fv(colorLocation, 1, color.asFloat().getPtr()); break; } default: DE_ASSERT(DE_FALSE); } GLU_EXPECT_NO_ERROR(m_gl.getError(), "genUniformColor()"); } void FramebufferFetchTestCase::render (void) { const GLfloat coords[] = { -1.0f, -1.0f, +1.0f, -1.0f, +1.0f, +1.0f, -1.0f, +1.0f, }; const GLushort indices[] = { 0, 1, 2, 2, 3, 0, }; const GLuint coordLocation = m_gl.getAttribLocation(m_program->getProgram(), "a_position"); m_gl.viewport(0, 0, VIEWPORT_WIDTH, VIEWPORT_HEIGHT); glu::Buffer coordinatesBuffer(m_context.getRenderContext()); glu::Buffer elementsBuffer(m_context.getRenderContext()); m_gl.bindBuffer(GL_ARRAY_BUFFER, *coordinatesBuffer); m_gl.bufferData(GL_ARRAY_BUFFER, (GLsizeiptr)sizeof(coords), coords, GL_STATIC_DRAW); m_gl.enableVertexAttribArray(coordLocation); m_gl.vertexAttribPointer(coordLocation, 2, GL_FLOAT, GL_FALSE, 0, DE_NULL); m_gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, *elementsBuffer); m_gl.bufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)sizeof(indices), &indices[0], GL_STATIC_DRAW); m_gl.drawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, DE_NULL); GLU_EXPECT_NO_ERROR(m_gl.getError(), "render()"); } // Test description: // - Attach texture containing solid color to framebuffer. // - Draw full quad covering the entire viewport. // - Sum framebuffer read color with passed in uniform color. // - Compare resulting surface with reference. class TextureFormatTestCase : public FramebufferFetchTestCase { public: TextureFormatTestCase (Context& context, const char* name, const char* desc, deUint32 format); ~TextureFormatTestCase (void) {}; IterateResult iterate (void); private: tcu::TextureLevel genReferenceTexture (const tcu::Vec4& fbColor, const tcu::Vec4& uniformColor); }; TextureFormatTestCase::TextureFormatTestCase (Context& context, const char* name, const char* desc, deUint32 format) : FramebufferFetchTestCase(context, name, desc, format) { } tcu::TextureLevel TextureFormatTestCase::genReferenceTexture (const tcu::Vec4& fbColor, const tcu::Vec4& uniformColor) { tcu::TextureLevel reference (glu::mapGLTransferFormat(m_transferFmt.format, m_transferFmt.dataType), VIEWPORT_WIDTH, VIEWPORT_HEIGHT, 1); tcu::TextureChannelClass textureChannelClass = tcu::getTextureChannelClass(m_texFmt.type); if (textureChannelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER) { tcu::clear(reference.getAccess(), fbColor.asUint() + uniformColor.asUint()); } else if (textureChannelClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER) { tcu::clear(reference.getAccess(), fbColor.asInt() + uniformColor.asInt()); } else { if (tcu::isSRGB(m_texFmt)) { const tcu::Vec4 fragmentColor = tcu::sRGBToLinear(fbColor) + uniformColor; tcu::clear(reference.getAccess(), tcu::linearToSRGB(fragmentColor)); } else { tcu::clear(reference.getAccess(), fbColor + uniformColor); } } return reference; } TextureFormatTestCase::IterateResult TextureFormatTestCase::iterate (void) { const tcu::Vec4 uniformColor = scaleColorValue(m_texFmt, tcu::Vec4(0.1f, 0.1f, 0.1f, 1.0f)); const tcu::Vec4 fbColor = scaleColorValue(m_texFmt, tcu::Vec4(0.5f, 0.0f, 0.0f, 1.0f)); tcu::TextureLevel reference = genReferenceTexture(fbColor, uniformColor); tcu::TextureLevel result (getReadPixelFormat(m_texFmt), VIEWPORT_WIDTH, VIEWPORT_HEIGHT); genFramebufferWithTexture(fbColor); genUniformColor(uniformColor); render(); glu::readPixels(m_context.getRenderContext(), 0, 0, result.getAccess()); verifyRenderbuffer(m_testCtx.getLog(), m_texFmt, reference, result); return STOP; } // Test description: // - Attach multiple textures containing solid colors to framebuffer. // - Draw full quad covering the entire viewport. // - For each render target sum framebuffer read color with passed in uniform color. // - Compare resulting surfaces with references. class MultipleRenderTargetsTestCase : public FramebufferFetchTestCase { public: MultipleRenderTargetsTestCase (Context& context, const char* name, const char* desc, deUint32 format); ~MultipleRenderTargetsTestCase (void); IterateResult iterate (void); void deinit (void); private: void genFramebufferWithTextures (const vector<tcu::Vec4>& colors); void genAttachmentTextures (const vector<tcu::Vec4>& colors); tcu::TextureLevel genReferenceTexture (const tcu::Vec4& fbColor, const tcu::Vec4& uniformColor); glu::ProgramSources genShaderSources (void); enum { MAX_COLOR_BUFFERS = 4 }; GLuint m_texColorBuffers [MAX_COLOR_BUFFERS]; GLenum m_colorBuffers [MAX_COLOR_BUFFERS]; }; MultipleRenderTargetsTestCase::MultipleRenderTargetsTestCase (Context& context, const char* name, const char* desc, deUint32 format) : FramebufferFetchTestCase(context, name, desc, format) , m_texColorBuffers () { m_colorBuffers[0] = GL_COLOR_ATTACHMENT0; m_colorBuffers[1] = GL_COLOR_ATTACHMENT1; m_colorBuffers[2] = GL_COLOR_ATTACHMENT2; m_colorBuffers[3] = GL_COLOR_ATTACHMENT3; } MultipleRenderTargetsTestCase::~MultipleRenderTargetsTestCase (void) { MultipleRenderTargetsTestCase::deinit(); } void MultipleRenderTargetsTestCase::deinit (void) { // Clean up texture data for (int i = 0; i < DE_LENGTH_OF_ARRAY(m_texColorBuffers); ++i) { if (m_texColorBuffers[i]) m_context.getRenderContext().getFunctions().deleteTextures(1, &m_texColorBuffers[i]); } FramebufferFetchTestCase::deinit(); } void MultipleRenderTargetsTestCase::genFramebufferWithTextures (const vector<tcu::Vec4>& colors) { m_gl.genFramebuffers(1, &m_framebuffer); m_gl.bindFramebuffer(GL_FRAMEBUFFER, m_framebuffer); genAttachmentTextures(colors); for (int i = 0; i < DE_LENGTH_OF_ARRAY(m_texColorBuffers); ++i) m_gl.framebufferTexture2D(GL_FRAMEBUFFER, m_colorBuffers[i], GL_TEXTURE_2D, m_texColorBuffers[i], 0); TCU_CHECK(m_gl.checkFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE); m_gl.drawBuffers((glw::GLsizei)MAX_COLOR_BUFFERS, &m_colorBuffers[0]); GLU_EXPECT_NO_ERROR(m_gl.getError(), "genFramebufferWithTextures()"); } void MultipleRenderTargetsTestCase::genAttachmentTextures (const vector<tcu::Vec4>& colors) { tcu::TextureLevel data (glu::mapGLTransferFormat(m_transferFmt.format, m_transferFmt.dataType), VIEWPORT_WIDTH, VIEWPORT_HEIGHT, 1); m_gl.genTextures(MAX_COLOR_BUFFERS, m_texColorBuffers); for (int i = 0; i < DE_LENGTH_OF_ARRAY(m_texColorBuffers); ++i) { m_gl.bindTexture(GL_TEXTURE_2D, m_texColorBuffers[i]); m_gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); m_gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); m_gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); m_gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, m_isFilterable ? GL_LINEAR : GL_NEAREST); m_gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, m_isFilterable ? GL_LINEAR : GL_NEAREST); clear(data.getAccess(), colors[i]); m_gl.texImage2D(GL_TEXTURE_2D, 0, m_format, VIEWPORT_WIDTH, VIEWPORT_HEIGHT, 0, m_transferFmt.format, m_transferFmt.dataType, data.getAccess().getDataPtr()); } m_gl.bindTexture(GL_TEXTURE_2D, 0); GLU_EXPECT_NO_ERROR(m_gl.getError(), "genAttachmentTextures()"); } tcu::TextureLevel MultipleRenderTargetsTestCase::genReferenceTexture (const tcu::Vec4& fbColor, const tcu::Vec4& uniformColor) { tcu::TextureLevel reference (glu::mapGLTransferFormat(m_transferFmt.format, m_transferFmt.dataType), VIEWPORT_WIDTH, VIEWPORT_HEIGHT, 1); tcu::clear(reference.getAccess(), fbColor + uniformColor); return reference; } glu::ProgramSources MultipleRenderTargetsTestCase::genShaderSources (void) { const string vecType = getColorOutputType(m_texFmt); std::ostringstream fragShaderSource; fragShaderSource << "#version 310 es\n" << "#extension GL_EXT_shader_framebuffer_fetch : require\n" << "layout(location = 0) inout highp " << vecType << " o_color0;\n" << "layout(location = 1) inout highp " << vecType << " o_color1;\n" << "layout(location = 2) inout highp " << vecType << " o_color2;\n" << "layout(location = 3) inout highp " << vecType << " o_color3;\n" << "uniform highp " << vecType << " u_color;\n" << "\n" << "void main (void)\n" << "{\n" << " o_color0 += u_color;\n" << " o_color1 += u_color;\n" << " o_color2 += u_color;\n" << " o_color3 += u_color;\n" << "}\n"; return glu::makeVtxFragSources(genPassThroughVertSource(), fragShaderSource.str()); } MultipleRenderTargetsTestCase::IterateResult MultipleRenderTargetsTestCase::iterate (void) { const tcu::Vec4 uniformColor = scaleColorValue(m_texFmt, tcu::Vec4(0.1f, 0.1f, 0.1f, 1.0f)); tcu::TextureLevel result (getReadPixelFormat(m_texFmt), VIEWPORT_WIDTH, VIEWPORT_HEIGHT); vector<tcu::Vec4> colors; colors.push_back(scaleColorValue(m_texFmt, tcu::Vec4(0.9f, 0.0f, 0.0f, 1.0f))); colors.push_back(scaleColorValue(m_texFmt, tcu::Vec4(0.0f, 0.9f, 0.0f, 1.0f))); colors.push_back(scaleColorValue(m_texFmt, tcu::Vec4(0.0f, 0.0f, 0.9f, 1.0f))); colors.push_back(scaleColorValue(m_texFmt, tcu::Vec4(0.0f, 0.9f, 0.9f, 1.0f))); genFramebufferWithTextures(colors); genUniformColor(uniformColor); render(); for (int i = 0; i < DE_LENGTH_OF_ARRAY(m_colorBuffers); ++i) { tcu::TextureLevel reference = genReferenceTexture(colors[i], uniformColor); m_gl.readBuffer(m_colorBuffers[i]); glu::readPixels(m_context.getRenderContext(), 0, 0, result.getAccess()); verifyRenderbuffer(m_testCtx.getLog(), m_texFmt, reference, result); } return STOP; } // Test description: // - Same as TextureFormatTestCase except uses built-in fragment output of ES 2.0 class LastFragDataTestCase : public FramebufferFetchTestCase { public: LastFragDataTestCase (Context& context, const char* name, const char* desc, deUint32 format); ~LastFragDataTestCase (void) {}; IterateResult iterate (void); private: glu::ProgramSources genShaderSources (void); tcu::TextureLevel genReferenceTexture (const tcu::Vec4& fbColor, const tcu::Vec4& uniformColor); }; LastFragDataTestCase::LastFragDataTestCase (Context& context, const char* name, const char* desc, deUint32 format) : FramebufferFetchTestCase(context, name, desc, format) { } glu::ProgramSources LastFragDataTestCase::genShaderSources (void) { const string vecType = getColorOutputType(m_texFmt); std::ostringstream vertShaderSource; std::ostringstream fragShaderSource; vertShaderSource << "#version 100\n" << "attribute vec4 a_position;\n" << "\n" << "void main (void)\n" << "{\n" << " gl_Position = a_position;\n" << "}\n"; fragShaderSource << "#version 100\n" << "#extension GL_EXT_shader_framebuffer_fetch : require\n" << "uniform highp " << vecType << " u_color;\n" << "\n" << "void main (void)\n" << "{\n" << " gl_FragColor = u_color + gl_LastFragData[0];\n" << "}\n"; return glu::makeVtxFragSources(vertShaderSource.str(), fragShaderSource.str()); } tcu::TextureLevel LastFragDataTestCase::genReferenceTexture (const tcu::Vec4& fbColor, const tcu::Vec4& uniformColor) { tcu::TextureLevel reference (glu::mapGLTransferFormat(m_transferFmt.format, m_transferFmt.dataType), VIEWPORT_WIDTH, VIEWPORT_HEIGHT, 1); tcu::clear(reference.getAccess(), fbColor + uniformColor); return reference; } LastFragDataTestCase::IterateResult LastFragDataTestCase::iterate (void) { const tcu::Vec4 uniformColor = scaleColorValue(m_texFmt, tcu::Vec4(0.1f, 0.1f, 0.1f, 1.0f)); const tcu::Vec4 fbColor = scaleColorValue(m_texFmt, tcu::Vec4(0.5f, 0.0f, 0.0f, 1.0f)); tcu::TextureLevel reference = genReferenceTexture(fbColor, uniformColor); tcu::TextureLevel result (getReadPixelFormat(m_texFmt), VIEWPORT_WIDTH, VIEWPORT_HEIGHT); genFramebufferWithTexture(fbColor); genUniformColor(uniformColor); render(); glu::readPixels(m_context.getRenderContext(), 0, 0, result.getAccess()); verifyRenderbuffer(m_testCtx.getLog(), m_texFmt, reference, result); return STOP; } // Test description: // - Attach texture containing solid color to framebuffer. // - Create one 2D texture for sampler with a grid pattern // - Draw full screen quad covering the entire viewport. // - Sum color values taken from framebuffer texture and sampled texture // - Compare resulting surface with reference. class TexelFetchTestCase : public FramebufferFetchTestCase { public: TexelFetchTestCase (Context& context, const char* name, const char* desc, deUint32 format); ~TexelFetchTestCase (void) {} IterateResult iterate (void); private: glu::ProgramSources genShaderSources (void); tcu::TextureLevel genReferenceTexture (const tcu::Vec4& colorEven, const tcu::Vec4& colorOdd, const tcu::Vec4& fbColor); void genSamplerTexture (const tcu::Vec4& colorEven, const tcu::Vec4& colorOdd); GLuint m_samplerTexture; }; TexelFetchTestCase::TexelFetchTestCase (Context& context, const char* name, const char* desc, deUint32 format) : FramebufferFetchTestCase(context, name, desc, format) , m_samplerTexture(0) { } void TexelFetchTestCase::genSamplerTexture (const tcu::Vec4& colorEven, const tcu::Vec4& colorOdd) { tcu::TextureLevel data (glu::mapGLTransferFormat(m_transferFmt.format, m_transferFmt.dataType), VIEWPORT_WIDTH, VIEWPORT_HEIGHT, 1); m_gl.activeTexture(GL_TEXTURE1); m_gl.genTextures(1, &m_samplerTexture); m_gl.bindTexture(GL_TEXTURE_2D, m_texColorBuffer); m_gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); m_gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); tcu::fillWithGrid(data.getAccess(), 8, colorEven, colorOdd); m_gl.texImage2D(GL_TEXTURE_2D, 0, m_format, VIEWPORT_WIDTH, VIEWPORT_HEIGHT, 0, m_transferFmt.format, m_transferFmt.dataType, data.getAccess().getDataPtr()); m_gl.bindTexture(GL_TEXTURE_2D, 0); const GLuint samplerLocation = m_gl.getUniformLocation(m_program->getProgram(), "u_sampler"); m_gl.uniform1i(samplerLocation, 1); GLU_EXPECT_NO_ERROR(m_gl.getError(), "genSamplerTexture()"); } glu::ProgramSources TexelFetchTestCase::genShaderSources (void) { const string vecType = getColorOutputType(m_texFmt); std::ostringstream fragShaderSource; fragShaderSource << "#version 310 es\n" << "#extension GL_EXT_shader_framebuffer_fetch : require\n" << "layout(location = 0) inout highp " << vecType << " o_color;\n" << "\n" << "uniform sampler2D u_sampler;\n" << "void main (void)\n" << "{\n" << " o_color += texelFetch(u_sampler, ivec2(gl_FragCoord), 0);\n" << "}\n"; return glu::makeVtxFragSources(genPassThroughVertSource(), fragShaderSource.str()); } tcu::TextureLevel TexelFetchTestCase::genReferenceTexture (const tcu::Vec4& colorEven, const tcu::Vec4& colorOdd, const tcu::Vec4& fbColor) { tcu::TextureLevel reference (glu::mapGLTransferFormat(m_transferFmt.format, m_transferFmt.dataType), VIEWPORT_WIDTH, VIEWPORT_HEIGHT, 1); tcu::fillWithGrid(reference.getAccess(), 8, colorEven + fbColor, colorOdd + fbColor); return reference; } TexelFetchTestCase::IterateResult TexelFetchTestCase::iterate (void) { const tcu::Vec4 fbColor = scaleColorValue(m_texFmt, tcu::Vec4(0.5f, 0.0f, 0.5f, 1.0f)); const tcu::Vec4 colorEven = scaleColorValue(m_texFmt, tcu::Vec4(0.5f, 0.5f, 0.0f, 1.0f)); const tcu::Vec4 colorOdd = scaleColorValue(m_texFmt, tcu::Vec4(0.5f, 0.0f, 0.5f, 1.0f)); genSamplerTexture(colorEven, colorOdd); tcu::TextureLevel reference = genReferenceTexture(colorEven, colorOdd, fbColor); tcu::TextureLevel result (getReadPixelFormat(m_texFmt), VIEWPORT_WIDTH, VIEWPORT_HEIGHT); genFramebufferWithTexture(fbColor); render(); glu::readPixels(m_context.getRenderContext(), 0, 0, result.getAccess()); verifyRenderbuffer(m_testCtx.getLog(), m_texFmt, reference, result); // cleanup m_gl.deleteTextures(1, &m_samplerTexture); return STOP; } // Test description: // - Attach texture containing solid color to framebuffer. // - Draw full screen quad covering the entire viewport. // - Multiple assignments are made to the output color for fragments on the right vertical half of the screen. // - A single assignment is made to the output color for fragments on the left vertical centre of the screen. // - Values are calculated using the sum of the passed in uniform color and the previous framebuffer color. // - Compare resulting surface with reference. class MultipleAssignmentTestCase : public FramebufferFetchTestCase { public: MultipleAssignmentTestCase (Context& context, const char* name, const char* desc, deUint32 format); ~MultipleAssignmentTestCase (void) {} IterateResult iterate (void); private: glu::ProgramSources genShaderSources (void); tcu::TextureLevel genReferenceTexture (const tcu::Vec4& fbColor, const tcu::Vec4& uniformColor); }; MultipleAssignmentTestCase::MultipleAssignmentTestCase (Context& context, const char* name, const char* desc, deUint32 format) : FramebufferFetchTestCase(context, name, desc, format) { } glu::ProgramSources MultipleAssignmentTestCase::genShaderSources (void) { const string vecType = getColorOutputType(m_texFmt); std::ostringstream vertShaderSource; std::ostringstream fragShaderSource; vertShaderSource << "#version 310 es\n" << "in highp vec4 a_position;\n" << "out highp vec4 v_position;\n" << "\n" << "void main (void)\n" << "{\n" << " gl_Position = a_position;\n" << " v_position = gl_Position;\n" << "}\n"; fragShaderSource << "#version 310 es\n" << "#extension GL_EXT_shader_framebuffer_fetch : require\n" << "in highp vec4 v_position;\n" << "layout(location = 0) inout highp " << vecType << " o_color;\n" << "uniform highp " << vecType << " u_color;\n" << "\n" << "void main (void)\n" << "{\n" << " if (v_position.x > 0.0f)\n" << " o_color += u_color;\n" << "\n" << " o_color += u_color;\n" << "}\n"; return glu::makeVtxFragSources(vertShaderSource.str(), fragShaderSource.str()); } tcu::TextureLevel MultipleAssignmentTestCase::genReferenceTexture (const tcu::Vec4& fbColor, const tcu::Vec4& uniformColor) { tcu::TextureLevel reference (glu::mapGLTransferFormat(m_transferFmt.format, m_transferFmt.dataType), VIEWPORT_WIDTH, VIEWPORT_HEIGHT, 1); int width = reference.getAccess().getWidth(); int height = reference.getAccess().getHeight(); int left = width /2; int top = height/2; tcu::Vec4 compositeColor(uniformColor * 2.0f); tcu::clear(getSubregion(reference.getAccess(), left, 0, 0, width-left, top, 1), fbColor + compositeColor); tcu::clear(getSubregion(reference.getAccess(), 0, top, 0, left, height-top, 1), fbColor + uniformColor); tcu::clear(getSubregion(reference.getAccess(), left, top, 0, width-left, height-top, 1), fbColor + compositeColor); tcu::clear(getSubregion(reference.getAccess(), 0, 0, 0, left, top, 1), fbColor + uniformColor); return reference; } MultipleAssignmentTestCase::IterateResult MultipleAssignmentTestCase::iterate (void) { const tcu::Vec4 fbColor = scaleColorValue(m_texFmt, tcu::Vec4(0.5f, 0.0f, 0.0f, 1.0f)); const tcu::Vec4 uniformColor = scaleColorValue(m_texFmt, tcu::Vec4(0.25f, 0.0f, 0.0f, 1.0f)); tcu::TextureLevel reference = genReferenceTexture(fbColor, uniformColor); tcu::TextureLevel result (getReadPixelFormat(m_texFmt), VIEWPORT_WIDTH, VIEWPORT_HEIGHT); genFramebufferWithTexture(fbColor); genUniformColor(uniformColor); render(); glu::readPixels(m_context.getRenderContext(), 0, 0, result.getAccess()); verifyRenderbuffer(m_testCtx.getLog(), m_texFmt, reference, result); return STOP; } // Test description: // - Attach texture containing grid pattern to framebuffer. // - Using framebuffer reads discard odd squares in the grid. // - The even squares framebuffer color is added to the passed in uniform color. class FragmentDiscardTestCase : public FramebufferFetchTestCase { public: FragmentDiscardTestCase (Context& context, const char* name, const char* desc, deUint32 format); ~FragmentDiscardTestCase (void) {} IterateResult iterate (void); private: glu::ProgramSources genShaderSources (void); void genFramebufferWithGrid (const tcu::Vec4& fbColorEven, const tcu::Vec4& fbColorOdd); tcu::TextureLevel genReferenceTexture (const tcu::Vec4& fbColorEven, const tcu::Vec4& fbColorOdd); }; FragmentDiscardTestCase::FragmentDiscardTestCase (Context& context, const char* name, const char* desc, deUint32 format) : FramebufferFetchTestCase(context, name, desc, format) { } glu::ProgramSources FragmentDiscardTestCase::genShaderSources (void) { const string vecType = getColorOutputType(m_texFmt); std::ostringstream fragShaderSource; fragShaderSource << "#version 310 es\n" << "#extension GL_EXT_shader_framebuffer_fetch : require\n" << "layout(location = 0) inout highp " << vecType << " o_color;\n" << "uniform highp " << vecType << " u_color;\n" << "\n" << "void main (void)\n" << "{\n" << " const highp float threshold = 0.0005f;\n" << " bool valuesEqual = all(lessThan(abs(o_color - u_color), vec4(threshold)));\n\n" << " if (valuesEqual)\n" << " o_color += u_color;\n" << " else\n" << " discard;\n" << "}\n"; return glu::makeVtxFragSources(genPassThroughVertSource(), fragShaderSource.str()); } void FragmentDiscardTestCase::genFramebufferWithGrid (const tcu::Vec4& fbColorEven, const tcu::Vec4& fbColorOdd) { tcu::TextureLevel data (glu::mapGLTransferFormat(m_transferFmt.format, m_transferFmt.dataType), VIEWPORT_WIDTH, VIEWPORT_HEIGHT, 1); m_gl.genFramebuffers(1, &m_framebuffer); m_gl.bindFramebuffer(GL_FRAMEBUFFER, m_framebuffer); m_gl.genTextures(1, &m_texColorBuffer); m_gl.bindTexture(GL_TEXTURE_2D, m_texColorBuffer); tcu::fillWithGrid(data.getAccess(), 8, fbColorEven, fbColorOdd); m_gl.texImage2D(GL_TEXTURE_2D, 0, m_format, VIEWPORT_WIDTH, VIEWPORT_HEIGHT, 0, m_transferFmt.format, m_transferFmt.dataType, data.getAccess().getDataPtr()); m_gl.bindTexture(GL_TEXTURE_2D, 0); m_gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texColorBuffer, 0); TCU_CHECK(m_gl.checkFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE); } tcu::TextureLevel FragmentDiscardTestCase::genReferenceTexture (const tcu::Vec4& fbColorEven, const tcu::Vec4& fbColorOdd) { tcu::TextureLevel reference (glu::mapGLTransferFormat(m_transferFmt.format, m_transferFmt.dataType), VIEWPORT_WIDTH, VIEWPORT_HEIGHT, 1); tcu::fillWithGrid(reference.getAccess(), 8, fbColorEven + fbColorEven, fbColorOdd); return reference; } FragmentDiscardTestCase::IterateResult FragmentDiscardTestCase::iterate (void) { const tcu::Vec4 fbColorEven = scaleColorValue(m_texFmt, tcu::Vec4(0.5f, 0.0f, 1.0f, 1.0f)); const tcu::Vec4 fbColorOdd = scaleColorValue(m_texFmt, tcu::Vec4(0.0f, 1.0f, 1.0f, 1.0f)); tcu::TextureLevel reference = genReferenceTexture(fbColorEven, fbColorOdd); tcu::TextureLevel result (getReadPixelFormat(m_texFmt), VIEWPORT_WIDTH, VIEWPORT_HEIGHT); genFramebufferWithGrid(fbColorEven, fbColorOdd); genUniformColor(fbColorEven); render(); glu::readPixels(m_context.getRenderContext(), 0, 0, result.getAccess()); verifyRenderbuffer(m_testCtx.getLog(), m_texFmt, reference, result); return STOP; } // Test description: // - Create 2D texture array containing three mipmaps. // - Each mipmap level is assigned a different color. // - Attach single mipmap level to framebuffer and draw full screen quad. // - Sum framebuffer read color with passed in uniform color. // - Compare resulting surface with reference. // - Repeat for subsequent mipmap levels. class TextureLevelTestCase : public FramebufferFetchTestCase { public: TextureLevelTestCase (Context& context, const char* name, const char* desc, deUint32 format); ~TextureLevelTestCase (void) {} IterateResult iterate (void); private: void create2DTextureArrayMipMaps (const vector<tcu::Vec4>& colors); tcu::TextureLevel genReferenceTexture (int level, const vector<tcu::Vec4>& colors, const tcu::Vec4& uniformColor); void genReferenceMipmap (const tcu::Vec4& color, tcu::TextureLevel& reference); }; TextureLevelTestCase::TextureLevelTestCase (Context& context, const char* name, const char* desc, deUint32 format) : FramebufferFetchTestCase(context, name, desc, format) { } void TextureLevelTestCase::create2DTextureArrayMipMaps (const vector<tcu::Vec4>& colors) { int numLevels = (int)colors.size(); tcu::TextureLevel levelData (glu::mapGLTransferFormat(m_transferFmt.format, m_transferFmt.dataType)); m_gl.genTextures(1, &m_texColorBuffer); m_gl.bindTexture(GL_TEXTURE_2D_ARRAY, m_texColorBuffer); m_gl.texImage3D(GL_TEXTURE_2D_ARRAY, 0, m_format, VIEWPORT_WIDTH, VIEWPORT_HEIGHT, 1, 0, m_transferFmt.format, m_transferFmt.dataType, DE_NULL); m_gl.generateMipmap(GL_TEXTURE_2D_ARRAY); for (int level = 0; level < numLevels; level++) { int levelW = de::max(1, VIEWPORT_WIDTH >> level); int levelH = de::max(1, VIEWPORT_HEIGHT >> level); levelData.setSize(levelW, levelH, 1); clear(levelData.getAccess(), colors[level]); m_gl.texImage3D(GL_TEXTURE_2D_ARRAY, level, m_format, levelW, levelH, 1, 0, m_transferFmt.format, m_transferFmt.dataType, levelData.getAccess().getDataPtr()); } m_gl.bindTexture(GL_TEXTURE_2D_ARRAY, 0); GLU_EXPECT_NO_ERROR(m_gl.getError(), "create2DTextureArrayMipMaps()"); } tcu::TextureLevel TextureLevelTestCase::genReferenceTexture (int level, const vector<tcu::Vec4>& colors, const tcu::Vec4& uniformColor) { tcu::TextureLevel reference (glu::mapGLTransferFormat(m_transferFmt.format, m_transferFmt.dataType), VIEWPORT_WIDTH >> level, VIEWPORT_HEIGHT >> level, 1); genReferenceMipmap(colors[level] + uniformColor, reference); return reference; } void TextureLevelTestCase::genReferenceMipmap (const tcu::Vec4& color, tcu::TextureLevel& reference) { const int width = reference.getAccess().getWidth(); const int height = reference.getAccess().getHeight(); const int left = width / 2; const int top = height / 2; clear(getSubregion(reference.getAccess(), left, 0, 0, width-left, top, 1), color); clear(getSubregion(reference.getAccess(), 0, top, 0, left, height-top, 1), color); clear(getSubregion(reference.getAccess(), left, top, 0, width-left, height-top, 1), color); clear(getSubregion(reference.getAccess(), 0, 0, 0, left, top, 1), color); } TextureLevelTestCase::IterateResult TextureLevelTestCase::iterate (void) { const tcu::Vec4 uniformColor = scaleColorValue(m_texFmt, tcu::Vec4(0.1f, 0.0f, 0.0f, 1.0f)); vector<tcu::Vec4> levelColors; levelColors.push_back(scaleColorValue(m_texFmt, tcu::Vec4(0.4f, 0.0f, 0.0f, 1.0f))); levelColors.push_back(scaleColorValue(m_texFmt, tcu::Vec4(0.2f, 0.0f, 0.0f, 1.0f))); levelColors.push_back(scaleColorValue(m_texFmt, tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f))); m_gl.genFramebuffers(1, &m_framebuffer); m_gl.bindFramebuffer(GL_FRAMEBUFFER, m_framebuffer); create2DTextureArrayMipMaps(levelColors); // attach successive mipmap layers to framebuffer and render for (int level = 0; level < (int)levelColors.size(); ++level) { std::ostringstream name, desc; name << "Level " << level; desc << "Mipmap level " << level; const tcu::ScopedLogSection section (m_testCtx.getLog(), name.str(), desc.str()); tcu::TextureLevel result (getReadPixelFormat(m_texFmt), VIEWPORT_WIDTH >> level, VIEWPORT_HEIGHT >> level); tcu::TextureLevel reference = genReferenceTexture(level, levelColors, uniformColor); m_gl.framebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_texColorBuffer, level, 0); genUniformColor(uniformColor); render(); glu::readPixels(m_context.getRenderContext(), 0, 0, result.getAccess()); verifyRenderbuffer(m_testCtx.getLog(), m_texFmt, reference, result); if (m_testCtx.getTestResult() != QP_TEST_RESULT_PASS) return STOP; } return STOP; } class TextureLayerTestCase : public FramebufferFetchTestCase { public: TextureLayerTestCase (Context& context, const char* name, const char* desc, deUint32 format); ~TextureLayerTestCase (void) {} IterateResult iterate (void); private: void create2DTextureArrayLayers (const vector<tcu::Vec4>& colors); tcu::TextureLevel genReferenceTexture (int layer, const vector<tcu::Vec4>& colors, const tcu::Vec4& uniformColor); }; TextureLayerTestCase::TextureLayerTestCase (Context& context, const char* name, const char* desc, deUint32 format) : FramebufferFetchTestCase(context, name, desc, format) { } void TextureLayerTestCase::create2DTextureArrayLayers (const vector<tcu::Vec4>& colors) { int numLayers = (int)colors.size(); tcu::TextureLevel layerData (glu::mapGLTransferFormat(m_transferFmt.format, m_transferFmt.dataType)); m_gl.genTextures(1, &m_texColorBuffer); m_gl.bindTexture(GL_TEXTURE_2D_ARRAY, m_texColorBuffer); m_gl.texStorage3D(GL_TEXTURE_2D_ARRAY, 1, m_format, VIEWPORT_WIDTH, VIEWPORT_HEIGHT, numLayers); m_gl.bindImageTexture(0, m_texColorBuffer, 0, GL_FALSE, 0, GL_READ_ONLY, m_format); layerData.setSize(VIEWPORT_WIDTH, VIEWPORT_HEIGHT, numLayers); for (int layer = 0; layer < numLayers; layer++) { clear(layerData.getAccess(), colors[layer]); m_gl.texSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, layer, VIEWPORT_WIDTH, VIEWPORT_HEIGHT, 1, m_transferFmt.format, m_transferFmt.dataType, layerData.getAccess().getDataPtr()); } m_gl.bindTexture(GL_TEXTURE_2D_ARRAY, 0); GLU_EXPECT_NO_ERROR(m_gl.getError(), "create2DTextureArrayLayers()"); } tcu::TextureLevel TextureLayerTestCase::genReferenceTexture (int layer, const vector<tcu::Vec4>& colors, const tcu::Vec4& uniformColor) { tcu::TextureLevel reference (glu::mapGLTransferFormat(m_transferFmt.format, m_transferFmt.dataType), VIEWPORT_WIDTH, VIEWPORT_HEIGHT, 1); clear(reference.getAccess(), colors[layer] + uniformColor); return reference; } // Test description // - Create 2D texture array containing three layers. // - Each layer is assigned a different color. // - Attach single layer to framebuffer and draw full screen quad. // - Sum framebuffer read color with passed in uniform color. // - Compare resulting surface with reference. // - Repeat for subsequent texture layers. TextureLayerTestCase::IterateResult TextureLayerTestCase::iterate (void) { const tcu::Vec4 uniformColor = scaleColorValue(m_texFmt, tcu::Vec4(0.1f, 0.1f, 0.1f, 1.0f)); tcu::TextureLevel result (getReadPixelFormat(m_texFmt), VIEWPORT_WIDTH, VIEWPORT_HEIGHT); vector<tcu::Vec4> layerColors; layerColors.push_back(scaleColorValue(m_texFmt, tcu::Vec4(0.4f, 0.0f, 0.0f, 1.0f))); layerColors.push_back(scaleColorValue(m_texFmt, tcu::Vec4(0.2f, 0.0f, 0.0f, 1.0f))); layerColors.push_back(scaleColorValue(m_texFmt, tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f))); m_gl.genFramebuffers(1, &m_framebuffer); m_gl.bindFramebuffer(GL_FRAMEBUFFER, m_framebuffer); create2DTextureArrayLayers(layerColors); for (int layer = 0; layer < (int)layerColors.size(); ++layer) { std::ostringstream name, desc; name << "Layer " << layer; desc << "Layer " << layer; const tcu::ScopedLogSection section (m_testCtx.getLog(), name.str(), desc.str()); tcu::TextureLevel reference = genReferenceTexture(layer, layerColors, uniformColor); m_gl.framebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_texColorBuffer, 0, layer); genUniformColor(uniformColor); render(); glu::readPixels(m_context.getRenderContext(), 0, 0, result.getAccess()); verifyRenderbuffer(m_testCtx.getLog(), m_texFmt, reference, result); if (m_testCtx.getTestResult() != QP_TEST_RESULT_PASS) return STOP; } return STOP; } } // Anonymous ShaderFramebufferFetchTests::ShaderFramebufferFetchTests (Context& context) : TestCaseGroup (context, "framebuffer_fetch", "GL_EXT_shader_framebuffer_fetch tests") { } ShaderFramebufferFetchTests::~ShaderFramebufferFetchTests (void) { } void ShaderFramebufferFetchTests::init (void) { tcu::TestCaseGroup* const basicTestGroup = new tcu::TestCaseGroup(m_testCtx, "basic", "Basic framebuffer shader fetch tests"); tcu::TestCaseGroup* const framebufferFormatTestGroup = new tcu::TestCaseGroup(m_testCtx, "framebuffer_format", "Texture render target formats tests"); // basic { basicTestGroup->addChild(new TexelFetchTestCase (m_context, "texel_fetch", "Framebuffer fetches in conjunction with shader texel fetches", GL_RGBA8)); basicTestGroup->addChild(new LastFragDataTestCase (m_context, "last_frag_data", "Framebuffer fetches with built-in fragment output of ES 2.0", GL_RGBA8)); basicTestGroup->addChild(new FragmentDiscardTestCase (m_context, "fragment_discard", "Framebuffer fetches in combination with fragment discards", GL_RGBA8)); basicTestGroup->addChild(new MultipleAssignmentTestCase (m_context, "multiple_assignment", "Multiple assignments to fragment color inout", GL_RGBA8)); basicTestGroup->addChild(new MultipleRenderTargetsTestCase (m_context, "multiple_render_targets", "Framebuffer fetches used in combination with multiple render targets", GL_RGBA8)); basicTestGroup->addChild(new TextureLevelTestCase (m_context, "framebuffer_texture_level", "Framebuffer fetches with individual texture render target mipmaps", GL_RGBA8)); basicTestGroup->addChild(new TextureLayerTestCase (m_context, "framebuffer_texture_layer", "Framebuffer fetches with individual texture render target layers", GL_RGBA8)); } // framebuffer formats { static const deUint32 colorFormats[] = { // RGBA formats GL_RGBA32I, GL_RGBA32UI, GL_RGBA16I, GL_RGBA16UI, GL_RGBA8, GL_RGBA8I, GL_RGBA8UI, GL_SRGB8_ALPHA8, GL_RGB10_A2, GL_RGB10_A2UI, GL_RGBA4, GL_RGB5_A1, // RGB formats GL_RGB8, GL_RGB565, // RG formats GL_RG32I, GL_RG32UI, GL_RG16I, GL_RG16UI, GL_RG8, GL_RG8I, GL_RG8UI, // R formats GL_R32I, GL_R32UI, GL_R16I, GL_R16UI, GL_R8, GL_R8I, GL_R8UI, // GL_EXT_color_buffer_float GL_RGBA32F, GL_RGBA16F, GL_R11F_G11F_B10F, GL_RG32F, GL_RG16F, GL_R32F, GL_R16F, // GL_EXT_color_buffer_half_float GL_RGB16F }; for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(colorFormats); ndx++) framebufferFormatTestGroup->addChild(new TextureFormatTestCase(m_context, getFormatName(colorFormats[ndx]), "Framebuffer fetches from texture attachments with varying formats", colorFormats[ndx])); } addChild(basicTestGroup); addChild(framebufferFormatTestGroup); } } // Functional } // gles31 } // deqp