blob: 840bc547d86cf24c2ba1435330d9092dba0a7dc7 [file] [log] [blame]
// 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.
#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 {
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(); }
// 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( 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
} // namespace escher