]> git.tdb.fi Git - libs/gl.git/commitdiff
Add some documentation to the GLSL compiler
authorMikko Rasa <tdb@tdb.fi>
Sat, 27 Feb 2021 14:32:33 +0000 (16:32 +0200)
committerMikko Rasa <tdb@tdb.fi>
Sat, 27 Feb 2021 14:32:33 +0000 (16:32 +0200)
source/glsl/compatibility.h
source/glsl/compiler.cpp
source/glsl/compiler.h
source/glsl/debug.h
source/glsl/evaluate.h
source/glsl/generate.cpp
source/glsl/generate.h
source/glsl/optimize.h
source/glsl/output.h
source/glsl/visitor.h

index 852a6590bd67c287cf272d1a85bc9cfdb746a5c3..ad6c7cbe9c875f3a63c7cdb69c682f2f7f7a0aa3 100644 (file)
@@ -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:
index a18b8e8c2c3df57e0f26c2d126719edbaced8fb5..5bec9c8b1b8f475163b50a35b57b0a92e5bec84b 100644 (file)
@@ -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);
 
index 69ac7427d80fc97188fa2bcbb0c2c600ef6cf67a..1f3cbee4698c466a7b88b562d56373f7f9b0fb6e 100644 (file)
@@ -28,35 +28,87 @@ private:
        std::map<std::string, int> 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 & = "<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 & = "<file>");
+
+       /** 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<std::string, int> &);
+
+       /** 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<Stage::Type> 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<std::string, unsigned> &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<std::string, unsigned> &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 &);
 };
 
index 6aca7af0fb2a94b0aab0b8936f1c9ea902021d2a..87ec4734e0b1bda18e4513a481688bbfee693fc0 100644 (file)
@@ -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:
index 6cbc6cb4a24c0aa8325e300a780e3bf34ee79393..2c80a6cba24fd90881e85062400a052f63335a7a 100644 (file)
@@ -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:
index 30dca25a2939c28068f3493e18275ebd51ca0026..09c5c37d3fa2c21fbf6afde8a594e04d1ecfa5f7 100644 (file)
@@ -128,7 +128,7 @@ void ConstantSpecializer::visit(VariableDeclaration &var)
 }
 
 
-void BlockResolver::enter(Block &block)
+void BlockHierarchyResolver::enter(Block &block)
 {
        block.parent = current_block;
 }
index 68816b8b50acec9411ec331e8b866749412bb3d2..b82bdca365bc02e7fd856c86f5011eb124517f92 100644 (file)
@@ -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<std::string, std::vector<FunctionDeclaration *> > 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:
index 38218966369213c5fbc8ba802d38bbf1e8bda420..ed016ca0b9ddd26dd5e8e871b25a0f15484e2881 100644 (file)
@@ -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:
index 66b77bbaaca62a391cce7b022b68473a2f9595e5..69a99d1e5e67979f9dddcd48d5db4c236ce5882e 100644 (file)
@@ -9,6 +9,7 @@ namespace Msp {
 namespace GL {
 namespace SL {
 
+/** Formats the syntax tree as GLSL. */
 class Formatter: private TraversingVisitor
 {
 private:
index a26e785c741e3b97e643d78f6353742feca04dd2..4e48a1a11f112205ec10feedf2017d6c7099ddd1 100644 (file)
@@ -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<typename T>
 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: