-
Notifications
You must be signed in to change notification settings - Fork 6k
[Impeller] Allocate buffers out of a pool on the raster thread. #43564
Changes from 1 commit
8590d30
866761f
1a01926
c85a337
3947f81
b8bee47
9d4d44a
4efb6a8
10d29cc
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
- Loading branch information
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -93,6 +93,11 @@ AllocatorVK::AllocatorVK(std::weak_ptr<Context> context, | |
| VALIDATION_LOG << "Could not create memory allocator"; | ||
| return; | ||
| } | ||
| for (auto i = 0u; i < 3u; i++) { | ||
| if (!CreateBufferPool(allocator, &staging_buffer_pools_[i])) { | ||
| return; | ||
| } | ||
| } | ||
| allocator_ = allocator; | ||
| supports_memoryless_textures_ = capabilities.SupportsMemorylessTextures(); | ||
| is_valid_ = true; | ||
|
|
@@ -101,6 +106,11 @@ AllocatorVK::AllocatorVK(std::weak_ptr<Context> context, | |
| AllocatorVK::~AllocatorVK() { | ||
| TRACE_EVENT0("impeller", "DestroyAllocatorVK"); | ||
| if (allocator_) { | ||
| for (auto i = 0u; i < 3u; i++) { | ||
| if (staging_buffer_pools_[i]) { | ||
| ::vmaDestroyPool(allocator_, staging_buffer_pools_[i]); | ||
| } | ||
| } | ||
| ::vmaDestroyAllocator(allocator_); | ||
| } | ||
| } | ||
|
|
@@ -210,6 +220,22 @@ static constexpr VkMemoryPropertyFlags ToVKBufferMemoryPropertyFlags( | |
| FML_UNREACHABLE(); | ||
| } | ||
|
|
||
| static VmaAllocationCreateFlags ToVmaAllocationBufferCreateFlags( | ||
| StorageMode mode) { | ||
| VmaAllocationCreateFlags flags = 0; | ||
| switch (mode) { | ||
| case StorageMode::kHostVisible: | ||
| flags |= VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT; | ||
| flags |= VMA_ALLOCATION_CREATE_MAPPED_BIT; | ||
| return flags; | ||
| case StorageMode::kDevicePrivate: | ||
| return flags; | ||
| case StorageMode::kDeviceTransient: | ||
| return flags; | ||
| } | ||
| FML_UNREACHABLE(); | ||
| } | ||
|
|
||
| static VmaAllocationCreateFlags ToVmaAllocationCreateFlags(StorageMode mode, | ||
| bool is_texture, | ||
| size_t size) { | ||
|
|
@@ -388,6 +414,11 @@ std::shared_ptr<Texture> AllocatorVK::OnCreateTexture( | |
| return std::make_shared<TextureVK>(context_, std::move(source)); | ||
| } | ||
|
|
||
| void AllocatorVK::IncrementFrame() { | ||
| frame_count_++; | ||
| raster_thread_id_ = std::this_thread::get_id(); | ||
| } | ||
|
|
||
| // |Allocator| | ||
| std::shared_ptr<DeviceBuffer> AllocatorVK::OnCreateBuffer( | ||
| const DeviceBufferDescriptor& desc) { | ||
|
|
@@ -410,6 +441,11 @@ std::shared_ptr<DeviceBuffer> AllocatorVK::OnCreateBuffer( | |
| ToVKBufferMemoryPropertyFlags(desc.storage_mode); | ||
| allocation_info.flags = ToVmaAllocationCreateFlags( | ||
| desc.storage_mode, /*is_texture=*/false, desc.size); | ||
| allocation_info.flags = ToVmaAllocationBufferCreateFlags(desc.storage_mode); | ||
| if (desc.storage_mode == StorageMode::kHostVisible && | ||
| raster_thread_id_ == std::this_thread::get_id()) { | ||
| allocation_info.pool = staging_buffer_pools_[frame_count_ % 3u]; | ||
| } | ||
|
|
||
| VkBuffer buffer = {}; | ||
| VmaAllocation buffer_allocation = {}; | ||
|
|
@@ -437,4 +473,46 @@ std::shared_ptr<DeviceBuffer> AllocatorVK::OnCreateBuffer( | |
| ); | ||
| } | ||
|
|
||
| // static | ||
| bool AllocatorVK::CreateBufferPool(VmaAllocator allocator, VmaPool* pool) { | ||
| vk::BufferCreateInfo buffer_info; | ||
| buffer_info.usage = vk::BufferUsageFlagBits::eVertexBuffer | | ||
| vk::BufferUsageFlagBits::eIndexBuffer | | ||
| vk::BufferUsageFlagBits::eUniformBuffer | | ||
| vk::BufferUsageFlagBits::eStorageBuffer | | ||
| vk::BufferUsageFlagBits::eTransferSrc | | ||
| vk::BufferUsageFlagBits::eTransferDst; | ||
| buffer_info.size = 1u; // doesn't matter | ||
| buffer_info.sharingMode = vk::SharingMode::eExclusive; | ||
| auto buffer_info_native = | ||
| static_cast<vk::BufferCreateInfo::NativeType>(buffer_info); | ||
|
|
||
| VmaAllocationCreateInfo allocation_info = {}; | ||
| allocation_info.usage = VMA_MEMORY_USAGE_AUTO; | ||
| allocation_info.preferredFlags = | ||
| ToVKBufferMemoryPropertyFlags(StorageMode::kHostVisible); | ||
| allocation_info.flags = | ||
| ToVmaAllocationBufferCreateFlags(StorageMode::kHostVisible); | ||
|
|
||
| uint32_t memTypeIndex; | ||
| auto result = vk::Result{vmaFindMemoryTypeIndexForBufferInfo( | ||
| allocator, &buffer_info_native, &allocation_info, &memTypeIndex)}; | ||
| if (result != vk::Result::eSuccess) { | ||
| VALIDATION_LOG << "Could not find memory type for buffer pool."; | ||
| return false; | ||
| } | ||
|
|
||
| VmaPoolCreateInfo pool_create_info = {}; | ||
| pool_create_info.memoryTypeIndex = memTypeIndex; | ||
| pool_create_info.flags = VMA_POOL_CREATE_IGNORE_BUFFER_IMAGE_GRANULARITY_BIT | | ||
| VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT; | ||
|
|
||
| result = vk::Result{vmaCreatePool(allocator, &pool_create_info, pool)}; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Pools, allocators, and allocations are getting pervasive enough that not having RAII wrappers is getting hard to reason about. In this patch or another if you prefer, can we wrap these in
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think I could make one for the allocator, but the pools also need an allocator for disposal and it doesn't look like fml::UniqueObject supports a userdata like ptr I could use for that. Is that a reasonable update you could make to support disposing pools? |
||
| if (result != vk::Result::eSuccess) { | ||
| VALIDATION_LOG << "Could not create buffer pool."; | ||
| return false; | ||
| } | ||
| return true; | ||
| } | ||
|
|
||
| } // namespace impeller | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -27,11 +27,14 @@ class AllocatorVK final : public Allocator { | |
|
|
||
| fml::RefPtr<vulkan::VulkanProcTable> vk_; | ||
| VmaAllocator allocator_ = {}; | ||
| VmaPool staging_buffer_pools_[3] = {}; | ||
|
||
| std::weak_ptr<Context> context_; | ||
| std::weak_ptr<DeviceHolder> device_holder_; | ||
| ISize max_texture_size_; | ||
| bool is_valid_ = false; | ||
| bool supports_memoryless_textures_ = false; | ||
| uint32_t frame_count_ = 0; | ||
| std::thread::id raster_thread_id_; | ||
|
|
||
| AllocatorVK(std::weak_ptr<Context> context, | ||
| uint32_t vulkan_api_version, | ||
|
|
@@ -45,6 +48,9 @@ class AllocatorVK final : public Allocator { | |
| // |Allocator| | ||
| bool IsValid() const; | ||
|
|
||
| // |Allocator| | ||
| void IncrementFrame() override; | ||
|
|
||
| // |Allocator| | ||
| std::shared_ptr<DeviceBuffer> OnCreateBuffer( | ||
| const DeviceBufferDescriptor& desc) override; | ||
|
|
@@ -56,6 +62,8 @@ class AllocatorVK final : public Allocator { | |
| // |Allocator| | ||
| ISize GetMaxTextureSizeSupported() const override; | ||
|
|
||
| static bool CreateBufferPool(VmaAllocator allocator, VmaPool* pool); | ||
|
|
||
| FML_DISALLOW_COPY_AND_ASSIGN(AllocatorVK); | ||
| }; | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -39,6 +39,7 @@ sk_sp<DlImage> SnapshotControllerImpeller::DoMakeRasterSnapshot( | |
| impeller::Picture picture = dispatcher.EndRecordingAsPicture(); | ||
| auto context = GetDelegate().GetAiksContext(); | ||
| if (context) { | ||
| context->GetContext()->GetResourceAllocator()->IncrementFrame(); | ||
|
||
| auto max_size = context->GetContext() | ||
| ->GetResourceAllocator() | ||
| ->GetMaxTextureSizeSupported(); | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is an assumption that the thread which invokves IncrementFrame is the raster thread and will do most of the allocation. This is important to keep worker thread allocations in the default pool.