2
0
Эх сурвалжийг харах

Some async rendering works

Krzysztof Krysiński 3 долоо хоног өмнө
parent
commit
0c74fea2b7

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

@@ -150,6 +150,8 @@ internal class ActionAccumulator
                         undoBoundaryPassed || viewportRefreshRequest);
                 }*/
 
+                await document.SceneRenderer.RenderAsync(internals.State.Viewports);
+
                 bool previewsDisabled = PixiEditorSettings.Performance.DisablePreviews.Value;
 
                 if (!previewsDisabled)

+ 3 - 0
src/PixiEditor/Models/Handlers/IDocument.cs

@@ -52,6 +52,9 @@ internal interface IDocument : IHandler, Extensions.CommonApi.Documents.IDocumen
     public IReadOnlyCollection<Guid> SelectedMembers { get; }
     public PreviewPainter? MiniPreviewPainter { get; set; }
     public PreviewRenderer PreviewRenderer { get; }
+    public Dictionary<Guid, Texture> SceneTextures { get; }
+    public Texture DocumentTexture { get; }
+    public SceneRenderer SceneRenderer { get; }
     public void RemoveSoftSelectedMember(IStructureMemberHandler member);
     public void ClearSoftSelectedMembers();
     public void AddSoftSelectedMember(IStructureMemberHandler member);

+ 4 - 0
src/PixiEditor/Models/Position/ViewportInfo.cs

@@ -1,5 +1,6 @@
 using ChunkyImageLib.DataHolders;
 using Drawie.Backend.Core.Numerics;
+using Drawie.Backend.Core.Surfaces;
 using Drawie.Numerics;
 
 namespace PixiEditor.Models.Position;
@@ -11,6 +12,9 @@ internal readonly record struct ViewportInfo(
     double Angle,
     VecD Center,
     VecD RealDimensions,
+    Matrix3X3 Transform,
+    string RenderOutput,
+    SamplingOptions Sampling,
     VecD Dimensions,
     ChunkResolution Resolution,
     Guid Id,

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

@@ -1,5 +1,6 @@
 using ChunkyImageLib.DataHolders;
 using Drawie.Backend.Core;
+using Drawie.Backend.Core.ColorsImpl;
 using Drawie.Backend.Core.Numerics;
 using PixiEditor.ChangeableDocument.Changeables.Interfaces;
 using PixiEditor.ChangeableDocument.Rendering;
@@ -11,6 +12,7 @@ using PixiEditor.ChangeableDocument.Changeables.Graph.Interfaces;
 using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
 using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes.Workspace;
 using PixiEditor.Models.Handlers;
+using PixiEditor.Models.Position;
 
 namespace PixiEditor.Models.Rendering;
 
@@ -21,7 +23,6 @@ internal class SceneRenderer : IDisposable
     public IDocument DocumentViewModel { get; }
     public bool HighResRendering { get; set; } = true;
 
-    private Dictionary<string, Texture> cachedTextures = new();
     private bool lastHighResRendering = true;
     private int lastGraphCacheHash = -1;
     private KeyFrameTime lastFrameTime;
@@ -30,13 +31,38 @@ internal class SceneRenderer : IDisposable
 
     private ChunkResolution? lastResolution;
 
-    public SceneRenderer(IReadOnlyDocument trackerDocument, IDocument documentViewModel, PreviewRenderer previewRenderer)
+    public SceneRenderer(IReadOnlyDocument trackerDocument, IDocument documentViewModel,
+        PreviewRenderer previewRenderer)
     {
         Document = trackerDocument;
         DocumentViewModel = documentViewModel;
         this.previewRenderer = previewRenderer;
     }
 
+
+    public async Task RenderAsync(Dictionary<Guid, ViewportInfo> stateViewports)
+    {
+        await Task.Run(() =>
+        {
+            foreach (var viewport in stateViewports)
+            {
+                if (viewport.Value.RealDimensions.ShortestAxis <= 0) continue;
+
+                if (!DocumentViewModel.SceneTextures.TryGetValue(viewport.Key, out var texture)
+                    || texture.Size != (VecI)viewport.Value.RealDimensions)
+                {
+                    texture?.Dispose();
+                    texture = Texture.ForProcessing((VecI)viewport.Value.RealDimensions,
+                        Document.ProcessingColorSpace);
+                }
+
+                RenderScene(texture.DrawingSurface, viewport.Value.Resolution,
+                    viewport.Value.Sampling, viewport.Value.RenderOutput == "DEFAULT" ? null : viewport.Value.RenderOutput);
+                DocumentViewModel.SceneTextures[viewport.Key] = texture;
+            }
+        }).ConfigureAwait(false);
+    }
+
     public void RenderScene(DrawingSurface target, ChunkResolution resolution, SamplingOptions samplingOptions,
         string? targetOutput = null)
     {
@@ -52,20 +78,14 @@ internal class SceneRenderer : IDisposable
         // TODO: Check if clipping to visible area improves performance on full resolution
         // Meaning zoomed big textures
 
+        using var rendered = RenderGraph(target, resolution, samplingOptions, targetOutput, finalGraph);
         if (shouldRerender)
         {
-            if (cachedTextures.ContainsKey(adjustedTargetOutput))
-            {
-                cachedTextures[adjustedTargetOutput]?.Dispose();
-            }
-
-            var rendered = RenderGraph(target, resolution, samplingOptions, targetOutput, finalGraph);
             //previewRenderer.RenderPreviews(DocumentViewModel.AnimationHandler.ActiveFrameTime);
-            cachedTextures[adjustedTargetOutput] = rendered;
             return;
         }
 
-        var cachedTexture = cachedTextures[adjustedTargetOutput];
+        /*var cachedTexture = DocumentViewModel.SceneTextures[adjustedTargetOutput];
         Matrix3X3 matrixDiff = SolveMatrixDiff(target, cachedTexture);
         int saved = target.Canvas.Save();
         target.Canvas.SetMatrix(matrixDiff);
@@ -79,7 +99,7 @@ internal class SceneRenderer : IDisposable
             target.Canvas.DrawImage(img, 0, 0, samplingOptions);
         }
 
-        target.Canvas.RestoreToCount(saved);
+        target.Canvas.RestoreToCount(saved);*/
     }
 
     private Texture RenderGraph(DrawingSurface target, ChunkResolution resolution, SamplingOptions samplingOptions,
@@ -125,6 +145,7 @@ internal class SceneRenderer : IDisposable
 
         if (renderTexture != null)
         {
+            target.Canvas.Clear();
             if (samplingOptions == SamplingOptions.Default)
             {
                 target.Canvas.DrawSurface(renderTexture.DrawingSurface, 0, 0);
@@ -173,11 +194,13 @@ internal class SceneRenderer : IDisposable
     private bool ShouldRerender(DrawingSurface target, ChunkResolution resolution, string? targetOutput,
         IReadOnlyNodeGraph finalGraph)
     {
+        /*
         if (!cachedTextures.TryGetValue(targetOutput ?? "", out var cachedTexture) || cachedTexture == null ||
             cachedTexture.IsDisposed)
         {
             return true;
         }
+        */
 
         if (lastResolution != resolution)
         {
@@ -196,10 +219,12 @@ internal class SceneRenderer : IDisposable
             ? (VecI)(Document.Size * resolution.Multiplier())
             : target.DeviceClipBounds.Size;
 
+        /*
         if (cachedTexture.DrawingSurface.DeviceClipBounds.Size != compareSize)
         {
             return true;
         }
+        */
 
         if (lastFrameTime.Frame != DocumentViewModel.AnimationHandler.ActiveFrameTime.Frame)
         {
@@ -224,7 +249,7 @@ internal class SceneRenderer : IDisposable
             }
         }
 
-        if (!renderInDocumentSize)
+        /*if (!renderInDocumentSize)
         {
             double lengthDiff = target.LocalClipBounds.Size.Length -
                                 cachedTexture.DrawingSurface.LocalClipBounds.Size.Length;
@@ -233,7 +258,7 @@ internal class SceneRenderer : IDisposable
             {
                 return true;
             }
-        }
+        }*/
 
         int currentGraphCacheHash = finalGraph.GetCacheHash();
         if (lastGraphCacheHash != currentGraphCacheHash)
@@ -269,7 +294,8 @@ internal class SceneRenderer : IDisposable
         return highDpiRenderNodePresent;
     }
 
-    private void RenderOnionSkin(DrawingSurface target, ChunkResolution resolution, SamplingOptions sampling, string? targetOutput)
+    private void RenderOnionSkin(DrawingSurface target, ChunkResolution resolution, SamplingOptions sampling,
+        string? targetOutput)
     {
         var animationData = Document.AnimationData;
         if (!DocumentViewModel.AnimationHandler.OnionSkinningEnabledBindable)
@@ -320,9 +346,9 @@ internal class SceneRenderer : IDisposable
 
     public void Dispose()
     {
-        foreach (var texture in cachedTextures)
+        /*foreach (var texture in cachedTextures)
         {
             texture.Value?.Dispose();
-        }
+        }*/
     }
 }

+ 4 - 0
src/PixiEditor/ViewModels/Document/DocumentViewModel.cs

@@ -207,6 +207,10 @@ internal partial class DocumentViewModel : PixiObservableObject, IDocument
         }
     }
 
+    public Dictionary<Guid, Texture> SceneTextures { get; } = new();
+    public Texture DocumentTexture { get; set; }
+
+
     private VectorPath selectionPath = new VectorPath();
     public VectorPath SelectionPathBindable => selectionPath;
     public ObservableCollection<PaletteColor> Swatches { get; set; } = new();

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

@@ -7,6 +7,8 @@ using Avalonia.Media;
 using Avalonia.Threading;
 using ChunkyImageLib.DataHolders;
 using Drawie.Backend.Core;
+using Drawie.Backend.Core.Numerics;
+using Drawie.Backend.Core.Surfaces;
 using PixiEditor.Models.DocumentModels;
 using PixiEditor.Models.Position;
 using Drawie.Numerics;
@@ -123,6 +125,9 @@ internal partial class FixedViewport : UserControl, INotifyPropertyChanged
             0,
             docSize / 2,
             new VecD(mainImage.Bounds.Width, mainImage.Bounds.Height),
+            Matrix3X3.Identity,
+            "Default",
+            SamplingOptions.Bilinear,
             docSize,
             CalculateResolution(),
             GuidValue,

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

@@ -253,6 +253,7 @@
             FadeOut="{Binding Source={viewModels:ToolVM ColorPickerToolViewModel}, Path=PickOnlyFromReferenceLayer, Mode=OneWay}"
             DefaultCursor="{Binding Source={viewModels:MainVM}, Path=ToolsSubViewModel.ToolCursor, Mode=OneWay}"
             RenderOutput="{Binding ViewportRenderOutput, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=viewportControls:Viewport}, Mode=OneWay}"
+            ViewportId="{Binding GuidValue, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=viewportControls:Viewport}, Mode=OneWay}"
             AutoBackgroundScale="{Binding AutoBackgroundScale, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=viewportControls:Viewport}, Mode=OneWay}"
             CustomBackgroundScaleX="{Binding CustomBackgroundScaleX, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=viewportControls:Viewport}, Mode=OneWay}"
             CustomBackgroundScaleY="{Binding CustomBackgroundScaleY, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=viewportControls:Viewport}, Mode=OneWay}"

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

@@ -5,6 +5,7 @@ using Avalonia;
 using Avalonia.Controls;
 using Avalonia.Input;
 using Avalonia.Interactivity;
+using Avalonia.Skia;
 using Avalonia.VisualTree;
 using ChunkyImageLib;
 using ChunkyImageLib.DataHolders;
@@ -20,6 +21,7 @@ using PixiEditor.Models.Controllers.InputDevice;
 using PixiEditor.Models.DocumentModels;
 using PixiEditor.Models.Position;
 using Drawie.Numerics;
+using Drawie.Skia;
 using PixiEditor.Extensions.CommonApi.UserPreferences.Settings.PixiEditor;
 using PixiEditor.UI.Common.Behaviors;
 using PixiEditor.ViewModels.Document;
@@ -512,7 +514,7 @@ internal partial class Viewport : UserControl, INotifyPropertyChanged
 
     private ViewportInfo GetLocation()
     {
-        return new(AngleRadians, Center, RealDimensions, Dimensions, CalculateResolution(), GuidValue, Delayed,
+        return new(AngleRadians, Center, RealDimensions, Scene.CalculateTransformMatrix().ToSKMatrix().ToMatrix3X3(), ViewportRenderOutput, Scene.CalculateSampling(), Dimensions, CalculateResolution(), GuidValue, Delayed,
             ForceRefreshFinalImage);
     }
 

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

@@ -157,6 +157,15 @@ internal class Scene : Zoombox.Zoombox, ICustomHitTest
         set => SetValue(MaxBilinearSamplingSizeProperty, value);
     }
 
+    public static readonly StyledProperty<Guid> ViewportIdProperty = AvaloniaProperty.Register<Scene, Guid>(
+        nameof(ViewportId));
+
+    public Guid ViewportId
+    {
+        get => GetValue(ViewportIdProperty);
+        set => SetValue(ViewportIdProperty, value);
+    }
+
     private Overlay? capturedOverlay;
 
     private List<Overlay> mouseOverOverlays = new();
@@ -239,8 +248,11 @@ internal class Scene : Zoombox.Zoombox, ICustomHitTest
         };
     }
 
-    private SamplingOptions CalculateSampling()
+    internal SamplingOptions CalculateSampling()
     {
+        if (Document == null)
+            return SamplingOptions.Default;
+
         if (Document.SizeBindable.LongestAxis > MaxBilinearSamplingSize)
         {
             return SamplingOptions.Default;
@@ -335,8 +347,9 @@ internal class Scene : Zoombox.Zoombox, ICustomHitTest
         DrawOverlays(renderTexture.DrawingSurface, bounds, OverlayRenderSorting.Background);
         try
         {
-            SceneRenderer.RenderScene(renderTexture.DrawingSurface, CalculateResolution(), CalculateSampling(),
-                renderOutput);
+            renderTexture.DrawingSurface.Canvas.DrawSurface(Document.SceneTextures[ViewportId].DrawingSurface, 0, 0);
+            /*SceneRenderer.RenderScene(renderTexture.DrawingSurface, CalculateResolution(), CalculateSampling(),
+                renderOutput);*/
         }
         catch (Exception e)
         {
@@ -714,7 +727,7 @@ internal class Scene : Zoombox.Zoombox, ICustomHitTest
         return new VecD(transformed.X, transformed.Y);
     }
 
-    private Matrix CalculateTransformMatrix()
+    internal Matrix CalculateTransformMatrix()
     {
         Matrix transform = Matrix.Identity;
         transform = transform.Append(Matrix.CreateRotation((float)AngleRadians));