return BUILTIN_INVOCATION_ID;
else if(name=="gl_Layer")
return BUILTIN_LAYER;
+ else if(name=="gl_TessLevelOuter")
+ return BUILTIN_TESS_LEVEL_OUTER;
+ else if(name=="gl_TessLevelInner")
+ return BUILTIN_TESS_LEVEL_INNER;
+ else if(name=="gl_TessCoord")
+ return BUILTIN_TESS_COORD;
+ else if(name=="gl_PatchVerticesIn")
+ return BUILTIN_PATCH_VERTICES;
else if(name=="gl_FragCoord")
return BUILTIN_FRAG_COORD;
else if(name=="gl_PointCoord")
return BUILTIN_SAMPLE_POSITION;
else if(name=="gl_FragDepth")
return BUILTIN_FRAG_DEPTH;
+ else if(name=="gl_NumWorkGroups")
+ return BUILTIN_NUM_WORKGROUPS;
+ else if(name=="gl_WorkGroupSize")
+ return BUILTIN_WORKGROUP_SIZE;
+ else if(name=="gl_WorkGroupID")
+ return BUILTIN_WORKGROUP_ID;
+ else if(name=="gl_LocalInvocationID")
+ return BUILTIN_LOCAL_INVOCATION_ID;
+ else if(name=="gl_GlobalInvocationID")
+ return BUILTIN_GLOBAL_INVOCATION_ID;
+ else if(name=="gl_LocalInvocationIndex")
+ return BUILTIN_LOCAL_INVOCATION_INDEX;
else
throw invalid_argument("SpirVGenerator::get_builtin_semantic");
}
if(composite_access)
{
r_expression_result_id = 0;
- if(!assignment_source_id)
+ if(assignment_source_id)
+ variable_load_ids.erase(var.declaration);
+ else
{
auto i = variable_load_ids.find(var.declaration);
if(i!=variable_load_ids.end())
compare_id = write_construct(bool_vec_type_id, column_ids, n_elems);
}
+ else
+ throw internal_error("unsupported types for non-scalar equality comparison");
- if(compare_id)
- r_expression_result_id = write_expression(combine_op, result_type_id, compare_id);
+ r_expression_result_id = write_expression(combine_op, result_type_id, compare_id);
return;
}
}
void SpirVGenerator::visit_builtin_texture_fetch(FunctionCall &call, const vector<Id> &argument_ids)
{
- const ImageTypeDeclaration &image = dynamic_cast<const ImageTypeDeclaration &>(*call.arguments[0]->type);
+ ImageTypeDeclaration &image = dynamic_cast<ImageTypeDeclaration &>(*call.arguments[0]->type);
Opcode opcode;
if(call.name=="texelFetch")
if(argument_ids.size()!=2U+need_sample+need_lod)
throw internal_error("invalid texture fetch call");
+ Id image_id;
+ if(image.sampled)
+ {
+ Id image_type_id = get_item(image_type_ids, get_id(image));
+ image_id = write_expression(OP_IMAGE, image_type_id, argument_ids[0]);
+ }
+ else
+ image_id = argument_ids[0];
+
r_expression_result_id = begin_expression(opcode, get_id(*call.type), 2+(need_lod|need_sample)+need_lod+need_sample);
- for(unsigned i=0; i<2; ++i)
- writer.write(argument_ids[i]);
+ writer.write(image_id);
+ writer.write(argument_ids[1]);
if(need_lod || need_sample)
{
writer.write(need_lod*0x02 | need_sample*0x40);
return;
Id type_id = allocate_id(image, 0);
+ SpirVFormat format = get_format(image.format);
Id image_id = (image.sampled ? next_id++ : type_id);
writer.begin_op(content.globals, OP_TYPE_IMAGE, 9);
writer.write(image.array);
writer.write(image.multisample);
writer.write(image.sampled ? 1 : 2);
- writer.write(get_format(image.format));
+ writer.write(format);
writer.end_op(OP_TYPE_IMAGE);
if(image.sampled)
if(image.multisample && !image.sampled)
use_capability(CAP_STORAGE_IMAGE_MULTISAMPLE);
+
+ if(format>=FORMAT_RG32F && format<=FORMAT_R8_SNORM)
+ use_capability(CAP_STORAGE_IMAGE_EXTENDED_FORMATS);
}
void SpirVGenerator::visit(StructDeclaration &strct)
BuiltinSemantic semantic = get_builtin_semantic(var.name);
writer.write_op_decorate(var_id, DECO_BUILTIN, semantic);
}
+ if(var.interpolation=="flat")
+ writer.write_op_decorate(var_id, DECO_FLAT);
+ if(var.sampling=="centroid")
+ writer.write_op_decorate(var_id, DECO_CENTROID);
+ if(var.sampling=="patch")
+ writer.write_op_decorate(var_id, DECO_PATCH);
if(init_id && current_function)
{
switch(stage->type)
{
case Stage::VERTEX: writer.write(0); break;
+ case Stage::TESS_CONTROL: writer.write(1); break;
+ case Stage::TESS_EVAL: writer.write(2); break;
case Stage::GEOMETRY: writer.write(3); break;
case Stage::FRAGMENT: writer.write(4); break;
+ case Stage::COMPUTE: writer.write(5); break;
default: throw internal_error("unknown stage");
}
writer.write(func_id);
for(Node *n: dependencies)
if(const VariableDeclaration *var = dynamic_cast<const VariableDeclaration *>(n))
if(!var->interface.empty())
- writer.write(get_id(*n));
+ writer.write(allocate_forward_id(*n));
writer.end_op(OP_ENTRY_POINT);
use_capability(CAP_GEOMETRY);
writer.write_op(content.exec_modes, OP_EXECUTION_MODE, func_id, EXEC_INVOCATIONS, 1);
}
+ else if(stage->type==Stage::TESS_CONTROL || stage->type==Stage::TESS_EVAL)
+ {
+ use_capability(CAP_TESSELLATION);
+ }
+
+ unsigned local_size[3] = { 0, 1, 1 };
for(const InterfaceLayout *i: interface_layouts)
{
writer.write_op(content.exec_modes, OP_EXECUTION_MODE, func_id, EXEC_TRIANGLES);
else if(q.name=="triangles_adjacency")
writer.write_op(content.exec_modes, OP_EXECUTION_MODE, func_id, EXEC_INPUT_TRIANGLES_ADJACENCY);
+ else if(q.name=="quads")
+ writer.write_op(content.exec_modes, OP_EXECUTION_MODE, func_id, EXEC_QUADS);
+ else if(q.name=="isolines")
+ writer.write_op(content.exec_modes, OP_EXECUTION_MODE, func_id, EXEC_ISOLINES);
else if(q.name=="line_strip")
writer.write_op(content.exec_modes, OP_EXECUTION_MODE, func_id, EXEC_OUTPUT_LINE_STRIP);
else if(q.name=="triangle_strip")
writer.write_op(content.exec_modes, OP_EXECUTION_MODE, func_id, EXEC_OUTPUT_TRIANGLE_STRIP);
- else if(q.name=="max_vertices")
+ else if(q.name=="max_vertices" || q.name=="vertices")
writer.write_op(content.exec_modes, OP_EXECUTION_MODE, func_id, EXEC_OUTPUT_VERTICES, q.value);
+ else if(q.name=="cw")
+ writer.write_op(content.exec_modes, OP_EXECUTION_MODE, func_id, EXEC_VERTEX_ORDER_CW);
+ else if(q.name=="ccw")
+ writer.write_op(content.exec_modes, OP_EXECUTION_MODE, func_id, EXEC_VERTEX_ORDER_CCW);
+ else if(q.name=="equal_spacing")
+ writer.write_op(content.exec_modes, OP_EXECUTION_MODE, func_id, EXEC_SPACING_EQUAL);
+ else if(q.name=="fractional_even_spacing")
+ writer.write_op(content.exec_modes, OP_EXECUTION_MODE, func_id, EXEC_SPACING_FRACTIONAL_EVEN);
+ else if(q.name=="fractional_odd_spacing")
+ writer.write_op(content.exec_modes, OP_EXECUTION_MODE, func_id, EXEC_SPACING_FRACTIONAL_ODD);
+ else if(q.name=="local_size_x")
+ local_size[0] = q.value;
+ else if(q.name=="local_size_y")
+ local_size[1] = q.value;
+ else if(q.name=="local_size_z")
+ local_size[2] = q.value;
}
}
+
+ if(stage->type==Stage::COMPUTE && local_size[0])
+ {
+ writer.begin_op(content.exec_modes, OP_EXECUTION_MODE);
+ writer.write(func_id);
+ writer.write(EXEC_LOCAL_SIZE);
+ for(unsigned j=0; j<3; ++j)
+ writer.write(local_size[j]);
+ writer.end_op(OP_EXECUTION_MODE);
+ }
}
void SpirVGenerator::visit(FunctionDeclaration &func)