Edit

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

Branch :

  • Show log

    Commit

  • Author : Mohan Maiya
    Date : 2021-02-27 08:28:03
    Hash : fe2efefa
    Message : Add FramebufferAttachmentPerfTest Two tests are added to measure the overhead involved in the Observer/Subject interface - 1. FramebufferAttachmentBenchmark - stresses repeated attach/detach of observers to subjects. 2. FramebufferAttachmentStateUpdateBenchmark - stresses state updates to subjects and their propagation to observers. Bug: angleproject:5692 Change-Id: I6e573f3a948ef2b20c56091e549eb871051e0103 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2725740 Commit-Queue: Mohan Maiya <m.maiya@samsung.com> Reviewed-by: Jamie Madill <jmadill@chromium.org> Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org>

  • src/tests/perf_tests/FramebufferAttachmentPerfTest.cpp
  • //
    // Copyright 2021 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.
    //
    // FramebufferAttachPerfTest:
    //   Performance test for attaching and detaching resources to a Framebuffer.
    //
    
    #include "ANGLEPerfTest.h"
    #include "test_utils/gl_raii.h"
    
    #include <iostream>
    #include <random>
    #include <sstream>
    
    namespace angle
    {
    constexpr unsigned int kIterationsPerStep = 256;
    constexpr unsigned int kTextureSize       = 256;
    constexpr std::size_t kTextureCount       = 4;
    constexpr std::size_t kFboCount           = kTextureCount;
    constexpr std::size_t kAdditionalFboCount = kFboCount * kFboCount;
    
    struct FramebufferAttachmentParams final : public RenderTestParams
    {
        FramebufferAttachmentParams()
        {
            iterationsPerStep = kIterationsPerStep;
    
            // Common default params
            majorVersion = 3;
            minorVersion = 0;
            windowWidth  = kTextureSize;
            windowHeight = kTextureSize;
        }
    
        std::string story() const override;
    };
    
    std::ostream &operator<<(std::ostream &os, const FramebufferAttachmentParams &params)
    {
        os << params.backendAndStory().substr(1);
        return os;
    }
    
    std::string FramebufferAttachmentParams::story() const
    {
        std::stringstream strstr;
    
        strstr << RenderTestParams::story();
    
        return strstr.str();
    }
    
    class FramebufferAttachmentBenchmark
        : public ANGLERenderTest,
          public ::testing::WithParamInterface<FramebufferAttachmentParams>
    {
      public:
        FramebufferAttachmentBenchmark() : ANGLERenderTest("Framebuffers", GetParam()) {}
        void initializeBenchmark() override;
        void drawBenchmark() override;
    
      protected:
        void initTextures();
    
        std::array<GLTexture, kTextureCount> mTextures;
        std::array<GLFramebuffer, kFboCount> mFbo;
    };
    
    void FramebufferAttachmentBenchmark::initializeBenchmark()
    {
        initTextures();
    
        glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
        glViewport(0, 0, getWindow()->getWidth(), getWindow()->getHeight());
    
        ASSERT_GL_NO_ERROR();
    
        GLint maxAttachmentCount;
        glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &maxAttachmentCount);
        if (mTextures.size() > static_cast<size_t>(maxAttachmentCount))
        {
            // Texture count exceeds maximum attachment unit count, skip the test
            mSkipTest = true;
        }
    }
    
    void FramebufferAttachmentBenchmark::initTextures()
    {
        std::vector<GLubyte> textureData(kTextureSize * kTextureSize * 4);
        for (auto &byte : textureData)
        {
            byte = rand() % 255u;
        }
    
        for (GLTexture &texture : mTextures)
        {
            glBindTexture(GL_TEXTURE_2D, texture);
            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kTextureSize, kTextureSize, 0, GL_RGBA,
                         GL_UNSIGNED_BYTE, textureData.data());
            glBindTexture(GL_TEXTURE_2D, 0);
        }
    }
    
    void FramebufferAttachmentBenchmark::drawBenchmark()
    {
        const auto &params = GetParam();
    
        size_t fboCount     = mFbo.size();
        size_t textureCount = mTextures.size();
    
        for (size_t it = 0; it < params.iterationsPerStep; ++it)
        {
            // Attach
            for (size_t fboIndex = 0; fboIndex < fboCount; fboIndex++)
            {
                glBindFramebuffer(GL_FRAMEBUFFER, mFbo[fboIndex]);
                for (size_t textureIndex = 0; textureIndex < textureCount; textureIndex++)
                {
                    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + textureIndex,
                                           GL_TEXTURE_2D, mTextures[textureIndex], 0);
                }
                glBindFramebuffer(GL_FRAMEBUFFER, 0);
            }
    
            // Detach
            for (size_t fboIndex = 0; fboIndex < fboCount; fboIndex++)
            {
                glBindFramebuffer(GL_FRAMEBUFFER, mFbo[fboIndex]);
                for (size_t index = 0; index < textureCount; index++)
                {
                    size_t textureIndex = mTextures.size() - (index + 1);
                    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + textureIndex,
                                           GL_TEXTURE_2D, 0, 0);
                }
                glBindFramebuffer(GL_FRAMEBUFFER, 0);
            }
        }
    
        ASSERT_GL_NO_ERROR();
    }
    
    class FramebufferAttachmentStateUpdateBenchmark : public FramebufferAttachmentBenchmark
    {
      public:
        FramebufferAttachmentStateUpdateBenchmark() : FramebufferAttachmentBenchmark() {}
        void initializeBenchmark() override;
        void destroyBenchmark() override;
        void drawBenchmark() override;
    
      private:
        std::array<GLFramebuffer, kAdditionalFboCount> mAdditionalFbo;
    };
    
    void FramebufferAttachmentStateUpdateBenchmark::initializeBenchmark()
    {
        FramebufferAttachmentBenchmark::initializeBenchmark();
    
        // Attach
        for (size_t fboIndex = 0; fboIndex < mAdditionalFbo.size(); fboIndex++)
        {
            glBindFramebuffer(GL_FRAMEBUFFER, mAdditionalFbo[fboIndex]);
            for (size_t textureIndex = 0; textureIndex < mTextures.size(); textureIndex++)
            {
                glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + textureIndex,
                                       GL_TEXTURE_2D, mTextures[textureIndex], 0);
            }
            glBindFramebuffer(GL_FRAMEBUFFER, 0);
        }
    }
    
    void FramebufferAttachmentStateUpdateBenchmark::destroyBenchmark()
    {
        // Detach
        for (size_t fboIndex = 0; fboIndex < mAdditionalFbo.size(); fboIndex++)
        {
            glBindFramebuffer(GL_FRAMEBUFFER, mAdditionalFbo[fboIndex]);
            for (size_t index = 0; index < mTextures.size(); index++)
            {
                glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + index, GL_TEXTURE_2D, 0,
                                       0);
            }
            glBindFramebuffer(GL_FRAMEBUFFER, 0);
        }
    
        FramebufferAttachmentBenchmark::destroyBenchmark();
    }
    
    void FramebufferAttachmentStateUpdateBenchmark::drawBenchmark()
    {
        const auto &params = GetParam();
    
        size_t textureCount  = mTextures.size();
        GLenum nearestFilter = GL_NEAREST;
        GLenum linearFilter  = GL_LINEAR;
        for (size_t it = 0; it < params.iterationsPerStep; ++it)
        {
            for (size_t textureIndex = 0; textureIndex < textureCount; textureIndex++)
            {
                glBindTexture(GL_TEXTURE_2D, mTextures[textureIndex]);
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
                                (it % 2) ? linearFilter : nearestFilter);
                glBindTexture(GL_TEXTURE_2D, 0);
            }
        }
    
        ASSERT_GL_NO_ERROR();
    }
    
    FramebufferAttachmentParams VulkanParams()
    {
        FramebufferAttachmentParams params;
        params.eglParameters = egl_platform::VULKAN_NULL();
    
        return params;
    }
    
    TEST_P(FramebufferAttachmentBenchmark, Run)
    {
        run();
    }
    
    TEST_P(FramebufferAttachmentStateUpdateBenchmark, Run)
    {
        run();
    }
    
    GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(FramebufferAttachmentBenchmark);
    ANGLE_INSTANTIATE_TEST(FramebufferAttachmentBenchmark, VulkanParams());
    
    GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(FramebufferAttachmentStateUpdateBenchmark);
    ANGLE_INSTANTIATE_TEST(FramebufferAttachmentStateUpdateBenchmark, VulkanParams());
    }  // namespace angle