Skip to content

RFC: implement commit-timing-v1 and fifo-v1 - #2797

Open
skygrango wants to merge 6 commits into
pop-os:masterfrom
skygrango:commit-timing_fifo_noble
Open

RFC: implement commit-timing-v1 and fifo-v1#2797
skygrango wants to merge 6 commits into
pop-os:masterfrom
skygrango:commit-timing_fifo_noble

Conversation

@skygrango

@skygrango skygrango commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

related: #1549

The main purpose of this PR is to verify that the commit-timing-1 and fifo-1 functionality work correctly.

Test conditions:

  • Vsync ON
  • Enable built-in frame limiter
  • PROTON_ENABLE_WAYLAND=1
  • Disable DLSS, FSR, XeSS (those tech will force Vsync to turn off)
  • WAYLAND_DEBUG show wp_commit_timer_v1 and wp_fifo_v1
  • no crash, no hang indefinitely and frame limiter work = ✅
Game Vulkan DXVK VKD3D Note
Ready or Not AMD
Elden Ring AMD
STAR WARS Zero Company AMD
MONSTER HUNTER WILD AMD
ARC Raiders AMD
PRAGMATA AMD
Sekiro™: Shadows Die Twice AMD

Note: if someone want to test DXVK game, you need custon proton: https://github.com/NelloKudo/proton-dev/actions/runs/33871680219 and PROTON_PRESENT_TIMING=1 PROTON_ENABLE_WAYLAND=1

logs sample:

[12:38:32.982612] {mesa vk surface 39 swapchain 2 queue} wp_presentation_feedback#60.sync_output(wl_output#22)
[12:38:32.982619] {mesa vk surface 39 swapchain 2 queue} wp_presentation_feedback#60.presented(0, 5433, 958401000, 4166840, 0, 34657727, 7)
[12:38:32.984089] {mesa vk display queue}  -> wp_linux_drm_syncobj_surface_v1#65.set_acquire_point(wp_linux_drm_syncobj_timeline_v1#63, 0, 10)
[12:38:32.984097] {mesa vk display queue}  -> wp_linux_drm_syncobj_surface_v1#65.set_release_point(wp_linux_drm_syncobj_timeline_v1#68, 0, 10)
[12:38:32.984102] {mesa vk display queue}  -> wl_surface#39.attach(wl_buffer#75, 0, 0)
[12:38:32.984104] {mesa vk display queue}  -> wl_surface#39.damage_buffer(0, 0, 2147483647, 2147483647)
[12:38:32.984107] {mesa vk display queue}  -> wp_commit_timer_v1#57.set_timestamp(0, 5433, 970401520)
[12:38:32.984111] {mesa vk surface 39 swapchain 2 queue}  -> wp_presentation#43.feedback(wl_surface#39, new id wp_presentation_feedback#60)
[12:38:32.984121] {mesa vk display queue}  -> wp_fifo_v1#56.set_barrier()
[12:38:32.984129] {mesa vk display queue}  -> wp_fifo_v1#56.wait_barrier()
[12:38:32.984136] {mesa vk display queue}  -> wl_surface#39.commit()
[12:38:32.984144] {mesa vk display queue}  -> wp_fifo_v1#56.wait_barrier()
[12:38:32.984151] {mesa vk display queue}  -> wl_surface#39.commit()
[12:38:32.984174] {mesa vk display queue} discarded wl_buffer#79.release()
[12:38:32.986777] {Display Queue} wl_display#1.delete_id(62)
[12:38:32.986787] {mesa vk surface 39 swapchain 2 queue} wp_presentation_feedback#62.sync_output(wl_output#22)
[12:38:32.986793] {mesa vk surface 39 swapchain 2 queue} wp_presentation_feedback#62.presented(0, 5433, 962567000, 4166840, 0, 34657728, 7)

need: Smithay/smithay#2149

The purpose of this PR is to serve as a proof of concept (POC) for validating the schedule_barrier handler I added to Smithay. No longer need to update smithay.

The OutputSurface introduced in this PR is optional rather than required. It is only used to make it easier for me to iterate on and test the output/window behavior during development, and is not intended to be a fundamental requirement of the approach. No longer need to lookup

  • I have disclosed use of any AI generated code in my commit messages.
    • If you are using an LLM, and do not fully understand the changes it is making to the code base, do not create a PR.
    • In our experience, AI generated code often results in overly complex code that lacks enough context for a proper fix or feature inclusion. This results in considerably longer code reviews. Due to this, AI authored or partially authored PRs may be closed without comment.
  • I understand these changes in full and will be able to respond to review comments.
  • My change is accurately described in the commit message.
  • My contribution is tested and working as described.
  • I have read the Developer Certificate of Origin and certify my contribution under its conditions.

@Drakulix
Drakulix requested a review from ids1024 August 31, 2026 10:50
@skygrango
skygrango force-pushed the commit-timing_fifo_noble branch from ea85282 to 62753b0 Compare August 31, 2026 14:23
@ids1024

ids1024 commented Aug 31, 2026

Copy link
Copy Markdown
Member

We definitely want to get fifo and commit-timing working. Though we do have to be careful here since if we fail to signal a fifo barrier for a particular type of surface in any circumstance, it could hang indefinitely.

@skygrango

Copy link
Copy Markdown
Contributor Author

We definitely want to get fifo and commit-timing working. Though we do have to be careful here since if we fail to signal a fifo barrier for a particular type of surface in any circumstance, it could hang indefinitely.

yep. I noticed that your original signal_fifos seems to hang indefinitely under certain conditions(when switching to full-screen mode), so I replaced it with my version. I’ve tested my version for several months, and it seems to work well. I haven’t investigated yet why the original FIFO signaling mechanism has this issue.

The main purpose of this PR is to investigate whether the commit-timing implementation has reached a sufficient level of correctness, even though its timing precision still needs improvement. It may also provide a good opportunity to use it as a reference when investigating where it differs from your original approach.

@skygrango
skygrango force-pushed the commit-timing_fifo_noble branch from 62753b0 to fd272c0 Compare September 1, 2026 12:09
@skygrango

Copy link
Copy Markdown
Contributor Author

Following the suggestion, this no longer needs to depend on updates to smithay.

@skygrango

Copy link
Copy Markdown
Contributor Author

@ids1024 I’ve updated the fifo-v1 implementation to use FifoManagerState::unmanaged together with visible_output_for_surface to keep track of the output associated with the barrier, eliminating the need for a lookup. This should greatly reduce the risk of fifo barrier not being signaled correctly.

@skygrango
skygrango force-pushed the commit-timing_fifo_noble branch 5 times, most recently from 2db3184 to af2c2be Compare September 2, 2026 06:22
@skygrango

skygrango commented Sep 2, 2026

Copy link
Copy Markdown
Contributor Author

commit-timing-v1 requirement:

content updates should be presented as closely as possible to, but not before, the specified time

I implemented a frame-time-based early commit strategy.

@ids1024

ids1024 commented Sep 3, 2026

Copy link
Copy Markdown
Member

Not having an extra place or two where we iterate over all types of surfaces is definitely good.

Comment thread src/utils/prelude.rs Outdated
Comment on lines +193 to +196
fn init_fifo(&self) {
self.user_data()
.insert_if_missing_threadsafe(|| FifoBarriers(Mutex::new(Vec::new())));
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Isn't this redundant if fifo_barrier() also calls insert_if_missing_threadsafe()?

Comment thread src/utils/prelude.rs Outdated
Comment on lines +200 to +201
user_data.insert_if_missing_threadsafe(|| FifoBarriers(Mutex::new(Vec::new())));
if let Some(barriers) = user_data.get::<FifoBarriers>()

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

insert_if_missing_threadsafe and get can be combining into get_or_insert_threadsafe.

Comment thread src/utils/prelude.rs Outdated
Comment on lines +224 to +225
user_data.insert_if_missing_threadsafe(|| AvgFrameTime(RwLock::new(None)));
if let Some(avg_frametime) = user_data.get::<AvgFrameTime>() {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This likewise can use get_or_insert_threadsafe.

}
});

add_pre_commit_hook::<Self, _>(surface, move |state, _dh, surface| {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It's probably unnecessary to add three different pre-commit hooks to each surface in new_surface().

Maybe a single hook that could invoke helper functions for the different things it does?

Comment thread src/wayland/handlers/compositor.rs Outdated

impl State {
fn schedule_commit_timing(&self, surface: &WlSurface, deadline: Timestamp) {
const SAFE_MARGE: Duration = Duration::from_millis(1);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Is MARGE here a "margin"? If so presumably SAFE_MARGIN would be clearer. Unless I misunderstand this.

Is there any particular logic behind the 1ms value, or is it just an extra margin that seemed to work well based on testing?

@skygrango skygrango Sep 3, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

yeah, it should be SAFE_MARGIN.

commit-timing requires us not to present frames early, so this 1 ms is a tolerance designed to respect that requirement. We can improve this part further in the future.

@ids1024

ids1024 commented Sep 3, 2026

Copy link
Copy Markdown
Member

Storing the fifos to signal with the output seems good. I see it does signal fifos on output removal, which should cover things; either the output will be presented or it will be removed. If a change of primary scanout output happens after setting the barrier it will still wait on the previous output? But that's probably fine.

Commit timing is a protocol I'm a little less familiar with.

Enable built-in frame limiter

no crash, no hang indefinitely and frame limiter work

So is the testing of commit timing mainly just enabling the frame rate limiter and a frame rate overlay and seeing that it seems to report the frame rate it should?

Are there any good clients to test/measure how well it is doing more precisely? I suppose comparing requested commit timings to presentation-time feedback.

@skygrango

skygrango commented Sep 3, 2026

Copy link
Copy Markdown
Contributor Author

Storing the fifos to signal with the output seems good. I see it does signal fifos on output removal, which should cover things; either the output will be presented or it will be removed. If a change of primary scanout output happens after setting the barrier it will still wait on the previous output? But that's probably fine.

work fine in my test, I think the current state of fifo-v1 looks good.

Commit timing is a protocol I'm a little less familiar with.

Enable built-in frame limiter

no crash, no hang indefinitely and frame limiter work

So is the testing of commit timing mainly just enabling the frame rate limiter and frame rate counter and seeing that it seems to report the frame rate it should?

I'm digging deeper into DXVK's design to better understand client-side behavior. Here's how DXVK describes its present timing feature:

Whether to enable present timing features.

Present timing is used to improve frame time consistency when emulating non-native display modes (e.g. 60 Hz on a high-refresh-rate display), and for the frame rate limiter. It can be disabled for debugging purposes.

FYR: https://github.com/doitsujin/dxvk/pull/5869/changes#diff-51c6436f1bc3ea9e601312655dae5b7534c646e09002ca98467e2758f967014b

To achieve this, DXVK maintains its own internal timeline algorithm and continuously updates it dynamically.

I'm still looking for the most appropriate approach to accommodate this kind of client-side behavior. If you have any suggestions, I'd really appreciate it.

Are there any good clients to test/measure how well it is doing more precisely? I suppose comparing required commit timings to presentation-time feedback.

I recommend: https://github.com/Themaister/Granite/blob/master/tests/present_timing.cpp

the tool is great. It allows you to toggle VSync (FIFO), enable or disable and configure time requests (commit-timing), adjust GPU load, and toggle VRR.

Since this involves frame pacing, it is relevant to #2420

@ids1024

ids1024 commented Sep 3, 2026

Copy link
Copy Markdown
Member

work fine in my test, I think the current state of fifo-v1 looks good.

Yeah, this version of fifo looks fairly safe.

Commit-timing is a little more complicated. I'm not familiar with the details of optimal frame pacing, but I know it can be a complicated matter.

Probably this version at least a good start and it can be improved later. Though it would be good to see some specific metrics for how well it is working.

@skygrango

skygrango commented Sep 3, 2026

Copy link
Copy Markdown
Contributor Author

Commit-timing is a little more complicated. I'm not familiar with the details of optimal frame pacing, but I know it can be a complicated matter.

Probably this version at least a good start and it can be improved later. Though it would be good to see some specific metrics for how well it is working.

After integrating #2420, I think commit-timing performs reasonably well in fullscreen mode. the reason I integrate this is that the PR prevents commits from other non-fullscreen surfaces from interfering with the scheduling, which can affect frame pacing.

here are some screenshots I can use to explain the current situation:
My monitor is running at 240 Hz, which means a refresh interval of 4.167 ms.

The graph below shows the result with commit-timing and FIFO enabled, VRR disabled, and the commit-timing interval set to 10.417 ms. The average frame time is 12.379 ms, which means the presentation is occurring around every third vblank, since 4.167 ms × 3 ≈ 12.5 ms.
Screenshot_2026-09-03_13-29-22

The graph below shows the result with VRR enabled and the commit-timing interval set to 14.063 ms. The average frame time is 14.064 ms.
Screenshot_2026-09-03_13-30-32

If you're interested in testing this as well, I've prepared the branch I used for you to try: https://github.com/skygrango/cosmic-comp/tree/commit-timing_fifo_with_fullscreen_patch

@skygrango

Copy link
Copy Markdown
Contributor Author

A clarification: Presentation Error in the graphs indicates whether the timestamp specified by commit-timing was respected. If it remains as a straight line in the middle, that means it is working as expected.

@skygrango

Copy link
Copy Markdown
Contributor Author

@ids1024 Do you think I should also include #2420 in this PR, or would you prefer to handle it separately?

@ids1024

ids1024 commented Sep 4, 2026

Copy link
Copy Markdown
Member

Probably best to keep it separate and update #2420 after this one is merged.

@skygrango
skygrango force-pushed the commit-timing_fifo_noble branch from afb1a39 to b12c0ae Compare September 4, 2026 13:29
@skygrango

skygrango commented Sep 4, 2026

Copy link
Copy Markdown
Contributor Author

Rebase and cleanup.

I don't have an NVIDIA 20–50 series GPU, which supports the open-source driver, so I haven't been able to test this on those GPUs. I've done extensive testing with my AMD GPU, though, and based on those results, I think the current state is good enough for me.

Also, since NVIDIA GPUs are currently forced to use Duration::Zero in next_render_time(), I'm not sure whether the behavior on NVIDIA hardware might be somewhat unusual.

edit: I noticed something a bit strange. Let me investigate it a little further.

@skygrango

Copy link
Copy Markdown
Contributor Author

I went back and tested FIFO on its own again, and I realized that FIFO wasn't actually making the window's update rate follow the display refresh rate.

I had forgotten that we only need to process the current barrier, not pending barrier. Otherwise, we would signal all the barriers at once, which defeats the purpose of FIFO.

I've updated the FIFO implementation accordingly. Could you please take another look and verify it?

This time, I'm confident that the window's frame rate is actually being limited by the vblank.

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.

2 participants