Edit

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

Branch :

  • Show log

    Commit

  • Author : Jamie Madill
    Date : 2019-11-27 21:43:22
    Hash : fc3ec57d
    Message : Reland "Vulkan: Accelerate Texture PBO updates" This reverts commit 27d3c9399925d23726880ef910b9068fa39307cf. Reason for revert: Investigation is unable to reproduce the regresion. Shows up on the perf CI. Original change's description: > Revert "Vulkan: Accelerate Texture PBO updates" > > This reverts commit efb45edaefc07fc7120ebbde83bbc84876afda1a. > > Reason for revert: Significant perf regression on several benchmarks. > See bug for more details. > > Bug: chromium:1027098 > > Original change's description: > > Vulkan: Accelerate Texture PBO updates > > > > If the format of the image and the PBO match, > > use a vkCmdCopyBufferToImage transfer operation. > > > > Test: angle_end2end_tests --gtest_filter=*PBOCompressedSubImage* > > angle_end2end_tests --gtest_filter=*PBOWithMultipleDraws* > > dEQP-GLES3.functional.texture.specification.tex*image*d_pbo* > > Bug: angleproject:3777 > > Change-Id: I3f271024a635be113202a16f8893a199c194172d > > Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1906203 > > Reviewed-by: Cody Northrop <cnorthrop@google.com> > > Commit-Queue: Mohan Maiya <m.maiya@samsung.com> > > TBR=cnorthrop@google.com,syoussefi@chromium.org,jmadill@chromium.org,m.maiya@samsung.com,b.schade@samsung.com > > # Not skipping CQ checks because original CL landed > 1 day ago. > > Bug: angleproject:3777 > Change-Id: I774655962e9ab5a866b9324002fb8edae8550834 > Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1939927 > Reviewed-by: Jamie Madill <jmadill@chromium.org> > Commit-Queue: Jamie Madill <jmadill@chromium.org> TBR=cnorthrop@google.com,syoussefi@chromium.org,jmadill@chromium.org,m.maiya@samsung.com,b.schade@samsung.com Change-Id: I8560a2e70de230eac3256a1df5eb2ecaa6f26bcf No-Presubmit: true No-Tree-Checks: true No-Try: true Bug: chromium:1027098, angleproject:3777 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1939852 Reviewed-by: Jamie Madill <jmadill@chromium.org> Commit-Queue: Jamie Madill <jmadill@chromium.org>

  • src/tests/perf_tests/TextureUploadPerf.cpp
  • //
    // Copyright 2019 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.
    //
    // TextureUploadBenchmark:
    //   Performance test for uploading texture data.
    //
    
    #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 = 2;
    
    struct TextureUploadParams final : public RenderTestParams
    {
        TextureUploadParams()
        {
            iterationsPerStep = kIterationsPerStep;
            trackGpuTime      = true;
    
            baseSize     = 1024;
            subImageSize = 64;
    
            webgl = false;
        }
    
        std::string story() const override;
    
        GLsizei baseSize;
        GLsizei subImageSize;
    
        bool webgl;
    };
    
    std::ostream &operator<<(std::ostream &os, const TextureUploadParams &params)
    {
        os << params.backendAndStory().substr(1);
        return os;
    }
    
    std::string TextureUploadParams::story() const
    {
        std::stringstream strstr;
    
        strstr << RenderTestParams::story();
    
        if (webgl)
        {
            strstr << "_webgl";
        }
    
        return strstr.str();
    }
    
    class TextureUploadBenchmarkBase : public ANGLERenderTest,
                                       public ::testing::WithParamInterface<TextureUploadParams>
    {
      public:
        TextureUploadBenchmarkBase(const char *benchmarkName);
    
        void initializeBenchmark() override;
        void destroyBenchmark() override;
    
      protected:
        void initShaders();
    
        GLuint mProgram    = 0;
        GLint mPositionLoc = -1;
        GLint mSamplerLoc  = -1;
        GLuint mTexture    = 0;
        std::vector<float> mTextureData;
    };
    
    class TextureUploadSubImageBenchmark : public TextureUploadBenchmarkBase
    {
      public:
        TextureUploadSubImageBenchmark() : TextureUploadBenchmarkBase("TexSubImage")
        {
            addExtensionPrerequisite("GL_EXT_texture_storage");
        }
    
        void initializeBenchmark() override
        {
            TextureUploadBenchmarkBase::initializeBenchmark();
    
            const auto &params = GetParam();
            glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGBA8, params.baseSize, params.baseSize);
        }
    
        void drawBenchmark() override;
    };
    
    class TextureUploadFullMipBenchmark : public TextureUploadBenchmarkBase
    {
      public:
        TextureUploadFullMipBenchmark() : TextureUploadBenchmarkBase("TextureUpload") {}
    
        void drawBenchmark() override;
    };
    
    class PBOSubImageBenchmark : public TextureUploadBenchmarkBase
    {
      public:
        PBOSubImageBenchmark() : TextureUploadBenchmarkBase("PBO") {}
    
        void initializeBenchmark() override
        {
            TextureUploadBenchmarkBase::initializeBenchmark();
    
            const auto &params = GetParam();
    
            glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGBA8, params.baseSize, params.baseSize);
    
            glGenBuffers(1, &mPBO);
            glBindBuffer(GL_PIXEL_UNPACK_BUFFER, mPBO);
            glBufferData(GL_PIXEL_UNPACK_BUFFER, params.baseSize * params.baseSize * 4,
                         mTextureData.data(), GL_STREAM_DRAW);
        }
    
        void destroyBenchmark()
        {
            TextureUploadBenchmarkBase::destroyBenchmark();
            glDeleteBuffers(1, &mPBO);
        }
    
        void drawBenchmark() override;
    
      private:
        GLuint mPBO;
    };
    
    class PBOCompressedSubImageBenchmark : public TextureUploadBenchmarkBase
    {
      public:
        PBOCompressedSubImageBenchmark() : TextureUploadBenchmarkBase("PBOCompressed") {}
    
        void initializeBenchmark() override
        {
            TextureUploadBenchmarkBase::initializeBenchmark();
    
            const auto &params = GetParam();
    
            glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_COMPRESSED_RGB8_ETC2, params.baseSize,
                              params.baseSize);
    
            glGenBuffers(1, &mPBO);
            glBindBuffer(GL_PIXEL_UNPACK_BUFFER, mPBO);
            glBufferData(GL_PIXEL_UNPACK_BUFFER, params.subImageSize * params.subImageSize / 2,
                         mTextureData.data(), GL_STREAM_DRAW);
        }
    
        void destroyBenchmark()
        {
            TextureUploadBenchmarkBase::destroyBenchmark();
            glDeleteBuffers(1, &mPBO);
        }
    
        void drawBenchmark() override;
    
      private:
        GLuint mPBO;
    };
    
    TextureUploadBenchmarkBase::TextureUploadBenchmarkBase(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;
        }
    }
    
    void TextureUploadBenchmarkBase::initializeBenchmark()
    {
        const auto &params = GetParam();
    
        initShaders();
        glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
        glViewport(0, 0, getWindow()->getWidth(), getWindow()->getHeight());
    
        if (params.webgl)
        {
            glRequestExtensionANGLE("GL_EXT_disjoint_timer_query");
        }
    
        glActiveTexture(GL_TEXTURE0);
        glGenTextures(1, &mTexture);
        glBindTexture(GL_TEXTURE_2D, mTexture);
    
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_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);
    
        ASSERT_TRUE(params.baseSize >= params.subImageSize);
        mTextureData.resize(params.baseSize * params.baseSize * 4, 0.5);
    
        ASSERT_GL_NO_ERROR();
    }
    
    void TextureUploadBenchmarkBase::initShaders()
    {
        constexpr char kVS[] = R"(attribute vec4 a_position;
    void main()
    {
        gl_Position = a_position;
    })";
    
        constexpr char kFS[] = R"(precision mediump float;
    uniform sampler2D s_texture;
    void main()
    {
        gl_FragColor = texture2D(s_texture, vec2(0, 0));
    })";
    
        mProgram = CompileProgram(kVS, kFS);
        ASSERT_NE(0u, mProgram);
    
        mPositionLoc = glGetAttribLocation(mProgram, "a_position");
        mSamplerLoc  = glGetUniformLocation(mProgram, "s_texture");
        glUseProgram(mProgram);
        glUniform1i(mSamplerLoc, 0);
    
        glDisable(GL_DEPTH_TEST);
    
        ASSERT_GL_NO_ERROR();
    }
    
    void TextureUploadBenchmarkBase::destroyBenchmark()
    {
        glDeleteTextures(1, &mTexture);
        glDeleteProgram(mProgram);
    }
    
    void TextureUploadSubImageBenchmark::drawBenchmark()
    {
        const auto &params = GetParam();
    
        startGpuTimer();
        for (unsigned int iteration = 0; iteration < params.iterationsPerStep; ++iteration)
        {
            glTexSubImage2D(GL_TEXTURE_2D, 0, rand() % (params.baseSize - params.subImageSize),
                            rand() % (params.baseSize - params.subImageSize), params.subImageSize,
                            params.subImageSize, GL_RGBA, GL_UNSIGNED_BYTE, mTextureData.data());
    
            // 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 TextureUploadFullMipBenchmark::drawBenchmark()
    {
        const auto &params = GetParam();
    
        startGpuTimer();
        for (size_t it = 0; it < params.iterationsPerStep; ++it)
        {
            // Stage data for all mips
            GLint mip = 0;
            for (GLsizei levelSize = params.baseSize; levelSize > 0; levelSize >>= 1)
            {
                glTexImage2D(GL_TEXTURE_2D, mip++, GL_RGBA, levelSize, levelSize, 0, GL_RGBA,
                             GL_UNSIGNED_BYTE, mTextureData.data());
            }
    
            // 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 PBOSubImageBenchmark::drawBenchmark()
    {
        const auto &params = GetParam();
    
        startGpuTimer();
        for (unsigned int iteration = 0; iteration < params.iterationsPerStep; ++iteration)
        {
            glTexSubImage2D(GL_TEXTURE_2D, 0, rand() % (params.baseSize - params.subImageSize),
                            rand() % (params.baseSize - params.subImageSize), params.subImageSize,
                            params.subImageSize, GL_RGBA, GL_UNSIGNED_BYTE, 0);
    
            // 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 PBOCompressedSubImageBenchmark::drawBenchmark()
    {
        const auto &params = GetParam();
    
        startGpuTimer();
        for (unsigned int iteration = 0; iteration < params.iterationsPerStep; ++iteration)
        {
            glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, params.subImageSize, params.subImageSize,
                                      GL_COMPRESSED_RGB8_ETC2,
                                      params.subImageSize * params.subImageSize / 2, 0);
    
            // 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();
    }
    
    TextureUploadParams D3D11Params(bool webglCompat)
    {
        TextureUploadParams params;
        params.eglParameters = egl_platform::D3D11();
        params.webgl         = webglCompat;
        return params;
    }
    
    TextureUploadParams OpenGLOrGLESParams(bool webglCompat)
    {
        TextureUploadParams params;
        params.eglParameters = egl_platform::OPENGL_OR_GLES();
        params.webgl         = webglCompat;
        return params;
    }
    
    TextureUploadParams VulkanParams(bool webglCompat)
    {
        TextureUploadParams params;
        params.eglParameters = egl_platform::VULKAN();
        params.webgl         = webglCompat;
        return params;
    }
    
    TextureUploadParams VulkanPBOParams(GLsizei baseSize, GLsizei subImageSize)
    {
        TextureUploadParams params;
        params.eglParameters = egl_platform::VULKAN();
        params.webgl         = false;
        params.trackGpuTime  = false;
        params.baseSize      = baseSize;
        params.subImageSize  = subImageSize;
        return params;
    }
    
    TextureUploadParams ES3OpenGLPBOParams(GLsizei baseSize, GLsizei subImageSize)
    {
        TextureUploadParams params;
        params.eglParameters = egl_platform::OPENGL();
        params.majorVersion  = 3;
        params.minorVersion  = 0;
        params.webgl         = false;
        params.trackGpuTime  = false;
        params.baseSize      = baseSize;
        params.subImageSize  = subImageSize;
        return params;
    }
    
    }  // anonymous namespace
    
    TEST_P(TextureUploadSubImageBenchmark, Run)
    {
        run();
    }
    
    TEST_P(TextureUploadFullMipBenchmark, Run)
    {
        run();
    }
    
    TEST_P(PBOSubImageBenchmark, Run)
    {
        run();
    }
    
    TEST_P(PBOCompressedSubImageBenchmark, Run)
    {
        run();
    }
    
    using namespace params;
    
    ANGLE_INSTANTIATE_TEST(TextureUploadSubImageBenchmark,
                           D3D11Params(false),
                           D3D11Params(true),
                           OpenGLOrGLESParams(false),
                           OpenGLOrGLESParams(true),
                           VulkanParams(false),
                           NullDevice(VulkanParams(false)),
                           VulkanParams(true));
    
    ANGLE_INSTANTIATE_TEST(TextureUploadFullMipBenchmark,
                           D3D11Params(false),
                           D3D11Params(true),
                           OpenGLOrGLESParams(false),
                           OpenGLOrGLESParams(true),
                           VulkanParams(false),
                           NullDevice(VulkanParams(false)),
                           VulkanParams(true));
    
    ANGLE_INSTANTIATE_TEST(PBOSubImageBenchmark,
                           ES3OpenGLPBOParams(1024, 128),
                           VulkanPBOParams(1024, 128));
    
    ANGLE_INSTANTIATE_TEST(PBOCompressedSubImageBenchmark,
                           ES3OpenGLPBOParams(128, 128),
                           VulkanPBOParams(128, 128));