[Vulkan] Shared memory trace download
This commit is contained in:
@@ -982,17 +982,11 @@ bool VulkanImmediateDrawer::CreateTextureResource(
|
||||
VkDeviceMemory upload_buffer_memory = VK_NULL_HANDLE;
|
||||
if (data) {
|
||||
size_t data_size = sizeof(uint32_t) * width * height;
|
||||
VkBufferCreateInfo upload_buffer_create_info;
|
||||
upload_buffer_create_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
|
||||
upload_buffer_create_info.pNext = nullptr;
|
||||
upload_buffer_create_info.flags = 0;
|
||||
upload_buffer_create_info.size = VkDeviceSize(data_size);
|
||||
upload_buffer_create_info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
|
||||
upload_buffer_create_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||
upload_buffer_create_info.queueFamilyIndexCount = 0;
|
||||
upload_buffer_create_info.pQueueFamilyIndices = nullptr;
|
||||
if (dfn.vkCreateBuffer(device, &upload_buffer_create_info, nullptr,
|
||||
&upload_buffer) != VK_SUCCESS) {
|
||||
uint32_t upload_buffer_memory_type;
|
||||
if (!util::CreateDedicatedAllocationBuffer(
|
||||
provider, VkDeviceSize(data_size), VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
|
||||
util::MemoryPurpose::kUpload, upload_buffer, upload_buffer_memory,
|
||||
&upload_buffer_memory_type)) {
|
||||
XELOGE(
|
||||
"Failed to create a Vulkan upload buffer for a {}x{} immediate "
|
||||
"drawer texture",
|
||||
@@ -1003,72 +997,6 @@ bool VulkanImmediateDrawer::CreateTextureResource(
|
||||
dfn.vkFreeMemory(device, image_memory, nullptr);
|
||||
return false;
|
||||
}
|
||||
|
||||
VkMemoryAllocateInfo upload_buffer_memory_allocate_info;
|
||||
VkMemoryRequirements upload_buffer_memory_requirements;
|
||||
dfn.vkGetBufferMemoryRequirements(device, upload_buffer,
|
||||
&upload_buffer_memory_requirements);
|
||||
upload_buffer_memory_allocate_info.memoryTypeIndex =
|
||||
util::ChooseHostMemoryType(
|
||||
provider, upload_buffer_memory_requirements.memoryTypeBits, false);
|
||||
if (upload_buffer_memory_allocate_info.memoryTypeIndex == UINT32_MAX) {
|
||||
XELOGE(
|
||||
"Failed to get a host-visible memory type for a Vulkan upload buffer "
|
||||
"for a {}x{} immediate drawer texture",
|
||||
width, height);
|
||||
dfn.vkDestroyBuffer(device, upload_buffer, nullptr);
|
||||
FreeTextureDescriptor(descriptor_index);
|
||||
dfn.vkDestroyImageView(device, image_view, nullptr);
|
||||
dfn.vkDestroyImage(device, image, nullptr);
|
||||
dfn.vkFreeMemory(device, image_memory, nullptr);
|
||||
return false;
|
||||
}
|
||||
upload_buffer_memory_allocate_info.sType =
|
||||
VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
|
||||
VkMemoryDedicatedAllocateInfoKHR
|
||||
upload_buffer_memory_dedicated_allocate_info;
|
||||
if (dedicated_allocation_supported) {
|
||||
upload_buffer_memory_dedicated_allocate_info.sType =
|
||||
VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR;
|
||||
upload_buffer_memory_dedicated_allocate_info.pNext = nullptr;
|
||||
upload_buffer_memory_dedicated_allocate_info.image = VK_NULL_HANDLE;
|
||||
upload_buffer_memory_dedicated_allocate_info.buffer = upload_buffer;
|
||||
upload_buffer_memory_allocate_info.pNext =
|
||||
&upload_buffer_memory_dedicated_allocate_info;
|
||||
} else {
|
||||
upload_buffer_memory_allocate_info.pNext = nullptr;
|
||||
}
|
||||
upload_buffer_memory_allocate_info.allocationSize =
|
||||
util::GetMappableMemorySize(provider,
|
||||
upload_buffer_memory_requirements.size);
|
||||
if (dfn.vkAllocateMemory(device, &upload_buffer_memory_allocate_info,
|
||||
nullptr, &upload_buffer_memory) != VK_SUCCESS) {
|
||||
XELOGE(
|
||||
"Failed to allocate memory for a Vulkan upload buffer for a {}x{} "
|
||||
"immediate drawer texture",
|
||||
width, height);
|
||||
dfn.vkDestroyBuffer(device, upload_buffer, nullptr);
|
||||
FreeTextureDescriptor(descriptor_index);
|
||||
dfn.vkDestroyImageView(device, image_view, nullptr);
|
||||
dfn.vkDestroyImage(device, image, nullptr);
|
||||
dfn.vkFreeMemory(device, image_memory, nullptr);
|
||||
return false;
|
||||
}
|
||||
if (dfn.vkBindBufferMemory(device, upload_buffer, upload_buffer_memory,
|
||||
0) != VK_SUCCESS) {
|
||||
XELOGE(
|
||||
"Failed to bind memory to a Vulkan upload buffer for a {}x{} "
|
||||
"immediate drawer texture",
|
||||
width, height);
|
||||
dfn.vkDestroyBuffer(device, upload_buffer, nullptr);
|
||||
dfn.vkFreeMemory(device, upload_buffer_memory, nullptr);
|
||||
FreeTextureDescriptor(descriptor_index);
|
||||
dfn.vkDestroyImageView(device, image_view, nullptr);
|
||||
dfn.vkDestroyImage(device, image, nullptr);
|
||||
dfn.vkFreeMemory(device, image_memory, nullptr);
|
||||
return false;
|
||||
}
|
||||
|
||||
void* upload_buffer_mapping;
|
||||
if (dfn.vkMapMemory(device, upload_buffer_memory, 0, VK_WHOLE_SIZE, 0,
|
||||
&upload_buffer_mapping) != VK_SUCCESS) {
|
||||
@@ -1085,9 +1013,8 @@ bool VulkanImmediateDrawer::CreateTextureResource(
|
||||
return false;
|
||||
}
|
||||
std::memcpy(upload_buffer_mapping, data, data_size);
|
||||
util::FlushMappedMemoryRange(
|
||||
provider, upload_buffer_memory,
|
||||
upload_buffer_memory_allocate_info.memoryTypeIndex);
|
||||
util::FlushMappedMemoryRange(provider, upload_buffer_memory,
|
||||
upload_buffer_memory_type);
|
||||
dfn.vkUnmapMemory(device, upload_buffer_memory);
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,9 @@
|
||||
|
||||
#include "xenia/ui/vulkan/vulkan_util.h"
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "xenia/base/assert.h"
|
||||
#include "xenia/base/math.h"
|
||||
#include "xenia/ui/vulkan/vulkan_provider.h"
|
||||
|
||||
@@ -43,6 +46,93 @@ void FlushMappedMemoryRange(const VulkanProvider& provider,
|
||||
provider.dfn().vkFlushMappedMemoryRanges(provider.device(), 1, &range);
|
||||
}
|
||||
|
||||
bool CreateDedicatedAllocationBuffer(
|
||||
const VulkanProvider& provider, VkDeviceSize size, VkBufferUsageFlags usage,
|
||||
MemoryPurpose memory_purpose, VkBuffer& buffer_out,
|
||||
VkDeviceMemory& memory_out, uint32_t* memory_type_out) {
|
||||
const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider.dfn();
|
||||
VkDevice device = provider.device();
|
||||
|
||||
VkBufferCreateInfo buffer_create_info;
|
||||
buffer_create_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
|
||||
buffer_create_info.pNext = nullptr;
|
||||
buffer_create_info.flags = 0;
|
||||
buffer_create_info.size = size;
|
||||
buffer_create_info.usage = usage;
|
||||
buffer_create_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||
buffer_create_info.queueFamilyIndexCount = 0;
|
||||
buffer_create_info.pQueueFamilyIndices = nullptr;
|
||||
VkBuffer buffer;
|
||||
if (dfn.vkCreateBuffer(device, &buffer_create_info, nullptr, &buffer) !=
|
||||
VK_SUCCESS) {
|
||||
return false;
|
||||
}
|
||||
|
||||
VkMemoryRequirements memory_requirements;
|
||||
dfn.vkGetBufferMemoryRequirements(device, buffer, &memory_requirements);
|
||||
uint32_t memory_type = UINT32_MAX;
|
||||
switch (memory_purpose) {
|
||||
case MemoryPurpose::kDeviceLocal:
|
||||
if (!xe::bit_scan_forward(memory_requirements.memoryTypeBits &
|
||||
provider.memory_types_device_local(),
|
||||
&memory_type)) {
|
||||
memory_type = UINT32_MAX;
|
||||
}
|
||||
break;
|
||||
case MemoryPurpose::kUpload:
|
||||
case MemoryPurpose::kReadback:
|
||||
memory_type =
|
||||
ChooseHostMemoryType(provider, memory_requirements.memoryTypeBits,
|
||||
memory_purpose == MemoryPurpose::kReadback);
|
||||
break;
|
||||
default:
|
||||
assert_unhandled_case(memory_purpose);
|
||||
}
|
||||
if (memory_type == UINT32_MAX) {
|
||||
dfn.vkDestroyBuffer(device, buffer, nullptr);
|
||||
return false;
|
||||
}
|
||||
|
||||
VkMemoryAllocateInfo memory_allocate_info;
|
||||
memory_allocate_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
|
||||
VkMemoryDedicatedAllocateInfoKHR memory_dedicated_allocate_info;
|
||||
if (provider.device_extensions().khr_dedicated_allocation) {
|
||||
memory_dedicated_allocate_info.sType =
|
||||
VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR;
|
||||
memory_dedicated_allocate_info.pNext = nullptr;
|
||||
memory_dedicated_allocate_info.image = VK_NULL_HANDLE;
|
||||
memory_dedicated_allocate_info.buffer = buffer;
|
||||
memory_allocate_info.pNext = &memory_dedicated_allocate_info;
|
||||
} else {
|
||||
memory_allocate_info.pNext = nullptr;
|
||||
}
|
||||
memory_allocate_info.allocationSize = memory_requirements.size;
|
||||
if (memory_purpose == MemoryPurpose::kUpload ||
|
||||
memory_purpose == MemoryPurpose::kReadback) {
|
||||
memory_allocate_info.allocationSize =
|
||||
GetMappableMemorySize(provider, memory_allocate_info.allocationSize);
|
||||
}
|
||||
memory_allocate_info.memoryTypeIndex = memory_type;
|
||||
VkDeviceMemory memory;
|
||||
if (dfn.vkAllocateMemory(device, &memory_allocate_info, nullptr, &memory) !=
|
||||
VK_SUCCESS) {
|
||||
dfn.vkDestroyBuffer(device, buffer, nullptr);
|
||||
return false;
|
||||
}
|
||||
if (dfn.vkBindBufferMemory(device, buffer, memory, 0) != VK_SUCCESS) {
|
||||
dfn.vkDestroyBuffer(device, buffer, nullptr);
|
||||
dfn.vkFreeMemory(device, memory, nullptr);
|
||||
return false;
|
||||
}
|
||||
|
||||
buffer_out = buffer;
|
||||
memory_out = memory;
|
||||
if (memory_type_out) {
|
||||
*memory_type_out = memory_type;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace util
|
||||
} // namespace vulkan
|
||||
} // namespace ui
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
#ifndef XENIA_UI_VULKAN_VULKAN_UTIL_H_
|
||||
#define XENIA_UI_VULKAN_VULKAN_UTIL_H_
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "xenia/base/math.h"
|
||||
#include "xenia/ui/vulkan/vulkan_provider.h"
|
||||
|
||||
@@ -38,6 +40,12 @@ inline bool DestroyAndNullHandle(F* destroy_function, P parent, T& handle) {
|
||||
return false;
|
||||
}
|
||||
|
||||
enum class MemoryPurpose {
|
||||
kDeviceLocal,
|
||||
kUpload,
|
||||
kReadback,
|
||||
};
|
||||
|
||||
inline VkDeviceSize GetMappableMemorySize(const VulkanProvider& provider,
|
||||
VkDeviceSize size) {
|
||||
VkDeviceSize non_coherent_atom_size =
|
||||
@@ -85,6 +93,14 @@ inline void InitializeSubresourceRange(
|
||||
range.layerCount = layer_count;
|
||||
}
|
||||
|
||||
// Creates a buffer backed by a dedicated allocation. If using a mappable memory
|
||||
// purpose (upload/readback), the allocation size will be aligned to
|
||||
// nonCoherentAtomSize.
|
||||
bool CreateDedicatedAllocationBuffer(
|
||||
const VulkanProvider& provider, VkDeviceSize size, VkBufferUsageFlags usage,
|
||||
MemoryPurpose memory_purpose, VkBuffer& buffer_out,
|
||||
VkDeviceMemory& memory_out, uint32_t* memory_type_out = nullptr);
|
||||
|
||||
inline VkShaderModule CreateShaderModule(const VulkanProvider& provider,
|
||||
const void* code, size_t code_size) {
|
||||
VkShaderModuleCreateInfo shader_module_create_info;
|
||||
|
||||
Reference in New Issue
Block a user