Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
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
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: "
117 << vk::to_string(result);
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
std::shared_ptr< DescriptorPoolRecyclerVK > GetDescriptorPoolRecycler() const
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
static const constexpr DescriptorPoolSize kDefaultBindingSize
Descriptor pools are always allocated with the following sizes.
Definition ref_ptr.h:256
#define VALIDATION_LOG
Definition validation.h:73