Merge pull request #10413 from hrydgard/x11-vulkan-init

SDL/X11 Vulkan init
This commit is contained in:
Henrik Rydgård 2017-12-21 14:52:01 +01:00 committed by GitHub
commit 99f8c19d6a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 583 additions and 300 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,33 @@ 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 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)
@ -86,6 +106,12 @@ else()
message("Normal Build")
endif()
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
#if(NOT DEFINED UNITTEST)
# set(UNITTEST OFF)
@ -113,6 +139,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)
@ -325,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}
@ -808,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
@ -1640,11 +1665,21 @@ 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}
${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)
target_link_libraries(${CoreLibName}

View File

@ -109,6 +109,16 @@ 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_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
//...
#endif
if (flags_ & VULKAN_FLAG_VALIDATE) {
@ -424,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_)) {
@ -545,6 +556,7 @@ VkResult VulkanContext::CreateDevice() {
} else {
VulkanLoadDeviceFunctions(device_);
}
ILOG("Device created.\n");
return res;
}
@ -563,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);
@ -578,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();
}
}
@ -631,6 +643,31 @@ 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;
@ -684,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<VkSurfaceFormatKHR> 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,
@ -720,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_);

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

@ -17,11 +17,13 @@
#include "Common/Vulkan/VulkanLoader.h"
#include "base/logging.h"
#include "base/basictypes.h"
#ifndef _WIN32
#include <dlfcn.h>
#endif
#ifndef VULKAN_STATIC
PFN_vkCreateInstance vkCreateInstance;
PFN_vkDestroyInstance vkDestroyInstance;
@ -165,6 +167,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;
@ -179,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;
@ -195,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
@ -214,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");
@ -237,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);
@ -374,7 +399,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,12 +415,16 @@ 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);
#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.");
}
@ -404,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);
@ -421,4 +453,5 @@ void VulkanFree() {
#endif
vulkanLibrary = nullptr;
}
#endif
}

View File

@ -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;
@ -171,6 +174,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;
@ -187,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();
@ -198,4 +207,3 @@ bool VulkanLoad();
void VulkanLoadInstanceFunctions(VkInstance instance);
void VulkanLoadDeviceFunctions(VkDevice device);
void VulkanFree();

View File

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

View File

@ -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 <Windows.h>
#include <shlobj.h>
#include <shlwapi.h>
#include <ShellAPI.h>
#else
#include <unistd.h>
#include <pwd.h>
#endif
#include "SDL.h"
#ifndef _WIN32
#include "SDL/SDLJoystick.h"
SDLJoystick *joystick = NULL;
#endif
#if PPSSPP_PLATFORM(RPI)
#include <bcm_host.h>
@ -28,6 +16,7 @@ SDLJoystick *joystick = NULL;
#include <algorithm>
#include <cassert>
#include <cmath>
#include "base/display.h"
#include "base/logging.h"
@ -41,34 +30,35 @@ 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"
#include "math.h"
#if defined(VK_USE_PLATFORM_XLIB_KHR)
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include "SDL_syswm.h"
#elif defined(VK_USE_PLATFORM_XCB_KHR)
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xlib-xcb.h>
#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 GLDummyGraphicsContext : public DummyGraphicsContext {
public:
GLDummyGraphicsContext() {
CheckGLExtensions();
draw_ = Draw::T3DCreateGLContext();
bool success = draw_->CreatePresets();
assert(success);
}
~GLDummyGraphicsContext() { delete draw_; }
Draw::DrawContext *GetDrawContext() override {
return draw_;
}
private:
Draw::DrawContext *draw_;
};
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;
@ -76,16 +66,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"
#if !defined(USING_FBDEV)
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#endif
#include "SDL_syswm.h"
#include "math.h"
static EGLDisplay g_eglDisplay = NULL;
static EGLContext g_eglContext = NULL;
@ -172,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)
@ -216,6 +196,293 @@ void EGL_Close() {
}
#endif
class SDLGLGraphicsContext : public DummyGraphicsContext {
public:
SDLGLGraphicsContext() {
}
~SDLGLGraphicsContext() {
delete draw_;
}
// 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
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;
};
// 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;
};
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;
return 0;
}
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) {
window = SDL_CreateWindow("Initializing Vulkan...", x, y, pixel_xres, pixel_yres, mode);
if (!window) {
fprintf(stderr, "Error creating SDL window: %s\n", SDL_GetError());
exit(1);
}
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;
}
#if !defined(__APPLE__)
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;
}
#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)
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();
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;
@ -399,11 +666,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) {
@ -411,7 +678,7 @@ void ToggleFullScreenIfFlagSet() {
} else {
window_flags &= ~SDL_WINDOW_FULLSCREEN_DESKTOP;
}
SDL_SetWindowFullscreen(g_Screen, window_flags);
SDL_SetWindowFullscreen(window, window_flags);
}
}
@ -419,57 +686,20 @@ 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");
std::string app_name;
std::string app_name_nice;
std::string version;
bool landscape;
NativeGetAppInfo(&app_name, &app_name_nice, &landscape, &version);
bool joystick_enabled = true;
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER | SDL_INIT_AUDIO) < 0) {
joystick_enabled = false;
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0) {
fprintf(stderr, "Unable to initialize SDL: %s\n", SDL_GetError());
return 1;
}
if (VulkanMayBeAvailable()) {
printf("Vulkan might be available.\n");
} else {
printf("Vulkan is not available.\n");
}
#ifdef USING_EGL
if (EGL_Open())
return 1;
#endif
// Get the video info before doing anything else, so we don't get skewed resolution results.
// TODO: support multiple displays correctly
SDL_DisplayMode displayMode;
int should_be_zero = SDL_GetCurrentDisplayMode(0, &displayMode);
if (should_be_zero != 0) {
fprintf(stderr, "Could not get display mode: %s\n", SDL_GetError());
return 1;
}
g_DesktopWidth = displayMode.w;
g_DesktopHeight = displayMode.h;
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetSwapInterval(1);
Uint32 mode;
#ifdef USING_GLES2
mode = SDL_WINDOW_OPENGL | SDL_WINDOW_FULLSCREEN;
#else
mode = SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE;
#endif
int set_xres = -1;
int set_yres = -1;
bool portrait = false;
@ -481,6 +711,7 @@ int main(int argc, char *argv[]) {
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;
@ -509,6 +740,47 @@ int main(int argc, char *argv[]) {
}
}
std::string app_name;
std::string app_name_nice;
std::string version;
bool landscape;
NativeGetAppInfo(&app_name, &app_name_nice, &landscape, &version);
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());
return 1;
}
}
// TODO: How do we get this into the GraphicsContext?
#ifdef USING_EGL
if (EGL_Open())
return 1;
#endif
// Get the video info before doing anything else, so we don't get skewed resolution results.
// TODO: support multiple displays correctly
SDL_DisplayMode displayMode;
int should_be_zero = SDL_GetCurrentDisplayMode(0, &displayMode);
if (should_be_zero != 0) {
fprintf(stderr, "Could not get display mode: %s\n", SDL_GetError());
return 1;
}
g_DesktopWidth = displayMode.w;
g_DesktopHeight = displayMode.h;
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetSwapInterval(1);
// Is resolution is too low to run windowed
if (g_DesktopWidth < 480 * 2 && g_DesktopHeight < 272 * 2) {
mode |= SDL_WINDOW_FULLSCREEN_DESKTOP;
@ -552,12 +824,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");
@ -569,13 +835,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)
@ -584,107 +845,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_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
g_Screen = SDL_CreateWindow(app_name_nice.c_str(), x,y, pixel_xres, pixel_yres, mode);
if (g_Screen == nullptr) {
fprintf(stderr, "SDL_CreateWindow failed: %s\n", SDL_GetError());
continue;
}
glContext = SDL_GL_CreateContext(g_Screen);
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(g_Screen);
}
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);
g_Screen = SDL_CreateWindow(app_name_nice.c_str(), x,y, pixel_xres, pixel_yres, mode);
if (g_Screen == nullptr) {
NativeShutdown();
fprintf(stderr, "SDL_CreateWindow failed: %s\n", SDL_GetError());
SDL_Quit();
return 2;
}
glContext = SDL_GL_CreateContext(g_Screen);
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(g_Screen, (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;
@ -695,9 +855,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);
glslang::InitializeProcess();
GraphicsContext *graphicsContext = nullptr;
SDL_Window *window = nullptr;
std::string error_message;
if (g_Config.iGPUBackend == GPU_BACKEND_OPENGL) {
SDLGLGraphicsContext *ctx = new SDLGLGraphicsContext();
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) {
SDLVulkanGraphicsContext *ctx = new SDLVulkanGraphicsContext();
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;
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
GraphicsContext *graphicsContext = new GLDummyGraphicsContext();
NativeInitGraphics(graphicsContext);
NativeResized();
@ -728,18 +914,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) {
@ -758,7 +940,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;
@ -900,11 +1082,9 @@ int main(int argc, char *argv[]) {
}
break;
default:
#ifndef _WIN32
if (joystick) {
joystick->ProcessInput(event);
}
#endif
break;
}
}
@ -928,44 +1108,25 @@ 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();
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();
@ -190,7 +191,7 @@ void GameSettingsScreen::CreateViews() {
}
#endif
bool vulkanAvailable = false;
#if PPSSPP_PLATFORM(WINDOWS) || PPSSPP_PLATFORM(ANDROID)
#ifndef IOS
vulkanAvailable = VulkanMayBeAvailable();
#endif
if (!vulkanAvailable) {

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

View File

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