Browse Source

Merge pull request #3818 from MarchingCube/deferred-renderer-memory

Limit reallocations in the deferred renderer.
fixes/handle-invalid-dirty-rects
Steven Kirk 6 years ago
committed by GitHub
parent
commit
21b21e40bc
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 18
      src/Avalonia.Visuals/Rendering/SceneGraph/Scene.cs
  2. 20
      src/Avalonia.Visuals/Rendering/SceneGraph/SceneLayers.cs
  3. 25
      src/Avalonia.Visuals/Rendering/SceneGraph/VisualNode.cs

18
src/Avalonia.Visuals/Rendering/SceneGraph/Scene.cs

@ -12,7 +12,7 @@ namespace Avalonia.Rendering.SceneGraph
/// </summary>
public class Scene : IDisposable
{
private Dictionary<IVisual, IVisualNode> _index;
private readonly Dictionary<IVisual, IVisualNode> _index;
/// <summary>
/// Initializes a new instance of the <see cref="Scene"/> class.
@ -83,7 +83,7 @@ namespace Avalonia.Rendering.SceneGraph
/// <returns>The cloned scene.</returns>
public Scene CloneScene()
{
var index = new Dictionary<IVisual, IVisualNode>();
var index = new Dictionary<IVisual, IVisualNode>(_index.Count);
var root = Clone((VisualNode)Root, null, index);
var result = new Scene(root, index, Layers.Clone(), Generation + 1)
@ -162,9 +162,19 @@ namespace Avalonia.Rendering.SceneGraph
index.Add(result.Visual, result);
foreach (var child in source.Children)
var children = source.Children;
var childrenCount = children.Count;
if (childrenCount > 0)
{
result.AddChild(Clone((VisualNode)child, result, index));
result.TryPreallocateChildren(childrenCount);
for (var i = 0; i < childrenCount; i++)
{
var child = children[i];
result.AddChild(Clone((VisualNode)child, result, index));
}
}
return result;

20
src/Avalonia.Visuals/Rendering/SceneGraph/SceneLayers.cs

@ -11,16 +11,28 @@ namespace Avalonia.Rendering.SceneGraph
public class SceneLayers : IEnumerable<SceneLayer>
{
private readonly IVisual _root;
private readonly List<SceneLayer> _inner = new List<SceneLayer>();
private readonly Dictionary<IVisual, SceneLayer> _index = new Dictionary<IVisual, SceneLayer>();
private readonly List<SceneLayer> _inner;
private readonly Dictionary<IVisual, SceneLayer> _index;
/// <summary>
/// Initializes a new instance of the <see cref="SceneLayers"/> class.
/// </summary>
/// <param name="root">The scene's root visual.</param>
public SceneLayers(IVisual root)
public SceneLayers(IVisual root) : this(root, 0)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="SceneLayers"/> class.
/// </summary>
/// <param name="root">The scene's root visual.</param>
/// <param name="capacity">Initial layer capacity.</param>
public SceneLayers(IVisual root, int capacity)
{
_root = root;
_inner = new List<SceneLayer>(capacity);
_index = new Dictionary<IVisual, SceneLayer>(capacity);
}
/// <summary>
@ -84,7 +96,7 @@ namespace Avalonia.Rendering.SceneGraph
/// <returns>The cloned layers.</returns>
public SceneLayers Clone()
{
var result = new SceneLayers(_root);
var result = new SceneLayers(_root, Count);
foreach (var src in _inner)
{

25
src/Avalonia.Visuals/Rendering/SceneGraph/VisualNode.cs

@ -1,7 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reactive.Disposables;
using Avalonia.Collections;
using Avalonia.Media;
using Avalonia.Platform;
using Avalonia.Utilities;
@ -349,6 +349,11 @@ namespace Avalonia.Rendering.SceneGraph
context.Transform = transformRestore;
}
internal void TryPreallocateChildren(int count)
{
EnsureChildrenCreated(count);
}
private Rect CalculateBounds()
{
var result = new Rect();
@ -362,11 +367,11 @@ namespace Avalonia.Rendering.SceneGraph
return result;
}
private void EnsureChildrenCreated()
private void EnsureChildrenCreated(int capacity = 0)
{
if (_children == null)
{
_children = new List<IVisualNode>();
_children = new List<IVisualNode>(capacity);
}
}
@ -383,7 +388,15 @@ namespace Avalonia.Rendering.SceneGraph
}
else if (_drawOperationsCloned)
{
_drawOperations = new List<IRef<IDrawOperation>>(_drawOperations.Select(op => op.Clone()));
var oldDrawOperations = _drawOperations;
_drawOperations = new List<IRef<IDrawOperation>>(oldDrawOperations.Count);
foreach (var drawOperation in oldDrawOperations)
{
_drawOperations.Add(drawOperation.Clone());
}
_drawOperationsRefCounter.Dispose();
_drawOperationsRefCounter = RefCountable.Create(CreateDisposeDrawOperations(_drawOperations));
_drawOperationsCloned = false;
@ -399,9 +412,9 @@ namespace Avalonia.Rendering.SceneGraph
/// <returns>Disposable for given draw operations.</returns>
private static IDisposable CreateDisposeDrawOperations(List<IRef<IDrawOperation>> drawOperations)
{
return Disposable.Create(() =>
return Disposable.Create(drawOperations, operations =>
{
foreach (var operation in drawOperations)
foreach (var operation in operations)
{
operation.Dispose();
}

Loading…
Cancel
Save