Browse Source

Fixed document size bug, func inputs in shader uniforms

Krzysztof Krysiński 5 months ago
parent
commit
29e2ea33a7

+ 1 - 1
src/Drawie

@@ -1 +1 @@
-Subproject commit e31b43ced0fd8e89707ff2226de7f7b886f66b4a
+Subproject commit f55664535230db4f22341724f7b5016af89947f2

+ 36 - 12
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/ShaderNode.cs

@@ -1,6 +1,7 @@
 using Drawie.Backend.Core;
 using Drawie.Backend.Core.ColorsImpl;
 using Drawie.Backend.Core.Shaders;
+using Drawie.Backend.Core.Shaders.Generation;
 using Drawie.Backend.Core.Surfaces;
 using Drawie.Backend.Core.Surfaces.PaintImpl;
 using Drawie.Numerics;
@@ -23,7 +24,7 @@ public class ShaderNode : RenderNode, IRenderInput, ICustomShaderNode
     private VecI lastDocumentSize;
     private List<Shader> lastCustomImageShaders = new();
 
-    private Dictionary<string, InputProperty> uniformInputs = new();
+    private Dictionary<string, (InputProperty prop, UniformValueType valueType)> uniformInputs = new();
 
     protected override bool ExecuteOnlyOnCacheChange => true;
     protected override CacheTriggerFlags CacheTrigger => CacheTriggerFlags.All;
@@ -151,7 +152,7 @@ public class ShaderNode : RenderNode, IRenderInput, ICustomShaderNode
         {
             foreach (var input in uniformInputs)
             {
-                RemoveInputProperty(input.Value);
+                RemoveInputProperty(input.Value.prop);
             }
 
             uniformInputs.Clear();
@@ -163,7 +164,7 @@ public class ShaderNode : RenderNode, IRenderInput, ICustomShaderNode
         var nonExistingUniforms = uniformInputs.Keys.Where(x => uniforms.All(y => y.Name != x)).ToList();
         foreach (var nonExistingUniform in nonExistingUniforms)
         {
-            RemoveInputProperty(uniformInputs[nonExistingUniform]);
+            RemoveInputProperty(uniformInputs[nonExistingUniform].prop);
             uniformInputs.Remove(nonExistingUniform);
         }
 
@@ -174,6 +175,12 @@ public class ShaderNode : RenderNode, IRenderInput, ICustomShaderNode
                 continue;
             }
 
+            if (uniformInputs.ContainsKey(uniform.Name) && uniformInputs[uniform.Name].valueType != uniform.DataType)
+            {
+                RemoveInputProperty(uniformInputs[uniform.Name].prop);
+                uniformInputs.Remove(uniform.Name);
+            }
+
             if (!uniformInputs.ContainsKey(uniform.Name))
             {
                 InputProperty input;
@@ -185,17 +192,20 @@ public class ShaderNode : RenderNode, IRenderInput, ICustomShaderNode
                 {
                     input = CreateInput<Texture>(uniform.Name, uniform.Name, null);
                 }
-                //TODO
-                /*else if (uniform.DataType == UniformValueType.FloatArray)
+                else if (uniform.DataType == UniformValueType.Color)
                 {
-                    input = CreateFuncInput<Kernel>(uniform.Name, uniform.Name, null);
-                }*/
+                    input = CreateInput<Color>(uniform.Name, uniform.Name, Colors.Black);
+                }
+                else if (uniform.DataType == UniformValueType.Vector2)
+                {
+                    input = CreateInput<VecD>(uniform.Name, uniform.Name, new VecD(0, 0));
+                }
                 else
                 {
                     continue;
                 }
 
-                uniformInputs.Add(uniform.Name, input);
+                uniformInputs.Add(uniform.Name, (input, uniform.DataType));
             }
         }
     }
@@ -211,19 +221,33 @@ public class ShaderNode : RenderNode, IRenderInput, ICustomShaderNode
 
         foreach (var input in uniformInputs)
         {
-            if (input.Value.Value is float floatValue)
+            object value = input.Value.prop.Value;
+            if (input.Value.prop.Value is ShaderExpressionVariable expressionVariable)
+            {
+                value = expressionVariable.GetConstant();
+            }
+
+            if (value is float floatValue)
             {
                 uniforms.Add(input.Key, new Uniform(input.Key, floatValue));
             }
-            else if (input.Value.Value is double doubleValue)
+            else if (value is double doubleValue)
             {
                 uniforms.Add(input.Key, new Uniform(input.Key, (float)doubleValue));
             }
-            else if (input.Value.Value is int intValue)
+            else if (value is int intValue)
             {
                 uniforms.Add(input.Key, new Uniform(input.Key, intValue));
             }
-            else if (input.Value.Value is Texture texture)
+            else if (value is VecD vector)
+            {
+                uniforms.Add(input.Key, new Uniform(input.Key, vector));
+            }
+            else if (value is Color color)
+            {
+                uniforms.Add(input.Key, new Uniform(input.Key, color));
+            }
+            else if (value is Texture texture)
             {
                 var snapshot = texture.DrawingSurface.Snapshot();
                 Shader snapshotShader = snapshot.ToShader();

+ 2 - 0
src/PixiEditor.ChangeableDocument/Changes/NodeGraph/UpdateProperty_Change.cs

@@ -145,6 +145,7 @@ internal class UpdatePropertyValue_Change : Change
         foreach (var input in node.InputProperties)
         {
             hash.Add(input.InternalPropertyName);
+            hash.Add(input.ValueType);
         }
 
         return hash.ToHashCode();
@@ -156,6 +157,7 @@ internal class UpdatePropertyValue_Change : Change
         foreach (var output in node.OutputProperties)
         {
             hash.Add(output.InternalPropertyName);
+            hash.Add(output.ValueType);
         }
 
         return hash.ToHashCode();

+ 12 - 2
src/PixiEditor/Views/Rendering/Scene.cs

@@ -493,7 +493,6 @@ internal class Scene : Zoombox.Zoombox, ICustomHitTest
                 ? released.InitialPressMouseButton
                 : MouseButton.None,
             ClickCount = e is PointerPressedEventArgs pressed ? pressed.ClickCount : 0,
-            
         };
     }
 
@@ -659,7 +658,7 @@ internal class Scene : Zoombox.Zoombox, ICustomHitTest
     {
         renderTexture?.Dispose();
         renderTexture = null;
-        
+
         framebuffer?.Dispose();
         framebuffer = null;
 
@@ -767,12 +766,23 @@ internal class Scene : Zoombox.Zoombox, ICustomHitTest
 
     private static void DocumentChanged(Scene scene, AvaloniaPropertyChangedEventArgs e)
     {
+        if (e.OldValue is DocumentViewModel oldDocumentViewModel)
+        {
+            oldDocumentViewModel.SizeChanged -= scene.DocumentViewModelOnSizeChanged;
+        }
+
         if (e.NewValue is DocumentViewModel documentViewModel)
         {
+            documentViewModel.SizeChanged += scene.DocumentViewModelOnSizeChanged;
             scene.ContentDimensions = documentViewModel.SizeBindable;
         }
     }
 
+    private void DocumentViewModelOnSizeChanged(object? sender, DocumentSizeChangedEventArgs e)
+    {
+        ContentDimensions = e.NewSize;
+    }
+
     private static void DefaultCursorChanged(Scene scene, AvaloniaPropertyChangedEventArgs e)
     {
         if (e.NewValue is Cursor cursor)

+ 114 - 0
tests/PixiEditor.Backend.Tests/ShaderTests.cs

@@ -0,0 +1,114 @@
+using Drawie.Backend.Core.Shaders;
+using Drawie.Skia.Implementations;
+
+namespace PixiEditor.Backend.Tests;
+
+public class ShaderTests
+{
+    [Fact]
+    public void TestThatFindUniformTypeSolvesTrivialCase()
+    {
+        string sksl = """
+                      uniform float flUniform;
+
+                      half4 main(vec2 coords)
+                      {
+                          return half4(1, 1, 1, 1);
+                      }
+
+                      """;
+        UniformValueType? valueType = SkiaShaderImplementation.FindUniformType(sksl, "flUniform");
+
+        Assert.Equal(UniformValueType.Float, valueType);
+    }
+
+    [Fact]
+    public void TestThatFindUniformTypeSolvesDoesntGetFooledByComment()
+    {
+        string sksl = """
+                      /* uniform vec2 flUniform */uniform float flUniform;
+                      // uniform half4 vecUniform
+                      uniform vec2 vecUniform;
+
+                      half4 main(vec2 coords)
+                      {
+                          return half4(1, 1, 1, 1);
+                      }
+
+                      """;
+
+        UniformValueType? flValueType = SkiaShaderImplementation.FindUniformType(sksl, "flUniform");
+        UniformValueType? vecValueType = SkiaShaderImplementation.FindUniformType(sksl, "vecUniform");
+
+        Assert.Equal(UniformValueType.Float, flValueType);
+        Assert.Equal(UniformValueType.Vector2, vecValueType);
+    }
+
+    [Fact]
+    public void TestThatFindUniformTypeFindsUniformsInTheMiddle()
+    {
+        string sksl = """
+                      float getBlue()
+                      {
+                       return 0.5;
+                      }
+                      
+                      uniform vec2 uni1;
+                      
+                      half4 main(vec2 coords)
+                      {
+                          return half4(uni1.xy, getBlue(), 1);
+                      }
+                      
+                      """;
+
+        UniformValueType? uni1Type = SkiaShaderImplementation.FindUniformType(sksl, "uni1");
+
+        Assert.Equal(UniformValueType.Vector2, uni1Type);
+    }
+
+    [Fact]
+    public void TestThatMinifiedSkslIsParsedCorrectly()
+    {
+        string sksl = "uniform float flUniform; half4 main(vec2 coords) { return half4(1, 1, 1, 1); }";
+        UniformValueType? valueType = SkiaShaderImplementation.FindUniformType(sksl, "flUniform");
+
+        Assert.Equal(UniformValueType.Float, valueType);
+    }
+
+    [Fact]
+    public void TestThatAllTypesAreParsedCorrectly()
+    {
+        string sksl = """
+                      uniform float floatUniform;
+                      uniform vec2 vector2Uniform;
+                      uniform half4 halfArrayUniform;
+                      uniform vec4 vec4Uniform;
+                      uniform shader shaderUniform;
+                      layout(color) uniform half4 colorUniform;
+                      layout ( color ) uniform vec4 colorUniform2;
+
+                      half4 main(vec2 coords)
+                      {
+                          return half4(1, 1, 1, 1);
+                      }
+
+                      """;
+
+        UniformValueType? floatType = SkiaShaderImplementation.FindUniformType(sksl, "floatUniform");
+        UniformValueType? vector2Type = SkiaShaderImplementation.FindUniformType(sksl, "vector2Uniform");
+        UniformValueType? halfArrayType = SkiaShaderImplementation.FindUniformType(sksl, "halfArrayUniform");
+        UniformValueType? vec4Type = SkiaShaderImplementation.FindUniformType(sksl, "vec4Uniform");
+        UniformValueType? shaderType = SkiaShaderImplementation.FindUniformType(sksl, "shaderUniform");
+        UniformValueType? colorType = SkiaShaderImplementation.FindUniformType(sksl, "colorUniform");
+        UniformValueType? colorType2 = SkiaShaderImplementation.FindUniformType(sksl, "colorUniform2");
+
+        Assert.Equal(UniformValueType.Float, floatType);
+        Assert.Equal(UniformValueType.Vector2, vector2Type);
+        Assert.Equal(UniformValueType.FloatArray, halfArrayType);
+        Assert.Equal(UniformValueType.FloatArray, vec4Type);
+        Assert.Equal(UniformValueType.Shader, shaderType);
+        Assert.Equal(UniformValueType.Color, colorType);
+        Assert.Equal(UniformValueType.Color, colorType2);
+    }
+}