From 5b9634a7b76fc36b5b2e182fdca53bc51aa6409d Mon Sep 17 00:00:00 2001 From: Shaun Ren Date: Thu, 16 Jan 2025 15:48:11 -0500 Subject: [PATCH] vkd3d-shader/hlsl: Implement the InterlockedMin() intrinsic. --- libs/vkd3d-shader/hlsl.c | 1 + libs/vkd3d-shader/hlsl.h | 1 + libs/vkd3d-shader/hlsl.y | 9 ++++++++- libs/vkd3d-shader/hlsl_codegen.c | 6 ++++++ libs/vkd3d-shader/tpf.c | 4 ++++ tests/hlsl/uav-atomics.shader_test | 17 +++++++++-------- 6 files changed, 29 insertions(+), 9 deletions(-) diff --git a/libs/vkd3d-shader/hlsl.c b/libs/vkd3d-shader/hlsl.c index d0405975..cdf32459 100644 --- a/libs/vkd3d-shader/hlsl.c +++ b/libs/vkd3d-shader/hlsl.c @@ -3511,6 +3511,7 @@ static void dump_ir_interlocked(struct vkd3d_string_buffer *buffer, const struct [HLSL_INTERLOCKED_CMP_EXCH] = "cmp_exch", [HLSL_INTERLOCKED_EXCH] = "exch", [HLSL_INTERLOCKED_MAX] = "max", + [HLSL_INTERLOCKED_MIN] = "min", }; VKD3D_ASSERT(interlocked->op < ARRAY_SIZE(op_names)); diff --git a/libs/vkd3d-shader/hlsl.h b/libs/vkd3d-shader/hlsl.h index c5703417..88ca5282 100644 --- a/libs/vkd3d-shader/hlsl.h +++ b/libs/vkd3d-shader/hlsl.h @@ -958,6 +958,7 @@ enum hlsl_interlocked_op HLSL_INTERLOCKED_CMP_EXCH, HLSL_INTERLOCKED_EXCH, HLSL_INTERLOCKED_MAX, + HLSL_INTERLOCKED_MIN, }; /* Represents an interlocked operation. diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y index 5f9d47f2..106459ee 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -5429,7 +5429,7 @@ static bool intrinsic_interlocked(struct hlsl_ctx *ctx, enum hlsl_interlocked_op /* Interlocked*() functions always take uint for the value parameters, * except for InterlockedMax()/InterlockedMin(). */ - if (op == HLSL_INTERLOCKED_MAX) + if (op == HLSL_INTERLOCKED_MAX || op == HLSL_INTERLOCKED_MIN) { enum hlsl_base_type val_base_type = val->data_type->e.numeric.type; @@ -5536,6 +5536,12 @@ static bool intrinsic_InterlockedMax(struct hlsl_ctx *ctx, return intrinsic_interlocked(ctx, HLSL_INTERLOCKED_MAX, params, loc, "InterlockedMax"); } +static bool intrinsic_InterlockedMin(struct hlsl_ctx *ctx, + const struct parse_initializer *params, const struct vkd3d_shader_location *loc) +{ + return intrinsic_interlocked(ctx, HLSL_INTERLOCKED_MIN, params, loc, "InterlockedMin"); +} + static const struct intrinsic_function { const char *name; @@ -5555,6 +5561,7 @@ intrinsic_functions[] = {"InterlockedCompareStore", 3, true, intrinsic_InterlockedCompareStore}, {"InterlockedExchange", 3, true, intrinsic_InterlockedExchange}, {"InterlockedMax", -1, true, intrinsic_InterlockedMax}, + {"InterlockedMin", -1, true, intrinsic_InterlockedMin}, {"abs", 1, true, intrinsic_abs}, {"acos", 1, true, intrinsic_acos}, {"all", 1, true, intrinsic_all}, diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c index c67ce835..c0eaacba 100644 --- a/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d-shader/hlsl_codegen.c @@ -10004,6 +10004,7 @@ static bool sm4_generate_vsir_instr_interlocked(struct hlsl_ctx *ctx, [HLSL_INTERLOCKED_AND] = VKD3DSIH_ATOMIC_AND, [HLSL_INTERLOCKED_CMP_EXCH] = VKD3DSIH_ATOMIC_CMP_STORE, [HLSL_INTERLOCKED_MAX] = VKD3DSIH_ATOMIC_UMAX, + [HLSL_INTERLOCKED_MIN] = VKD3DSIH_ATOMIC_UMIN, }; static const enum vkd3d_shader_opcode imm_opcodes[] = @@ -10013,6 +10014,7 @@ static bool sm4_generate_vsir_instr_interlocked(struct hlsl_ctx *ctx, [HLSL_INTERLOCKED_CMP_EXCH] = VKD3DSIH_IMM_ATOMIC_CMP_EXCH, [HLSL_INTERLOCKED_EXCH] = VKD3DSIH_IMM_ATOMIC_EXCH, [HLSL_INTERLOCKED_MAX] = VKD3DSIH_IMM_ATOMIC_UMAX, + [HLSL_INTERLOCKED_MIN] = VKD3DSIH_IMM_ATOMIC_UMIN, }; struct hlsl_ir_node *cmp_value = interlocked->cmp_value.node, *value = interlocked->value.node; @@ -10029,8 +10031,12 @@ static bool sm4_generate_vsir_instr_interlocked(struct hlsl_ctx *ctx, { if (opcode == VKD3DSIH_ATOMIC_UMAX) opcode = VKD3DSIH_ATOMIC_IMAX; + else if (opcode == VKD3DSIH_ATOMIC_UMIN) + opcode = VKD3DSIH_ATOMIC_IMIN; else if (opcode == VKD3DSIH_IMM_ATOMIC_UMAX) opcode = VKD3DSIH_IMM_ATOMIC_IMAX; + else if (opcode == VKD3DSIH_IMM_ATOMIC_UMIN) + opcode = VKD3DSIH_IMM_ATOMIC_IMIN; } if (!(ins = generate_vsir_add_program_instruction(ctx, program, &instr->loc, opcode, diff --git a/libs/vkd3d-shader/tpf.c b/libs/vkd3d-shader/tpf.c index b5dbd566..8a91620e 100644 --- a/libs/vkd3d-shader/tpf.c +++ b/libs/vkd3d-shader/tpf.c @@ -4030,7 +4030,9 @@ static void tpf_handle_instruction(struct tpf_compiler *tpf, const struct vkd3d_ case VKD3DSIH_ATOMIC_CMP_STORE: case VKD3DSIH_ATOMIC_IADD: case VKD3DSIH_ATOMIC_IMAX: + case VKD3DSIH_ATOMIC_IMIN: case VKD3DSIH_ATOMIC_UMAX: + case VKD3DSIH_ATOMIC_UMIN: case VKD3DSIH_AND: case VKD3DSIH_BREAK: case VKD3DSIH_CASE: @@ -4078,7 +4080,9 @@ static void tpf_handle_instruction(struct tpf_compiler *tpf, const struct vkd3d_ case VKD3DSIH_IMM_ATOMIC_EXCH: case VKD3DSIH_IMM_ATOMIC_IADD: case VKD3DSIH_IMM_ATOMIC_IMAX: + case VKD3DSIH_IMM_ATOMIC_IMIN: case VKD3DSIH_IMM_ATOMIC_UMAX: + case VKD3DSIH_IMM_ATOMIC_UMIN: case VKD3DSIH_IMUL: case VKD3DSIH_INE: case VKD3DSIH_INEG: diff --git a/tests/hlsl/uav-atomics.shader_test b/tests/hlsl/uav-atomics.shader_test index 1746ae40..71c0ac8f 100644 --- a/tests/hlsl/uav-atomics.shader_test +++ b/tests/hlsl/uav-atomics.shader_test @@ -66,7 +66,7 @@ size (buffer, 2) -3 1 -[compute shader fail(sm<5) todo(sm>=5)] +[compute shader fail(sm<5)] RWBuffer u : register(u2); uniform int4 i; @@ -80,12 +80,12 @@ void main() [test] uniform 0 int4 1 -3 0 0 -todo(sm<6) dispatch 1 1 1 +todo(glsl | msl) dispatch 1 1 1 probe uav 2 (0) ri (1) probe uav 2 (1) ri (-3) uniform 0 int4 -3 1 0 0 -todo(sm<6) dispatch 1 1 1 +todo(glsl | msl) dispatch 1 1 1 probe uav 2 (0) ri (1) probe uav 2 (1) ri (-3) @@ -134,7 +134,7 @@ probe uav 1 (9) rui (3) probe uav 1 (10) rui (1) -[compute shader fail(sm<5) todo(sm>=5)] +[compute shader fail(sm<5)] RWTexture2D u : register(u2); uniform int4 i; @@ -148,12 +148,13 @@ void main() [test] uniform 0 int4 1 -3 0 0 -todo(sm<6) dispatch 1 1 1 +% SPIR-V compilation currently fails because of the mismatched resource type for u2. +todo(mvk | vulkan | opengl | msl) dispatch 1 1 1 probe uav 2 (0) ri (1) probe uav 2 (1) ri (-3) uniform 0 int4 -3 1 0 0 -todo(sm<6) dispatch 1 1 1 +todo(mvk | vulkan | opengl | msl) dispatch 1 1 1 probe uav 2 (0) ri (1) probe uav 2 (1) ri (-3) @@ -173,7 +174,7 @@ size (buffer, 3) % The value fields of InterlockedMax/Min have the same type as the underlying scalar type of dst. % However, floating point numbers are always converted to signed integers. -[compute shader fail(sm<5) todo(sm>=5)] +[compute shader fail(sm<5)] RWBuffer u : register(u1); RWBuffer s : register(u2); @@ -195,7 +196,7 @@ void main() [test] uniform 0 uint 0xffffffff uniform 1 float 0x80000000 -todo(sm<6) dispatch 1 1 1 +todo(glsl | msl) dispatch 1 1 1 probe uav 1 (0) rui (0xffffffff) probe uav 1 (1) rui (1) probe uav 1 (2) rui (0x7fffffff)