From bd0c4895f0172ef0d3ff01d2af02bec048c0a471 Mon Sep 17 00:00:00 2001 From: Elias Holzer Date: Wed, 29 Nov 2023 18:04:47 +0100 Subject: [PATCH 1/3] Everything still operational --- src/Fuse/FuseEffectInstance.cs | 86 +++++ src/Fuse/Inputs.cs | 53 ++- src/Fuse/Properties/launchSettings.json | 4 +- src/Fuse/ShaderFX/AbstractToShaderFX.cs | 37 ++- src/Fuse/ShaderNode.cs | 4 +- src/Fuse/ShaderNodesUtil.cs | 20 +- vl/Fuse.Core.vl | 419 +++++++++++++++++++++++- 7 files changed, 567 insertions(+), 56 deletions(-) create mode 100644 src/Fuse/FuseEffectInstance.cs diff --git a/src/Fuse/FuseEffectInstance.cs b/src/Fuse/FuseEffectInstance.cs new file mode 100644 index 000000000..5df8bb3da --- /dev/null +++ b/src/Fuse/FuseEffectInstance.cs @@ -0,0 +1,86 @@ +using Stride.Core; +using Stride.Graphics; +using Stride.Rendering; +using Stride.Shaders; +using Stride.Shaders.Compiler; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Fuse +{ + public class FuseEffectInstance : EffectInstance + { + private readonly ShaderSource shaderSource; + private readonly IDisposable subscriptions; + private EffectSystem effectSystem; + + public FuseEffectInstance(ShaderSource shaderSource, ParameterCollection parameters, IDisposable subscriptions) : base(null, parameters) + { + this.shaderSource = shaderSource; + this.subscriptions = subscriptions; + } + + protected override void Destroy() + { + subscriptions.Dispose(); + base.Destroy(); + } + + /// + /// Defines the effect parameters used when compiling this effect. + /// + public EffectCompilerParameters EffectCompilerParameters = EffectCompilerParameters.Default; + + public void Initialize(IServiceRegistry services) + { + this.effectSystem = services.GetSafeServiceAs(); + } + + protected override void ChooseEffect(GraphicsDevice graphicsDevice) + { + var watch = Stopwatch.StartNew(); + + // TODO: Free previous descriptor sets and layouts? + + // Looks like the effect changed, it needs a recompilation + var compilerParameters = new CompilerParameters + { + EffectParameters = EffectCompilerParameters, + }; + + foreach (var effectParameterKey in Parameters.ParameterKeyInfos) + { + if (effectParameterKey.Key.Type == ParameterKeyType.Permutation) + { + // TODO GRAPHICS REFACTOR avoid direct access, esp. since permutation values might be separated from Objects at some point + compilerParameters.SetObject(effectParameterKey.Key, Parameters.ObjectValues[effectParameterKey.BindingSlot]); + } + } + + var effectCompiler = effectSystem.Compiler; + + // Setup compilation parameters + // GraphicsDevice might have been not valid until this point, which is why we compute platform and profile only at this point + compilerParameters.EffectParameters.Platform = GraphicsDevice.Platform; + compilerParameters.EffectParameters.Profile = /*graphicsDevice.ShaderProfile ?? */graphicsDevice.Features.RequestedProfile; + // Copy optimization/debug levels + //compilerParameters.EffectParameters.OptimizationLevel = ; + //compilerParameters.EffectParameters.Debug = effectCompilerParameters.Debug; + + // Get the compiled result + var compilerResult = effectCompiler.Compile(shaderSource, compilerParameters); + + // Only take the sub-effect + var bytecodeTask = compilerResult.Bytecode; + var byteCode = bytecodeTask.WaitForResult().Bytecode; + + effect = new Effect(graphicsDevice, byteCode); + + Console.WriteLine($"Compile Time: {watch.ElapsedMilliseconds} ms for Shader {shaderSource}"); + } + } +} diff --git a/src/Fuse/Inputs.cs b/src/Fuse/Inputs.cs index 49a4e41c5..3d7d3c6e8 100644 --- a/src/Fuse/Inputs.cs +++ b/src/Fuse/Inputs.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Text; using Fuse.compute; using Stride.Graphics; using Stride.Rendering; @@ -101,7 +102,9 @@ public override string ToString() public bool IsResource { get; } } - public abstract class AbstractInput : ShaderNode, IGpuInput where TParameterKeyType : ParameterKey where TParameterUpdaterType : ParameterUpdater + public abstract class AbstractInput : ShaderNode, IGpuInput + where TParameterKeyType : ParameterKey + where TParameterUpdaterType : ParameterUpdater { protected readonly TParameterUpdaterType Updater;// = new ValueParameterUpdater(); @@ -408,30 +411,44 @@ public override void OnUpdateName() SetFieldDeclaration(TypeHelpers.GetGpuType()); } } - /* - public class CompositionInput : AbstractInput, PermutationParameterUpdater> where T : IComputeNode + + public interface IComposition { + string Declaration { get; } + string Name { get; } + IComputeNode ComputeNode { get; } + } - public CompositionInput(SetVar value): base("input", false, value) - { - } - protected override PermutationParameterUpdater CreateUpdater() - { - return new PermutationParameterUpdater(); - } + public class CompositionInput : ShaderNode, IComposition + where T : unmanaged + { + IComputeValue _value; - protected override void OnPassContext(ShaderGeneratorContext nodeContext) + public CompositionInput(NodeContext nodeContext, IComputeValue value) + : base(nodeContext, "compInput") { - Updater.Track(nodeContext, ParameterKey); + _value = value; + + SetProperty(Compositions, this); } - protected override void OnGenerateCode(ShaderGeneratorContext nodeContext) + public string Declaration => ShaderNodesUtil.Evaluate("compose ${compositionType} ${compositionId};", + new Dictionary() + { + { "compositionType", TypeHelpers.GetCompositionType() }, + { "compositionId", ID } + }); + + public IComputeNode ComputeNode => _value; + + protected override string SourceTemplate() { - ParameterKey = new PermutationParameterKey(ID); - SetFieldDeclaration(TypeHelpers.GetGpuTypeForType()); + return ShaderNodesUtil.Evaluate("${resultType} ${resultName} = ${in}.Compute();", + new Dictionary + { + {"in", ID}, + }); } - - - }*/ + } } \ No newline at end of file diff --git a/src/Fuse/Properties/launchSettings.json b/src/Fuse/Properties/launchSettings.json index 0dbbaf3c3..b8a1d596e 100644 --- a/src/Fuse/Properties/launchSettings.json +++ b/src/Fuse/Properties/launchSettings.json @@ -2,12 +2,12 @@ "profiles": { "Normal startup": { "commandName": "Executable", - "executablePath": "C:\\Program Files\\vvvv\\vvvv_gamma_5.3-0251-gc882d50ce8\\vvvv.exe", + "executablePath": "C:\\Program Files\\vvvv\\vvvv_gamma_5.3-0346-g0a53f6c531\\vvvv.exe", "commandLineArgs": "--package-repositories $(PackageRepositories)" }, "Work on Fuse patches": { "commandName": "Executable", - "executablePath": "C:\\Program Files\\vvvv\\vvvv_gamma_5.3-0251-gc882d50ce8\\vvvv.exe", + "executablePath": "C:\\Program Files\\vvvv\\vvvv_gamma_5.3-0346-g0a53f6c531\\vvvv.exe", "commandLineArgs": "--package-repositories $(PackageRepositories) --editable-packages VL.Fuse" } } diff --git a/src/Fuse/ShaderFX/AbstractToShaderFX.cs b/src/Fuse/ShaderFX/AbstractToShaderFX.cs index a84bcdb10..c1ba3f26a 100644 --- a/src/Fuse/ShaderFX/AbstractToShaderFX.cs +++ b/src/Fuse/ShaderFX/AbstractToShaderFX.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Text; using JetBrains.Profiler.Api; +using Stride.Core.Yaml.Tokens; using Stride.Rendering.Materials; using Stride.Rendering.Materials.ComputeColors; using Stride.Shaders; @@ -58,7 +59,7 @@ public abstract class AbstractToShaderFX : IComputeValue private readonly HashSet_constantArrays = new(); private readonly HashSet_streams = new(); private readonly HashSet_mixins = new(); - private readonly HashSet_compositions = new(); + private readonly HashSet_compositions = new(); private readonly Dictionary _functionMap = new(); private readonly string _sourceTemplate; @@ -148,7 +149,7 @@ private Dictionary BuildTemplateMap() _mixins.ForEach(mixin => mixinBuilder.Append(", " + mixin)); var compositionBuilder = new StringBuilder(); - _compositions.ForEach(composition => compositionBuilder.AppendLine(composition)); + _compositions.ForEach(composition => compositionBuilder.AppendLine(composition.Declaration)); var functionBuilder = new StringBuilder(); _functionMap?.ForEach(kv => functionBuilder.AppendLine(kv.Value)); @@ -212,11 +213,11 @@ private void HandleShader(bool theIsComputeShader, AbstractShaderNode theShaderI _stopwatch.Restart(); theShaderInput.MixinList().ForEach(value => _mixins.Add(value)); if(ShaderNodesUtil.TimeShaderGeneration)Console.WriteLine($" Mixins: {_stopwatch.ElapsedMilliseconds} ms"); - /* + _stopwatch.Restart(); theShaderInput.CompositionList().ForEach(value => _compositions.Add(value)); if(ShaderNodesUtil.TimeShaderGeneration)Console.WriteLine($" Compositions: {_stopwatch.ElapsedMilliseconds} ms"); - */ + _stopwatch.Restart(); theShaderInput.FunctionMap().ForEach(HandleFunction); if(ShaderNodesUtil.TimeShaderGeneration)Console.WriteLine($" Functions: {_stopwatch.ElapsedMilliseconds} ms"); @@ -291,18 +292,28 @@ public ShaderSource GenerateShaderSource(ShaderGeneratorContext theContext, Mate } if(ShaderNodesUtil.TimeShaderGeneration)Console.WriteLine($"-> Evaluate: {_stopwatch.ElapsedMilliseconds} ms"); - _stopwatch.Restart(); - ShaderNodesUtil.AddShaderSource( ShaderName, ShaderCode, "shaders\\" + ShaderName + ".sdsl"); - if(ShaderNodesUtil.TimeShaderGeneration)Console.WriteLine($"-> AddShaderSource: {_stopwatch.ElapsedMilliseconds} ms"); - // _parameters = theContext.Parameters; - - // _input.InputList().ForEach(input => input.AddParameters(_parameters)); - var result = new ShaderClassSource(ShaderName); - _stopwatch.Stop(); + var shaderClassString = new ShaderClassString(ShaderName, ShaderCode); + + var mixin = new ShaderMixinSource(); + mixin.Mixins.Add(shaderClassString); + + foreach (var composition in _compositions) + { + var compositionSource = composition.ComputeNode.GenerateShaderSource(theContext, baseKeys); + mixin.AddComposition(composition.Name, compositionSource); + } + + // _parameters = theContext.Parameters; + + // _input.InputList().ForEach(input => input.AddParameters(_parameters)); + //var result = new ShaderClassSource(ShaderName); + _stopwatch.Stop(); if(ShaderNodesUtil.TimeShaderGeneration)Console.WriteLine($"-> Execution Time: {watch.ElapsedMilliseconds} ms for Shader {ShaderName}"); //MeasureProfiler.SaveData(ShaderName); - return result; + //return result; + + return mixin; } } } \ No newline at end of file diff --git a/src/Fuse/ShaderNode.cs b/src/Fuse/ShaderNode.cs index 9ca6c6123..d560dffa4 100644 --- a/src/Fuse/ShaderNode.cs +++ b/src/Fuse/ShaderNode.cs @@ -605,9 +605,9 @@ public List InputList() return PropertyForTree(Inputs); } - public List CompositionList() + public List CompositionList() { - return PropertyForTree(Compositions); + return PropertyForTree(Compositions); } public List DeclarationList() diff --git a/src/Fuse/ShaderNodesUtil.cs b/src/Fuse/ShaderNodesUtil.cs index 4d263501f..0a6139be0 100644 --- a/src/Fuse/ShaderNodesUtil.cs +++ b/src/Fuse/ShaderNodesUtil.cs @@ -10,12 +10,15 @@ using Fuse.ShaderFX; using Stride.Core; using Stride.Core.Mathematics; +using Stride.Graphics; using Stride.Rendering; using Stride.Rendering.Materials; +using Stride.Shaders; using Stride.Shaders.Compiler; using Stride.Shaders.Parser; using VL.Core; using VL.Stride; +using VL.Stride.Effects; using VL.Stride.Rendering; using VL.Stride.Rendering.ComputeEffect; using VL.Stride.Shaders.ShaderFX; @@ -273,7 +276,7 @@ protected override void Destroy() } - public static DynamicEffectInstance RegisterDrawShader(ToDrawFX theDrawShader) + public static FuseEffectInstance RegisterDrawShader(ToDrawFX theDrawShader) { var watch = new Stopwatch(); @@ -281,16 +284,19 @@ public static DynamicEffectInstance RegisterDrawShader(ToDrawFX theDrawShader) var game = ServiceRegistry.Current.GetGameProvider().GetHandle().Resource; if (game == null) return null; - var effectImageShader = new DynamicDrawEffectInstance("ShaderFXGraphEffect"); + var parameters = new ParameterCollection(); + var subscriptions = new CompositeDisposable(); var method = typeof(ShaderGraph).GetMethod("NewShaderGeneratorContext", BindingFlags.Static | BindingFlags.NonPublic); - var context = method?.Invoke(null, new object[]{game.GraphicsDevice, effectImageShader.Parameters, effectImageShader.Subscriptions}); + var context = (ShaderGeneratorContext)method?.Invoke(null, new object[]{game.GraphicsDevice, parameters, subscriptions}); //var context = ShaderGraph.NewShaderGeneratorContext(game.GraphicsDevice, effectImageShader.Parameters, effectImageShader.Subscriptions); var key = new MaterialComputeColorKeys(MaterialKeys.DiffuseMap, MaterialKeys.DiffuseValue, Stride.Core.Mathematics.Color.White); - theDrawShader.GenerateShaderSource((ShaderGeneratorContext) context,key); - effectImageShader.EffectName = theDrawShader.ShaderName; - Console.WriteLine($"Register Time: {watch.ElapsedMilliseconds} ms for Shader {theDrawShader.ShaderName}"); - return effectImageShader; + var shaderSource = theDrawShader.GenerateShaderSource(context,key); + + var effectSource = new ShaderMixinGeneratorSource("DrawFXEffect"); + parameters.Set(EffectNodeBaseKeys.EffectNodeBaseShader, shaderSource); + + return new FuseEffectInstance(effectSource, parameters, subscriptions); } // ReSharper disable once UnusedMember.Global diff --git a/vl/Fuse.Core.vl b/vl/Fuse.Core.vl index 83ac52181..aa361f5a7 100644 --- a/vl/Fuse.Core.vl +++ b/vl/Fuse.Core.vl @@ -1,6 +1,6 @@  - - + + @@ -87710,14 +87710,14 @@ - - + + - + - + @@ -87860,10 +87860,10 @@ - - - + + + @@ -88244,6 +88244,394 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -88255,7 +88643,6 @@ - @@ -88345,6 +88732,7 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 11