vkd3d-shader/ir: Fix r0 allocation for PS 1.x shaders.

In order to allocate it properly we have to ensure it is the first
register to be processed. The current algorithm fails to do so, so
a more explicit approach is introduced.
This commit is contained in:
Giovanni Mascellani
2025-09-19 10:44:09 +02:00
committed by Henri Verbeet
parent 89b05594f5
commit 52b9aa416b
Notes: Henri Verbeet 2025-09-19 12:54:47 +02:00
Approved-by: Henri Verbeet (@hverbeet)
Merge-Request: https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/1744

View File

@@ -8940,11 +8940,13 @@ struct temp_allocator
uint32_t temp_id;
enum vkd3d_shader_register_type type;
unsigned int idx;
bool force_first;
} *ssa_regs, *temp_regs;
size_t ssa_count, temp_count;
unsigned int new_temp_count;
enum vkd3d_result result;
uint8_t *current_allocation;
bool ps_1_x;
};
static void temp_allocator_set_src(struct temp_allocator *allocator, struct vkd3d_shader_src_param *src)
@@ -9092,15 +9094,12 @@ static int temp_allocate_compare_open(const void *ptr1, const void *ptr2)
const struct temp_allocator_reg * const *reg1 = ptr1, * const *reg2 = ptr2;
int ret;
if ((ret = vkd3d_u32_compare((*reg1)->force_first, (*reg2)->force_first)))
return -ret;
if ((ret = vkd3d_u32_compare((*reg1)->liveness_reg->first_write, (*reg2)->liveness_reg->first_write)))
return ret;
if ((ret = vkd3d_u32_compare((*reg1)->liveness_reg->last_access, (*reg2)->liveness_reg->last_access)))
return ret;
/* r0 must compare before everything else for SM 1.x PS (see comment below). */
if ((*reg1)->type == VKD3DSPR_TEMP && (*reg1)->idx == 0)
return -1;
if ((*reg2)->type == VKD3DSPR_TEMP && (*reg2)->idx == 0)
return 1;
return 0;
}
@@ -9268,6 +9267,17 @@ static enum vkd3d_result temp_allocator_compute_allocation_map(struct temp_alloc
{
reg->type = VKD3DSPR_TEMP;
reg->idx = i - allocator->ssa_count;
/* For SM 1.x ps we need to ensure that r0 is reallocated to itself,
* because it doubles as the output register. To do so we
* artificially make it alive for the whole program and make it
* compare before anything else. */
if (reg->idx == 0 && allocator->ps_1_x)
{
reg->force_first = true;
liveness->ssa_regs[i].first_write = 0;
liveness->ssa_regs[i].last_access = UINT_MAX;
}
}
reg->liveness_reg = &liveness->ssa_regs[i];
@@ -9375,15 +9385,8 @@ enum vkd3d_result vsir_allocate_temp_registers(struct vsir_program *program,
allocator.temp_regs = regs + program->ssa_count;
allocator.new_temp_count = 0;
/* For SM 1.x ps we need to ensure that r0 is reallocated to itself, because
* it doubles as the output register. To do so we artificially make it
* alive for the whole program. */
if (program->shader_version.type == VKD3D_SHADER_TYPE_PIXEL
&& program->shader_version.major < 2 && allocator.temp_count >= 1)
{
tracker.temp_regs[0].first_write = 0;
tracker.temp_regs[0].last_access = UINT_MAX;
}
if (program->shader_version.type == VKD3D_SHADER_TYPE_PIXEL && program->shader_version.major < 2)
allocator.ps_1_x = true;
if ((ret = temp_allocator_compute_allocation_map(&allocator, &tracker)) < 0)
{