X-Git-Url: http://git.tdb.fi/?p=libs%2Fgl.git;a=blobdiff_plain;f=source%2Fglsl%2Fspirv.cpp;h=40e731fe63fa9fcfb384dd61baf8429e34be3382;hp=186521c5efe109b1bfcb1f6d331cfb666f2617fa;hb=76cc18518fc8b0b4fa11fda153e7d9b3899ed112;hpb=ece3438c6a1630ada39cc01ae3d54b27aacdd663 diff --git a/source/glsl/spirv.cpp b/source/glsl/spirv.cpp index 186521c5..40e731fe 100644 --- a/source/glsl/spirv.cpp +++ b/source/glsl/spirv.cpp @@ -1,3 +1,4 @@ +#include #include #include #include "reflect.h" @@ -108,6 +109,8 @@ const SpirVGenerator::BuiltinFunctionInfo SpirVGenerator::builtin_functions[] = { "findMSB", "i", "GLSL.std.450", GLSL450_FIND_S_MSB, { 1 }, 0, 0 }, { "findMSB", "u", "GLSL.std.450", GLSL450_FIND_U_MSB, { 1 }, 0, 0 }, { "textureSize", "", "", 0, { }, CAP_IMAGE_QUERY, &SpirVGenerator::visit_builtin_texture_query }, + { "textureQueryLod", "", "", 0, { }, CAP_IMAGE_QUERY, &SpirVGenerator::visit_builtin_texture_query }, + { "textureQueryLevels", "", "", 0, { }, CAP_IMAGE_QUERY, &SpirVGenerator::visit_builtin_texture_query }, { "texture", "", "", 0, { }, 0, &SpirVGenerator::visit_builtin_texture }, { "textureLod", "", "", 0, { }, 0, &SpirVGenerator::visit_builtin_texture }, { "texelFetch", "", "", 0, { }, 0, &SpirVGenerator::visit_builtin_texel_fetch }, @@ -129,31 +132,18 @@ const SpirVGenerator::BuiltinFunctionInfo SpirVGenerator::builtin_functions[] = }; SpirVGenerator::SpirVGenerator(): - stage(0), - current_function(0), - writer(content), - next_id(1), - r_expression_result_id(0), - constant_expression(false), - spec_constant(false), - reachable(false), - composite_access(false), - r_composite_base_id(0), - r_composite_base(0), - assignment_source_id(0), - loop_merge_block_id(0), - loop_continue_target_id(0) + writer(content) { } void SpirVGenerator::apply(Module &module) { use_capability(CAP_SHADER); - for(list::iterator i=module.stages.begin(); i!=module.stages.end(); ++i) + for(Stage &s: module.stages) { - stage = &*i; + stage = &s; interface_layouts.clear(); - i->content.visit(*this); + s.content.visit(*this); } writer.finalize(SPIRV_GENERATOR_MSP, next_id); @@ -237,7 +227,7 @@ SpirVGenerator::Id SpirVGenerator::get_id(Node &node) const SpirVGenerator::Id SpirVGenerator::allocate_id(Node &node, Id type_id) { - map::iterator i = declared_ids.find(&node); + auto i = declared_ids.find(&node); if(i!=declared_ids.end()) { if(i->second.type_id) @@ -253,7 +243,7 @@ SpirVGenerator::Id SpirVGenerator::allocate_id(Node &node, Id type_id) SpirVGenerator::Id SpirVGenerator::allocate_forward_id(Node &node) { - map::iterator i = declared_ids.find(&node); + auto i = declared_ids.find(&node); if(i!=declared_ids.end()) return i->second.id; @@ -343,7 +333,7 @@ SpirVGenerator::Id SpirVGenerator::get_standard_type_id(BasicTypeDeclaration::Ki bool SpirVGenerator::is_scalar_type(Id type_id, BasicTypeDeclaration::Kind kind) const { - map::const_iterator i = standard_type_ids.find(TypeKey(kind, true)); + auto i = standard_type_ids.find(TypeKey(kind, true)); return (i!=standard_type_ids.end() && i->second==type_id); } @@ -411,7 +401,7 @@ SpirVGenerator::Id SpirVGenerator::get_load_id(VariableDeclaration &var) void SpirVGenerator::prune_loads(Id min_id) { - for(map::iterator i=variable_load_ids.begin(); i!=variable_load_ids.end(); ) + for(auto i=variable_load_ids.begin(); i!=variable_load_ids.end(); ) { if(i->second>=min_id) variable_load_ids.erase(i++); @@ -497,8 +487,8 @@ SpirVGenerator::Id SpirVGenerator::write_construct(Id type_id, const Id *elem_id void SpirVGenerator::visit(Block &block) { - for(NodeList::iterator i=block.body.begin(); i!=block.body.end(); ++i) - (*i)->visit(*this); + for(const RefPtr &s: block.body) + s->visit(*this); } void SpirVGenerator::visit(Literal &literal) @@ -528,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) { @@ -562,13 +559,13 @@ void SpirVGenerator::generate_composite_access(TypeDeclaration &result_type) throw internal_error("composite access through pointer in constant context"); Id int32_type_id = get_standard_type_id(BasicTypeDeclaration::INT, 1); - for(vector::iterator i=r_composite_chain.begin(); i!=r_composite_chain.end(); ++i) - *i = (*i<0x400000 ? get_constant_id(int32_type_id, static_cast(*i)) : *i&0x3FFFFF); + for(unsigned &i: r_composite_chain) + i = (i<0x400000 ? get_constant_id(int32_type_id, static_cast(i)) : i&0x3FFFFF); /* Find the storage class of the base and obtain appropriate pointer type for the result. */ const Declaration &base_decl = get_item(declared_ids, r_composite_base); - map::const_iterator i = pointer_type_ids.begin(); + auto i = pointer_type_ids.begin(); for(; (i!=pointer_type_ids.end() && i->second!=base_decl.type_id); ++i) ; if(i==pointer_type_ids.end()) throw internal_error("could not find storage class"); @@ -580,18 +577,18 @@ void SpirVGenerator::generate_composite_access(TypeDeclaration &result_type) throw internal_error("assignment to temporary composite"); else { - for(vector::iterator i=r_composite_chain.begin(); i!=r_composite_chain.end(); ++i) - for(map::iterator j=constant_ids.begin(); (*i>=0x400000 && j!=constant_ids.end()); ++j) - if(j->second==(*i&0x3FFFFF)) - *i = j->first.int_value; + for(unsigned &i: r_composite_chain) + for(auto j=constant_ids.begin(); (i>=0x400000 && j!=constant_ids.end()); ++j) + if(j->second==(i&0x3FFFFF)) + i = j->first.int_value; opcode = OP_COMPOSITE_EXTRACT; } Id access_id = begin_expression(opcode, access_type_id, 1+r_composite_chain.size()); writer.write(r_composite_base_id); - for(vector::const_iterator i=r_composite_chain.begin(); i!=r_composite_chain.end(); ++i) - writer.write(*i); + for(unsigned i: r_composite_chain) + writer.write(i); end_expression(opcode); r_constant_result = false; @@ -693,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]; @@ -777,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"); @@ -1001,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); @@ -1031,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); @@ -1060,9 +1066,9 @@ void SpirVGenerator::visit(FunctionCall &call) vector argument_ids; argument_ids.reserve(call.arguments.size()); bool all_args_const = true; - for(NodeArray::const_iterator i=call.arguments.begin(); i!=call.arguments.end(); ++i) + for(const RefPtr &a: call.arguments) { - (*i)->visit(*this); + a->visit(*this); argument_ids.push_back(r_expression_result_id); all_args_const &= r_constant_result; } @@ -1078,8 +1084,8 @@ void SpirVGenerator::visit(FunctionCall &call) else if(call.declaration->source==BUILTIN_SOURCE) { string arg_types; - for(NodeArray::const_iterator i=call.arguments.begin(); i!=call.arguments.end(); ++i) - if(BasicTypeDeclaration *basic_arg = dynamic_cast((*i)->type)) + for(const RefPtr &a: call.arguments) + if(BasicTypeDeclaration *basic_arg = dynamic_cast(a->type)) { BasicTypeDeclaration &elem_arg = *get_element_type(*basic_arg); switch(elem_arg.kind) @@ -1135,14 +1141,14 @@ void SpirVGenerator::visit(FunctionCall &call) { r_expression_result_id = begin_expression(OP_FUNCTION_CALL, result_type_id, 1+call.arguments.size()); writer.write(get_id(*call.declaration->definition)); - for(vector::const_iterator i=argument_ids.begin(); i!=argument_ids.end(); ++i) - writer.write(*i); + for(Id i: argument_ids) + writer.write(i); end_expression(OP_FUNCTION_CALL); // Any global variables the called function uses might have changed value set dependencies = DependencyCollector().apply(*call.declaration->definition); - for(set::const_iterator i=dependencies.begin(); i!=dependencies.end(); ++i) - if(const VariableDeclaration *var = dynamic_cast(*i)) + for(Node *n: dependencies) + if(const VariableDeclaration *var = dynamic_cast(n)) variable_load_ids.erase(var); } } @@ -1292,6 +1298,10 @@ void SpirVGenerator::visit_builtin_texture_query(FunctionCall &call, const vecto Opcode opcode; if(call.name=="textureSize") opcode = OP_IMAGE_QUERY_SIZE_LOD; + else if(call.name=="textureQueryLod") + opcode = OP_IMAGE_QUERY_LOD; + else if(call.name=="textureQueryLevels") + opcode = OP_IMAGE_QUERY_LEVELS; else throw internal_error("invalid texture query call"); @@ -1399,7 +1409,7 @@ void SpirVGenerator::visit_builtin_interpolate(FunctionCall &call, const vector< writer.write(ext_id); writer.write(opcode); writer.write(get_id(*var->declaration)); - for(vector::const_iterator i=argument_ids.begin(); ++i!=argument_ids.end(); ) + for(auto i=argument_ids.begin(); ++i!=argument_ids.end(); ) writer.write(*i); end_expression(OP_EXT_INST); } @@ -1416,11 +1426,11 @@ void SpirVGenerator::visit(InterfaceLayout &layout) bool SpirVGenerator::check_duplicate_type(TypeDeclaration &type) { - for(map::const_iterator i=declared_ids.begin(); i!=declared_ids.end(); ++i) - if(TypeDeclaration *type2 = dynamic_cast(i->first)) + for(const auto &kvp: declared_ids) + if(TypeDeclaration *type2 = dynamic_cast(kvp.first)) if(TypeComparer().apply(type, *type2)) { - insert_unique(declared_ids, &type, i->second); + insert_unique(declared_ids, &type, kvp.second); return true; } @@ -1521,9 +1531,9 @@ void SpirVGenerator::visit(StructDeclaration &strct) bool builtin = (strct.interface_block && !strct.interface_block->block_name.compare(0, 3, "gl_")); vector member_type_ids; member_type_ids.reserve(strct.members.body.size()); - for(NodeList::const_iterator i=strct.members.body.begin(); i!=strct.members.body.end(); ++i) + for(const RefPtr &s: strct.members.body) { - const VariableDeclaration *var = dynamic_cast(i->get()); + const VariableDeclaration *var = dynamic_cast(s.get()); if(!var) continue; @@ -1541,14 +1551,13 @@ void SpirVGenerator::visit(StructDeclaration &strct) { if(var->layout) { - const vector &qualifiers = var->layout->qualifiers; - for(vector::const_iterator j=qualifiers.begin(); j!=qualifiers.end(); ++j) + for(const Layout::Qualifier &q: var->layout->qualifiers) { - if(j->name=="offset") - writer.write_op_member_decorate(type_id, index, DECO_OFFSET, j->value); - else if(j->name=="column_major") + if(q.name=="offset") + writer.write_op_member_decorate(type_id, index, DECO_OFFSET, q.value); + else if(q.name=="column_major") writer.write_op_member_decorate(type_id, index, DECO_COL_MAJOR); - else if(j->name=="row_major") + else if(q.name=="row_major") writer.write_op_member_decorate(type_id, index, DECO_ROW_MAJOR); } } @@ -1566,23 +1575,13 @@ void SpirVGenerator::visit(StructDeclaration &strct) writer.begin_op(content.globals, OP_TYPE_STRUCT); writer.write(type_id); - for(vector::const_iterator i=member_type_ids.begin(); i!=member_type_ids.end(); ++i) - writer.write(*i); + for(Id i: member_type_ids) + writer.write(i); writer.end_op(OP_TYPE_STRUCT); } void SpirVGenerator::visit(VariableDeclaration &var) { - const vector *layout_ql = (var.layout ? &var.layout->qualifiers : 0); - - int spec_id = -1; - if(layout_ql) - { - for(vector::const_iterator i=layout_ql->begin(); (spec_id<0 && i!=layout_ql->end()); ++i) - if(i->name=="constant_id") - spec_id = i->value; - } - Id type_id = get_variable_type_id(var); Id var_id; @@ -1591,6 +1590,8 @@ void SpirVGenerator::visit(VariableDeclaration &var) if(!var.init_expression) throw internal_error("const variable without initializer"); + int spec_id = get_layout_value(var.layout.get(), "constant_id"); + SetFlag set_const(constant_expression); SetFlag set_spec(spec_constant, spec_id>=0); r_expression_result_id = 0; @@ -1641,18 +1642,23 @@ void SpirVGenerator::visit(VariableDeclaration &var) writer.write(init_id); writer.end_op(OP_VARIABLE); - if(layout_ql) + if(var.layout) { - for(vector::const_iterator i=layout_ql->begin(); i!=layout_ql->end(); ++i) + for(const Layout::Qualifier &q: var.layout->qualifiers) { - if(i->name=="location") - writer.write_op_decorate(var_id, DECO_LOCATION, i->value); - else if(i->name=="set") - writer.write_op_decorate(var_id, DECO_DESCRIPTOR_SET, i->value); - else if(i->name=="binding") - writer.write_op_decorate(var_id, DECO_BINDING, i->value); + if(q.name=="location") + writer.write_op_decorate(var_id, DECO_LOCATION, q.value); + else if(q.name=="set") + writer.write_op_decorate(var_id, DECO_DESCRIPTOR_SET, q.value); + else if(q.name=="binding") + 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) { @@ -1666,7 +1672,9 @@ void SpirVGenerator::visit(VariableDeclaration &var) void SpirVGenerator::visit(InterfaceBlock &iface) { - StorageClass storage = get_interface_storage(iface.interface, true); + bool push_const = has_layout_qualifier(iface.layout.get(), "push_constant"); + + 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); @@ -1694,10 +1702,13 @@ void SpirVGenerator::visit(InterfaceBlock &iface) if(iface.layout) { - const vector &qualifiers = iface.layout->qualifiers; - for(vector::const_iterator i=qualifiers.begin(); i!=qualifiers.end(); ++i) - if(i->name=="binding") - writer.write_op_decorate(block_id, DECO_BINDING, i->value); + for(const Layout::Qualifier &q: iface.layout->qualifiers) + { + 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); + } } } @@ -1715,15 +1726,15 @@ void SpirVGenerator::visit_entry_point(FunctionDeclaration &func, Id func_id) writer.write_string(func.name); set dependencies = DependencyCollector().apply(func); - for(set::const_iterator i=dependencies.begin(); i!=dependencies.end(); ++i) + for(Node *n: dependencies) { - if(const VariableDeclaration *var = dynamic_cast(*i)) + if(const VariableDeclaration *var = dynamic_cast(n)) { if(!var->interface.empty()) - writer.write(get_id(**i)); + writer.write(get_id(*n)); } - else if(dynamic_cast(*i)) - writer.write(get_id(**i)); + else if(dynamic_cast(n)) + writer.write(get_id(*n)); } writer.end_op(OP_ENTRY_POINT); @@ -1733,28 +1744,27 @@ void SpirVGenerator::visit_entry_point(FunctionDeclaration &func, Id func_id) else if(stage->type==Stage::GEOMETRY) use_capability(CAP_GEOMETRY); - for(vector::const_iterator i=interface_layouts.begin(); i!=interface_layouts.end(); ++i) + for(const InterfaceLayout *i: interface_layouts) { - const vector &qualifiers = (*i)->layout.qualifiers; - for(vector::const_iterator j=qualifiers.begin(); j!=qualifiers.end(); ++j) + for(const Layout::Qualifier &q: i->layout.qualifiers) { - if(j->name=="point") + if(q.name=="point") writer.write_op(content.exec_modes, OP_EXECUTION_MODE, func_id, - ((*i)->interface=="in" ? EXEC_INPUT_POINTS : EXEC_OUTPUT_POINTS)); - else if(j->name=="lines") + (i->interface=="in" ? EXEC_INPUT_POINTS : EXEC_OUTPUT_POINTS)); + else if(q.name=="lines") writer.write_op(content.exec_modes, OP_EXECUTION_MODE, func_id, EXEC_INPUT_LINES); - else if(j->name=="lines_adjacency") + else if(q.name=="lines_adjacency") writer.write_op(content.exec_modes, OP_EXECUTION_MODE, func_id, EXEC_INPUT_LINES_ADJACENCY); - else if(j->name=="triangles") + else if(q.name=="triangles") writer.write_op(content.exec_modes, OP_EXECUTION_MODE, func_id, EXEC_TRIANGLES); - else if(j->name=="triangles_adjacency") + else if(q.name=="triangles_adjacency") writer.write_op(content.exec_modes, OP_EXECUTION_MODE, func_id, EXEC_INPUT_TRIANGLES_ADJACENCY); - else if(j->name=="line_strip") + else if(q.name=="line_strip") writer.write_op(content.exec_modes, OP_EXECUTION_MODE, func_id, EXEC_OUTPUT_LINE_STRIP); - else if(j->name=="triangle_strip") + else if(q.name=="triangle_strip") writer.write_op(content.exec_modes, OP_EXECUTION_MODE, func_id, EXEC_OUTPUT_TRIANGLE_STRIP); - else if(j->name=="max_vertices") - writer.write_op(content.exec_modes, OP_EXECUTION_MODE, func_id, EXEC_OUTPUT_VERTICES, j->value); + else if(q.name=="max_vertices") + writer.write_op(content.exec_modes, OP_EXECUTION_MODE, func_id, EXEC_OUTPUT_VERTICES, q.value); } } } @@ -1773,8 +1783,8 @@ void SpirVGenerator::visit(FunctionDeclaration &func) Id return_type_id = get_id(*func.return_type_declaration); vector param_type_ids; param_type_ids.reserve(func.parameters.size()); - for(NodeArray::const_iterator i=func.parameters.begin(); i!=func.parameters.end(); ++i) - param_type_ids.push_back(get_variable_type_id(**i)); + for(const RefPtr &p: func.parameters) + param_type_ids.push_back(get_variable_type_id(*p)); string sig_with_return = func.return_type+func.signature; Id &type_id = function_type_ids[sig_with_return]; @@ -1784,8 +1794,8 @@ void SpirVGenerator::visit(FunctionDeclaration &func) writer.begin_op(content.globals, OP_TYPE_FUNCTION); writer.write(type_id); writer.write(return_type_id); - for(vector::const_iterator i=param_type_ids.begin(); i!=param_type_ids.end(); ++i) - writer.write(*i); + for(unsigned i: param_type_ids) + writer.write(i); writer.end_op(OP_TYPE_FUNCTION); writer.write_op_name(type_id, sig_with_return); @@ -1812,11 +1822,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); @@ -1843,9 +1854,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; @@ -1853,6 +1866,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; @@ -1867,7 +1881,9 @@ void SpirVGenerator::visit(Iteration &iter) if(iter.init_statement) iter.init_statement->visit(*this); - variable_load_ids.clear(); + 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++; @@ -1896,6 +1912,7 @@ void SpirVGenerator::visit(Iteration &iter) writer.write_op(content.function_body, OP_BRANCH, header_id); writer.write_op_label(merge_block_id); + prune_loads(header_id); reachable = true; }