vkd3d-shader/ir: Use a vkd3d_shader_instruction_array in struct vsir_cfg_emit_target.

This commit is contained in:
Francisco Casas
2025-09-15 22:15:13 -03:00
committed by Henri Verbeet
parent e935e06e23
commit ebb180c2a8
Notes: Henri Verbeet 2025-09-29 13:04:35 +02:00
Approved-by: Giovanni Mascellani (@giomasce)
Approved-by: Henri Verbeet (@hverbeet)
Merge-Request: https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/1739

View File

@@ -3850,6 +3850,17 @@ static enum vkd3d_result vsir_program_remove_dead_code(struct vsir_program *prog
return VKD3D_OK; return VKD3D_OK;
} }
/* NOTE: This invalidates all iterators, since the position of the
* vkd3d_shader_instruction_array itself changes. */
static void vsir_program_replace_instructions(struct vsir_program *program,
struct vkd3d_shader_instruction_array *array)
{
shader_instruction_array_destroy(&program->instructions);
program->instructions = *array;
memset(array, 0, sizeof(*array));
}
struct cf_flattener_if_info struct cf_flattener_if_info
{ {
struct vkd3d_shader_src_param *false_param; struct vkd3d_shader_src_param *false_param;
@@ -5120,8 +5131,8 @@ static void vsir_cfg_structure_cleanup(struct vsir_cfg_structure *structure)
struct vsir_cfg_emit_target struct vsir_cfg_emit_target
{ {
struct vkd3d_shader_instruction *instructions; struct vkd3d_shader_instruction_array instructions;
size_t ins_capacity, ins_count;
unsigned int jump_target_temp_idx; unsigned int jump_target_temp_idx;
unsigned int temp_count; unsigned int temp_count;
}; };
@@ -6713,7 +6724,7 @@ static enum vkd3d_result vsir_cfg_structure_list_emit_block(struct vsir_cfg *cfg
struct vsir_block *block) struct vsir_block *block)
{ {
struct vsir_cfg_emit_target *target = cfg->target; struct vsir_cfg_emit_target *target = cfg->target;
struct vkd3d_shader_instruction *ins, *end; struct vkd3d_shader_instruction *ins, *end, *dst;
struct vsir_program_iterator it; struct vsir_program_iterator it;
size_t ins_count = 0; size_t ins_count = 0;
@@ -6725,14 +6736,15 @@ static enum vkd3d_result vsir_cfg_structure_list_emit_block(struct vsir_cfg *cfg
++ins_count; ++ins_count;
} }
if (!reserve_instructions(&target->instructions, &target->ins_capacity, if (!shader_instruction_array_reserve(&target->instructions, target->instructions.count + ins_count))
target->ins_count + ins_count))
return VKD3D_ERROR_OUT_OF_MEMORY; return VKD3D_ERROR_OUT_OF_MEMORY;
it = block->begin; it = block->begin;
for (ins = vsir_program_iterator_current(&it); ins != end; ins = vsir_program_iterator_next(&it)) for (ins = vsir_program_iterator_current(&it); ins != end; ins = vsir_program_iterator_next(&it))
{ {
target->instructions[target->ins_count++] = *ins; dst = shader_instruction_array_append(&target->instructions);
VKD3D_ASSERT(dst);
*dst = *ins;
} }
return VKD3D_OK; return VKD3D_OK;
@@ -6743,20 +6755,22 @@ static enum vkd3d_result vsir_cfg_structure_list_emit_loop(struct vsir_cfg *cfg,
{ {
struct vsir_cfg_emit_target *target = cfg->target; struct vsir_cfg_emit_target *target = cfg->target;
const struct vkd3d_shader_location no_loc = {0}; const struct vkd3d_shader_location no_loc = {0};
struct vkd3d_shader_instruction *ins;
enum vkd3d_result ret; enum vkd3d_result ret;
if (!reserve_instructions(&target->instructions, &target->ins_capacity, target->ins_count + 1)) if (!(ins = shader_instruction_array_append(&target->instructions)))
return VKD3D_ERROR_OUT_OF_MEMORY; return VKD3D_ERROR_OUT_OF_MEMORY;
vsir_instruction_init(&target->instructions[target->ins_count++], &no_loc, VSIR_OP_LOOP); vsir_instruction_init(ins, &no_loc, VSIR_OP_LOOP);
if ((ret = vsir_cfg_structure_list_emit(cfg, &loop->body, loop->idx)) < 0) if ((ret = vsir_cfg_structure_list_emit(cfg, &loop->body, loop->idx)) < 0)
return ret; return ret;
if (!reserve_instructions(&target->instructions, &target->ins_capacity, target->ins_count + 5)) if (!shader_instruction_array_reserve(&target->instructions, target->instructions.count + 5))
return VKD3D_ERROR_OUT_OF_MEMORY; return VKD3D_ERROR_OUT_OF_MEMORY;
vsir_instruction_init(&target->instructions[target->ins_count++], &no_loc, VSIR_OP_ENDLOOP); ins = shader_instruction_array_append(&target->instructions);
vsir_instruction_init(ins, &no_loc, VSIR_OP_ENDLOOP);
/* Add a trampoline to implement multilevel jumping depending on the stored /* Add a trampoline to implement multilevel jumping depending on the stored
* jump_target value. */ * jump_target value. */
@@ -6770,44 +6784,50 @@ static enum vkd3d_result vsir_cfg_structure_list_emit_loop(struct vsir_cfg *cfg,
* we have to reach an outer loop, so we keep breaking. */ * we have to reach an outer loop, so we keep breaking. */
const unsigned int inner_break_target = loop->idx << 1; const unsigned int inner_break_target = loop->idx << 1;
if (!vsir_instruction_init_with_params(cfg->program, &target->instructions[target->ins_count], ins = shader_instruction_array_append(&target->instructions);
&no_loc, VSIR_OP_IEQ, 1, 2)) if (!vsir_instruction_init_with_params(cfg->program, ins, &no_loc, VSIR_OP_IEQ, 1, 2))
{
vkd3d_shader_instruction_make_nop(ins);
return VKD3D_ERROR_OUT_OF_MEMORY; 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);
++target->ins_count;
if (!vsir_instruction_init_with_params(cfg->program, &target->instructions[target->ins_count],
&no_loc, VSIR_OP_CONTINUEP, 0, 1))
return VKD3D_ERROR_OUT_OF_MEMORY;
src_param_init_temp_bool(&target->instructions[target->ins_count].src[0], target->temp_count);
++target->ins_count;
++target->temp_count; ++target->temp_count;
if (!vsir_instruction_init_with_params(cfg->program, &target->instructions[target->ins_count], dst_param_init_temp_bool(&ins->dst[0], target->temp_count - 1);
&no_loc, VSIR_OP_IEQ, 1, 2)) src_param_init_temp_uint(&ins->src[0], target->jump_target_temp_idx);
src_param_init_const_uint(&ins->src[1], outer_continue_target);
ins = shader_instruction_array_append(&target->instructions);
if (!vsir_instruction_init_with_params(cfg->program, ins, &no_loc, VSIR_OP_CONTINUEP, 0, 1))
{
vkd3d_shader_instruction_make_nop(ins);
return VKD3D_ERROR_OUT_OF_MEMORY; 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_bool(&ins->src[0], target->temp_count - 1);
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; ins = shader_instruction_array_append(&target->instructions);
if (!vsir_instruction_init_with_params(cfg->program, ins, &no_loc, VSIR_OP_IEQ, 1, 2))
if (!vsir_instruction_init_with_params(cfg->program, &target->instructions[target->ins_count], {
&no_loc, VSIR_OP_BREAKP, 0, 1)) vkd3d_shader_instruction_make_nop(ins);
return VKD3D_ERROR_OUT_OF_MEMORY; return VKD3D_ERROR_OUT_OF_MEMORY;
target->instructions[target->ins_count].flags |= VKD3D_SHADER_CONDITIONAL_OP_Z; }
src_param_init_temp_bool(&target->instructions[target->ins_count].src[0], target->temp_count);
++target->ins_count;
++target->temp_count; ++target->temp_count;
dst_param_init_temp_bool(&ins->dst[0], target->temp_count - 1);
src_param_init_temp_uint(&ins->src[0], target->jump_target_temp_idx);
src_param_init_const_uint(&ins->src[1], inner_break_target);
ins = shader_instruction_array_append(&target->instructions);
if (!vsir_instruction_init_with_params(cfg->program, ins, &no_loc, VSIR_OP_BREAKP, 0, 1))
{
vkd3d_shader_instruction_make_nop(ins);
return VKD3D_ERROR_OUT_OF_MEMORY;
}
ins->flags |= VKD3D_SHADER_CONDITIONAL_OP_Z;
src_param_init_temp_bool(&ins->src[0], target->temp_count - 1);
} }
return VKD3D_OK; return VKD3D_OK;
@@ -6818,40 +6838,40 @@ static enum vkd3d_result vsir_cfg_structure_list_emit_selection(struct vsir_cfg
{ {
struct vsir_cfg_emit_target *target = cfg->target; struct vsir_cfg_emit_target *target = cfg->target;
const struct vkd3d_shader_location no_loc = {0}; const struct vkd3d_shader_location no_loc = {0};
struct vkd3d_shader_instruction *ins;
enum vkd3d_result ret; enum vkd3d_result ret;
if (!reserve_instructions(&target->instructions, &target->ins_capacity, target->ins_count + 1)) if (!(ins = shader_instruction_array_append(&target->instructions)))
return VKD3D_ERROR_OUT_OF_MEMORY; return VKD3D_ERROR_OUT_OF_MEMORY;
if (!vsir_instruction_init_with_params(cfg->program, &target->instructions[target->ins_count], if (!vsir_instruction_init_with_params(cfg->program, ins, &no_loc, VSIR_OP_IF, 0, 1))
&no_loc, VSIR_OP_IF, 0, 1)) {
vkd3d_shader_instruction_make_nop(ins);
return VKD3D_ERROR_OUT_OF_MEMORY; return VKD3D_ERROR_OUT_OF_MEMORY;
}
target->instructions[target->ins_count].src[0] = *selection->condition; ins->src[0] = *selection->condition;
if (selection->invert_condition) if (selection->invert_condition)
target->instructions[target->ins_count].flags |= VKD3D_SHADER_CONDITIONAL_OP_Z; ins->flags |= VKD3D_SHADER_CONDITIONAL_OP_Z;
++target->ins_count;
if ((ret = vsir_cfg_structure_list_emit(cfg, &selection->if_body, loop_idx)) < 0) if ((ret = vsir_cfg_structure_list_emit(cfg, &selection->if_body, loop_idx)) < 0)
return ret; return ret;
if (selection->else_body.count != 0) if (selection->else_body.count != 0)
{ {
if (!reserve_instructions(&target->instructions, &target->ins_capacity, target->ins_count + 1)) if (!(ins = shader_instruction_array_append(&target->instructions)))
return VKD3D_ERROR_OUT_OF_MEMORY; return VKD3D_ERROR_OUT_OF_MEMORY;
vsir_instruction_init(&target->instructions[target->ins_count++], &no_loc, VSIR_OP_ELSE); vsir_instruction_init(ins, &no_loc, VSIR_OP_ELSE);
if ((ret = vsir_cfg_structure_list_emit(cfg, &selection->else_body, loop_idx)) < 0) if ((ret = vsir_cfg_structure_list_emit(cfg, &selection->else_body, loop_idx)) < 0)
return ret; return ret;
} }
if (!reserve_instructions(&target->instructions, &target->ins_capacity, target->ins_count + 1)) if (!(ins = shader_instruction_array_append(&target->instructions)))
return VKD3D_ERROR_OUT_OF_MEMORY; return VKD3D_ERROR_OUT_OF_MEMORY;
vsir_instruction_init(ins, &no_loc, VSIR_OP_ENDIF);
vsir_instruction_init(&target->instructions[target->ins_count++], &no_loc, VSIR_OP_ENDIF);
return VKD3D_OK; return VKD3D_OK;
} }
@@ -6864,6 +6884,7 @@ static enum vkd3d_result vsir_cfg_structure_list_emit_jump(struct vsir_cfg *cfg,
/* Encode the jump target as the loop index plus a bit to remember whether /* Encode the jump target as the loop index plus a bit to remember whether
* we're breaking or continue-ing. */ * we're breaking or continue-ing. */
unsigned int jump_target = jump->target << 1; unsigned int jump_target = jump->target << 1;
struct vkd3d_shader_instruction *ins;
enum vkd3d_shader_opcode opcode; enum vkd3d_shader_opcode opcode;
switch (jump->type) switch (jump->type)
@@ -6894,32 +6915,34 @@ static enum vkd3d_result vsir_cfg_structure_list_emit_jump(struct vsir_cfg *cfg,
vkd3d_unreachable(); vkd3d_unreachable();
} }
if (!reserve_instructions(&target->instructions, &target->ins_capacity, target->ins_count + 2)) if (!shader_instruction_array_reserve(&target->instructions, target->instructions.count + 2))
return VKD3D_ERROR_OUT_OF_MEMORY; return VKD3D_ERROR_OUT_OF_MEMORY;
if (jump->needs_launcher) if (jump->needs_launcher)
{ {
if (!vsir_instruction_init_with_params(cfg->program, &target->instructions[target->ins_count], ins = shader_instruction_array_append(&target->instructions);
&no_loc, VSIR_OP_MOV, 1, 1)) if (!vsir_instruction_init_with_params(cfg->program, ins, &no_loc, VSIR_OP_MOV, 1, 1))
{
vkd3d_shader_instruction_make_nop(ins);
return VKD3D_ERROR_OUT_OF_MEMORY; return VKD3D_ERROR_OUT_OF_MEMORY;
}
dst_param_init_temp_uint(&target->instructions[target->ins_count].dst[0], target->jump_target_temp_idx); dst_param_init_temp_uint(&ins->dst[0], target->jump_target_temp_idx);
src_param_init_const_uint(&target->instructions[target->ins_count].src[0], jump_target); src_param_init_const_uint(&ins->src[0], jump_target);
++target->ins_count;
} }
if (!vsir_instruction_init_with_params(cfg->program, &target->instructions[target->ins_count], ins = shader_instruction_array_append(&target->instructions);
&no_loc, opcode, 0, !!jump->condition)) if (!vsir_instruction_init_with_params(cfg->program, ins, &no_loc, opcode, 0, !!jump->condition))
{
vkd3d_shader_instruction_make_nop(ins);
return VKD3D_ERROR_OUT_OF_MEMORY; return VKD3D_ERROR_OUT_OF_MEMORY;
}
if (jump->invert_condition) if (jump->invert_condition)
target->instructions[target->ins_count].flags |= VKD3D_SHADER_CONDITIONAL_OP_Z; ins->flags |= VKD3D_SHADER_CONDITIONAL_OP_Z;
if (jump->condition) if (jump->condition)
target->instructions[target->ins_count].src[0] = *jump->condition; ins->src[0] = *jump->condition;
++target->ins_count;
return VKD3D_OK; return VKD3D_OK;
} }
@@ -7011,8 +7034,8 @@ static enum vkd3d_result vsir_program_structurize(struct vsir_program *program,
{ {
struct vsir_program_iterator it = vsir_program_iterator(&program->instructions); struct vsir_program_iterator it = vsir_program_iterator(&program->instructions);
struct vkd3d_shader_message_context *message_context = ctx->message_context; struct vkd3d_shader_message_context *message_context = ctx->message_context;
struct vkd3d_shader_instruction *ins, *dst;
struct vsir_cfg_emit_target target = {0}; struct vsir_cfg_emit_target target = {0};
struct vkd3d_shader_instruction *ins;
enum vkd3d_result ret; enum vkd3d_result ret;
VKD3D_ASSERT(program->cf_type == VSIR_CF_BLOCKS); VKD3D_ASSERT(program->cf_type == VSIR_CF_BLOCKS);
@@ -7020,7 +7043,7 @@ static enum vkd3d_result vsir_program_structurize(struct vsir_program *program,
target.jump_target_temp_idx = program->temp_count; target.jump_target_temp_idx = program->temp_count;
target.temp_count = program->temp_count + 1; target.temp_count = program->temp_count + 1;
if (!reserve_instructions(&target.instructions, &target.ins_capacity, program->instructions.count)) if (!shader_instruction_array_reserve(&target.instructions, target.instructions.count))
return VKD3D_ERROR_OUT_OF_MEMORY; return VKD3D_ERROR_OUT_OF_MEMORY;
for (ins = vsir_program_iterator_head(&it); ins;) for (ins = vsir_program_iterator_head(&it); ins;)
@@ -7041,7 +7064,10 @@ static enum vkd3d_result vsir_program_structurize(struct vsir_program *program,
case VSIR_OP_HS_JOIN_PHASE: case VSIR_OP_HS_JOIN_PHASE:
VKD3D_ASSERT(program->shader_version.type == VKD3D_SHADER_TYPE_HULL); VKD3D_ASSERT(program->shader_version.type == VKD3D_SHADER_TYPE_HULL);
TRACE("Structurizing phase %u of a hull shader.\n", ins->opcode); TRACE("Structurizing phase %u of a hull shader.\n", ins->opcode);
target.instructions[target.ins_count++] = *ins;
dst = shader_instruction_array_append(&target.instructions);
*dst = *ins;
vsir_program_iterator_next(&it); vsir_program_iterator_next(&it);
if ((ret = vsir_program_structurize_function(program, message_context, &target, &it)) < 0) if ((ret = vsir_program_structurize_function(program, message_context, &target, &it)) < 0)
goto fail; goto fail;
@@ -7049,25 +7075,22 @@ static enum vkd3d_result vsir_program_structurize(struct vsir_program *program,
break; break;
default: default:
if (!reserve_instructions(&target.instructions, &target.ins_capacity, target.ins_count + 1)) if (!(dst = shader_instruction_array_append(&target.instructions)))
return VKD3D_ERROR_OUT_OF_MEMORY; return VKD3D_ERROR_OUT_OF_MEMORY;
target.instructions[target.ins_count++] = *ins; *dst = *ins;
ins = vsir_program_iterator_next(&it); ins = vsir_program_iterator_next(&it);
break; break;
} }
} }
vkd3d_free(program->instructions.elements); vsir_program_replace_instructions(program, &target.instructions);
program->instructions.elements = target.instructions;
program->instructions.capacity = target.ins_capacity;
program->instructions.count = target.ins_count;
program->temp_count = target.temp_count; program->temp_count = target.temp_count;
program->cf_type = VSIR_CF_STRUCTURED; program->cf_type = VSIR_CF_STRUCTURED;
return VKD3D_OK; return VKD3D_OK;
fail: fail:
vkd3d_free(target.instructions); shader_instruction_array_destroy(&target.instructions);
return ret; return ret;
} }