mirror of
https://github.com/stenzek/duckstation.git
synced 2025-06-06 03:25:36 +00:00
VulkanDevice: Support SDL window type
This commit is contained in:
parent
4bddd38d70
commit
ee1a3b904e
@ -23,6 +23,11 @@
|
||||
#include "fmt/format.h"
|
||||
#include "xxhash.h"
|
||||
|
||||
#ifdef ENABLE_SDL
|
||||
#include <SDL3/SDL.h>
|
||||
#include <SDL3/SDL_vulkan.h>
|
||||
#endif
|
||||
|
||||
#include <cstdlib>
|
||||
#include <limits>
|
||||
#include <mutex>
|
||||
@ -245,29 +250,53 @@ bool VulkanDevice::SelectInstanceExtensions(ExtensionList* extension_list, const
|
||||
return false;
|
||||
};
|
||||
|
||||
// Common extensions
|
||||
if (wi.type != WindowInfo::Type::Surfaceless && !SupportsExtension(VK_KHR_SURFACE_EXTENSION_NAME, true))
|
||||
return false;
|
||||
|
||||
#if defined(VK_USE_PLATFORM_WIN32_KHR)
|
||||
if (wi.type == WindowInfo::Type::Win32 && !SupportsExtension(VK_KHR_WIN32_SURFACE_EXTENSION_NAME, true))
|
||||
if (wi.type == WindowInfo::Type::Win32 && (!SupportsExtension(VK_KHR_SURFACE_EXTENSION_NAME, true) ||
|
||||
!SupportsExtension(VK_KHR_WIN32_SURFACE_EXTENSION_NAME, true)))
|
||||
return false;
|
||||
#endif
|
||||
#if defined(VK_USE_PLATFORM_XCB_KHR)
|
||||
if (wi.type == WindowInfo::Type::XCB && !SupportsExtension(VK_KHR_XCB_SURFACE_EXTENSION_NAME, true))
|
||||
if (wi.type == WindowInfo::Type::XCB && (!SupportsExtension(VK_KHR_SURFACE_EXTENSION_NAME, true) ||
|
||||
!SupportsExtension(VK_KHR_XCB_SURFACE_EXTENSION_NAME, true)))
|
||||
return false;
|
||||
#endif
|
||||
#if defined(VK_USE_PLATFORM_WAYLAND_KHR)
|
||||
if (wi.type == WindowInfo::Type::Wayland && !SupportsExtension(VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME, true))
|
||||
if (wi.type == WindowInfo::Type::Wayland && (!SupportsExtension(VK_KHR_SURFACE_EXTENSION_NAME, true) ||
|
||||
!SupportsExtension(VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME, true)))
|
||||
return false;
|
||||
#endif
|
||||
#if defined(VK_USE_PLATFORM_METAL_EXT)
|
||||
if (wi.type == WindowInfo::Type::MacOS && !SupportsExtension(VK_EXT_METAL_SURFACE_EXTENSION_NAME, true))
|
||||
if (wi.type == WindowInfo::Type::MacOS && (!SupportsExtension(VK_KHR_SURFACE_EXTENSION_NAME, true) ||
|
||||
!SupportsExtension(VK_EXT_METAL_SURFACE_EXTENSION_NAME, true)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
#if defined(VK_USE_PLATFORM_ANDROID_KHR)
|
||||
if (wi.type == WindowInfo::Type::Android && !SupportsExtension(VK_KHR_ANDROID_SURFACE_EXTENSION_NAME, true))
|
||||
if (wi.type == WindowInfo::Type::Android && (!SupportsExtension(VK_KHR_SURFACE_EXTENSION_NAME, true) ||
|
||||
!SupportsExtension(VK_KHR_ANDROID_SURFACE_EXTENSION_NAME, true)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(ENABLE_SDL)
|
||||
if (wi.type == WindowInfo::Type::SDL)
|
||||
{
|
||||
Uint32 sdl_extension_count = 0;
|
||||
const char* const* sdl_extensions = SDL_Vulkan_GetInstanceExtensions(&sdl_extension_count);
|
||||
if (!sdl_extensions)
|
||||
{
|
||||
ERROR_LOG("SDL_Vulkan_GetInstanceExtensions() failed: {}", SDL_GetError());
|
||||
return false;
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < sdl_extension_count; i++)
|
||||
{
|
||||
if (!SupportsExtension(sdl_extensions[i], true))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// VK_EXT_debug_utils
|
||||
@ -374,7 +403,10 @@ VulkanDevice::GPUList VulkanDevice::EnumerateGPUs()
|
||||
if (Vulkan::LoadVulkanInstanceFunctions(instance))
|
||||
ret = EnumerateGPUs(instance);
|
||||
|
||||
vkDestroyInstance(instance, nullptr);
|
||||
if (vkDestroyInstance)
|
||||
vkDestroyInstance(instance, nullptr);
|
||||
else
|
||||
ERROR_LOG("Vulkan instance was leaked because vkDestroyInstance() could not be loaded.");
|
||||
}
|
||||
|
||||
Vulkan::UnloadVulkanLibrary();
|
||||
@ -1894,7 +1926,13 @@ bool VulkanDevice::CreateDeviceAndMainSwapChain(std::string_view adapter, Featur
|
||||
bool enable_debug_utils = m_debug_device;
|
||||
bool enable_validation_layer = m_debug_device;
|
||||
|
||||
if (!Vulkan::LoadVulkanLibrary(error))
|
||||
#ifdef ENABLE_SDL
|
||||
const bool library_loaded =
|
||||
(wi.type == WindowInfo::Type::SDL) ? Vulkan::LoadVulkanLibraryFromSDL(error) : Vulkan::LoadVulkanLibrary(error);
|
||||
#else
|
||||
const bool library_loaded = Vulkan::LoadVulkanLibrary(error);
|
||||
#endif
|
||||
if (!library_loaded)
|
||||
{
|
||||
Error::AddPrefix(error,
|
||||
"Failed to load Vulkan library. Does your GPU and/or driver support Vulkan?\nThe error was:");
|
||||
@ -1924,6 +1962,12 @@ bool VulkanDevice::CreateDeviceAndMainSwapChain(std::string_view adapter, Featur
|
||||
{
|
||||
ERROR_LOG("Failed to load Vulkan instance functions");
|
||||
Error::SetStringView(error, "Failed to load Vulkan instance functions");
|
||||
|
||||
if (vkDestroyInstance)
|
||||
vkDestroyInstance(std::exchange(m_instance, nullptr), nullptr);
|
||||
else
|
||||
ERROR_LOG("Vulkan instance was leaked because vkDestroyInstance() could not be loaded.");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -14,12 +14,12 @@ VULKAN_MODULE_ENTRY_POINT(vkGetInstanceProcAddr, true)
|
||||
VULKAN_MODULE_ENTRY_POINT(vkEnumerateInstanceExtensionProperties, true)
|
||||
VULKAN_MODULE_ENTRY_POINT(vkEnumerateInstanceLayerProperties, true)
|
||||
VULKAN_MODULE_ENTRY_POINT(vkEnumerateInstanceVersion, false)
|
||||
VULKAN_MODULE_ENTRY_POINT(vkDestroyInstance, true)
|
||||
|
||||
#endif // VULKAN_MODULE_ENTRY_POINT
|
||||
|
||||
#ifdef VULKAN_INSTANCE_ENTRY_POINT
|
||||
|
||||
VULKAN_INSTANCE_ENTRY_POINT(vkDestroyInstance, true)
|
||||
VULKAN_INSTANCE_ENTRY_POINT(vkGetDeviceProcAddr, true)
|
||||
VULKAN_INSTANCE_ENTRY_POINT(vkEnumeratePhysicalDevices, true)
|
||||
VULKAN_INSTANCE_ENTRY_POINT(vkGetPhysicalDeviceFeatures, true)
|
||||
|
@ -11,6 +11,10 @@
|
||||
#include "common/error.h"
|
||||
#include "common/log.h"
|
||||
|
||||
#ifdef ENABLE_SDL
|
||||
#include <SDL3/SDL_vulkan.h>
|
||||
#endif
|
||||
|
||||
#include <cstdarg>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
@ -43,9 +47,17 @@ void Vulkan::ResetVulkanLibraryFunctionPointers()
|
||||
|
||||
static DynamicLibrary s_vulkan_library;
|
||||
|
||||
#ifdef ENABLE_SDL
|
||||
static bool s_vulkan_library_loaded_from_sdl = false;
|
||||
#endif
|
||||
|
||||
bool Vulkan::IsVulkanLibraryLoaded()
|
||||
{
|
||||
#ifdef ENABLE_SDL
|
||||
return (s_vulkan_library.IsOpen() || s_vulkan_library_loaded_from_sdl);
|
||||
#else
|
||||
return s_vulkan_library.IsOpen();
|
||||
#endif
|
||||
}
|
||||
|
||||
bool Vulkan::LoadVulkanLibrary(Error* error)
|
||||
@ -93,10 +105,65 @@ bool Vulkan::LoadVulkanLibrary(Error* error)
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_SDL
|
||||
|
||||
bool Vulkan::LoadVulkanLibraryFromSDL(Error* error)
|
||||
{
|
||||
if (!SDL_Vulkan_LoadLibrary(nullptr))
|
||||
{
|
||||
Error::SetStringFmt(error, "SDL_Vulkan_LoadLibrary() failed: {}", SDL_GetError());
|
||||
return false;
|
||||
}
|
||||
|
||||
vkGetInstanceProcAddr = reinterpret_cast<PFN_vkGetInstanceProcAddr>(SDL_Vulkan_GetVkGetInstanceProcAddr());
|
||||
if (!vkGetInstanceProcAddr)
|
||||
{
|
||||
Error::SetStringFmt(error, "SDL_Vulkan_GetVkGetInstanceProcAddr() failed: {}", SDL_GetError());
|
||||
SDL_Vulkan_UnloadLibrary();
|
||||
return false;
|
||||
}
|
||||
|
||||
bool required_functions_missing = false;
|
||||
|
||||
// vkGetInstanceProcAddr() can't resolve itself until Vulkan 1.2.
|
||||
|
||||
#define VULKAN_MODULE_ENTRY_POINT(name, required) \
|
||||
if ((reinterpret_cast<const void*>(&name) != reinterpret_cast<const void*>(&vkGetInstanceProcAddr)) && \
|
||||
!(name = reinterpret_cast<decltype(name)>(vkGetInstanceProcAddr(nullptr, #name))) && required) \
|
||||
{ \
|
||||
ERROR_LOG("Vulkan: Failed to load required module function {}", #name); \
|
||||
required_functions_missing = true; \
|
||||
}
|
||||
#include "vulkan_entry_points.inl"
|
||||
#undef VULKAN_MODULE_ENTRY_POINT
|
||||
|
||||
if (required_functions_missing)
|
||||
{
|
||||
Error::SetStringView(error, "One or more required functions are missing. The log contains more information.");
|
||||
ResetVulkanLibraryFunctionPointers();
|
||||
SDL_Vulkan_UnloadLibrary();
|
||||
return false;
|
||||
}
|
||||
|
||||
s_vulkan_library_loaded_from_sdl = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void Vulkan::UnloadVulkanLibrary()
|
||||
{
|
||||
ResetVulkanLibraryFunctionPointers();
|
||||
|
||||
s_vulkan_library.Close();
|
||||
|
||||
#ifdef ENABLE_SDL
|
||||
if (s_vulkan_library_loaded_from_sdl)
|
||||
{
|
||||
s_vulkan_library_loaded_from_sdl = false;
|
||||
SDL_Vulkan_UnloadLibrary();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
bool Vulkan::LoadVulkanInstanceFunctions(VkInstance instance)
|
||||
|
@ -59,10 +59,16 @@ class Error;
|
||||
#endif
|
||||
|
||||
namespace Vulkan {
|
||||
|
||||
bool IsVulkanLibraryLoaded();
|
||||
bool LoadVulkanLibrary(Error* error);
|
||||
bool LoadVulkanInstanceFunctions(VkInstance instance);
|
||||
bool LoadVulkanDeviceFunctions(VkDevice device);
|
||||
void UnloadVulkanLibrary();
|
||||
void ResetVulkanLibraryFunctionPointers();
|
||||
|
||||
#ifdef ENABLE_SDL
|
||||
bool LoadVulkanLibraryFromSDL(Error* error);
|
||||
#endif
|
||||
|
||||
} // namespace Vulkan
|
||||
|
@ -13,14 +13,14 @@
|
||||
#include <array>
|
||||
#include <cmath>
|
||||
|
||||
#if defined(VK_USE_PLATFORM_XLIB_KHR)
|
||||
#include <X11/Xlib.h>
|
||||
#endif
|
||||
|
||||
#if defined(VK_USE_PLATFORM_METAL_EXT)
|
||||
#include "util/metal_layer.h"
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_SDL
|
||||
#include <SDL3/SDL_vulkan.h>
|
||||
#endif
|
||||
|
||||
LOG_CHANNEL(GPUDevice);
|
||||
|
||||
static VkFormat GetLinearFormat(VkFormat format)
|
||||
@ -185,6 +185,19 @@ bool VulkanSwapChain::CreateSurface(VkInstance instance, VkPhysicalDevice physic
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(ENABLE_SDL)
|
||||
if (m_window_info.type == WindowInfo::Type::SDL)
|
||||
{
|
||||
if (!SDL_Vulkan_CreateSurface(static_cast<SDL_Window*>(m_window_info.window_handle), instance, nullptr, &m_surface))
|
||||
{
|
||||
Error::SetStringFmt(error, "SDL_Vulkan_CreateSurface() failed: {}", SDL_GetError());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
Error::SetStringFmt(error, "Unhandled window type: {}", static_cast<unsigned>(m_window_info.type));
|
||||
return false;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user