Prevents any non-zero value in fields starting at bit 14 from causing the modifier flags to be skipped, and emits proper warning and fixme messages.
Signed-off-by: Conor McCarthy cmccarthy@codeweavers.com --- Supersedes patch 211558. --- libs/vkd3d-shader/dxbc.c | 60 ++++++++++++++++++++++++++++------------ libs/vkd3d-shader/sm4.h | 25 +++++++++++++---- 2 files changed, 63 insertions(+), 22 deletions(-)
diff --git a/libs/vkd3d-shader/dxbc.c b/libs/vkd3d-shader/dxbc.c index fab19046..338499cd 100644 --- a/libs/vkd3d-shader/dxbc.c +++ b/libs/vkd3d-shader/dxbc.c @@ -1123,8 +1123,9 @@ static bool shader_sm4_read_param(struct vkd3d_sm4_data *priv, const DWORD **ptr } param->data_type = data_type;
- if (token & VKD3D_SM4_REGISTER_MODIFIER) + if (token & VKD3D_SM4_EXTENDED_OPERAND) { + unsigned int type; DWORD m;
if (*ptr >= end) @@ -1133,27 +1134,52 @@ static bool shader_sm4_read_param(struct vkd3d_sm4_data *priv, const DWORD **ptr return false; } m = *(*ptr)++; + type = m & VKD3D_SM4_EXTENDED_OPERAND_TYPE_MASK;
- switch (m) + if (type == VKD3D_SM4_EXTENDED_OPERAND_MODIFIER) { - case VKD3D_SM4_REGISTER_MODIFIER_NEGATE: - *modifier = VKD3DSPSM_NEG; - break; + unsigned int min_precis = (m & VKD3D_SM4_REGISTER_MIN_PRECIS_MASK) >> VKD3D_SM4_REGISTER_MIN_PRECIS_SHIFT; + unsigned int op_mod = (m & VKD3D_SM4_REGISTER_MODIFIER_MASK) >> VKD3D_SM4_REGISTER_MODIFIER_SHIFT; + unsigned int non_uniform = + (m & VKD3D_SM4_REGISTER_NON_UNIFORM_MASK) >> VKD3D_SM4_REGISTER_NON_UNIFORM_SHIFT;
- case VKD3D_SM4_REGISTER_MODIFIER_ABS: - *modifier = VKD3DSPSM_ABS; - break; + switch (op_mod & (VKD3D_SM4_REGISTER_MODIFIER_ABS | VKD3D_SM4_REGISTER_MODIFIER_NEGATE)) + { + case VKD3D_SM4_REGISTER_MODIFIER_NEGATE: + *modifier = VKD3DSPSM_NEG; + break;
- case VKD3D_SM4_REGISTER_MODIFIER_ABS_NEGATE: - *modifier = VKD3DSPSM_ABSNEG; - break; + case VKD3D_SM4_REGISTER_MODIFIER_ABS: + *modifier = VKD3DSPSM_ABS; + break;
- default: - FIXME("Skipping modifier 0x%08x.\n", m); - /* fall-through */ - case VKD3D_SM4_REGISTER_MODIFIER_NONE: - *modifier = VKD3DSPSM_NONE; - break; + case VKD3D_SM4_REGISTER_MODIFIER_ABS | VKD3D_SM4_REGISTER_MODIFIER_NEGATE: + *modifier = VKD3DSPSM_ABSNEG; + break; + + default: + *modifier = VKD3DSPSM_NONE; + break; + } + op_mod &= ~(VKD3D_SM4_REGISTER_MODIFIER_ABS | VKD3D_SM4_REGISTER_MODIFIER_NEGATE); + if (op_mod) + FIXME("Skipping modifier flags %#x.\n", op_mod); + + if (min_precis) + WARN("Ignoring minimum precision %#x.\n", min_precis); + + if (non_uniform) + FIXME("Ignoring extended modifier NON_UNIFORM.\n"); + } + else if (type) + { + FIXME("Unhandled extended operand type %#x.\n", type); + } + + if (m & VKD3D_SM4_EXTENDED_OPERAND) + { + FIXME("Skipping second-order extended operand.\n"); + *ptr += *ptr < end; } } else diff --git a/libs/vkd3d-shader/sm4.h b/libs/vkd3d-shader/sm4.h index 335f0161..495582ca 100644 --- a/libs/vkd3d-shader/sm4.h +++ b/libs/vkd3d-shader/sm4.h @@ -93,7 +93,18 @@
#define VKD3D_SM4_OPCODE_MASK 0xff
-#define VKD3D_SM4_REGISTER_MODIFIER (0x1u << 31) +#define VKD3D_SM4_EXTENDED_OPERAND (0x1u << 31) + +#define VKD3D_SM4_EXTENDED_OPERAND_TYPE_MASK 0x1fu + +#define VKD3D_SM4_REGISTER_MODIFIER_SHIFT 6 +#define VKD3D_SM4_REGISTER_MODIFIER_MASK (0xffu << VKD3D_SM4_REGISTER_MODIFIER_SHIFT) + +#define VKD3D_SM4_REGISTER_MIN_PRECIS_SHIFT 14 +#define VKD3D_SM4_REGISTER_MIN_PRECIS_MASK (0x7u << VKD3D_SM4_REGISTER_MIN_PRECIS_SHIFT) + +#define VKD3D_SM4_REGISTER_NON_UNIFORM_SHIFT 17 +#define VKD3D_SM4_REGISTER_NON_UNIFORM_MASK (0x1u << VKD3D_SM4_REGISTER_NON_UNIFORM_SHIFT)
#define VKD3D_SM4_ADDRESSING_SHIFT2 28 #define VKD3D_SM4_ADDRESSING_MASK2 (0x3u << VKD3D_SM4_ADDRESSING_SHIFT2) @@ -381,12 +392,16 @@ enum vkd3d_sm4_register_type VKD3D_SM5_RT_DEPTHOUT_LESS_EQUAL = 0x27, };
+enum vkd3d_sm4_extended_operand_type +{ + VKD3D_SM4_EXTENDED_OPERAND_NONE = 0x0, + VKD3D_SM4_EXTENDED_OPERAND_MODIFIER = 0x1, +}; + enum vkd3d_sm4_register_modifier { - VKD3D_SM4_REGISTER_MODIFIER_NONE = 0x01, - VKD3D_SM4_REGISTER_MODIFIER_NEGATE = 0x41, - VKD3D_SM4_REGISTER_MODIFIER_ABS = 0x81, - VKD3D_SM4_REGISTER_MODIFIER_ABS_NEGATE = 0xc1, + VKD3D_SM4_REGISTER_MODIFIER_NEGATE = 0x1, + VKD3D_SM4_REGISTER_MODIFIER_ABS = 0x2, };
enum vkd3d_sm4_output_primitive_type