diff --git a/engine/src/flutter/ci/licenses_golden/excluded_files b/engine/src/flutter/ci/licenses_golden/excluded_files index 7cd7633870..6e43c1045f 100644 --- a/engine/src/flutter/ci/licenses_golden/excluded_files +++ b/engine/src/flutter/ci/licenses_golden/excluded_files @@ -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 diff --git a/engine/src/flutter/impeller/renderer/backend/vulkan/BUILD.gn b/engine/src/flutter/impeller/renderer/backend/vulkan/BUILD.gn index 43b15f40dc..6e8b85e9f6 100644 --- a/engine/src/flutter/impeller/renderer/backend/vulkan/BUILD.gn +++ b/engine/src/flutter/impeller/renderer/backend/vulkan/BUILD.gn @@ -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", diff --git a/engine/src/flutter/impeller/renderer/backend/vulkan/render_pass_vk.cc b/engine/src/flutter/impeller/renderer/backend/vulkan/render_pass_vk.cc index f946cf3571..a770765a79 100644 --- a/engine/src/flutter/impeller/renderer/backend/vulkan/render_pass_vk.cc +++ b/engine/src/flutter/impeller/renderer/backend/vulkan/render_pass_vk.cc @@ -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); } diff --git a/engine/src/flutter/impeller/renderer/backend/vulkan/render_pass_vk.h b/engine/src/flutter/impeller/renderer/backend/vulkan/render_pass_vk.h index 80d6d93f0c..bc921f1077 100644 --- a/engine/src/flutter/impeller/renderer/backend/vulkan/render_pass_vk.h +++ b/engine/src/flutter/impeller/renderer/backend/vulkan/render_pass_vk.h @@ -34,6 +34,7 @@ class RenderPassVK final : public RenderPass { vk::CommandBuffer command_buffer_vk_; std::shared_ptr color_image_vk_; std::shared_ptr resolve_image_vk_; + uint32_t current_stencil_ = 0; // Per-command state. std::array image_workspace_; diff --git a/engine/src/flutter/impeller/renderer/backend/vulkan/render_pass_vk_unittests.cc b/engine/src/flutter/impeller/renderer/backend/vulkan/render_pass_vk_unittests.cc new file mode 100644 index 0000000000..e692f51beb --- /dev/null +++ b/engine/src/flutter/impeller/renderer/backend/vulkan/render_pass_vk_unittests.cc @@ -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 context = MockVulkanContextBuilder().Build(); + std::shared_ptr copy = context; + auto cmd_buffer = context->CreateCommandBuffer(); + + RenderTargetAllocator allocator(context->GetResourceAllocator()); + RenderTarget target = allocator.CreateOffscreenMSAA(*copy.get(), {1, 1}, 1); + + std::shared_ptr 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