mirror of
https://gitlab.winehq.org/wine/vkd3d.git
synced 2025-09-12 18:50:22 -07:00
vkd3d-shader/msl: Implement VKD3DSIH_LD.
Co-authored-by: Giovanni Mascellani <gmascellani@codeweavers.com>
This commit is contained in:
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
@@ -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"
|
||||
|
@@ -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,
|
||||
|
@@ -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]
|
||||
|
@@ -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
|
||||
|
||||
|
||||
|
@@ -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)
|
||||
|
@@ -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)
|
||||
|
||||
|
||||
|
@@ -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)
|
||||
|
@@ -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]
|
||||
|
Reference in New Issue
Block a user