123 lines
5.0 KiB
C++
123 lines
5.0 KiB
C++
#pragma once
|
||
#include <core/vk_types.h>
|
||
#include <functional>
|
||
#include <vector>
|
||
|
||
class DeviceManager;
|
||
class RenderGraph;
|
||
struct FrameResources;
|
||
|
||
// VMA-backed allocator + upload helper.
|
||
// Creates buffers/images, offers an immediate-submit path, and supports
|
||
// deferring uploads into a single Render Graph transfer pass per frame.
|
||
class ResourceManager
|
||
{
|
||
public:
|
||
struct MipLevelCopy
|
||
{
|
||
uint64_t offset{0};
|
||
uint64_t length{0};
|
||
uint32_t width{0};
|
||
uint32_t height{0};
|
||
};
|
||
struct BufferCopyRegion
|
||
{
|
||
VkBuffer destination = VK_NULL_HANDLE;
|
||
VkDeviceSize dstOffset = 0;
|
||
VkDeviceSize size = 0;
|
||
VkDeviceSize stagingOffset = 0;
|
||
};
|
||
|
||
struct PendingBufferUpload
|
||
{
|
||
AllocatedBuffer staging;
|
||
std::vector<BufferCopyRegion> copies;
|
||
};
|
||
|
||
struct PendingImageUpload
|
||
{
|
||
AllocatedBuffer staging;
|
||
VkImage image = VK_NULL_HANDLE;
|
||
VkExtent3D extent{0, 0, 0};
|
||
VkFormat format = VK_FORMAT_UNDEFINED;
|
||
VkImageLayout initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||
VkImageLayout finalLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||
bool generateMips = false;
|
||
uint32_t mipLevels = 1;
|
||
// For multi-region (per-mip) uploads
|
||
std::vector<VkBufferImageCopy> copies;
|
||
};
|
||
|
||
void init(DeviceManager *deviceManager);
|
||
|
||
void cleanup();
|
||
|
||
AllocatedBuffer create_buffer(size_t allocSize, VkBufferUsageFlags usage, VmaMemoryUsage memoryUsage) const;
|
||
|
||
void destroy_buffer(const AllocatedBuffer &buffer) const;
|
||
|
||
AllocatedImage create_image(VkExtent3D size, VkFormat format, VkImageUsageFlags usage,
|
||
bool mipmapped = false) const;
|
||
// Variant with explicit mip level count (>=1). If 0, computes full chain when mipmapped.
|
||
AllocatedImage create_image(VkExtent3D size, VkFormat format, VkImageUsageFlags usage,
|
||
bool mipmapped, uint32_t mipLevelsOverride) const;
|
||
|
||
AllocatedImage create_image(const void *data, VkExtent3D size, VkFormat format, VkImageUsageFlags usage,
|
||
bool mipmapped = false);
|
||
// Variant with explicit mip level count used for generate_mipmaps.
|
||
AllocatedImage create_image(const void *data, VkExtent3D size, VkFormat format, VkImageUsageFlags usage,
|
||
bool mipmapped, uint32_t mipLevelsOverride);
|
||
|
||
// Create an image from a compressed payload (e.g., KTX2 pre-transcoded BCn).
|
||
// 'bytes' backs a single staging buffer; 'levels' provides per-mip copy regions.
|
||
// No GPU mip generation is performed; the number of mips equals levels.size().
|
||
AllocatedImage create_image_compressed(const void* bytes, size_t size,
|
||
VkFormat fmt,
|
||
std::span<const MipLevelCopy> levels,
|
||
VkImageUsageFlags usage = VK_IMAGE_USAGE_SAMPLED_BIT);
|
||
|
||
// Create a layered image (2D array or cubemap) from a compressed payload.
|
||
// - 'bytes' is the full KTX2 data payload staged into one buffer
|
||
// - 'regions' lists VkBufferImageCopy entries (one per mip × layer)
|
||
// - 'mipLevels' and 'layerCount' define the image subresource counts
|
||
// - for cubemaps, pass flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT and layerCount=6
|
||
AllocatedImage create_image_compressed_layers(const void* bytes, size_t size,
|
||
VkFormat fmt,
|
||
uint32_t mipLevels,
|
||
uint32_t layerCount,
|
||
std::span<const VkBufferImageCopy> regions,
|
||
VkImageUsageFlags usage = VK_IMAGE_USAGE_SAMPLED_BIT,
|
||
VkImageCreateFlags flags = 0);
|
||
|
||
void destroy_image(const AllocatedImage &img) const;
|
||
|
||
GPUMeshBuffers uploadMesh(std::span<uint32_t> indices, std::span<Vertex> vertices);
|
||
|
||
void immediate_submit(std::function<void(VkCommandBuffer)> &&function) const;
|
||
|
||
bool has_pending_uploads() const;
|
||
const std::vector<PendingBufferUpload> &pending_buffer_uploads() const { return _pendingBufferUploads; }
|
||
const std::vector<PendingImageUpload> &pending_image_uploads() const { return _pendingImageUploads; }
|
||
void clear_pending_uploads();
|
||
void process_queued_uploads_immediate();
|
||
|
||
void register_upload_pass(RenderGraph &graph, FrameResources &frame);
|
||
|
||
void set_deferred_uploads(bool enabled) { _deferUploads = enabled; }
|
||
bool deferred_uploads() const { return _deferUploads; }
|
||
|
||
private:
|
||
DeviceManager *_deviceManager = nullptr;
|
||
|
||
// immediate submit structures
|
||
VkFence _immFence = nullptr;
|
||
VkCommandBuffer _immCommandBuffer = nullptr;
|
||
VkCommandPool _immCommandPool = nullptr;
|
||
|
||
std::vector<PendingBufferUpload> _pendingBufferUploads;
|
||
std::vector<PendingImageUpload> _pendingImageUploads;
|
||
bool _deferUploads = false;
|
||
|
||
DeletionQueue _deletionQueue;
|
||
};
|