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

This commit is contained in:
Francisco Casas
2025-09-16 03:12:59 -03:00
committed by Henri Verbeet
parent ebb180c2a8
commit 27dffc9f4e
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
2 changed files with 35 additions and 38 deletions

View File

@@ -3884,7 +3884,7 @@ struct cf_flattener_switch_case
struct cf_flattener_switch_info
{
size_t ins_location;
struct vsir_program_iterator ins_it;
const struct vkd3d_shader_src_param *condition;
unsigned int id;
unsigned int merge_block_id;
@@ -3919,9 +3919,7 @@ struct cf_flattener
struct vkd3d_shader_location location;
enum vkd3d_result status;
struct vkd3d_shader_instruction *instructions;
size_t instruction_capacity;
size_t instruction_count;
struct vkd3d_shader_instruction_array instructions;
unsigned int block_id;
const char **block_names;
@@ -3944,18 +3942,6 @@ static void cf_flattener_set_error(struct cf_flattener *flattener, enum vkd3d_re
flattener->status = error;
}
static struct vkd3d_shader_instruction *cf_flattener_require_space(struct cf_flattener *flattener, size_t count)
{
if (!vkd3d_array_reserve((void **)&flattener->instructions, &flattener->instruction_capacity,
flattener->instruction_count + count, sizeof(*flattener->instructions)))
{
ERR("Failed to allocate instructions.\n");
cf_flattener_set_error(flattener, VKD3D_ERROR_OUT_OF_MEMORY);
return NULL;
}
return &flattener->instructions[flattener->instruction_count];
}
static bool cf_flattener_copy_instruction(struct cf_flattener *flattener,
const struct vkd3d_shader_instruction *instruction)
{
@@ -3964,11 +3950,10 @@ static bool cf_flattener_copy_instruction(struct cf_flattener *flattener,
if (instruction->opcode == VSIR_OP_NOP)
return true;
if (!(dst_ins = cf_flattener_require_space(flattener, 1)))
if (!(dst_ins = shader_instruction_array_append(&flattener->instructions)))
return false;
*dst_ins = *instruction;
++flattener->instruction_count;
return true;
}
@@ -3996,12 +3981,13 @@ static void cf_flattener_emit_label(struct cf_flattener *flattener, unsigned int
{
struct vkd3d_shader_instruction *ins;
if (!(ins = cf_flattener_require_space(flattener, 1)))
if (!(ins = shader_instruction_array_append(&flattener->instructions)))
return;
if (vsir_instruction_init_label(ins, &flattener->location, label_id, flattener->program))
++flattener->instruction_count;
else
if (!vsir_instruction_init_label(ins, &flattener->location, label_id, flattener->program))
{
vkd3d_shader_instruction_make_nop(ins);
cf_flattener_set_error(flattener, VKD3D_ERROR_OUT_OF_MEMORY);
}
}
/* For conditional branches, this returns the false target branch parameter. */
@@ -4013,14 +3999,17 @@ static struct vkd3d_shader_src_param *cf_flattener_emit_branch(struct cf_flatten
struct vkd3d_shader_src_param *src_params, *false_branch_param;
struct vkd3d_shader_instruction *ins;
if (!(ins = cf_flattener_require_space(flattener, 1)))
if (!(ins = shader_instruction_array_append(&flattener->instructions)))
return NULL;
vsir_instruction_init(ins, &flattener->location, VSIR_OP_BRANCH);
if (condition)
{
if (!(src_params = instruction_src_params_alloc(ins, 4 + !!continue_block_id, flattener)))
{
vkd3d_shader_instruction_make_nop(ins);
return NULL;
}
src_params[0] = *condition;
if (flags == VKD3D_SHADER_CONDITIONAL_OP_Z)
{
@@ -4041,7 +4030,10 @@ static struct vkd3d_shader_src_param *cf_flattener_emit_branch(struct cf_flatten
else
{
if (!(src_params = instruction_src_params_alloc(ins, merge_block_id ? 3 : 1, flattener)))
{
vkd3d_shader_instruction_make_nop(ins);
return NULL;
}
vsir_src_param_init_label(&src_params[0], true_id);
if (merge_block_id)
{
@@ -4053,8 +4045,6 @@ static struct vkd3d_shader_src_param *cf_flattener_emit_branch(struct cf_flatten
false_branch_param = NULL;
}
++flattener->instruction_count;
return false_branch_param;
}
@@ -4160,8 +4150,12 @@ static enum vkd3d_result cf_flattener_iterate_instruction_array(struct cf_flatte
is_hull_shader = program->shader_version.type == VKD3D_SHADER_TYPE_HULL;
after_declarations_section = is_hull_shader;
if (!cf_flattener_require_space(flattener, instructions->count + 1))
if (!shader_instruction_array_reserve(&flattener->instructions, instructions->count + 1))
{
ERR("Failed to allocate instructions.\n");
cf_flattener_set_error(flattener, VKD3D_ERROR_OUT_OF_MEMORY);
return VKD3D_ERROR_OUT_OF_MEMORY;
}
it = vsir_program_iterator(instructions);
for (instruction = vsir_program_iterator_head(&it); instruction; instruction = vsir_program_iterator_next(&it))
@@ -4301,13 +4295,14 @@ static enum vkd3d_result cf_flattener_iterate_instruction_array(struct cf_flatte
merge_block_id = cf_flattener_alloc_block_id(flattener);
cf_info->u.switch_.ins_location = flattener->instruction_count;
cf_info->u.switch_.condition = src;
if (!(dst_ins = cf_flattener_require_space(flattener, 1)))
if (!(dst_ins = shader_instruction_array_append(&flattener->instructions)))
return VKD3D_ERROR_OUT_OF_MEMORY;
vsir_instruction_init(dst_ins, &instruction->location, VSIR_OP_SWITCH_MONOLITHIC);
++flattener->instruction_count;
cf_info->u.switch_.ins_it = vsir_program_iterator(&flattener->instructions);
vsir_program_iterator_tail(&cf_info->u.switch_.ins_it);
cf_info->u.switch_.id = flattener->switch_id;
cf_info->u.switch_.merge_block_id = merge_block_id;
@@ -4340,8 +4335,12 @@ static enum vkd3d_result cf_flattener_iterate_instruction_array(struct cf_flatte
/* The SWITCH instruction is completed when the endswitch
* instruction is processed because we do not know the number
* of case statements or the default block id in advance.*/
dst_ins = &flattener->instructions[cf_info->u.switch_.ins_location];
if (!(src_params = instruction_src_params_alloc(dst_ins, cf_info->u.switch_.cases_count * 2 + 3, flattener)))
/* NOTE: This relies on iterators not being invalidated
* when new instructions are appended to the
* vkd3d_shader_instruction_array. */
dst_ins = vsir_program_iterator_current(&cf_info->u.switch_.ins_it);
if (!(src_params = instruction_src_params_alloc(dst_ins,
cf_info->u.switch_.cases_count * 2 + 3, flattener)))
{
vkd3d_free(cf_info->u.switch_.cases);
return VKD3D_ERROR_OUT_OF_MEMORY;
@@ -4504,16 +4503,13 @@ static enum vkd3d_result vsir_program_flatten_control_flow_constructs(struct vsi
if ((result = cf_flattener_iterate_instruction_array(&flattener, message_context)) >= 0)
{
vkd3d_free(program->instructions.elements);
program->instructions.elements = flattener.instructions;
program->instructions.capacity = flattener.instruction_capacity;
program->instructions.count = flattener.instruction_count;
vsir_program_replace_instructions(program, &flattener.instructions);
program->block_count = flattener.block_id;
program->cf_type = VSIR_CF_BLOCKS;
}
else
{
vkd3d_free(flattener.instructions);
shader_instruction_array_destroy(&flattener.instructions);
}
vkd3d_free(flattener.control_flow_info);

View File

@@ -1486,8 +1486,9 @@ static inline struct vkd3d_shader_instruction *vsir_program_iterator_prev(
}
/* When insertion takes place, argument `it' is updated to point to the same
* instruction as before the insertion, but all other iterators and pointers
* to the same container are invalidated and cannot be used any more. */
* instruction as before the insertion, but all existing pointers to the same
* container, as well as any iterators pointing to instructions after the
* insertion point should be considered invalid. */
static inline bool vsir_program_iterator_insert_after(struct vsir_program_iterator *it, size_t count)
{
return shader_instruction_array_insert_at(it->array, it->idx + 1, count);