blob: e3aad3e6a2088606526b272552119a217a1352aa [file] [log] [blame]
// 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_