[Impeller] dont redundantly set stencil reference on vulkan backend. (#164763)

Cache the last stencil reference in RenderPassVK. If the requested
stencil reference is set to the same value, don't update it on the cmd
buffer.


Hypothetical performance improvement, but easy to do.
This commit is contained in:
Jonah Williams 2025-03-07 14:53:26 -08:00 committed by GitHub
parent 711162887d
commit 74a8d79e14
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 60 additions and 0 deletions

View File

@ -202,6 +202,7 @@
../../../flutter/impeller/renderer/backend/vulkan/pipeline_cache_data_vk_unittests.cc
../../../flutter/impeller/renderer/backend/vulkan/render_pass_builder_vk_unittests.cc
../../../flutter/impeller/renderer/backend/vulkan/render_pass_cache_unittests.cc
../../../flutter/impeller/renderer/backend/vulkan/render_pass_vk_unittests.cc
../../../flutter/impeller/renderer/backend/vulkan/resource_manager_vk_unittests.cc
../../../flutter/impeller/renderer/backend/vulkan/swapchain/README.md
../../../flutter/impeller/renderer/backend/vulkan/swapchain/khr/README.md

View File

@ -19,6 +19,7 @@ impeller_component("vulkan_unittests") {
"pipeline_cache_data_vk_unittests.cc",
"render_pass_builder_vk_unittests.cc",
"render_pass_cache_unittests.cc",
"render_pass_vk_unittests.cc",
"resource_manager_vk_unittests.cc",
"test/gpu_tracer_unittests.cc",
"test/mock_vulkan.cc",

View File

@ -340,6 +340,10 @@ void RenderPassVK::SetCommandLabel(std::string_view label) {
// |RenderPass|
void RenderPassVK::SetStencilReference(uint32_t value) {
if (current_stencil_ == value) {
return;
}
current_stencil_ = value;
command_buffer_vk_.setStencilReference(
vk::StencilFaceFlagBits::eVkStencilFrontAndBack, value);
}

View File

@ -34,6 +34,7 @@ class RenderPassVK final : public RenderPass {
vk::CommandBuffer command_buffer_vk_;
std::shared_ptr<Texture> color_image_vk_;
std::shared_ptr<Texture> resolve_image_vk_;
uint32_t current_stencil_ = 0;
// Per-command state.
std::array<vk::DescriptorImageInfo, kMaxBindings> image_workspace_;

View File

@ -0,0 +1,53 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "flutter/testing/testing.h" // IWYU pragma: keep
#include "gtest/gtest.h"
#include "impeller/core/formats.h"
#include "impeller/renderer/backend/vulkan/render_pass_builder_vk.h"
#include "impeller/renderer/backend/vulkan/render_pass_vk.h"
#include "impeller/renderer/backend/vulkan/test/mock_vulkan.h"
#include "impeller/renderer/render_target.h"
#include "vulkan/vulkan_enums.hpp"
namespace impeller {
namespace testing {
TEST(RenderPassVK, DoesNotRedundantlySetStencil) {
std::shared_ptr<ContextVK> context = MockVulkanContextBuilder().Build();
std::shared_ptr<Context> copy = context;
auto cmd_buffer = context->CreateCommandBuffer();
RenderTargetAllocator allocator(context->GetResourceAllocator());
RenderTarget target = allocator.CreateOffscreenMSAA(*copy.get(), {1, 1}, 1);
std::shared_ptr<RenderPass> render_pass =
cmd_buffer->CreateRenderPass(target);
// Stencil reference set once at buffer start.
auto called_functions = GetMockVulkanFunctions(context->GetDevice());
EXPECT_EQ(std::count(called_functions->begin(), called_functions->end(),
"vkCmdSetStencilReference"),
1);
// Duplicate stencil ref is not replaced.
render_pass->SetStencilReference(0);
render_pass->SetStencilReference(0);
render_pass->SetStencilReference(0);
called_functions = GetMockVulkanFunctions(context->GetDevice());
EXPECT_EQ(std::count(called_functions->begin(), called_functions->end(),
"vkCmdSetStencilReference"),
1);
// Different stencil value is updated.
render_pass->SetStencilReference(1);
called_functions = GetMockVulkanFunctions(context->GetDevice());
EXPECT_EQ(std::count(called_functions->begin(), called_functions->end(),
"vkCmdSetStencilReference"),
2);
}
} // namespace testing
} // namespace impeller