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
10
11namespace impeller {
12
19
20/// Descriptor pools are always allocated with the following sizes.
23 .buffer_bindings = 512u, // Buffer Bindings
24 .texture_bindings = 256u, // Texture Bindings
25 .storage_bindings = 32,
26 .subpass_bindings = 4u // Subpass Bindings
27 };
28
29DescriptorPoolVK::DescriptorPoolVK(std::weak_ptr<const ContextVK> context)
30 : context_(std::move(context)) {}
31
32void DescriptorPoolVK::Destroy() {
33 pools_.clear();
34}
35
36DescriptorPoolVK::DescriptorPoolVK(std::weak_ptr<const ContextVK> context,
37 DescriptorCacheMap descriptor_sets,
38 std::vector<vk::UniqueDescriptorPool> pools)
39 : context_(std::move(context)),
40 descriptor_sets_(std::move(descriptor_sets)),
41 pools_(std::move(pools)) {}
42
44 if (pools_.empty()) {
45 return;
46 }
47
48 auto const context = context_.lock();
49 if (!context) {
50 return;
51 }
52 auto const recycler = context->GetDescriptorPoolRecycler();
53 if (!recycler) {
54 return;
55 }
56
57 recycler->Reclaim(std::move(descriptor_sets_), std::move(pools_));
58}
59
61 const vk::DescriptorSetLayout& layout,
62 PipelineKey pipeline_key,
63 const ContextVK& context_vk) {
64 DescriptorCacheMap::iterator existing = descriptor_sets_.find(pipeline_key);
65 if (existing != descriptor_sets_.end() && !existing->second.unused.empty()) {
66 auto descriptor_set = existing->second.unused.back();
67 existing->second.unused.pop_back();
68 existing->second.used.push_back(descriptor_set);
69 return descriptor_set;
70 }
71
72 if (pools_.empty()) {
73 CreateNewPool(context_vk);
74 }
75
76 vk::DescriptorSetAllocateInfo set_info;
77 set_info.setDescriptorPool(pools_.back().get());
78 set_info.setPSetLayouts(&layout);
79 set_info.setDescriptorSetCount(1);
80
81 vk::DescriptorSet set;
82 auto result = context_vk.GetDevice().allocateDescriptorSets(&set_info, &set);
83 if (result == vk::Result::eErrorOutOfPoolMemory) {
84 // If the pool ran out of memory, we need to create a new pool.
85 CreateNewPool(context_vk);
86 set_info.setDescriptorPool(pools_.back().get());
87 result = context_vk.GetDevice().allocateDescriptorSets(&set_info, &set);
88 }
89 auto lookup_result =
90 descriptor_sets_.try_emplace(pipeline_key, DescriptorCache{});
91 lookup_result.first->second.used.push_back(set);
92
93 if (result != vk::Result::eSuccess) {
94 VALIDATION_LOG << "Could not allocate descriptor sets: "
95 << vk::to_string(result);
97 }
98 return set;
99}
100
101fml::Status DescriptorPoolVK::CreateNewPool(const ContextVK& context_vk) {
102 auto new_pool = context_vk.GetDescriptorPoolRecycler()->Get();
103 if (!new_pool) {
105 "Failed to create descriptor pool");
106 }
107 pools_.emplace_back(std::move(new_pool));
108 return fml::Status();
109}
110
112 DescriptorCacheMap descriptor_sets,
113 std::vector<vk::UniqueDescriptorPool> pools) {
114 // Reset the pool on a background thread.
115 auto strong_context = context_.lock();
116 if (!strong_context) {
117 return;
118 }
119
120 for (auto& [_, cache] : descriptor_sets) {
121 cache.unused.insert(cache.unused.end(), cache.used.begin(),
122 cache.used.end());
123 cache.used.clear();
124 }
125
126 // Move the pool to the recycled list. If more than 32 pool are
127 // cached then delete the newest entry.
128 Lock recycled_lock(recycled_mutex_);
129 while (recycled_.size() >= kMaxRecycledPools) {
130 auto& back_entry = recycled_.back();
131 back_entry->Destroy();
132 recycled_.pop_back();
133 }
134 recycled_.push_back(std::make_shared<DescriptorPoolVK>(
135 context_, std::move(descriptor_sets), std::move(pools)));
136}
137
138vk::UniqueDescriptorPool DescriptorPoolRecyclerVK::Get() {
139 // Recycle a pool with a matching minumum capcity if it is available.
140 return Create();
141}
142
143vk::UniqueDescriptorPool DescriptorPoolRecyclerVK::Create() {
144 auto strong_context = context_.lock();
145 if (!strong_context) {
146 VALIDATION_LOG << "Unable to create a descriptor pool";
147 return {};
148 }
149
150 std::vector<vk::DescriptorPoolSize> pools = {
151 vk::DescriptorPoolSize{vk::DescriptorType::eCombinedImageSampler,
153 vk::DescriptorPoolSize{vk::DescriptorType::eUniformBuffer,
155 vk::DescriptorPoolSize{vk::DescriptorType::eStorageBuffer,
157 vk::DescriptorPoolSize{vk::DescriptorType::eInputAttachment,
159 vk::DescriptorPoolCreateInfo pool_info;
160 pool_info.setMaxSets(kDefaultBindingSize.texture_bindings +
164 pool_info.setPoolSizes(pools);
165 auto [result, pool] =
166 strong_context->GetDevice().createDescriptorPoolUnique(pool_info);
167 if (result != vk::Result::eSuccess) {
168 VALIDATION_LOG << "Unable to create a descriptor pool";
169 }
170 return std::move(pool);
171}
172
173std::shared_ptr<DescriptorPoolVK>
175 {
176 Lock recycled_lock(recycled_mutex_);
177 if (!recycled_.empty()) {
178 auto result = recycled_.back();
179 recycled_.pop_back();
180 return result;
181 }
182 }
183 return std::make_shared<DescriptorPoolVK>(context_);
184}
185
186} // namespace impeller
const vk::Device & GetDevice() const
std::shared_ptr< DescriptorPoolRecyclerVK > GetDescriptorPoolRecycler() const
std::shared_ptr< DescriptorPoolVK > GetDescriptorPool()
void Reclaim(DescriptorCacheMap descriptor_sets, std::vector< vk::UniqueDescriptorPool > pools)
vk::UniqueDescriptorPool Get()
Gets a descriptor pool.
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, PipelineKey pipeline_key, const ContextVK &context_vk)
std::unordered_map< PipelineKey, DescriptorCache > DescriptorCacheMap
int64_t PipelineKey
Definition pipeline.h:21
static const constexpr DescriptorPoolSize kDefaultBindingSize
Descriptor pools are always allocated with the following sizes.
Definition ref_ptr.h:261
Used and un-used descriptor sets.
#define VALIDATION_LOG
Definition validation.h:91