internal void RegisterEffect(string shaderEffectString, string[] techniqueNames, ShaderFlags sFlags = ShaderFlags.None, EffectFlags eFlags = EffectFlags.None) { #if DEBUG sFlags |= ShaderFlags.Debug; eFlags |= EffectFlags.None; #endif var preprocess = ShaderBytecode.Preprocess(shaderEffectString, null, new IncludeHandler()); var hashCode = preprocess.GetHashCode(); if (!File.Exists(hashCode.ToString())) { try { var shaderBytes = ShaderBytecode.Compile(preprocess, "fx_5_0", sFlags, eFlags); shaderBytes.Bytecode.Save(hashCode.ToString()); this.RegisterEffect(shaderBytes.Bytecode, techniqueNames); } catch (Exception ex) { System.Windows.MessageBox.Show(string.Format("Error compiling effect: {0}", ex.Message), "Error"); } } else { var shaderBytes = ShaderBytecode.FromFile(hashCode.ToString()); this.RegisterEffect(shaderBytes, techniqueNames); } }
static string CalculateCacheKey(string source, string function, string profile) { StringBuilder builder = new StringBuilder(); builder.Append(function); builder.Append(profile); if (MyRender11.DebugMode) { builder.Append("$DEBUG"); } try { var includes = new MyIncludeProcessor(Path.Combine(MyFileSystem.ContentPath, ShadersContentPath)); builder.Append(ShaderBytecode.Preprocess(source, null, includes)); byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes(builder.ToString()); byte[] hash = m_md5.ComputeHash(inputBytes); builder.Clear(); for (int i = 0; i < hash.Length; i++) { builder.Append(hash[i].ToString("X2")); } return(builder.ToString()); } catch (CompilationException e) { return(null); } return(null); }
/// <summary> /// Parses the specified input. /// </summary> /// <param name="input">The input.</param> /// <param name="fileName">Name of the file.</param> /// <returns>Result of parsing</returns> private EffectParserResult PrepareParsing(string input, string fileName) { var filePath = Path.GetFullPath(fileName); fileName = Path.GetFileName(fileName); var localResult = new EffectParserResult { SourceFileName = Path.Combine(Environment.CurrentDirectory, filePath), IncludeHandler = new FileIncludeHandler { Logger = Logger } }; localResult.IncludeHandler.CurrentDirectory.Push(Path.GetDirectoryName(localResult.SourceFileName)); localResult.IncludeHandler.IncludeDirectories.AddRange(IncludeDirectoryList); localResult.IncludeHandler.IncludeFileCallback = IncludeFileCallback; localResult.IncludeHandler.FileResolved.Add(fileName, new FileIncludeHandler.FileItem(fileName, filePath, File.GetLastWriteTime(filePath))); string compilationErrors = null; var preprocessedInput = ShaderBytecode.Preprocess(input, Macros.ToArray(), localResult.IncludeHandler, out compilationErrors, filePath); localResult.PreprocessedSource = preprocessedInput; localResult.DependencyList = CalculateDependencies(localResult); return(localResult); }
/// <summary> /// Register an effect for a set of RenderTechniques. /// </summary> /// <param name="shaderEffectString">A string representing the shader code.</param> /// <param name="techniques">A set of RenderTechnique objects for which to associate the Effect.</param> /// <param name="sFlags"></param> /// <param name="eFlags"></param> public void RegisterEffect(string shaderEffectString, RenderTechnique[] techniques, ShaderFlags sFlags = ShaderFlags.None, EffectFlags eFlags = EffectFlags.None) { #if PRECOMPILED_SHADERS try { var shaderBytes = Techniques.TechniquesSourceDict[techniques[0]]; this.RegisterEffect(shaderBytes, techniques); } catch (Exception ex) { //System.Windows.MessageBox.Show(string.Format("Error registering effect: {0}", ex.Message), "Error"); Debug.WriteLine(string.Format("Error registering effect: {0}", ex.Message), "Error"); throw; } #else #if DEBUG sFlags |= ShaderFlags.Debug; eFlags |= EffectFlags.None; #else sFlags |= ShaderFlags.OptimizationLevel3; eFlags |= EffectFlags.None; #endif var preposessMacros = new List <ShaderMacro>(); #if DEFERRED #if DEFERRED_MSAA preposessMacros.Add(new ShaderMacro("DEFERRED_MSAA", true)); #endif #if SSAO preposessMacros.Add(new ShaderMacro("SSAO", true)); #endif #endif var preprocess = ShaderBytecode.Preprocess(shaderEffectString, preposessMacros.ToArray(), new IncludeHandler()); var hashCode = preprocess.GetHashCode(); if (!File.Exists(hashCode.ToString())) { try { var shaderBytes = ShaderBytecode.Compile(preprocess, "fx_5_0", sFlags, eFlags); shaderBytes.Bytecode.Save(hashCode.ToString()); this.RegisterEffect(shaderBytes.Bytecode, techniques); } catch (Exception ex) { //System.Windows.MessageBox.Show(string.Format("Error compiling effect: {0}", ex.Message), "Error"); Debug.WriteLine(string.Format("Error compiling effect: {0}", ex.Message), "Error"); throw; } } else { var shaderBytes = ShaderBytecode.FromFile(hashCode.ToString()); this.RegisterEffect(shaderBytes, techniques); } #endif }
private static string PreprocessShader(string source, ShaderMacro[] macros) { try { var includes = new MyIncludeProcessor(Path.Combine(MyFileSystem.ContentPath, MyShadersDefines.ShadersContentPath)); return(ShaderBytecode.Preprocess(source, macros, includes)); } catch (CompilationException e) { return(null); } }
protected static void RegisterPixelShaderEffect(string shaderSource, Include includeHandler, string entryPoint = DEFAULT_ENTRY_POINT, string shaderVersion = DEFAULT_SHADER_VER) { var processedSource = ShaderBytecode.Preprocess(shaderSource, include: includeHandler); RegisterPixelShaderEffect(processedSource, entryPoint, shaderVersion); }
private static void CollectCompilationTargets(string source, string workingPath, ShaderFileCache shaderFileCache, ShaderCompilationCache loadedCache, ShaderCompilationCache cache, List <ShaderCompilationResult> errors, List <ShaderCompilationTarget> compilationTargets) { if (!shaderFileCache.TryLoad(source, out string shaderCode)) { lock (errors) { errors.Add(new ShaderCompilationResult("Shader", "", "", source, 0, 0, 0, 0, "Could not find file " + source)); } return; } //Only compile this shader if the shader has been modified since the previous compile. var currentTimeStamp = File.GetLastWriteTime(source).Ticks; if (loadedCache.ShaderFlags == cache.ShaderFlags && loadedCache.TimeStamps.TryGetValue(source, out long previousTimeStamp)) //If this file was contained before, we MIGHT be able to skip its compilation. { if (currentTimeStamp <= previousTimeStamp) //If the file hasn't been updated, we MIGHT be able to skip. { //Check the timestamps associated with the dependencies of this file. //If any are newer than the previous snapshot, skip. bool allowSkip = true; if (loadedCache.Dependencies.TryGetValue(source, out HashSet <string> loadedDependencyPaths)) { foreach (var dependency in loadedDependencyPaths) { //The loadedCache is guaranteed to contain a time stamp for any dependency referenced, //because the only time any dependency is added to the list the dependency is ALSO put into the timestamps list. var previousDependencyTimeStamp = loadedCache.TimeStamps[dependency]; var currentDependencyTimeStamp = File.GetLastWriteTime(dependency).Ticks; if (currentDependencyTimeStamp > previousDependencyTimeStamp) { //One of the dependencies has been updated. This shader must be compiled. allowSkip = false; break; } } } else { //One of the dependencies could not be found in the old cache. Implies a new dependency was added; must compile. allowSkip = false; } if (allowSkip) { Console.WriteLine($"Shader up to date: {Path.GetFileName(source)}"); cache.CopyFrom(source, loadedCache); return; } } } var localWorkingPath = Path.GetDirectoryName(source); var include = new IncludeHandler(shaderFileCache, workingPath, localWorkingPath); var stages = new List <ShaderStage>(); var macroGroups = new List <MacroGroup>(); var metadataParsingErrors = new List <MetadataParsingError>(); MetadataParsing.Parse(source, shaderCode, stages, macroGroups, metadataParsingErrors); //Prepass to collect include metadata. Seems hacky, oh well. try { ShaderBytecode.Preprocess(shaderCode, null, include); } catch (CompilationException e) { if (ParseCompilerResult(e.Message, out string filePath, out int lineBegin, out int columnBegin, out int lineEnd, out int columnEnd, out string description)) { var errorChecker = new Regex("error X(?<errorCode>[0-9]{4}): "); var errorCode = errorChecker.Match(e.Message).Groups["errorCode"].Value; lock (errors) { errors.Add(new ShaderCompilationResult("Shader", errorCode, "", source, lineBegin, columnBegin, lineEnd, columnEnd, description)); } }
public static void CompileD3D12Shader(H1ShaderCompileInput input, H1ShaderCompileOutput output) { // process shared/single environments String includeContent = ""; List <SharpDX.Direct3D.ShaderMacro> macros = new List <SharpDX.Direct3D.ShaderMacro>(); // 1. shared environment ProcessShaderCompilerEnvironment(input.SharedEnvironment, ref includeContent, macros); // 2. single environment ProcessShaderCompilerEnvironment(input.Environment, ref includeContent, macros); // load shader file content String sourceContent = includeContent + "\n" + LoadShaderFile(input.SourceFileName); // preprocess the shader file sourceContent = ShaderBytecode.Preprocess(sourceContent, macros.ToArray(), new H1SharpDXCompileInclude()); #if DEBUG var shader = ShaderBytecode.Compile(sourceContent, input.EntryPointName, input.Target.ToFormat, SharpDX.D3DCompiler.ShaderFlags.Debug | SharpDX.D3DCompiler.ShaderFlags.SkipOptimization); #else var shader = ShaderBytecode.Compile(sourceContent, input.EntryPointName, input.Target.ToFormat); #endif if (shader.Message != null) // failed to compile the shader { // @TODO - should log the error for failing compiling shader output.IsSucceed = false; return; } // assign the resultant byte code output.Code = shader; // create shader parameter map output.ParameterMap = new H1ShaderParameterMap(); // reflection for the compiled shader ShaderReflection shaderReflect = new ShaderReflection(shader); ShaderDescription shaderDesc = shaderReflect.Description; int bindResCounts = shaderDesc.BoundResources; for (int resIdx = 0; resIdx < bindResCounts; ++resIdx) { InputBindingDescription bindDesc = shaderReflect.GetResourceBindingDescription(resIdx); // for constant buffers if (bindDesc.Type == ShaderInputType.ConstantBuffer) { int cbIndex = bindDesc.BindPoint; ConstantBuffer cb = shaderReflect.GetConstantBuffer(cbIndex); ConstantBufferDescription cbDesc; cbDesc = cb.Description; // track all variables in this constant buffer for (int varIdx = 0; varIdx < cbDesc.VariableCount; varIdx++) { ShaderReflectionVariable variable = cb.GetVariable(varIdx); ShaderVariableDescription variableDesc = variable.Description; output.ParameterMap.ParameterMap.Add(variableDesc.Name, new H1ParameterAllocation(H1ParameterType.Variable, cbIndex, variableDesc.StartOffset, variableDesc.Size)); } // add constant buffer parameter output.ParameterMap.ParameterMap.Add(cbDesc.Name, new H1ParameterAllocation(H1ParameterType.ConstantBuffer, cbIndex, -1, cbDesc.Size)); } // texture, samplers .... other various GDI data } // release shader reflection shaderReflect.Dispose(); output.IsSucceed = true; // successfully compiled }
public string Preprocess(string shadertext, Include include) { return(ShaderBytecode.Preprocess(shadertext, new ShaderMacro[0], include)); }