Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial support for DRM async page flip #1335

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

PolyMeilex
Copy link
Member

@PolyMeilex PolyMeilex commented Feb 17, 2024

This allows users to select if frame should be presented with VSync or fully ASync.

blocked by: Smithay/drm-rs#190 (awaiting releasse)
blocked by: Smithay/gbm.rs#40
related: #1325

@codecov-commenter
Copy link

codecov-commenter commented Feb 17, 2024

Codecov Report

Attention: Patch coverage is 0% with 20 lines in your changes are missing coverage. Please review.

Project coverage is 21.23%. Comparing base (91e61f1) to head (a7e1c32).
Report is 16 commits behind head on master.

Files Patch % Lines
src/backend/renderer/element/mod.rs 0.00% 15 Missing ⚠️
src/backend/renderer/element/surface.rs 0.00% 5 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #1335      +/-   ##
==========================================
- Coverage   21.32%   21.23%   -0.09%     
==========================================
  Files         156      156              
  Lines       25121    25042      -79     
==========================================
- Hits         5356     5317      -39     
+ Misses      19765    19725      -40     
Flag Coverage Δ
wlcs-buffer 18.37% <0.00%> (-0.05%) ⬇️
wlcs-core 18.03% <0.00%> (-0.07%) ⬇️
wlcs-output 7.78% <0.00%> (+0.02%) ⬆️
wlcs-pointer-input 20.05% <0.00%> (-0.13%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@PolyMeilex PolyMeilex force-pushed the drm-async-page-flip branch 2 times, most recently from 1a8c49e to 0d62362 Compare February 17, 2024 04:08
@nferhat
Copy link
Contributor

nferhat commented Feb 17, 2024

Well I'm no Smithay maintainer but still curious whether this will help with integrating tearing-control-v1 or not? Because it seems quite promising!

It actually does.

@PolyMeilex
Copy link
Member Author

Well I'm no Smithay maintainer but still curious whether this will help with integrating tearing-control-v1 or not? Because it seems quite promising!

It actually does.

Yep, it's more or less the only use-case for this.

Comment on lines 116 to 125
/// Hint for DRM backend on how the surface should be presented
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum PresentationMode {
/// Vertical synchronization
VSync,
/// Thearing presentationres
ASync,
// NOTE: Auto for detecting when thearing is desired would probably go here
}

Copy link
Collaborator

@cmeissl cmeissl Feb 17, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We might be able to get away without introducing some Auto variant. After all every frame needs to have a preference anyway. By adding PresentationMode to queue_frame this can be nicely communicated (nice work btw 👍 ) frame by frame. I think it would be nice to keep it this way and always let downstream decide without some internal mechanism to detect it. What we should do instead is to provide some helper representing some sane behavior that can be used when downstream has no preference on its own.

I was thinking about doing it this way:

  • Moving the PresentationMode enum to our render element module and introducing RenderElement::presentation_mode(&self) -> PresentationMode function
  • Adding a helper to RenderFrameResult of DrmCompositor to get a sane default PresentationMode

The RenderFrameResult already has a reference to all Elements assigned to planes, so it should be as easy
as to verify that all planes have something assigned that prefers tearing.

This way downstream should have the complete freedom to decide, but can opt in to auto easily by just forwarding the PresentationMode from RenderFrameResult to DrmCompositor::queue_frame.

@Drakulix @YaLTeR

Copy link
Member

@Drakulix Drakulix Feb 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good to me.

The RenderFrameResult already has a reference to all Elements assigned to planes, so it should be as easy
as to verify that all planes have something assigned that prefers tearing.

This is a the part however that might warrent allowing customization in some way (perhaps with a closure, like default_primary_output_compare?). E.g. some compositors might want to tear if a single element is added to the primary-plane that preferrs tearing (perhaps even dependant on the content-type?). To name a more concrete example, some FPS overlay on an overlay plane shouldn't be blocking tearing of an directly scanned-out fullscreen game on the primary plane. Of course interactions here can be extremly subtle, which is why I would also prefer to just delegate those issues to downstream.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean, everything the helper function uses internally should be public accessible. So I don't think we need to complicate the default function, especially as it should be trivial to implement. The FPS overlay is a good example, so maybe just a single parameter if it should only check the primary plane or all assigned planes. Everything more complicated than that might be better handled completely downstream.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good to me

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, but on Element rather than RenderElement, as R: Renderer generic was kinda annoying to deal with.

Elements can choose to request VSync, Async, or set no preference. Based on that we search for common denominator.

The whole change is self-contained in this new commit: a7e1c32

src/backend/drm/mod.rs Outdated Show resolved Hide resolved
@PolyMeilex PolyMeilex force-pushed the drm-async-page-flip branch 4 times, most recently from e141600 to fb65980 Compare April 19, 2024 18:00
@PolyMeilex PolyMeilex marked this pull request as ready for review April 19, 2024 18:07
@PolyMeilex
Copy link
Member Author

Ok, I belive this is ready.

Although I still can't test the atomic path, even tho my driver started to report AtomicASyncPageFlip as supported recently, any attempt to page flip results in Invalid argument (os error 22) (perhaps it's a code issue so any testing with presentation mode flipped to Async would be welcome, just flip VSync to Async in anvil's udev.rs)

Running with SMITHAY_USE_LEGACY=1 on the other hand works flawlesly for me already (if one can use flawless to describe tearing 😄).

fn presentation_mode(&self) -> Option<PresentationMode> {
// On Wayland assume VSync as default preference
Some(PresentationMode::VSync)
// TODO: Return Async in case wp_tearing is attatched to the surface
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is waiting on the tearing control PR?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, or the other way around, I don't care. Although the protocol PR is probably more merge ready. We could also just merge the PRs into one.

@cmeissl
Copy link
Collaborator

cmeissl commented Apr 21, 2024

Okay, so this is not going to work this way unfortunately. Async page flips have some special limitations we need to account for. For an async page flip to succeed the atomic commit is only allowed to change the framebuffer on the primary plane. Every other change will result in the page flip request to be declined.

This unfortunately also includes IN_FENCE_FD required for explicit sync. But this is something that is being worked on, so imo we should not special case this and just wait for it to land. Currently we do not support explicit sync for direct scan-out anyway.

Not sure what to do about FB_DAMAGE_CLIPS, need to check what the plan for this is. (worst case is we disable it for async page flips).

There are also driver specific limitations like for example intel not supporting async page flips if the plane uses some compressed tiling format.

So imo the most sane way to handle this is to do best guessing in render_frame if an async page flip might work.
Then in queue_frame do trail and error with a retry without async flip and remember that it failed for this frame state.
render_frame would then use the state as a feedback loop to prevent endless retries. The failed state should reset in case the format or other stuff changes allowing to re-test.

I prototyped some parts of this and will post a patch when its ready.

@cmeissl
Copy link
Collaborator

cmeissl commented Apr 21, 2024

Okay, I put something together that should work (at least it seems to work on my system).
https://github.com/cmeissl/smithay/commits/drm_async_page_flip/ (@PolyMeilex PR branch rebased on top of current master + some small fixes)

Curious if this also works on AMD and Nvidia now @PolyMeilex @YaLTeR @Drakulix
Filtering for linear formats is probably not going to work on Nvidia and probably also not needed.
Intel also does support async page flips with some modifiers (probably only compressed one are not supported, which kind of makes sense), but I was too lazy to put together a list of working formats.

@PolyMeilex
Copy link
Member Author

@cmeissl Atomic backend now works on my AMD systems, looks promising.

Rebased on master, and cherrypicked the cmeissl's commit (with some minnor reverts of debug code edits)

@PolyMeilex
Copy link
Member Author

Confits resolved, everything seems to still work as expected on my AMD machines both with atomic and legacy

@Drakulix
Copy link
Member

Drakulix commented Jun 3, 2024

Feedback from the display next hackfest:

  • IN_FENCE_FD will be added as a supported property in some future kernel
  • FB_DAMAGE_CLIPS is unclear, but amd/intel are aware that their current set of properties is too restrictive
  • There was a proposal to have an additional IN_FORMATS_ASYNC (or similarly named) property to solve the format issue.
  • Other compositors currently seem to just fall back to non-tearing presentation, when the format doesn't work out or default to the legacy api. Just using linear was deemed to potentially have performance issues...

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