Skip to content

Instantly share code, notes, and snippets.

@Eideren
Last active April 28, 2024 21:29
Show Gist options
  • Save Eideren/ef6be9508d8d3b0e460d8a6d15f0937b to your computer and use it in GitHub Desktop.
Save Eideren/ef6be9508d8d3b0e460d8a6d15f0937b to your computer and use it in GitHub Desktop.
How to setup async shader compilation in stride, note that the game will still freeze initially to compile the fallback
public class YourGameDefinition : Stride.Engine.Game
{
protected override void BeginRun()
{
base.BeginRun();
foreach( var feature in SceneSystem.GraphicsCompositor.RenderFeatures )
{
if( feature is MeshRenderFeature meshRf )
{
meshRf.ComputeFallbackEffect += FallbackForAsyncCompilation;
}
}
}
Material fallbackColorMaterial;
Effect FallbackForAsyncCompilation(RenderObject renderObject, RenderEffect renderEffect, RenderEffectState renderEffectState)
{
// Source is 'ComputeMeshFallbackEffect' in EntityHierarchyEditorGame.cs
try
{
var renderMesh = (RenderMesh)renderObject;
fallbackColorMaterial ??= Material.New(GraphicsDevice, new MaterialDescriptor
{
Attributes =
{
Diffuse = new MaterialDiffuseMapFeature(new ComputeColor(new Color4(1f, 1f, 1f))),
DiffuseModel = new MaterialDiffuseLambertModelFeature()
}
});
// High priority
var compilerParameters = new CompilerParameters { EffectParameters = { TaskPriority = -1 } };
// Set material permutations
compilerParameters.Set(MaterialKeys.PixelStageSurfaceShaders, fallbackColorMaterial.Passes[0].Parameters.Get(MaterialKeys.PixelStageSurfaceShaders));
compilerParameters.Set(MaterialKeys.PixelStageStreamInitializer, fallbackColorMaterial.Passes[0].Parameters.Get(MaterialKeys.PixelStageStreamInitializer));
// Set lighting permutations (use custom white light, since this effect will not be processed by the lighting render feature)
compilerParameters.Set(LightingKeys.EnvironmentLights, new ShaderSourceCollection { new ShaderClassSource("LightConstantWhite") });
// Initialize parameters with material ones (need a CopyTo?)
renderEffect.FallbackParameters = new ParameterCollection(renderMesh.MaterialPass.Parameters);
if (renderEffectState == RenderEffectState.Error)
{
// Retry every few seconds
renderEffect.RetryTime = DateTime.UtcNow + TimeSpan.FromSeconds(5);
}
return EffectSystem.LoadEffect(renderEffect.EffectSelector.EffectName, compilerParameters).WaitForResult();
}
catch(Exception e)
{
renderEffect.State = RenderEffectState.Error;
System.Console.WriteLine(e.ToString());
return null;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment