From 30465dd3b9f55ec42c4b19c3c2077eede7237a26 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Sat, 27 Feb 2021 16:32:33 +0200 Subject: [PATCH] Add some documentation to the GLSL compiler --- source/glsl/compatibility.h | 6 +++++ source/glsl/compiler.cpp | 12 +++++++-- source/glsl/compiler.h | 52 +++++++++++++++++++++++++++++++++++++ source/glsl/debug.h | 2 ++ source/glsl/evaluate.h | 2 ++ source/glsl/generate.cpp | 2 +- source/glsl/generate.h | 23 ++++++++++++++-- source/glsl/optimize.h | 11 ++++++++ source/glsl/output.h | 1 + source/glsl/visitor.h | 4 +++ 10 files changed, 110 insertions(+), 5 deletions(-) diff --git a/source/glsl/compatibility.h b/source/glsl/compatibility.h index 852a6590..ad6c7cbe 100644 --- a/source/glsl/compatibility.h +++ b/source/glsl/compatibility.h @@ -8,6 +8,8 @@ namespace Msp { namespace GL { namespace SL { +/** Generates default precision declarations if they are missing, to satisfy +GLSL ES requirements. */ class DefaultPrecisionGenerator: private TraversingVisitor { private: @@ -26,6 +28,8 @@ private: virtual void visit(VariableDeclaration &); }; +/** Removes precision qualifiers from variable declarations, as well as +default precision declarations. */ class PrecisionRemover: private TraversingVisitor { private: @@ -39,6 +43,8 @@ private: virtual void visit(VariableDeclaration &); }; +/** Converts structures of the syntax tree to match a particular set of +features. */ class LegacyConverter: private TraversingVisitor { private: diff --git a/source/glsl/compiler.cpp b/source/glsl/compiler.cpp index a18b8e8c..5bec9c8b 100644 --- a/source/glsl/compiler.cpp +++ b/source/glsl/compiler.cpp @@ -214,11 +214,17 @@ void Compiler::generate(Stage &stage, Mode mode) inject_block(stage.content, module->shared.content); DeclarationReorderer().apply(stage); - BlockResolver().apply(stage); + + // Initial resolving pass + BlockHierarchyResolver().apply(stage); FunctionResolver().apply(stage); VariableResolver().apply(stage); + + /* All variables local to a stage have been resolved. Resolve non-local + variables through interfaces. */ InterfaceGenerator().apply(stage); VariableResolver().apply(stage); + DeclarationReorderer().apply(stage); FunctionResolver().apply(stage); ConstantSpecializer().apply(stage, (mode==PROGRAM && specialized ? &spec_values : 0)); @@ -231,9 +237,11 @@ bool Compiler::optimize(Stage &stage) ConstantConditionEliminator().apply(stage); FunctionInliner().apply(stage); - BlockResolver().apply(stage); + BlockHierarchyResolver().apply(stage); VariableResolver().apply(stage); + /* Removing variables or functions may cause things from the previous stage + to become unused. */ bool result = UnusedVariableRemover().apply(stage); result |= UnusedFunctionRemover().apply(stage); diff --git a/source/glsl/compiler.h b/source/glsl/compiler.h index 69ac7427..1f3cbee4 100644 --- a/source/glsl/compiler.h +++ b/source/glsl/compiler.h @@ -28,35 +28,87 @@ private: std::map spec_values; public: + /** Creates a compiler using features from the current OpenGL context. */ Compiler(); + + /** Creates a compiler targeting a specific set of features. */ Compiler(const Features &); + ~Compiler(); private: void clear(); + public: + /** Sets the source code to be compiled. Only builtin imports are + available. */ void set_source(const std::string &, const std::string & = ""); + + /** Loads source code from an I/O object. If a collection is used, imports + can be fetched from it. */ void load_source(IO::Base &, DataFile::Collection * = 0, const std::string & = ""); + + /** Loads source code from an I/O object. Only builtin imports are + available. */ void load_source(IO::Base &, const std::string &); + + /** Specializes the shader. All specialization constants are considered + specialized, even if they do not appear in the map. */ void specialize(const std::map &); + + /** Compiles the shader. */ void compile(Mode); + /** Returns combined GLSL source for all shader stages. The result is + suitable for feeding back to the compiler. */ std::string get_combined_glsl() const; + + /** Returns a list of compiled stage types. */ std::vector get_stages() const; + + /** Returns GLSL source for a single shader stage. The result is standard + GLSL suitable for OpenGL or an external GLSL compiler. */ std::string get_stage_glsl(Stage::Type) const; + + /** Returns a map of vertex attribute locations. If the target GLSL version + supports interface layouts, the map is empty (locations are included in the + GLSL soucre). */ const std::map &get_vertex_attributes() const; + + /** Returns a map of fragment output locations. If the target GLSL version + supports interface layouts, the map is empty (locations are included in the + GLSL soucre). */ const std::map &get_fragment_outputs() const; + + /** Returns the mapping of source indices to filenames. Can be used to + translate error messages. */ const SourceMap &get_source_map() const; + /** Returns a textual representation of the syntax tree for a shader stage. + Intended for debugging purposes. */ std::string get_stage_debug(Stage::Type) const; private: + /** Appends a module to the target, processing any imports found in it. */ void append_module(Module &, DataFile::Collection *); + + /** Appends a single stage to the matching stage of the target. */ void append_stage(Stage &); + + /// Imports a module by name and appends it to the target. */ void import(DataFile::Collection *, const std::string &); + + /** Generates any implicitly defines syntactic structures and resolves + variables. */ void generate(Stage &, Mode); + + /** Applies optimizations to a stage. The return value indicates if the + preceding stage should be processed again. */ bool optimize(Stage &); + + /** Performs final adjustments on a stage after compilation. */ void finalize(Stage &, Mode); + static void inject_block(Block &, const Block &); }; diff --git a/source/glsl/debug.h b/source/glsl/debug.h index 6aca7af0..87ec4734 100644 --- a/source/glsl/debug.h +++ b/source/glsl/debug.h @@ -8,6 +8,8 @@ namespace Msp { namespace GL { namespace SL { +/** Creates a textual representation of the syntax tree. The result is encoded +as UTF-8. */ class DumpTree: private TraversingVisitor { private: diff --git a/source/glsl/evaluate.h b/source/glsl/evaluate.h index 6cbc6cb4..2c80a6cb 100644 --- a/source/glsl/evaluate.h +++ b/source/glsl/evaluate.h @@ -7,6 +7,8 @@ namespace Msp { namespace GL { namespace SL { +/** Evaluates an expression. Only expressions consisting entirely of compile- +time constants can be evaluated. */ class ExpressionEvaluator: public NodeVisitor { public: diff --git a/source/glsl/generate.cpp b/source/glsl/generate.cpp index 30dca25a..09c5c37d 100644 --- a/source/glsl/generate.cpp +++ b/source/glsl/generate.cpp @@ -128,7 +128,7 @@ void ConstantSpecializer::visit(VariableDeclaration &var) } -void BlockResolver::enter(Block &block) +void BlockHierarchyResolver::enter(Block &block) { block.parent = current_block; } diff --git a/source/glsl/generate.h b/source/glsl/generate.h index 68816b8b..b82bdca3 100644 --- a/source/glsl/generate.h +++ b/source/glsl/generate.h @@ -11,6 +11,7 @@ namespace Msp { namespace GL { namespace SL { +/** Combines multiple declarations of the same identifier into one. */ class DeclarationCombiner: private TraversingVisitor { private: @@ -27,6 +28,9 @@ private: virtual void visit(VariableDeclaration &); }; +/** Manipulates specialization constants. If values are specified, turns +specialization constants into normal constants. Without values assigns +automatic constant_ids to specialization constants. */ class ConstantSpecializer: private TraversingVisitor { private: @@ -41,7 +45,8 @@ private: virtual void visit(VariableDeclaration &); }; -class BlockResolver: private TraversingVisitor +/** Forms links between nested blocks in the syntax tree. */ +class BlockHierarchyResolver: private TraversingVisitor { public: void apply(Stage &s) { s.content.visit(*this); } @@ -50,6 +55,8 @@ private: virtual void enter(Block &); }; +/** Resolves variable references. Variable references which match the name +of an interface block are turned into interface block references. */ class VariableResolver: private TraversingVisitor { private: @@ -81,19 +88,29 @@ private: virtual void visit(InterfaceBlock &); }; +/** Resolves function declarations and calls. */ class FunctionResolver: private TraversingVisitor { private: + Stage *stage; std::map > functions; public: - void apply(Stage &s) { s.content.visit(*this); } + void apply(Stage &); private: virtual void visit(FunctionCall &); virtual void visit(FunctionDeclaration &); }; +/** Materializes implicitly declared interfaces. + +Out variable declarations inside functions are moved to the global scope. + +Passthrough statements are processed, generating out variables to match in +variables and copying values. + +Unresolved variables are looked up in the previous stage's out variables. */ class InterfaceGenerator: private TraversingVisitor { private: @@ -127,6 +144,8 @@ private: virtual void visit(Passthrough &); }; +/** Reorders declarations to ensure that declarations always appear before +references. */ class DeclarationReorderer: private TraversingVisitor { private: diff --git a/source/glsl/optimize.h b/source/glsl/optimize.h index 38218966..ed016ca0 100644 --- a/source/glsl/optimize.h +++ b/source/glsl/optimize.h @@ -10,6 +10,9 @@ namespace Msp { namespace GL { namespace SL { +/** Finds functions which are candidates for inlining. Currently this means +functions which have no parameters, are only called once, and that call occurs +after the definition of the function. */ class InlineableFunctionLocator: private TraversingVisitor { private: @@ -27,6 +30,9 @@ private: virtual void visit(FunctionDeclaration &); }; +/** Inlines functions. Internally uses InlineableFunctionLocator to find +candidate functions. Only functions which consist of a single return statement +are inlined. */ class FunctionInliner: private TraversingVisitor { private: @@ -51,6 +57,8 @@ private: virtual void visit(Return &); }; +/** Removes conditional statements and loops where the condition can be +determined as constant at compile time. */ class ConstantConditionEliminator: private TraversingVisitor { private: @@ -73,6 +81,8 @@ private: virtual void visit(Iteration &); }; +/** Removes variable declarations with no references to them. Assignment +statements where the result is not used are also removed. */ class UnusedVariableRemover: private TraversingVisitor { private: @@ -119,6 +129,7 @@ private: virtual void visit(Iteration &); }; +/** Removes function declarations with no references to them. */ class UnusedFunctionRemover: private TraversingVisitor { private: diff --git a/source/glsl/output.h b/source/glsl/output.h index 66b77bba..69a99d1e 100644 --- a/source/glsl/output.h +++ b/source/glsl/output.h @@ -9,6 +9,7 @@ namespace Msp { namespace GL { namespace SL { +/** Formats the syntax tree as GLSL. */ class Formatter: private TraversingVisitor { private: diff --git a/source/glsl/visitor.h b/source/glsl/visitor.h index a26e785c..4e48a1a1 100644 --- a/source/glsl/visitor.h +++ b/source/glsl/visitor.h @@ -9,6 +9,7 @@ namespace Msp { namespace GL { namespace SL { +/** Base class for all node visitors. */ class NodeVisitor { protected: @@ -42,6 +43,7 @@ public: virtual void visit(Jump &) { } }; +/** An intermediate base visitor class which traverses the syntax tree. */ class TraversingVisitor: public NodeVisitor { protected: @@ -69,6 +71,7 @@ public: virtual void visit(Return &); }; +/** Gathers nodes of a particular type from the syntax tree. */ template class NodeGatherer: private TraversingVisitor { @@ -82,6 +85,7 @@ private: virtual void visit(T &n) { nodes.push_back(&n); } }; +/** Removes a set of nodes from the syntax tree. */ class NodeRemover: private TraversingVisitor { private: -- 2.43.0