From 8a1bb4f9605c13cc1efd54258e9e75252c040f7c Mon Sep 17 00:00:00 2001 From: Kaushik Iska Date: Tue, 15 Nov 2022 13:01:37 -0500 Subject: [PATCH 1/2] [Impeller] Add fenced command buffer that waits on-submit this isn't ideal for performance long term but aligns well with what the other backends do. This also lets us remove the dependence on frame numbers for renderpasses setting up for implementing MSAA. --- impeller/renderer/backend/vulkan/BUILD.gn | 4 + .../backend/vulkan/command_buffer_vk.cc | 64 +++--- .../backend/vulkan/command_buffer_vk.h | 10 +- .../renderer/backend/vulkan/context_vk.cc | 14 +- impeller/renderer/backend/vulkan/context_vk.h | 6 +- .../backend/vulkan/deletion_queue_vk.cc | 27 +++ .../backend/vulkan/deletion_queue_vk.h | 32 +++ .../backend/vulkan/descriptor_pool_vk.cc | 8 +- .../backend/vulkan/descriptor_pool_vk.h | 1 - .../vulkan/fenced_command_buffer_vk.cc | 100 +++++++++ .../backend/vulkan/fenced_command_buffer_vk.h | 44 ++++ .../renderer/backend/vulkan/render_pass_vk.cc | 201 ++++++++---------- .../renderer/backend/vulkan/render_pass_vk.h | 33 ++- .../backend/vulkan/surface_producer_vk.cc | 16 -- .../backend/vulkan/surface_producer_vk.h | 9 - 15 files changed, 358 insertions(+), 211 deletions(-) create mode 100644 impeller/renderer/backend/vulkan/deletion_queue_vk.cc create mode 100644 impeller/renderer/backend/vulkan/deletion_queue_vk.h create mode 100644 impeller/renderer/backend/vulkan/fenced_command_buffer_vk.cc create mode 100644 impeller/renderer/backend/vulkan/fenced_command_buffer_vk.h diff --git a/impeller/renderer/backend/vulkan/BUILD.gn b/impeller/renderer/backend/vulkan/BUILD.gn index 6db2d4df534ea..3ba6c17ccdc53 100644 --- a/impeller/renderer/backend/vulkan/BUILD.gn +++ b/impeller/renderer/backend/vulkan/BUILD.gn @@ -18,10 +18,14 @@ impeller_component("vulkan") { "command_pool_vk.h", "context_vk.cc", "context_vk.h", + "deletion_queue_vk.cc", + "deletion_queue_vk.h", "descriptor_pool_vk.cc", "descriptor_pool_vk.h", "device_buffer_vk.cc", "device_buffer_vk.h", + "fenced_command_buffer_vk.cc", + "fenced_command_buffer_vk.h", "formats_vk.cc", "formats_vk.h", "pipeline_library_vk.cc", diff --git a/impeller/renderer/backend/vulkan/command_buffer_vk.cc b/impeller/renderer/backend/vulkan/command_buffer_vk.cc index 6db5c36c2c391..6e6096a8412c6 100644 --- a/impeller/renderer/backend/vulkan/command_buffer_vk.cc +++ b/impeller/renderer/backend/vulkan/command_buffer_vk.cc @@ -4,11 +4,13 @@ #include "impeller/renderer/backend/vulkan/command_buffer_vk.h" +#include #include #include "flutter/fml/logging.h" #include "impeller/base/validation.h" #include "impeller/renderer/backend/vulkan/context_vk.h" +#include "impeller/renderer/backend/vulkan/fenced_command_buffer_vk.h" #include "impeller/renderer/backend/vulkan/formats_vk.h" #include "impeller/renderer/backend/vulkan/render_pass_vk.h" #include "impeller/renderer/command_buffer.h" @@ -17,37 +19,30 @@ namespace impeller { std::shared_ptr CommandBufferVK::Create( - const std::weak_ptr& context, + const std::weak_ptr& context_arg, vk::Device device, - vk::CommandPool command_pool, - SurfaceProducerVK* surface_producer) { - vk::CommandBufferAllocateInfo allocate_info; - allocate_info.setLevel(vk::CommandBufferLevel::ePrimary); - allocate_info.setCommandBufferCount(1); - allocate_info.setCommandPool(command_pool); - - auto res = device.allocateCommandBuffersUnique(allocate_info); - if (res.result != vk::Result::eSuccess) { - VALIDATION_LOG << "Failed to allocate command buffer: " - << vk::to_string(res.result); + vk::CommandPool command_pool) { + if (auto context = context_arg.lock()) { + auto queue = + reinterpret_cast(context.get())->GetGraphicsQueue(); + auto fenced_command_buffer = + std::make_shared(device, queue, command_pool); + return std::make_shared(context, device, command_pool, + fenced_command_buffer); + } else { return nullptr; } - - vk::UniqueCommandBuffer cmd = std::move(res.value[0]); - return std::make_shared(context, device, surface_producer, - command_pool, std::move(cmd)); } -CommandBufferVK::CommandBufferVK(std::weak_ptr context, - vk::Device device, - SurfaceProducerVK* surface_producer, - vk::CommandPool command_pool, - vk::UniqueCommandBuffer command_buffer) +CommandBufferVK::CommandBufferVK( + std::weak_ptr context, + vk::Device device, + vk::CommandPool command_pool, + std::shared_ptr command_buffer) : CommandBuffer(std::move(context)), device_(device), command_pool_(command_pool), - command_buffer_(std::move(command_buffer)), - surface_producer_(surface_producer) { + fenced_command_buffer_(std::move(command_buffer)) { is_valid_ = true; } @@ -56,7 +51,7 @@ CommandBufferVK::~CommandBufferVK() = default; void CommandBufferVK::SetLabel(const std::string& label) const { if (auto context = context_.lock()) { reinterpret_cast(context.get()) - ->SetDebugName(*command_buffer_, label); + ->SetDebugName(fenced_command_buffer_->Get(), label); } } @@ -65,16 +60,12 @@ bool CommandBufferVK::IsValid() const { } bool CommandBufferVK::OnSubmitCommands(CompletionCallback callback) { - // TODO(https://github.com/flutter/flutter/issues/112387) - // This needs to be the place where the command buffer, renderpass, - // and the various descriptor sets in use by the command buffer are - // disposed of. - + bool submit = fenced_command_buffer_->Submit(); if (callback) { - callback(CommandBuffer::Status::kCompleted); + callback(submit ? CommandBuffer::Status::kCompleted + : CommandBuffer::Status::kError); } - - return true; + return submit; } std::shared_ptr CommandBufferVK::OnCreateRenderPass( @@ -115,17 +106,16 @@ std::shared_ptr CommandBufferVK::OnCreateRenderPass( render_pass_create.setSubpassCount(1); render_pass_create.setPSubpasses(&subpass_desc); - auto render_pass_create_res = - device_.createRenderPassUnique(render_pass_create); + auto render_pass_create_res = device_.createRenderPass(render_pass_create); if (render_pass_create_res.result != vk::Result::eSuccess) { VALIDATION_LOG << "Failed to create render pass: " << vk::to_string(render_pass_create_res.result); return nullptr; } - return std::make_shared( - context_, device_, std::move(target), std::move(command_buffer_), - std::move(render_pass_create_res.value), surface_producer_); + vk::RenderPass render_pass = render_pass_create_res.value; + return std::make_shared(context_, device_, std::move(target), + fenced_command_buffer_, render_pass); } std::shared_ptr CommandBufferVK::OnCreateBlitPass() const { diff --git a/impeller/renderer/backend/vulkan/command_buffer_vk.h b/impeller/renderer/backend/vulkan/command_buffer_vk.h index 2b004071d683e..941c110c6c35e 100644 --- a/impeller/renderer/backend/vulkan/command_buffer_vk.h +++ b/impeller/renderer/backend/vulkan/command_buffer_vk.h @@ -5,6 +5,7 @@ #pragma once #include "flutter/fml/macros.h" +#include "impeller/renderer/backend/vulkan/fenced_command_buffer_vk.h" #include "impeller/renderer/backend/vulkan/surface_producer_vk.h" #include "impeller/renderer/backend/vulkan/vk.h" #include "impeller/renderer/command_buffer.h" @@ -16,14 +17,12 @@ class CommandBufferVK final : public CommandBuffer { static std::shared_ptr Create( const std::weak_ptr& context, vk::Device device, - vk::CommandPool command_pool, - SurfaceProducerVK* surface_producer); + vk::CommandPool command_pool); CommandBufferVK(std::weak_ptr context, vk::Device device, - SurfaceProducerVK* surface_producer, vk::CommandPool command_pool, - vk::UniqueCommandBuffer command_buffer); + std::shared_ptr command_buffer); // |CommandBuffer| ~CommandBufferVK() override; @@ -33,9 +32,8 @@ class CommandBufferVK final : public CommandBuffer { vk::Device device_; vk::CommandPool command_pool_; - vk::UniqueCommandBuffer command_buffer_; vk::UniqueRenderPass render_pass_; - SurfaceProducerVK* surface_producer_; + std::shared_ptr fenced_command_buffer_; bool is_valid_ = false; // |CommandBuffer| diff --git a/impeller/renderer/backend/vulkan/context_vk.cc b/impeller/renderer/backend/vulkan/context_vk.cc index 2d4ebbe910ec9..6a9ceca89a017 100644 --- a/impeller/renderer/backend/vulkan/context_vk.cc +++ b/impeller/renderer/backend/vulkan/context_vk.cc @@ -21,6 +21,7 @@ #include "impeller/renderer/backend/vulkan/allocator_vk.h" #include "impeller/renderer/backend/vulkan/capabilities_vk.h" #include "impeller/renderer/backend/vulkan/command_buffer_vk.h" +#include "impeller/renderer/backend/vulkan/deletion_queue_vk.h" #include "impeller/renderer/backend/vulkan/formats_vk.h" #include "impeller/renderer/backend/vulkan/surface_producer_vk.h" #include "impeller/renderer/backend/vulkan/swapchain_details_vk.h" @@ -492,7 +493,7 @@ ContextVK::ContextVK( device_->getQueue(transfer_queue->family, transfer_queue->index); graphics_command_pool_ = CommandPoolVK::Create(*device_, graphics_queue->index); - descriptor_pool_ = std::make_shared(*device_); + is_valid_ = true; } @@ -525,8 +526,7 @@ std::shared_ptr ContextVK::GetWorkQueue() const { std::shared_ptr ContextVK::CreateCommandBuffer() const { return CommandBufferVK::Create(weak_from_this(), *device_, - graphics_command_pool_->Get(), - surface_producer_.get()); + graphics_command_pool_->Get()); } vk::Instance ContextVK::GetInstance() const { @@ -589,8 +589,8 @@ bool ContextVK::SupportsOffscreenMSAA() const { return true; } -std::shared_ptr ContextVK::GetDescriptorPool() const { - return descriptor_pool_; +std::unique_ptr ContextVK::CreateDescriptorPool() const { + return std::make_unique(*device_); } PixelFormat ContextVK::GetColorAttachmentPixelFormat() const { @@ -601,4 +601,8 @@ const BackendFeatures& ContextVK::GetBackendFeatures() const { return kModernBackendFeatures; } +vk::Queue ContextVK::GetGraphicsQueue() const { + return graphics_queue_; +} + } // namespace impeller diff --git a/impeller/renderer/backend/vulkan/context_vk.h b/impeller/renderer/backend/vulkan/context_vk.h index ef8a5661564ee..207d5ee5d3700 100644 --- a/impeller/renderer/backend/vulkan/context_vk.h +++ b/impeller/renderer/backend/vulkan/context_vk.h @@ -11,6 +11,7 @@ #include "flutter/fml/mapping.h" #include "impeller/base/backend_cast.h" #include "impeller/renderer/backend/vulkan/command_pool_vk.h" +#include "impeller/renderer/backend/vulkan/deletion_queue_vk.h" #include "impeller/renderer/backend/vulkan/descriptor_pool_vk.h" #include "impeller/renderer/backend/vulkan/pipeline_library_vk.h" #include "impeller/renderer/backend/vulkan/sampler_library_vk.h" @@ -85,12 +86,14 @@ class ContextVK final : public Context, public BackendCast { std::unique_ptr AcquireSurface(size_t current_frame); - std::shared_ptr GetDescriptorPool() const; + std::unique_ptr CreateDescriptorPool() const; #ifdef FML_OS_ANDROID vk::UniqueSurfaceKHR CreateAndroidSurface(ANativeWindow* window) const; #endif // FML_OS_ANDROID + vk::Queue GetGraphicsQueue() const; + private: std::shared_ptr worker_task_runner_; vk::UniqueInstance instance_; @@ -111,7 +114,6 @@ class ContextVK final : public Context, public BackendCast { std::unique_ptr graphics_command_pool_; std::unique_ptr surface_producer_; std::shared_ptr work_queue_; - std::shared_ptr descriptor_pool_; bool is_valid_ = false; ContextVK( diff --git a/impeller/renderer/backend/vulkan/deletion_queue_vk.cc b/impeller/renderer/backend/vulkan/deletion_queue_vk.cc new file mode 100644 index 0000000000000..2c202e7ed81f2 --- /dev/null +++ b/impeller/renderer/backend/vulkan/deletion_queue_vk.cc @@ -0,0 +1,27 @@ +// 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 "impeller/renderer/backend/vulkan/deletion_queue_vk.h" + +namespace impeller { + +DeletionQueueVK::DeletionQueueVK() = default; + +DeletionQueueVK::~DeletionQueueVK() { + Flush(); +} + +void DeletionQueueVK::Flush() { + for (auto it = deletors_.rbegin(); it != deletors_.rend(); ++it) { + (*it)(); + } + + deletors_.clear(); +} + +void DeletionQueueVK::Push(Deletor&& deletor) { + deletors_.push_back(std::move(deletor)); +} + +} // namespace impeller diff --git a/impeller/renderer/backend/vulkan/deletion_queue_vk.h b/impeller/renderer/backend/vulkan/deletion_queue_vk.h new file mode 100644 index 0000000000000..427844f752680 --- /dev/null +++ b/impeller/renderer/backend/vulkan/deletion_queue_vk.h @@ -0,0 +1,32 @@ +// 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. + +#pragma once + +#include +#include + +#include "flutter/fml/macros.h" + +namespace impeller { + +class DeletionQueueVK { + public: + using Deletor = std::function; + + explicit DeletionQueueVK(); + + ~DeletionQueueVK(); + + void Flush(); + + void Push(Deletor&& deletor); + + private: + std::deque deletors_; + + FML_DISALLOW_COPY_AND_ASSIGN(DeletionQueueVK); +}; + +} // namespace impeller diff --git a/impeller/renderer/backend/vulkan/descriptor_pool_vk.cc b/impeller/renderer/backend/vulkan/descriptor_pool_vk.cc index b4e44282f3b06..47e2cfe444103 100644 --- a/impeller/renderer/backend/vulkan/descriptor_pool_vk.cc +++ b/impeller/renderer/backend/vulkan/descriptor_pool_vk.cc @@ -10,7 +10,7 @@ namespace impeller { -DescriptorPoolVK::DescriptorPoolVK(vk::Device device) : device_(device) { +DescriptorPoolVK::DescriptorPoolVK(vk::Device device) { constexpr size_t kPoolSize = 1024; std::vector pool_sizes = { @@ -48,10 +48,6 @@ vk::DescriptorPool DescriptorPoolVK::GetPool() { return pool_; } -DescriptorPoolVK::~DescriptorPoolVK() { - if (is_valid_) { - device_.destroyDescriptorPool(pool_); - } -} +DescriptorPoolVK::~DescriptorPoolVK() = default; } // namespace impeller diff --git a/impeller/renderer/backend/vulkan/descriptor_pool_vk.h b/impeller/renderer/backend/vulkan/descriptor_pool_vk.h index c4d33d9289a05..e7ff29ee9215b 100644 --- a/impeller/renderer/backend/vulkan/descriptor_pool_vk.h +++ b/impeller/renderer/backend/vulkan/descriptor_pool_vk.h @@ -22,7 +22,6 @@ class DescriptorPoolVK { vk::DescriptorPool GetPool(); private: - vk::Device device_; vk::DescriptorPool pool_; bool is_valid_ = false; diff --git a/impeller/renderer/backend/vulkan/fenced_command_buffer_vk.cc b/impeller/renderer/backend/vulkan/fenced_command_buffer_vk.cc new file mode 100644 index 0000000000000..895c0f62b6ab2 --- /dev/null +++ b/impeller/renderer/backend/vulkan/fenced_command_buffer_vk.cc @@ -0,0 +1,100 @@ +// 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 "impeller/renderer/backend/vulkan/fenced_command_buffer_vk.h" + +#include + +#include "impeller/base/validation.h" +#include "impeller/renderer/backend/vulkan/deletion_queue_vk.h" + +namespace impeller { + +static vk::CommandBuffer CreateCommandBuffer(vk::Device device, + vk::CommandPool pool) { + vk::CommandBufferAllocateInfo allocate_info; + allocate_info.setLevel(vk::CommandBufferLevel::ePrimary); + allocate_info.setCommandBufferCount(1); + allocate_info.setCommandPool(pool); + + auto res = device.allocateCommandBuffers(allocate_info); + if (res.result != vk::Result::eSuccess) { + VALIDATION_LOG << "Failed to allocate command buffer: " + << vk::to_string(res.result); + return nullptr; + } + + return res.value[0]; +} + +FencedCommandBufferVK::FencedCommandBufferVK(vk::Device device, + vk::Queue queue, + vk::CommandPool command_pool) + : device_(device), + queue_(queue), + command_pool_(command_pool), + deletion_queue_(std::make_unique()) { + command_buffer_ = CreateCommandBuffer(device_, command_pool_); +} + +vk::CommandBuffer FencedCommandBufferVK::Get() const { + return command_buffer_; +} + +vk::CommandBuffer FencedCommandBufferVK::GetSingleUseChild() { + auto child = CreateCommandBuffer(device_, command_pool_); + children_.push_back(child); + return child; +} + +FencedCommandBufferVK::~FencedCommandBufferVK() { + if (!submitted_) { + VALIDATION_LOG + << "FencedCommandBufferVK is being destroyed without being submitted."; + } + device_.freeCommandBuffers(command_pool_, children_); +} + +bool FencedCommandBufferVK::Submit() { + if (submitted_) { + VALIDATION_LOG << "Command buffer already submitted."; + return false; + } + + children_.push_back(command_buffer_); + + auto fence_res = device_.createFenceUnique(vk::FenceCreateInfo()); + if (fence_res.result != vk::Result::eSuccess) { + VALIDATION_LOG << "Failed to create fence: " + << vk::to_string(fence_res.result); + return false; + } + vk::UniqueFence fence = std::move(fence_res.value); + + vk::SubmitInfo submit_info; + submit_info.setCommandBuffers(children_); + auto res = queue_.submit(submit_info, *fence); + if (res != vk::Result::eSuccess) { + VALIDATION_LOG << "Failed to submit command buffer: " << vk::to_string(res); + return false; + } + + auto wait = device_.waitForFences(fence.get(), true, UINT64_MAX); + if (wait != vk::Result::eSuccess) { + VALIDATION_LOG << "Failed to wait for fence: " << vk::to_string(wait); + return false; + } + + // cleanup all the resources held by the command buffer and its children. + deletion_queue_->Flush(); + + submitted_ = true; + return true; +} + +DeletionQueueVK* FencedCommandBufferVK::GetDeletionQueue() const { + return deletion_queue_.get(); +} + +} // namespace impeller diff --git a/impeller/renderer/backend/vulkan/fenced_command_buffer_vk.h b/impeller/renderer/backend/vulkan/fenced_command_buffer_vk.h new file mode 100644 index 0000000000000..760d6f44d7e2f --- /dev/null +++ b/impeller/renderer/backend/vulkan/fenced_command_buffer_vk.h @@ -0,0 +1,44 @@ +// 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. + +#pragma once + +#include + +#include "flutter/fml/macros.h" +#include "impeller/renderer/backend/vulkan/deletion_queue_vk.h" +#include "impeller/renderer/backend/vulkan/vk.h" + +namespace impeller { + +class FencedCommandBufferVK { + public: + FencedCommandBufferVK(vk::Device device, + vk::Queue queue, + vk::CommandPool command_pool); + + ~FencedCommandBufferVK(); + + vk::CommandBuffer Get() const; + + vk::CommandBuffer GetSingleUseChild(); + + // this is a blocking call that waits for the fence to be signaled. + bool Submit(); + + DeletionQueueVK* GetDeletionQueue() const; + + private: + vk::Device device_; + vk::Queue queue_; + vk::CommandPool command_pool_; + std::unique_ptr deletion_queue_; + vk::CommandBuffer command_buffer_; + std::vector children_; + bool submitted_ = false; + + FML_DISALLOW_COPY_AND_ASSIGN(FencedCommandBufferVK); +}; + +} // namespace impeller diff --git a/impeller/renderer/backend/vulkan/render_pass_vk.cc b/impeller/renderer/backend/vulkan/render_pass_vk.cc index 8ee31b70ea267..7006dd244bf2a 100644 --- a/impeller/renderer/backend/vulkan/render_pass_vk.cc +++ b/impeller/renderer/backend/vulkan/render_pass_vk.cc @@ -25,17 +25,16 @@ namespace impeller { static uint32_t color_flash = 0; -RenderPassVK::RenderPassVK(std::weak_ptr context, - vk::Device device, - const RenderTarget& target, - vk::UniqueCommandBuffer command_buffer, - vk::UniqueRenderPass render_pass, - SurfaceProducerVK* surface_producer) +RenderPassVK::RenderPassVK( + std::weak_ptr context, + vk::Device device, + const RenderTarget& target, + std::shared_ptr command_buffer, + vk::RenderPass render_pass) : RenderPass(std::move(context), target), device_(device), command_buffer_(std::move(command_buffer)), - render_pass_(std::move(render_pass)), - surface_producer_(surface_producer) { + render_pass_(render_pass) { is_valid_ = true; } @@ -60,7 +59,7 @@ bool RenderPassVK::OnEncodeCommands(const Context& context) const { } vk::CommandBufferBeginInfo begin_info; - auto res = command_buffer_->begin(begin_info); + auto res = command_buffer_->Get().begin(begin_info); if (res != vk::Result::eSuccess) { VALIDATION_LOG << "Failed to begin command buffer: " << vk::to_string(res); return false; @@ -70,19 +69,16 @@ bool RenderPassVK::OnEncodeCommands(const Context& context) const { const auto& depth0 = render_target.GetDepthAttachment(); const auto& stencil0 = render_target.GetStencilAttachment(); - auto& wrapped_texture = TextureVK::Cast(*color0.texture); - FML_CHECK(wrapped_texture.IsWrapped()); + auto& texture = TextureVK::Cast(*color0.texture); + vk::Framebuffer framebuffer = CreateFrameBuffer(texture); - auto tex_info = wrapped_texture.GetTextureInfo()->wrapped_texture; - // TODO (https://github.com/flutter/flutter/issues/112387) - // this frame buffer has to be destroyed when the command buffer is destroyed. - vk::Framebuffer framebuffer = CreateFrameBuffer(tex_info); - - const uint32_t frame_num = tex_info.frame_num; + command_buffer_->GetDeletionQueue()->Push( + [device = device_, fbo = framebuffer]() { + device.destroyFramebuffer(fbo); + }); // layout transition. - if (!TransitionImageLayout(frame_num, tex_info.swapchain_image->GetImage(), - vk::ImageLayout::eUndefined, + if (!TransitionImageLayout(texture.GetImage(), vk::ImageLayout::eUndefined, vk::ImageLayout::eColorAttachmentOptimal)) { return false; } @@ -91,18 +87,19 @@ bool RenderPassVK::OnEncodeCommands(const Context& context) const { clear_value.color = vk::ClearColorValue(std::array{0.0f, 0.0f, 0.0, 0.0f}); - const auto& size = tex_info.swapchain_image->GetSize(); + const auto& size = texture.GetTextureDescriptor().size; vk::Rect2D render_area = vk::Rect2D() .setOffset(vk::Offset2D(0, 0)) .setExtent(vk::Extent2D(size.width, size.height)); auto rp_begin_info = vk::RenderPassBeginInfo() - .setRenderPass(*render_pass_) + .setRenderPass(render_pass_) .setFramebuffer(framebuffer) .setRenderArea(render_area) .setClearValues(clear_value); - command_buffer_->beginRenderPass(rp_begin_info, vk::SubpassContents::eInline); + command_buffer_->Get().beginRenderPass(rp_begin_info, + vk::SubpassContents::eInline); const auto& transients_allocator = context.GetResourceAllocator(); @@ -120,53 +117,53 @@ bool RenderPassVK::OnEncodeCommands(const Context& context) const { continue; } - if (!EncodeCommand(frame_num, context, command)) { + if (!EncodeCommand(context, command)) { return false; } } - if (!TransitionImageLayout(frame_num, tex_info.swapchain_image->GetImage(), - vk::ImageLayout::eUndefined, + if (!TransitionImageLayout(texture.GetImage(), vk::ImageLayout::eUndefined, vk::ImageLayout::eColorAttachmentOptimal)) { return false; } - command_buffer_->endRenderPass(); + command_buffer_->Get().endRenderPass(); - return const_cast(this)->EndCommandBuffer(frame_num); + return const_cast(this)->EndCommandBuffer(); } -bool RenderPassVK::EndCommandBuffer(uint32_t frame_num) { +bool RenderPassVK::EndCommandBuffer() { if (command_buffer_) { - auto res = command_buffer_->end(); + auto res = command_buffer_->Get().end(); if (res != vk::Result::eSuccess) { VALIDATION_LOG << "Failed to end command buffer: " << vk::to_string(res); return false; } - surface_producer_->StashRP(frame_num, std::move(render_pass_)); + const auto& context_vk = GetContextVK(); + command_buffer_->GetDeletionQueue()->Push( + [device = device_, render_pass = render_pass_]() { + device.destroyRenderPass(render_pass); + }); - return surface_producer_->QueueCommandBuffer(frame_num, - std::move(command_buffer_)); + return true; } return false; } -bool RenderPassVK::EncodeCommand(uint32_t frame_num, - const Context& context, +bool RenderPassVK::EncodeCommand(const Context& context, const Command& command) const { SetViewportAndScissor(command); auto& pipeline_vk = PipelineVK::Cast(*command.pipeline); PipelineCreateInfoVK* pipeline_create_info = pipeline_vk.GetCreateInfo(); - if (!AllocateAndBindDescriptorSets(frame_num, context, command, - pipeline_create_info)) { + if (!AllocateAndBindDescriptorSets(context, command, pipeline_create_info)) { return false; } - command_buffer_->bindPipeline(vk::PipelineBindPoint::eGraphics, - pipeline_create_info->GetVKPipeline()); + command_buffer_->Get().bindPipeline(vk::PipelineBindPoint::eGraphics, + pipeline_create_info->GetVKPipeline()); auto vertex_buffer_view = command.GetVertexBuffer(); auto index_buffer_view = command.index_buffer; @@ -192,24 +189,24 @@ bool RenderPassVK::EncodeCommand(uint32_t frame_num, DeviceBufferVK::Cast(*vertex_buffer).GetVKBufferHandle(); vk::Buffer vertex_buffers[] = {vertex_buffer_handle}; vk::DeviceSize vertex_buffer_offsets[] = {vertex_buffer_view.range.offset}; - command_buffer_->bindVertexBuffers(0, 1, vertex_buffers, - vertex_buffer_offsets); + command_buffer_->Get().bindVertexBuffers(0, 1, vertex_buffers, + vertex_buffer_offsets); // index buffer auto index_buffer_handle = DeviceBufferVK::Cast(*index_buffer).GetVKBufferHandle(); - command_buffer_->bindIndexBuffer(index_buffer_handle, - index_buffer_view.range.offset, - ToVKIndexType(command.index_type)); + command_buffer_->Get().bindIndexBuffer(index_buffer_handle, + index_buffer_view.range.offset, + ToVKIndexType(command.index_type)); // execute draw - command_buffer_->drawIndexed(command.index_count, command.instance_count, 0, - 0, 0); + command_buffer_->Get().drawIndexed(command.index_count, + command.instance_count, 0, 0, 0); return true; } bool RenderPassVK::AllocateAndBindDescriptorSets( - uint32_t frame_num, + const Context& context, const Command& command, PipelineCreateInfoVK* pipeline_create_info) const { @@ -217,8 +214,13 @@ bool RenderPassVK::AllocateAndBindDescriptorSets( vk::PipelineLayout pipeline_layout = pipeline_create_info->GetPipelineLayout(); - const auto& context_vk = ContextVK::Cast(context); - const auto& pool = context_vk.GetDescriptorPool(); + const auto& context_vk = GetContextVK(); + const auto& pool = context_vk.CreateDescriptorPool(); + + command_buffer_->GetDeletionQueue()->Push( + [pool = pool->GetPool(), device = device_]() { + device.destroyDescriptorPool(pool); + }); vk::DescriptorSetAllocateInfo alloc_info; std::array dsls = { @@ -236,26 +238,23 @@ bool RenderPassVK::AllocateAndBindDescriptorSets( } auto desc_sets = desc_sets_res.value; - bool update_vertex_descriptors = - UpdateDescriptorSets(frame_num, "vertex_bindings", - command.vertex_bindings, allocator, desc_sets[0]); + bool update_vertex_descriptors = UpdateDescriptorSets( + "vertex_bindings", command.vertex_bindings, allocator, desc_sets[0]); if (!update_vertex_descriptors) { return false; } - bool update_frag_descriptors = - UpdateDescriptorSets(frame_num, "fragment_bindings", - command.fragment_bindings, allocator, desc_sets[0]); + bool update_frag_descriptors = UpdateDescriptorSets( + "fragment_bindings", command.fragment_bindings, allocator, desc_sets[0]); if (!update_frag_descriptors) { return false; } - command_buffer_->bindDescriptorSets(vk::PipelineBindPoint::eGraphics, - pipeline_layout, 0, desc_sets, nullptr); + command_buffer_->Get().bindDescriptorSets( + vk::PipelineBindPoint::eGraphics, pipeline_layout, 0, desc_sets, nullptr); return true; } -bool RenderPassVK::UpdateDescriptorSets(uint32_t frame_num, - const char* label, +bool RenderPassVK::UpdateDescriptorSets(const char* label, const Bindings& bindings, Allocator& allocator, vk::DescriptorSet desc_set) const { @@ -316,15 +315,15 @@ bool RenderPassVK::UpdateDescriptorSets(uint32_t frame_num, const SampledImageSlot& slot = bindings.sampled_images.at(index); - if (!TransitionImageLayout(frame_num, texture_vk.GetImage(), + if (!TransitionImageLayout(texture_vk.GetImage(), vk::ImageLayout::eUndefined, vk::ImageLayout::eTransferDstOptimal)) { return false; } - CopyBufferToImage(frame_num, texture_vk); + CopyBufferToImage(texture_vk); - if (!TransitionImageLayout(frame_num, texture_vk.GetImage(), + if (!TransitionImageLayout(texture_vk.GetImage(), vk::ImageLayout::eTransferDstOptimal, vk::ImageLayout::eShaderReadOnlyOptimal)) { return false; @@ -362,7 +361,7 @@ void RenderPassVK::SetViewportAndScissor(const Command& command) const { .setY(vp.rect.size.height) .setMinDepth(0.0f) .setMaxDepth(1.0f); - command_buffer_->setViewport(0, 1, &viewport); + command_buffer_->Get().setViewport(0, 1, &viewport); // scissor const auto& sc = @@ -371,15 +370,15 @@ void RenderPassVK::SetViewportAndScissor(const Command& command) const { vk::Rect2D() .setOffset(vk::Offset2D(sc.origin.x, sc.origin.y)) .setExtent(vk::Extent2D(sc.size.width, sc.size.height)); - command_buffer_->setScissor(0, 1, &scissor); + command_buffer_->Get().setScissor(0, 1, &scissor); } vk::Framebuffer RenderPassVK::CreateFrameBuffer( - const WrappedTextureInfoVK& wrapped_texture_info) const { - auto img_view = wrapped_texture_info.swapchain_image->GetImageView(); - auto size = wrapped_texture_info.swapchain_image->GetSize(); + const TextureVK& texture) const { + auto img_view = texture.GetImageView(); + auto size = texture.GetTextureDescriptor().size; vk::FramebufferCreateInfo fb_create_info = vk::FramebufferCreateInfo() - .setRenderPass(*render_pass_) + .setRenderPass(render_pass_) .setAttachmentCount(1) .setPAttachments(&img_view) .setWidth(size.width) @@ -390,26 +389,14 @@ vk::Framebuffer RenderPassVK::CreateFrameBuffer( return res.value; } -bool RenderPassVK::TransitionImageLayout(uint32_t frame_num, - vk::Image image, +bool RenderPassVK::TransitionImageLayout(vk::Image image, vk::ImageLayout layout_old, vk::ImageLayout layout_new) const { - auto pool = command_buffer_.getPool(); - vk::CommandBufferAllocateInfo alloc_info = - vk::CommandBufferAllocateInfo() - .setCommandPool(pool) - .setLevel(vk::CommandBufferLevel::ePrimary) - .setCommandBufferCount(1); - auto cmd_buf_res = device_.allocateCommandBuffersUnique(alloc_info); - if (cmd_buf_res.result != vk::Result::eSuccess) { - VALIDATION_LOG << "Failed to allocate command buffer: " - << vk::to_string(cmd_buf_res.result); - return false; - } - auto transition_cmd = std::move(cmd_buf_res.value[0]); + auto transition_cmd = command_buffer_->GetSingleUseChild(); vk::CommandBufferBeginInfo begin_info; - auto res = transition_cmd->begin(begin_info); + begin_info.setFlags(vk::CommandBufferUsageFlagBits::eOneTimeSubmit); + auto res = transition_cmd.begin(begin_info); if (res != vk::Result::eSuccess) { VALIDATION_LOG << "Failed to begin command buffer: " << vk::to_string(res); @@ -434,36 +421,21 @@ bool RenderPassVK::TransitionImageLayout(uint32_t frame_num, .setLevelCount(1) .setBaseArrayLayer(0) .setLayerCount(1)); - transition_cmd->pipelineBarrier(vk::PipelineStageFlagBits::eAllGraphics, - vk::PipelineStageFlagBits::eAllGraphics, {}, - nullptr, nullptr, barrier); + transition_cmd.pipelineBarrier(vk::PipelineStageFlagBits::eAllGraphics, + vk::PipelineStageFlagBits::eAllGraphics, {}, + nullptr, nullptr, barrier); - res = transition_cmd->end(); + res = transition_cmd.end(); if (res != vk::Result::eSuccess) { VALIDATION_LOG << "Failed to end command buffer: " << vk::to_string(res); return false; } - surface_producer_->QueueCommandBuffer(frame_num, std::move(transition_cmd)); return true; } -bool RenderPassVK::CopyBufferToImage(uint32_t frame_num, - const TextureVK& texture_vk) const { - auto pool = command_buffer_.getPool(); - vk::CommandBufferAllocateInfo alloc_info = - vk::CommandBufferAllocateInfo() - .setCommandPool(pool) - .setLevel(vk::CommandBufferLevel::ePrimary) - .setCommandBufferCount(1); - auto cmd_buf_res = device_.allocateCommandBuffersUnique(alloc_info); - if (cmd_buf_res.result != vk::Result::eSuccess) { - VALIDATION_LOG << "Failed to allocate command buffer: " - << vk::to_string(cmd_buf_res.result); - return false; - } - - auto copy_cmd = std::move(cmd_buf_res.value[0]); +bool RenderPassVK::CopyBufferToImage(const TextureVK& texture_vk) const { + auto copy_cmd = command_buffer_->GetSingleUseChild(); const auto& size = texture_vk.GetTextureDescriptor().size; @@ -483,25 +455,34 @@ bool RenderPassVK::CopyBufferToImage(uint32_t frame_num, .setImageExtent(vk::Extent3D(size.width, size.height, 1)); vk::CommandBufferBeginInfo begin_info; - auto res = copy_cmd->begin(begin_info); + begin_info.setFlags(vk::CommandBufferUsageFlagBits::eOneTimeSubmit); + auto res = copy_cmd.begin(begin_info); if (res != vk::Result::eSuccess) { VALIDATION_LOG << "Failed to begin command buffer: " << vk::to_string(res); return false; } - copy_cmd->copyBufferToImage(texture_vk.GetStagingBuffer(), - texture_vk.GetImage(), - vk::ImageLayout::eTransferDstOptimal, region); + copy_cmd.copyBufferToImage(texture_vk.GetStagingBuffer(), + texture_vk.GetImage(), + vk::ImageLayout::eTransferDstOptimal, region); - res = copy_cmd->end(); + res = copy_cmd.end(); if (res != vk::Result::eSuccess) { VALIDATION_LOG << "Failed to end command buffer: " << vk::to_string(res); return false; } - surface_producer_->QueueCommandBuffer(frame_num, std::move(copy_cmd)); return true; } +const ContextVK& RenderPassVK::GetContextVK() const { + if (auto context = context_.lock()) { + const auto& context_vk = ContextVK::Cast(*context); + return context_vk; + } + + FML_UNREACHABLE(); +} + } // namespace impeller diff --git a/impeller/renderer/backend/vulkan/render_pass_vk.h b/impeller/renderer/backend/vulkan/render_pass_vk.h index 9bf05412b5eee..811267e41021a 100644 --- a/impeller/renderer/backend/vulkan/render_pass_vk.h +++ b/impeller/renderer/backend/vulkan/render_pass_vk.h @@ -5,6 +5,8 @@ #pragma once #include "flutter/fml/macros.h" +#include "impeller/renderer/backend/vulkan/context_vk.h" +#include "impeller/renderer/backend/vulkan/fenced_command_buffer_vk.h" #include "impeller/renderer/backend/vulkan/surface_producer_vk.h" #include "impeller/renderer/backend/vulkan/texture_vk.h" #include "impeller/renderer/backend/vulkan/vk.h" @@ -19,9 +21,8 @@ class RenderPassVK final : public RenderPass { RenderPassVK(std::weak_ptr context, vk::Device device, const RenderTarget& target, - vk::UniqueCommandBuffer command_buffer, - vk::UniqueRenderPass render_pass, - SurfaceProducerVK* surface_producer); + std::shared_ptr command_buffer, + vk::RenderPass render_pass); // |RenderPass| ~RenderPassVK() override; @@ -30,10 +31,8 @@ class RenderPassVK final : public RenderPass { friend class CommandBufferVK; vk::Device device_; - vk::UniqueCommandBuffer command_buffer_; - vk::UniqueRenderPass render_pass_; - SurfaceProducerVK* surface_producer_; - + std::shared_ptr command_buffer_; + vk::RenderPass render_pass_; std::string label_ = ""; bool is_valid_ = false; @@ -46,35 +45,31 @@ class RenderPassVK final : public RenderPass { // |RenderPass| bool OnEncodeCommands(const Context& context) const override; - bool EncodeCommand(uint32_t frame_num, - const Context& context, - const Command& command) const; + bool EncodeCommand(const Context& context, const Command& command) const; bool AllocateAndBindDescriptorSets( - uint32_t frame_num, const Context& context, const Command& command, PipelineCreateInfoVK* pipeline_create_info) const; - bool EndCommandBuffer(uint32_t frame_num); + bool EndCommandBuffer(); - bool UpdateDescriptorSets(uint32_t frame_num, - const char* label, + bool UpdateDescriptorSets(const char* label, const Bindings& bindings, Allocator& allocator, vk::DescriptorSet desc_set) const; void SetViewportAndScissor(const Command& command) const; - vk::Framebuffer CreateFrameBuffer( - const WrappedTextureInfoVK& wrapped_texture_info) const; + vk::Framebuffer CreateFrameBuffer(const TextureVK& texture) const; - bool TransitionImageLayout(uint32_t frame_num, - vk::Image image, + bool TransitionImageLayout(vk::Image image, vk::ImageLayout layout_old, vk::ImageLayout layout_new) const; - bool CopyBufferToImage(uint32_t frame_num, const TextureVK& texture_vk) const; + bool CopyBufferToImage(const TextureVK& texture_vk) const; + + const ContextVK& GetContextVK() const; FML_DISALLOW_COPY_AND_ASSIGN(RenderPassVK); }; diff --git a/impeller/renderer/backend/vulkan/surface_producer_vk.cc b/impeller/renderer/backend/vulkan/surface_producer_vk.cc index b3a0f7a0f79de..8bd94893753ee 100644 --- a/impeller/renderer/backend/vulkan/surface_producer_vk.cc +++ b/impeller/renderer/backend/vulkan/surface_producer_vk.cc @@ -133,12 +133,6 @@ bool SurfaceProducerVK::SetupSyncObjects() { return true; } -bool SurfaceProducerVK::QueueCommandBuffer(uint32_t frame_num, - vk::UniqueCommandBuffer buffer) { - command_buffers_[frame_num].push_back(std::move(buffer)); - return true; -} - bool SurfaceProducerVK::Submit(uint32_t frame_num) { auto& sync_objects = sync_objects_[frame_num]; vk::SubmitInfo submit_info; @@ -154,12 +148,6 @@ bool SurfaceProducerVK::Submit(uint32_t frame_num) { *sync_objects->render_finished_semaphore}; submit_info.setSignalSemaphores(signal_semaphores); - std::vector command_buffers = {}; - for (auto& buf : command_buffers_[frame_num]) { - command_buffers.push_back(*buf); - } - submit_info.setCommandBuffers(command_buffers); - auto graphics_submit_res = create_info_.graphics_queue.submit( {submit_info}, *sync_objects->in_flight_fence); if (graphics_submit_res != vk::Result::eSuccess) { @@ -199,13 +187,9 @@ bool SurfaceProducerVK::Present(size_t frame_num, uint32_t image_index) { auto present_res = create_info_.present_queue.presentKHR(present_info); if ((present_res != vk::Result::eSuccess) && (present_res != vk::Result::eSuboptimalKHR)) { - command_buffers_[frame_num].clear(); - stash_rp_[frame_num].clear(); return false; } - command_buffers_[frame_num].clear(); - stash_rp_[frame_num].clear(); return true; } diff --git a/impeller/renderer/backend/vulkan/surface_producer_vk.h b/impeller/renderer/backend/vulkan/surface_producer_vk.h index 2b8a823bf723c..88133ea6e9d48 100644 --- a/impeller/renderer/backend/vulkan/surface_producer_vk.h +++ b/impeller/renderer/backend/vulkan/surface_producer_vk.h @@ -43,13 +43,6 @@ class SurfaceProducerVK { std::unique_ptr AcquireSurface(size_t current_frame); - // take ownership of the command buffer until present. - bool QueueCommandBuffer(uint32_t frame_num, vk::UniqueCommandBuffer buffer); - - void StashRP(uint32_t frame_num, vk::UniqueRenderPass data) { - stash_rp_[frame_num].push_back(std::move(data)); - } - private: std::weak_ptr context_; @@ -63,8 +56,6 @@ class SurfaceProducerVK { // sync objects std::unique_ptr sync_objects_[kMaxFramesInFlight]; - std::vector command_buffers_[kMaxFramesInFlight]; - std::vector stash_rp_[kMaxFramesInFlight]; FML_DISALLOW_COPY_AND_ASSIGN(SurfaceProducerVK); }; From ce7f56e195fc709a2cd995bbffb8dfae1a405c66 Mon Sep 17 00:00:00 2001 From: Kaushik Iska Date: Fri, 18 Nov 2022 13:10:02 -0500 Subject: [PATCH 2/2] fix licenses --- ci/licenses_golden/licenses_flutter | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index 14ffe3d669c09..61ee1801fa045 100644 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -1461,10 +1461,14 @@ FILE: ../../../flutter/impeller/renderer/backend/vulkan/command_pool_vk.cc FILE: ../../../flutter/impeller/renderer/backend/vulkan/command_pool_vk.h FILE: ../../../flutter/impeller/renderer/backend/vulkan/context_vk.cc FILE: ../../../flutter/impeller/renderer/backend/vulkan/context_vk.h +FILE: ../../../flutter/impeller/renderer/backend/vulkan/deletion_queue_vk.cc +FILE: ../../../flutter/impeller/renderer/backend/vulkan/deletion_queue_vk.h FILE: ../../../flutter/impeller/renderer/backend/vulkan/descriptor_pool_vk.cc FILE: ../../../flutter/impeller/renderer/backend/vulkan/descriptor_pool_vk.h FILE: ../../../flutter/impeller/renderer/backend/vulkan/device_buffer_vk.cc FILE: ../../../flutter/impeller/renderer/backend/vulkan/device_buffer_vk.h +FILE: ../../../flutter/impeller/renderer/backend/vulkan/fenced_command_buffer_vk.cc +FILE: ../../../flutter/impeller/renderer/backend/vulkan/fenced_command_buffer_vk.h FILE: ../../../flutter/impeller/renderer/backend/vulkan/formats_vk.cc FILE: ../../../flutter/impeller/renderer/backend/vulkan/formats_vk.h FILE: ../../../flutter/impeller/renderer/backend/vulkan/pipeline_library_vk.cc