From 671361c80567de107a2069d4ac450d570e662573 Mon Sep 17 00:00:00 2001 From: Dariusz Komosinski Date: Tue, 10 Sep 2019 00:02:05 +0200 Subject: [PATCH 1/2] Remove extra lambda allocations from render loop. --- .../Rendering/DeferredRenderer.cs | 52 +++++++++++-------- src/Avalonia.Visuals/Rendering/RenderLoop.cs | 14 ++++- 2 files changed, 42 insertions(+), 24 deletions(-) diff --git a/src/Avalonia.Visuals/Rendering/DeferredRenderer.cs b/src/Avalonia.Visuals/Rendering/DeferredRenderer.cs index bf1799bbdc..64df472e93 100644 --- a/src/Avalonia.Visuals/Rendering/DeferredRenderer.cs +++ b/src/Avalonia.Visuals/Rendering/DeferredRenderer.cs @@ -246,22 +246,7 @@ namespace Avalonia.Rendering { try { - IDrawingContextImpl GetContext() - { - if (context != null) - return context; - if ((RenderTarget as IRenderTargetWithCorruptionInfo)?.IsCorrupted == true) - { - RenderTarget.Dispose(); - RenderTarget = null; - } - if (RenderTarget == null) - RenderTarget = ((IRenderRoot)_root).CreateRenderTarget(); - return context = RenderTarget.CreateDrawingContext(this); - - } - - var (scene, updated) = UpdateRenderLayersAndConsumeSceneIfNeeded(GetContext); + var (scene, updated) = UpdateRenderLayersAndConsumeSceneIfNeeded(ref context); using (scene) { @@ -271,9 +256,9 @@ namespace Avalonia.Rendering if (DrawDirtyRects) _dirtyRectsDisplay.Tick(); if (overlay) - RenderOverlay(scene.Item, GetContext()); + RenderOverlay(scene.Item, ref context); if (updated || forceComposite || overlay) - RenderComposite(scene.Item, GetContext()); + RenderComposite(scene.Item, ref context); } } } @@ -291,7 +276,7 @@ namespace Avalonia.Rendering } } - private (IRef scene, bool updated) UpdateRenderLayersAndConsumeSceneIfNeeded(Func contextFactory, + private (IRef scene, bool updated) UpdateRenderLayersAndConsumeSceneIfNeeded(ref IDrawingContextImpl context, bool recursiveCall = false) { IRef sceneRef; @@ -304,7 +289,8 @@ namespace Avalonia.Rendering var scene = sceneRef.Item; if (scene.Generation != _lastSceneId) { - var context = contextFactory(); + context = context ?? CreateDrawingContext(); + Layers.Update(scene, context); RenderToLayers(scene); @@ -325,7 +311,7 @@ namespace Avalonia.Rendering if (!recursiveCall && Dispatcher.UIThread.CheckAccess() && NeedsUpdate) { UpdateScene(); - var (rs, _) = UpdateRenderLayersAndConsumeSceneIfNeeded(contextFactory, true); + var (rs, _) = UpdateRenderLayersAndConsumeSceneIfNeeded(ref context, true); return (rs, true); } @@ -432,8 +418,10 @@ namespace Avalonia.Rendering } - private void RenderOverlay(Scene scene, IDrawingContextImpl parentContent) + private void RenderOverlay(Scene scene, ref IDrawingContextImpl parentContent) { + parentContent = parentContent ?? CreateDrawingContext(); + if (DrawDirtyRects) { var overlay = GetOverlay(parentContent, scene.Size, scene.Scaling); @@ -460,8 +448,10 @@ namespace Avalonia.Rendering } } - private void RenderComposite(Scene scene, IDrawingContextImpl context) + private void RenderComposite(Scene scene, ref IDrawingContextImpl context) { + context = context ?? CreateDrawingContext(); + context.Clear(Colors.Transparent); var clientRect = new Rect(scene.Size); @@ -503,6 +493,22 @@ namespace Avalonia.Rendering } } + private IDrawingContextImpl CreateDrawingContext() + { + if ((RenderTarget as IRenderTargetWithCorruptionInfo)?.IsCorrupted == true) + { + RenderTarget.Dispose(); + RenderTarget = null; + } + + if (RenderTarget == null) + { + RenderTarget = ((IRenderRoot)_root).CreateRenderTarget(); + } + + return RenderTarget.CreateDrawingContext(this); + } + private void UpdateScene() { Dispatcher.UIThread.VerifyAccess(); diff --git a/src/Avalonia.Visuals/Rendering/RenderLoop.cs b/src/Avalonia.Visuals/Rendering/RenderLoop.cs index 64a8427290..140688f8bc 100644 --- a/src/Avalonia.Visuals/Rendering/RenderLoop.cs +++ b/src/Avalonia.Visuals/Rendering/RenderLoop.cs @@ -91,7 +91,19 @@ namespace Avalonia.Rendering { try { - if (_items.Any(item => item.NeedsUpdate) && + bool needsUpdate = false; + + foreach (IRenderLoopTask item in _items) + { + if (item.NeedsUpdate) + { + needsUpdate = true; + + break; + } + } + + if (needsUpdate && Interlocked.CompareExchange(ref _inUpdate, 1, 0) == 0) { _dispatcher.Post(() => From c755334ddece0d094435d50e3c8942cf9572190b Mon Sep 17 00:00:00 2001 From: Dariusz Komosinski Date: Tue, 10 Sep 2019 22:12:38 +0200 Subject: [PATCH 2/2] Review feedback. --- .../Rendering/DeferredRenderer.cs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/Avalonia.Visuals/Rendering/DeferredRenderer.cs b/src/Avalonia.Visuals/Rendering/DeferredRenderer.cs index 64df472e93..efcc555159 100644 --- a/src/Avalonia.Visuals/Rendering/DeferredRenderer.cs +++ b/src/Avalonia.Visuals/Rendering/DeferredRenderer.cs @@ -289,7 +289,7 @@ namespace Avalonia.Rendering var scene = sceneRef.Item; if (scene.Generation != _lastSceneId) { - context = context ?? CreateDrawingContext(); + EnsureDrawingContext(ref context); Layers.Update(scene, context); @@ -420,7 +420,7 @@ namespace Avalonia.Rendering private void RenderOverlay(Scene scene, ref IDrawingContextImpl parentContent) { - parentContent = parentContent ?? CreateDrawingContext(); + EnsureDrawingContext(ref parentContent); if (DrawDirtyRects) { @@ -450,7 +450,7 @@ namespace Avalonia.Rendering private void RenderComposite(Scene scene, ref IDrawingContextImpl context) { - context = context ?? CreateDrawingContext(); + EnsureDrawingContext(ref context); context.Clear(Colors.Transparent); @@ -493,8 +493,13 @@ namespace Avalonia.Rendering } } - private IDrawingContextImpl CreateDrawingContext() + private void EnsureDrawingContext(ref IDrawingContextImpl context) { + if (context != null) + { + return; + } + if ((RenderTarget as IRenderTargetWithCorruptionInfo)?.IsCorrupted == true) { RenderTarget.Dispose(); @@ -506,7 +511,7 @@ namespace Avalonia.Rendering RenderTarget = ((IRenderRoot)_root).CreateRenderTarget(); } - return RenderTarget.CreateDrawingContext(this); + context = RenderTarget.CreateDrawingContext(this); } private void UpdateScene()