| // Copyright 2018 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_RENDERER_BUFFER_CACHE_H_ |
| #define SRC_UI_LIB_ESCHER_RENDERER_BUFFER_CACHE_H_ |
| |
| #include <chrono> |
| #include <list> |
| #include <map> |
| |
| #include "src/lib/fxl/memory/weak_ptr.h" |
| #include "src/ui/lib/escher/escher.h" |
| #include "src/ui/lib/escher/forward_declarations.h" |
| #include "src/ui/lib/escher/resources/resource_recycler.h" |
| #include "src/ui/lib/escher/vk/buffer.h" |
| #include "src/ui/lib/escher/vk/gpu_allocator.h" |
| |
| #include <vulkan/vulkan.hpp> |
| |
| namespace escher { |
| |
| using BufferCacheWeakPtr = fxl::WeakPtr<BufferCache>; |
| using GpuAllocatorWeakPtr = fxl::WeakPtr<GpuAllocator>; |
| |
| // Allow client to obtain new or recycled Buffers backed by host GPU memory. |
| // All Buffers obtained from a BufferCache must be destroyed before the |
| // BufferCache is destroyed. |
| class BufferCache : public ResourceRecycler { |
| public: |
| explicit BufferCache(EscherWeakPtr escher); |
| ~BufferCache() override; |
| |
| fxl::WeakPtr<BufferCache> GetWeakPtr() { return weak_factory_.GetWeakPtr(); } |
| |
| // Obtain an unused Buffer with the required properties. A new Buffer might |
| // be created, or an existing one reused. NOTE: the buffer is not guaranteed |
| // to be exactly the requested size; it may be larger. |
| BufferPtr NewHostBuffer(vk::DeviceSize size); |
| |
| // |ResourceRecycler| |
| void RecycleResource(std::unique_ptr<Resource> resource) override; |
| |
| size_t free_buffer_count() const { return free_buffers_by_id_.size(); } |
| |
| private: |
| // The maximum amount of allocated memory cached in the BufferCache. |
| // TODO() Optimize the maximum amount of memory to cache. Value was chosen |
| // to match the amount of memory allocated by the GpuUploader by default. |
| static constexpr size_t kMaxMemoryCached = 1024 * 1024; |
| |
| // Buffer usage info. |
| // TODO(fxbug.dev/24068) Grow this class to handle different buffer usage and memory |
| // flags. It should work with the UniformBlockAllocator. |
| const vk::BufferUsageFlags kUsageFlags = |
| vk::BufferUsageFlagBits::eTransferSrc | vk::BufferUsageFlagBits::eTransferDst; |
| const vk::MemoryPropertyFlags kMemoryPropertyFlags = |
| vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent; |
| |
| struct CacheInfo { |
| uint64_t id; |
| std::chrono::steady_clock::time_point allocation_time; |
| vk::DeviceSize size; |
| }; |
| |
| // Represents an LRU cache of Buffers. Buffers are identified by their ID and |
| // accessed from the map of free buffers by their size. The cache is pruned |
| // when the working cache size exceeds kMaxMemoryCached. |
| std::map<std::chrono::steady_clock::time_point, CacheInfo> free_buffer_cache_; |
| std::map<uint64_t, CacheInfo> free_buffers_by_id_; |
| size_t cache_size_ = 0; |
| |
| // Map of free buffers. |
| std::map<vk::DeviceSize, std::list<std::unique_ptr<Buffer>>> free_buffers_; |
| |
| // Allocator for the buffers. |
| GpuAllocatorWeakPtr gpu_allocator_; |
| |
| fxl::WeakPtrFactory<BufferCache> weak_factory_; // must be last |
| |
| FXL_DISALLOW_COPY_AND_ASSIGN(BufferCache); |
| }; |
| |
| } // namespace escher |
| |
| #endif // SRC_UI_LIB_ESCHER_RENDERER_BUFFER_CACHE_H_ |