Example #1
0
        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);
            }
        }
Example #2
0
        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);
        }
Example #3
0
        /// <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);
        }
Example #4
0
        /// <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
        }
Example #5
0
 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));
                    }
                }
Example #8
0
        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));
 }