Use vma in GEVulkanDynamicBuffer
This commit is contained in:
parent
b0f91ff33d
commit
cf8bafaab3
@ -9,7 +9,7 @@
|
||||
|
||||
namespace GE
|
||||
{
|
||||
VkMemoryPropertyFlags GEVulkanDynamicBuffer::m_host_flag = (VkMemoryPropertyFlags)-1;
|
||||
int GEVulkanDynamicBuffer::m_supports_host_transfer = -1;
|
||||
// ----------------------------------------------------------------------------
|
||||
GEVulkanDynamicBuffer::GEVulkanDynamicBuffer(GEVulkanDynamicBufferType t,
|
||||
VkBufferUsageFlags usage,
|
||||
@ -20,12 +20,12 @@ GEVulkanDynamicBuffer::GEVulkanDynamicBuffer(GEVulkanDynamicBufferType t,
|
||||
m_size = m_real_size = initial_size;
|
||||
|
||||
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()];
|
||||
if (t == GVDBT_GPU_RAM)
|
||||
{
|
||||
m_staging_buffer = new VkBuffer[GEVulkanDriver::getMaxFrameInFlight()];
|
||||
m_staging_memory = new VkDeviceMemory[GEVulkanDriver::getMaxFrameInFlight()];
|
||||
m_staging_memory = new VmaAllocation[GEVulkanDriver::getMaxFrameInFlight()];
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -51,6 +51,7 @@ GEVulkanDynamicBuffer::~GEVulkanDynamicBuffer()
|
||||
// ----------------------------------------------------------------------------
|
||||
void GEVulkanDynamicBuffer::initPerFrame(unsigned frame)
|
||||
{
|
||||
GEVulkanDriver* vk = getVKDriver();
|
||||
m_buffer[frame] = VK_NULL_HANDLE;
|
||||
m_memory[frame] = VK_NULL_HANDLE;
|
||||
m_mapped_addr[frame] = NULL;
|
||||
@ -60,128 +61,85 @@ void GEVulkanDynamicBuffer::initPerFrame(unsigned frame)
|
||||
m_staging_memory[frame] = VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
start:
|
||||
VkMemoryPropertyFlags prop = {};
|
||||
VkBuffer host_buffer = VK_NULL_HANDLE;
|
||||
VkDeviceMemory host_memory = VK_NULL_HANDLE;
|
||||
VkMemoryPropertyFlags host_flag = 0;
|
||||
if (m_host_flag == (VkFlags)-1)
|
||||
VmaAllocation host_memory = VK_NULL_HANDLE;
|
||||
VmaAllocationCreateInfo host_info = {};
|
||||
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/
|
||||
m_host_flag = VK_MEMORY_PROPERTY_DEVICE_LOCAL_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_info.flags |=
|
||||
VMA_ALLOCATION_CREATE_HOST_ACCESS_ALLOW_TRANSFER_INSTEAD_BIT;
|
||||
}
|
||||
|
||||
host_flag = m_host_flag;
|
||||
// From the above website:
|
||||
// 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)
|
||||
if (!vk->createBuffer(m_size, m_usage | VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
|
||||
host_info, host_buffer, host_memory))
|
||||
{
|
||||
host_flag = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
|
||||
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);
|
||||
vmaDestroyBuffer(vk->getVmaAllocator(), host_buffer, host_memory);
|
||||
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)
|
||||
{
|
||||
m_buffer[frame] = host_buffer;
|
||||
m_memory[frame] = host_memory;
|
||||
|
||||
if (vkMapMemory(getVKDriver()->getDevice(), m_memory[frame], 0, m_size,
|
||||
0, &m_mapped_addr[frame]) != VK_SUCCESS)
|
||||
{
|
||||
destroyPerFrame(frame);
|
||||
}
|
||||
m_mapped_addr[frame] = info.pMappedData;
|
||||
return;
|
||||
}
|
||||
|
||||
VkBuffer local_buffer = VK_NULL_HANDLE;
|
||||
VkDeviceMemory local_memory = VK_NULL_HANDLE;
|
||||
if (!getVKDriver()->createBuffer(m_size,
|
||||
m_usage | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
|
||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, local_buffer, local_memory))
|
||||
VmaAllocation local_memory = VK_NULL_HANDLE;
|
||||
VmaAllocationCreateInfo local_info = {};
|
||||
local_info.usage = VMA_MEMORY_USAGE_AUTO;
|
||||
|
||||
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)
|
||||
vkDestroyBuffer(getVKDriver()->getDevice(), host_buffer, NULL);
|
||||
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);
|
||||
vmaDestroyBuffer(vk->getVmaAllocator(), host_buffer, host_memory);
|
||||
vmaDestroyBuffer(vk->getVmaAllocator(), local_buffer, local_memory);
|
||||
return;
|
||||
}
|
||||
m_buffer[frame] = local_buffer;
|
||||
m_memory[frame] = local_memory;
|
||||
m_staging_buffer[frame] = host_buffer;
|
||||
m_staging_memory[frame] = host_memory;
|
||||
|
||||
if (vkMapMemory(getVKDriver()->getDevice(), m_staging_memory[frame], 0,
|
||||
m_size, 0, &m_mapped_addr[frame]) != VK_SUCCESS)
|
||||
{
|
||||
destroyPerFrame(frame);
|
||||
}
|
||||
m_mapped_addr[frame] = info.pMappedData;
|
||||
} // initPerFrame
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void GEVulkanDynamicBuffer::destroyPerFrame(unsigned frame)
|
||||
{
|
||||
if ((m_staging_memory && m_staging_memory[frame] != VK_NULL_HANDLE) ||
|
||||
m_memory[frame] != VK_NULL_HANDLE)
|
||||
{
|
||||
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);
|
||||
|
||||
GEVulkanDriver* vk = getVKDriver();
|
||||
vmaDestroyBuffer(vk->getVmaAllocator(), m_buffer[frame], m_memory[frame]);
|
||||
m_buffer[frame] = VK_NULL_HANDLE;
|
||||
m_memory[frame] = VK_NULL_HANDLE;
|
||||
m_mapped_addr[frame] = NULL;
|
||||
|
||||
if (m_type == GVDBT_GPU_RAM)
|
||||
{
|
||||
if (m_staging_buffer[frame] != VK_NULL_HANDLE)
|
||||
vkDestroyBuffer(getVKDriver()->getDevice(), m_staging_buffer[frame], NULL);
|
||||
if (m_staging_memory[frame] != VK_NULL_HANDLE)
|
||||
vkFreeMemory(getVKDriver()->getDevice(), m_staging_memory[frame], NULL);
|
||||
vmaDestroyBuffer(vk->getVmaAllocator(), m_staging_buffer[frame],
|
||||
m_staging_memory[frame]);
|
||||
m_staging_buffer[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)
|
||||
{
|
||||
const unsigned cur_frame = getVKDriver()->getCurrentFrame();
|
||||
GEVulkanDriver* vk = getVKDriver();
|
||||
const unsigned cur_frame = vk->getCurrentFrame();
|
||||
if (size > m_size)
|
||||
{
|
||||
destroy();
|
||||
@ -210,11 +169,14 @@ void GEVulkanDynamicBuffer::setCurrentData(void* data, size_t size)
|
||||
if (size == 0 || m_mapped_addr[cur_frame] == NULL)
|
||||
return;
|
||||
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)
|
||||
{
|
||||
VkBufferCopy copy_region = {};
|
||||
copy_region.size = size;
|
||||
vkCmdCopyBuffer(getVKDriver()->getCurrentCommandBuffer(),
|
||||
vkCmdCopyBuffer(vk->getCurrentCommandBuffer(),
|
||||
m_staging_buffer[cur_frame], m_buffer[cur_frame], 1, ©_region);
|
||||
}
|
||||
} // setCurrentData
|
||||
|
@ -2,6 +2,7 @@
|
||||
#define HEADER_GE_VULKAN_DYNAMIC_BUFFER_HPP
|
||||
|
||||
#include "vulkan_wrapper.h"
|
||||
#include "ge_vma.hpp"
|
||||
|
||||
namespace GE
|
||||
{
|
||||
@ -17,11 +18,11 @@ class GEVulkanDynamicBuffer
|
||||
private:
|
||||
VkBuffer* m_buffer;
|
||||
|
||||
VkDeviceMemory* m_memory;
|
||||
VmaAllocation* m_memory;
|
||||
|
||||
VkBuffer* m_staging_buffer;
|
||||
|
||||
VkDeviceMemory* m_staging_memory;
|
||||
VmaAllocation* m_staging_memory;
|
||||
|
||||
void** m_mapped_addr;
|
||||
|
||||
@ -29,10 +30,9 @@ private:
|
||||
|
||||
GEVulkanDynamicBufferType m_type;
|
||||
|
||||
static VkMemoryPropertyFlags m_host_flag;
|
||||
|
||||
size_t m_size, m_real_size;
|
||||
|
||||
static int m_supports_host_transfer;
|
||||
// ------------------------------------------------------------------------
|
||||
void initPerFrame(unsigned frame);
|
||||
// ------------------------------------------------------------------------
|
||||
|
Loading…
Reference in New Issue
Block a user