WIP vulkan on linux stuff

This commit is contained in:
Henrik Rydgård 2017-12-13 22:58:45 +01:00
parent c27d64f273
commit ea387b2a48
9 changed files with 266 additions and 74 deletions

View File

@ -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)

View File

@ -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;

View File

@ -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<const char *> instance_layer_names_;
std::vector<LayerProperties> instance_layer_properties_;
std::vector<const char *> instance_extensions_enabled_;
std::vector<VkExtensionProperties> instance_extension_properties_;
std::vector<const char *> device_layer_names_;
std::vector<LayerProperties> device_layer_properties_;
std::vector<const char *> device_extensions_enabled_;
std::vector<VkExtensionProperties> device_extension_properties_;
std::vector<VkPhysicalDevice> physical_devices_;
int physical_device_ = -1;

View File

@ -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);

View File

@ -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;

View File

@ -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 <X11/Xlib.h>
#include <X11/Xutil.h>
#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 <X11/Xlib.h>
#include <X11/Xutil.h>
#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;
}

View File

@ -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();

@ -1 +1 @@
Subproject commit 6537fc1bf38d0787a1d86375e5b3cb267349d2d5
Subproject commit 1e3e4a0ba0ca8c0a092e027dfb7c1c4778366db5

View File

@ -1,6 +1,7 @@
#pragma once
#include <cstdint>
#include <cstdlib>
namespace Draw {