Wayland support. (#55)

This commit is contained in:
Darío 2024-12-19 20:29:18 -03:00 committed by GitHub
parent bacfe02d0e
commit 68343a574c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
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)
endif()
if (CMAKE_SYSTEM_NAME MATCHES "Linux")
target_compile_definitions(UnleashedRecomp PRIVATE SDL_VULKAN_ENABLED)
endif()
find_package(directx-dxc REQUIRED)
if (SWA_D3D12)

View file

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

View file

@ -1989,6 +1989,13 @@ namespace plume {
fprintf(stderr, "vkCreateWin32SurfaceKHR failed with error code 0x%X.\n", res);
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__)
assert(renderWindow != nullptr);
VkAndroidSurfaceCreateInfoKHR surfaceCreateInfo = {};
@ -2312,6 +2319,8 @@ namespace plume {
GetClientRect(renderWindow, &rect);
dstWidth = rect.right - rect.left;
dstHeight = rect.bottom - rect.top;
# elif defined(SDL_VULKAN_ENABLED)
SDL_GetWindowSize(renderWindow, (int *)(&dstWidth), (int *)(&dstHeight));
# elif defined(__ANDROID__)
dstWidth = ANativeWindow_getWidth(renderWindow);
dstHeight = ANativeWindow_getHeight(renderWindow);
@ -4073,7 +4082,11 @@ namespace plume {
// VulkanInterface
#if SDL_VULKAN_ENABLED
VulkanInterface::VulkanInterface(RenderWindow sdlWindow) {
#else
VulkanInterface::VulkanInterface() {
#endif
VkResult res = volkInitialize();
if (res != VK_SUCCESS) {
fprintf(stderr, "volkInitialize failed with error code 0x%X.\n", res);
@ -4100,11 +4113,31 @@ namespace plume {
std::vector<VkExtensionProperties> availableExtensions(extensionCount);
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;
# if DLSS_ENABLED
const std::unordered_set<std::string> dlssExtensions = DLSS::getRequiredInstanceExtensionsVulkan();
# 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++) {
const std::string extensionName(availableExtensions[i].extensionName);
missingRequiredExtensions.erase(extensionName);
@ -4129,7 +4162,7 @@ namespace plume {
}
std::vector<const char *> enabledExtensions;
for (const std::string &extension : RequiredInstanceExtensions) {
for (const std::string &extension : requiredExtensions) {
enabledExtensions.push_back(extension.c_str());
}
@ -4192,8 +4225,15 @@ namespace plume {
// 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<VulkanInterface> createdInterface = std::make_unique<VulkanInterface>();
return createdInterface->isValid() ? std::move(createdInterface) : nullptr;
}
#endif
};

View file

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

View file

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

View file

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

View file

@ -145,10 +145,12 @@ int main(int argc, char *argv[])
bool forceInstaller = false;
bool forceDLCInstaller = false;
bool sdlVideoDefault = false;
for (uint32_t i = 1; i < argc; i++)
{
forceInstaller = forceInstaller || (strcmp(argv[i], "--install") == 0);
forceDLCInstaller = forceDLCInstaller || (strcmp(argv[i], "--install-dlc") == 0);
sdlVideoDefault = sdlVideoDefault || (strcmp(argv[i], "--sdl-video-default") == 0);
}
Config::Load();
@ -159,7 +161,7 @@ int main(int argc, char *argv[])
bool runInstallerWizard = forceInstaller || forceDLCInstaller || !isGameInstalled;
if (runInstallerWizard)
{
Video::CreateHostDevice();
Video::CreateHostDevice(sdlVideoDefault);
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)));
if (!runInstallerWizard)
Video::CreateHostDevice();
Video::CreateHostDevice(sdlVideoDefault);
Video::StartPipelinePrecompilation();

View file

@ -147,9 +147,26 @@ int Window_OnSDLEvent(void*, SDL_Event* event)
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_AddEventWatch(Window_OnSDLEvent, s_pWindow);
#ifdef _WIN32
@ -185,6 +202,8 @@ void GameWindow::Init()
#if defined(_WIN32)
s_renderWindow = info.info.win.window;
SetDarkTitleBar(true);
#elif defined(SDL_VULKAN_ENABLED)
s_renderWindow = s_pWindow;
#elif defined(__linux__)
s_renderWindow = { info.info.x11.display, info.info.x11.window };
#else

View file

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