4 using System.Collections.Generic;
5 using System.Collections.ObjectModel;
9 using SiliconStudio.Core;
10 using SiliconStudio.Core.Diagnostics;
11 using SiliconStudio.Core.Storage;
12 using SiliconStudio.Paradox.Effects;
13 using SiliconStudio.Paradox.Graphics;
14 using SiliconStudio.Paradox.Shaders.Parser;
15 using SiliconStudio.Shaders.Utility;
19 namespace SiliconStudio.
Paradox.Shaders.Compiler
26 private bool d3dcompilerLoaded =
false;
27 private static readonly Object WriterLock =
new Object();
31 public List<string> SourceDirectories {
get;
private set; }
33 public Dictionary<string, string> UrlToFilePath {
get;
private set; }
37 NativeLibrary.PreloadLibrary(
"d3dcompiler_47.dll");
38 SourceDirectories =
new List<string>();
39 UrlToFilePath =
new Dictionary<string, string>();
42 #region Public methods
50 NativeLibrary.PreloadLibrary(
"d3dcompiler_47.dll");
51 d3dcompilerLoaded =
true;
56 shaderMixinSourceCopy.DeepCloneFrom(shaderMixinSource);
58 shaderMixinSource = shaderMixinSourceCopy;
61 var platform = compilerParameters.Get(CompilerParameters.GraphicsPlatformKey);
64 case GraphicsPlatform.Direct3D11:
65 shaderMixinSource.AddMacro(
"SILICONSTUDIO_PARADOX_GRAPHICS_API_DIRECT3D", 1);
66 shaderMixinSource.AddMacro(
"SILICONSTUDIO_PARADOX_GRAPHICS_API_DIRECT3D11", 1);
68 case GraphicsPlatform.OpenGL:
69 shaderMixinSource.AddMacro(
"SILICONSTUDIO_PARADOX_GRAPHICS_API_OPENGL", 1);
70 shaderMixinSource.AddMacro(
"SILICONSTUDIO_PARADOX_GRAPHICS_API_OPENGLCORE", 1);
72 case GraphicsPlatform.OpenGLES:
73 shaderMixinSource.AddMacro(
"SILICONSTUDIO_PARADOX_GRAPHICS_API_OPENGL", 1);
74 shaderMixinSource.AddMacro(
"SILICONSTUDIO_PARADOX_GRAPHICS_API_OPENGLES", 1);
77 throw new NotSupportedException();
81 if (shaderMixinParser == null)
84 shaderMixinParser.SourceManager.LookupDirectoryList = SourceDirectories;
85 shaderMixinParser.SourceManager.UrlToFilePath = UrlToFilePath;
88 if (recentlyModifiedShaders != null && recentlyModifiedShaders.Count > 0)
90 shaderMixinParser.DeleteObsoleteCache(GetShaderNames(recentlyModifiedShaders));
91 recentlyModifiedShaders.Clear();
93 var parsingResult = shaderMixinParser.Parse(shaderMixinSource, shaderMixinSource.Macros.ToArray(), modifiedShaders);
96 CopyLogs(parsingResult, log);
99 if (parsingResult.HasErrors)
106 writer.Visit(parsingResult.Shader);
107 var shaderSourceText = writer.Text;
112 #if SILICONSTUDIO_PLATFORM_WINDOWS_DESKTOP
113 var shaderId = ObjectId.FromBytes(Encoding.UTF8.GetBytes(shaderSourceText));
116 if (!Directory.Exists(logDir))
118 Directory.CreateDirectory(logDir);
120 var shaderSourceFilename = Path.Combine(logDir,
"shader_" + shaderId);
123 if (!
File.Exists(shaderSourceFilename))
125 var builder =
new StringBuilder();
126 builder.AppendLine(
"/***** Used Parameters *****");
127 builder.Append(
" * EffectName: ");
128 builder.AppendLine(fullEffectName ??
"");
129 WriteParameters(builder, compilerParameters, 0,
false);
130 builder.AppendLine(
" ***************************/");
131 builder.Append(shaderSourceText);
132 File.WriteAllText(shaderSourceFilename, builder.ToString());
138 var bytecode =
new EffectBytecode { Reflection = parsingResult.Reflection, HashSources = parsingResult.HashSources };
141 IShaderCompiler compiler;
144 case GraphicsPlatform.Direct3D11:
145 compiler =
new Direct3D.ShaderCompiler();
147 case GraphicsPlatform.OpenGL:
148 case GraphicsPlatform.OpenGLES:
149 compiler =
new OpenGL.ShaderCompiler();
152 throw new NotSupportedException();
155 var shaderStageBytecodes =
new List<ShaderBytecode>();
157 foreach (var stageBinding
in parsingResult.EntryPoints)
160 var result = compiler.Compile(shaderSourceText, stageBinding.Value, stageBinding.Key, compilerParameters, bytecode.Reflection, shaderSourceFilename);
163 if (result.HasErrors)
170 #if SILICONSTUDIO_PLATFORM_WINDOWS_DESKTOP
173 if (
File.Exists(shaderSourceFilename))
176 File.AppendAllText(shaderSourceFilename,
"\n// {0} {1}".ToFormat(stageBinding.Key, result.Bytecode.Id));
182 shaderStageBytecodes.Add(result.Bytecode);
190 bytecode.Time = DateTime.Now;
195 CleanupReflection(bytecode.Reflection);
198 bytecode.Stages = shaderStageBytecodes.ToArray();
204 #region Private static methods
206 private static void CopyLogs(SiliconStudio.Shaders.Utility.LoggerResult inputLog,
LoggerResult outputLog)
208 foreach (var inputMessage
in inputLog.Messages)
210 var logType = LogMessageType.Info;
211 switch (inputMessage.Level)
213 case ReportMessageLevel.Error:
214 logType = LogMessageType.Error;
216 case ReportMessageLevel.Info:
217 logType = LogMessageType.Info;
219 case ReportMessageLevel.Warning:
220 logType = LogMessageType.Warning;
223 var outputMessage =
new LogMessage(inputMessage.Span.ToString(), logType, string.Format(
" {0}: {1}", inputMessage.Code, inputMessage.Text));
224 outputLog.Log(outputMessage);
226 outputLog.HasErrors = inputLog.HasErrors;
229 private static void WriteParameters(StringBuilder builder,
ParameterCollection parameters,
int indent,
bool isArray)
231 var indentation =
"";
232 for (var i = 0; i < indent - 1; ++i)
235 foreach (var usedParam
in parameters)
237 builder.Append(
" * ");
238 builder.Append(indentation);
239 if (isArray && first)
241 builder.Append(
" - ");
247 if (usedParam.Key == null)
248 builder.Append(
"NullKey");
250 builder.Append(usedParam.Key);
251 builder.Append(
": ");
252 if (usedParam.Value == null)
253 builder.AppendLine(
"NullValue");
256 builder.AppendLine(usedParam.Value.ToString());
258 WriteParameters(builder, usedParam.Value as ParameterCollection, indent+1,
false);
259 else if (usedParam.Value is ParameterCollection[])
261 var collectionArray = (ParameterCollection[])usedParam.Value;
262 foreach (var collection in collectionArray)
263 WriteParameters(builder, collection, indent + 1,
true);
270 private static void CleanupReflection(EffectReflection reflection)
272 for (
int i = reflection.ConstantBuffers.Count - 1; i >= 0; i--)
274 var cBuffer = reflection.ConstantBuffers[i];
277 reflection.ConstantBuffers.RemoveAt(i);
281 for (
int i = reflection.ResourceBindings.Count - 1; i >= 0; i--)
283 var resourceBinding = reflection.ResourceBindings[i];
286 reflection.ResourceBindings.RemoveAt(i);
291 private static HashSet<string> GetShaderNames(HashSet<string> shaderPaths)
293 var shaderNames =
new HashSet<string>();
295 foreach (var shader
in shaderPaths)
297 if (
String.IsNullOrEmpty(shader))
300 var shaderNameWithExtensionParts = shader.Split(
'/');
301 var shaderNameWithExtension = shaderNameWithExtensionParts[shaderNameWithExtensionParts.Length - 1];
302 var shaderNameParts = shaderNameWithExtension.Split(
'.');
303 var shaderName = shaderNameParts[0];
305 shaderNames.Add(shaderName);
307 if (shaderNames.Count == 0)
Parameters used for mixin.
A mixin performing a combination of ShaderClassSource and other mixins.
SiliconStudio.Core.Diagnostics.LoggerResult LoggerResult
A logger that stores messages locally useful for internal log scenarios.
GraphicsPlatform
The graphics platform.
Base class for implementations of IEffectCompiler, providing some helper functions.
System.Text.Encoding Encoding
An IEffectCompiler which will compile effect into multiple shader code, and compile them with a IShad...
override EffectBytecode Compile(ShaderMixinSource shaderMixinSource, string fullEffectName, ShaderMixinParameters compilerParameters, HashSet< string > modifiedShaders, HashSet< string > recentlyModifiedShaders, LoggerResult log)
Compiles the ShaderMixinSource into a platform bytecode.
A base log message used by the logging infrastructure.
ShaderStage
Enum to specify shader stage.
Contains a compiled shader with bytecode for each stage.
A container to handle a hierarchical collection of effect variables.