4 using System.Collections.Generic;
6 using System.Security.Cryptography.X509Certificates;
8 using SiliconStudio.Paradox.Shaders.Parser.Ast;
9 using SiliconStudio.Paradox.Shaders.Parser.Mixins;
10 using SiliconStudio.Paradox.Shaders.Parser.Performance;
11 using SiliconStudio.Shaders.Analysis.Hlsl;
12 using SiliconStudio.Shaders.Ast;
13 using SiliconStudio.Shaders.Ast.Hlsl;
14 using SiliconStudio.Shaders.Utility;
16 namespace SiliconStudio.
Paradox.Shaders.Parser
23 #region Private members
28 private readonly
static Object PreprocessLock =
new Object();
33 private readonly
static Object SemanticAnalyzerLock =
new Object();
43 private readonly ParadoxShaderLibrary shaderLibrary;
47 #region Public members
64 var shaderLoader =
new ShaderLoader(SourceManager);
66 if (shaderLibrary == null)
68 shaderLibrary =
new ParadoxShaderLibrary(shaderLoader);
72 HlslSemanticAnalysis.FillCloneContext(hlslCloneContext);
85 shaderLibrary.DeleteObsoleteCache(modifiedShaders);
104 shaderLibrary.ModifiedShaders = modifiedShaders;
117 for (var i = 0; i < macros.Length; ++i)
118 macrosParser[i] =
new SiliconStudio.Shaders.Parser.
ShaderMacro(macros[i].Name, macros[i].Definition);
125 HashSet<ModuleMixinInfo> mixinsToAnalyze;
129 mixinsToAnalyze = shaderLibrary.LoadShaderSource(shaderMixinSource, macrosParser);
134 var allMixinInfos =
new HashSet<ModuleMixinInfo>();
135 foreach (var moduleMixinInfo
in mixinsToAnalyze)
137 allMixinInfos.UnionWith(moduleMixinInfo.MinimalContext);
139 foreach (var moduleMixinInfo
in allMixinInfos)
141 moduleMixinInfo.Log.CopyTo(parsingResult);
143 var ast = moduleMixinInfo.MixinAst;
145 if (ast != null && shaderClassSource != null)
147 var sourcePath = SourceManager.FindFilePath(shaderClassSource.ClassName);
148 if (sourcePath == null)
149 throw new InvalidOperationException(
string.Format(
"Can't find source path for class {0}", shaderClassSource.ClassName));
150 parsingResult.HashSources[sourcePath] = ast.SourceHash;
155 if (parsingResult.HasErrors)
156 return parsingResult;
162 var context = GetCompilationContext(mixinsToAnalyze, parsingResult);
166 if (parsingResult.HasErrors)
167 return parsingResult;
169 lock (SemanticAnalyzerLock)
173 foreach (var mixin
in mixinsToAnalyze)
174 context.Analyze(mixin);
180 if (parsingResult.HasErrors)
181 return parsingResult;
184 lock (hlslCloneContext)
186 HlslSemanticAnalysis.UpdateCloneContext(hlslCloneContext);
190 var mixCloneContext =
new CloneContext(hlslCloneContext);
191 foreach (var mixinInfo
in mixinsToAnalyze)
193 foreach (var mixin
in mixinInfo.Mixin.MinimalContext.Where(x => x.StageOnlyClass))
195 mixin.DeepClone(mixCloneContext);
202 var externDict =
new Dictionary<Variable, List<ModuleMixin>>();
203 var finalModuleList = BuildCompositionsDictionary(shaderMixinSource, externDict, context, mixCloneContext);
205 var mixinDictionary = BuildMixinDictionary(finalModuleList);
207 if (finalModuleList != null)
209 var finalModule = finalModuleList[0];
211 var mixer =
new ParadoxShaderMixer(finalModule, parsingResult, mixinDictionary, externDict,
new CloneContext(mixCloneContext));
216 if (parsingResult.HasErrors)
217 return parsingResult;
219 var finalShader = mixer.GetMixedShader();
222 var pdxShaderLinker =
new ShaderLinker(parsingResult);
223 pdxShaderLinker.Run(finalShader);
226 if (parsingResult.HasErrors)
227 return parsingResult;
231 foreach (var stage
in new[] {ShaderStage.Compute, ShaderStage.Vertex, ShaderStage.Hull, ShaderStage.Domain, ShaderStage.Geometry, ShaderStage.Pixel})
233 var entryPoint = finalShader.Declarations.OfType<
MethodDefinition>().FirstOrDefault(f => f.Attributes.OfType<
AttributeDeclaration>().Any(
a => a.Name ==
"EntryPoint" && (string)a.Parameters[0].Value == stage.ToString()));
235 if (entryPoint == null)
240 parsingResult.EntryPoints[stage] = entryPoint.Name.Text;
247 var typeCleaner =
new ParadoxShaderCleaner();
248 typeCleaner.Run(finalShader);
261 parsingResult.Shader = finalShader;
264 return parsingResult;
269 #region Internal methods
271 internal ModuleMixinInfo GetMixin(
string mixinName)
273 return shaderLibrary.MixinInfos.FirstOrDefault(x => x.MixinGenericName == mixinName);
278 #region Private methods
288 private List<ModuleMixin> BuildCompositionsDictionary(
ShaderSource shaderSource, Dictionary<
Variable, List<ModuleMixin>> dictionary, ShaderCompilationContext compilationContext,
CloneContext cloneContext)
292 var shaderMixinSource = shaderSource as ShaderMixinSource;
294 var finalModule = compilationContext.GetModuleMixinFromShaderSource(shaderSource);
297 finalModule = finalModule.DeepClone(
new CloneContext(cloneContext));
300 foreach (var composition
in shaderMixinSource.Compositions)
303 var foundVars = finalModule.FindAllVariablesByName(composition.Key).Where(value => value.Variable.Qualifiers.Contains(
ParadoxStorageQualifier.
Compose)).ToList();
305 if (foundVars.Count > 0)
308 var moduleMixins = BuildCompositionsDictionary(composition.Value, dictionary, compilationContext, cloneContext);
309 if (moduleMixins == null)
312 dictionary.Add(foundVar, moduleMixins);
319 return new List<ModuleMixin> { finalModule };
323 if (shaderSource is ShaderClassSource)
325 var finalModule = compilationContext.GetModuleMixinFromShaderSource(shaderSource);
328 finalModule = finalModule.DeepClone(
new CloneContext(cloneContext));
331 return new List<ModuleMixin> { finalModule };
334 if (shaderSource is ShaderArraySource)
336 var shaderArraySource = shaderSource as ShaderArraySource;
337 var compositionArray =
new List<ModuleMixin>();
338 foreach (var shader
in shaderArraySource.Values)
340 var mixin = BuildCompositionsDictionary(shader, dictionary, compilationContext, cloneContext);
343 compositionArray.AddRange(mixin);
345 return compositionArray;
359 var mixinInfos =
new HashSet<ModuleMixinInfo>();
360 foreach (var mixin
in mixinToAnalyze)
361 mixinInfos.UnionWith(mixin.MinimalContext);
363 var context =
new ShaderCompilationContext(log);
364 context.Preprocess(mixinInfos);
375 var allMixins =
new HashSet<ModuleMixin>();
376 foreach (var mixin
in finalMixins)
378 if (allMixins.All(x => x.MixinName != mixin.MixinName))
379 allMixins.Add(mixin);
382 return allMixins.ToDictionary(x => x.MixinName, x => x);
static readonly SiliconStudio.Shaders.Ast.StorageQualifier Compose
Compose keyword (compose).
A mixin performing a combination of ShaderClassSource and other mixins.
Macro to be used with PreProcessor.
ShaderMixinParsingResult Parse(ShaderMixinSource shaderMixinSource, Paradox.Shaders.ShaderMacro[] macros=null, HashSet< string > modifiedShaders=null)
Mixes shader parts to produces a single HLSL file shader.
A class to collect parsing/expression messages.
ShaderMixinParser()
Initializes a new instance of the ShaderMixinParser class.
void DeleteObsoleteCache(HashSet< string > modifiedShaders)
Deletes the shader cache for the specified shaders.
A method definition with a body of statements.
The reflection data describing the parameters of a shader.
Provides a dictionary of cloned values, where the [key] is the original object and [value] the new ob...
Class ShaderSourceManager
ShaderStage
Enum to specify shader stage.
readonly ShaderSourceManager SourceManager
The shader source manager.
ShaderMacro(string name, object definition)
Initializes a new instance of the ShaderMacro struct.
A shader class used for mixin.