示例#1
0
        /// <summary>
        /// Get the ModuleMixinInfo based on the ShaderSource and the macros. Creates the needed shader if necessary
        /// </summary>
        /// <param name="shaderSource">the ShaderSource</param>
        /// <param name="macros">the macros</param>
        /// <param name="macrosString">the name of the macros</param>
        /// <returns>ModuleMixinInfo.</returns>
        private ModuleMixinInfo GetModuleMixinInfo(ShaderSource shaderSource, Xenko.Core.Shaders.Parser.ShaderMacro[] macros, string macrosString = null)
        {
            if (macros == null)
            {
                macros = new Xenko.Core.Shaders.Parser.ShaderMacro[0];
            }

            if (macrosString == null)
            {
                macrosString = string.Join(",", macros.OrderBy(x => x.Name));
            }

            List <ModuleMixinInfo> context;

            if (!mapMacrosToMixins.TryGetValue(macrosString, out context))
            {
                context = new List <ModuleMixinInfo>();
                mapMacrosToMixins.Add(macrosString, context);
            }

            var mixinInfo = context.FirstOrDefault(x => x.AreEqual(shaderSource, macros));

            if (mixinInfo == null)
            {
                mixinInfo = BuildMixinInfo(shaderSource, macros);

                if (mixinInfo.Instanciated)
                {
                    MixinInfos.Add(mixinInfo);
                    mapMacrosToMixins[macrosString].Add(mixinInfo);

                    mixinInfo.MinimalContext.Add(mixinInfo);

                    if (!mixinInfo.Log.HasErrors)
                    {
                        LoadNecessaryShaders(mixinInfo, macros, macrosString);
                    }
                    mixinInfo.MinimalContext = new HashSet <ModuleMixinInfo>(mixinInfo.MinimalContext.Distinct());
                }
            }

            return(mixinInfo);
        }
示例#2
0
        /// <summary>
        /// Merge the set of macros in the mixin. The top level macros are always overidden by the child's ones (the one defined in the current ShaderMixinSource).
        /// Also update the macros of the mixin.
        /// </summary>
        /// <param name="mixin">The mixin that will be looked at with the macros.</param>
        /// <param name="macros">The external macros.</param>
        /// <returns>An array with all the macros</returns>
        private Xenko.Core.Shaders.Parser.ShaderMacro[] MergeMacroSets(ShaderMixinSource mixin, Xenko.Core.Shaders.Parser.ShaderMacro[] macros)
        {
            var newMacros = new List <Xenko.Core.Shaders.Parser.ShaderMacro>();

            // get the parent macros
            foreach (var macro in macros)
            {
                newMacros.RemoveAll(x => x.Name == macro.Name);
                newMacros.Add(macro);
            }

            // override with child macros, the mixin's ones
            foreach (var macro in mixin.Macros)
            {
                newMacros.RemoveAll(x => x.Name == macro.Name);
                var tempMacro = new Xenko.Core.Shaders.Parser.ShaderMacro(macro.Name, macro.Definition);
                newMacros.Add(tempMacro);
            }

            mixin.Macros = newMacros.Select(x => new ShaderMacro(x.Name, x.Definition)).ToList();
            return(newMacros.ToArray());
        }
示例#3
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 ShaderClassSource;
                // 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);
        }