Hull Shaders contain two functions instead of just one, so all the algorithms that require computing a CFG need to be run twice. Here we refactor the code so that this can be done more easily.
This MR is relatively long, but it is essentially just moving code around, so hopefully it is not too difficult to review anyway.
From: Giovanni Mascellani gmascellani@codeweavers.com
--- libs/vkd3d-shader/ir.c | 76 +++++++++++++++++++----------------------- 1 file changed, 35 insertions(+), 41 deletions(-)
diff --git a/libs/vkd3d-shader/ir.c b/libs/vkd3d-shader/ir.c index 9d5b79047..3cbc83e54 100644 --- a/libs/vkd3d-shader/ir.c +++ b/libs/vkd3d-shader/ir.c @@ -4445,6 +4445,40 @@ fail: return ret; }
+static enum vkd3d_result vsir_program_structurize(struct vsir_program *program, + struct vkd3d_shader_message_context *message_context) +{ + enum vkd3d_result result; + struct vsir_cfg cfg; + + if ((result = vsir_cfg_init(&cfg, program, message_context)) < 0) + return result; + + vsir_cfg_compute_dominators(&cfg); + + if ((result = vsir_cfg_compute_loops(&cfg)) < 0) + goto out; + + if ((result = vsir_cfg_sort_nodes(&cfg)) < 0) + goto out; + + if ((result = vsir_cfg_generate_synthetic_loop_intervals(&cfg)) < 0) + goto out; + + if ((result = vsir_cfg_build_structured_program(&cfg)) < 0) + goto out; + + if ((result = vsir_cfg_optimize(&cfg)) < 0) + goto out; + + result = vsir_cfg_emit_structured_program(&cfg); + +out: + vsir_cfg_cleanup(&cfg); + + return result; +} + static void register_map_undominated_use(struct vkd3d_shader_register *reg, struct ssas_to_temps_alloc *alloc, struct vsir_block *block, struct vsir_block **origin_blocks) { @@ -5422,48 +5456,8 @@ enum vkd3d_result vsir_program_normalise(struct vsir_program *program, uint64_t if ((result = lower_switch_to_if_ladder(program)) < 0) return result;
- if ((result = vsir_cfg_init(&cfg, program, message_context)) < 0) - return result; - - vsir_cfg_compute_dominators(&cfg); - - if ((result = vsir_cfg_compute_loops(&cfg)) < 0) - { - vsir_cfg_cleanup(&cfg); - return result; - } - - if ((result = vsir_cfg_sort_nodes(&cfg)) < 0) - { - vsir_cfg_cleanup(&cfg); - return result; - } - - if ((result = vsir_cfg_generate_synthetic_loop_intervals(&cfg)) < 0) - { - vsir_cfg_cleanup(&cfg); - return result; - } - - if ((result = vsir_cfg_build_structured_program(&cfg)) < 0) - { - vsir_cfg_cleanup(&cfg); + if ((result = vsir_program_structurize(program, message_context)) < 0) return result; - } - - if ((result = vsir_cfg_optimize(&cfg)) < 0) - { - vsir_cfg_cleanup(&cfg); - return result; - } - - if ((result = vsir_cfg_emit_structured_program(&cfg)) < 0) - { - vsir_cfg_cleanup(&cfg); - return result; - } - - vsir_cfg_cleanup(&cfg);
if ((result = vsir_program_flatten_control_flow_constructs(program, message_context)) < 0) return result;
From: Giovanni Mascellani gmascellani@codeweavers.com
--- libs/vkd3d-shader/ir.c | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-)
diff --git a/libs/vkd3d-shader/ir.c b/libs/vkd3d-shader/ir.c index 3cbc83e54..896839b34 100644 --- a/libs/vkd3d-shader/ir.c +++ b/libs/vkd3d-shader/ir.c @@ -4571,6 +4571,24 @@ done: return VKD3D_OK; }
+static enum vkd3d_result vsir_program_materialize_undominated_ssas_to_temps(struct vsir_program *program, + struct vkd3d_shader_message_context *message_context) +{ + struct vsir_cfg cfg; + enum vkd3d_result result; + + if ((result = vsir_cfg_init(&cfg, program, message_context)) < 0) + return result; + + vsir_cfg_compute_dominators(&cfg); + + result = vsir_cfg_materialize_undominated_ssas_to_temps(&cfg); + + vsir_cfg_cleanup(&cfg); + + return result; +} + struct validation_context { struct vkd3d_shader_message_context *message_context; @@ -5448,8 +5466,6 @@ enum vkd3d_result vsir_program_normalise(struct vsir_program *program, uint64_t
if (program->shader_version.major >= 6) { - struct vsir_cfg cfg; - if ((result = vsir_program_materialise_phi_ssas_to_temps(program)) < 0) return result;
@@ -5462,15 +5478,7 @@ enum vkd3d_result vsir_program_normalise(struct vsir_program *program, uint64_t if ((result = vsir_program_flatten_control_flow_constructs(program, message_context)) < 0) return result;
- if ((result = vsir_cfg_init(&cfg, program, message_context)) < 0) - return result; - vsir_cfg_compute_dominators(&cfg); - - result = vsir_cfg_materialize_undominated_ssas_to_temps(&cfg); - - vsir_cfg_cleanup(&cfg); - - if (result < 0) + if ((result = vsir_program_materialize_undominated_ssas_to_temps(program, message_context)) < 0) return result; } else
From: Giovanni Mascellani gmascellani@codeweavers.com
This is in preparation of handling more than one function (as it happens for Hull Shaders), which will require having a single row of declarations, but handling more than one CFG. --- libs/vkd3d-shader/ir.c | 190 ++++++++++++++++++++++------------------- 1 file changed, 102 insertions(+), 88 deletions(-)
diff --git a/libs/vkd3d-shader/ir.c b/libs/vkd3d-shader/ir.c index 896839b34..22639325b 100644 --- a/libs/vkd3d-shader/ir.c +++ b/libs/vkd3d-shader/ir.c @@ -3013,6 +3013,14 @@ static void vsir_cfg_structure_cleanup(struct vsir_cfg_structure *structure) } }
+struct vsir_cfg_emit_target +{ + struct vkd3d_shader_instruction *instructions; + size_t ins_capacity, ins_count; + unsigned int jump_target_temp_idx; + unsigned int temp_count; +}; + struct vsir_cfg { struct vkd3d_shader_message_context *message_context; @@ -3061,10 +3069,7 @@ struct vsir_cfg
struct vsir_cfg_structure_list structured_program;
- struct vkd3d_shader_instruction *instructions; - size_t ins_capacity, ins_count; - unsigned int jump_target_temp_idx; - unsigned int temp_count; + struct vsir_cfg_emit_target *target; };
static void vsir_cfg_cleanup(struct vsir_cfg *cfg) @@ -3258,7 +3263,7 @@ static void vsir_cfg_dump_structured_program(struct vsir_cfg *cfg) }
static enum vkd3d_result vsir_cfg_init(struct vsir_cfg *cfg, struct vsir_program *program, - struct vkd3d_shader_message_context *message_context) + struct vkd3d_shader_message_context *message_context, struct vsir_cfg_emit_target *target) { struct vsir_block *current_block = NULL; enum vkd3d_result ret; @@ -3268,6 +3273,7 @@ static enum vkd3d_result vsir_cfg_init(struct vsir_cfg *cfg, struct vsir_program cfg->message_context = message_context; cfg->program = program; cfg->block_count = program->block_count; + cfg->target = target;
vsir_block_list_init(&cfg->order);
@@ -4206,6 +4212,7 @@ static enum vkd3d_result vsir_cfg_optimize(struct vsir_cfg *cfg) static enum vkd3d_result vsir_cfg_structure_list_emit(struct vsir_cfg *cfg, struct vsir_cfg_structure_list *list, unsigned int loop_idx) { + struct vsir_cfg_emit_target *target = cfg->target; const struct vkd3d_shader_location no_loc = {0}; enum vkd3d_result ret; size_t i; @@ -4220,29 +4227,29 @@ static enum vkd3d_result vsir_cfg_structure_list_emit(struct vsir_cfg *cfg, { struct vsir_block *block = structure->u.block;
- if (!reserve_instructions(&cfg->instructions, &cfg->ins_capacity, cfg->ins_count + (block->end - block->begin))) + if (!reserve_instructions(&target->instructions, &target->ins_capacity, target->ins_count + (block->end - block->begin))) return VKD3D_ERROR_OUT_OF_MEMORY;
- memcpy(&cfg->instructions[cfg->ins_count], block->begin, (char *)block->end - (char *)block->begin); + memcpy(&target->instructions[target->ins_count], block->begin, (char *)block->end - (char *)block->begin);
- cfg->ins_count += block->end - block->begin; + target->ins_count += block->end - block->begin; break; }
case STRUCTURE_TYPE_LOOP: { - if (!reserve_instructions(&cfg->instructions, &cfg->ins_capacity, cfg->ins_count + 1)) + if (!reserve_instructions(&target->instructions, &target->ins_capacity, target->ins_count + 1)) return VKD3D_ERROR_OUT_OF_MEMORY;
- vsir_instruction_init(&cfg->instructions[cfg->ins_count++], &no_loc, VKD3DSIH_LOOP); + vsir_instruction_init(&target->instructions[target->ins_count++], &no_loc, VKD3DSIH_LOOP);
if ((ret = vsir_cfg_structure_list_emit(cfg, &structure->u.loop.body, structure->u.loop.idx)) < 0) return ret;
- if (!reserve_instructions(&cfg->instructions, &cfg->ins_capacity, cfg->ins_count + 5)) + if (!reserve_instructions(&target->instructions, &target->ins_capacity, target->ins_count + 5)) return VKD3D_ERROR_OUT_OF_MEMORY;
- vsir_instruction_init(&cfg->instructions[cfg->ins_count++], &no_loc, VKD3DSIH_ENDLOOP); + vsir_instruction_init(&target->instructions[target->ins_count++], &no_loc, VKD3DSIH_ENDLOOP);
/* Add a trampoline to implement multilevel jumping depending on the stored * jump_target value. */ @@ -4256,82 +4263,82 @@ static enum vkd3d_result vsir_cfg_structure_list_emit(struct vsir_cfg *cfg, * we have to reach an outer loop, so we keep breaking. */ const unsigned int inner_break_target = structure->u.loop.idx << 1;
- if (!vsir_instruction_init_with_params(cfg->program, &cfg->instructions[cfg->ins_count], + if (!vsir_instruction_init_with_params(cfg->program, &target->instructions[target->ins_count], &no_loc, VKD3DSIH_IEQ, 1, 2)) return VKD3D_ERROR_OUT_OF_MEMORY;
- dst_param_init_temp_bool(&cfg->instructions[cfg->ins_count].dst[0], cfg->temp_count); - src_param_init_temp_uint(&cfg->instructions[cfg->ins_count].src[0], cfg->jump_target_temp_idx); - src_param_init_const_uint(&cfg->instructions[cfg->ins_count].src[1], outer_continue_target); + dst_param_init_temp_bool(&target->instructions[target->ins_count].dst[0], target->temp_count); + src_param_init_temp_uint(&target->instructions[target->ins_count].src[0], target->jump_target_temp_idx); + src_param_init_const_uint(&target->instructions[target->ins_count].src[1], outer_continue_target);
- ++cfg->ins_count; + ++target->ins_count;
- if (!vsir_instruction_init_with_params(cfg->program, &cfg->instructions[cfg->ins_count], + if (!vsir_instruction_init_with_params(cfg->program, &target->instructions[target->ins_count], &no_loc, VKD3DSIH_CONTINUEP, 0, 1)) return VKD3D_ERROR_OUT_OF_MEMORY;
- src_param_init_temp_bool(&cfg->instructions[cfg->ins_count].src[0], cfg->temp_count); + src_param_init_temp_bool(&target->instructions[target->ins_count].src[0], target->temp_count);
- ++cfg->ins_count; - ++cfg->temp_count; + ++target->ins_count; + ++target->temp_count;
- if (!vsir_instruction_init_with_params(cfg->program, &cfg->instructions[cfg->ins_count], + if (!vsir_instruction_init_with_params(cfg->program, &target->instructions[target->ins_count], &no_loc, VKD3DSIH_IEQ, 1, 2)) return VKD3D_ERROR_OUT_OF_MEMORY;
- dst_param_init_temp_bool(&cfg->instructions[cfg->ins_count].dst[0], cfg->temp_count); - src_param_init_temp_uint(&cfg->instructions[cfg->ins_count].src[0], cfg->jump_target_temp_idx); - src_param_init_const_uint(&cfg->instructions[cfg->ins_count].src[1], inner_break_target); + dst_param_init_temp_bool(&target->instructions[target->ins_count].dst[0], target->temp_count); + src_param_init_temp_uint(&target->instructions[target->ins_count].src[0], target->jump_target_temp_idx); + src_param_init_const_uint(&target->instructions[target->ins_count].src[1], inner_break_target);
- ++cfg->ins_count; + ++target->ins_count;
- if (!vsir_instruction_init_with_params(cfg->program, &cfg->instructions[cfg->ins_count], + if (!vsir_instruction_init_with_params(cfg->program, &target->instructions[target->ins_count], &no_loc, VKD3DSIH_BREAKP, 0, 1)) return VKD3D_ERROR_OUT_OF_MEMORY; - cfg->instructions[cfg->ins_count].flags |= VKD3D_SHADER_CONDITIONAL_OP_Z; + target->instructions[target->ins_count].flags |= VKD3D_SHADER_CONDITIONAL_OP_Z;
- src_param_init_temp_bool(&cfg->instructions[cfg->ins_count].src[0], cfg->temp_count); + src_param_init_temp_bool(&target->instructions[target->ins_count].src[0], target->temp_count);
- ++cfg->ins_count; - ++cfg->temp_count; + ++target->ins_count; + ++target->temp_count; }
break; }
case STRUCTURE_TYPE_SELECTION: - if (!reserve_instructions(&cfg->instructions, &cfg->ins_capacity, cfg->ins_count + 1)) + if (!reserve_instructions(&target->instructions, &target->ins_capacity, target->ins_count + 1)) return VKD3D_ERROR_OUT_OF_MEMORY;
- if (!vsir_instruction_init_with_params(cfg->program, &cfg->instructions[cfg->ins_count], &no_loc, + if (!vsir_instruction_init_with_params(cfg->program, &target->instructions[target->ins_count], &no_loc, VKD3DSIH_IF, 0, 1)) return VKD3D_ERROR_OUT_OF_MEMORY;
- cfg->instructions[cfg->ins_count].src[0] = *structure->u.selection.condition; + target->instructions[target->ins_count].src[0] = *structure->u.selection.condition;
if (structure->u.selection.invert_condition) - cfg->instructions[cfg->ins_count].flags |= VKD3D_SHADER_CONDITIONAL_OP_Z; + target->instructions[target->ins_count].flags |= VKD3D_SHADER_CONDITIONAL_OP_Z;
- ++cfg->ins_count; + ++target->ins_count;
if ((ret = vsir_cfg_structure_list_emit(cfg, &structure->u.selection.if_body, loop_idx)) < 0) return ret;
if (structure->u.selection.else_body.count != 0) { - if (!reserve_instructions(&cfg->instructions, &cfg->ins_capacity, cfg->ins_count + 1)) + if (!reserve_instructions(&target->instructions, &target->ins_capacity, target->ins_count + 1)) return VKD3D_ERROR_OUT_OF_MEMORY;
- vsir_instruction_init(&cfg->instructions[cfg->ins_count++], &no_loc, VKD3DSIH_ELSE); + vsir_instruction_init(&target->instructions[target->ins_count++], &no_loc, VKD3DSIH_ELSE);
if ((ret = vsir_cfg_structure_list_emit(cfg, &structure->u.selection.else_body, loop_idx)) < 0) return ret; }
- if (!reserve_instructions(&cfg->instructions, &cfg->ins_capacity, cfg->ins_count + 1)) + if (!reserve_instructions(&target->instructions, &target->ins_capacity, target->ins_count + 1)) return VKD3D_ERROR_OUT_OF_MEMORY;
- vsir_instruction_init(&cfg->instructions[cfg->ins_count++], &no_loc, VKD3DSIH_ENDIF); + vsir_instruction_init(&target->instructions[target->ins_count++], &no_loc, VKD3DSIH_ENDIF); break;
case STRUCTURE_TYPE_JUMP: @@ -4369,32 +4376,32 @@ static enum vkd3d_result vsir_cfg_structure_list_emit(struct vsir_cfg *cfg, vkd3d_unreachable(); }
- if (!reserve_instructions(&cfg->instructions, &cfg->ins_capacity, cfg->ins_count + 2)) + if (!reserve_instructions(&target->instructions, &target->ins_capacity, target->ins_count + 2)) return VKD3D_ERROR_OUT_OF_MEMORY;
if (opcode == VKD3DSIH_BREAK || opcode == VKD3DSIH_BREAKP) { - if (!vsir_instruction_init_with_params(cfg->program, &cfg->instructions[cfg->ins_count], + if (!vsir_instruction_init_with_params(cfg->program, &target->instructions[target->ins_count], &no_loc, VKD3DSIH_MOV, 1, 1)) return VKD3D_ERROR_OUT_OF_MEMORY;
- dst_param_init_temp_uint(&cfg->instructions[cfg->ins_count].dst[0], cfg->jump_target_temp_idx); - src_param_init_const_uint(&cfg->instructions[cfg->ins_count].src[0], jump_target); + dst_param_init_temp_uint(&target->instructions[target->ins_count].dst[0], target->jump_target_temp_idx); + src_param_init_const_uint(&target->instructions[target->ins_count].src[0], jump_target);
- ++cfg->ins_count; + ++target->ins_count; }
- if (!vsir_instruction_init_with_params(cfg->program, &cfg->instructions[cfg->ins_count], + if (!vsir_instruction_init_with_params(cfg->program, &target->instructions[target->ins_count], &no_loc, opcode, 0, !!structure->u.jump.condition)) return VKD3D_ERROR_OUT_OF_MEMORY;
if (structure->u.jump.invert_condition) - cfg->instructions[cfg->ins_count].flags |= VKD3D_SHADER_CONDITIONAL_OP_Z; + target->instructions[target->ins_count].flags |= VKD3D_SHADER_CONDITIONAL_OP_Z;
if (structure->u.jump.condition) - cfg->instructions[cfg->ins_count].src[0] = *structure->u.jump.condition; + target->instructions[target->ins_count].src[0] = *structure->u.jump.condition;
- ++cfg->ins_count; + ++target->ins_count; break; }
@@ -4408,50 +4415,16 @@ static enum vkd3d_result vsir_cfg_structure_list_emit(struct vsir_cfg *cfg,
static enum vkd3d_result vsir_cfg_emit_structured_program(struct vsir_cfg *cfg) { - enum vkd3d_result ret; - size_t i; - - cfg->jump_target_temp_idx = cfg->program->temp_count; - cfg->temp_count = cfg->program->temp_count + 1; - - if (!reserve_instructions(&cfg->instructions, &cfg->ins_capacity, cfg->program->instructions.count)) - return VKD3D_ERROR_OUT_OF_MEMORY; - - /* Copy declarations until the first block. */ - for (i = 0; i < cfg->program->instructions.count; ++i) - { - struct vkd3d_shader_instruction *ins = &cfg->program->instructions.elements[i]; - - if (ins->handler_idx == VKD3DSIH_LABEL) - break; - - cfg->instructions[cfg->ins_count++] = *ins; - } - - if ((ret = vsir_cfg_structure_list_emit(cfg, &cfg->structured_program, UINT_MAX)) < 0) - goto fail; - - vkd3d_free(cfg->program->instructions.elements); - cfg->program->instructions.elements = cfg->instructions; - cfg->program->instructions.capacity = cfg->ins_capacity; - cfg->program->instructions.count = cfg->ins_count; - cfg->program->temp_count = cfg->temp_count; - - return VKD3D_OK; - -fail: - vkd3d_free(cfg->instructions); - - return ret; + return vsir_cfg_structure_list_emit(cfg, &cfg->structured_program, UINT_MAX); }
-static enum vkd3d_result vsir_program_structurize(struct vsir_program *program, - struct vkd3d_shader_message_context *message_context) +static enum vkd3d_result vsir_program_structurize_function(struct vsir_program *program, + struct vkd3d_shader_message_context *message_context, struct vsir_cfg_emit_target *target) { enum vkd3d_result result; struct vsir_cfg cfg;
- if ((result = vsir_cfg_init(&cfg, program, message_context)) < 0) + if ((result = vsir_cfg_init(&cfg, program, message_context, target)) < 0) return result;
vsir_cfg_compute_dominators(&cfg); @@ -4479,6 +4452,47 @@ out: return result; }
+static enum vkd3d_result vsir_program_structurize(struct vsir_program *program, + struct vkd3d_shader_message_context *message_context) +{ + struct vsir_cfg_emit_target target = {0}; + enum vkd3d_result ret; + unsigned int i; + + target.jump_target_temp_idx = program->temp_count; + target.temp_count = program->temp_count + 1; + + if (!reserve_instructions(&target.instructions, &target.ins_capacity, program->instructions.count)) + return VKD3D_ERROR_OUT_OF_MEMORY; + + /* Copy declarations until the first block. */ + for (i = 0; i < program->instructions.count; ++i) + { + struct vkd3d_shader_instruction *ins = &program->instructions.elements[i]; + + if (ins->handler_idx == VKD3DSIH_LABEL) + break; + + target.instructions[target.ins_count++] = *ins; + } + + if ((ret = vsir_program_structurize_function(program, message_context, &target)) < 0) + goto fail; + + vkd3d_free(program->instructions.elements); + program->instructions.elements = target.instructions; + program->instructions.capacity = target.ins_capacity; + program->instructions.count = target.ins_count; + program->temp_count = target.temp_count; + + return VKD3D_OK; + +fail: + vkd3d_free(target.instructions); + + return ret; +} + static void register_map_undominated_use(struct vkd3d_shader_register *reg, struct ssas_to_temps_alloc *alloc, struct vsir_block *block, struct vsir_block **origin_blocks) { @@ -4577,7 +4591,7 @@ static enum vkd3d_result vsir_program_materialize_undominated_ssas_to_temps(stru struct vsir_cfg cfg; enum vkd3d_result result;
- if ((result = vsir_cfg_init(&cfg, program, message_context)) < 0) + if ((result = vsir_cfg_init(&cfg, program, message_context, NULL)) < 0) return result;
vsir_cfg_compute_dominators(&cfg);
From: Giovanni Mascellani gmascellani@codeweavers.com
--- libs/vkd3d-shader/ir.c | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-)
diff --git a/libs/vkd3d-shader/ir.c b/libs/vkd3d-shader/ir.c index 22639325b..484fcc30f 100644 --- a/libs/vkd3d-shader/ir.c +++ b/libs/vkd3d-shader/ir.c @@ -4209,6 +4209,23 @@ static enum vkd3d_result vsir_cfg_optimize(struct vsir_cfg *cfg) return ret; }
+static enum vkd3d_result vsir_cfg_structure_list_emit_block(struct vsir_cfg *cfg, + struct vsir_block *block) +{ + struct vsir_cfg_emit_target *target = cfg->target; + + if (!reserve_instructions(&target->instructions, &target->ins_capacity, + target->ins_count + (block->end - block->begin))) + return VKD3D_ERROR_OUT_OF_MEMORY; + + memcpy(&target->instructions[target->ins_count], block->begin, + (char *)block->end - (char *)block->begin); + + target->ins_count += block->end - block->begin; + + return VKD3D_OK; +} + static enum vkd3d_result vsir_cfg_structure_list_emit(struct vsir_cfg *cfg, struct vsir_cfg_structure_list *list, unsigned int loop_idx) { @@ -4224,17 +4241,9 @@ static enum vkd3d_result vsir_cfg_structure_list_emit(struct vsir_cfg *cfg, switch (structure->type) { case STRUCTURE_TYPE_BLOCK: - { - struct vsir_block *block = structure->u.block; - - if (!reserve_instructions(&target->instructions, &target->ins_capacity, target->ins_count + (block->end - block->begin))) - return VKD3D_ERROR_OUT_OF_MEMORY; - - memcpy(&target->instructions[target->ins_count], block->begin, (char *)block->end - (char *)block->begin); - - target->ins_count += block->end - block->begin; + if ((ret = vsir_cfg_structure_list_emit_block(cfg, structure->u.block)) < 0) + return ret; break; - }
case STRUCTURE_TYPE_LOOP: {
From: Giovanni Mascellani gmascellani@codeweavers.com
--- libs/vkd3d-shader/ir.c | 139 ++++++++++++++++++++++------------------- 1 file changed, 76 insertions(+), 63 deletions(-)
diff --git a/libs/vkd3d-shader/ir.c b/libs/vkd3d-shader/ir.c index 484fcc30f..b1ae13ae9 100644 --- a/libs/vkd3d-shader/ir.c +++ b/libs/vkd3d-shader/ir.c @@ -2917,7 +2917,7 @@ struct vsir_cfg_structure union { struct vsir_block *block; - struct + struct vsir_cfg_structure_loop { struct vsir_cfg_structure_list body; unsigned idx; @@ -4209,6 +4209,9 @@ static enum vkd3d_result vsir_cfg_optimize(struct vsir_cfg *cfg) return ret; }
+static enum vkd3d_result vsir_cfg_structure_list_emit(struct vsir_cfg *cfg, + struct vsir_cfg_structure_list *list, unsigned int loop_idx); + static enum vkd3d_result vsir_cfg_structure_list_emit_block(struct vsir_cfg *cfg, struct vsir_block *block) { @@ -4226,94 +4229,104 @@ static enum vkd3d_result vsir_cfg_structure_list_emit_block(struct vsir_cfg *cfg return VKD3D_OK; }
-static enum vkd3d_result vsir_cfg_structure_list_emit(struct vsir_cfg *cfg, - struct vsir_cfg_structure_list *list, unsigned int loop_idx) +static enum vkd3d_result vsir_cfg_structure_list_emit_loop(struct vsir_cfg *cfg, + struct vsir_cfg_structure_loop *loop, unsigned int loop_idx) { struct vsir_cfg_emit_target *target = cfg->target; const struct vkd3d_shader_location no_loc = {0}; enum vkd3d_result ret; - size_t i;
- for (i = 0; i < list->count; ++i) - { - struct vsir_cfg_structure *structure = &list->structures[i]; + if (!reserve_instructions(&target->instructions, &target->ins_capacity, target->ins_count + 1)) + return VKD3D_ERROR_OUT_OF_MEMORY;
- switch (structure->type) - { - case STRUCTURE_TYPE_BLOCK: - if ((ret = vsir_cfg_structure_list_emit_block(cfg, structure->u.block)) < 0) - return ret; - break; + vsir_instruction_init(&target->instructions[target->ins_count++], &no_loc, VKD3DSIH_LOOP);
- case STRUCTURE_TYPE_LOOP: - { - if (!reserve_instructions(&target->instructions, &target->ins_capacity, target->ins_count + 1)) - return VKD3D_ERROR_OUT_OF_MEMORY; + if ((ret = vsir_cfg_structure_list_emit(cfg, &loop->body, loop->idx)) < 0) + return ret;
- vsir_instruction_init(&target->instructions[target->ins_count++], &no_loc, VKD3DSIH_LOOP); + if (!reserve_instructions(&target->instructions, &target->ins_capacity, target->ins_count + 5)) + return VKD3D_ERROR_OUT_OF_MEMORY;
- if ((ret = vsir_cfg_structure_list_emit(cfg, &structure->u.loop.body, structure->u.loop.idx)) < 0) - return ret; + vsir_instruction_init(&target->instructions[target->ins_count++], &no_loc, VKD3DSIH_ENDLOOP);
- if (!reserve_instructions(&target->instructions, &target->ins_capacity, target->ins_count + 5)) - return VKD3D_ERROR_OUT_OF_MEMORY; + /* Add a trampoline to implement multilevel jumping depending on the stored + * jump_target value. */ + if (loop_idx != UINT_MAX) + { + /* If the multilevel jump is a `continue' and the target is the loop we're inside + * right now, then we can finally do the `continue'. */ + const unsigned int outer_continue_target = loop_idx << 1 | 1; + /* If the multilevel jump is a `continue' to any other target, or if it is a `break' + * and the target is not the loop we just finished emitting, then it means that + * we have to reach an outer loop, so we keep breaking. */ + const unsigned int inner_break_target = loop->idx << 1; + + if (!vsir_instruction_init_with_params(cfg->program, &target->instructions[target->ins_count], + &no_loc, VKD3DSIH_IEQ, 1, 2)) + return VKD3D_ERROR_OUT_OF_MEMORY;
- vsir_instruction_init(&target->instructions[target->ins_count++], &no_loc, VKD3DSIH_ENDLOOP); + dst_param_init_temp_bool(&target->instructions[target->ins_count].dst[0], target->temp_count); + src_param_init_temp_uint(&target->instructions[target->ins_count].src[0], target->jump_target_temp_idx); + src_param_init_const_uint(&target->instructions[target->ins_count].src[1], outer_continue_target);
- /* Add a trampoline to implement multilevel jumping depending on the stored - * jump_target value. */ - if (loop_idx != UINT_MAX) - { - /* If the multilevel jump is a `continue' and the target is the loop we're inside - * right now, then we can finally do the `continue'. */ - const unsigned int outer_continue_target = loop_idx << 1 | 1; - /* If the multilevel jump is a `continue' to any other target, or if it is a `break' - * and the target is not the loop we just finished emitting, then it means that - * we have to reach an outer loop, so we keep breaking. */ - const unsigned int inner_break_target = structure->u.loop.idx << 1; + ++target->ins_count;
- if (!vsir_instruction_init_with_params(cfg->program, &target->instructions[target->ins_count], - &no_loc, VKD3DSIH_IEQ, 1, 2)) - return VKD3D_ERROR_OUT_OF_MEMORY; + if (!vsir_instruction_init_with_params(cfg->program, &target->instructions[target->ins_count], + &no_loc, VKD3DSIH_CONTINUEP, 0, 1)) + return VKD3D_ERROR_OUT_OF_MEMORY;
- dst_param_init_temp_bool(&target->instructions[target->ins_count].dst[0], target->temp_count); - src_param_init_temp_uint(&target->instructions[target->ins_count].src[0], target->jump_target_temp_idx); - src_param_init_const_uint(&target->instructions[target->ins_count].src[1], outer_continue_target); + src_param_init_temp_bool(&target->instructions[target->ins_count].src[0], target->temp_count);
- ++target->ins_count; + ++target->ins_count; + ++target->temp_count;
- if (!vsir_instruction_init_with_params(cfg->program, &target->instructions[target->ins_count], - &no_loc, VKD3DSIH_CONTINUEP, 0, 1)) - return VKD3D_ERROR_OUT_OF_MEMORY; + if (!vsir_instruction_init_with_params(cfg->program, &target->instructions[target->ins_count], + &no_loc, VKD3DSIH_IEQ, 1, 2)) + return VKD3D_ERROR_OUT_OF_MEMORY;
- src_param_init_temp_bool(&target->instructions[target->ins_count].src[0], target->temp_count); + dst_param_init_temp_bool(&target->instructions[target->ins_count].dst[0], target->temp_count); + src_param_init_temp_uint(&target->instructions[target->ins_count].src[0], target->jump_target_temp_idx); + src_param_init_const_uint(&target->instructions[target->ins_count].src[1], inner_break_target);
- ++target->ins_count; - ++target->temp_count; + ++target->ins_count;
- if (!vsir_instruction_init_with_params(cfg->program, &target->instructions[target->ins_count], - &no_loc, VKD3DSIH_IEQ, 1, 2)) - return VKD3D_ERROR_OUT_OF_MEMORY; + if (!vsir_instruction_init_with_params(cfg->program, &target->instructions[target->ins_count], + &no_loc, VKD3DSIH_BREAKP, 0, 1)) + return VKD3D_ERROR_OUT_OF_MEMORY; + target->instructions[target->ins_count].flags |= VKD3D_SHADER_CONDITIONAL_OP_Z;
- dst_param_init_temp_bool(&target->instructions[target->ins_count].dst[0], target->temp_count); - src_param_init_temp_uint(&target->instructions[target->ins_count].src[0], target->jump_target_temp_idx); - src_param_init_const_uint(&target->instructions[target->ins_count].src[1], inner_break_target); + src_param_init_temp_bool(&target->instructions[target->ins_count].src[0], target->temp_count);
- ++target->ins_count; + ++target->ins_count; + ++target->temp_count; + }
- if (!vsir_instruction_init_with_params(cfg->program, &target->instructions[target->ins_count], - &no_loc, VKD3DSIH_BREAKP, 0, 1)) - return VKD3D_ERROR_OUT_OF_MEMORY; - target->instructions[target->ins_count].flags |= VKD3D_SHADER_CONDITIONAL_OP_Z; + return VKD3D_OK; +}
- src_param_init_temp_bool(&target->instructions[target->ins_count].src[0], target->temp_count); +static enum vkd3d_result vsir_cfg_structure_list_emit(struct vsir_cfg *cfg, + struct vsir_cfg_structure_list *list, unsigned int loop_idx) +{ + struct vsir_cfg_emit_target *target = cfg->target; + const struct vkd3d_shader_location no_loc = {0}; + enum vkd3d_result ret; + size_t i;
- ++target->ins_count; - ++target->temp_count; - } + for (i = 0; i < list->count; ++i) + { + struct vsir_cfg_structure *structure = &list->structures[i]; + + switch (structure->type) + { + case STRUCTURE_TYPE_BLOCK: + if ((ret = vsir_cfg_structure_list_emit_block(cfg, structure->u.block)) < 0) + return ret; + break;
+ case STRUCTURE_TYPE_LOOP: + if ((ret = vsir_cfg_structure_list_emit_loop(cfg, &structure->u.loop, loop_idx)) < 0) + return ret; break; - }
case STRUCTURE_TYPE_SELECTION: if (!reserve_instructions(&target->instructions, &target->ins_capacity, target->ins_count + 1))
From: Giovanni Mascellani gmascellani@codeweavers.com
--- libs/vkd3d-shader/ir.c | 81 +++++++++++++++++++++++++----------------- 1 file changed, 48 insertions(+), 33 deletions(-)
diff --git a/libs/vkd3d-shader/ir.c b/libs/vkd3d-shader/ir.c index b1ae13ae9..012b5b2e6 100644 --- a/libs/vkd3d-shader/ir.c +++ b/libs/vkd3d-shader/ir.c @@ -2922,7 +2922,7 @@ struct vsir_cfg_structure struct vsir_cfg_structure_list body; unsigned idx; } loop; - struct + struct vsir_cfg_structure_selection { struct vkd3d_shader_src_param *condition; struct vsir_cfg_structure_list if_body; @@ -4304,6 +4304,49 @@ static enum vkd3d_result vsir_cfg_structure_list_emit_loop(struct vsir_cfg *cfg, return VKD3D_OK; }
+static enum vkd3d_result vsir_cfg_structure_list_emit_selection(struct vsir_cfg *cfg, + struct vsir_cfg_structure_selection *selection, unsigned int loop_idx) +{ + struct vsir_cfg_emit_target *target = cfg->target; + const struct vkd3d_shader_location no_loc = {0}; + enum vkd3d_result ret; + + if (!reserve_instructions(&target->instructions, &target->ins_capacity, target->ins_count + 1)) + return VKD3D_ERROR_OUT_OF_MEMORY; + + if (!vsir_instruction_init_with_params(cfg->program, &target->instructions[target->ins_count], + &no_loc, VKD3DSIH_IF, 0, 1)) + return VKD3D_ERROR_OUT_OF_MEMORY; + + target->instructions[target->ins_count].src[0] = *selection->condition; + + if (selection->invert_condition) + target->instructions[target->ins_count].flags |= VKD3D_SHADER_CONDITIONAL_OP_Z; + + ++target->ins_count; + + if ((ret = vsir_cfg_structure_list_emit(cfg, &selection->if_body, loop_idx)) < 0) + return ret; + + if (selection->else_body.count != 0) + { + if (!reserve_instructions(&target->instructions, &target->ins_capacity, target->ins_count + 1)) + return VKD3D_ERROR_OUT_OF_MEMORY; + + vsir_instruction_init(&target->instructions[target->ins_count++], &no_loc, VKD3DSIH_ELSE); + + if ((ret = vsir_cfg_structure_list_emit(cfg, &selection->else_body, loop_idx)) < 0) + return ret; + } + + if (!reserve_instructions(&target->instructions, &target->ins_capacity, target->ins_count + 1)) + return VKD3D_ERROR_OUT_OF_MEMORY; + + vsir_instruction_init(&target->instructions[target->ins_count++], &no_loc, VKD3DSIH_ENDIF); + + return VKD3D_OK; +} + static enum vkd3d_result vsir_cfg_structure_list_emit(struct vsir_cfg *cfg, struct vsir_cfg_structure_list *list, unsigned int loop_idx) { @@ -4324,43 +4367,15 @@ static enum vkd3d_result vsir_cfg_structure_list_emit(struct vsir_cfg *cfg, break;
case STRUCTURE_TYPE_LOOP: - if ((ret = vsir_cfg_structure_list_emit_loop(cfg, &structure->u.loop, loop_idx)) < 0) + if ((ret = vsir_cfg_structure_list_emit_loop(cfg, &structure->u.loop, + loop_idx)) < 0) return ret; break;
case STRUCTURE_TYPE_SELECTION: - if (!reserve_instructions(&target->instructions, &target->ins_capacity, target->ins_count + 1)) - return VKD3D_ERROR_OUT_OF_MEMORY; - - if (!vsir_instruction_init_with_params(cfg->program, &target->instructions[target->ins_count], &no_loc, - VKD3DSIH_IF, 0, 1)) - return VKD3D_ERROR_OUT_OF_MEMORY; - - target->instructions[target->ins_count].src[0] = *structure->u.selection.condition; - - if (structure->u.selection.invert_condition) - target->instructions[target->ins_count].flags |= VKD3D_SHADER_CONDITIONAL_OP_Z; - - ++target->ins_count; - - if ((ret = vsir_cfg_structure_list_emit(cfg, &structure->u.selection.if_body, loop_idx)) < 0) + if ((ret = vsir_cfg_structure_list_emit_selection(cfg, &structure->u.selection, + loop_idx)) < 0) return ret; - - if (structure->u.selection.else_body.count != 0) - { - if (!reserve_instructions(&target->instructions, &target->ins_capacity, target->ins_count + 1)) - return VKD3D_ERROR_OUT_OF_MEMORY; - - vsir_instruction_init(&target->instructions[target->ins_count++], &no_loc, VKD3DSIH_ELSE); - - if ((ret = vsir_cfg_structure_list_emit(cfg, &structure->u.selection.else_body, loop_idx)) < 0) - return ret; - } - - if (!reserve_instructions(&target->instructions, &target->ins_capacity, target->ins_count + 1)) - return VKD3D_ERROR_OUT_OF_MEMORY; - - vsir_instruction_init(&target->instructions[target->ins_count++], &no_loc, VKD3DSIH_ENDIF); break;
case STRUCTURE_TYPE_JUMP:
From: Giovanni Mascellani gmascellani@codeweavers.com
--- libs/vkd3d-shader/ir.c | 136 ++++++++++++++++++++++------------------- 1 file changed, 72 insertions(+), 64 deletions(-)
diff --git a/libs/vkd3d-shader/ir.c b/libs/vkd3d-shader/ir.c index 012b5b2e6..58be99687 100644 --- a/libs/vkd3d-shader/ir.c +++ b/libs/vkd3d-shader/ir.c @@ -2929,7 +2929,7 @@ struct vsir_cfg_structure struct vsir_cfg_structure_list else_body; bool invert_condition; } selection; - struct + struct vsir_cfg_structure_jump { enum vsir_cfg_jump_type { @@ -4347,11 +4347,77 @@ static enum vkd3d_result vsir_cfg_structure_list_emit_selection(struct vsir_cfg return VKD3D_OK; }
-static enum vkd3d_result vsir_cfg_structure_list_emit(struct vsir_cfg *cfg, - struct vsir_cfg_structure_list *list, unsigned int loop_idx) +static enum vkd3d_result vsir_cfg_structure_list_emit_jump(struct vsir_cfg *cfg, + struct vsir_cfg_structure_jump *jump, unsigned int loop_idx) { struct vsir_cfg_emit_target *target = cfg->target; const struct vkd3d_shader_location no_loc = {0}; + /* Encode the jump target as the loop index plus a bit to remember whether + * we're breaking or continueing. */ + unsigned int jump_target = jump->target << 1; + enum vkd3d_shader_opcode opcode; + + switch (jump->type) + { + case JUMP_CONTINUE: + /* If we're continueing the loop we're directly inside, then we can emit a + * `continue'. Otherwise we first have to break all the loops between here + * and the loop to continue, recording our intention to continue + * in the lowest bit of jump_target. */ + if (jump->target == loop_idx) + { + opcode = jump->condition ? VKD3DSIH_CONTINUEP : VKD3DSIH_CONTINUE; + break; + } + jump_target |= 1; + /* fall through */ + + case JUMP_BREAK: + opcode = jump->condition ? VKD3DSIH_BREAKP : VKD3DSIH_BREAK; + break; + + case JUMP_RET: + assert(!jump->condition); + opcode = VKD3DSIH_RET; + break; + + default: + vkd3d_unreachable(); + } + + if (!reserve_instructions(&target->instructions, &target->ins_capacity, target->ins_count + 2)) + return VKD3D_ERROR_OUT_OF_MEMORY; + + if (opcode == VKD3DSIH_BREAK || opcode == VKD3DSIH_BREAKP) + { + if (!vsir_instruction_init_with_params(cfg->program, &target->instructions[target->ins_count], + &no_loc, VKD3DSIH_MOV, 1, 1)) + return VKD3D_ERROR_OUT_OF_MEMORY; + + dst_param_init_temp_uint(&target->instructions[target->ins_count].dst[0], target->jump_target_temp_idx); + src_param_init_const_uint(&target->instructions[target->ins_count].src[0], jump_target); + + ++target->ins_count; + } + + if (!vsir_instruction_init_with_params(cfg->program, &target->instructions[target->ins_count], + &no_loc, opcode, 0, !!jump->condition)) + return VKD3D_ERROR_OUT_OF_MEMORY; + + if (jump->invert_condition) + target->instructions[target->ins_count].flags |= VKD3D_SHADER_CONDITIONAL_OP_Z; + + if (jump->condition) + target->instructions[target->ins_count].src[0] = *jump->condition; + + ++target->ins_count; + + return VKD3D_OK; +} + +static enum vkd3d_result vsir_cfg_structure_list_emit(struct vsir_cfg *cfg, + struct vsir_cfg_structure_list *list, unsigned int loop_idx) +{ enum vkd3d_result ret; size_t i;
@@ -4379,68 +4445,10 @@ static enum vkd3d_result vsir_cfg_structure_list_emit(struct vsir_cfg *cfg, break;
case STRUCTURE_TYPE_JUMP: - { - /* Encode the jump target as the loop index plus a bit to remember whether - * we're breaking or continueing. */ - unsigned int jump_target = structure->u.jump.target << 1; - enum vkd3d_shader_opcode opcode; - - switch (structure->u.jump.type) - { - case JUMP_CONTINUE: - /* If we're continueing the loop we're directly inside, then we can emit a - * `continue'. Otherwise we first have to break all the loops between here - * and the loop to continue, recording our intention to continue - * in the lowest bit of jump_target. */ - if (structure->u.jump.target == loop_idx) - { - opcode = structure->u.jump.condition ? VKD3DSIH_CONTINUEP : VKD3DSIH_CONTINUE; - break; - } - jump_target |= 1; - /* fall through */ - - case JUMP_BREAK: - opcode = structure->u.jump.condition ? VKD3DSIH_BREAKP : VKD3DSIH_BREAK; - break; - - case JUMP_RET: - assert(!structure->u.jump.condition); - opcode = VKD3DSIH_RET; - break; - - default: - vkd3d_unreachable(); - } - - if (!reserve_instructions(&target->instructions, &target->ins_capacity, target->ins_count + 2)) - return VKD3D_ERROR_OUT_OF_MEMORY; - - if (opcode == VKD3DSIH_BREAK || opcode == VKD3DSIH_BREAKP) - { - if (!vsir_instruction_init_with_params(cfg->program, &target->instructions[target->ins_count], - &no_loc, VKD3DSIH_MOV, 1, 1)) - return VKD3D_ERROR_OUT_OF_MEMORY; - - dst_param_init_temp_uint(&target->instructions[target->ins_count].dst[0], target->jump_target_temp_idx); - src_param_init_const_uint(&target->instructions[target->ins_count].src[0], jump_target); - - ++target->ins_count; - } - - if (!vsir_instruction_init_with_params(cfg->program, &target->instructions[target->ins_count], - &no_loc, opcode, 0, !!structure->u.jump.condition)) - return VKD3D_ERROR_OUT_OF_MEMORY; - - if (structure->u.jump.invert_condition) - target->instructions[target->ins_count].flags |= VKD3D_SHADER_CONDITIONAL_OP_Z; - - if (structure->u.jump.condition) - target->instructions[target->ins_count].src[0] = *structure->u.jump.condition; - - ++target->ins_count; + if ((ret = vsir_cfg_structure_list_emit_jump(cfg, &structure->u.jump, + loop_idx)) < 0) + return ret; break; - }
default: vkd3d_unreachable();
This merge request was approved by Giovanni Mascellani.
Conor McCarthy (@cmccarthy) commented about libs/vkd3d-shader/ir.c:
return VKD3D_OK;
}
+static enum vkd3d_result vsir_program_materialize_undominated_ssas_to_temps(struct vsir_program *program,
struct vkd3d_shader_message_context *message_context)
+{
- struct vsir_cfg cfg;
- enum vkd3d_result result;
Minor nitpick: these should be swapped to fit the formatting style.
Conor McCarthy (@cmccarthy) commented about libs/vkd3d-shader/ir.c:
break; case STRUCTURE_TYPE_LOOP:
if ((ret = vsir_cfg_structure_list_emit_loop(cfg, &structure->u.loop, loop_idx)) < 0)
if ((ret = vsir_cfg_structure_list_emit_loop(cfg, &structure->u.loop,
loop_idx)) < 0)
Unrelated (accidental?) change.
The `Split handling * when emitting a structured program` commits do no more than move code to helper functions, right? Maybe the commit messages should state that instead.