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

Commit dbb697c

Browse files
authored
Create a unique command pool per render pass (#37965)
This ensures that the command pool is not accessed from multiple threads at the same time. This fixes the validation errors: ``` Check failed: false. Error[337425955][UNASSIGNED-Threading-MultipleThreads] : Validation Error: [ UNASSIGNED-Threading-MultipleThreads ] Object 0: handle = 0x59ffe0000000003d, type = VK_OBJECT_TYPE_COMMAND_POOL; | MessageID = 0x141cb623 | THREADING ERROR : vkFreeCommandBuffers(): object of type VkCommandPool is simultaneously used in thread 471586061488 and thread 471275924656' ```
1 parent 05e2de7 commit dbb697c

File tree

6 files changed

+28
-21
lines changed

6 files changed

+28
-21
lines changed

impeller/renderer/backend/vulkan/command_buffer_vk.cc

+10-10
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,15 @@ namespace impeller {
2020

2121
std::shared_ptr<CommandBufferVK> CommandBufferVK::Create(
2222
const std::weak_ptr<const Context>& context_arg,
23-
vk::Device device,
24-
vk::CommandPool command_pool) {
23+
vk::Device device) {
2524
if (auto context = context_arg.lock()) {
26-
auto queue =
27-
reinterpret_cast<const ContextVK*>(context.get())->GetGraphicsQueue();
28-
auto fenced_command_buffer =
29-
std::make_shared<FencedCommandBufferVK>(device, queue, command_pool);
30-
return std::make_shared<CommandBufferVK>(context, device, command_pool,
31-
fenced_command_buffer);
25+
auto context_vk = reinterpret_cast<const ContextVK*>(context.get());
26+
auto queue = context_vk->GetGraphicsQueue();
27+
auto command_pool = context_vk->CreateGraphicsCommandPool();
28+
auto fenced_command_buffer = std::make_shared<FencedCommandBufferVK>(
29+
device, queue, command_pool->Get());
30+
return std::make_shared<CommandBufferVK>(
31+
context, device, std::move(command_pool), fenced_command_buffer);
3232
} else {
3333
return nullptr;
3434
}
@@ -37,11 +37,11 @@ std::shared_ptr<CommandBufferVK> CommandBufferVK::Create(
3737
CommandBufferVK::CommandBufferVK(
3838
std::weak_ptr<const Context> context,
3939
vk::Device device,
40-
vk::CommandPool command_pool,
40+
std::unique_ptr<CommandPoolVK> command_pool,
4141
std::shared_ptr<FencedCommandBufferVK> command_buffer)
4242
: CommandBuffer(std::move(context)),
4343
device_(device),
44-
command_pool_(command_pool),
44+
command_pool_(std::move(command_pool)),
4545
fenced_command_buffer_(std::move(command_buffer)) {
4646
is_valid_ = true;
4747
}

impeller/renderer/backend/vulkan/command_buffer_vk.h

+4-4
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#pragma once
66

77
#include "flutter/fml/macros.h"
8+
#include "impeller/renderer/backend/vulkan/command_pool_vk.h"
89
#include "impeller/renderer/backend/vulkan/fenced_command_buffer_vk.h"
910
#include "impeller/renderer/backend/vulkan/surface_producer_vk.h"
1011
#include "impeller/renderer/backend/vulkan/vk.h"
@@ -16,12 +17,11 @@ class CommandBufferVK final : public CommandBuffer {
1617
public:
1718
static std::shared_ptr<CommandBufferVK> Create(
1819
const std::weak_ptr<const Context>& context,
19-
vk::Device device,
20-
vk::CommandPool command_pool);
20+
vk::Device device);
2121

2222
CommandBufferVK(std::weak_ptr<const Context> context,
2323
vk::Device device,
24-
vk::CommandPool command_pool,
24+
std::unique_ptr<CommandPoolVK> command_pool,
2525
std::shared_ptr<FencedCommandBufferVK> command_buffer);
2626

2727
// |CommandBuffer|
@@ -31,7 +31,7 @@ class CommandBufferVK final : public CommandBuffer {
3131
friend class ContextVK;
3232

3333
vk::Device device_;
34-
vk::CommandPool command_pool_;
34+
std::unique_ptr<CommandPoolVK> command_pool_;
3535
vk::UniqueRenderPass render_pass_;
3636
std::shared_ptr<FencedCommandBufferVK> fenced_command_buffer_;
3737
bool is_valid_ = false;

impeller/renderer/backend/vulkan/context_vk.cc

+6-4
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,7 @@ ContextVK::ContextVK(
398398

399399
auto graphics_queue =
400400
PickQueue(physical_device.value(), vk::QueueFlagBits::eGraphics);
401+
graphics_queue_idx_ = graphics_queue->index;
401402
auto transfer_queue =
402403
PickQueue(physical_device.value(), vk::QueueFlagBits::eTransfer);
403404
auto compute_queue =
@@ -491,8 +492,6 @@ ContextVK::ContextVK(
491492
device_->getQueue(compute_queue->family, compute_queue->index);
492493
transfer_queue_ =
493494
device_->getQueue(transfer_queue->family, transfer_queue->index);
494-
graphics_command_pool_ =
495-
CommandPoolVK::Create(*device_, graphics_queue->index);
496495

497496
is_valid_ = true;
498497
}
@@ -525,8 +524,7 @@ std::shared_ptr<WorkQueue> ContextVK::GetWorkQueue() const {
525524
}
526525

527526
std::shared_ptr<CommandBuffer> ContextVK::CreateCommandBuffer() const {
528-
return CommandBufferVK::Create(weak_from_this(), *device_,
529-
graphics_command_pool_->Get());
527+
return CommandBufferVK::Create(weak_from_this(), *device_);
530528
}
531529

532530
vk::Instance ContextVK::GetInstance() const {
@@ -605,4 +603,8 @@ vk::Queue ContextVK::GetGraphicsQueue() const {
605603
return graphics_queue_;
606604
}
607605

606+
std::unique_ptr<CommandPoolVK> ContextVK::CreateGraphicsCommandPool() const {
607+
return CommandPoolVK::Create(*device_, graphics_queue_idx_);
608+
}
609+
608610
} // namespace impeller

impeller/renderer/backend/vulkan/context_vk.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,8 @@ class ContextVK final : public Context, public BackendCast<ContextVK, Context> {
9494

9595
vk::Queue GetGraphicsQueue() const;
9696

97+
std::unique_ptr<CommandPoolVK> CreateGraphicsCommandPool() const;
98+
9799
private:
98100
std::shared_ptr<fml::ConcurrentTaskRunner> worker_task_runner_;
99101
vk::UniqueInstance instance_;
@@ -104,14 +106,14 @@ class ContextVK final : public Context, public BackendCast<ContextVK, Context> {
104106
std::shared_ptr<ShaderLibraryVK> shader_library_;
105107
std::shared_ptr<SamplerLibraryVK> sampler_library_;
106108
std::shared_ptr<PipelineLibraryVK> pipeline_library_;
109+
uint32_t graphics_queue_idx_;
107110
vk::Queue graphics_queue_;
108111
vk::Queue compute_queue_;
109112
vk::Queue transfer_queue_;
110113
vk::Queue present_queue_;
111114
vk::UniqueSurfaceKHR surface_;
112115
vk::Format surface_format_;
113116
std::unique_ptr<SwapchainVK> swapchain_;
114-
std::unique_ptr<CommandPoolVK> graphics_command_pool_;
115117
std::unique_ptr<SurfaceProducerVK> surface_producer_;
116118
std::shared_ptr<WorkQueue> work_queue_;
117119
bool is_valid_ = false;

impeller/renderer/backend/vulkan/fenced_command_buffer_vk.cc

+2-1
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,9 @@ vk::CommandBuffer FencedCommandBufferVK::GetSingleUseChild() {
5050

5151
FencedCommandBufferVK::~FencedCommandBufferVK() {
5252
if (!submitted_) {
53-
VALIDATION_LOG
53+
FML_LOG(WARNING)
5454
<< "FencedCommandBufferVK is being destroyed without being submitted.";
55+
children_.push_back(command_buffer_);
5556
}
5657
device_.freeCommandBuffers(command_pool_, children_);
5758
}

impeller/renderer/backend/vulkan/render_pass_vk.cc

+3-1
Original file line numberDiff line numberDiff line change
@@ -346,7 +346,9 @@ bool RenderPassVK::UpdateDescriptorSets(const char* label,
346346
}
347347

348348
std::array<vk::CopyDescriptorSet, 0> copies;
349-
device_.updateDescriptorSets(writes, copies);
349+
if (!writes.empty()) {
350+
device_.updateDescriptorSets(writes, copies);
351+
}
350352

351353
return true;
352354
}

0 commit comments

Comments
 (0)