Parcourir la source

Render output refreshing and disabled chunk pooling

Krzysztof Krysiński il y a 2 semaines
Parent
commit
7d50edce3f

+ 7 - 4
src/ChunkyImageLib/Chunk.cs

@@ -67,7 +67,8 @@ public class Chunk : IDisposable
     /// </summary>
     public static Chunk Create(ColorSpace chunkCs, ChunkResolution resolution = ChunkResolution.Full)
     {
-        var chunk = ChunkPool.Instance.Get(resolution, chunkCs);
+        return new Chunk(resolution, chunkCs);
+        /*var chunk = ChunkPool.Instance.Get(resolution, chunkCs);
         if (chunk == null || chunk.Disposed)
         {
             chunk = new Chunk(resolution, chunkCs);
@@ -75,7 +76,7 @@ public class Chunk : IDisposable
 
         chunk.returned = false;
         Interlocked.Increment(ref chunkCounter);
-        return chunk;
+        return chunk;*/
     }
 
     /// <summary>
@@ -134,12 +135,14 @@ public class Chunk : IDisposable
     /// </summary>
     public void Dispose()
     {
-        if (returned)
+        returned = true;
+        internalSurface.Dispose();
+        /*if (returned)
             return;
         Interlocked.Decrement(ref chunkCounter);
         Surface.DrawingSurface.Canvas.Clear();
         Surface.DrawingSurface.Canvas.SetMatrix(Matrix3X3.Identity);
         ChunkPool.Instance.Push(this);
-        returned = true;
+        returned = true;*/
     }
 }

+ 1 - 0
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/LayerNode.cs

@@ -44,6 +44,7 @@ public abstract class LayerNode : StructureNode, IReadOnlyLayerNode, IClipSource
                 blendPaint.BlendMode = RenderContext.GetDrawingBlendMode(BlendMode.Value);
             }
 
+            // TODO: Optimizattion: Simple graphs can draw directly to scene, skipping the intermediate surface
             if (AllowHighDpiRendering || renderOnto.DeviceClipBounds.Size == context.RenderOutputSize)
             {
                 DrawLayerInScene(context, renderOnto, useFilters);

+ 40 - 27
src/PixiEditor/Models/Rendering/SceneRenderer.cs

@@ -25,7 +25,7 @@ internal class SceneRenderer : IDisposable
     public IDocument DocumentViewModel { get; }
     public bool HighResRendering { get; set; } = true;
 
-    private bool lastHighResRendering = true;
+    private Dictionary<Guid, RenderState> lastRenderedStates = new();
     private int lastGraphCacheHash = -1;
     private KeyFrameTime lastFrameTime;
     private Dictionary<Guid, bool> lastFramesVisibility = new();
@@ -83,13 +83,17 @@ internal class SceneRenderer : IDisposable
             target.DeviceClipBounds.Size.ShortestAxis <= 0) return;*/
         //RenderOnionSkin(target, resolution, samplingOptions, targetOutput);
 
+        /*TODO:
+         - Onion skinning
+         - Previews generation
+         - Rendering optimizer
+         - Render thread and proper locking/synchronization
+         */
+
         IReadOnlyNodeGraph finalGraph = RenderingUtils.SolveFinalNodeGraph(targetOutput, Document);
         bool shouldRerender =
             ShouldRerender(renderTargetSize, targetMatrix, resolution, viewportId, targetOutput, finalGraph);
 
-        // TODO: Check if clipping to visible area improves performance on full resolution
-        // Meaning zoomed big textures
-
         if (shouldRerender)
         {
             return RenderGraph(renderTargetSize, targetMatrix, viewportId, resolution, samplingOptions, affectedArea,
@@ -99,10 +103,6 @@ internal class SceneRenderer : IDisposable
         //previewRenderer.RenderPreviews(DocumentViewModel.AnimationHandler.ActiveFrameTime);
 
         var cachedTexture = DocumentViewModel.SceneTextures[viewportId];
-        Matrix3X3 matrixDiff = SolveMatrixDiff(targetMatrix, cachedTexture);
-        var target = cachedTexture.DrawingSurface;
-        target.Canvas.SetMatrix(matrixDiff);
-
         return cachedTexture;
     }
 
@@ -221,9 +221,25 @@ internal class SceneRenderer : IDisposable
             return true;
         }
 
-        if (lastHighResRendering != HighResRendering)
+        var renderState = new RenderState
+        {
+            ChunkResolution = resolution,
+            HighResRendering = HighResRendering,
+            TargetOutput = targetOutput,
+            GraphCacheHash = finalGraph.GetCacheHash()
+        };
+
+        if (lastRenderedStates.TryGetValue(viewportId, out var lastState))
+        {
+            if (!lastState.Equals(renderState))
+            {
+                lastRenderedStates[viewportId] = renderState;
+                return true;
+            }
+        }
+        else
         {
-            lastHighResRendering = HighResRendering;
+            lastRenderedStates[viewportId] = renderState;
             return true;
         }
 
@@ -271,26 +287,9 @@ internal class SceneRenderer : IDisposable
         }
         //}
 
-        int currentGraphCacheHash = finalGraph.GetCacheHash();
-        if (lastGraphCacheHash != currentGraphCacheHash)
-        {
-            lastGraphCacheHash = currentGraphCacheHash;
-            return true;
-        }
-
         return false;
     }
 
-    private Matrix3X3 SolveMatrixDiff(Matrix3X3 matrix, Texture cachedTexture)
-    {
-        Matrix3X3 old = cachedTexture.DrawingSurface.Canvas.TotalMatrix;
-        Matrix3X3 current = matrix;
-
-        Matrix3X3 solveMatrixDiff = current.Concat(old.Invert());
-        return solveMatrixDiff;
-    }
-
-
     private bool HighDpiRenderNodePresent(IReadOnlyNodeGraph documentNodeGraph)
     {
         bool highDpiRenderNodePresent = false;
@@ -363,3 +362,17 @@ internal class SceneRenderer : IDisposable
         }*/
     }
 }
+
+
+struct RenderState
+{
+    public ChunkResolution ChunkResolution { get; set; }
+    public bool HighResRendering { get; set; }
+    public string TargetOutput { get; set; }
+    public int GraphCacheHash { get; set; }
+
+    public bool Equals(RenderState other)
+    {
+        return ChunkResolution.Equals(other.ChunkResolution) && HighResRendering == other.HighResRendering && TargetOutput == other.TargetOutput && GraphCacheHash == other.GraphCacheHash;
+    }
+}

+ 5 - 0
src/PixiEditor/Views/Main/ViewportControls/Viewport.axaml.cs

@@ -398,6 +398,11 @@ internal partial class Viewport : UserControl, INotifyPropertyChanged
     static Viewport()
     {
         DocumentProperty.Changed.Subscribe(OnDocumentChange);
+        ViewportRenderOutputProperty.Changed.Subscribe(e =>
+        {
+            Viewport? viewport = (Viewport)e.Sender;
+            viewport.Document?.Operations.AddOrUpdateViewport(viewport.GetLocation());
+        });
         ZoomViewportTriggerProperty.Changed.Subscribe(ZoomViewportTriggerChanged);
         CenterViewportTriggerProperty.Changed.Subscribe(CenterViewportTriggerChanged);
         HighResPreviewProperty.Changed.Subscribe(OnHighResPreviewChanged);

+ 22 - 4
src/PixiEditor/Views/Rendering/Scene.cs

@@ -351,28 +351,36 @@ internal class Scene : Zoombox.Zoombox, ICustomHitTest
 
             bool hasSaved = false;
             int saved = -1;
+
+            var matrix = CalculateTransformMatrix().ToSKMatrix().ToMatrix3X3();
+            var cachedTexture = Document.SceneTextures[ViewportId];
+            Matrix3X3 matrixDiff = SolveMatrixDiff(matrix, cachedTexture);
+            var target = cachedTexture.DrawingSurface;
+
             if (tex.Size == (VecI)RealDimensions)
             {
                 saved = texture.Canvas.Save();
                 texture.Canvas.ClipRect(bounds);
-                texture.Canvas.SetMatrix(Matrix3X3.Identity);
+                texture.Canvas.SetMatrix(matrixDiff);
                 hasSaved = true;
             }
             else
             {
                 float scale = CalculateResolutionScale();
                 saved = texture.Canvas.Save();
+                texture.Canvas.SetMatrix(matrixDiff);
                 texture.Canvas.Scale(scale);
                 hasSaved = true;
             }
 
-            texture.Canvas.DrawSurface(Document.SceneTextures[ViewportId].DrawingSurface, 0, 0);
+
+            texture.Canvas.Save();
+
+            texture.Canvas.DrawSurface(target, 0, 0);
             if (hasSaved)
             {
                 texture.Canvas.RestoreToCount(saved);
             }
-            /*SceneRenderer.RenderScene(renderTexture.DrawingSurface, CalculateResolution(), CalculateSampling(),
-                renderOutput);*/
         }
         catch (Exception e)
         {
@@ -860,6 +868,16 @@ internal class Scene : Zoombox.Zoombox, ICustomHitTest
         base.OnPropertyChanged(change);
     }
 
+
+    private Matrix3X3 SolveMatrixDiff(Matrix3X3 matrix, Texture cachedTexture)
+    {
+        Matrix3X3 old = cachedTexture.DrawingSurface.Canvas.TotalMatrix;
+        Matrix3X3 current = matrix;
+
+        Matrix3X3 solveMatrixDiff = current.Concat(old.Invert());
+        return solveMatrixDiff;
+    }
+
     private async Task<(bool success, string info)> DoInitialize(Compositor compositor,
         CompositionDrawingSurface surface)
     {