diff --git a/Sources/backends/metal.c b/Sources/backends/metal.c index 3411882..43b4305 100644 --- a/Sources/backends/metal.c +++ b/Sources/backends/metal.c @@ -287,23 +287,6 @@ static void write_types(char *metal, size_t *offset) { static int global_register_indices[512]; -static void write_globals(char *metal, size_t *offset) { - for (global_id i = 0; get_global(i).type != NO_TYPE; ++i) { - global g = get_global(i); - int register_index = global_register_indices[i]; - - if (g.type == sampler_type_id) { - *offset += sprintf(&metal[*offset], "SamplerState _%" PRIu64 " : register(s%i);\n\n", g.var_index, register_index); - } - else if (g.type == tex2d_type_id) { - *offset += sprintf(&metal[*offset], "Texture2D _%" PRIu64 " : register(t%i);\n\n", g.var_index, register_index); - } - else if (g.type == texcube_type_id) { - *offset += sprintf(&metal[*offset], "TextureCube _%" PRIu64 " : register(t%i);\n\n", g.var_index, register_index); - } - } -} - static function_id vertex_functions[256]; static size_t vertex_functions_size = 0; static function_id fragment_functions[256]; @@ -327,7 +310,7 @@ static bool is_fragment_function(function_id f) { return false; } -static void write_functions(char *metal, size_t *offset) { +static void write_functions(char *code, size_t *offset) { for (function_id i = 0; get_function(i) != NULL; ++i) { function *f = get_function(i); @@ -363,8 +346,10 @@ static void write_functions(char *metal, size_t *offset) { int register_index = global_register_indices[globals[i]]; if (g.type == sampler_type_id) { + buffers_offset += sprintf(&buffers[buffers_offset], ", sampler _%" PRIu64 " [[sampler(%i)]]", g.var_index, register_index); } else if (g.type == tex2d_type_id) { + buffers_offset += sprintf(&buffers[buffers_offset], ", texture2d _%" PRIu64 " [[texture(%i)]]", g.var_index, register_index); } else if (g.type == texcube_type_id) { } @@ -378,26 +363,26 @@ static void write_functions(char *metal, size_t *offset) { } if (is_vertex_function(i)) { - *offset += sprintf(&metal[*offset], "vertex %s %s(%s _%" PRIu64 "%s) {\n", type_string(f->return_type.type), get_name(f->name), + *offset += sprintf(&code[*offset], "vertex %s %s(%s _%" PRIu64 " [[stage_in]]%s) {\n", type_string(f->return_type.type), get_name(f->name), type_string(f->parameter_type.type), parameter_id, buffers); } else if (is_fragment_function(i)) { if (f->return_type.array_size > 0) { - *offset += sprintf(&metal[*offset], "struct _render_targets {\n"); + *offset += sprintf(&code[*offset], "struct _render_targets {\n"); for (uint32_t j = 0; j < f->return_type.array_size; ++j) { - *offset += sprintf(&metal[*offset], "\t%s _%i : SV_Target%i;\n", type_string(f->return_type.type), j, j); + *offset += sprintf(&code[*offset], "\t%s _%i : SV_Target%i;\n", type_string(f->return_type.type), j, j); } - *offset += sprintf(&metal[*offset], "};\n\n"); - *offset += sprintf(&metal[*offset], "_render_targets main(%s _%" PRIu64 ") {\n", type_string(f->parameter_type.type), parameter_id); + *offset += sprintf(&code[*offset], "};\n\n"); + *offset += sprintf(&code[*offset], "_render_targets main(%s _%" PRIu64 ") {\n", type_string(f->parameter_type.type), parameter_id); } else { - *offset += sprintf(&metal[*offset], "fragment %s %s(%s _%" PRIu64 "%s) [[color(0)]] {\n", type_string(f->return_type.type), get_name(f->name), + *offset += sprintf(&code[*offset], "fragment ColorOut %s(%s _%" PRIu64 " [[stage_in]]%s) {\n", get_name(f->name), type_string(f->parameter_type.type), parameter_id, buffers); } } else { - *offset += sprintf(&metal[*offset], "%s %s(%s _%" PRIu64 ") {\n", type_string(f->return_type.type), get_name(f->name), + *offset += sprintf(&code[*offset], "%s %s(%s _%" PRIu64 ") {\n", type_string(f->return_type.type), get_name(f->name), type_string(f->parameter_type.type), parameter_id); } @@ -415,50 +400,84 @@ static void write_functions(char *metal, size_t *offset) { } } - *offset += sprintf(&metal[*offset], "\t%s _%" PRIu64 " = _%" PRIu64, type_string(o->op_load_member.to.type.type), o->op_load_member.to.index, + *offset += sprintf(&code[*offset], "\t%s _%" PRIu64 " = _%" PRIu64, type_string(o->op_load_member.to.type.type), o->op_load_member.to.index, o->op_load_member.from.index); type *s = get_type(o->op_load_member.member_parent_type); for (size_t i = 0; i < o->op_load_member.member_indices_size; ++i) { - *offset += sprintf(&metal[*offset], ".%s", get_name(s->members.m[o->op_load_member.member_indices[i]].name)); + *offset += sprintf(&code[*offset], ".%s", get_name(s->members.m[o->op_load_member.member_indices[i]].name)); s = get_type(s->members.m[o->op_load_member.member_indices[i]].type.type); } - *offset += sprintf(&metal[*offset], ";\n"); + *offset += sprintf(&code[*offset], ";\n"); break; } case OPCODE_RETURN: { if (o->size > offsetof(opcode, op_return)) { if (is_fragment_function(i) && f->return_type.array_size > 0) { - *offset += sprintf(&metal[*offset], "\t{\n"); - *offset += sprintf(&metal[*offset], "\t\t_render_targets rts;\n"); + *offset += sprintf(&code[*offset], "\t{\n"); + *offset += sprintf(&code[*offset], "\t\t_render_targets rts;\n"); for (uint32_t j = 0; j < f->return_type.array_size; ++j) { - *offset += sprintf(&metal[*offset], "\t\trts._%i = _%" PRIu64 "[%i];\n", j, o->op_return.var.index, j); + *offset += sprintf(&code[*offset], "\t\trts._%i = _%" PRIu64 "[%i];\n", j, o->op_return.var.index, j); } - *offset += sprintf(&metal[*offset], "\t\treturn rts;\n"); - *offset += sprintf(&metal[*offset], "\t}\n"); + *offset += sprintf(&code[*offset], "\t\treturn rts;\n"); + *offset += sprintf(&code[*offset], "\t}\n"); + } + else if (is_fragment_function(i)) { + *offset += sprintf(&code[*offset], "\t{\n"); + *offset += sprintf(&code[*offset], "\t\tColorOut out;\n"); + *offset += sprintf(&code[*offset], "\t\tout.out = _%" PRIu64 ";\n", o->op_return.var.index); + *offset += sprintf(&code[*offset], "\t\treturn out;\n"); + *offset += sprintf(&code[*offset], "\t}\n"); } else { - *offset += sprintf(&metal[*offset], "\treturn _%" PRIu64 ";\n", o->op_return.var.index); + *offset += sprintf(&code[*offset], "\treturn _%" PRIu64 ";\n", o->op_return.var.index); } } else { - *offset += sprintf(&metal[*offset], "\treturn;\n"); + *offset += sprintf(&code[*offset], "\treturn;\n"); + } + break; + } + case OPCODE_CALL: { + debug_context context = {0}; + if (o->op_call.func == add_name("sample")) { + check(o->op_call.parameters_size == 3, context, "sample requires three parameters"); + *offset += + sprintf(&code[*offset], "\t%s _%" PRIu64 " = _%" PRIu64 ".sample(_%" PRIu64 ", _%" PRIu64 ");\n", type_string(o->op_call.var.type.type), + o->op_call.var.index, o->op_call.parameters[0].index, o->op_call.parameters[1].index, o->op_call.parameters[2].index); + } + else if (o->op_call.func == add_name("sample_lod")) { + check(o->op_call.parameters_size == 4, context, "sample_lod requires four parameters"); + *offset += sprintf(&code[*offset], "\t%s _%" PRIu64 " = _%" PRIu64 ".sampleLevel(_%" PRIu64 ", _%" PRIu64 ", _%" PRIu64 ");\n", + type_string(o->op_call.var.type.type), o->op_call.var.index, o->op_call.parameters[0].index, + o->op_call.parameters[1].index, o->op_call.parameters[2].index, o->op_call.parameters[3].index); + } + else { + *offset += sprintf(&code[*offset], "\t%s _%" PRIu64 " = %s(", type_string(o->op_call.var.type.type), o->op_call.var.index, + function_string(o->op_call.func)); + if (o->op_call.parameters_size > 0) { + *offset += sprintf(&code[*offset], "_%" PRIu64, o->op_call.parameters[0].index); + for (uint8_t i = 1; i < o->op_call.parameters_size; ++i) { + *offset += sprintf(&code[*offset], ", _%" PRIu64, o->op_call.parameters[i].index); + } + } + *offset += sprintf(&code[*offset], ");\n"); } break; } case OPCODE_MULTIPLY: { - *offset += sprintf(&metal[*offset], "\t%s _%" PRIu64 " = _%" PRIu64 " * _%" PRIu64 ";\n", type_string(o->op_multiply.result.type.type), + *offset += sprintf(&code[*offset], "\t%s _%" PRIu64 " = _%" PRIu64 " * _%" PRIu64 ";\n", type_string(o->op_multiply.result.type.type), o->op_multiply.result.index, o->op_multiply.left.index, o->op_multiply.right.index); break; } default: - cstyle_write_opcode(metal, offset, o, type_string); + cstyle_write_opcode(code, offset, o, type_string); break; } index += o->size; } - *offset += sprintf(&metal[*offset], "}\n\n"); + *offset += sprintf(&code[*offset], "}\n\n"); } } @@ -472,9 +491,11 @@ static void metal_export_everything(char *directory) { offset += sprintf(&metal[offset], "#include \n\n"); offset += sprintf(&metal[offset], "using namespace metal;\n\n"); - write_types(metal, &offset); + offset += sprintf(&metal[offset], "struct ColorOut {\n"); + offset += sprintf(&metal[offset], "\tfloat4 out [[color(0)]];\n"); + offset += sprintf(&metal[offset], "};\n\n"); - write_globals(metal, &offset); + write_types(metal, &offset); write_functions(metal, &offset);