فهرست منبع

Some more progress

Krzysztof Krysiński 3 هفته پیش
والد
کامیت
ac86d1e720

+ 27 - 20
src/PixiEditor.ChangeableDocument/Changeables/Graph/NodeGraph.cs

@@ -8,7 +8,7 @@ namespace PixiEditor.ChangeableDocument.Changeables.Graph;
 public class NodeGraph : IReadOnlyNodeGraph
 {
     private ImmutableList<IReadOnlyNode>? cachedExecutionList;
-    
+
     private readonly List<Node> _nodes = new();
     public IReadOnlyCollection<Node> Nodes => _nodes;
     public IReadOnlyDictionary<Guid, Node> NodeLookup => nodeLookup;
@@ -27,7 +27,7 @@ public class NodeGraph : IReadOnlyNodeGraph
         {
             return;
         }
-        
+
         node.ConnectionsChanged += ResetCache;
         _nodes.Add(node);
         nodeLookup[node.Id] = node;
@@ -86,8 +86,10 @@ public class NodeGraph : IReadOnlyNodeGraph
                     var connectedNode = input.Connection.Node;
                     if (nodeMapping.TryGetValue(connectedNode as Node, out var clonedConnectedNode))
                     {
-                        var clonedOutput = clonedConnectedNode.OutputProperties.FirstOrDefault(o => o.InternalPropertyName == input.Connection.InternalPropertyName);
-                        var clonedInput = clonedNode.InputProperties.FirstOrDefault(i => i.InternalPropertyName == input.InternalPropertyName);
+                        var clonedOutput = clonedConnectedNode.OutputProperties.FirstOrDefault(o =>
+                            o.InternalPropertyName == input.Connection.InternalPropertyName);
+                        var clonedInput = clonedNode.InputProperties.FirstOrDefault(i =>
+                            i.InternalPropertyName == input.InternalPropertyName);
                         if (clonedOutput != null && clonedInput != null)
                         {
                             clonedOutput.ConnectTo(clonedInput);
@@ -125,44 +127,49 @@ public class NodeGraph : IReadOnlyNodeGraph
 
     public bool TryTraverse(Action<IReadOnlyNode> action)
     {
-        if(OutputNode == null) return false;
-        
+        if (OutputNode == null) return false;
+
         var queue = CalculateExecutionQueueInternal(OutputNode);
-        
+
         foreach (var node in queue)
         {
             action(node);
         }
-        
+
         return true;
     }
 
     bool isexecuting = false;
+
     public void Execute(RenderContext context)
     {
         if (isexecuting) return;
         isexecuting = true;
         if (OutputNode == null) return;
-        if(!CanExecute()) return;
+        if (!CanExecute()) return;
 
         var queue = CalculateExecutionQueueInternal(OutputNode);
-        
+
         foreach (var node in queue)
         {
-            if (node is Node typedNode)
-            {
-                if(typedNode.IsDisposed) continue;
-                
-                typedNode.ExecuteInternal(context);
-            }
-            else
+            lock (node)
             {
-                node.Execute(context);
+                if (node is Node typedNode)
+                {
+                    if (typedNode.IsDisposed) continue;
+
+                    typedNode.ExecuteInternal(context);
+                }
+                else
+                {
+                    node.Execute(context);
+                }
             }
         }
+
         isexecuting = false;
     }
-    
+
     private bool CanExecute()
     {
         foreach (var node in Nodes)
@@ -175,7 +182,7 @@ public class NodeGraph : IReadOnlyNodeGraph
 
         return true;
     }
-    
+
     private void ResetCache()
     {
         cachedExecutionList = null;

+ 2 - 7
src/PixiEditor/Models/DocumentModels/ActionAccumulator.cs

@@ -139,16 +139,11 @@ internal class ActionAccumulator
                     internals.Tracker,
                     optimizedChanges, refreshPreviewsRequest);
 
-                if (DrawingBackendApi.Current.IsHardwareAccelerated && !allPassthrough)
-                {
-                    canvasUpdater.UpdateGatheredChunksSync(affectedAreas,
-                        undoBoundaryPassed || viewportRefreshRequest);
-                }
-                /*else
+                if (!allPassthrough)
                 {
                     await canvasUpdater.UpdateGatheredChunks(affectedAreas,
                         undoBoundaryPassed || viewportRefreshRequest);
-                }*/
+                }
 
                 await document.SceneRenderer.RenderAsync(internals.State.Viewports);
 

+ 3 - 1
src/PixiEditor/Models/Position/ViewportInfo.cs

@@ -19,4 +19,6 @@ internal readonly record struct ViewportInfo(
     ChunkResolution Resolution,
     Guid Id,
     bool Delayed,
-    Action InvalidateVisual);
+    Action InvalidateVisual)
+{
+}

+ 3 - 2
src/PixiEditor/Models/Rendering/CanvasUpdater.cs

@@ -1,4 +1,5 @@
-using ChunkyImageLib.DataHolders;
+using Avalonia.Threading;
+using ChunkyImageLib.DataHolders;
 using ChunkyImageLib.Operations;
 using PixiEditor.ChangeableDocument.Changeables.Animations;
 using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
@@ -59,7 +60,7 @@ internal class CanvasUpdater
     public async Task UpdateGatheredChunks
         (AffectedAreasGatherer chunkGatherer, bool rerenderDelayed)
     {
-        await Task.Run(() => Render(chunkGatherer, rerenderDelayed)).ConfigureAwait(true);
+        await Dispatcher.UIThread.InvokeAsync(() => Render(chunkGatherer, rerenderDelayed), DispatcherPriority.Background);
     }
 
     /// <summary>

+ 42 - 35
src/PixiEditor/Models/Rendering/SceneRenderer.cs

@@ -1,4 +1,5 @@
-using ChunkyImageLib.DataHolders;
+using Avalonia.Threading;
+using ChunkyImageLib.DataHolders;
 using Drawie.Backend.Core;
 using Drawie.Backend.Core.ColorsImpl;
 using Drawie.Backend.Core.Numerics;
@@ -31,6 +32,8 @@ internal class SceneRenderer : IDisposable
 
     private ChunkResolution? lastResolution;
 
+    private TextureCache textureCache = new();
+
     public SceneRenderer(IReadOnlyDocument trackerDocument, IDocument documentViewModel,
         PreviewRenderer previewRenderer)
     {
@@ -39,32 +42,35 @@ internal class SceneRenderer : IDisposable
         this.previewRenderer = previewRenderer;
     }
 
-
     public async Task RenderAsync(Dictionary<Guid, ViewportInfo> stateViewports)
     {
-        await Task.Run(() =>
+        await Dispatcher.UIThread.InvokeAsync(() =>
         {
             foreach (var viewport in stateViewports)
             {
                 if (viewport.Value.RealDimensions.ShortestAxis <= 0) continue;
 
-                var rendered = RenderScene((VecI)viewport.Value.RealDimensions, viewport.Value.Transform,
+                var rendered = RenderScene(
+                    viewport.Key,
+                    (VecI)viewport.Value.RealDimensions,
+                    viewport.Value.Transform,
                     viewport.Value.Resolution,
                     viewport.Value.Sampling,
                     viewport.Value.RenderOutput.Equals("DEFAULT", StringComparison.InvariantCultureIgnoreCase)
                         ? null
                         : viewport.Value.RenderOutput);
-                if (DocumentViewModel.SceneTextures.TryGetValue(viewport.Key, out var texture))
+                if (DocumentViewModel.SceneTextures.TryGetValue(viewport.Key, out var texture) && texture != rendered)
                 {
                     texture.Dispose();
                 }
 
                 DocumentViewModel.SceneTextures[viewport.Key] = rendered;
             }
-        });
+        }, DispatcherPriority.Background);
     }
 
-    public Texture? RenderScene(VecI renderTargetSize, Matrix3X3 targetMatrix, ChunkResolution resolution,
+    public Texture? RenderScene(Guid viewportId, VecI renderTargetSize, Matrix3X3 targetMatrix,
+        ChunkResolution resolution,
         SamplingOptions samplingOptions,
         string? targetOutput = null)
     {
@@ -75,22 +81,23 @@ internal class SceneRenderer : IDisposable
         string adjustedTargetOutput = targetOutput ?? "";
 
         IReadOnlyNodeGraph finalGraph = RenderingUtils.SolveFinalNodeGraph(targetOutput, Document);
-        //bool shouldRerender = ShouldRerender(target, resolution, adjustedTargetOutput, finalGraph);
+        bool shouldRerender =
+            ShouldRerender(renderTargetSize, targetMatrix, resolution, viewportId, finalGraph);
 
         // TODO: Check if clipping to visible area improves performance on full resolution
         // Meaning zoomed big textures
 
-        return RenderGraph(renderTargetSize, targetMatrix, resolution, samplingOptions, targetOutput, finalGraph);
-        //previewRenderer.RenderPreviews(DocumentViewModel.AnimationHandler.ActiveFrameTime);
-        /*
         if (shouldRerender)
         {
-            return;
+            return RenderGraph(renderTargetSize, targetMatrix, resolution, samplingOptions, targetOutput, finalGraph);
         }
-        */
+        //previewRenderer.RenderPreviews(DocumentViewModel.AnimationHandler.ActiveFrameTime);
+
+        var cachedTexture = DocumentViewModel.SceneTextures[viewportId];
 
-        /*var cachedTexture = DocumentViewModel.SceneTextures[adjustedTargetOutput];
-        Matrix3X3 matrixDiff = SolveMatrixDiff(target, cachedTexture);
+        return cachedTexture;
+        Matrix3X3 matrixDiff = SolveMatrixDiff(targetMatrix, cachedTexture);
+        var target = cachedTexture.DrawingSurface;
         int saved = target.Canvas.Save();
         target.Canvas.SetMatrix(matrixDiff);
         if (samplingOptions == SamplingOptions.Default)
@@ -103,7 +110,9 @@ internal class SceneRenderer : IDisposable
             target.Canvas.DrawImage(img, 0, 0, samplingOptions);
         }
 
-        target.Canvas.RestoreToCount(saved);*/
+        target.Canvas.RestoreToCount(saved);
+
+        return cachedTexture;
     }
 
     private Texture RenderGraph(VecI renderTargetSize, Matrix3X3 targetMatrix, ChunkResolution resolution,
@@ -120,7 +129,7 @@ internal class SceneRenderer : IDisposable
         {
             finalSize = (VecI)(finalSize * resolution.Multiplier());
 
-            renderTexture = Texture.ForProcessing(finalSize, Document.ProcessingColorSpace);
+            renderTexture = textureCache.RequestTexture(0, finalSize, Document.ProcessingColorSpace);
             renderTarget = renderTexture.DrawingSurface;
             renderTarget.Canvas.Save();
             renderTexture.DrawingSurface.Canvas.Save();
@@ -131,7 +140,7 @@ internal class SceneRenderer : IDisposable
         }
         else
         {
-            renderTexture = Texture.ForProcessing(renderTargetSize, Document.ProcessingColorSpace);
+            renderTexture = textureCache.RequestTexture(0, renderTargetSize, Document.ProcessingColorSpace);
 
             renderTarget = renderTexture.DrawingSurface;
 
@@ -199,16 +208,15 @@ internal class SceneRenderer : IDisposable
         return !HighResRendering || !HighDpiRenderNodePresent(finalGraph);
     }
 
-    private bool ShouldRerender(DrawingSurface target, ChunkResolution resolution, string? targetOutput,
+    private bool ShouldRerender(VecI targetSize, Matrix3X3 matrix, ChunkResolution resolution,
+        Guid viewporId,
         IReadOnlyNodeGraph finalGraph)
     {
-        /*
-        if (!cachedTextures.TryGetValue(targetOutput ?? "", out var cachedTexture) || cachedTexture == null ||
+        if (!DocumentViewModel.SceneTextures.TryGetValue(viewporId, out var cachedTexture) || cachedTexture == null ||
             cachedTexture.IsDisposed)
         {
             return true;
         }
-        */
 
         if (lastResolution != resolution)
         {
@@ -225,14 +233,12 @@ internal class SceneRenderer : IDisposable
         bool renderInDocumentSize = RenderInOutputSize(finalGraph);
         VecI compareSize = renderInDocumentSize
             ? (VecI)(Document.Size * resolution.Multiplier())
-            : target.DeviceClipBounds.Size;
+            : targetSize;
 
-        /*
-        if (cachedTexture.DrawingSurface.DeviceClipBounds.Size != compareSize)
+        if (cachedTexture.Size != compareSize)
         {
             return true;
         }
-        */
 
         if (lastFrameTime.Frame != DocumentViewModel.AnimationHandler.ActiveFrameTime.Frame)
         {
@@ -257,16 +263,17 @@ internal class SceneRenderer : IDisposable
             }
         }
 
-        /*if (!renderInDocumentSize)
+        if (!renderInDocumentSize)
         {
-            double lengthDiff = target.LocalClipBounds.Size.Length -
-                                cachedTexture.DrawingSurface.LocalClipBounds.Size.Length;
-            if (lengthDiff > 0 || target.LocalClipBounds.Pos != cachedTexture.DrawingSurface.LocalClipBounds.Pos ||
-                lengthDiff < -ZoomDiffToRerender)
+            if (!renderInDocumentSize)
             {
-                return true;
+                double zoomDiff = Math.Abs(matrix.ScaleX - cachedTexture.DrawingSurface.Canvas.TotalMatrix.ScaleX);
+                if (zoomDiff != 0)
+                {
+                    return true;
+                }
             }
-        }*/
+        }
 
         int currentGraphCacheHash = finalGraph.GetCacheHash();
         if (lastGraphCacheHash != currentGraphCacheHash)
@@ -278,10 +285,10 @@ internal class SceneRenderer : IDisposable
         return false;
     }
 
-    private Matrix3X3 SolveMatrixDiff(DrawingSurface target, Texture cachedTexture)
+    private Matrix3X3 SolveMatrixDiff(Matrix3X3 matrix, Texture cachedTexture)
     {
         Matrix3X3 old = cachedTexture.DrawingSurface.Canvas.TotalMatrix;
-        Matrix3X3 current = target.Canvas.TotalMatrix;
+        Matrix3X3 current = matrix;
 
         Matrix3X3 solveMatrixDiff = current.Concat(old.Invert());
         return solveMatrixDiff;

+ 1 - 1
src/PixiEditor/Views/Main/ViewportControls/FixedViewport.axaml.cs

@@ -126,7 +126,7 @@ internal partial class FixedViewport : UserControl, INotifyPropertyChanged
             docSize / 2,
             new VecD(mainImage.Bounds.Width, mainImage.Bounds.Height),
             Matrix3X3.Identity,
-            "Default",
+            "DEFAULT",
             SamplingOptions.Bilinear,
             docSize,
             CalculateResolution(),

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

@@ -514,7 +514,7 @@ internal partial class Viewport : UserControl, INotifyPropertyChanged
 
     private ViewportInfo GetLocation()
     {
-        return new(AngleRadians, Center, RealDimensions, Scene.CalculateTransformMatrix().ToSKMatrix().ToMatrix3X3(), ViewportRenderOutput, Scene.CalculateSampling(), Dimensions, CalculateResolution(), GuidValue, Delayed,
+        return new(AngleRadians, Center, RealDimensions, Scene.CalculateTransformMatrix().ToSKMatrix().ToMatrix3X3(), ViewportRenderOutput, Scene.CalculateSampling(), Dimensions,CalculateResolution(), GuidValue, Delayed,
             ForceRefreshFinalImage);
     }
 

+ 23 - 15
src/PixiEditor/Views/Rendering/Scene.cs

@@ -323,61 +323,69 @@ internal class Scene : Zoombox.Zoombox, ICustomHitTest
         QueueNextFrame();
     }
 
-    public void Draw(DrawingSurface renderTexture)
+    public void Draw(DrawingSurface texture)
     {
         if (Document == null || SceneRenderer == null) return;
 
-        renderTexture.Canvas.Save();
+        texture.Canvas.Save();
         var matrix = CalculateTransformMatrix();
 
-        renderTexture.Canvas.SetMatrix(matrix.ToSKMatrix().ToMatrix3X3());
+        texture.Canvas.SetMatrix(matrix.ToSKMatrix().ToMatrix3X3());
 
         VecI outputSize = FindOutputSize();
 
         RectD dirtyBounds = new RectD(0, 0, outputSize.X, outputSize.Y);
-        RenderScene(dirtyBounds);
+        RenderScene(texture, dirtyBounds);
 
-        renderTexture.Canvas.Restore();
+        texture.Canvas.Restore();
     }
 
-    private void RenderScene(RectD bounds)
+    private void RenderScene(DrawingSurface texture, RectD bounds)
     {
         var renderOutput = RenderOutput == "DEFAULT" ? null : RenderOutput;
-        DrawCheckerboard(renderTexture.DrawingSurface, bounds);
-        DrawOverlays(renderTexture.DrawingSurface, bounds, OverlayRenderSorting.Background);
+        DrawCheckerboard(texture, bounds);
+        DrawOverlays(texture, bounds, OverlayRenderSorting.Background);
         try
         {
             var tex = Document.SceneTextures[ViewportId];
+
             bool hasSaved = false;
             int saved = -1;
             if (tex.Size == (VecI)RealDimensions)
             {
-                saved = renderTexture.DrawingSurface.Canvas.Save();
-                renderTexture.DrawingSurface.Canvas.SetMatrix(Matrix3X3.Identity);
+                saved = texture.Canvas.Save();
+                texture.Canvas.SetMatrix(Matrix3X3.Identity);
+                hasSaved = true;
+            }
+            else
+            {
+                float scale = CalculateResolutionScale();
+                saved = texture.Canvas.Save();
+                texture.Canvas.Scale(scale);
                 hasSaved = true;
             }
 
-            renderTexture.DrawingSurface.Canvas.DrawSurface(Document.SceneTextures[ViewportId].DrawingSurface, 0, 0);
+            texture.Canvas.DrawSurface(Document.SceneTextures[ViewportId].DrawingSurface, 0, 0);
             if (hasSaved)
             {
-                renderTexture.DrawingSurface.Canvas.RestoreToCount(saved);
+                texture.Canvas.RestoreToCount(saved);
             }
             /*SceneRenderer.RenderScene(renderTexture.DrawingSurface, CalculateResolution(), CalculateSampling(),
                 renderOutput);*/
         }
         catch (Exception e)
         {
-            renderTexture.DrawingSurface.Canvas.Clear();
+            texture.Canvas.Clear();
             using Paint paint = new Paint { Color = Colors.White, IsAntiAliased = true };
 
             using Font defaultSizedFont = Font.CreateDefault();
             defaultSizedFont.Size = 24;
 
-            renderTexture.DrawingSurface.Canvas.DrawText(new LocalizedString("ERROR_GRAPH"), renderTexture.Size / 2f,
+            texture.Canvas.DrawText(new LocalizedString("ERROR_GRAPH"), renderTexture.Size / 2f,
                 TextAlign.Center, defaultSizedFont, paint);
         }
 
-        DrawOverlays(renderTexture.DrawingSurface, bounds, OverlayRenderSorting.Foreground);
+        DrawOverlays(texture, bounds, OverlayRenderSorting.Foreground);
     }
 
     private void DrawCheckerboard(DrawingSurface surface, RectD dirtyBounds)