Edit

kc3-lang/angle/src/tests/gl_tests/VulkanPerformanceCounterTest.cpp

Branch :

  • Show log

    Commit

  • Author : Jamie Madill
    Date : 2020-08-01 13:45:11
    Hash : 25b0de6b
    Message : Vulkan: Squash Texture+ImageView Serial and improve caching. Previously we regenerated TextureSerial on Texture state changes such as base/max level changes. This caused ANGLE to update descriptor sets even though it was using the same image view handles. This change instead uses an ImageViewSubresourceSerial which includes both a serial for the ImageView and a 32-bit packed subresource range. The CL speeds up NBA2k because ANGLE no longer writes new descriptors for Texture max level changes. Local testing showed up to a 40% speedup. Also adds a regression test with a counter for the number of descriptor set writes in a frame. This change will also be useful in upcoming changes that track Image serials in the RenderPass. Bug: angleproject:4911 Change-Id: I66249634aa56288079acf2c0eb8aa3391103533c Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2333396 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: Tim Van Patten <timvp@google.com>

  • src/tests/gl_tests/VulkanPerformanceCounterTest.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.
    //
    // VulkanPerformanceCounterTest:
    //   Validates specific GL call patterns with ANGLE performance counters.
    //   For example we can verify a certain call set doesn't break the RenderPass.
    //
    // TODO(jmadill): Move to a GL extension. http://anglebug.com/4918
    
    #include "test_utils/ANGLETest.h"
    #include "test_utils/angle_test_instantiate.h"
    // 'None' is defined as 'struct None {};' in
    // third_party/googletest/src/googletest/include/gtest/internal/gtest-type-util.h.
    // But 'None' is also defined as a numeric constant 0L in <X11/X.h>.
    // So we need to include ANGLETest.h first to avoid this conflict.
    
    #include "libANGLE/Context.h"
    #include "libANGLE/angletypes.h"
    #include "libANGLE/renderer/vulkan/ContextVk.h"
    #include "test_utils/gl_raii.h"
    
    using namespace angle;
    
    namespace
    {
    class VulkanPerformanceCounterTest : public ANGLETest
    {
      protected:
        rx::ContextVk *hackANGLE() const
        {
            // Hack the angle!
            const gl::Context *context = static_cast<gl::Context *>(getEGLWindow()->getContext());
            return rx::GetImplAs<rx::ContextVk>(context);
        }
    };
    
    // Tests that texture updates to unused textures don't break the RP.
    TEST_P(VulkanPerformanceCounterTest, NewTextureDoesNotBreakRenderPass)
    {
        // TODO(jmadill): Fix test. http://anglebug.com/4911
        ANGLE_SKIP_TEST_IF(IsVulkan());
    
        rx::ContextVk *contextVk = hackANGLE();
    
        GLColor kInitialData[4] = {GLColor::red, GLColor::blue, GLColor::green, GLColor::yellow};
    
        // Step 1: Set up a simple 2D Texture rendering loop.
        GLTexture texture;
        glBindTexture(GL_TEXTURE_2D, texture);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, kInitialData);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    
        auto quadVerts = GetQuadVertices();
    
        GLBuffer vertexBuffer;
        glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
        glBufferData(GL_ARRAY_BUFFER, quadVerts.size() * sizeof(quadVerts[0]), quadVerts.data(),
                     GL_STATIC_DRAW);
    
        ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
        glUseProgram(program);
    
        GLint posLoc = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
        ASSERT_NE(-1, posLoc);
    
        glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
        glEnableVertexAttribArray(posLoc);
        ASSERT_GL_NO_ERROR();
    
        glDrawArrays(GL_TRIANGLES, 0, 6);
        ASSERT_GL_NO_ERROR();
        uint32_t expectedRenderPassCount = contextVk->getRenderPassCounter();
    
        // Step 2: Introduce a new 2D Texture with the same Program and Framebuffer.
        GLTexture newTexture;
        glBindTexture(GL_TEXTURE_2D, newTexture);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, kInitialData);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    
        glDrawArrays(GL_TRIANGLES, 0, 6);
        ASSERT_GL_NO_ERROR();
    
        uint32_t actualRenderPassCount = contextVk->getRenderPassCounter();
        EXPECT_EQ(expectedRenderPassCount, actualRenderPassCount);
    }
    
    // Tests that changing a Texture's max level hits the descriptor set cache.
    TEST_P(VulkanPerformanceCounterTest, ChangingMaxLevelHitsDescriptorCache)
    {
        rx::ContextVk *contextVk = hackANGLE();
    
        GLColor kInitialData[4] = {GLColor::red, GLColor::blue, GLColor::green, GLColor::yellow};
    
        // Step 1: Set up a simple mipped 2D Texture rendering loop.
        GLTexture texture;
        glBindTexture(GL_TEXTURE_2D, texture);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, kInitialData);
        glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, kInitialData);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
    
        auto quadVerts = GetQuadVertices();
    
        GLBuffer vertexBuffer;
        glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
        glBufferData(GL_ARRAY_BUFFER, quadVerts.size() * sizeof(quadVerts[0]), quadVerts.data(),
                     GL_STATIC_DRAW);
    
        ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
        glUseProgram(program);
    
        GLint posLoc = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
        ASSERT_NE(-1, posLoc);
    
        glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
        glEnableVertexAttribArray(posLoc);
        ASSERT_GL_NO_ERROR();
    
        glDrawArrays(GL_TRIANGLES, 0, 6);
        ASSERT_GL_NO_ERROR();
    
        // Step 2: Change max level and draw.
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
        glDrawArrays(GL_TRIANGLES, 0, 6);
        ASSERT_GL_NO_ERROR();
    
        uint32_t expectedWriteDescriptorSetCount = contextVk->getWriteDescriptorSetCounter();
    
        // Step 3: Change max level back to original value and verify we hit the cache.
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
        glDrawArrays(GL_TRIANGLES, 0, 6);
        ASSERT_GL_NO_ERROR();
    
        uint32_t actualWriteDescriptorSetCount = contextVk->getWriteDescriptorSetCounter();
        EXPECT_EQ(expectedWriteDescriptorSetCount, actualWriteDescriptorSetCount);
    }
    
    ANGLE_INSTANTIATE_TEST(VulkanPerformanceCounterTest, ES3_VULKAN());
    
    }  // anonymous namespace