[PATCH vkd3d v2 2/2] vkd3d-shader: Correctly handle bit shifts greater than 31 bits.
Conor McCarthy
cmccarthy at codeweavers.com
Mon Oct 11 21:50:00 CDT 2021
This is undefined behaviour in SPIR-V, but well-defined in
DXBC, so we should explicitly 'and' the shift amount with 31.
Based on a vkd3d-proton patch by Philip Rebohle.
Signed-off-by: Conor McCarthy <cmccarthy at codeweavers.com>
---
v2: Do not skip the operation for immediate constants.
---
libs/vkd3d-shader/spirv.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c
index fab92059..23668216 100644
--- a/libs/vkd3d-shader/spirv.c
+++ b/libs/vkd3d-shader/spirv.c
@@ -6846,6 +6846,18 @@ static void vkd3d_dxbc_compiler_emit_alu_instruction(struct vkd3d_dxbc_compiler
for (i = 0; i < instruction->src_count; ++i)
src_ids[i] = vkd3d_dxbc_compiler_emit_load_src(compiler, &src[i], dst->write_mask);
+ /* The SPIR-V specification states, "The resulting value is undefined if Shift is greater than or
+ * equal to the bit width of the components of Base." D3D applies only the lowest 5 bits of the shift.
+ * Microsoft fxc will compile immediate constants larger than 5 bits. Fixing up the constants would be
+ * more elegant, but the simplest way is to let this handle constants too. */
+ if (instruction->handler_idx == VKD3DSIH_ISHL || instruction->handler_idx == VKD3DSIH_ISHR
+ || instruction->handler_idx == VKD3DSIH_USHR)
+ {
+ uint32_t mask_id = vkd3d_dxbc_compiler_get_constant_vector(compiler, VKD3D_SHADER_COMPONENT_UINT,
+ vkd3d_write_mask_component_count(dst->write_mask), 0x1f);
+ src_ids[1] = vkd3d_spirv_build_op_and(builder, type_id, src_ids[1], mask_id);
+ }
+
val_id = vkd3d_spirv_build_op_trv(builder, &builder->function_stream, op, type_id,
src_ids, instruction->src_count);
if (instruction->flags & VKD3DSI_PRECISE_XYZW)
--
2.32.0
More information about the wine-devel
mailing list