mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-24 14:49:42 -06:00
VideoBackends:Vulkan: Use VMA for stream buffer
This commit is contained in:
@ -568,6 +568,13 @@ void CommandBufferManager::DeferImageDestruction(VkImage object)
|
|||||||
[object]() { vkDestroyImage(g_vulkan_context->GetDevice(), object, nullptr); });
|
[object]() { vkDestroyImage(g_vulkan_context->GetDevice(), object, nullptr); });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CommandBufferManager::DeferImageDestruction(VkImage image, VmaAllocation alloc)
|
||||||
|
{
|
||||||
|
CmdBufferResources& cmd_buffer_resources = GetCurrentCmdBufferResources();
|
||||||
|
cmd_buffer_resources.cleanup_resources.push_back(
|
||||||
|
[image, alloc]() { vmaDestroyImage(g_vulkan_context->GetMemoryAllocator(), image, alloc); });
|
||||||
|
}
|
||||||
|
|
||||||
void CommandBufferManager::DeferImageViewDestruction(VkImageView object)
|
void CommandBufferManager::DeferImageViewDestruction(VkImageView object)
|
||||||
{
|
{
|
||||||
CmdBufferResources& cmd_buffer_resources = GetCurrentCmdBufferResources();
|
CmdBufferResources& cmd_buffer_resources = GetCurrentCmdBufferResources();
|
||||||
|
@ -92,6 +92,7 @@ public:
|
|||||||
void DeferBufferDestruction(VkBuffer buffer, VmaAllocation alloc);
|
void DeferBufferDestruction(VkBuffer buffer, VmaAllocation alloc);
|
||||||
void DeferFramebufferDestruction(VkFramebuffer object);
|
void DeferFramebufferDestruction(VkFramebuffer object);
|
||||||
void DeferImageDestruction(VkImage object);
|
void DeferImageDestruction(VkImage object);
|
||||||
|
void DeferImageDestruction(VkImage object, VmaAllocation alloc);
|
||||||
void DeferImageViewDestruction(VkImageView object);
|
void DeferImageViewDestruction(VkImageView object);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -22,13 +22,9 @@ StreamBuffer::StreamBuffer(VkBufferUsageFlags usage, u32 size) : m_usage(usage),
|
|||||||
|
|
||||||
StreamBuffer::~StreamBuffer()
|
StreamBuffer::~StreamBuffer()
|
||||||
{
|
{
|
||||||
if (m_host_pointer)
|
// VMA_ALLOCATION_CREATE_MAPPED_BIT automatically handles unmapping for us
|
||||||
vkUnmapMemory(g_vulkan_context->GetDevice(), m_memory);
|
|
||||||
|
|
||||||
if (m_buffer != VK_NULL_HANDLE)
|
if (m_buffer != VK_NULL_HANDLE)
|
||||||
g_command_buffer_mgr->DeferBufferDestruction(m_buffer);
|
g_command_buffer_mgr->DeferBufferDestruction(m_buffer, m_alloc);
|
||||||
if (m_memory != VK_NULL_HANDLE)
|
|
||||||
g_command_buffer_mgr->DeferDeviceMemoryDestruction(m_memory);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<StreamBuffer> StreamBuffer::Create(VkBufferUsageFlags usage, u32 size)
|
std::unique_ptr<StreamBuffer> StreamBuffer::Create(VkBufferUsageFlags usage, u32 size)
|
||||||
@ -54,74 +50,38 @@ bool StreamBuffer::AllocateBuffer()
|
|||||||
nullptr // const uint32_t* pQueueFamilyIndices
|
nullptr // const uint32_t* pQueueFamilyIndices
|
||||||
};
|
};
|
||||||
|
|
||||||
|
VmaAllocationCreateInfo alloc_create_info = {};
|
||||||
|
alloc_create_info.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT |
|
||||||
|
VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT |
|
||||||
|
VMA_ALLOCATION_CREATE_MAPPED_BIT;
|
||||||
|
alloc_create_info.usage =
|
||||||
|
VMA_MEMORY_USAGE_AUTO_PREFER_HOST; // Host visible VRAM is slower in practice
|
||||||
|
alloc_create_info.pool = VK_NULL_HANDLE;
|
||||||
|
alloc_create_info.pUserData = nullptr;
|
||||||
|
alloc_create_info.priority = 0.0;
|
||||||
|
alloc_create_info.requiredFlags = 0;
|
||||||
|
alloc_create_info.preferredFlags = 0;
|
||||||
|
|
||||||
VkBuffer buffer = VK_NULL_HANDLE;
|
VkBuffer buffer = VK_NULL_HANDLE;
|
||||||
VkResult res =
|
VmaAllocation alloc = VK_NULL_HANDLE;
|
||||||
vkCreateBuffer(g_vulkan_context->GetDevice(), &buffer_create_info, nullptr, &buffer);
|
VmaAllocationInfo alloc_info;
|
||||||
|
VkResult res = vmaCreateBuffer(g_vulkan_context->GetMemoryAllocator(), &buffer_create_info,
|
||||||
|
&alloc_create_info, &buffer, &alloc, &alloc_info);
|
||||||
if (res != VK_SUCCESS)
|
if (res != VK_SUCCESS)
|
||||||
{
|
{
|
||||||
LOG_VULKAN_ERROR(res, "vkCreateBuffer failed: ");
|
LOG_VULKAN_ERROR(res, "vmaCreateBuffer failed: ");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get memory requirements (types etc) for this buffer
|
|
||||||
VkMemoryRequirements memory_requirements;
|
|
||||||
vkGetBufferMemoryRequirements(g_vulkan_context->GetDevice(), buffer, &memory_requirements);
|
|
||||||
|
|
||||||
// Aim for a coherent mapping if possible.
|
|
||||||
u32 memory_type_index = g_vulkan_context->GetUploadMemoryType(memory_requirements.memoryTypeBits,
|
|
||||||
&m_coherent_mapping);
|
|
||||||
|
|
||||||
// Allocate memory for backing this buffer
|
|
||||||
VkMemoryAllocateInfo memory_allocate_info = {
|
|
||||||
VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // VkStructureType sType
|
|
||||||
nullptr, // const void* pNext
|
|
||||||
memory_requirements.size, // VkDeviceSize allocationSize
|
|
||||||
memory_type_index // uint32_t memoryTypeIndex
|
|
||||||
};
|
|
||||||
VkDeviceMemory memory = VK_NULL_HANDLE;
|
|
||||||
res = vkAllocateMemory(g_vulkan_context->GetDevice(), &memory_allocate_info, nullptr, &memory);
|
|
||||||
if (res != VK_SUCCESS)
|
|
||||||
{
|
|
||||||
LOG_VULKAN_ERROR(res, "vkAllocateMemory failed: ");
|
|
||||||
vkDestroyBuffer(g_vulkan_context->GetDevice(), buffer, nullptr);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bind memory to buffer
|
|
||||||
res = vkBindBufferMemory(g_vulkan_context->GetDevice(), buffer, memory, 0);
|
|
||||||
if (res != VK_SUCCESS)
|
|
||||||
{
|
|
||||||
LOG_VULKAN_ERROR(res, "vkBindBufferMemory failed: ");
|
|
||||||
vkDestroyBuffer(g_vulkan_context->GetDevice(), buffer, nullptr);
|
|
||||||
vkFreeMemory(g_vulkan_context->GetDevice(), memory, nullptr);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Map this buffer into user-space
|
|
||||||
void* mapped_ptr = nullptr;
|
|
||||||
res = vkMapMemory(g_vulkan_context->GetDevice(), memory, 0, m_size, 0, &mapped_ptr);
|
|
||||||
if (res != VK_SUCCESS)
|
|
||||||
{
|
|
||||||
LOG_VULKAN_ERROR(res, "vkMapMemory failed: ");
|
|
||||||
vkDestroyBuffer(g_vulkan_context->GetDevice(), buffer, nullptr);
|
|
||||||
vkFreeMemory(g_vulkan_context->GetDevice(), memory, nullptr);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unmap current host pointer (if there was a previous buffer)
|
|
||||||
if (m_host_pointer)
|
|
||||||
vkUnmapMemory(g_vulkan_context->GetDevice(), m_memory);
|
|
||||||
|
|
||||||
// Destroy the backings for the buffer after the command buffer executes
|
// Destroy the backings for the buffer after the command buffer executes
|
||||||
|
// VMA_ALLOCATION_CREATE_MAPPED_BIT automatically handles unmapping for us
|
||||||
if (m_buffer != VK_NULL_HANDLE)
|
if (m_buffer != VK_NULL_HANDLE)
|
||||||
g_command_buffer_mgr->DeferBufferDestruction(m_buffer);
|
g_command_buffer_mgr->DeferBufferDestruction(m_buffer, m_alloc);
|
||||||
if (m_memory != VK_NULL_HANDLE)
|
|
||||||
g_command_buffer_mgr->DeferDeviceMemoryDestruction(m_memory);
|
|
||||||
|
|
||||||
// Replace with the new buffer
|
// Replace with the new buffer
|
||||||
m_buffer = buffer;
|
m_buffer = buffer;
|
||||||
m_memory = memory;
|
m_alloc = alloc;
|
||||||
m_host_pointer = reinterpret_cast<u8*>(mapped_ptr);
|
m_host_pointer = reinterpret_cast<u8*>(alloc_info.pMappedData);
|
||||||
m_current_offset = 0;
|
m_current_offset = 0;
|
||||||
m_current_gpu_position = 0;
|
m_current_gpu_position = 0;
|
||||||
m_tracked_fences.clear();
|
m_tracked_fences.clear();
|
||||||
@ -201,12 +161,9 @@ void StreamBuffer::CommitMemory(u32 final_num_bytes)
|
|||||||
ASSERT(final_num_bytes <= m_last_allocation_size);
|
ASSERT(final_num_bytes <= m_last_allocation_size);
|
||||||
|
|
||||||
// For non-coherent mappings, flush the memory range
|
// For non-coherent mappings, flush the memory range
|
||||||
if (!m_coherent_mapping)
|
// vmaFlushAllocation checks whether the allocation uses a coherent memory type internally
|
||||||
{
|
vmaFlushAllocation(g_vulkan_context->GetMemoryAllocator(), m_alloc, m_current_offset,
|
||||||
VkMappedMemoryRange range = {VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, nullptr, m_memory,
|
final_num_bytes);
|
||||||
m_current_offset, final_num_bytes};
|
|
||||||
vkFlushMappedMemoryRanges(g_vulkan_context->GetDevice(), 1, &range);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_current_offset += final_num_bytes;
|
m_current_offset += final_num_bytes;
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,6 @@ public:
|
|||||||
~StreamBuffer();
|
~StreamBuffer();
|
||||||
|
|
||||||
VkBuffer GetBuffer() const { return m_buffer; }
|
VkBuffer GetBuffer() const { return m_buffer; }
|
||||||
VkDeviceMemory GetDeviceMemory() const { return m_memory; }
|
|
||||||
u8* GetHostPointer() const { return m_host_pointer; }
|
u8* GetHostPointer() const { return m_host_pointer; }
|
||||||
u8* GetCurrentHostPointer() const { return m_host_pointer + m_current_offset; }
|
u8* GetCurrentHostPointer() const { return m_host_pointer + m_current_offset; }
|
||||||
u32 GetCurrentSize() const { return m_size; }
|
u32 GetCurrentSize() const { return m_size; }
|
||||||
@ -45,13 +44,11 @@ private:
|
|||||||
u32 m_last_allocation_size = 0;
|
u32 m_last_allocation_size = 0;
|
||||||
|
|
||||||
VkBuffer m_buffer = VK_NULL_HANDLE;
|
VkBuffer m_buffer = VK_NULL_HANDLE;
|
||||||
VkDeviceMemory m_memory = VK_NULL_HANDLE;
|
VmaAllocation m_alloc = VK_NULL_HANDLE;
|
||||||
u8* m_host_pointer = nullptr;
|
u8* m_host_pointer = nullptr;
|
||||||
|
|
||||||
// List of fences and the corresponding positions in the buffer
|
// List of fences and the corresponding positions in the buffer
|
||||||
std::deque<std::pair<u64, u32>> m_tracked_fences;
|
std::deque<std::pair<u64, u32>> m_tracked_fences;
|
||||||
|
|
||||||
bool m_coherent_mapping = false;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Vulkan
|
} // namespace Vulkan
|
||||||
|
@ -26,10 +26,10 @@
|
|||||||
|
|
||||||
namespace Vulkan
|
namespace Vulkan
|
||||||
{
|
{
|
||||||
VKTexture::VKTexture(const TextureConfig& tex_config, VkDeviceMemory device_memory, VkImage image,
|
VKTexture::VKTexture(const TextureConfig& tex_config, VmaAllocation alloc, VkImage image,
|
||||||
std::string_view name, VkImageLayout layout /* = VK_IMAGE_LAYOUT_UNDEFINED */,
|
std::string_view name, VkImageLayout layout /* = VK_IMAGE_LAYOUT_UNDEFINED */,
|
||||||
ComputeImageLayout compute_layout /* = ComputeImageLayout::Undefined */)
|
ComputeImageLayout compute_layout /* = ComputeImageLayout::Undefined */)
|
||||||
: AbstractTexture(tex_config), m_device_memory(device_memory), m_image(image), m_layout(layout),
|
: AbstractTexture(tex_config), m_alloc(alloc), m_image(image), m_layout(layout),
|
||||||
m_compute_layout(compute_layout), m_name(name)
|
m_compute_layout(compute_layout), m_name(name)
|
||||||
{
|
{
|
||||||
if (!m_name.empty() && g_ActiveConfig.backend_info.bSupportsSettingObjectNames)
|
if (!m_name.empty() && g_ActiveConfig.backend_info.bSupportsSettingObjectNames)
|
||||||
@ -49,10 +49,9 @@ VKTexture::~VKTexture()
|
|||||||
g_command_buffer_mgr->DeferImageViewDestruction(m_view);
|
g_command_buffer_mgr->DeferImageViewDestruction(m_view);
|
||||||
|
|
||||||
// If we don't have device memory allocated, the image is not owned by us (e.g. swapchain)
|
// If we don't have device memory allocated, the image is not owned by us (e.g. swapchain)
|
||||||
if (m_device_memory != VK_NULL_HANDLE)
|
if (m_alloc != VK_NULL_HANDLE)
|
||||||
{
|
{
|
||||||
g_command_buffer_mgr->DeferImageDestruction(m_image);
|
g_command_buffer_mgr->DeferImageDestruction(m_image, m_alloc);
|
||||||
g_command_buffer_mgr->DeferDeviceMemoryDestruction(m_device_memory);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,46 +84,28 @@ std::unique_ptr<VKTexture> VKTexture::Create(const TextureConfig& tex_config, st
|
|||||||
nullptr,
|
nullptr,
|
||||||
VK_IMAGE_LAYOUT_UNDEFINED};
|
VK_IMAGE_LAYOUT_UNDEFINED};
|
||||||
|
|
||||||
|
VmaAllocationCreateInfo alloc_create_info = {};
|
||||||
|
alloc_create_info.flags = VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT;
|
||||||
|
alloc_create_info.usage = VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE;
|
||||||
|
alloc_create_info.pool = VK_NULL_HANDLE;
|
||||||
|
alloc_create_info.pUserData = nullptr;
|
||||||
|
alloc_create_info.priority =
|
||||||
|
tex_config.IsComputeImage() || tex_config.IsRenderTarget() ? 1.0 : 0.0;
|
||||||
|
alloc_create_info.requiredFlags = 0;
|
||||||
|
alloc_create_info.preferredFlags = 0;
|
||||||
|
|
||||||
VkImage image = VK_NULL_HANDLE;
|
VkImage image = VK_NULL_HANDLE;
|
||||||
VkResult res = vkCreateImage(g_vulkan_context->GetDevice(), &image_info, nullptr, &image);
|
VmaAllocation alloc = VK_NULL_HANDLE;
|
||||||
|
VkResult res = vmaCreateImage(g_vulkan_context->GetMemoryAllocator(), &image_info,
|
||||||
|
&alloc_create_info, &image, &alloc, nullptr);
|
||||||
if (res != VK_SUCCESS)
|
if (res != VK_SUCCESS)
|
||||||
{
|
{
|
||||||
LOG_VULKAN_ERROR(res, "vkCreateImage failed: ");
|
LOG_VULKAN_ERROR(res, "vmaCreateImage failed: ");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allocate memory to back this texture, we want device local memory in this case
|
std::unique_ptr<VKTexture> texture = std::make_unique<VKTexture>(
|
||||||
VkMemoryRequirements memory_requirements;
|
tex_config, alloc, image, name, VK_IMAGE_LAYOUT_UNDEFINED, ComputeImageLayout::Undefined);
|
||||||
vkGetImageMemoryRequirements(g_vulkan_context->GetDevice(), image, &memory_requirements);
|
|
||||||
|
|
||||||
VkMemoryAllocateInfo memory_info = {
|
|
||||||
VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, nullptr, memory_requirements.size,
|
|
||||||
g_vulkan_context
|
|
||||||
->GetMemoryType(memory_requirements.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
|
|
||||||
false)
|
|
||||||
.value_or(0)};
|
|
||||||
|
|
||||||
VkDeviceMemory device_memory;
|
|
||||||
res = vkAllocateMemory(g_vulkan_context->GetDevice(), &memory_info, nullptr, &device_memory);
|
|
||||||
if (res != VK_SUCCESS)
|
|
||||||
{
|
|
||||||
LOG_VULKAN_ERROR(res, "vkAllocateMemory failed: ");
|
|
||||||
vkDestroyImage(g_vulkan_context->GetDevice(), image, nullptr);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
res = vkBindImageMemory(g_vulkan_context->GetDevice(), image, device_memory, 0);
|
|
||||||
if (res != VK_SUCCESS)
|
|
||||||
{
|
|
||||||
LOG_VULKAN_ERROR(res, "vkBindImageMemory failed: ");
|
|
||||||
vkDestroyImage(g_vulkan_context->GetDevice(), image, nullptr);
|
|
||||||
vkFreeMemory(g_vulkan_context->GetDevice(), device_memory, nullptr);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unique_ptr<VKTexture> texture =
|
|
||||||
std::make_unique<VKTexture>(tex_config, device_memory, image, name, VK_IMAGE_LAYOUT_UNDEFINED,
|
|
||||||
ComputeImageLayout::Undefined);
|
|
||||||
if (!texture->CreateView(VK_IMAGE_VIEW_TYPE_2D_ARRAY))
|
if (!texture->CreateView(VK_IMAGE_VIEW_TYPE_2D_ARRAY))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
@ -135,7 +116,7 @@ std::unique_ptr<VKTexture> VKTexture::CreateAdopted(const TextureConfig& tex_con
|
|||||||
VkImageViewType view_type, VkImageLayout layout)
|
VkImageViewType view_type, VkImageLayout layout)
|
||||||
{
|
{
|
||||||
std::unique_ptr<VKTexture> texture = std::make_unique<VKTexture>(
|
std::unique_ptr<VKTexture> texture = std::make_unique<VKTexture>(
|
||||||
tex_config, VkDeviceMemory(VK_NULL_HANDLE), image, "", layout, ComputeImageLayout::Undefined);
|
tex_config, VmaAllocation(VK_NULL_HANDLE), image, "", layout, ComputeImageLayout::Undefined);
|
||||||
if (!texture->CreateView(view_type))
|
if (!texture->CreateView(view_type))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
@ -701,9 +682,9 @@ void VKTexture::TransitionToLayout(VkCommandBuffer command_buffer,
|
|||||||
|
|
||||||
VKStagingTexture::VKStagingTexture(PrivateTag, StagingTextureType type, const TextureConfig& config,
|
VKStagingTexture::VKStagingTexture(PrivateTag, StagingTextureType type, const TextureConfig& config,
|
||||||
std::unique_ptr<StagingBuffer> buffer, VkImage linear_image,
|
std::unique_ptr<StagingBuffer> buffer, VkImage linear_image,
|
||||||
VkDeviceMemory linear_image_memory)
|
VmaAllocation linear_image_alloc)
|
||||||
: AbstractStagingTexture(type, config), m_staging_buffer(std::move(buffer)),
|
: AbstractStagingTexture(type, config), m_staging_buffer(std::move(buffer)),
|
||||||
m_linear_image(linear_image), m_linear_image_memory(linear_image_memory)
|
m_linear_image(linear_image), m_linear_image_alloc(linear_image_alloc)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -711,8 +692,7 @@ VKStagingTexture::~VKStagingTexture()
|
|||||||
{
|
{
|
||||||
if (m_linear_image != VK_NULL_HANDLE)
|
if (m_linear_image != VK_NULL_HANDLE)
|
||||||
{
|
{
|
||||||
g_command_buffer_mgr->DeferImageDestruction(m_linear_image);
|
g_command_buffer_mgr->DeferImageDestruction(m_linear_image, m_linear_image_alloc);
|
||||||
g_command_buffer_mgr->DeferDeviceMemoryDestruction(m_linear_image_memory);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -751,18 +731,17 @@ std::unique_ptr<VKStagingTexture> VKStagingTexture::Create(StagingTextureType ty
|
|||||||
|
|
||||||
// Linear image
|
// Linear image
|
||||||
VkImage linear_image = VK_NULL_HANDLE;
|
VkImage linear_image = VK_NULL_HANDLE;
|
||||||
VkDeviceMemory linear_image_device_memory = VK_NULL_HANDLE;
|
VmaAllocation linear_image_alloc = VK_NULL_HANDLE;
|
||||||
if (DriverDetails::HasBug(DriverDetails::BUG_SLOW_OPTIMAL_IMAGE_TO_BUFFER_COPY) &&
|
if (DriverDetails::HasBug(DriverDetails::BUG_SLOW_OPTIMAL_IMAGE_TO_BUFFER_COPY) &&
|
||||||
type == StagingTextureType::Readback && config.samples == 1)
|
type == StagingTextureType::Readback && config.samples == 1)
|
||||||
{
|
{
|
||||||
std::tie(linear_image, linear_image_device_memory) = CreateLinearImage(type, config);
|
std::tie(linear_image, linear_image_alloc) = CreateLinearImage(type, config);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<StagingBuffer> staging_buffer =
|
std::unique_ptr<StagingBuffer> staging_buffer =
|
||||||
std::make_unique<StagingBuffer>(buffer_type, buffer, alloc, buffer_size, map_ptr);
|
std::make_unique<StagingBuffer>(buffer_type, buffer, alloc, buffer_size, map_ptr);
|
||||||
std::unique_ptr<VKStagingTexture> staging_tex =
|
std::unique_ptr<VKStagingTexture> staging_tex = std::make_unique<VKStagingTexture>(
|
||||||
std::make_unique<VKStagingTexture>(PrivateTag{}, type, config, std::move(staging_buffer),
|
PrivateTag{}, type, config, std::move(staging_buffer), linear_image, linear_image_alloc);
|
||||||
linear_image, linear_image_device_memory);
|
|
||||||
|
|
||||||
// Use persistent mapping.
|
// Use persistent mapping.
|
||||||
if (!staging_tex->m_staging_buffer->Map())
|
if (!staging_tex->m_staging_buffer->Map())
|
||||||
@ -772,7 +751,7 @@ std::unique_ptr<VKStagingTexture> VKStagingTexture::Create(StagingTextureType ty
|
|||||||
return staging_tex;
|
return staging_tex;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<VkImage, VkDeviceMemory> VKStagingTexture::CreateLinearImage(StagingTextureType type,
|
std::pair<VkImage, VmaAllocation> VKStagingTexture::CreateLinearImage(StagingTextureType type,
|
||||||
const TextureConfig& config)
|
const TextureConfig& config)
|
||||||
{
|
{
|
||||||
// Create a intermediate texture with linear tiling
|
// Create a intermediate texture with linear tiling
|
||||||
@ -802,43 +781,25 @@ std::pair<VkImage, VkDeviceMemory> VKStagingTexture::CreateLinearImage(StagingTe
|
|||||||
return std::make_pair(VK_NULL_HANDLE, VK_NULL_HANDLE);
|
return std::make_pair(VK_NULL_HANDLE, VK_NULL_HANDLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VmaAllocationCreateInfo alloc_create_info = {};
|
||||||
|
alloc_create_info.flags = VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT;
|
||||||
|
alloc_create_info.usage = VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE;
|
||||||
|
alloc_create_info.pool = VK_NULL_HANDLE;
|
||||||
|
alloc_create_info.pUserData = nullptr;
|
||||||
|
alloc_create_info.priority = 0.0;
|
||||||
|
alloc_create_info.requiredFlags = 0;
|
||||||
|
alloc_create_info.preferredFlags = 0;
|
||||||
|
|
||||||
VkImage image;
|
VkImage image;
|
||||||
res = vkCreateImage(g_vulkan_context->GetDevice(), &image_info, nullptr, &image);
|
VmaAllocation alloc;
|
||||||
|
res = vmaCreateImage(g_vulkan_context->GetMemoryAllocator(), &image_info, &alloc_create_info,
|
||||||
|
&image, &alloc, nullptr);
|
||||||
if (res != VK_SUCCESS)
|
if (res != VK_SUCCESS)
|
||||||
{
|
{
|
||||||
LOG_VULKAN_ERROR(res, "vkCreateImage failed: ");
|
LOG_VULKAN_ERROR(res, "vmaCreateImage failed: ");
|
||||||
return std::make_pair(VK_NULL_HANDLE, VK_NULL_HANDLE);
|
return std::make_pair(VK_NULL_HANDLE, VK_NULL_HANDLE);
|
||||||
}
|
}
|
||||||
|
return std::make_pair(image, alloc);
|
||||||
// Allocate memory to back this texture, we want device local memory in this case
|
|
||||||
VkMemoryRequirements memory_requirements;
|
|
||||||
vkGetImageMemoryRequirements(g_vulkan_context->GetDevice(), image, &memory_requirements);
|
|
||||||
|
|
||||||
VkMemoryAllocateInfo memory_info = {
|
|
||||||
VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, nullptr, memory_requirements.size,
|
|
||||||
g_vulkan_context
|
|
||||||
->GetMemoryType(memory_requirements.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
|
|
||||||
false)
|
|
||||||
.value_or(0)};
|
|
||||||
|
|
||||||
VkDeviceMemory device_memory;
|
|
||||||
res = vkAllocateMemory(g_vulkan_context->GetDevice(), &memory_info, nullptr, &device_memory);
|
|
||||||
if (res != VK_SUCCESS)
|
|
||||||
{
|
|
||||||
LOG_VULKAN_ERROR(res, "vkAllocateMemory failed: ");
|
|
||||||
vkDestroyImage(g_vulkan_context->GetDevice(), image, nullptr);
|
|
||||||
return std::make_pair(VK_NULL_HANDLE, VK_NULL_HANDLE);
|
|
||||||
}
|
|
||||||
|
|
||||||
res = vkBindImageMemory(g_vulkan_context->GetDevice(), image, device_memory, 0);
|
|
||||||
if (res != VK_SUCCESS)
|
|
||||||
{
|
|
||||||
LOG_VULKAN_ERROR(res, "vkBindImageMemory failed: ");
|
|
||||||
vkDestroyImage(g_vulkan_context->GetDevice(), image, nullptr);
|
|
||||||
vkFreeMemory(g_vulkan_context->GetDevice(), device_memory, nullptr);
|
|
||||||
return std::make_pair(VK_NULL_HANDLE, VK_NULL_HANDLE);
|
|
||||||
}
|
|
||||||
return std::make_pair(image, device_memory);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void VKStagingTexture::CopyFromTexture(const AbstractTexture* src,
|
void VKStagingTexture::CopyFromTexture(const AbstractTexture* src,
|
||||||
|
@ -30,7 +30,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
VKTexture() = delete;
|
VKTexture() = delete;
|
||||||
VKTexture(const TextureConfig& tex_config, VkDeviceMemory device_memory, VkImage image,
|
VKTexture(const TextureConfig& tex_config, VmaAllocation alloc, VkImage image,
|
||||||
std::string_view name, VkImageLayout layout = VK_IMAGE_LAYOUT_UNDEFINED,
|
std::string_view name, VkImageLayout layout = VK_IMAGE_LAYOUT_UNDEFINED,
|
||||||
ComputeImageLayout compute_layout = ComputeImageLayout::Undefined);
|
ComputeImageLayout compute_layout = ComputeImageLayout::Undefined);
|
||||||
~VKTexture();
|
~VKTexture();
|
||||||
@ -51,11 +51,10 @@ public:
|
|||||||
void FinishedRendering() override;
|
void FinishedRendering() override;
|
||||||
|
|
||||||
VkImage GetImage() const { return m_image; }
|
VkImage GetImage() const { return m_image; }
|
||||||
VkDeviceMemory GetDeviceMemory() const { return m_device_memory; }
|
|
||||||
VkImageView GetView() const { return m_view; }
|
VkImageView GetView() const { return m_view; }
|
||||||
VkImageLayout GetLayout() const { return m_layout; }
|
VkImageLayout GetLayout() const { return m_layout; }
|
||||||
VkFormat GetVkFormat() const { return GetVkFormatForHostTextureFormat(m_config.format); }
|
VkFormat GetVkFormat() const { return GetVkFormatForHostTextureFormat(m_config.format); }
|
||||||
bool IsAdopted() const { return m_device_memory != VkDeviceMemory(VK_NULL_HANDLE); }
|
bool IsAdopted() const { return m_alloc != VmaAllocation(VK_NULL_HANDLE); }
|
||||||
|
|
||||||
static std::unique_ptr<VKTexture> Create(const TextureConfig& tex_config, std::string_view name);
|
static std::unique_ptr<VKTexture> Create(const TextureConfig& tex_config, std::string_view name);
|
||||||
static std::unique_ptr<VKTexture>
|
static std::unique_ptr<VKTexture>
|
||||||
@ -74,7 +73,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
bool CreateView(VkImageViewType type);
|
bool CreateView(VkImageViewType type);
|
||||||
|
|
||||||
VkDeviceMemory m_device_memory;
|
VmaAllocation m_alloc;
|
||||||
VkImage m_image;
|
VkImage m_image;
|
||||||
VkImageView m_view = VK_NULL_HANDLE;
|
VkImageView m_view = VK_NULL_HANDLE;
|
||||||
mutable VkImageLayout m_layout = VK_IMAGE_LAYOUT_UNDEFINED;
|
mutable VkImageLayout m_layout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||||
@ -92,7 +91,7 @@ public:
|
|||||||
VKStagingTexture() = delete;
|
VKStagingTexture() = delete;
|
||||||
VKStagingTexture(PrivateTag, StagingTextureType type, const TextureConfig& config,
|
VKStagingTexture(PrivateTag, StagingTextureType type, const TextureConfig& config,
|
||||||
std::unique_ptr<StagingBuffer> buffer, VkImage linear_image,
|
std::unique_ptr<StagingBuffer> buffer, VkImage linear_image,
|
||||||
VkDeviceMemory linear_image_memory);
|
VmaAllocation linear_image_alloc);
|
||||||
|
|
||||||
~VKStagingTexture();
|
~VKStagingTexture();
|
||||||
|
|
||||||
@ -110,7 +109,7 @@ public:
|
|||||||
static std::unique_ptr<VKStagingTexture> Create(StagingTextureType type,
|
static std::unique_ptr<VKStagingTexture> Create(StagingTextureType type,
|
||||||
const TextureConfig& config);
|
const TextureConfig& config);
|
||||||
|
|
||||||
static std::pair<VkImage, VkDeviceMemory> CreateLinearImage(StagingTextureType type,
|
static std::pair<VkImage, VmaAllocation> CreateLinearImage(StagingTextureType type,
|
||||||
const TextureConfig& config);
|
const TextureConfig& config);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -120,7 +119,7 @@ private:
|
|||||||
|
|
||||||
std::unique_ptr<StagingBuffer> m_staging_buffer;
|
std::unique_ptr<StagingBuffer> m_staging_buffer;
|
||||||
VkImage m_linear_image = VK_NULL_HANDLE;
|
VkImage m_linear_image = VK_NULL_HANDLE;
|
||||||
VkDeviceMemory m_linear_image_memory = VK_NULL_HANDLE;
|
VmaAllocation m_linear_image_alloc = VK_NULL_HANDLE;
|
||||||
u64 m_flush_fence_counter = 0;
|
u64 m_flush_fence_counter = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user