Paradox Game Engine  v1.0.0 beta06
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros Pages
EffectCompilerBase.cs
Go to the documentation of this file.
1 // Copyright (c) 2014 Silicon Studio Corp. (http://siliconstudio.co.jp)
2 // This file is distributed under GPL v3. See LICENSE.md for details.
3 using System;
4 using System.Collections.Generic;
5 using System.Linq;
6 
7 using SiliconStudio.Core.Diagnostics;
8 using SiliconStudio.Core.Storage;
9 using SiliconStudio.Paradox.Effects;
10 
11 namespace SiliconStudio.Paradox.Shaders.Compiler
12 {
13  /// <summary>
14  /// Base class for implementations of <see cref="IEffectCompiler"/>, providing some helper functions.
15  /// </summary>
16  public abstract class EffectCompilerBase : IEffectCompiler
17  {
18  private readonly Dictionary<string, List<CompilerResults>> earlyCompilerCache = new Dictionary<string, List<CompilerResults>>();
19 
20  protected EffectCompilerBase()
21  {
22  }
23 
24  public CompilerResults Compile(ShaderSource shaderSource, CompilerParameters compilerParameters, HashSet<string> modifiedShaders, HashSet<string> recentlyModifiedShaders)
25  {
26  ShaderMixinSourceTree mixinTree;
27  var shaderMixinGeneratorSource = shaderSource as ShaderMixinGeneratorSource;
28  var mainUsedParameters = new ShaderMixinParameters();
29  var usedParameters = new List<ShaderMixinParameters>();
30 
31  string effectName = null;
32 
33  if (shaderMixinGeneratorSource != null)
34  {
35  effectName = shaderMixinGeneratorSource.Name;
36 
37  // getting the effect from the used parameters only makes sense when the source files are the same
38  // TODO: improve this by updating earlyCompilerCache - cache can still be relevant
39  if (modifiedShaders == null || modifiedShaders.Count == 0)
40  {
41  // perform an early test only based on the parameters
42  var foundCompilerResults = GetShaderFromParameters(effectName, compilerParameters);
43  if (foundCompilerResults != null)
44  {
45  var earlyCompilerResults = new CompilerResults();
46  earlyCompilerResults.Module = string.Format("EffectCompile [{0}]", effectName);
47  earlyCompilerResults.MainBytecode = foundCompilerResults.MainBytecode;
48  earlyCompilerResults.MainUsedParameters = foundCompilerResults.MainUsedParameters;
49  foreach (var foundBytecode in foundCompilerResults.Bytecodes)
50  {
51  earlyCompilerResults.Bytecodes.Add(foundBytecode.Key, foundBytecode.Value);
52  }
53 
54  foreach (var foundUsedParameters in foundCompilerResults.UsedParameters)
55  {
56  earlyCompilerResults.UsedParameters.Add(foundUsedParameters.Key, foundUsedParameters.Value);
57  }
58  return earlyCompilerResults;
59  }
60  }
61  mixinTree = ShaderMixinManager.Generate(effectName, compilerParameters, out mainUsedParameters, out usedParameters);
62  }
63  else
64  {
65  effectName = "Effect";
66 
67  var shaderMixinSource = shaderSource as ShaderMixinSource;
68  var shaderClassSource = shaderSource as ShaderClassSource;
69 
70  if (shaderClassSource != null)
71  {
72  shaderMixinSource = new ShaderMixinSource();
73  shaderMixinSource.Mixins.Add(shaderClassSource);
74  }
75 
76  if (shaderMixinSource != null)
77  {
78  mixinTree = new ShaderMixinSourceTree() { Mixin = shaderMixinSource };
79  }
80  else
81  {
82  throw new ArgumentException("Unsupported ShaderSource type [{0}]. Supporting only ShaderMixinSource/pdxfx, ShaderClassSource", "shaderSource");
83  }
84  }
85 
86  // Copy global parameters to used Parameters by default, as it is used by the compiler
87  mainUsedParameters.Set(CompilerParameters.GraphicsPlatformKey, compilerParameters.Platform);
88  mainUsedParameters.Set(CompilerParameters.GraphicsProfileKey, compilerParameters.Profile);
89  mainUsedParameters.Set(CompilerParameters.DebugKey, compilerParameters.Debug);
90 
91  foreach (var parameters in usedParameters)
92  {
93  parameters.Set(CompilerParameters.GraphicsPlatformKey, compilerParameters.Platform);
94  parameters.Set(CompilerParameters.GraphicsProfileKey, compilerParameters.Profile);
95  parameters.Set(CompilerParameters.DebugKey, compilerParameters.Debug);
96  }
97 
98  // Compile the whole mixin tree
99  var compilerResults = new CompilerResults();
100  compilerResults.Module = string.Format("EffectCompile [{0}]", effectName);
101  var wasCompiled = Compile(string.Empty, effectName, mixinTree, mainUsedParameters, usedParameters, modifiedShaders, recentlyModifiedShaders, compilerResults);
102 
103  if (wasCompiled && shaderMixinGeneratorSource != null)
104  {
105  lock (earlyCompilerCache)
106  {
107  List<CompilerResults> effectCompilerResults;
108  if (!earlyCompilerCache.TryGetValue(effectName, out effectCompilerResults))
109  {
110  effectCompilerResults = new List<CompilerResults>();
111  earlyCompilerCache.Add(effectName, effectCompilerResults);
112  }
113 
114  // Register bytecode used parameters so that they are checked when another effect is instanced
115  effectCompilerResults.Add(compilerResults);
116  }
117  }
118 
119  return compilerResults;
120  }
121 
122  /// <summary>
123  /// Compile the effect and its children.
124  /// </summary>
125  /// <param name="effectName">The name of the effect (without the base effect name).</param>
126  /// <param name="fullEffectName">The full name of the effect (with the base effect name).</param>
127  /// <param name="mixinTree">The ShaderMixinSourceTree.</param>
128  /// <param name="mainCompilerParameters">The parameters used to create the main effect.</param>
129  /// <param name="compilerParameters">The parameters used to create the child effects</param>
130  /// <param name="modifiedShaders">The list of modified shaders since the beginning of the runtime.</param>
131  /// <param name="recentlyModifiedShaders">The list of modified shaders that have not been replaced yet.</param>
132  /// <param name="compilerResults">The result of the compilation.</param>
133  /// <returns>true if the compilation succeded, false otherwise.</returns>
134  protected virtual bool Compile(string effectName, string fullEffectName, ShaderMixinSourceTree mixinTree, ShaderMixinParameters mainCompilerParameters, List<ShaderMixinParameters> compilerParameters, HashSet<string> modifiedShaders, HashSet<string> recentlyModifiedShaders, CompilerResults compilerResults)
135  {
136  if (mixinTree.Mixin == null) return false;
137 
138  var cp = compilerParameters.FirstOrDefault(x => x.Name == fullEffectName);
139  var bytecode = Compile(mixinTree.Mixin, fullEffectName, cp ?? mainCompilerParameters, modifiedShaders, recentlyModifiedShaders, compilerResults);
140 
141  var wasCompiled = false;
142  if (bytecode != null)
143  {
144  if (effectName == string.Empty)
145  {
146  compilerResults.MainBytecode = bytecode;
147  compilerResults.MainUsedParameters = mainCompilerParameters;
148  }
149  compilerResults.Bytecodes.Add(effectName, bytecode);
150  compilerResults.UsedParameters.Add(effectName, cp);
151 
152  wasCompiled = true;
153  }
154 
155  foreach (var childTree in mixinTree.Children)
156  {
157  var childEffectName = effectName == string.Empty ? childTree.Key : effectName + "." + childTree.Key;
158  var fullChildEffectName = fullEffectName == string.Empty ? childTree.Key : fullEffectName + "." + childTree.Key;
159  wasCompiled |= Compile(childEffectName, fullChildEffectName, childTree.Value, mainCompilerParameters, compilerParameters, modifiedShaders, recentlyModifiedShaders, compilerResults);
160  }
161 
162  return wasCompiled;
163  }
164 
165  /// <summary>
166  /// Compiles the ShaderMixinSource into a platform bytecode.
167  /// </summary>
168  /// <param name="mixin">The ShaderMixinSource.</param>
169  /// <param name="fullEffectName">The name of the effect.</param>
170  /// <param name="compilerParameters">The parameters used for compilation.</param>
171  /// <param name="modifiedShaders">The list of modified shaders.</param>
172  /// <param name="recentlyModifiedShaders">The list of recently modified shaders.</param>
173  /// <param name="log">The logger.</param>
174  /// <returns>The platform-dependent bytecode.</returns>
175  public abstract EffectBytecode Compile(ShaderMixinSource mixin, string fullEffectName, ShaderMixinParameters compilerParameters, HashSet<string> modifiedShaders, HashSet<string> recentlyModifiedShaders, LoggerResult log);
176 
177  /// <summary>
178  /// Get the shader from the database based on the parameters used for its compilation.
179  /// </summary>
180  /// <param name="effectName">Name of the effect.</param>
181  /// <param name="parameters">The parameters.</param>
182  /// <returns>The EffectBytecode if found.</returns>
183  protected CompilerResults GetShaderFromParameters(string effectName, CompilerParameters parameters)
184  {
185  lock (earlyCompilerCache)
186  {
187  List<CompilerResults> effectCompilerResults;
188  if (!earlyCompilerCache.TryGetValue(effectName, out effectCompilerResults))
189  return null;
190 
191  // TODO: Optimize it so that search is not linear?
192  // TODO: are macros taken into account?
193  // Probably not trivial for subset testing
194  foreach (var compiledResults in effectCompilerResults)
195  {
196  if (compiledResults.MainUsedParameters != null && parameters.Contains(compiledResults.MainUsedParameters))
197  return compiledResults;
198  }
199  }
200 
201  return null;
202  }
203  }
204 }
ShaderMixinSource Mixin
Gets or sets the mixin.
A shader source that is linked to a pdxfx effect.
A mixin performing a combination of ShaderClassSource and other mixins.
A logger that stores messages locally useful for internal log scenarios.
Definition: LoggerResult.cs:14
Base class for implementations of IEffectCompiler, providing some helper functions.
CompilerResults Compile(ShaderSource shaderSource, CompilerParameters compilerParameters, HashSet< string > modifiedShaders, HashSet< string > recentlyModifiedShaders)
Compiles the specified shader source.
bool Contains(ParameterCollection parameters)
Tests if the values in parameters are contained into this instance. It will automatically handle defa...
virtual bool Compile(string effectName, string fullEffectName, ShaderMixinSourceTree mixinTree, ShaderMixinParameters mainCompilerParameters, List< ShaderMixinParameters > compilerParameters, HashSet< string > modifiedShaders, HashSet< string > recentlyModifiedShaders, CompilerResults compilerResults)
Compile the effect and its children.
CompilerResults GetShaderFromParameters(string effectName, CompilerParameters parameters)
Get the shader from the database based on the parameters used for its compilation.
Contains a compiled shader with bytecode for each stage.
Main interface used to compile a shader.