Skip to content

fix(videoout): create the window and the device when VideoOut starts - #1367

Merged
oneandonlydean merged 1 commit into
boykopovar:mainfrom
Raghav314:fix/videoout-window-at-start
Oct 9, 2026
Merged

oneandonlydean merged 1 commit into
boykopovar:mainfrom
Raghav314:fix/videoout-window-at-start

Conversation

@Raghav314

@Raghav314 Raghav314 commented Oct 8, 2026 •

Copy link
Copy Markdown
Contributor

What

The driver created a windowless Vulkan device at the first dispatch and replaced it with a windowed one at the first flip. The replacement built a second device and re-imported the host imports (#284), and the first flip waited for both. #59, #110, #284 and #373 fix problems caused by the replacement.

shadPS4, KytyPS5 and SharpEmu create the window first and build one device with its surface:

  • shadPS4: emulator.cpp creates the window at startup; gnmdriver.cpp RegisterLib creates Vulkan::Presenter(*g_window).
  • KytyPS5: agc.cpp Initialize calls WindowInit, which creates the window and the Vulkan device, before VideoOutInit.
  • SharpEmu: VulkanVideoPresenter.Initialize creates the instance, the surface, the device, then the swapchain.

This change does the same at the first VideoOut call. AnyPS5 has no hook before the guest's entry point, and the libraries' static initializers can't create a window (loader lock on Windows).

  • VideoOut creates its window on the presentation thread when it starts, at the default 1920x1080 output, and attaches it with AgcDriverAttachWindow before the call returns. The driver creates its device with that window.
  • Present no longer creates or replaces a device. A device created by GPU work submitted before VideoOut started is still replaced, now in AttachWindow.
  • A failure to create the window or the device is thrown from the first VideoOut call. Before, it terminated the process from the presentation thread.
  • The window opens at the first VideoOut call and stays empty until the first flip. It always starts at 16:9; buffers of another aspect are letterboxed as before.

Tests that open VideoOut now need a display and a Vulkan device. guest_video_out_wqhd_detection writes a param.json for the window title and is skipped without a display or Vulkan device unless ANYPS5_REQUIRE_DISPLAY is set. ANYPS5_REQUIRE_VULKAN can't be used: the Linux job sets it, but its SDL is built without X11 and Wayland, so neither CI job can create a Vulkan window and the test is skipped in both.

Hades II (PPSA36082) also needs this to load: its 512 MiB upload pool is freed only after a GPU fence, and creating the device at the first dispatch was one of the delays in front of that fence. With this change and some local changes, it gets past loading; without this change it overflows the pool and crashes (2/2 runs).

Tested

Linux (CachyOS), x86-64, GCC, 7800X3D / RTX 4090.

  • video_out_flip_tests onedevice (new): GPU work, then a flip, leaves one device. Fails on main (two devices); dropping the attach at start fails it.
  • pacing relied on the first flip creating the device to span several vblanks. It now queues GPU work ahead of the flip and checks that lastFlipVblank is at least 3 vblanks behind the vblank the presentation finished at, so it doesn't depend on which vblank the flip reaches the presenter at. Moving the lastFlipVblank store back after the present fails it.
  • unavailable now expects the failure from sceVideoOutOpen, and the same failure from a second open (run without a Vulkan driver).
  • onedevice, pacing, aftergpu, present, backtoback, dcc, controls, decode, unavailable pass.
  • Windows: cross-built on Linux with MinGW-w64 GCC 15.2.0 (UCRT, posix threads, SEH, mingw-w64 14.0.0, as in CI) and run under Wine 11.19 on the same GPU. The flip modes above pass, unavailable with Vulkan disabled.

Checklist

  • Based on current main; no other open PR implements the same functions
  • One topic per PR; follow-ups go in a new PR
  • No comments in code except technical debt
  • Unimplemented paths throw (NotImplemented_nid_no_patch); silent stubs are listed in TechnicalDebt
  • No notes, investigation .md files or images added to the repository (attach them to this PR)
  • New third-party code is a submodule built from source
  • Generic behaviour, not specific to one title
  • Depends on: none
  • AI-assisted: yes

The driver created a windowless Vulkan device at the first dispatch and
replaced it with a windowed one at the first flip. The replacement built a
second device and re-imported every host import, and the first flip paid
for it.

VideoOut now creates its window when it starts (the first VideoOut call),
at the default 1920x1080 output, and attaches it to the driver
(AgcDriverAttachWindow) before the call returns. The driver creates its
device with that window, so GPU work and presentation use one device.
Present no longer creates or replaces a device. A device created by GPU
work before VideoOut started is still replaced, now in AttachWindow.

A failure to create the window or the device is thrown from that first
VideoOut call instead of terminating the presentation thread.

Tests:
- video_out_flip_tests onedevice: GPU work, then a flip, leaves one device.
- pacing makes its first presentation span vblanks with GPU work queued
  ahead of the flip; it relied on the device being created at the flip.
- unavailable expects the failure from sceVideoOutOpen.
- guest_video_out_wqhd_detection writes a param.json for the window title
  and is skipped without a display or Vulkan device unless
  ANYPS5_REQUIRE_DISPLAY is set.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions github-actions Bot added build prx agc libSceAgc* labels Oct 8, 2026
@github-actions

github-actions Bot commented Oct 8, 2026 •

Copy link
Copy Markdown

Other open pull requests touch the same code. Merging one will break the other, or both implement the same thing. If this one builds on them, list them in Depends on.

Pull request Conflicting files (lines on main) Same exports Same new files
#1575 core/libs/prx/libSceVideoOut/CMakeLists.txt L29-33

@oneandonlydean
oneandonlydean merged commit 3e66276 into boykopovar:main Oct 9, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants