From d4bb50e646849dd747c804afef18f463c6cd7a8e Mon Sep 17 00:00:00 2001 From: Alistair Leslie-Hughes Date: Thu, 1 May 2025 06:41:00 +1000 Subject: [PATCH] Updated vkd3d to 541060215e338a419a5a6fe6ae156fecf1c4b89f. --- libs/vkd3d/libs/vkd3d-shader/d3dbc.c | 61 ++++++- libs/vkd3d/libs/vkd3d-shader/dxil.c | 68 ++++--- libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c | 4 +- libs/vkd3d/libs/vkd3d-shader/ir.c | 4 +- libs/vkd3d/libs/vkd3d-shader/msl.c | 187 ++++++++++---------- 5 files changed, 201 insertions(+), 123 deletions(-) diff --git a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c index 77498f26c7f..57d874efe37 100644 --- a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c +++ b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c @@ -1215,6 +1215,7 @@ static void shader_sm1_read_instruction(struct vkd3d_shader_sm1_parser *sm1, str struct vkd3d_shader_src_param *src_params, *predicate; const struct vkd3d_sm1_opcode_info *opcode_info; struct vsir_program *program = sm1->p.program; + unsigned int vsir_dst_count, vsir_src_count; struct vkd3d_shader_dst_param *dst_param; const uint32_t **ptr = &sm1->ptr; uint32_t opcode_token; @@ -1241,6 +1242,17 @@ static void shader_sm1_read_instruction(struct vkd3d_shader_sm1_parser *sm1, str goto fail; } + if (opcode_info->vkd3d_opcode == VKD3DSIH_TEXKILL) + { + vsir_src_count = 1; + vsir_dst_count = 0; + } + else + { + vsir_src_count = opcode_info->src_count; + vsir_dst_count = opcode_info->dst_count; + } + vsir_instruction_init(ins, &sm1->p.location, opcode_info->vkd3d_opcode); ins->flags = (opcode_token & VKD3D_SM1_INSTRUCTION_FLAGS_MASK) >> VKD3D_SM1_INSTRUCTION_FLAGS_SHIFT; ins->coissue = opcode_token & VKD3D_SM1_COISSUE; @@ -1248,9 +1260,9 @@ static void shader_sm1_read_instruction(struct vkd3d_shader_sm1_parser *sm1, str ins->structured = false; predicated = !!(opcode_token & VKD3D_SM1_INSTRUCTION_PREDICATED); ins->predicate = predicate = predicated ? vsir_program_get_src_params(program, 1) : NULL; - ins->dst_count = opcode_info->dst_count; + ins->dst_count = vsir_dst_count; ins->dst = dst_param = vsir_program_get_dst_params(program, ins->dst_count); - ins->src_count = opcode_info->src_count; + ins->src_count = vsir_src_count; ins->src = src_params = vsir_program_get_src_params(program, ins->src_count); if ((!predicate && predicated) || (!src_params && ins->src_count) || (!dst_param && ins->dst_count)) { @@ -1298,6 +1310,25 @@ static void shader_sm1_read_instruction(struct vkd3d_shader_sm1_parser *sm1, str shader_sm1_read_immconst(sm1, &p, &src_params[0], VSIR_DIMENSION_VEC4, VKD3D_DATA_INT); shader_sm1_scan_register(sm1, &dst_param->reg, dst_param->write_mask, true); } + else if (ins->opcode == VKD3DSIH_TEXKILL) + { + /* TEXKILL, uniquely, encodes its argument as a destination, when it is + * semantically a source. Since we have multiple passes which operate + * generically on sources or destinations, normalize that. */ + const struct vkd3d_shader_register *reg; + struct vkd3d_shader_dst_param tmp_dst; + + reg = &tmp_dst.reg; + shader_sm1_read_dst_param(sm1, &p, &tmp_dst); + shader_sm1_scan_register(sm1, reg, tmp_dst.write_mask, false); + + vsir_src_param_init(&src_params[0], reg->type, reg->data_type, reg->idx_count); + src_params[0].reg = *reg; + src_params[0].swizzle = vsir_swizzle_from_writemask(tmp_dst.write_mask); + + if (ins->predicate) + shader_sm1_read_src_param(sm1, &p, predicate); + } else { /* Destination token */ @@ -1834,6 +1865,27 @@ static void d3dbc_write_instruction(struct d3dbc_compiler *d3dbc, const struct v } }; +static void d3dbc_write_texkill(struct d3dbc_compiler *d3dbc, const struct vkd3d_shader_instruction *ins) +{ + const struct vkd3d_shader_register *reg = &ins->src[0].reg; + struct vkd3d_shader_instruction tmp; + struct vkd3d_shader_dst_param dst; + + /* TEXKILL, uniquely, encodes its argument as a destination, when it is + * semantically a source. We store it as a source in vsir, so convert it. */ + + vsir_dst_param_init(&dst, reg->type, reg->data_type, reg->idx_count); + dst.reg = *reg; + dst.write_mask = mask_from_swizzle(ins->src[0].swizzle); + + tmp = *ins; + tmp.dst_count = 1; + tmp.dst = &dst; + tmp.src_count = 0; + + d3dbc_write_instruction(d3dbc, &tmp); +} + static void d3dbc_write_vsir_def(struct d3dbc_compiler *d3dbc, const struct vkd3d_shader_instruction *ins) { const struct vkd3d_shader_version *version = &d3dbc->program->shader_version; @@ -1938,6 +1990,10 @@ static void d3dbc_write_vsir_instruction(struct d3dbc_compiler *d3dbc, const str d3dbc_write_vsir_dcl(d3dbc, ins); break; + case VKD3DSIH_TEXKILL: + d3dbc_write_texkill(d3dbc, ins); + break; + case VKD3DSIH_ABS: case VKD3DSIH_ADD: case VKD3DSIH_CMP: @@ -1959,7 +2015,6 @@ static void d3dbc_write_vsir_instruction(struct d3dbc_compiler *d3dbc, const str case VKD3DSIH_SINCOS: case VKD3DSIH_SLT: case VKD3DSIH_TEX: - case VKD3DSIH_TEXKILL: case VKD3DSIH_TEXLDD: d3dbc_write_instruction(d3dbc, ins); break; diff --git a/libs/vkd3d/libs/vkd3d-shader/dxil.c b/libs/vkd3d/libs/vkd3d-shader/dxil.c index d5f9626ec9d..775be85334e 100644 --- a/libs/vkd3d/libs/vkd3d-shader/dxil.c +++ b/libs/vkd3d/libs/vkd3d-shader/dxil.c @@ -659,7 +659,8 @@ struct sm6_function_data struct sm6_handle_data { const struct sm6_descriptor_info *d; - struct vkd3d_shader_register reg; + const struct sm6_value *index; + bool non_uniform; }; struct sm6_value @@ -2519,6 +2520,25 @@ static void register_index_address_init(struct vkd3d_shader_register_index *idx, } } +static void sm6_register_from_handle(struct sm6_parser *sm6, + const struct sm6_handle_data *handle, struct vkd3d_shader_register *reg) +{ + vsir_register_init(reg, handle->d->reg_type, handle->d->reg_data_type, 2); + reg->dimension = VSIR_DIMENSION_VEC4; + reg->idx[0].offset = handle->d->id; + register_index_address_init(®->idx[1], handle->index, sm6); + reg->non_uniform = handle->non_uniform; +} + +static void src_param_init_vector_from_handle(struct sm6_parser *sm6, + struct vkd3d_shader_src_param *param, const struct sm6_handle_data *handle) +{ + struct vkd3d_shader_register reg; + + sm6_register_from_handle(sm6, handle, ®); + src_param_init_vector_from_reg(param, ®); +} + static bool instruction_dst_param_init_ssa_scalar(struct vkd3d_shader_instruction *ins, struct sm6_parser *sm6) { struct sm6_value *dst = sm6_parser_get_current_value(sm6); @@ -4788,7 +4808,7 @@ static void sm6_parser_emit_dx_atomic_binop(struct sm6_parser *sm6, enum dx_intr dst_param_init(&dst_params[0]); register_init_ssa_scalar(&dst_params[0].reg, dst->type, dst, sm6); dst_param_init(&dst_params[1]); - dst_params[1].reg = resource->u.handle.reg; + sm6_register_from_handle(sm6, &resource->u.handle, &dst_params[1].reg); dst->u.reg = dst_params[0].reg; } @@ -4846,7 +4866,7 @@ static void sm6_parser_emit_dx_buffer_update_counter(struct sm6_parser *sm6, enu vsir_instruction_init(ins, &sm6->p.location, (inc < 0) ? VKD3DSIH_IMM_ATOMIC_CONSUME : VKD3DSIH_IMM_ATOMIC_ALLOC); if (!(src_params = instruction_src_params_alloc(ins, 1, sm6))) return; - src_param_init_vector_from_reg(&src_params[0], &resource->u.handle.reg); + src_param_init_vector_from_handle(sm6, &src_params[0], &resource->u.handle); instruction_dst_param_init_ssa_scalar(ins, sm6); } @@ -4878,9 +4898,9 @@ static void sm6_parser_emit_dx_calculate_lod(struct sm6_parser *sm6, enum dx_int if (!(src_params = instruction_src_params_alloc(ins, 3, sm6))) return; src_param_init_vector_from_reg(&src_params[0], &coord); - src_params[1].reg = resource->u.handle.reg; + sm6_register_from_handle(sm6, &resource->u.handle, &src_params[1].reg); src_param_init_scalar(&src_params[1], !clamp); - src_param_init_vector_from_reg(&src_params[2], &sampler->u.handle.reg); + src_param_init_vector_from_handle(sm6, &src_params[2], &sampler->u.handle); instruction_dst_param_init_ssa_scalar(ins, sm6); } @@ -4902,7 +4922,7 @@ static void sm6_parser_emit_dx_cbuffer_load(struct sm6_parser *sm6, enum dx_intr if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) return; - src_param_init_vector_from_reg(src_param, &buffer->u.handle.reg); + src_param_init_vector_from_handle(sm6, src_param, &buffer->u.handle); /* Differently from other descriptors, constant buffers require an * additional index, used to index within the constant buffer itself. */ src_param->reg.idx_count = 3; @@ -4986,7 +5006,6 @@ static void sm6_parser_emit_dx_create_handle(struct sm6_parser *sm6, enum dx_int struct vkd3d_shader_instruction *ins = state->ins; enum vkd3d_shader_descriptor_type type; const struct sm6_descriptor_info *d; - struct vkd3d_shader_register *reg; struct sm6_value *dst; unsigned int id; @@ -5003,13 +5022,8 @@ static void sm6_parser_emit_dx_create_handle(struct sm6_parser *sm6, enum dx_int dst = sm6_parser_get_current_value(sm6); dst->value_type = VALUE_TYPE_HANDLE; dst->u.handle.d = d; - - reg = &dst->u.handle.reg; - vsir_register_init(reg, d->reg_type, d->reg_data_type, 2); - reg->dimension = VSIR_DIMENSION_VEC4; - reg->idx[0].offset = id; - register_index_address_init(®->idx[1], operands[2], sm6); - reg->non_uniform = !!sm6_value_get_constant_uint(operands[3]); + dst->u.handle.index = operands[2]; + dst->u.handle.non_uniform = !!sm6_value_get_constant_uint(operands[3]); /* NOP is used to flag no instruction emitted. */ ins->opcode = VKD3DSIH_NOP; @@ -5284,7 +5298,7 @@ static void sm6_parser_emit_dx_get_dimensions(struct sm6_parser *sm6, enum dx_in if (!(src_params = instruction_src_params_alloc(ins, 1 + is_texture, sm6))) return; - src_param_init_vector_from_reg(&src_params[is_texture], &resource->u.handle.reg); + src_param_init_vector_from_handle(sm6, &src_params[is_texture], &resource->u.handle); if (is_texture) { @@ -5304,7 +5318,7 @@ static void sm6_parser_emit_dx_get_dimensions(struct sm6_parser *sm6, enum dx_in if (!(src_params = instruction_src_params_alloc(ins, 1, sm6))) return; - src_param_init_vector_from_reg(&src_params[0], &resource->u.handle.reg); + src_param_init_vector_from_handle(sm6, &src_params[0], &resource->u.handle); src_params[0].swizzle = VKD3D_SHADER_SWIZZLE(X, X, X, X); if (!instruction_dst_param_init_temp_vector(ins, sm6)) @@ -5546,7 +5560,7 @@ static void sm6_parser_emit_dx_raw_buffer_load(struct sm6_parser *sm6, enum dx_i if (!(src_params = instruction_src_params_alloc(ins, operand_count, sm6))) return; src_params_init_from_operands(src_params, &operands[1], operand_count - 1); - src_param_init_vector_from_reg(&src_params[operand_count - 1], &resource->u.handle.reg); + src_param_init_vector_from_handle(sm6, &src_params[operand_count - 1], &resource->u.handle); instruction_dst_param_init_ssa_vector(ins, component_count, sm6); } @@ -5617,7 +5631,7 @@ static void sm6_parser_emit_dx_raw_buffer_store(struct sm6_parser *sm6, enum dx_ dst_param = instruction_dst_params_alloc(ins, 1, sm6); dst_param_init_with_mask(dst_param, write_mask); - dst_param->reg = resource->u.handle.reg; + sm6_register_from_handle(sm6, &resource->u.handle, &dst_param->reg); dst_param->reg.alignment = alignment; } @@ -5658,7 +5672,7 @@ static void sm6_parser_emit_dx_buffer_load(struct sm6_parser *sm6, enum dx_intri vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_OPERANDS, "Ignoring structure offset for a typed buffer load."); } - src_param_init_vector_from_reg(&src_params[1], &resource->u.handle.reg); + src_param_init_vector_from_handle(sm6, &src_params[1], &resource->u.handle); instruction_dst_param_init_ssa_vector(ins, VKD3D_VEC4_SIZE, sm6); } @@ -5727,7 +5741,7 @@ static void sm6_parser_emit_dx_buffer_store(struct sm6_parser *sm6, enum dx_intr dst_param = instruction_dst_params_alloc(ins, 1, sm6); dst_param_init_with_mask(dst_param, write_mask); - dst_param->reg = resource->u.handle.reg; + sm6_register_from_handle(sm6, &resource->u.handle, &dst_param->reg); } static void sm6_parser_emit_dx_get_sample_count(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, @@ -5769,7 +5783,7 @@ static void sm6_parser_emit_dx_get_sample_pos(struct sm6_parser *sm6, enum dx_in return; if (op == DX_TEX2DMS_GET_SAMPLE_POS) { - src_param_init_vector_from_reg(&src_params[0], &resource->u.handle.reg); + src_param_init_vector_from_handle(sm6, &src_params[0], &resource->u.handle); src_param_init_from_value(&src_params[1], operands[1]); } else @@ -5873,8 +5887,8 @@ static void sm6_parser_emit_dx_sample(struct sm6_parser *sm6, enum dx_intrinsic_ } src_param_init_vector_from_reg(&src_params[0], &coord); - src_param_init_vector_from_reg(&src_params[1], &resource->u.handle.reg); - src_param_init_vector_from_reg(&src_params[2], &sampler->u.handle.reg); + src_param_init_vector_from_handle(sm6, &src_params[1], &resource->u.handle); + src_param_init_vector_from_handle(sm6, &src_params[2], &sampler->u.handle); instruction_set_texel_offset(ins, &operands[6], sm6); instruction_dst_param_init_ssa_vector(ins, component_count, sm6); @@ -6071,8 +6085,8 @@ static void sm6_parser_emit_dx_texture_gather(struct sm6_parser *sm6, enum dx_in src_param_init_vector_from_reg(&src_params[1], &offset); else instruction_set_texel_offset(ins, &operands[6], sm6); - src_param_init_vector_from_reg(&src_params[1 + extended_offset], &resource->u.handle.reg); - src_param_init_vector_from_reg(&src_params[2 + extended_offset], &sampler->u.handle.reg); + src_param_init_vector_from_handle(sm6, &src_params[1 + extended_offset], &resource->u.handle); + src_param_init_vector_from_handle(sm6, &src_params[2 + extended_offset], &sampler->u.handle); /* Swizzle stored in the sampler parameter is the scalar component index to be gathered. */ swizzle = sm6_value_get_constant_uint(operands[8]); if (swizzle >= VKD3D_VEC4_SIZE) @@ -6124,7 +6138,7 @@ static void sm6_parser_emit_dx_texture_load(struct sm6_parser *sm6, enum dx_intr if (!(src_params = instruction_src_params_alloc(ins, 2 + is_multisample, sm6))) return; src_param_init_vector_from_reg(&src_params[0], &coord); - src_param_init_vector_from_reg(&src_params[1], &resource->u.handle.reg); + src_param_init_vector_from_handle(sm6, &src_params[1], &resource->u.handle); if (is_multisample) src_param_init_from_value(&src_params[2], mip_level_or_sample_count); @@ -6177,7 +6191,7 @@ static void sm6_parser_emit_dx_texture_store(struct sm6_parser *sm6, enum dx_int src_param_init_vector_from_reg(&src_params[1], &texel); dst_param = instruction_dst_params_alloc(ins, 1, sm6); - dst_param->reg = resource->u.handle.reg; + sm6_register_from_handle(sm6, &resource->u.handle, &dst_param->reg); dst_param_init_with_mask(dst_param, write_mask); } diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c index 8dff48ee83e..bc14885af2b 100644 --- a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c @@ -9263,10 +9263,10 @@ static void sm1_generate_vsir_instr_jump(struct hlsl_ctx *ctx, if (jump->type == HLSL_IR_JUMP_DISCARD_NEG) { - if (!(ins = generate_vsir_add_program_instruction(ctx, program, &instr->loc, VKD3DSIH_TEXKILL, 1, 0))) + if (!(ins = generate_vsir_add_program_instruction(ctx, program, &instr->loc, VKD3DSIH_TEXKILL, 0, 1))) return; - vsir_dst_from_hlsl_node(&ins->dst[0], ctx, condition); + vsir_src_from_hlsl_node(&ins->src[0], ctx, condition, VKD3DSP_WRITEMASK_ALL); } else { diff --git a/libs/vkd3d/libs/vkd3d-shader/ir.c b/libs/vkd3d/libs/vkd3d-shader/ir.c index b8f83946294..4101e92e91f 100644 --- a/libs/vkd3d/libs/vkd3d-shader/ir.c +++ b/libs/vkd3d/libs/vkd3d-shader/ir.c @@ -622,7 +622,7 @@ static enum vkd3d_result vsir_program_lower_texkill(struct vsir_program *program if (*tmp_idx == ~0u) *tmp_idx = program->temp_count++; - /* tmp = ins->dst[0] < 0 */ + /* tmp = ins->src[0] < 0 */ ins = &instructions->elements[pos + 1]; if (!vsir_instruction_init_with_params(program, ins, &texkill->location, VKD3DSIH_LTO, 1, 2)) @@ -633,7 +633,7 @@ static enum vkd3d_result vsir_program_lower_texkill(struct vsir_program *program ins->dst[0].reg.idx[0].offset = *tmp_idx; ins->dst[0].write_mask = VKD3DSP_WRITEMASK_ALL; - ins->src[0].reg = texkill->dst[0].reg; + ins->src[0].reg = texkill->src[0].reg; ins->src[0].swizzle = VKD3D_SHADER_NO_SWIZZLE; vsir_register_init(&ins->src[1].reg, VKD3DSPR_IMMCONST, VKD3D_DATA_FLOAT, 0); ins->src[1].reg.dimension = VSIR_DIMENSION_VEC4; diff --git a/libs/vkd3d/libs/vkd3d-shader/msl.c b/libs/vkd3d/libs/vkd3d-shader/msl.c index def6f459f69..4f37468af86 100644 --- a/libs/vkd3d/libs/vkd3d-shader/msl.c +++ b/libs/vkd3d/libs/vkd3d-shader/msl.c @@ -18,6 +18,13 @@ #include "vkd3d_shader_private.h" +enum msl_data_type +{ + MSL_DATA_FLOAT, + MSL_DATA_UINT, + MSL_DATA_UNION, +}; + struct msl_src { struct vkd3d_string_buffer *str; @@ -267,15 +274,14 @@ static void msl_print_srv_name(struct vkd3d_string_buffer *buffer, struct msl_ge vkd3d_string_buffer_printf(buffer, ">>()"); } -static void msl_print_register_name(struct vkd3d_string_buffer *buffer, +static enum msl_data_type msl_print_register_name(struct vkd3d_string_buffer *buffer, struct msl_generator *gen, const struct vkd3d_shader_register *reg) { switch (reg->type) { case VKD3DSPR_TEMP: vkd3d_string_buffer_printf(buffer, "r[%u]", reg->idx[0].offset); - msl_print_register_datatype(buffer, gen, reg->data_type); - break; + return MSL_DATA_UNION; case VKD3DSPR_INPUT: if (reg->idx_count != 1) @@ -283,18 +289,17 @@ static void msl_print_register_name(struct vkd3d_string_buffer *buffer, msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, "Internal compiler error: Unhandled input register index count %u.", reg->idx_count); vkd3d_string_buffer_printf(buffer, "", reg->type); - break; + return MSL_DATA_UNION; } if (reg->idx[0].rel_addr) { msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, "Internal compiler error: Unhandled input register indirect addressing."); vkd3d_string_buffer_printf(buffer, "", reg->type); - break; + return MSL_DATA_UNION; } vkd3d_string_buffer_printf(buffer, "v[%u]", reg->idx[0].offset); - msl_print_register_datatype(buffer, gen, reg->data_type); - break; + return MSL_DATA_UNION; case VKD3DSPR_OUTPUT: if (reg->idx_count != 1) @@ -302,18 +307,17 @@ static void msl_print_register_name(struct vkd3d_string_buffer *buffer, msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, "Internal compiler error: Unhandled output register index count %u.", reg->idx_count); vkd3d_string_buffer_printf(buffer, "", reg->type); - break; + return MSL_DATA_UNION; } if (reg->idx[0].rel_addr) { msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, "Internal compiler error: Unhandled output register indirect addressing."); vkd3d_string_buffer_printf(buffer, "", reg->type); - break; + return MSL_DATA_UNION; } vkd3d_string_buffer_printf(buffer, "o[%u]", reg->idx[0].offset); - msl_print_register_datatype(buffer, gen, reg->data_type); - break; + return MSL_DATA_UNION; case VKD3DSPR_DEPTHOUT: if (gen->program->shader_version.type != VKD3D_SHADER_TYPE_PIXEL) @@ -321,64 +325,27 @@ static void msl_print_register_name(struct vkd3d_string_buffer *buffer, "Internal compiler error: Unhandled depth output in shader type #%x.", gen->program->shader_version.type); vkd3d_string_buffer_printf(buffer, "o_depth"); - break; + return MSL_DATA_FLOAT; case VKD3DSPR_IMMCONST: switch (reg->dimension) { case VSIR_DIMENSION_SCALAR: - switch (reg->data_type) - { - case VKD3D_DATA_INT: - vkd3d_string_buffer_printf(buffer, "as_type(%#xu)", reg->u.immconst_u32[0]); - break; - case VKD3D_DATA_UINT: - vkd3d_string_buffer_printf(buffer, "%#xu", reg->u.immconst_u32[0]); - break; - case VKD3D_DATA_FLOAT: - vkd3d_string_buffer_printf(buffer, "as_type(%#xu)", reg->u.immconst_u32[0]); - break; - default: - msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, - "Internal compiler error: Unhandled immconst datatype %#x.", reg->data_type); - vkd3d_string_buffer_printf(buffer, "", reg->data_type); - break; - } - break; + vkd3d_string_buffer_printf(buffer, "%#xu", reg->u.immconst_u32[0]); + return MSL_DATA_UINT; case VSIR_DIMENSION_VEC4: - switch (reg->data_type) - { - case VKD3D_DATA_INT: - vkd3d_string_buffer_printf(buffer, "as_type(uint4(%#xu, %#xu, %#xu, %#xu))", - reg->u.immconst_u32[0], reg->u.immconst_u32[1], - reg->u.immconst_u32[2], reg->u.immconst_u32[3]); - break; - case VKD3D_DATA_UINT: - vkd3d_string_buffer_printf(buffer, "uint4(%#xu, %#xu, %#xu, %#xu)", - reg->u.immconst_u32[0], reg->u.immconst_u32[1], - reg->u.immconst_u32[2], reg->u.immconst_u32[3]); - break; - case VKD3D_DATA_FLOAT: - vkd3d_string_buffer_printf(buffer, "as_type(uint4(%#xu, %#xu, %#xu, %#xu))", - reg->u.immconst_u32[0], reg->u.immconst_u32[1], - reg->u.immconst_u32[2], reg->u.immconst_u32[3]); - break; - default: - msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, - "Internal compiler error: Unhandled immconst datatype %#x.", reg->data_type); - vkd3d_string_buffer_printf(buffer, "", reg->data_type); - break; - } - break; + vkd3d_string_buffer_printf(buffer, "uint4(%#xu, %#xu, %#xu, %#xu)", + reg->u.immconst_u32[0], reg->u.immconst_u32[1], + reg->u.immconst_u32[2], reg->u.immconst_u32[3]); + return MSL_DATA_UINT; default: vkd3d_string_buffer_printf(buffer, "", reg->dimension); msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, "Internal compiler error: Unhandled dimension %#x.", reg->dimension); - break; + return MSL_DATA_UINT; } - break; case VKD3DSPR_CONSTBUFFER: { @@ -390,33 +357,32 @@ static void msl_print_register_name(struct vkd3d_string_buffer *buffer, "Internal compiler error: Unhandled constant buffer register index count %u.", reg->idx_count); vkd3d_string_buffer_printf(buffer, "", reg->type); - break; + return MSL_DATA_UNION; } if (reg->idx[0].rel_addr || reg->idx[1].rel_addr || reg->idx[2].rel_addr) { msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, "Internal compiler error: Unhandled constant buffer register indirect addressing."); vkd3d_string_buffer_printf(buffer, "", reg->type); - break; + return MSL_DATA_UNION; } if (!(binding = msl_get_cbv_binding(gen, 0, reg->idx[1].offset))) { msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_BINDING_NOT_FOUND, "Cannot finding binding for CBV register %u.", reg->idx[0].offset); vkd3d_string_buffer_printf(buffer, "", reg->type); - break; + return MSL_DATA_UNION; } msl_print_cbv_name(buffer, binding->binding); vkd3d_string_buffer_printf(buffer, "[%u]", reg->idx[2].offset); - msl_print_register_datatype(buffer, gen, reg->data_type); - break; + return MSL_DATA_UNION; } default: msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, "Internal compiler error: Unhandled register type %#x.", reg->type); vkd3d_string_buffer_printf(buffer, "", reg->type); - break; + return MSL_DATA_UINT; } } @@ -451,24 +417,64 @@ static void msl_src_cleanup(struct msl_src *src, struct vkd3d_string_buffer_cach vkd3d_string_buffer_release(cache, src->str); } -static void msl_src_init(struct msl_src *msl_src, struct msl_generator *gen, - const struct vkd3d_shader_src_param *vsir_src, uint32_t mask) +static void msl_print_bitcast(struct vkd3d_string_buffer *dst, struct msl_generator *gen, const char *src, + enum vkd3d_data_type dst_data_type, enum msl_data_type src_data_type, enum vsir_dimension dimension) +{ + bool write_cast = false; + + if (dst_data_type == VKD3D_DATA_UNORM || dst_data_type == VKD3D_DATA_SNORM) + dst_data_type = VKD3D_DATA_FLOAT; + + switch (src_data_type) + { + case MSL_DATA_FLOAT: + write_cast = dst_data_type != VKD3D_DATA_FLOAT; + break; + + case MSL_DATA_UINT: + write_cast = dst_data_type != VKD3D_DATA_UINT; + break; + + case MSL_DATA_UNION: + break; + } + + if (write_cast) + { + vkd3d_string_buffer_printf(dst, "as_type<"); + msl_print_resource_datatype(gen, dst, dst_data_type); + vkd3d_string_buffer_printf(dst, "%s>(", dimension == VSIR_DIMENSION_VEC4 ? "4" : ""); + } + + vkd3d_string_buffer_printf(dst, "%s", src); + + if (write_cast) + vkd3d_string_buffer_printf(dst, ")"); + + if (src_data_type == MSL_DATA_UNION) + msl_print_register_datatype(dst, gen, dst_data_type); +} + +static void msl_print_src_with_type(struct vkd3d_string_buffer *buffer, struct msl_generator *gen, + const struct vkd3d_shader_src_param *vsir_src, uint32_t mask, enum vkd3d_data_type data_type) { const struct vkd3d_shader_register *reg = &vsir_src->reg; - struct vkd3d_string_buffer *str; + struct vkd3d_string_buffer *register_name, *str; + enum msl_data_type src_data_type; - msl_src->str = vkd3d_string_buffer_get(&gen->string_buffers); + register_name = vkd3d_string_buffer_get(&gen->string_buffers); if (reg->non_uniform) msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, "Internal compiler error: Unhandled 'non-uniform' modifier."); if (!vsir_src->modifiers) - str = msl_src->str; + str = buffer; else str = vkd3d_string_buffer_get(&gen->string_buffers); - msl_print_register_name(str, gen, reg); + src_data_type = msl_print_register_name(register_name, gen, reg); + msl_print_bitcast(str, gen, register_name->buffer, data_type, src_data_type, reg->dimension); if (reg->dimension == VSIR_DIMENSION_VEC4) msl_print_swizzle(str, vsir_src->swizzle, mask); @@ -477,23 +483,30 @@ static void msl_src_init(struct msl_src *msl_src, struct msl_generator *gen, case VKD3DSPSM_NONE: break; case VKD3DSPSM_NEG: - vkd3d_string_buffer_printf(msl_src->str, "-%s", str->buffer); + vkd3d_string_buffer_printf(buffer, "-%s", str->buffer); break; case VKD3DSPSM_ABS: - vkd3d_string_buffer_printf(msl_src->str, "abs(%s)", str->buffer); + vkd3d_string_buffer_printf(buffer, "abs(%s)", str->buffer); break; default: - vkd3d_string_buffer_printf(msl_src->str, "(%s)", + vkd3d_string_buffer_printf(buffer, "(%s)", vsir_src->modifiers, str->buffer); msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, "Internal compiler error: Unhandled source modifier(s) %#x.", vsir_src->modifiers); break; } - if (str != msl_src->str) + if (str != buffer) vkd3d_string_buffer_release(&gen->string_buffers, str); } +static void msl_src_init(struct msl_src *msl_src, struct msl_generator *gen, + const struct vkd3d_shader_src_param *vsir_src, uint32_t mask) +{ + msl_src->str = vkd3d_string_buffer_get(&gen->string_buffers); + msl_print_src_with_type(msl_src->str, gen, vsir_src, mask, vsir_src->reg.data_type); +} + static void msl_dst_cleanup(struct msl_dst *dst, struct vkd3d_string_buffer_cache *cache) { vkd3d_string_buffer_release(cache, dst->mask); @@ -504,6 +517,7 @@ static uint32_t msl_dst_init(struct msl_dst *msl_dst, struct msl_generator *gen, const struct vkd3d_shader_instruction *ins, const struct vkd3d_shader_dst_param *vsir_dst) { uint32_t write_mask = vsir_dst->write_mask; + enum msl_data_type dst_data_type; if (ins->flags & VKD3DSI_PRECISE_XYZW) msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, @@ -516,7 +530,9 @@ static uint32_t msl_dst_init(struct msl_dst *msl_dst, struct msl_generator *gen, msl_dst->register_name = vkd3d_string_buffer_get(&gen->string_buffers); msl_dst->mask = vkd3d_string_buffer_get(&gen->string_buffers); - msl_print_register_name(msl_dst->register_name, gen, &vsir_dst->reg); + dst_data_type = msl_print_register_name(msl_dst->register_name, gen, &vsir_dst->reg); + if (dst_data_type == MSL_DATA_UNION) + msl_print_register_datatype(msl_dst->mask, gen, vsir_dst->reg.data_type); if (vsir_dst->reg.dimension == VSIR_DIMENSION_VEC4) msl_print_write_mask(msl_dst->mask, write_mask); @@ -710,7 +726,6 @@ static void msl_ld(struct msl_generator *gen, const struct vkd3d_shader_instruct 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; enum vkd3d_data_type data_type; uint32_t coord_mask; @@ -762,34 +777,28 @@ static void msl_ld(struct msl_generator *gen, const struct vkd3d_shader_instruct } 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, 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); + msl_print_src_with_type(read, gen, &ins->src[0], coord_mask, VKD3D_DATA_UINT); if (resource_type_info->array) - vkd3d_string_buffer_printf(read, ", as_type(%s)", array_index.str->buffer); + { + vkd3d_string_buffer_printf(read, ", "); + msl_print_src_with_type(read, gen, &ins->src[0], coord_mask + 1, VKD3D_DATA_UINT); + } if (resource_type_info->lod) - vkd3d_string_buffer_printf(read, ", as_type(%s)", lod.str->buffer); + { + vkd3d_string_buffer_printf(read, ", "); + msl_print_src_with_type(read, gen, &ins->src[0], VKD3DSP_WRITEMASK_3, VKD3D_DATA_UINT); + } 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); } -- 2.47.2