Flutter Engine
The Flutter Engine
descriptor_pool_vk.cc
Go to the documentation of this file.
1// Copyright 2013 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
6
7#include <optional>
8
11#include "vulkan/vulkan_enums.hpp"
12#include "vulkan/vulkan_handles.hpp"
13
14namespace impeller {
15
21};
22
23/// Descriptor pools are always allocated with the following sizes.
26 .buffer_bindings = 512u, // Buffer Bindings
27 .texture_bindings = 256u, // Texture Bindings
28 .storage_bindings = 32,
29 .subpass_bindings = 4u // Subpass Bindings
30 };
31
32// Holds the command pool in a background thread, recyling it when not in use.
34 public:
36
38 vk::UniqueDescriptorPool&& pool,
39 std::weak_ptr<DescriptorPoolRecyclerVK> recycler)
40 : pool_(std::move(pool)), recycler_(std::move(recycler)) {}
41
43 auto const recycler = recycler_.lock();
44
45 // Not only does this prevent recycling when the context is being destroyed,
46 // but it also prevents the destructor from effectively being called twice;
47 // once for the original BackgroundCommandPoolVK() and once for the moved
48 // BackgroundCommandPoolVK().
49 if (!recycler) {
50 return;
51 }
52
53 recycler->Reclaim(std::move(pool_));
54 }
55
56 private:
58
60 delete;
61
62 vk::UniqueDescriptorPool pool_;
63 uint32_t allocated_capacity_;
64 std::weak_ptr<DescriptorPoolRecyclerVK> recycler_;
65};
66
67DescriptorPoolVK::DescriptorPoolVK(std::weak_ptr<const ContextVK> context)
68 : context_(std::move(context)) {}
69
71 if (pools_.empty()) {
72 return;
73 }
74
75 auto const context = context_.lock();
76 if (!context) {
77 return;
78 }
79 auto const recycler = context->GetDescriptorPoolRecycler();
80 if (!recycler) {
81 return;
82 }
83
84 for (auto i = 0u; i < pools_.size(); i++) {
85 auto reset_pool_when_dropped =
86 BackgroundDescriptorPoolVK(std::move(pools_[i]), recycler);
87
89 context->GetResourceManager(), std::move(reset_pool_when_dropped));
90 }
91 pools_.clear();
92}
93
95 const vk::DescriptorSetLayout& layout,
96 const ContextVK& context_vk) {
97 if (pools_.empty()) {
98 CreateNewPool(context_vk);
99 }
100
101 vk::DescriptorSetAllocateInfo set_info;
102 set_info.setDescriptorPool(pools_.back().get());
103 set_info.setPSetLayouts(&layout);
104 set_info.setDescriptorSetCount(1);
105
106 vk::DescriptorSet set;
107 auto result = context_vk.GetDevice().allocateDescriptorSets(&set_info, &set);
108 if (result == vk::Result::eErrorOutOfPoolMemory) {
109 // If the pool ran out of memory, we need to create a new pool.
110 CreateNewPool(context_vk);
111 set_info.setDescriptorPool(pools_.back().get());
112 result = context_vk.GetDevice().allocateDescriptorSets(&set_info, &set);
113 }
114
115 if (result != vk::Result::eSuccess) {
116 VALIDATION_LOG << "Could not allocate descriptor sets: "
119 }
120 return set;
121}
122
123fml::Status DescriptorPoolVK::CreateNewPool(const ContextVK& context_vk) {
124 auto new_pool = context_vk.GetDescriptorPoolRecycler()->Get();
125 if (!new_pool) {
127 "Failed to create descriptor pool");
128 }
129 pools_.emplace_back(std::move(new_pool));
130 return fml::Status();
131}
132
133void DescriptorPoolRecyclerVK::Reclaim(vk::UniqueDescriptorPool&& pool) {
134 // Reset the pool on a background thread.
135 auto strong_context = context_.lock();
136 if (!strong_context) {
137 return;
138 }
139 auto device = strong_context->GetDevice();
140 device.resetDescriptorPool(pool.get());
141
142 // Move the pool to the recycled list.
143 Lock recycled_lock(recycled_mutex_);
144
145 if (recycled_.size() < kMaxRecycledPools) {
146 recycled_.push_back(std::move(pool));
147 return;
148 }
149}
150
151vk::UniqueDescriptorPool DescriptorPoolRecyclerVK::Get() {
152 // Recycle a pool with a matching minumum capcity if it is available.
153 auto recycled_pool = Reuse();
154 if (recycled_pool.has_value()) {
155 return std::move(recycled_pool.value());
156 }
157 return Create();
158}
159
160vk::UniqueDescriptorPool DescriptorPoolRecyclerVK::Create() {
161 auto strong_context = context_.lock();
162 if (!strong_context) {
163 VALIDATION_LOG << "Unable to create a descriptor pool";
164 return {};
165 }
166
167 std::vector<vk::DescriptorPoolSize> pools = {
168 vk::DescriptorPoolSize{vk::DescriptorType::eCombinedImageSampler,
170 vk::DescriptorPoolSize{vk::DescriptorType::eUniformBuffer,
172 vk::DescriptorPoolSize{vk::DescriptorType::eStorageBuffer,
174 vk::DescriptorPoolSize{vk::DescriptorType::eInputAttachment,
176 vk::DescriptorPoolCreateInfo pool_info;
177 pool_info.setMaxSets(kDefaultBindingSize.texture_bindings +
181 pool_info.setPoolSizes(pools);
182 auto [result, pool] =
183 strong_context->GetDevice().createDescriptorPoolUnique(pool_info);
184 if (result != vk::Result::eSuccess) {
185 VALIDATION_LOG << "Unable to create a descriptor pool";
186 }
187 return std::move(pool);
188}
189
190std::optional<vk::UniqueDescriptorPool> DescriptorPoolRecyclerVK::Reuse() {
191 Lock lock(recycled_mutex_);
192 if (recycled_.empty()) {
193 return std::nullopt;
194 }
195
196 auto recycled = std::move(recycled_[recycled_.size() - 1]);
197 recycled_.pop_back();
198 return recycled;
199}
200
201} // namespace impeller
AutoreleasePool pool
BackgroundDescriptorPoolVK(BackgroundDescriptorPoolVK &&)=default
BackgroundDescriptorPoolVK(vk::UniqueDescriptorPool &&pool, std::weak_ptr< DescriptorPoolRecyclerVK > recycler)
const vk::Device & GetDevice() const
Definition: context_vk.cc:513
std::shared_ptr< DescriptorPoolRecyclerVK > GetDescriptorPoolRecycler() const
Definition: context_vk.cc:572
vk::UniqueDescriptorPool Get()
Gets a descriptor pool.
void Reclaim(vk::UniqueDescriptorPool &&pool)
Returns the descriptor pool to be reset on a background thread.
static constexpr size_t kMaxRecycledPools
The maximum number of descriptor pools this recycler will hold onto.
DescriptorPoolVK(std::weak_ptr< const ContextVK > context)
fml::StatusOr< vk::DescriptorSet > AllocateDescriptorSets(const vk::DescriptorSetLayout &layout, const ContextVK &context_vk)
A unique handle to a resource which will be reclaimed by the specified resource manager.
VkDevice device
Definition: main.cc:53
GAsyncResult * result
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not set
Definition: switches.h:76
static const constexpr DescriptorPoolSize kDefaultBindingSize
Descriptor pools are always allocated with the following sizes.
Task::Status Status
Definition: TaskList.cpp:15
Definition: ref_ptr.h:256
static SkString to_string(int n)
Definition: nanobench.cpp:119
#define VALIDATION_LOG
Definition: validation.h:73