Flutter Impeller
descriptor_pool_vk.h
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 
5 #ifndef FLUTTER_IMPELLER_RENDERER_BACKEND_VULKAN_DESCRIPTOR_POOL_VK_H_
6 #define FLUTTER_IMPELLER_RENDERER_BACKEND_VULKAN_DESCRIPTOR_POOL_VK_H_
7 
8 #include <cstdint>
9 
10 #include "fml/status_or.h"
12 #include "vulkan/vulkan_handles.hpp"
13 
14 namespace impeller {
15 
16 //------------------------------------------------------------------------------
17 /// @brief A short-lived fixed-sized descriptor pool. Descriptors
18 /// from this pool don't need to be freed individually. Instead, the
19 /// pool must be collected after all the descriptors allocated from
20 /// it are done being used.
21 ///
22 /// The pool or it's descriptors may not be accessed from multiple
23 /// threads.
24 ///
25 /// Encoders create pools as necessary as they have the same
26 /// threading and lifecycle restrictions.
28  public:
29  explicit DescriptorPoolVK(const std::weak_ptr<const ContextVK>& context);
30 
32 
33  fml::StatusOr<std::vector<vk::DescriptorSet>> AllocateDescriptorSets(
34  uint32_t buffer_count,
35  uint32_t sampler_count,
36  uint32_t subpass_count,
37  const std::vector<vk::DescriptorSetLayout>& layouts);
38 
39  private:
40  std::weak_ptr<const ContextVK> context_;
41  vk::UniqueDescriptorPool pool_ = {};
42  uint32_t allocated_capacity_ = 0;
43 
44  DescriptorPoolVK(const DescriptorPoolVK&) = delete;
45 
46  DescriptorPoolVK& operator=(const DescriptorPoolVK&) = delete;
47 };
48 
49 // A descriptor pool and its allocated buffer/sampler size.
50 using DescriptorPoolAndSize = std::pair<vk::UniqueDescriptorPool, uint32_t>;
51 
52 //------------------------------------------------------------------------------
53 /// @brief Creates and manages the lifecycle of |vk::DescriptorPoolVK|
54 /// objects.
55 ///
56 /// To make descriptor pool recycling more effective, the number of requusted
57 /// descriptor slots is rounded up the nearest power of two. This also makes
58 /// determining whether a recycled pool has sufficient slots easier as only a
59 /// single number comparison is required.
60 ///
61 /// We round up to a minimum of 64 as the smallest power of two to reduce the
62 /// range of potential allocations to approximately: 64, 128, 256, 512, 1024,
63 /// 2048, 4096. Beyond this size applications will have far too many drawing
64 /// commands to render correctly. We also limit the number of cached descriptor
65 /// pools to 32, which is somewhat arbitrarily chosen, but given 2-ish frames in
66 /// flight is about 16 descriptors pools per frame which is extremely generous.
68  : public std::enable_shared_from_this<DescriptorPoolRecyclerVK> {
69  public:
70  ~DescriptorPoolRecyclerVK() = default;
71 
72  /// The maximum number of descriptor pools this recycler will hold onto.
73  static constexpr size_t kMaxRecycledPools = 32u;
74 
75  /// @brief Creates a recycler for the given |ContextVK|.
76  ///
77  /// @param[in] context The context to create the recycler for.
78  explicit DescriptorPoolRecyclerVK(std::weak_ptr<ContextVK> context)
79  : context_(std::move(context)) {}
80 
81  /// @brief Gets a descriptor pool with at least [minimum_capacity]
82  /// sampler and slots.
83  ///
84  /// This may create a new descriptor pool if no existing pools had
85  /// the necessary capacity.
86  DescriptorPoolAndSize Get(uint32_t minimum_capacity);
87 
88  /// @brief Returns the descriptor pool to be reset on a background
89  /// thread.
90  ///
91  /// @param[in] pool The pool to recycler.
92  void Reclaim(vk::UniqueDescriptorPool&& pool, uint32_t allocated_capacity);
93 
94  private:
95  std::weak_ptr<ContextVK> context_;
96 
97  Mutex recycled_mutex_;
98  std::vector<DescriptorPoolAndSize> recycled_ IPLR_GUARDED_BY(recycled_mutex_);
99 
100  /// @brief Creates a new |vk::CommandPool|.
101  ///
102  /// The descriptor pool will have at least [minimum_capacity]
103  /// buffer and texture slots.
104  ///
105  /// @returns Returns a |std::nullopt| if a pool could not be created.
106  DescriptorPoolAndSize Create(uint32_t minimum_capacity);
107 
108  /// @brief Reuses a recycled |vk::CommandPool|, if available.
109  ///
110  /// The descriptor pool will have at least [minimum_capacity]
111  /// buffer and texture slots. [minimum_capacity] should be rounded
112  /// up to the next power of two for more efficient cache reuse.
113  ///
114  /// @returns Returns a |std::nullopt| if a pool was not available.
115  std::optional<DescriptorPoolAndSize> Reuse(uint32_t minimum_capacity);
116 
118 
119  DescriptorPoolRecyclerVK& operator=(const DescriptorPoolRecyclerVK&) = delete;
120 };
121 
122 } // namespace impeller
123 
124 #endif // FLUTTER_IMPELLER_RENDERER_BACKEND_VULKAN_DESCRIPTOR_POOL_VK_H_
impeller::DescriptorPoolVK::~DescriptorPoolVK
~DescriptorPoolVK()
Definition: descriptor_pool_vk.cc:61
impeller::DescriptorPoolRecyclerVK::Reclaim
void Reclaim(vk::UniqueDescriptorPool &&pool, uint32_t allocated_capacity)
Returns the descriptor pool to be reset on a background thread.
Definition: descriptor_pool_vk.cc:117
impeller::DescriptorPoolRecyclerVK::~DescriptorPoolRecyclerVK
~DescriptorPoolRecyclerVK()=default
impeller::DescriptorPoolRecyclerVK
Creates and manages the lifecycle of |vk::DescriptorPoolVK| objects.
Definition: descriptor_pool_vk.h:67
impeller::DescriptorPoolVK::DescriptorPoolVK
DescriptorPoolVK(const std::weak_ptr< const ContextVK > &context)
Definition: descriptor_pool_vk.cc:55
impeller::DescriptorPoolRecyclerVK::kMaxRecycledPools
static constexpr size_t kMaxRecycledPools
The maximum number of descriptor pools this recycler will hold onto.
Definition: descriptor_pool_vk.h:73
impeller::DescriptorPoolRecyclerVK::DescriptorPoolRecyclerVK
DescriptorPoolRecyclerVK(std::weak_ptr< ContextVK > context)
Creates a recycler for the given |ContextVK|.
Definition: descriptor_pool_vk.h:78
impeller::DescriptorPoolVK
A short-lived fixed-sized descriptor pool. Descriptors from this pool don't need to be freed individu...
Definition: descriptor_pool_vk.h:27
impeller::DescriptorPoolAndSize
std::pair< vk::UniqueDescriptorPool, uint32_t > DescriptorPoolAndSize
Definition: descriptor_pool_vk.h:50
std
Definition: comparable.h:95
impeller::DescriptorPoolRecyclerVK::Get
DescriptorPoolAndSize Get(uint32_t minimum_capacity)
Gets a descriptor pool with at least [minimum_capacity] sampler and slots.
Definition: descriptor_pool_vk.cc:158
impeller::DescriptorPoolVK::AllocateDescriptorSets
fml::StatusOr< std::vector< vk::DescriptorSet > > AllocateDescriptorSets(uint32_t buffer_count, uint32_t sampler_count, uint32_t subpass_count, const std::vector< vk::DescriptorSetLayout > &layouts)
Definition: descriptor_pool_vk.cc:83
context_vk.h
impeller
Definition: aiks_context.cc:10