diff --git a/CMakeLists.txt b/CMakeLists.txt index df8dbd20787a..b85ea1264345 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -69,32 +69,13 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "Android") set(ANDROID ON) endif() -# Of the CMake platforms, we only support Vulkan on Android and Windows. -if(ANDROID OR WIN32 OR LINUX) +# We only support Vulkan on Unix, Android and Windows. +if(ANDROID OR WIN32 OR (UNIX AND NOT APPLE)) 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(VULKAN AND NOT WIN32 AND NOT ANDROID) - IF (NOT Vulkan_FOUND) - find_library(Vulkan_LIBRARY NAMES vulkan HINTS "$ENV{VULKAN_SDK}/lib" "${CMAKE_SOURCE_DIR}/ext/vulkan" REQUIRED) - IF (Vulkan_LIBRARY) - set(Vulkan_FOUND ON) - MESSAGE("Using bundled Vulkan library version") - add_definitions(-DVULKAN_STATIC) - ENDIF() - ENDIF() -endif() - if(NOT DEFINED HEADLESS) set(HEADLESS OFF) endif() @@ -106,12 +87,6 @@ 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) @@ -138,10 +113,20 @@ option(SIMULATOR "Set to ON when targeting an x86 simulator of an ARM platform" # :: Options option(USE_FFMPEG "Build with FFMPEG support" ${USE_FFMPEG}) option(USE_SYSTEM_FFMPEG "Dynamically link against system FFMPEG" ${USE_SYSTEM_FFMPEG}) +option(USE_WAYLAND_WSI "Set to ON to require Wayland support for Vulkan" ${USE_WAYLAND_WSI}) -# 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(UNIX AND NOT (APPLE OR ANDROID) AND VULKAN) + add_definitions(-DVK_USE_PLATFORM_XLIB_KHR) + # add_definitions(-DVK_USE_PLATFORM_XCB_KHR) + find_package(Wayland) + if (USE_WAYLAND_WSI AND NOT WAYLAND_FOUND) + message(FATAL_ERROR "Could not find libwayland, but USE_WAYLAND_WSI was enabled. Failing.") + endif() + if (WAYLAND_FOUND) + include_directories(${WAYLAND_INCLUDE_DIR}) + add_definitions(-DVK_USE_PLATFORM_WAYLAND_KHR) + endif() +endif() if(ANDROID) set(CoreLibName ppsspp_jni) @@ -1676,10 +1661,6 @@ set(GlslangLibs glslang OGLCompiler OSDependent SPIRV SPVRemapper spirv-cross-gl target_link_libraries(${CoreLibName} Common native kirk cityhash sfmt19937 xbrz xxhash ${GlslangLibs} ${CoreExtraLibs} ${OPENGL_LIBRARIES} ${X11_LIBRARIES} ${CMAKE_DL_LIBS}) -if(VULKAN AND NOT ANDROID AND NOT WIN32) - 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 c0f7f5f6baff..41a98808269f 100644 --- a/Common/Vulkan/VulkanContext.cpp +++ b/Common/Vulkan/VulkanContext.cpp @@ -109,16 +109,19 @@ 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 - //... +#if defined(VK_USE_PLATFORM_XLIB_KHR) + instance_extensions_enabled_.push_back(VK_KHR_XLIB_SURFACE_EXTENSION_NAME); +#endif +//#if defined(VK_USE_PLATFORM_XCB_KHR) +// instance_extensions_enabled_.push_back(VK_KHR_XCB_SURFACE_EXTENSION_NAME); +//#endif +//#if defined(VK_USE_PLATFORM_MIR_KHR) +// instance_extensions_enabled_.push_back(VK_KHR_MIR_SURFACE_EXTENSION_NAME); +//#endif +#if defined(VK_USE_PLATFORM_WAYLAND_KHR) + instance_extensions_enabled_.push_back(VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME); +#endif #endif if (flags_ & VULKAN_FLAG_VALIDATE) { @@ -667,6 +670,18 @@ void VulkanContext::ReinitSurface(int width, int height) { break; } #endif +#if defined(VK_USE_PLATFORM_WAYLAND_KHR) + case WINDOWSYSTEM_WAYLAND: + { + VkWaylandSurfaceCreateInfoKHR wayland = { VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR }; + wayland.flags = 0; + wayland.display = (wl_display *)winsysData1_; + wayland.surface = (wl_surface *)winsysData2_; + VkResult res = vkCreateWaylandSurfaceKHR(instance_, &wayland, nullptr, &surface_); + assert(res == VK_SUCCESS); + break; + } +#endif default: _assert_msg_(G3D, false, "Vulkan support for chosen window system not implemented"); diff --git a/Common/Vulkan/VulkanContext.h b/Common/Vulkan/VulkanContext.h index 0c60a3bef23e..03b9f1b21ad6 100644 --- a/Common/Vulkan/VulkanContext.h +++ b/Common/Vulkan/VulkanContext.h @@ -43,6 +43,9 @@ enum WindowSystem { #ifdef VK_USE_PLATFORM_XCB_KHR WINDOWSYSTEM_XCB, #endif +#ifdef VK_USE_PLATFORM_WAYLAND_KHR + WINDOWSYSTEM_WAYLAND, +#endif }; struct VulkanPhysicalDeviceInfo { diff --git a/Common/Vulkan/VulkanLoader.cpp b/Common/Vulkan/VulkanLoader.cpp index e40c3ec6bf52..c82c0eef9583 100644 --- a/Common/Vulkan/VulkanLoader.cpp +++ b/Common/Vulkan/VulkanLoader.cpp @@ -23,8 +23,6 @@ #include #endif -#ifndef VULKAN_STATIC - PFN_vkCreateInstance vkCreateInstance; PFN_vkDestroyInstance vkDestroyInstance; PFN_vkEnumeratePhysicalDevices vkEnumeratePhysicalDevices; @@ -167,9 +165,13 @@ PFN_vkCmdExecuteCommands vkCmdExecuteCommands; PFN_vkCreateAndroidSurfaceKHR vkCreateAndroidSurfaceKHR; #elif defined(_WIN32) PFN_vkCreateWin32SurfaceKHR vkCreateWin32SurfaceKHR; -#elif defined(VK_USE_PLATFORM_XLIB_KHR) +#endif +#if defined(VK_USE_PLATFORM_XLIB_KHR) PFN_vkCreateXlibSurfaceKHR vkCreateXlibSurfaceKHR; #endif +#if defined(VK_USE_PLATFORM_WAYLAND_KHR) +PFN_vkCreateWaylandSurfaceKHR vkCreateWaylandSurfaceKHR; +#endif PFN_vkDestroySurfaceKHR vkDestroySurfaceKHR; @@ -183,7 +185,6 @@ 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; @@ -207,9 +208,6 @@ static const char *so_names[] = { }; bool VulkanMayBeAvailable() { -#ifdef VULKAN_STATIC - return true; -#else if (vulkanLibrary) return true; bool available = false; @@ -231,11 +229,9 @@ bool VulkanMayBeAvailable() { } #endif return available; -#endif } bool VulkanLoad() { -#ifndef VULKAN_STATIC if (!vulkanLibrary) { #ifndef _WIN32 for (int i = 0; i < ARRAY_SIZE(so_names); i++) { @@ -260,12 +256,10 @@ 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); @@ -415,12 +409,15 @@ void VulkanLoadInstanceFunctions(VkInstance instance) { LOAD_INSTANCE_FUNC(instance, vkCreateWin32SurfaceKHR); #elif defined(__ANDROID__) LOAD_INSTANCE_FUNC(instance, vkCreateAndroidSurfaceKHR); -#elif defined(VK_USE_PLATFORM_XLIB_KHR) +#endif +#if defined(VK_USE_PLATFORM_XLIB_KHR) LOAD_INSTANCE_FUNC(instance, vkCreateXlibSurfaceKHR); #endif +#if defined(VK_USE_PLATFORM_WAYLAND_KHR) + LOAD_INSTANCE_FUNC(instance, vkCreateWaylandSurfaceKHR); +#endif LOAD_INSTANCE_FUNC(instance, vkDestroySurfaceKHR); -#endif dyn_vkCreateDebugReportCallbackEXT = (PFN_vkCreateDebugReportCallbackEXT)vkGetInstanceProcAddr(instance, "vkCreateDebugReportCallbackEXT"); dyn_vkDestroyDebugReportCallbackEXT = (PFN_vkDestroyDebugReportCallbackEXT)vkGetInstanceProcAddr(instance, "vkCreateDebugReportCallbackEXT"); @@ -433,18 +430,15 @@ 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); @@ -453,5 +447,4 @@ void VulkanFree() { #endif vulkanLibrary = nullptr; } -#endif } diff --git a/Common/Vulkan/VulkanLoader.h b/Common/Vulkan/VulkanLoader.h index 16fbe1fd2e00..636bff82c707 100644 --- a/Common/Vulkan/VulkanLoader.h +++ b/Common/Vulkan/VulkanLoader.h @@ -25,13 +25,10 @@ #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; @@ -174,9 +171,13 @@ extern PFN_vkCmdExecuteCommands vkCmdExecuteCommands; extern PFN_vkCreateAndroidSurfaceKHR vkCreateAndroidSurfaceKHR; #elif defined(_WIN32) extern PFN_vkCreateWin32SurfaceKHR vkCreateWin32SurfaceKHR; -#elif defined(VK_USE_PLATFORM_XLIB_KHR) +#endif +#if defined(VK_USE_PLATFORM_XLIB_KHR) extern PFN_vkCreateXlibSurfaceKHR vkCreateXlibSurfaceKHR; #endif +#if defined(VK_USE_PLATFORM_WAYLAND_KHR) +extern PFN_vkCreateWaylandSurfaceKHR vkCreateWaylandSurfaceKHR; +#endif extern PFN_vkDestroySurfaceKHR vkDestroySurfaceKHR; @@ -192,8 +193,6 @@ extern PFN_vkGetSwapchainImagesKHR vkGetSwapchainImagesKHR; extern PFN_vkAcquireNextImageKHR vkAcquireNextImageKHR; extern PFN_vkQueuePresentKHR vkQueuePresentKHR; -#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; diff --git a/Core/Config.cpp b/Core/Config.cpp index 125f5b55599c..bac7222e0b9f 100644 --- a/Core/Config.cpp +++ b/Core/Config.cpp @@ -489,20 +489,20 @@ static int DefaultGPUBackend() { #if PPSSPP_PLATFORM(WINDOWS) || PPSSPP_PLATFORM(ANDROID) // Where supported, let's use Vulkan. if (VulkanMayBeAvailable()) { - return GPU_BACKEND_VULKAN; + return (int)GPUBackend::VULKAN; } #endif #if PPSSPP_PLATFORM(WINDOWS) // If no Vulkan, use Direct3D 11 on Windows 8+ (most importantly 10.) if (DoesVersionMatchWindows(6, 2, 0, 0, true)) { - return GPU_BACKEND_DIRECT3D11; + return (int)GPUBackend::DIRECT3D11; } #endif - return GPU_BACKEND_OPENGL; + return (int)GPUBackend::OPENGL; } static bool DefaultVertexCache() { - return DefaultGPUBackend() == GPU_BACKEND_OPENGL; + return DefaultGPUBackend() == (int)GPUBackend::OPENGL; } static ConfigSetting graphicsSettings[] = { diff --git a/Core/Config.h b/Core/Config.h index 07f0975dd54f..551537707044 100644 --- a/Core/Config.h +++ b/Core/Config.h @@ -57,12 +57,6 @@ enum class GPUBackend { DIRECT3D11 = 2, VULKAN = 3, }; -enum { - GPU_BACKEND_OPENGL = (int)GPUBackend::OPENGL, - GPU_BACKEND_DIRECT3D9 = (int)GPUBackend::DIRECT3D9, - GPU_BACKEND_DIRECT3D11 = (int)GPUBackend::DIRECT3D11, - GPU_BACKEND_VULKAN = (int)GPUBackend::VULKAN, -}; enum AudioBackendType { AUDIO_BACKEND_AUTO, diff --git a/Core/Debugger/SymbolMap.cpp b/Core/Debugger/SymbolMap.cpp index b36e0353403b..b369c014cef9 100644 --- a/Core/Debugger/SymbolMap.cpp +++ b/Core/Debugger/SymbolMap.cpp @@ -58,6 +58,7 @@ void SymbolMap::Clear() { activeData.clear(); activeModuleEnds.clear(); modules.clear(); + activeNeedUpdate_ = false; } bool SymbolMap::LoadSymbolMap(const char *filename) { @@ -296,7 +297,10 @@ void SymbolMap::SaveNocashSym(const char *filename) const { fclose(f); } -SymbolType SymbolMap::GetSymbolType(u32 address) const { +SymbolType SymbolMap::GetSymbolType(u32 address) { + if (activeNeedUpdate_) + UpdateActiveSymbols(); + std::lock_guard guard(lock_); if (activeFunctions.find(address) != activeFunctions.end()) return ST_FUNCTION; @@ -305,7 +309,7 @@ SymbolType SymbolMap::GetSymbolType(u32 address) const { return ST_NONE; } -bool SymbolMap::GetSymbolInfo(SymbolInfo *info, u32 address, SymbolType symmask) const { +bool SymbolMap::GetSymbolInfo(SymbolInfo *info, u32 address, SymbolType symmask) { u32 functionAddress = INVALID_ADDRESS; u32 dataAddress = INVALID_ADDRESS; @@ -344,6 +348,9 @@ bool SymbolMap::GetSymbolInfo(SymbolInfo *info, u32 address, SymbolType symmask) } u32 SymbolMap::GetNextSymbolAddress(u32 address, SymbolType symmask) { + if (activeNeedUpdate_) + UpdateActiveSymbols(); + std::lock_guard guard(lock_); const auto functionEntry = symmask & ST_FUNCTION ? activeFunctions.upper_bound(address) : activeFunctions.end(); const auto dataEntry = symmask & ST_DATA ? activeData.upper_bound(address) : activeData.end(); @@ -360,7 +367,7 @@ u32 SymbolMap::GetNextSymbolAddress(u32 address, SymbolType symmask) { return dataAddress; } -std::string SymbolMap::GetDescription(unsigned int address) const { +std::string SymbolMap::GetDescription(unsigned int address) { std::lock_guard guard(lock_); const char* labelName = NULL; @@ -382,6 +389,9 @@ std::string SymbolMap::GetDescription(unsigned int address) const { } std::vector SymbolMap::GetAllSymbols(SymbolType symmask) { + if (activeNeedUpdate_) + UpdateActiveSymbols(); + std::vector result; if (symmask & ST_FUNCTION) { @@ -422,7 +432,7 @@ void SymbolMap::AddModule(const char *name, u32 address, u32 size) { it->start = address; it->size = size; activeModuleEnds.insert(std::make_pair(it->start + it->size, *it)); - UpdateActiveSymbols(); + activeNeedUpdate_ = true; return; } } @@ -435,13 +445,13 @@ void SymbolMap::AddModule(const char *name, u32 address, u32 size) { modules.push_back(mod); activeModuleEnds.insert(std::make_pair(mod.start + mod.size, mod)); - UpdateActiveSymbols(); + activeNeedUpdate_ = true; } void SymbolMap::UnloadModule(u32 address, u32 size) { std::lock_guard guard(lock_); activeModuleEnds.erase(address + size); - UpdateActiveSymbols(); + activeNeedUpdate_ = true; } u32 SymbolMap::GetModuleRelativeAddr(u32 address, int moduleIndex) const { @@ -476,7 +486,7 @@ int SymbolMap::GetModuleIndex(u32 address) const { return iter->second.index; } -bool SymbolMap::IsModuleActive(int moduleIndex) const { +bool SymbolMap::IsModuleActive(int moduleIndex) { if (moduleIndex == 0) { return true; } @@ -559,7 +569,10 @@ void SymbolMap::AddFunction(const char* name, u32 address, u32 size, int moduleI AddLabel(name, address, moduleIndex); } -u32 SymbolMap::GetFunctionStart(u32 address) const { +u32 SymbolMap::GetFunctionStart(u32 address) { + if (activeNeedUpdate_) + UpdateActiveSymbols(); + std::lock_guard guard(lock_); auto it = activeFunctions.upper_bound(address); if (it == activeFunctions.end()) { @@ -586,7 +599,10 @@ u32 SymbolMap::GetFunctionStart(u32 address) const { return INVALID_ADDRESS; } -u32 SymbolMap::FindPossibleFunctionAtAfter(u32 address) const { +u32 SymbolMap::FindPossibleFunctionAtAfter(u32 address) { + if (activeNeedUpdate_) + UpdateActiveSymbols(); + std::lock_guard guard(lock_); auto it = activeFunctions.lower_bound(address); if (it == activeFunctions.end()) { @@ -595,7 +611,10 @@ u32 SymbolMap::FindPossibleFunctionAtAfter(u32 address) const { return it->first; } -u32 SymbolMap::GetFunctionSize(u32 startAddress) const { +u32 SymbolMap::GetFunctionSize(u32 startAddress) { + if (activeNeedUpdate_) + UpdateActiveSymbols(); + std::lock_guard guard(lock_); auto it = activeFunctions.find(startAddress); if (it == activeFunctions.end()) @@ -604,7 +623,10 @@ u32 SymbolMap::GetFunctionSize(u32 startAddress) const { return it->second.size; } -u32 SymbolMap::GetFunctionModuleAddress(u32 startAddress) const { +u32 SymbolMap::GetFunctionModuleAddress(u32 startAddress) { + if (activeNeedUpdate_) + UpdateActiveSymbols(); + std::lock_guard guard(lock_); auto it = activeFunctions.find(startAddress); if (it == activeFunctions.end()) @@ -613,7 +635,10 @@ u32 SymbolMap::GetFunctionModuleAddress(u32 startAddress) const { return GetModuleAbsoluteAddr(0, it->second.module); } -int SymbolMap::GetFunctionNum(u32 address) const { +int SymbolMap::GetFunctionNum(u32 address) { + if (activeNeedUpdate_) + UpdateActiveSymbols(); + std::lock_guard guard(lock_); u32 start = GetFunctionStart(address); if (start == INVALID_ADDRESS) @@ -685,9 +710,13 @@ void SymbolMap::UpdateActiveSymbols() { } AssignFunctionIndices(); + activeNeedUpdate_ = false; } bool SymbolMap::SetFunctionSize(u32 startAddress, u32 newSize) { + if (activeNeedUpdate_) + UpdateActiveSymbols(); + std::lock_guard guard(lock_); auto funcInfo = activeFunctions.find(startAddress); @@ -696,7 +725,8 @@ bool SymbolMap::SetFunctionSize(u32 startAddress, u32 newSize) { auto func = functions.find(symbolKey); if (func != functions.end()) { func->second.size = newSize; - UpdateActiveSymbols(); + activeFunctions.erase(funcInfo); + activeFunctions.insert(std::make_pair(startAddress, func->second)); } } @@ -705,6 +735,9 @@ bool SymbolMap::SetFunctionSize(u32 startAddress, u32 newSize) { } bool SymbolMap::RemoveFunction(u32 startAddress, bool removeName) { + if (activeNeedUpdate_) + UpdateActiveSymbols(); + std::lock_guard guard(lock_); auto it = activeFunctions.find(startAddress); @@ -782,6 +815,9 @@ void SymbolMap::AddLabel(const char* name, u32 address, int moduleIndex) { } void SymbolMap::SetLabelName(const char* name, u32 address) { + if (activeNeedUpdate_) + UpdateActiveSymbols(); + std::lock_guard guard(lock_); auto labelInfo = activeLabels.find(address); if (labelInfo == activeLabels.end()) { @@ -803,7 +839,10 @@ void SymbolMap::SetLabelName(const char* name, u32 address) { } } -const char *SymbolMap::GetLabelName(u32 address) const { +const char *SymbolMap::GetLabelName(u32 address) { + if (activeNeedUpdate_) + UpdateActiveSymbols(); + std::lock_guard guard(lock_); auto it = activeLabels.find(address); if (it == activeLabels.end()) @@ -821,7 +860,7 @@ const char *SymbolMap::GetLabelNameRel(u32 relAddress, int moduleIndex) const { return it->second.name; } -std::string SymbolMap::GetLabelString(u32 address) const { +std::string SymbolMap::GetLabelString(u32 address) { std::lock_guard guard(lock_); const char *label = GetLabelName(address); if (label == NULL) @@ -830,6 +869,9 @@ std::string SymbolMap::GetLabelString(u32 address) const { } bool SymbolMap::GetLabelValue(const char* name, u32& dest) { + if (activeNeedUpdate_) + UpdateActiveSymbols(); + std::lock_guard guard(lock_); for (auto it = activeLabels.begin(); it != activeLabels.end(); it++) { if (strcasecmp(name, it->second.name) == 0) { @@ -890,7 +932,10 @@ void SymbolMap::AddData(u32 address, u32 size, DataType type, int moduleIndex) { } } -u32 SymbolMap::GetDataStart(u32 address) const { +u32 SymbolMap::GetDataStart(u32 address) { + if (activeNeedUpdate_) + UpdateActiveSymbols(); + std::lock_guard guard(lock_); auto it = activeData.upper_bound(address); if (it == activeData.end()) @@ -920,7 +965,10 @@ u32 SymbolMap::GetDataStart(u32 address) const { return INVALID_ADDRESS; } -u32 SymbolMap::GetDataSize(u32 startAddress) const { +u32 SymbolMap::GetDataSize(u32 startAddress) { + if (activeNeedUpdate_) + UpdateActiveSymbols(); + std::lock_guard guard(lock_); auto it = activeData.find(startAddress); if (it == activeData.end()) @@ -928,7 +976,10 @@ u32 SymbolMap::GetDataSize(u32 startAddress) const { return it->second.size; } -u32 SymbolMap::GetDataModuleAddress(u32 startAddress) const { +u32 SymbolMap::GetDataModuleAddress(u32 startAddress) { + if (activeNeedUpdate_) + UpdateActiveSymbols(); + std::lock_guard guard(lock_); auto it = activeData.find(startAddress); if (it == activeData.end()) @@ -936,7 +987,10 @@ u32 SymbolMap::GetDataModuleAddress(u32 startAddress) const { return GetModuleAbsoluteAddr(0, it->second.module); } -DataType SymbolMap::GetDataType(u32 startAddress) const { +DataType SymbolMap::GetDataType(u32 startAddress) { + if (activeNeedUpdate_) + UpdateActiveSymbols(); + std::lock_guard guard(lock_); auto it = activeData.find(startAddress); if (it == activeData.end()) @@ -944,8 +998,10 @@ DataType SymbolMap::GetDataType(u32 startAddress) const { return it->second.type; } -void SymbolMap::GetLabels(std::vector &dest) const -{ +void SymbolMap::GetLabels(std::vector &dest) { + if (activeNeedUpdate_) + UpdateActiveSymbols(); + std::lock_guard guard(lock_); for (auto it = activeLabels.begin(); it != activeLabels.end(); it++) { LabelDefinition entry; @@ -970,7 +1026,10 @@ static const DefaultSymbol defaultSymbols[]= { { 0x00010000, "Scratchpad" }, }; -void SymbolMap::FillSymbolListBox(HWND listbox,SymbolType symType) const { +void SymbolMap::FillSymbolListBox(HWND listbox,SymbolType symType) { + if (activeNeedUpdate_) + UpdateActiveSymbols(); + wchar_t temp[256]; std::lock_guard guard(lock_); diff --git a/Core/Debugger/SymbolMap.h b/Core/Debugger/SymbolMap.h index 88d03a0f8e43..1a58dd2ac195 100644 --- a/Core/Debugger/SymbolMap.h +++ b/Core/Debugger/SymbolMap.h @@ -65,7 +65,7 @@ typedef struct HWND__ *HWND; class SymbolMap { public: - SymbolMap() : sawUnknownModule(false) {} + SymbolMap() {} void Clear(); void SortSymbols(); @@ -74,46 +74,46 @@ class SymbolMap { bool LoadNocashSym(const char *ilename); void SaveNocashSym(const char *filename) const; - SymbolType GetSymbolType(u32 address) const; - bool GetSymbolInfo(SymbolInfo *info, u32 address, SymbolType symmask = ST_FUNCTION) const; + SymbolType GetSymbolType(u32 address); + bool GetSymbolInfo(SymbolInfo *info, u32 address, SymbolType symmask = ST_FUNCTION); u32 GetNextSymbolAddress(u32 address, SymbolType symmask); - std::string GetDescription(unsigned int address) const; + std::string GetDescription(unsigned int address); std::vector GetAllSymbols(SymbolType symmask); #ifdef _WIN32 - void FillSymbolListBox(HWND listbox, SymbolType symType) const; + void FillSymbolListBox(HWND listbox, SymbolType symType); #endif - void GetLabels(std::vector &dest) const; + void GetLabels(std::vector &dest); void AddModule(const char *name, u32 address, u32 size); void UnloadModule(u32 address, u32 size); u32 GetModuleRelativeAddr(u32 address, int moduleIndex = -1) const; u32 GetModuleAbsoluteAddr(u32 relative, int moduleIndex) const; int GetModuleIndex(u32 address) const; - bool IsModuleActive(int moduleIndex) const; + bool IsModuleActive(int moduleIndex); std::vector getAllModules() const; void AddFunction(const char* name, u32 address, u32 size, int moduleIndex = -1); - u32 GetFunctionStart(u32 address) const; - int GetFunctionNum(u32 address) const; - u32 GetFunctionSize(u32 startAddress) const; - u32 GetFunctionModuleAddress(u32 startAddress) const; + u32 GetFunctionStart(u32 address); + int GetFunctionNum(u32 address); + u32 GetFunctionSize(u32 startAddress); + u32 GetFunctionModuleAddress(u32 startAddress); bool SetFunctionSize(u32 startAddress, u32 newSize); bool RemoveFunction(u32 startAddress, bool removeName); // Search for the first address their may be a function after address. // Only valid for currently loaded modules. Not guaranteed there will be a function. - u32 FindPossibleFunctionAtAfter(u32 address) const; + u32 FindPossibleFunctionAtAfter(u32 address); void AddLabel(const char* name, u32 address, int moduleIndex = -1); - std::string GetLabelString(u32 address) const; + std::string GetLabelString(u32 address); void SetLabelName(const char* name, u32 address); bool GetLabelValue(const char* name, u32& dest); void AddData(u32 address, u32 size, DataType type, int moduleIndex = -1); - u32 GetDataStart(u32 address) const; - u32 GetDataSize(u32 startAddress) const; - u32 GetDataModuleAddress(u32 startAddress) const; - DataType GetDataType(u32 startAddress) const; + u32 GetDataStart(u32 address); + u32 GetDataSize(u32 startAddress); + u32 GetDataModuleAddress(u32 startAddress); + DataType GetDataType(u32 startAddress); static const u32 INVALID_ADDRESS = (u32)-1; @@ -121,7 +121,7 @@ class SymbolMap { private: void AssignFunctionIndices(); - const char *GetLabelName(u32 address) const; + const char *GetLabelName(u32 address); const char *GetLabelNameRel(u32 relAddress, int moduleIndex) const; struct FunctionEntry { @@ -156,6 +156,7 @@ class SymbolMap { std::map activeFunctions; std::map activeLabels; std::map activeData; + bool activeNeedUpdate_ = false; // This is indexed by the end address of the module. std::map activeModuleEnds; @@ -169,7 +170,7 @@ class SymbolMap { std::vector modules; mutable std::recursive_mutex lock_; - bool sawUnknownModule; + bool sawUnknownModule = false; }; extern SymbolMap *g_symbolMap; diff --git a/Core/HLE/sceDisplay.cpp b/Core/HLE/sceDisplay.cpp index e35c35ca6331..6addbee0ae98 100644 --- a/Core/HLE/sceDisplay.cpp +++ b/Core/HLE/sceDisplay.cpp @@ -918,7 +918,7 @@ u32 sceDisplaySetFramebuf(u32 topaddr, int linesize, int pixelformat, int sync) u64 now = CoreTiming::GetTicks(); s64 cyclesAhead = nextFlipCycles - now; if (cyclesAhead > FLIP_DELAY_CYCLES_MIN) { - if (lastFlipsTooFrequent >= FLIP_DELAY_MIN_FLIPS) { + if (lastFlipsTooFrequent >= FLIP_DELAY_MIN_FLIPS && gpuStats.numClears > 0) { delayCycles = cyclesAhead; } else { ++lastFlipsTooFrequent; diff --git a/Core/HLE/sceKernelModule.cpp b/Core/HLE/sceKernelModule.cpp index bc37345197b3..d26eabf4f448 100644 --- a/Core/HLE/sceKernelModule.cpp +++ b/Core/HLE/sceKernelModule.cpp @@ -295,9 +295,7 @@ class Module : public KernelObject { // On load state, we re-examine in case our syscall ids changed. if (libstub != 0) { importedFuncs.clear(); - if (!KernelImportModuleFuncs(this, nullptr, true)) { - ERROR_LOG(LOADER, "Something went wrong loading imports on load state"); - } + // Imports reloaded in KernelModuleDoState. } else { // Older save state. Let's still reload, but this may not pick up new flags, etc. bool foundBroken = false; @@ -499,6 +497,19 @@ void __KernelModuleDoState(PointerWrap &p) p.Do(loadedModules); } + if (p.mode == p.MODE_READ) { + u32 error; + // We process these late, since they depend on loadedModules for interlinking. + for (SceUID moduleId : loadedModules) { + Module *module = kernelObjects.Get(moduleId, error); + if (module && module->libstub != 0) { + if (!KernelImportModuleFuncs(module, nullptr, true)) { + ERROR_LOG(LOADER, "Something went wrong loading imports on load state"); + } + } + } + } + if (g_Config.bFuncReplacements) { MIPSAnalyst::ReplaceFunctions(); } @@ -637,8 +648,8 @@ void ImportVarSymbol(const VarSymbolImport &var) { } u32 error; - for (auto mod = loadedModules.begin(), modend = loadedModules.end(); mod != modend; ++mod) { - Module *module = kernelObjects.Get(*mod, error); + for (SceUID moduleId : loadedModules) { + Module *module = kernelObjects.Get(moduleId, error); if (!module || !module->ImportsOrExportsModuleName(var.moduleName)) { continue; } @@ -658,8 +669,8 @@ void ImportVarSymbol(const VarSymbolImport &var) { void ExportVarSymbol(const VarSymbolExport &var) { u32 error; - for (auto mod = loadedModules.begin(), modend = loadedModules.end(); mod != modend; ++mod) { - Module *module = kernelObjects.Get(*mod, error); + for (SceUID moduleId : loadedModules) { + Module *module = kernelObjects.Get(moduleId, error); if (!module || !module->ImportsOrExportsModuleName(var.moduleName)) { continue; } @@ -676,8 +687,8 @@ void ExportVarSymbol(const VarSymbolExport &var) { void UnexportVarSymbol(const VarSymbolExport &var) { u32 error; - for (auto mod = loadedModules.begin(), modend = loadedModules.end(); mod != modend; ++mod) { - Module *module = kernelObjects.Get(*mod, error); + for (SceUID moduleId : loadedModules) { + Module *module = kernelObjects.Get(moduleId, error); if (!module || !module->ImportsOrExportsModuleName(var.moduleName)) { continue; } @@ -705,8 +716,8 @@ void ImportFuncSymbol(const FuncSymbolImport &func, bool reimporting) { } u32 error; - for (auto mod = loadedModules.begin(), modend = loadedModules.end(); mod != modend; ++mod) { - Module *module = kernelObjects.Get(*mod, error); + for (SceUID moduleId : loadedModules) { + Module *module = kernelObjects.Get(moduleId, error); if (!module || !module->ImportsOrExportsModuleName(func.moduleName)) { continue; } @@ -745,8 +756,8 @@ void ExportFuncSymbol(const FuncSymbolExport &func) { } u32 error; - for (auto mod = loadedModules.begin(), modend = loadedModules.end(); mod != modend; ++mod) { - Module *module = kernelObjects.Get(*mod, error); + for (SceUID moduleId : loadedModules) { + Module *module = kernelObjects.Get(moduleId, error); if (!module || !module->ImportsOrExportsModuleName(func.moduleName)) { continue; } @@ -769,8 +780,8 @@ void UnexportFuncSymbol(const FuncSymbolExport &func) { } u32 error; - for (auto mod = loadedModules.begin(), modend = loadedModules.end(); mod != modend; ++mod) { - Module *module = kernelObjects.Get(*mod, error); + for (SceUID moduleId : loadedModules) { + Module *module = kernelObjects.Get(moduleId, error); if (!module || !module->ImportsOrExportsModuleName(func.moduleName)) { continue; } @@ -2390,8 +2401,8 @@ static u32 sceKernelGetModuleIdList(u32 resultBuffer, u32 resultBufferSize, u32 u32 resultBufferOffset = 0; u32 error; - for (auto mod = loadedModules.begin(), modend = loadedModules.end(); mod != modend; ++mod) { - Module *module = kernelObjects.Get(*mod, error); + for (SceUID moduleId : loadedModules) { + Module *module = kernelObjects.Get(moduleId, error); if (!module->isFake) { if (resultBufferOffset < resultBufferSize) { Memory::Write_U32(module->GetUID(), resultBuffer + resultBufferOffset); diff --git a/GPU/Common/FramebufferCommon.cpp b/GPU/Common/FramebufferCommon.cpp index 9054ffe7de79..aa8d9f007efa 100644 --- a/GPU/Common/FramebufferCommon.cpp +++ b/GPU/Common/FramebufferCommon.cpp @@ -1299,6 +1299,9 @@ bool FramebufferManagerCommon::NotifyFramebufferCopy(u32 src, u32 dst, int size, } return false; } else if (dstBuffer) { + if (isMemset) { + gpuStats.numClears++; + } WARN_LOG_ONCE(btucpy, G3D, "Memcpy fbo upload %08x -> %08x", src, dst); if (g_Config.bBlockTransferGPU) { FlushBeforeCopy(); @@ -1930,7 +1933,7 @@ bool FramebufferManagerCommon::GetFramebuffer(u32 fb_address, int fb_stride, GEB } // TODO: Maybe should handle flipY inside CopyFramebufferToMemorySync somehow? - bool flipY = (g_Config.iGPUBackend == GPU_BACKEND_OPENGL && !useBufferedRendering_) ? true : false; + bool flipY = (GetGPUBackend() == GPUBackend::OPENGL && !useBufferedRendering_) ? true : false; buffer.Allocate(w, h, GE_FORMAT_8888, flipY, true); bool retval = draw_->CopyFramebufferToMemorySync(bound, Draw::FB_COLOR_BIT, 0, 0, w, h, Draw::DataFormat::R8G8B8A8_UNORM, buffer.GetData(), w); gpuStats.numReadbacks++; @@ -1962,7 +1965,7 @@ bool FramebufferManagerCommon::GetDepthbuffer(u32 fb_address, int fb_stride, u32 h = std::min(h, PSP_CoreParameter().pixelHeight); } - bool flipY = (g_Config.iGPUBackend == GPU_BACKEND_OPENGL && !useBufferedRendering_) ? true : false; + bool flipY = (GetGPUBackend() == GPUBackend::OPENGL && !useBufferedRendering_) ? true : false; if (gstate_c.Supports(GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT)) { buffer.Allocate(w, h, GPU_DBG_FORMAT_FLOAT_DIV_256, flipY); } else { @@ -1996,7 +1999,7 @@ bool FramebufferManagerCommon::GetStencilbuffer(u32 fb_address, int fb_stride, G h = std::min(h, PSP_CoreParameter().pixelHeight); } - bool flipY = (g_Config.iGPUBackend == GPU_BACKEND_OPENGL && !useBufferedRendering_) ? true : false; + bool flipY = (GetGPUBackend() == GPUBackend::OPENGL && !useBufferedRendering_) ? true : false; // No need to free on failure, the caller/destructor will do that. Usually this is a reused buffer, anyway. buffer.Allocate(w, h, GPU_DBG_FORMAT_8BIT, flipY); bool retval = draw_->CopyFramebufferToMemorySync(vfb->fbo, Draw::FB_STENCIL_BIT, 0, 0, w,h, Draw::DataFormat::S8, buffer.GetData(), w); diff --git a/GPU/Common/GPUStateUtils.cpp b/GPU/Common/GPUStateUtils.cpp index e5497ea19a4c..80a9b83d7bb4 100644 --- a/GPU/Common/GPUStateUtils.cpp +++ b/GPU/Common/GPUStateUtils.cpp @@ -509,6 +509,9 @@ float DepthSliceFactor() { if (gstate_c.Supports(GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT)) { return DEPTH_SLICE_FACTOR_16BIT; } + if (gstate_c.Supports(GPU_SUPPORTS_DEPTH_CLAMP)) { + return 1.0f; + } return DEPTH_SLICE_FACTOR_HIGH; } @@ -682,6 +685,7 @@ void ConvertViewportAndScissor(bool useBufferedRendering, float renderWidth, flo // So, we apply the depth range as minz/maxz, and transform for the viewport. float vpZScale = gstate.getViewportZScale(); float vpZCenter = gstate.getViewportZCenter(); + // TODO: This clip the entire draw if minz > maxz. float minz = gstate.getDepthRangeMin(); float maxz = gstate.getDepthRangeMax(); diff --git a/GPU/Common/SoftwareTransformCommon.cpp b/GPU/Common/SoftwareTransformCommon.cpp index c92b9b9131fb..a29c987c11de 100644 --- a/GPU/Common/SoftwareTransformCommon.cpp +++ b/GPU/Common/SoftwareTransformCommon.cpp @@ -408,6 +408,7 @@ void SoftwareTransform( // Need to rescale from a [0, 1] float. This is the final transformed value. result->depth = ToScaledDepth((s16)(int)(transformed[1].z * 65535.0f)); result->action = SW_CLEAR; + gpuStats.numClears++; return; } } @@ -560,5 +561,9 @@ void SoftwareTransform( } } + if (gstate.isModeClear()) { + gpuStats.numClears++; + } + result->action = SW_DRAW_PRIMITIVES; } diff --git a/GPU/D3D11/GPU_D3D11.cpp b/GPU/D3D11/GPU_D3D11.cpp index 6fae0890526d..df3a9aa6f1ae 100644 --- a/GPU/D3D11/GPU_D3D11.cpp +++ b/GPU/D3D11/GPU_D3D11.cpp @@ -518,7 +518,7 @@ void GPU_D3D11::GetStats(char *buffer, size_t bufsize) { float vertexAverageCycles = gpuStats.numVertsSubmitted > 0 ? (float)gpuStats.vertexGPUCycles / (float)gpuStats.numVertsSubmitted : 0.0f; snprintf(buffer, bufsize - 1, "DL processing time: %0.2f ms\n" - "Draw calls: %i, flushes %i\n" + "Draw calls: %i, flushes %i, clears %i\n" "Cached Draw calls: %i\n" "Num Tracked Vertex Arrays: %i\n" "GPU cycles executed: %d (%f per vertex)\n" @@ -532,6 +532,7 @@ void GPU_D3D11::GetStats(char *buffer, size_t bufsize) { gpuStats.msProcessingDisplayLists * 1000.0f, gpuStats.numDrawCalls, gpuStats.numFlushes, + gpuStats.numClears, gpuStats.numCachedDrawCalls, gpuStats.numTrackedVertexArrays, gpuStats.vertexGPUCycles + gpuStats.otherGPUCycles, diff --git a/GPU/D3D11/TextureCacheD3D11.cpp b/GPU/D3D11/TextureCacheD3D11.cpp index 3bf06d5515cb..4132b2d8e675 100644 --- a/GPU/D3D11/TextureCacheD3D11.cpp +++ b/GPU/D3D11/TextureCacheD3D11.cpp @@ -789,7 +789,7 @@ bool TextureCacheD3D11::GetCurrentTextureDebug(GPUDebugBuffer &buffer, int level // TODO: Centralize. if (nextTexture_->framebuffer) { VirtualFramebuffer *vfb = nextTexture_->framebuffer; - bool flipY = g_Config.iGPUBackend == GPU_BACKEND_OPENGL && g_Config.iRenderingMode != FB_NON_BUFFERED_MODE; + bool flipY = GetGPUBackend() == GPUBackend::OPENGL && g_Config.iRenderingMode != FB_NON_BUFFERED_MODE; buffer.Allocate(vfb->bufferWidth, vfb->bufferHeight, GPU_DBG_FORMAT_8888, flipY); bool retval = draw_->CopyFramebufferToMemorySync(vfb->fbo, Draw::FB_COLOR_BIT, 0, 0, vfb->bufferWidth, vfb->bufferHeight, Draw::DataFormat::R8G8B8A8_UNORM, buffer.GetData(), vfb->bufferWidth); // Vulkan requires us to re-apply all dynamic state for each command buffer, and the above will cause us to start a new cmdbuf. diff --git a/GPU/Directx9/GPU_DX9.cpp b/GPU/Directx9/GPU_DX9.cpp index 4afaa7238a59..fb071c7a50c5 100644 --- a/GPU/Directx9/GPU_DX9.cpp +++ b/GPU/Directx9/GPU_DX9.cpp @@ -492,7 +492,7 @@ void GPU_DX9::GetStats(char *buffer, size_t bufsize) { float vertexAverageCycles = gpuStats.numVertsSubmitted > 0 ? (float)gpuStats.vertexGPUCycles / (float)gpuStats.numVertsSubmitted : 0.0f; snprintf(buffer, bufsize - 1, "DL processing time: %0.2f ms\n" - "Draw calls: %i, flushes %i\n" + "Draw calls: %i, flushes %i, clears %i\n" "Cached Draw calls: %i\n" "Num Tracked Vertex Arrays: %i\n" "GPU cycles executed: %d (%f per vertex)\n" @@ -506,6 +506,7 @@ void GPU_DX9::GetStats(char *buffer, size_t bufsize) { gpuStats.msProcessingDisplayLists * 1000.0f, gpuStats.numDrawCalls, gpuStats.numFlushes, + gpuStats.numClears, gpuStats.numCachedDrawCalls, gpuStats.numTrackedVertexArrays, gpuStats.vertexGPUCycles + gpuStats.otherGPUCycles, diff --git a/GPU/GLES/GPU_GLES.cpp b/GPU/GLES/GPU_GLES.cpp index 8142419e9767..eecabf5bfa6b 100644 --- a/GPU/GLES/GPU_GLES.cpp +++ b/GPU/GLES/GPU_GLES.cpp @@ -693,7 +693,7 @@ void GPU_GLES::GetStats(char *buffer, size_t bufsize) { float vertexAverageCycles = gpuStats.numVertsSubmitted > 0 ? (float)gpuStats.vertexGPUCycles / (float)gpuStats.numVertsSubmitted : 0.0f; snprintf(buffer, bufsize - 1, "DL processing time: %0.2f ms\n" - "Draw calls: %i, flushes %i\n" + "Draw calls: %i, flushes %i, clears %i\n" "Cached Draw calls: %i\n" "Num Tracked Vertex Arrays: %i\n" "GPU cycles executed: %d (%f per vertex)\n" @@ -707,6 +707,7 @@ void GPU_GLES::GetStats(char *buffer, size_t bufsize) { gpuStats.msProcessingDisplayLists * 1000.0f, gpuStats.numDrawCalls, gpuStats.numFlushes, + gpuStats.numClears, gpuStats.numCachedDrawCalls, gpuStats.numTrackedVertexArrays, gpuStats.vertexGPUCycles + gpuStats.otherGPUCycles, diff --git a/GPU/GPU.h b/GPU/GPU.h index b10bf19d9aea..7e10db49aaf9 100644 --- a/GPU/GPU.h +++ b/GPU/GPU.h @@ -68,6 +68,7 @@ struct GPUStatistics { numFlushes = 0; numTexturesDecoded = 0; numReadbacks = 0; + numClears = 0; msProcessingDisplayLists = 0; vertexGPUCycles = 0; otherGPUCycles = 0; @@ -87,6 +88,7 @@ struct GPUStatistics { int numShaderSwitches; int numTexturesDecoded; int numReadbacks; + int numClears; double msProcessingDisplayLists; int vertexGPUCycles; int otherGPUCycles; diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index 0897f78c6a89..485475f0f46c 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -181,7 +181,7 @@ const CommonCommandTableEntry commonCommandTable[] = { { GE_CMD_VIEWPORTYCENTER, FLAG_FLUSHBEFOREONCHANGE, DIRTY_FRAMEBUF | DIRTY_TEXTURE_PARAMS | DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_GUARDBAND}, { GE_CMD_VIEWPORTZSCALE, FLAG_FLUSHBEFOREONCHANGE, DIRTY_FRAMEBUF | DIRTY_TEXTURE_PARAMS | DIRTY_DEPTHRANGE | DIRTY_PROJMATRIX | DIRTY_VIEWPORTSCISSOR_STATE }, { GE_CMD_VIEWPORTZCENTER, FLAG_FLUSHBEFOREONCHANGE, DIRTY_FRAMEBUF | DIRTY_TEXTURE_PARAMS | DIRTY_DEPTHRANGE | DIRTY_PROJMATRIX | DIRTY_VIEWPORTSCISSOR_STATE }, - { GE_CMD_CLIPENABLE, FLAG_FLUSHBEFOREONCHANGE, DIRTY_VIEWPORTSCISSOR_STATE }, + { GE_CMD_CLIPENABLE, FLAG_FLUSHBEFOREONCHANGE, DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_RASTER_STATE }, // Z clip { GE_CMD_MINZ, FLAG_FLUSHBEFOREONCHANGE, DIRTY_DEPTHRANGE | DIRTY_VIEWPORTSCISSOR_STATE }, @@ -1745,7 +1745,6 @@ void GPUCommon::Execute_BoneMtxNum(u32 op, u32 diff) { const int end = 12 * 8 - (op & 0x7F); int i = 0; - // TODO: Validate what should happen when explicitly setting num to 96 or higher. bool fastLoad = !debugRecording_ && end > 0; if (currentList->pc < currentList->stall && currentList->pc + end * 4 >= currentList->stall) { fastLoad = false; diff --git a/GPU/GPUState.cpp b/GPU/GPUState.cpp index 976201a120c1..ad71b4ce75cd 100644 --- a/GPU/GPUState.cpp +++ b/GPU/GPUState.cpp @@ -37,6 +37,9 @@ alignas(16) GPUgstate gstate; // Let's align this one too for good measure. alignas(16) GPUStateCache gstate_c; +// For save state compatibility. +static int savedContextVersion = 1; + struct CmdRange { u8 start; u8 end; @@ -77,6 +80,25 @@ static const CmdRange contextCmdRanges[] = { // Skip: {0xFA, 0xFF}, }; +static u32_le *SaveMatrix(u32_le *cmds, const float *mtx, int sz, int numcmd, int datacmd) { + *cmds++ = numcmd << 24; + for (int i = 0; i < sz; ++i) { + *cmds++ = (datacmd << 24) | toFloat24(mtx[i]); + } + + return cmds; +} + +static const u32_le *LoadMatrix(const u32_le *cmds, float *mtx, int sz) { + // Skip the reset. + cmds++; + for (int i = 0; i < sz; ++i) { + mtx[i] = getFloat24(*cmds++); + } + + return cmds; +} + void GPUgstate::Reset() { memset(gstate.cmdmem, 0, sizeof(gstate.cmdmem)); for (int i = 0; i < 256; i++) { @@ -89,6 +111,8 @@ void GPUgstate::Reset() { memset(gstate.projMatrix, 0, sizeof(gstate.projMatrix)); memset(gstate.tgenMatrix, 0, sizeof(gstate.tgenMatrix)); memset(gstate.boneMatrix, 0, sizeof(gstate.boneMatrix)); + + savedContextVersion = 1; } void GPUgstate::Save(u32_le *ptr) { @@ -105,22 +129,37 @@ void GPUgstate::Save(u32_le *ptr) { } } - if (Memory::IsValidAddress(getClutAddress())) - *cmds++ = loadclut; - - // Seems like it actually writes commands to load the matrices and then reset the counts. - *cmds++ = boneMatrixNumber; - *cmds++ = worldmtxnum; - *cmds++ = viewmtxnum; - *cmds++ = projmtxnum; - *cmds++ = texmtxnum; - - u8 *matrices = (u8 *)cmds; - memcpy(matrices, boneMatrix, sizeof(boneMatrix)); matrices += sizeof(boneMatrix); - memcpy(matrices, worldMatrix, sizeof(worldMatrix)); matrices += sizeof(worldMatrix); - memcpy(matrices, viewMatrix, sizeof(viewMatrix)); matrices += sizeof(viewMatrix); - memcpy(matrices, projMatrix, sizeof(projMatrix)); matrices += sizeof(projMatrix); - memcpy(matrices, tgenMatrix, sizeof(tgenMatrix)); matrices += sizeof(tgenMatrix); + if (savedContextVersion == 0) { + if (Memory::IsValidAddress(getClutAddress())) + *cmds++ = loadclut; + + // Seems like it actually writes commands to load the matrices and then reset the counts. + *cmds++ = boneMatrixNumber; + *cmds++ = worldmtxnum; + *cmds++ = viewmtxnum; + *cmds++ = projmtxnum; + *cmds++ = texmtxnum; + + u8 *matrices = (u8 *)cmds; + memcpy(matrices, boneMatrix, sizeof(boneMatrix)); matrices += sizeof(boneMatrix); + memcpy(matrices, worldMatrix, sizeof(worldMatrix)); matrices += sizeof(worldMatrix); + memcpy(matrices, viewMatrix, sizeof(viewMatrix)); matrices += sizeof(viewMatrix); + memcpy(matrices, projMatrix, sizeof(projMatrix)); matrices += sizeof(projMatrix); + memcpy(matrices, tgenMatrix, sizeof(tgenMatrix)); matrices += sizeof(tgenMatrix); + } else { + cmds = SaveMatrix(cmds, boneMatrix, ARRAY_SIZE(boneMatrix), GE_CMD_BONEMATRIXNUMBER, GE_CMD_BONEMATRIXDATA); + cmds = SaveMatrix(cmds, worldMatrix, ARRAY_SIZE(worldMatrix), GE_CMD_WORLDMATRIXNUMBER, GE_CMD_WORLDMATRIXDATA); + cmds = SaveMatrix(cmds, viewMatrix, ARRAY_SIZE(viewMatrix), GE_CMD_VIEWMATRIXNUMBER, GE_CMD_VIEWMATRIXDATA); + cmds = SaveMatrix(cmds, projMatrix, ARRAY_SIZE(projMatrix), GE_CMD_PROJMATRIXNUMBER, GE_CMD_PROJMATRIXDATA); + cmds = SaveMatrix(cmds, tgenMatrix, ARRAY_SIZE(tgenMatrix), GE_CMD_TGENMATRIXNUMBER, GE_CMD_TGENMATRIXDATA); + + *cmds++ = boneMatrixNumber; + *cmds++ = worldmtxnum; + *cmds++ = viewmtxnum; + *cmds++ = projmtxnum; + *cmds++ = texmtxnum; + *cmds++ = GE_CMD_END << 24; + } } void GPUgstate::FastLoadBoneMatrix(u32 addr) { @@ -165,27 +204,41 @@ void GPUgstate::Restore(u32_le *ptr) { gstate_c.offsetAddr = ptr[7]; // Command values start 17 ints in. - u32_le *cmds = ptr + 17; + const u32_le *cmds = ptr + 17; for (size_t i = 0; i < ARRAY_SIZE(contextCmdRanges); ++i) { for (int n = contextCmdRanges[i].start; n <= contextCmdRanges[i].end; ++n) { cmdmem[n] = *cmds++; } } - if (Memory::IsValidAddress(getClutAddress())) - loadclut = *cmds++; - boneMatrixNumber = *cmds++; - worldmtxnum = *cmds++; - viewmtxnum = *cmds++; - projmtxnum = *cmds++; - texmtxnum = *cmds++; - - u8 *matrices = (u8 *)cmds; - memcpy(boneMatrix, matrices, sizeof(boneMatrix)); matrices += sizeof(boneMatrix); - memcpy(worldMatrix, matrices, sizeof(worldMatrix)); matrices += sizeof(worldMatrix); - memcpy(viewMatrix, matrices, sizeof(viewMatrix)); matrices += sizeof(viewMatrix); - memcpy(projMatrix, matrices, sizeof(projMatrix)); matrices += sizeof(projMatrix); - memcpy(tgenMatrix, matrices, sizeof(tgenMatrix)); matrices += sizeof(tgenMatrix); + if (savedContextVersion == 0) { + if (Memory::IsValidAddress(getClutAddress())) + loadclut = *cmds++; + boneMatrixNumber = *cmds++; + worldmtxnum = *cmds++; + viewmtxnum = *cmds++; + projmtxnum = *cmds++; + texmtxnum = *cmds++; + + u8 *matrices = (u8 *)cmds; + memcpy(boneMatrix, matrices, sizeof(boneMatrix)); matrices += sizeof(boneMatrix); + memcpy(worldMatrix, matrices, sizeof(worldMatrix)); matrices += sizeof(worldMatrix); + memcpy(viewMatrix, matrices, sizeof(viewMatrix)); matrices += sizeof(viewMatrix); + memcpy(projMatrix, matrices, sizeof(projMatrix)); matrices += sizeof(projMatrix); + memcpy(tgenMatrix, matrices, sizeof(tgenMatrix)); matrices += sizeof(tgenMatrix); + } else { + cmds = LoadMatrix(cmds, boneMatrix, ARRAY_SIZE(boneMatrix)); + cmds = LoadMatrix(cmds, worldMatrix, ARRAY_SIZE(worldMatrix)); + cmds = LoadMatrix(cmds, viewMatrix, ARRAY_SIZE(viewMatrix)); + cmds = LoadMatrix(cmds, projMatrix, ARRAY_SIZE(projMatrix)); + cmds = LoadMatrix(cmds, tgenMatrix, ARRAY_SIZE(tgenMatrix)); + + boneMatrixNumber = *cmds++; + worldmtxnum = *cmds++; + viewmtxnum = *cmds++; + projmtxnum = *cmds++; + texmtxnum = *cmds++; + } } bool vertTypeIsSkinningEnabled(u32 vertType) { @@ -217,7 +270,7 @@ void GPUStateCache::Reset() { } void GPUStateCache::DoState(PointerWrap &p) { - auto s = p.Section("GPUStateCache", 0, 4); + auto s = p.Section("GPUStateCache", 0, 5); if (!s) { // Old state, this was not versioned. GPUStateCache_v0 old; @@ -231,6 +284,8 @@ void GPUStateCache::DoState(PointerWrap &p) { vertexFullAlpha = old.vertexFullAlpha; skipDrawReason = old.skipDrawReason; uv = old.uv; + + savedContextVersion = 0; } else { p.Do(vertexAddr); p.Do(indexAddr); @@ -290,4 +345,9 @@ void GPUStateCache::DoState(PointerWrap &p) { p.Do(curRTHeight); // curRTBufferWidth, curRTBufferHeight, and cutRTOffsetX don't need to be saved. + if (s < 5) { + savedContextVersion = 0; + } else { + p.Do(savedContextVersion); + } } diff --git a/GPU/GPUState.h b/GPU/GPUState.h index 060fffb47dea..811f1fa62155 100644 --- a/GPU/GPUState.h +++ b/GPU/GPUState.h @@ -477,6 +477,7 @@ enum { GPU_SUPPORTS_VERTEX_TEXTURE_FETCH = FLAG_BIT(11), GPU_SUPPORTS_TEXTURE_FLOAT = FLAG_BIT(12), GPU_SUPPORTS_16BIT_FORMATS = FLAG_BIT(13), + GPU_SUPPORTS_DEPTH_CLAMP = FLAG_BIT(14), GPU_SUPPORTS_LARGE_VIEWPORTS = FLAG_BIT(16), GPU_SUPPORTS_ACCURATE_DEPTH = FLAG_BIT(17), GPU_SUPPORTS_VAO = FLAG_BIT(18), diff --git a/GPU/Software/Clipper.cpp b/GPU/Software/Clipper.cpp index 72859b71c073..2dcb1dd91951 100644 --- a/GPU/Software/Clipper.cpp +++ b/GPU/Software/Clipper.cpp @@ -255,7 +255,7 @@ void ProcessLine(VertexData& v0, VertexData& v1) return; } - if (mask && (gstate.clipEnable & 0x1)) { + if (mask && gstate.isClippingEnabled()) { // discard if any vertex is outside the near clipping plane if (mask & CLIP_NEG_Z_BIT) return; @@ -303,7 +303,7 @@ void ProcessTriangle(VertexData& v0, VertexData& v1, VertexData& v2) mask |= CalcClipMask(v1.clippos); mask |= CalcClipMask(v2.clippos); - if (mask && (gstate.clipEnable & 0x1)) { + if (mask && gstate.isClippingEnabled()) { // discard if any vertex is outside the near clipping plane if (mask & CLIP_NEG_Z_BIT) return; diff --git a/GPU/Software/TransformUnit.cpp b/GPU/Software/TransformUnit.cpp index 12dec65ea6f7..8f5505aa798a 100644 --- a/GPU/Software/TransformUnit.cpp +++ b/GPU/Software/TransformUnit.cpp @@ -104,8 +104,8 @@ static inline ScreenCoords ClipToScreenInternal(const ClipCoords& coords, bool * float y = coords.y * yScale / coords.w + yCenter; float z = coords.z * zScale / coords.w + zCenter; - // Is this really right? - if (gstate.clipEnable & 0x1) { + // This matches hardware tests - depth is clamped when this flag is on. + if (gstate.isClippingEnabled()) { if (z < 0.f) z = 0.f; if (z > 65535.f) diff --git a/GPU/Vulkan/FragmentShaderGeneratorVulkan.cpp b/GPU/Vulkan/FragmentShaderGeneratorVulkan.cpp index 9d67e73f8988..65b8c4bf719c 100644 --- a/GPU/Vulkan/FragmentShaderGeneratorVulkan.cpp +++ b/GPU/Vulkan/FragmentShaderGeneratorVulkan.cpp @@ -457,8 +457,20 @@ bool GenerateVulkanGLSLFragmentShader(const FShaderID &id, char *buffer) { } if (gstate_c.Supports(GPU_ROUND_FRAGMENT_DEPTH_TO_16BIT)) { + const double scale = DepthSliceFactor() * 65535.0; + WRITE(p, " highp float z = gl_FragCoord.z;\n"); - WRITE(p, " z = (1.0/65535.0) * floor(z * 65535.0);\n"); + if (gstate_c.Supports(GPU_SUPPORTS_ACCURATE_DEPTH)) { + // We center the depth with an offset, but only its fraction matters. + // When (DepthSliceFactor() - 1) is odd, it will be 0.5, otherwise 0. + if (((int)(DepthSliceFactor() - 1.0f) & 1) == 1) { + WRITE(p, " z = (floor((z * %f) - (1.0 / 2.0)) + (1.0 / 2.0)) * (1.0 / %f);\n", scale, scale); + } else { + WRITE(p, " z = floor(z * %f) * (1.0 / %f);\n", scale, scale); + } + } else { + WRITE(p, " z = (1.0/65535.0) * floor(z * 65535.0);\n"); + } if (PSP_CoreParameter().compat.flags().DecreaseFragmentDepthAccuracy) { WRITE(p, " z /= 2000.0;\n"); // Nasty hack to completely remove flicker in Heroes Phantasia } diff --git a/GPU/Vulkan/GPU_Vulkan.cpp b/GPU/Vulkan/GPU_Vulkan.cpp index e2015c32d5b4..2f3689081aa6 100644 --- a/GPU/Vulkan/GPU_Vulkan.cpp +++ b/GPU/Vulkan/GPU_Vulkan.cpp @@ -209,6 +209,9 @@ void GPU_Vulkan::CheckGPUFeatures() { if (vulkan_->GetFeaturesEnabled().wideLines) { features |= GPU_SUPPORTS_WIDE_LINES; } + if (vulkan_->GetFeaturesEnabled().depthClamp) { + features |= GPU_SUPPORTS_DEPTH_CLAMP; + } if (vulkan_->GetFeaturesEnabled().dualSrcBlend) { switch (vulkan_->GetPhysicalDeviceProperties().vendorID) { case VULKAN_VENDOR_NVIDIA: @@ -656,7 +659,7 @@ void GPU_Vulkan::GetStats(char *buffer, size_t bufsize) { float vertexAverageCycles = gpuStats.numVertsSubmitted > 0 ? (float)gpuStats.vertexGPUCycles / (float)gpuStats.numVertsSubmitted : 0.0f; snprintf(buffer, bufsize - 1, "DL processing time: %0.2f ms\n" - "Draw calls: %i, flushes %i\n" + "Draw calls: %i, flushes %i, clears %i\n" "Cached Draw calls: %i\n" "Num Tracked Vertex Arrays: %i\n" "GPU cycles executed: %d (%f per vertex)\n" @@ -672,6 +675,7 @@ void GPU_Vulkan::GetStats(char *buffer, size_t bufsize) { gpuStats.msProcessingDisplayLists * 1000.0f, gpuStats.numDrawCalls, gpuStats.numFlushes, + gpuStats.numClears, gpuStats.numCachedDrawCalls, gpuStats.numTrackedVertexArrays, gpuStats.vertexGPUCycles + gpuStats.otherGPUCycles, diff --git a/GPU/Vulkan/PipelineManagerVulkan.cpp b/GPU/Vulkan/PipelineManagerVulkan.cpp index dbf3e1e130b0..4dcd4b623524 100644 --- a/GPU/Vulkan/PipelineManagerVulkan.cpp +++ b/GPU/Vulkan/PipelineManagerVulkan.cpp @@ -188,7 +188,7 @@ static VulkanPipeline *CreateVulkanPipeline(VkDevice device, VkPipelineCache pip rs.lineWidth = lineWidth; rs.rasterizerDiscardEnable = false; rs.polygonMode = VK_POLYGON_MODE_FILL; - rs.depthClampEnable = false; + rs.depthClampEnable = key.depthClampEnable; VkPipelineMultisampleStateCreateInfo ms = { VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO }; ms.pSampleMask = nullptr; diff --git a/GPU/Vulkan/StateMappingVulkan.cpp b/GPU/Vulkan/StateMappingVulkan.cpp index 9af27db04275..1e78e352ef4b 100644 --- a/GPU/Vulkan/StateMappingVulkan.cpp +++ b/GPU/Vulkan/StateMappingVulkan.cpp @@ -241,10 +241,13 @@ void DrawEngineVulkan::ConvertStateToVulkanKey(FramebufferManagerVulkan &fbManag if (gstate_c.IsDirty(DIRTY_RASTER_STATE)) { if (gstate.isModeClear()) { key.cullMode = VK_CULL_MODE_NONE; + // TODO: Or does it always clamp? + key.depthClampEnable = false; } else { // Set cull bool wantCull = !gstate.isModeThrough() && prim != GE_PRIM_RECTANGLES && gstate.isCullEnabled(); key.cullMode = wantCull ? (gstate.getCullMode() ? VK_CULL_MODE_FRONT_BIT : VK_CULL_MODE_BACK_BIT) : VK_CULL_MODE_NONE; + key.depthClampEnable = gstate.isClippingEnabled() && gstate_c.Supports(GPU_SUPPORTS_DEPTH_CLAMP); } } diff --git a/GPU/Vulkan/StateMappingVulkan.h b/GPU/Vulkan/StateMappingVulkan.h index f1d8013f69d8..9306f5051df1 100644 --- a/GPU/Vulkan/StateMappingVulkan.h +++ b/GPU/Vulkan/StateMappingVulkan.h @@ -20,7 +20,7 @@ struct VulkanDynamicState { // Let's pack this tight using bitfields. // If an enable flag is set to 0, all the data fields for that section should // also be set to 0. -// ~54 bits. +// ~64 bits. // Can't use enums unfortunately, they end up signed and breaking values above half their ranges. struct VulkanPipelineRasterStateKey { // Blend @@ -37,6 +37,7 @@ struct VulkanPipelineRasterStateKey { unsigned int colorWriteMask : 4; // Depth/Stencil + unsigned int depthClampEnable : 1; unsigned int depthTestEnable : 1; unsigned int depthWriteEnable : 1; unsigned int depthCompareOp : 3; // VkCompareOp @@ -57,4 +58,4 @@ struct VulkanPipelineRasterStateKey { size_t size = sizeof(VulkanPipelineRasterStateKey); return memcmp(this, &other, size) < 0; } -}; \ No newline at end of file +}; diff --git a/GPU/Vulkan/TextureCacheVulkan.cpp b/GPU/Vulkan/TextureCacheVulkan.cpp index 6c5f01bd6d90..fe33b0945ff0 100644 --- a/GPU/Vulkan/TextureCacheVulkan.cpp +++ b/GPU/Vulkan/TextureCacheVulkan.cpp @@ -797,7 +797,7 @@ bool TextureCacheVulkan::GetCurrentTextureDebug(GPUDebugBuffer &buffer, int leve // TODO: Centralize? if (nextTexture_->framebuffer) { VirtualFramebuffer *vfb = nextTexture_->framebuffer; - bool flipY = g_Config.iGPUBackend == GPU_BACKEND_OPENGL && g_Config.iRenderingMode != FB_NON_BUFFERED_MODE; + bool flipY = GetGPUBackend() == GPUBackend::OPENGL && g_Config.iRenderingMode != FB_NON_BUFFERED_MODE; buffer.Allocate(vfb->bufferWidth, vfb->bufferHeight, GPU_DBG_FORMAT_8888, flipY); bool retval = draw_->CopyFramebufferToMemorySync(vfb->fbo, Draw::FB_COLOR_BIT, 0, 0, vfb->bufferWidth, vfb->bufferHeight, Draw::DataFormat::R8G8B8A8_UNORM, buffer.GetData(), vfb->bufferWidth); // Vulkan requires us to re-apply all dynamic state for each command buffer, and the above will cause us to start a new cmdbuf. diff --git a/Qt/QtMain.h b/Qt/QtMain.h index d1bcc87fa984..f4f1b3c5c281 100644 --- a/Qt/QtMain.h +++ b/Qt/QtMain.h @@ -25,6 +25,7 @@ QTM_USE_NAMESPACE #include "base/timeutil.h" #include "file/zip_read.h" #include "gfx/gl_common.h" +#include "gfx_es2/gpu_features.h" #include "input/input_state.h" #include "input/keycodes.h" #include "thin3d/thin3d.h" @@ -33,9 +34,9 @@ QTM_USE_NAMESPACE #include "base/NKCodeFromQt.h" #include "Common/GraphicsContext.h" -#include "Core/System.h" #include "Core/Core.h" #include "Core/Config.h" +#include "Core/System.h" // Input void SimulateGamepad(); @@ -43,7 +44,9 @@ void SimulateGamepad(); class QtDummyGraphicsContext : public DummyGraphicsContext { public: QtDummyGraphicsContext() { + CheckGLExtensions(); draw_ = Draw::T3DCreateGLContext(); + SetGPUBackend(GPUBackend::OPENGL); bool success = draw_->CreatePresets(); assert(success); } diff --git a/SDL/SDLMain.cpp b/SDL/SDLMain.cpp index 04e011e314cd..acc5cc0e1061 100644 --- a/SDL/SDLMain.cpp +++ b/SDL/SDLMain.cpp @@ -340,6 +340,7 @@ int SDLGLGraphicsContext::Init(SDL_Window *&window, int x, int y, int mode, std: // Finally we can do the regular initialization. CheckGLExtensions(); draw_ = Draw::T3DCreateGLContext(); + SetGPUBackend(GPUBackend::OPENGL); bool success = draw_->CreatePresets(); assert(success); window_ = window; @@ -438,27 +439,27 @@ bool SDLVulkanGraphicsContext::Init(SDL_Window *&window, int x, int y, int mode, 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: +#if defined(VK_USE_PLATFORM_XLIB_KHR) + vulkan_->InitSurface(WINDOWSYSTEM_XLIB, (void*)sys_info.info.x11.display, + (void *)(intptr_t)sys_info.info.x11.window, pixel_xres, pixel_yres); +#elif defined(VK_USE_PLATFORM_XCB_KHR) + vulkan_->InitSurface(WINDOWSYSTEM_XCB, (void*)XGetXCBConnection(sys_info.info.x11.display), + (void *)(intptr_t)sys_info.info.x11.window, pixel_xres, pixel_yres); +#endif break; +#if defined(VK_USE_PLATFORM_WAYLAND_KHR) + case SDL_SYSWM_WAYLAND: + vulkan_->InitSurface(WINDOWSYSTEM_WAYLAND, (void*)sys_info.info.wl.display, + (void *)sys_info.info.wl.surface, pixel_xres, pixel_yres); + break; +#endif 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()) { @@ -468,6 +469,7 @@ bool SDLVulkanGraphicsContext::Init(SDL_Window *&window, int x, int y, int mode, } draw_ = Draw::T3DCreateVulkanContext(vulkan_, false); + SetGPUBackend(GPUBackend::VULKAN); bool success = draw_->CreatePresets(); assert(success); draw_->HandleEvent(Draw::Event::GOT_BACKBUFFER, vulkan_->GetBackbufferWidth(), vulkan_->GetBackbufferHeight()); @@ -865,17 +867,18 @@ int main(int argc, char *argv[]) { GraphicsContext *graphicsContext = nullptr; SDL_Window *window = nullptr; std::string error_message; - if (g_Config.iGPUBackend == GPU_BACKEND_OPENGL) { + if (g_Config.iGPUBackend == (int)GPUBackend::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) { + } else if (g_Config.iGPUBackend == (int)GPUBackend::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; + g_Config.iGPUBackend = (int)GPUBackend::OPENGL; + SetGPUBackend((GPUBackend)g_Config.iGPUBackend); delete ctx; SDLGLGraphicsContext *glctx = new SDLGLGraphicsContext(); glctx->Init(window, x, y, mode, &error_message); diff --git a/UI/DevScreens.cpp b/UI/DevScreens.cpp index 60a8bc8a6795..e5b6addd636d 100644 --- a/UI/DevScreens.cpp +++ b/UI/DevScreens.cpp @@ -391,7 +391,7 @@ void SystemInfoScreen::CreateViews() { deviceSpecs->Add(new InfoItem(si->T("Vendor (detected)"), vendor)); deviceSpecs->Add(new InfoItem(si->T("Driver Version"), draw->GetInfoString(InfoField::DRIVER))); #ifdef _WIN32 - if (g_Config.iGPUBackend != GPU_BACKEND_VULKAN) + if (GetGPUBackend() != GPUBackend::VULKAN) deviceSpecs->Add(new InfoItem(si->T("Driver Version"), System_GetProperty(SYSPROP_GPUDRIVER_VERSION))); #if !PPSSPP_PLATFORM(UWP) if (GetGPUBackend() == GPUBackend::DIRECT3D9) { @@ -399,7 +399,7 @@ void SystemInfoScreen::CreateViews() { } #endif #endif - if (g_Config.iGPUBackend == GPU_BACKEND_OPENGL) { + if (GetGPUBackend() == GPUBackend::OPENGL) { deviceSpecs->Add(new InfoItem(si->T("Core Context"), gl_extensions.IsCoreContext ? si->T("Yes") : si->T("No"))); } deviceSpecs->Add(new ItemHeader(si->T("OS Information"))); @@ -510,7 +510,7 @@ void SystemInfoScreen::CreateViews() { gpuExtensions->SetSpacing(0); gpuExtensionsScroll->Add(gpuExtensions); - if (g_Config.iGPUBackend == GPU_BACKEND_OPENGL) { + if (GetGPUBackend() == GPUBackend::OPENGL) { tabHolder->AddTab(si->T("OGL Extensions"), gpuExtensionsScroll); if (!gl_extensions.IsGLES) { @@ -547,7 +547,7 @@ void SystemInfoScreen::CreateViews() { eglExtensions->Add(new TextView(extension, new LayoutParams(FILL_PARENT, WRAP_CONTENT)))->SetFocusable(true); } } - } else if (g_Config.iGPUBackend == GPU_BACKEND_VULKAN) { + } else if (GetGPUBackend() == GPUBackend::VULKAN) { tabHolder->AddTab(si->T("Vulkan Features"), gpuExtensionsScroll); gpuExtensions->Add(new ItemHeader(si->T("Vulkan Features"))); diff --git a/UI/DisplayLayoutScreen.cpp b/UI/DisplayLayoutScreen.cpp index f198e18647c0..7b9dfc2f7c1e 100644 --- a/UI/DisplayLayoutScreen.cpp +++ b/UI/DisplayLayoutScreen.cpp @@ -165,7 +165,11 @@ bool DisplayLayoutScreen::touch(const TouchInput &touch) { picked_ = 0; } return true; -}; +} + +void DisplayLayoutScreen::resized() { + RecreateViews(); +} void DisplayLayoutScreen::onFinish(DialogResult reason) { g_Config.Save(); diff --git a/UI/DisplayLayoutScreen.h b/UI/DisplayLayoutScreen.h index a9d29c19e9e6..725131fab31a 100644 --- a/UI/DisplayLayoutScreen.h +++ b/UI/DisplayLayoutScreen.h @@ -31,6 +31,7 @@ class DisplayLayoutScreen : public UIDialogScreenWithBackground { virtual bool touch(const TouchInput &touch) override; virtual void dialogFinished(const Screen *dialog, DialogResult result) override; virtual void onFinish(DialogResult reason) override; + virtual void resized() override; std::string tag() const override { return "display layout screen"; } protected: diff --git a/UI/GameSettingsScreen.cpp b/UI/GameSettingsScreen.cpp index 827bbc2297ad..a54d341239cd 100644 --- a/UI/GameSettingsScreen.cpp +++ b/UI/GameSettingsScreen.cpp @@ -106,11 +106,11 @@ bool CheckSupportInstancedTessellationGLES() { } bool IsBackendSupportHWTess() { - switch (g_Config.iGPUBackend) { - case GPU_BACKEND_OPENGL: + switch (GetGPUBackend()) { + case GPUBackend::OPENGL: return CheckSupportInstancedTessellationGLES(); - case GPU_BACKEND_VULKAN: - case GPU_BACKEND_DIRECT3D11: + case GPUBackend::VULKAN: + case GPUBackend::DIRECT3D11: return true; } return false; @@ -181,7 +181,7 @@ void GameSettingsScreen::CreateViews() { if (!g_Config.bSimpleUI) { graphicsSettings->Add(new ItemHeader(gr->T("Rendering Mode"))); static const char *renderingBackend[] = { "OpenGL", "Direct3D 9", "Direct3D 11", "Vulkan" }; - PopupMultiChoice *renderingBackendChoice = graphicsSettings->Add(new PopupMultiChoice(&g_Config.iGPUBackend, gr->T("Backend"), renderingBackend, GPU_BACKEND_OPENGL, ARRAY_SIZE(renderingBackend), gr->GetName(), screenManager())); + PopupMultiChoice *renderingBackendChoice = graphicsSettings->Add(new PopupMultiChoice(&g_Config.iGPUBackend, gr->T("Backend"), renderingBackend, (int)GPUBackend::OPENGL, ARRAY_SIZE(renderingBackend), gr->GetName(), screenManager())); renderingBackendChoice->OnChoice.Handle(this, &GameSettingsScreen::OnRenderingBackend); #if !PPSSPP_PLATFORM(WINDOWS) renderingBackendChoice->HideChoice(1); // D3D9 @@ -254,7 +254,7 @@ void GameSettingsScreen::CreateViews() { } graphicsSettings->Add(new ItemHeader(gr->T("Features"))); // Hide postprocess option on unsupported backends to avoid confusion. - if (g_Config.iGPUBackend != GPU_BACKEND_DIRECT3D9) { + if (GetGPUBackend() != GPUBackend::DIRECT3D9) { I18NCategory *ps = GetI18NCategory("PostShaders"); postProcChoice_ = graphicsSettings->Add(new ChoiceWithValueDisplay(&g_Config.sPostShaderName, gr->T("Postprocessing Shader"), ps->GetName())); postProcChoice_->OnClick.Handle(this, &GameSettingsScreen::OnPostProcShader); diff --git a/UI/NativeApp.cpp b/UI/NativeApp.cpp index 6c501f8df8d7..1b4c4ad62a6d 100644 --- a/UI/NativeApp.cpp +++ b/UI/NativeApp.cpp @@ -1099,10 +1099,6 @@ void NativeResized() { // NativeResized can come from any thread so we just set a flag, then process it later. if (g_graphicsInited) { resized = true; - if (uiContext) { - // Still have to update bounds to avoid problems in display layout and touch controls layout screens - uiContext->SetBounds(Bounds(0, 0, dp_xres, dp_yres)); - } } else { ILOG("NativeResized ignored, not initialized"); } diff --git a/UI/TouchControlLayoutScreen.cpp b/UI/TouchControlLayoutScreen.cpp index 08e1159b04e0..87dee45e3144 100644 --- a/UI/TouchControlLayoutScreen.cpp +++ b/UI/TouchControlLayoutScreen.cpp @@ -279,7 +279,11 @@ bool TouchControlLayoutScreen::touch(const TouchInput &touch) { pickedControl_ = 0; } return true; -}; +} + +void TouchControlLayoutScreen::resized() { + RecreateViews(); +} void TouchControlLayoutScreen::onFinish(DialogResult reason) { g_Config.Save(); diff --git a/UI/TouchControlLayoutScreen.h b/UI/TouchControlLayoutScreen.h index 59e3d9fd650c..789d5a25e73c 100644 --- a/UI/TouchControlLayoutScreen.h +++ b/UI/TouchControlLayoutScreen.h @@ -34,6 +34,7 @@ class TouchControlLayoutScreen : public UIDialogScreenWithBackground { virtual bool touch(const TouchInput &touch) override; virtual void dialogFinished(const Screen *dialog, DialogResult result) override; virtual void onFinish(DialogResult reason) override; + virtual void resized() override; protected: virtual UI::EventReturn OnReset(UI::EventParams &e); diff --git a/Windows/EmuThread.cpp b/Windows/EmuThread.cpp index b48f92e394e9..87ae5f1d1707 100644 --- a/Windows/EmuThread.cpp +++ b/Windows/EmuThread.cpp @@ -106,19 +106,19 @@ void EmuThreadFunc() { const char *defaultErrorOpenGL = "Failed initializing graphics. Try upgrading your graphics drivers.\n\nWould you like to try switching to DirectX 9?\n\nError message:"; const char *defaultErrorDirect3D9 = "Failed initializing graphics. Try upgrading your graphics drivers and directx 9 runtime.\n\nWould you like to try switching to OpenGL?\n\nError message:"; const char *genericError; - int nextBackend = GPU_BACKEND_DIRECT3D9; + GPUBackend nextBackend = GPUBackend::DIRECT3D9; switch (g_Config.iGPUBackend) { - case GPU_BACKEND_DIRECT3D9: - nextBackend = GPU_BACKEND_OPENGL; + case (int)GPUBackend::DIRECT3D9: + nextBackend = GPUBackend::OPENGL; genericError = err->T("GenericDirect3D9Error", defaultErrorDirect3D9); break; - case GPU_BACKEND_VULKAN: - nextBackend = GPU_BACKEND_OPENGL; + case (int)GPUBackend::VULKAN: + nextBackend = GPUBackend::OPENGL; genericError = err->T("GenericVulkanError", defaultErrorVulkan); break; - case GPU_BACKEND_OPENGL: + case (int)GPUBackend::OPENGL: default: - nextBackend = GPU_BACKEND_DIRECT3D9; + nextBackend = GPUBackend::DIRECT3D9; genericError = err->T("GenericOpenGLError", defaultErrorOpenGL); break; } @@ -129,7 +129,7 @@ void EmuThreadFunc() { if (yes) { // Change the config to the alternative and restart. - g_Config.iGPUBackend = nextBackend; + g_Config.iGPUBackend = (int)nextBackend; g_Config.Save(); W32Util::ExitAndRestart(); diff --git a/Windows/GPU/D3D11Context.cpp b/Windows/GPU/D3D11Context.cpp index bf7765c77191..b8ec01bd4be9 100644 --- a/Windows/GPU/D3D11Context.cpp +++ b/Windows/GPU/D3D11Context.cpp @@ -10,6 +10,7 @@ #include "Core/Config.h" #include "Core/Reporting.h" +#include "Core/System.h" #include "Windows/GPU/D3D11Context.h" #include "Windows/W32Util/Misc.h" #include "thin3d/thin3d.h" @@ -113,7 +114,7 @@ bool D3D11Context::Init(HINSTANCE hInst, HWND wnd, std::string *error_message) { bool yes = IDYES == MessageBox(hWnd_, error.c_str(), title.c_str(), MB_ICONERROR | MB_YESNO); if (yes) { // Change the config to D3D and restart. - g_Config.iGPUBackend = GPU_BACKEND_DIRECT3D9; + g_Config.iGPUBackend = (int)GPUBackend::DIRECT3D9; g_Config.Save(); W32Util::ExitAndRestart(); @@ -140,6 +141,7 @@ bool D3D11Context::Init(HINSTANCE hInst, HWND wnd, std::string *error_message) { #endif draw_ = Draw::T3DCreateD3D11Context(device_, context_, device1_, context1_, featureLevel_, hWnd_); + SetGPUBackend(GPUBackend::DIRECT3D11); bool success = draw_->CreatePresets(); // If we can run D3D11, there's a compiler installed. I think. assert(success); diff --git a/Windows/GPU/D3D9Context.cpp b/Windows/GPU/D3D9Context.cpp index 4566464a78dc..19f772fb91bd 100644 --- a/Windows/GPU/D3D9Context.cpp +++ b/Windows/GPU/D3D9Context.cpp @@ -9,6 +9,7 @@ #include "Core/Config.h" #include "Core/Reporting.h" +#include "Core/System.h" #include "Common/OSVersion.h" #include "Windows/GPU/D3D9Context.h" #include "Windows/W32Util/Misc.h" @@ -165,6 +166,7 @@ bool D3D9Context::Init(HINSTANCE hInst, HWND wnd, std::string *error_message) { //deviceEx->SetMaximumFrameLatency(1); } draw_ = Draw::T3DCreateDX9Context(d3d_, d3dEx_, adapterId_, device_, deviceEx_); + SetGPUBackend(GPUBackend::DIRECT3D9); if (!draw_->CreatePresets()) { // Shader compiler not installed? Return an error so we can fall back to GL. device_->Release(); diff --git a/Windows/GPU/WindowsGLContext.cpp b/Windows/GPU/WindowsGLContext.cpp index 54486671d130..3b9707ca4c05 100644 --- a/Windows/GPU/WindowsGLContext.cpp +++ b/Windows/GPU/WindowsGLContext.cpp @@ -243,7 +243,7 @@ bool WindowsGLContext::Init(HINSTANCE hInst, HWND window, std::string *error_mes if (yes) { // Change the config to D3D and restart. - g_Config.iGPUBackend = GPU_BACKEND_DIRECT3D9; + g_Config.iGPUBackend = (int)GPUBackend::DIRECT3D9; g_Config.Save(); W32Util::ExitAndRestart(); @@ -362,6 +362,7 @@ bool WindowsGLContext::Init(HINSTANCE hInst, HWND window, std::string *error_mes CheckGLExtensions(); draw_ = Draw::T3DCreateGLContext(); + SetGPUBackend(GPUBackend::OPENGL); bool success = draw_->CreatePresets(); // if we get this far, there will always be a GLSL compiler capable of compiling these. assert(success); CHECK_GL_ERROR_IF_DEBUG(); diff --git a/Windows/GPU/WindowsVulkanContext.cpp b/Windows/GPU/WindowsVulkanContext.cpp index 87ceca55362f..67e6f5195495 100644 --- a/Windows/GPU/WindowsVulkanContext.cpp +++ b/Windows/GPU/WindowsVulkanContext.cpp @@ -51,6 +51,7 @@ #include #include "Core/Config.h" +#include "Core/System.h" #include "Common/Vulkan/VulkanLoader.h" #include "Common/Vulkan/VulkanContext.h" #include "Common/Vulkan/VulkanDebug.h" @@ -131,6 +132,7 @@ bool WindowsVulkanContext::Init(HINSTANCE hInst, HWND hWnd, std::string *error_m bool splitSubmit = g_Config.bGfxDebugSplitSubmit; draw_ = Draw::T3DCreateVulkanContext(g_Vulkan, splitSubmit); + SetGPUBackend(GPUBackend::VULKAN); bool success = draw_->CreatePresets(); assert(success); // Doesn't fail, we include the compiler. draw_->HandleEvent(Draw::Event::GOT_BACKBUFFER, g_Vulkan->GetBackbufferWidth(), g_Vulkan->GetBackbufferHeight()); diff --git a/Windows/MainWindow.cpp b/Windows/MainWindow.cpp index 61a195000227..f56ade7bce2d 100644 --- a/Windows/MainWindow.cpp +++ b/Windows/MainWindow.cpp @@ -279,10 +279,6 @@ namespace MainWindow NativeMessageReceived("gpu_resized", ""); } - if (screenManager) { - screenManager->RecreateAllViews(); - } - // Don't save the window state if fullscreen. if (!g_Config.bFullScreen) { g_WindowState = newSizingType; diff --git a/Windows/MainWindowMenu.cpp b/Windows/MainWindowMenu.cpp index 44831441f744..3ddafc14e487 100644 --- a/Windows/MainWindowMenu.cpp +++ b/Windows/MainWindowMenu.cpp @@ -213,7 +213,7 @@ namespace MainWindow { const char *translatedShaderName = nullptr; availableShaders.clear(); - if (g_Config.iGPUBackend == GPU_BACKEND_DIRECT3D9) { + if (GetGPUBackend() == GPUBackend::DIRECT3D9) { translatedShaderName = ps->T("Not available in Direct3D9 backend"); AppendMenu(shaderMenu, MF_STRING | MF_BYPOSITION | MF_GRAYED, item++, ConvertUTF8ToWString(translatedShaderName).c_str()); } else { @@ -787,22 +787,22 @@ namespace MainWindow { break; case ID_OPTIONS_DIRECT3D9: - g_Config.iGPUBackend = GPU_BACKEND_DIRECT3D9; + g_Config.iGPUBackend = (int)GPUBackend::DIRECT3D9; RestartApp(); break; case ID_OPTIONS_DIRECT3D11: - g_Config.iGPUBackend = GPU_BACKEND_DIRECT3D11; + g_Config.iGPUBackend = (int)GPUBackend::DIRECT3D11; RestartApp(); break; case ID_OPTIONS_OPENGL: - g_Config.iGPUBackend = GPU_BACKEND_OPENGL; + g_Config.iGPUBackend = (int)GPUBackend::OPENGL; RestartApp(); break; case ID_OPTIONS_VULKAN: - g_Config.iGPUBackend = GPU_BACKEND_VULKAN; + g_Config.iGPUBackend = (int)GPUBackend::VULKAN; RestartApp(); break; @@ -1275,8 +1275,8 @@ namespace MainWindow { CheckMenuItem(menu, savestateSlot[i], MF_BYCOMMAND | ((i == g_Config.iCurrentStateSlot) ? MF_CHECKED : MF_UNCHECKED)); } - switch (g_Config.iGPUBackend) { - case GPU_BACKEND_DIRECT3D9: + switch (GetGPUBackend()) { + case GPUBackend::DIRECT3D9: EnableMenuItem(menu, ID_OPTIONS_DIRECT3D9, MF_GRAYED); EnableMenuItem(menu, ID_OPTIONS_DIRECT3D11, MF_ENABLED); EnableMenuItem(menu, ID_OPTIONS_OPENGL, MF_ENABLED); @@ -1286,7 +1286,7 @@ namespace MainWindow { CheckMenuItem(menu, ID_OPTIONS_OPENGL, MF_UNCHECKED); CheckMenuItem(menu, ID_OPTIONS_VULKAN, MF_UNCHECKED); break; - case GPU_BACKEND_OPENGL: + case GPUBackend::OPENGL: EnableMenuItem(menu, ID_OPTIONS_DIRECT3D9, MF_ENABLED); EnableMenuItem(menu, ID_OPTIONS_DIRECT3D11, MF_ENABLED); EnableMenuItem(menu, ID_OPTIONS_OPENGL, MF_GRAYED); @@ -1296,7 +1296,7 @@ namespace MainWindow { CheckMenuItem(menu, ID_OPTIONS_OPENGL, MF_CHECKED); CheckMenuItem(menu, ID_OPTIONS_VULKAN, MF_UNCHECKED); break; - case GPU_BACKEND_VULKAN: + case GPUBackend::VULKAN: EnableMenuItem(menu, ID_OPTIONS_DIRECT3D9, MF_ENABLED); EnableMenuItem(menu, ID_OPTIONS_DIRECT3D11, MF_ENABLED); EnableMenuItem(menu, ID_OPTIONS_OPENGL, MF_ENABLED); @@ -1306,7 +1306,7 @@ namespace MainWindow { CheckMenuItem(menu, ID_OPTIONS_OPENGL, MF_UNCHECKED); CheckMenuItem(menu, ID_OPTIONS_VULKAN, MF_CHECKED); break; - case GPU_BACKEND_DIRECT3D11: + case GPUBackend::DIRECT3D11: EnableMenuItem(menu, ID_OPTIONS_DIRECT3D9, MF_ENABLED); EnableMenuItem(menu, ID_OPTIONS_DIRECT3D11, MF_GRAYED); EnableMenuItem(menu, ID_OPTIONS_OPENGL, MF_ENABLED); diff --git a/Windows/WindowsHost.cpp b/Windows/WindowsHost.cpp index 921f19516795..f6110b54931f 100644 --- a/Windows/WindowsHost.cpp +++ b/Windows/WindowsHost.cpp @@ -114,16 +114,16 @@ void WindowsHost::UpdateConsolePosition() { bool WindowsHost::InitGraphics(std::string *error_message, GraphicsContext **ctx) { WindowsGraphicsContext *graphicsContext = nullptr; switch (g_Config.iGPUBackend) { - case GPU_BACKEND_OPENGL: + case (int)GPUBackend::OPENGL: graphicsContext = new WindowsGLContext(); break; - case GPU_BACKEND_DIRECT3D9: + case (int)GPUBackend::DIRECT3D9: graphicsContext = new D3D9Context(); break; - case GPU_BACKEND_DIRECT3D11: + case (int)GPUBackend::DIRECT3D11: graphicsContext = new D3D11Context(); break; - case GPU_BACKEND_VULKAN: + case (int)GPUBackend::VULKAN: graphicsContext = new WindowsVulkanContext(); break; default: diff --git a/Windows/main.cpp b/Windows/main.cpp index 3be01d8354af..88320386537d 100644 --- a/Windows/main.cpp +++ b/Windows/main.cpp @@ -466,19 +466,19 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin // such as "software-gles", "software-d3d9", and "software-d3d11", or something similar. // For now, software rendering force-activates OpenGL. if (restOfOption == L"directx9") { - g_Config.iGPUBackend = GPU_BACKEND_DIRECT3D9; + g_Config.iGPUBackend = (int)GPUBackend::DIRECT3D9; g_Config.bSoftwareRendering = false; } else if (restOfOption == L"directx11") { - g_Config.iGPUBackend = GPU_BACKEND_DIRECT3D11; + g_Config.iGPUBackend = (int)GPUBackend::DIRECT3D11; g_Config.bSoftwareRendering = false; } else if (restOfOption == L"gles") { - g_Config.iGPUBackend = GPU_BACKEND_OPENGL; + g_Config.iGPUBackend = (int)GPUBackend::OPENGL; g_Config.bSoftwareRendering = false; } else if (restOfOption == L"vulkan") { - g_Config.iGPUBackend = GPU_BACKEND_VULKAN; + g_Config.iGPUBackend = (int)GPUBackend::VULKAN; g_Config.bSoftwareRendering = false; } else if (restOfOption == L"software") { - g_Config.iGPUBackend = GPU_BACKEND_OPENGL; + g_Config.iGPUBackend = (int)GPUBackend::OPENGL; g_Config.bSoftwareRendering = true; } } diff --git a/android/jni/app-android.cpp b/android/jni/app-android.cpp index 970b36d27ff1..a06e2125f546 100644 --- a/android/jni/app-android.cpp +++ b/android/jni/app-android.cpp @@ -135,6 +135,7 @@ bool AndroidEGLGraphicsContext::Init(ANativeWindow *wnd, int backbufferWidth, in gl->MakeCurrent(); CheckGLExtensions(); draw_ = Draw::T3DCreateGLContext(); + SetGPUBackend(GPUBackend::OPENGL); bool success = draw_->CreatePresets(); // There will always be a GLSL compiler capable of compiling these. assert(success); return true; @@ -161,6 +162,7 @@ class AndroidJavaEGLGraphicsContext : public GraphicsContext { AndroidJavaEGLGraphicsContext() { CheckGLExtensions(); draw_ = Draw::T3DCreateGLContext(); + SetGPUBackend(GPUBackend::OPENGL); bool success = draw_->CreatePresets(); assert(success); } @@ -339,6 +341,7 @@ bool AndroidVulkanContext::Init(ANativeWindow *wnd, int desiredBackbufferSizeX, bool success = true; if (g_Vulkan->InitObjects()) { draw_ = Draw::T3DCreateVulkanContext(g_Vulkan, g_Config.bGfxDebugSplitSubmit); + SetGPUBackend(GPUBackend::VULKAN); success = draw_->CreatePresets(); // Doesn't fail, we ship the compiler. assert(success); draw_->HandleEvent(Draw::Event::GOT_BACKBUFFER, g_Vulkan->GetBackbufferWidth(), g_Vulkan->GetBackbufferHeight()); @@ -1125,7 +1128,7 @@ extern "C" bool JNICALL Java_org_ppsspp_ppsspp_NativeActivity_runEGLRenderLoop(J retry: - bool vulkan = g_Config.iGPUBackend == GPU_BACKEND_VULKAN; + bool vulkan = g_Config.iGPUBackend == (int)GPUBackend::VULKAN; int tries = 0; AndroidGraphicsContext *graphicsContext; @@ -1140,8 +1143,8 @@ extern "C" bool JNICALL Java_org_ppsspp_ppsspp_NativeActivity_runEGLRenderLoop(J if (!exitRenderLoop && (vulkan && tries < 2)) { ILOG("Trying again, this time with OpenGL."); - g_Config.iGPUBackend = GPU_BACKEND_OPENGL; - SetGPUBackend((GPUBackend)g_Config.iGPUBackend); // Wait, why do we need a separate enum here? + g_Config.iGPUBackend = (int)GPUBackend::OPENGL; + SetGPUBackend((GPUBackend)g_Config.iGPUBackend); tries++; goto retry; } diff --git a/cmake/Modules/FindWayland.cmake b/cmake/Modules/FindWayland.cmake new file mode 100644 index 000000000000..f93218b8739e --- /dev/null +++ b/cmake/Modules/FindWayland.cmake @@ -0,0 +1,66 @@ +# Try to find Wayland on a Unix system +# +# This will define: +# +# WAYLAND_FOUND - True if Wayland is found +# WAYLAND_LIBRARIES - Link these to use Wayland +# WAYLAND_INCLUDE_DIR - Include directory for Wayland +# WAYLAND_DEFINITIONS - Compiler flags for using Wayland +# +# In addition the following more fine grained variables will be defined: +# +# WAYLAND_CLIENT_FOUND WAYLAND_CLIENT_INCLUDE_DIR WAYLAND_CLIENT_LIBRARIES +# WAYLAND_SERVER_FOUND WAYLAND_SERVER_INCLUDE_DIR WAYLAND_SERVER_LIBRARIES +# WAYLAND_EGL_FOUND WAYLAND_EGL_INCLUDE_DIR WAYLAND_EGL_LIBRARIES +# +# Copyright (c) 2013 Martin Gräßlin +# +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. + +IF (NOT WIN32) + IF (WAYLAND_INCLUDE_DIR AND WAYLAND_LIBRARIES) + # In the cache already + SET(WAYLAND_FIND_QUIETLY TRUE) + ENDIF () + + # Use pkg-config to get the directories and then use these values + # in the FIND_PATH() and FIND_LIBRARY() calls + FIND_PACKAGE(PkgConfig) + PKG_CHECK_MODULES(PKG_WAYLAND QUIET wayland-client wayland-server wayland-egl wayland-cursor) + + SET(WAYLAND_DEFINITIONS ${PKG_WAYLAND_CFLAGS}) + + FIND_PATH(WAYLAND_CLIENT_INCLUDE_DIR NAMES wayland-client.h HINTS ${PKG_WAYLAND_INCLUDE_DIRS}) + FIND_PATH(WAYLAND_SERVER_INCLUDE_DIR NAMES wayland-server.h HINTS ${PKG_WAYLAND_INCLUDE_DIRS}) + FIND_PATH(WAYLAND_EGL_INCLUDE_DIR NAMES wayland-egl.h HINTS ${PKG_WAYLAND_INCLUDE_DIRS}) + FIND_PATH(WAYLAND_CURSOR_INCLUDE_DIR NAMES wayland-cursor.h HINTS ${PKG_WAYLAND_INCLUDE_DIRS}) + + FIND_LIBRARY(WAYLAND_CLIENT_LIBRARIES NAMES wayland-client HINTS ${PKG_WAYLAND_LIBRARY_DIRS}) + FIND_LIBRARY(WAYLAND_SERVER_LIBRARIES NAMES wayland-server HINTS ${PKG_WAYLAND_LIBRARY_DIRS}) + FIND_LIBRARY(WAYLAND_EGL_LIBRARIES NAMES wayland-egl HINTS ${PKG_WAYLAND_LIBRARY_DIRS}) + FIND_LIBRARY(WAYLAND_CURSOR_LIBRARIES NAMES wayland-cursor HINTS ${PKG_WAYLAND_LIBRARY_DIRS}) + + set(WAYLAND_INCLUDE_DIR ${WAYLAND_CLIENT_INCLUDE_DIR} ${WAYLAND_SERVER_INCLUDE_DIR} ${WAYLAND_EGL_INCLUDE_DIR} ${WAYLAND_CURSOR_INCLUDE_DIR}) + + set(WAYLAND_LIBRARIES ${WAYLAND_CLIENT_LIBRARIES} ${WAYLAND_SERVER_LIBRARIES} ${WAYLAND_EGL_LIBRARIES} ${WAYLAND_CURSOR_LIBRARIES}) + + list(REMOVE_DUPLICATES WAYLAND_INCLUDE_DIR) + + include(FindPackageHandleStandardArgs) + + FIND_PACKAGE_HANDLE_STANDARD_ARGS(WAYLAND_CLIENT DEFAULT_MSG WAYLAND_CLIENT_LIBRARIES WAYLAND_CLIENT_INCLUDE_DIR) + FIND_PACKAGE_HANDLE_STANDARD_ARGS(WAYLAND_SERVER DEFAULT_MSG WAYLAND_SERVER_LIBRARIES WAYLAND_SERVER_INCLUDE_DIR) + FIND_PACKAGE_HANDLE_STANDARD_ARGS(WAYLAND_EGL DEFAULT_MSG WAYLAND_EGL_LIBRARIES WAYLAND_EGL_INCLUDE_DIR) + FIND_PACKAGE_HANDLE_STANDARD_ARGS(WAYLAND_CURSOR DEFAULT_MSG WAYLAND_CURSOR_LIBRARIES WAYLAND_CURSOR_INCLUDE_DIR) + FIND_PACKAGE_HANDLE_STANDARD_ARGS(WAYLAND DEFAULT_MSG WAYLAND_LIBRARIES WAYLAND_INCLUDE_DIR) + + MARK_AS_ADVANCED( + WAYLAND_INCLUDE_DIR WAYLAND_LIBRARIES + WAYLAND_CLIENT_INCLUDE_DIR WAYLAND_CLIENT_LIBRARIES + WAYLAND_SERVER_INCLUDE_DIR WAYLAND_SERVER_LIBRARIES + WAYLAND_EGL_INCLUDE_DIR WAYLAND_EGL_LIBRARIES + WAYLAND_CURSOR_INCLUDE_DIR WAYLAND_CURSOR_LIBRARIES + ) + +ENDIF () diff --git a/ext/native/native.vcxproj b/ext/native/native.vcxproj index b8db0d2f53ca..9ccbc1e64443 100644 --- a/ext/native/native.vcxproj +++ b/ext/native/native.vcxproj @@ -192,6 +192,7 @@ + diff --git a/ext/native/native.vcxproj.filters b/ext/native/native.vcxproj.filters index 175c41bf21bc..bec0f42ceebe 100644 --- a/ext/native/native.vcxproj.filters +++ b/ext/native/native.vcxproj.filters @@ -329,6 +329,9 @@ ui + + base + diff --git a/ext/native/ui/ui_screen.cpp b/ext/native/ui/ui_screen.cpp index babbae9d7ce1..7581e5fcdca5 100644 --- a/ext/native/ui/ui_screen.cpp +++ b/ext/native/ui/ui_screen.cpp @@ -309,6 +309,10 @@ void PopupScreen::TriggerFinish(DialogResult result) { OnCompleted(result); } +void PopupScreen::resized() { + RecreateViews(); +} + void PopupScreen::CreateViews() { using namespace UI; UIContext &dc = *screenManager()->getUIContext(); diff --git a/ext/native/ui/ui_screen.h b/ext/native/ui/ui_screen.h index 8ab4ce49fbeb..3844cba71a9a 100644 --- a/ext/native/ui/ui_screen.h +++ b/ext/native/ui/ui_screen.h @@ -72,6 +72,7 @@ class PopupScreen : public UIDialogScreen { virtual bool isTransparent() const override { return true; } virtual bool touch(const TouchInput &touch) override; virtual bool key(const KeyInput &key) override; + virtual void resized() override; virtual void TriggerFinish(DialogResult result) override; diff --git a/headless/Headless.cpp b/headless/Headless.cpp index e18e326710b2..661211d1d0d0 100644 --- a/headless/Headless.cpp +++ b/headless/Headless.cpp @@ -373,6 +373,7 @@ int main(int argc, const char* argv[]) g_Config.bVertexDecoderJit = true; g_Config.bBlockTransferGPU = true; g_Config.iSplineBezierQuality = 2; + g_Config.bHighQualityDepth = true; #ifdef _WIN32 InitSysDirectories(); diff --git a/headless/SDLHeadlessHost.cpp b/headless/SDLHeadlessHost.cpp index 1176bef1e284..17026f7fcaf6 100644 --- a/headless/SDLHeadlessHost.cpp +++ b/headless/SDLHeadlessHost.cpp @@ -54,6 +54,7 @@ class GLDummyGraphicsContext : public DummyGraphicsContext { GLDummyGraphicsContext() { CheckGLExtensions(); draw_ = Draw::T3DCreateGLContext(); + SetGPUBackend(GPUBackend::OPENGL); bool success = draw_->CreatePresets(); assert(success); } diff --git a/ios/ViewController.mm b/ios/ViewController.mm index 4c81509ec54d..528287094c3f 100644 --- a/ios/ViewController.mm +++ b/ios/ViewController.mm @@ -21,6 +21,7 @@ #include "gfx_es2/gpu_features.h" #include "Core/Config.h" +#include "Core/System.h" #include "Common/GraphicsContext.h" #include @@ -39,6 +40,7 @@ IOSDummyGraphicsContext() { CheckGLExtensions(); draw_ = Draw::T3DCreateGLContext(); + SetGPUBackend(GPUBackend::OPENGL); bool success = draw_->CreatePresets(); assert(success); }