Browse Source

Better shader generation

flabbet 1 year ago
parent
commit
e20c347359

+ 35 - 0
src/PixiEditor.ChangeableDocument/Changeables/Graph/Context/FuncContext.cs

@@ -57,8 +57,43 @@ public class FuncContext
         return Builder.ConstructFloat1(result);
     }
 
+
+    public Int2 NewInt2(Expression first, Expression second)
+    {
+        return Builder.ConstructInt2(first, second);
+    }
+
     public Half4 NewHalf4(Expression r, Expression g, Expression b, Expression a)
     {
         return Builder.ConstructHalf4(r, g, b, a);
     }
+
+    public Float1 GetValue(FuncInputProperty<Float1> getFrom)
+    {
+        if (getFrom.Connection == null || !IsFuncType(getFrom))
+        {
+            string uniformName = $"float_{Builder.GetUniqueNameNumber()}";
+            Builder.AddUniform(uniformName, (float)getFrom.Value(this).ConstantValue);
+            return new Float1(uniformName);
+        }
+
+        return getFrom.Value(this);
+    }
+
+    public Expression GetValue(FuncInputProperty<Int1> getFrom)
+    {
+        if (getFrom.Connection == null || !IsFuncType(getFrom))
+        {
+            string uniformName = $"int_{Builder.GetUniqueNameNumber()}";
+            Builder.AddUniform(uniformName, (int)getFrom.Value(this).ConstantValue);
+            return new Expression(uniformName);
+        }
+
+        return getFrom.Value(this);
+    }
+
+    private static bool IsFuncType<T>(FuncInputProperty<T> getFrom)
+    {
+        return getFrom.Connection.ValueType.IsAssignableTo(typeof(Delegate));
+    }
 }

+ 2 - 2
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/CombineSeparate/CombineVecD.cs

@@ -29,8 +29,8 @@ public class CombineVecD : Node
     
     private Float2 GetVector(FuncContext ctx)
     {
-        var x = X.Value(ctx);
-        var y = Y.Value(ctx);
+        var x = ctx.GetValue(X); 
+        var y = ctx.GetValue(Y);
 
         return ctx.NewFloat2(x, y); 
     }

+ 10 - 9
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/CombineSeparate/CombineVecI.cs

@@ -1,6 +1,7 @@
 using PixiEditor.ChangeableDocument.Changeables.Graph.Context;
 using PixiEditor.ChangeableDocument.Rendering;
 using PixiEditor.DrawingApi.Core;
+using PixiEditor.DrawingApi.Core.Shaders.Generation.Expressions;
 using PixiEditor.Numerics;
 
 namespace PixiEditor.ChangeableDocument.Changeables.Graph.Nodes.CombineSeparate;
@@ -8,11 +9,11 @@ namespace PixiEditor.ChangeableDocument.Changeables.Graph.Nodes.CombineSeparate;
 [NodeInfo("CombineVecI")]
 public class CombineVecI : Node
 {
-    public FuncOutputProperty<VecI> Vector { get; }
+    public FuncOutputProperty<Int2> Vector { get; }
     
-    public FuncInputProperty<int> X { get; }
+    public FuncInputProperty<Int1> X { get; }
     
-    public FuncInputProperty<int> Y { get; }
+    public FuncInputProperty<Int1> Y { get; }
 
     public override string DisplayName { get; set; } = "COMBINE_VECI_NODE";
 
@@ -20,16 +21,16 @@ public class CombineVecI : Node
     {
         Vector = CreateFuncOutput(nameof(Vector), "VECTOR", GetVector);
 
-        X = CreateFuncInput(nameof(X), "X", 0);
-        Y = CreateFuncInput(nameof(Y), "Y", 0);
+        X = CreateFuncInput<Int1>(nameof(X), "X", 0);
+        Y = CreateFuncInput<Int1>(nameof(Y), "Y", 0);
     }
 
-    private VecI GetVector(FuncContext ctx)
+    private Int2 GetVector(FuncContext ctx)
     {
-        var r = X.Value(ctx);
-        var g = Y.Value(ctx);
+        var x = ctx.GetValue(X);
+        var y = ctx.GetValue(Y);
 
-        return new VecI(r, g);
+        return ctx.NewInt2(x, y);
     }
 
 

+ 4 - 1
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/MathNode.cs

@@ -56,7 +56,10 @@ public class MathNode : Node
         return context.NewFloat1(result);
     }
 
-    private (Float1 x, Float1 y) GetValues(FuncContext context) => (X.Value(context), Y.Value(context));
+    private (Float1 x, Float1 y) GetValues(FuncContext context)
+    {
+        return (context.GetValue(X), context.GetValue(Y));
+    }
 
 
     protected override Texture? OnExecute(RenderingContext context)

+ 9 - 3
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/ModifyImageRightNode.cs

@@ -86,12 +86,15 @@ public class ModifyImageRightNode : Node, IPairNodeEnd
                 }
                 else
                 {
-                    builder.Set(context.Position, Coordinate.Value(context));
+                    builder.Set(context.Position, coordinate);
                 }
             }
             else
             {
-                builder.SetConstant(context.Position, Coordinate.NonOverridenValue(FuncContext.NoContext));
+                var constCoords = Coordinate.NonOverridenValue(FuncContext.NoContext);
+                constCoords.UniformName = "constCords";
+                builder.AddUniform(constCoords.UniformName, constCoords.ConstantValue);
+                builder.Set(context.Position, constCoords);
             }
 
             if (Color.Connection != null)
@@ -100,7 +103,10 @@ public class ModifyImageRightNode : Node, IPairNodeEnd
             }
             else
             {
-                builder.ReturnConst(Color.NonOverridenValue(FuncContext.NoContext));
+                Half4 color = Color.NonOverridenValue(FuncContext.NoContext);
+                color.UniformName = "color";
+                builder.AddUniform(color.UniformName, color.ConstantValue);
+                builder.ReturnVar(color);
             }
 
             string sksl = builder.ToSkSl();

+ 13 - 0
src/PixiEditor.ChangeableDocument/Changes/NodeGraph/ConversionTable.cs

@@ -1,5 +1,7 @@
 using System.Numerics;
+using System.Reflection;
 using PixiEditor.ChangeableDocument.Changeables.Graph.Context;
+using PixiEditor.DrawingApi.Core.Shaders.Generation;
 using PixiEditor.Numerics;
 
 namespace PixiEditor.ChangeableDocument.Changes.NodeGraph;
@@ -49,6 +51,11 @@ public static class ConversionTable
         {
             try
             {
+                if (IsCrossExpression(func.Method, targetType))
+                {
+                    //TODO
+                }
+
                 var actualArg = func.DynamicInvoke(FuncContext.NoContext);
                 return TryConvert(actualArg, targetType, out result);
             }
@@ -98,6 +105,12 @@ public static class ConversionTable
 
         throw new InvalidCastException($"Cannot convert {arg.GetType()} to {targetType}");
     }
+    
+    private static bool IsCrossExpression(MethodInfo method, Type targetType)
+    {
+        return method.ReturnType.IsAssignableTo(typeof(ShaderExpressionVariable))
+               && targetType.IsAssignableTo(typeof(Delegate));
+    }
 
     private static int DoubleToInt(double d)
     {

+ 9 - 0
src/PixiEditor.DrawingApi.Core/Shaders/Generation/Expressions/Int1.cs

@@ -0,0 +1,9 @@
+namespace PixiEditor.DrawingApi.Core.Shaders.Generation.Expressions;
+
+public class Int1(string name) : ShaderExpressionVariable<int>(name)
+{
+    public override string ConstantValueString => ConstantValue.ToString(System.Globalization.CultureInfo.InvariantCulture);
+    
+    public static implicit operator Int1(int value) => new Int1("") { ConstantValue = value };
+    public static explicit operator int(Int1 value) => value.ConstantValue;
+}

+ 11 - 0
src/PixiEditor.DrawingApi.Core/Shaders/Generation/Expressions/Int2.cs

@@ -0,0 +1,11 @@
+using PixiEditor.Numerics;
+
+namespace PixiEditor.DrawingApi.Core.Shaders.Generation.Expressions;
+
+public class Int2(string name) : ShaderExpressionVariable<VecI>(name)
+{
+    public override string ConstantValueString => $"int2({ConstantValue.X}, {ConstantValue.Y})";
+    
+    public static implicit operator Int2(VecI value) => new Int2("") { ConstantValue = value };
+    public static explicit operator VecI(Int2 value) => value.ConstantValue;
+}

+ 58 - 19
src/PixiEditor.DrawingApi.Core/Shaders/Generation/ShaderBuilder.cs

@@ -1,5 +1,6 @@
 using System.Collections.Generic;
 using System.Text;
+using PixiEditor.DrawingApi.Core.ColorsImpl;
 using PixiEditor.DrawingApi.Core.Shaders.Generation.Expressions;
 using PixiEditor.Numerics;
 
@@ -10,9 +11,9 @@ public class ShaderBuilder
     public Uniforms Uniforms { get; } = new Uniforms();
 
     private StringBuilder _bodyBuilder = new StringBuilder();
-    
+
     private List<ShaderExpressionVariable> _variables = new List<ShaderExpressionVariable>();
-    
+
     private Dictionary<Texture, TextureSampler> _samplers = new Dictionary<Texture, TextureSampler>();
 
     public Shader BuildShader()
@@ -47,22 +48,22 @@ public class ShaderBuilder
         {
             return sampler;
         }
-        
-        string name = $"texture_{Uniforms.Count}";
+
+        string name = $"texture_{GetUniqueNameNumber()}";
         using var snapshot = texture.DrawingSurface.Snapshot();
         Uniforms[name] = new Uniform(name, snapshot.ToShader());
         var newSampler = new TextureSampler(name);
         _samplers[texture] = newSampler;
-        
+
         return newSampler;
     }
-    
+
     public Half4 Sample(TextureSampler texName, Float2 pos)
     {
-        string resultName = $"color_{_variables.Count}";
+        string resultName = $"color_{GetUniqueNameNumber()}";
         Half4 result = new Half4(resultName);
         _variables.Add(result);
-        _bodyBuilder.AppendLine($"half4 {resultName} = sample({texName.UniformName}, {pos.UniformName});"); 
+        _bodyBuilder.AppendLine($"half4 {resultName} = sample({texName.UniformName}, {pos.UniformName});");
         return result;
     }
 
@@ -70,56 +71,89 @@ public class ShaderBuilder
     {
         _bodyBuilder.AppendLine($"return {colorValue.UniformName};");
     }
-    
+
     public void ReturnConst(Half4 colorValue)
     {
         _bodyBuilder.AppendLine($"return {colorValue.ConstantValueString};");
     }
 
+    public void AddUniform(string uniformName, Color color)
+    {
+        Uniforms[uniformName] = new Uniform(uniformName, color);
+    }
+
+    public void AddUniform(string coords, VecD constCoordsConstantValue)
+    {
+        Uniforms[coords] = new Uniform(coords, constCoordsConstantValue);
+    }
+
+    public void AddUniform(string uniformName, float floatValue)
+    {
+        Uniforms[uniformName] = new Uniform(uniformName, floatValue);
+    }
+
     public void Set<T>(T contextPosition, T coordinateValue) where T : ShaderExpressionVariable
     {
+        if (contextPosition.UniformName == coordinateValue.UniformName)
+        {
+            return;
+        }
+
         _bodyBuilder.AppendLine($"{contextPosition.UniformName} = {coordinateValue.UniformName};");
     }
 
     public void SetConstant<T>(T contextPosition, T constantValueVar) where T : ShaderExpressionVariable
     {
-        _bodyBuilder.AppendLine($"{contextPosition.UniformName} = {constantValueVar.ConstantValueString};"); 
+        _bodyBuilder.AppendLine($"{contextPosition.UniformName} = {constantValueVar.ConstantValueString};");
     }
 
     public Float2 ConstructFloat2(Expression x, Expression y)
     {
-        string name = $"vec2_{_variables.Count}";
+        string name = $"vec2_{GetUniqueNameNumber()}";
         Float2 result = new Float2(name);
         _variables.Add(result);
 
-        string xExpression = x.ExpressionValue; 
+        string xExpression = x.ExpressionValue;
         string yExpression = y.ExpressionValue;
-        
+
         _bodyBuilder.AppendLine($"float2 {name} = float2({xExpression}, {yExpression});");
         return result;
     }
 
     public Float1 ConstructFloat1(Expression assignment)
     {
-        string name = $"float_{_variables.Count}";
+        string name = $"float_{GetUniqueNameNumber()}";
         Float1 result = new Float1(name);
         _variables.Add(result);
-        
+
         _bodyBuilder.AppendLine($"float {name} = {assignment.ExpressionValue};");
         return result;
     }
 
+    public Int2 ConstructInt2(Expression first, Expression second)
+    {
+        string name = $"int2_{GetUniqueNameNumber()}";
+        Int2 result = new Int2(name);
+        _variables.Add(result);
+
+        string firstExpression = first.ExpressionValue;
+        string secondExpression = second.ExpressionValue;
+
+        _bodyBuilder.AppendLine($"int2 {name} = int2({firstExpression}, {secondExpression});");
+        return result;
+    }
+
     public Half4 ConstructHalf4(Expression r, Expression g, Expression b, Expression a)
     {
-        string name = $"color_{_variables.Count}";
+        string name = $"color_{GetUniqueNameNumber()}";
         Half4 result = new Half4(name);
         _variables.Add(result);
-        
+
         string rExpression = r.ExpressionValue;
         string gExpression = g.ExpressionValue;
         string bExpression = b.ExpressionValue;
         string aExpression = a.ExpressionValue;
-        
+
         _bodyBuilder.AppendLine($"half4 {name} = half4({rExpression}, {gExpression}, {bExpression}, {aExpression});");
         return result;
     }
@@ -129,10 +163,15 @@ public class ShaderBuilder
         _bodyBuilder.Clear();
         _variables.Clear();
         _samplers.Clear();
-        
+
         foreach (var uniform in Uniforms)
         {
             uniform.Value.Dispose();
         }
     }
+
+    public string GetUniqueNameNumber()
+    {
+        return (_variables.Count + Uniforms.Count + 1).ToString();
+    }
 }

+ 13 - 2
src/PixiEditor.DrawingApi.Core/Shaders/Uniform.cs

@@ -1,5 +1,6 @@
 using System;
 using System.ComponentModel;
+using PixiEditor.DrawingApi.Core.ColorsImpl;
 using PixiEditor.Numerics;
 
 namespace PixiEditor.DrawingApi.Core.Shaders;
@@ -14,7 +15,7 @@ public struct Uniform
     public string UniformName { get; }
 
     public UniformValueType DataType { get; }
-    
+
     public Uniform(string name, float value)
     {
         Name = name;
@@ -44,10 +45,20 @@ public struct Uniform
         DataType = UniformValueType.Shader;
         UniformName = "shader";
     }
+    
+    public Uniform(string name, Color color)
+    {
+        Name = name;
+        FloatValue = default;
+        FloatArrayValue = new float[] { color.R, color.G, color.B, color.A };
+        ShaderValue = default;
+        DataType = UniformValueType.FloatArray;
+        UniformName = "half4";
+    }
 
     public void Dispose()
     {
-        ShaderValue.Dispose();
+        ShaderValue?.Dispose();
     }
 }
 

+ 2 - 0
src/PixiEditor.UI.Common/Accents/Base.axaml

@@ -100,7 +100,9 @@
             <SolidColorBrush x:Key="VecDSocketBrush" Color="{StaticResource VecDSocketColor}"/>
             <SolidColorBrush x:Key="Float2SocketBrush" Color="{StaticResource VecDSocketColor}"/>
             <SolidColorBrush x:Key="VecISocketBrush" Color="{StaticResource VecISocketColor}"/>
+            <SolidColorBrush x:Key="Int2SocketBrush" Color="{StaticResource VecISocketColor}"/>
             <SolidColorBrush x:Key="Int32SocketBrush" Color="{StaticResource IntSocketColor}"/>
+            <SolidColorBrush x:Key="Int1SocketBrush" Color="{StaticResource IntSocketColor}"/>
             
             <SolidColorBrush x:Key="PixiEditorModifyImageLeftBorderBrush" Color="{StaticResource PixiEditorModifyImageBorderColor}"/>
             <SolidColorBrush x:Key="PixiEditorModifyImageRightBorderBrush" Color="{StaticResource PixiEditorModifyImageBorderColor}"/>