Image memory allocator.
Started process of removing demo project's allocator code.
This commit is contained in:
parent
f823930d83
commit
6dab078992
|
|
@ -40,6 +40,20 @@ static bool is_extension_available(const std::vector<VkExtensionProperties>& pro
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ri.Error(ERR_FATAL, "Vulkan error: failed to find matching memory type with requested properties");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
static VkFormat find_format_with_features(VkPhysicalDevice physical_device, const std::vector<VkFormat>& candidates, VkImageTiling tiling, VkFormatFeatureFlags features) {
|
static VkFormat find_format_with_features(VkPhysicalDevice physical_device, const std::vector<VkFormat>& candidates, VkImageTiling tiling, VkFormatFeatureFlags features) {
|
||||||
for (VkFormat format : candidates) {
|
for (VkFormat format : candidates) {
|
||||||
VkFormatProperties properties;
|
VkFormatProperties properties;
|
||||||
|
|
@ -431,6 +445,61 @@ static void record_image_layout_transition(VkCommandBuffer command_buffer, VkIma
|
||||||
0, nullptr, 0, nullptr, 1, &barrier);
|
0, nullptr, 0, nullptr, 1, &barrier);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void allocate_and_bind_image_memory(VkImage image) {
|
||||||
|
VkMemoryRequirements memory_requirements;
|
||||||
|
vkGetImageMemoryRequirements(vk.device, image, &memory_requirements);
|
||||||
|
|
||||||
|
if (memory_requirements.size > IMAGE_CHUNK_SIZE) {
|
||||||
|
ri.Error(ERR_FATAL, "Vulkan: could not allocate memory, image is too large.");
|
||||||
|
}
|
||||||
|
|
||||||
|
Vulkan_Resources::Chunk* chunk = nullptr;
|
||||||
|
|
||||||
|
// Try to find an existing chunk of sufficient capacity.
|
||||||
|
const auto mask = ~(memory_requirements.alignment - 1);
|
||||||
|
for (int i = 0; i < tr.vk_resources.num_image_chunks; i++) {
|
||||||
|
// ensure that memory region has proper alignment
|
||||||
|
VkDeviceSize offset = (tr.vk_resources.image_chunks[i].used + memory_requirements.alignment - 1) & mask;
|
||||||
|
|
||||||
|
if (offset + memory_requirements.size <= IMAGE_CHUNK_SIZE) {
|
||||||
|
chunk = &tr.vk_resources.image_chunks[i];
|
||||||
|
chunk->used = offset + memory_requirements.size;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allocate a new chunk in case we couldn't find suitable existing chunk.
|
||||||
|
if (chunk == nullptr) {
|
||||||
|
if (tr.vk_resources.num_image_chunks >= MAX_IMAGE_CHUNKS) {
|
||||||
|
ri.Error(ERR_FATAL, "Vulkan: image chunk limit has been reached");
|
||||||
|
}
|
||||||
|
|
||||||
|
VkMemoryAllocateInfo alloc_info;
|
||||||
|
alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
|
||||||
|
alloc_info.pNext = nullptr;
|
||||||
|
alloc_info.allocationSize = IMAGE_CHUNK_SIZE;
|
||||||
|
alloc_info.memoryTypeIndex = find_memory_type(vk.physical_device, memory_requirements.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
||||||
|
|
||||||
|
VkDeviceMemory memory;
|
||||||
|
VK_CHECK(vkAllocateMemory(vk.device, &alloc_info, nullptr, &memory));
|
||||||
|
|
||||||
|
chunk = &tr.vk_resources.image_chunks[tr.vk_resources.num_image_chunks];
|
||||||
|
tr.vk_resources.num_image_chunks++;
|
||||||
|
chunk->memory = memory;
|
||||||
|
chunk->used = memory_requirements.size;
|
||||||
|
}
|
||||||
|
|
||||||
|
VK_CHECK(vkBindImageMemory(vk.device, image, chunk->memory, chunk->used - memory_requirements.size));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void deallocate_image_chunks() {
|
||||||
|
for (int i = 0; i < tr.vk_resources.num_image_chunks; i++) {
|
||||||
|
vkFreeMemory(vk.device, tr.vk_resources.image_chunks[i].memory, nullptr);
|
||||||
|
}
|
||||||
|
tr.vk_resources.num_image_chunks = 0;
|
||||||
|
Com_Memset(tr.vk_resources.image_chunks, 0, sizeof(tr.vk_resources.image_chunks));
|
||||||
|
}
|
||||||
|
|
||||||
VkPipeline create_pipeline(const Vk_Pipeline_Desc&);
|
VkPipeline create_pipeline(const Vk_Pipeline_Desc&);
|
||||||
|
|
||||||
bool vk_initialize(HWND hwnd) {
|
bool vk_initialize(HWND hwnd) {
|
||||||
|
|
@ -497,8 +566,6 @@ bool vk_initialize(HWND hwnd) {
|
||||||
VK_CHECK(vkAllocateCommandBuffers(vk.device, &alloc_info, &g.command_buffer));
|
VK_CHECK(vkAllocateCommandBuffers(vk.device, &alloc_info, &g.command_buffer));
|
||||||
}
|
}
|
||||||
|
|
||||||
get_allocator()->initialize(vk.physical_device, vk.device);
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Depth attachment image.
|
// Depth attachment image.
|
||||||
//
|
//
|
||||||
|
|
@ -526,9 +593,17 @@ bool vk_initialize(HWND hwnd) {
|
||||||
|
|
||||||
VK_CHECK(vkCreateImage(vk.device, &desc, nullptr, &vk.depth_image));
|
VK_CHECK(vkCreateImage(vk.device, &desc, nullptr, &vk.depth_image));
|
||||||
|
|
||||||
VkDeviceMemory memory = get_allocator()->allocate_memory(vk.depth_image);
|
VkMemoryRequirements memory_requirements;
|
||||||
VK_CHECK(vkBindImageMemory(vk.device, vk.depth_image, memory, 0));
|
vkGetImageMemoryRequirements(vk.device, vk.depth_image, &memory_requirements);
|
||||||
|
|
||||||
|
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(vk.physical_device, memory_requirements.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
||||||
|
|
||||||
|
VK_CHECK(vkAllocateMemory(vk.device, &alloc_info, nullptr, &vk.depth_image_memory));
|
||||||
|
VK_CHECK(vkBindImageMemory(vk.device, vk.depth_image, vk.depth_image_memory, 0));
|
||||||
vk.depth_image_view = create_image_view(vk.depth_image, depth_format, VK_IMAGE_ASPECT_DEPTH_BIT);
|
vk.depth_image_view = create_image_view(vk.depth_image, depth_format, VK_IMAGE_ASPECT_DEPTH_BIT);
|
||||||
|
|
||||||
record_and_run_commands(vk.command_pool, vk.queue, [&depth_format](VkCommandBuffer command_buffer) {
|
record_and_run_commands(vk.command_pool, vk.queue, [&depth_format](VkCommandBuffer command_buffer) {
|
||||||
|
|
@ -765,8 +840,10 @@ void vk_deinitialize() {
|
||||||
vk_log_file = nullptr;
|
vk_log_file = nullptr;
|
||||||
|
|
||||||
get_allocator()->deallocate_all();
|
get_allocator()->deallocate_all();
|
||||||
|
deallocate_image_chunks();
|
||||||
|
|
||||||
vkDestroyImage(vk.device, vk.depth_image, nullptr);
|
vkDestroyImage(vk.device, vk.depth_image, nullptr);
|
||||||
|
vkFreeMemory(vk.device, vk.depth_image_memory, nullptr);
|
||||||
vkDestroyImageView(vk.device, vk.depth_image_view, nullptr);
|
vkDestroyImageView(vk.device, vk.depth_image_view, nullptr);
|
||||||
|
|
||||||
for (uint32_t i = 0; i < vk.swapchain_image_count; i++) {
|
for (uint32_t i = 0; i < vk.swapchain_image_count; i++) {
|
||||||
|
|
@ -842,8 +919,8 @@ VkImage vk_create_texture(const uint8_t* rgba_pixels, int image_width, int image
|
||||||
VkBuffer staging_buffer;
|
VkBuffer staging_buffer;
|
||||||
VK_CHECK(vkCreateBuffer(vk.device, &buffer_desc, nullptr, &staging_buffer));
|
VK_CHECK(vkCreateBuffer(vk.device, &buffer_desc, nullptr, &staging_buffer));
|
||||||
|
|
||||||
get_allocator()->get_shared_staging_memory().ensure_allocation_for_object(staging_buffer);
|
get_allocator()->ensure_allocation_for_staging_buffer(staging_buffer);
|
||||||
VkDeviceMemory buffer_memory = get_allocator()->get_shared_staging_memory().get_handle();
|
VkDeviceMemory buffer_memory = get_allocator()->get_staging_buffer_memory();
|
||||||
VK_CHECK(vkBindBufferMemory(vk.device, staging_buffer, buffer_memory, 0));
|
VK_CHECK(vkBindBufferMemory(vk.device, staging_buffer, buffer_memory, 0));
|
||||||
|
|
||||||
void* buffer_data;
|
void* buffer_data;
|
||||||
|
|
@ -873,9 +950,7 @@ VkImage vk_create_texture(const uint8_t* rgba_pixels, int image_width, int image
|
||||||
|
|
||||||
VkImage texture_image;
|
VkImage texture_image;
|
||||||
VK_CHECK(vkCreateImage(vk.device, &desc, nullptr, &texture_image));
|
VK_CHECK(vkCreateImage(vk.device, &desc, nullptr, &texture_image));
|
||||||
|
allocate_and_bind_image_memory(texture_image);
|
||||||
VkDeviceMemory memory = get_allocator()->allocate_memory(texture_image);
|
|
||||||
VK_CHECK(vkBindImageMemory(vk.device, texture_image, memory, 0));
|
|
||||||
|
|
||||||
// copy buffer's content to texture
|
// copy buffer's content to texture
|
||||||
record_and_run_commands(vk.command_pool, vk.queue,
|
record_and_run_commands(vk.command_pool, vk.queue,
|
||||||
|
|
@ -950,8 +1025,7 @@ VkImage vk_create_cinematic_image(int width, int height, Vk_Staging_Buffer& stag
|
||||||
VkImage image;
|
VkImage image;
|
||||||
VK_CHECK(vkCreateImage(vk.device, &image_desc, nullptr, &image));
|
VK_CHECK(vkCreateImage(vk.device, &image_desc, nullptr, &image));
|
||||||
|
|
||||||
VkDeviceMemory image_memory = get_allocator()->allocate_memory(image);
|
allocate_and_bind_image_memory(image);
|
||||||
VK_CHECK(vkBindImageMemory(vk.device, image, image_memory, 0));
|
|
||||||
|
|
||||||
staging_buffer.handle = buffer;
|
staging_buffer.handle = buffer;
|
||||||
staging_buffer.memory = buffer_memory;
|
staging_buffer.memory = buffer_memory;
|
||||||
|
|
@ -1374,6 +1448,8 @@ VkDescriptorSet vk_create_descriptor_set(VkImageView image_view) {
|
||||||
void vk_destroy_resources() {
|
void vk_destroy_resources() {
|
||||||
vkDeviceWaitIdle(vk.device);
|
vkDeviceWaitIdle(vk.device);
|
||||||
|
|
||||||
|
deallocate_image_chunks();
|
||||||
|
|
||||||
// Destroy pipelines
|
// Destroy pipelines
|
||||||
for (int i = 0; i < tr.vk_resources.num_pipelines; i++) {
|
for (int i = 0; i < tr.vk_resources.num_pipelines; i++) {
|
||||||
vkDestroyPipeline(vk.device, tr.vk_resources.pipelines[i], nullptr);
|
vkDestroyPipeline(vk.device, tr.vk_resources.pipelines[i], nullptr);
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,9 @@ const int MAX_SWAPCHAIN_IMAGES = 8;
|
||||||
const int MAX_VK_PIPELINES = 1024;
|
const int MAX_VK_PIPELINES = 1024;
|
||||||
const int MAX_VK_IMAGES = 2048; // should be the same as MAX_DRAWIMAGES
|
const int MAX_VK_IMAGES = 2048; // should be the same as MAX_DRAWIMAGES
|
||||||
|
|
||||||
|
const int IMAGE_CHUNK_SIZE = 32 * 1024 * 1024;
|
||||||
|
const int MAX_IMAGE_CHUNKS = 16;
|
||||||
|
|
||||||
#define VK_CHECK(function_call) { \
|
#define VK_CHECK(function_call) { \
|
||||||
VkResult result = function_call; \
|
VkResult result = function_call; \
|
||||||
if (result < 0) \
|
if (result < 0) \
|
||||||
|
|
@ -113,6 +116,7 @@ struct Vulkan_Instance {
|
||||||
VkCommandBuffer command_buffer = VK_NULL_HANDLE;
|
VkCommandBuffer command_buffer = VK_NULL_HANDLE;
|
||||||
|
|
||||||
VkImage depth_image = VK_NULL_HANDLE;
|
VkImage depth_image = VK_NULL_HANDLE;
|
||||||
|
VkDeviceMemory depth_image_memory = VK_NULL_HANDLE;
|
||||||
VkImageView depth_image_view = VK_NULL_HANDLE;
|
VkImageView depth_image_view = VK_NULL_HANDLE;
|
||||||
|
|
||||||
VkRenderPass render_pass = VK_NULL_HANDLE;
|
VkRenderPass render_pass = VK_NULL_HANDLE;
|
||||||
|
|
@ -155,4 +159,12 @@ struct Vulkan_Resources {
|
||||||
VkPipeline pipelines[MAX_VK_PIPELINES];
|
VkPipeline pipelines[MAX_VK_PIPELINES];
|
||||||
|
|
||||||
Vk_Image images[MAX_VK_IMAGES];
|
Vk_Image images[MAX_VK_IMAGES];
|
||||||
|
|
||||||
|
struct Chunk {
|
||||||
|
VkDeviceMemory memory = VK_NULL_HANDLE;
|
||||||
|
VkDeviceSize used = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
int num_image_chunks = 0;
|
||||||
|
Chunk image_chunks[MAX_IMAGE_CHUNKS];
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -21,105 +21,59 @@ static uint32_t find_memory_type(VkPhysicalDevice physical_device, uint32_t memo
|
||||||
return -1;
|
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;
|
|
||||||
|
|
||||||
VK_CHECK(vkAllocateMemory(device, &alloc_info, nullptr, &handle));
|
|
||||||
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() {
|
void Device_Memory_Allocator::deallocate_all() {
|
||||||
for (auto chunk : chunks) {
|
for (auto chunk : chunks) {
|
||||||
vkFreeMemory(device, chunk, nullptr);
|
vkFreeMemory(vk.device, chunk, nullptr);
|
||||||
}
|
}
|
||||||
chunks.clear();
|
chunks.clear();
|
||||||
shared_staging_memory.deallocate_all();
|
|
||||||
}
|
|
||||||
|
|
||||||
VkDeviceMemory Device_Memory_Allocator::allocate_memory(VkImage image) {
|
if (staging_buffer_memory != VK_NULL_HANDLE) {
|
||||||
VkMemoryRequirements memory_requirements;
|
vkFreeMemory(vk.device, staging_buffer_memory, nullptr);
|
||||||
vkGetImageMemoryRequirements(device, image, &memory_requirements);
|
staging_buffer_memory = VK_NULL_HANDLE;
|
||||||
return allocate_memory(memory_requirements, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
staging_buffer_size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
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(VkBuffer buffer) {
|
VkDeviceMemory Device_Memory_Allocator::allocate_staging_memory(VkBuffer buffer) {
|
||||||
VkMemoryRequirements memory_requirements;
|
VkMemoryRequirements memory_requirements;
|
||||||
vkGetBufferMemoryRequirements(device, buffer, &memory_requirements);
|
vkGetBufferMemoryRequirements(vk.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;
|
VkMemoryAllocateInfo alloc_info;
|
||||||
alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
|
alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
|
||||||
alloc_info.pNext = nullptr;
|
alloc_info.pNext = nullptr;
|
||||||
alloc_info.allocationSize = memory_requirements.size;
|
alloc_info.allocationSize = memory_requirements.size;
|
||||||
alloc_info.memoryTypeIndex = find_memory_type(physical_device, memory_requirements.memoryTypeBits, properties);
|
alloc_info.memoryTypeIndex = find_memory_type(vk.physical_device, memory_requirements.memoryTypeBits,
|
||||||
|
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
|
||||||
|
|
||||||
VkDeviceMemory chunk;
|
VkDeviceMemory chunk;
|
||||||
VK_CHECK(vkAllocateMemory(device, &alloc_info, nullptr, &chunk));
|
VK_CHECK(vkAllocateMemory(vk.device, &alloc_info, nullptr, &chunk));
|
||||||
chunks.push_back(chunk);
|
chunks.push_back(chunk);
|
||||||
return chunk;
|
return chunk;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Device_Memory_Allocator::ensure_allocation_for_staging_buffer(VkBuffer buffer) {
|
||||||
|
VkMemoryRequirements memory_requirements;
|
||||||
|
vkGetBufferMemoryRequirements(vk.device, buffer, &memory_requirements);
|
||||||
|
|
||||||
|
if (staging_buffer_size < memory_requirements.size) {
|
||||||
|
if (staging_buffer_memory != VK_NULL_HANDLE) {
|
||||||
|
vkFreeMemory(vk.device, staging_buffer_memory, nullptr);
|
||||||
|
}
|
||||||
|
staging_buffer_memory = VK_NULL_HANDLE;
|
||||||
|
staging_buffer_size = 0;
|
||||||
|
|
||||||
|
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(vk.physical_device, memory_requirements.memoryTypeBits,
|
||||||
|
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
|
||||||
|
|
||||||
|
VK_CHECK(vkAllocateMemory(vk.device, &alloc_info, nullptr, &staging_buffer_memory));
|
||||||
|
staging_buffer_size = memory_requirements.size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VkDeviceMemory Device_Memory_Allocator::get_staging_buffer_memory() const {
|
||||||
|
return staging_buffer_memory;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,49 +3,22 @@
|
||||||
#include "vk.h"
|
#include "vk.h"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
class Shared_Staging_Memory {
|
|
||||||
public:
|
|
||||||
void initialize(VkPhysicalDevice physical_device, VkDevice device);
|
|
||||||
void deallocate_all();
|
|
||||||
|
|
||||||
void ensure_allocation_for_object(VkImage image);
|
|
||||||
void ensure_allocation_for_object(VkBuffer buffer);
|
|
||||||
VkDeviceMemory get_handle() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void ensure_allocation(const VkMemoryRequirements& memory_requirements);
|
|
||||||
|
|
||||||
private:
|
|
||||||
VkPhysicalDevice physical_device = VK_NULL_HANDLE;
|
|
||||||
VkDevice device = VK_NULL_HANDLE;
|
|
||||||
|
|
||||||
VkDeviceMemory handle = VK_NULL_HANDLE;
|
|
||||||
VkDeviceSize size = 0;
|
|
||||||
uint32_t memory_type_index = -1;
|
|
||||||
};
|
|
||||||
|
|
||||||
// NOTE: in this implementation I do memory allocation for each allocation request.
|
// NOTE: in this implementation I do memory allocation for each allocation request.
|
||||||
// TODO: sub-allocate from larger chunks and return chunk handle plus offset withing corresponding chunk.
|
// TODO: sub-allocate from larger chunks and return chunk handle plus offset withing corresponding chunk.
|
||||||
class Device_Memory_Allocator {
|
class Device_Memory_Allocator {
|
||||||
public:
|
public:
|
||||||
void initialize(VkPhysicalDevice physical_device, VkDevice device);
|
|
||||||
void deallocate_all();
|
void deallocate_all();
|
||||||
|
|
||||||
VkDeviceMemory allocate_memory(VkImage image);
|
|
||||||
VkDeviceMemory allocate_memory(VkBuffer buffer);
|
|
||||||
VkDeviceMemory allocate_staging_memory(VkBuffer buffer);
|
VkDeviceMemory allocate_staging_memory(VkBuffer buffer);
|
||||||
|
|
||||||
Shared_Staging_Memory& get_shared_staging_memory();
|
void ensure_allocation_for_staging_buffer(VkBuffer buffer);
|
||||||
|
VkDeviceMemory get_staging_buffer_memory() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
VkDeviceMemory allocate_memory(const VkMemoryRequirements& memory_requirements, VkMemoryPropertyFlags properties);
|
|
||||||
|
|
||||||
private:
|
|
||||||
VkPhysicalDevice physical_device = VK_NULL_HANDLE;
|
|
||||||
VkDevice device = VK_NULL_HANDLE;
|
|
||||||
|
|
||||||
std::vector<VkDeviceMemory> chunks;
|
std::vector<VkDeviceMemory> chunks;
|
||||||
Shared_Staging_Memory shared_staging_memory;
|
|
||||||
|
VkDeviceMemory staging_buffer_memory;
|
||||||
|
VkDeviceSize staging_buffer_size = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
Device_Memory_Allocator* get_allocator();
|
Device_Memory_Allocator* get_allocator();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user