RetroArch
RetroArch copied to clipboard
[Wayland] Add support for wp_presentation
Guidelines
- Rebase before opening a pull request
- If you are sending several unrelated fixes or features, use a branch and a separate pull request for each
- 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?
@ColinKinloch Could you also look at the code if you have time?
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..
@sonninnos can you help?
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)
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.
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.
Ready for initial review. Please DON'T MERGE until review is completed. @Themaister @ColinKinloch
@Sunderland93 I'll try to ask Themaister to see if he has any interest in reviewing this
What does this provide over VK_KHR_present_wait?
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.
Where are we now with this PR?
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.
Where are we now with this PR?
Needs proper code review and testing
@ColinKinloch can you test again with the latest commit's?
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
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
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?
@ColinKinloch ping
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 🤷.