]> git.tdb.fi Git - libs/gl.git/commitdiff
Colorize the debug output of the GLSL compiler
authorMikko Rasa <tdb@tdb.fi>
Wed, 17 Nov 2021 20:27:08 +0000 (22:27 +0200)
committerMikko Rasa <tdb@tdb.fi>
Thu, 18 Nov 2021 00:50:28 +0000 (02:50 +0200)
source/glsl/compiler.cpp
source/glsl/compiler.h
source/glsl/debug.cpp
source/glsl/debug.h
tools/glslcompiler.cpp

index 0e26a16353b46bf1ae73876fc08be92b20621b2d..16ac375ca57f05660aa83ae89d9e75b4aff2a941 100644 (file)
@@ -209,11 +209,11 @@ const SourceMap &Compiler::get_source_map() const
        return module->source_map;
 }
 
-string Compiler::get_stage_debug(Stage::Type stage_type) const
+string Compiler::get_stage_debug(Stage::Type stage_type, bool use_colors) const
 {
        auto i = find_member(module->stages, stage_type, &Stage::type);
        if(i!=module->stages.end())
-               return DumpTree().apply(*i);
+               return DumpTree(use_colors).apply(*i);
        throw key_error(Stage::get_stage_name(stage_type));
 }
 
index 52076e693f66c9f84a7282dca8b0c9fa91b559d4..0db1ca400de7f017b2991e414dd3c0c331bc8a3d 100644 (file)
@@ -117,7 +117,7 @@ public:
 
        /** Returns a textual representation of the syntax tree for a shader stage.
        Intended for debugging purposes. */
-       std::string get_stage_debug(Stage::Type) const;
+       std::string get_stage_debug(Stage::Type, bool = false) const;
 
        /** Returns diagnostics from compilation.  The output is intended to be
        viewed by humans. */
index 60ac76f252594f79b823f30cc8c1f015766e4d92..5ee30e0996c4dfc6ff5331d1c1b200f472c6fcf1 100644 (file)
@@ -8,6 +8,24 @@ namespace Msp {
 namespace GL {
 namespace SL {
 
+const DumpTree::Colors DumpTree::no_colors =
+{ "", "", "", "", "", "", "" };
+
+const DumpTree::Colors DumpTree::default_colors =
+{
+       "\033[0m",         // default
+       "\033[38;5;250m",  // tree
+       "\033[38;5;244m",  // location
+       "\033[38;5;146m",  // label
+       "\033[38;5;194m",  // type
+       "\033[38;5;230m",  // name
+       "\033[38;5;210m"   // error
+};
+
+DumpTree::DumpTree(bool use_colors):
+       colors(use_colors ? default_colors : no_colors)
+{ }
+
 string DumpTree::apply(Stage &stage)
 {
        formatted = format("Stage: %s\n", Stage::get_stage_name(stage.type));
@@ -15,13 +33,13 @@ string DumpTree::apply(Stage &stage)
        append(format("Version: %d.%02d", stage.required_features.glsl_version.major, stage.required_features.glsl_version.minor));
 
        for(const auto &kvp: stage.types)
-               append(format("Type: %%%d %s", get_label(*kvp.second), kvp.first));
+               append(format("Type: %s %s%s%s", get_label(*kvp.second), colors.type_color, kvp.first, colors.default_color));
 
        for(const auto &kvp: stage.interface_blocks)
-               append(format("Interface block: %%%d %s", get_label(*kvp.second), kvp.first));
+               append(format("Interface block: %s %s", get_label(*kvp.second), format_name(kvp.first)));
 
        for(const auto &kvp: stage.functions)
-               append(format("Function: %%%d %s", get_label(*kvp.second), kvp.first));
+               append(format("Function: %s %s", get_label(*kvp.second), format_name(kvp.first)));
 
        last_branch();
        stage.content.visit(*this);
@@ -30,19 +48,30 @@ string DumpTree::apply(Stage &stage)
 
 void DumpTree::append(const string &line)
 {
+       formatted += colors.tree_color;
        StringCodec::Utf8::Encoder enc;
        for(auto i=tree.begin(); i!=tree.end(); )
        {
                enc.encode_char(*i++, formatted);
                enc.encode_char((i==tree.end() ? REACH : EMPTY), formatted);
        }
+       formatted += colors.default_color;
        formatted += line;
        formatted += '\n';
 }
 
 void DumpTree::append(const Node &node, const string &line)
 {
-       append(format("<%d:%d> %s", node.source, node.line, line));
+       string location;
+       if(node.source==BUILTIN_SOURCE)
+               location = "builtin";
+       else if(node.source==INTERNAL_SOURCE)
+               location = "internal";
+       else if(node.source==GENERATED_SOURCE)
+               location = "generated";
+       else
+               location = format("%s:%s", node.source, node.line);
+       append(format("%s<%s>%s %s", colors.location_color, location, colors.default_color, line));
 }
 
 void DumpTree::append_subtree(const vector<Branch> &branches)
@@ -95,17 +124,27 @@ void DumpTree::end_sub()
                tree.back() = BRANCH;
 }
 
-unsigned DumpTree::get_label(const Node &node)
+std::string DumpTree::get_label(const Node &node)
 {
        unsigned &label = node_labels[&node];
        if(!label)
                label = node_labels.size();
-       return label;
+       return format("%s%%%d%s", colors.label_color, label, colors.default_color);
 }
 
 string DumpTree::format_type(TypeDeclaration *type)
 {
-       return (type ? type->name : "?");
+       return type ? format_type(type->name) : format("%s?%s", colors.error_color, colors.default_color);
+}
+
+string DumpTree::format_type(const string &type)
+{
+       return format("%s%s%s", colors.type_color, type, colors.default_color);
+}
+
+string DumpTree::format_name(const string &name)
+{
+       return format("%s%s%s", colors.name_color, name, colors.default_color);
 }
 
 template<typename T>
@@ -123,7 +162,7 @@ void DumpTree::visit(Block &block)
        begin_sub();
 
        for(const auto &kvp: block.variables)
-               append(format("Variable: %%%d %s %s", get_label(*kvp.second), kvp.second->type, kvp.first));
+               append(format("Variable: %s %s %s", get_label(*kvp.second), format_type(kvp.second->type), format_name(kvp.first)));
 
        for(auto i=block.body.cbegin(); i!=block.body.cend(); )
        {
@@ -143,8 +182,8 @@ void DumpTree::visit(VariableReference &var)
 {
        string text;
        if(var.declaration)
-               text += format("%%%d ", get_label(*var.declaration));
-       text += format("%s (var) -> %s", var.name, format_type(var.type));
+               text += format("%s ", get_label(*var.declaration));
+       text += format("%s (var) -> %s", format_name(var.name), format_type(var.type));
        append(var, text);
 }
 
@@ -152,8 +191,8 @@ void DumpTree::visit(InterfaceBlockReference &iface)
 {
        string text;
        if(iface.declaration)
-               text += format("%%%d ", get_label(*iface.declaration));
-       text += format("%s (iface) -> %s", iface.name, format_type(iface.type));
+               text += format("%s ", get_label(*iface.declaration));
+       text += format("%s (iface) -> %s", format_name(iface.name), format_type(iface.type));
        append(iface, text);
 }
 
@@ -161,8 +200,8 @@ void DumpTree::visit(MemberAccess &memacc)
 {
        string text = "Member access:";
        if(memacc.declaration)
-               text += format(" %%%d", get_label(*memacc.declaration));
-       text += format(" .%s (%d) -> %s", memacc.member, memacc.index, format_type(memacc.type));
+               text += format(" %s", get_label(*memacc.declaration));
+       text += format(" .%s (%d) -> %s", format_name(memacc.member), memacc.index, format_type(memacc.type));
        append(memacc, text);
        append_subtree(*memacc.left);
 }
@@ -201,7 +240,7 @@ void DumpTree::visit(Assignment &assign)
        begin_sub();
        if(assign.target.declaration)
        {
-               string text = format("Target: %%%d", get_label(*assign.target.declaration));
+               string text = format("Target: %s", get_label(*assign.target.declaration));
 
                static const char swizzle[4] = { 'x', 'y', 'z', 'w' };
                for(unsigned i=0; i<assign.target.chain_len; ++i)
@@ -246,8 +285,8 @@ void DumpTree::visit(FunctionCall &call)
 {
        string head = "Function call: ";
        if(call.declaration)
-               head += format("%%%d ", get_label(*call.declaration));
-       head += call.name;
+               head += format("%s ", get_label(*call.declaration));
+       head += format_name(call.name);
        if(call.constructor)
                head += " (constructor)";
        head += format(" -> %s", format_type(call.type));
@@ -301,11 +340,11 @@ void DumpTree::visit(InterfaceLayout &layout)
 
 void DumpTree::visit(BasicTypeDeclaration &type)
 {
-       append(type, format("%%%d typedef %s", get_label(type), type.name));
+       append(type, format("%s typedef %s", get_label(type), format_type(type.name)));
 
        vector<Branch> branches;
        if(type.base_type)
-               branches.emplace_back(format("%s: %%%d %s", (type.kind==BasicTypeDeclaration::ALIAS ? "Alias of" : "Base"), get_label(*type.base_type), type.base_type->name));
+               branches.emplace_back(format("%s: %s %s", (type.kind==BasicTypeDeclaration::ALIAS ? "Alias of" : "Base"), get_label(*type.base_type), format_type(type.base_type->name)));
        if(type.kind==BasicTypeDeclaration::VECTOR)
                branches.emplace_back(format("Vector: %d", type.size));
        else if(type.kind==BasicTypeDeclaration::MATRIX)
@@ -317,12 +356,12 @@ void DumpTree::visit(ImageTypeDeclaration &type)
 {
        static const char *const dims[] = { "1D", "2D", "3D", "Cube" };
 
-       append(type, format("%%%d typedef %s", get_label(type), type.name));
+       append(type, format("%s typedef %s", get_label(type), format_type(type.name)));
 
        vector<Branch> branches;
        branches.emplace_back(format("Dimensions: %s%s", dims[type.dimensions-1], (type.array ? " array" : "")));
        if(type.base_type)
-               branches.emplace_back(format("Element type: %%%d %s", get_label(*type.base_type), type.base_type->name));
+               branches.emplace_back(format("Element type: %s %s", get_label(*type.base_type), format_type(type.base_type->name)));
        if(type.shadow)
                branches.emplace_back("Shadow");
        append_subtree(branches);
@@ -330,13 +369,13 @@ void DumpTree::visit(ImageTypeDeclaration &type)
 
 void DumpTree::visit(StructDeclaration &strct)
 {
-       append(strct, format("%%%d struct %s", get_label(strct), strct.name));
+       append(strct, format("%s struct %s", get_label(strct), strct.name));
        append_subtree(strct.members);
 }
 
 void DumpTree::visit(VariableDeclaration &var)
 {
-       string decl = format("%%%d ", get_label(var));
+       string decl = format("%s ", get_label(var));
        if(var.constant)
                decl += "const ";
        if(!var.interpolation.empty())
@@ -347,7 +386,7 @@ void DumpTree::visit(VariableDeclaration &var)
                decl += format("%s ", var.interface);
        if(!var.precision.empty())
                decl += format("%s ", var.precision);
-       decl += format("%s %s", var.type, var.name);
+       decl += format("%s %s", format_type(var.type), format_name(var.name));
        if(var.source==BUILTIN_SOURCE)
                decl += " (builtin)";
        else if(var.linked_declaration)
@@ -356,26 +395,26 @@ void DumpTree::visit(VariableDeclaration &var)
 
        vector<Branch> branches;
        if(var.type_declaration)
-               branches.push_back(format("Type: %%%d %s", get_label(*var.type_declaration), var.type_declaration->name));
+               branches.emplace_back(format("Type: %s %s", get_label(*var.type_declaration), format_type(var.type_declaration->name)));
        if(var.layout)
-               branches.push_back(var.layout.get());
+               branches.emplace_back(var.layout.get());
        if(var.array)
        {
                if(var.array_size)
                        branches.emplace_back("Array []", var.array_size.get());
                else
-                       branches.push_back("Array []");
+                       branches.emplace_back("Array []");
        }
        if(var.init_expression)
-               branches.push_back(var.init_expression.get());
+               branches.emplace_back(var.init_expression.get());
        append_subtree(branches);
 }
 
 void DumpTree::visit(InterfaceBlock &iface)
 {
-       string head = format("%%%d %s %s", get_label(iface), iface.interface, iface.block_name);
+       string head = format("%s %s %s", get_label(iface), iface.interface, format_name(iface.block_name));
        if(!iface.instance_name.empty())
-               head += format(" %s", iface.instance_name);
+               head += format(" %s", format_name(iface.instance_name));
        if(iface.array)
                head += "[]";
        if(iface.source==BUILTIN_SOURCE)
@@ -386,17 +425,17 @@ void DumpTree::visit(InterfaceBlock &iface)
 
        vector<Branch> branches;
        if(iface.type_declaration)
-               branches.push_back(format("Type: %%%d %s", get_label(*iface.type_declaration), iface.type_declaration->name));
+               branches.emplace_back(format("Type: %s %s", get_label(*iface.type_declaration), format_type(iface.type_declaration->name)));
        if(iface.layout)
-               branches.push_back(iface.layout.get());
+               branches.emplace_back(iface.layout.get());
        if(iface.members)
-               branches.push_back(iface.members.get());
+               branches.emplace_back(iface.members.get());
        append_subtree(branches);
 }
 
 void DumpTree::visit(FunctionDeclaration &func)
 {
-       string text = format("%%%d %s %s%s", get_label(func), func.return_type, func.name, (func.signature.empty() ? "(?)" : func.signature));
+       string text = format("%s %s %s%s", get_label(func), format_type(func.return_type), format_name(func.name), (func.signature.empty() ? "(?)" : func.signature));
        if(func.source==BUILTIN_SOURCE)
                text += " (builtin)";
        else if(!func.definition)
@@ -405,14 +444,14 @@ void DumpTree::visit(FunctionDeclaration &func)
 
        begin_sub();
        if(func.return_type_declaration)
-               append(format("Return type: %%%d %s", get_label(*func.return_type_declaration), func.return_type_declaration->name));
+               append(format("Return type: %s %s", get_label(*func.return_type_declaration), format_type(func.return_type_declaration)));
        for(const RefPtr<VariableDeclaration> &p: func.parameters)
                p->visit(*this);
        last_branch();
        if(func.definition==&func)
                func.body.visit(*this);
        else if(func.definition)
-               append(format("Definition: %%%d", get_label(*func.definition)));
+               append(format("Definition: %s", get_label(*func.definition)));
        end_sub();
 }
 
index c3e9c701075b87974a7e5101ad635bf0bf8e5d8b..5b2a3d96594460459d34783a93545e22dc23cb01 100644 (file)
@@ -32,11 +32,28 @@ private:
                Branch(Node *n): node(n) { }
        };
 
+       struct Colors
+       {
+               const char *default_color;
+               const char *tree_color;
+               const char *location_color;
+               const char *label_color;
+               const char *type_color;
+               const char *name_color;
+               const char *error_color;
+       };
+
        std::map<const Node *, unsigned> node_labels;
        std::string formatted;
        std::vector<TreeChars> tree;
+       const Colors &colors;
+
+       static const Colors no_colors;
+       static const Colors default_colors;
 
 public:
+       DumpTree(bool = false);
+
        std::string apply(Stage &);
        std::string apply(Node &n) { n.visit(*this); return formatted; }
 
@@ -48,8 +65,10 @@ private:
        void begin_sub();
        void last_branch();
        void end_sub();
-       unsigned get_label(const Node &);
+       std::string get_label(const Node &);
        std::string format_type(TypeDeclaration *);
+       std::string format_type(const std::string &);
+       std::string format_name(const std::string &);
 
        template<typename T>
        typename T::const_iterator increment(typename T::const_iterator &, const T &);
index ee9c2d3ca6ec895574213589db91f09f70f2c447..f7bb2de9af1b8b090341d34383e0cde66cb7a204 100644 (file)
@@ -168,7 +168,7 @@ int GlslCompiler::main()
        {
                vector<GL::SL::Stage::Type> stages = compiler.get_stages();
                for(vector<GL::SL::Stage::Type>::const_iterator i=stages.begin(); i!=stages.end(); ++i)
-                       IO::print("%s\n", compiler.get_stage_debug(*i));
+                       IO::print("%s\n", compiler.get_stage_debug(*i, true));
        }
 
        IO::Base *out = &IO::cout;