From 3d53d90d4b67232ebcbe0063ab1a84e2d40a2f51 Mon Sep 17 00:00:00 2001 From: Conor McCarthy Date: Tue, 29 Oct 2024 17:49:42 +1000 Subject: [PATCH] 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 --- libs/vkd3d-shader/ir.c | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/libs/vkd3d-shader/ir.c b/libs/vkd3d-shader/ir.c index 836e0ade..10b172ad 100644 --- a/libs/vkd3d-shader/ir.c +++ b/libs/vkd3d-shader/ir.c @@ -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)