| 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"
11 #include "impeller/renderer/backend/vulkan/context_vk.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.
27 class DescriptorPoolVK {
28 public:
29 explicit DescriptorPoolVK(const std::weak_ptr<const ContextVK>& context);
30
31 ~DescriptorPoolVK();
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.
67 class DescriptorPoolRecyclerVK final
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
117 DescriptorPoolRecyclerVK(const DescriptorPoolRecyclerVK&) = delete;
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