diff --git a/libs/vkd3d-shader/d3dbc.c b/libs/vkd3d-shader/d3dbc.c index b69b70c6..f9cb0d18 100644 --- a/libs/vkd3d-shader/d3dbc.c +++ b/libs/vkd3d-shader/d3dbc.c @@ -2162,6 +2162,7 @@ static void d3dbc_write_vsir_simple_instruction(struct d3dbc_compiler *d3dbc, return; instr.opcode = info->sm1_opcode; + instr.flags = ins->flags; instr.has_dst = info->dst_count; instr.src_count = info->src_count; @@ -2195,7 +2196,10 @@ static void d3dbc_write_vsir_instruction(struct d3dbc_compiler *d3dbc, const str case VKD3DSIH_DP4: case VKD3DSIH_DSX: case VKD3DSIH_DSY: + case VKD3DSIH_ELSE: + case VKD3DSIH_ENDIF: case VKD3DSIH_FRC: + case VKD3DSIH_IFC: case VKD3DSIH_MAD: case VKD3DSIH_MAX: case VKD3DSIH_MIN: @@ -2299,48 +2303,6 @@ static void d3dbc_write_semantic_dcls(struct d3dbc_compiler *d3dbc) } } -static void d3dbc_write_block(struct d3dbc_compiler *d3dbc, const struct hlsl_block *block); - -static void d3dbc_write_if(struct d3dbc_compiler *d3dbc, const struct hlsl_ir_node *instr) -{ - const struct hlsl_ir_if *iff = hlsl_ir_if(instr); - const struct hlsl_ir_node *condition; - struct sm1_instruction sm1_ifc, sm1_else, sm1_endif; - - condition = iff->condition.node; - VKD3D_ASSERT(condition->data_type->dimx == 1 && condition->data_type->dimy == 1); - - sm1_ifc = (struct sm1_instruction) - { - .opcode = VKD3D_SM1_OP_IFC, - .flags = VKD3D_SHADER_REL_OP_NE, /* Make it a "if_ne" instruction. */ - - .srcs[0].type = VKD3DSPR_TEMP, - .srcs[0].swizzle = hlsl_swizzle_from_writemask(condition->reg.writemask), - .srcs[0].reg = condition->reg.id, - .srcs[0].mod = 0, - - .srcs[1].type = VKD3DSPR_TEMP, - .srcs[1].swizzle = hlsl_swizzle_from_writemask(condition->reg.writemask), - .srcs[1].reg = condition->reg.id, - .srcs[1].mod = VKD3DSPSM_NEG, - - .src_count = 2, - }; - d3dbc_write_instruction(d3dbc, &sm1_ifc); - d3dbc_write_block(d3dbc, &iff->then_block); - - if (!list_empty(&iff->else_block.instrs)) - { - sm1_else = (struct sm1_instruction){.opcode = VKD3D_SM1_OP_ELSE}; - d3dbc_write_instruction(d3dbc, &sm1_else); - d3dbc_write_block(d3dbc, &iff->else_block); - } - - sm1_endif = (struct sm1_instruction){.opcode = VKD3D_SM1_OP_ENDIF}; - d3dbc_write_instruction(d3dbc, &sm1_endif); -} - static void d3dbc_write_block(struct d3dbc_compiler *d3dbc, const struct hlsl_block *block) { struct vkd3d_shader_instruction *vsir_instr; @@ -2364,13 +2326,6 @@ static void d3dbc_write_block(struct d3dbc_compiler *d3dbc, const struct hlsl_bl case HLSL_IR_CALL: vkd3d_unreachable(); - case HLSL_IR_IF: - if (hlsl_version_ge(ctx, 2, 1)) - d3dbc_write_if(d3dbc, instr); - else - hlsl_fixme(ctx, &instr->loc, "Flatten \"if\" conditionals branches."); - break; - case HLSL_IR_VSIR_INSTRUCTION_REF: vsir_instr_idx = hlsl_ir_vsir_instruction_ref(instr)->vsir_instr_idx; vsir_instr = &d3dbc->program->instructions.elements[vsir_instr_idx]; diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c index 93f19360..d8485bae 100644 --- a/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d-shader/hlsl_codegen.c @@ -7241,44 +7241,127 @@ static void sm1_generate_vsir_instr_jump(struct hlsl_ctx *ctx, } } -static bool sm1_generate_vsir_instr(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context) +static void sm1_generate_vsir_block(struct hlsl_ctx *ctx, struct hlsl_block *block, struct vsir_program *program); + +static void sm1_generate_vsir_instr_if(struct hlsl_ctx *ctx, struct vsir_program *program, struct hlsl_ir_if *iff) { - struct vsir_program *program = context; + struct hlsl_ir_node *condition = iff->condition.node; + struct vkd3d_shader_src_param *src_param; + struct hlsl_ir_node *instr = &iff->node; + struct vkd3d_shader_instruction *ins; + struct hlsl_ir_node *vsir_instr; + struct hlsl_block block; + uint32_t swizzle; - switch (instr->type) + if (hlsl_version_lt(ctx, 2, 1)) { - case HLSL_IR_CONSTANT: - sm1_generate_vsir_instr_constant(ctx, program, hlsl_ir_constant(instr)); - return true; - - case HLSL_IR_EXPR: - return sm1_generate_vsir_instr_expr(ctx, program, hlsl_ir_expr(instr)); - - case HLSL_IR_JUMP: - sm1_generate_vsir_instr_jump(ctx, program, hlsl_ir_jump(instr)); - return true; - - case HLSL_IR_LOAD: - sm1_generate_vsir_instr_load(ctx, program, hlsl_ir_load(instr)); - return true; - - case HLSL_IR_RESOURCE_LOAD: - sm1_generate_vsir_instr_resource_load(ctx, program, hlsl_ir_resource_load(instr)); - return true; - - case HLSL_IR_STORE: - sm1_generate_vsir_instr_store(ctx, program, hlsl_ir_store(instr)); - return true; - - case HLSL_IR_SWIZZLE: - sm1_generate_vsir_instr_swizzle(ctx, program, hlsl_ir_swizzle(instr)); - return true; - - default: - break; + hlsl_fixme(ctx, &instr->loc, "Flatten \"if\" conditionals branches."); + return; } + VKD3D_ASSERT(condition->data_type->dimx == 1 && condition->data_type->dimy == 1); - return false; + hlsl_block_init(&block); + + if (!(ins = generate_vsir_add_program_instruction(ctx, program, &instr->loc, VKD3DSIH_IFC, 0, 2))) + return; + ins->flags = VKD3D_SHADER_REL_OP_NE; + + swizzle = hlsl_swizzle_from_writemask(condition->reg.writemask); + swizzle = vsir_swizzle_from_hlsl(swizzle); + + src_param = &ins->src[0]; + vsir_register_init(&src_param->reg, VKD3DSPR_TEMP, VKD3D_DATA_FLOAT, 1); + src_param->reg.idx[0].offset = condition->reg.id; + src_param->swizzle = swizzle; + src_param->modifiers = 0; + + src_param = &ins->src[1]; + vsir_register_init(&src_param->reg, VKD3DSPR_TEMP, VKD3D_DATA_FLOAT, 1); + src_param->reg.idx[0].offset = condition->reg.id; + src_param->swizzle = swizzle; + src_param->modifiers = VKD3DSPSM_NEG; + + if (!(vsir_instr = hlsl_new_vsir_instruction_ref(ctx, program->instructions.count - 1, NULL, NULL, &instr->loc))) + { + ctx->result = VKD3D_ERROR_OUT_OF_MEMORY; + return; + } + hlsl_block_add_instr(&block, vsir_instr); + + sm1_generate_vsir_block(ctx, &iff->then_block, program); + hlsl_block_add_block(&block, &iff->then_block); + + if (!(ins = generate_vsir_add_program_instruction(ctx, program, &instr->loc, VKD3DSIH_ELSE, 0, 0))) + return; + if (!(vsir_instr = hlsl_new_vsir_instruction_ref(ctx, program->instructions.count - 1, NULL, NULL, &instr->loc))) + { + ctx->result = VKD3D_ERROR_OUT_OF_MEMORY; + return; + } + hlsl_block_add_instr(&block, vsir_instr); + + sm1_generate_vsir_block(ctx, &iff->else_block, program); + hlsl_block_add_block(&block, &iff->else_block); + + if (!(ins = generate_vsir_add_program_instruction(ctx, program, &instr->loc, VKD3DSIH_ENDIF, 0, 0))) + return; + if (!(vsir_instr = hlsl_new_vsir_instruction_ref(ctx, program->instructions.count - 1, NULL, NULL, &instr->loc))) + { + ctx->result = VKD3D_ERROR_OUT_OF_MEMORY; + return; + } + hlsl_block_add_instr(&block, vsir_instr); + + list_move_after(&instr->entry, &block.instrs); + hlsl_block_cleanup(&block); + list_remove(&instr->entry); + hlsl_free_instr(instr); +} + +static void sm1_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) + { + switch (instr->type) + { + case HLSL_IR_CONSTANT: + sm1_generate_vsir_instr_constant(ctx, program, hlsl_ir_constant(instr)); + break; + + case HLSL_IR_EXPR: + sm1_generate_vsir_instr_expr(ctx, program, hlsl_ir_expr(instr)); + break; + + case HLSL_IR_IF: + sm1_generate_vsir_instr_if(ctx, program, hlsl_ir_if(instr)); + break; + + case HLSL_IR_JUMP: + sm1_generate_vsir_instr_jump(ctx, program, hlsl_ir_jump(instr)); + break; + + case HLSL_IR_LOAD: + sm1_generate_vsir_instr_load(ctx, program, hlsl_ir_load(instr)); + break; + + case HLSL_IR_RESOURCE_LOAD: + sm1_generate_vsir_instr_resource_load(ctx, program, hlsl_ir_resource_load(instr)); + break; + + case HLSL_IR_STORE: + sm1_generate_vsir_instr_store(ctx, program, hlsl_ir_store(instr)); + break; + + case HLSL_IR_SWIZZLE: + sm1_generate_vsir_instr_swizzle(ctx, program, hlsl_ir_swizzle(instr)); + break; + + default: + break; + } + } } /* OBJECTIVE: Translate all the information from ctx and entry_func to the @@ -7317,7 +7400,7 @@ static void sm1_generate_vsir(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl sm1_generate_vsir_sampler_dcls(ctx, program, &block); list_move_head(&entry_func->body.instrs, &block.instrs); - hlsl_transform_ir(ctx, sm1_generate_vsir_instr, &entry_func->body, program); + sm1_generate_vsir_block(ctx, &entry_func->body, program); } static struct hlsl_ir_jump *loop_unrolling_find_jump(struct hlsl_block *block, struct hlsl_ir_node *stop_point,