Use vma in GEVulkanDynamicBuffer
This commit is contained in:
parent
b0f91ff33d
commit
cf8bafaab3
@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
namespace GE
|
namespace GE
|
||||||
{
|
{
|
||||||
VkMemoryPropertyFlags GEVulkanDynamicBuffer::m_host_flag = (VkMemoryPropertyFlags)-1;
|
int GEVulkanDynamicBuffer::m_supports_host_transfer = -1;
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
GEVulkanDynamicBuffer::GEVulkanDynamicBuffer(GEVulkanDynamicBufferType t,
|
GEVulkanDynamicBuffer::GEVulkanDynamicBuffer(GEVulkanDynamicBufferType t,
|
||||||
VkBufferUsageFlags usage,
|
VkBufferUsageFlags usage,
|
||||||
@ -20,12 +20,12 @@ GEVulkanDynamicBuffer::GEVulkanDynamicBuffer(GEVulkanDynamicBufferType t,
|
|||||||
m_size = m_real_size = initial_size;
|
m_size = m_real_size = initial_size;
|
||||||
|
|
||||||
m_buffer = new VkBuffer[GEVulkanDriver::getMaxFrameInFlight()];
|
m_buffer = new VkBuffer[GEVulkanDriver::getMaxFrameInFlight()];
|
||||||
m_memory = new VkDeviceMemory[GEVulkanDriver::getMaxFrameInFlight()];
|
m_memory = new VmaAllocation[GEVulkanDriver::getMaxFrameInFlight()];
|
||||||
m_mapped_addr = new void*[GEVulkanDriver::getMaxFrameInFlight()];
|
m_mapped_addr = new void*[GEVulkanDriver::getMaxFrameInFlight()];
|
||||||
if (t == GVDBT_GPU_RAM)
|
if (t == GVDBT_GPU_RAM)
|
||||||
{
|
{
|
||||||
m_staging_buffer = new VkBuffer[GEVulkanDriver::getMaxFrameInFlight()];
|
m_staging_buffer = new VkBuffer[GEVulkanDriver::getMaxFrameInFlight()];
|
||||||
m_staging_memory = new VkDeviceMemory[GEVulkanDriver::getMaxFrameInFlight()];
|
m_staging_memory = new VmaAllocation[GEVulkanDriver::getMaxFrameInFlight()];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -51,6 +51,7 @@ GEVulkanDynamicBuffer::~GEVulkanDynamicBuffer()
|
|||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
void GEVulkanDynamicBuffer::initPerFrame(unsigned frame)
|
void GEVulkanDynamicBuffer::initPerFrame(unsigned frame)
|
||||||
{
|
{
|
||||||
|
GEVulkanDriver* vk = getVKDriver();
|
||||||
m_buffer[frame] = VK_NULL_HANDLE;
|
m_buffer[frame] = VK_NULL_HANDLE;
|
||||||
m_memory[frame] = VK_NULL_HANDLE;
|
m_memory[frame] = VK_NULL_HANDLE;
|
||||||
m_mapped_addr[frame] = NULL;
|
m_mapped_addr[frame] = NULL;
|
||||||
@ -60,128 +61,85 @@ void GEVulkanDynamicBuffer::initPerFrame(unsigned frame)
|
|||||||
m_staging_memory[frame] = VK_NULL_HANDLE;
|
m_staging_memory[frame] = VK_NULL_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
start:
|
||||||
|
VkMemoryPropertyFlags prop = {};
|
||||||
VkBuffer host_buffer = VK_NULL_HANDLE;
|
VkBuffer host_buffer = VK_NULL_HANDLE;
|
||||||
VkDeviceMemory host_memory = VK_NULL_HANDLE;
|
VmaAllocation host_memory = VK_NULL_HANDLE;
|
||||||
VkMemoryPropertyFlags host_flag = 0;
|
VmaAllocationCreateInfo host_info = {};
|
||||||
if (m_host_flag == (VkFlags)-1)
|
host_info.usage = VMA_MEMORY_USAGE_AUTO;
|
||||||
|
host_info.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT |
|
||||||
|
VMA_ALLOCATION_CREATE_MAPPED_BIT;
|
||||||
|
host_info.preferredFlags = VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
|
||||||
|
if ((m_type == GVDBT_SYSTEM_RAM && m_supports_host_transfer == 1) ||
|
||||||
|
(m_type == GVDBT_SYSTEM_RAM && m_supports_host_transfer == -1))
|
||||||
{
|
{
|
||||||
// https://zeux.io/2020/02/27/writing-an-efficient-vulkan-renderer/
|
host_info.flags |=
|
||||||
m_host_flag = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
|
VMA_ALLOCATION_CREATE_HOST_ACCESS_ALLOW_TRANSFER_INSTEAD_BIT;
|
||||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
|
|
||||||
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
|
|
||||||
bool better_flag_exist = false;
|
|
||||||
if (getVKDriver()->createBuffer(m_size,
|
|
||||||
m_usage | VK_BUFFER_USAGE_TRANSFER_SRC_BIT, m_host_flag,
|
|
||||||
host_buffer, host_memory))
|
|
||||||
{
|
|
||||||
better_flag_exist = true;
|
|
||||||
if (m_type == GVDBT_SYSTEM_RAM)
|
|
||||||
goto succeed;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (host_buffer != VK_NULL_HANDLE)
|
|
||||||
vkDestroyBuffer(getVKDriver()->getDevice(), host_buffer, NULL);
|
|
||||||
host_buffer = VK_NULL_HANDLE;
|
|
||||||
if (host_memory != VK_NULL_HANDLE)
|
|
||||||
vkFreeMemory(getVKDriver()->getDevice(), host_memory, NULL);
|
|
||||||
host_memory = VK_NULL_HANDLE;
|
|
||||||
|
|
||||||
if (!better_flag_exist)
|
|
||||||
{
|
|
||||||
m_host_flag = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
|
|
||||||
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
host_flag = m_host_flag;
|
if (!vk->createBuffer(m_size, m_usage | VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
|
||||||
// From the above website:
|
host_info, host_buffer, host_memory))
|
||||||
// This flag should be used to store staging buffers that are used to
|
|
||||||
// populate static resources allocated with
|
|
||||||
// VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT with data.
|
|
||||||
if (m_type == GVDBT_GPU_RAM)
|
|
||||||
{
|
{
|
||||||
host_flag = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
|
vmaDestroyBuffer(vk->getVmaAllocator(), host_buffer, host_memory);
|
||||||
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!getVKDriver()->createBuffer(m_size,
|
|
||||||
m_usage | VK_BUFFER_USAGE_TRANSFER_SRC_BIT, host_flag,
|
|
||||||
host_buffer, host_memory))
|
|
||||||
{
|
|
||||||
if (host_buffer != VK_NULL_HANDLE)
|
|
||||||
vkDestroyBuffer(getVKDriver()->getDevice(), host_buffer, NULL);
|
|
||||||
if (host_memory != VK_NULL_HANDLE)
|
|
||||||
vkFreeMemory(getVKDriver()->getDevice(), host_memory, NULL);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
succeed:
|
if (m_type == GVDBT_SYSTEM_RAM && m_supports_host_transfer == -1)
|
||||||
|
{
|
||||||
|
vmaGetAllocationMemoryProperties(vk->getVmaAllocator(), host_memory,
|
||||||
|
&prop);
|
||||||
|
if ((prop & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) == 0)
|
||||||
|
{
|
||||||
|
m_supports_host_transfer = 0;
|
||||||
|
vmaDestroyBuffer(vk->getVmaAllocator(), host_buffer, host_memory);
|
||||||
|
goto start;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
m_supports_host_transfer = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
VmaAllocationInfo info = {};
|
||||||
|
vmaGetAllocationInfo(vk->getVmaAllocator(), host_memory, &info);
|
||||||
if (m_type == GVDBT_SYSTEM_RAM)
|
if (m_type == GVDBT_SYSTEM_RAM)
|
||||||
{
|
{
|
||||||
m_buffer[frame] = host_buffer;
|
m_buffer[frame] = host_buffer;
|
||||||
m_memory[frame] = host_memory;
|
m_memory[frame] = host_memory;
|
||||||
|
m_mapped_addr[frame] = info.pMappedData;
|
||||||
if (vkMapMemory(getVKDriver()->getDevice(), m_memory[frame], 0, m_size,
|
|
||||||
0, &m_mapped_addr[frame]) != VK_SUCCESS)
|
|
||||||
{
|
|
||||||
destroyPerFrame(frame);
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
VkBuffer local_buffer = VK_NULL_HANDLE;
|
VkBuffer local_buffer = VK_NULL_HANDLE;
|
||||||
VkDeviceMemory local_memory = VK_NULL_HANDLE;
|
VmaAllocation local_memory = VK_NULL_HANDLE;
|
||||||
if (!getVKDriver()->createBuffer(m_size,
|
VmaAllocationCreateInfo local_info = {};
|
||||||
m_usage | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
|
local_info.usage = VMA_MEMORY_USAGE_AUTO;
|
||||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, local_buffer, local_memory))
|
|
||||||
|
if (!vk->createBuffer(m_size, m_usage | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
|
||||||
|
local_info, local_buffer, local_memory))
|
||||||
{
|
{
|
||||||
if (host_buffer != VK_NULL_HANDLE)
|
vmaDestroyBuffer(vk->getVmaAllocator(), host_buffer, host_memory);
|
||||||
vkDestroyBuffer(getVKDriver()->getDevice(), host_buffer, NULL);
|
vmaDestroyBuffer(vk->getVmaAllocator(), local_buffer, local_memory);
|
||||||
if (host_memory != VK_NULL_HANDLE)
|
|
||||||
vkFreeMemory(getVKDriver()->getDevice(), host_memory, NULL);
|
|
||||||
if (local_buffer != VK_NULL_HANDLE)
|
|
||||||
vkDestroyBuffer(getVKDriver()->getDevice(), local_buffer, NULL);
|
|
||||||
if (local_memory != VK_NULL_HANDLE)
|
|
||||||
vkFreeMemory(getVKDriver()->getDevice(), local_memory, NULL);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_buffer[frame] = local_buffer;
|
m_buffer[frame] = local_buffer;
|
||||||
m_memory[frame] = local_memory;
|
m_memory[frame] = local_memory;
|
||||||
m_staging_buffer[frame] = host_buffer;
|
m_staging_buffer[frame] = host_buffer;
|
||||||
m_staging_memory[frame] = host_memory;
|
m_staging_memory[frame] = host_memory;
|
||||||
|
m_mapped_addr[frame] = info.pMappedData;
|
||||||
if (vkMapMemory(getVKDriver()->getDevice(), m_staging_memory[frame], 0,
|
|
||||||
m_size, 0, &m_mapped_addr[frame]) != VK_SUCCESS)
|
|
||||||
{
|
|
||||||
destroyPerFrame(frame);
|
|
||||||
}
|
|
||||||
} // initPerFrame
|
} // initPerFrame
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
void GEVulkanDynamicBuffer::destroyPerFrame(unsigned frame)
|
void GEVulkanDynamicBuffer::destroyPerFrame(unsigned frame)
|
||||||
{
|
{
|
||||||
if ((m_staging_memory && m_staging_memory[frame] != VK_NULL_HANDLE) ||
|
GEVulkanDriver* vk = getVKDriver();
|
||||||
m_memory[frame] != VK_NULL_HANDLE)
|
vmaDestroyBuffer(vk->getVmaAllocator(), m_buffer[frame], m_memory[frame]);
|
||||||
{
|
|
||||||
vkUnmapMemory(getVKDriver()->getDevice(), m_type == GVDBT_GPU_RAM ?
|
|
||||||
m_staging_memory[frame] : m_memory[frame]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_memory[frame] != VK_NULL_HANDLE)
|
|
||||||
vkFreeMemory(getVKDriver()->getDevice(), m_memory[frame], NULL);
|
|
||||||
if (m_buffer[frame] != VK_NULL_HANDLE)
|
|
||||||
vkDestroyBuffer(getVKDriver()->getDevice(), m_buffer[frame], NULL);
|
|
||||||
|
|
||||||
m_buffer[frame] = VK_NULL_HANDLE;
|
m_buffer[frame] = VK_NULL_HANDLE;
|
||||||
m_memory[frame] = VK_NULL_HANDLE;
|
m_memory[frame] = VK_NULL_HANDLE;
|
||||||
m_mapped_addr[frame] = NULL;
|
m_mapped_addr[frame] = NULL;
|
||||||
|
|
||||||
if (m_type == GVDBT_GPU_RAM)
|
if (m_type == GVDBT_GPU_RAM)
|
||||||
{
|
{
|
||||||
if (m_staging_buffer[frame] != VK_NULL_HANDLE)
|
vmaDestroyBuffer(vk->getVmaAllocator(), m_staging_buffer[frame],
|
||||||
vkDestroyBuffer(getVKDriver()->getDevice(), m_staging_buffer[frame], NULL);
|
m_staging_memory[frame]);
|
||||||
if (m_staging_memory[frame] != VK_NULL_HANDLE)
|
|
||||||
vkFreeMemory(getVKDriver()->getDevice(), m_staging_memory[frame], NULL);
|
|
||||||
m_staging_buffer[frame] = VK_NULL_HANDLE;
|
m_staging_buffer[frame] = VK_NULL_HANDLE;
|
||||||
m_staging_memory[frame] = VK_NULL_HANDLE;
|
m_staging_memory[frame] = VK_NULL_HANDLE;
|
||||||
}
|
}
|
||||||
@ -198,7 +156,8 @@ void GEVulkanDynamicBuffer::destroy()
|
|||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
void GEVulkanDynamicBuffer::setCurrentData(void* data, size_t size)
|
void GEVulkanDynamicBuffer::setCurrentData(void* data, size_t size)
|
||||||
{
|
{
|
||||||
const unsigned cur_frame = getVKDriver()->getCurrentFrame();
|
GEVulkanDriver* vk = getVKDriver();
|
||||||
|
const unsigned cur_frame = vk->getCurrentFrame();
|
||||||
if (size > m_size)
|
if (size > m_size)
|
||||||
{
|
{
|
||||||
destroy();
|
destroy();
|
||||||
@ -210,11 +169,14 @@ void GEVulkanDynamicBuffer::setCurrentData(void* data, size_t size)
|
|||||||
if (size == 0 || m_mapped_addr[cur_frame] == NULL)
|
if (size == 0 || m_mapped_addr[cur_frame] == NULL)
|
||||||
return;
|
return;
|
||||||
memcpy(m_mapped_addr[cur_frame], data, size);
|
memcpy(m_mapped_addr[cur_frame], data, size);
|
||||||
|
vmaFlushAllocation(vk->getVmaAllocator(), m_staging_memory != NULL ?
|
||||||
|
m_staging_memory[cur_frame] : m_memory[cur_frame], 0, size);
|
||||||
|
|
||||||
if (m_type == GVDBT_GPU_RAM)
|
if (m_type == GVDBT_GPU_RAM)
|
||||||
{
|
{
|
||||||
VkBufferCopy copy_region = {};
|
VkBufferCopy copy_region = {};
|
||||||
copy_region.size = size;
|
copy_region.size = size;
|
||||||
vkCmdCopyBuffer(getVKDriver()->getCurrentCommandBuffer(),
|
vkCmdCopyBuffer(vk->getCurrentCommandBuffer(),
|
||||||
m_staging_buffer[cur_frame], m_buffer[cur_frame], 1, ©_region);
|
m_staging_buffer[cur_frame], m_buffer[cur_frame], 1, ©_region);
|
||||||
}
|
}
|
||||||
} // setCurrentData
|
} // setCurrentData
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#define HEADER_GE_VULKAN_DYNAMIC_BUFFER_HPP
|
#define HEADER_GE_VULKAN_DYNAMIC_BUFFER_HPP
|
||||||
|
|
||||||
#include "vulkan_wrapper.h"
|
#include "vulkan_wrapper.h"
|
||||||
|
#include "ge_vma.hpp"
|
||||||
|
|
||||||
namespace GE
|
namespace GE
|
||||||
{
|
{
|
||||||
@ -17,11 +18,11 @@ class GEVulkanDynamicBuffer
|
|||||||
private:
|
private:
|
||||||
VkBuffer* m_buffer;
|
VkBuffer* m_buffer;
|
||||||
|
|
||||||
VkDeviceMemory* m_memory;
|
VmaAllocation* m_memory;
|
||||||
|
|
||||||
VkBuffer* m_staging_buffer;
|
VkBuffer* m_staging_buffer;
|
||||||
|
|
||||||
VkDeviceMemory* m_staging_memory;
|
VmaAllocation* m_staging_memory;
|
||||||
|
|
||||||
void** m_mapped_addr;
|
void** m_mapped_addr;
|
||||||
|
|
||||||
@ -29,10 +30,9 @@ private:
|
|||||||
|
|
||||||
GEVulkanDynamicBufferType m_type;
|
GEVulkanDynamicBufferType m_type;
|
||||||
|
|
||||||
static VkMemoryPropertyFlags m_host_flag;
|
|
||||||
|
|
||||||
size_t m_size, m_real_size;
|
size_t m_size, m_real_size;
|
||||||
|
|
||||||
|
static int m_supports_host_transfer;
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
void initPerFrame(unsigned frame);
|
void initPerFrame(unsigned frame);
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
Loading…
Reference in New Issue
Block a user