RetroArch icon indicating copy to clipboard operation
RetroArch copied to clipboard

[Wayland] Add support for wp_presentation

Open Sunderland93 opened this issue 6 months ago • 13 comments

Guidelines

  1. Rebase before opening a pull request
  2. If you are sending several unrelated fixes or features, use a branch and a separate pull request for each
  3. If possible try squashing everything in a single commit. This is particularly beneficial in the case of feature merges since it allows easy bisecting when a problem arises

Description

Added support for wp_presentation protocol. Currently only v1, which means there is no handling of VRR cases yet. Also I'm not sure about Vulkan context, it works, but I'm not sure that it's right implementation.

Related Issues

Related to https://github.com/libretro/RetroArch/issues/17310

Related Pull Requests

[Any other PRs from related repositories that might be needed for this pull request to work]

Reviewers

@Themaister could you please do a review?

Sunderland93 avatar May 09 '25 09:05 Sunderland93

@ColinKinloch Could you also look at the code if you have time?

Sunderland93 avatar May 12 '25 11:05 Sunderland93

Currently RetroArch crashes in Vulkan mode when changing max swapchain images in settings:

[ERROR] [Vulkan]: Bogus present modes found.
[ERROR] [Vulkan]: Failed to set video mode.
[ERROR] [Video]: Cannot open video driver.. Exiting..

Sunderland93 avatar May 15 '25 15:05 Sunderland93

@sonninnos can you help?

Sunderland93 avatar May 15 '25 16:05 Sunderland93

There is also error in the log:

[ERROR] [Vulkan]: Validation Error: vkCreateSwapchainKHR(): pCreateInfo->minImageCount 3, which is outside the bounds returned by vkGetPhysicalDeviceSurfaceCapabilitiesKHR() (i.e. minImageCount = 4, maxImageCount = 0).
The Vulkan spec states: If presentMode is not VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR nor VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR, then minImageCount must be greater than or equal to the value returned in the minImageCount member of the VkSurfaceCapabilitiesKHR structure returned by vkGetPhysicalDeviceSurfaceCapabilitiesKHR for the surface (https://docs.vulkan.org/spec/latest/chapters/VK_KHR_surface/wsi.html#VUID-VkSwapchainCreateInfoKHR-presentMode-02839)

Sunderland93 avatar May 15 '25 17:05 Sunderland93

I don't know anything about that. Other than that 3 is the default, and some time ago the minimum clamping from the reported minimum was removed because some platform was reporting higher than what it could actually do. So clearly the log says minimum is 4, so test with that value instead of 3. Obviously there ought to be a failsafe of some kind to revert to the clamping if it fails that hard with the chosen value.

sonninnos avatar May 15 '25 18:05 sonninnos

It seems that this crash only happens when RetroArch is compiled with the --enable-debug option, and is not relevant to this PR as it happens in the master branch as well.

Sunderland93 avatar May 22 '25 09:05 Sunderland93

Ready for initial review. Please DON'T MERGE until review is completed. @Themaister @ColinKinloch

Sunderland93 avatar May 23 '25 08:05 Sunderland93

@Sunderland93 I'll try to ask Themaister to see if he has any interest in reviewing this

LibretroAdmin avatar May 26 '25 16:05 LibretroAdmin

What does this provide over VK_KHR_present_wait?

Themaister avatar May 26 '25 16:05 Themaister

What does this provide over VK_KHR_present_wait?

Unfortunately, I am not very familiar with Vulkan and this extension in particular. It is possible that using presentation-time for a Vulkan context is redundant.

Sunderland93 avatar May 26 '25 17:05 Sunderland93

Where are we now with this PR?

LibretroAdmin avatar Jun 07 '25 08:06 LibretroAdmin

I just tested it, vulkan segfaults due to gfx/drivers/vulkan.c:2865 as it trys to use a null vk->filter_chain. I haven't dug into it but maybe the vulkan code should throw a more graceful error when it's not been initialized properly.

ColinKinloch avatar Jun 07 '25 15:06 ColinKinloch

Where are we now with this PR?

Needs proper code review and testing

Sunderland93 avatar Jun 20 '25 08:06 Sunderland93

@ColinKinloch can you test again with the latest commit's?

Sunderland93 avatar Aug 13 '25 13:08 Sunderland93

While I have no way of testing, I just wanted to say thanks for having focus on Wayland. Had reports in the Flatpak-space that RetroArch Wayland has been buggy, so I appreciate your focus. Hopefully once the new release is out, we can get some others to test Wayland out.

Flatpak-related wayland issue: https://github.com/flathub/org.libretro.RetroArch/issues/325

RobLoach avatar Aug 24 '25 18:08 RobLoach

Tested with several cores on GL and Vulkan drivers. No issues at all. Output of WAYLAND_DEBUG=1 in OpenGL/EGL mode:

[3788850.946] {Default Queue}  -> wp_presentation#18.feedback(wl_surface#21, new id wp_presentation_feedback#57)
[3788859.217] {Default Queue} wl_keyboard#3.key(35268, 16091536, 1, 0)
[3788859.251] {Display Queue} wl_display#1.delete_id(54)
[3788859.257] {Default Queue} wp_presentation_feedback#54.presented(0, 16091, 542774000, 16653066, 0, 0, 7)
[3788868.734] {Display Queue} wl_display#1.delete_id(46)
[3788868.766] {mesa egl surface queue} wl_buffer#53.release()
[3788868.774] {mesa egl surface queue} wl_callback#46.done(16091542)
[3788868.787] {mesa egl surface queue}  -> wl_surface#21.frame(new id wl_callback#46)
[3788868.797] {mesa egl surface queue}  -> wl_surface#21.attach(wl_buffer#51, 0, 0)
[3788868.805] {mesa egl surface queue}  -> wl_surface#21.damage(0, 0, 2147483647, 2147483647)
[3788868.814] {mesa egl surface queue}  -> wl_surface#21.commit()
[3788868.844] {Default Queue}  -> wp_presentation#18.feedback(wl_surface#21, new id wp_presentation_feedback#54)
[3788876.146] {Display Queue} wl_display#1.delete_id(52)
[3788876.161] {Default Queue} wp_presentation_feedback#52.presented(0, 16091, 559432000, 16653066, 0, 0, 7)
[3788884.111] {Display Queue} wl_display#1.delete_id(46)
[3788884.132] {mesa egl surface queue} wl_buffer#50.release()
[3788884.142] {mesa egl surface queue} wl_callback#46.done(16091559)
[3788884.152] {mesa egl surface queue}  -> wl_surface#21.frame(new id wl_callback#46)
[3788884.159] {mesa egl surface queue}  -> wl_surface#21.attach(wl_buffer#53, 0, 0)
[3788884.167] {mesa egl surface queue}  -> wl_surface#21.damage(0, 0, 2147483647, 2147483647)
[3788884.175] {mesa egl surface queue}  -> wl_surface#21.commit()
[3788884.199] {Default Queue}  -> wp_presentation#18.feedback(wl_surface#21, new id wp_presentation_feedback#52)
[3788892.480] {Display Queue} wl_display#1.delete_id(56)
[3788892.494] {Default Queue} wp_presentation_feedback#56.presented(0, 16091, 576086000, 16653066, 0, 0, 7)
[3788901.467] {Display Queue} wl_display#1.delete_id(46)
[3788901.494] {mesa egl surface queue} wl_buffer#51.release()
[3788901.502] {mesa egl surface queue} wl_callback#46.done(16091576)
[3788901.510] {mesa egl surface queue}  -> wl_surface#21.frame(new id wl_callback#46)
[3788901.517] {mesa egl surface queue}  -> wl_surface#21.attach(wl_buffer#50, 0, 0)
[3788901.523] {mesa egl surface queue}  -> wl_surface#21.damage(0, 0, 2147483647, 2147483647)
[3788901.528] {mesa egl surface queue}  -> wl_surface#21.commit()
[3788901.546] {Default Queue}  -> wp_presentation#18.feedback(wl_surface#21, new id wp_presentation_feedback#56)
[3788908.695] {Display Queue} wl_display#1.delete_id(57)
[3788908.726] {Default Queue} wl_keyboard#3.key(35270, 16091591, 1, 1)
[3788908.748] {Default Queue} wp_presentation_feedback#57.presented(0, 16091, 592732000, 16653066, 0, 0, 7)
[3788920.361] {Display Queue} wl_display#1.delete_id(46)
[3788920.392] {mesa egl surface queue} wl_buffer#53.release()
[3788920.426] {mesa egl surface queue} wl_callback#46.done(16091592)
[3788920.451] {mesa egl surface queue}  -> wl_surface#21.frame(new id wl_callback#46)
[3788920.465] {mesa egl surface queue}  -> wl_surface#21.attach(wl_buffer#51, 0, 0)
[3788920.478] {mesa egl surface queue}  -> wl_surface#21.damage(0, 0, 2147483647, 2147483647)
[3788920.493] {mesa egl surface queue}  -> wl_surface#21.commit()

And in Vulkan mode:

[3984948.208] {Default Queue}  -> wp_presentation#18.feedback(wl_surface#21, new id wp_presentation_feedback#67)
[3984948.687] {Default Queue} wp_presentation_feedback#63.presented(0, 16287, 627731000, 16653066, 0, 0, 7)
[3984961.980] {Display Queue} wl_display#1.delete_id(72)
[3984962.021] {Display Queue} wl_display#1.delete_id(73)
[3984962.041] {mesa vk display queue} discarded wl_buffer#68.release()
[3984962.054] {mesa vk display queue} wl_callback#72.done(16287627)
[3984962.073] {mesa vk display queue}  -> wp_linux_drm_syncobj_surface_v1#59.set_acquire_point(wp_linux_drm_syncobj_timeline_v1#65, 0, 24)
[3984962.094] {mesa vk display queue}  -> wp_linux_drm_syncobj_surface_v1#59.set_release_point(wp_linux_drm_syncobj_timeline_v1#66, 0, 24)
[3984962.112] {mesa vk display queue}  -> wl_surface#21.attach(wl_buffer#64, 0, 0)
[3984962.127] {mesa vk display queue}  -> wl_surface#21.damage(0, 0, 2147483647, 2147483647)
[3984962.144] {mesa vk display queue}  -> wl_surface#21.frame(new id wl_callback#72)
[3984962.158] {mesa vk display queue}  -> wl_surface#21.commit()
[3984962.215] {Default Queue}  -> wp_presentation#18.feedback(wl_surface#21, new id wp_presentation_feedback#63)
[3984962.481] {Default Queue} wp_presentation_feedback#73.presented(0, 16287, 644386000, 16653066, 0, 0, 7)
[3984972.157] {Display Queue} wl_display#1.delete_id(72)
[3984972.187] {Display Queue} wl_display#1.delete_id(58)
[3984972.198] {mesa vk display queue} discarded wl_buffer#60.release()
[3984972.207] {mesa vk display queue} wl_callback#72.done(16287644)
[3984972.222] {mesa vk display queue}  -> wp_linux_drm_syncobj_surface_v1#59.set_acquire_point(wp_linux_drm_syncobj_timeline_v1#69, 0, 24)
[3984972.239] {mesa vk display queue}  -> wp_linux_drm_syncobj_surface_v1#59.set_release_point(wp_linux_drm_syncobj_timeline_v1#70, 0, 24)
[3984972.255] {mesa vk display queue}  -> wl_surface#21.attach(wl_buffer#68, 0, 0)
[3984972.267] {mesa vk display queue}  -> wl_surface#21.damage(0, 0, 2147483647, 2147483647)
[3984972.281] {mesa vk display queue}  -> wl_surface#21.frame(new id wl_callback#72)
[3984972.292] {mesa vk display queue}  -> wl_surface#21.commit()
[3984972.325] {Default Queue}  -> wp_presentation#18.feedback(wl_surface#21, new id wp_presentation_feedback#73)
[3984972.532] {Default Queue} wp_presentation_feedback#58.presented(0, 16287, 661046000, 16653066, 0, 0, 7)
[3984981.703] {Default Queue} wl_keyboard#3.key(36160, 16287663, 1, 1)
[3984986.764] {Display Queue} wl_display#1.delete_id(72)
[3984986.784] {mesa vk display queue} discarded wl_buffer#64.release()
[3984986.791] {mesa vk display queue} wl_callback#72.done(16287661)
[3984986.800] {mesa vk display queue}  -> wp_linux_drm_syncobj_surface_v1#59.set_acquire_point(wp_linux_drm_syncobj_timeline_v1#61, 0, 25)
[3984986.810] {mesa vk display queue}  -> wp_linux_drm_syncobj_surface_v1#59.set_release_point(wp_linux_drm_syncobj_timeline_v1#62, 0, 25)
[3984986.819] {mesa vk display queue}  -> wl_surface#21.attach(wl_buffer#60, 0, 0)
[3984986.826] {mesa vk display queue}  -> wl_surface#21.damage(0, 0, 2147483647, 2147483647)
[3984986.835] {mesa vk display queue}  -> wl_surface#21.frame(new id wl_callback#72)
[3984986.841] {mesa vk display queue}  -> wl_surface#21.commit()

Still needs some code review

Sunderland93 avatar Aug 26 '25 10:08 Sunderland93

It would also be nice to force the MAILBOX mode for Vulkan in case the Wayland compositor does not support the presentation-time and fifo-v1 protocols (like MPV does), since without them, in FIFO mode, random freezes may appear, up to a complete freeze of RetroArch. I think it's relevant to https://github.com/libretro/RetroArch/issues/15268 @sonninnos what do you think?

Sunderland93 avatar Aug 26 '25 10:08 Sunderland93

@ColinKinloch ping

Sunderland93 avatar Oct 17 '25 08:10 Sunderland93

I'll try to take a look at it this weekend while wayland is fresh in my mind from my current refactor attempt. I'm a tad worried that wp_presentation was designed specifically for playback of media files.

My gut says that vulkan/egl should provide enough synchronisation features but I'm not sure at the moment.

My current refactor attempt has hit a snag where it prints amdgpu: the cs has been rejected and the vulkan device disconnects randomly during resizes. I'm going to have to dig in and understand the vulkan driver. It could be that this protocol could help with that somehow 🤷.

ColinKinloch avatar Oct 17 '25 12:10 ColinKinloch