Skip to content

Commit

Permalink
Adds an option that enables the rendering runs instantly.
Browse files Browse the repository at this point in the history
Before this commit: UI -> render -> UI -> render (then it rendered)
After this commit: UI -> render (then it rendered)
Yes, It reduced rendering delay at least one frame.
  • Loading branch information
walterlv committed Sep 3, 2024
1 parent 883d240 commit 0f997e7
Show file tree
Hide file tree
Showing 4 changed files with 24 additions and 7 deletions.
13 changes: 10 additions & 3 deletions src/Avalonia.Base/Media/MediaContext.Compositor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,16 @@ private CompositionBatch CommitCompositor(Compositor compositor)
var commit = compositor.Commit();
_requestedCommits.Remove(compositor);
_pendingCompositionBatches[compositor] = commit;
commit.Processed.ContinueWith(_ =>
_dispatcher.Post(() => CompositionBatchFinished(compositor, commit), DispatcherPriority.Send),
TaskContinuationOptions.ExecuteSynchronously);
if (_dispatcherOptions.InstantRendering)
{
CompositionBatchFinished(compositor, commit);
}
else
{
commit.Processed.ContinueWith(_ =>
_dispatcher.Post(() => CompositionBatchFinished(compositor, commit), DispatcherPriority.Send),
TaskContinuationOptions.ExecuteSynchronously);
}
return commit;
}

Expand Down
8 changes: 5 additions & 3 deletions src/Avalonia.Base/Media/MediaContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ private record TopLevelInfo(Compositor Compositor, CompositingRenderer Renderer

private List<Action>? _invokeOnRenderCallbacks;
private readonly Stack<List<Action>> _invokeOnRenderCallbackListPool = new();
private readonly DispatcherOptions _dispatcherOptions;

private readonly DispatcherTimer _animationsTimer = new(DispatcherPriority.Render)
{
Expand All @@ -37,13 +38,14 @@ private record TopLevelInfo(Compositor Compositor, CompositingRenderer Renderer

private readonly Dictionary<object, TopLevelInfo> _topLevels = new();

private MediaContext(Dispatcher dispatcher, TimeSpan inputStarvationTimeout)
private MediaContext(Dispatcher dispatcher, DispatcherOptions dispatcherOptions)
{
_render = Render;
_inputMarkerHandler = InputMarkerHandler;
_clock = new(this);
_dispatcher = dispatcher;
MaxSecondsWithoutInput = inputStarvationTimeout.TotalSeconds;
_dispatcherOptions = dispatcherOptions;
MaxSecondsWithoutInput = dispatcherOptions.InputStarvationTimeout.TotalSeconds;
_animationsTimer.Tick += (_, _) =>
{
_animationsTimer.Stop();
Expand All @@ -62,7 +64,7 @@ public static MediaContext Instance
if (context == null)
{
var opts = AvaloniaLocator.Current.GetService<DispatcherOptions>() ?? new();
context = new MediaContext(Dispatcher.UIThread, opts.InputStarvationTimeout);
context = new MediaContext(Dispatcher.UIThread, opts);
AvaloniaLocator.CurrentMutable.Bind<MediaContext>().ToConstant(context);
}

Expand Down
4 changes: 3 additions & 1 deletion src/Avalonia.Base/Rendering/Composition/Compositor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ public partial class Compositor
private readonly List<Action> _pendingServerCompositorPostTargetJobs = new();
private DiagnosticTextRenderer? _diagnosticTextRenderer;
private readonly Action _triggerCommitRequested;
private readonly DispatcherOptions _dispatcherOptions;

internal IEasing DefaultEasing { get; }

Expand Down Expand Up @@ -89,6 +90,7 @@ internal Compositor(IRenderLoop loop, IPlatformGraphics? gpu,
_batchObjectPool = new(reclaimBuffersImmediately);
_server = new ServerCompositor(loop, gpu, options, _batchObjectPool, _batchMemoryPool);
_triggerCommitRequested = () => scheduler.CommitRequested(this);
_dispatcherOptions = AvaloniaLocator.Current.GetService<DispatcherOptions>() ?? new();

DefaultEasing = new SplineEasing(new KeySpline(0.25, 0.1, 0.25, 1.0));
}
Expand All @@ -110,7 +112,7 @@ public CompositionBatch RequestCompositionBatchCommitAsync()
{
_nextCommit = new ();
var pending = _pendingBatch;
if (pending != null)
if (pending != null && !_dispatcherOptions.InstantRendering)
pending.Processed.ContinueWith(
_ => Dispatcher.Post(_triggerCommitRequested, DispatcherPriority.Send),
TaskContinuationOptions.ExecuteSynchronously);
Expand Down
6 changes: 6 additions & 0 deletions src/Avalonia.Base/Threading/DispatcherOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,10 @@ public class DispatcherOptions
/// the same thread as rendering.
/// </remarks>
public TimeSpan InputStarvationTimeout { get; set; } = TimeSpan.FromSeconds(1);

/// <summary>
/// Gets or sets a value indicating whether rendering should be performed synchronously.<br/>
/// Otherwise, rendering will be invoked from UI thread to the render thread, back to the UI thread and then back to the render thread.
/// </summary>
public bool InstantRendering { get; set; } = false;
}

0 comments on commit 0f997e7

Please sign in to comment.