Wayland support.

This commit is contained in:
Dario 2024-12-19 18:34:34 -03:00
parent bacfe02d0e
commit ddda801d47
9 changed files with 102 additions and 13 deletions

View file

@ -272,6 +272,10 @@ if (SWA_D3D12)
target_compile_definitions(UnleashedRecomp PRIVATE SWA_D3D12) target_compile_definitions(UnleashedRecomp PRIVATE SWA_D3D12)
endif() endif()
if (CMAKE_SYSTEM_NAME MATCHES "Linux")
target_compile_definitions(UnleashedRecomp PRIVATE SDL_VULKAN_ENABLED)
endif()
find_package(directx-dxc REQUIRED) find_package(directx-dxc REQUIRED)
if (SWA_D3D12) if (SWA_D3D12)

View file

@ -29,12 +29,18 @@
typedef struct _NSWindow NSWindow; typedef struct _NSWindow NSWindow;
#endif #endif
#ifdef SDL_VULKAN_ENABLED
#include <SDL_vulkan.h>
#endif
namespace plume { namespace plume {
#if defined(_WIN64) #if defined(_WIN64)
// Native HWND handle to the target window. // Native HWND handle to the target window.
typedef HWND RenderWindow; typedef HWND RenderWindow;
#elif defined(__ANDROID__) #elif defined(__ANDROID__)
typedef ANativeWindow* RenderWindow; typedef ANativeWindow* RenderWindow;
#elif defined(SDL_VULKAN_ENABLED)
typedef SDL_Window *RenderWindow;
#elif defined(__linux__) #elif defined(__linux__)
struct RenderWindow { struct RenderWindow {
Display* display; Display* display;

View file

@ -1989,6 +1989,13 @@ namespace plume {
fprintf(stderr, "vkCreateWin32SurfaceKHR failed with error code 0x%X.\n", res); fprintf(stderr, "vkCreateWin32SurfaceKHR failed with error code 0x%X.\n", res);
return; return;
} }
# elif defined(SDL_VULKAN_ENABLED)
VulkanInterface *renderInterface = commandQueue->device->renderInterface;
SDL_bool sdlRes = SDL_Vulkan_CreateSurface(renderWindow, renderInterface->instance, &surface);
if (sdlRes == SDL_FALSE) {
fprintf(stderr, "SDL_Vulkan_CreateSurface failed with error %s.\n", SDL_GetError());
return;
}
# elif defined(__ANDROID__) # elif defined(__ANDROID__)
assert(renderWindow != nullptr); assert(renderWindow != nullptr);
VkAndroidSurfaceCreateInfoKHR surfaceCreateInfo = {}; VkAndroidSurfaceCreateInfoKHR surfaceCreateInfo = {};
@ -2312,6 +2319,8 @@ namespace plume {
GetClientRect(renderWindow, &rect); GetClientRect(renderWindow, &rect);
dstWidth = rect.right - rect.left; dstWidth = rect.right - rect.left;
dstHeight = rect.bottom - rect.top; dstHeight = rect.bottom - rect.top;
# elif defined(SDL_VULKAN_ENABLED)
SDL_GetWindowSize(renderWindow, (int *)(&dstWidth), (int *)(&dstHeight));
# elif defined(__ANDROID__) # elif defined(__ANDROID__)
dstWidth = ANativeWindow_getWidth(renderWindow); dstWidth = ANativeWindow_getWidth(renderWindow);
dstHeight = ANativeWindow_getHeight(renderWindow); dstHeight = ANativeWindow_getHeight(renderWindow);
@ -4073,7 +4082,11 @@ namespace plume {
// VulkanInterface // VulkanInterface
#if SDL_VULKAN_ENABLED
VulkanInterface::VulkanInterface(RenderWindow sdlWindow) {
#else
VulkanInterface::VulkanInterface() { VulkanInterface::VulkanInterface() {
#endif
VkResult res = volkInitialize(); VkResult res = volkInitialize();
if (res != VK_SUCCESS) { if (res != VK_SUCCESS) {
fprintf(stderr, "volkInitialize failed with error code 0x%X.\n", res); fprintf(stderr, "volkInitialize failed with error code 0x%X.\n", res);
@ -4100,11 +4113,31 @@ namespace plume {
std::vector<VkExtensionProperties> availableExtensions(extensionCount); std::vector<VkExtensionProperties> availableExtensions(extensionCount);
vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, availableExtensions.data()); vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, availableExtensions.data());
std::unordered_set<std::string> missingRequiredExtensions = RequiredInstanceExtensions; std::unordered_set<std::string> requiredExtensions = RequiredInstanceExtensions;
std::unordered_set<std::string> supportedOptionalExtensions; std::unordered_set<std::string> supportedOptionalExtensions;
# if DLSS_ENABLED # if DLSS_ENABLED
const std::unordered_set<std::string> dlssExtensions = DLSS::getRequiredInstanceExtensionsVulkan(); const std::unordered_set<std::string> dlssExtensions = DLSS::getRequiredInstanceExtensionsVulkan();
# endif # endif
# if SDL_VULKAN_ENABLED
// Push the extensions specified by SDL as required.
// SDL2 has this awkward requirement for the window to pull the extensions from.
// This can be removed when upgrading to SDL3.
if (sdlWindow != nullptr) {
uint32_t sdlVulkanExtensionCount = 0;
if (SDL_Vulkan_GetInstanceExtensions(sdlWindow, &sdlVulkanExtensionCount, nullptr)) {
std::vector<char *> sdlVulkanExtensions;
sdlVulkanExtensions.resize(sdlVulkanExtensionCount);
if (SDL_Vulkan_GetInstanceExtensions(sdlWindow, &sdlVulkanExtensionCount, (const char **)(sdlVulkanExtensions.data()))) {
for (char *sdlVulkanExtension : sdlVulkanExtensions) {
requiredExtensions.insert(sdlVulkanExtension);
}
}
}
}
# endif
std::unordered_set<std::string> missingRequiredExtensions = requiredExtensions;
for (uint32_t i = 0; i < extensionCount; i++) { for (uint32_t i = 0; i < extensionCount; i++) {
const std::string extensionName(availableExtensions[i].extensionName); const std::string extensionName(availableExtensions[i].extensionName);
missingRequiredExtensions.erase(extensionName); missingRequiredExtensions.erase(extensionName);
@ -4129,7 +4162,7 @@ namespace plume {
} }
std::vector<const char *> enabledExtensions; std::vector<const char *> enabledExtensions;
for (const std::string &extension : RequiredInstanceExtensions) { for (const std::string &extension : requiredExtensions) {
enabledExtensions.push_back(extension.c_str()); enabledExtensions.push_back(extension.c_str());
} }
@ -4192,8 +4225,15 @@ namespace plume {
// Global creation function. // Global creation function.
#if SDL_VULKAN_ENABLED
std::unique_ptr<RenderInterface> CreateVulkanInterface(RenderWindow sdlWindow) {
std::unique_ptr<VulkanInterface> createdInterface = std::make_unique<VulkanInterface>(sdlWindow);
return createdInterface->isValid() ? std::move(createdInterface) : nullptr;
}
#else
std::unique_ptr<RenderInterface> CreateVulkanInterface() { std::unique_ptr<RenderInterface> CreateVulkanInterface() {
std::unique_ptr<VulkanInterface> createdInterface = std::make_unique<VulkanInterface>(); std::unique_ptr<VulkanInterface> createdInterface = std::make_unique<VulkanInterface>();
return createdInterface->isValid() ? std::move(createdInterface) : nullptr; return createdInterface->isValid() ? std::move(createdInterface) : nullptr;
} }
#endif
}; };

View file

@ -422,7 +422,12 @@ namespace plume {
VkApplicationInfo appInfo = {}; VkApplicationInfo appInfo = {};
RenderInterfaceCapabilities capabilities; RenderInterfaceCapabilities capabilities;
# if SDL_VULKAN_ENABLED
VulkanInterface(RenderWindow sdlWindow);
# else
VulkanInterface(); VulkanInterface();
# endif
~VulkanInterface() override; ~VulkanInterface() override;
std::unique_ptr<RenderDevice> createDevice() override; std::unique_ptr<RenderDevice> createDevice() override;
const RenderInterfaceCapabilities &getCapabilities() const override; const RenderInterfaceCapabilities &getCapabilities() const override;

View file

@ -83,7 +83,11 @@ namespace plume
#ifdef SWA_D3D12 #ifdef SWA_D3D12
extern std::unique_ptr<RenderInterface> CreateD3D12Interface(); extern std::unique_ptr<RenderInterface> CreateD3D12Interface();
#endif #endif
#ifdef SDL_VULKAN_ENABLED
extern std::unique_ptr<RenderInterface> CreateVulkanInterface(RenderWindow sdlWindow);
#else
extern std::unique_ptr<RenderInterface> CreateVulkanInterface(); extern std::unique_ptr<RenderInterface> CreateVulkanInterface();
#endif
} }
#pragma pack(push, 1) #pragma pack(push, 1)
@ -1306,7 +1310,7 @@ static void CreateImGuiBackend()
static void BeginCommandList(); static void BeginCommandList();
void Video::CreateHostDevice() void Video::CreateHostDevice(bool sdlVideoDefault)
{ {
for (uint32_t i = 0; i < 16; i++) for (uint32_t i = 0; i < 16; i++)
g_inputSlots[i].index = i; g_inputSlots[i].index = i;
@ -1314,7 +1318,7 @@ void Video::CreateHostDevice()
IMGUI_CHECKVERSION(); IMGUI_CHECKVERSION();
ImGui::CreateContext(); ImGui::CreateContext();
GameWindow::Init(); GameWindow::Init(sdlVideoDefault);
#ifdef SWA_D3D12 #ifdef SWA_D3D12
g_vulkan = DetectWine() || Config::GraphicsAPI == EGraphicsAPI::Vulkan; g_vulkan = DetectWine() || Config::GraphicsAPI == EGraphicsAPI::Vulkan;
@ -1322,11 +1326,16 @@ void Video::CreateHostDevice()
LoadEmbeddedResources(); LoadEmbeddedResources();
#ifdef SWA_D3D12 if (g_vulkan)
g_interface = g_vulkan ? CreateVulkanInterface() : CreateD3D12Interface(); #ifdef SDL_VULKAN_ENABLED
g_interface = CreateVulkanInterface(GameWindow::s_renderWindow);
#else #else
g_interface = CreateVulkanInterface(); g_interface = CreateVulkanInterface();
#endif #endif
#ifdef SWA_D3D12
else
g_interface = CreateD3D12Interface();
#endif
g_device = g_interface->createDevice(); g_device = g_interface->createDevice();

View file

@ -14,7 +14,7 @@ using namespace plume;
struct Video struct Video
{ {
static void CreateHostDevice(); static void CreateHostDevice(bool sdlVideoDefault);
static void HostPresent(); static void HostPresent();
static void StartPipelinePrecompilation(); static void StartPipelinePrecompilation();
static void WaitForGPU(); static void WaitForGPU();

View file

@ -145,10 +145,12 @@ int main(int argc, char *argv[])
bool forceInstaller = false; bool forceInstaller = false;
bool forceDLCInstaller = false; bool forceDLCInstaller = false;
bool sdlVideoDefault = false;
for (uint32_t i = 1; i < argc; i++) for (uint32_t i = 1; i < argc; i++)
{ {
forceInstaller = forceInstaller || (strcmp(argv[i], "--install") == 0); forceInstaller = forceInstaller || (strcmp(argv[i], "--install") == 0);
forceDLCInstaller = forceDLCInstaller || (strcmp(argv[i], "--install-dlc") == 0); forceDLCInstaller = forceDLCInstaller || (strcmp(argv[i], "--install-dlc") == 0);
sdlVideoDefault = sdlVideoDefault || (strcmp(argv[i], "--sdl-video-default") == 0);
} }
Config::Load(); Config::Load();
@ -159,7 +161,7 @@ int main(int argc, char *argv[])
bool runInstallerWizard = forceInstaller || forceDLCInstaller || !isGameInstalled; bool runInstallerWizard = forceInstaller || forceDLCInstaller || !isGameInstalled;
if (runInstallerWizard) if (runInstallerWizard)
{ {
Video::CreateHostDevice(); Video::CreateHostDevice(sdlVideoDefault);
if (!InstallerWizard::Run(GAME_INSTALL_DIRECTORY, isGameInstalled && forceDLCInstaller)) if (!InstallerWizard::Run(GAME_INSTALL_DIRECTORY, isGameInstalled && forceDLCInstaller))
{ {
@ -175,7 +177,7 @@ int main(int argc, char *argv[])
uint32_t entry = LdrLoadModule(std::u8string_view((const char8_t*)(modulePath))); uint32_t entry = LdrLoadModule(std::u8string_view((const char8_t*)(modulePath)));
if (!runInstallerWizard) if (!runInstallerWizard)
Video::CreateHostDevice(); Video::CreateHostDevice(sdlVideoDefault);
Video::StartPipelinePrecompilation(); Video::StartPipelinePrecompilation();

View file

@ -147,9 +147,26 @@ int Window_OnSDLEvent(void*, SDL_Event* event)
return 0; return 0;
} }
void GameWindow::Init() void GameWindow::Init(bool sdlVideoDefault)
{ {
SDL_InitSubSystem(SDL_INIT_VIDEO); #ifdef __linux__
if (!sdlVideoDefault)
{
int videoRes = SDL_VideoInit("wayland");
if (videoRes != 0)
SDL_VideoInit(nullptr);
}
#else
else
{
SDL_VideoInit(nullptr);
}
#endif
const char* videoDriverName = SDL_GetCurrentVideoDriver();
if (videoDriverName != nullptr)
fmt::println("SDL Video Driver: {}", videoDriverName);
SDL_EventState(SDL_SYSWMEVENT, SDL_ENABLE); SDL_EventState(SDL_SYSWMEVENT, SDL_ENABLE);
SDL_AddEventWatch(Window_OnSDLEvent, s_pWindow); SDL_AddEventWatch(Window_OnSDLEvent, s_pWindow);
#ifdef _WIN32 #ifdef _WIN32
@ -185,6 +202,8 @@ void GameWindow::Init()
#if defined(_WIN32) #if defined(_WIN32)
s_renderWindow = info.info.win.window; s_renderWindow = info.info.win.window;
SetDarkTitleBar(true); SetDarkTitleBar(true);
#elif defined(SDL_VULKAN_ENABLED)
s_renderWindow = s_pWindow;
#elif defined(__linux__) #elif defined(__linux__)
s_renderWindow = { info.info.x11.display, info.info.x11.window }; s_renderWindow = { info.info.x11.display, info.info.x11.window };
#else #else

View file

@ -199,6 +199,10 @@ public:
if (Config::Fullscreen) if (Config::Fullscreen)
flags |= SDL_WINDOW_FULLSCREEN_DESKTOP; flags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
#ifdef SDL_VULKAN_ENABLED
flags |= SDL_WINDOW_VULKAN;
#endif
return flags; return flags;
} }
@ -299,6 +303,6 @@ public:
return false; return false;
} }
static void Init(); static void Init(bool sdlVideoDefault);
static void Update(); static void Update();
}; };