mirror of
https://gitlab.winehq.org/wine/vkd3d.git
synced 2025-09-12 18:50:22 -07:00
vkd3d-shader/hlsl: Implement the InterlockedAdd() intrinsic.
This commit is contained in:
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
@@ -739,6 +739,10 @@ static bool transform_instr_derefs(struct hlsl_ctx *ctx, struct hlsl_ir_node *in
|
||||
res = func(ctx, &hlsl_ir_resource_store(instr)->resource, instr);
|
||||
return res;
|
||||
|
||||
case HLSL_IR_INTERLOCKED:
|
||||
res = func(ctx, &hlsl_ir_interlocked(instr)->dst, instr);
|
||||
return res;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
@@ -1836,6 +1840,15 @@ static bool copy_propagation_transform_resource_store(struct hlsl_ctx *ctx,
|
||||
return progress;
|
||||
}
|
||||
|
||||
static bool copy_propagation_transform_interlocked(struct hlsl_ctx *ctx,
|
||||
struct hlsl_ir_interlocked *interlocked, struct copy_propagation_state *state)
|
||||
{
|
||||
bool progress = false;
|
||||
|
||||
progress |= copy_propagation_transform_object_load(ctx, &interlocked->dst, state, interlocked->node.index);
|
||||
return progress;
|
||||
}
|
||||
|
||||
static void copy_propagation_record_store(struct hlsl_ctx *ctx, struct hlsl_ir_store *store,
|
||||
struct copy_propagation_state *state)
|
||||
{
|
||||
@@ -2042,6 +2055,9 @@ static bool copy_propagation_transform_block(struct hlsl_ctx *ctx, struct hlsl_b
|
||||
progress |= copy_propagation_process_switch(ctx, hlsl_ir_switch(instr), state);
|
||||
break;
|
||||
|
||||
case HLSL_IR_INTERLOCKED:
|
||||
progress |= copy_propagation_transform_interlocked(ctx, hlsl_ir_interlocked(instr), state);
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -2225,6 +2241,24 @@ static bool validate_dereferences(struct hlsl_ctx *ctx, struct hlsl_ir_node *ins
|
||||
validate_component_index_range_from_deref(ctx, &store->lhs);
|
||||
break;
|
||||
}
|
||||
case HLSL_IR_INTERLOCKED:
|
||||
{
|
||||
struct hlsl_ir_interlocked *interlocked = hlsl_ir_interlocked(instr);
|
||||
|
||||
if (!interlocked->dst.var->is_uniform)
|
||||
{
|
||||
hlsl_error(ctx, &instr->loc, VKD3D_SHADER_ERROR_HLSL_NON_STATIC_OBJECT_REF,
|
||||
"Accessed resource must have a single uniform source.");
|
||||
}
|
||||
else if (validate_component_index_range_from_deref(ctx, &interlocked->dst) == DEREF_VALIDATION_NOT_CONSTANT)
|
||||
{
|
||||
hlsl_error(ctx, &instr->loc, VKD3D_SHADER_ERROR_HLSL_NON_STATIC_OBJECT_REF,
|
||||
"Accessed resource from \"%s\" must be determinable at compile time.",
|
||||
interlocked->dst.var->name);
|
||||
note_non_static_deref_expressions(ctx, &interlocked->dst, "accessed resource");
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -4478,6 +4512,7 @@ static bool dce(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context)
|
||||
case HLSL_IR_LOOP:
|
||||
case HLSL_IR_RESOURCE_STORE:
|
||||
case HLSL_IR_SWITCH:
|
||||
case HLSL_IR_INTERLOCKED:
|
||||
break;
|
||||
case HLSL_IR_STATEBLOCK_CONSTANT:
|
||||
/* Stateblock constants should not appear in the shader program. */
|
||||
@@ -4724,6 +4759,19 @@ static void compute_liveness_recurse(struct hlsl_block *block, unsigned int loop
|
||||
index->idx.node->last_read = last_read;
|
||||
break;
|
||||
}
|
||||
case HLSL_IR_INTERLOCKED:
|
||||
{
|
||||
struct hlsl_ir_interlocked *interlocked = hlsl_ir_interlocked(instr);
|
||||
|
||||
var = interlocked->dst.var;
|
||||
var->last_read = max(var->last_read, last_read);
|
||||
deref_mark_last_read(&interlocked->dst, last_read);
|
||||
interlocked->coords.node->last_read = last_read;
|
||||
interlocked->value.node->last_read = last_read;
|
||||
if (interlocked->cmp_value.node)
|
||||
interlocked->cmp_value.node->last_read = last_read;
|
||||
break;
|
||||
}
|
||||
case HLSL_IR_JUMP:
|
||||
{
|
||||
struct hlsl_ir_jump *jump = hlsl_ir_jump(instr);
|
||||
@@ -5135,6 +5183,10 @@ static bool track_components_usage(struct hlsl_ctx *ctx, struct hlsl_ir_node *in
|
||||
register_deref_usage(ctx, &hlsl_ir_resource_store(instr)->resource);
|
||||
break;
|
||||
|
||||
case HLSL_IR_INTERLOCKED:
|
||||
register_deref_usage(ctx, &hlsl_ir_interlocked(instr)->dst);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -9942,6 +9994,45 @@ static bool sm4_generate_vsir_instr_resource_load(struct hlsl_ctx *ctx,
|
||||
}
|
||||
}
|
||||
|
||||
static bool sm4_generate_vsir_instr_interlocked(struct hlsl_ctx *ctx,
|
||||
struct vsir_program *program, struct hlsl_ir_interlocked *interlocked)
|
||||
{
|
||||
|
||||
static const enum vkd3d_shader_opcode opcodes[] =
|
||||
{
|
||||
[HLSL_INTERLOCKED_ADD] = VKD3DSIH_ATOMIC_IADD,
|
||||
};
|
||||
|
||||
static const enum vkd3d_shader_opcode imm_opcodes[] =
|
||||
{
|
||||
[HLSL_INTERLOCKED_ADD] = VKD3DSIH_IMM_ATOMIC_IADD,
|
||||
};
|
||||
|
||||
struct hlsl_ir_node *coords = interlocked->coords.node, *value = interlocked->value.node;
|
||||
struct hlsl_ir_node *instr = &interlocked->node;
|
||||
bool is_imm = interlocked->node.reg.allocated;
|
||||
struct vkd3d_shader_dst_param *dst_param;
|
||||
struct vkd3d_shader_instruction *ins;
|
||||
enum vkd3d_shader_opcode opcode;
|
||||
|
||||
opcode = is_imm ? imm_opcodes[interlocked->op] : opcodes[interlocked->op];
|
||||
if (!(ins = generate_vsir_add_program_instruction(ctx, program, &instr->loc, opcode, is_imm ? 2 : 1, 2)))
|
||||
return false;
|
||||
|
||||
if (is_imm)
|
||||
vsir_dst_from_hlsl_node(&ins->dst[0], ctx, instr);
|
||||
|
||||
dst_param = is_imm ? &ins->dst[1] : &ins->dst[0];
|
||||
if (!sm4_generate_vsir_init_dst_param_from_deref(ctx, program, dst_param, &interlocked->dst, &instr->loc, 0))
|
||||
return false;
|
||||
dst_param->reg.dimension = VSIR_DIMENSION_NONE;
|
||||
|
||||
vsir_src_from_hlsl_node(&ins->src[0], ctx, coords, VKD3DSP_WRITEMASK_ALL);
|
||||
vsir_src_from_hlsl_node(&ins->src[1], ctx, value, VKD3DSP_WRITEMASK_ALL);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool sm4_generate_vsir_instr_jump(struct hlsl_ctx *ctx,
|
||||
struct vsir_program *program, const struct hlsl_ir_jump *jump)
|
||||
{
|
||||
@@ -10119,6 +10210,10 @@ static void sm4_generate_vsir_block(struct hlsl_ctx *ctx, struct hlsl_block *blo
|
||||
generate_vsir_instr_swizzle(ctx, program, hlsl_ir_swizzle(instr));
|
||||
break;
|
||||
|
||||
case HLSL_IR_INTERLOCKED:
|
||||
sm4_generate_vsir_instr_interlocked(ctx, program, hlsl_ir_interlocked(instr));
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
Reference in New Issue
Block a user