/// <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, Stride.Core.Shaders.Parser.ShaderMacro[] macros, string macrosString = null) { if (macros == null) { macros = new Stride.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); }
/// <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 Stride.Core.Shaders.Parser.ShaderMacro[] MergeMacroSets(ShaderMixinSource mixin, Stride.Core.Shaders.Parser.ShaderMacro[] macros) { var newMacros = new List <Stride.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 Stride.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()); }
internal ShaderCompilationContext ParseAndAnalyze(ShaderMixinSource shaderMixinSource, Stride.Shaders.ShaderMacro[] macros, out ShaderMixinParsingResult parsingResult, out HashSet <ModuleMixinInfo> mixinsToAnalyze) { // Creates a parsing result parsingResult = new ShaderMixinParsingResult(); Stride.Core.Shaders.Parser.ShaderMacro[] macrosParser; if (macros == null) { macrosParser = new Stride.Core.Shaders.Parser.ShaderMacro[0]; } else { macrosParser = new Stride.Core.Shaders.Parser.ShaderMacro[macros.Length]; for (var i = 0; i < macros.Length; ++i) { macrosParser[i] = new Stride.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); }