Wine-Devel
By thread
wine-devel@list.winehq.org
By month
Messages by month
- ----- 2026 -----
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2001 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
January 2022
- 86 participants
- 2418 messages
[PATCH vkd3d v6 4/9] vkd3d-shader/hlsl: Add support for sm4 instruction modifiers.
by Matteo Bruni
From: Francisco Casas <fcasas(a)codeweavers.com>
Signed-off-by: Francisco Casas <fcasas(a)codeweavers.com>
Signed-off-by: Zebediah Figura <zfigura(a)codeweavers.com>
Signed-off-by: Giovanni Mascellani <gmascellani(a)codeweavers.com>
Signed-off-by: Matteo Bruni <mbruni(a)codeweavers.com>
---
libs/vkd3d-shader/hlsl_sm4.c | 53 ++++++++++++++++++++++++++++++++++++
1 file changed, 53 insertions(+)
diff --git a/libs/vkd3d-shader/hlsl_sm4.c b/libs/vkd3d-shader/hlsl_sm4.c
index 3982a9b8..21d6c0d4 100644
--- a/libs/vkd3d-shader/hlsl_sm4.c
+++ b/libs/vkd3d-shader/hlsl_sm4.c
@@ -727,6 +727,44 @@ static enum vkd3d_sm4_resource_type sm4_resource_dimension(const struct hlsl_typ
}
}
+struct sm4_instruction_modifier
+{
+ enum vkd3d_sm4_instruction_modifier type;
+
+ union
+ {
+ struct
+ {
+ int u, v, w;
+ } aoffimmi;
+ } u;
+};
+
+static uint32_t sm4_encode_instruction_modifier(const struct sm4_instruction_modifier *imod)
+{
+ uint32_t word = 0;
+
+ word |= VKD3D_SM4_MODIFIER_MASK & imod->type;
+
+ switch (imod->type)
+ {
+ case VKD3D_SM4_MODIFIER_AOFFIMMI:
+ assert(-8 <= imod->u.aoffimmi.u && imod->u.aoffimmi.u <= 7);
+ assert(-8 <= imod->u.aoffimmi.v && imod->u.aoffimmi.v <= 7);
+ assert(-8 <= imod->u.aoffimmi.w && imod->u.aoffimmi.w <= 7);
+ word |= ((uint32_t)imod->u.aoffimmi.u & 0xf) << VKD3D_SM4_AOFFIMMI_U_SHIFT;
+ word |= ((uint32_t)imod->u.aoffimmi.v & 0xf) << VKD3D_SM4_AOFFIMMI_V_SHIFT;
+ word |= ((uint32_t)imod->u.aoffimmi.w & 0xf) << VKD3D_SM4_AOFFIMMI_W_SHIFT;
+ break;
+
+ default:
+ assert(0);
+ break;
+ }
+
+ return word;
+}
+
struct sm4_register
{
enum vkd3d_sm4_register_type type;
@@ -741,6 +779,9 @@ struct sm4_instruction
{
enum vkd3d_sm4_opcode opcode;
+ struct sm4_instruction_modifier modifiers[1];
+ unsigned int modifier_count;
+
struct sm4_dst_register
{
struct sm4_register reg;
@@ -939,6 +980,7 @@ static void write_sm4_instruction(struct vkd3d_bytecode_buffer *buffer, const st
uint32_t token = instr->opcode;
unsigned int size = 1, i, j;
+ size += instr->modifier_count;
for (i = 0; i < instr->dst_count; ++i)
size += sm4_register_order(&instr->dsts[i].reg);
for (i = 0; i < instr->src_count; ++i)
@@ -946,8 +988,19 @@ static void write_sm4_instruction(struct vkd3d_bytecode_buffer *buffer, const st
size += instr->idx_count;
token |= (size << VKD3D_SM4_INSTRUCTION_LENGTH_SHIFT);
+
+ if (instr->modifier_count > 0)
+ token |= VKD3D_SM4_INSTRUCTION_MODIFIER;
put_u32(buffer, token);
+ for (i = 0; i < instr->modifier_count; ++i)
+ {
+ token = sm4_encode_instruction_modifier(&instr->modifiers[i]);
+ if (instr->modifier_count > i + 1)
+ token |= VKD3D_SM4_INSTRUCTION_MODIFIER;
+ put_u32(buffer, token);
+ }
+
for (i = 0; i < instr->dst_count; ++i)
{
token = sm4_encode_register(&instr->dsts[i].reg);
--
2.34.1
Jan. 26, 2022
[PATCH vkd3d v6 3/9] vkd3d-shader/hlsl: Introduce a sm4_dst_from_node() helper.
by Matteo Bruni
From: Zebediah Figura <zfigura(a)codeweavers.com>
Signed-off-by: Zebediah Figura <zfigura(a)codeweavers.com>
Signed-off-by: Giovanni Mascellani <gmascellani(a)codeweavers.com>
Signed-off-by: Matteo Bruni <mbruni(a)codeweavers.com>
---
libs/vkd3d-shader/hlsl_sm4.c | 26 ++++++++++++++++----------
1 file changed, 16 insertions(+), 10 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl_sm4.c b/libs/vkd3d-shader/hlsl_sm4.c
index 714e237d..3982a9b8 100644
--- a/libs/vkd3d-shader/hlsl_sm4.c
+++ b/libs/vkd3d-shader/hlsl_sm4.c
@@ -741,7 +741,7 @@ struct sm4_instruction
{
enum vkd3d_sm4_opcode opcode;
- struct
+ struct sm4_dst_register
{
struct sm4_register reg;
unsigned int writemask;
@@ -893,13 +893,19 @@ static void sm4_register_from_node(struct sm4_register *reg, unsigned int *write
assert(instr->reg.allocated);
reg->type = VKD3D_SM4_RT_TEMP;
reg->dim = VKD3D_SM4_DIMENSION_VEC4;
- if (swizzle_type)
- *swizzle_type = VKD3D_SM4_SWIZZLE_VEC4;
+ *swizzle_type = VKD3D_SM4_SWIZZLE_VEC4;
reg->idx[0] = instr->reg.id;
reg->idx_count = 1;
*writemask = instr->reg.writemask;
}
+static void sm4_dst_from_node(struct sm4_dst_register *dst, const struct hlsl_ir_node *instr)
+{
+ unsigned int swizzle_type;
+
+ sm4_register_from_node(&dst->reg, &dst->writemask, &swizzle_type, instr);
+}
+
static void sm4_src_from_node(struct sm4_src_register *src,
const struct hlsl_ir_node *instr, unsigned int map_writemask)
{
@@ -1156,7 +1162,7 @@ static void write_sm4_unary_op(struct vkd3d_bytecode_buffer *buffer, enum vkd3d_
memset(&instr, 0, sizeof(instr));
instr.opcode = opcode;
- sm4_register_from_node(&instr.dsts[0].reg, &instr.dsts[0].writemask, NULL, dst);
+ sm4_dst_from_node(&instr.dsts[0], dst);
instr.dst_count = 1;
sm4_src_from_node(&instr.srcs[0], src, instr.dsts[0].writemask);
@@ -1174,7 +1180,7 @@ static void write_sm4_binary_op(struct vkd3d_bytecode_buffer *buffer, enum vkd3d
memset(&instr, 0, sizeof(instr));
instr.opcode = opcode;
- sm4_register_from_node(&instr.dsts[0].reg, &instr.dsts[0].writemask, NULL, dst);
+ sm4_dst_from_node(&instr.dsts[0], dst);
instr.dst_count = 1;
sm4_src_from_node(&instr.srcs[0], src1, instr.dsts[0].writemask);
@@ -1194,7 +1200,7 @@ static void write_sm4_constant(struct hlsl_ctx *ctx,
memset(&instr, 0, sizeof(instr));
instr.opcode = VKD3D_SM4_OP_MOV;
- sm4_register_from_node(&instr.dsts[0].reg, &instr.dsts[0].writemask, NULL, &constant->node);
+ sm4_dst_from_node(&instr.dsts[0], &constant->node);
instr.dst_count = 1;
instr.srcs[0].swizzle_type = VKD3D_SM4_SWIZZLE_NONE;
@@ -1229,7 +1235,7 @@ static void write_sm4_ld(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *buf
memset(&instr, 0, sizeof(instr));
instr.opcode = VKD3D_SM4_OP_LD;
- sm4_register_from_node(&instr.dsts[0].reg, &instr.dsts[0].writemask, NULL, dst);
+ sm4_dst_from_node(&instr.dsts[0], dst);
instr.dst_count = 1;
sm4_src_from_node(&instr.srcs[0], coords, VKD3DSP_WRITEMASK_ALL);
@@ -1270,7 +1276,7 @@ static void write_sm4_sample(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer
memset(&instr, 0, sizeof(instr));
instr.opcode = VKD3D_SM4_OP_SAMPLE;
- sm4_register_from_node(&instr.dsts[0].reg, &instr.dsts[0].writemask, NULL, dst);
+ sm4_dst_from_node(&instr.dsts[0], dst);
instr.dst_count = 1;
sm4_src_from_node(&instr.srcs[0], coords, VKD3DSP_WRITEMASK_ALL);
@@ -1653,7 +1659,7 @@ static void write_sm4_load(struct hlsl_ctx *ctx,
memset(&instr, 0, sizeof(instr));
instr.opcode = VKD3D_SM4_OP_MOV;
- sm4_register_from_node(&instr.dsts[0].reg, &instr.dsts[0].writemask, NULL, &load->node);
+ sm4_dst_from_node(&instr.dsts[0], &load->node);
instr.dst_count = 1;
sm4_src_from_deref(ctx, &instr.srcs[0], &load->src, load->node.data_type, instr.dsts[0].writemask);
@@ -1754,7 +1760,7 @@ static void write_sm4_swizzle(struct hlsl_ctx *ctx,
memset(&instr, 0, sizeof(instr));
instr.opcode = VKD3D_SM4_OP_MOV;
- sm4_register_from_node(&instr.dsts[0].reg, &instr.dsts[0].writemask, NULL, &swizzle->node);
+ sm4_dst_from_node(&instr.dsts[0], &swizzle->node);
instr.dst_count = 1;
sm4_register_from_node(&instr.srcs[0].reg, &writemask, &instr.srcs[0].swizzle_type, swizzle->val.node);
--
2.34.1
Jan. 26, 2022
[PATCH vkd3d v6 2/9] vkd3d-shader/hlsl: Introduce a sm4_src_from_deref() helper.
by Matteo Bruni
From: Zebediah Figura <zfigura(a)codeweavers.com>
Signed-off-by: Zebediah Figura <zfigura(a)codeweavers.com>
Signed-off-by: Giovanni Mascellani <gmascellani(a)codeweavers.com>
Signed-off-by: Matteo Bruni <mbruni(a)codeweavers.com>
---
libs/vkd3d-shader/hlsl_sm4.c | 31 ++++++++++++++-----------------
1 file changed, 14 insertions(+), 17 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl_sm4.c b/libs/vkd3d-shader/hlsl_sm4.c
index 082c1c28..714e237d 100644
--- a/libs/vkd3d-shader/hlsl_sm4.c
+++ b/libs/vkd3d-shader/hlsl_sm4.c
@@ -877,6 +877,16 @@ static void sm4_register_from_deref(struct hlsl_ctx *ctx, struct sm4_register *r
}
}
+static void sm4_src_from_deref(struct hlsl_ctx *ctx, struct sm4_src_register *src,
+ const struct hlsl_deref *deref, const struct hlsl_type *data_type, unsigned int map_writemask)
+{
+ unsigned int writemask;
+
+ sm4_register_from_deref(ctx, &src->reg, &writemask, &src->swizzle_type, deref, data_type);
+ if (src->swizzle_type == VKD3D_SM4_SWIZZLE_VEC4)
+ src->swizzle = hlsl_map_swizzle(hlsl_swizzle_from_writemask(writemask), map_writemask);
+}
+
static void sm4_register_from_node(struct sm4_register *reg, unsigned int *writemask,
enum vkd3d_sm4_swizzle_type *swizzle_type, const struct hlsl_ir_node *instr)
{
@@ -1215,7 +1225,6 @@ static void write_sm4_ld(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *buf
const struct hlsl_deref *resource, const struct hlsl_ir_node *coords)
{
struct sm4_instruction instr;
- unsigned int writemask;
memset(&instr, 0, sizeof(instr));
instr.opcode = VKD3D_SM4_OP_LD;
@@ -1245,9 +1254,7 @@ static void write_sm4_ld(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *buf
assert(0);
}
- sm4_register_from_deref(ctx, &instr.srcs[1].reg, &writemask, &instr.srcs[1].swizzle_type,
- resource, resource_type);
- instr.srcs[1].swizzle = hlsl_map_swizzle(hlsl_swizzle_from_writemask(writemask), instr.dsts[0].writemask);
+ sm4_src_from_deref(ctx, &instr.srcs[1], resource, resource_type, instr.dsts[0].writemask);
instr.src_count = 2;
@@ -1259,7 +1266,6 @@ static void write_sm4_sample(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer
const struct hlsl_deref *resource, const struct hlsl_deref *sampler, const struct hlsl_ir_node *coords)
{
struct sm4_instruction instr;
- unsigned int writemask;
memset(&instr, 0, sizeof(instr));
instr.opcode = VKD3D_SM4_OP_SAMPLE;
@@ -1268,14 +1274,8 @@ static void write_sm4_sample(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer
instr.dst_count = 1;
sm4_src_from_node(&instr.srcs[0], coords, VKD3DSP_WRITEMASK_ALL);
-
- sm4_register_from_deref(ctx, &instr.srcs[1].reg, &writemask,
- &instr.srcs[1].swizzle_type, resource, resource_type);
- instr.srcs[1].swizzle = hlsl_map_swizzle(hlsl_swizzle_from_writemask(writemask), instr.dsts[0].writemask);
-
- sm4_register_from_deref(ctx, &instr.srcs[2].reg, &writemask,
- &instr.srcs[2].swizzle_type, sampler, sampler->var->data_type);
-
+ sm4_src_from_deref(ctx, &instr.srcs[1], resource, resource_type, instr.dsts[0].writemask);
+ sm4_src_from_deref(ctx, &instr.srcs[2], sampler, sampler->var->data_type, VKD3DSP_WRITEMASK_ALL);
instr.src_count = 3;
write_sm4_instruction(buffer, &instr);
@@ -1649,7 +1649,6 @@ static void write_sm4_load(struct hlsl_ctx *ctx,
struct vkd3d_bytecode_buffer *buffer, const struct hlsl_ir_load *load)
{
struct sm4_instruction instr;
- unsigned int writemask;
memset(&instr, 0, sizeof(instr));
instr.opcode = VKD3D_SM4_OP_MOV;
@@ -1657,9 +1656,7 @@ static void write_sm4_load(struct hlsl_ctx *ctx,
sm4_register_from_node(&instr.dsts[0].reg, &instr.dsts[0].writemask, NULL, &load->node);
instr.dst_count = 1;
- sm4_register_from_deref(ctx, &instr.srcs[0].reg, &writemask, &instr.srcs[0].swizzle_type,
- &load->src, load->node.data_type);
- instr.srcs[0].swizzle = hlsl_map_swizzle(hlsl_swizzle_from_writemask(writemask), instr.dsts[0].writemask);
+ sm4_src_from_deref(ctx, &instr.srcs[0], &load->src, load->node.data_type, instr.dsts[0].writemask);
instr.src_count = 1;
write_sm4_instruction(buffer, &instr);
--
2.34.1
Jan. 26, 2022
[PATCH vkd3d v6 1/9] vkd3d-shader/hlsl: Introduce a sm4_src_from_node() helper.
by Matteo Bruni
From: Zebediah Figura <zfigura(a)codeweavers.com>
Signed-off-by: Zebediah Figura <zfigura(a)codeweavers.com>
Signed-off-by: Giovanni Mascellani <gmascellani(a)codeweavers.com>
Signed-off-by: Matteo Bruni <mbruni(a)codeweavers.com>
---
libs/vkd3d-shader/hlsl_sm4.c | 36 ++++++++++++++++++------------------
1 file changed, 18 insertions(+), 18 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl_sm4.c b/libs/vkd3d-shader/hlsl_sm4.c
index 8fc4e738..082c1c28 100644
--- a/libs/vkd3d-shader/hlsl_sm4.c
+++ b/libs/vkd3d-shader/hlsl_sm4.c
@@ -748,7 +748,7 @@ struct sm4_instruction
} dsts[1];
unsigned int dst_count;
- struct
+ struct sm4_src_register
{
struct sm4_register reg;
enum vkd3d_sm4_swizzle_type swizzle_type;
@@ -890,6 +890,16 @@ static void sm4_register_from_node(struct sm4_register *reg, unsigned int *write
*writemask = instr->reg.writemask;
}
+static void sm4_src_from_node(struct sm4_src_register *src,
+ const struct hlsl_ir_node *instr, unsigned int map_writemask)
+{
+ unsigned int writemask;
+
+ sm4_register_from_node(&src->reg, &writemask, &src->swizzle_type, instr);
+ if (src->swizzle_type == VKD3D_SM4_SWIZZLE_VEC4)
+ src->swizzle = hlsl_map_swizzle(hlsl_swizzle_from_writemask(writemask), map_writemask);
+}
+
static uint32_t sm4_encode_register(const struct sm4_register *reg)
{
return (reg->type << VKD3D_SM4_REGISTER_TYPE_SHIFT)
@@ -1132,7 +1142,6 @@ static void write_sm4_unary_op(struct vkd3d_bytecode_buffer *buffer, enum vkd3d_
const struct hlsl_ir_node *dst, const struct hlsl_ir_node *src, unsigned int src_mod)
{
struct sm4_instruction instr;
- unsigned int writemask;
memset(&instr, 0, sizeof(instr));
instr.opcode = opcode;
@@ -1140,8 +1149,7 @@ static void write_sm4_unary_op(struct vkd3d_bytecode_buffer *buffer, enum vkd3d_
sm4_register_from_node(&instr.dsts[0].reg, &instr.dsts[0].writemask, NULL, dst);
instr.dst_count = 1;
- sm4_register_from_node(&instr.srcs[0].reg, &writemask, &instr.srcs[0].swizzle_type, src);
- instr.srcs[0].swizzle = hlsl_map_swizzle(hlsl_swizzle_from_writemask(writemask), instr.dsts[0].writemask);
+ sm4_src_from_node(&instr.srcs[0], src, instr.dsts[0].writemask);
instr.srcs[0].reg.mod = src_mod;
instr.src_count = 1;
@@ -1152,7 +1160,6 @@ static void write_sm4_binary_op(struct vkd3d_bytecode_buffer *buffer, enum vkd3d
const struct hlsl_ir_node *dst, const struct hlsl_ir_node *src1, const struct hlsl_ir_node *src2)
{
struct sm4_instruction instr;
- unsigned int writemask;
memset(&instr, 0, sizeof(instr));
instr.opcode = opcode;
@@ -1160,10 +1167,8 @@ static void write_sm4_binary_op(struct vkd3d_bytecode_buffer *buffer, enum vkd3d
sm4_register_from_node(&instr.dsts[0].reg, &instr.dsts[0].writemask, NULL, dst);
instr.dst_count = 1;
- sm4_register_from_node(&instr.srcs[0].reg, &writemask, &instr.srcs[0].swizzle_type, src1);
- instr.srcs[0].swizzle = hlsl_map_swizzle(hlsl_swizzle_from_writemask(writemask), instr.dsts[0].writemask);
- sm4_register_from_node(&instr.srcs[1].reg, &writemask, &instr.srcs[1].swizzle_type, src2);
- instr.srcs[1].swizzle = hlsl_map_swizzle(hlsl_swizzle_from_writemask(writemask), instr.dsts[0].writemask);
+ sm4_src_from_node(&instr.srcs[0], src1, instr.dsts[0].writemask);
+ sm4_src_from_node(&instr.srcs[1], src2, instr.dsts[0].writemask);
instr.src_count = 2;
write_sm4_instruction(buffer, &instr);
@@ -1218,8 +1223,7 @@ static void write_sm4_ld(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *buf
sm4_register_from_node(&instr.dsts[0].reg, &instr.dsts[0].writemask, NULL, dst);
instr.dst_count = 1;
- sm4_register_from_node(&instr.srcs[0].reg, &writemask, &instr.srcs[0].swizzle_type, coords);
- instr.srcs[0].swizzle = hlsl_swizzle_from_writemask(writemask);
+ sm4_src_from_node(&instr.srcs[0], coords, VKD3DSP_WRITEMASK_ALL);
/* Mipmap level is in the last component in the IR, but needs to be in the W
* component in the instruction. */
@@ -1263,8 +1267,7 @@ static void write_sm4_sample(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer
sm4_register_from_node(&instr.dsts[0].reg, &instr.dsts[0].writemask, NULL, dst);
instr.dst_count = 1;
- sm4_register_from_node(&instr.srcs[0].reg, &writemask, &instr.srcs[0].swizzle_type, coords);
- instr.srcs[0].swizzle = hlsl_swizzle_from_writemask(writemask);
+ sm4_src_from_node(&instr.srcs[0], coords, VKD3DSP_WRITEMASK_ALL);
sm4_register_from_deref(ctx, &instr.srcs[1].reg, &writemask,
&instr.srcs[1].swizzle_type, resource, resource_type);
@@ -1621,12 +1624,10 @@ static void write_sm4_if(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *buf
.opcode = VKD3D_SM4_OP_IF | VKD3D_SM4_CONDITIONAL_NZ,
.src_count = 1,
};
- unsigned int writemask;
assert(iff->condition.node->data_type->dimx == 1);
- sm4_register_from_node(&instr.srcs[0].reg, &writemask, &instr.srcs[0].swizzle_type, iff->condition.node);
- instr.srcs[0].swizzle = hlsl_swizzle_from_writemask(writemask);
+ sm4_src_from_node(&instr.srcs[0], iff->condition.node, VKD3DSP_WRITEMASK_ALL);
write_sm4_instruction(buffer, &instr);
write_sm4_block(ctx, buffer, &iff->then_instrs);
@@ -1741,8 +1742,7 @@ static void write_sm4_store(struct hlsl_ctx *ctx,
instr.dsts[0].writemask = hlsl_combine_writemasks(writemask, store->writemask);
instr.dst_count = 1;
- sm4_register_from_node(&instr.srcs[0].reg, &writemask, &instr.srcs[0].swizzle_type, rhs);
- instr.srcs[0].swizzle = hlsl_map_swizzle(hlsl_swizzle_from_writemask(writemask), instr.dsts[0].writemask);
+ sm4_src_from_node(&instr.srcs[0], rhs, instr.dsts[0].writemask);
instr.src_count = 1;
write_sm4_instruction(buffer, &instr);
--
2.34.1
Jan. 26, 2022
Re: [PATCH v2 5/6] winhttp: Don't send pong on timeout in socket_receive().
by Paul Gofman
On 1/26/22 17:26, Hans Leidekker wrote:
> On Wed, 2022-01-26 at 16:14 +0300, Paul Gofman wrote:
>> Signed-off-by: Paul Gofman <pgofman(a)codeweavers.com>
>> ---
>> v2:
>> - no changes.
>>
>> As testing involves waiting for timeouts it doesn't look good for inclusion into the test suite.
>> I've tested this change separately: https://gist.github.com/gofman/bd2f3b6fd6cbe993e97353560ce81e04
>> This test succeeds on Windows for me but fails without this patch in Wine: the server close status received
>> during closing handshake becomes WINHTTP_WEB_SOCKET_PROTOCOL_ERROR_CLOSE_STATUS (1002).
>>
>> Sending ping instead of pong causes the server to send a pong reply as expected although I still see status
>> 1002 on close after. Which probably suggests that Windows doesn't send the ping as well (I also tried that with
>> WINHTTP_OPTION_WEB_SOCKET_KEEPALIVE_INTERVAL socket option set to 15000 and Sleep to 30000).
> It should be an unsollicited pong, which serves as a keepalive packet. I'm
> pretty sure I observed this, although I don't remember the exact conditions.
>
>
>
I did observer unsolicited pong from server with Halo Infinite servers.
Although I am not sure if we should do anything with it (sending some
app callback?) instead of ignoring.
Jan. 26, 2022
Re: [PATCH v2 5/6] winhttp: Don't send pong on timeout in socket_receive().
by Hans Leidekker
On Wed, 2022-01-26 at 16:14 +0300, Paul Gofman wrote:
> Signed-off-by: Paul Gofman <pgofman(a)codeweavers.com>
> ---
> v2:
> - no changes.
>
> As testing involves waiting for timeouts it doesn't look good for inclusion into the test suite.
> I've tested this change separately: https://gist.github.com/gofman/bd2f3b6fd6cbe993e97353560ce81e04
> This test succeeds on Windows for me but fails without this patch in Wine: the server close status received
> during closing handshake becomes WINHTTP_WEB_SOCKET_PROTOCOL_ERROR_CLOSE_STATUS (1002).
>
> Sending ping instead of pong causes the server to send a pong reply as expected although I still see status
> 1002 on close after. Which probably suggests that Windows doesn't send the ping as well (I also tried that with
> WINHTTP_OPTION_WEB_SOCKET_KEEPALIVE_INTERVAL socket option set to 15000 and Sleep to 30000).
It should be an unsollicited pong, which serves as a keepalive packet. I'm
pretty sure I observed this, although I don't remember the exact conditions.
Jan. 26, 2022
[PATCH v2 5/5] winhttp: Remove and extra pending_sends increment in WinHttpWebSocketSend().
by Hans Leidekker
From: Paul Gofman <pgofman(a)codeweavers.com>
Signed-off-by: Paul Gofman <pgofman(a)codeweavers.com>
Signed-off-by: Hans Leidekker <hans(a)codeweavers.com>
---
dlls/winhttp/request.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/dlls/winhttp/request.c b/dlls/winhttp/request.c
index 279e0522166..cbfe2b21bd0 100644
--- a/dlls/winhttp/request.c
+++ b/dlls/winhttp/request.c
@@ -3375,7 +3375,6 @@ DWORD WINAPI WinHttpWebSocketSend( HINTERNET hsocket, WINHTTP_WEB_SOCKET_BUFFER_
release_object( &socket->hdr );
free( s );
}
- else ++socket->hdr.pending_sends;
}
else
{
--
2.30.2
Jan. 26, 2022
[PATCH v2 4/5] winhttp: Return error from WinHttpWebSocketQueryCloseStatus() if close frame was not received.
by Hans Leidekker
From: Paul Gofman <pgofman(a)codeweavers.com>
Signed-off-by: Paul Gofman <pgofman(a)codeweavers.com>
Signed-off-by: Hans Leidekker <hans(a)codeweavers.com>
---
dlls/winhttp/request.c | 6 ++++++
dlls/winhttp/tests/notification.c | 6 +++---
2 files changed, 9 insertions(+), 3 deletions(-)
diff --git a/dlls/winhttp/request.c b/dlls/winhttp/request.c
index 39223d41bbb..279e0522166 100644
--- a/dlls/winhttp/request.c
+++ b/dlls/winhttp/request.c
@@ -3909,6 +3909,12 @@ DWORD WINAPI WinHttpWebSocketQueryCloseStatus( HINTERNET hsocket, USHORT *status
return ERROR_INVALID_OPERATION;
}
+ if (!socket->close_frame_received || socket->close_frame_receive_err)
+ {
+ ret = socket->close_frame_received ? socket->close_frame_receive_err : ERROR_INVALID_OPERATION;
+ release_object( &socket->hdr );
+ return ret;
+ }
*status = socket->status;
*ret_len = socket->reason_len;
if (socket->reason_len > len) ret = ERROR_INSUFFICIENT_BUFFER;
diff --git a/dlls/winhttp/tests/notification.c b/dlls/winhttp/tests/notification.c
index c57c0ef598a..cab87df339d 100644
--- a/dlls/winhttp/tests/notification.c
+++ b/dlls/winhttp/tests/notification.c
@@ -971,9 +971,9 @@ static void test_websocket(BOOL secure)
close_status = 0xdead;
size = sizeof(buffer) + 1;
err = pWinHttpWebSocketQueryCloseStatus( socket, &close_status, buffer, sizeof(buffer), &size );
- todo_wine ok( err == ERROR_INVALID_OPERATION, "got %u\n", err );
- todo_wine ok( close_status == 0xdead, "got %u\n", close_status );
- todo_wine ok( size == sizeof(buffer) + 1, "got %u\n", size );
+ ok( err == ERROR_INVALID_OPERATION, "got %u\n", err );
+ ok( close_status == 0xdead, "got %u\n", close_status );
+ ok( size == sizeof(buffer) + 1, "got %u\n", size );
WaitForSingleObject( info.wait, INFINITE );
--
2.30.2
Jan. 26, 2022
[PATCH v2 3/5] winhttp: Send callback for pending receives right away when closing websocket.
by Hans Leidekker
From: Paul Gofman <pgofman(a)codeweavers.com>
v2: Fix printf format warning.
Signed-off-by: Paul Gofman <pgofman(a)codeweavers.com>
Signed-off-by: Hans Leidekker <hans(a)codeweavers.com>
---
dlls/winhttp/request.c | 65 ++++++++++++++++++++++---------
dlls/winhttp/tests/notification.c | 18 ++++++++-
2 files changed, 63 insertions(+), 20 deletions(-)
diff --git a/dlls/winhttp/request.c b/dlls/winhttp/request.c
index 7666bae4e68..39223d41bbb 100644
--- a/dlls/winhttp/request.c
+++ b/dlls/winhttp/request.c
@@ -3244,10 +3244,14 @@ static void send_io_complete( struct object_header *hdr )
assert( count >= 0 );
}
-static void receive_io_complete( struct socket *socket )
+/* returns FALSE if sending callback should be omitted. */
+static BOOL receive_io_complete( struct socket *socket )
{
LONG count = InterlockedDecrement( &socket->hdr.pending_receives );
- assert( count >= 0 );
+ assert( count >= 0 || socket->state == SOCKET_STATE_CLOSED);
+ /* count is reset to zero during websocket close so if count went negative
+ * then WinHttpWebSocketClose() is to send the callback. */
+ return count >= 0;
}
static enum socket_opcode map_buffer_type( WINHTTP_WEB_SOCKET_BUFFER_TYPE type )
@@ -3620,22 +3624,24 @@ static void CALLBACK task_socket_receive( TP_CALLBACK_INSTANCE *instance, void *
TRACE("running %p\n", work);
ret = socket_receive( r->socket, r->buf, r->len, &count, &type );
- receive_io_complete( r->socket );
- if (!ret)
- {
- WINHTTP_WEB_SOCKET_STATUS status;
- status.dwBytesTransferred = count;
- status.eBufferType = type;
- send_callback( &r->socket->hdr, WINHTTP_CALLBACK_STATUS_READ_COMPLETE, &status, sizeof(status) );
- }
- else
+ if (receive_io_complete( r->socket ))
{
- WINHTTP_WEB_SOCKET_ASYNC_RESULT result;
- result.AsyncResult.dwResult = API_READ_DATA;
- result.AsyncResult.dwError = ret;
- result.Operation = WINHTTP_WEB_SOCKET_RECEIVE_OPERATION;
- send_callback( &r->socket->hdr, WINHTTP_CALLBACK_STATUS_REQUEST_ERROR, &result, sizeof(result) );
+ if (!ret)
+ {
+ WINHTTP_WEB_SOCKET_STATUS status;
+ status.dwBytesTransferred = count;
+ status.eBufferType = type;
+ send_callback( &r->socket->hdr, WINHTTP_CALLBACK_STATUS_READ_COMPLETE, &status, sizeof(status) );
+ }
+ else
+ {
+ WINHTTP_WEB_SOCKET_ASYNC_RESULT result;
+ result.AsyncResult.dwResult = API_READ_DATA;
+ result.AsyncResult.dwError = ret;
+ result.Operation = WINHTTP_WEB_SOCKET_RECEIVE_OPERATION;
+ send_callback( &r->socket->hdr, WINHTTP_CALLBACK_STATUS_REQUEST_ERROR, &result, sizeof(result) );
+ }
}
release_object( &r->socket->hdr );
@@ -3719,7 +3725,7 @@ static DWORD send_socket_shutdown( struct socket *socket, USHORT status, const v
{
DWORD ret;
- socket->state = SOCKET_STATE_SHUTDOWN;
+ if (socket->state < SOCKET_STATE_SHUTDOWN) socket->state = SOCKET_STATE_SHUTDOWN;
if (socket->request->connect->hdr.flags & WINHTTP_FLAG_ASYNC)
{
@@ -3816,6 +3822,8 @@ static void CALLBACK task_socket_close( TP_CALLBACK_INSTANCE *instance, void *ct
DWORD WINAPI WinHttpWebSocketClose( HINTERNET hsocket, USHORT status, void *reason, DWORD len )
{
+ enum socket_state prev_state;
+ LONG pending_receives = 0;
struct socket *socket;
DWORD ret;
@@ -3835,10 +3843,29 @@ DWORD WINAPI WinHttpWebSocketClose( HINTERNET hsocket, USHORT status, void *reas
return ERROR_INVALID_OPERATION;
}
- if (socket->state < SOCKET_STATE_SHUTDOWN
+ prev_state = socket->state;
+ socket->state = SOCKET_STATE_CLOSED;
+
+ if (socket->request->connect->hdr.flags & WINHTTP_FLAG_ASYNC)
+ {
+ /* When closing the socket pending receives are cancelled. Setting socket->hdr.pending_receives to zero
+ * will prevent pending receives from sending callbacks. */
+ pending_receives = InterlockedExchange( &socket->hdr.pending_receives, 0 );
+ assert( pending_receives >= 0 );
+ if (pending_receives)
+ {
+ WINHTTP_WEB_SOCKET_ASYNC_RESULT result;
+
+ result.AsyncResult.dwResult = 0;
+ result.AsyncResult.dwError = ERROR_WINHTTP_OPERATION_CANCELLED;
+ result.Operation = WINHTTP_WEB_SOCKET_RECEIVE_OPERATION;
+ send_callback( &socket->hdr, WINHTTP_CALLBACK_STATUS_REQUEST_ERROR, &result, sizeof(result) );
+ }
+ }
+
+ if (prev_state < SOCKET_STATE_SHUTDOWN
&& (ret = send_socket_shutdown( socket, status, reason, len, FALSE ))) goto done;
- socket->state = SOCKET_STATE_CLOSED;
if (socket->request->connect->hdr.flags & WINHTTP_FLAG_ASYNC)
{
struct socket_shutdown *s;
diff --git a/dlls/winhttp/tests/notification.c b/dlls/winhttp/tests/notification.c
index 2707151e00f..c57c0ef598a 100644
--- a/dlls/winhttp/tests/notification.c
+++ b/dlls/winhttp/tests/notification.c
@@ -63,6 +63,7 @@ struct notification
#define NF_WINE_ALLOW 0x0002 /* wine sends notification when it should not */
#define NF_SIGNAL 0x0004 /* signal wait handle when notified */
#define NF_MAIN_THREAD 0x0008 /* the operation completes synchronously and callback is called from the main thread */
+#define NF_SAVE_BUFFER 0x0010 /* save buffer data when notified */
struct info
{
@@ -75,6 +76,8 @@ struct info
DWORD main_thread_id;
DWORD last_thread_id;
DWORD last_status;
+ char buffer[256];
+ unsigned int buflen;
};
struct test_request
@@ -118,6 +121,11 @@ static void CALLBACK check_notification( HINTERNET handle, DWORD_PTR context, DW
ok(GetCurrentThreadId() == info->main_thread_id, "%u: expected callback to be called from the same thread\n",
info->line);
}
+ if (info->test[info->index].flags & NF_SAVE_BUFFER)
+ {
+ info->buflen = buflen;
+ memcpy( info->buffer, buffer, min( buflen, sizeof(info->buffer) ));
+ }
if (status_ok && function_ok && info->test[info->index++].flags & NF_SIGNAL)
{
@@ -694,7 +702,7 @@ static const struct notification websocket_test2[] =
{ winhttp_receive_response, WINHTTP_CALLBACK_STATUS_HEADERS_AVAILABLE, NF_SIGNAL },
{ winhttp_websocket_complete_upgrade, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED, NF_SIGNAL },
{ winhttp_websocket_receive, WINHTTP_CALLBACK_STATUS_READ_COMPLETE, NF_SIGNAL },
- { winhttp_websocket_close, WINHTTP_CALLBACK_STATUS_REQUEST_ERROR },
+ { winhttp_websocket_close, WINHTTP_CALLBACK_STATUS_REQUEST_ERROR, NF_MAIN_THREAD | NF_SAVE_BUFFER},
{ winhttp_websocket_close, WINHTTP_CALLBACK_STATUS_CLOSE_COMPLETE, NF_SIGNAL },
{ winhttp_close_handle, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING },
{ winhttp_close_handle, WINHTTP_CALLBACK_STATUS_CLOSING_CONNECTION, NF_WINE_ALLOW },
@@ -707,6 +715,7 @@ static const struct notification websocket_test2[] =
static void test_websocket(BOOL secure)
{
HANDLE session, connection, request, socket, event;
+ WINHTTP_WEB_SOCKET_ASYNC_RESULT *result;
WINHTTP_WEB_SOCKET_BUFFER_TYPE type;
DWORD size, status, err;
BOOL ret, unload = TRUE;
@@ -951,6 +960,13 @@ static void test_websocket(BOOL secure)
setup_test( &info, winhttp_websocket_close, __LINE__ );
ret = pWinHttpWebSocketClose( socket, 1000, (void *)"success", sizeof("success") );
ok( err == ERROR_SUCCESS, "got %u\n", err );
+ ok( info.buflen == sizeof(*result), "got unexpected buflen %u.\n", info.buflen );
+ result = (WINHTTP_WEB_SOCKET_ASYNC_RESULT *)info.buffer;
+ ok( result->Operation == WINHTTP_WEB_SOCKET_RECEIVE_OPERATION, "got unexpected operation %u.\n",
+ result->Operation );
+ ok( !result->AsyncResult.dwResult, "got unexpected result %lu.\n", result->AsyncResult.dwResult );
+ ok( result->AsyncResult.dwError == ERROR_WINHTTP_OPERATION_CANCELLED, "got unexpected error %u.\n",
+ result->AsyncResult.dwError );
close_status = 0xdead;
size = sizeof(buffer) + 1;
--
2.30.2
Jan. 26, 2022
[PATCH v2 2/5] winhttp: Count queued websocket receive operations.
by Hans Leidekker
From: Paul Gofman <pgofman(a)codeweavers.com>
Signed-off-by: Paul Gofman <pgofman(a)codeweavers.com>
Signed-off-by: Hans Leidekker <hans(a)codeweavers.com>
---
dlls/winhttp/request.c | 9 +++++++++
dlls/winhttp/winhttp_private.h | 1 +
2 files changed, 10 insertions(+)
diff --git a/dlls/winhttp/request.c b/dlls/winhttp/request.c
index bddbf4a03b2..7666bae4e68 100644
--- a/dlls/winhttp/request.c
+++ b/dlls/winhttp/request.c
@@ -3244,6 +3244,12 @@ static void send_io_complete( struct object_header *hdr )
assert( count >= 0 );
}
+static void receive_io_complete( struct socket *socket )
+{
+ LONG count = InterlockedDecrement( &socket->hdr.pending_receives );
+ assert( count >= 0 );
+}
+
static enum socket_opcode map_buffer_type( WINHTTP_WEB_SOCKET_BUFFER_TYPE type )
{
switch (type)
@@ -3614,6 +3620,7 @@ static void CALLBACK task_socket_receive( TP_CALLBACK_INSTANCE *instance, void *
TRACE("running %p\n", work);
ret = socket_receive( r->socket, r->buf, r->len, &count, &type );
+ receive_io_complete( r->socket );
if (!ret)
{
@@ -3667,8 +3674,10 @@ DWORD WINAPI WinHttpWebSocketReceive( HINTERNET hsocket, void *buf, DWORD len, D
r->len = len;
addref_object( &socket->hdr );
+ InterlockedIncrement( &socket->hdr.pending_receives );
if ((ret = queue_task( &socket->recv_q, task_socket_receive, r )))
{
+ InterlockedDecrement( &socket->hdr.pending_receives );
release_object( &socket->hdr );
free( r );
}
diff --git a/dlls/winhttp/winhttp_private.h b/dlls/winhttp/winhttp_private.h
index 5eb3e97a916..a6638aba30f 100644
--- a/dlls/winhttp/winhttp_private.h
+++ b/dlls/winhttp/winhttp_private.h
@@ -52,6 +52,7 @@ struct object_header
LONG recursion_count;
struct list entry;
volatile LONG pending_sends;
+ volatile LONG pending_receives;
};
struct hostdata
--
2.30.2
Jan. 26, 2022