mirror of
https://github.com/stenzek/duckstation.git
synced 2025-06-07 03:55:33 +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 "fmt/format.h"
|
||||||
#include "xxhash.h"
|
#include "xxhash.h"
|
||||||
|
|
||||||
|
#ifdef ENABLE_SDL
|
||||||
|
#include <SDL3/SDL.h>
|
||||||
|
#include <SDL3/SDL_vulkan.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
@ -245,29 +250,53 @@ bool VulkanDevice::SelectInstanceExtensions(ExtensionList* extension_list, const
|
|||||||
return false;
|
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 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;
|
return false;
|
||||||
#endif
|
#endif
|
||||||
#if defined(VK_USE_PLATFORM_XCB_KHR)
|
#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;
|
return false;
|
||||||
#endif
|
#endif
|
||||||
#if defined(VK_USE_PLATFORM_WAYLAND_KHR)
|
#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;
|
return false;
|
||||||
#endif
|
#endif
|
||||||
#if defined(VK_USE_PLATFORM_METAL_EXT)
|
#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;
|
return false;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
#if defined(VK_USE_PLATFORM_ANDROID_KHR)
|
#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;
|
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
|
#endif
|
||||||
|
|
||||||
// VK_EXT_debug_utils
|
// VK_EXT_debug_utils
|
||||||
@ -374,7 +403,10 @@ VulkanDevice::GPUList VulkanDevice::EnumerateGPUs()
|
|||||||
if (Vulkan::LoadVulkanInstanceFunctions(instance))
|
if (Vulkan::LoadVulkanInstanceFunctions(instance))
|
||||||
ret = EnumerateGPUs(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();
|
Vulkan::UnloadVulkanLibrary();
|
||||||
@ -1894,7 +1926,13 @@ bool VulkanDevice::CreateDeviceAndMainSwapChain(std::string_view adapter, Featur
|
|||||||
bool enable_debug_utils = m_debug_device;
|
bool enable_debug_utils = m_debug_device;
|
||||||
bool enable_validation_layer = 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,
|
Error::AddPrefix(error,
|
||||||
"Failed to load Vulkan library. Does your GPU and/or driver support Vulkan?\nThe error was:");
|
"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_LOG("Failed to load Vulkan instance functions");
|
||||||
Error::SetStringView(error, "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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,12 +14,12 @@ VULKAN_MODULE_ENTRY_POINT(vkGetInstanceProcAddr, true)
|
|||||||
VULKAN_MODULE_ENTRY_POINT(vkEnumerateInstanceExtensionProperties, true)
|
VULKAN_MODULE_ENTRY_POINT(vkEnumerateInstanceExtensionProperties, true)
|
||||||
VULKAN_MODULE_ENTRY_POINT(vkEnumerateInstanceLayerProperties, true)
|
VULKAN_MODULE_ENTRY_POINT(vkEnumerateInstanceLayerProperties, true)
|
||||||
VULKAN_MODULE_ENTRY_POINT(vkEnumerateInstanceVersion, false)
|
VULKAN_MODULE_ENTRY_POINT(vkEnumerateInstanceVersion, false)
|
||||||
VULKAN_MODULE_ENTRY_POINT(vkDestroyInstance, true)
|
|
||||||
|
|
||||||
#endif // VULKAN_MODULE_ENTRY_POINT
|
#endif // VULKAN_MODULE_ENTRY_POINT
|
||||||
|
|
||||||
#ifdef VULKAN_INSTANCE_ENTRY_POINT
|
#ifdef VULKAN_INSTANCE_ENTRY_POINT
|
||||||
|
|
||||||
|
VULKAN_INSTANCE_ENTRY_POINT(vkDestroyInstance, true)
|
||||||
VULKAN_INSTANCE_ENTRY_POINT(vkGetDeviceProcAddr, true)
|
VULKAN_INSTANCE_ENTRY_POINT(vkGetDeviceProcAddr, true)
|
||||||
VULKAN_INSTANCE_ENTRY_POINT(vkEnumeratePhysicalDevices, true)
|
VULKAN_INSTANCE_ENTRY_POINT(vkEnumeratePhysicalDevices, true)
|
||||||
VULKAN_INSTANCE_ENTRY_POINT(vkGetPhysicalDeviceFeatures, true)
|
VULKAN_INSTANCE_ENTRY_POINT(vkGetPhysicalDeviceFeatures, true)
|
||||||
|
@ -11,6 +11,10 @@
|
|||||||
#include "common/error.h"
|
#include "common/error.h"
|
||||||
#include "common/log.h"
|
#include "common/log.h"
|
||||||
|
|
||||||
|
#ifdef ENABLE_SDL
|
||||||
|
#include <SDL3/SDL_vulkan.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <cstdarg>
|
#include <cstdarg>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
@ -43,9 +47,17 @@ void Vulkan::ResetVulkanLibraryFunctionPointers()
|
|||||||
|
|
||||||
static DynamicLibrary s_vulkan_library;
|
static DynamicLibrary s_vulkan_library;
|
||||||
|
|
||||||
|
#ifdef ENABLE_SDL
|
||||||
|
static bool s_vulkan_library_loaded_from_sdl = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
bool Vulkan::IsVulkanLibraryLoaded()
|
bool Vulkan::IsVulkanLibraryLoaded()
|
||||||
{
|
{
|
||||||
|
#ifdef ENABLE_SDL
|
||||||
|
return (s_vulkan_library.IsOpen() || s_vulkan_library_loaded_from_sdl);
|
||||||
|
#else
|
||||||
return s_vulkan_library.IsOpen();
|
return s_vulkan_library.IsOpen();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Vulkan::LoadVulkanLibrary(Error* error)
|
bool Vulkan::LoadVulkanLibrary(Error* error)
|
||||||
@ -93,10 +105,65 @@ bool Vulkan::LoadVulkanLibrary(Error* error)
|
|||||||
return true;
|
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()
|
void Vulkan::UnloadVulkanLibrary()
|
||||||
{
|
{
|
||||||
ResetVulkanLibraryFunctionPointers();
|
ResetVulkanLibraryFunctionPointers();
|
||||||
|
|
||||||
s_vulkan_library.Close();
|
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)
|
bool Vulkan::LoadVulkanInstanceFunctions(VkInstance instance)
|
||||||
|
@ -59,10 +59,16 @@ class Error;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace Vulkan {
|
namespace Vulkan {
|
||||||
|
|
||||||
bool IsVulkanLibraryLoaded();
|
bool IsVulkanLibraryLoaded();
|
||||||
bool LoadVulkanLibrary(Error* error);
|
bool LoadVulkanLibrary(Error* error);
|
||||||
bool LoadVulkanInstanceFunctions(VkInstance instance);
|
bool LoadVulkanInstanceFunctions(VkInstance instance);
|
||||||
bool LoadVulkanDeviceFunctions(VkDevice device);
|
bool LoadVulkanDeviceFunctions(VkDevice device);
|
||||||
void UnloadVulkanLibrary();
|
void UnloadVulkanLibrary();
|
||||||
void ResetVulkanLibraryFunctionPointers();
|
void ResetVulkanLibraryFunctionPointers();
|
||||||
|
|
||||||
|
#ifdef ENABLE_SDL
|
||||||
|
bool LoadVulkanLibraryFromSDL(Error* error);
|
||||||
|
#endif
|
||||||
|
|
||||||
} // namespace Vulkan
|
} // namespace Vulkan
|
||||||
|
@ -13,14 +13,14 @@
|
|||||||
#include <array>
|
#include <array>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
#if defined(VK_USE_PLATFORM_XLIB_KHR)
|
|
||||||
#include <X11/Xlib.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(VK_USE_PLATFORM_METAL_EXT)
|
#if defined(VK_USE_PLATFORM_METAL_EXT)
|
||||||
#include "util/metal_layer.h"
|
#include "util/metal_layer.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef ENABLE_SDL
|
||||||
|
#include <SDL3/SDL_vulkan.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
LOG_CHANNEL(GPUDevice);
|
LOG_CHANNEL(GPUDevice);
|
||||||
|
|
||||||
static VkFormat GetLinearFormat(VkFormat format)
|
static VkFormat GetLinearFormat(VkFormat format)
|
||||||
@ -185,6 +185,19 @@ bool VulkanSwapChain::CreateSurface(VkInstance instance, VkPhysicalDevice physic
|
|||||||
}
|
}
|
||||||
#endif
|
#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));
|
Error::SetStringFmt(error, "Unhandled window type: {}", static_cast<unsigned>(m_window_info.type));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user