X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fglsl%2Fspirv.cpp;h=20345e20ae0760de48e4bbea923e89fea7d9356b;hb=3fe1aab63922eec99d8bf6fd4fd60bec10df173c;hp=16168a8cb8725671197bf39567d276992e6c5695;hpb=6f06479b765946bdd3174b2c05e7a1dda24c31c2;p=libs%2Fgl.git diff --git a/source/glsl/spirv.cpp b/source/glsl/spirv.cpp index 16168a8c..20345e20 100644 --- a/source/glsl/spirv.cpp +++ b/source/glsl/spirv.cpp @@ -518,8 +518,15 @@ void SpirVGenerator::visit(VariableReference &var) r_constant_result = false; if(composite_access) { - r_composite_base = var.declaration; r_expression_result_id = 0; + if(!assignment_source_id) + { + auto i = variable_load_ids.find(var.declaration); + if(i!=variable_load_ids.end()) + r_expression_result_id = i->second; + } + if(!r_expression_result_id) + r_composite_base = var.declaration; } else if(assignment_source_id) { @@ -683,6 +690,9 @@ void SpirVGenerator::visit(Swizzle &swizzle) void SpirVGenerator::visit(UnaryExpression &unary) { + if(composite_access) + return visit_isolated(unary); + unary.expression->visit(*this); char oper = unary.oper->token[0]; @@ -767,6 +777,8 @@ void SpirVGenerator::visit(BinaryExpression &binary) visit_isolated(*binary.right); return visit_composite(*binary.left, 0x400000|r_expression_result_id, *binary.type); } + else if(composite_access) + return visit_isolated(binary); if(assignment_source_id) throw internal_error("invalid binary expression in assignment target"); @@ -991,6 +1003,8 @@ void SpirVGenerator::visit(Assignment &assign) void SpirVGenerator::visit(TernaryExpression &ternary) { + if(composite_access) + return visit_isolated(ternary); if(constant_expression) { ternary.condition->visit(*this); @@ -1021,11 +1035,13 @@ void SpirVGenerator::visit(TernaryExpression &ternary) writer.write_op_label(true_label_id); ternary.true_expr->visit(*this); Id true_result_id = r_expression_result_id; + true_label_id = writer.get_current_block(); writer.write_op(content.function_body, OP_BRANCH, merge_block_id); writer.write_op_label(false_label_id); ternary.false_expr->visit(*this); Id false_result_id = r_expression_result_id; + false_label_id = writer.get_current_block(); writer.write_op_label(merge_block_id); r_expression_result_id = begin_expression(OP_PHI, get_id(*ternary.type), 4); @@ -1646,6 +1662,11 @@ void SpirVGenerator::visit(VariableDeclaration &var) writer.write_op_decorate(var_id, DECO_BINDING, q.value); } } + if(!var.name.compare(0, 3, "gl_")) + { + BuiltinSemantic semantic = get_builtin_semantic(var.name); + writer.write_op_decorate(var_id, DECO_BUILTIN, semantic); + } if(init_id && current_function) { @@ -1659,7 +1680,16 @@ void SpirVGenerator::visit(VariableDeclaration &var) void SpirVGenerator::visit(InterfaceBlock &iface) { - StorageClass storage = get_interface_storage(iface.interface, true); + const vector *layout_ql = (iface.layout ? &iface.layout->qualifiers : 0); + + bool push_const = false; + if(layout_ql) + { + auto i = find_member(*layout_ql, string("push_constant"), &Layout::Qualifier::name); + push_const = (i!=layout_ql->end()); + } + + StorageClass storage = (push_const ? STORAGE_PUSH_CONSTANT : get_interface_storage(iface.interface, true)); Id type_id; if(iface.array) type_id = get_array_type_id(*iface.struct_declaration, 0); @@ -1685,11 +1715,15 @@ void SpirVGenerator::visit(InterfaceBlock &iface) writer.write_op(content.globals, OP_VARIABLE, ptr_type_id, block_id, storage); - if(iface.layout) + if(layout_ql) { - auto i = find_member(iface.layout->qualifiers, string("binding"), &Layout::Qualifier::name); - if(i!=iface.layout->qualifiers.end()) - writer.write_op_decorate(block_id, DECO_BINDING, i->value); + for(const Layout::Qualifier &q: *layout_ql) + { + if(q.name=="set") + writer.write_op_decorate(block_id, DECO_DESCRIPTOR_SET, q.value); + else if(q.name=="binding") + writer.write_op_decorate(block_id, DECO_BINDING, q.value); + } } } @@ -1803,11 +1837,12 @@ void SpirVGenerator::visit(FunctionDeclaration &func) variable_load_ids[func.parameters[i].get()] = param_id; } + reachable = true; writer.begin_function_body(next_id++); SetForScope set_func(current_function, &func); func.body.visit(*this); - if(writer.has_current_block()) + if(writer.get_current_block()) { if(!reachable) writer.write_op(content.function_body, OP_UNREACHABLE); @@ -1834,9 +1869,11 @@ void SpirVGenerator::visit(Conditional &cond) writer.write_op(content.function_body, OP_SELECTION_MERGE, merge_block_id, 0); // Selection control (none) writer.write_op(content.function_body, OP_BRANCH_CONDITIONAL, r_expression_result_id, true_label_id, false_label_id); + std::map saved_load_ids = variable_load_ids; + writer.write_op_label(true_label_id); cond.body.visit(*this); - if(writer.has_current_block()) + if(writer.get_current_block()) writer.write_op(content.function_body, OP_BRANCH, merge_block_id); bool reachable_if_true = reachable; @@ -1844,6 +1881,7 @@ void SpirVGenerator::visit(Conditional &cond) reachable = true; if(!cond.else_body.body.empty()) { + swap(saved_load_ids, variable_load_ids); writer.write_op_label(false_label_id); cond.else_body.visit(*this); reachable |= reachable_if_true; @@ -1858,8 +1896,9 @@ void SpirVGenerator::visit(Iteration &iter) if(iter.init_statement) iter.init_statement->visit(*this); - for(VariableDeclaration *v: AssignmentCollector().apply(iter)) - variable_load_ids.erase(v); + for(Node *n: AssignmentCollector().apply(iter)) + if(VariableDeclaration *var = dynamic_cast(n)) + variable_load_ids.erase(var); Id header_id = next_id++; Id continue_id = next_id++;