diff --git a/libs/vkd3d-shader/msl.c b/libs/vkd3d-shader/msl.c index 7bb8307b1..55e5aa2b9 100644 --- a/libs/vkd3d-shader/msl.c +++ b/libs/vkd3d-shader/msl.c @@ -46,6 +46,14 @@ struct msl_generator const struct vkd3d_shader_interface_info *interface_info; }; +struct msl_resource_type_info +{ + size_t read_coord_size; + bool array; + bool lod; + const char *type_suffix; +}; + static void VKD3D_PRINTF_FUNC(3, 4) msl_compiler_error(struct msl_generator *gen, enum vkd3d_shader_error error, const char *fmt, ...) { @@ -57,6 +65,30 @@ static void VKD3D_PRINTF_FUNC(3, 4) msl_compiler_error(struct msl_generator *gen gen->failed = true; } +static const struct msl_resource_type_info *msl_get_resource_type_info(enum vkd3d_shader_resource_type t) +{ + static const struct msl_resource_type_info info[] = + { + [VKD3D_SHADER_RESOURCE_NONE] = {0, false, false, "none"}, + [VKD3D_SHADER_RESOURCE_BUFFER] = {1, false, false, "_buffer"}, + [VKD3D_SHADER_RESOURCE_TEXTURE_1D] = {1, false, false, "1d"}, + [VKD3D_SHADER_RESOURCE_TEXTURE_2D] = {2, false, true, "2d"}, + [VKD3D_SHADER_RESOURCE_TEXTURE_2DMS] = {2, false, false, "2d_ms"}, + [VKD3D_SHADER_RESOURCE_TEXTURE_3D] = {3, false, true, "3d"}, + [VKD3D_SHADER_RESOURCE_TEXTURE_CUBE] = {2, false, true, "cube"}, + [VKD3D_SHADER_RESOURCE_TEXTURE_1DARRAY] = {1, true, false, "1d_array"}, + [VKD3D_SHADER_RESOURCE_TEXTURE_2DARRAY] = {2, true, true, "2d_array"}, + [VKD3D_SHADER_RESOURCE_TEXTURE_2DMSARRAY] = {2, true, false, "2d_ms_array"}, + [VKD3D_SHADER_RESOURCE_TEXTURE_CUBEARRAY] = {2, true, true, "cube_array"}, + }; + + if (!t || t >= ARRAY_SIZE(info)) + return NULL; + + return &info[t]; +} + + static const char *msl_get_prefix(enum vkd3d_shader_type type) { switch (type) @@ -83,6 +115,30 @@ static void msl_print_indent(struct vkd3d_string_buffer *buffer, unsigned int in vkd3d_string_buffer_printf(buffer, "%*s", 4 * indent, ""); } +static void msl_print_resource_datatype(struct msl_generator *gen, + struct vkd3d_string_buffer *buffer, enum vkd3d_shader_resource_data_type data_type) +{ + switch (data_type) + { + case VKD3D_SHADER_RESOURCE_DATA_FLOAT: + case VKD3D_SHADER_RESOURCE_DATA_UNORM: + case VKD3D_SHADER_RESOURCE_DATA_SNORM: + vkd3d_string_buffer_printf(buffer, "float"); + break; + case VKD3D_SHADER_RESOURCE_DATA_INT: + vkd3d_string_buffer_printf(buffer, "int"); + break; + case VKD3D_SHADER_RESOURCE_DATA_UINT: + vkd3d_string_buffer_printf(buffer, "uint"); + break; + default: + msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, + "Internal compiler error: Unhandled resource datatype %#x.", data_type); + vkd3d_string_buffer_printf(buffer, "", data_type); + break; + } +} + static void msl_print_register_datatype(struct vkd3d_string_buffer *buffer, struct msl_generator *gen, enum vkd3d_data_type data_type) { @@ -163,11 +219,55 @@ static const struct vkd3d_shader_descriptor_binding *msl_get_cbv_binding(const s return NULL; } +static const struct vkd3d_shader_descriptor_binding *msl_get_srv_binding(const struct msl_generator *gen, + unsigned int register_space, unsigned int register_idx, enum vkd3d_shader_resource_type resource_type) +{ + const struct vkd3d_shader_interface_info *interface_info = gen->interface_info; + enum vkd3d_shader_binding_flag resource_type_flag; + unsigned int i; + + if (!interface_info) + return NULL; + + resource_type_flag = resource_type == VKD3D_SHADER_RESOURCE_BUFFER + ? VKD3D_SHADER_BINDING_FLAG_BUFFER : VKD3D_SHADER_BINDING_FLAG_IMAGE; + + for (i = 0; i < interface_info->binding_count; ++i) + { + const struct vkd3d_shader_resource_binding *binding = &interface_info->bindings[i]; + + if (binding->type != VKD3D_SHADER_DESCRIPTOR_TYPE_SRV) + continue; + if (binding->register_space != register_space) + continue; + if (binding->register_index != register_idx) + continue; + if (!msl_check_shader_visibility(gen, binding->shader_visibility)) + continue; + if (!(binding->flags & resource_type_flag)) + continue; + + return &binding->binding; + } + + return NULL; +} + static void msl_print_cbv_name(struct vkd3d_string_buffer *buffer, unsigned int binding) { vkd3d_string_buffer_printf(buffer, "descriptors[%u].buf()", binding); } +static void msl_print_srv_name(struct vkd3d_string_buffer *buffer, struct msl_generator *gen, + unsigned int binding, const struct msl_resource_type_info *resource_type_info, + enum vkd3d_shader_resource_data_type resource_data_type) +{ + vkd3d_string_buffer_printf(buffer, "descriptors[%u].textype_suffix); + msl_print_resource_datatype(gen, buffer, resource_data_type); + vkd3d_string_buffer_printf(buffer, ">>()"); +} + static void msl_print_register_name(struct vkd3d_string_buffer *buffer, struct msl_generator *gen, const struct vkd3d_shader_register *reg) { @@ -604,6 +704,96 @@ static void msl_else(struct msl_generator *gen) msl_begin_block(gen); } +static void msl_ld(struct msl_generator *gen, const struct vkd3d_shader_instruction *ins) +{ + const struct msl_resource_type_info *resource_type_info; + enum vkd3d_shader_resource_data_type resource_data_type; + unsigned int resource_id, resource_idx, resource_space; + const struct vkd3d_shader_descriptor_info1 *descriptor; + const struct vkd3d_shader_descriptor_binding *binding; + enum vkd3d_shader_resource_type resource_type; + struct msl_src coord, array_index, lod; + struct vkd3d_string_buffer *read; + uint32_t coord_mask; + struct msl_dst dst; + + if (vkd3d_shader_instruction_has_texel_offset(ins)) + msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, + "Internal compiler error: Unhandled texel fetch offset."); + + if (ins->src[1].reg.idx[0].rel_addr || ins->src[1].reg.idx[1].rel_addr) + msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_UNSUPPORTED, + "Descriptor indexing is not supported."); + + resource_id = ins->src[1].reg.idx[0].offset; + resource_idx = ins->src[1].reg.idx[1].offset; + if ((descriptor = vkd3d_shader_find_descriptor(&gen->program->descriptors, + VKD3D_SHADER_DESCRIPTOR_TYPE_SRV, resource_id))) + { + resource_type = descriptor->resource_type; + resource_space = descriptor->register_space; + resource_data_type = descriptor->resource_data_type; + } + else + { + msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, + "Internal compiler error: Undeclared resource descriptor %u.", resource_id); + resource_space = 0; + resource_type = VKD3D_SHADER_RESOURCE_TEXTURE_2D; + resource_data_type = VKD3D_SHADER_RESOURCE_DATA_FLOAT; + } + + if ((resource_type_info = msl_get_resource_type_info(resource_type))) + { + coord_mask = vkd3d_write_mask_from_component_count(resource_type_info->read_coord_size); + } + else + { + msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, + "Internal compiler error: Unhandled resource type %#x.", resource_type); + coord_mask = vkd3d_write_mask_from_component_count(2); + } + + if (!(binding = msl_get_srv_binding(gen, resource_space, resource_idx, resource_type))) + { + msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_BINDING_NOT_FOUND, + "Cannot finding binding for SRV register %u index %u space %u.", + resource_id, resource_idx, resource_space); + return; + } + + msl_dst_init(&dst, gen, ins, &ins->dst[0]); + msl_src_init(&coord, gen, &ins->src[0], coord_mask); + /* `coord_mask + 1` gives exactly the array index component mask if it is an array resource */ + /* Or it's simply unused, saving some branches */ + msl_src_init(&array_index, gen, &ins->src[0], coord_mask + 1); + msl_src_init(&lod, gen, &ins->src[0], VKD3DSP_WRITEMASK_3); + read = vkd3d_string_buffer_get(&gen->string_buffers); + + vkd3d_string_buffer_printf(read, "as_type("); + msl_print_srv_name(read, gen, binding->binding, resource_type_info, resource_data_type); + vkd3d_string_buffer_printf(read, ".read("); + if (resource_type_info->read_coord_size > 1) + vkd3d_string_buffer_printf(read, "as_type(%s)", + resource_type_info->read_coord_size, coord.str->buffer); + else + vkd3d_string_buffer_printf(read, "as_type(%s)", coord.str->buffer); + if (resource_type_info->array) + vkd3d_string_buffer_printf(read, ", as_type(%s)", array_index.str->buffer); + if (resource_type_info->lod) + vkd3d_string_buffer_printf(read, ", as_type(%s)", lod.str->buffer); + vkd3d_string_buffer_printf(read, "))"); + msl_print_swizzle(read, ins->src[1].swizzle, ins->dst[0].write_mask); + + msl_print_assignment(gen, &dst, "%s", read->buffer); + + vkd3d_string_buffer_release(&gen->string_buffers, read); + msl_src_cleanup(&lod, &gen->string_buffers); + msl_src_cleanup(&array_index, &gen->string_buffers); + msl_src_cleanup(&coord, &gen->string_buffers); + msl_dst_cleanup(&dst, &gen->string_buffers); +} + static void msl_unary_op(struct msl_generator *gen, const struct vkd3d_shader_instruction *ins, const char *op) { struct msl_src src; @@ -745,6 +935,9 @@ static void msl_handle_instruction(struct msl_generator *gen, const struct vkd3d case VKD3DSIH_UTOF: msl_cast(gen, ins, "float"); break; + case VKD3DSIH_LD: + msl_ld(gen, ins); + break; case VKD3DSIH_LOG: msl_intrinsic(gen, ins, "log2"); break; @@ -1148,7 +1341,8 @@ static int msl_generator_generate(struct msl_generator *gen, struct vkd3d_shader MESSAGE("Generating a MSL shader. This is unsupported; you get to keep all the pieces if it breaks.\n"); vkd3d_string_buffer_printf(gen->buffer, "/* Generated by %s. */\n\n", vkd3d_shader_get_version(NULL, NULL)); - vkd3d_string_buffer_printf(gen->buffer, "#include \n\n"); + vkd3d_string_buffer_printf(gen->buffer, "#include \n"); + vkd3d_string_buffer_printf(gen->buffer, "#include \n\n"); vkd3d_string_buffer_printf(gen->buffer, "using namespace metal;\n\n"); if (gen->program->global_flags) @@ -1168,6 +1362,12 @@ static int msl_generator_generate(struct msl_generator *gen, struct vkd3d_shader " const device void *ptr;\n" "\n" " template\n" + " constant T &tex() constant\n" + " {\n" + " return reinterpret_cast(this->ptr);\n" + " }\n" + "\n" + " template\n" " const device T * constant &buf() constant\n" " {\n" " return reinterpret_cast(this->ptr);\n" diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index 168c40bd3..03dc02174 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -262,6 +262,7 @@ enum vkd3d_shader_error VKD3D_SHADER_ERROR_MSL_INTERNAL = 10000, VKD3D_SHADER_ERROR_MSL_BINDING_NOT_FOUND = 10001, + VKD3D_SHADER_ERROR_MSL_UNSUPPORTED = 10002, VKD3D_SHADER_ERROR_FX_NOT_IMPLEMENTED = 11000, VKD3D_SHADER_ERROR_FX_INVALID_VERSION = 11001, diff --git a/tests/hlsl/cbuffer.shader_test b/tests/hlsl/cbuffer.shader_test index cdba5e282..c0caeefd9 100644 --- a/tests/hlsl/cbuffer.shader_test +++ b/tests/hlsl/cbuffer.shader_test @@ -619,7 +619,7 @@ float4 main() : sv_target } [test] -todo(msl) draw quad +draw quad probe (0, 0) rgba (1.0, 1.0, 1.0, 1.0) @@ -850,7 +850,7 @@ uniform 4 float4 4.0 5.0 6.0 7.0 uniform 8 float4 8.0 9.0 10.0 11.0 uniform 12 float4 12.0 13.0 14.0 15.0 uniform 16 float4 16.0 17.0 18.0 19.0 -todo(msl) draw quad +draw quad probe (0, 0) rgba (124.0, 135.0, 146.0, 150.5) [require] diff --git a/tests/hlsl/initializer-objects.shader_test b/tests/hlsl/initializer-objects.shader_test index aea171549..6156233da 100644 --- a/tests/hlsl/initializer-objects.shader_test +++ b/tests/hlsl/initializer-objects.shader_test @@ -25,7 +25,7 @@ float4 main() : sv_target } [test] -todo(msl) draw quad +draw quad probe (0, 0) rgba (0.2, 0.2, 0.2, 0.1) @@ -48,7 +48,7 @@ float4 main() : sv_target } [test] -todo(msl) draw quad +draw quad probe (0, 0) rgba (31.1, 41.1, 51.1, 61.1) 1 diff --git a/tests/hlsl/load-level.shader_test b/tests/hlsl/load-level.shader_test index 99a86d71d..668fe4e33 100644 --- a/tests/hlsl/load-level.shader_test +++ b/tests/hlsl/load-level.shader_test @@ -22,10 +22,10 @@ float4 main() : sv_target [test] uniform 0 uint 0 -todo(msl) draw quad +draw quad probe (0, 0) rgba (1.0, 0.0, 1.0, 0.0) uniform 0 uint 1 -todo(msl) draw quad +draw quad probe (0, 0) rgba (0.0, 0.0, 1.0, 0.0) [pixel shader fail] @@ -47,5 +47,5 @@ float4 main() : sv_target } [test] -todo(msl) draw quad +draw quad probe (0, 0) rgba (1.0, 0.0, 1.0, 0.0) diff --git a/tests/hlsl/object-references.shader_test b/tests/hlsl/object-references.shader_test index 79355c7d2..ef126b611 100644 --- a/tests/hlsl/object-references.shader_test +++ b/tests/hlsl/object-references.shader_test @@ -111,7 +111,7 @@ float4 main() : sv_target } [test] -todo(msl) draw quad +draw quad probe (0, 0) rgba (312, 312, 312, 111) @@ -134,7 +134,7 @@ float4 main() : sv_target } [test] -todo(msl) draw quad +draw quad probe (0, 0) rgba (2132, 2132, 2132, 1111) diff --git a/tests/hlsl/register-reservations-resources.shader_test b/tests/hlsl/register-reservations-resources.shader_test index fa4968d28..b94eee4bd 100644 --- a/tests/hlsl/register-reservations-resources.shader_test +++ b/tests/hlsl/register-reservations-resources.shader_test @@ -34,7 +34,7 @@ float4 main() : sv_target } [test] -todo(msl) draw quad +draw quad probe (0, 0) rgba (41.0, 41.0, 41.0, 1089.0) @@ -50,7 +50,7 @@ float4 main() : sv_target } [test] -todo(msl) draw quad +draw quad probe (0, 0) rgba (0.0, 0.0, 0.0, 99.0) @@ -65,7 +65,7 @@ float4 main() : sv_target } [test] -todo(msl) draw quad +draw quad probe (0, 0) rgba (1.0, 1.0, 1.0, 99.0) @@ -84,7 +84,7 @@ shader model >= 4.0 shader model < 6.0 [test] -todo(msl) draw quad +draw quad probe (0, 0) rgba (0.0, 0.0, 0.0, 99.0) [require] @@ -110,7 +110,7 @@ float4 main() : sv_target [test] -todo(msl) draw quad +draw quad probe (0, 0) rgba (0.0, 0.0, 0.0, 99.0) [pixel shader] @@ -123,7 +123,7 @@ float4 main() : sv_target } [test] -todo(msl) draw quad +draw quad probe (0, 0) rgba (4.0, 4.0, 4.0, 99.0) @@ -139,7 +139,7 @@ float4 main() : sv_target } [test] -todo(msl) draw quad +draw quad probe (0, 0) rgba (1.0, 1.0, 1.0, 99.0) @@ -154,7 +154,7 @@ float4 main() : sv_target } [test] -todo(msl) draw quad +draw quad probe (0, 0) rgba (2.0, 2.0, 2.0, 99.0) @@ -168,7 +168,7 @@ float4 main() : sv_target } [test] -todo(msl) draw quad +draw quad probe (0, 0) rgba (2.0, 2.0, 2.0, 99.0) @@ -241,5 +241,5 @@ float4 main() : sv_target } [test] -todo(msl) draw quad +draw quad probe (0, 0) rgba (1.0, 1.0, 1.0, 99.0) diff --git a/tests/hlsl/texture-load-typed.shader_test b/tests/hlsl/texture-load-typed.shader_test index d08783944..8ca4a915e 100644 --- a/tests/hlsl/texture-load-typed.shader_test +++ b/tests/hlsl/texture-load-typed.shader_test @@ -48,7 +48,7 @@ float4 main() : sv_target } [test] -todo(msl) draw quad +draw quad probe (0, 0) rgba (0.8, -3.0, 4294967295.0, 123.0) % lowercase 'texture2D' @@ -65,7 +65,7 @@ float4 main() : sv_target } [test] -todo(msl) draw quad +draw quad probe (0, 0) rgba (0.8, -3.0, 4294967295.0, 123.0) [require]