| /*------------------------------------------------------------------------- |
| * 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 |