4ef2bae8
by Francisco Casas at 2026-02-17T13:46:09+01:00
vkd3d-shader/ir: Don't reach unreacheable code in vsir_dst_operand_io_normalise().
Wine-Bug: http://bugs.winehq.org/show_bug.cgi?id=59380
The application in the bug contains dxbc-tpf hs_5_0 shaders, compiled by
HLSL Shader Compiler 9.29.952.3111.
The patch constant signature looks like this:
// Name Index Mask Register SysValue Format Used
// -------------------- ----- ------ -------- -------- ------- ------
// SV_TessFactor 0 x 0 TRIEDGE float x
// PATCHCONSTANT 0 y 0 NONE uint y
// SV_TessFactor 1 x 1 TRIEDGE float x
// PATCHCONSTANT 1 y 1 NONE uint y
// SV_TessFactor 2 x 2 TRIEDGE float x
// SV_InsideTessFactor 0 x 3 TRIINT float x
However, the fork phase contains this instruction:
dcl_index_range o0.xy <v4:opaque> 2
this goes against our validator's assumptions that a dcl_index_range
doesn't overlap with more than 1 signature element for every register.
This results in the patch constant signature being transformed from:
.patch_constant
.param SV_TessFactor.x, o0.x, float, TRIEDGE
.param PATCHCONSTANT.y, o0.y, uint
.param SV_TessFactor1.x, o1.x, float, TRIEDGE
.param PATCHCONSTANT1.y, o1.y, uint
.param SV_TessFactor2.x, o2.x, float, TRIEDGE
.param SV_InsideTessFactor.x, o3.x, float, TRIINT
to:
.patch_constant
.param SV_TessFactor.x, o0.x, float, TRIEDGE
.param SV_InsideTessFactor.x, o3.x, float, TRIINT
by the vsir_program_normalise_io_registers() pass. Specifically by
shader_signature_merge().
These missing signature elements result in
vsir_dst_operand_io_normalise() reaching unreacheable code.
Since this is pretty brittle, this patch replaces the assert with
an error.
Interestingly, the only moment that relative addressing is used in this
shader is for this instruction:
mov o[r0.w <v4:i32> + 0].x <v4:f32>, r0.x <v4:f32>
so it is possible that the dcl_index_range emitted by the native
compiler had a wider write mask than necessary.