Edit

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

Branch :

  • Show log

    Commit

  • Author : Peng Huang
    Date : 2021-03-12 12:39:27
    Hash : c99e405c
    Message : Disable timestamp queries for some GPUs on Android Copy some workaround from chromium. Bug: chromium:702980,chromium:477514,chromium:462553,chromium:1178333 Change-Id: I9acb6ef49c91193a9e6bb03c6fc5eabf336cba9a Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2756728 Commit-Queue: Peng Huang <penghuang@chromium.org> Reviewed-by: Geoff Lang <geofflang@chromium.org> Reviewed-by: Jonah Ryan-Davis <jonahr@google.com>

  • src/tests/perf_tests/GenerateMipmapPerf.cpp
  • //
    // Copyright 2020 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.
    //
    // GenerateMipmapBenchmark:
    //   Performance test for generating texture mipmaps.
    //
    
    #include "ANGLEPerfTest.h"
    
    #include <iostream>
    #include <random>
    #include <sstream>
    
    #include "test_utils/gl_raii.h"
    #include "util/shader_utils.h"
    
    using namespace angle;
    
    namespace
    {
    constexpr unsigned int kIterationsPerStep = 5;
    
    struct GenerateMipmapParams final : public RenderTestParams
    {
        GenerateMipmapParams()
        {
            iterationsPerStep = kIterationsPerStep;
            trackGpuTime      = true;
    
            textureWidth  = 1920;
            textureHeight = 1080;
    
            internalFormat = GL_RGBA;
    
            webgl = false;
        }
    
        std::string story() const override;
    
        GLsizei textureWidth;
        GLsizei textureHeight;
    
        GLenum internalFormat;
    
        bool webgl;
    };
    
    std::ostream &operator<<(std::ostream &os, const GenerateMipmapParams &params)
    {
        return os << params.backendAndStory().substr(1);
    }
    
    std::string GenerateMipmapParams::story() const
    {
        std::stringstream strstr;
    
        strstr << RenderTestParams::story();
    
        if (webgl)
        {
            strstr << "_webgl";
        }
    
        if (internalFormat == GL_RGB)
        {
            strstr << "_rgb";
        }
    
        return strstr.str();
    }
    
    template <typename T>
    void FillWithRandomData(T *storage)
    {
        for (uint8_t &u : *storage)
        {
            u = rand() & 0xFF;
        }
    }
    
    class GenerateMipmapBenchmarkBase : public ANGLERenderTest,
                                        public ::testing::WithParamInterface<GenerateMipmapParams>
    {
      public:
        GenerateMipmapBenchmarkBase(const char *benchmarkName);
    
        void initializeBenchmark() override;
        void destroyBenchmark() override;
    
      protected:
        void initShaders();
    
        GLuint mProgram = 0;
        GLuint mTexture = 0;
    
        std::vector<uint8_t> mTextureData;
    };
    
    class GenerateMipmapBenchmark : public GenerateMipmapBenchmarkBase
    {
      public:
        GenerateMipmapBenchmark() : GenerateMipmapBenchmarkBase("GenerateMipmap") {}
    
        void initializeBenchmark() override;
    
        void drawBenchmark() override;
    };
    
    class GenerateMipmapWithRedefineBenchmark : public GenerateMipmapBenchmarkBase
    {
      public:
        GenerateMipmapWithRedefineBenchmark()
            : GenerateMipmapBenchmarkBase("GenerateMipmapWithRedefine")
        {}
    
        void drawBenchmark() override;
    };
    
    GenerateMipmapBenchmarkBase::GenerateMipmapBenchmarkBase(const char *benchmarkName)
        : ANGLERenderTest(benchmarkName, GetParam())
    {
        setWebGLCompatibilityEnabled(GetParam().webgl);
        setRobustResourceInit(GetParam().webgl);
    
        // Crashes on nvidia+d3d11. http://crbug.com/945415
        if (GetParam().getRenderer() == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
        {
            mSkipTest = true;
        }
    
        // Fails on Windows7 NVIDIA Vulkan, presumably due to old drivers. http://crbug.com/1096510
        if (IsWindows7() && IsNVIDIA() &&
            GetParam().eglParameters.renderer == EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE)
        {
            mSkipTest = true;
        }
    }
    
    void GenerateMipmapBenchmarkBase::initializeBenchmark()
    {
        const auto &params = GetParam();
    
        initShaders();
        glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
        glViewport(0, 0, getWindow()->getWidth(), getWindow()->getHeight());
    
        if (mIsTimestampQueryAvailable && params.webgl)
        {
            glRequestExtensionANGLE("GL_EXT_disjoint_timer_query");
        }
    
        glGenTextures(1, &mTexture);
        glBindTexture(GL_TEXTURE_2D, mTexture);
    
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    
        mTextureData.resize(params.textureWidth * params.textureHeight * 4);
        FillWithRandomData(&mTextureData);
    
        glTexImage2D(GL_TEXTURE_2D, 0, params.internalFormat, params.textureWidth, params.textureHeight,
                     0, params.internalFormat, GL_UNSIGNED_BYTE, mTextureData.data());
    
        // Perform a draw so the image data is flushed.
        glDrawArrays(GL_TRIANGLES, 0, 3);
    
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
    
        ASSERT_GL_NO_ERROR();
    }
    
    void GenerateMipmapBenchmarkBase::initShaders()
    {
        constexpr char kVS[] = R"(void main()
    {
        gl_Position = vec4(0, 0, 0, 1);
    })";
    
        constexpr char kFS[] = R"(precision mediump float;
    void main()
    {
        gl_FragColor = vec4(0);
    })";
    
        mProgram = CompileProgram(kVS, kFS);
        ASSERT_NE(0u, mProgram);
    
        glUseProgram(mProgram);
    
        glDisable(GL_DEPTH_TEST);
    
        ASSERT_GL_NO_ERROR();
    }
    
    void GenerateMipmapBenchmarkBase::destroyBenchmark()
    {
        glDeleteTextures(1, &mTexture);
        glDeleteProgram(mProgram);
    }
    
    void GenerateMipmapBenchmark::initializeBenchmark()
    {
        GenerateMipmapBenchmarkBase::initializeBenchmark();
    
        // Generate mipmaps once so the texture doesn't need to be redefined.
        glGenerateMipmap(GL_TEXTURE_2D);
    
        // Perform a draw so the image data is flushed.
        glDrawArrays(GL_TRIANGLES, 0, 3);
    }
    
    void GenerateMipmapBenchmark::drawBenchmark()
    {
        const auto &params = GetParam();
    
        startGpuTimer();
        for (unsigned int iteration = 0; iteration < params.iterationsPerStep; ++iteration)
        {
            // Slightly modify the base texture so the mipmap is definitely regenerated.
            std::array<uint8_t, 4> randomData;
            FillWithRandomData(&randomData);
    
            glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, params.internalFormat, GL_UNSIGNED_BYTE,
                            randomData.data());
    
            // Generate mipmaps
            glGenerateMipmap(GL_TEXTURE_2D);
    
            // Perform a draw just so the texture data is flushed.  With the position attributes not
            // set, a constant default value is used, resulting in a very cheap draw.
            glDrawArrays(GL_TRIANGLES, 0, 3);
        }
        stopGpuTimer();
    
        ASSERT_GL_NO_ERROR();
    }
    
    void GenerateMipmapWithRedefineBenchmark::drawBenchmark()
    {
        const auto &params = GetParam();
    
        // Create a new texture every time, so image redefinition happens every time.
        GLTexture texture;
        glBindTexture(GL_TEXTURE_2D, texture);
    
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    
        glTexImage2D(GL_TEXTURE_2D, 0, params.internalFormat, params.textureWidth, params.textureHeight,
                     0, params.internalFormat, GL_UNSIGNED_BYTE, mTextureData.data());
    
        // Perform a draw so the image data is flushed.
        glDrawArrays(GL_TRIANGLES, 0, 3);
    
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
    
        startGpuTimer();
    
        // Do a single iteration, otherwise the cost of redefinition is amortized.
        ASSERT_EQ(params.iterationsPerStep, 1u);
    
        // Generate mipmaps
        glGenerateMipmap(GL_TEXTURE_2D);
    
        // Perform a draw just so the texture data is flushed.  With the position attributes not
        // set, a constant default value is used, resulting in a very cheap draw.
        glDrawArrays(GL_TRIANGLES, 0, 3);
    
        stopGpuTimer();
    
        ASSERT_GL_NO_ERROR();
    }
    
    GenerateMipmapParams D3D11Params(bool webglCompat, bool singleIteration)
    {
        GenerateMipmapParams params;
        params.eglParameters = egl_platform::D3D11();
        params.majorVersion  = 3;
        params.minorVersion  = 0;
        params.webgl         = webglCompat;
        if (singleIteration)
        {
            params.iterationsPerStep = 1;
        }
        return params;
    }
    
    GenerateMipmapParams OpenGLOrGLESParams(bool webglCompat, bool singleIteration)
    {
        GenerateMipmapParams params;
        params.eglParameters = egl_platform::OPENGL_OR_GLES();
        params.majorVersion  = 3;
        params.minorVersion  = 0;
        params.webgl         = webglCompat;
        if (singleIteration)
        {
            params.iterationsPerStep = 1;
        }
        return params;
    }
    
    GenerateMipmapParams VulkanParams(bool webglCompat, bool singleIteration, bool emulatedFormat)
    {
        GenerateMipmapParams params;
        params.eglParameters = egl_platform::VULKAN();
        params.majorVersion  = 3;
        params.minorVersion  = 0;
        params.webgl         = webglCompat;
        if (emulatedFormat)
        {
            params.internalFormat = GL_RGB;
        }
        if (singleIteration)
        {
            params.iterationsPerStep = 1;
        }
        return params;
    }
    
    }  // anonymous namespace
    
    TEST_P(GenerateMipmapBenchmark, Run)
    {
        run();
    }
    
    TEST_P(GenerateMipmapWithRedefineBenchmark, Run)
    {
        run();
    }
    
    using namespace params;
    
    ANGLE_INSTANTIATE_TEST(GenerateMipmapBenchmark,
                           D3D11Params(false, false),
                           D3D11Params(true, false),
                           OpenGLOrGLESParams(false, false),
                           OpenGLOrGLESParams(true, false),
                           VulkanParams(false, false, false),
                           VulkanParams(true, false, false),
                           VulkanParams(false, false, true),
                           VulkanParams(true, false, true));
    
    ANGLE_INSTANTIATE_TEST(GenerateMipmapWithRedefineBenchmark,
                           D3D11Params(false, true),
                           D3D11Params(true, true),
                           OpenGLOrGLESParams(false, true),
                           OpenGLOrGLESParams(true, true),
                           VulkanParams(false, true, false),
                           VulkanParams(true, true, false),
                           VulkanParams(false, true, true),
                           VulkanParams(true, true, true));