Ejemplo n.º 1
0
 /// <summary>
 /// Create this ShaderObject.
 /// </summary>
 /// <param name="ctx">
 /// A <see cref="GraphicsContext"/> used for creating this object.
 /// </param>
 /// <exception cref="ArgumentNullException">
 /// Exception thrown if <paramref name="ctx"/> is null.
 /// </exception>
 public override void Create(GraphicsContext ctx)
 {
     // Create default compilation
     _CompilationParams = new ShaderCompilerContext(ctx.ShadingVersion);
     // Base implementation
     base.Create(ctx);
 }
Ejemplo n.º 2
0
            /// <summary>
            ///
            /// </summary>
            /// <param name="cctx"></param>
            /// <returns></returns>
            internal string GetHashInfo(ShaderCompilerContext cctx)
            {
                StringBuilder hashMessage = new StringBuilder();

                // Take into account the shader program name
                hashMessage.Append(Id);

                // Objects hash
                if (Objects != null)
                {
                    foreach (Object programObject in Objects)
                    {
                        hashMessage.Append(programObject);
                    }
                }

                // Compilation parameters (common to all shaders?)
                hashMessage.Append(cctx.ShaderVersion);

                if (cctx.Includes != null)
                {
                    foreach (string includePath in cctx.Includes)
                    {
                        hashMessage.Append(includePath);
                    }
                }

                hashMessage.Append(cctx.FeedbackVaryingsFormat);

                return(hashMessage.ToString());
            }
Ejemplo n.º 3
0
            /// <summary>
            /// Create a ProgramTag from a <see cref="Program"/>.
            /// </summary>
            /// <param name="program">
            /// The <see cref="Program"/> that specifies how to build the shader.
            /// </param>
            internal ProgramTag(Program program, ShaderCompilerContext cctx) : this(program)
            {
                if (cctx == null)
                {
                    throw new ArgumentNullException("cctx");
                }

                CompilerContext.Merge(cctx);
            }
Ejemplo n.º 4
0
        /// <summary>
        /// Append default source header.
        /// </summary>
        /// <param name="ctx">
        /// A <see cref="GraphicsContext"/> used for the compilation process.
        /// </param>
        /// <param name="sourceLines">
        /// A <see cref="List{String}"/> which represent the current shader object
        /// source lines.
        /// </param>
        /// <param name="version">
        /// A <see cref="Int32"/> representing the shader language version to use in generated shader.
        /// </param>
        protected void AppendHeader(GraphicsContext ctx, ShaderCompilerContext cctx, List <string> sourceLines, int version)
        {
            if (ctx == null)
            {
                throw new ArgumentNullException("ctx");
            }
            if (cctx == null)
            {
                throw new ArgumentNullException("ctx");
            }
            if (sourceLines == null)
            {
                throw new ArgumentNullException("sLines");
            }

            // Prepend required shader version
            if (version >= 150)
            {
                // Starting from GLSL 1.50, profiles are implemented

                if ((ctx.Flags & GraphicsContextFlags.ForwardCompatible) != 0)
                {
                    sourceLines.Add(String.Format("#version {0} core\n", version));
                }
                else
                {
                    sourceLines.Add(String.Format("#version {0} compatibility\n", version));
                }
            }
            else
            {
                sourceLines.Add(String.Format("#version {0}\n", version));
            }

            // #extension
            List <ShaderExtension> shaderExtensions = new List <ShaderExtension>(Extensions);

            // Includes generic extension from compiler
            foreach (ShaderExtension contextShaderExtension in cctx.Extensions)
            {
                if (!shaderExtensions.Exists(delegate(ShaderExtension item) { return(item.Name == contextShaderExtension.Name); }))
                {
                    shaderExtensions.Add(contextShaderExtension);
                }
            }

            // #pragma
#if DEBUG
            // Debug directives
            //sourceLines.Add("#pragma optimization(off)\n");
            //sourceLines.Add("#pragma debug(on)\n");
#else
            //sourceLines.Add("#pragma optimization(on)\n");
            //sourceLines.Add("#pragma debug(off)\n");
#endif
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Create a <see cref="ProgramTag"/> used for creating (lazily) a <see cref="ShaderProgram"/>.
        /// </summary>
        /// <param name="programId">
        /// A <see cref="String"/> that specifies the program identifier.
        /// </param>
        /// <param name="cctx">
        /// A <see cref="ShaderCompilerContext"/> that specifies *additional* parameters to be applied/merged to the default
        /// compiler parameters.
        /// </param>
        /// <returns>
        /// It returns a <see cref="ProgramTag"/> for creating the program identified with <paramref name="programId"/>.
        /// </returns>
        public ProgramTag CreateProgramTag(string programId, ShaderCompilerContext cctx)
        {
            Program libraryProgram = GetProgram(programId);

            if (libraryProgram == null)
            {
                throw new ArgumentException("no program with such identifier", "programId");
            }

            return(new ProgramTag(libraryProgram, cctx));
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Create this ShaderObject.
        /// </summary>
        /// <param name="ctx">
        /// A <see cref="GraphicsContext"/> used for creating this object.
        /// </param>
        /// <param name="cctx">
        /// A <see cref="ShaderCompilerContext"/> that specify compiler parameters.
        /// </param>
        /// <exception cref="ArgumentNullException">
        /// Exception thrown if <paramref name="ctx"/> is null.
        /// </exception>
        /// <exception cref="ArgumentNullException">
        /// Exception thrown if <paramref name="cctx"/> is null.
        /// </exception>
        public virtual void Create(GraphicsContext ctx, ShaderCompilerContext cctx)
        {
            if (cctx == null)
            {
                throw new ArgumentNullException("cctx");
            }

            // Cache compilation parameters (used by CreateObject)
            _CompilationParams = cctx;
            // Base implementation
            base.Create(ctx);
        }
Ejemplo n.º 7
0
            /// <summary>
            /// Create a program from this Program.
            /// </summary>
            /// <param name="cctx"></param>
            /// <returns></returns>
            public ShaderProgram Create(ShaderCompilerContext cctx)
            {
                if (string.IsNullOrEmpty(Id))
                {
                    throw new InvalidOperationException("invalid program identifier");
                }
                if (cctx == null)
                {
                    throw new ArgumentNullException("cctx");
                }

                ShaderProgram shaderProgram = new ShaderProgram(Id);

                // Attach required objects
                if (Objects != null)
                {
                    foreach (Object shaderProgramObject in Objects)
                    {
                        Shader shaderObject = new Shader(shaderProgramObject.Stage);

                        // Load source
                        shaderObject.LoadSource(shaderProgramObject.Resource);
                        // Attach object
                        shaderProgram.Attach(shaderObject);
                    }
                }

                // Register attributes semantic
                if (Attributes != null)
                {
                    foreach (Attribute attribute in Attributes)
                    {
                        shaderProgram.SetAttributeSemantic(attribute.Name, attribute.Semantic);
                        if (attribute.Location >= 0)
                        {
                            shaderProgram.SetAttributeLocation(attribute.Name, attribute.Location);
                        }
                    }
                }

                // Register uniforms semantic
                if (Uniforms != null)
                {
                    foreach (Uniform uniform in Uniforms)
                    {
                        shaderProgram.SetUniformSemantic(uniform.Name, uniform.Semantic);
                    }
                }

                shaderProgram.Create(cctx);

                return(shaderProgram);
            }
Ejemplo n.º 8
0
        /// <summary>
        /// Generate ShaderObject source.
        /// </summary>
        /// <param name="ctx">
        /// A <see cref="GraphicsContext"/> used for the compilation process.
        /// </param>
        /// <param name="cctx">
        /// A <see cref="ShaderCompilerContext"/> that specify the information required for compiling this ShaderObject.
        /// </param>
        /// <returns>
        /// It returns a <see cref="List{T}"/> which represent this ShaderObject source. This source text is ready to be compiled.
        /// </returns>
        private List <string> GenerateSource(GraphicsContext ctx, ShaderCompilerContext cctx)
        {
            if (ctx == null)
            {
                throw new ArgumentNullException("ctx");
            }
            if (cctx == null)
            {
                throw new ArgumentNullException("cctx");
            }

            if (_SourceStrings == null)
            {
                throw new InvalidOperationException("no source loaded");
            }

            List <string> shaderSource = new List <string>(256);

            string[] shaderSourceStrings = _SourceStrings.ToArray();

            // Append imposed header - Every source shall compile with this header
            AppendHeader(ctx, cctx, shaderSource, cctx.ShaderVersion.VersionId);

            // Append required #define statments
            if (cctx.Defines != null)
            {
                foreach (string def in cctx.Defines)
                {
                    shaderSource.Add(String.Format("#define {0} 1\n", def));
                    Log("  Symbol: {0}", def);
                }
            }

            // Append specific source for composing shader essence
            AppendSourceStrings(shaderSource, shaderSourceStrings);

            // Remove comment lines
            shaderSource = CleanSource(shaderSource);

            // Preprocessing
            // Manage #include preprocessor directives in the case GL_ARB_shading_language_include is not supported
            // When #include are replaced, conditionals are processed too
            if (ctx.Extensions.ShadingLanguageInclude_ARB == false)
            {
                shaderSource = ShaderPreprocessor.Process(shaderSource, cctx, ctx.IncludeLibrary, ShaderPreprocessor.Stage.All);
            }

            shaderSource = CleanSource(shaderSource);

            return(shaderSource);
        }
Ejemplo n.º 9
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="cctx"></param>
 /// <returns></returns>
 internal void GetHashInfo(StringBuilder hashMessage, ShaderCompilerContext cctx)
 {
     // Shaders can be compiled at different stages
     hashMessage.Append(Stage);
     // All symbols known for this shader are included
     foreach (string define in cctx.Defines)
     {
         if (Symbols.Contains(define) == false)
         {
             continue;
         }
         hashMessage.Append(define);
     }
 }
Ejemplo n.º 10
0
            internal ShaderCompilerContext GetCompilerContext()
            {
                ShaderCompilerContext shaderCompilerParams = new ShaderCompilerContext();

                foreach (Object shaderProgramObject in Objects)
                {
                    // Take into account required preprocessor symbols
                    foreach (string preprocessorSymbol in shaderProgramObject.Symbols)
                    {
                        shaderCompilerParams.Defines.Add(preprocessorSymbol);
                    }
                }

                return(shaderCompilerParams);
            }
Ejemplo n.º 11
0
            internal ShaderCompilerContext GetCompilerContext()
            {
                ShaderCompilerContext shaderCompilerParams = new ShaderCompilerContext();

                // Preprocessor symbols
                foreach (Object shaderProgramObject in Objects)
                {
                    foreach (string preprocessorSymbol in shaderProgramObject.Symbols)
                    {
                        shaderCompilerParams.Defines.Add(preprocessorSymbol);
                    }
                }
                // Shader extensions
                shaderCompilerParams.Extensions.AddRange(Extensions);

                return(shaderCompilerParams);
            }
Ejemplo n.º 12
0
        /// <summary>
        /// Process shader source lines to resolve #include directives.
        /// </summary>
        /// <param name="shaderSource">
        /// A <see cref="IEnumerable{String}"/> that specify the shader source lines. Null items in the enumeration
        /// will be ignored.
        /// </param>
        /// <param name="cctx">
        /// A <see cref="ShaderCompilerContext"/> that specify the compiler parameteres.
        /// </param>
        /// <param name="includeLibrary">
        /// A <see cref="ShaderIncludeLibrary"/> determining the shader include file system.
        /// </param>
        /// <returns>
        /// It returns the processed source lines <paramref name="shaderSource"/>, but without any #include directive. Each #include
        /// directive will be replaced by the corresponding text depending on <paramref name="cctx"/>.
        /// </returns>
        /// <remarks>
        /// <para>
        /// </para>
        /// </remarks>
        /// <exception cref="ArgumentNullException">
        /// Exception throw if <paramref name="includeLibrary"/>, <paramref name="cctx"/> or <paramref name="shaderSource"/> is null.
        /// </exception>
        private static List <string> ProcessIncludes(List <string> shaderSource, ShaderCompilerContext cctx, ShaderIncludeLibrary includeLibrary)
        {
            if (includeLibrary == null)
            {
                throw new ArgumentNullException("includeLibrary");
            }
            if (cctx == null)
            {
                throw new ArgumentNullException("cctx");
            }
            if (shaderSource == null)
            {
                throw new ArgumentNullException("sSource");
            }

            IncludeProcessorContext ictx = new IncludeProcessorContext();

            return(ProcessIncludes(shaderSource, cctx, includeLibrary, ictx));
        }
Ejemplo n.º 13
0
        /// <summary>
        /// Process shader source lines to resolve #include directives.
        /// </summary>
        /// <param name="includeLibrary">
        /// A <see cref="ShaderIncludeLibrary"/> determining the shader include file system.
        /// </param>
        /// <param name="cctx">
        /// A <see cref="ShaderCompilerContext"/> that specify the compiler parameteres.
        /// </param>
        /// <param name="shaderSource">
        /// A <see cref="IEnumerable{String}"/> that specify the shader source lines. Null items in the enumeration
        /// will be ignored.
        /// </param>
        /// <returns>
        /// It returns the processed source lines <paramref name="shaderSource"/>, but without any #include directive. Each #include
        /// directive will be replaced by the corresponding text depending on <paramref name="cctx"/>.
        /// </returns>
        /// <remarks>
        /// <para>
        /// </para>
        /// </remarks>
        /// <exception cref="ArgumentNullException">
        /// Exception throw if <paramref name="includeLibrary"/>, <paramref name="cctx"/> or <paramref name="shaderSource"/> is null.
        /// </exception>
        public static List <string> Process(ShaderIncludeLibrary includeLibrary, ShaderCompilerContext cctx, List <string> shaderSource)
        {
            if (includeLibrary == null)
            {
                throw new ArgumentNullException("includeLibrary");
            }
            if (cctx == null)
            {
                throw new ArgumentNullException("cctx");
            }
            if (shaderSource == null)
            {
                throw new ArgumentNullException("sSource");
            }

            IncludeProcessorContext ictx = new IncludeProcessorContext();

            return(Process(includeLibrary, cctx, ictx, shaderSource));
        }
Ejemplo n.º 14
0
        /// <summary>
        /// Process a source using the preprocessor.
        /// </summary>
        /// <param name="shaderSource"></param>
        /// <returns></returns>
        public static List <string> Process(List <string> shaderSource, ShaderCompilerContext cctx, ShaderIncludeLibrary includeLibrary, Stage stages)
        {
            if (shaderSource == null)
            {
                throw new ArgumentNullException("shaderSource");
            }
            if (cctx == null)
            {
                throw new ArgumentNullException("cctx");
            }

            List <string> processedSource = shaderSource;

            if ((stages & Stage.Includes) != 0)
            {
                processedSource = ProcessIncludes(processedSource, cctx, includeLibrary);
            }
            if ((stages & Stage.Conditionals) != 0)
            {
                processedSource = ProcessConditionals(processedSource, cctx);
            }

            return(processedSource);
        }
Ejemplo n.º 15
0
        /// <summary>
        /// Generate ShaderObject source.
        /// </summary>
        /// <param name="ctx">
        /// A <see cref="GraphicsContext"/> used for the compilation process.
        /// </param>
        /// <param name="cctx">
        /// A <see cref="ShaderCompilerContext"/> that specify the information required for compiling this ShaderObject.
        /// </param>
        /// <returns>
        /// It returns a <see cref="List{T}"/> which represent this ShaderObject source. This source text is ready to be compiled.
        /// </returns>
        private List <string> GenerateSource(GraphicsContext ctx, ShaderCompilerContext cctx)
        {
            if (ctx == null)
            {
                throw new ArgumentNullException("ctx");
            }
            if (cctx == null)
            {
                throw new ArgumentNullException("cctx");
            }

            if (_SourceStrings == null)
            {
                throw new InvalidOperationException("no source loaded");
            }

            List <string> shaderSource = new List <string>(256);

            string[] shaderSourceStrings = _SourceStrings.ToArray();

            // Append imposed header - Every source shall compile with this header
            AppendHeader(ctx, cctx, shaderSource, cctx.ShaderVersion.VersionId);

            // Shader extension behavior
            if (ctx.Extensions.ShadingLanguageInclude_ARB)
            {
                shaderSource.Add("#extension GL_ARB_shading_language_include : require\n");
            }

            if (ctx.Extensions.UniformBufferObject_ARB)
            {
                shaderSource.Add("#extension GL_ARB_uniform_buffer_object : enable\n");
            }
            else
            {
                shaderSource.Add("#define DISABLE_GL_ARB_uniform_buffer_object\n");
            }

            if (ObjectStage == ShaderStage.Geometry && ctx.Extensions.GeometryShader4_ARB)
            {
                shaderSource.Add("#extension GL_ARB_geometry_shader4 : enable\n");
            }

            // Append required #define statments
            if (cctx.Defines != null)
            {
                foreach (string def in cctx.Defines)
                {
                    shaderSource.Add(String.Format("#define {0}\n", def));
                    Log("  Symbol: {0}", def);
                }
            }

            // Append specific source for composing shader essence
            AppendSourceStrings(shaderSource, shaderSourceStrings);

            // Manage #include preprocessor directives in the case GL_ARB_shading_language_include is not supported
            if (ctx.Extensions.ShadingLanguageInclude_ARB == false)
            {
                shaderSource = ShaderIncludePreprocessor.Process(ctx.IncludeLibrary, cctx, shaderSource);
            }

            // Remove comment lines
            shaderSource = CleanSource(shaderSource);

            return(shaderSource);
        }
Ejemplo n.º 16
0
        /// <summary>
        /// Generate Shader source.
        /// </summary>
        /// <param name="ctx">
        /// A <see cref="GraphicsContext"/> used for the compilation process.
        /// </param>
        /// <param name="cctx">
        /// A <see cref="ShaderCompilerContext"/> that specify the information required for compiling this Shader.
        /// </param>
        /// <returns>
        /// It returns a <see cref="List{T}"/> which represent this Shader source. This source text is ready to be compiled.
        /// </returns>
        private List <string> GenerateSource(GraphicsContext ctx, ShaderCompilerContext cctx)
        {
            if (ctx == null)
            {
                throw new ArgumentNullException("ctx");
            }
            if (cctx == null)
            {
                throw new ArgumentNullException("cctx");
            }
            if (_SourceStrings == null)
            {
                throw new InvalidOperationException("no source loaded");
            }

            List <string> sourceLines = new List <string>();

            // Initial status: original
            AppendSourceStrings(sourceLines, _SourceStrings.ToArray());

            // Append imposed header - Every source shall compile with this header
            int headerLine = 0;

            if (ctx.ShadingVersion.Api == KhronosVersion.ApiGlsl)
            {
                // Automatically prepend required shader version, if necessary
                if (sourceLines.Count > 0 && !Regex.IsMatch(sourceLines[0], @"\s*#version \d+.*"))
                {
                    int version = cctx.ShaderVersion.VersionId;

                    if (version >= 150)
                    {
                        // Starting from GLSL 1.50, profiles are implemented

                        if ((ctx.Flags & GraphicsContextFlags.ForwardCompatible) != 0)
                        {
                            sourceLines.Insert(headerLine++, $"#version {version} core\n");
                        }
                        else
                        {
                            sourceLines.Insert(headerLine++, $"#version {version} compatibility\n");
                        }
                    }
                    else
                    {
                        sourceLines.Insert(headerLine++, $"#version {version}\n");
                    }
                }
                else
                {
                    headerLine++;                               // #version already specified by implementor
                }
                // #extension
                if (ctx.Extensions.ShadingLanguageInclude_ARB)
                {
                    sourceLines.Insert(headerLine++, "#extension GL_ARB_shading_language_include : require\n");
                }

                if (ctx.Extensions.UniformBufferObject_ARB)
                {
                    sourceLines.Insert(headerLine++, "#extension GL_ARB_uniform_buffer_object : enable\n");
                }
                else
                {
                    sourceLines.Insert(headerLine++, "#define DISABLE_GL_ARB_uniform_buffer_object\n");
                }

                if (ObjectStage == ShaderType.GeometryShader && ctx.Extensions.GeometryShader4_ARB)
                {
                    sourceLines.Insert(headerLine++, "#extension GL_ARB_geometry_shader4 : enable\n");
                }

                if (ctx.Extensions.ShaderDrawParameters_ARB)
                {
                    sourceLines.Insert(headerLine++, "#extension GL_ARB_shader_draw_parameters : enable\n");
                }

                foreach (ShaderExtension shaderExtension in cctx.Extensions)
                {
                    // Do not include any #extension directive on extensions not supported by driver
                    if (ctx.Extensions.HasExtensions(shaderExtension.Name) == false)
                    {
                        continue;
                    }
                    sourceLines.Insert(headerLine++, $"#extension {shaderExtension.Name} : {shaderExtension.Behavior.ToString().ToLowerInvariant()}\n");
                }

                // #pragma
#if DEBUG
                // Debug directives
                sourceLines.Insert(headerLine++, "#pragma optimization(off)\n");
                sourceLines.Insert(headerLine++, "#pragma debug(on)\n");
#else
                sourceLines.Insert(headerLine++, "#pragma optimization(on)\n");
                sourceLines.Insert(headerLine++, "#pragma debug(off)\n");
#endif
            }
            else
            {
                switch (ObjectStage)
                {
                case ShaderType.FragmentShader:
                    sourceLines.Insert(headerLine++, "precision mediump float;\n");
                    break;
                }
            }

            // Append required #define statments
            if (cctx.Defines != null)
            {
                foreach (string def in cctx.Defines)
                {
                    sourceLines.Insert(headerLine++, $"#define {def} 1\n");
                    Log("  Symbol: {0}", def);
                }
            }

            // Remove comment lines
            sourceLines = CleanSource(sourceLines);

            // Preprocessing
            // Manage #include preprocessor directives in the case GL_ARB_shading_language_include is not supported
            // When #include are replaced, conditionals are processed too
            if (!ctx.Extensions.ShadingLanguageInclude_ARB)
            {
                sourceLines = ShaderPreprocessor.Process(sourceLines, cctx, ctx.IncludeLibrary, ShaderPreprocessor.Stage.All);
                sourceLines = CleanSource(sourceLines);
            }

            return(sourceLines);
        }
Ejemplo n.º 17
0
        /// <summary>
        /// Actually create this ShaderObject resource.
        /// </summary>
        /// <param name="ctx">
        /// A <see cref="GraphicsContext"/> used for allocating resources.
        /// </param>
        protected override void CreateObject(GraphicsContext ctx)
        {
            if (ctx == null)
            {
                throw new ArgumentNullException("ctx");
            }
            if (_CompilationParams == null)
            {
                throw new InvalidOperationException("no compiler parameters");
            }

            // Using a deep copy of the shader compiler context, since it will be modified by this ShaderProgram
            // instance and the attached ShaderObject instances
            ShaderCompilerContext cctx = new ShaderCompilerContext(_CompilationParams);

            Log("=== Compilation of shader object '{0}'.", _SourcePath);

            List <string> source = GenerateSource(ctx, cctx);                   // Source generation!

            // Set shader source
            Gl.ShaderSource(ObjectName, source.ToArray());

#if !MONODROID
            if (ctx.Extensions.ShadingLanguageInclude_ARB)
            {
                string[] includePaths = new string[cctx.Includes.Count];

                cctx.Includes.CopyTo(includePaths, 0);

                // Compile shader object (specifying include paths)
                Gl.CompileShaderIncludeARB(ObjectName, includePaths, null);
            }
            else
            {
                // Compile shader object (includes are already preprocessed)
                Gl.CompileShader(ObjectName);
            }
#else
            // Compile shader object (includes are already preprocessed)
            Gl.CompileShader(ObjectName);
#endif

            // Check for compilation errors
            int compilationStatus;

            Gl.GetShader(ObjectName, ShaderParameterName.CompileStatus, out compilationStatus);

            if (compilationStatus != Gl.TRUE)
            {
                StringBuilder sb = GetInfoLog();

                // Stop compilation process
                Log("Shader object \"{0}\" compilation failed:\n{1}", _SourcePath ?? "<Hardcoded>", sb.ToString());

                // Log the source code referred to the shader log
                Log("Source code for shader '{0}' that has generated the compiler error.", _SourcePath);
                Log("--------------------------------------------------------------------------------");
                uint sourcelineNo = 0;
                foreach (string sourceline in source)
                {
                    Log("{0,4} | {1}", ++sourcelineNo, sourceline.Length > 0 ? sourceline.Remove(sourceline.Length - 1, 1) : String.Empty);
                }
                Log("--------------------------------------------------------------------------------");

                throw new ShaderException("shader object is not valid. Compiler output for {0}: {1}\n", _SourcePath, sb.ToString());
            }
            else
            {
                StringBuilder sb = GetInfoLog();

                if (sb.Length > 0)
                {
                    Log("Shader object \"{0}\" compilation warning: {1}", _SourcePath ?? "<Hardcoded>", sb.ToString());
                }
            }

            _Compiled = true;
        }
Ejemplo n.º 18
0
        /// <summary>
        /// Process a source using the preprocessor.
        /// </summary>
        /// <param name="shaderSource"></param>
        /// <returns></returns>
        private static List <string> ProcessConditionals(List <string> shaderSource, ShaderCompilerContext cctx)
        {
            if (shaderSource == null)
            {
                throw new ArgumentNullException("shaderSource");
            }
            if (cctx == null)
            {
                throw new ArgumentNullException("cctx");
            }

            ShaderPreprocessorParser expressionEvaluator = new ShaderPreprocessorParser();
            List <string>            processedSource     = new List <string>();

            // Define system preprocessor symbols
            // TODO: support __FILE__ and __LINE__
            expressionEvaluator.Define("__VERSION__", cctx.ShaderVersion.VersionId.ToString());
            if (cctx.ShaderVersion.Api == KhronosVersion.ApiEssl)
            {
                expressionEvaluator.Define("GL_ES", "1");
            }
            // Define user preprocessor symbols
            foreach (string symbol in cctx.Defines)
            {
                expressionEvaluator.Define(symbol, "1");
            }

            foreach (string sourceLine in shaderSource)
            {
                Match match;

                if ((match = _RegexPreprocessorExpression.Match(sourceLine)).Success)
                {
                    string op   = match.Groups["Op"].Value;
                    string expr = match.Groups["Expr"].Success ? match.Groups["Expr"].Value : null;

                    // TODO: support empty # directive

                    switch (op)
                    {
                    case "if":
                        if (expr == null)
                        {
                            throw new InvalidOperationException("invalid #if directive");
                        }
                        expressionEvaluator.If(expr);
                        break;

                    case "ifdef":
                        if (expr == null)
                        {
                            throw new InvalidOperationException("invalid #ifdef directive");
                        }
                        expressionEvaluator.IfDef(expr);
                        break;

                    case "ifndef":
                        if (expr == null)
                        {
                            throw new InvalidOperationException("invalid #ifndef directive");
                        }
                        expressionEvaluator.IfNDef(expr);
                        break;

                    case "elif":
                        if (expr == null)
                        {
                            throw new InvalidOperationException("invalid #elif directive");
                        }
                        expressionEvaluator.ElIf(expr);
                        break;

                    case "else":
                        if (expr != null)
                        {
                            throw new InvalidOperationException("invalid #else directive");
                        }
                        expressionEvaluator.Else();
                        break;

                    case "endif":
                        if (expr != null)
                        {
                            throw new InvalidOperationException("invalid #endif directive");
                        }
                        expressionEvaluator.Endif();
                        break;

                    case "define":
                        if (expr == null)
                        {
                            throw new InvalidOperationException("invalid #define directive");
                        }
                        if (expressionEvaluator.IsActive)
                        {
                            expressionEvaluator.Define(expr);
                            processedSource.Add(sourceLine);
                        }
                        break;

                    case "undef":
                        if (expr == null)
                        {
                            throw new InvalidOperationException("invalid #undef directive");
                        }
                        if (expressionEvaluator.IsActive)
                        {
                            expressionEvaluator.Undef(expr);
                            processedSource.Add(sourceLine);
                        }
                        break;

                    case "line":                                        // TODO: support __LINE__
                    case "version":                                     // TODO: support __VERSION__ warning (mismatch with cctx.ShaderVersion)
                    case "error":
                    case "pragma":
                    case "extension":
                        // Note: above directives are output as they are, only if the preprocessor is active
                        if (expressionEvaluator.IsActive)
                        {
                            processedSource.Add(sourceLine);
                        }
                        break;

                    default:
                        throw new NotSupportedException("preprocessor token " + op + " not supported");
                    }
                }
                else
                {
                    if (expressionEvaluator.IsActive)
                    {
                        processedSource.Add(sourceLine);
                    }
                }
            }

            return(processedSource);
        }
Ejemplo n.º 19
0
        /// <summary>
        /// Append default source header.
        /// </summary>
        /// <param name="ctx">
        /// A <see cref="GraphicsContext"/> used for the compilation process.
        /// </param>
        /// <param name="sourceLines">
        /// A <see cref="List{String}"/> which represent the current shader object
        /// source lines.
        /// </param>
        /// <param name="version">
        /// A <see cref="Int32"/> representing the shader language version to use in generated shader.
        /// </param>
        protected void AppendHeader(GraphicsContext ctx, ShaderCompilerContext cctx, List <string> sourceLines, int version)
        {
            if (ctx == null)
            {
                throw new ArgumentNullException("ctx");
            }
            if (cctx == null)
            {
                throw new ArgumentNullException("ctx");
            }
            if (sourceLines == null)
            {
                throw new ArgumentNullException("sourceLines");
            }

            if (ctx.ShadingVersion.Api == KhronosVersion.ApiGlsl)
            {
                // Prepend required shader version
                if (version >= 150)
                {
                    // Starting from GLSL 1.50, profiles are implemented

                    if ((ctx.Flags & GraphicsContextFlags.ForwardCompatible) != 0)
                    {
                        sourceLines.Add(String.Format("#version {0} core\n", version));
                    }
                    else
                    {
                        sourceLines.Add(String.Format("#version {0} compatibility\n", version));
                    }
                }
                else
                {
                    sourceLines.Add(String.Format("#version {0}\n", version));
                }

                // #extension
                if (ctx.Extensions.ShadingLanguageInclude_ARB)
                {
                    sourceLines.Add("#extension GL_ARB_shading_language_include : require\n");
                }

                if (ctx.Extensions.UniformBufferObject_ARB)
                {
                    sourceLines.Add("#extension GL_ARB_uniform_buffer_object : enable\n");
                }
                else
                {
                    sourceLines.Add("#define DISABLE_GL_ARB_uniform_buffer_object\n");
                }

                if (ObjectStage == ShaderType.GeometryShader && ctx.Extensions.GeometryShader4_ARB)
                {
                    sourceLines.Add("#extension GL_ARB_geometry_shader4 : enable\n");
                }

                if (ctx.Extensions.ShaderDrawParameters_ARB)
                {
                    sourceLines.Add("#extension GL_ARB_shader_draw_parameters : enable\n");
                }

                foreach (ShaderExtension shaderExtension in cctx.Extensions)
                {
                    // Do not include any #extension directive on extensions not supported by driver
                    if (ctx.Extensions.HasExtensions(shaderExtension.Name) == false)
                    {
                        continue;
                    }
                    sourceLines.Add(String.Format(
                                        "#extension {0} : {1}\n", shaderExtension.Name, shaderExtension.Behavior.ToString().ToLowerInvariant())
                                    );
                }

                // #pragma
#if DEBUG
                // Debug directives
                sourceLines.Add("#pragma optimization(off)\n");
                sourceLines.Add("#pragma debug(on)\n");
#else
                sourceLines.Add("#pragma optimization(on)\n");
                sourceLines.Add("#pragma debug(off)\n");
#endif
            }
            else
            {
                switch (ObjectStage)
                {
                case ShaderType.FragmentShader:
                    sourceLines.Add("precision mediump float;\n");
                    break;
                }
            }
        }
Ejemplo n.º 20
0
        private static List <string> Process(ShaderIncludeLibrary includeLibrary, ShaderCompilerContext cctx, IncludeProcessorContext ictx, IEnumerable <string> shaderSource)
        {
            if (includeLibrary == null)
            {
                throw new ArgumentNullException("includeLibrary");
            }
            if (cctx == null)
            {
                throw new ArgumentNullException("cctx");
            }
            if (shaderSource == null)
            {
                throw new ArgumentNullException("sSource");
            }

            List <string> processedSource = new List <string>();

            // Shader includes not supported. Process them manually before submitting shader source text lines.

            foreach (string line in shaderSource)
            {
                // Ignore null items
                if (line == null)
                {
                    continue;
                }

                if ((_RegexInclude.Match(line)).Success)
                {
                    ShaderInclude shaderInclude = null;
                    string        includePath   = ExtractIncludePath(line);
                    string        canonicalPath = String.Empty;

                    if (includePath.StartsWith("/") == false)
                    {
                        // If <path> does not start with a forward slash, it is a path relative
                        // to one of the ordered list of initial search points.

                        if ((ictx.CurrentPath != String.Empty) && (_RegexIncludeAngular.Match(line).Success == false))
                        {
                            // If it is quoted with double quotes in a previously included string, then the first
                            // search point will be the tree location where the previously included
                            // string had been found. If not found there, the search continues at
                            // the beginning of the list of search points, as just described (see comment later).

                            canonicalPath = NormalizeIncludePath(Path.Combine(ictx.CurrentPath, includePath));
                            if (includeLibrary.IsPathDefined(canonicalPath))
                            {
                                shaderInclude = includeLibrary.GetInclude(canonicalPath);
                            }
                        }

                        // If this path is quoted with angled brackets, the tree is searched relative to the
                        // first search point in the ordered list, and then relative to each
                        // subsequent search point, in order, until a matching path is found in
                        // the tree. This is also the behavior if it is quoted with double
                        // quotes in an initial (non-included) shader string.

                        if (shaderInclude == null)
                        {
                            foreach (string includeSearchPath in cctx.Includes)
                            {
                                canonicalPath = NormalizeIncludePath(Path.Combine(includeSearchPath, includePath));
                                if (includeLibrary.IsPathDefined(canonicalPath))
                                {
                                    shaderInclude = includeLibrary.GetInclude(canonicalPath);
                                    break;
                                }
                            }
                        }
                    }
                    else
                    {
                        // If <path> starts with a forward slash, whether it is quoted with
                        // double quotes or with angled brackets, the list of search points is
                        // ignored and <path> is looked up in the tree as described in Appendix
                        // A.

                        canonicalPath = includePath;
                        if (includeLibrary.IsPathDefined(canonicalPath) == false)
                        {
                            throw new InvalidOperationException(String.Format("absolute include path \"{0}\" not existing", canonicalPath));
                        }
                        shaderInclude = includeLibrary.GetInclude(canonicalPath);
                    }

                    if (shaderInclude == null)
                    {
                        throw new InvalidOperationException(String.Format("include path '{0}' not found", includePath));
                    }

                    // Recurse on included source (it may contain other includes)
                    IncludeProcessorContext ictxRecurse = new IncludeProcessorContext();

                    System.Diagnostics.Debug.Assert(String.IsNullOrEmpty(canonicalPath) == false);
                    ictxRecurse.CurrentPath = canonicalPath;

                    processedSource.AddRange(Process(includeLibrary, cctx, ictxRecurse, shaderInclude.Source));
                }
                else
                {
                    processedSource.Add(line);
                }
            }

            return(processedSource);
        }