Пример #1
0
 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();
                }
            }
Пример #6
0
            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;
        }
Пример #8
0
            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();
                    }
                }
            }
Пример #10
0
        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);
        }
Пример #11
0
 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));
 }
Пример #12
0
        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"));
        }
Пример #13
0
 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");
 }
Пример #15
0
            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();
                }
            }
Пример #16
0
 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");
     }
 }
Пример #18
0
 /// <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);
     }
 }
Пример #19
0
 public void Generate(ShaderMixinSource mixin, ShaderMixinContext context)
 {
     if (context.GetParam(CustomShaderKeys.SwitchEffectLevel) < 10)
     {
         context.Mixin(mixin, "CustomShader");
     }
     else
     {
         context.Mixin(mixin, "CustomShader2");
     }
 }
Пример #20
0
            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);
     }
 }
Пример #25
0
            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;
            }
Пример #26
0
        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;
        }
Пример #27
0
            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();
                }
            }
Пример #28
0
            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();
                }
            }
Пример #29
0
            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();
                    }
                }
            }
Пример #30
0
        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);
        }
Пример #31
0
 public void Generate(ShaderMixinSource mixin, ShaderMixinContext context)
 {
     context.Mixin(mixin, "MultiTexturesSpriteShader");
 }
Пример #32
0
        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));
 }
Пример #34
0
 public void Generate(ShaderMixinSource mixin, ShaderMixinContext context)
 {
     context.Mixin(mixin, "SimpleShader");
 }
Пример #35
0
        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));
 }
Пример #37
0
 public void Generate(ShaderMixinSource mixin, ShaderMixinContext context)
 {
     context.Mixin(mixin, "ComputeShaderTest", context.GetParam(ComputeShaderTestParams.NbOfIterations));
 }
Пример #38
0
        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);
        }
Пример #39
0
        /// <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);
        }
Пример #40
0
 public void Generate(ShaderMixinSource mixin, ShaderMixinContext context)
 {
     context.Mixin(mixin, "StrideForwardShadingEffect");
     context.Mixin(mixin, "MultipleRenderTargetsEffectShader");
 }
Пример #41
0
 /// <inheritdoc/>
 public override TaskOrResult <EffectBytecodeCompilerResult> Compile(ShaderMixinSource mixinTree, EffectCompilerParameters effectParameters, CompilerParameters compilerParameters = null)
 {
     return(CompileAsync(mixinTree, effectParameters));
 }
Пример #42
0
 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);
        }
Пример #45
0
            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));
                }
            }
Пример #46
0
        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));
 }
Пример #48
0
 /// <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));
 }
Пример #50
0
        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);
        }
Пример #51
0
 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));
 }
Пример #53
0
        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));
                }
            }
        }
Пример #54
0
 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));
            }
        }
Пример #56
0
        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;
            }
        }
Пример #57
0
 public void Generate(ShaderMixinSource mixin, ShaderMixinContext context)
 {
     context.Mixin(mixin, "ParadoxEffectBase");
     context.Mixin(mixin, "MaterialFrontBackBlendShader", context.GetParam(MaterialFrontBackBlendShaderKeys.UseNormalBackFace));
 }
Пример #58
0
        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));
        }
Пример #59
0
 private async Task <EffectBytecodeCompilerResult> CompileAsync(ShaderMixinSource mixinTree, EffectCompilerParameters effectParameters)
 {
     return(await remoteEffectCompilerClient.Compile(mixinTree, effectParameters));
 }
Пример #60
0
        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));
                }
            }
        }