Skip to content

Commit 4f338a7

Browse files
authored
[Impeller] Create a resource manager that batch deallocates resources on a dedicated thread. (flutter#43579)
This also sets up well for a unified resource pooling and deferred collection mechanism.
1 parent 1b44d7e commit 4f338a7

File tree

9 files changed

+370
-51
lines changed

9 files changed

+370
-51
lines changed

ci/licenses_golden/licenses_flutter

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1537,6 +1537,8 @@ ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/queue_vk.cc + ../../..
15371537
ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/queue_vk.h + ../../../flutter/LICENSE
15381538
ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/render_pass_vk.cc + ../../../flutter/LICENSE
15391539
ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/render_pass_vk.h + ../../../flutter/LICENSE
1540+
ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/resource_manager_vk.cc + ../../../flutter/LICENSE
1541+
ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/resource_manager_vk.h + ../../../flutter/LICENSE
15401542
ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/sampler_library_vk.cc + ../../../flutter/LICENSE
15411543
ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/sampler_library_vk.h + ../../../flutter/LICENSE
15421544
ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/sampler_vk.cc + ../../../flutter/LICENSE
@@ -4223,6 +4225,8 @@ FILE: ../../../flutter/impeller/renderer/backend/vulkan/queue_vk.cc
42234225
FILE: ../../../flutter/impeller/renderer/backend/vulkan/queue_vk.h
42244226
FILE: ../../../flutter/impeller/renderer/backend/vulkan/render_pass_vk.cc
42254227
FILE: ../../../flutter/impeller/renderer/backend/vulkan/render_pass_vk.h
4228+
FILE: ../../../flutter/impeller/renderer/backend/vulkan/resource_manager_vk.cc
4229+
FILE: ../../../flutter/impeller/renderer/backend/vulkan/resource_manager_vk.h
42264230
FILE: ../../../flutter/impeller/renderer/backend/vulkan/sampler_library_vk.cc
42274231
FILE: ../../../flutter/impeller/renderer/backend/vulkan/sampler_library_vk.h
42284232
FILE: ../../../flutter/impeller/renderer/backend/vulkan/sampler_vk.cc

impeller/renderer/backend/vulkan/BUILD.gn

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@ impeller_component("vulkan") {
6767
"queue_vk.h",
6868
"render_pass_vk.cc",
6969
"render_pass_vk.h",
70+
"resource_manager_vk.cc",
71+
"resource_manager_vk.h",
7072
"sampler_library_vk.cc",
7173
"sampler_library_vk.h",
7274
"sampler_vk.cc",

impeller/renderer/backend/vulkan/allocator_vk.cc

Lines changed: 64 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -241,11 +241,12 @@ static VmaAllocationCreateFlags ToVmaAllocationCreateFlags(StorageMode mode,
241241

242242
class AllocatedTextureSourceVK final : public TextureSourceVK {
243243
public:
244-
AllocatedTextureSourceVK(const TextureDescriptor& desc,
244+
AllocatedTextureSourceVK(std::weak_ptr<ResourceManagerVK> resource_manager,
245+
const TextureDescriptor& desc,
245246
VmaAllocator allocator,
246247
vk::Device device,
247248
bool supports_memoryless_textures)
248-
: TextureSourceVK(desc) {
249+
: TextureSourceVK(desc), resource_(std::move(resource_manager)) {
249250
TRACE_EVENT0("impeller", "CreateDeviceTexture");
250251
vk::ImageCreateInfo image_info;
251252
image_info.flags = ToVKImageCreateFlags(desc.type);
@@ -305,12 +306,10 @@ class AllocatedTextureSourceVK final : public TextureSourceVK {
305306
}
306307
}
307308

308-
image_ = vk::Image{vk_image};
309-
allocator_ = allocator;
310-
allocation_ = allocation;
309+
auto image = vk::Image{vk_image};
311310

312311
vk::ImageViewCreateInfo view_info = {};
313-
view_info.image = image_;
312+
view_info.image = image;
314313
view_info.viewType = ToVKImageViewType(desc.type);
315314
view_info.format = image_info.format;
316315
view_info.subresourceRange.aspectMask = ToVKImageAspectFlags(desc.format);
@@ -332,34 +331,65 @@ class AllocatedTextureSourceVK final : public TextureSourceVK {
332331
<< vk::to_string(result);
333332
return;
334333
}
335-
image_view_ = std::move(image_view);
336-
334+
resource_.Reset(
335+
ImageResource(image, allocator, allocation, std::move(image_view)));
337336
is_valid_ = true;
338337
}
339338

340-
~AllocatedTextureSourceVK() {
341-
TRACE_EVENT0("impeller", "DestroyDeviceTexture");
342-
image_view_.reset();
343-
if (image_) {
344-
::vmaDestroyImage(
345-
allocator_, //
346-
static_cast<typename decltype(image_)::NativeType>(image_), //
347-
allocation_ //
348-
);
349-
}
350-
}
339+
~AllocatedTextureSourceVK() = default;
351340

352341
bool IsValid() const { return is_valid_; }
353342

354-
vk::Image GetImage() const override { return image_; }
343+
vk::Image GetImage() const override { return resource_->image; }
355344

356-
vk::ImageView GetImageView() const override { return image_view_.get(); }
345+
vk::ImageView GetImageView() const override {
346+
return resource_->image_view.get();
347+
}
357348

358349
private:
359-
vk::Image image_ = {};
360-
VmaAllocator allocator_ = {};
361-
VmaAllocation allocation_ = {};
362-
vk::UniqueImageView image_view_;
350+
struct ImageResource {
351+
vk::Image image = {};
352+
VmaAllocator allocator = {};
353+
VmaAllocation allocation = {};
354+
vk::UniqueImageView image_view;
355+
356+
ImageResource() = default;
357+
358+
ImageResource(vk::Image p_image,
359+
VmaAllocator p_allocator,
360+
VmaAllocation p_allocation,
361+
vk::UniqueImageView p_image_view)
362+
: image(p_image),
363+
allocator(p_allocator),
364+
allocation(p_allocation),
365+
image_view(std::move(p_image_view)) {}
366+
367+
ImageResource(ImageResource&& o) {
368+
std::swap(image, o.image);
369+
std::swap(allocator, o.allocator);
370+
std::swap(allocation, o.allocation);
371+
std::swap(image_view, o.image_view);
372+
}
373+
374+
~ImageResource() {
375+
if (!image) {
376+
return;
377+
}
378+
TRACE_EVENT0("impeller", "DestroyDeviceTexture");
379+
image_view.reset();
380+
if (image) {
381+
::vmaDestroyImage(
382+
allocator, //
383+
static_cast<typename decltype(image)::NativeType>(image), //
384+
allocation //
385+
);
386+
}
387+
}
388+
389+
FML_DISALLOW_COPY_AND_ASSIGN(ImageResource);
390+
};
391+
392+
UniqueResourceVKT<ImageResource> resource_;
363393
bool is_valid_ = false;
364394

365395
FML_DISALLOW_COPY_AND_ASSIGN(AllocatedTextureSourceVK);
@@ -376,11 +406,16 @@ std::shared_ptr<Texture> AllocatorVK::OnCreateTexture(
376406
if (!device_holder) {
377407
return nullptr;
378408
}
409+
auto context = context_.lock();
410+
if (!context) {
411+
return nullptr;
412+
}
379413
auto source = std::make_shared<AllocatedTextureSourceVK>(
380-
desc, //
381-
allocator_, //
382-
device_holder->GetDevice(), //
383-
supports_memoryless_textures_ //
414+
ContextVK::Cast(*context).GetResourceManager(), //
415+
desc, //
416+
allocator_, //
417+
device_holder->GetDevice(), //
418+
supports_memoryless_textures_ //
384419
);
385420
if (!source->IsValid()) {
386421
return nullptr;

impeller/renderer/backend/vulkan/context_vk.cc

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include "impeller/renderer/backend/vulkan/debug_report_vk.h"
3030
#include "impeller/renderer/backend/vulkan/fence_waiter_vk.h"
3131
#include "impeller/renderer/backend/vulkan/formats_vk.h"
32+
#include "impeller/renderer/backend/vulkan/resource_manager_vk.h"
3233
#include "impeller/renderer/backend/vulkan/surface_vk.h"
3334
#include "impeller/renderer/backend/vulkan/vk.h"
3435
#include "impeller/renderer/capabilities.h"
@@ -379,6 +380,15 @@ void ContextVK::Setup(Settings settings) {
379380
return;
380381
}
381382

383+
//----------------------------------------------------------------------------
384+
/// Create the resource manager.
385+
///
386+
auto resource_manager = ResourceManagerVK::Create();
387+
if (!resource_manager) {
388+
VALIDATION_LOG << "Could not create resource manager.";
389+
return;
390+
}
391+
382392
//----------------------------------------------------------------------------
383393
/// Fetch the queues.
384394
///
@@ -408,6 +418,7 @@ void ContextVK::Setup(Settings settings) {
408418
queues_ = std::move(queues);
409419
device_capabilities_ = std::move(caps);
410420
fence_waiter_ = std::move(fence_waiter);
421+
resource_manager_ = std::move(resource_manager);
411422
device_name_ = std::string(physical_device_properties.deviceName);
412423
is_valid_ = true;
413424

@@ -533,6 +544,10 @@ std::shared_ptr<FenceWaiterVK> ContextVK::GetFenceWaiter() const {
533544
return fence_waiter_;
534545
}
535546

547+
std::shared_ptr<ResourceManagerVK> ContextVK::GetResourceManager() const {
548+
return resource_manager_;
549+
}
550+
536551
std::unique_ptr<CommandEncoderVK> ContextVK::CreateGraphicsCommandEncoder()
537552
const {
538553
auto tls_pool = CommandPoolVK::GetThreadLocal(this);

impeller/renderer/backend/vulkan/context_vk.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ bool HasValidationLayers();
3030
class CommandEncoderVK;
3131
class DebugReportVK;
3232
class FenceWaiterVK;
33+
class ResourceManagerVK;
3334

3435
class ContextVK final : public Context,
3536
public BackendCast<ContextVK, Context>,
@@ -136,6 +137,8 @@ class ContextVK final : public Context,
136137

137138
std::shared_ptr<FenceWaiterVK> GetFenceWaiter() const;
138139

140+
std::shared_ptr<ResourceManagerVK> GetResourceManager() const;
141+
139142
private:
140143
struct DeviceHolderImpl : public DeviceHolder {
141144
// |DeviceHolder|
@@ -160,6 +163,7 @@ class ContextVK final : public Context,
160163
std::shared_ptr<SwapchainVK> swapchain_;
161164
std::shared_ptr<const Capabilities> device_capabilities_;
162165
std::shared_ptr<FenceWaiterVK> fence_waiter_;
166+
std::shared_ptr<ResourceManagerVK> resource_manager_;
163167
std::string device_name_;
164168
std::shared_ptr<fml::ConcurrentMessageLoop> raster_message_loop_;
165169
const uint64_t hash_;

impeller/renderer/backend/vulkan/device_buffer_vk.cc

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -18,22 +18,18 @@ DeviceBufferVK::DeviceBufferVK(DeviceBufferDescriptor desc,
1818
vk::Buffer buffer)
1919
: DeviceBuffer(desc),
2020
context_(std::move(context)),
21-
allocator_(allocator),
22-
allocation_(allocation),
23-
info_(info),
24-
buffer_(buffer) {}
25-
26-
DeviceBufferVK::~DeviceBufferVK() {
27-
TRACE_EVENT0("impeller", "DestroyDeviceBuffer");
28-
if (buffer_) {
29-
::vmaDestroyBuffer(allocator_,
30-
static_cast<decltype(buffer_)::NativeType>(buffer_),
31-
allocation_);
32-
}
33-
}
21+
resource_(ContextVK::Cast(*context_.lock().get()).GetResourceManager(),
22+
BufferResource{
23+
allocator, //
24+
allocation, //
25+
info, //
26+
buffer //
27+
}) {}
28+
29+
DeviceBufferVK::~DeviceBufferVK() {}
3430

3531
uint8_t* DeviceBufferVK::OnGetContents() const {
36-
return static_cast<uint8_t*>(info_.pMappedData);
32+
return static_cast<uint8_t*>(resource_->info.pMappedData);
3733
}
3834

3935
bool DeviceBufferVK::OnCopyHostBuffer(const uint8_t* source,
@@ -55,14 +51,17 @@ bool DeviceBufferVK::OnCopyHostBuffer(const uint8_t* source,
5551

5652
bool DeviceBufferVK::SetLabel(const std::string& label) {
5753
auto context = context_.lock();
58-
if (!context || !buffer_) {
54+
if (!context || !resource_->buffer) {
5955
// The context could have died at this point.
6056
return false;
6157
}
6258

63-
::vmaSetAllocationName(allocator_, allocation_, label.c_str());
59+
::vmaSetAllocationName(resource_->allocator, //
60+
resource_->allocation, //
61+
label.c_str() //
62+
);
6463

65-
return ContextVK::Cast(*context).SetDebugName(buffer_, label);
64+
return ContextVK::Cast(*context).SetDebugName(resource_->buffer, label);
6665
}
6766

6867
bool DeviceBufferVK::SetLabel(const std::string& label, Range range) {
@@ -71,7 +70,7 @@ bool DeviceBufferVK::SetLabel(const std::string& label, Range range) {
7170
}
7271

7372
vk::Buffer DeviceBufferVK::GetBuffer() const {
74-
return buffer_;
73+
return resource_->buffer;
7574
}
7675

7776
} // namespace impeller

impeller/renderer/backend/vulkan/device_buffer_vk.h

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,11 @@
77
#include <memory>
88

99
#include "flutter/fml/macros.h"
10+
#include "flutter/fml/trace_event.h"
1011
#include "impeller/base/backend_cast.h"
1112
#include "impeller/core/device_buffer.h"
1213
#include "impeller/renderer/backend/vulkan/context_vk.h"
14+
#include "impeller/renderer/backend/vulkan/resource_manager_vk.h"
1315

1416
namespace impeller {
1517

@@ -31,11 +33,45 @@ class DeviceBufferVK final : public DeviceBuffer,
3133
private:
3234
friend class AllocatorVK;
3335

36+
struct BufferResource {
37+
VmaAllocator allocator = {};
38+
VmaAllocation allocation = {};
39+
VmaAllocationInfo info = {};
40+
vk::Buffer buffer = {};
41+
42+
BufferResource() = default;
43+
44+
BufferResource(VmaAllocator p_allocator,
45+
VmaAllocation p_allocation,
46+
VmaAllocationInfo p_info,
47+
vk::Buffer p_buffer)
48+
: allocator(p_allocator),
49+
allocation(p_allocation),
50+
info(p_info),
51+
buffer(p_buffer) {}
52+
53+
BufferResource(BufferResource&& o) {
54+
std::swap(o.allocator, allocator);
55+
std::swap(o.allocation, allocation);
56+
std::swap(o.info, info);
57+
std::swap(o.buffer, buffer);
58+
}
59+
60+
~BufferResource() {
61+
if (!buffer) {
62+
return;
63+
}
64+
TRACE_EVENT0("impeller", "DestroyDeviceBuffer");
65+
::vmaDestroyBuffer(allocator,
66+
static_cast<decltype(buffer)::NativeType>(buffer),
67+
allocation);
68+
}
69+
70+
FML_DISALLOW_COPY_AND_ASSIGN(BufferResource);
71+
};
72+
3473
std::weak_ptr<Context> context_;
35-
VmaAllocator allocator_ = {};
36-
VmaAllocation allocation_ = {};
37-
VmaAllocationInfo info_ = {};
38-
vk::Buffer buffer_ = {};
74+
UniqueResourceVKT<BufferResource> resource_;
3975

4076
// |DeviceBuffer|
4177
uint8_t* OnGetContents() const override;

0 commit comments

Comments
 (0)