Files
QuaternionEngine/src/core/device/resource.h

124 lines
4.8 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#pragma once
#include <core/types.h>
#include <functional>
#include <vector>
#include <mutex>
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;
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;
mutable std::mutex _pendingMutex;
};