summaryrefslogtreecommitdiff
path: root/Source
diff options
context:
space:
mode:
authorRobin Kertels <robin.kertels@gmail.com>2022-10-07 23:36:16 +0200
committerRobin Kertels <robin.kertels@gmail.com>2022-10-23 02:54:35 +0200
commit3ffbf94b2a7460e250ae81e3eb6a40dcc1024e36 (patch)
treef33b7a015b70e19269d26c07388864fd3ecca004 /Source
parent5e96733e353c8cbca0b9d467332d073daed1952d (diff)
VideoBackends:Vulkan: Set up VMA
Co-authored-by: iwubcode <iwubcode@users.noreply.github.com>
Diffstat (limited to 'Source')
-rw-r--r--Source/Core/VideoBackends/Vulkan/CMakeLists.txt1
-rw-r--r--Source/Core/VideoBackends/Vulkan/VKMain.cpp15
-rw-r--r--Source/Core/VideoBackends/Vulkan/VulkanContext.cpp48
-rw-r--r--Source/Core/VideoBackends/Vulkan/VulkanContext.h8
-rw-r--r--Source/Core/VideoBackends/Vulkan/VulkanEntryPoints.inl5
-rw-r--r--Source/Core/VideoBackends/Vulkan/VulkanLoader.cpp1
-rw-r--r--Source/Core/VideoBackends/Vulkan/VulkanLoader.h36
7 files changed, 100 insertions, 14 deletions
diff --git a/Source/Core/VideoBackends/Vulkan/CMakeLists.txt b/Source/Core/VideoBackends/Vulkan/CMakeLists.txt
index 4489ca9e10..5fd6aa1ed7 100644
--- a/Source/Core/VideoBackends/Vulkan/CMakeLists.txt
+++ b/Source/Core/VideoBackends/Vulkan/CMakeLists.txt
@@ -52,6 +52,7 @@ PRIVATE
target_include_directories(videovulkan
PRIVATE
${CMAKE_SOURCE_DIR}/Externals/Vulkan/Include
+ ${CMAKE_SOURCE_DIR}/Externals/VulkanMemoryAllocator/include
)
if(MSVC)
diff --git a/Source/Core/VideoBackends/Vulkan/VKMain.cpp b/Source/Core/VideoBackends/Vulkan/VKMain.cpp
index bc76aa5610..e81c5d066b 100644
--- a/Source/Core/VideoBackends/Vulkan/VKMain.cpp
+++ b/Source/Core/VideoBackends/Vulkan/VKMain.cpp
@@ -35,8 +35,9 @@ void VideoBackend::InitBackendInfo()
if (LoadVulkanLibrary())
{
- VkInstance temp_instance =
- VulkanContext::CreateVulkanInstance(WindowSystemType::Headless, false, false);
+ u32 vk_api_version = 0;
+ VkInstance temp_instance = VulkanContext::CreateVulkanInstance(WindowSystemType::Headless,
+ false, false, &vk_api_version);
if (temp_instance)
{
if (LoadVulkanInstanceFunctions(temp_instance))
@@ -114,8 +115,9 @@ bool VideoBackend::Initialize(const WindowSystemInfo& wsi)
// We use this instance to fill in backend info, then re-use it for the actual device.
bool enable_surface = wsi.type != WindowSystemType::Headless;
bool enable_debug_reports = ShouldEnableDebugReports(enable_validation_layer);
- VkInstance instance =
- VulkanContext::CreateVulkanInstance(wsi.type, enable_debug_reports, enable_validation_layer);
+ u32 vk_api_version = 0;
+ VkInstance instance = VulkanContext::CreateVulkanInstance(
+ wsi.type, enable_debug_reports, enable_validation_layer, &vk_api_version);
if (instance == VK_NULL_HANDLE)
{
PanicAlertFmt("Failed to create Vulkan instance.");
@@ -171,8 +173,9 @@ bool VideoBackend::Initialize(const WindowSystemInfo& wsi)
}
// Now we can create the Vulkan device. VulkanContext takes ownership of the instance and surface.
- g_vulkan_context = VulkanContext::Create(instance, gpu_list[selected_adapter_index], surface,
- enable_debug_reports, enable_validation_layer);
+ g_vulkan_context =
+ VulkanContext::Create(instance, gpu_list[selected_adapter_index], surface,
+ enable_debug_reports, enable_validation_layer, vk_api_version);
if (!g_vulkan_context)
{
PanicAlertFmt("Failed to create Vulkan device");
diff --git a/Source/Core/VideoBackends/Vulkan/VulkanContext.cpp b/Source/Core/VideoBackends/Vulkan/VulkanContext.cpp
index bc9cc1169b..6df7ed3414 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,
diff --git a/Source/Core/VideoBackends/Vulkan/VulkanContext.h b/Source/Core/VideoBackends/Vulkan/VulkanContext.h
index 7f5d72a7d9..522ce69d13 100644
--- a/Source/Core/VideoBackends/Vulkan/VulkanContext.h
+++ b/Source/Core/VideoBackends/Vulkan/VulkanContext.h
@@ -26,7 +26,7 @@ public:
// Helper method to create a Vulkan instance.
static VkInstance CreateVulkanInstance(WindowSystemType wstype, bool enable_debug_report,
- bool enable_validation_layer);
+ bool enable_validation_layer, u32* out_vk_api_version);
// Returns a list of Vulkan-compatible GPUs.
using GPUList = std::vector<VkPhysicalDevice>;
@@ -47,7 +47,7 @@ public:
// been called for the specified VideoConfig.
static std::unique_ptr<VulkanContext> Create(VkInstance instance, VkPhysicalDevice gpu,
VkSurfaceKHR surface, bool enable_debug_reports,
- bool enable_validation_layer);
+ bool enable_validation_layer, u32 api_version);
// Enable/disable debug message runtime.
bool EnableDebugReports();
@@ -113,6 +113,8 @@ public:
// Returns true if exclusive fullscreen is supported for the given surface.
bool SupportsExclusiveFullscreen(const WindowSystemInfo& wsi, VkSurfaceKHR surface);
+ VmaAllocator GetMemoryAllocator() const { return m_allocator; }
+
#ifdef WIN32
// Returns the platform-specific exclusive fullscreen structure.
VkSurfaceFullScreenExclusiveWin32InfoEXT
@@ -127,10 +129,12 @@ private:
bool CreateDevice(VkSurfaceKHR surface, bool enable_validation_layer);
void InitDriverDetails();
void PopulateShaderSubgroupSupport();
+ bool CreateAllocator(u32 vk_api_version);
VkInstance m_instance = VK_NULL_HANDLE;
VkPhysicalDevice m_physical_device = VK_NULL_HANDLE;
VkDevice m_device = VK_NULL_HANDLE;
+ VmaAllocator m_allocator = VK_NULL_HANDLE;
VkQueue m_graphics_queue = VK_NULL_HANDLE;
u32 m_graphics_queue_family_index = 0;
diff --git a/Source/Core/VideoBackends/Vulkan/VulkanEntryPoints.inl b/Source/Core/VideoBackends/Vulkan/VulkanEntryPoints.inl
index 8c6db283c9..3bb21c41e3 100644
--- a/Source/Core/VideoBackends/Vulkan/VulkanEntryPoints.inl
+++ b/Source/Core/VideoBackends/Vulkan/VulkanEntryPoints.inl
@@ -37,6 +37,7 @@ VULKAN_INSTANCE_ENTRY_POINT(vkGetPhysicalDeviceSurfaceSupportKHR, false)
VULKAN_INSTANCE_ENTRY_POINT(vkGetPhysicalDeviceSurfaceCapabilitiesKHR, false)
VULKAN_INSTANCE_ENTRY_POINT(vkGetPhysicalDeviceSurfaceFormatsKHR, false)
VULKAN_INSTANCE_ENTRY_POINT(vkGetPhysicalDeviceSurfacePresentModesKHR, false)
+VULKAN_INSTANCE_ENTRY_POINT(vkGetPhysicalDeviceMemoryProperties2, false)
#if defined(VK_USE_PLATFORM_WIN32_KHR)
VULKAN_INSTANCE_ENTRY_POINT(vkCreateWin32SurfaceKHR, false)
@@ -192,6 +193,10 @@ VULKAN_DEVICE_ENTRY_POINT(vkDestroySwapchainKHR, false)
VULKAN_DEVICE_ENTRY_POINT(vkGetSwapchainImagesKHR, false)
VULKAN_DEVICE_ENTRY_POINT(vkAcquireNextImageKHR, false)
VULKAN_DEVICE_ENTRY_POINT(vkQueuePresentKHR, false)
+VULKAN_DEVICE_ENTRY_POINT(vkGetBufferMemoryRequirements2, false)
+VULKAN_DEVICE_ENTRY_POINT(vkGetImageMemoryRequirements2, false)
+VULKAN_DEVICE_ENTRY_POINT(vkBindBufferMemory2, false)
+VULKAN_DEVICE_ENTRY_POINT(vkBindImageMemory2, false)
#ifdef SUPPORTS_VULKAN_EXCLUSIVE_FULLSCREEN
VULKAN_DEVICE_ENTRY_POINT(vkAcquireFullScreenExclusiveModeEXT, false)
diff --git a/Source/Core/VideoBackends/Vulkan/VulkanLoader.cpp b/Source/Core/VideoBackends/Vulkan/VulkanLoader.cpp
index c554f07314..9b62244dfd 100644
--- a/Source/Core/VideoBackends/Vulkan/VulkanLoader.cpp
+++ b/Source/Core/VideoBackends/Vulkan/VulkanLoader.cpp
@@ -1,6 +1,7 @@
// Copyright 2016 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
+#define VMA_IMPLEMENTATION
#include "VideoBackends/Vulkan/VulkanLoader.h"
#include <atomic>
diff --git a/Source/Core/VideoBackends/Vulkan/VulkanLoader.h b/Source/Core/VideoBackends/Vulkan/VulkanLoader.h
index 2d6843953b..c9b92f5ac8 100644
--- a/Source/Core/VideoBackends/Vulkan/VulkanLoader.h
+++ b/Source/Core/VideoBackends/Vulkan/VulkanLoader.h
@@ -37,6 +37,42 @@
#undef VULKAN_INSTANCE_ENTRY_POINT
#undef VULKAN_MODULE_ENTRY_POINT
+// Include vma allocator globally since including it before the vulkan headers causes
+// errors
+#ifdef _MSVC_LANG
+#pragma warning(push, 4)
+#pragma warning(disable : 4189) // local variable is initialized but not referenced
+
+#endif // #ifdef _MSVC_LANG
+
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunused-variable"
+#endif // #ifdef __clang__
+
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-variable"
+#endif // #ifdef __GNUC__
+
+#define VMA_VULKAN_VERSION 1001000
+#define VMA_STATIC_VULKAN_FUNCTIONS 1
+#define VMA_DYNAMIC_VULKAN_FUNCTIONS 0
+#undef VK_NO_PROTOTYPES
+#include "vk_mem_alloc.h"
+
+#ifdef _MSVC_LANG
+#pragma warning(pop)
+#endif // #ifdef _MSVC_LANG
+
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif // #ifdef __clang__
+
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif // #ifdef __GNUC__
+
#include "Common/Logging/Log.h"
namespace Vulkan