134 lines
5.1 KiB
C++
134 lines
5.1 KiB
C++
#include "vk_allocator.h"
|
|
#include "vk_utils.h"
|
|
|
|
static Device_Memory_Allocator allocator;
|
|
|
|
Device_Memory_Allocator* get_allocator() {
|
|
return &allocator;
|
|
}
|
|
|
|
static uint32_t find_memory_type(VkPhysicalDevice physical_device, uint32_t memory_type_bits, VkMemoryPropertyFlags properties) {
|
|
VkPhysicalDeviceMemoryProperties memory_properties;
|
|
vkGetPhysicalDeviceMemoryProperties(physical_device, &memory_properties);
|
|
|
|
for (uint32_t i = 0; i < memory_properties.memoryTypeCount; i++) {
|
|
if ((memory_type_bits & (1 << i)) != 0 &&
|
|
(memory_properties.memoryTypes[i].propertyFlags & properties) == properties) {
|
|
return i;
|
|
}
|
|
}
|
|
error("failed to find matching memory type with requested properties");
|
|
return -1;
|
|
}
|
|
|
|
void Shared_Staging_Memory::initialize(VkPhysicalDevice physical_device, VkDevice device) {
|
|
this->physical_device = physical_device;
|
|
this->device = device;
|
|
}
|
|
|
|
void Shared_Staging_Memory::deallocate_all() {
|
|
if (handle != VK_NULL_HANDLE) {
|
|
vkFreeMemory(device, handle, nullptr);
|
|
}
|
|
handle = VK_NULL_HANDLE;
|
|
size = 0;
|
|
memory_type_index = -1;
|
|
}
|
|
|
|
void Shared_Staging_Memory::ensure_allocation_for_object(VkImage image) {
|
|
VkMemoryRequirements memory_requirements;
|
|
vkGetImageMemoryRequirements(device, image, &memory_requirements);
|
|
ensure_allocation(memory_requirements);
|
|
}
|
|
|
|
void Shared_Staging_Memory::ensure_allocation_for_object(VkBuffer buffer) {
|
|
VkMemoryRequirements memory_requirements;
|
|
vkGetBufferMemoryRequirements(device, buffer, &memory_requirements);
|
|
ensure_allocation(memory_requirements);
|
|
}
|
|
|
|
VkDeviceMemory Shared_Staging_Memory::get_handle() const {
|
|
return handle;
|
|
}
|
|
|
|
void Shared_Staging_Memory::ensure_allocation(const VkMemoryRequirements& memory_requirements) {
|
|
uint32_t required_memory_type_index = find_memory_type(physical_device, memory_requirements.memoryTypeBits,
|
|
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
|
|
|
|
if (size < memory_requirements.size || memory_type_index != required_memory_type_index) {
|
|
if (handle != VK_NULL_HANDLE) {
|
|
vkFreeMemory(device, handle, nullptr);
|
|
}
|
|
handle = VK_NULL_HANDLE;
|
|
size = 0;
|
|
memory_type_index = -1;
|
|
|
|
VkMemoryAllocateInfo alloc_info;
|
|
alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
|
|
alloc_info.pNext = nullptr;
|
|
alloc_info.allocationSize = memory_requirements.size;
|
|
alloc_info.memoryTypeIndex = required_memory_type_index;
|
|
|
|
VkResult result = vkAllocateMemory(device, &alloc_info, nullptr, &handle);
|
|
check_vk_result(result, "vkAllocateMemory");
|
|
size = memory_requirements.size;
|
|
memory_type_index = required_memory_type_index;
|
|
}
|
|
}
|
|
|
|
void Device_Memory_Allocator::initialize(VkPhysicalDevice physical_device, VkDevice device) {
|
|
this->physical_device = physical_device;
|
|
this->device = device;
|
|
shared_staging_memory.initialize(physical_device, device);
|
|
}
|
|
|
|
void Device_Memory_Allocator::deallocate_all() {
|
|
for (auto chunk : chunks) {
|
|
vkFreeMemory(device, chunk, nullptr);
|
|
}
|
|
chunks.clear();
|
|
shared_staging_memory.deallocate_all();
|
|
}
|
|
|
|
VkDeviceMemory Device_Memory_Allocator::allocate_memory(VkImage image) {
|
|
VkMemoryRequirements memory_requirements;
|
|
vkGetImageMemoryRequirements(device, image, &memory_requirements);
|
|
return allocate_memory(memory_requirements, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
|
}
|
|
|
|
VkDeviceMemory Device_Memory_Allocator::allocate_memory(VkBuffer buffer) {
|
|
VkMemoryRequirements memory_requirements;
|
|
vkGetBufferMemoryRequirements(device, buffer, &memory_requirements);
|
|
return allocate_memory(memory_requirements, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
|
}
|
|
|
|
VkDeviceMemory Device_Memory_Allocator::allocate_staging_memory(VkImage image) {
|
|
VkMemoryRequirements memory_requirements;
|
|
vkGetImageMemoryRequirements(device, image, &memory_requirements);
|
|
return allocate_memory(memory_requirements, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
|
|
}
|
|
|
|
VkDeviceMemory Device_Memory_Allocator::allocate_staging_memory(VkBuffer buffer) {
|
|
VkMemoryRequirements memory_requirements;
|
|
vkGetBufferMemoryRequirements(device, buffer, &memory_requirements);
|
|
return allocate_memory(memory_requirements, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
|
|
}
|
|
|
|
Shared_Staging_Memory& Device_Memory_Allocator::get_shared_staging_memory() {
|
|
return shared_staging_memory;
|
|
}
|
|
|
|
VkDeviceMemory Device_Memory_Allocator::allocate_memory(const VkMemoryRequirements& memory_requirements, VkMemoryPropertyFlags properties) {
|
|
VkMemoryAllocateInfo alloc_info;
|
|
alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
|
|
alloc_info.pNext = nullptr;
|
|
alloc_info.allocationSize = memory_requirements.size;
|
|
alloc_info.memoryTypeIndex = find_memory_type(physical_device, memory_requirements.memoryTypeBits, properties);
|
|
|
|
VkDeviceMemory chunk;
|
|
VkResult result = vkAllocateMemory(device, &alloc_info, nullptr, &chunk);
|
|
check_vk_result(result, "vkAllocateMemory");
|
|
chunks.push_back(chunk);
|
|
return chunk;
|
|
}
|