public void Generate(ShaderMixinSource mixin, ShaderMixinContext context) { context.Mixin(mixin, "A"); context.Mixin(mixin, "B"); context.Mixin(mixin, "C"); context.Mixin(mixin, "ChildMixin"); }
public void Visit(MaterialGeneratorContext context) { var alpha = Alpha ?? new ComputeFloat(0.5f); var tint = Tint ?? new ComputeColor(Color.White); // Use pre-multiplied alpha to support both additive and alpha blending var blendDesc = new BlendStateDescription(Blend.One, Blend.InverseSourceAlpha); context.Material.HasTransparency = true; context.Parameters.Set(Effect.BlendStateKey, BlendState.NewFake(blendDesc)); var alphaColor = alpha.GenerateShaderSource(context, new MaterialComputeColorKeys(MaterialKeys.DiffuseSpecularAlphaBlendMap, MaterialKeys.DiffuseSpecularAlphaBlendValue, Color.White)); var mixin = new ShaderMixinSource(); mixin.Mixins.Add(new ShaderClassSource("ComputeColorMaterialAlphaBlend")); mixin.AddComposition("color", alphaColor); context.SetStream(MaterialShaderStage.Pixel, AlphaBlendStream.Stream, MaterialStreamType.Float2, mixin); context.SetStream(AlphaBlendColorStream.Stream, tint, MaterialKeys.AlphaBlendColorMap, MaterialKeys.AlphaBlendColorValue, Color.White); if (!context.Tags.Get(HasFinalCallback)) { context.Tags.Set(HasFinalCallback, true); context.AddFinalCallback(MaterialShaderStage.Pixel, AddDiffuseSpecularAlphaBlendColor); } }
public void Generate(ShaderMixinSource mixin, ShaderMixinContext context) { var directLightGroups = context.GetParam(LightingKeys.DirectLightGroups); if (directLightGroups != null) { foreach(var directLightGroup in directLightGroups) { { var __mixinToCompose__ = (directLightGroup); var __subMixin = new ShaderMixinSource(); context.PushCompositionArray(mixin, "directLightGroups", __subMixin); context.Mixin(__subMixin, __mixinToCompose__); context.PopComposition(); } } } var environmentLights = context.GetParam(LightingKeys.EnvironmentLights); if (environmentLights != null) { foreach(var environmentLight in environmentLights) { { var __mixinToCompose__ = (environmentLight); var __subMixin = new ShaderMixinSource(); context.PushCompositionArray(mixin, "environmentLights", __subMixin); context.Mixin(__subMixin, __mixinToCompose__); context.PopComposition(); } } } }
public void Generate(ShaderMixinSource mixin, ShaderMixinContext context) { context.Mixin(mixin, "A"); context.Mixin(mixin, "B"); if (context.GetParam(TestParameters.param1)) { context.Mixin(mixin, "C"); mixin.AddMacro("param2", context.GetParam(TestParameters.param2)); { var __mixinToCompose__ = "X"; var __subMixin = new ShaderMixinSource(); context.PushComposition(mixin, "x", __subMixin); context.Mixin(__subMixin, __mixinToCompose__); context.PopComposition(); } } else { context.Mixin(mixin, "D"); mixin.AddMacro("Test", context.GetParam(TestParameters.param3)); { var __mixinToCompose__ = "Y"; var __subMixin = new ShaderMixinSource(); context.PushComposition(mixin, "y", __subMixin); context.Mixin(__subMixin, __mixinToCompose__); context.PopComposition(); } } }
public void Generate(ShaderMixinSource mixin, ShaderMixinContext context) { context.Mixin(mixin, "A"); context.Mixin(mixin, "B"); context.Mixin(mixin, "C"); int x = 1; foreach(var ____1 in context.GetParam(TestParameters.subParameters)) { context.PushParameters(____1); if (context.GetParam(SubParameters.param1)) { context.Mixin(mixin, "C" + x); } x++; context.PopParameters(); } { context.PushParameters(context.GetParam(TestParameters.subParam1)); if (context.GetParam(SubParameters.param2) == 1) { context.Mixin(mixin, "D"); } context.PopParameters(); } }
public void Generate(ShaderMixinSource mixin, ShaderMixinContext context) { context.Mixin(mixin, "LightSkyboxShader"); if (context.GetParam(LightSkyboxShaderKeys.LightDiffuseColor) != null) { { var __mixinToCompose__ = context.GetParam(LightSkyboxShaderKeys.LightDiffuseColor); var __subMixin = new ShaderMixinSource(); context.PushComposition(mixin, "lightDiffuseColor", __subMixin); context.Mixin(__subMixin, __mixinToCompose__); context.PopComposition(); } } if (context.GetParam(LightSkyboxShaderKeys.LightSpecularColor) != null) { { var __mixinToCompose__ = context.GetParam(LightSkyboxShaderKeys.LightSpecularColor); var __subMixin = new ShaderMixinSource(); context.PushComposition(mixin, "lightSpecularColor", __subMixin); context.Mixin(__subMixin, __mixinToCompose__); context.PopComposition(); } } }
/// <summary> /// Squash <see cref="ShaderSources"/> to a single ShaderSource (compatible with IComputeColor) /// </summary> /// <returns>The squashed <see cref="ShaderSource"/> or null if nothing to squash</returns> public ShaderSource ComputeShaderSource() { if (ShaderSources.Count == 0) { return null; } ShaderSource result; // If there is only a single op, don't generate a mixin if (ShaderSources.Count == 1) { result = ShaderSources[0]; } else { var mixin = new ShaderMixinSource(); result = mixin; mixin.Mixins.Add(new ShaderClassSource("MaterialSurfaceArray")); // Squash all operations into MaterialLayerArray foreach (var operation in ShaderSources) { mixin.AddCompositionToArray("layers", operation); } } return result; }
public void Generate(ShaderMixinSource mixin, ShaderMixinContext context) { context.Mixin(mixin, "A"); { var __mixinToCompose__ = "ABCSubEffect"; var __subMixin = new ShaderMixinSource(); context.PushComposition(mixin, "SubCompute1", __subMixin); context.Mixin(__subMixin, __mixinToCompose__); context.PopComposition(); } { var __mixinToCompose__ = "ABCSubEffect"; var __subMixin = new ShaderMixinSource(); context.PushComposition(mixin, "SubCompute2", __subMixin); context.Mixin(__subMixin, __mixinToCompose__); context.PopComposition(); } { var __mixinToCompose__ = "ABCSubEffect"; var __subMixin = new ShaderMixinSource(); context.PushCompositionArray(mixin, "SubComputes", __subMixin); context.Mixin(__subMixin, __mixinToCompose__); context.PopComposition(); } }
public void Generate(ShaderMixinSource mixin, ShaderMixinContext context) { context.Mixin(mixin, "ParticleBaseEffect"); context.Mixin(mixin, "ParticleCustomShader"); if (context.GetParam(ParticleCustomShaderKeys.BaseColor) != null) { { var __mixinToCompose__ = context.GetParam(ParticleCustomShaderKeys.BaseColor); var __subMixin = new ShaderMixinSource(); context.PushComposition(mixin, "baseColor", __subMixin); context.Mixin(__subMixin, __mixinToCompose__); context.PopComposition(); } } if (context.GetParam(ParticleCustomShaderKeys.BaseIntensity) != null) { { var __mixinToCompose__ = context.GetParam(ParticleCustomShaderKeys.BaseIntensity); var __subMixin = new ShaderMixinSource(); context.PushComposition(mixin, "baseIntensity", __subMixin); context.Mixin(__subMixin, __mixinToCompose__); context.PopComposition(); } } }
private async Task<EffectBytecodeCompilerResult> CompileAsync(ShaderMixinSource mixinTree, CompilerParameters compilerParameters) { // Make sure we are connected // TODO: Handle reconnections, etc... await shaderCompilerConnected; return await shaderCompilerTarget.Compile(mixinTree, compilerParameters); }
public void Generate(ShaderMixinSource mixin, ShaderMixinContext context) { mixin.AddMacro("ThreadNumberX", context.GetParam(ComputeEffectShaderKeys.ThreadNumbers).X); mixin.AddMacro("ThreadNumberY", context.GetParam(ComputeEffectShaderKeys.ThreadNumbers).Y); mixin.AddMacro("ThreadNumberZ", context.GetParam(ComputeEffectShaderKeys.ThreadNumbers).Z); context.Mixin(mixin, "ComputeShaderBase"); context.Mixin(mixin, context.GetParam(ComputeEffectShaderKeys.ComputeShaderName)); }
public void TestMacros() { // test that macros are correctly used var baseMixin = new ShaderMixinSource(); baseMixin.AddMacro("SILICONSTUDIO_XENKO_GRAPHICS_API_DIRECT3D", 1); baseMixin.Macros.Add(new ShaderMacro("MACRO_TEST", "int")); baseMixin.Mixins.Add(new ShaderClassSource("TestMacros")); var macros0 = new ShaderMixinSource(); macros0.Mixins.Add(new ShaderClassSource("MacroTest")); baseMixin.Compositions.Add("macros0", macros0); var macros1 = new ShaderMixinSource(); macros1.Mixins.Add(new ShaderClassSource("MacroTest")); macros1.Macros.Add(new ShaderMacro("MACRO_TEST", "float")); baseMixin.Compositions.Add("macros1", macros1); var macros2 = new ShaderMixinSource(); macros2.Mixins.Add(new ShaderClassSource("MacroTest")); macros2.Macros.Add(new ShaderMacro("MACRO_TEST", "float4")); baseMixin.Compositions.Add("macros2", macros2); var parsingResult = shaderMixinParser.Parse(baseMixin, baseMixin.Macros.ToArray()); Assert.IsFalse(parsingResult.HasErrors); var cBufferVar = parsingResult.Shader.Declarations.OfType<ConstantBuffer>().First(x => x.Name == "Globals").Members.OfType<Variable>().ToList(); Assert.AreEqual(1, cBufferVar.Count(x => x.Type.Name.Text == "int")); Assert.AreEqual(1, cBufferVar.Count(x => x.Type.Name.Text == "float")); Assert.AreEqual(1, cBufferVar.Count(x => x.Type.Name.Text == "float4")); // test clash when reloading var baseMixin2 = new ShaderMixinSource(); baseMixin2.AddMacro("SILICONSTUDIO_XENKO_GRAPHICS_API_DIRECT3D", 1); baseMixin2.Macros.Add(new ShaderMacro("MACRO_TEST", "int")); baseMixin2.Mixins.Add(new ShaderClassSource("TestMacros")); var macros3 = new ShaderMixinSource(); macros3.Mixins.Add(new ShaderClassSource("MacroTest")); baseMixin2.Compositions.Add("macros0", macros3); var macros4 = new ShaderMixinSource(); macros4.Mixins.Add(new ShaderClassSource("MacroTest")); macros4.Macros.Add(new ShaderMacro("MACRO_TEST", "uint4")); baseMixin2.Compositions.Add("macros1", macros4); var macros5 = new ShaderMixinSource(); macros5.Mixins.Add(new ShaderClassSource("MacroTest")); macros5.Macros.Add(new ShaderMacro("MACRO_TEST", "float4")); baseMixin2.Compositions.Add("macros2", macros5); var parsingResult2 = shaderMixinParser.Parse(baseMixin2, baseMixin2.Macros.ToArray()); Assert.IsFalse(parsingResult.HasErrors); var cBufferVar2 = parsingResult2.Shader.Declarations.OfType<ConstantBuffer>().First(x => x.Name == "Globals").Members.OfType<Variable>().ToList(); Assert.AreEqual(1, cBufferVar2.Count(x => x.Type.Name.Text == "int")); Assert.AreEqual(1, cBufferVar2.Count(x => x.Type.Name.Text == "uint4")); Assert.AreEqual(1, cBufferVar2.Count(x => x.Type.Name.Text == "float4")); }
public void Generate(ShaderMixinSource mixin, ShaderMixinContext context) { context.Mixin(mixin, "CustomShader"); if (context.ChildEffectName == "CustomSubEffect") { context.Mixin(mixin, "CustomSubEffect"); return; } }
public void Generate(ShaderMixinSource mixin, ShaderMixinContext context) { context.Mixin(mixin, "ParadoxForwardShadingEffect"); if (context.GetParam(GameParameters.EnableOnflyTextureUVChange)) context.Mixin(mixin, "TransformationTextureUV"); if (context.GetParam(GameParameters.EnableBend)) context.Mixin(mixin, "TransformationBendWorld"); if (context.GetParam(GameParameters.EnableFog)) context.Mixin(mixin, "FogEffect"); }
public void Generate(ShaderMixinSource mixin, ShaderMixinContext context) { context.Mixin(mixin, "ToneMapShader"); { var __subMixin = new ShaderMixinSource() { Parent = mixin }; context.PushComposition(mixin, "ToneMapOperator", __subMixin); context.Mixin(__subMixin, context.GetParam(ColorTransformKeys.Shader)); context.PopComposition(); } }
public void Generate(ShaderMixinSource mixin, ShaderMixinContext context) { context.Mixin(mixin, "A"); context.Mixin(mixin, "B"); context.Mixin(mixin, "C"); if (context.ChildEffectName == "Test") { context.Mixin(mixin, "ChildClone"); return; } }
public void Generate(ShaderMixinSource mixin, ShaderMixinContext context) { if (context.GetParam(ColorTransformKeys.Enabled)) { context.Mixin(mixin, context.GetParam(ColorTransformKeys.Shader), context.GetParam(ColorTransformKeys.GenericArguments)); } else { context.Mixin(mixin, "ColorTransformShader"); } }
/// <summary> /// Computes a hash <see cref="ObjectId"/> for the specified mixin. /// </summary> /// <param name="mixin">The mixin.</param> /// <param name="mixinParameters">The mixin parameters.</param> /// <returns>EffectObjectIds.</returns> public static ObjectId Compute(ShaderMixinSource mixin, CompilerParameters compilerParameters) { lock (generatorLock) { if (generator == null) { generator = new ShaderMixinObjectId(); } return generator.ComputeInternal(mixin, compilerParameters); } }
public void Generate(ShaderMixinSource mixin, ShaderMixinContext context) { if (context.GetParam(CustomShaderKeys.SwitchEffectLevel) < 10) { context.Mixin(mixin, "CustomShader"); } else { context.Mixin(mixin, "CustomShader2"); } }
public void Generate(ShaderMixinSource mixin, ShaderMixinContext context) { context.Mixin(mixin, "ToneMapShader", context.GetParam(ToneMapKeys.AutoKey), context.GetParam(ToneMapKeys.AutoExposure)); { var __mixinToCompose__ = context.GetParam(ColorTransformKeys.Shader); var __subMixin = new ShaderMixinSource(); context.PushComposition(mixin, "ToneMapOperator", __subMixin); context.Mixin(__subMixin, __mixinToCompose__); context.PopComposition(); } }
public void Visit(MaterialGeneratorContext context) { if (MetalnessMap != null) { var computeColorSource = MetalnessMap.GenerateShaderSource(context, new MaterialComputeColorKeys(MaterialKeys.MetalnessMap, MaterialKeys.MetalnessValue)); var mixin = new ShaderMixinSource(); mixin.Mixins.Add(new ShaderClassSource("MaterialSurfaceMetalness")); mixin.AddComposition("metalnessMap", computeColorSource); context.UseStream(MaterialShaderStage.Pixel, "matSpecular"); context.AddSurfaceShader(MaterialShaderStage.Pixel, mixin); } }
public override void VisitFeature(MaterialGeneratorContext context) { if (GlossinessMap != null) { context.UseStream(MaterialShaderStage.Pixel, GlossinessStream.Stream); var computeColorSource = GlossinessMap.GenerateShaderSource(context, new MaterialComputeColorKeys(MaterialKeys.GlossinessMap, MaterialKeys.GlossinessValue)); var mixin = new ShaderMixinSource(); mixin.Mixins.Add(new ShaderClassSource("MaterialSurfaceGlossinessMap", Invert)); mixin.AddComposition("glossinessMap", computeColorSource); context.AddSurfaceShader(MaterialShaderStage.Pixel, mixin); } }
public void Generate(ShaderMixinSource mixin, ShaderMixinContext context) { context.Mixin(mixin, "A"); if (context.GetParam(TestParameters.TestCount) == 0) context.Mixin(mixin, "B"); if (context.ChildEffectName == "ChildParamsMixin") { context.Mixin(mixin, "ChildParamsMixin"); return; } if (context.GetParam(TestParameters.TestCount) == 0) context.Mixin(mixin, "C"); }
public void Visit(MaterialGeneratorContext context) { if (DiffuseMap != null) { var computeColorSource = DiffuseMap.GenerateShaderSource(context, new MaterialComputeColorKeys(MaterialKeys.DiffuseMap, MaterialKeys.DiffuseValue, Color.White)); var mixin = new ShaderMixinSource(); mixin.Mixins.Add(new ShaderClassSource("MaterialSurfaceDiffuse")); mixin.AddComposition("diffuseMap", computeColorSource); context.UseStream(MaterialShaderStage.Pixel, DiffuseStream.Stream); context.UseStream(MaterialShaderStage.Pixel, ColorBaseStream.Stream); context.AddSurfaceShader(MaterialShaderStage.Pixel, mixin); } }
protected override void UpdateLightCount() { base.UpdateLightCount(); var mixin = new ShaderMixinSource(); mixin.Mixins.Add(new ShaderClassSource("LightSpotGroup", LightCurrentCount)); // Old fixed path kept in case we need it again later //mixin.Mixins.Add(new ShaderClassSource("LightSpotGroup", LightCurrentCount)); //mixin.Mixins.Add(new ShaderClassSource("DirectLightGroupFixed", LightCurrentCount)); ShadowGroup?.ApplyShader(mixin); ShaderSource = mixin; }
public CompilerResults Compile(ShaderSource shaderSource, CompilerParameters compilerParameters) { ShaderMixinSource mixinToCompile; var shaderMixinGeneratorSource = shaderSource as ShaderMixinGeneratorSource; if (shaderMixinGeneratorSource != null) { mixinToCompile = ShaderMixinManager.Generate(shaderMixinGeneratorSource.Name, compilerParameters); } else { mixinToCompile = shaderSource as ShaderMixinSource; var shaderClassSource = shaderSource as ShaderClassSource; if (shaderClassSource != null) { mixinToCompile = new ShaderMixinSource { Name = shaderClassSource.ClassName }; mixinToCompile.Mixins.Add(shaderClassSource); } if (mixinToCompile == null) { throw new ArgumentException("Unsupported ShaderSource type [{0}]. Supporting only ShaderMixinSource/pdxfx, ShaderClassSource", "shaderSource"); } if (string.IsNullOrEmpty(mixinToCompile.Name)) { throw new ArgumentException("ShaderMixinSource must have a name", "shaderSource"); } } // Copy global parameters to used Parameters by default, as it is used by the compiler mixinToCompile.UsedParameters.Set(CompilerParameters.GraphicsPlatformKey, compilerParameters.Platform); mixinToCompile.UsedParameters.Set(CompilerParameters.GraphicsProfileKey, compilerParameters.Profile); mixinToCompile.UsedParameters.Set(CompilerParameters.DebugKey, compilerParameters.Debug); // Compile the whole mixin tree var compilerResults = new CompilerResults { Module = string.Format("EffectCompile [{0}]", mixinToCompile.Name) }; var bytecode = Compile(mixinToCompile, compilerParameters); // Since bytecode.Result is a struct, we check if any of its member has been set to know if it's valid if (bytecode.Result.CompilationLog != null || bytecode.Task != null) { if (bytecode.Result.CompilationLog != null) { bytecode.Result.CompilationLog.CopyTo(compilerResults); } compilerResults.Bytecode = bytecode; compilerResults.UsedParameters = mixinToCompile.UsedParameters; } return compilerResults; }
public void Generate(ShaderMixinSource mixin, ShaderMixinContext context) { context.Mixin(mixin, "ShaderBase"); context.Mixin(mixin, "TransformationWAndVP"); context.Mixin(mixin, "AlbedoFlatShading"); { var __mixinToCompose__ = "ComputeColorTextureCubeBasic"; var __subMixin = new ShaderMixinSource(); context.PushComposition(mixin, "albedoDiffuse", __subMixin); context.Mixin(__subMixin, __mixinToCompose__, TexturingKeys.TextureCube0); context.PopComposition(); } }
public void Generate(ShaderMixinSource mixin, ShaderMixinContext context) { context.Mixin(mixin, "A"); context.Mixin(mixin, "B"); context.Mixin(mixin, "C"); { var __mixinToCompose__ = "X"; var __subMixin = new ShaderMixinSource(); context.PushComposition(mixin, "x", __subMixin); context.Mixin(__subMixin, __mixinToCompose__); context.PopComposition(); } }
public void Generate(ShaderMixinSource mixin, ShaderMixinContext context) { context.Mixin(mixin, "SkyboxShader"); if (context.GetParam(SkyboxKeys.Shader) != null) { { var __subMixin = new ShaderMixinSource() { Parent = mixin }; context.PushComposition(mixin, "skyboxColor", __subMixin); context.Mixin(__subMixin, context.GetParam(SkyboxKeys.Shader)); context.PopComposition(); } } }
public async Task<EffectBytecodeCompilerResult> Compile(ShaderMixinSource mixinTree, CompilerParameters compilerParameters) { // Make sure we are connected // TODO: Handle reconnections, etc... var socketMessageLayer = await GetOrCreateConnection(); var shaderCompilerAnswer = (RemoteEffectCompilerEffectAnswer)await socketMessageLayer.SendReceiveAsync(new RemoteEffectCompilerEffectRequest { MixinTree = mixinTree, UsedParameters = mixinTree.UsedParameters, }); // TODO: Get LoggerResult as well return new EffectBytecodeCompilerResult(shaderCompilerAnswer.EffectBytecode); }
public void Generate(ShaderMixinSource mixin, ShaderMixinContext context) { context.Mixin(mixin, "MultiTexturesSpriteShader"); }
private void AnalyzeAndGoToDefinition(string shaderSource, Stride.Core.Shaders.Ast.SourceLocation location, List <string> shaderDirectories, ShaderNavigationResult result) { // We are not using the storage when loading shaders from VS but directly the filesystem var mixer = new ShaderMixinParser(null); mixer.SourceManager.UseFileSystem = true; mixer.AllowNonInstantiatedGenerics = true; mixer.SourceManager.LookupDirectoryList.AddRange(shaderDirectories); var shaderSourceName = Path.GetFileNameWithoutExtension(location.FileSource); mixer.SourceManager.AddShaderSource(shaderSourceName, shaderSource, location.FileSource); var mixinSource = new ShaderMixinSource(); mixinSource.Mixins.Add(new ShaderClassSource(shaderSourceName)); ShaderMixinParsingResult parsingResult; HashSet <ModuleMixinInfo> moduleMixins; var mixerResult = mixer.ParseAndAnalyze(mixinSource, null, out parsingResult, out moduleMixins); // Copy shader analysis to result parsingResult.CopyTo(result.Messages); if (mixerResult == null) { return; } var mixin = mixerResult.MixinInfos.FirstOrDefault(item => item.MixinName == shaderSourceName); if (mixin == null) { result.Messages.Error(ErrorMixinNotFound, GetSpan(location), shaderSourceName); return; } // If first line, first column, this is not a go to definition but only parsing request, so return directly if (location.Line == 1 && location.Column == 1) { return; } // var ast = mixin.MixinAst; var parsingInfo = mixin.Mixin.ParsingInfo; var pools = new List <ReferencesPool> { parsingInfo.ClassReferences, parsingInfo.StaticReferences, parsingInfo.ExternReferences, parsingInfo.StageInitReferences, }; foreach (var pool in pools) { var span = Find(pool, location); if (span.HasValue) { result.DefinitionLocation = span.Value; return; } } // Else Try to find from remaining navigable nodes foreach (var node in parsingInfo.NavigableNodes) { if (IsExpressionMatching(node, location)) { var typeReferencer = node as ITypeInferencer; if (typeReferencer != null && typeReferencer.TypeInference != null && typeReferencer.TypeInference.Declaration != null) { var declarationNode = (Node)typeReferencer.TypeInference.Declaration; result.DefinitionLocation = declarationNode.Span; break; } } } }
public void Generate(ShaderMixinSource mixin, ShaderMixinContext context) { context.Mixin(mixin, "AtmosphereMultipleScatteringTextureEffectCS", context.GetParam(AtmosphereParameters.MultiScatteringApproximationEnabled), context.GetParam(AtmosphereParameters.AtmosphereGroup)); }
public void Generate(ShaderMixinSource mixin, ShaderMixinContext context) { context.Mixin(mixin, "SimpleShader"); }
public void TestMacros() { // test that macros are correctly used var baseMixin = new ShaderMixinSource(); baseMixin.AddMacro("SILICONSTUDIO_XENKO_GRAPHICS_API_DIRECT3D", 1); baseMixin.Macros.Add(new ShaderMacro("MACRO_TEST", "int")); baseMixin.Mixins.Add(new ShaderClassSource("TestMacros")); var macros0 = new ShaderMixinSource(); macros0.Mixins.Add(new ShaderClassSource("MacroTest")); baseMixin.Compositions.Add("macros0", macros0); var macros1 = new ShaderMixinSource(); macros1.Mixins.Add(new ShaderClassSource("MacroTest")); macros1.Macros.Add(new ShaderMacro("MACRO_TEST", "float")); baseMixin.Compositions.Add("macros1", macros1); var macros2 = new ShaderMixinSource(); macros2.Mixins.Add(new ShaderClassSource("MacroTest")); macros2.Macros.Add(new ShaderMacro("MACRO_TEST", "float4")); baseMixin.Compositions.Add("macros2", macros2); var parsingResult = shaderMixinParser.Parse(baseMixin, baseMixin.Macros.ToArray()); Assert.IsFalse(parsingResult.HasErrors); var cBufferVar = parsingResult.Shader.Declarations.OfType <ConstantBuffer>().First(x => x.Name == "Globals").Members.OfType <Variable>().ToList(); Assert.AreEqual(1, cBufferVar.Count(x => x.Type.Name.Text == "int")); Assert.AreEqual(1, cBufferVar.Count(x => x.Type.Name.Text == "float")); Assert.AreEqual(1, cBufferVar.Count(x => x.Type.Name.Text == "float4")); // test clash when reloading var baseMixin2 = new ShaderMixinSource(); baseMixin2.AddMacro("SILICONSTUDIO_XENKO_GRAPHICS_API_DIRECT3D", 1); baseMixin2.Macros.Add(new ShaderMacro("MACRO_TEST", "int")); baseMixin2.Mixins.Add(new ShaderClassSource("TestMacros")); var macros3 = new ShaderMixinSource(); macros3.Mixins.Add(new ShaderClassSource("MacroTest")); baseMixin2.Compositions.Add("macros0", macros3); var macros4 = new ShaderMixinSource(); macros4.Mixins.Add(new ShaderClassSource("MacroTest")); macros4.Macros.Add(new ShaderMacro("MACRO_TEST", "uint4")); baseMixin2.Compositions.Add("macros1", macros4); var macros5 = new ShaderMixinSource(); macros5.Mixins.Add(new ShaderClassSource("MacroTest")); macros5.Macros.Add(new ShaderMacro("MACRO_TEST", "float4")); baseMixin2.Compositions.Add("macros2", macros5); var parsingResult2 = shaderMixinParser.Parse(baseMixin2, baseMixin2.Macros.ToArray()); Assert.IsFalse(parsingResult.HasErrors); var cBufferVar2 = parsingResult2.Shader.Declarations.OfType <ConstantBuffer>().First(x => x.Name == "Globals").Members.OfType <Variable>().ToList(); Assert.AreEqual(1, cBufferVar2.Count(x => x.Type.Name.Text == "int")); Assert.AreEqual(1, cBufferVar2.Count(x => x.Type.Name.Text == "uint4")); Assert.AreEqual(1, cBufferVar2.Count(x => x.Type.Name.Text == "float4")); }
public void Generate(ShaderMixinSource mixin, ShaderMixinContext context) { context.Mixin(mixin, "LambertianPrefilteringSHNoComputePass1", context.GetParam(SphericalHarmonicsParameters.HarmonicsOrder)); }
public void Generate(ShaderMixinSource mixin, ShaderMixinContext context) { context.Mixin(mixin, "ComputeShaderTest", context.GetParam(ComputeShaderTestParams.NbOfIterations)); }
internal ShaderCompilationContext ParseAndAnalyze(ShaderMixinSource shaderMixinSource, Xenko.Shaders.ShaderMacro[] macros, out ShaderMixinParsingResult parsingResult, out HashSet <ModuleMixinInfo> mixinsToAnalyze) { // Creates a parsing result parsingResult = new ShaderMixinParsingResult(); Xenko.Core.Shaders.Parser.ShaderMacro[] macrosParser; if (macros == null) { macrosParser = new Xenko.Core.Shaders.Parser.ShaderMacro[0]; } else { macrosParser = new Xenko.Core.Shaders.Parser.ShaderMacro[macros.Length]; for (var i = 0; i < macros.Length; ++i) { macrosParser[i] = new Xenko.Core.Shaders.Parser.ShaderMacro(macros[i].Name, macros[i].Definition); } } //PerformanceLogger.Start(PerformanceStage.Global); // ---------------------------------------------------------- // Load all shaders // ---------------------------------------------------------- lock (shaderLibrary) { //PerformanceLogger.Start(PerformanceStage.Loading); mixinsToAnalyze = shaderLibrary.LoadShaderSource(shaderMixinSource, macrosParser); //PerformanceLogger.Stop(PerformanceStage.Loading); } // Extract all ModuleMixinInfo and check for any errors var allMixinInfos = new HashSet <ModuleMixinInfo>(); foreach (var moduleMixinInfo in mixinsToAnalyze) { allMixinInfos.UnionWith(moduleMixinInfo.MinimalContext); } foreach (var moduleMixinInfo in allMixinInfos) { moduleMixinInfo.Log.CopyTo(parsingResult); var ast = moduleMixinInfo.MixinAst; var shaderClassSource = moduleMixinInfo.ShaderSource as ShaderClassCode; // If we have a ShaderClassSource and it is not an inline one, then we can store the hash sources if (ast != null && shaderClassSource != null) { parsingResult.HashSources[shaderClassSource.ClassName] = moduleMixinInfo.SourceHash; } } // Return directly if there was any errors if (parsingResult.HasErrors) { return(null); } // ---------------------------------------------------------- // Perform Type Analysis // ---------------------------------------------------------- //PerformanceLogger.Start(PerformanceStage.TypeAnalysis); var context = GetCompilationContext(mixinsToAnalyze, parsingResult); //PerformanceLogger.Stop(PerformanceStage.TypeAnalysis); // Return directly if there was any errors if (parsingResult.HasErrors) { return(context); } lock (SemanticAnalyzerLock) { //PerformanceLogger.Start(PerformanceStage.SemanticAnalysis); //SemanticPerformance.Start(SemanticStage.Global); foreach (var mixin in mixinsToAnalyze) { context.Analyze(mixin); } //SemanticPerformance.Pause(SemanticStage.Global); //PerformanceLogger.Stop(PerformanceStage.SemanticAnalysis); } return(context); }
/// <summary> /// Mixes shader parts to produces a single HLSL file shader. /// </summary> /// <param name="shaderMixinSource">The shader source.</param> /// <param name="macros">The shader perprocessor macros.</param> /// <param name="modifiedShaders">The list of modified shaders.</param> /// <returns>The combined shader in AST form.</returns> public ShaderMixinParsingResult Parse(ShaderMixinSource shaderMixinSource, Xenko.Shaders.ShaderMacro[] macros = null) { // Creates a parsing result HashSet <ModuleMixinInfo> mixinsToAnalyze; ShaderMixinParsingResult parsingResult; var context = ParseAndAnalyze(shaderMixinSource, macros, out parsingResult, out mixinsToAnalyze); // Return directly if there was any errors if (parsingResult.HasErrors) { return(parsingResult); } // Update the clone context in case new instances of classes are created CloneContext mixCloneContext; lock (hlslCloneContextLock) { if (hlslCloneContext == null) { hlslCloneContext = new CloneContext(); // Create the clone context with the instances of Hlsl classes HlslSemanticAnalysis.FillCloneContext(hlslCloneContext); } HlslSemanticAnalysis.UpdateCloneContext(hlslCloneContext); mixCloneContext = new CloneContext(hlslCloneContext); } // only clone once the stage classes foreach (var mixinInfo in mixinsToAnalyze) { foreach (var mixin in mixinInfo.Mixin.MinimalContext.Where(x => x.StageOnlyClass)) { mixin.DeepClone(mixCloneContext); } } // ---------------------------------------------------------- // Perform Shader Mixer // ---------------------------------------------------------- var externDict = new CompositionDictionary(); var finalModuleList = BuildCompositionsDictionary(shaderMixinSource, externDict, context, mixCloneContext, parsingResult); //PerformanceLogger.Stop(PerformanceStage.DeepClone); if (parsingResult.HasErrors) { return(parsingResult); } // look for stage compositions and add the links between variables and compositions when necessary var extraExternDict = new Dictionary <Variable, List <ModuleMixin> >(); foreach (var item in externDict) { if (item.Key.Qualifiers.Contains(XenkoStorageQualifier.Stage)) { FullLinkStageCompositions(item.Key, item.Value, externDict, extraExternDict, parsingResult); } } foreach (var item in extraExternDict) { externDict.Add(item.Key, item.Value); } var mixinDictionary = BuildMixinDictionary(finalModuleList); if (finalModuleList != null) { var finalModule = finalModuleList[0]; //PerformanceLogger.Start(PerformanceStage.Mix); parsingResult.Reflection = new EffectReflection(); var mixer = new XenkoShaderMixer(finalModule, parsingResult, mixinDictionary, externDict, new CloneContext(mixCloneContext)); mixer.Mix(); //PerformanceLogger.Stop(PerformanceStage.Mix); // Return directly if there was any errors if (parsingResult.HasErrors) { return(parsingResult); } var finalShader = mixer.GetMixedShader(); // Simplifies the shader by removing dead code var simplifier = new ExpressionSimplifierVisitor(); simplifier.Run(finalShader); var xkShaderLinker = new ShaderLinker(parsingResult); xkShaderLinker.Run(finalShader); // Return directly if there was any errors if (parsingResult.HasErrors) { return(parsingResult); } // Find all entry points // TODO: make this configurable by CompileParameters foreach (var stage in new[] { ShaderStage.Compute, ShaderStage.Vertex, ShaderStage.Hull, ShaderStage.Domain, ShaderStage.Geometry, ShaderStage.Pixel }) { var entryPoint = finalShader.Declarations.OfType <MethodDefinition>().FirstOrDefault(f => f.Attributes.OfType <AttributeDeclaration>().Any(a => a.Name == "EntryPoint" && (string)a.Parameters[0].Value == stage.ToString())); if (entryPoint == null) { continue; } parsingResult.EntryPoints[stage] = entryPoint.Name.Text; // When this is a compute shader, there is no need to scan other stages if (stage == ShaderStage.Compute) { break; } } var typeCleaner = new XenkoShaderCleaner(); typeCleaner.Run(finalShader); //PerformanceLogger.Stop(PerformanceStage.Global); //PerformanceLogger.PrintLastResult(); //SemanticPerformance.PrintResult(); //MixPerformance.PrintResult(); //GenerateShaderPerformance.PrintResult(); //StreamCreatorPerformance.PrintResult(); //ShaderLoader.PrintTime(); //PerformanceLogger.WriteOut(52); parsingResult.Shader = finalShader; } return(parsingResult); }
public void Generate(ShaderMixinSource mixin, ShaderMixinContext context) { context.Mixin(mixin, "StrideForwardShadingEffect"); context.Mixin(mixin, "MultipleRenderTargetsEffectShader"); }
/// <inheritdoc/> public override TaskOrResult <EffectBytecodeCompilerResult> Compile(ShaderMixinSource mixinTree, EffectCompilerParameters effectParameters, CompilerParameters compilerParameters = null) { return(CompileAsync(mixinTree, effectParameters)); }
public void Generate(ShaderMixinSource mixin, ShaderMixinContext context) { context.Mixin(mixin, "C1"); context.Mixin(mixin, "C2"); }
private void AddSecondarySpecularGlintsNoiseTexture(MaterialGeneratorContext context, ShaderMixinSource shaderSource) { MaterialComputeColorKeys materialComputeColorKeys = new MaterialComputeColorKeys(SecondarySpecularReflectionNoiseTexture, SecondarySpecularReflectionNoiseValue); var computeColorSource = HairSecondarySpecularGlintsNoise.GenerateShaderSource(context, materialComputeColorKeys); shaderSource.AddComposition("SecondarySpecularGlintsNoiseTexture", computeColorSource); }
private void AddSpecularHighlightsShiftNoiseTexture(MaterialGeneratorContext context, ShaderMixinSource shaderSource) { MaterialComputeColorKeys materialComputeColorKeys = new MaterialComputeColorKeys(PrimarySpecularReflectionNoiseTexture, PrimarySpecularReflectionNoiseValue); var computeColorSource = HairSpecularHighlightsShiftNoise.GenerateShaderSource(context, materialComputeColorKeys); shaderSource.AddComposition("SpecularHighlightsShiftNoiseTexture", computeColorSource); }
public void Generate(ShaderMixinSource mixin, ShaderMixinContext context) { context.Mixin(mixin, "ShaderBase"); context.Mixin(mixin, "ShadingBase"); var extensionPreVertexStageSurfaceShaders = context.GetParam(MaterialKeys.VertexStageSurfaceShaders); if (extensionPreVertexStageSurfaceShaders != null) { context.Mixin(mixin, "MaterialSurfaceVertexStageCompositor"); { var __mixinToCompose__ = (extensionPreVertexStageSurfaceShaders); var __subMixin = new ShaderMixinSource(); context.PushComposition(mixin, "materialVertexStage", __subMixin); context.Mixin(__subMixin, __mixinToCompose__); context.PopComposition(); } { var __mixinToCompose__ = context.GetParam(MaterialKeys.VertexStageStreamInitializer); var __subMixin = new ShaderMixinSource(); context.PushComposition(mixin, "streamInitializerVertexStage", __subMixin); context.Mixin(__subMixin, __mixinToCompose__); context.PopComposition(); } } context.Mixin(mixin, "TransformationBase"); context.Mixin(mixin, "NormalStream"); context.Mixin(mixin, "TransformationWAndVP"); if (context.GetParam(MaterialKeys.HasNormalMap)) { context.Mixin(mixin, "NormalFromNormalMapping"); } else { context.Mixin(mixin, "NormalFromMesh"); } if (context.GetParam(MaterialKeys.HasSkinningPosition)) { mixin.AddMacro("SkinningMaxBones", context.GetParam(MaterialKeys.SkinningMaxBones)); context.Mixin(mixin, "TransformationSkinning"); if (context.GetParam(MaterialKeys.HasSkinningNormal)) { context.Mixin(mixin, "NormalMeshSkinning"); } if (context.GetParam(MaterialKeys.HasSkinningTangent)) { context.Mixin(mixin, "TangentMeshSkinning"); } if (context.GetParam(MaterialKeys.HasSkinningNormal)) { if (context.GetParam(MaterialKeys.HasNormalMap)) { context.Mixin(mixin, "NormalVSSkinningNormalMapping"); } else { context.Mixin(mixin, "NormalVSSkinningFromMesh"); } } } var extensionTessellationShader = context.GetParam(MaterialKeys.TessellationShader); if (extensionTessellationShader != null) { context.Mixin(mixin, (extensionTessellationShader)); var extensionDomainStageSurfaceShaders = context.GetParam(MaterialKeys.DomainStageSurfaceShaders); if (extensionDomainStageSurfaceShaders != null) { context.Mixin(mixin, "MaterialSurfaceDomainStageCompositor"); { var __mixinToCompose__ = (extensionDomainStageSurfaceShaders); var __subMixin = new ShaderMixinSource(); context.PushComposition(mixin, "materialDomainStage", __subMixin); context.Mixin(__subMixin, __mixinToCompose__); context.PopComposition(); } { var __mixinToCompose__ = context.GetParam(MaterialKeys.DomainStageStreamInitializer); var __subMixin = new ShaderMixinSource(); context.PushComposition(mixin, "streamInitializerDomainStage", __subMixin); context.Mixin(__subMixin, __mixinToCompose__); context.PopComposition(); } } } var computeVelocityShader = context.GetParam(StrideEffectBaseKeys.ComputeVelocityShader); if (computeVelocityShader != null) { context.Mixin(mixin, (computeVelocityShader)); } var extensionPostVertexStage = context.GetParam(StrideEffectBaseKeys.ExtensionPostVertexStageShader); if (extensionPostVertexStage != null) { context.Mixin(mixin, (extensionPostVertexStage)); } var targetExtensions = context.GetParam(StrideEffectBaseKeys.RenderTargetExtensions); if (targetExtensions != null) { context.Mixin(mixin, (targetExtensions)); } }
private EffectBytecodeCompilerResult CompileBytecode(ShaderMixinSource mixinTree, EffectCompilerParameters effectParameters, CompilerParameters compilerParameters, ObjectId mixinObjectId, DatabaseFileProvider database, string compiledUrl) { // Open the database for writing var log = new LoggerResult(); // Note: this compiler is expected to not be async and directly write stuff in localLogger var compiledShader = base.Compile(mixinTree, effectParameters, compilerParameters).WaitForResult(); compiledShader.CompilationLog.CopyTo(log); // If there are any errors, return immediately if (log.HasErrors) { lock (compilingShaders) { compilingShaders.Remove(mixinObjectId); } return(new EffectBytecodeCompilerResult(null, log)); } // Compute the bytecodeId var newBytecodeId = compiledShader.Bytecode.ComputeId(); // Check if we really need to store the bytecode lock (bytecodes) { // Using custom serialization to the database to store an object with a custom id // TODO: Check if we really need to write the bytecode everytime even if id is not changed var memoryStream = new MemoryStream(); compiledShader.Bytecode.WriteTo(memoryStream); // Write current cache at the end (not part of the pure bytecode, but we use this as meta info) var writer = new BinarySerializationWriter(memoryStream); writer.Write(CurrentCache); memoryStream.Position = 0; database.ObjectDatabase.Write(memoryStream, newBytecodeId, true); database.AssetIndexMap[compiledUrl] = newBytecodeId; // Save bytecode Id to the database cache as well memoryStream.SetLength(0); memoryStream.Write((byte[])newBytecodeId, 0, ObjectId.HashSize); memoryStream.Position = 0; database.ObjectDatabase.Write(memoryStream, mixinObjectId, true); if (!bytecodes.ContainsKey(newBytecodeId)) { log.Verbose("New effect compiled #{0} [{1}] (db: {2})\r\n{3}", effectCompileCount, mixinObjectId, newBytecodeId, compilerParameters?.ToStringPermutationsDetailed()); Interlocked.Increment(ref effectCompileCount); // Replace or add new bytecode bytecodes[newBytecodeId] = new KeyValuePair <EffectBytecode, EffectBytecodeCacheLoadSource>(compiledShader.Bytecode, EffectBytecodeCacheLoadSource.JustCompiled); } } lock (compilingShaders) { compilingShaders.Remove(mixinObjectId); } return(compiledShader); }
public void Generate(ShaderMixinSource mixin, ShaderMixinContext context) { context.Mixin(mixin, "AtmosphereRenderSkyRayMarching", context.GetParam(AtmosphereParameters.FastSkyEnabled), context.GetParam(AtmosphereParameters.FastAerialPerspectiveEnabled), context.GetParam(AtmosphereParameters.RenderSunDisk), context.GetParam(AtmosphereParameters.MultiScatteringApproximationEnabled), context.GetParam(AtmosphereParameters.AtmosphereGroup)); }
/// <summary> /// Compiles the ShaderMixinSource into a platform bytecode. /// </summary> /// <param name="mixinTree">The mixin tree.</param> /// <param name="compilerParameters">The compiler parameters.</param> /// <returns>The platform-dependent bytecode.</returns> public abstract TaskOrResult <EffectBytecodeCompilerResult> Compile(ShaderMixinSource mixinTree, CompilerParameters compilerParameters);
public void Generate(ShaderMixinSource mixin, ShaderMixinContext context) { context.Mixin(mixin, "AtmosphereRenderScatteringCameraVolume", context.GetParam(AtmosphereParameters.MultiScatteringApproximationEnabled), context.GetParam(AtmosphereParameters.AtmosphereGroup)); }
public override ShaderSource GenerateShaderSource(MaterialGeneratorContext context, MaterialComputeColorKeys baseKeys) { if (string.IsNullOrEmpty(MixinReference)) { return(new ShaderClassSource("ComputeColor")); } var mixinName = MixinReference; object[] generics = null; if (Generics.Count > 0) { // TODO: correct generic order var mixinGenerics = new List <object>(); foreach (var genericKey in Generics.Keys) { var generic = Generics[genericKey]; if (generic is ComputeColorParameterTexture) { var textureParameter = ((ComputeColorParameterTexture)generic); var textureKey = context.GetTextureKey(textureParameter.Texture, baseKeys); mixinGenerics.Add(textureKey.ToString()); } else if (generic is ComputeColorParameterSampler) { var pk = context.GetSamplerKey((ComputeColorParameterSampler)generic); mixinGenerics.Add(pk.ToString()); } else if (generic is ComputeColorParameterFloat) { mixinGenerics.Add(((ComputeColorParameterFloat)generic).Value.ToString(CultureInfo.InvariantCulture)); } else if (generic is ComputeColorParameterInt) { mixinGenerics.Add(((ComputeColorParameterInt)generic).Value.ToString(CultureInfo.InvariantCulture)); } else if (generic is ComputeColorParameterFloat2) { mixinGenerics.Add(MaterialUtility.GetAsShaderString(((ComputeColorParameterFloat2)generic).Value)); } else if (generic is ComputeColorParameterFloat3) { mixinGenerics.Add(MaterialUtility.GetAsShaderString(((ComputeColorParameterFloat3)generic).Value)); } else if (generic is ComputeColorParameterFloat4) { mixinGenerics.Add(MaterialUtility.GetAsShaderString(((ComputeColorParameterFloat4)generic).Value)); } else if (generic is ComputeColorStringParameter) { mixinGenerics.Add(((ComputeColorStringParameter)generic).Value); } else { throw new Exception("[Material] Unknown node type: " + generic.GetType()); } } generics = mixinGenerics.ToArray(); } var shaderClassSource = new ShaderClassSource(mixinName, generics); if (CompositionNodes.Count == 0) { return(shaderClassSource); } var mixin = new ShaderMixinSource(); mixin.Mixins.Add(shaderClassSource); foreach (var comp in CompositionNodes) { if (comp.Value != null) { var compShader = comp.Value.GenerateShaderSource(context, baseKeys); if (compShader != null) { mixin.Compositions.Add(comp.Key, compShader); } } } return(mixin); }
public override TaskOrResult <EffectBytecodeCompilerResult> Compile(ShaderMixinSource mixinTree, EffectCompilerParameters effectParameters, CompilerParameters compilerParameters = null) { throw new NotSupportedException("Shader Compilation is not allowed at run time on this platform."); }
public void Generate(ShaderMixinSource mixin, ShaderMixinContext context) { context.Mixin(mixin, "RadiancePrefilteringGGXNoComputeShader", context.GetParam(RadiancePrefilteringGGXNoComputeParams.NbOfSamplings)); }
public override TaskOrResult <EffectBytecodeCompilerResult> Compile(ShaderMixinSource mixin, EffectCompilerParameters effectParameters, CompilerParameters compilerParameters) { var database = (FileProvider ?? ContentManager.FileProvider) as DatabaseFileProvider; if (database == null) { throw new NotSupportedException("Using the cache requires to ContentManager.FileProvider to be valid."); } // Forward DatabaseFileProvider to actual compiler here // Since we might be in a Task, it has to be forwarded manually (otherwise MicroThreadLocal ones wouldn't work during build) // Note: this system might need an overhaul... (too many states?) base.FileProvider = database; var usedParameters = compilerParameters; var mixinObjectId = ShaderMixinObjectId.Compute(mixin, usedParameters.EffectParameters); // Final url of the compiled bytecode var compiledUrl = string.Format("{0}/{1}", CompiledShadersKey, mixinObjectId); var bytecode = new KeyValuePair <EffectBytecode, EffectBytecodeCacheLoadSource>(null, EffectBytecodeCacheLoadSource.JustCompiled); lock (bytecodes) { // ------------------------------------------------------------------------------------------------------------ // 1) Try to load latest bytecode // ------------------------------------------------------------------------------------------------------------ ObjectId bytecodeId; if (database.AssetIndexMap.TryGetValue(compiledUrl, out bytecodeId)) { bytecode = LoadEffectBytecode(database, bytecodeId); } // On non Windows platform, we are expecting to have the bytecode stored directly if (Compiler is NullEffectCompiler && bytecode.Key == null) { var stringBuilder = new StringBuilder(); stringBuilder.AppendFormat("Unable to find compiled shaders [{0}] for mixin [{1}] with parameters [{2}]", compiledUrl, mixin, usedParameters.ToStringPermutationsDetailed()); Log.Error(stringBuilder.ToString()); throw new InvalidOperationException(stringBuilder.ToString()); } // ------------------------------------------------------------------------------------------------------------ // 2) Try to load from database cache // ------------------------------------------------------------------------------------------------------------ if (bytecode.Key == null && database.ObjectDatabase.Exists(mixinObjectId)) { using (var stream = database.ObjectDatabase.OpenStream(mixinObjectId)) { // We have an existing stream, make sure the shader is compiled var objectIdBuffer = new byte[ObjectId.HashSize]; if (stream.Read(objectIdBuffer, 0, ObjectId.HashSize) == ObjectId.HashSize) { var newBytecodeId = new ObjectId(objectIdBuffer); bytecode = LoadEffectBytecode(database, newBytecodeId); if (bytecode.Key != null) { // If we successfully retrieved it from cache, add it to index map so that it won't be collected and available for faster lookup database.AssetIndexMap[compiledUrl] = newBytecodeId; } } } } } if (bytecode.Key != null) { return(new EffectBytecodeCompilerResult(bytecode.Key, bytecode.Value)); } // ------------------------------------------------------------------------------------------------------------ // 3) Compile the shader // ------------------------------------------------------------------------------------------------------------ lock (compilingShaders) { Task <EffectBytecodeCompilerResult> compilingShaderTask; if (compilingShaders.TryGetValue(mixinObjectId, out compilingShaderTask)) { // Note: Task might still be compiling return(compilingShaderTask); } // Compile the mixin in a Task if (CompileEffectAsynchronously) { var compilerParametersCopy = compilerParameters != null ? new CompilerParameters(compilerParameters) : null; var resultTask = Task.Factory.StartNew(() => CompileBytecode(mixin, effectParameters, compilerParametersCopy, mixinObjectId, database, compiledUrl), CancellationToken.None, TaskCreationOptions.None, taskSchedulerSelector != null ? taskSchedulerSelector(mixin, compilerParametersCopy.EffectParameters) : TaskScheduler.Default); compilingShaders.Add(mixinObjectId, resultTask); return(resultTask); } else { return(CompileBytecode(mixin, effectParameters, compilerParameters, mixinObjectId, database, compiledUrl)); } } }
public CompilerThread(EffectCompiler compiler, ShaderMixinSource source) { effectCompiler = compiler; mixinSource = source; }
protected virtual void GenerateShaderCompositions(MaterialGeneratorContext context, ShaderMixinSource shaderSource) { if (Fresnel != null) { shaderSource.AddComposition("fresnelFunction", Fresnel.Generate(context)); } if (Visibility != null) { shaderSource.AddComposition("geometricShadowingFunction", Visibility.Generate(context)); } if (NormalDistribution != null) { shaderSource.AddComposition("normalDistributionFunction", NormalDistribution.Generate(context)); } if (Environment != null) { shaderSource.AddComposition("environmentFunction", Environment.Generate(context)); } }
public void PopLayer() { // If current shading model is not set, if (CurrentShadingModel == null && Current.ShadingModels.Count > 0) { CurrentShadingModel = Current.ShadingModels; } var sameShadingModel = Current.ShadingModels.Equals(CurrentShadingModel); if (!sameShadingModel) { shadingModelCount++; } var shouldBlendShadingModels = CurrentShadingModel != null && (!sameShadingModel || Current.Parent == null); // current shading model different from next shading model // -------------------------------------------------------------------- // Copy the shading surfaces and the stream initializer to the parent. // -------------------------------------------------------------------- if (Current.Parent != null) { foreach (MaterialShaderStage stage in Enum.GetValues(typeof(MaterialShaderStage))) { // the initializers Current.Parent.StreamInitializers[stage].AddRange(Current.StreamInitializers[stage]); // skip pixel shader if shading model need to be blended if (stage == MaterialShaderStage.Pixel && shouldBlendShadingModels) { continue; } // the surface shaders Current.Parent.SurfaceShaders[stage].AddRange(Current.SurfaceShaders[stage]); } } // ------------------------------------------------- // Blend shading models between layers if necessary // ------------------------------------------------- if (shouldBlendShadingModels) { var shadingSources = CurrentShadingModel.Generate(this); // If we are in a multi-shading-blending, only blend shading models after 1st shading model if (shadingModelCount > 1) { var shaderBlendingSource = new ShaderMixinSource(); shaderBlendingSource.Mixins.Add(new ShaderClassSource("MaterialSurfaceBlendShading")); foreach (var shaderSource in shadingSources) { shaderBlendingSource.AddCompositionToArray("layers", shaderSource); } shadingSources = new List <ShaderSource>() { shaderBlendingSource }; } var currentOrParentLayer = Current.Parent ?? Current; foreach (var shaderSource in shadingSources) { currentOrParentLayer.SurfaceShaders[MaterialShaderStage.Pixel].Add(shaderSource); } } // In case of the root material, add all stream modifiers just at the end and call final callbacks if (Current.Parent == null) { foreach (var modifierKey in inputStreamModifiers.Keys) { Current.SurfaceShaders[modifierKey.Key].Add(inputStreamModifiers[modifierKey]); } // Clear final callback foreach (var callbackKeyPair in finalCallbacks) { var stage = callbackKeyPair.Key; var callbacks = callbackKeyPair.Value; foreach (var callback in callbacks) { callback(stage, this); } callbacks.Clear(); } } // ---------------------------------------------- // Pop to Parent and set Current // ---------------------------------------------- if (Current.Parent != null && !sameShadingModel) { CurrentShadingModel = Current.ShadingModels; } if (Current.Parent != null) { Current = Current.Parent; } }
public void Generate(ShaderMixinSource mixin, ShaderMixinContext context) { context.Mixin(mixin, "ParadoxEffectBase"); context.Mixin(mixin, "MaterialFrontBackBlendShader", context.GetParam(MaterialFrontBackBlendShaderKeys.UseNormalBackFace)); }
public override TaskOrResult <EffectBytecodeCompilerResult> Compile(ShaderMixinSource mixinTree, EffectCompilerParameters effectParameters, CompilerParameters compilerParameters) { var log = new LoggerResult(); // Load D3D compiler dll // Note: No lock, it's probably fine if it gets called from multiple threads at the same time. if (Platform.IsWindowsDesktop && !d3dCompilerLoaded) { NativeLibrary.PreloadLibrary("d3dcompiler_47.dll"); d3dCompilerLoaded = true; } var shaderMixinSource = mixinTree; var fullEffectName = mixinTree.Name; // Make a copy of shaderMixinSource. Use deep clone since shaderMixinSource can be altered during compilation (e.g. macros) var shaderMixinSourceCopy = new ShaderMixinSource(); shaderMixinSourceCopy.DeepCloneFrom(shaderMixinSource); shaderMixinSource = shaderMixinSourceCopy; // Generate platform-specific macros switch (effectParameters.Platform) { case GraphicsPlatform.Direct3D11: shaderMixinSource.AddMacro("SILICONSTUDIO_XENKO_GRAPHICS_API_DIRECT3D", 1); shaderMixinSource.AddMacro("SILICONSTUDIO_XENKO_GRAPHICS_API_DIRECT3D11", 1); break; case GraphicsPlatform.Direct3D12: shaderMixinSource.AddMacro("SILICONSTUDIO_XENKO_GRAPHICS_API_DIRECT3D", 1); shaderMixinSource.AddMacro("SILICONSTUDIO_XENKO_GRAPHICS_API_DIRECT3D12", 1); break; case GraphicsPlatform.OpenGL: shaderMixinSource.AddMacro("SILICONSTUDIO_XENKO_GRAPHICS_API_OPENGL", 1); shaderMixinSource.AddMacro("SILICONSTUDIO_XENKO_GRAPHICS_API_OPENGLCORE", 1); break; case GraphicsPlatform.OpenGLES: shaderMixinSource.AddMacro("SILICONSTUDIO_XENKO_GRAPHICS_API_OPENGL", 1); shaderMixinSource.AddMacro("SILICONSTUDIO_XENKO_GRAPHICS_API_OPENGLES", 1); break; case GraphicsPlatform.Vulkan: shaderMixinSource.AddMacro("SILICONSTUDIO_XENKO_GRAPHICS_API_VULKAN", 1); break; default: throw new NotSupportedException(); } // Generate profile-specific macros shaderMixinSource.AddMacro("SILICONSTUDIO_XENKO_GRAPHICS_PROFILE", (int)effectParameters.Profile); shaderMixinSource.AddMacro("GRAPHICS_PROFILE_LEVEL_9_1", (int)GraphicsProfile.Level_9_1); shaderMixinSource.AddMacro("GRAPHICS_PROFILE_LEVEL_9_2", (int)GraphicsProfile.Level_9_2); shaderMixinSource.AddMacro("GRAPHICS_PROFILE_LEVEL_9_3", (int)GraphicsProfile.Level_9_3); shaderMixinSource.AddMacro("GRAPHICS_PROFILE_LEVEL_10_0", (int)GraphicsProfile.Level_10_0); shaderMixinSource.AddMacro("GRAPHICS_PROFILE_LEVEL_10_1", (int)GraphicsProfile.Level_10_1); shaderMixinSource.AddMacro("GRAPHICS_PROFILE_LEVEL_11_0", (int)GraphicsProfile.Level_11_0); shaderMixinSource.AddMacro("GRAPHICS_PROFILE_LEVEL_11_1", (int)GraphicsProfile.Level_11_1); shaderMixinSource.AddMacro("GRAPHICS_PROFILE_LEVEL_11_2", (int)GraphicsProfile.Level_11_2); // In .xksl, class has been renamed to shader to avoid ambiguities with HLSL shaderMixinSource.AddMacro("class", "shader"); var parsingResult = GetMixinParser().Parse(shaderMixinSource, shaderMixinSource.Macros.ToArray()); // Copy log from parser results to output CopyLogs(parsingResult, log); // Return directly if there are any errors if (parsingResult.HasErrors) { return(new EffectBytecodeCompilerResult(null, log)); } // Convert the AST to HLSL var writer = new SiliconStudio.Shaders.Writer.Hlsl.HlslWriter { EnablePreprocessorLine = false // Allow to output links to original pdxsl via #line pragmas }; writer.Visit(parsingResult.Shader); var shaderSourceText = writer.Text; if (string.IsNullOrEmpty(shaderSourceText)) { log.Error("No code generated for effect [{0}]", fullEffectName); return(new EffectBytecodeCompilerResult(null, log)); } // ------------------------------------------------------- // Save shader log // TODO: TEMP code to allow debugging generated shaders on Windows Desktop #if SILICONSTUDIO_PLATFORM_WINDOWS_DESKTOP var shaderId = ObjectId.FromBytes(Encoding.UTF8.GetBytes(shaderSourceText)); var logDir = Path.Combine(Directory.GetCurrentDirectory(), "log"); if (!Directory.Exists(logDir)) { Directory.CreateDirectory(logDir); } var shaderSourceFilename = Path.Combine(logDir, "shader_" + fullEffectName.Replace('.', '_') + "_" + shaderId + ".hlsl"); lock (WriterLock) // protect write in case the same shader is created twice { // Write shader before generating to make sure that we are having a trace before compiling it (compiler may crash...etc.) if (!File.Exists(shaderSourceFilename)) { File.WriteAllText(shaderSourceFilename, shaderSourceText); } } #else string shaderSourceFilename = null; #endif // ------------------------------------------------------- var bytecode = new EffectBytecode { Reflection = parsingResult.Reflection, HashSources = parsingResult.HashSources }; // Select the correct backend compiler IShaderCompiler compiler; switch (effectParameters.Platform) { #if SILICONSTUDIO_PLATFORM_WINDOWS case GraphicsPlatform.Direct3D11: case GraphicsPlatform.Direct3D12: compiler = new Direct3D.ShaderCompiler(); break; #endif case GraphicsPlatform.OpenGL: case GraphicsPlatform.OpenGLES: case GraphicsPlatform.Vulkan: // get the number of render target outputs var rtOutputs = 0; var psOutput = parsingResult.Shader.Declarations.OfType <StructType>().FirstOrDefault(x => x.Name.Text == "PS_OUTPUT"); if (psOutput != null) { foreach (var rto in psOutput.Fields) { var sem = rto.Qualifiers.OfType <Semantic>().FirstOrDefault(); if (sem != null) { // special case SV_Target if (rtOutputs == 0 && sem.Name.Text == "SV_Target") { rtOutputs = 1; break; } for (var i = rtOutputs; i < 8; ++i) { if (sem.Name.Text == ("SV_Target" + i)) { rtOutputs = i + 1; break; } } } } } compiler = new OpenGL.ShaderCompiler(rtOutputs); break; default: throw new NotSupportedException(); } var shaderStageBytecodes = new List <ShaderBytecode>(); #if SILICONSTUDIO_PLATFORM_WINDOWS_DESKTOP var stageStringBuilder = new StringBuilder(); #endif // if the shader (non-compute) does not have a pixel shader, we should add it for OpenGL and OpenGL ES. if ((effectParameters.Platform == GraphicsPlatform.OpenGL || effectParameters.Platform == GraphicsPlatform.OpenGLES) && !parsingResult.EntryPoints.ContainsKey(ShaderStage.Pixel) && !parsingResult.EntryPoints.ContainsKey(ShaderStage.Compute)) { parsingResult.EntryPoints.Add(ShaderStage.Pixel, null); } foreach (var stageBinding in parsingResult.EntryPoints) { // Compile // TODO: We could compile stages in different threads to improve compiler throughput? var result = compiler.Compile(shaderSourceText, stageBinding.Value, stageBinding.Key, effectParameters, bytecode.Reflection, shaderSourceFilename); result.CopyTo(log); if (result.HasErrors) { continue; } // ------------------------------------------------------- // Append bytecode id to shader log #if SILICONSTUDIO_PLATFORM_WINDOWS_DESKTOP stageStringBuilder.AppendLine("@G {0} => {1}".ToFormat(stageBinding.Key, result.Bytecode.Id)); if (result.DisassembleText != null) { stageStringBuilder.Append(result.DisassembleText); } #endif // ------------------------------------------------------- shaderStageBytecodes.Add(result.Bytecode); // When this is a compute shader, there is no need to scan other stages if (stageBinding.Key == ShaderStage.Compute) { break; } } // Remove unused reflection data, as it is entirely resolved at compile time. CleanupReflection(bytecode.Reflection); bytecode.Stages = shaderStageBytecodes.ToArray(); #if SILICONSTUDIO_PLATFORM_WINDOWS_DESKTOP lock (WriterLock) // protect write in case the same shader is created twice { var builder = new StringBuilder(); builder.AppendLine("/**************************"); builder.AppendLine("***** Compiler Parameters *****"); builder.AppendLine("***************************"); builder.Append("@P EffectName: "); builder.AppendLine(fullEffectName ?? ""); builder.Append(compilerParameters?.ToStringPermutationsDetailed()); builder.AppendLine("***************************"); if (bytecode.Reflection.ConstantBuffers.Count > 0) { builder.AppendLine("**** ConstantBuffers ****"); builder.AppendLine("***************************"); foreach (var cBuffer in bytecode.Reflection.ConstantBuffers) { builder.AppendFormat("cbuffer {0} [Size: {1}]", cBuffer.Name, cBuffer.Size).AppendLine(); foreach (var parameter in cBuffer.Members) { builder.AppendFormat("@C {0} => {1}", parameter.RawName, parameter.KeyInfo.KeyName).AppendLine(); } } builder.AppendLine("***************************"); } if (bytecode.Reflection.ResourceBindings.Count > 0) { builder.AppendLine("****** Resources ******"); builder.AppendLine("***************************"); foreach (var resource in bytecode.Reflection.ResourceBindings) { builder.AppendFormat("@R {0} => {1} [Stage: {2}, Slot: ({3}-{4})]", resource.RawName, resource.KeyInfo.KeyName, resource.Stage, resource.SlotStart, resource.SlotStart + resource.SlotCount - 1).AppendLine(); } builder.AppendLine("***************************"); } if (bytecode.HashSources.Count > 0) { builder.AppendLine("***** Sources *****"); builder.AppendLine("***************************"); foreach (var hashSource in bytecode.HashSources) { builder.AppendFormat("@S {0} => {1}", hashSource.Key, hashSource.Value).AppendLine(); } builder.AppendLine("***************************"); } if (bytecode.Stages.Length > 0) { builder.AppendLine("***** Stages *****"); builder.AppendLine("***************************"); builder.Append(stageStringBuilder); builder.AppendLine("***************************"); } builder.AppendLine("*************************/"); // Re-append the shader with all informations builder.Append(shaderSourceText); File.WriteAllText(shaderSourceFilename, builder.ToString()); } #endif return(new EffectBytecodeCompilerResult(bytecode, log)); }
private async Task <EffectBytecodeCompilerResult> CompileAsync(ShaderMixinSource mixinTree, EffectCompilerParameters effectParameters) { return(await remoteEffectCompilerClient.Compile(mixinTree, effectParameters)); }
public void TestDefaultValuesBeingPresentInReflection() { Init(); var shaderClassName = "DefaultValuesTest"; var variables = new List <(string name, string type, string value, object clrValue)>(); variables.Add((name: "floatVar", type: "float", value: "1", clrValue: 1f)); variables.Add((name: "doubleVar", type: "double", value: "1", clrValue: 1d)); variables.Add((name: "intVar", type: "int", value: "1", clrValue: 1)); variables.Add((name: "uintVar", type: "uint", value: "1", clrValue: 1u)); variables.Add((name: "boolVar", type: "bool", value: "true", clrValue: true)); AddVectorVariable(VectorType.Float2, 1f, Vector2.One); AddVectorVariable(VectorType.Float3, 1f, Vector3.One); AddVectorVariable(VectorType.Float4, 1f, Vector4.One); AddVectorVariable(VectorType.Double2, 1d, Double2.One); AddVectorVariable(VectorType.Double3, 1d, Double3.One); AddVectorVariable(VectorType.Double4, 1d, Double4.One); // error X3650: global variables cannot use the 'half' type in vs_5_0. To treat this variable as a float, use the backwards compatibility flag. //AddVectorVariable(VectorType.Half2, (Half)1f, Half2.One); //AddVectorVariable(VectorType.Half3, (Half)1f, Half3.One); //AddVectorVariable(VectorType.Half4, (Half)1f, Half4.One); AddVectorVariable(VectorType.Int2, 1, Int2.One); AddVectorVariable(VectorType.Int3, 1, Int3.One); AddVectorVariable(VectorType.Int4, 1, Int4.One); AddVectorVariable(VectorType.UInt4, 1u, UInt4.One); AddVectorVariable(new MatrixType(ScalarType.Float, 4, 4), 1f, new Matrix(1f)); var assignments = new StringBuilder(); foreach (var v in variables) { assignments.AppendLine($"{v.type} {v.name} = {v.value};"); } var mixinSource = new ShaderMixinSource() { Name = shaderClassName }; mixinSource.Mixins.Add(CreateShaderClassCode(shaderClassName, assignments.ToString())); var byteCodeTask = Compiler.Compile(mixinSource, MixinParameters.EffectParameters, MixinParameters); Assert.False(byteCodeTask.Result.CompilationLog.HasErrors); var byteCode = byteCodeTask.Result.Bytecode; var members = byteCode.Reflection.ConstantBuffers[0].Members; foreach (var v in variables) { var defaultValue = members.FirstOrDefault(k => k.KeyInfo.KeyName == $"{shaderClassName}.{v.name}").DefaultValue; Assert.NotNull(defaultValue); Assert.Equal(v.clrValue, defaultValue); } unsafe void AddVectorVariable <TVector, TComponent>(TypeBase type, TComponent scalarValue, TVector vectorValue) where TVector : unmanaged where TComponent : unmanaged { var name = $"{typeof(TVector).Name}Var"; var dimension = sizeof(TVector) / sizeof(TComponent); var components = string.Join(", ", Enumerable.Repeat(scalarValue, dimension)); variables.Add(( name: name, type: type.ToString(), value: $"{type}({components})", clrValue: vectorValue)); variables.Add(( name: $"{name}_Promoted", type: type.ToString(), value: $"{scalarValue}", clrValue: vectorValue)); variables.Add(( name: $"{name}_Array", type: type.ToString(), value: $"{{{components}}}", clrValue: vectorValue)); var aliasType = type is MatrixType m ? $"{m.Type}{m.RowCount}x{m.ColumnCount}" : type is VectorType v ? $"{v.Type}{v.Dimension}" : default; if (aliasType != null) { // Check type alias like float4 for vector<float, 4> variables.Add(( name: $"{name}_Alias", type: aliasType, value: $"{{{components}}}", clrValue: vectorValue)); } } }