Commit Graph
71 Commits
Author SHA1 Message Date
Henrik RydgårdandClaude Opus 5 f9315e9bc1 Vulkan: Keep draining the delete list until a lap comes up empty
The previous commit moved everything out of the list before running callbacks, to
avoid appending to a vector being iterated. That regressed device teardown: a
callback can queue more deletes (~VKFramebuffer does, via ~VKRFramebuffer, which
queues image views, image allocations and framebuffers), and those land back on a
list that used to be picked up by the object loops later in the same pass.

That's harmless for the per-frame lists, since callbacks queue onto the global
list and a later frame drains it. But PerformPendingDeletes() drains the global
list itself, and DestroyDevice() calls it immediately before vmaDestroyAllocator
and vkDestroyDevice - so the re-queued objects were never destroyed at all.

Loop instead. In the per-frame case that's one extra empty lap.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vd8ntC2brCUtCrDJMqLbs8
2026-08-28 22:56:18 +02:00
Henrik RydgårdandClaude Opus 5 6862bc1721 Vulkan: Fix threading issues around pipeline layouts and the delete list
pipelineLayouts_ was mutated from the main thread (CreatePipelineLayout, and the
deferred callback queued by DestroyPipelineLayout) while the render thread walked
it every frame in FlushDescriptors. Exiting a game in Vulkan mode hits this
reliably: ~GPU_Vulkan stops the render thread and destroys the draw engine's
layout, but the destruction is deferred onto the delete list and doesn't actually
run until a BeginFrame two frames later, with the render thread running again.
Guard the list, and the lifetime of the layouts in it, with a mutex.

The global delete list had the same problem - VulkanDescSetPool::Recreate queues
the old pool from FlushDescSets on the render thread, which happens for real once
a game goes past the initial 1024 descriptors, while the main thread moves the
list into the current frame's list in EndFrame(). Lock the queueing functions and
Take's source list.

While in there:
* Take() didn't move queryPools_, so query pools queued for deletion sat on the
  global list until device teardown instead of being deleted a few frames later.
* PerformDeletes now drains into a local list before destroying anything. A
  callback is allowed to queue further deletes (~VKFramebuffer's does, via
  ~VKRFramebuffer), which used to append to the very vector being iterated.
  They now get the normal deferral instead of running in the same pass.
* Missing semicolon in BeginFrame that only compiles because VLOG is empty.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vd8ntC2brCUtCrDJMqLbs8
2026-08-28 22:43:58 +02:00
Henrik Rydgård 4160414b31 Vulkan: remove libretro's global function-pointer wrapper hack
libretro/libretro_vulkan.cpp got PPSSPP's libretro core working with
RetroArch's Vulkan integration by globally monkey-patching PPSSPP's Vulkan
loader function pointers (vkCreateInstance, vkCreateDevice,
vkCreateSwapchainKHR, vkAcquireNextImageKHR, vkQueuePresentKHR,
vkQueueSubmit, etc.) so the unmodified VulkanContext class would end up
wrapping RetroArch's already-existing VkInstance/VkDevice instead of
creating its own, and so a fake VkSwapchainKHR (a self-managed array of
images synced against RetroArch's retro_hw_render_interface_vulkan
callbacks) could stand in for the real swapchain that libretro's Vulkan
model doesn't have. Flagged in-code as "a wacky wrapper".

Replaces that with first-class support in VulkanContext for the two things
libretro actually needs:

- Adopting an externally-created instance/device instead of faking
  vkCreateInstance/vkCreateDevice: VulkanContext::CreateInstanceExternal()
  adopts RetroArch's VkInstance; CreateDevice() gained optional
  extraDeviceExtensions/extraRequiredFeatures params so RetroArch's
  requirements get merged into a real vkCreateDevice() call;
  ownsInstance_/ownsDevice_ flags (the latter set via
  SetDeviceExternallyOwned()) mean DestroyInstance()/DestroyDevice() skip
  the real vkDestroy* calls when something else owns the object, without
  needing to intercept anything. VulkanLoader gained
  VulkanLoadFromGetInstanceProcAddr() for bootstrapping from a
  host-supplied proc-addr getter instead of dlopen/dlsym-ing the loader
  ourselves - vkGetDeviceProcAddr is resolved via the real instance handle
  (not NULL), since per the Vulkan spec it's not one of the handful of
  commands queryable with a NULL instance.
- A pluggable presentation backend (Common/GPU/Vulkan/VulkanPresentation.h)
  for hosts with no real VK_KHR_swapchain, replacing the fake-swapchain-
  handle trick. VulkanContext::GetPresentation() is null by default, so
  every existing platform's real-swapchain code path is untouched;
  libretro/LibretroVulkanPresentation implements this interface directly
  against retro_hw_render_interface_vulkan, as real class state instead of
  file-scope globals. Several pieces of state that are normally only
  populated as a side effect of ReinitSurface()/InitSwapchain() - the
  graphics queue/queue family index (ChooseQueue() is entangled with
  real-surface presentation-support checks), the swapchain format, and
  the available present modes - needed presentation-aware fallbacks since
  libretro never calls that real-surface path at all.

libretro/LibretroVulkanContext.cpp now drives VulkanContext's real, public
API directly - no more hijacked function pointers, no more fake surface or
swapchain. libretro/libretro_vulkan.cpp is deleted.

Verified with a full build+run in RetroArch (not just compile-time
checks): the libretro Makefile doesn't track header dependencies
(cl.exe doesn't support -MMD/-MP, and Makefile.common never sets up an
equivalent), so a `make clean` full rebuild is required after any header
change to avoid linking stale object code from before the change - several
of the fixes above were initially masked by exactly that.
2026-08-06 17:07:05 +02:00
Katharine Chui c39205496c bring back VulkanContext::SetCbGetDrawSize for linux wayland
It was removed during https://github.com/hrydgard/ppsspp/pull/21982

On Linux Wayland however this can be observed without:
34:25:550 Vulkan/VulkanContext.cpp:1401 I[G3D]: surfCapabilities_.current: -1x-1
34:25:550 Vulkan/VulkanContext.cpp:1406 I[G3D]: surfCapabilities_.current after clamp: -1x-1 min: 1x1 max: 32768x32768 computed: 1x1 cbdraw
2026-08-06 00:29:21 +02:00
Henrik Rydgård 1c40facc4c Vulkan SDL: Remove an old workaround 2026-07-26 19:10:46 +02:00
Henrik Rydgård 7f218acc53 Change the GraphicsContext interface to be more consistent 2026-07-26 10:22:00 +02:00
Henrik Rydgård 7b3405ab86 Fix a Vulkan lifetime issue causing invalid descriptors on shutdown
Also simplifies the code a little
2026-06-25 21:56:33 +02:00
jasaaved 5e25118043 Fix the exclusive fullscreen config guard and switching the setting on/off
Previously the exclusive fullscreen option in the settings screen was
guarded by a compile-time #ifdef VK_EXT_full_screen_exclusive, which is
always true on Windows. It now uses a runtime fullScreenExclusiveSupported
cap derived from whether the extension is actually enabled by the driver.

Switching between borderless and exclusive fullscreen currently requires a
restart. This is because once DWM has claimed the window (any frames
presented), ALLOWED_EXT cannot re-engage exclusive mode on an existing
swapchain. A new process gets a fresh HWND that DWM has not claimed yet,
so ALLOWED_EXT works correctly at startup.

The proper fix is to use VK_FULL_SCREEN_EXCLUSIVE_APPLICATION_CONTROLLED_EXT
with vkAcquireFullScreenExclusiveModeEXT/vkReleaseFullScreenExclusiveModeEXT
to explicitly negotiate exclusive mode with DWM mid-session without needing
a restart. To be done in a follow-up.
2026-06-03 17:15:13 -07:00
jasaaved 0c23cdaf3d Windows Vulkan: default to borderless fullscreen, add exclusive option
Vulkan swapchain now explicitly sets VK_FULL_SCREEN_EXCLUSIVE_DISALLOWED_EXT by default, enabling proper borderless fullscreen behavior with benefits including better Alt+Tab, VRR/G-Sync/FreeSync, and Auto HDR support.
2026-06-03 17:15:13 -07:00
Henrik Rydgård 947217d1be Convert the pre-rotation to just the matrix multiplication. 2026-05-17 10:59:40 +02:00
Henrik Rydgård 85ddf03c4b Vulkan: Remove deprecated use of device layers 2026-05-13 23:09:04 +02:00
Henrik Rydgård 4c2be7f8af More work. Some initialization order problem. 2026-04-23 13:31:51 +02:00
Henrik Rydgård 00b28e28dc Mac/iOS: Avoid a vulkan warning about primitive restart 2026-02-10 10:41:52 +01:00
Henrik Rydgård b4f7635719 Vulkan: Check the available present modes right after initializing the surface 2025-10-20 19:52:24 +02:00
Henrik Rydgård 80bd32325c Move the present mode from the CreateInfo to InitSwapchain 2025-10-20 16:33:34 +02:00
Henrik Rydgård 6338832015 Vulkan: Smoothly recreate the swapchain using oldSwapchain on "resize" on Windows 2025-10-20 15:42:34 +02:00
Henrik Rydgård 2cf0ffea73 Allow choosing the frame presentation mode in detail in Vulkan mode 2025-08-21 01:01:16 +02:00
Henrik Rydgård c0b7ecc686 Refactor: Unify the Vulkan init info logic 2025-08-21 01:01:16 +02:00
Henrik Rydgård 5e05a6d0ac Get rid of some more backward Common/Core dependencies 2025-08-06 00:16:35 +02:00
Henrik Rydgård 9137eedb7b Windows/Vulkan: Correctly handle minimizing and restoring the window
We can't create a swapchain in this case but we still want emulation to
keep running. So we ditch the last renderpass in VulkanQueueRunner but
run all the rest (if PauseWhenMinimized isn't set).

Now works without any validation errors or hangs.
2025-07-18 20:01:48 +02:00
Henrik Rydgård 67dfbfe97e Add developer setting to prevent loading overlays (and other 'implicit' Vulkan layers) 2025-04-10 18:56:05 +02:00
Henrik Rydgård 670ff21529 Make the Vulkan init flags a proper enum class 2025-04-10 18:16:05 +02:00
Henrik Rydgård 8c8b34aac4 Vulkan: Separate the instance and device API versions, for extension loading purposes 2024-09-25 18:38:31 +02:00
Henrik Rydgård b2d9ac54dd Make InfoField an "enum class", extract function FormatAPIVersion 2024-09-25 16:34:33 +02:00
Henrik Rydgård 7c817f3ecd Add helper for Vulkan struct chaining 2024-07-19 09:45:02 +02:00
Henrik Rydgård 138193a776 Add support for the EXT_provoking_vertex Vulkan extension, allowing us to skip software transform for this case. 2024-07-17 10:41:25 +02:00
Henrik Rydgård 9f1f75ddab Refactor: Merge the ChooseDevice function into CreateDevice 2024-07-17 10:31:49 +02:00
Henrik Rydgård fea6727ffd Add a convenience method to VulkanContext to reduce code duplication
Will need the exact same code for iOS.
2024-05-23 02:13:54 +02:00
Henrik Rydgård d28e9dc006 Minor cleanup 2024-04-06 17:03:40 +02:00
Henrik Rydgård ae6e0d182e Vulkan: Fix function loading regression affecting MSAA
When loading function that have been merged into core, use the core
names.
2024-04-05 17:28:37 +02:00
Henrik Rydgård 9f9881dfe3 Move some code, minor cleanup.
See #18987
2024-04-04 12:30:41 +02:00
Henrik Rydgård 32fe47d761 Fix or ignore some various Vulkan validation errors 2024-04-03 13:37:40 +02:00
Herman Semenov 5a0d54be83 [Common/Data/GPU/Input/System/UI] Added const reference for function params 2023-12-14 14:21:11 +03:00
Henrik Rydgård 2c751d39f8 Vulkan: Add simple delete count to GPU profiler, to make sure we don't have more resource churn
Also fix the render pass type name lookup table.
2023-10-12 09:02:45 +02:00
Henrik Rydgård 13cfd9c3d6 Add Mesa as a known GPU driver "vendor". 2023-08-17 22:06:03 +02:00
Henrik Rydgård 8e1dc35dd1 Vulkan: Show instance extensions, both enabled and available, in sysinfo 2023-08-03 18:56:47 +02:00
Henrik Rydgård 1c83c4a1fe Vulkan: Enable the present-id/present-wait/display-timing extensions
Doesn't actually use any of them yet, just making sure enabling them
doesn't cause any weird issues. They will be used for the future display
timing rewrite.
2023-07-14 10:43:47 +02:00
Henrik Rydgård c81ec8c74d List Vulkan present modes in system info, show the current one 2023-04-20 00:21:06 +02:00
Henrik Rydgård 56d792f422 Sketch the new VulkanPushPool 2023-03-15 01:25:00 +01:00
Henrik Rydgård cc9c01b1d0 Vulkan texture uploads: Take optimalBufferCopyRowPitchAlignment into account
Might marginally increase texture upload performance on some GPUs, but
mainly just the right thing to do.

For example, on Intel, this is 64.
2023-03-05 17:32:41 +01:00
Henrik Rydgård cf52324e9e Vulkan: Fix pipeline cache clearing.
Extracted from #16759 and bugfixed. Fixes a leak of Vulkan pipelines.

I guess another way would be to queue the variants for destruction at
the same time as we queue the callback, but I like this better.
2023-01-09 09:49:55 +01:00
Henrik Rydgård 25115fee7f Found a bug where we tried to look up queue family -1 when initializing the frame profiler. 2022-12-23 11:37:59 +01:00
Henrik Rydgård 31d5881c90 Enable support for Android Vulkan validation. Fix a minor validation error. 2022-12-22 11:13:52 +01:00
Henrik Rydgård 28e1b532bd Detect Apple/MoltenVK and allow multisampling. Unfortunately no support for sample rate shading. 2022-12-01 22:49:01 +01:00
Henrik Rydgård 8b9b80f044 Add path that uses CreateRenderpass2, we're gonna need it for depth resolve. 2022-12-01 22:49:00 +01:00
Henrik Rydgård 6daecb4e2b Add check for tiling GPUs. We'll use this to inform on what MSAA modes to support. 2022-12-01 22:48:59 +01:00
Henrik Rydgård 162290147f UWP build fix. Had to reshuffle some stuff and compile some Vulkan files. 2022-11-06 15:54:00 +01:00
Henrik Rydgård 31fd928a5c Name more image views. Very useful with a little patch to the Vulkan debug layers. 2022-10-27 11:05:59 +02:00
Henrik Rydgård fb250c4b29 More multiview work 2022-10-27 11:05:58 +02:00
Henrik Rydgård 1d8ab38ce5 Vulkan: Use v2 feature checks, and add check for multiview features.
Extracted from the multiview PR, and renamed some stuff.
2022-10-24 00:21:28 +02:00