zink: handle global atomic intrinsics
authorMike Blumenkrantz <michael.blumenkrantz@gmail.com>
Thu, 6 Oct 2022 15:55:56 +0000 (11:55 -0400)
committerMarge Bot <emma+marge@anholt.net>
Thu, 24 Aug 2023 12:44:22 +0000 (12:44 +0000)
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/24859>

src/gallium/drivers/zink/nir_to_spirv/nir_to_spirv.c

index 154807f..c810d04 100644 (file)
@@ -2785,6 +2785,31 @@ emit_shared_atomic_intrinsic(struct ntv_context *ctx, nir_intrinsic_instr *intr)
 }
 
 static void
+emit_global_atomic_intrinsic(struct ntv_context *ctx, nir_intrinsic_instr *intr)
+{
+   unsigned bit_size = nir_src_bit_size(intr->src[1]);
+   SpvId dest_type = get_def_type(ctx, &intr->def, nir_type_uint);
+   nir_alu_type atype;
+   nir_alu_type ret_type = nir_atomic_op_type(nir_intrinsic_atomic_op(intr)) == nir_type_float ? nir_type_float : nir_type_uint;
+   SpvId param = get_src(ctx, &intr->src[1], &atype);
+
+   spirv_builder_emit_cap(&ctx->builder, SpvCapabilityPhysicalStorageBufferAddresses);
+   SpvId pointer_type = spirv_builder_type_pointer(&ctx->builder,
+                                                   SpvStorageClassPhysicalStorageBuffer,
+                                                   dest_type);
+   SpvId ptr = emit_bitcast(ctx, pointer_type, get_src(ctx, &intr->src[0], &atype));
+
+   if (bit_size == 64)
+      spirv_builder_emit_cap(&ctx->builder, SpvCapabilityInt64Atomics);
+   SpvId param2 = 0;
+
+   if (intr->intrinsic == nir_intrinsic_global_atomic_swap)
+      param2 = get_src(ctx, &intr->src[2], &atype);
+
+   handle_atomic_op(ctx, intr, ptr, param, param2, ret_type);
+}
+
+static void
 emit_get_ssbo_size(struct ntv_context *ctx, nir_intrinsic_instr *intr)
 {
    SpvId uint_type = get_uvec_type(ctx, 32, 1);
@@ -3283,6 +3308,11 @@ emit_intrinsic(struct ntv_context *ctx, nir_intrinsic_instr *intr)
       emit_shared_atomic_intrinsic(ctx, intr);
       break;
 
+   case nir_intrinsic_global_atomic:
+   case nir_intrinsic_global_atomic_swap:
+      emit_global_atomic_intrinsic(ctx, intr);
+      break;
+
    case nir_intrinsic_begin_invocation_interlock:
    case nir_intrinsic_end_invocation_interlock:
       spirv_builder_emit_interlock(&ctx->builder, intr->intrinsic == nir_intrinsic_end_invocation_interlock);