+#include <msp/core/algorithm.h>
#include <msp/core/maputils.h>
#include <msp/core/raii.h>
#include "reflect.h"
{ "findLSB", "u", "GLSL.std.450", GLSL450_FIND_I_LSB, { 1 }, 0, 0 },
{ "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", "", "", OP_IMAGE_QUERY_SIZE_LOD, { 1, 2 }, CAP_IMAGE_QUERY, 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 },
};
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<Stage>::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);
SpirVGenerator::Id SpirVGenerator::allocate_id(Node &node, Id type_id)
{
- map<Node *, Declaration>::iterator i = declared_ids.find(&node);
+ auto i = declared_ids.find(&node);
if(i!=declared_ids.end())
{
if(i->second.type_id)
SpirVGenerator::Id SpirVGenerator::allocate_forward_id(Node &node)
{
- map<Node *, Declaration>::iterator i = declared_ids.find(&node);
+ auto i = declared_ids.find(&node);
if(i!=declared_ids.end())
return i->second.id;
bool SpirVGenerator::is_scalar_type(Id type_id, BasicTypeDeclaration::Kind kind) const
{
- map<TypeKey, Id>::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);
}
void SpirVGenerator::prune_loads(Id min_id)
{
- for(map<const VariableDeclaration *, Id>::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++);
void SpirVGenerator::visit(Block &block)
{
- for(NodeList<Statement>::iterator i=block.body.begin(); i!=block.body.end(); ++i)
- (*i)->visit(*this);
+ for(const RefPtr<Statement> &s: block.body)
+ s->visit(*this);
}
void SpirVGenerator::visit(Literal &literal)
throw internal_error("composite access through pointer in constant context");
Id int32_type_id = get_standard_type_id(BasicTypeDeclaration::INT, 1);
- for(vector<unsigned>::iterator i=r_composite_chain.begin(); i!=r_composite_chain.end(); ++i)
- *i = (*i<0x400000 ? get_constant_id(int32_type_id, static_cast<int>(*i)) : *i&0x3FFFFF);
+ for(unsigned &i: r_composite_chain)
+ i = (i<0x400000 ? get_constant_id(int32_type_id, static_cast<int>(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<TypeKey, Id>::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");
throw internal_error("assignment to temporary composite");
else
{
- for(vector<unsigned>::iterator i=r_composite_chain.begin(); i!=r_composite_chain.end(); ++i)
- for(map<ConstantKey, Id>::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<unsigned>::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;
vector<Id> argument_ids;
argument_ids.reserve(call.arguments.size());
bool all_args_const = true;
- for(NodeArray<Expression>::const_iterator i=call.arguments.begin(); i!=call.arguments.end(); ++i)
+ for(const RefPtr<Expression> &a: call.arguments)
{
- (*i)->visit(*this);
+ a->visit(*this);
argument_ids.push_back(r_expression_result_id);
all_args_const &= r_constant_result;
}
else if(call.declaration->source==BUILTIN_SOURCE)
{
string arg_types;
- for(NodeArray<Expression>::const_iterator i=call.arguments.begin(); i!=call.arguments.end(); ++i)
- if(BasicTypeDeclaration *basic_arg = dynamic_cast<BasicTypeDeclaration *>((*i)->type))
+ for(const RefPtr<Expression> &a: call.arguments)
+ if(BasicTypeDeclaration *basic_arg = dynamic_cast<BasicTypeDeclaration *>(a->type))
{
BasicTypeDeclaration &elem_arg = *get_element_type(*basic_arg);
switch(elem_arg.kind)
{
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<Id>::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<Node *> dependencies = DependencyCollector().apply(*call.declaration->definition);
- for(set<Node *>::const_iterator i=dependencies.begin(); i!=dependencies.end(); ++i)
- if(const VariableDeclaration *var = dynamic_cast<const VariableDeclaration *>(*i))
+ for(Node *n: dependencies)
+ if(const VariableDeclaration *var = dynamic_cast<const VariableDeclaration *>(n))
variable_load_ids.erase(var);
}
}
r_expression_result_id = write_construct(get_id(*call.type), column_ids, n_columns);
}
+void SpirVGenerator::visit_builtin_texture_query(FunctionCall &call, const vector<Id> &argument_ids)
+{
+ if(argument_ids.size()<1)
+ throw internal_error("invalid texture query call");
+
+ 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");
+
+ ImageTypeDeclaration &image_arg0 = dynamic_cast<ImageTypeDeclaration &>(*call.arguments[0]->type);
+
+ Id image_id;
+ if(image_arg0.sampled)
+ {
+ Id image_type_id = get_item(image_type_ids, get_id(image_arg0));
+ image_id = write_expression(OP_IMAGE, image_type_id, argument_ids[0]);
+ }
+ else
+ image_id = argument_ids[0];
+
+ Id result_type_id = get_id(*call.type);
+ r_expression_result_id = begin_expression(opcode, result_type_id, argument_ids.size());
+ writer.write(image_id);
+ for(unsigned i=1; i<argument_ids.size(); ++i)
+ writer.write(argument_ids[i]);
+ end_expression(opcode);
+}
+
void SpirVGenerator::visit_builtin_texture(FunctionCall &call, const vector<Id> &argument_ids)
{
if(argument_ids.size()<2)
writer.write(ext_id);
writer.write(opcode);
writer.write(get_id(*var->declaration));
- for(vector<Id>::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);
}
bool SpirVGenerator::check_duplicate_type(TypeDeclaration &type)
{
- for(map<Node *, Declaration>::const_iterator i=declared_ids.begin(); i!=declared_ids.end(); ++i)
- if(TypeDeclaration *type2 = dynamic_cast<TypeDeclaration *>(i->first))
+ for(const auto &kvp: declared_ids)
+ if(TypeDeclaration *type2 = dynamic_cast<TypeDeclaration *>(kvp.first))
if(TypeComparer().apply(type, *type2))
{
- insert_unique(declared_ids, &type, i->second);
+ insert_unique(declared_ids, &type, kvp.second);
return true;
}
{
writer.write_op_name(type_id, image.name);
writer.write_op(content.globals, OP_TYPE_SAMPLED_IMAGE, type_id, image_id);
+ insert_unique(image_type_ids, type_id, image_id);
}
if(image.dimensions==ImageTypeDeclaration::ONE)
bool builtin = (strct.interface_block && !strct.interface_block->block_name.compare(0, 3, "gl_"));
vector<Id> member_type_ids;
member_type_ids.reserve(strct.members.body.size());
- for(NodeList<Statement>::const_iterator i=strct.members.body.begin(); i!=strct.members.body.end(); ++i)
+ for(const RefPtr<Statement> &s: strct.members.body)
{
- const VariableDeclaration *var = dynamic_cast<const VariableDeclaration *>(i->get());
+ const VariableDeclaration *var = dynamic_cast<const VariableDeclaration *>(s.get());
if(!var)
continue;
{
if(var->layout)
{
- const vector<Layout::Qualifier> &qualifiers = var->layout->qualifiers;
- for(vector<Layout::Qualifier>::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);
}
}
writer.begin_op(content.globals, OP_TYPE_STRUCT);
writer.write(type_id);
- for(vector<Id>::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);
}
int spec_id = -1;
if(layout_ql)
{
- for(vector<Layout::Qualifier>::const_iterator i=layout_ql->begin(); (spec_id<0 && i!=layout_ql->end()); ++i)
- if(i->name=="constant_id")
- spec_id = i->value;
+ auto i = find_member(*layout_ql, string("constant_id"), &Layout::Qualifier::name);
+ if(i!=layout_ql->end())
+ spec_id = i->value;
}
Id type_id = get_variable_type_id(var);
if(layout_ql)
{
- for(vector<Layout::Qualifier>::const_iterator i=layout_ql->begin(); i!=layout_ql->end(); ++i)
+ for(const Layout::Qualifier &q: *layout_ql)
{
- 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)
{
if(iface.layout)
{
- const vector<Layout::Qualifier> &qualifiers = iface.layout->qualifiers;
- for(vector<Layout::Qualifier>::const_iterator i=qualifiers.begin(); i!=qualifiers.end(); ++i)
- if(i->name=="binding")
- writer.write_op_decorate(block_id, DECO_BINDING, i->value);
+ 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);
}
}
writer.write_string(func.name);
set<Node *> dependencies = DependencyCollector().apply(func);
- for(set<Node *>::const_iterator i=dependencies.begin(); i!=dependencies.end(); ++i)
+ for(Node *n: dependencies)
{
- if(const VariableDeclaration *var = dynamic_cast<const VariableDeclaration *>(*i))
+ if(const VariableDeclaration *var = dynamic_cast<const VariableDeclaration *>(n))
{
if(!var->interface.empty())
- writer.write(get_id(**i));
+ writer.write(get_id(*n));
}
- else if(dynamic_cast<InterfaceBlock *>(*i))
- writer.write(get_id(**i));
+ else if(dynamic_cast<InterfaceBlock *>(n))
+ writer.write(get_id(*n));
}
writer.end_op(OP_ENTRY_POINT);
else if(stage->type==Stage::GEOMETRY)
use_capability(CAP_GEOMETRY);
- for(vector<const InterfaceLayout *>::const_iterator i=interface_layouts.begin(); i!=interface_layouts.end(); ++i)
+ for(const InterfaceLayout *i: interface_layouts)
{
- const vector<Layout::Qualifier> &qualifiers = (*i)->layout.qualifiers;
- for(vector<Layout::Qualifier>::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);
}
}
}
Id return_type_id = get_id(*func.return_type_declaration);
vector<unsigned> param_type_ids;
param_type_ids.reserve(func.parameters.size());
- for(NodeArray<VariableDeclaration>::const_iterator i=func.parameters.begin(); i!=func.parameters.end(); ++i)
- param_type_ids.push_back(get_variable_type_id(**i));
+ for(const RefPtr<VariableDeclaration> &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];
writer.begin_op(content.globals, OP_TYPE_FUNCTION);
writer.write(type_id);
writer.write(return_type_id);
- for(vector<unsigned>::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);
if(iter.init_statement)
iter.init_statement->visit(*this);
- variable_load_ids.clear();
+ for(VariableDeclaration *v: AssignmentCollector().apply(iter))
+ variable_load_ids.erase(v);
Id header_id = next_id++;
Id continue_id = next_id++;
writer.write_op(content.function_body, OP_BRANCH, header_id);
writer.write_op_label(merge_block_id);
+ prune_loads(header_id);
reachable = true;
}