mirror of
https://gitlab.winehq.org/wine/vkd3d.git
synced 2025-01-28 13:05:02 -08:00
vkd3d-shader/ir: Split handling jumps when emitting a structured program.
This commit is contained in:
parent
1a8a4c7787
commit
a7dc6dcce2
Notes:
Alexandre Julliard
2024-04-15 22:22:40 +02:00
Approved-by: Giovanni Mascellani (@giomasce) Approved-by: Conor McCarthy (@cmccarthy) Approved-by: Henri Verbeet (@hverbeet) Approved-by: Alexandre Julliard (@julliard) Merge-Request: https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/778
@ -2929,7 +2929,7 @@ struct vsir_cfg_structure
|
|||||||
struct vsir_cfg_structure_list else_body;
|
struct vsir_cfg_structure_list else_body;
|
||||||
bool invert_condition;
|
bool invert_condition;
|
||||||
} selection;
|
} selection;
|
||||||
struct
|
struct vsir_cfg_structure_jump
|
||||||
{
|
{
|
||||||
enum vsir_cfg_jump_type
|
enum vsir_cfg_jump_type
|
||||||
{
|
{
|
||||||
@ -4579,11 +4579,77 @@ static enum vkd3d_result vsir_cfg_structure_list_emit_selection(struct vsir_cfg
|
|||||||
return VKD3D_OK;
|
return VKD3D_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum vkd3d_result vsir_cfg_structure_list_emit(struct vsir_cfg *cfg,
|
static enum vkd3d_result vsir_cfg_structure_list_emit_jump(struct vsir_cfg *cfg,
|
||||||
struct vsir_cfg_structure_list *list, unsigned int loop_idx)
|
struct vsir_cfg_structure_jump *jump, unsigned int loop_idx)
|
||||||
{
|
{
|
||||||
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};
|
||||||
|
/* 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;
|
enum vkd3d_result ret;
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
@ -4610,68 +4676,10 @@ static enum vkd3d_result vsir_cfg_structure_list_emit(struct vsir_cfg *cfg,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case STRUCTURE_TYPE_JUMP:
|
case STRUCTURE_TYPE_JUMP:
|
||||||
{
|
if ((ret = vsir_cfg_structure_list_emit_jump(cfg, &structure->u.jump,
|
||||||
/* Encode the jump target as the loop index plus a bit to remember whether
|
loop_idx)) < 0)
|
||||||
* we're breaking or continueing. */
|
return ret;
|
||||||
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;
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
vkd3d_unreachable();
|
vkd3d_unreachable();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user