| // Copyright 2016 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef SRC_UI_LIB_ESCHER_IMPL_UNIFORM_BUFFER_POOL_H_ |
| #define SRC_UI_LIB_ESCHER_IMPL_UNIFORM_BUFFER_POOL_H_ |
| |
| #include <vector> |
| #include <vulkan/vulkan.hpp> |
| |
| #include "src/lib/fxl/memory/weak_ptr.h" |
| #include "src/ui/lib/escher/forward_declarations.h" |
| #include "src/ui/lib/escher/resources/resource_manager.h" |
| #include "src/ui/lib/escher/vk/buffer.h" |
| |
| namespace escher { |
| namespace impl { |
| |
| // Vends host-accessible Buffers whose resources are automatically returned |
| // to the pool upon destruction. If necessary, it will grow by creating new |
| // buffers (and allocating backing memory for them). |additional_flags| allows |
| // the user to customize the memory that is allocated by the pool; by default, |
| // only eHostVisible is used. Not thread-safe. |
| class UniformBufferPool : public ResourceManager { |
| public: |
| UniformBufferPool(EscherWeakPtr escher, size_t ring_size, |
| // If no allocator is provided, Escher's default allocator will be used. |
| GpuAllocator* allocator = nullptr, |
| vk::MemoryPropertyFlags additional_flags = vk::MemoryPropertyFlags()); |
| ~UniformBufferPool(); |
| |
| UniformBufferPoolWeakPtr GetWeakPtr() { return weak_factory_.GetWeakPtr(); } |
| |
| // Allocate a buffer that will be returned to this pool when the last |
| // reference to it is dropped. |
| BufferPtr Allocate(); |
| |
| // Rotate the ring buffer so that buffers freed in previous frames are moved |
| // toward the front. |
| void BeginFrame(); |
| |
| // Return the size of buffers allocated by this allocator; constant over the |
| // allocator's lifetime. |
| // |
| // NOTE: this value is currently always 64kB, which is a typical max-size for |
| // Vulkan uniform buffers. |
| vk::DeviceSize buffer_size() const { return buffer_size_; } |
| |
| private: |
| // Implement ResourceManager::OnReceiveOwnable(). |
| void OnReceiveOwnable(std::unique_ptr<Resource> resource) override; |
| |
| // Create a batch of new buffers, which are added to free_buffers_. |
| void InternalAllocate(); |
| |
| // Used to allocate backing memory for the pool's buffers. |
| GpuAllocator* const allocator_; |
| |
| // Specify the properties of the memory used to back the pool's buffers (e.g. |
| // host-visible and coherent). |
| const vk::MemoryPropertyFlags flags_; |
| |
| // The size of each allocated buffer. |
| const vk::DeviceSize buffer_size_; |
| |
| using FreeBuffers = std::vector<std::unique_ptr<Buffer>>; |
| |
| // Queue of FreeBuffers that will become available for allocation once they |
| // reach the front. This allows reuse to be deferred for a number of frames, |
| // so that the memory isn't stomped while it is still in use. |
| static constexpr size_t kMaxRingSize = 25; |
| FreeBuffers ring_[kMaxRingSize]; |
| size_t ring_size_; |
| |
| // See comment in InternalAllocate(). |
| bool is_allocating_ = false; |
| |
| fxl::WeakPtrFactory<UniformBufferPool> weak_factory_; // must be last |
| |
| FXL_DISALLOW_COPY_AND_ASSIGN(UniformBufferPool); |
| }; |
| |
| } // namespace impl |
| } // namespace escher |
| |
| #endif // SRC_UI_LIB_ESCHER_IMPL_UNIFORM_BUFFER_POOL_H_ |