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

Commit 356f0a2

Browse files
authored
[Impeller] Add RAII wrappers for VMA objects. (#43626)
Uses `fml::UniqueObject<T>`.
1 parent 359a0ed commit 356f0a2

13 files changed

Lines changed: 266 additions & 179 deletions

File tree

ci/licenses_golden/licenses_flutter

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1562,6 +1562,8 @@ ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/texture_vk.h + ../../.
15621562
ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/vertex_descriptor_vk.cc + ../../../flutter/LICENSE
15631563
ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/vertex_descriptor_vk.h + ../../../flutter/LICENSE
15641564
ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/vk.h + ../../../flutter/LICENSE
1565+
ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/vma.cc + ../../../flutter/LICENSE
1566+
ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/vma.h + ../../../flutter/LICENSE
15651567
ORIGIN: ../../../flutter/impeller/renderer/blit_command.cc + ../../../flutter/LICENSE
15661568
ORIGIN: ../../../flutter/impeller/renderer/blit_command.h + ../../../flutter/LICENSE
15671569
ORIGIN: ../../../flutter/impeller/renderer/blit_pass.cc + ../../../flutter/LICENSE
@@ -4252,6 +4254,8 @@ FILE: ../../../flutter/impeller/renderer/backend/vulkan/texture_vk.h
42524254
FILE: ../../../flutter/impeller/renderer/backend/vulkan/vertex_descriptor_vk.cc
42534255
FILE: ../../../flutter/impeller/renderer/backend/vulkan/vertex_descriptor_vk.h
42544256
FILE: ../../../flutter/impeller/renderer/backend/vulkan/vk.h
4257+
FILE: ../../../flutter/impeller/renderer/backend/vulkan/vma.cc
4258+
FILE: ../../../flutter/impeller/renderer/backend/vulkan/vma.h
42554259
FILE: ../../../flutter/impeller/renderer/blit_command.cc
42564260
FILE: ../../../flutter/impeller/renderer/blit_command.h
42574261
FILE: ../../../flutter/impeller/renderer/blit_pass.cc

impeller/renderer/backend/vulkan/BUILD.gn

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,8 @@ impeller_component("vulkan") {
9494
"vertex_descriptor_vk.cc",
9595
"vertex_descriptor_vk.h",
9696
"vk.h",
97+
"vma.cc",
98+
"vma.h",
9799
]
98100

99101
public_deps = [

impeller/renderer/backend/vulkan/allocator_vk.cc

Lines changed: 93 additions & 124 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,75 @@
1616

1717
namespace impeller {
1818

19+
static constexpr vk::Flags<vk::MemoryPropertyFlagBits>
20+
ToVKBufferMemoryPropertyFlags(StorageMode mode) {
21+
switch (mode) {
22+
case StorageMode::kHostVisible:
23+
return vk::MemoryPropertyFlagBits::eHostVisible;
24+
case StorageMode::kDevicePrivate:
25+
return vk::MemoryPropertyFlagBits::eDeviceLocal;
26+
case StorageMode::kDeviceTransient:
27+
return vk::MemoryPropertyFlagBits::eLazilyAllocated;
28+
}
29+
FML_UNREACHABLE();
30+
}
31+
32+
static VmaAllocationCreateFlags ToVmaAllocationBufferCreateFlags(
33+
StorageMode mode) {
34+
VmaAllocationCreateFlags flags = 0;
35+
switch (mode) {
36+
case StorageMode::kHostVisible:
37+
flags |= VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT;
38+
flags |= VMA_ALLOCATION_CREATE_MAPPED_BIT;
39+
return flags;
40+
case StorageMode::kDevicePrivate:
41+
return flags;
42+
case StorageMode::kDeviceTransient:
43+
return flags;
44+
}
45+
FML_UNREACHABLE();
46+
}
47+
48+
static PoolVMA CreateBufferPool(VmaAllocator allocator) {
49+
vk::BufferCreateInfo buffer_info;
50+
buffer_info.usage = vk::BufferUsageFlagBits::eVertexBuffer |
51+
vk::BufferUsageFlagBits::eIndexBuffer |
52+
vk::BufferUsageFlagBits::eUniformBuffer |
53+
vk::BufferUsageFlagBits::eStorageBuffer |
54+
vk::BufferUsageFlagBits::eTransferSrc |
55+
vk::BufferUsageFlagBits::eTransferDst;
56+
buffer_info.size = 1u; // doesn't matter
57+
buffer_info.sharingMode = vk::SharingMode::eExclusive;
58+
auto buffer_info_native =
59+
static_cast<vk::BufferCreateInfo::NativeType>(buffer_info);
60+
61+
VmaAllocationCreateInfo allocation_info = {};
62+
allocation_info.usage = VMA_MEMORY_USAGE_AUTO;
63+
allocation_info.preferredFlags = static_cast<VkMemoryPropertyFlags>(
64+
ToVKBufferMemoryPropertyFlags(StorageMode::kHostVisible));
65+
allocation_info.flags =
66+
ToVmaAllocationBufferCreateFlags(StorageMode::kHostVisible);
67+
68+
uint32_t memTypeIndex;
69+
auto result = vk::Result{vmaFindMemoryTypeIndexForBufferInfo(
70+
allocator, &buffer_info_native, &allocation_info, &memTypeIndex)};
71+
if (result != vk::Result::eSuccess) {
72+
return {};
73+
}
74+
75+
VmaPoolCreateInfo pool_create_info = {};
76+
pool_create_info.memoryTypeIndex = memTypeIndex;
77+
pool_create_info.flags = VMA_POOL_CREATE_IGNORE_BUFFER_IMAGE_GRANULARITY_BIT |
78+
VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT;
79+
80+
VmaPool pool = {};
81+
result = vk::Result{::vmaCreatePool(allocator, &pool_create_info, &pool)};
82+
if (result != vk::Result::eSuccess) {
83+
return {};
84+
}
85+
return {allocator, pool};
86+
}
87+
1988
AllocatorVK::AllocatorVK(std::weak_ptr<Context> context,
2089
uint32_t vulkan_api_version,
2190
const vk::PhysicalDevice& physical_device,
@@ -93,26 +162,16 @@ AllocatorVK::AllocatorVK(std::weak_ptr<Context> context,
93162
VALIDATION_LOG << "Could not create memory allocator";
94163
return;
95164
}
96-
for (auto i = 0u; i < kPoolCount; i++) {
97-
created_buffer_pools_ &=
98-
CreateBufferPool(allocator, &staging_buffer_pools_[i]);
165+
for (size_t i = 0u; i < staging_buffer_pools_.size(); i++) {
166+
staging_buffer_pools_[i].reset(CreateBufferPool(allocator));
167+
created_buffer_pools_ &= staging_buffer_pools_[i].is_valid();
99168
}
100-
allocator_ = allocator;
169+
allocator_.reset(allocator);
101170
supports_memoryless_textures_ = capabilities.SupportsMemorylessTextures();
102171
is_valid_ = true;
103172
}
104173

105-
AllocatorVK::~AllocatorVK() {
106-
TRACE_EVENT0("impeller", "DestroyAllocatorVK");
107-
if (allocator_) {
108-
for (auto i = 0u; i < kPoolCount; i++) {
109-
if (staging_buffer_pools_[i]) {
110-
::vmaDestroyPool(allocator_, staging_buffer_pools_[i]);
111-
}
112-
}
113-
::vmaDestroyAllocator(allocator_);
114-
}
115-
}
174+
AllocatorVK::~AllocatorVK() = default;
116175

117176
// |Allocator|
118177
bool AllocatorVK::IsValid() const {
@@ -206,35 +265,6 @@ ToVKTextureMemoryPropertyFlags(StorageMode mode,
206265
FML_UNREACHABLE();
207266
}
208267

209-
static constexpr vk::Flags<vk::MemoryPropertyFlagBits>
210-
ToVKBufferMemoryPropertyFlags(StorageMode mode) {
211-
switch (mode) {
212-
case StorageMode::kHostVisible:
213-
return vk::MemoryPropertyFlagBits::eHostVisible;
214-
case StorageMode::kDevicePrivate:
215-
return vk::MemoryPropertyFlagBits::eDeviceLocal;
216-
case StorageMode::kDeviceTransient:
217-
return vk::MemoryPropertyFlagBits::eLazilyAllocated;
218-
}
219-
FML_UNREACHABLE();
220-
}
221-
222-
static VmaAllocationCreateFlags ToVmaAllocationBufferCreateFlags(
223-
StorageMode mode) {
224-
VmaAllocationCreateFlags flags = 0;
225-
switch (mode) {
226-
case StorageMode::kHostVisible:
227-
flags |= VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT;
228-
flags |= VMA_ALLOCATION_CREATE_MAPPED_BIT;
229-
return flags;
230-
case StorageMode::kDevicePrivate:
231-
return flags;
232-
case StorageMode::kDeviceTransient:
233-
return flags;
234-
}
235-
FML_UNREACHABLE();
236-
}
237-
238268
static VmaAllocationCreateFlags ToVmaAllocationCreateFlags(StorageMode mode,
239269
bool is_texture,
240270
size_t size) {
@@ -357,61 +387,36 @@ class AllocatedTextureSourceVK final : public TextureSourceVK {
357387
<< vk::to_string(result);
358388
return;
359389
}
360-
resource_.Reset(
361-
ImageResource(image, allocator, allocation, std::move(image_view)));
390+
resource_.Reset(ImageResource(ImageVMA{allocator, allocation, image},
391+
std::move(image_view)));
362392
is_valid_ = true;
363393
}
364394

365395
~AllocatedTextureSourceVK() = default;
366396

367397
bool IsValid() const { return is_valid_; }
368398

369-
vk::Image GetImage() const override { return resource_->image; }
399+
vk::Image GetImage() const override { return resource_->image.get().image; }
370400

371401
vk::ImageView GetImageView() const override {
372402
return resource_->image_view.get();
373403
}
374404

375405
private:
376406
struct ImageResource {
377-
vk::Image image = {};
378-
VmaAllocator allocator = {};
379-
VmaAllocation allocation = {};
407+
UniqueImageVMA image;
380408
vk::UniqueImageView image_view;
381409

382410
ImageResource() = default;
383411

384-
ImageResource(vk::Image p_image,
385-
VmaAllocator p_allocator,
386-
VmaAllocation p_allocation,
387-
vk::UniqueImageView p_image_view)
388-
: image(p_image),
389-
allocator(p_allocator),
390-
allocation(p_allocation),
391-
image_view(std::move(p_image_view)) {}
412+
ImageResource(ImageVMA p_image, vk::UniqueImageView p_image_view)
413+
: image(p_image), image_view(std::move(p_image_view)) {}
392414

393415
ImageResource(ImageResource&& o) {
394416
std::swap(image, o.image);
395-
std::swap(allocator, o.allocator);
396-
std::swap(allocation, o.allocation);
397417
std::swap(image_view, o.image_view);
398418
}
399419

400-
~ImageResource() {
401-
if (!image) {
402-
return;
403-
}
404-
TRACE_EVENT0("impeller", "DestroyDeviceTexture");
405-
image_view.reset();
406-
if (image) {
407-
::vmaDestroyImage(
408-
allocator, //
409-
static_cast<typename decltype(image)::NativeType>(image), //
410-
allocation //
411-
);
412-
}
413-
}
414-
415420
FML_DISALLOW_COPY_AND_ASSIGN(ImageResource);
416421
};
417422

@@ -439,7 +444,7 @@ std::shared_ptr<Texture> AllocatorVK::OnCreateTexture(
439444
auto source = std::make_shared<AllocatedTextureSourceVK>(
440445
ContextVK::Cast(*context).GetResourceManager(), //
441446
desc, //
442-
allocator_, //
447+
allocator_.get(), //
443448
device_holder->GetDevice(), //
444449
supports_memoryless_textures_ //
445450
);
@@ -477,13 +482,16 @@ std::shared_ptr<DeviceBuffer> AllocatorVK::OnCreateBuffer(
477482
allocation_info.flags = ToVmaAllocationBufferCreateFlags(desc.storage_mode);
478483
if (created_buffer_pools_ && desc.storage_mode == StorageMode::kHostVisible &&
479484
raster_thread_id_ == std::this_thread::get_id()) {
480-
allocation_info.pool = staging_buffer_pools_[frame_count_ % kPoolCount];
485+
allocation_info.pool =
486+
staging_buffer_pools_[frame_count_ % staging_buffer_pools_.size()]
487+
.get()
488+
.pool;
481489
}
482490

483491
VkBuffer buffer = {};
484492
VmaAllocation buffer_allocation = {};
485493
VmaAllocationInfo buffer_allocation_info = {};
486-
auto result = vk::Result{::vmaCreateBuffer(allocator_, //
494+
auto result = vk::Result{::vmaCreateBuffer(allocator_.get(), //
487495
&buffer_info_native, //
488496
&allocation_info, //
489497
&buffer, //
@@ -497,53 +505,14 @@ std::shared_ptr<DeviceBuffer> AllocatorVK::OnCreateBuffer(
497505
return {};
498506
}
499507

500-
return std::make_shared<DeviceBufferVK>(desc, //
501-
context_, //
502-
allocator_, //
503-
buffer_allocation, //
504-
buffer_allocation_info, //
505-
vk::Buffer{buffer} //
508+
return std::make_shared<DeviceBufferVK>(
509+
desc, //
510+
context_, //
511+
UniqueBufferVMA{BufferVMA{allocator_.get(), //
512+
buffer_allocation, //
513+
vk::Buffer{buffer}}}, //
514+
buffer_allocation_info //
506515
);
507516
}
508517

509-
// static
510-
bool AllocatorVK::CreateBufferPool(VmaAllocator allocator, VmaPool* pool) {
511-
vk::BufferCreateInfo buffer_info;
512-
buffer_info.usage = vk::BufferUsageFlagBits::eVertexBuffer |
513-
vk::BufferUsageFlagBits::eIndexBuffer |
514-
vk::BufferUsageFlagBits::eUniformBuffer |
515-
vk::BufferUsageFlagBits::eStorageBuffer |
516-
vk::BufferUsageFlagBits::eTransferSrc |
517-
vk::BufferUsageFlagBits::eTransferDst;
518-
buffer_info.size = 1u; // doesn't matter
519-
buffer_info.sharingMode = vk::SharingMode::eExclusive;
520-
auto buffer_info_native =
521-
static_cast<vk::BufferCreateInfo::NativeType>(buffer_info);
522-
523-
VmaAllocationCreateInfo allocation_info = {};
524-
allocation_info.usage = VMA_MEMORY_USAGE_AUTO;
525-
allocation_info.preferredFlags = static_cast<VkMemoryPropertyFlags>(
526-
ToVKBufferMemoryPropertyFlags(StorageMode::kHostVisible));
527-
allocation_info.flags =
528-
ToVmaAllocationBufferCreateFlags(StorageMode::kHostVisible);
529-
530-
uint32_t memTypeIndex;
531-
auto result = vk::Result{vmaFindMemoryTypeIndexForBufferInfo(
532-
allocator, &buffer_info_native, &allocation_info, &memTypeIndex)};
533-
if (result != vk::Result::eSuccess) {
534-
return false;
535-
}
536-
537-
VmaPoolCreateInfo pool_create_info = {};
538-
pool_create_info.memoryTypeIndex = memTypeIndex;
539-
pool_create_info.flags = VMA_POOL_CREATE_IGNORE_BUFFER_IMAGE_GRANULARITY_BIT |
540-
VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT;
541-
542-
result = vk::Result{vmaCreatePool(allocator, &pool_create_info, pool)};
543-
if (result != vk::Result::eSuccess) {
544-
return false;
545-
}
546-
return true;
547-
}
548-
549518
} // namespace impeller

impeller/renderer/backend/vulkan/allocator_vk.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "impeller/renderer/backend/vulkan/device_holder.h"
1414
#include "impeller/renderer/backend/vulkan/vk.h"
1515

16+
#include <array>
1617
#include <memory>
1718

1819
namespace impeller {
@@ -28,8 +29,8 @@ class AllocatorVK final : public Allocator {
2829
static constexpr size_t kPoolCount = 3;
2930

3031
fml::RefPtr<vulkan::VulkanProcTable> vk_;
31-
VmaAllocator allocator_ = {};
32-
VmaPool staging_buffer_pools_[kPoolCount] = {};
32+
UniqueAllocatorVMA allocator_;
33+
std::array<UniquePoolVMA, kPoolCount> staging_buffer_pools_;
3334
std::weak_ptr<Context> context_;
3435
std::weak_ptr<DeviceHolder> device_holder_;
3536
ISize max_texture_size_;
@@ -66,8 +67,6 @@ class AllocatorVK final : public Allocator {
6667
// |Allocator|
6768
ISize GetMaxTextureSizeSupported() const override;
6869

69-
static bool CreateBufferPool(VmaAllocator allocator, VmaPool* pool);
70-
7170
FML_DISALLOW_COPY_AND_ASSIGN(AllocatorVK);
7271
};
7372

0 commit comments

Comments
 (0)