/// <summary>
		/// Construct a ShaderIncludeLibrary.
		/// </summary>
		public ShaderIncludeLibrary()
		{
			// Load all include files defined by ShadersLibrary
			foreach (ShadersLibrary.Include shaderLibraryInclude in ShadersLibrary.Instance.Includes) {
				if (_IncludeFileSystem.ContainsKey(shaderLibraryInclude.Id))
					throw new InvalidOperationException(String.Format("include path '{0}' is duplicated", shaderLibraryInclude.Id));

				ShaderInclude shaderInclude = new ShaderInclude(shaderLibraryInclude.Id);

				shaderInclude.LoadSource(shaderLibraryInclude.Path);
				shaderInclude.IncRef();

				_IncludeFileSystem.Add(shaderInclude.IncludePath, shaderInclude);
			}
		}
        /// <summary>
        /// Construct a ShaderIncludeLibrary.
        /// </summary>
        public ShaderIncludeLibrary()
        {
            // Load all include files defined by ShadersLibrary
            foreach (ShadersLibrary.Include shaderLibraryInclude in ShadersLibrary.Instance.Includes)
            {
                if (_IncludeFileSystem.ContainsKey(shaderLibraryInclude.Id))
                {
                    throw new InvalidOperationException(String.Format("include path '{0}' is duplicated", shaderLibraryInclude.Id));
                }

                ShaderInclude shaderInclude = new ShaderInclude(shaderLibraryInclude.Id);

                shaderInclude.LoadSource(shaderLibraryInclude.Path);
                shaderInclude.IncRef();

                _IncludeFileSystem.Add(shaderInclude.IncludePath, shaderInclude);
            }
        }
        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);
        }