vkd3d-shader/ir: Add a secondary sort by sysval for signature element register merges.

Fixes output signature normalisation failures in Silent Hill 2 caused by
failure of shader_signature_find_element_for_reg().

Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=57359
This commit is contained in:
Conor McCarthy 2024-10-29 17:49:42 +10:00 committed by Henri Verbeet
parent 7412e66064
commit 3d53d90d4b
Notes: Henri Verbeet 2024-11-13 16:29:49 +01:00
Approved-by: Henri Verbeet (@hverbeet)
Merge-Request: https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/1235

View File

@ -1727,8 +1727,34 @@ static void shader_signature_map_patch_constant_index_ranges(struct shader_signa
static int signature_element_register_compare(const void *a, const void *b)
{
const struct signature_element *e = a, *f = b;
int ret;
return vkd3d_u32_compare(e->register_index, f->register_index);
if ((ret = vkd3d_u32_compare(e->register_index, f->register_index)))
return ret;
/* System values like SV_RenderTargetArrayIndex and SV_ViewPortArrayIndex
* can get packed into the same I/O register as non-system values, but
* only at the end. E.g.:
*
* vs_4_0
* ...
* .output
* ...
* .param B.x, o1.x, uint
* .param C.y, o1.y, uint
* .param SV_RenderTargetArrayIndex.z, o1.z, uint, RTINDEX
* .text
* ...
* mov o1.xy, v1.xyxx
* mov o1.z, v1.z
* ret
*
* Because I/O normalisation doesn't split writes like the mov to o1.xy
* above, we want to make sure that o1.x and o1.y continue to be packed
* into a single register after I/O normalisation, so we order system
* values after non-system values here, allowing the non-system values to
* get merged into a single register. */
return vkd3d_u32_compare(f->sysval_semantic, e->sysval_semantic);
}
static int signature_element_index_compare(const void *a, const void *b)