mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-01-25 07:21:14 +01:00
VideoBackends:Vulkan: Set up VMA
Co-authored-by: iwubcode <iwubcode@users.noreply.github.com>
This commit is contained in:
parent
5e96733e35
commit
3ffbf94b2a
@ -52,6 +52,7 @@ PRIVATE
|
|||||||
target_include_directories(videovulkan
|
target_include_directories(videovulkan
|
||||||
PRIVATE
|
PRIVATE
|
||||||
${CMAKE_SOURCE_DIR}/Externals/Vulkan/Include
|
${CMAKE_SOURCE_DIR}/Externals/Vulkan/Include
|
||||||
|
${CMAKE_SOURCE_DIR}/Externals/VulkanMemoryAllocator/include
|
||||||
)
|
)
|
||||||
|
|
||||||
if(MSVC)
|
if(MSVC)
|
||||||
|
@ -35,8 +35,9 @@ void VideoBackend::InitBackendInfo()
|
|||||||
|
|
||||||
if (LoadVulkanLibrary())
|
if (LoadVulkanLibrary())
|
||||||
{
|
{
|
||||||
VkInstance temp_instance =
|
u32 vk_api_version = 0;
|
||||||
VulkanContext::CreateVulkanInstance(WindowSystemType::Headless, false, false);
|
VkInstance temp_instance = VulkanContext::CreateVulkanInstance(WindowSystemType::Headless,
|
||||||
|
false, false, &vk_api_version);
|
||||||
if (temp_instance)
|
if (temp_instance)
|
||||||
{
|
{
|
||||||
if (LoadVulkanInstanceFunctions(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.
|
// 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_surface = wsi.type != WindowSystemType::Headless;
|
||||||
bool enable_debug_reports = ShouldEnableDebugReports(enable_validation_layer);
|
bool enable_debug_reports = ShouldEnableDebugReports(enable_validation_layer);
|
||||||
VkInstance instance =
|
u32 vk_api_version = 0;
|
||||||
VulkanContext::CreateVulkanInstance(wsi.type, enable_debug_reports, enable_validation_layer);
|
VkInstance instance = VulkanContext::CreateVulkanInstance(
|
||||||
|
wsi.type, enable_debug_reports, enable_validation_layer, &vk_api_version);
|
||||||
if (instance == VK_NULL_HANDLE)
|
if (instance == VK_NULL_HANDLE)
|
||||||
{
|
{
|
||||||
PanicAlertFmt("Failed to create Vulkan instance.");
|
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.
|
// 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,
|
g_vulkan_context =
|
||||||
enable_debug_reports, enable_validation_layer);
|
VulkanContext::Create(instance, gpu_list[selected_adapter_index], surface,
|
||||||
|
enable_debug_reports, enable_validation_layer, vk_api_version);
|
||||||
if (!g_vulkan_context)
|
if (!g_vulkan_context)
|
||||||
{
|
{
|
||||||
PanicAlertFmt("Failed to create Vulkan device");
|
PanicAlertFmt("Failed to create Vulkan device");
|
||||||
|
@ -40,6 +40,8 @@ VulkanContext::VulkanContext(VkInstance instance, VkPhysicalDevice physical_devi
|
|||||||
|
|
||||||
VulkanContext::~VulkanContext()
|
VulkanContext::~VulkanContext()
|
||||||
{
|
{
|
||||||
|
if (m_allocator != VK_NULL_HANDLE)
|
||||||
|
vmaDestroyAllocator(m_allocator);
|
||||||
if (m_device != VK_NULL_HANDLE)
|
if (m_device != VK_NULL_HANDLE)
|
||||||
vkDestroyDevice(m_device, nullptr);
|
vkDestroyDevice(m_device, nullptr);
|
||||||
|
|
||||||
@ -86,7 +88,8 @@ bool VulkanContext::CheckValidationLayerAvailablility()
|
|||||||
}
|
}
|
||||||
|
|
||||||
VkInstance VulkanContext::CreateVulkanInstance(WindowSystemType wstype, bool enable_debug_report,
|
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;
|
std::vector<const char*> enabled_extensions;
|
||||||
if (!SelectInstanceExtensions(&enabled_extensions, wstype, enable_debug_report))
|
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 = {};
|
VkInstanceCreateInfo instance_create_info = {};
|
||||||
instance_create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
|
instance_create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
|
||||||
instance_create_info.pNext = nullptr;
|
instance_create_info.pNext = nullptr;
|
||||||
@ -429,10 +434,9 @@ void VulkanContext::PopulateBackendInfoMultisampleModes(
|
|||||||
config->backend_info.AAModes.emplace_back(64);
|
config->backend_info.AAModes.emplace_back(64);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<VulkanContext> VulkanContext::Create(VkInstance instance, VkPhysicalDevice gpu,
|
std::unique_ptr<VulkanContext>
|
||||||
VkSurfaceKHR surface,
|
VulkanContext::Create(VkInstance instance, VkPhysicalDevice gpu, VkSurfaceKHR surface,
|
||||||
bool enable_debug_reports,
|
bool enable_debug_reports, bool enable_validation_layer, u32 vk_api_version)
|
||||||
bool enable_validation_layer)
|
|
||||||
{
|
{
|
||||||
std::unique_ptr<VulkanContext> context = std::make_unique<VulkanContext>(instance, gpu);
|
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();
|
context->EnableDebugReports();
|
||||||
|
|
||||||
// Attempt to create the device.
|
// 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.
|
// Since we are destroying the instance, we're also responsible for destroying the surface.
|
||||||
if (surface != VK_NULL_HANDLE)
|
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.");
|
INFO_LOG_FMT(VIDEO, "Using VK_EXT_full_screen_exclusive for exclusive fullscreen.");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
AddExtension(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, false);
|
||||||
|
AddExtension(VK_EXT_MEMORY_BUDGET_EXTENSION_NAME, false);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -695,6 +703,34 @@ bool VulkanContext::CreateDevice(VkSurfaceKHR surface, bool enable_validation_la
|
|||||||
return true;
|
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,
|
static VKAPI_ATTR VkBool32 VKAPI_CALL DebugReportCallback(VkDebugReportFlagsEXT flags,
|
||||||
VkDebugReportObjectTypeEXT objectType,
|
VkDebugReportObjectTypeEXT objectType,
|
||||||
uint64_t object, size_t location,
|
uint64_t object, size_t location,
|
||||||
|
@ -26,7 +26,7 @@ public:
|
|||||||
|
|
||||||
// Helper method to create a Vulkan instance.
|
// Helper method to create a Vulkan instance.
|
||||||
static VkInstance CreateVulkanInstance(WindowSystemType wstype, bool enable_debug_report,
|
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.
|
// Returns a list of Vulkan-compatible GPUs.
|
||||||
using GPUList = std::vector<VkPhysicalDevice>;
|
using GPUList = std::vector<VkPhysicalDevice>;
|
||||||
@ -47,7 +47,7 @@ public:
|
|||||||
// been called for the specified VideoConfig.
|
// been called for the specified VideoConfig.
|
||||||
static std::unique_ptr<VulkanContext> Create(VkInstance instance, VkPhysicalDevice gpu,
|
static std::unique_ptr<VulkanContext> Create(VkInstance instance, VkPhysicalDevice gpu,
|
||||||
VkSurfaceKHR surface, bool enable_debug_reports,
|
VkSurfaceKHR surface, bool enable_debug_reports,
|
||||||
bool enable_validation_layer);
|
bool enable_validation_layer, u32 api_version);
|
||||||
|
|
||||||
// Enable/disable debug message runtime.
|
// Enable/disable debug message runtime.
|
||||||
bool EnableDebugReports();
|
bool EnableDebugReports();
|
||||||
@ -113,6 +113,8 @@ public:
|
|||||||
// Returns true if exclusive fullscreen is supported for the given surface.
|
// Returns true if exclusive fullscreen is supported for the given surface.
|
||||||
bool SupportsExclusiveFullscreen(const WindowSystemInfo& wsi, VkSurfaceKHR surface);
|
bool SupportsExclusiveFullscreen(const WindowSystemInfo& wsi, VkSurfaceKHR surface);
|
||||||
|
|
||||||
|
VmaAllocator GetMemoryAllocator() const { return m_allocator; }
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
// Returns the platform-specific exclusive fullscreen structure.
|
// Returns the platform-specific exclusive fullscreen structure.
|
||||||
VkSurfaceFullScreenExclusiveWin32InfoEXT
|
VkSurfaceFullScreenExclusiveWin32InfoEXT
|
||||||
@ -127,10 +129,12 @@ private:
|
|||||||
bool CreateDevice(VkSurfaceKHR surface, bool enable_validation_layer);
|
bool CreateDevice(VkSurfaceKHR surface, bool enable_validation_layer);
|
||||||
void InitDriverDetails();
|
void InitDriverDetails();
|
||||||
void PopulateShaderSubgroupSupport();
|
void PopulateShaderSubgroupSupport();
|
||||||
|
bool CreateAllocator(u32 vk_api_version);
|
||||||
|
|
||||||
VkInstance m_instance = VK_NULL_HANDLE;
|
VkInstance m_instance = VK_NULL_HANDLE;
|
||||||
VkPhysicalDevice m_physical_device = VK_NULL_HANDLE;
|
VkPhysicalDevice m_physical_device = VK_NULL_HANDLE;
|
||||||
VkDevice m_device = VK_NULL_HANDLE;
|
VkDevice m_device = VK_NULL_HANDLE;
|
||||||
|
VmaAllocator m_allocator = VK_NULL_HANDLE;
|
||||||
|
|
||||||
VkQueue m_graphics_queue = VK_NULL_HANDLE;
|
VkQueue m_graphics_queue = VK_NULL_HANDLE;
|
||||||
u32 m_graphics_queue_family_index = 0;
|
u32 m_graphics_queue_family_index = 0;
|
||||||
|
@ -37,6 +37,7 @@ VULKAN_INSTANCE_ENTRY_POINT(vkGetPhysicalDeviceSurfaceSupportKHR, false)
|
|||||||
VULKAN_INSTANCE_ENTRY_POINT(vkGetPhysicalDeviceSurfaceCapabilitiesKHR, false)
|
VULKAN_INSTANCE_ENTRY_POINT(vkGetPhysicalDeviceSurfaceCapabilitiesKHR, false)
|
||||||
VULKAN_INSTANCE_ENTRY_POINT(vkGetPhysicalDeviceSurfaceFormatsKHR, false)
|
VULKAN_INSTANCE_ENTRY_POINT(vkGetPhysicalDeviceSurfaceFormatsKHR, false)
|
||||||
VULKAN_INSTANCE_ENTRY_POINT(vkGetPhysicalDeviceSurfacePresentModesKHR, false)
|
VULKAN_INSTANCE_ENTRY_POINT(vkGetPhysicalDeviceSurfacePresentModesKHR, false)
|
||||||
|
VULKAN_INSTANCE_ENTRY_POINT(vkGetPhysicalDeviceMemoryProperties2, false)
|
||||||
|
|
||||||
#if defined(VK_USE_PLATFORM_WIN32_KHR)
|
#if defined(VK_USE_PLATFORM_WIN32_KHR)
|
||||||
VULKAN_INSTANCE_ENTRY_POINT(vkCreateWin32SurfaceKHR, false)
|
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(vkGetSwapchainImagesKHR, false)
|
||||||
VULKAN_DEVICE_ENTRY_POINT(vkAcquireNextImageKHR, false)
|
VULKAN_DEVICE_ENTRY_POINT(vkAcquireNextImageKHR, false)
|
||||||
VULKAN_DEVICE_ENTRY_POINT(vkQueuePresentKHR, 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
|
#ifdef SUPPORTS_VULKAN_EXCLUSIVE_FULLSCREEN
|
||||||
VULKAN_DEVICE_ENTRY_POINT(vkAcquireFullScreenExclusiveModeEXT, false)
|
VULKAN_DEVICE_ENTRY_POINT(vkAcquireFullScreenExclusiveModeEXT, false)
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
// Copyright 2016 Dolphin Emulator Project
|
// Copyright 2016 Dolphin Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#define VMA_IMPLEMENTATION
|
||||||
#include "VideoBackends/Vulkan/VulkanLoader.h"
|
#include "VideoBackends/Vulkan/VulkanLoader.h"
|
||||||
|
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
|
@ -37,6 +37,42 @@
|
|||||||
#undef VULKAN_INSTANCE_ENTRY_POINT
|
#undef VULKAN_INSTANCE_ENTRY_POINT
|
||||||
#undef VULKAN_MODULE_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"
|
#include "Common/Logging/Log.h"
|
||||||
|
|
||||||
namespace Vulkan
|
namespace Vulkan
|
||||||
|
Loading…
x
Reference in New Issue
Block a user