project-aster/samples/04_scenes/render_resource_manager.h

252 lines
7.5 KiB
C++

// =============================================
// Aster: render_resource_manager.h
// Copyright (c) 2020-2024 Anish Bhobe
// =============================================
#pragma once
#include "aster/aster.h"
#include <EASTL/deque.h>
#include <EASTL/vector_map.h>
struct Device;
struct Texture;
struct StorageTexture;
struct StorageBuffer;
struct Buffer;
struct GpuResourceHandle
{
constexpr static u32 INVALID_HANDLE = MaxValue<u32>;
u32 m_Index = INVALID_HANDLE; // Default = invalid
[[nodiscard]] bool
IsInvalid() const
{
return m_Index == INVALID_HANDLE;
}
};
struct BufferHandle : GpuResourceHandle
{
};
struct TextureHandle : GpuResourceHandle
{
};
struct StorageTextureHandle : GpuResourceHandle
{
};
struct SamplerHandle : GpuResourceHandle
{
};
struct VirtualizedBufferHandle : GpuResourceHandle
{
};
struct GeometryHandle : VirtualizedBufferHandle
{
};
struct IndexHandle : VirtualizedBufferHandle
{
};
struct MaterialHandle : VirtualizedBufferHandle
{
};
struct TextureManager
{
eastl::vector<Texture> m_Textures;
u32 m_MaxCapacity;
u32 m_FreeHead;
void Init(u32 maxCapacity);
TextureHandle Commit(Texture *texture);
Texture *Fetch(TextureHandle handle);
void Release(const Device *device, TextureHandle handle);
void Destroy(const Device *device);
};
struct BufferManager
{
Buffer* m_Buffers;
u32 m_MaxCapacity;
u32 m_FreeHead;
void Init(u32 maxCapacity);
BufferHandle Allocate(const Device *device, u32 bufferSize, cstr name);
BufferHandle Commit_(StorageBuffer *buffer);
StorageBuffer *Fetch(BufferHandle handle);
void Release(const Device *device, BufferHandle handle);
void Destroy(const Device *device);
};
struct StorageTextureManager : TextureManager
{
StorageTextureHandle Commit(StorageTexture *texture);
StorageTexture *Fetch(StorageTextureHandle handle);
void Release(const Device *device, StorageTextureHandle handle);
};
struct SamplerManager
{
// There can only be so many samplers.
eastl::vector<vk::Sampler> m_Samplers;
eastl::vector<usize> m_SamplerHashes;
void Init(usize size);
SamplerHandle Create(const Device *device, const vk::SamplerCreateInfo *createInfo);
vk::Sampler Fetch(SamplerHandle handle);
void Destroy(const Device *device);
};
struct VirtualizedBufferPool
{
// TODO: Use buffer device address
std::unique_ptr<StorageBuffer> m_BackingBuffer;
uptr m_BufferPtr;
VmaVirtualBlock m_Block;
struct VirtualBuffer
{
VmaVirtualAllocation m_Allocation;
usize m_Offset;
usize m_Size;
};
eastl::vector<VirtualBuffer> m_VirtualBuffers;
u32 m_FreeHead = GpuResourceHandle::INVALID_HANDLE;
bool m_Dirty = false;
void InitStorage(const Device *device, usize bufferMaxSize);
void InitIndex(const Device *device, usize bufferMaxSize);
// Sync the offset buffer if required.
// FUTURE(Bob): Handle the writes for non-ReBAR system.
void UpdateToGpu(const Device *device);
VirtualizedBufferHandle Create(usize size, usize alignment);
usize FetchOffset(VirtualizedBufferHandle handle);
void Release(VirtualizedBufferHandle handle);
void Write(VirtualizedBufferHandle handle, usize offset, usize size, const void *data);
void Destroy(const Device *device);
};
struct RenderResourceManager
{
private:
union WriteInfo {
vk::DescriptorBufferInfo uBufferInfo;
vk::DescriptorImageInfo uImageInfo;
vk::BufferView uBufferView;
WriteInfo()
{
}
explicit WriteInfo(vk::DescriptorBufferInfo info);
explicit WriteInfo(vk::DescriptorImageInfo info);
explicit WriteInfo(vk::BufferView info);
};
enum class HandleType
{
eBuffer,
eTexture,
eStorageTexture,
};
using WriteOwner = eastl::pair<HandleType, u32>;
eastl::deque<WriteInfo> m_WriteInfos;
eastl::vector<vk::WriteDescriptorSet> m_Writes;
eastl::vector<WriteOwner> m_WriteOwner;
vk::Sampler m_DefaultSampler;
VirtualizedBufferPool m_Geometry;
VirtualizedBufferPool m_Index;
VirtualizedBufferPool m_Material;
BufferManager m_BufferManager;
TextureManager m_TextureManager;
StorageTextureManager m_StorageTextureManager;
SamplerManager m_SamplerManager;
void EraseWrites(u32 handleIndex, HandleType handleType);
BufferHandle Commit_(StorageBuffer *storageBuffer); // Commit to GPU and take Ownership
public:
Device *m_Device;
constexpr static u32 BUFFER_BINDING_INDEX = 0;
constexpr static u32 TEXTURE_BINDING_INDEX = 1;
constexpr static u32 STORAGE_TEXTURE_BINDING_INDEX = 2;
constexpr static u32 UNIFIED_GEOMETRY_DATA_HANDLE_INDEX = 0;
constexpr static u32 UNIFIED_GEOMETRY_OFFSET_HANDLE_INDEX = 1;
constexpr static u32 MATERIAL_HANDLE_INDEX = 2;
vk::SamplerCreateInfo m_DefaultSamplerCreateInfo;
vk::DescriptorPool m_DescriptorPool;
vk::DescriptorSetLayout m_SetLayout;
vk::DescriptorSet m_DescriptorSet;
bool m_UseBufferAddr;
BufferHandle CreateStorageBuffer(u32 bufferSize, cstr name); // Allocate a new buffer and commit to GPU.
void Write(BufferHandle handle, usize offset, usize size, const void *data); // Write to buffer
void Release(BufferHandle handle); // Release and Destroy
void Release(StorageBuffer *storageBuffer, BufferHandle handle); // Release and Return
TextureHandle CommitTexture(Texture *texture, SamplerHandle sampler = {}); // Commit to GPU and take Ownership
void Release(TextureHandle handle); // Release and Destroy
void Release(Texture *texture, TextureHandle handle); // Release and Return
StorageTextureHandle CommitStorageTexture(StorageTexture *storageTexture,
SamplerHandle sampler = {}); // Commit to GPU and take Ownership
void Release(StorageTextureHandle handle); // Release and Destroy
void Release(StorageTexture *texture, StorageTextureHandle handle); // Release and Return
SamplerHandle CreateSampler(const vk::SamplerCreateInfo *samplerCreateInfo);
GeometryHandle CreateGeometryBuffer(usize size, usize alignment, uptr *addr = nullptr);
uptr FetchAddress(GeometryHandle handle);
void Write(GeometryHandle handle, usize offset, usize size, const void *data);
void Release(GeometryHandle handle);
MaterialHandle CreateMaterialBuffer(usize size, usize alignment, uptr *addr = nullptr);
uptr FetchAddress(MaterialHandle handle);
void Write(MaterialHandle handle, usize offset, usize size, const void *data);
void Release(MaterialHandle handle);
IndexHandle CreateIndexBuffer(usize size, usize alignment, u32 *firstIndex = nullptr);
u32 FetchIndex(IndexHandle handle);
void Write(IndexHandle handle, usize offset, usize size, const void *data);
void Release(IndexHandle handle);
vk::Buffer GetIndexBuffer() const;
void Update(); // Update all the descriptors required.
// Ctor/Dtor
RenderResourceManager(Device *device, u16 maxSize, bool useBufferAddress = true);
~RenderResourceManager();
RenderResourceManager(RenderResourceManager &&other) noexcept;
RenderResourceManager &operator=(RenderResourceManager &&other) noexcept;
#if !defined(ASTER_NDEBUG)
usize m_CommitedBufferCount = 0;
usize m_CommitedTextureCount = 0;
usize m_CommitedStorageTextureCount = 0;
#endif
DISALLOW_COPY_AND_ASSIGN(RenderResourceManager);
};