summaryrefslogtreecommitdiff
path: root/Source/Core/VideoBackends/Vulkan/VulkanContext.cpp
diff options
context:
space:
mode:
authorJMC47 <JMC4789@gmail.com>2022-10-23 01:18:47 -0400
committerGitHub <noreply@github.com>2022-10-23 01:18:47 -0400
commit06bd0a908692f61702a483c51c93fadb2ed7eefc (patch)
treedbfa5f3b73e9d58ae5f0a61a30549f9d0ab3e30f /Source/Core/VideoBackends/Vulkan/VulkanContext.cpp
parent8ec1bb6be5b7626b5801e502cb8f647ce5370de7 (diff)
parentaa1679f2c7428720d6ded0c69668311b552c60d4 (diff)
Merge pull request #11132 from K0bin/vma
Vulkan: Use VMA for memory allocations
Diffstat (limited to 'Source/Core/VideoBackends/Vulkan/VulkanContext.cpp')
-rw-r--r--Source/Core/VideoBackends/Vulkan/VulkanContext.cpp151
1 files changed, 42 insertions, 109 deletions
diff --git a/Source/Core/VideoBackends/Vulkan/VulkanContext.cpp b/Source/Core/VideoBackends/Vulkan/VulkanContext.cpp
index bc9cc1169b..4d6b5c8903 100644
--- a/Source/Core/VideoBackends/Vulkan/VulkanContext.cpp
+++ b/Source/Core/VideoBackends/Vulkan/VulkanContext.cpp
@@ -40,6 +40,8 @@ VulkanContext::VulkanContext(VkInstance instance, VkPhysicalDevice physical_devi
VulkanContext::~VulkanContext()
{
+ if (m_allocator != VK_NULL_HANDLE)
+ vmaDestroyAllocator(m_allocator);
if (m_device != VK_NULL_HANDLE)
vkDestroyDevice(m_device, nullptr);
@@ -86,7 +88,8 @@ bool VulkanContext::CheckValidationLayerAvailablility()
}
VkInstance VulkanContext::CreateVulkanInstance(WindowSystemType wstype, bool enable_debug_report,
- bool enable_validation_layer)
+ bool enable_validation_layer,
+ u32* out_vk_api_version)
{
std::vector<const char*> enabled_extensions;
if (!SelectInstanceExtensions(&enabled_extensions, wstype, enable_debug_report))
@@ -114,6 +117,8 @@ VkInstance VulkanContext::CreateVulkanInstance(WindowSystemType wstype, bool ena
}
}
+ *out_vk_api_version = app_info.apiVersion;
+
VkInstanceCreateInfo instance_create_info = {};
instance_create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
instance_create_info.pNext = nullptr;
@@ -429,10 +434,9 @@ void VulkanContext::PopulateBackendInfoMultisampleModes(
config->backend_info.AAModes.emplace_back(64);
}
-std::unique_ptr<VulkanContext> VulkanContext::Create(VkInstance instance, VkPhysicalDevice gpu,
- VkSurfaceKHR surface,
- bool enable_debug_reports,
- bool enable_validation_layer)
+std::unique_ptr<VulkanContext>
+VulkanContext::Create(VkInstance instance, VkPhysicalDevice gpu, VkSurfaceKHR surface,
+ bool enable_debug_reports, bool enable_validation_layer, u32 vk_api_version)
{
std::unique_ptr<VulkanContext> context = std::make_unique<VulkanContext>(instance, gpu);
@@ -445,7 +449,8 @@ std::unique_ptr<VulkanContext> VulkanContext::Create(VkInstance instance, VkPhys
context->EnableDebugReports();
// Attempt to create the device.
- if (!context->CreateDevice(surface, enable_validation_layer))
+ if (!context->CreateDevice(surface, enable_validation_layer) ||
+ !context->CreateAllocator(vk_api_version))
{
// Since we are destroying the instance, we're also responsible for destroying the surface.
if (surface != VK_NULL_HANDLE)
@@ -508,6 +513,9 @@ bool VulkanContext::SelectDeviceExtensions(bool enable_surface)
INFO_LOG_FMT(VIDEO, "Using VK_EXT_full_screen_exclusive for exclusive fullscreen.");
#endif
+ AddExtension(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, false);
+ AddExtension(VK_EXT_MEMORY_BUDGET_EXTENSION_NAME, false);
+
return true;
}
@@ -695,6 +703,34 @@ bool VulkanContext::CreateDevice(VkSurfaceKHR surface, bool enable_validation_la
return true;
}
+bool VulkanContext::CreateAllocator(u32 vk_api_version)
+{
+ VmaAllocatorCreateInfo allocator_info = {};
+ allocator_info.flags = VMA_ALLOCATOR_CREATE_EXTERNALLY_SYNCHRONIZED_BIT;
+ allocator_info.physicalDevice = m_physical_device;
+ allocator_info.device = m_device;
+ allocator_info.preferredLargeHeapBlockSize = 64 << 20;
+ allocator_info.pAllocationCallbacks = nullptr;
+ allocator_info.pDeviceMemoryCallbacks = nullptr;
+ allocator_info.pHeapSizeLimit = nullptr;
+ allocator_info.pVulkanFunctions = nullptr;
+ allocator_info.instance = m_instance;
+ allocator_info.vulkanApiVersion = vk_api_version;
+ allocator_info.pTypeExternalMemoryHandleTypes = nullptr;
+
+ if (SupportsDeviceExtension(VK_EXT_MEMORY_BUDGET_EXTENSION_NAME))
+ allocator_info.flags |= VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT;
+
+ VkResult res = vmaCreateAllocator(&allocator_info, &m_allocator);
+ if (res != VK_SUCCESS)
+ {
+ LOG_VULKAN_ERROR(res, "vmaCreateAllocator failed: ");
+ return false;
+ }
+
+ return true;
+}
+
static VKAPI_ATTR VkBool32 VKAPI_CALL DebugReportCallback(VkDebugReportFlagsEXT flags,
VkDebugReportObjectTypeEXT objectType,
uint64_t object, size_t location,
@@ -756,109 +792,6 @@ void VulkanContext::DisableDebugReports()
}
}
-std::optional<u32> VulkanContext::GetMemoryType(u32 bits, VkMemoryPropertyFlags properties,
- bool strict, bool* is_coherent)
-{
- static constexpr u32 ALL_MEMORY_PROPERTY_FLAGS = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
- VK_MEMORY_PROPERTY_HOST_COHERENT_BIT |
- VK_MEMORY_PROPERTY_HOST_CACHED_BIT;
-
- const u32 mask = strict ? ALL_MEMORY_PROPERTY_FLAGS : properties;
-
- for (u32 i = 0; i < VK_MAX_MEMORY_TYPES; i++)
- {
- if ((bits & (1 << i)) != 0)
- {
- const VkMemoryPropertyFlags type_flags =
- m_device_memory_properties.memoryTypes[i].propertyFlags;
- const VkMemoryPropertyFlags supported = type_flags & mask;
- if (supported == properties)
- {
- if (is_coherent)
- *is_coherent = (type_flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) != 0;
- return i;
- }
- }
- }
-
- return std::nullopt;
-}
-
-u32 VulkanContext::GetUploadMemoryType(u32 bits, bool* is_coherent)
-{
- static constexpr VkMemoryPropertyFlags COHERENT_FLAGS =
- VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
-
- // Try for coherent memory. Some drivers (looking at you, Adreno) have the cached type before the
- // uncached type, so use a strict check first.
- std::optional<u32> type_index = GetMemoryType(bits, COHERENT_FLAGS, true, is_coherent);
- if (type_index)
- return type_index.value();
-
- // Try for coherent memory, with any other bits set.
- type_index = GetMemoryType(bits, COHERENT_FLAGS, false, is_coherent);
- if (type_index)
- {
- WARN_LOG_FMT(VIDEO,
- "Strict check for upload memory properties failed, this may affect performance");
- return type_index.value();
- }
-
- // Fall back to non-coherent memory.
- WARN_LOG_FMT(
- VIDEO,
- "Vulkan: Failed to find a coherent memory type for uploads, this will affect performance.");
- type_index = GetMemoryType(bits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, false, is_coherent);
- if (type_index)
- return type_index.value();
-
- // Shouldn't happen, there should be at least one host-visible heap.
- PanicAlertFmt("Unable to get memory type for upload.");
- return 0;
-}
-
-u32 VulkanContext::GetReadbackMemoryType(u32 bits, bool* is_coherent)
-{
- std::optional<u32> type_index;
-
- // Mali driver appears to be significantly slower for readbacks when using cached memory.
- if (DriverDetails::HasBug(DriverDetails::BUG_SLOW_CACHED_READBACK_MEMORY))
- {
- type_index = GetMemoryType(
- bits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, true,
- is_coherent);
- if (type_index)
- return type_index.value();
- }
-
- // Optimal config uses cached+coherent.
- type_index =
- GetMemoryType(bits,
- VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_CACHED_BIT |
- VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
- true, is_coherent);
- if (type_index)
- return type_index.value();
-
- // Otherwise, prefer cached over coherent if we must choose one.
- type_index =
- GetMemoryType(bits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_CACHED_BIT,
- false, is_coherent);
- if (type_index)
- return type_index.value();
-
- WARN_LOG_FMT(VIDEO, "Vulkan: Failed to find a cached memory type for readbacks, this will affect "
- "performance.");
- type_index = GetMemoryType(bits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, false, is_coherent);
- *is_coherent = false;
- if (type_index)
- return type_index.value();
-
- // We should have at least one host visible memory type...
- PanicAlertFmt("Unable to get memory type for upload.");
- return 0;
-}
-
bool VulkanContext::SupportsDeviceExtension(const char* name) const
{
return std::any_of(m_device_extensions.begin(), m_device_extensions.end(),