From ea387b2a48a95be31a07f907fb3adf86c46f47a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 13 Dec 2017 22:58:45 +0100 Subject: [PATCH 1/5] WIP vulkan on linux stuff --- CMakeLists.txt | 24 ++- Common/Vulkan/VulkanContext.cpp | 34 +++++ Common/Vulkan/VulkanContext.h | 13 +- Common/Vulkan/VulkanLoader.cpp | 6 +- Common/Vulkan/VulkanLoader.h | 2 + SDL/SDLMain.cpp | 255 ++++++++++++++++++++++++-------- UI/GameSettingsScreen.cpp | 3 +- assets/lang | 2 +- ext/native/thin3d/DataFormat.h | 1 + 9 files changed, 266 insertions(+), 74 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b11630d109..cc7190270e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,12 +13,6 @@ list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/Modules) add_definitions(-D__STDC_CONSTANT_MACROS) -# Of the CMake platforms, we only support Vulkan on Android and Windows. -if(ANDROID OR WIN32) - set(VULKAN ON) -else() - add_definitions(-DNO_VULKAN) -endif() if(${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang") set(CLANG ON) @@ -72,7 +66,14 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") endif() if(${CMAKE_SYSTEM_NAME} MATCHES "Android") - set(ANDROID ON) + set(ANDROID ON) +endif() + +# Of the CMake platforms, we only support Vulkan on Android and Windows. +if(ANDROID OR WIN32 OR LINUX) + set(VULKAN ON) +else() + add_definitions(-DNO_VULKAN) endif() if(NOT DEFINED HEADLESS) @@ -86,6 +87,11 @@ else() message("Normal Build") endif() +if(LINUX) + message("Using direct to display extension...") + add_definitions(-DVK_USE_PLATFORM_XLIB_KHR) +endif() + # Doesn't link on some platforms #if(NOT DEFINED UNITTEST) # set(UNITTEST OFF) @@ -113,6 +119,10 @@ option(SIMULATOR "Set to ON when targeting an x86 simulator of an ARM platform" option(USE_FFMPEG "Build with FFMPEG support" ${USE_FFMPEG}) option(USE_SYSTEM_FFMPEG "Dynamically link against system FFMPEG" ${USE_SYSTEM_FFMPEG}) +# Vulkan on Linux options. If none of these are set, X11 is assumed. +OPTION(USE_D2D_WSI "Build the project using Direct to Display swapchain" OFF) +OPTION(USE_WAYLAND_WSI "Build the project using Wayland swapchain" OFF) + if(ANDROID) set(CoreLibName ppsspp_jni) set(CoreLinkType SHARED) diff --git a/Common/Vulkan/VulkanContext.cpp b/Common/Vulkan/VulkanContext.cpp index 02d0282946..0c0b0471d2 100644 --- a/Common/Vulkan/VulkanContext.cpp +++ b/Common/Vulkan/VulkanContext.cpp @@ -109,6 +109,14 @@ VkResult VulkanContext::CreateInstance(const CreateInfo &info) { instance_extensions_enabled_.push_back(VK_KHR_WIN32_SURFACE_EXTENSION_NAME); #elif defined(__ANDROID__) instance_extensions_enabled_.push_back(VK_KHR_ANDROID_SURFACE_EXTENSION_NAME); +#elif defined(VK_USE_PLATFORM_XLIB_KHR) + instance_extensions_enabled_.push_back(VK_KHR_XLIB_SURFACE_EXTENSION_NAME); +#elif defined(VK_USE_PLATFORM_XCB_KHR) + instance_extensions_enabled_.push_back(VK_KHR_XCB_SURFACE_EXTENSION_NAME); +#elif defined(VK_USE_PLATFORM_WAYLAND_KHR) + instance_extensions.enabled_.push_back(VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME); +#else + //... #endif if (flags_ & VULKAN_FLAG_VALIDATE) { @@ -631,6 +639,32 @@ void VulkanContext::ReinitSurface(int width, int height) { break; } #endif +#if defined(VK_USE_PLATFORM_XLIB_KHR) + case WINDOWSYSTEM_XLIB: + { + VkXlibSurfaceCreateInfoKHR xlib = { VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR }; + xlib.flags = 0; + xlib.dpy = (Display *)winsysData1_; + xlib.window = (Window)winsysData2_; + VkResult res = vkCreateXlibSurfaceKHR(instance_, &xlib, nullptr, &surface_); + assert(res == VK_SUCCESS); + break; + } + +#endif +#if defined(VK_USE_PLATFORM_XCB_KHR) + case WINDOWSYSTEM_XCB: + { + VkXCBSurfaceCreateInfoKHR xcb = { VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR }; + xcb.flags = 0; + xcb.connection = (Connection *)winsysData1_; + xcb.window = (Window)(uintptr_t)winsysData2_; + VkResult res = vkCreateXcbSurfaceKHR(instance_, &xcb, nullptr, &surface_); + assert(res == VK_SUCCESS); + break; + } +#endif + default: _assert_msg_(G3D, false, "Vulkan support for chosen window system not implemented"); break; diff --git a/Common/Vulkan/VulkanContext.h b/Common/Vulkan/VulkanContext.h index 0fee12770a..0c60a3bef2 100644 --- a/Common/Vulkan/VulkanContext.h +++ b/Common/Vulkan/VulkanContext.h @@ -37,6 +37,12 @@ enum WindowSystem { #ifdef __ANDROID__ WINDOWSYSTEM_ANDROID, #endif +#ifdef VK_USE_PLATFORM_XLIB_KHR + WINDOWSYSTEM_XLIB, +#endif +#ifdef VK_USE_PLATFORM_XCB_KHR + WINDOWSYSTEM_XCB, +#endif }; struct VulkanPhysicalDeviceInfo { @@ -127,6 +133,7 @@ public: // The parameters are whatever the chosen window system wants. void InitSurface(WindowSystem winsys, void *data1, void *data2, int width = -1, int height = -1); void ReinitSurface(int width = -1, int height = -1); + bool InitQueue(); bool InitObjects(); bool InitSwapchain(); @@ -238,16 +245,16 @@ private: std::string init_error_; std::vector instance_layer_names_; std::vector instance_layer_properties_; - + std::vector instance_extensions_enabled_; std::vector instance_extension_properties_; std::vector device_layer_names_; std::vector device_layer_properties_; - + std::vector device_extensions_enabled_; std::vector device_extension_properties_; - + std::vector physical_devices_; int physical_device_ = -1; diff --git a/Common/Vulkan/VulkanLoader.cpp b/Common/Vulkan/VulkanLoader.cpp index 7b8e83c91f..61d613966f 100644 --- a/Common/Vulkan/VulkanLoader.cpp +++ b/Common/Vulkan/VulkanLoader.cpp @@ -165,6 +165,8 @@ PFN_vkCmdExecuteCommands vkCmdExecuteCommands; PFN_vkCreateAndroidSurfaceKHR vkCreateAndroidSurfaceKHR; #elif defined(_WIN32) PFN_vkCreateWin32SurfaceKHR vkCreateWin32SurfaceKHR; +#elif defined(VK_USE_PLATFORM_XLIB_KHR) +PFN_vkCreateXlibSurfaceKHR vkCreateXlibSurfaceKHR; #endif PFN_vkDestroySurfaceKHR vkDestroySurfaceKHR; @@ -374,7 +376,7 @@ void VulkanLoadInstanceFunctions(VkInstance instance) { LOAD_INSTANCE_FUNC(instance, vkCmdNextSubpass); LOAD_INSTANCE_FUNC(instance, vkCmdEndRenderPass); LOAD_INSTANCE_FUNC(instance, vkCmdExecuteCommands); - + LOAD_INSTANCE_FUNC(instance, vkGetPhysicalDeviceSurfaceSupportKHR); LOAD_INSTANCE_FUNC(instance, vkGetPhysicalDeviceSurfaceCapabilitiesKHR); LOAD_INSTANCE_FUNC(instance, vkGetPhysicalDeviceSurfaceFormatsKHR); @@ -390,6 +392,8 @@ void VulkanLoadInstanceFunctions(VkInstance instance) { LOAD_INSTANCE_FUNC(instance, vkCreateWin32SurfaceKHR); #elif defined(__ANDROID__) LOAD_INSTANCE_FUNC(instance, vkCreateAndroidSurfaceKHR); +#elif defined(VK_USE_PLATFORM_XLIB_KHR) + LOAD_INSTANCE_FUNC(instance, vkCreateXlibSurfaceKHR); #endif LOAD_INSTANCE_FUNC(instance, vkDestroySurfaceKHR); diff --git a/Common/Vulkan/VulkanLoader.h b/Common/Vulkan/VulkanLoader.h index 67042c0c0c..18ab75555f 100644 --- a/Common/Vulkan/VulkanLoader.h +++ b/Common/Vulkan/VulkanLoader.h @@ -171,6 +171,8 @@ extern PFN_vkCmdExecuteCommands vkCmdExecuteCommands; extern PFN_vkCreateAndroidSurfaceKHR vkCreateAndroidSurfaceKHR; #elif defined(_WIN32) extern PFN_vkCreateWin32SurfaceKHR vkCreateWin32SurfaceKHR; +#elif defined(VK_USE_PLATFORM_XLIB_KHR) +extern PFN_vkCreateXlibSurfaceKHR vkCreateXlibSurfaceKHR; #endif extern PFN_vkDestroySurfaceKHR vkDestroySurfaceKHR; diff --git a/SDL/SDLMain.cpp b/SDL/SDLMain.cpp index 660663037f..2f9f4aefff 100644 --- a/SDL/SDLMain.cpp +++ b/SDL/SDLMain.cpp @@ -41,28 +41,156 @@ SDLJoystick *joystick = NULL; #include "base/NKCodeFromSDL.h" #include "util/const_map.h" #include "util/text/utf8.h" +#include "util/text/parsers.h" #include "math/math_util.h" +#include "Common/Vulkan/VulkanContext.h" +#include "Common/Vulkan/VulkanDebug.h" + +#if !defined(USING_FBDEV) +#include +#include +#include "SDL_syswm.h" +#endif #include "Core/System.h" #include "Core/Core.h" #include "Core/Config.h" #include "Common/GraphicsContext.h" -class GLDummyGraphicsContext : public DummyGraphicsContext { +class SDLGLGraphicsContext : public DummyGraphicsContext { public: - GLDummyGraphicsContext() { + SDLGLGraphicsContext() { CheckGLExtensions(); draw_ = Draw::T3DCreateGLContext(); bool success = draw_->CreatePresets(); assert(success); } - ~GLDummyGraphicsContext() { delete draw_; } + ~SDLGLGraphicsContext() { + delete draw_; + } + + void Shutdown() override { + } + + Draw::DrawContext *GetDrawContext() override { + return draw_; + } + +private: + Draw::DrawContext *draw_ = nullptr; +}; + +static VulkanLogOptions g_LogOptions; + +class SDLVulkanGraphicsContext : public GraphicsContext { +public: + SDLVulkanGraphicsContext() {} + ~SDLVulkanGraphicsContext() { + delete draw_; + } + + bool Init(SDL_Window *sdl_window, std::string *error_message) { + SDL_SysWMinfo sys_info; + SDL_VERSION(&sys_info.version); //Set SDL version + SDL_GetWindowWMInfo(sdl_window, &sys_info); + + Display *display = sys_info.info.x11.display; + Window window = sys_info.info.x11.window; + + init_glslang(); + + g_LogOptions.breakOnError = true; + g_LogOptions.breakOnWarning = true; + g_LogOptions.msgBoxOnError = false; + + Version gitVer(PPSSPP_GIT_VERSION); + + vulkan_ = new VulkanContext(); + if (vulkan_->InitError().size()) { + *error_message = vulkan_->InitError(); + delete vulkan_; + vulkan_ = nullptr; + return false; + } + + int vulkanFlags = VULKAN_FLAG_PRESENT_MAILBOX; + // vulkanFlags |= VULKAN_FLAG_VALIDATE; + VulkanContext::CreateInfo info{}; + info.app_name = "PPSSPP"; + info.app_ver = gitVer.ToInteger(); + info.flags = VULKAN_FLAG_PRESENT_MAILBOX; + if (VK_SUCCESS != vulkan_->CreateInstance(info)) { + *error_message = vulkan_->InitError(); + delete vulkan_; + vulkan_ = nullptr; + return false; + } + vulkan_->ChooseDevice(vulkan_->GetBestPhysicalDevice()); + if (vulkan_->CreateDevice() != VK_SUCCESS) { + *error_message = vulkan_->InitError(); + delete vulkan_; + vulkan_ = nullptr; + return false; + } + + vulkan_->InitSurface(WINDOWSYSTEM_XLIB, (void *)display, (void *)(intptr_t)window, pixel_xres, pixel_yres); + + if (!vulkan_->InitObjects()) { + *error_message = vulkan_->InitError(); + Shutdown(); + return false; + } + + draw_ = Draw::T3DCreateVulkanContext(vulkan_, false); + bool success = draw_->CreatePresets(); + assert(success); + draw_->HandleEvent(Draw::Event::GOT_BACKBUFFER, vulkan_->GetBackbufferWidth(), vulkan_->GetBackbufferHeight()); + + return true; + } + + void Shutdown() override { + if (draw_) + draw_->HandleEvent(Draw::Event::LOST_BACKBUFFER, vulkan_->GetBackbufferWidth(), vulkan_->GetBackbufferHeight()); + delete draw_; + draw_ = nullptr; + vulkan_->WaitUntilQueueIdle(); + vulkan_->DestroyObjects(); + vulkan_->DestroyDevice(); + vulkan_->DestroyDebugMsgCallback(); + vulkan_->DestroyInstance(); + delete vulkan_; + vulkan_ = nullptr; + finalize_glslang(); + } + + void SwapBuffers() override { + // We don't do it this way. + } + + void Resize() override { + draw_->HandleEvent(Draw::Event::LOST_BACKBUFFER, vulkan_->GetBackbufferWidth(), vulkan_->GetBackbufferHeight()); + vulkan_->DestroyObjects(); + // TODO: Take from real window dimensions + int width = 1024; + int height = 768; + vulkan_->ReinitSurface(width, height); + vulkan_->InitObjects(); + draw_->HandleEvent(Draw::Event::GOT_BACKBUFFER, vulkan_->GetBackbufferWidth(), vulkan_->GetBackbufferHeight()); + } + + void SwapInterval(int interval) override { + } + void *GetAPIContext() override { + return vulkan_; + } Draw::DrawContext *GetDrawContext() override { return draw_; } private: - Draw::DrawContext *draw_; + Draw::DrawContext *draw_ = nullptr; + VulkanContext *vulkan_ = nullptr; }; GlobalUIState lastUIState = UISTATE_MENU; @@ -79,11 +207,6 @@ static int g_DesktopHeight = 0; #if defined(USING_EGL) #include "EGL/egl.h" -#if !defined(USING_FBDEV) -#include -#include -#endif - #include "SDL_syswm.h" #include "math.h" @@ -419,12 +542,54 @@ void ToggleFullScreenIfFlagSet() { #undef main #endif int main(int argc, char *argv[]) { + glslang::InitializeProcess(); + #if PPSSPP_PLATFORM(RPI) bcm_host_init(); #endif putenv((char*)"SDL_VIDEO_CENTERED=1"); SDL_SetHint(SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS, "0"); + int set_xres = -1; + int set_yres = -1; + bool portrait = false; + bool set_ipad = false; + float set_dpi = 1.0f; + float set_scale = 1.0f; + + // Produce a new set of arguments with the ones we skip. + int remain_argc = 1; + const char *remain_argv[256] = { argv[0] }; + + Uint32 mode = 0; + for (int i = 1; i < argc; i++) { + if (!strcmp(argv[i],"--fullscreen")) + mode |= SDL_WINDOW_FULLSCREEN_DESKTOP; + else if (set_xres == -2) + set_xres = parseInt(argv[i]); + else if (set_yres == -2) + set_yres = parseInt(argv[i]); + else if (set_dpi == -2) + set_dpi = parseFloat(argv[i]); + else if (set_scale == -2) + set_scale = parseFloat(argv[i]); + else if (!strcmp(argv[i],"--xres")) + set_xres = -2; + else if (!strcmp(argv[i],"--yres")) + set_yres = -2; + else if (!strcmp(argv[i],"--dpi")) + set_dpi = -2; + else if (!strcmp(argv[i],"--scale")) + set_scale = -2; + else if (!strcmp(argv[i],"--ipad")) + set_ipad = true; + else if (!strcmp(argv[i],"--portrait")) + portrait = true; + else { + remain_argv[remain_argc++] = argv[i]; + } + } + std::string app_name; std::string app_name_nice; std::string version; @@ -464,50 +629,11 @@ int main(int argc, char *argv[]) { SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); SDL_GL_SetSwapInterval(1); - Uint32 mode; #ifdef USING_GLES2 - mode = SDL_WINDOW_OPENGL | SDL_WINDOW_FULLSCREEN; + mode |= SDL_WINDOW_OPENGL | SDL_WINDOW_FULLSCREEN; #else - mode = SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE; + mode |= SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE; #endif - int set_xres = -1; - int set_yres = -1; - bool portrait = false; - bool set_ipad = false; - float set_dpi = 1.0f; - float set_scale = 1.0f; - - // Produce a new set of arguments with the ones we skip. - int remain_argc = 1; - const char *remain_argv[256] = { argv[0] }; - - for (int i = 1; i < argc; i++) { - if (!strcmp(argv[i],"--fullscreen")) - mode |= SDL_WINDOW_FULLSCREEN_DESKTOP; - else if (set_xres == -2) - set_xres = parseInt(argv[i]); - else if (set_yres == -2) - set_yres = parseInt(argv[i]); - else if (set_dpi == -2) - set_dpi = parseFloat(argv[i]); - else if (set_scale == -2) - set_scale = parseFloat(argv[i]); - else if (!strcmp(argv[i],"--xres")) - set_xres = -2; - else if (!strcmp(argv[i],"--yres")) - set_yres = -2; - else if (!strcmp(argv[i],"--dpi")) - set_dpi = -2; - else if (!strcmp(argv[i],"--scale")) - set_scale = -2; - else if (!strcmp(argv[i],"--ipad")) - set_ipad = true; - else if (!strcmp(argv[i],"--portrait")) - portrait = true; - else { - remain_argv[remain_argc++] = argv[i]; - } - } // Is resolution is too low to run windowed if (g_DesktopWidth < 480 * 2 && g_DesktopHeight < 272 * 2) { @@ -695,9 +821,21 @@ int main(int argc, char *argv[]) { printf("Pixels: %i x %i\n", pixel_xres, pixel_yres); printf("Virtual pixels: %i x %i\n", dp_xres, dp_yres); - glslang::InitializeProcess(); - - GraphicsContext *graphicsContext = new GLDummyGraphicsContext(); + GraphicsContext *graphicsContext; + if (g_Config.iGPUBackend == GPU_BACKEND_OPENGL) { + graphicsContext = new SDLGLGraphicsContext(); + } else if (g_Config.iGPUBackend == GPU_BACKEND_VULKAN) { + SDLVulkanGraphicsContext *ctx = new SDLVulkanGraphicsContext(); + std::string error_message; + if (!ctx->Init(g_Screen, &error_message)) { + printf("Vulkan init error '%s' - falling back to GL\n", error_message.c_str()); + g_Config.iGPUBackend = GPU_BACKEND_OPENGL; + delete ctx; + graphicsContext = new SDLGLGraphicsContext(); + } else { + graphicsContext = ctx; + } + } NativeInitGraphics(graphicsContext); NativeResized(); @@ -946,26 +1084,21 @@ int main(int argc, char *argv[]) { delete joystick; #endif NativeShutdownGraphics(); + SDL_GL_DeleteContext(glContext); graphicsContext->Shutdown(); NativeShutdown(); delete graphicsContext; - glslang::FinalizeProcess(); - // Faster exit, thanks to the OS. Remove this if you want to debug shutdown - // The speed difference is only really noticable on Linux. On Windows you do notice it though -#ifndef MOBILE_DEVICE - exit(0); -#endif + SDL_PauseAudio(1); SDL_CloseAudio(); #ifdef USING_EGL EGL_Close(); #endif - SDL_GL_DeleteContext(glContext); SDL_Quit(); #if PPSSPP_PLATFORM(RPI) bcm_host_deinit(); #endif - exit(0); + glslang::FinalizeProcess(); return 0; } diff --git a/UI/GameSettingsScreen.cpp b/UI/GameSettingsScreen.cpp index 9a8dea5b6a..c3dfcd193d 100644 --- a/UI/GameSettingsScreen.cpp +++ b/UI/GameSettingsScreen.cpp @@ -48,7 +48,6 @@ #include "Common/KeyMap.h" #include "Common/FileUtil.h" #include "Common/OSVersion.h" -#include "Common/Vulkan/VulkanLoader.h" #include "Core/Config.h" #include "Core/Host.h" #include "Core/System.h" @@ -73,6 +72,8 @@ extern bool iosCanUseJit; extern bool targetIsJailbroken; #endif +extern bool VulkanMayBeAvailable(); + GameSettingsScreen::GameSettingsScreen(std::string gamePath, std::string gameID, bool editThenRestore) : UIDialogScreenWithGameBackground(gamePath), gameID_(gameID), enableReports_(false), editThenRestore_(editThenRestore) { lastVertical_ = UseVerticalLayout(); diff --git a/assets/lang b/assets/lang index 6537fc1bf3..1e3e4a0ba0 160000 --- a/assets/lang +++ b/assets/lang @@ -1 +1 @@ -Subproject commit 6537fc1bf38d0787a1d86375e5b3cb267349d2d5 +Subproject commit 1e3e4a0ba0ca8c0a092e027dfb7c1c4778366db5 diff --git a/ext/native/thin3d/DataFormat.h b/ext/native/thin3d/DataFormat.h index 22cd4d3c07..467f9e4a00 100644 --- a/ext/native/thin3d/DataFormat.h +++ b/ext/native/thin3d/DataFormat.h @@ -1,6 +1,7 @@ #pragma once #include +#include namespace Draw { From 6d6ad3ed146b2f65dd0ce0144e82fa3b8e2fd97e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 13 Dec 2017 23:22:21 +0100 Subject: [PATCH 2/5] Cleanups in PCMain.cpp --- SDL/SDLMain.cpp | 94 +++++++++++++++++-------------------------------- 1 file changed, 32 insertions(+), 62 deletions(-) diff --git a/SDL/SDLMain.cpp b/SDL/SDLMain.cpp index 2f9f4aefff..d75581368c 100644 --- a/SDL/SDLMain.cpp +++ b/SDL/SDLMain.cpp @@ -3,24 +3,12 @@ // Note: SDL1.2 implementation is deprecated and will soon be replaced by SDL2.0. // If your platform is not supported, it is suggested to use Qt instead. -#ifdef _WIN32 -#pragma warning(disable:4091) // workaround bug in VS2015 headers - -#define WIN32_LEAN_AND_MEAN -#include -#include -#include -#include -#else #include #include -#endif #include "SDL.h" -#ifndef _WIN32 #include "SDL/SDLJoystick.h" SDLJoystick *joystick = NULL; -#endif #if PPSSPP_PLATFORM(RPI) #include @@ -28,6 +16,7 @@ SDLJoystick *joystick = NULL; #include #include +#include #include "base/display.h" #include "base/logging.h" @@ -45,8 +34,9 @@ SDLJoystick *joystick = NULL; #include "math/math_util.h" #include "Common/Vulkan/VulkanContext.h" #include "Common/Vulkan/VulkanDebug.h" +#include "math.h" -#if !defined(USING_FBDEV) +#if defined(VK_USE_PLATFORM_XLIB_KHR) #include #include #include "SDL_syswm.h" @@ -59,7 +49,7 @@ SDLJoystick *joystick = NULL; class SDLGLGraphicsContext : public DummyGraphicsContext { public: - SDLGLGraphicsContext() { + SDLGLGraphicsContext(SDL_Window *window) : window_(window) { CheckGLExtensions(); draw_ = Draw::T3DCreateGLContext(); bool success = draw_->CreatePresets(); @@ -72,12 +62,21 @@ public: void Shutdown() override { } + void SwapBuffers() override { +#ifdef USING_EGL + eglSwapBuffers(g_eglDisplay, g_eglSurface); +#else + SDL_GL_SwapWindow(window_); +#endif + } + Draw::DrawContext *GetDrawContext() override { return draw_; } private: Draw::DrawContext *draw_ = nullptr; + SDL_Window *window_; }; static VulkanLogOptions g_LogOptions; @@ -196,7 +195,6 @@ private: GlobalUIState lastUIState = UISTATE_MENU; GlobalUIState GetUIState(); -static SDL_Window* g_Screen = NULL; static bool g_ToggleFullScreenNextFrame = false; static int g_ToggleFullScreenType; static int g_QuitRequested = 0; @@ -207,9 +205,6 @@ static int g_DesktopHeight = 0; #if defined(USING_EGL) #include "EGL/egl.h" -#include "SDL_syswm.h" -#include "math.h" - static EGLDisplay g_eglDisplay = NULL; static EGLContext g_eglContext = NULL; static EGLSurface g_eglSurface = NULL; @@ -522,11 +517,11 @@ static float parseFloat(const char *str) { } } -void ToggleFullScreenIfFlagSet() { +void ToggleFullScreenIfFlagSet(SDL_Window *window) { if (g_ToggleFullScreenNextFrame) { g_ToggleFullScreenNextFrame = false; - Uint32 window_flags = SDL_GetWindowFlags(g_Screen); + Uint32 window_flags = SDL_GetWindowFlags(window); if (g_ToggleFullScreenType == -1) { window_flags ^= SDL_WINDOW_FULLSCREEN_DESKTOP; } else if (g_ToggleFullScreenType == 1) { @@ -534,7 +529,7 @@ void ToggleFullScreenIfFlagSet() { } else { window_flags &= ~SDL_WINDOW_FULLSCREEN_DESKTOP; } - SDL_SetWindowFullscreen(g_Screen, window_flags); + SDL_SetWindowFullscreen(window, window_flags); } } @@ -678,12 +673,6 @@ int main(int argc, char *argv[]) { dp_xres = (float)pixel_xres * dpi_scale; dp_yres = (float)pixel_yres * dpi_scale; -#ifdef _MSC_VER - // VFSRegister("temp/", new DirectoryAssetReader("E:\\Temp\\")); - TCHAR path[MAX_PATH]; - SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, 0, path); - PathAppend(path, (app_name + "\\").c_str()); -#else // Mac / Linux char path[2048]; const char *the_path = getenv("HOME"); @@ -695,13 +684,8 @@ int main(int argc, char *argv[]) { strcpy(path, the_path); if (path[strlen(path)-1] != '/') strcat(path, "/"); -#endif -#ifdef _WIN32 - NativeInit(remain_argc, (const char **)remain_argv, path, "D:\\", nullptr); -#else NativeInit(remain_argc, (const char **)remain_argv, path, "/tmp", nullptr); -#endif // Use the setting from the config when initing the window. if (g_Config.bFullScreen) @@ -723,6 +707,7 @@ int main(int argc, char *argv[]) { #endif }; + SDL_Window *window = nullptr; SDL_GLContext glContext = nullptr; for (size_t i = 0; i < ARRAY_SIZE(attemptVersions); ++i) { const auto &ver = attemptVersions[i]; @@ -738,13 +723,14 @@ int main(int argc, char *argv[]) { SetGLCoreContext(true); #endif - g_Screen = SDL_CreateWindow(app_name_nice.c_str(), x,y, pixel_xres, pixel_yres, mode); - if (g_Screen == nullptr) { + window = SDL_CreateWindow(app_name_nice.c_str(), x,y, pixel_xres, pixel_yres, mode); + if (!window) { + NativeShutdown(); fprintf(stderr, "SDL_CreateWindow failed: %s\n", SDL_GetError()); continue; } - glContext = SDL_GL_CreateContext(g_Screen); + glContext = SDL_GL_CreateContext(window); if (glContext != nullptr) { // Victory, got one. break; @@ -752,7 +738,7 @@ int main(int argc, char *argv[]) { // Let's keep trying. To be safe, destroy the window - docs say needed to change profile. // in practice, it doesn't seem to matter, but maybe it differs by platform. - SDL_DestroyWindow(g_Screen); + SDL_DestroyWindow(window); } if (glContext == nullptr) { @@ -761,15 +747,15 @@ int main(int argc, char *argv[]) { SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); SetGLCoreContext(false); - g_Screen = SDL_CreateWindow(app_name_nice.c_str(), x,y, pixel_xres, pixel_yres, mode); - if (g_Screen == nullptr) { + window = SDL_CreateWindow(app_name_nice.c_str(), x,y, pixel_xres, pixel_yres, mode); + if (window == nullptr) { NativeShutdown(); fprintf(stderr, "SDL_CreateWindow failed: %s\n", SDL_GetError()); SDL_Quit(); return 2; } - glContext = SDL_GL_CreateContext(g_Screen); + glContext = SDL_GL_CreateContext(window); if (glContext == nullptr) { NativeShutdown(); fprintf(stderr, "SDL_GL_CreateContext failed: %s\n", SDL_GetError()); @@ -782,7 +768,7 @@ int main(int argc, char *argv[]) { EGL_Init(); #endif - SDL_SetWindowTitle(g_Screen, (app_name_nice + " " + PPSSPP_GIT_VERSION).c_str()); + SDL_SetWindowTitle(window, (app_name_nice + " " + PPSSPP_GIT_VERSION).c_str()); #ifdef MOBILE_DEVICE SDL_ShowCursor(SDL_DISABLE); @@ -823,15 +809,15 @@ int main(int argc, char *argv[]) { GraphicsContext *graphicsContext; if (g_Config.iGPUBackend == GPU_BACKEND_OPENGL) { - graphicsContext = new SDLGLGraphicsContext(); + graphicsContext = new SDLGLGraphicsContext(window); } else if (g_Config.iGPUBackend == GPU_BACKEND_VULKAN) { SDLVulkanGraphicsContext *ctx = new SDLVulkanGraphicsContext(); std::string error_message; - if (!ctx->Init(g_Screen, &error_message)) { + if (!ctx->Init(window, &error_message)) { printf("Vulkan init error '%s' - falling back to GL\n", error_message.c_str()); g_Config.iGPUBackend = GPU_BACKEND_OPENGL; delete ctx; - graphicsContext = new SDLGLGraphicsContext(); + graphicsContext = new SDLGLGraphicsContext(window); } else { graphicsContext = ctx; } @@ -866,18 +852,14 @@ int main(int argc, char *argv[]) { // Audio must be unpaused _after_ NativeInit() SDL_PauseAudio(0); -#ifndef _WIN32 if (joystick_enabled) { joystick = new SDLJoystick(); } else { joystick = nullptr; } -#endif EnableFZ(); int framecount = 0; - float t = 0; - float lastT = 0; bool mouseDown = false; while (true) { @@ -896,7 +878,7 @@ int main(int argc, char *argv[]) { switch (event.window.event) { case SDL_WINDOWEVENT_RESIZED: { - Uint32 window_flags = SDL_GetWindowFlags(g_Screen); + Uint32 window_flags = SDL_GetWindowFlags(window); bool fullscreen = (window_flags & SDL_WINDOW_FULLSCREEN); pixel_xres = event.window.data1; @@ -1038,11 +1020,9 @@ int main(int argc, char *argv[]) { } break; default: -#ifndef _WIN32 if (joystick) { joystick->ProcessInput(event); } -#endif break; } } @@ -1066,23 +1046,13 @@ int main(int argc, char *argv[]) { // glsl_refresh(); // auto-reloads modified GLSL shaders once per second. } -#ifdef USING_EGL - eglSwapBuffers(g_eglDisplay, g_eglSurface); -#else - if (!keys[SDLK_TAB] || t - lastT >= 1.0/60.0) { - SDL_GL_SwapWindow(g_Screen); - lastT = t; - } -#endif + graphicsContext->SwapBuffers(); - ToggleFullScreenIfFlagSet(); + ToggleFullScreenIfFlagSet(window); time_update(); - t = time_now(); framecount++; } -#ifndef _WIN32 delete joystick; -#endif NativeShutdownGraphics(); SDL_GL_DeleteContext(glContext); graphicsContext->Shutdown(); From 7f758d52dcd8d2cc322755ce114e682d04d07c15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 15 Dec 2017 15:29:19 +0100 Subject: [PATCH 3/5] Statically link a vulkan loader on Linux. Use to to init vulkan on X11. Unfortunately, it's broken. --- CMakeLists.txt | 21 +- Common/Vulkan/VulkanContext.cpp | 23 +- Common/Vulkan/VulkanLoader.cpp | 49 +- Common/Vulkan/VulkanLoader.h | 14 +- GPU/Vulkan/VertexShaderGeneratorVulkan.cpp | 14 +- SDL/SDLMain.cpp | 555 +++++++++++---------- UI/GameSettingsScreen.cpp | 2 +- 7 files changed, 381 insertions(+), 297 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index cc7190270e..cb071f54ce 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -76,6 +76,25 @@ else() add_definitions(-DNO_VULKAN) endif() +if(NOT ANDROID) + # Use FindVulkan module added with CMAKE 3.7 + if (NOT CMAKE_VERSION VERSION_LESS 3.7.0) + message(STATUS "Using module to find Vulkan") + find_package(Vulkan) + endif() +endif() + +if(NOT WIN32 AND VULKAN) + IF (NOT Vulkan_FOUND) + find_library(Vulkan_LIBRARY NAMES vulkan HINTS "$ENV{VULKAN_SDK}/lib" "${CMAKE_SOURCE_DIR}/ext/vulkan" REQUIRED) + IF (Vulkan_LIBRARY) + set(Vulkan_FOUND ON) + MESSAGE("Using bundled Vulkan library version") + add_definitions(-DVULKAN_STATIC) + ENDIF() + ENDIF() +endif() + if(NOT DEFINED HEADLESS) set(HEADLESS OFF) endif() @@ -1653,7 +1672,7 @@ set(CoreExtraLibs ${CoreExtraLibs} armips) set(GlslangLibs glslang OGLCompiler OSDependent SPIRV SPVRemapper spirv-cross-glsl) target_link_libraries(${CoreLibName} Common native kirk cityhash sfmt19937 xbrz xxhash ${GlslangLibs} - ${CoreExtraLibs} ${OPENGL_LIBRARIES} ${X11_LIBRARIES} ${CMAKE_DL_LIBS}) + ${CoreExtraLibs} ${OPENGL_LIBRARIES} ${X11_LIBRARIES} ${CMAKE_DL_LIBS} ${Vulkan_LIBRARY}) if(FFmpeg_FOUND) target_compile_definitions(${CoreLibName} PRIVATE USE_FFMPEG=1) diff --git a/Common/Vulkan/VulkanContext.cpp b/Common/Vulkan/VulkanContext.cpp index 0c0b0471d2..c0f7f5f6ba 100644 --- a/Common/Vulkan/VulkanContext.cpp +++ b/Common/Vulkan/VulkanContext.cpp @@ -113,6 +113,8 @@ VkResult VulkanContext::CreateInstance(const CreateInfo &info) { instance_extensions_enabled_.push_back(VK_KHR_XLIB_SURFACE_EXTENSION_NAME); #elif defined(VK_USE_PLATFORM_XCB_KHR) instance_extensions_enabled_.push_back(VK_KHR_XCB_SURFACE_EXTENSION_NAME); +#elif defined(VK_USE_PLATFORM_MIR_KHR) + instance_extensions_enabled_.push_back(VK_KHR_MIR_SURFACE_EXTENSION_NAME); #elif defined(VK_USE_PLATFORM_WAYLAND_KHR) instance_extensions.enabled_.push_back(VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME); #else @@ -432,6 +434,7 @@ int VulkanContext::GetBestPhysicalDevice() { void VulkanContext::ChooseDevice(int physical_device) { physical_device_ = physical_device; + ILOG("Chose physical device %d: %p", physical_device, physical_devices_[physical_device]); GetDeviceLayerProperties(); if (!CheckLayers(device_layer_properties_, device_layer_names_)) { @@ -553,6 +556,7 @@ VkResult VulkanContext::CreateDevice() { } else { VulkanLoadDeviceFunctions(device_); } + ILOG("Device created.\n"); return res; } @@ -571,7 +575,7 @@ VkResult VulkanContext::InitDebugMsgCallback(PFN_vkDebugReportCallbackEXT dbgFun cb.flags = bits; cb.pfnCallback = dbgFunc; cb.pUserData = userdata; - VkResult res = vkCreateDebugReportCallbackEXT(instance_, &cb, nullptr, &msg_callback); + VkResult res = dyn_vkCreateDebugReportCallbackEXT(instance_, &cb, nullptr, &msg_callback); switch (res) { case VK_SUCCESS: msg_callbacks.push_back(msg_callback); @@ -586,7 +590,7 @@ VkResult VulkanContext::InitDebugMsgCallback(PFN_vkDebugReportCallbackEXT dbgFun void VulkanContext::DestroyDebugMsgCallback() { while (msg_callbacks.size() > 0) { - vkDestroyDebugReportCallbackEXT(instance_, msg_callbacks.back(), nullptr); + dyn_vkDestroyDebugReportCallbackEXT(instance_, msg_callbacks.back(), nullptr); msg_callbacks.pop_back(); } } @@ -650,7 +654,6 @@ void VulkanContext::ReinitSurface(int width, int height) { assert(res == VK_SUCCESS); break; } - #endif #if defined(VK_USE_PLATFORM_XCB_KHR) case WINDOWSYSTEM_XCB: @@ -718,16 +721,17 @@ bool VulkanContext::InitQueue() { graphics_queue_family_index_ = graphicsQueueNodeIndex; // Get the list of VkFormats that are supported: - uint32_t formatCount; + uint32_t formatCount = 0; VkResult res = vkGetPhysicalDeviceSurfaceFormatsKHR(physical_devices_[physical_device_], surface_, &formatCount, nullptr); - assert(res == VK_SUCCESS); - if (res != VK_SUCCESS) + _assert_msg_(G3D, res == VK_SUCCESS, "Failed to get formats for device %p: %d surface: %p", physical_devices_[physical_device_], (int)res, surface_); + if (res != VK_SUCCESS) { return false; - VkSurfaceFormatKHR *surfFormats = new VkSurfaceFormatKHR[formatCount]; - res = vkGetPhysicalDeviceSurfaceFormatsKHR(physical_devices_[physical_device_], surface_, &formatCount, surfFormats); + } + + std::vector surfFormats(formatCount); + res = vkGetPhysicalDeviceSurfaceFormatsKHR(physical_devices_[physical_device_], surface_, &formatCount, surfFormats.data()); assert(res == VK_SUCCESS); if (res != VK_SUCCESS) { - delete[] surfFormats; return false; } // If the format list includes just one entry of VK_FORMAT_UNDEFINED, @@ -754,7 +758,6 @@ bool VulkanContext::InitQueue() { } ILOG("swapchain_format: %d (/%d)", swapchainFormat_, formatCount); } - delete[] surfFormats; vkGetDeviceQueue(device_, graphics_queue_family_index_, 0, &gfx_queue_); ILOG("gfx_queue_: %p", gfx_queue_); diff --git a/Common/Vulkan/VulkanLoader.cpp b/Common/Vulkan/VulkanLoader.cpp index 61d613966f..e40c3ec6bf 100644 --- a/Common/Vulkan/VulkanLoader.cpp +++ b/Common/Vulkan/VulkanLoader.cpp @@ -17,11 +17,13 @@ #include "Common/Vulkan/VulkanLoader.h" #include "base/logging.h" +#include "base/basictypes.h" #ifndef _WIN32 #include #endif +#ifndef VULKAN_STATIC PFN_vkCreateInstance vkCreateInstance; PFN_vkDestroyInstance vkDestroyInstance; @@ -181,10 +183,12 @@ PFN_vkDestroySwapchainKHR vkDestroySwapchainKHR; PFN_vkGetSwapchainImagesKHR vkGetSwapchainImagesKHR; PFN_vkAcquireNextImageKHR vkAcquireNextImageKHR; PFN_vkQueuePresentKHR vkQueuePresentKHR; +#endif + +// And the DEBUG_REPORT extension. We dynamically load this. +PFN_vkCreateDebugReportCallbackEXT dyn_vkCreateDebugReportCallbackEXT; +PFN_vkDestroyDebugReportCallbackEXT dyn_vkDestroyDebugReportCallbackEXT; -// And the DEBUG_REPORT extension. -PFN_vkCreateDebugReportCallbackEXT vkCreateDebugReportCallbackEXT; -PFN_vkDestroyDebugReportCallbackEXT vkDestroyDebugReportCallbackEXT; #ifdef _WIN32 static HINSTANCE vulkanLibrary; @@ -197,15 +201,26 @@ static void *vulkanLibrary; #define LOAD_DEVICE_FUNC(instance, x) x = (PFN_ ## x)vkGetDeviceProcAddr(instance, #x); if (!x) {ILOG("Missing (device): %s", #x);} #define LOAD_GLOBAL_FUNC(x) x = (PFN_ ## x)dlsym(vulkanLibrary, #x); if (!x) {ILOG("Missing (global): %s", #x);} +static const char *so_names[] = { + "libvulkan.so", + "libvulkan.so.1", +}; + bool VulkanMayBeAvailable() { +#ifdef VULKAN_STATIC + return true; +#else if (vulkanLibrary) return true; bool available = false; #ifndef _WIN32 - void *lib = dlopen("libvulkan.so", RTLD_NOW | RTLD_LOCAL); - available = lib != nullptr; - if (lib) { - dlclose(lib); + for (int i = 0; i < ARRAY_SIZE(so_names); i++) { + void *lib = dlopen(so_names[i], RTLD_NOW | RTLD_LOCAL); + if (lib) { + available = true; + dlclose(lib); + break; + } } #else // LoadLibrary etc @@ -216,12 +231,18 @@ bool VulkanMayBeAvailable() { } #endif return available; +#endif } bool VulkanLoad() { +#ifndef VULKAN_STATIC if (!vulkanLibrary) { #ifndef _WIN32 - vulkanLibrary = dlopen("libvulkan.so", RTLD_NOW | RTLD_LOCAL); + for (int i = 0; i < ARRAY_SIZE(so_names); i++) { + vulkanLibrary = dlopen(so_names[i], RTLD_NOW | RTLD_LOCAL); + if (vulkanLibrary) + break; + } #else // LoadLibrary etc vulkanLibrary = LoadLibrary(L"vulkan-1.dll"); @@ -239,10 +260,12 @@ bool VulkanLoad() { LOAD_GLOBAL_FUNC(vkEnumerateInstanceLayerProperties); WLOG("Vulkan base functions loaded."); +#endif return true; } void VulkanLoadInstanceFunctions(VkInstance instance) { +#ifndef VULKAN_STATIC // OK, let's use the above functions to get the rest. LOAD_INSTANCE_FUNC(instance, vkDestroyInstance); LOAD_INSTANCE_FUNC(instance, vkEnumeratePhysicalDevices); @@ -397,9 +420,11 @@ void VulkanLoadInstanceFunctions(VkInstance instance) { #endif LOAD_INSTANCE_FUNC(instance, vkDestroySurfaceKHR); +#endif + + dyn_vkCreateDebugReportCallbackEXT = (PFN_vkCreateDebugReportCallbackEXT)vkGetInstanceProcAddr(instance, "vkCreateDebugReportCallbackEXT"); + dyn_vkDestroyDebugReportCallbackEXT = (PFN_vkDestroyDebugReportCallbackEXT)vkGetInstanceProcAddr(instance, "vkCreateDebugReportCallbackEXT"); - LOAD_INSTANCE_FUNC(instance, vkCreateDebugReportCallbackEXT); - LOAD_INSTANCE_FUNC(instance, vkDestroyDebugReportCallbackEXT); WLOG("Vulkan instance functions loaded."); } @@ -408,15 +433,18 @@ void VulkanLoadInstanceFunctions(VkInstance instance) { // good for multi-device. void VulkanLoadDeviceFunctions(VkDevice device) { WLOG("Vulkan device functions loaded."); +#ifndef VULKAN_STATIC // TODO: Move more functions VulkanLoadInstanceFunctions to here. LOAD_DEVICE_FUNC(device, vkCreateSwapchainKHR); LOAD_DEVICE_FUNC(device, vkDestroySwapchainKHR); LOAD_DEVICE_FUNC(device, vkGetSwapchainImagesKHR); LOAD_DEVICE_FUNC(device, vkAcquireNextImageKHR); LOAD_DEVICE_FUNC(device, vkQueuePresentKHR); +#endif } void VulkanFree() { +#ifndef VULKAN_STATIC if (vulkanLibrary) { #ifdef _WIN32 FreeLibrary(vulkanLibrary); @@ -425,4 +453,5 @@ void VulkanFree() { #endif vulkanLibrary = nullptr; } +#endif } diff --git a/Common/Vulkan/VulkanLoader.h b/Common/Vulkan/VulkanLoader.h index 18ab75555f..16fbe1fd2e 100644 --- a/Common/Vulkan/VulkanLoader.h +++ b/Common/Vulkan/VulkanLoader.h @@ -25,10 +25,13 @@ #define NOMINMAX #endif +#ifndef VULKAN_STATIC #define VK_NO_PROTOTYPES +#endif #include "ext/vulkan/vulkan.h" +#ifndef VULKAN_STATIC extern PFN_vkCreateInstance vkCreateInstance; extern PFN_vkDestroyInstance vkDestroyInstance; extern PFN_vkEnumeratePhysicalDevices vkEnumeratePhysicalDevices; @@ -189,9 +192,13 @@ extern PFN_vkGetSwapchainImagesKHR vkGetSwapchainImagesKHR; extern PFN_vkAcquireNextImageKHR vkAcquireNextImageKHR; extern PFN_vkQueuePresentKHR vkQueuePresentKHR; -// And the DEBUG_REPORT extension. -extern PFN_vkCreateDebugReportCallbackEXT vkCreateDebugReportCallbackEXT; -extern PFN_vkDestroyDebugReportCallbackEXT vkDestroyDebugReportCallbackEXT; +#endif + +// And the DEBUG_REPORT extension. Since we load this dynamically even in static +// linked mode, we have to rename it :( +extern PFN_vkCreateDebugReportCallbackEXT dyn_vkCreateDebugReportCallbackEXT; +extern PFN_vkDestroyDebugReportCallbackEXT dyn_vkDestroyDebugReportCallbackEXT; + // Way to do a quick check before even attempting to load. bool VulkanMayBeAvailable(); @@ -200,4 +207,3 @@ bool VulkanLoad(); void VulkanLoadInstanceFunctions(VkInstance instance); void VulkanLoadDeviceFunctions(VkDevice device); void VulkanFree(); - diff --git a/GPU/Vulkan/VertexShaderGeneratorVulkan.cpp b/GPU/Vulkan/VertexShaderGeneratorVulkan.cpp index 7f94806fcd..8aa8b1719f 100644 --- a/GPU/Vulkan/VertexShaderGeneratorVulkan.cpp +++ b/GPU/Vulkan/VertexShaderGeneratorVulkan.cpp @@ -169,27 +169,27 @@ bool GenerateVulkanGLSLVertexShader(const VShaderID &id, char *buffer, bool *use } if (useHWTransform) - WRITE(p, "layout (location = %d) in vec3 position;\n", PspAttributeLocation::POSITION); + WRITE(p, "layout (location = %d) in vec3 position;\n", (int)PspAttributeLocation::POSITION); else // we pass the fog coord in w - WRITE(p, "layout (location = %d) in vec4 position;\n", PspAttributeLocation::POSITION); + WRITE(p, "layout (location = %d) in vec4 position;\n", (int)PspAttributeLocation::POSITION); if (useHWTransform && hasNormal) - WRITE(p, "layout (location = %d) in vec3 normal;\n", PspAttributeLocation::NORMAL); + WRITE(p, "layout (location = %d) in vec3 normal;\n", (int)PspAttributeLocation::NORMAL); bool texcoordInVec3 = false; if (doTexture && hasTexcoord) { if (!useHWTransform && doTextureTransform && !throughmode) { - WRITE(p, "layout (location = %d) in vec3 texcoord;\n", PspAttributeLocation::TEXCOORD); + WRITE(p, "layout (location = %d) in vec3 texcoord;\n", (int)PspAttributeLocation::TEXCOORD); texcoordInVec3 = true; } else - WRITE(p, "layout (location = %d) in vec2 texcoord;\n", PspAttributeLocation::TEXCOORD); + WRITE(p, "layout (location = %d) in vec2 texcoord;\n", (int)PspAttributeLocation::TEXCOORD); } if (hasColor) { - WRITE(p, "layout (location = %d) in vec4 color0;\n", PspAttributeLocation::COLOR0); + WRITE(p, "layout (location = %d) in vec4 color0;\n", (int)PspAttributeLocation::COLOR0); if (lmode && !useHWTransform) // only software transform supplies color1 as vertex data - WRITE(p, "layout (location = %d) in vec3 color1;\n", PspAttributeLocation::COLOR1); + WRITE(p, "layout (location = %d) in vec3 color1;\n", (int)PspAttributeLocation::COLOR1); } WRITE(p, "layout (location = 1) %sout vec4 v_color0;\n", shading); diff --git a/SDL/SDLMain.cpp b/SDL/SDLMain.cpp index d75581368c..c8fa5c32ca 100644 --- a/SDL/SDLMain.cpp +++ b/SDL/SDLMain.cpp @@ -42,156 +42,15 @@ SDLJoystick *joystick = NULL; #include "SDL_syswm.h" #endif +#if defined(USING_EGL) +#include "EGL/egl.h" +#endif + #include "Core/System.h" #include "Core/Core.h" #include "Core/Config.h" #include "Common/GraphicsContext.h" -class SDLGLGraphicsContext : public DummyGraphicsContext { -public: - SDLGLGraphicsContext(SDL_Window *window) : window_(window) { - CheckGLExtensions(); - draw_ = Draw::T3DCreateGLContext(); - bool success = draw_->CreatePresets(); - assert(success); - } - ~SDLGLGraphicsContext() { - delete draw_; - } - - void Shutdown() override { - } - - void SwapBuffers() override { -#ifdef USING_EGL - eglSwapBuffers(g_eglDisplay, g_eglSurface); -#else - SDL_GL_SwapWindow(window_); -#endif - } - - Draw::DrawContext *GetDrawContext() override { - return draw_; - } - -private: - Draw::DrawContext *draw_ = nullptr; - SDL_Window *window_; -}; - -static VulkanLogOptions g_LogOptions; - -class SDLVulkanGraphicsContext : public GraphicsContext { -public: - SDLVulkanGraphicsContext() {} - ~SDLVulkanGraphicsContext() { - delete draw_; - } - - bool Init(SDL_Window *sdl_window, std::string *error_message) { - SDL_SysWMinfo sys_info; - SDL_VERSION(&sys_info.version); //Set SDL version - SDL_GetWindowWMInfo(sdl_window, &sys_info); - - Display *display = sys_info.info.x11.display; - Window window = sys_info.info.x11.window; - - init_glslang(); - - g_LogOptions.breakOnError = true; - g_LogOptions.breakOnWarning = true; - g_LogOptions.msgBoxOnError = false; - - Version gitVer(PPSSPP_GIT_VERSION); - - vulkan_ = new VulkanContext(); - if (vulkan_->InitError().size()) { - *error_message = vulkan_->InitError(); - delete vulkan_; - vulkan_ = nullptr; - return false; - } - - int vulkanFlags = VULKAN_FLAG_PRESENT_MAILBOX; - // vulkanFlags |= VULKAN_FLAG_VALIDATE; - VulkanContext::CreateInfo info{}; - info.app_name = "PPSSPP"; - info.app_ver = gitVer.ToInteger(); - info.flags = VULKAN_FLAG_PRESENT_MAILBOX; - if (VK_SUCCESS != vulkan_->CreateInstance(info)) { - *error_message = vulkan_->InitError(); - delete vulkan_; - vulkan_ = nullptr; - return false; - } - vulkan_->ChooseDevice(vulkan_->GetBestPhysicalDevice()); - if (vulkan_->CreateDevice() != VK_SUCCESS) { - *error_message = vulkan_->InitError(); - delete vulkan_; - vulkan_ = nullptr; - return false; - } - - vulkan_->InitSurface(WINDOWSYSTEM_XLIB, (void *)display, (void *)(intptr_t)window, pixel_xres, pixel_yres); - - if (!vulkan_->InitObjects()) { - *error_message = vulkan_->InitError(); - Shutdown(); - return false; - } - - draw_ = Draw::T3DCreateVulkanContext(vulkan_, false); - bool success = draw_->CreatePresets(); - assert(success); - draw_->HandleEvent(Draw::Event::GOT_BACKBUFFER, vulkan_->GetBackbufferWidth(), vulkan_->GetBackbufferHeight()); - - return true; - } - - void Shutdown() override { - if (draw_) - draw_->HandleEvent(Draw::Event::LOST_BACKBUFFER, vulkan_->GetBackbufferWidth(), vulkan_->GetBackbufferHeight()); - delete draw_; - draw_ = nullptr; - vulkan_->WaitUntilQueueIdle(); - vulkan_->DestroyObjects(); - vulkan_->DestroyDevice(); - vulkan_->DestroyDebugMsgCallback(); - vulkan_->DestroyInstance(); - delete vulkan_; - vulkan_ = nullptr; - finalize_glslang(); - } - - void SwapBuffers() override { - // We don't do it this way. - } - - void Resize() override { - draw_->HandleEvent(Draw::Event::LOST_BACKBUFFER, vulkan_->GetBackbufferWidth(), vulkan_->GetBackbufferHeight()); - vulkan_->DestroyObjects(); - // TODO: Take from real window dimensions - int width = 1024; - int height = 768; - vulkan_->ReinitSurface(width, height); - vulkan_->InitObjects(); - draw_->HandleEvent(Draw::Event::GOT_BACKBUFFER, vulkan_->GetBackbufferWidth(), vulkan_->GetBackbufferHeight()); - } - - void SwapInterval(int interval) override { - } - void *GetAPIContext() override { - return vulkan_; - } - - Draw::DrawContext *GetDrawContext() override { - return draw_; - } -private: - Draw::DrawContext *draw_ = nullptr; - VulkanContext *vulkan_ = nullptr; -}; - GlobalUIState lastUIState = UISTATE_MENU; GlobalUIState GetUIState(); @@ -202,8 +61,9 @@ static int g_QuitRequested = 0; static int g_DesktopWidth = 0; static int g_DesktopHeight = 0; +static VulkanLogOptions g_LogOptions; + #if defined(USING_EGL) -#include "EGL/egl.h" static EGLDisplay g_eglDisplay = NULL; static EGLContext g_eglContext = NULL; @@ -334,6 +194,264 @@ void EGL_Close() { } #endif +class SDLGLGraphicsContext : public DummyGraphicsContext { +public: + SDLGLGraphicsContext() { + } + ~SDLGLGraphicsContext() { + delete draw_; + } + + bool Init(SDL_Window *&window, int x, int y, int mode, std::string *error_message); + + void Shutdown() override { +#ifdef USING_EGL + EGL_Close(); +#else + SDL_GL_DeleteContext(glContext); +#endif + } + + void SwapBuffers() override { +#ifdef USING_EGL + eglSwapBuffers(g_eglDisplay, g_eglSurface); +#else + SDL_GL_SwapWindow(window_); +#endif + } + + Draw::DrawContext *GetDrawContext() override { + return draw_; + } + +private: + Draw::DrawContext *draw_ = nullptr; + SDL_Window *window_; + SDL_GLContext glContext = nullptr; +}; + +bool SDLGLGraphicsContext::Init(SDL_Window *&window, int x, int y, int mode, std::string *error_message) { + struct GLVersionPair { + int major; + int minor; + }; + GLVersionPair attemptVersions[] = { +#ifdef USING_GLES2 + {3, 2}, {3, 1}, {3, 0}, {2, 0}, +#else + {4, 6}, {4, 5}, {4, 4}, {4, 3}, {4, 2}, {4, 1}, {4, 0}, + {3, 3}, {3, 2}, {3, 1}, {3, 0}, +#endif + }; + + SDL_GLContext glContext = nullptr; + for (size_t i = 0; i < ARRAY_SIZE(attemptVersions); ++i) { + const auto &ver = attemptVersions[i]; + // Make sure to request a somewhat modern GL context at least - the + // latest supported by MacOS X (really, really sad...) + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, ver.major); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, ver.minor); +#ifdef USING_GLES2 + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); + SetGLCoreContext(false); +#else + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); + SetGLCoreContext(true); +#endif + + window = SDL_CreateWindow("PPSSPP", x,y, pixel_xres, pixel_yres, mode); + if (!window) { + NativeShutdown(); + fprintf(stderr, "SDL_CreateWindow failed: %s\n", SDL_GetError()); + continue; + } + + glContext = SDL_GL_CreateContext(window); + if (glContext != nullptr) { + // Victory, got one. + break; + } + + // Let's keep trying. To be safe, destroy the window - docs say needed to change profile. + // in practice, it doesn't seem to matter, but maybe it differs by platform. + SDL_DestroyWindow(window); + } + + if (glContext == nullptr) { + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, 0); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 0); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); + SetGLCoreContext(false); + + window = SDL_CreateWindow("PPSSPP", x,y, pixel_xres, pixel_yres, mode); + if (window == nullptr) { + NativeShutdown(); + fprintf(stderr, "SDL_CreateWindow failed: %s\n", SDL_GetError()); + SDL_Quit(); + return 2; + } + + glContext = SDL_GL_CreateContext(window); + if (glContext == nullptr) { + NativeShutdown(); + fprintf(stderr, "SDL_GL_CreateContext failed: %s\n", SDL_GetError()); + SDL_Quit(); + return 2; + } + } + +#ifdef USING_EGL + EGL_Init(); +#endif + +#ifndef USING_GLES2 + // Some core profile drivers elide certain extensions from GL_EXTENSIONS/etc. + // glewExperimental allows us to force GLEW to search for the pointers anyway. + if (gl_extensions.IsCoreContext) { + glewExperimental = true; + } + if (GLEW_OK != glewInit()) { + printf("Failed to initialize glew!\n"); + return 1; + } + // Unfortunately, glew will generate an invalid enum error, ignore. + if (gl_extensions.IsCoreContext) + glGetError(); + + if (GLEW_VERSION_2_0) { + printf("OpenGL 2.0 or higher.\n"); + } else { + printf("Sorry, this program requires OpenGL 2.0.\n"); + return 1; + } +#endif + + // Finally we can do the regular initialization. + CheckGLExtensions(); + draw_ = Draw::T3DCreateGLContext(); + bool success = draw_->CreatePresets(); + assert(success); + window_ = window; +} + +class SDLVulkanGraphicsContext : public GraphicsContext { +public: + SDLVulkanGraphicsContext() {} + ~SDLVulkanGraphicsContext() { + delete draw_; + } + + bool Init(SDL_Window *&window, int x, int y, int mode, std::string *error_message); + + void Shutdown() override; + + void SwapBuffers() override { + // We don't do it this way. + } + + void Resize() override { + draw_->HandleEvent(Draw::Event::LOST_BACKBUFFER, vulkan_->GetBackbufferWidth(), vulkan_->GetBackbufferHeight()); + vulkan_->DestroyObjects(); + // TODO: Take from real window dimensions + int width = 1024; + int height = 768; + vulkan_->ReinitSurface(width, height); + vulkan_->InitObjects(); + draw_->HandleEvent(Draw::Event::GOT_BACKBUFFER, vulkan_->GetBackbufferWidth(), vulkan_->GetBackbufferHeight()); + } + + void SwapInterval(int interval) override { + } + void *GetAPIContext() override { + return vulkan_; + } + + Draw::DrawContext *GetDrawContext() override { + return draw_; + } +private: + Draw::DrawContext *draw_ = nullptr; + VulkanContext *vulkan_ = nullptr; +}; + +bool SDLVulkanGraphicsContext::Init(SDL_Window *&window, int x, int y, int mode, std::string *error_message) { + mode |= SDL_WINDOW_VULKAN; + window = SDL_CreateWindow("Initializing Vulkan...", x, y, pixel_xres, pixel_yres, mode); + SDL_SysWMinfo sys_info; + SDL_VERSION(&sys_info.version); + SDL_GetWindowWMInfo(window, &sys_info); + Display *display = sys_info.info.x11.display; + Window x11_window = sys_info.info.x11.window; + + ILOG("Display: %p", display); + + init_glslang(); + + g_LogOptions.breakOnError = true; + g_LogOptions.breakOnWarning = true; + g_LogOptions.msgBoxOnError = false; + + Version gitVer(PPSSPP_GIT_VERSION); + + vulkan_ = new VulkanContext(); + if (vulkan_->InitError().size()) { + *error_message = vulkan_->InitError(); + delete vulkan_; + vulkan_ = nullptr; + return false; + } + + int vulkanFlags = VULKAN_FLAG_PRESENT_MAILBOX; + // vulkanFlags |= VULKAN_FLAG_VALIDATE; + VulkanContext::CreateInfo info{}; + info.app_name = "PPSSPP"; + info.app_ver = gitVer.ToInteger(); + info.flags = vulkanFlags; + if (VK_SUCCESS != vulkan_->CreateInstance(info)) { + *error_message = vulkan_->InitError(); + delete vulkan_; + vulkan_ = nullptr; + return false; + } + vulkan_->ChooseDevice(vulkan_->GetBestPhysicalDevice()); + if (vulkan_->CreateDevice() != VK_SUCCESS) { + *error_message = vulkan_->InitError(); + delete vulkan_; + vulkan_ = nullptr; + return false; + } + + vulkan_->InitSurface(WINDOWSYSTEM_XLIB, (void *)display, (void *)(intptr_t)x11_window, pixel_xres, pixel_yres); + + if (!vulkan_->InitObjects()) { + *error_message = vulkan_->InitError(); + Shutdown(); + return false; + } + + draw_ = Draw::T3DCreateVulkanContext(vulkan_, false); + bool success = draw_->CreatePresets(); + assert(success); + draw_->HandleEvent(Draw::Event::GOT_BACKBUFFER, vulkan_->GetBackbufferWidth(), vulkan_->GetBackbufferHeight()); + + return true; +} + +void SDLVulkanGraphicsContext::Shutdown() { + if (draw_) + draw_->HandleEvent(Draw::Event::LOST_BACKBUFFER, vulkan_->GetBackbufferWidth(), vulkan_->GetBackbufferHeight()); + delete draw_; + draw_ = nullptr; + vulkan_->WaitUntilQueueIdle(); + vulkan_->DestroyObjects(); + vulkan_->DestroyDevice(); + vulkan_->DestroyDebugMsgCallback(); + vulkan_->DestroyInstance(); + delete vulkan_; + vulkan_ = nullptr; + finalize_glslang(); +} + int getDisplayNumber(void) { int displayNumber = 0; char * displayNumberStr; @@ -545,6 +663,12 @@ int main(int argc, char *argv[]) { putenv((char*)"SDL_VIDEO_CENTERED=1"); SDL_SetHint(SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS, "0"); + if (VulkanMayBeAvailable()) { + printf("Vulkan might be available.\n"); + } else { + printf("Vulkan is not available.\n"); + } + int set_xres = -1; int set_yres = -1; bool portrait = false; @@ -593,6 +717,7 @@ int main(int argc, char *argv[]) { bool joystick_enabled = true; if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER | SDL_INIT_AUDIO) < 0) { + fprintf(stderr, "Failed to initialize SDL with joystick support. Retrying without.\n"); joystick_enabled = false; if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0) { fprintf(stderr, "Unable to initialize SDL: %s\n", SDL_GetError()); @@ -600,6 +725,7 @@ int main(int argc, char *argv[]) { } } + // TODO: How do we get this into the GraphicsContext? #ifdef USING_EGL if (EGL_Open()) return 1; @@ -624,12 +750,6 @@ int main(int argc, char *argv[]) { SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); SDL_GL_SetSwapInterval(1); -#ifdef USING_GLES2 - mode |= SDL_WINDOW_OPENGL | SDL_WINDOW_FULLSCREEN; -#else - mode |= SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE; -#endif - // Is resolution is too low to run windowed if (g_DesktopWidth < 480 * 2 && g_DesktopHeight < 272 * 2) { mode |= SDL_WINDOW_FULLSCREEN_DESKTOP; @@ -694,109 +814,6 @@ int main(int argc, char *argv[]) { int x = SDL_WINDOWPOS_UNDEFINED_DISPLAY(getDisplayNumber()); int y = SDL_WINDOWPOS_UNDEFINED; - struct GLVersionPair { - int major; - int minor; - }; - GLVersionPair attemptVersions[] = { -#ifdef USING_GLES2 - {3, 2}, {3, 1}, {3, 0}, {2, 0}, -#else - {4, 6}, {4, 5}, {4, 4}, {4, 3}, {4, 2}, {4, 1}, {4, 0}, - {3, 3}, {3, 2}, {3, 1}, {3, 0}, -#endif - }; - - SDL_Window *window = nullptr; - SDL_GLContext glContext = nullptr; - for (size_t i = 0; i < ARRAY_SIZE(attemptVersions); ++i) { - const auto &ver = attemptVersions[i]; - // Make sure to request a somewhat modern GL context at least - the - // latest supported by MacOS X (really, really sad...) - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, ver.major); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, ver.minor); -#ifdef USING_GLES2 - SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); - SetGLCoreContext(false); -#else - SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); - SetGLCoreContext(true); -#endif - - window = SDL_CreateWindow(app_name_nice.c_str(), x,y, pixel_xres, pixel_yres, mode); - if (!window) { - NativeShutdown(); - fprintf(stderr, "SDL_CreateWindow failed: %s\n", SDL_GetError()); - continue; - } - - glContext = SDL_GL_CreateContext(window); - if (glContext != nullptr) { - // Victory, got one. - break; - } - - // Let's keep trying. To be safe, destroy the window - docs say needed to change profile. - // in practice, it doesn't seem to matter, but maybe it differs by platform. - SDL_DestroyWindow(window); - } - - if (glContext == nullptr) { - SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, 0); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 0); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); - SetGLCoreContext(false); - - window = SDL_CreateWindow(app_name_nice.c_str(), x,y, pixel_xres, pixel_yres, mode); - if (window == nullptr) { - NativeShutdown(); - fprintf(stderr, "SDL_CreateWindow failed: %s\n", SDL_GetError()); - SDL_Quit(); - return 2; - } - - glContext = SDL_GL_CreateContext(window); - if (glContext == nullptr) { - NativeShutdown(); - fprintf(stderr, "SDL_GL_CreateContext failed: %s\n", SDL_GetError()); - SDL_Quit(); - return 2; - } - } - -#ifdef USING_EGL - EGL_Init(); -#endif - - SDL_SetWindowTitle(window, (app_name_nice + " " + PPSSPP_GIT_VERSION).c_str()); - -#ifdef MOBILE_DEVICE - SDL_ShowCursor(SDL_DISABLE); -#endif - - -#ifndef USING_GLES2 - // Some core profile drivers elide certain extensions from GL_EXTENSIONS/etc. - // glewExperimental allows us to force GLEW to search for the pointers anyway. - if (gl_extensions.IsCoreContext) - glewExperimental = true; - if (GLEW_OK != glewInit()) { - printf("Failed to initialize glew!\n"); - return 1; - } - // Unfortunately, glew will generate an invalid enum error, ignore. - if (gl_extensions.IsCoreContext) - glGetError(); - - if (GLEW_VERSION_2_0) { - printf("OpenGL 2.0 or higher.\n"); - } else { - printf("Sorry, this program requires OpenGL 2.0.\n"); - return 1; - } -#endif - - pixel_in_dps_x = (float)pixel_xres / dp_xres; pixel_in_dps_y = (float)pixel_yres / dp_yres; g_dpi_scale_x = dp_xres / (float)pixel_xres; @@ -807,21 +824,35 @@ int main(int argc, char *argv[]) { printf("Pixels: %i x %i\n", pixel_xres, pixel_yres); printf("Virtual pixels: %i x %i\n", dp_xres, dp_yres); - GraphicsContext *graphicsContext; + GraphicsContext *graphicsContext = nullptr; + SDL_Window *window = nullptr; + std::string error_message; if (g_Config.iGPUBackend == GPU_BACKEND_OPENGL) { - graphicsContext = new SDLGLGraphicsContext(window); + SDLGLGraphicsContext *ctx = new SDLGLGraphicsContext(); + if (!ctx->Init(window, x, y, mode, &error_message)) { + printf("GL init error '%s' - falling back to GL\n", error_message.c_str()); + } + graphicsContext = ctx; } else if (g_Config.iGPUBackend == GPU_BACKEND_VULKAN) { SDLVulkanGraphicsContext *ctx = new SDLVulkanGraphicsContext(); - std::string error_message; - if (!ctx->Init(window, &error_message)) { + if (!ctx->Init(window, x, y, mode, &error_message)) { printf("Vulkan init error '%s' - falling back to GL\n", error_message.c_str()); g_Config.iGPUBackend = GPU_BACKEND_OPENGL; delete ctx; - graphicsContext = new SDLGLGraphicsContext(window); + SDLGLGraphicsContext *glctx = new SDLGLGraphicsContext(); + glctx->Init(window, x, y, mode, &error_message); + graphicsContext = glctx; } else { graphicsContext = ctx; } } + + SDL_SetWindowTitle(window, (app_name_nice + " " + PPSSPP_GIT_VERSION).c_str()); + +#ifdef MOBILE_DEVICE + SDL_ShowCursor(SDL_DISABLE); +#endif + NativeInitGraphics(graphicsContext); NativeResized(); @@ -1054,16 +1085,12 @@ int main(int argc, char *argv[]) { } delete joystick; NativeShutdownGraphics(); - SDL_GL_DeleteContext(glContext); graphicsContext->Shutdown(); NativeShutdown(); delete graphicsContext; SDL_PauseAudio(1); SDL_CloseAudio(); -#ifdef USING_EGL - EGL_Close(); -#endif SDL_Quit(); #if PPSSPP_PLATFORM(RPI) bcm_host_deinit(); diff --git a/UI/GameSettingsScreen.cpp b/UI/GameSettingsScreen.cpp index c3dfcd193d..0c0b2dcdcf 100644 --- a/UI/GameSettingsScreen.cpp +++ b/UI/GameSettingsScreen.cpp @@ -191,7 +191,7 @@ void GameSettingsScreen::CreateViews() { } #endif bool vulkanAvailable = false; -#if PPSSPP_PLATFORM(WINDOWS) || PPSSPP_PLATFORM(ANDROID) +#ifndef IOS vulkanAvailable = VulkanMayBeAvailable(); #endif if (!vulkanAvailable) { From 9007abddbf0d78646b4bc57d21aaf5990746c2f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 15 Dec 2017 16:03:48 +0100 Subject: [PATCH 4/5] Get Vulkan going on Linux --- CMakeLists.txt | 11 +++++++++-- SDL/SDLMain.cpp | 43 ++++++++++++++++++++++++++++++++++--------- 2 files changed, 43 insertions(+), 11 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index cb071f54ce..5be4b7975a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -106,9 +106,10 @@ else() message("Normal Build") endif() -if(LINUX) - message("Using direct to display extension...") +if(LINUX AND VULKAN) + message("Using XCB extension...") add_definitions(-DVK_USE_PLATFORM_XLIB_KHR) + # add_definitions(-DVK_USE_PLATFORM_XCB_KHR) endif() # Doesn't link on some platforms @@ -1669,6 +1670,12 @@ endif() set(CoreExtraLibs ${CoreExtraLibs} armips) +# needed for VK_USE_PLATFORM_XCB_KHR only +#if(VULKAN AND NOT WIN32) +# target_link_libraries(native X11-xcb X11) +#endif() + + set(GlslangLibs glslang OGLCompiler OSDependent SPIRV SPVRemapper spirv-cross-glsl) target_link_libraries(${CoreLibName} Common native kirk cityhash sfmt19937 xbrz xxhash ${GlslangLibs} diff --git a/SDL/SDLMain.cpp b/SDL/SDLMain.cpp index c8fa5c32ca..fb7dc5f454 100644 --- a/SDL/SDLMain.cpp +++ b/SDL/SDLMain.cpp @@ -40,6 +40,11 @@ SDLJoystick *joystick = NULL; #include #include #include "SDL_syswm.h" +#elif defined(VK_USE_PLATFORM_XCB_KHR) +#include +#include +#include +#include "SDL_syswm.h" #endif #if defined(USING_EGL) @@ -350,6 +355,7 @@ public: } void Resize() override { + /* draw_->HandleEvent(Draw::Event::LOST_BACKBUFFER, vulkan_->GetBackbufferWidth(), vulkan_->GetBackbufferHeight()); vulkan_->DestroyObjects(); // TODO: Take from real window dimensions @@ -358,6 +364,7 @@ public: vulkan_->ReinitSurface(width, height); vulkan_->InitObjects(); draw_->HandleEvent(Draw::Event::GOT_BACKBUFFER, vulkan_->GetBackbufferWidth(), vulkan_->GetBackbufferHeight()); + */ } void SwapInterval(int interval) override { @@ -375,15 +382,11 @@ private: }; bool SDLVulkanGraphicsContext::Init(SDL_Window *&window, int x, int y, int mode, std::string *error_message) { - mode |= SDL_WINDOW_VULKAN; window = SDL_CreateWindow("Initializing Vulkan...", x, y, pixel_xres, pixel_yres, mode); - SDL_SysWMinfo sys_info; - SDL_VERSION(&sys_info.version); - SDL_GetWindowWMInfo(window, &sys_info); - Display *display = sys_info.info.x11.display; - Window x11_window = sys_info.info.x11.window; - - ILOG("Display: %p", display); + if (!window) { + fprintf(stderr, "Error creating SDL window: %s\n", SDL_GetError()); + exit(1); + } init_glslang(); @@ -421,7 +424,29 @@ bool SDLVulkanGraphicsContext::Init(SDL_Window *&window, int x, int y, int mode, return false; } - vulkan_->InitSurface(WINDOWSYSTEM_XLIB, (void *)display, (void *)(intptr_t)x11_window, pixel_xres, pixel_yres); + SDL_SysWMinfo sys_info{}; + SDL_VERSION(&sys_info.version); //Set SDL version + if (!SDL_GetWindowWMInfo(window, &sys_info)) { + fprintf(stderr, "Error getting SDL window wm info: %s\n", SDL_GetError()); + exit(1); + } + Display *display = sys_info.info.x11.display; + Window x11_window = sys_info.info.x11.window; + switch (sys_info.subsystem) { + case SDL_SYSWM_X11: + break; + default: + fprintf(stderr, "Vulkan subsystem %d not supported\n", sys_info.subsystem); + exit(1); + break; + } + ILOG("Display: %p", display); + +#if defined(VK_USE_PLATFORM_XLIB_KHR) + vulkan_->InitSurface(WINDOWSYSTEM_XLIB, (void*)display, (void *)(intptr_t)x11_window, pixel_xres, pixel_yres); +#elif defined(VK_USE_PLATFORM_XCB_KHR) + vulkan_->InitSurface(WINDOWSYSTEM_XCB, (void*)XGetXCBConnection(display), (void *)(intptr_t)x11_window, pixel_xres, pixel_yres); +#endif if (!vulkan_->InitObjects()) { *error_message = vulkan_->InitError(); From f73ec4608e72f6ec40861bd6bbaca82d97e51d7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 21 Dec 2017 14:13:55 +0100 Subject: [PATCH 5/5] Build Vulkan on all platforms, won't be used if not supported. --- CMakeLists.txt | 43 +++++++++++++++++++++---------------------- SDL/SDLMain.cpp | 26 ++++++++++++++++---------- 2 files changed, 37 insertions(+), 32 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5be4b7975a..a8915f868a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -355,23 +355,19 @@ set(CommonWindows Common/stdafx.h) source_group(Windows FILES ${CommonWindows}) -if(VULKAN) - set(CommonVulkan ${CommonExtra} - Common/Vulkan/SPIRVDisasm.cpp - Common/Vulkan/SPIRVDisasm.h - Common/Vulkan/VulkanContext.cpp - Common/Vulkan/VulkanContext.h - Common/Vulkan/VulkanDebug.cpp - Common/Vulkan/VulkanDebug.h - Common/Vulkan/VulkanImage.cpp - Common/Vulkan/VulkanImage.h - Common/Vulkan/VulkanLoader.cpp - Common/Vulkan/VulkanLoader.h - Common/Vulkan/VulkanMemory.cpp - Common/Vulkan/VulkanMemory.h) -else() - set(CommonVulkan) -endif() +set(CommonVulkan ${CommonExtra} + Common/Vulkan/SPIRVDisasm.cpp + Common/Vulkan/SPIRVDisasm.h + Common/Vulkan/VulkanContext.cpp + Common/Vulkan/VulkanContext.h + Common/Vulkan/VulkanDebug.cpp + Common/Vulkan/VulkanDebug.h + Common/Vulkan/VulkanImage.cpp + Common/Vulkan/VulkanImage.h + Common/Vulkan/VulkanLoader.cpp + Common/Vulkan/VulkanLoader.h + Common/Vulkan/VulkanMemory.cpp + Common/Vulkan/VulkanMemory.h) add_library(Common STATIC ${CommonX86} @@ -838,15 +834,14 @@ if(ANDROID) endif() set(THIN3D_PLATFORMS ext/native/thin3d/thin3d_gl.cpp) -if(VULKAN) - set(THIN3D_PLATFORMS ${THIN3D_PLATFORMS} - ext/native/thin3d/thin3d_vulkan.cpp +set(THIN3D_PLATFORMS ${THIN3D_PLATFORMS} + ext/native/thin3d/thin3d_vulkan.cpp ext/native/thin3d/VulkanRenderManager.cpp ext/native/thin3d/VulkanRenderManager.h ext/native/thin3d/VulkanQueueRunner.cpp ext/native/thin3d/VulkanQueueRunner.h ext/native/thin3d/DataFormat.h) -endif() + if(WIN32) set(THIN3D_PLATFORMS ${THIN3D_PLATFORMS} ext/native/thin3d/thin3d_d3d9.cpp @@ -1679,7 +1674,11 @@ set(CoreExtraLibs ${CoreExtraLibs} armips) set(GlslangLibs glslang OGLCompiler OSDependent SPIRV SPVRemapper spirv-cross-glsl) target_link_libraries(${CoreLibName} Common native kirk cityhash sfmt19937 xbrz xxhash ${GlslangLibs} - ${CoreExtraLibs} ${OPENGL_LIBRARIES} ${X11_LIBRARIES} ${CMAKE_DL_LIBS} ${Vulkan_LIBRARY}) + ${CoreExtraLibs} ${OPENGL_LIBRARIES} ${X11_LIBRARIES} ${CMAKE_DL_LIBS}) + +if(VULKAN) + target_link_libraries(${CoreLibName} ${Vulkan_LIBRARY}) +endif() if(FFmpeg_FOUND) target_compile_definitions(${CoreLibName} PRIVATE USE_FFMPEG=1) diff --git a/SDL/SDLMain.cpp b/SDL/SDLMain.cpp index fb7dc5f454..4f83c5e405 100644 --- a/SDL/SDLMain.cpp +++ b/SDL/SDLMain.cpp @@ -155,16 +155,13 @@ int8_t EGL_Init() { g_eglContext = eglCreateContext(g_eglDisplay, g_eglConfig, NULL, attributes ); if (g_eglContext == EGL_NO_CONTEXT) EGL_ERROR("Unable to create GLES context!", true); -#if !defined(USING_FBDEV) +#if !defined(USING_FBDEV) && !defined(__APPLE__) //Get the SDL window handle SDL_SysWMinfo sysInfo; //Will hold our Window information SDL_VERSION(&sysInfo.version); //Set SDL version -#endif - -#ifdef USING_FBDEV - g_Window = (NativeWindowType)NULL; -#else g_Window = (NativeWindowType)sysInfo.info.x11.window; +#else + g_Window = (NativeWindowType)NULL; #endif g_eglSurface = eglCreateWindowSurface(g_eglDisplay, g_eglConfig, g_Window, 0); if (g_eglSurface == EGL_NO_SURFACE) @@ -207,7 +204,8 @@ public: delete draw_; } - bool Init(SDL_Window *&window, int x, int y, int mode, std::string *error_message); + // Returns 0 on success. + int Init(SDL_Window *&window, int x, int y, int mode, std::string *error_message); void Shutdown() override { #ifdef USING_EGL @@ -235,7 +233,8 @@ private: SDL_GLContext glContext = nullptr; }; -bool SDLGLGraphicsContext::Init(SDL_Window *&window, int x, int y, int mode, std::string *error_message) { +// Returns 0 on success. +int SDLGLGraphicsContext::Init(SDL_Window *&window, int x, int y, int mode, std::string *error_message) { struct GLVersionPair { int major; int minor; @@ -337,6 +336,7 @@ bool SDLGLGraphicsContext::Init(SDL_Window *&window, int x, int y, int mode, std bool success = draw_->CreatePresets(); assert(success); window_ = window; + return 0; } class SDLVulkanGraphicsContext : public GraphicsContext { @@ -424,6 +424,7 @@ bool SDLVulkanGraphicsContext::Init(SDL_Window *&window, int x, int y, int mode, return false; } +#if !defined(__APPLE__) SDL_SysWMinfo sys_info{}; SDL_VERSION(&sys_info.version); //Set SDL version if (!SDL_GetWindowWMInfo(window, &sys_info)) { @@ -440,6 +441,11 @@ bool SDLVulkanGraphicsContext::Init(SDL_Window *&window, int x, int y, int mode, exit(1); break; } +#else + // Fake to make it build on Apple. This code won't run there though. + void *display = nullptr; + int x11_window = 0; +#endif ILOG("Display: %p", display); #if defined(VK_USE_PLATFORM_XLIB_KHR) @@ -854,8 +860,8 @@ int main(int argc, char *argv[]) { std::string error_message; if (g_Config.iGPUBackend == GPU_BACKEND_OPENGL) { SDLGLGraphicsContext *ctx = new SDLGLGraphicsContext(); - if (!ctx->Init(window, x, y, mode, &error_message)) { - printf("GL init error '%s' - falling back to GL\n", error_message.c_str()); + if (ctx->Init(window, x, y, mode, &error_message) != 0) { + printf("GL init error '%s'\n", error_message.c_str()); } graphicsContext = ctx; } else if (g_Config.iGPUBackend == GPU_BACKEND_VULKAN) {