hrydgard / ppsspp

A PSP emulator for Android, Windows, Mac and Linux, written in C++. Want to contribute? Join us on Discord at https://discord.gg/5NJB6dD or just send pull requests / issues. For discussion use the forums at forums.ppsspp.org.
https://www.ppsspp.org
Other
11.02k stars 2.15k forks source link

PPSSPP from git doesn't handle missing Vulkan device (Version 12.3 did, so a classic regression) #19080

Closed joroOnLinux closed 3 days ago

joroOnLinux commented 4 months ago

Game or games this happens in

-

What area of the game / PPSSPP

Startup / environment check: libvulkan.so is available, but it's not a Vulkan environment (it's the amber/gallium branch of mesa)

What should happen

log from v12.3:

VulkanMayBeAvailable: Device allowed ('SDL:Linux') VulkanMayBeAvailable: Library loaded ('libvulkan.so.1') VulkanMayBeAvailable: Enumerating instance extensions VulkanMayBeAvailable: Instance extension count: 18 VulkanMaybeAvailable: Instance extension found: VK_KHR_device_group_creation (00000001) VulkanMaybeAvailable: Instance extension found: VK_KHR_display (00000017) VulkanMaybeAvailable: Instance extension found: VK_KHR_external_fence_capabilities (00000001) VulkanMaybeAvailable: Instance extension found: VK_KHR_external_memory_capabilities (00000001) VulkanMaybeAvailable: Instance extension found: VK_KHR_external_semaphore_capabilities (00000001) VulkanMaybeAvailable: Instance extension found: VK_KHR_get_display_properties2 (00000001) VulkanMaybeAvailable: Instance extension found: VK_KHR_get_physical_device_properties2 (00000001) VulkanMaybeAvailable: Instance extension found: VK_KHR_get_surface_capabilities2 (00000001) VulkanMaybeAvailable: Instance extension found: VK_KHR_surface (00000019) VulkanMaybeAvailable: Instance extension found: VK_KHR_surface_protected_capabilities (00000001) VulkanMaybeAvailable: Instance extension found: VK_KHR_wayland_surface (00000006) VulkanMaybeAvailable: Instance extension found: VK_KHR_xcb_surface (00000006) VulkanMaybeAvailable: Instance extension found: VK_KHR_xlib_surface (00000006) VulkanMaybeAvailable: Instance extension found: VK_EXT_acquire_xlib_display (00000001) VulkanMaybeAvailable: Instance extension found: VK_EXT_debug_report (00000009) VulkanMaybeAvailable: Instance extension found: VK_EXT_direct_mode_display (00000001) VulkanMaybeAvailable: Instance extension found: VK_EXT_display_surface_counter (00000001) VulkanMaybeAvailable: Instance extension found: VK_EXT_debug_utils (00000001) VulkanMayBeAvailable: Calling vkCreateInstance VulkanMayBeAvailable: Vulkan test instance created successfully. VulkanMayBeAvailable: Failed to count physical devices (VK_ERROR_INITIALIZATION_FAILED) VulkanMayBeAvailable: Destroying instance DEBUG: Vulkan is not available, not using Vulkan. Info: We compiled against SDL version 2.0.10 and we are linking against SDL version 2.0.10. :) ThreadManager::Init(compute threads: 2, all: 6) 38:26:677 Core/Config.cpp:627 I[G3D]: Longest display side: -1 pixels. Choosing scale 1 Pixels: 960 x 544 Virtual pixels: 960 x 544 OpenGL 2.0 or higher. loading control pad mappings from gamecontrollerdb.txt: SUCCESS!

current version from git just freezes after 'virtual pixels'

Logs

see above

Platform

Linux / BSD

Mobile device model or graphics card (GPU)

Intell GM45

PPSSPP version affected

ppsspp from git

Last working version

v 12.3

Graphics backend (3D API)

OpenGL / GLES

Checklist

anr2me commented 4 months ago

Intel GM45 has the Intel GMA 4500MHD GPU which doesn't support vulkan isn't?

And as i remembered PPSSPP ignores virtual/emulated GPU such as llvmpipe (similar to what happen when running PPSSPP on WSL2), but you can enforce PPSSPP to use llvmpipe GPU device by changing the gpu backend setting directly on ppsspp.ini

Btw, there is a note regarding Intel old driver at https://github.com/hrydgard/ppsspp/wiki/Build-instructions#building-with-cmake-other-platforms-eg-linux

When using Intel integrated Graphics and Ubuntu 20.04 or newer you have to launch PPSSPPSDL with the following command to load the old drivers and prevent a crash:

MESA_LOADER_DRIVER_OVERRIDE=i965 ./build/PPSSPPSDL

Have you tired it?

joroOnLinux commented 4 months ago

It does not have Vulkan but it has Gallium which also implements OpenGL/GLSL on the GPU, no need for llvmpipe. As i wrote, v12.3 handled the situation gracefully and fell back to just plain OpenGL. The above hint did not help :-(

hrydgard commented 4 months ago

What's the log from 1.17.1?

joroOnLinux commented 4 months ago

That is the startup log of PPSSPP v1.12.3 which handled the situation gracefully and fell back to OpenGL

hrydgard commented 4 months ago

Yeah I got that, but can you give me a failing startup log from a newer version?

joroOnLinux commented 4 months ago

Here's the log with PPSSPP from git. Strangely enough, it reports success, but the screen just freezes and i have to switch to virtual console and kill/restart the X Server to continue.

VulkanMayBeAvailable: Device allowed ('SDL:Linux') Vulkan library loaded ('libvulkan.so') VulkanMayBeAvailable: Enumerating instance extensions VulkanMayBeAvailable: Instance extension count: 20 VulkanMaybeAvailable: Instance extension found: VK_KHR_device_group_creation (00 000001) VulkanMaybeAvailable: Instance extension found: VK_KHR_external_fence_capabiliti es (00000001) VulkanMaybeAvailable: Instance extension found: VK_KHR_external_memory_capabilit ies (00000001) VulkanMaybeAvailable: Instance extension found: VK_KHR_external_semaphore_capabi lities (00000001) VulkanMaybeAvailable: Instance extension found: VK_KHR_get_display_properties2 ( 00000001) VulkanMaybeAvailable: Instance extension found: VK_KHR_get_physical_device_prope rties2 (00000001) VulkanMaybeAvailable: Instance extension found: VK_KHR_get_surface_capabilities2 (00000001) VulkanMaybeAvailable: Instance extension found: VK_KHR_surface (00000019) VulkanMaybeAvailable: Instance extension found: VK_KHR_surface_protected_capabil ities (00000001) VulkanMaybeAvailable: Instance extension found: VK_KHR_wayland_surface (00000006 ) VulkanMaybeAvailable: Instance extension found: VK_KHR_xcb_surface (00000006) VulkanMaybeAvailable: Instance extension found: VK_KHR_xlib_surface (00000006) VulkanMaybeAvailable: Instance extension found: VK_KHR_display (00000017) VulkanMaybeAvailable: Instance extension found: VK_EXT_direct_mode_display (00000001) VulkanMaybeAvailable: Instance extension found: VK_EXT_acquire_xlib_display (00000001) VulkanMaybeAvailable: Instance extension found: VK_EXT_display_surface_counter (00000001) VulkanMaybeAvailable: Instance extension found: VK_EXT_debug_report (00000009) VulkanMaybeAvailable: Instance extension found: VK_EXT_acquire_drm_display (00000001) VulkanMaybeAvailable: Instance extension found: VK_EXT_debug_utils (00000002) VulkanMaybeAvailable: Instance extension found: VK_EXT_swapchain_colorspace (00000004) VulkanMayBeAvailable: Calling vkCreateInstance VulkanMayBeAvailable: Vulkan test instance created successfully. VulkanMayBeAvailable: Ineligible device found and ignored: 'llvmpipe (LLVM 15.0.7, 128 bits)' VulkanMayBeAvailable: Found Vulkan API, but no good Vulkan device! VulkanMayBeAvailable: Destroying instance Vulkan with working device not detected. DEBUG: Vulkan is not available, not using Vulkan. Info: We compiled against SDL version 2.0.20 and we are linking against SDL version 2.0.20. :) ThreadManager::Init(compute threads: 2, all: 6) OpenGL 2.0 or higher. loading control pad mappings from gamecontrollerdb.txt: SUCCESS!

hrydgard commented 4 months ago

OK, so it's not using Vulkan. Unclear why it would hang trying to use OpenGL though...

joroOnLinux commented 4 months ago

Well, it's software. So it must be in the code. Your code.

joroOnLinux commented 4 months ago

And since 1.12.3 works fine, by logical deduction there must be a change that causes that. a diff might come in handy.

hrydgard commented 4 months ago

A diff? it's several thousands of commits between 1.12.3 and 1.17.1. If you could narrow down the range a bit, that would be helpful.

joroOnLinux commented 4 months ago

Well, it's your code, so for me to "narrow down the range" is an interesting concept. But it happens in the init/config stage, which "narrows it down" quite a bit. My first guess - without knowing the structure of the code - would be that some code tries to access the vulkan device after it has been destroyed. You might also notice - the second guess - that the part

38:26:677 Core/Config.cpp:627 I[G3D]: Longest display side: -1 pixels. Choosing scale 1 Pixels: 960 x 544 Virtual pixels: 960 x 544

is missing in the second log (why ?), so the code obviously is not called (why ?) and maybe therefore some display variables are not set which would explain the frreeze. Maybe just diff-ing Core/Config.cpp does the trick.

hrydgard commented 4 months ago

You are the one who can reproduce the problem, I can't in any of my setups. So you're the one who can narrow the range, I can only debug it through other means, which may be less effective.

anr2me commented 4 months ago

Does the OpenGL initialization runs on a different thread? may be it caught on a deadlock?

I would suggest getting a backtrace after breaking it when it got frozen to find out the location of the freeze, but you will need to build & run the debug version of PPSSPP

joroOnLinux commented 4 months ago

I looked at the code.

I would suggest that the problem is this code snippet in SDLMain.cpp:

GraphicsContext *graphicsContext = nullptr;
SDL_Window *window = nullptr;

std::string error_message;
if (g_Config.iGPUBackend == (int)GPUBackend::OPENGL) {
    SDLGLGraphicsContext *ctx = new SDLGLGraphicsContext();
    if (ctx->Init(window, x, y, w, h, mode, &error_message) != 0) {
        printf("GL init error '%s'\n", error_message.c_str());
    }
    graphicsContext = ctx;

the problem - IMHO - is that the checks for Vulkan backend correctly fail in VulkanLoader.cpp/VulkanMayBeAvailable but the "backend" is still set to "VULKAN", so this code never runs and the poor thing is left in an undefined state. The solution, i would suggest, could be to switch the backend to OPENGL after this a little further up (actually, since OPENGL is the only backend handled in this code anyway, there isn't really a point checking for VULKAN in the first place, but hey, it's your code):

if (VulkanMayBeAvailable()) {
    printf("DEBUG: Vulkan might be available.\n");
} else {
    printf("DEBUG: Vulkan is not available, not using Vulkan.\n");
}

You're welcome.

hrydgard commented 3 days ago

19440 should take care of this, thanks @joroOnLinux