vkd3d-shader/msl: Implement VKD3DSIH_LD.

Co-authored-by: Giovanni Mascellani <gmascellani@codeweavers.com>
This commit is contained in:
Feifan He
2024-12-12 15:02:51 +08:00
committed by Henri Verbeet
parent 015a751ea0
commit ba7a9a0b29
Notes: Henri Verbeet 2025-04-14 17:16:19 +02:00
Approved-by: Henri Verbeet (@hverbeet)
Merge-Request: https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/1448
8 changed files with 223 additions and 22 deletions

View File

@@ -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, "<unrecognised resource datatype %#x>", 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<vkd3d_vec4>()", 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].tex<texture%s<",
binding, resource_type_info->type_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<uint4>(");
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<uint%zu>(%s)",
resource_type_info->read_coord_size, coord.str->buffer);
else
vkd3d_string_buffer_printf(read, "as_type<uint>(%s)", coord.str->buffer);
if (resource_type_info->array)
vkd3d_string_buffer_printf(read, ", as_type<uint>(%s)", array_index.str->buffer);
if (resource_type_info->lod)
vkd3d_string_buffer_printf(read, ", as_type<uint>(%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 <metal_common>\n\n");
vkd3d_string_buffer_printf(gen->buffer, "#include <metal_common>\n");
vkd3d_string_buffer_printf(gen->buffer, "#include <metal_texture>\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<typename T>\n"
" constant T &tex() constant\n"
" {\n"
" return reinterpret_cast<constant T &>(this->ptr);\n"
" }\n"
"\n"
" template<typename T>\n"
" const device T * constant &buf() constant\n"
" {\n"
" return reinterpret_cast<const device T * constant &>(this->ptr);\n"

View File

@@ -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,

View File

@@ -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]

View File

@@ -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

View File

@@ -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)

View File

@@ -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)

View File

@@ -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)

View File

@@ -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]