X-Git-Url: http://git.tdb.fi/?p=libs%2Fgl.git;a=blobdiff_plain;f=source%2Fglsl%2Foutput.cpp;h=c2c54f9ff33834d11d681a0e80e976aa75747b39;hp=7d502739903a6cd8708cfc758aac470cad2fa17f;hb=38712d8ecc57d043a2419ffbaeeb57f7a6586f14;hpb=19a24f859cd7fcf581442319499ae24b3e7385a4 diff --git a/source/glsl/output.cpp b/source/glsl/output.cpp index 7d502739..c2c54f9f 100644 --- a/source/glsl/output.cpp +++ b/source/glsl/output.cpp @@ -8,40 +8,37 @@ namespace Msp { namespace GL { namespace SL { -Formatter::Formatter(): - stage(0), - mode(Compiler::PROGRAM), - source_index(0), - source_line(1), - indent(0), - parameter_list(false) -{ } - -const string &Formatter::apply(Stage &s, Compiler::Mode m) +string Formatter::apply(Stage &s) { - mode = m; stage = &s; + omit_builtin = true; const Version &ver = s.required_features.glsl_version; if(ver) { append(format("#version %d%02d", ver.major, ver.minor)); - if(s.required_features.gl_api==OPENGL_ES2 && ver>=Version(3, 0)) + if(s.required_features.target_api==OPENGL_ES && ver>=Version(3, 0)) append(" es"); formatted += '\n'; } + if(s.required_features.arb_enhanced_layouts) + append("#extension GL_ARB_enhanced_layouts: require\n"); if(s.required_features.arb_explicit_attrib_location) - append("#extension arb_explicit_attrib_location: require\n"); + append("#extension GL_ARB_explicit_attrib_location: require\n"); + if(s.required_features.arb_explicit_uniform_location) + append("#extension GL_ARB_explicit_uniform_location: require\n"); if(s.required_features.arb_gpu_shader5) - append("#extension arb_gpu_shader5: require\n"); + append("#extension GL_ARB_gpu_shader5: require\n"); + if(s.required_features.arb_separate_shader_objects) + append("#extension GL_ARB_separate_shader_objects: require\n"); if(s.required_features.arb_uniform_buffer_object) - append("#extension arb_uniform_buffer_object: require\n"); + append("#extension GL_ARB_uniform_buffer_object: require\n"); if(s.required_features.ext_gpu_shader4) - append("#extension ext_gpu_shader4: require\n"); + append("#extension GL_EXT_gpu_shader4: require\n"); if(s.required_features.ext_texture_array) - append("#extension ext_texture_array: require\n"); + append("#extension GL_EXT_texture_array: require\n"); formatted += '\n'; s.content.visit(*this); @@ -52,8 +49,8 @@ const string &Formatter::apply(Stage &s, Compiler::Mode m) void Formatter::append(const string &text) { formatted += text; - for(string::const_iterator i=text.begin(); i!=text.end(); ++i) - if(*i=='\n') + for(char c: text) + if(c=='\n') ++source_line; } @@ -73,7 +70,7 @@ void Formatter::set_source(unsigned index, unsigned line) else { unsigned l = line; - if(mode==Compiler::PROGRAM && stage && stage->required_features.glsl_versionrequired_features.glsl_version && stage->required_features.glsl_version set(indent, indent+(indent>0 || use_braces)); + string spaces(indent*2, ' '); + bool first = true; + for(const RefPtr &s: block.body) + { + if(omit_builtin && s->source<=BUILTIN_SOURCE) + continue; + if(!first) + append('\n'); + first = false; + set_source(s->source, s->line); + append(spaces); + s->visit(*this); + } + + if(use_braces) + append(format("\n%s}", string(brace_indent*2, ' '))); } -void Formatter::visit(ParenthesizedExpression &parexpr) +void Formatter::visit_expression(Expression &expr, const Operator *outer_oper, bool on_rhs) { - append('('); - parexpr.expression->visit(*this); - append(')'); + unsigned outer_precedence = (outer_oper ? outer_oper->precedence : 20); + unsigned inner_precedence = (expr.oper ? expr.oper->precedence : 0); + + bool needs_parentheses = (inner_precedence>=outer_precedence); + + // Omit parentheses if the outer operator encloses this operand. + if(outer_oper && outer_oper->type==Operator::BINARY && outer_oper->token2[0] && on_rhs) + needs_parentheses = false; + + if(expr.oper) + { + /* Omit parentheses if the inner expression's operator sits between the + expression and the outer operator. */ + bool oper_on_left = expr.oper->type==Operator::PREFIX; + bool oper_on_right = expr.oper->type==Operator::POSTFIX || (expr.oper->type==Operator::BINARY && expr.oper->token2[0]); + if(expr.oper && ((oper_on_left && on_rhs) || (oper_on_right && !on_rhs))) + needs_parentheses = false; + + // Omit parentheses if the operator's natural grouping works out. + if(expr.oper==outer_oper) + needs_parentheses = (expr.oper->assoc!=Operator::ASSOCIATIVE && on_rhs!=(expr.oper->assoc==Operator::RIGHT_TO_LEFT)); + } + + if(needs_parentheses) + append('('); + expr.visit(*this); + if(needs_parentheses) + append(')'); +} + +void Formatter::visit(Literal &literal) +{ + append(literal.token); } void Formatter::visit(VariableReference &var) { append(var.name); + r_empty_name = false; } void Formatter::visit(InterfaceBlockReference &iface) { - append(iface.name); + r_empty_name = iface.declaration->instance_name.empty(); + if(!r_empty_name) + append(iface.declaration->instance_name); } void Formatter::visit(MemberAccess &memacc) { - memacc.left->visit(*this); - append(format(".%s", memacc.member)); + visit_expression(*memacc.left, memacc.oper, false); + if(!r_empty_name) + append('.'); + append(memacc.member); + r_empty_name = false; +} + +void Formatter::visit(Swizzle &swizzle) +{ + visit_expression(*swizzle.left, swizzle.oper, false); + append(format(".%s", swizzle.component_group)); } void Formatter::visit(UnaryExpression &unary) { if(unary.oper->type==Operator::PREFIX) append(unary.oper->token); - unary.expression->visit(*this); + visit_expression(*unary.expression, unary.oper, unary.oper->type==Operator::PREFIX); if(unary.oper->type==Operator::POSTFIX) append(unary.oper->token); } void Formatter::visit(BinaryExpression &binary) { - binary.left->visit(*this); + visit_expression(*binary.left, binary.oper, false); append(binary.oper->token); - binary.right->visit(*this); - if(binary.oper->token[0]=='[') - append(']'); + visit_expression(*binary.right, binary.oper, true); + if(binary.oper->token2[0]) + append(binary.oper->token2); } void Formatter::visit(Assignment &assign) { - assign.left->visit(*this); + visit_expression(*assign.left, assign.oper, false); append(format(" %s ", assign.oper->token)); - assign.right->visit(*this); + visit_expression(*assign.right, assign.oper, true); +} + +void Formatter::visit(TernaryExpression &ternary) +{ + visit_expression(*ternary.condition, ternary.oper, false); + append(ternary.oper->token); + visit_expression(*ternary.true_expr, ternary.oper, false); + if(ternary.oper->token2) + append(ternary.oper->token2); + visit_expression(*ternary.false_expr, ternary.oper, true); } void Formatter::visit(FunctionCall &call) { append(format("%s(", call.name)); - for(NodeArray::iterator i=call.arguments.begin(); i!=call.arguments.end(); ++i) + for(auto i=call.arguments.begin(); i!=call.arguments.end(); ++i) { if(i!=call.arguments.begin()) append(", "); @@ -153,32 +223,6 @@ void Formatter::visit(ExpressionStatement &expr) append(';'); } -void Formatter::visit(Block &block) -{ - unsigned brace_indent = indent; - bool use_braces = (block.use_braces || (indent && block.body.size()!=1)); - if(use_braces) - append(format("%s{\n", string(brace_indent*2, ' '))); - - SetForScope set(indent, indent+(indent>0 || use_braces)); - string spaces(indent*2, ' '); - bool first = true; - for(NodeList::iterator i=block.body.begin(); i!=block.body.end(); ++i) - { - if((*i)->source==BUILTIN_SOURCE) - continue; - if(!first) - append('\n'); - first = false; - set_source((*i)->source, (*i)->line); - append(spaces); - (*i)->visit(*this); - } - - if(use_braces) - append(format("\n%s}", string(brace_indent*2, ' '))); -} - void Formatter::visit(Import &import) { append(format("import %s;", import.module)); @@ -192,7 +236,7 @@ void Formatter::visit(Precision &prec) void Formatter::visit(Layout &layout) { append("layout("); - for(vector::const_iterator i=layout.qualifiers.begin(); i!=layout.qualifiers.end(); ++i) + for(auto i=layout.qualifiers.begin(); i!=layout.qualifiers.end(); ++i) { if(i!=layout.qualifiers.begin()) append(", "); @@ -229,10 +273,10 @@ void Formatter::visit(VariableDeclaration &var) append(format("%s ", var.interpolation)); if(!var.sampling.empty()) append(format("%s ", var.sampling)); - if(!var.interface.empty() && var.interface!=block_interface) + if(!var.interface.empty()) { string interface = var.interface; - if(mode==Compiler::PROGRAM && stage && stage->required_features.glsl_versionrequired_features.glsl_version && stage->required_features.glsl_versiontype==Stage::VERTEX && var.interface=="in") interface = "attribute"; @@ -243,7 +287,10 @@ void Formatter::visit(VariableDeclaration &var) } if(!var.precision.empty()) append(format("%s ", var.precision)); - append(format("%s %s", var.type, var.name)); + string type_name = var.type_declaration->name; + if(var.array) + type_name = type_name.substr(0, type_name.find('[')); + append(format("%s %s", type_name, var.name)); if(var.array) { append('['); @@ -262,9 +309,14 @@ void Formatter::visit(VariableDeclaration &var) void Formatter::visit(InterfaceBlock &iface) { - SetForScope set(block_interface, iface.interface); - append(format("%s %s\n", iface.interface, iface.name)); - iface.members.visit(*this); + if(iface.layout) + { + iface.layout->visit(*this); + append(' '); + } + append(format("%s %s\n", iface.interface, iface.block_name)); + if(iface.struct_declaration) + iface.struct_declaration->members.visit(*this); if(!iface.instance_name.empty()) { append(' '); @@ -277,8 +329,8 @@ void Formatter::visit(InterfaceBlock &iface) void Formatter::visit(FunctionDeclaration &func) { - append(format("%s %s(", func.return_type, func.name)); - for(NodeArray::iterator i=func.parameters.begin(); i!=func.parameters.end(); ++i) + append(format("%s %s(", func.return_type_declaration->name, func.name)); + for(auto i=func.parameters.begin(); i!=func.parameters.end(); ++i) { if(i!=func.parameters.begin()) append(", ");