X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fglsl%2Fgenerate.cpp;h=ce1283721d6f7b0796e40808b3425acd49d49b64;hb=d684e9f3007a0113c65c016ceb694eeac56a128c;hp=09a776afb7f60bb61d2bdc47d0a8f3fb9e470b3e;hpb=30f676460bb6e87fd7ca2532e507b97965c4a407;p=libs%2Fgl.git diff --git a/source/glsl/generate.cpp b/source/glsl/generate.cpp index 09a776af..ce128372 100644 --- a/source/glsl/generate.cpp +++ b/source/glsl/generate.cpp @@ -12,57 +12,6 @@ namespace Msp { namespace GL { namespace SL { -void DeclarationCombiner::apply(Stage &stage) -{ - stage.content.visit(*this); - NodeRemover().apply(stage, nodes_to_remove); -} - -void DeclarationCombiner::visit(Block &block) -{ - if(current_block) - return; - - TraversingVisitor::visit(block); -} - -void DeclarationCombiner::visit(VariableDeclaration &var) -{ - VariableDeclaration *&ptr = variables[var.name]; - if(ptr) - { - ptr->type = var.type; - if(var.init_expression) - ptr->init_expression = var.init_expression; - if(var.layout) - { - if(ptr->layout) - { - for(vector::iterator i=var.layout->qualifiers.begin(); i!=var.layout->qualifiers.end(); ++i) - { - bool found = false; - for(vector::iterator j=ptr->layout->qualifiers.begin(); (!found && j!=ptr->layout->qualifiers.end()); ++j) - if(j->name==i->name) - { - j->has_value = i->value; - j->value = i->value; - found = true; - } - - if(!found) - ptr->layout->qualifiers.push_back(*i); - } - } - else - ptr->layout = var.layout; - } - nodes_to_remove.insert(&var); - } - else - ptr = &var; -} - - ConstantSpecializer::ConstantSpecializer(): values(0) { } @@ -191,6 +140,9 @@ void TypeResolver::visit(BasicTypeDeclaration &type) if(basic_base->kind==BasicTypeDeclaration::VECTOR) { type.kind = BasicTypeDeclaration::MATRIX; + /* A matrix's base type is its column vector type. This will put + the column vector's size, i.e. the matrix's row count, in the high + half of the size. */ type.size |= basic_base->size<<16; } @@ -267,6 +219,9 @@ bool VariableResolver::apply(Stage &s) s.interface_blocks.clear(); r_any_resolved = false; s.content.visit(*this); + for(vector::const_iterator i=redeclared_builtins.begin(); i!=redeclared_builtins.end(); ++i) + (*i)->source = GENERATED_SOURCE; + NodeRemover().apply(s, nodes_to_remove); return r_any_resolved; } @@ -482,10 +437,51 @@ void VariableResolver::visit(Assignment &assign) assign.self_referencing = (r_self_referencing || assign.oper->token[0]!='='); } +void VariableResolver::merge_layouts(Layout &to_layout, const Layout &from_layout) +{ + for(vector::const_iterator i=from_layout.qualifiers.begin(); i!=from_layout.qualifiers.end(); ++i) + { + bool found = false; + for(vector::iterator j=to_layout.qualifiers.begin(); (!found && j!=to_layout.qualifiers.end()); ++j) + if(j->name==i->name) + { + j->has_value = i->value; + j->value = i->value; + found = true; + } + + if(!found) + to_layout.qualifiers.push_back(*i); + } +} + void VariableResolver::visit(VariableDeclaration &var) { TraversingVisitor::visit(var); - current_block->variables.insert(make_pair(var.name, &var)); + VariableDeclaration *&ptr = current_block->variables[var.name]; + if(!ptr) + ptr = &var; + else if(!current_block->parent && ptr->interface==var.interface && ptr->type==var.type) + { + if(ptr->source==BUILTIN_SOURCE) + redeclared_builtins.push_back(&var); + else + stage->diagnostics.push_back(Diagnostic(Diagnostic::WARN, var.source, var.line, + format("Redeclaring non-builtin variable '%s' is deprecated", var.name))); + + if(var.init_expression) + ptr->init_expression = var.init_expression; + if(var.layout) + { + if(ptr->layout) + merge_layouts(*ptr->layout, *var.layout); + else + ptr->layout = var.layout; + } + nodes_to_remove.insert(&var); + + r_any_resolved = true; + } } void VariableResolver::visit(InterfaceBlock &iface) @@ -869,6 +865,36 @@ void ExpressionResolver::visit(Assignment &assign) resolve(assign, assign.left->type, true); } +void ExpressionResolver::visit(TernaryExpression &ternary) +{ + TraversingVisitor::visit(ternary); + + BasicTypeDeclaration *basic_cond = dynamic_cast(ternary.condition->type); + if(!basic_cond || basic_cond->kind!=BasicTypeDeclaration::BOOL) + return; + + TypeDeclaration *type = 0; + if(ternary.true_expr->type==ternary.false_expr->type) + type = ternary.true_expr->type; + else + { + BasicTypeDeclaration *basic_true = dynamic_cast(ternary.true_expr->type); + BasicTypeDeclaration *basic_false = dynamic_cast(ternary.false_expr->type); + Compatibility compat = get_compatibility(*basic_true, *basic_false); + if(compat==NOT_COMPATIBLE) + return; + + type = (compat==LEFT_CONVERTIBLE ? basic_true : basic_false); + + if(compat==LEFT_CONVERTIBLE) + convert_to(ternary.true_expr, *basic_false); + else if(compat==RIGHT_CONVERTIBLE) + convert_to(ternary.false_expr, *basic_true); + } + + resolve(ternary, type, false); +} + void ExpressionResolver::visit(FunctionCall &call) { TraversingVisitor::visit(call); @@ -1037,6 +1063,9 @@ VariableDeclaration *InterfaceGenerator::generate_interface(VariableDeclaration if(stage->content.variables.count(name)) return 0; + if(stage->type==Stage::GEOMETRY && !copy_block && var.interface=="out" && var.array) + return 0; + VariableDeclaration* iface_var = new VariableDeclaration; iface_var->sampling = var.sampling; iface_var->interface = iface; @@ -1059,6 +1088,8 @@ VariableDeclaration *InterfaceGenerator::generate_interface(VariableDeclaration iface_target_block->body.insert(iface_insert_point, iface_var); iface_target_block->variables.insert(make_pair(name, iface_var)); + if(iface_target_block==&stage->content && iface=="in") + declared_inputs.push_back(iface_var); return iface_var; } @@ -1134,8 +1165,14 @@ void InterfaceGenerator::visit(VariableReference &var) i = prev_vars.find(in_prefix+var.name); if(i!=prev_vars.end() && i->second->interface=="out") { - generate_interface(*i->second, "in", i->second->name); - var.name = i->second->name; + if(stage->type==Stage::GEOMETRY && i->second->array) + stage->diagnostics.push_back(Diagnostic(Diagnostic::WARN, var.source, var.line, + format("Can't access '%s' through automatic interface because it's an array", var.name))); + else + { + generate_interface(*i->second, "in", i->second->name); + var.name = i->second->name; + } return; } @@ -1185,11 +1222,13 @@ void InterfaceGenerator::visit(VariableDeclaration &var) } } } - else if(var.interface=="in") + else if(var.interface=="in" && current_block==&stage->content) { + declared_inputs.push_back(&var); + /* Try to link input variables in global scope with output variables from previous stage. */ - if(current_block==&stage->content && !var.linked_declaration && stage->previous) + if(!var.linked_declaration && stage->previous) { const map &prev_vars = stage->previous->content.variables; map::const_iterator i = prev_vars.find(var.name); @@ -1234,12 +1273,8 @@ void InterfaceGenerator::visit(FunctionDeclaration &func) void InterfaceGenerator::visit(Passthrough &pass) { - vector pass_vars; - - // Pass through all input variables of this stage. - for(map::const_iterator i=stage->content.variables.begin(); i!=stage->content.variables.end(); ++i) - if(i->second->interface=="in") - pass_vars.push_back(i->second); + // Pass through all input variables declared so far. + vector pass_vars = declared_inputs; if(stage->previous) {