diff --git a/CMakeLists.txt b/CMakeLists.txt index 628831ba30..a8915f868a 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,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) @@ -130,7 +160,10 @@ if(NOT OPENGL_LIBRARIES AND USING_GLES2) endif() if(USING_EGL) - set(OPENGL_LIBRARIES ${OPENGL_LIBRARIES} EGL) + if(NOT EGL_LIBRARIES) + set(EGL_LIBRARIES EGL) + endif() + set(OPENGL_LIBRARIES ${OPENGL_LIBRARIES} ${EGL_LIBRARIES}) endif() if(NOT OPENGL_LIBRARIES) @@ -322,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} @@ -696,8 +725,8 @@ elseif(USING_QT_UI) qt5_wrap_ui(QT_UI_GEN ${Qt_UI}) list(APPEND NativeAppSource ${QT_UI_GEN} - ext/native/base/QtMain.cpp - ext/native/base/QtMain.h + Qt/QtMain.cpp + Qt/QtMain.h Qt/mainwindow.cpp Qt/mainwindow.h Qt/Debugger/ctrldisasmview.cpp @@ -742,16 +771,13 @@ elseif(TARGET SDL2::SDL2) set(nativeExtra ${nativeExtra} SDL/SDLJoystick.h SDL/SDLJoystick.cpp - ext/native/base/PCMain.cpp) + SDL/SDLMain.cpp) set(nativeExtraLibs ${nativeExtraLibs} SDL2::SDL2) if(APPLE) set(nativeExtra ${nativeExtra} SDL/SDLMain.h SDL/SDLMain.mm) set(nativeExtraLibs ${nativeExtraLibs} ${COCOA_LIBRARY}) elseif(USING_EGL) - if(NOT EGL_LIBRARIES) - set(EGL_LIBRARIES EGL) - endif() - set(nativeExtraLibs ${nativeExtraLibs} pthread ${EGL_LIBRARIES}) + set(nativeExtraLibs ${nativeExtraLibs} pthread) endif() set(TargetBin PPSSPPSDL) elseif(WIN32) @@ -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} diff --git a/Common/Vulkan/VulkanContext.cpp b/Common/Vulkan/VulkanContext.cpp index c70e492b72..c0f7f5f6ba 100644 --- a/Common/Vulkan/VulkanContext.cpp +++ b/Common/Vulkan/VulkanContext.cpp @@ -95,13 +95,13 @@ VulkanContext::VulkanContext() { GetInstanceLayerExtensionList(nullptr, instance_extension_properties_); } -VkResult VulkanContext::CreateInstance(const char *app_name, int app_ver, uint32_t flags) { +VkResult VulkanContext::CreateInstance(const CreateInfo &info) { if (!vkCreateInstance) { init_error_ = "Vulkan not loaded - can't create instance"; return VK_ERROR_INITIALIZATION_FAILED; } - flags_ = flags; + flags_ = info.flags; // List extensions to try to enable. instance_extensions_enabled_.push_back(VK_KHR_SURFACE_EXTENSION_NAME); @@ -109,6 +109,16 @@ VkResult VulkanContext::CreateInstance(const char *app_name, int app_ver, uint32 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) { @@ -120,9 +130,9 @@ VkResult VulkanContext::CreateInstance(const char *app_name, int app_ver, uint32 } VkApplicationInfo app_info { VK_STRUCTURE_TYPE_APPLICATION_INFO }; - app_info.pApplicationName = app_name; - app_info.applicationVersion = app_ver; - app_info.pEngineName = app_name; + app_info.pApplicationName = info.app_name; + app_info.applicationVersion = info.app_ver; + app_info.pEngineName = info.app_name; // Let's increment this when we make major engine/context changes. app_info.engineVersion = 2; app_info.apiVersion = VK_API_VERSION_1_0; @@ -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,70 +590,91 @@ 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(); } } +void VulkanContext::InitSurface(WindowSystem winsys, void *data1, void *data2, int width, int height) { + winsys_ = winsys; + winsysData1_ = data1; + winsysData2_ = data2; + ReinitSurface(width, height); +} + +void VulkanContext::ReinitSurface(int width, int height) { + if (surface_ != VK_NULL_HANDLE) { + ILOG("Destroying Vulkan surface (%d, %d)", width_, height_); + vkDestroySurfaceKHR(instance_, surface_, nullptr); + surface_ = VK_NULL_HANDLE; + } + + ILOG("Creating Vulkan surface (%d, %d)", width, height); + switch (winsys_) { #ifdef _WIN32 -void VulkanContext::InitSurfaceWin32(HINSTANCE conn, HWND wnd) { - connection = conn; - window = wnd; + case WINDOWSYSTEM_WIN32: + { + HINSTANCE connection = (HINSTANCE)winsysData1_; + HWND window = (HWND)winsysData2_; - ReinitSurfaceWin32(); -} + RECT rc; + GetClientRect(window, &rc); + width = rc.right - rc.left; + height = rc.bottom - rc.top; -void VulkanContext::ReinitSurfaceWin32() { - if (surface_ != VK_NULL_HANDLE) { - vkDestroySurfaceKHR(instance_, surface_, nullptr); - surface_ = VK_NULL_HANDLE; + VkWin32SurfaceCreateInfoKHR win32{ VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR }; + win32.flags = 0; + win32.hwnd = window; + win32.hinstance = connection; + VkResult res = vkCreateWin32SurfaceKHR(instance_, &win32, nullptr, &surface_); + assert(res == VK_SUCCESS); + break; } - - RECT rc; - GetClientRect(window, &rc); - width_ = rc.right - rc.left; - height_ = rc.bottom - rc.top; - - VkResult U_ASSERT_ONLY res; - - VkWin32SurfaceCreateInfoKHR win32 = { VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR }; - win32.flags = 0; - win32.hwnd = window; - win32.hinstance = connection; - res = vkCreateWin32SurfaceKHR(instance_, &win32, nullptr, &surface_); - - assert(res == VK_SUCCESS); -} - -#elif defined(__ANDROID__) - -void VulkanContext::InitSurfaceAndroid(ANativeWindow *wnd, int width, int height) { - native_window = wnd; - - ReinitSurfaceAndroid(width, height); -} - -void VulkanContext::ReinitSurfaceAndroid(int width, int height) { - if (surface_ != VK_NULL_HANDLE) { - ILOG("Destroying Android Vulkan surface (%d, %d)", width_, height_); - vkDestroySurfaceKHR(instance_, surface_, nullptr); - surface_ = VK_NULL_HANDLE; +#endif +#if defined(__ANDROID__) + case WINDOWSYSTEM_ANDROID: + { + ANativeWindow *wnd = (ANativeWindow *)winsysData1_; + VkAndroidSurfaceCreateInfoKHR android{ VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR }; + android.flags = 0; + android.window = wnd; + VkResult res = vkCreateAndroidSurfaceKHR(instance_, &android, nullptr, &surface_); + assert(res == VK_SUCCESS); + 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 - VkResult U_ASSERT_ONLY res; - - ILOG("Creating Android Vulkan surface (%d, %d)", width, height); - - VkAndroidSurfaceCreateInfoKHR android = { VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR }; - android.flags = 0; - android.window = native_window; - res = vkCreateAndroidSurfaceKHR(instance_, &android, nullptr, &surface_); - assert(res == VK_SUCCESS); - + default: + _assert_msg_(G3D, false, "Vulkan support for chosen window system not implemented"); + break; + } width_ = width; height_ = height; } -#endif bool VulkanContext::InitQueue() { // Iterate over each queue to learn whether it supports presenting: @@ -688,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, @@ -724,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_); @@ -732,11 +765,8 @@ bool VulkanContext::InitQueue() { } bool VulkanContext::InitSwapchain() { - VkResult U_ASSERT_ONLY res; - - res = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physical_devices_[physical_device_], surface_, &surfCapabilities_); + VkResult res = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physical_devices_[physical_device_], surface_, &surfCapabilities_); assert(res == VK_SUCCESS); - uint32_t presentModeCount; res = vkGetPhysicalDeviceSurfacePresentModesKHR(physical_devices_[physical_device_], surface_, &presentModeCount, nullptr); assert(res == VK_SUCCESS); diff --git a/Common/Vulkan/VulkanContext.h b/Common/Vulkan/VulkanContext.h index d0de32ca72..0c60a3bef2 100644 --- a/Common/Vulkan/VulkanContext.h +++ b/Common/Vulkan/VulkanContext.h @@ -1,41 +1,16 @@ -#ifndef UTIL_INIT -#define UTIL_INIT +#pragma once -#ifdef __ANDROID__ -#undef NDEBUG // asserts -#endif #include #include #include #include #include "base/logging.h" - -#ifdef _WIN32 -#define WIN32_LEAN_AND_MEAN -#define VK_USE_PLATFORM_WIN32_KHR -#define NOMINMAX /* Don't let Windows define min() or max() */ -#define APP_NAME_STR_LEN 80 -#include -#elif defined(__ANDROID__) // _WIN32 -#include -#define VK_USE_PLATFORM_ANDROID_KHR -#else -#define VK_USE_PLATFORM_XCB_KHR -#include -#endif // _WIN32 - #include "Common/Vulkan/VulkanLoader.h" // Amount of time, in nanoseconds, to wait for a command buffer to complete #define FENCE_TIMEOUT 10000000000 -#if defined(NDEBUG) && defined(__GNUC__) -#define U_ASSERT_ONLY __attribute__((unused)) -#else -#define U_ASSERT_ONLY -#endif - enum { VULKAN_FLAG_VALIDATE = 1, VULKAN_FLAG_PRESENT_MAILBOX = 2, @@ -54,6 +29,21 @@ enum { std::string VulkanVendorString(uint32_t vendorId); +// Not all will be usable on all platforms, of course... +enum WindowSystem { +#ifdef _WIN32 + WINDOWSYSTEM_WIN32, +#endif +#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 { VkFormat preferredDepthStencilFormat; @@ -117,7 +107,13 @@ public: VulkanContext(); ~VulkanContext(); - VkResult CreateInstance(const char *app_name, int app_ver, uint32_t flags); + struct CreateInfo { + const char *app_name; + int app_ver; + uint32_t flags; + }; + + VkResult CreateInstance(const CreateInfo &info); void DestroyInstance(); int GetBestPhysicalDevice(); @@ -134,13 +130,10 @@ public: VkPipelineCache CreatePipelineCache(); -#ifdef _WIN32 - void InitSurfaceWin32(HINSTANCE conn, HWND wnd); - void ReinitSurfaceWin32(); -#elif __ANDROID__ - void InitSurfaceAndroid(ANativeWindow *native_window, int width, int height); - void ReinitSurfaceAndroid(int width, int height); -#endif + // 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,12 +231,11 @@ private: bool CheckLayers(const std::vector &layer_props, const std::vector &layer_names) const; -#ifdef _WIN32 - HINSTANCE connection = nullptr; // hInstance - Windows Instance - HWND window = nullptr; // hWnd - window handle -#elif __ANDROID__ // _WIN32 - ANativeWindow *native_window = nullptr; -#endif // _WIN32 + WindowSystem winsys_; + // Don't use the real types here to avoid having to include platform-specific stuff + // that we really don't want in everything that uses VulkanContext. + void *winsysData1_; + void *winsysData2_; VkInstance instance_ = VK_NULL_HANDLE; VkDevice device_ = VK_NULL_HANDLE; @@ -253,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; @@ -320,6 +312,3 @@ void finalize_glslang(); bool GLSLtoSPV(const VkShaderStageFlagBits shader_type, const char *pshader, std::vector &spirv, std::string *errorMessage = nullptr); const char *VulkanResultToString(VkResult res); - -#endif // UTIL_INIT - diff --git a/Common/Vulkan/VulkanImage.cpp b/Common/Vulkan/VulkanImage.cpp index 05e0f2ac80..143ad16332 100644 --- a/Common/Vulkan/VulkanImage.cpp +++ b/Common/Vulkan/VulkanImage.cpp @@ -21,9 +21,7 @@ void VulkanTexture::CreateMappableImage() { vulkan_->Delete().QueueDeleteDeviceMemory(mappableMemory); } - bool U_ASSERT_ONLY pass; - - VkImageCreateInfo image_create_info = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO }; + VkImageCreateInfo image_create_info{ VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO }; image_create_info.imageType = VK_IMAGE_TYPE_2D; image_create_info.format = format_; image_create_info.extent.width = tex_width; @@ -40,7 +38,7 @@ void VulkanTexture::CreateMappableImage() { image_create_info.flags = 0; image_create_info.initialLayout = VK_IMAGE_LAYOUT_PREINITIALIZED; - VkMemoryAllocateInfo mem_alloc = { VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO }; + VkMemoryAllocateInfo mem_alloc{ VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO }; mem_alloc.allocationSize = 0; mem_alloc.memoryTypeIndex = 0; @@ -55,7 +53,7 @@ void VulkanTexture::CreateMappableImage() { mem_alloc.allocationSize = mem_reqs.size; // Find the memory type that is host mappable. - pass = vulkan_->MemoryTypeFromProperties(mem_reqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &mem_alloc.memoryTypeIndex); + bool pass = vulkan_->MemoryTypeFromProperties(mem_reqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &mem_alloc.memoryTypeIndex); assert(pass); res = vkAllocateMemory(vulkan_->GetDevice(), &mem_alloc, NULL, &mappableMemory); @@ -264,23 +262,6 @@ bool VulkanTexture::CreateDirect(VkCommandBuffer cmd, int w, int h, int numMips, return false; } - // Write a command to transition the image to the requested layout, if it's not already that layout. - if (initialLayout != VK_IMAGE_LAYOUT_UNDEFINED && initialLayout != VK_IMAGE_LAYOUT_PREINITIALIZED) { - switch (initialLayout) { - case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: - TransitionImageLayout2(cmd, image, 0, numMips, VK_IMAGE_ASPECT_COLOR_BIT, - VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, - 0, VK_ACCESS_TRANSFER_WRITE_BIT); - break; - default: - // If you planned to use UploadMip, you want VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL. After the - // upload, you can transition. - assert(false); - break; - } - } - vkGetImageMemoryRequirements(vulkan_->GetDevice(), image, &mem_reqs); if (allocator_) { @@ -313,6 +294,23 @@ bool VulkanTexture::CreateDirect(VkCommandBuffer cmd, int w, int h, int numMips, return false; } + // Write a command to transition the image to the requested layout, if it's not already that layout. + if (initialLayout != VK_IMAGE_LAYOUT_UNDEFINED && initialLayout != VK_IMAGE_LAYOUT_PREINITIALIZED) { + switch (initialLayout) { + case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: + TransitionImageLayout2(cmd, image, 0, numMips, VK_IMAGE_ASPECT_COLOR_BIT, + VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, + 0, VK_ACCESS_TRANSFER_WRITE_BIT); + break; + default: + // If you planned to use UploadMip, you want VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL. After the + // upload, you can transition. + assert(false); + break; + } + } + // Create the view while we're at it. VkImageViewCreateInfo view_info = { VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO }; view_info.image = image; diff --git a/Common/Vulkan/VulkanLoader.cpp b/Common/Vulkan/VulkanLoader.cpp index 7b8e83c91f..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; @@ -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 } diff --git a/Common/Vulkan/VulkanLoader.h b/Common/Vulkan/VulkanLoader.h index 67042c0c0c..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; @@ -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(); - diff --git a/Core/Config.cpp b/Core/Config.cpp index bb1e3113d1..5fa7ce1220 100644 --- a/Core/Config.cpp +++ b/Core/Config.cpp @@ -531,12 +531,9 @@ static ConfigSetting graphicsSettings[] = { #endif ReportedConfigSetting("ForceMaxEmulatedFPS", &g_Config.iForceMaxEmulatedFPS, 60, true, true), - // TODO: Hm, on fast mobile GPUs we should definitely default to at least 4 (setting = 2)... -#ifdef MOBILE_DEVICE - ConfigSetting("AnisotropyLevel", &g_Config.iAnisotropyLevel, 0, true, true), -#else + // Most low-performance (and many high performance) mobile GPUs do not support aniso anyway so defaulting to 4 is fine. ConfigSetting("AnisotropyLevel", &g_Config.iAnisotropyLevel, 4, true, true), -#endif + ReportedConfigSetting("VertexDecCache", &g_Config.bVertexCache, &DefaultVertexCache, true, true), ReportedConfigSetting("TextureBackoffCache", &g_Config.bTextureBackoffCache, false, true, true), ReportedConfigSetting("TextureSecondaryCache", &g_Config.bTextureSecondaryCache, false, true, true), diff --git a/Core/Core.cpp b/Core/Core.cpp index 73696842f6..c93cc683c6 100644 --- a/Core/Core.cpp +++ b/Core/Core.cpp @@ -18,7 +18,9 @@ #include "ppsspp_config.h" #include +#include #include +#include #include "base/NativeApp.h" #include "base/display.h" @@ -46,9 +48,9 @@ // Should this be configurable? 2 hours currently. static const double ACTIVITY_IDLE_TIMEOUT = 2.0 * 3600.0; -static event m_hStepEvent; +static std::condition_variable m_StepCond; static std::mutex m_hStepMutex; -static event m_hInactiveEvent; +static std::condition_variable m_InactiveCond; static std::mutex m_hInactiveMutex; static bool singleStepPending = false; static std::set shutdownFuncs; @@ -95,7 +97,7 @@ void Core_Halt(const char *msg) { void Core_Stop() { Core_UpdateState(CORE_POWERDOWN); Core_NotifyShutdown(); - m_hStepEvent.notify_one(); + m_StepCond.notify_one(); } bool Core_IsStepping() { @@ -112,13 +114,15 @@ bool Core_IsInactive() { void Core_WaitInactive() { while (Core_IsActive()) { - m_hInactiveEvent.wait(m_hInactiveMutex); + std::unique_lock guard(m_hInactiveMutex); + m_InactiveCond.wait(guard); } } void Core_WaitInactive(int milliseconds) { if (Core_IsActive()) { - m_hInactiveEvent.wait_for(m_hInactiveMutex, milliseconds); + std::unique_lock guard(m_hInactiveMutex); + m_InactiveCond.wait_for(guard, std::chrono::milliseconds(milliseconds)); } } @@ -191,11 +195,16 @@ void UpdateRunLoop() { } } +void KeepScreenAwake() { +#ifdef _WIN32 + SetThreadExecutionState(ES_SYSTEM_REQUIRED | ES_DISPLAY_REQUIRED); +#endif +} + void Core_RunLoop(GraphicsContext *ctx) { graphicsContext = ctx; while ((GetUIState() != UISTATE_INGAME || !PSP_IsInited()) && GetUIState() != UISTATE_EXIT) { time_update(); -#if defined(USING_WIN_UI) double startTime = time_now_d(); UpdateRunLoop(); @@ -204,19 +213,15 @@ void Core_RunLoop(GraphicsContext *ctx) { double diffTime = time_now_d() - startTime; int sleepTime = (int)(1000.0 / 60.0) - (int)(diffTime * 1000.0); if (sleepTime > 0) - Sleep(sleepTime); + sleep_ms(sleepTime); if (!windowHidden) { ctx->SwapBuffers(); } -#else - UpdateRunLoop(); -#endif } while (!coreState && GetUIState() == UISTATE_INGAME) { time_update(); UpdateRunLoop(); -#if defined(USING_WIN_UI) if (!windowHidden && !Core_IsStepping()) { ctx->SwapBuffers(); @@ -226,22 +231,21 @@ void Core_RunLoop(GraphicsContext *ctx) { // Only resetting it ever prime number seconds in case the call is expensive. // Using a prime number to ensure there's no interaction with other periodic events. if (now - lastKeepAwake > 89.0 || now < lastKeepAwake) { - SetThreadExecutionState(ES_SYSTEM_REQUIRED | ES_DISPLAY_REQUIRED); + KeepScreenAwake(); lastKeepAwake = now; } } } -#endif } } void Core_DoSingleStep() { singleStepPending = true; - m_hStepEvent.notify_one(); + m_StepCond.notify_one(); } void Core_UpdateSingleStep() { - m_hStepEvent.notify_one(); + m_StepCond.notify_one(); } void Core_SingleStep() { @@ -251,20 +255,15 @@ void Core_SingleStep() { static inline void CoreStateProcessed() { if (coreStatePending) { coreStatePending = false; - m_hInactiveEvent.notify_one(); + m_InactiveCond.notify_one(); } } -// Some platforms, like Android, do not call this function but handle things on their own. -void Core_Run(GraphicsContext *ctx) -{ -#if defined(_DEBUG) +// Many platforms, like Android, do not call this function but handle things on their own. +// Instead they simply call NativeRender and NativeUpdate directly. +void Core_Run(GraphicsContext *ctx) { host->UpdateDisassembly(); -#endif -#if !defined(USING_QT_UI) || defined(MOBILE_DEVICE) - while (true) -#endif - { + while (true) { reswitch: if (GetUIState() != UISTATE_INGAME) { CoreStateProcessed(); @@ -272,15 +271,10 @@ reswitch: return; } Core_RunLoop(ctx); -#if defined(USING_QT_UI) && !defined(MOBILE_DEVICE) - return; -#else continue; -#endif } - switch (coreState) - { + switch (coreState) { case CORE_RUNNING: // enter a fast runloop Core_RunLoop(ctx); @@ -298,21 +292,16 @@ reswitch: } // wait for step command.. -#if defined(USING_QT_UI) || defined(_DEBUG) host->UpdateDisassembly(); host->UpdateMemView(); host->SendCoreWait(true); -#endif - m_hStepEvent.wait(m_hStepMutex); + { + std::unique_lock guard(m_hStepMutex); + m_StepCond.wait(guard); + } -#if defined(USING_QT_UI) || defined(_DEBUG) host->SendCoreWait(false); -#endif -#if defined(USING_QT_UI) && !defined(MOBILE_DEVICE) - if (coreState != CORE_STEPPING) - return; -#endif // No step pending? Let's go back to the wait. if (!singleStepPending || coreState != CORE_STEPPING) { if (coreState == CORE_POWERDOWN) { @@ -323,10 +312,8 @@ reswitch: Core_SingleStep(); // update disasm dialog -#if defined(USING_QT_UI) || defined(_DEBUG) host->UpdateDisassembly(); host->UpdateMemView(); -#endif break; case CORE_POWERUP: @@ -346,17 +333,12 @@ reswitch: void Core_EnableStepping(bool step) { if (step) { sleep_ms(1); -#if defined(_DEBUG) host->SetDebugMode(true); -#endif - m_hStepEvent.reset(); Core_UpdateState(CORE_STEPPING); } else { -#if defined(_DEBUG) host->SetDebugMode(false); -#endif coreState = CORE_RUNNING; coreStatePending = false; - m_hStepEvent.notify_one(); + m_StepCond.notify_one(); } } diff --git a/Core/HLE/sceSas.cpp b/Core/HLE/sceSas.cpp index c6666beb55..73409c5eeb 100644 --- a/Core/HLE/sceSas.cpp +++ b/Core/HLE/sceSas.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include "base/basictypes.h" #include "profiler/profiler.h" diff --git a/Core/Reporting.cpp b/Core/Reporting.cpp index 930cc8a180..7b9e40af03 100644 --- a/Core/Reporting.cpp +++ b/Core/Reporting.cpp @@ -16,6 +16,8 @@ // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. #include +#include +#include #include "Core/Reporting.h" diff --git a/Core/System.cpp b/Core/System.cpp index aea38360ea..0c274f58f2 100644 --- a/Core/System.cpp +++ b/Core/System.cpp @@ -24,8 +24,10 @@ #include #include #endif + #include #include +#include #include "math/math_util.h" #include "thread/threadutil.h" diff --git a/GPU/Common/TextureCacheCommon.cpp b/GPU/Common/TextureCacheCommon.cpp index 806aec4bfc..953d64c202 100644 --- a/GPU/Common/TextureCacheCommon.cpp +++ b/GPU/Common/TextureCacheCommon.cpp @@ -910,12 +910,7 @@ void TextureCacheCommon::NotifyConfigChanged() { } } - // Mobile devices don't get the higher scale factors, too expensive. Very rough way to decide though... - if (!gstate_c.Supports(GPU_IS_MOBILE)) { - scaleFactor = std::min(5, scaleFactor); - } else { - scaleFactor = std::min(3, scaleFactor); - } + scaleFactor = std::min(5, scaleFactor); } else { scaleFactor = g_Config.iTexScalingLevel; } diff --git a/GPU/GLES/GPU_GLES.cpp b/GPU/GLES/GPU_GLES.cpp index 8ba73cbd87..6fc70b7ef7 100644 --- a/GPU/GLES/GPU_GLES.cpp +++ b/GPU/GLES/GPU_GLES.cpp @@ -342,11 +342,6 @@ void GPU_GLES::CheckGPUFeatures() { features |= GPU_USE_CLEAR_RAM_HACK; } -#ifdef MOBILE_DEVICE - // Arguably, we should turn off GPU_IS_MOBILE on like modern Tegras, etc. - features |= GPU_IS_MOBILE; -#endif - gstate_c.featureFlags = features; } diff --git a/GPU/GPUState.h b/GPU/GPUState.h index 58fd4b127b..060fffb47d 100644 --- a/GPU/GPUState.h +++ b/GPU/GPUState.h @@ -490,7 +490,6 @@ enum { GPU_SUPPORTS_ARB_FRAMEBUFFER_BLIT = FLAG_BIT(26), GPU_SUPPORTS_NV_FRAMEBUFFER_BLIT = FLAG_BIT(27), GPU_SUPPORTS_OES_TEXTURE_NPOT = FLAG_BIT(28), - GPU_IS_MOBILE = FLAG_BIT(29), GPU_PREFER_CPU_DOWNLOAD = FLAG_BIT(30), GPU_PREFER_REVERSE_COLOR_ORDER = FLAG_BIT(31), }; diff --git a/GPU/Vulkan/VertexShaderGeneratorVulkan.cpp b/GPU/Vulkan/VertexShaderGeneratorVulkan.cpp index cb9f230b01..aa457ede94 100644 --- a/GPU/Vulkan/VertexShaderGeneratorVulkan.cpp +++ b/GPU/Vulkan/VertexShaderGeneratorVulkan.cpp @@ -173,27 +173,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/ext/native/base/QtMain.cpp b/Qt/QtMain.cpp similarity index 100% rename from ext/native/base/QtMain.cpp rename to Qt/QtMain.cpp diff --git a/ext/native/base/QtMain.h b/Qt/QtMain.h similarity index 100% rename from ext/native/base/QtMain.h rename to Qt/QtMain.h diff --git a/Qt/mainwindow.h b/Qt/mainwindow.h index 51ffceb0de..c52120820e 100644 --- a/Qt/mainwindow.h +++ b/Qt/mainwindow.h @@ -14,7 +14,7 @@ #include "Debugger/debugger_memory.h" #include "Debugger/debugger_memorytex.h" #include "Debugger/debugger_displaylist.h" -#include "base/QtMain.h" +#include "Qt/QtMain.h" extern bool g_TakeScreenshot; diff --git a/ext/native/base/PCMain.cpp b/SDL/SDLMain.cpp similarity index 76% rename from ext/native/base/PCMain.cpp rename to SDL/SDLMain.cpp index 128e045d4c..f3202d24bf 100644 --- a/ext/native/base/PCMain.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" @@ -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 +#include +#include "SDL_syswm.h" +#elif defined(VK_USE_PLATFORM_XCB_KHR) +#include +#include +#include +#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 -#include -#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,298 @@ 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 + }; + +#ifdef USING_GLES2 + mode |= SDL_WINDOW_OPENGL | SDL_WINDOW_FULLSCREEN; +#else + mode |= SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE; +#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 +671,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 +683,7 @@ void ToggleFullScreenIfFlagSet() { } else { window_flags &= ~SDL_WINDOW_FULLSCREEN_DESKTOP; } - SDL_SetWindowFullscreen(g_Screen, window_flags); + SDL_SetWindowFullscreen(window, window_flags); } } @@ -419,57 +691,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 +716,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 +745,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 +829,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 +840,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,100 +850,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[] = { - {4, 6}, {4, 5}, {4, 4}, {4, 3}, {4, 2}, {4, 1}, {4, 0}, - {3, 3}, {3, 2}, {3, 1}, {3, 0}, - }; - - 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_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, ver.major); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, ver.minor); - SetGLCoreContext(true); - - 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) { - // 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; @@ -688,9 +860,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(); @@ -721,18 +919,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) { @@ -751,7 +945,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; @@ -893,11 +1087,9 @@ int main(int argc, char *argv[]) { } break; default: -#ifndef _WIN32 if (joystick) { joystick->ProcessInput(event); } -#endif break; } } @@ -921,44 +1113,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; } diff --git a/UI/GameSettingsScreen.cpp b/UI/GameSettingsScreen.cpp index 3e44ab0cb6..327a9d4358 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(); @@ -191,7 +192,7 @@ void GameSettingsScreen::CreateViews() { } #endif bool vulkanAvailable = false; -#if PPSSPP_PLATFORM(WINDOWS) || PPSSPP_PLATFORM(ANDROID) +#ifndef IOS vulkanAvailable = VulkanMayBeAvailable(); #endif if (!vulkanAvailable) { diff --git a/UI/RemoteISOScreen.cpp b/UI/RemoteISOScreen.cpp index 638a93a0db..0ae4fec31c 100644 --- a/UI/RemoteISOScreen.cpp +++ b/UI/RemoteISOScreen.cpp @@ -17,6 +17,8 @@ #include #include +#include +#include #include "base/timeutil.h" #include "ext/vjson/json.h" diff --git a/Windows/EmuThread.cpp b/Windows/EmuThread.cpp index 0dac8c9df1..b48f92e394 100644 --- a/Windows/EmuThread.cpp +++ b/Windows/EmuThread.cpp @@ -1,4 +1,6 @@ #include +#include +#include #include "base/timeutil.h" #include "base/NativeApp.h" @@ -21,20 +23,13 @@ #include "Core/Config.h" #include "thread/threadutil.h" -#include -#include -#include - -#pragma intrinsic(_InterlockedExchange) - static std::mutex emuThreadLock; -static HANDLE emuThread; -static volatile long emuThreadReady; +static std::thread emuThread; +static std::atomic emuThreadState; extern std::vector GetWideCmdLine(); -enum EmuThreadStatus : long -{ +enum EmuThreadStatus : int { THREAD_NONE = 0, THREAD_INIT, THREAD_CORE_LOOP, @@ -42,75 +37,51 @@ enum EmuThreadStatus : long THREAD_END, }; -HANDLE EmuThread_GetThreadHandle() -{ +void EmuThreadFunc(); + +void EmuThread_Start() { std::lock_guard guard(emuThreadLock); - return emuThread; + emuThread = std::thread(&EmuThreadFunc); } -unsigned int WINAPI TheThread(void *); - -void EmuThread_Start() -{ - std::lock_guard guard(emuThreadLock); - emuThread = (HANDLE)_beginthreadex(0, 0, &TheThread, 0, 0, 0); -} - -void EmuThread_Stop() -{ +void EmuThread_Stop() { // Already stopped? { std::lock_guard guard(emuThreadLock); - if (emuThread == NULL || emuThreadReady == THREAD_END) + if (emuThreadState == THREAD_END) return; } UpdateUIState(UISTATE_EXIT); Core_Stop(); Core_WaitInactive(800); - if (WAIT_TIMEOUT == WaitForSingleObject(emuThread, 800)) - { - //_dbg_assert_msg_(COMMON, false, "Wait for EmuThread timed out."); - } - { - std::lock_guard guard(emuThreadLock); - CloseHandle(emuThread); - emuThread = 0; - } + emuThread.join(); + PostMessage(MainWindow::GetHWND(), MainWindow::WM_USER_UPDATE_UI, 0, 0); } -bool EmuThread_Ready() -{ - return emuThreadReady == THREAD_CORE_LOOP; +bool EmuThread_Ready() { + return emuThreadState == THREAD_CORE_LOOP; } -unsigned int WINAPI TheThread(void *) -{ - _InterlockedExchange(&emuThreadReady, THREAD_INIT); +void EmuThreadFunc() { + emuThreadState = THREAD_INIT; - setCurrentThreadName("Emu"); // And graphics... + setCurrentThreadName("Emu"); host = new WindowsHost(MainWindow::GetHInstance(), MainWindow::GetHWND(), MainWindow::GetDisplayHWND()); host->SetWindowTitle(nullptr); - // Convert the command-line arguments to Unicode, then to proper UTF-8 - // (the benefit being that we don't have to pollute the UI project with win32 ifdefs and lots of ConvertTo). - // This avoids issues with PPSSPP inadvertently destroying paths with Unicode glyphs - // (using the ANSI args resulted in Japanese/Chinese glyphs being turned into question marks, at least for me..). - // -TheDax + // We convert command line arguments to UTF-8 immediately. std::vector wideArgs = GetWideCmdLine(); std::vector argsUTF8; for (auto& string : wideArgs) { argsUTF8.push_back(ConvertWStringToUTF8(string)); } - std::vector args; - for (auto& string : argsUTF8) { args.push_back(string.c_str()); } - bool performingRestart = NativeIsRestarting(); NativeInit(static_cast(args.size()), &args[0], "1234", "1234", nullptr); @@ -165,7 +136,7 @@ unsigned int WINAPI TheThread(void *) } // No safe way out without graphics. - ExitProcess(1); + exit(1); } NativeInitGraphics(graphicsContext); @@ -179,34 +150,29 @@ unsigned int WINAPI TheThread(void *) goto shutdown; } - _InterlockedExchange(&emuThreadReady, THREAD_CORE_LOOP); + emuThreadState = THREAD_CORE_LOOP; if (g_Config.bBrowse) PostMessage(MainWindow::GetHWND(), WM_COMMAND, ID_FILE_LOAD, 0); Core_EnableStepping(FALSE); - while (GetUIState() != UISTATE_EXIT) - { + while (GetUIState() != UISTATE_EXIT) { // We're here again, so the game quit. Restart Core_Run() which controls the UI. // This way they can load a new game. if (!Core_IsActive()) UpdateUIState(UISTATE_MENU); - Core_Run(graphicsContext); } shutdown: - _InterlockedExchange(&emuThreadReady, THREAD_SHUTDOWN); + emuThreadState = THREAD_SHUTDOWN; NativeShutdownGraphics(); // NativeShutdown deletes the graphics context through host->ShutdownGraphics(). NativeShutdown(); - - _InterlockedExchange(&emuThreadReady, THREAD_END); - - return 0; + emuThreadState = THREAD_END; } diff --git a/Windows/GPU/WindowsVulkanContext.cpp b/Windows/GPU/WindowsVulkanContext.cpp index c6c2259fd8..87ceca5536 100644 --- a/Windows/GPU/WindowsVulkanContext.cpp +++ b/Windows/GPU/WindowsVulkanContext.cpp @@ -46,7 +46,7 @@ // and use the same render pass configuration (clear to black). However, we can later change this so we switch // to a non-clearing render pass in buffered mode, which might be a tiny bit faster. -#include +#include #include #include @@ -93,13 +93,15 @@ bool WindowsVulkanContext::Init(HINSTANCE hInst, HWND hWnd, std::string *error_m g_Vulkan = nullptr; return false; } - // int vulkanFlags = VULKAN_FLAG_PRESENT_FIFO_RELAXED; - int vulkanFlags = VULKAN_FLAG_PRESENT_MAILBOX; + VulkanContext::CreateInfo info{}; + info.app_name = "PPSSPP"; + info.app_ver = gitVer.ToInteger(); + info.flags = VULKAN_FLAG_PRESENT_MAILBOX; if (g_validate_) { - vulkanFlags |= VULKAN_FLAG_VALIDATE; + info.flags |= VULKAN_FLAG_VALIDATE; } - if (VK_SUCCESS != g_Vulkan->CreateInstance("PPSSPP", gitVer.ToInteger(), vulkanFlags)) { + if (VK_SUCCESS != g_Vulkan->CreateInstance(info)) { *error_message = g_Vulkan->InitError(); delete g_Vulkan; g_Vulkan = nullptr; @@ -119,7 +121,7 @@ bool WindowsVulkanContext::Init(HINSTANCE hInst, HWND hWnd, std::string *error_m int bits = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT | VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT; g_Vulkan->InitDebugMsgCallback(&Vulkan_Dbg, bits, &g_LogOptions); } - g_Vulkan->InitSurfaceWin32(hInst, hWnd); + g_Vulkan->InitSurface(WINDOWSYSTEM_WIN32, (void *)hInst, (void *)hWnd); if (!g_Vulkan->InitObjects()) { *error_message = g_Vulkan->InitError(); Shutdown(); @@ -160,22 +162,16 @@ void WindowsVulkanContext::Shutdown() { finalize_glslang(); } -void WindowsVulkanContext::SwapBuffers() { -} - void WindowsVulkanContext::Resize() { draw_->HandleEvent(Draw::Event::LOST_BACKBUFFER, g_Vulkan->GetBackbufferWidth(), g_Vulkan->GetBackbufferHeight()); g_Vulkan->DestroyObjects(); - g_Vulkan->ReinitSurfaceWin32(); + g_Vulkan->ReinitSurface(); g_Vulkan->InitObjects(); draw_->HandleEvent(Draw::Event::GOT_BACKBUFFER, g_Vulkan->GetBackbufferWidth(), g_Vulkan->GetBackbufferHeight()); } -void WindowsVulkanContext::SwapInterval(int interval) { -} - void *WindowsVulkanContext::GetAPIContext() { return g_Vulkan; } diff --git a/Windows/GPU/WindowsVulkanContext.h b/Windows/GPU/WindowsVulkanContext.h index 52088efced..6c9f0f42dd 100644 --- a/Windows/GPU/WindowsVulkanContext.h +++ b/Windows/GPU/WindowsVulkanContext.h @@ -26,8 +26,8 @@ public: WindowsVulkanContext() : draw_(nullptr) {} bool Init(HINSTANCE hInst, HWND window, std::string *error_message) override; void Shutdown() override; - void SwapInterval(int interval) override; - void SwapBuffers() override; + void SwapInterval(int interval) override {} + void SwapBuffers() override {} void Resize() override; void *GetAPIContext(); diff --git a/Windows/InputDevice.cpp b/Windows/InputDevice.cpp index 6cdfe36eff..252d7ee94c 100644 --- a/Windows/InputDevice.cpp +++ b/Windows/InputDevice.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #include "input/input_state.h" #include "thread/threadutil.h" diff --git a/android/jni/app-android.cpp b/android/jni/app-android.cpp index 87d5d799c0..970b36d27f 100644 --- a/android/jni/app-android.cpp +++ b/android/jni/app-android.cpp @@ -284,13 +284,17 @@ bool AndroidVulkanContext::Init(ANativeWindow *wnd, int desiredBackbufferSizeX, g_LogOptions.breakOnWarning = true; g_LogOptions.msgBoxOnError = false; - ILOG("Creating vulkan context"); + ILOG("Creating Vulkan context"); Version gitVer(PPSSPP_GIT_VERSION); if (!g_Vulkan) { g_Vulkan = new VulkanContext(); } - if (VK_SUCCESS != g_Vulkan->CreateInstance("PPSSPP", gitVer.ToInteger(), VULKAN_FLAG_PRESENT_MAILBOX | VULKAN_FLAG_PRESENT_FIFO_RELAXED)) { + VulkanContext::CreateInfo info{}; + info.app_name = "PPSSPP"; + info.app_ver = gitVer.ToInteger(); + info.flags = VULKAN_FLAG_PRESENT_MAILBOX | VULKAN_FLAG_PRESENT_FIFO_RELAXED; + if (VK_SUCCESS != g_Vulkan->CreateInstance(info)) { ELOG("Failed to create vulkan context: %s", g_Vulkan->InitError().c_str()); System_SendMessage("toast", "No Vulkan compatible device found. Using OpenGL instead."); delete g_Vulkan; @@ -310,7 +314,7 @@ bool AndroidVulkanContext::Init(ANativeWindow *wnd, int desiredBackbufferSizeX, g_Vulkan->ChooseDevice(physicalDevice); // Here we can enable device extensions if we like. - ILOG("Creating vulkan device"); + ILOG("Creating Vulkan device"); if (g_Vulkan->CreateDevice() != VK_SUCCESS) { ILOG("Failed to create vulkan device: %s", g_Vulkan->InitError().c_str()); System_SendMessage("toast", "No Vulkan driver found. Using OpenGL instead."); @@ -326,7 +330,7 @@ bool AndroidVulkanContext::Init(ANativeWindow *wnd, int desiredBackbufferSizeX, height = pixel_yres; } ILOG("InitSurfaceAndroid: width=%d height=%d", width, height); - g_Vulkan->InitSurfaceAndroid(wnd, width, height); + g_Vulkan->InitSurface(WINDOWSYSTEM_ANDROID, (void *)wnd, nullptr, width, height); if (g_validate_) { int bits = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT | VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT; g_Vulkan->InitDebugMsgCallback(&Vulkan_Dbg, bits, &g_LogOptions); @@ -386,7 +390,7 @@ void AndroidVulkanContext::Resize() { g_Vulkan->DestroyObjects(); // backbufferResize updated these values. TODO: Notify another way? - g_Vulkan->ReinitSurfaceAndroid(pixel_xres, pixel_yres); + g_Vulkan->ReinitSurface(pixel_xres, pixel_yres); g_Vulkan->InitObjects(); draw_->HandleEvent(Draw::Event::GOT_BACKBUFFER, g_Vulkan->GetBackbufferWidth(), g_Vulkan->GetBackbufferHeight()); ILOG("AndroidVulkanContext::Resize end (%d, %d)", g_Vulkan->GetBackbufferWidth(), g_Vulkan->GetBackbufferHeight()); 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/base/NativeApp.h b/ext/native/base/NativeApp.h index 69bdf90b91..dd07afb996 100644 --- a/ext/native/base/NativeApp.h +++ b/ext/native/base/NativeApp.h @@ -111,7 +111,7 @@ void NativeSaveState(); // onDestroy void NativePermissionStatus(SystemPermission permission, PermissionStatus status); // Calls back into Java / SDL -// These APIs must be implemented by every port (for example app-android.cpp, PCMain.cpp). +// These APIs must be implemented by every port (for example app-android.cpp, SDLMain.cpp). // You are free to call these. void SystemToast(const char *text); void ShowKeyboard(); diff --git a/ext/native/native.vcxproj b/ext/native/native.vcxproj index ba0d1d399a..b8db0d2f53 100644 --- a/ext/native/native.vcxproj +++ b/ext/native/native.vcxproj @@ -299,13 +299,13 @@ - + true true true true - + true true true @@ -761,4 +761,4 @@ - \ No newline at end of file + diff --git a/ext/native/native.vcxproj.filters b/ext/native/native.vcxproj.filters index 60c65f1746..175c41bf21 100644 --- a/ext/native/native.vcxproj.filters +++ b/ext/native/native.vcxproj.filters @@ -739,10 +739,10 @@ thread - + base - + base @@ -868,4 +868,4 @@ {06c6305a-a646-485b-85b9-645a24dd6553} - \ No newline at end of file + 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 { diff --git a/ext/native/thin3d/VulkanQueueRunner.cpp b/ext/native/thin3d/VulkanQueueRunner.cpp index 169d276ad8..a2c5c0a631 100644 --- a/ext/native/thin3d/VulkanQueueRunner.cpp +++ b/ext/native/thin3d/VulkanQueueRunner.cpp @@ -78,8 +78,6 @@ void VulkanQueueRunner::DestroyDeviceObjects() { } void VulkanQueueRunner::InitBackbufferRenderPass() { - VkResult U_ASSERT_ONLY res; - VkAttachmentDescription attachments[2]; attachments[0].format = vulkan_->GetSwapchainFormat(); attachments[0].samples = VK_SAMPLE_COUNT_1_BIT; @@ -139,7 +137,7 @@ void VulkanQueueRunner::InitBackbufferRenderPass() { rp_info.dependencyCount = 1; rp_info.pDependencies = &dep; - res = vkCreateRenderPass(vulkan_->GetDevice(), &rp_info, nullptr, &backbufferRenderPass_); + VkResult res = vkCreateRenderPass(vulkan_->GetDevice(), &rp_info, nullptr, &backbufferRenderPass_); assert(res == VK_SUCCESS); } diff --git a/ext/native/thread/prioritizedworkqueue.h b/ext/native/thread/prioritizedworkqueue.h index d7c9ad5f71..032e6a9694 100644 --- a/ext/native/thread/prioritizedworkqueue.h +++ b/ext/native/thread/prioritizedworkqueue.h @@ -3,6 +3,7 @@ #include #include #include +#include #include "base/basictypes.h" #include "thread/threadutil.h" diff --git a/ext/native/thread/threadutil.h b/ext/native/thread/threadutil.h index 512c15d0bb..2723e2864f 100644 --- a/ext/native/thread/threadutil.h +++ b/ext/native/thread/threadutil.h @@ -1,35 +1,6 @@ #pragma once -#include -#include -#include - // Note that name must be a global string that lives until the end of the process, // for assertThreadName to work. void setCurrentThreadName(const char *threadName); -void AssertCurrentThreadName(const char *threadName); - -class event { -public: - void notify_one() { - cond_.notify_one(); - } - - // notify_all is not really possible to implement with win32 events? - - void wait(std::mutex &mtx) { - // broken logic - std::unique_lock guard(mtx); - cond_.wait(guard); - } - - void wait_for(std::mutex &mtx, int milliseconds) { - std::unique_lock guard(mtx); - cond_.wait_for(guard, std::chrono::milliseconds(milliseconds)); - } - - void reset() { - } -private: - std::condition_variable cond_; -}; \ No newline at end of file +void AssertCurrentThreadName(const char *threadName); \ No newline at end of file