From 6f52bb6b1aa3021e77ee205679a243767c026ec3 Mon Sep 17 00:00:00 2001 From: Francisco Casas Date: Fri, 25 Oct 2024 15:38:50 -0300 Subject: [PATCH] vkd3d-shader/hlsl: Store SM4 swizzles in the vsir program. --- libs/vkd3d-shader/hlsl_codegen.c | 104 +++++++++++++++++++++-- libs/vkd3d-shader/tpf.c | 89 +++++++++++++++++-- libs/vkd3d-shader/vkd3d_shader_private.h | 2 + 3 files changed, 181 insertions(+), 14 deletions(-) diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c index ce431ee6..6fab8349 100644 --- a/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d-shader/hlsl_codegen.c @@ -6579,6 +6579,42 @@ static void generate_vsir_signature(struct hlsl_ctx *ctx, } } +static enum vkd3d_data_type vsir_data_type_from_hlsl_type(struct hlsl_ctx *ctx, const struct hlsl_type *type) +{ + if (hlsl_version_lt(ctx, 4, 0)) + return VKD3D_DATA_FLOAT; + + if (type->class == HLSL_CLASS_ARRAY) + return vsir_data_type_from_hlsl_type(ctx, type->e.array.type); + if (type->class == HLSL_CLASS_STRUCT) + return VKD3D_DATA_MIXED; + if (type->class <= HLSL_CLASS_LAST_NUMERIC) + { + switch (type->e.numeric.type) + { + case HLSL_TYPE_DOUBLE: + return VKD3D_DATA_DOUBLE; + case HLSL_TYPE_FLOAT: + return VKD3D_DATA_FLOAT; + case HLSL_TYPE_HALF: + return VKD3D_DATA_HALF; + case HLSL_TYPE_INT: + return VKD3D_DATA_INT; + case HLSL_TYPE_UINT: + case HLSL_TYPE_BOOL: + return VKD3D_DATA_UINT; + } + } + + vkd3d_unreachable(); +} + +static enum vkd3d_data_type vsir_data_type_from_hlsl_instruction(struct hlsl_ctx *ctx, + const struct hlsl_ir_node *instr) +{ + return vsir_data_type_from_hlsl_type(ctx, instr->data_type); +} + static uint32_t sm1_generate_vsir_get_src_swizzle(uint32_t src_writemask, uint32_t dst_writemask) { uint32_t swizzle; @@ -7327,8 +7363,8 @@ static void sm1_generate_vsir_instr_resource_load(struct hlsl_ctx *ctx, } } -static void sm1_generate_vsir_instr_swizzle(struct hlsl_ctx *ctx, struct vsir_program *program, - struct hlsl_ir_swizzle *swizzle_instr) +static void generate_vsir_instr_swizzle(struct hlsl_ctx *ctx, + struct vsir_program *program, struct hlsl_ir_swizzle *swizzle_instr) { struct hlsl_ir_node *instr = &swizzle_instr->node, *val = swizzle_instr->val.node; struct vkd3d_shader_dst_param *dst_param; @@ -7342,8 +7378,9 @@ static void sm1_generate_vsir_instr_swizzle(struct hlsl_ctx *ctx, struct vsir_pr return; dst_param = &ins->dst[0]; - vsir_register_init(&dst_param->reg, VKD3DSPR_TEMP, VKD3D_DATA_FLOAT, 1); + vsir_register_init(&dst_param->reg, VKD3DSPR_TEMP, vsir_data_type_from_hlsl_instruction(ctx, instr), 1); dst_param->reg.idx[0].offset = instr->reg.id; + dst_param->reg.dimension = VSIR_DIMENSION_VEC4; dst_param->write_mask = instr->reg.writemask; swizzle = hlsl_swizzle_from_writemask(val->reg.writemask); @@ -7352,8 +7389,9 @@ static void sm1_generate_vsir_instr_swizzle(struct hlsl_ctx *ctx, struct vsir_pr swizzle = vsir_swizzle_from_hlsl(swizzle); src_param = &ins->src[0]; - vsir_register_init(&src_param->reg, VKD3DSPR_TEMP, VKD3D_DATA_FLOAT, 1); + vsir_register_init(&src_param->reg, VKD3DSPR_TEMP, vsir_data_type_from_hlsl_instruction(ctx, val), 1); src_param->reg.idx[0].offset = val->reg.id; + src_param->reg.dimension = VSIR_DIMENSION_VEC4; src_param->swizzle = swizzle; } @@ -7496,7 +7534,7 @@ static void sm1_generate_vsir_block(struct hlsl_ctx *ctx, struct hlsl_block *blo break; case HLSL_IR_SWIZZLE: - sm1_generate_vsir_instr_swizzle(ctx, program, hlsl_ir_swizzle(instr)); + generate_vsir_instr_swizzle(ctx, program, hlsl_ir_swizzle(instr)); break; default: @@ -7557,6 +7595,25 @@ static void add_last_vsir_instr_to_block(struct hlsl_ctx *ctx, struct vsir_progr hlsl_block_add_instr(block, vsir_instr); } +static void replace_instr_with_last_vsir_instr(struct hlsl_ctx *ctx, + struct vsir_program *program, struct hlsl_ir_node *instr) +{ + struct vkd3d_shader_location *loc; + struct hlsl_ir_node *vsir_instr; + + loc = &program->instructions.elements[program->instructions.count - 1].location; + + if (!(vsir_instr = hlsl_new_vsir_instruction_ref(ctx, + program->instructions.count - 1, instr->data_type, &instr->reg, loc))) + { + ctx->result = VKD3D_ERROR_OUT_OF_MEMORY; + return; + } + + list_add_before(&instr->entry, &vsir_instr->entry); + hlsl_replace_node(instr, vsir_instr); +} + static void sm4_generate_vsir_instr_dcl_temps(struct hlsl_ctx *ctx, struct vsir_program *program, uint32_t temp_count, struct hlsl_block *block, const struct vkd3d_shader_location *loc) { @@ -7589,6 +7646,41 @@ static void sm4_generate_vsir_instr_dcl_indexable_temp(struct hlsl_ctx *ctx, add_last_vsir_instr_to_block(ctx, program, block); } +static void sm4_generate_vsir_block(struct hlsl_ctx *ctx, struct hlsl_block *block, struct vsir_program *program) +{ + struct hlsl_ir_node *instr, *next; + + LIST_FOR_EACH_ENTRY_SAFE(instr, next, &block->instrs, struct hlsl_ir_node, entry) + { + if (instr->data_type) + { + if (instr->data_type->class != HLSL_CLASS_SCALAR && instr->data_type->class != HLSL_CLASS_VECTOR) + { + hlsl_fixme(ctx, &instr->loc, "Class %#x should have been lowered or removed.", instr->data_type->class); + break; + } + } + + switch (instr->type) + { + case HLSL_IR_CALL: + vkd3d_unreachable(); + + case HLSL_IR_CONSTANT: + /* In SM4 all constants are inlined. */ + break; + + case HLSL_IR_SWIZZLE: + generate_vsir_instr_swizzle(ctx, program, hlsl_ir_swizzle(instr)); + replace_instr_with_last_vsir_instr(ctx, program, instr); + break; + + default: + break; + } + } +} + static void sm4_generate_vsir_add_function(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *func, uint64_t config_flags, struct vsir_program *program) { @@ -7631,6 +7723,8 @@ static void sm4_generate_vsir_add_function(struct hlsl_ctx *ctx, list_move_head(&func->body.instrs, &block.instrs); hlsl_block_cleanup(&block); + + sm4_generate_vsir_block(ctx, &func->body, program); } /* OBJECTIVE: Translate all the information from ctx and entry_func to the diff --git a/libs/vkd3d-shader/tpf.c b/libs/vkd3d-shader/tpf.c index e128d26a..8158f3ab 100644 --- a/libs/vkd3d-shader/tpf.c +++ b/libs/vkd3d-shader/tpf.c @@ -674,6 +674,7 @@ struct sm4_index_range_array struct vkd3d_sm4_lookup_tables { const struct vkd3d_sm4_opcode_info *opcode_info_from_sm4[VKD3D_SM4_OP_COUNT]; + const struct vkd3d_sm4_opcode_info *opcode_info_from_vsir[VKD3DSIH_COUNT]; const struct vkd3d_sm4_register_type_info *register_type_info_from_sm4[VKD3D_SM4_REGISTER_TYPE_COUNT]; const struct vkd3d_sm4_register_type_info *register_type_info_from_vkd3d[VKD3DSPR_COUNT]; const struct vkd3d_sm4_stat_field_info *stat_field_from_sm4[VKD3D_SM4_OP_COUNT]; @@ -1412,6 +1413,8 @@ struct tpf_compiler struct vkd3d_sm4_lookup_tables lookup; struct sm4_stat *stat; + int result; + struct vkd3d_bytecode_buffer *buffer; struct dxbc_writer dxbc; }; @@ -1903,6 +1906,7 @@ static void init_sm4_lookup_tables(struct vkd3d_sm4_lookup_tables *lookup) const struct vkd3d_sm4_opcode_info *info = &opcode_table[i]; lookup->opcode_info_from_sm4[info->opcode] = info; + lookup->opcode_info_from_vsir[info->handler_idx] = info; } for (i = 0; i < ARRAY_SIZE(register_type_table); ++i) @@ -1929,6 +1933,24 @@ static const struct vkd3d_sm4_opcode_info *get_info_from_sm4_opcode( return lookup->opcode_info_from_sm4[sm4_opcode]; } +static const struct vkd3d_sm4_opcode_info *get_info_from_vsir_opcode( + const struct vkd3d_sm4_lookup_tables *lookup, enum vkd3d_shader_opcode vsir_opcode) +{ + if (vsir_opcode >= VKD3DSIH_COUNT) + return NULL; + return lookup->opcode_info_from_vsir[vsir_opcode]; +} + +static unsigned int opcode_info_get_dst_count(const struct vkd3d_sm4_opcode_info *info) +{ + return strnlen(info->dst_info, SM4_MAX_DST_COUNT); +} + +static unsigned int opcode_info_get_src_count(const struct vkd3d_sm4_opcode_info *info) +{ + return strnlen(info->src_info, SM4_MAX_SRC_COUNT); +} + static const struct vkd3d_sm4_register_type_info *get_info_from_sm4_register_type( const struct vkd3d_sm4_lookup_tables *lookup, enum vkd3d_sm4_register_type sm4_type) { @@ -2651,8 +2673,8 @@ static void shader_sm4_read_instruction(struct vkd3d_shader_sm4_parser *sm4, str ins->raw = false; ins->structured = false; ins->predicate = NULL; - ins->dst_count = strnlen(opcode_info->dst_info, SM4_MAX_DST_COUNT); - ins->src_count = strnlen(opcode_info->src_info, SM4_MAX_SRC_COUNT); + ins->dst_count = opcode_info_get_dst_count(opcode_info); + ins->src_count = opcode_info_get_src_count(opcode_info); ins->src = src_params = vsir_program_get_src_params(program, ins->src_count); if (!src_params && ins->src_count) { @@ -2971,7 +2993,7 @@ int tpf_parse(const struct vkd3d_shader_compile_info *compile_info, uint64_t con return VKD3D_OK; } -static void write_sm4_block(const struct tpf_compiler *tpf, const struct hlsl_block *block); +static void write_sm4_block(struct tpf_compiler *tpf, const struct hlsl_block *block); static bool type_is_integer(const struct hlsl_type *type) { @@ -6094,7 +6116,7 @@ static void write_sm4_expr(const struct tpf_compiler *tpf, const struct hlsl_ir_ hlsl_release_string_buffer(tpf->ctx, dst_type_string); } -static void write_sm4_if(const struct tpf_compiler *tpf, const struct hlsl_ir_if *iff) +static void write_sm4_if(struct tpf_compiler *tpf, const struct hlsl_ir_if *iff) { struct sm4_instruction instr = { @@ -6211,7 +6233,7 @@ static void write_sm4_load(const struct tpf_compiler *tpf, const struct hlsl_ir_ write_sm4_instruction(tpf, &instr); } -static void write_sm4_loop(const struct tpf_compiler *tpf, const struct hlsl_ir_loop *loop) +static void write_sm4_loop(struct tpf_compiler *tpf, const struct hlsl_ir_loop *loop) { struct sm4_instruction instr = { @@ -6395,7 +6417,7 @@ static void write_sm4_store(const struct tpf_compiler *tpf, const struct hlsl_ir write_sm4_instruction(tpf, &instr); } -static void write_sm4_switch(const struct tpf_compiler *tpf, const struct hlsl_ir_switch *s) +static void write_sm4_switch(struct tpf_compiler *tpf, const struct hlsl_ir_switch *s) { const struct hlsl_ir_node *selector = s->selector.node; struct hlsl_ir_switch_case *c; @@ -6456,7 +6478,46 @@ static void write_sm4_swizzle(const struct tpf_compiler *tpf, const struct hlsl_ write_sm4_instruction(tpf, &instr); } -static void tpf_handle_instruction(const struct tpf_compiler *tpf, const struct vkd3d_shader_instruction *ins) +static void tpf_simple_instruction(struct tpf_compiler *tpf, const struct vkd3d_shader_instruction *ins) +{ + const struct vkd3d_sm4_opcode_info *info; + struct sm4_instruction instr = {0}; + unsigned int dst_count, src_count; + + info = get_info_from_vsir_opcode(&tpf->lookup, ins->opcode); + VKD3D_ASSERT(info); + + dst_count = opcode_info_get_dst_count(info); + src_count = opcode_info_get_src_count(info); + + if (ins->dst_count != dst_count) + { + ERR("Invalid destination count %u for vsir instruction %#x (expected %u).\n", + ins->dst_count, ins->opcode, dst_count); + tpf->result = VKD3D_ERROR_INVALID_SHADER; + return; + } + if (ins->src_count != src_count) + { + ERR("Invalid source count %u for vsir instruction %#x (expected %u).\n", + ins->src_count, ins->opcode, src_count); + tpf->result = VKD3D_ERROR_INVALID_SHADER; + return; + } + + instr.opcode = info->opcode; + instr.dst_count = ins->dst_count; + instr.src_count = ins->src_count; + + for (unsigned int i = 0; i < ins->dst_count; ++i) + instr.dsts[i] = ins->dst[i]; + for (unsigned int i = 0; i < ins->src_count; ++i) + instr.srcs[i] = ins->src[i]; + + write_sm4_instruction(tpf, &instr); +} + +static void tpf_handle_instruction(struct tpf_compiler *tpf, const struct vkd3d_shader_instruction *ins) { switch (ins->opcode) { @@ -6468,13 +6529,17 @@ static void tpf_handle_instruction(const struct tpf_compiler *tpf, const struct tpf_dcl_indexable_temp(tpf, &ins->declaration.indexable_temp); break; + case VKD3DSIH_MOV: + tpf_simple_instruction(tpf, ins); + break; + default: vkd3d_unreachable(); break; } } -static void write_sm4_block(const struct tpf_compiler *tpf, const struct hlsl_block *block) +static void write_sm4_block(struct tpf_compiler *tpf, const struct hlsl_block *block) { const struct hlsl_ir_node *instr; unsigned int vsir_instr_idx; @@ -6766,7 +6831,13 @@ int tpf_compile(struct vsir_program *program, uint64_t config_flags, tpf_write_sfi0(&tpf); tpf_write_stat(&tpf); - if (!(ret = ctx->result)) + ret = VKD3D_OK; + if (ctx->result) + ret = ctx->result; + if (tpf.result) + ret = tpf.result; + + if (!ret) ret = dxbc_writer_write(&tpf.dxbc, out); for (i = 0; i < tpf.dxbc.section_count; ++i) vkd3d_shader_free_shader_code(&tpf.dxbc.sections[i].data); diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index a2afa0fe..07590b66 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -585,6 +585,8 @@ enum vkd3d_shader_opcode VKD3DSIH_XOR, VKD3DSIH_INVALID, + + VKD3DSIH_COUNT, }; enum vkd3d_shader_register_type