Skip to content
This repository has been archived by the owner on Feb 25, 2025. It is now read-only.

Commit

Permalink
[Impeller] Add fenced command buffer that waits on-submit
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
iskakaushik committed Nov 18, 2022
1 parent 44e2f58 commit 427684f
Show file tree
Hide file tree
Showing 15 changed files with 358 additions and 211 deletions.
4 changes: 4 additions & 0 deletions impeller/renderer/backend/vulkan/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
64 changes: 27 additions & 37 deletions impeller/renderer/backend/vulkan/command_buffer_vk.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@

#include "impeller/renderer/backend/vulkan/command_buffer_vk.h"

#include <memory>
#include <utility>

#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"
Expand All @@ -17,37 +19,30 @@
namespace impeller {

std::shared_ptr<CommandBufferVK> CommandBufferVK::Create(
const std::weak_ptr<const Context>& context,
const std::weak_ptr<const Context>& 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<const ContextVK*>(context.get())->GetGraphicsQueue();
auto fenced_command_buffer =
std::make_shared<FencedCommandBufferVK>(device, queue, command_pool);
return std::make_shared<CommandBufferVK>(context, device, command_pool,
fenced_command_buffer);
} else {
return nullptr;
}

vk::UniqueCommandBuffer cmd = std::move(res.value[0]);
return std::make_shared<CommandBufferVK>(context, device, surface_producer,
command_pool, std::move(cmd));
}

CommandBufferVK::CommandBufferVK(std::weak_ptr<const Context> context,
vk::Device device,
SurfaceProducerVK* surface_producer,
vk::CommandPool command_pool,
vk::UniqueCommandBuffer command_buffer)
CommandBufferVK::CommandBufferVK(
std::weak_ptr<const Context> context,
vk::Device device,
vk::CommandPool command_pool,
std::shared_ptr<FencedCommandBufferVK> 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;
}

Expand All @@ -56,7 +51,7 @@ CommandBufferVK::~CommandBufferVK() = default;
void CommandBufferVK::SetLabel(const std::string& label) const {
if (auto context = context_.lock()) {
reinterpret_cast<const ContextVK*>(context.get())
->SetDebugName(*command_buffer_, label);
->SetDebugName(fenced_command_buffer_->Get(), label);
}
}

Expand All @@ -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<RenderPass> CommandBufferVK::OnCreateRenderPass(
Expand Down Expand Up @@ -115,17 +106,16 @@ std::shared_ptr<RenderPass> 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<RenderPassVK>(
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<RenderPassVK>(context_, device_, std::move(target),
fenced_command_buffer_, render_pass);
}

std::shared_ptr<BlitPass> CommandBufferVK::OnCreateBlitPass() const {
Expand Down
10 changes: 4 additions & 6 deletions impeller/renderer/backend/vulkan/command_buffer_vk.h
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -16,14 +17,12 @@ class CommandBufferVK final : public CommandBuffer {
static std::shared_ptr<CommandBufferVK> Create(
const std::weak_ptr<const Context>& context,
vk::Device device,
vk::CommandPool command_pool,
SurfaceProducerVK* surface_producer);
vk::CommandPool command_pool);

CommandBufferVK(std::weak_ptr<const Context> context,
vk::Device device,
SurfaceProducerVK* surface_producer,
vk::CommandPool command_pool,
vk::UniqueCommandBuffer command_buffer);
std::shared_ptr<FencedCommandBufferVK> command_buffer);

// |CommandBuffer|
~CommandBufferVK() override;
Expand All @@ -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<FencedCommandBufferVK> fenced_command_buffer_;
bool is_valid_ = false;

// |CommandBuffer|
Expand Down
14 changes: 9 additions & 5 deletions impeller/renderer/backend/vulkan/context_vk.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -491,7 +492,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<DescriptorPoolVK>(*device_);

is_valid_ = true;
}

Expand Down Expand Up @@ -524,8 +525,7 @@ std::shared_ptr<WorkQueue> ContextVK::GetWorkQueue() const {

std::shared_ptr<CommandBuffer> 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 {
Expand Down Expand Up @@ -588,12 +588,16 @@ bool ContextVK::SupportsOffscreenMSAA() const {
return true;
}

std::shared_ptr<DescriptorPoolVK> ContextVK::GetDescriptorPool() const {
return descriptor_pool_;
std::unique_ptr<DescriptorPoolVK> ContextVK::CreateDescriptorPool() const {
return std::make_unique<DescriptorPoolVK>(*device_);
}

PixelFormat ContextVK::GetColorAttachmentPixelFormat() const {
return ToPixelFormat(surface_format_);
}

vk::Queue ContextVK::GetGraphicsQueue() const {
return graphics_queue_;
}

} // namespace impeller
6 changes: 4 additions & 2 deletions impeller/renderer/backend/vulkan/context_vk.h
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -85,12 +86,14 @@ class ContextVK final : public Context, public BackendCast<ContextVK, Context> {

std::unique_ptr<Surface> AcquireSurface(size_t current_frame);

std::shared_ptr<DescriptorPoolVK> GetDescriptorPool() const;
std::unique_ptr<DescriptorPoolVK> CreateDescriptorPool() const;

#ifdef FML_OS_ANDROID
vk::UniqueSurfaceKHR CreateAndroidSurface(ANativeWindow* window) const;
#endif // FML_OS_ANDROID

vk::Queue GetGraphicsQueue() const;

private:
std::shared_ptr<fml::ConcurrentTaskRunner> worker_task_runner_;
vk::UniqueInstance instance_;
Expand All @@ -111,7 +114,6 @@ class ContextVK final : public Context, public BackendCast<ContextVK, Context> {
std::unique_ptr<CommandPoolVK> graphics_command_pool_;
std::unique_ptr<SurfaceProducerVK> surface_producer_;
std::shared_ptr<WorkQueue> work_queue_;
std::shared_ptr<DescriptorPoolVK> descriptor_pool_;
bool is_valid_ = false;

ContextVK(
Expand Down
27 changes: 27 additions & 0 deletions impeller/renderer/backend/vulkan/deletion_queue_vk.cc
Original file line number Diff line number Diff line change
@@ -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
32 changes: 32 additions & 0 deletions impeller/renderer/backend/vulkan/deletion_queue_vk.h
Original file line number Diff line number Diff line change
@@ -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 <deque>
#include <functional>

#include "flutter/fml/macros.h"

namespace impeller {

class DeletionQueueVK {
public:
using Deletor = std::function<void()>;

explicit DeletionQueueVK();

~DeletionQueueVK();

void Flush();

void Push(Deletor&& deletor);

private:
std::deque<Deletor> deletors_;

FML_DISALLOW_COPY_AND_ASSIGN(DeletionQueueVK);
};

} // namespace impeller
8 changes: 2 additions & 6 deletions impeller/renderer/backend/vulkan/descriptor_pool_vk.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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<vk::DescriptorPoolSize> pool_sizes = {
Expand Down Expand Up @@ -48,10 +48,6 @@ vk::DescriptorPool DescriptorPoolVK::GetPool() {
return pool_;
}

DescriptorPoolVK::~DescriptorPoolVK() {
if (is_valid_) {
device_.destroyDescriptorPool(pool_);
}
}
DescriptorPoolVK::~DescriptorPoolVK() = default;

} // namespace impeller
1 change: 0 additions & 1 deletion impeller/renderer/backend/vulkan/descriptor_pool_vk.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ class DescriptorPoolVK {
vk::DescriptorPool GetPool();

private:
vk::Device device_;
vk::DescriptorPool pool_;
bool is_valid_ = false;

Expand Down
Loading

0 comments on commit 427684f

Please sign in to comment.