Edit

kc3-lang/angle/src/tests/perf_tests/BlitFramebufferPerf.cpp

Branch :

  • Show log

    Commit

  • Author : Jamie Madill
    Date : 2017-02-01 12:57:30
    Hash : 6483eb62
    Message : Add a BlitFramebuffer perf test. This microbenchmark targets a variety of blit use cases, including color blit, depth/stencil blit, and multisample resolve blit. BUG=angleproject:1710 Change-Id: Ia8b3eb40af29e809e803ed48a69f3975b97fd80b Reviewed-on: https://chromium-review.googlesource.com/435515 Reviewed-by: Geoff Lang <geofflang@chromium.org> Reviewed-by: Corentin Wallez <cwallez@chromium.org> Commit-Queue: Jamie Madill <jmadill@chromium.org>

  • src/tests/perf_tests/BlitFramebufferPerf.cpp
  • //
    // Copyright 2017 The ANGLE Project Authors. All rights reserved.
    // Use of this source code is governed by a BSD-style license that can be
    // found in the LICENSE file.
    //
    // BlitFramebufferPerf:
    //   Performance tests for glBlitFramebuffer in ES3. Includes tests for
    //   color, depth, and stencil blit, as well as the mutlisample versions.
    //   The test works by clearing a framebuffer, then blitting it to a second.
    
    #include "ANGLEPerfTest.h"
    
    namespace
    {
    
    enum class BufferType
    {
        COLOR,
        DEPTH,
        STENCIL,
        DEPTH_STENCIL
    };
    
    const char *BufferTypeString(BufferType type)
    {
        switch (type)
        {
            case BufferType::COLOR:
                return "color";
            case BufferType::DEPTH:
                return "depth";
            case BufferType::STENCIL:
                return "stencil";
            case BufferType::DEPTH_STENCIL:
                return "depth_stencil";
            default:
                return "error";
        }
    }
    
    GLbitfield BufferTypeMask(BufferType type)
    {
        switch (type)
        {
            case BufferType::COLOR:
                return GL_COLOR_BUFFER_BIT;
            case BufferType::DEPTH:
                return GL_DEPTH_BUFFER_BIT;
            case BufferType::STENCIL:
                return GL_STENCIL_BUFFER_BIT;
            case BufferType::DEPTH_STENCIL:
                return (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
            default:
                return 0;
        }
    }
    
    GLenum BufferTypeFormat(BufferType type)
    {
        switch (type)
        {
            case BufferType::COLOR:
                return GL_RGBA8;
            case BufferType::DEPTH:
                return GL_DEPTH_COMPONENT24;
            case BufferType::STENCIL:
                return GL_STENCIL_INDEX8;
            case BufferType::DEPTH_STENCIL:
                return GL_DEPTH24_STENCIL8;
            default:
                return GL_NONE;
        }
    }
    
    GLenum BufferTypeAttachment(BufferType type)
    {
        switch (type)
        {
            case BufferType::COLOR:
                return GL_COLOR_ATTACHMENT0;
            case BufferType::DEPTH:
                return GL_DEPTH_ATTACHMENT;
            case BufferType::STENCIL:
                return GL_STENCIL_ATTACHMENT;
            case BufferType::DEPTH_STENCIL:
                return GL_DEPTH_STENCIL_ATTACHMENT;
            default:
                return GL_NONE;
        }
    }
    
    struct BlitFramebufferParams final : public RenderTestParams
    {
        BlitFramebufferParams()
        {
            majorVersion = 3;
            minorVersion = 0;
            windowWidth  = 256;
            windowHeight = 256;
        }
    
        std::string suffix() const override
        {
            std::stringstream suffixStr;
            suffixStr << RenderTestParams::suffix();
            suffixStr << "_" << BufferTypeString(type);
            if (samples > 1)
            {
                suffixStr << "_" << samples << "_samples";
            }
            return suffixStr.str();
        }
    
        BufferType type              = BufferType::COLOR;
        unsigned int framebufferSize = 512;
        unsigned int samples         = 0;
        unsigned int iterations      = 5;
    };
    
    std::ostream &operator<<(std::ostream &os, const BlitFramebufferParams &params)
    {
        os << params.suffix().substr(1);
        return os;
    }
    
    class BlitFramebufferPerf : public ANGLERenderTest,
                                public ::testing::WithParamInterface<BlitFramebufferParams>
    {
      public:
        BlitFramebufferPerf() : ANGLERenderTest("BlitFramebufferPerf", GetParam()) {}
    
        void initializeBenchmark() override;
        void destroyBenchmark() override;
        void drawBenchmark() override;
    
      private:
        GLuint mReadFramebuffer  = 0;
        GLuint mReadRenderbuffer = 0;
        GLuint mDrawFramebuffer  = 0;
        GLuint mDrawRenderbuffer = 0;
    };
    
    void BlitFramebufferPerf::initializeBenchmark()
    {
        const auto &param = GetParam();
    
        glGenFramebuffers(1, &mReadFramebuffer);
        glGenFramebuffers(1, &mDrawFramebuffer);
    
        glBindFramebuffer(GL_READ_FRAMEBUFFER, mReadFramebuffer);
        glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mDrawFramebuffer);
    
        // Create source and destination Renderbuffers.
        glGenRenderbuffers(1, &mReadRenderbuffer);
        glGenRenderbuffers(1, &mDrawRenderbuffer);
    
        ASSERT_GL_NO_ERROR();
    
        GLenum format     = BufferTypeFormat(param.type);
        GLuint size       = param.framebufferSize;
        GLenum attachment = BufferTypeAttachment(param.type);
    
        glBindRenderbuffer(GL_RENDERBUFFER, mReadRenderbuffer);
        glRenderbufferStorageMultisample(GL_RENDERBUFFER, param.samples, format, size, size);
        glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, attachment, GL_RENDERBUFFER, mReadRenderbuffer);
        ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_READ_FRAMEBUFFER));
    
        glBindRenderbuffer(GL_RENDERBUFFER, mDrawRenderbuffer);
        glRenderbufferStorageMultisample(GL_RENDERBUFFER, 0, format, size, size);
        glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, attachment, GL_RENDERBUFFER, mDrawRenderbuffer);
        ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER));
    
        ASSERT_GL_NO_ERROR();
    }
    
    void BlitFramebufferPerf::destroyBenchmark()
    {
        glDeleteFramebuffers(1, &mReadFramebuffer);
        glDeleteRenderbuffers(1, &mReadRenderbuffer);
        glDeleteFramebuffers(1, &mDrawFramebuffer);
        glDeleteRenderbuffers(1, &mDrawRenderbuffer);
    }
    
    void BlitFramebufferPerf::drawBenchmark()
    {
        const auto &param = GetParam();
        auto size         = param.framebufferSize;
        auto mask         = BufferTypeMask(param.type);
    
        // We don't read from the draw buffer (ie rendering) to simplify the test, but we could.
        // This might trigger a flush, or we could trigger a flush manually to ensure the blit happens.
        // TODO(jmadill): Investigate performance on Vulkan, and placement of Clear call.
    
        switch (param.type)
        {
            case BufferType::COLOR:
            {
                GLfloat clearValues[4] = {1.0f, 0.0f, 0.0f, 1.0f};
                glClearBufferfv(GL_COLOR, 0, clearValues);
                break;
            }
            case BufferType::DEPTH:
            {
                GLfloat clearDepthValue = 0.5f;
                glClearBufferfv(GL_DEPTH, 0, &clearDepthValue);
                break;
            }
            case BufferType::STENCIL:
            {
                GLint clearStencilValue = 1;
                glClearBufferiv(GL_STENCIL, 0, &clearStencilValue);
                break;
            }
            case BufferType::DEPTH_STENCIL:
                glClearBufferfi(GL_DEPTH_STENCIL, 0, 0.5f, 1);
                break;
        }
    
        for (unsigned int iteration = 0; iteration < param.iterations; ++iteration)
        {
            glBlitFramebuffer(0, 0, size, size, 0, 0, size, size, mask, GL_NEAREST);
        }
    }
    
    TEST_P(BlitFramebufferPerf, Run)
    {
        run();
    }
    
    BlitFramebufferParams D3D11(BufferType type, unsigned int samples)
    {
        BlitFramebufferParams params;
        params.eglParameters = angle::egl_platform::D3D11();
        params.type          = type;
        params.samples       = samples;
        return params;
    }
    
    }  // anonymous namespace
    
    // TODO(jmadill): Programatically generate these combinations.
    ANGLE_INSTANTIATE_TEST(BlitFramebufferPerf,
                           D3D11(BufferType::COLOR, 0),
                           D3D11(BufferType::DEPTH, 0),
                           D3D11(BufferType::STENCIL, 0),
                           D3D11(BufferType::DEPTH_STENCIL, 0),
                           D3D11(BufferType::COLOR, 2),
                           D3D11(BufferType::DEPTH, 2),
                           D3D11(BufferType::STENCIL, 2),
                           D3D11(BufferType::DEPTH_STENCIL, 2))