Skip to content

Conversation

Sunderland93
Copy link
Contributor

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 #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 Sunderland93 marked this pull request as draft May 9, 2025 09:20
@Sunderland93
Copy link
Contributor Author

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

@Sunderland93
Copy link
Contributor Author

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
Copy link
Contributor Author

@sonninnos can you help?

@Sunderland93
Copy link
Contributor Author

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)

@sonninnos
Copy link
Collaborator

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.

@Sunderland93
Copy link
Contributor Author

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 Sunderland93 marked this pull request as ready for review May 23, 2025 08:15
@Sunderland93
Copy link
Contributor Author

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

@LibretroAdmin
Copy link
Contributor

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

@Themaister
Copy link
Contributor

What does this provide over VK_KHR_present_wait?

@Sunderland93
Copy link
Contributor Author

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.

@LibretroAdmin
Copy link
Contributor

Where are we now with this PR?

@ColinKinloch
Copy link
Contributor

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.

@Sunderland93
Copy link
Contributor Author

Where are we now with this PR?

Needs proper code review and testing

@Sunderland93
Copy link
Contributor Author

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

@RobLoach
Copy link
Member

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: flathub/org.libretro.RetroArch#325

@Sunderland93 Sunderland93 force-pushed the wp_presentation branch 2 times, most recently from 0c1cbb0 to 526d9df Compare August 25, 2025 13:29
correctly handle clock_id

bind to wp_presentation_v1 atm

more precise synchronization

Ensure that presented() is reached

wp_presentation: correctly set clock_type

wp_presentation: deduplicate code

use only nanoseconds

wp_presentation: use clock_nanosleep instead of usleep

don't replace wl_callback with presentation feedback

Remove presentation feedback more gracefully

Fix gap between request feedback and presented
@Sunderland93
Copy link
Contributor Author

Sunderland93 commented Aug 26, 2025

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
Copy link
Contributor Author

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 #15268 @sonninnos what do you think?

@Sunderland93
Copy link
Contributor Author

@ColinKinloch @Themaister ping

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants