1
0
Fork 0
Univerxel/src/client/render/vk/Allocator.hpp

112 lines
3.6 KiB
C++

#pragma once
#include "forward.hpp"
#include <vector>
#include <optional>
#include <memory>
namespace tracy {
class VkCtx;
}
typedef tracy::VkCtx* TracyVkCtx;
namespace render::vk {
class Allocator {
private:
struct Allocation;
public:
Allocator(VkDevice, const PhysicalDeviceInfo&);
~Allocator();
struct memory_area {
VkDeviceMemory ref;
VkDeviceSize size;
VkDeviceSize offset;
void *ptr = nullptr;
void write(const void*, VkDeviceSize size, VkDeviceSize offset = 0);
void read(void*, VkDeviceSize size, VkDeviceSize offset = 0);
};
class MemoryDeleter {
public:
MemoryDeleter(Allocation *owner): owner(owner) { }
void operator()(memory_area *);
private:
Allocation *owner;
};
using memory_ptr = std::unique_ptr<memory_area, MemoryDeleter>;
memory_ptr allocate(VkMemoryRequirements, VkMemoryPropertyFlags, bool optimalTiling = false);
bool deallocate(const memory_area&);
struct buffer_info {
VkBuffer buffer = nullptr;
VkDeviceSize offset = 0;
};
struct buffer_requirement {
VkDeviceSize size;
VkBufferUsageFlags usage;
const void *data = nullptr;
VkDeviceSize data_size = 0;
VkDeviceSize data_offset = 0;
};
memory_ptr createBuffer(const buffer_requirement&, VkMemoryPropertyFlags, buffer_info&);
memory_ptr createBuffers(const std::vector<buffer_requirement> &, VkMemoryPropertyFlags, std::vector<buffer_info> &);
struct image_info {
VkImage image = nullptr;
VkDeviceSize offset = 0;
};
memory_ptr createImage(const VkImageCreateInfo&, VkMemoryPropertyFlags, image_info&,
const void *data = nullptr, VkDeviceSize data_size = 0, VkDeviceSize data_offset = 0,
VkImageLayout finalLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
void copyBuffer(buffer_info srcBuffer, buffer_info dstBuffer, VkDeviceSize size);
void transitionImageLayout(VkImage image, VkFormat format, VkImageLayout oldLayout, VkImageLayout newLayout);
void copyBufferToImage(buffer_info buffer, image_info image, uint32_t width, uint32_t height);
void setTracyZone(const char* name);
static memory_ptr GetNull();
private:
std::optional<uint32_t> findMemory(uint32_t, VkMemoryPropertyFlags, VkDeviceSize size = 0);
constexpr bool hasBudget() const { return properties2.pNext != nullptr; }
constexpr const VkPhysicalDeviceMemoryProperties &getProperties() const { return hasBudget() ? properties2.memoryProperties : properties; }
void updateProperties();
struct Allocation {
Allocation(VkDevice, VkDeviceMemory, VkDeviceSize, uint32_t, bool optimalTiling, void *ptr);
~Allocation();
const VkDevice device;
const VkDeviceMemory memory;
const VkDeviceSize size;
const uint32_t memoryType;
const bool optimalTiling;
void *const ptr = nullptr;
const MemoryDeleter deleter;
struct area { VkDeviceSize size; VkDeviceSize offset; };
std::vector<area> areas;
};
VkPhysicalDevice const physicalDevice;
VkDevice const device;
VkPhysicalDeviceMemoryProperties properties{};
VkPhysicalDeviceMemoryProperties2 properties2{};
VkPhysicalDeviceMemoryBudgetPropertiesEXT budget{};
VkQueue transferQueue;
VkCommandPool transferPool;
VkCommandBuffer transferBuffer; // MAYBE: parallel upload
TracyVkCtx tracyCtx;
VkQueue graphicsQueue;
VkCommandPool graphicsPool;
VkCommandBuffer graphicsBuffer;
std::vector<std::unique_ptr<Allocation>> allocations;
};
}