vkd3d-shader/hlsl: Implement the InterlockedAdd() intrinsic.

This commit is contained in:
Shaun Ren
2024-12-12 17:59:15 -05:00
committed by Henri Verbeet
parent 5f943e9110
commit 660a71ef22
Notes: Henri Verbeet 2025-01-20 16:18:51 +01:00
Approved-by: Henri Verbeet (@hverbeet)
Approved-by: Elizabeth Figura (@zfigura)
Merge-Request: https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/1330
5 changed files with 309 additions and 0 deletions

View File

@@ -2031,6 +2031,25 @@ struct hlsl_ir_node *hlsl_new_stateblock_constant(struct hlsl_ctx *ctx, const ch
return &constant->node;
}
struct hlsl_ir_node *hlsl_new_interlocked(struct hlsl_ctx *ctx, enum hlsl_interlocked_op op, struct hlsl_type *type,
const struct hlsl_deref *dst, struct hlsl_ir_node *coords, struct hlsl_ir_node *cmp_value,
struct hlsl_ir_node *value, const struct vkd3d_shader_location *loc)
{
struct hlsl_ir_interlocked *interlocked;
if (!(interlocked = hlsl_alloc(ctx, sizeof(*interlocked))))
return NULL;
init_node(&interlocked->node, HLSL_IR_INTERLOCKED, type, loc);
interlocked->op = op;
hlsl_copy_deref(ctx, &interlocked->dst, dst);
hlsl_src_from_node(&interlocked->coords, coords);
hlsl_src_from_node(&interlocked->cmp_value, cmp_value);
hlsl_src_from_node(&interlocked->value, value);
return &interlocked->node;
}
bool hlsl_index_is_noncontiguous(struct hlsl_ir_index *index)
{
struct hlsl_type *type = index->val.node->data_type;
@@ -2375,6 +2394,27 @@ static struct hlsl_ir_node *clone_index(struct hlsl_ctx *ctx, struct clone_instr
return dst;
}
static struct hlsl_ir_node *clone_interlocked(struct hlsl_ctx *ctx,
struct clone_instr_map *map, struct hlsl_ir_interlocked *src)
{
struct hlsl_ir_interlocked *dst;
if (!(dst = hlsl_alloc(ctx, sizeof(*dst))))
return NULL;
init_node(&dst->node, HLSL_IR_INTERLOCKED, NULL, &src->node.loc);
dst->op = src->op;
if (!clone_deref(ctx, map, &dst->dst, &src->dst))
{
vkd3d_free(dst);
return NULL;
}
clone_src(map, &dst->coords, &src->coords);
clone_src(map, &dst->cmp_value, &src->cmp_value);
clone_src(map, &dst->value, &src->value);
return &dst->node;
}
static struct hlsl_ir_node *clone_compile(struct hlsl_ctx *ctx,
struct clone_instr_map *map, struct hlsl_ir_compile *compile)
{
@@ -2575,6 +2615,9 @@ static struct hlsl_ir_node *clone_instr(struct hlsl_ctx *ctx,
case HLSL_IR_SWIZZLE:
return clone_swizzle(ctx, map, hlsl_ir_swizzle(instr));
case HLSL_IR_INTERLOCKED:
return clone_interlocked(ctx, map, hlsl_ir_interlocked(instr));
case HLSL_IR_COMPILE:
return clone_compile(ctx, map, hlsl_ir_compile(instr));
@@ -3013,6 +3056,7 @@ const char *hlsl_node_type_to_string(enum hlsl_ir_node_type type)
[HLSL_IR_STORE ] = "HLSL_IR_STORE",
[HLSL_IR_SWITCH ] = "HLSL_IR_SWITCH",
[HLSL_IR_SWIZZLE ] = "HLSL_IR_SWIZZLE",
[HLSL_IR_INTERLOCKED ] = "HLSL_IR_INTERLOCKED",
[HLSL_IR_COMPILE] = "HLSL_IR_COMPILE",
[HLSL_IR_SAMPLER_STATE] = "HLSL_IR_SAMPLER_STATE",
@@ -3458,6 +3502,23 @@ static void dump_ir_index(struct vkd3d_string_buffer *buffer, const struct hlsl_
vkd3d_string_buffer_printf(buffer, "]");
}
static void dump_ir_interlocked(struct vkd3d_string_buffer *buffer, const struct hlsl_ir_interlocked *interlocked)
{
static const char *const op_names[] =
{
[HLSL_INTERLOCKED_ADD] = "add",
};
VKD3D_ASSERT(interlocked->op < ARRAY_SIZE(op_names));
vkd3d_string_buffer_printf(buffer, "interlocked_%s(dst = ", op_names[interlocked->op]);
dump_deref(buffer, &interlocked->dst);
vkd3d_string_buffer_printf(buffer, ", coords = ");
dump_src(buffer, &interlocked->coords);
vkd3d_string_buffer_printf(buffer, ", value = ");
dump_src(buffer, &interlocked->value);
vkd3d_string_buffer_printf(buffer, ")");
}
static void dump_ir_compile(struct hlsl_ctx *ctx, struct vkd3d_string_buffer *buffer,
const struct hlsl_ir_compile *compile)
{
@@ -3591,6 +3652,10 @@ static void dump_instr(struct hlsl_ctx *ctx, struct vkd3d_string_buffer *buffer,
dump_ir_swizzle(buffer, hlsl_ir_swizzle(instr));
break;
case HLSL_IR_INTERLOCKED:
dump_ir_interlocked(buffer, hlsl_ir_interlocked(instr));
break;
case HLSL_IR_COMPILE:
dump_ir_compile(ctx, buffer, hlsl_ir_compile(instr));
break;
@@ -3819,6 +3884,15 @@ static void free_ir_index(struct hlsl_ir_index *index)
vkd3d_free(index);
}
static void free_ir_interlocked(struct hlsl_ir_interlocked *interlocked)
{
hlsl_cleanup_deref(&interlocked->dst);
hlsl_src_remove(&interlocked->coords);
hlsl_src_remove(&interlocked->cmp_value);
hlsl_src_remove(&interlocked->value);
vkd3d_free(interlocked);
}
static void free_ir_compile(struct hlsl_ir_compile *compile)
{
unsigned int i;
@@ -3905,6 +3979,10 @@ void hlsl_free_instr(struct hlsl_ir_node *node)
free_ir_switch(hlsl_ir_switch(node));
break;
case HLSL_IR_INTERLOCKED:
free_ir_interlocked(hlsl_ir_interlocked(node));
break;
case HLSL_IR_COMPILE:
free_ir_compile(hlsl_ir_compile(node));
break;