Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Better interop with ShaderFX #114

Open
wants to merge 3 commits into
base: 1.0
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 98 additions & 0 deletions src/Fuse/FuseEffectInstance.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
using Stride.Core;
using Stride.Core.Diagnostics;
using Stride.Engine.Design;
using Stride.Games;
using Stride.Graphics;
using Stride.Rendering;
using Stride.Shaders;
using Stride.Shaders.Compiler;
using System;
using System.Collections.Generic;
using System.Diagnostics;

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();
}

/// <summary>
/// Defines the effect parameters used when compiling this effect.
/// </summary>
public EffectCompilerParameters EffectCompilerParameters = EffectCompilerParameters.Default;

public void Initialize(IServiceRegistry services)
{
this.effectSystem = services.GetSafeServiceAs<EffectSystem>();

var gameSettings = services.GetSafeServiceAs<IGameSettingsService>().Settings;
EffectCompilerParameters.ApplyCompilationMode(gameSettings.CompilationMode);

var graphicsDevice = services.GetSafeServiceAs<IGraphicsDeviceService>().GraphicsDevice;
EffectCompilerParameters.Platform = GraphicsDevice.Platform;
EffectCompilerParameters.Profile = graphicsDevice.Features.RequestedProfile;
}

protected override void ChooseEffect(GraphicsDevice graphicsDevice)
{
var watch = Stopwatch.StartNew();

// Setup compilation parameters
var compilerParameters = new CompilerParameters
{
EffectParameters = EffectCompilerParameters,
};

foreach (var effectParameterKey in Parameters.ParameterKeyInfos)
{
if (effectParameterKey.Key.Type == ParameterKeyType.Permutation)
{
compilerParameters.SetObject(effectParameterKey.Key, Parameters.ObjectValues[effectParameterKey.BindingSlot]);
}
}

var compiler = effectSystem.Compiler;

// Workaround for Stride effect compiler cache bug
ShaderNodesUtil.MakeInMemoryShadersAvailableToTheSourceManager(compiler, shaderSource);

// Compile the shader
var compilerResult = compiler.Compile(shaderSource, compilerParameters);
CheckResult(compilerResult);

var bytecodeResult = compilerResult.Bytecode.WaitForResult();

CheckResult(bytecodeResult.CompilationLog);

if (bytecodeResult.Bytecode is null)
throw new InvalidOperationException("EffectCompiler returned no shader and no compilation error.");

effect = new Effect(graphicsDevice, bytecodeResult.Bytecode);

Console.WriteLine($"Compile Time: {watch.ElapsedMilliseconds} ms for Shader {shaderSource}");
}

private static void CheckResult(LoggerResult compilerResult)
{
// Check errors
if (compilerResult.HasErrors)
{
throw new InvalidOperationException("Could not compile shader. See error messages." + compilerResult.ToText());
}
}
}
}
31 changes: 4 additions & 27 deletions src/Fuse/Inputs.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Text;
using Fuse.compute;
using Stride.Graphics;
using Stride.Rendering;
Expand Down Expand Up @@ -101,7 +102,9 @@ public override string ToString()
public bool IsResource { get; }
}

public abstract class AbstractInput<T, TParameterKeyType, TParameterUpdaterType> : ShaderNode<T>, IGpuInput where TParameterKeyType : ParameterKey<T> where TParameterUpdaterType : ParameterUpdater<T,TParameterKeyType>
public abstract class AbstractInput<T, TParameterKeyType, TParameterUpdaterType> : ShaderNode<T>, IGpuInput
where TParameterKeyType : ParameterKey<T>
where TParameterUpdaterType : ParameterUpdater<T,TParameterKeyType>
{

protected readonly TParameterUpdaterType Updater;// = new ValueParameterUpdater<T>();
Expand Down Expand Up @@ -408,30 +411,4 @@ public override void OnUpdateName()
SetFieldDeclaration(TypeHelpers.GetGpuType<T>());
}
}
/*
public class CompositionInput<T> : AbstractInput<IComputeNode,PermutationParameterKey<T>, PermutationParameterUpdater<T>> where T : IComputeNode
{

public CompositionInput(SetVar<T> value): base("input", false, value)
{
}

protected override PermutationParameterUpdater<IComputeNode> CreateUpdater()
{
return new PermutationParameterUpdater<IComputeNode>();
}

protected override void OnPassContext(ShaderGeneratorContext nodeContext)
{
Updater.Track(nodeContext, ParameterKey);
}

protected override void OnGenerateCode(ShaderGeneratorContext nodeContext)
{
ParameterKey = new PermutationParameterKey<ShaderSource>(ID);
SetFieldDeclaration(TypeHelpers.GetGpuTypeForType<T>());
}


}*/
}
4 changes: 2 additions & 2 deletions src/Fuse/Properties/launchSettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
}
}
Expand Down
41 changes: 28 additions & 13 deletions src/Fuse/ShaderFX/AbstractToShaderFX.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -58,7 +59,7 @@ public abstract class AbstractToShaderFX<T> : IComputeValue<T>
private readonly HashSet<string>_constantArrays = new();
private readonly HashSet<string>_streams = new();
private readonly HashSet<string>_mixins = new();
private readonly HashSet<string>_compositions = new();
private readonly HashSet<IComposition>_compositions = new();
private readonly Dictionary<string, string> _functionMap = new();

private readonly string _sourceTemplate;
Expand Down Expand Up @@ -148,7 +149,7 @@ public virtual IEnumerable<IComputeNode> GetChildren(object context = null)
_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));
Expand Down Expand Up @@ -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");
Expand Down Expand Up @@ -291,18 +292,32 @@ 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 shaderSource = new ShaderMixinSource()
{
Name = ShaderName,
Mixins =
{
new ShaderClassString(ShaderName, ShaderCode)
}
};

foreach (var composition in _compositions)
{
var compositionSource = composition.ComputeNode.GenerateShaderSource(theContext, baseKeys);
shaderSource.AddComposition(composition.CompositionName, 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 shaderSource;
}
}
}
57 changes: 29 additions & 28 deletions src/Fuse/ShaderFX/CompositionInput.cs
Original file line number Diff line number Diff line change
@@ -1,47 +1,48 @@
using System.Collections.Generic;
using NuGet;
using Stride.Rendering.Materials;
using VL.Core;
using VL.Stride.Shaders.ShaderFX;

namespace Fuse.ShaderFX
{
public interface IComposition
{
string Declaration { get; }
string CompositionName { get; }
IComputeNode ComputeNode { get; }
}

public class CompositionInput<T> : ShaderNode<T>
public class CompositionInput<T> : ShaderNode<T>, IComposition
where T : unmanaged
{
protected const string DeclarationTemplate = @"
compose Compute${compositionType} ${compositionName};";

public CompositionInput(NodeContext nodeContext, string theId, IComputeValue<T> theComposition) : base(nodeContext, theId, null)
IComputeValue<T> _value;

public CompositionInput(NodeContext nodeContext, SetVar<T> value /* Should just be IComputeValue<T> */)
: base(nodeContext, "compositionInput")
{

AddProperty(Compositions, this);
_value = value?.Value ?? new VL.Stride.Shaders.ShaderFX.ComputeNode<T>();

SetProperty(Compositions, this);
}

protected override Dictionary<string, string> CreateTemplateMap()
{
var result = new Dictionary<string, string>
{
{"compositionType", TypeHelpers.GetSignature<T>()},
{"compositionName", ID}
};

foreach (var template in base.CreateTemplateMap())
public string Declaration => ShaderNodesUtil.Evaluate("compose ${compositionType} ${compositionId};",
new Dictionary<string, string>()
{
result.Add(template.Key, template.Value);
}
{ "compositionType", TypeHelpers.GetCompositionType<T>() },
{ "compositionId", CompositionName }
});

public IComputeNode ComputeNode => _value;

public string CompositionName => $"composition{ID}";

return result;
}

protected override string SourceTemplate()
{
return "${resultType} ${resultName} = ${compositionName}.Compute();";
}

public override void OnPassContext(ShaderGeneratorContext theContext)
{
ShaderNodesUtil.Evaluate(DeclarationTemplate,CreateTemplateMap());
return ShaderNodesUtil.Evaluate("${resultType} ${resultName} = ${compositionId}.Compute();",
new Dictionary<string, string>
{
{"compositionId", CompositionName},
});
}
}
}
4 changes: 2 additions & 2 deletions src/Fuse/ShaderNode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -605,9 +605,9 @@ public List<IGpuInput> InputList()
return PropertyForTree<IGpuInput>(Inputs);
}

public List<string> CompositionList()
public List<IComposition> CompositionList()
{
return PropertyForTree<string>(Compositions);
return PropertyForTree<IComposition>(Compositions);
}

public List<FieldDeclaration> DeclarationList()
Expand Down
Loading