/// <summary>Appends the default line terminator to the end of this instance.</summary>
 public void AppendLine() => _vsb.AppendLine();
Exemple #2
0
        private static void PreprocessShaderSource(AssetManager assetManager,
                                                   ref Utf16ValueStringBuilder stringBuilder,
                                                   string shaderPath,
                                                   List <string> shaderIncludePaths,
                                                   Stack <string> includeStack)
        {
            string shaderSource = GetShaderSource(assetManager, shaderPath);

            // Skip pre-processing if the string doesn't have any include directives.
            if (!shaderSource.Contains("#include "))
            {
                stringBuilder.Append(shaderSource);
                return;
            }

            // Add current include path to the stack so we can book-keep to prevent circular dependencies.
            includeStack.Push(shaderPath);

            int lineNumber = 1;

            using var lineReader = new LineReader(shaderSource);

            for (ReadOnlyMemory <char> line = lineReader.ReadLine(); !lineReader.Finished; line = lineReader.ReadLine())
            {
                // Check if the line starts with "#include "
                if (line.Span.StartsWith(_includeCompare.Span))
                {
                    if (TryParseIncludeLine(line, out var includeFile))
                    {
                        string includePath = Path.Combine(Path.GetDirectoryName(shaderPath) ?? throw new Exception(), includeFile.ToString());

                        if (includeStack.Contains(includePath))
                        {
                            throw new ShaderPreprocessException($"Include statement would introduce cyclic dependency: {includeFile}\n" +
                                                                $"Parent: \"{shaderPath}\"");
                        }

                        shaderIncludePaths.Add(includePath);

                        stringBuilder.Append("#line 1 ");
                        stringBuilder.AppendLine((shaderIncludePaths.IndexOf(includePath) + 1).ToString());

                        PreprocessShaderSource(assetManager,
                                               ref stringBuilder,
                                               includePath,
                                               shaderIncludePaths,
                                               includeStack);

                        stringBuilder.Append("\n#line ");
                        stringBuilder.Append(lineNumber);
                        stringBuilder.AppendLine((shaderIncludePaths.IndexOf(includePath) + 1).ToString());
                    }
                    else
                    {
                        throw new ShaderPreprocessException($"Error when parsing include statement: {shaderPath}:{lineNumber}");
                    }
                }
                else
                {
                    stringBuilder.Append(line);
                    lineNumber++;
                }

                stringBuilder.Append('\n');
            }

            includeStack.Pop();
        }