From 2e1266d1fe9ef7ba152a86ef1dfa2bb3a8b61b94 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 19 Mar 2021 12:01:41 +1000 Subject: [PATCH] gallivm: add subgroup elect intrinsic support. Reviewed-by: Roland Scheidegger Part-of: --- src/gallium/auxiliary/gallivm/lp_bld_nir.c | 3 ++ src/gallium/auxiliary/gallivm/lp_bld_nir.h | 1 + .../auxiliary/gallivm/lp_bld_nir_soa.c | 37 +++++++++++++++++++ 3 files changed, 41 insertions(+) diff --git a/src/gallium/auxiliary/gallivm/lp_bld_nir.c b/src/gallium/auxiliary/gallivm/lp_bld_nir.c index c49a37cfadf..d41be6ba0fc 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_nir.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_nir.c @@ -1786,6 +1786,9 @@ static void visit_intrinsic(struct lp_build_nir_context *bld_base, case nir_intrinsic_vote_feq: bld_base->vote(bld_base, cast_type(bld_base, get_src(bld_base, instr->src[0]), nir_type_int, nir_src_bit_size(instr->src[0])), instr, result); break; + case nir_intrinsic_elect: + bld_base->elect(bld_base, result); + break; case nir_intrinsic_interp_deref_at_offset: case nir_intrinsic_interp_deref_at_centroid: case nir_intrinsic_interp_deref_at_sample: diff --git a/src/gallium/auxiliary/gallivm/lp_bld_nir.h b/src/gallium/auxiliary/gallivm/lp_bld_nir.h index 9de1ccbd16f..e396db71eb8 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_nir.h +++ b/src/gallium/auxiliary/gallivm/lp_bld_nir.h @@ -185,6 +185,7 @@ struct lp_build_nir_context void (*end_primitive)(struct lp_build_nir_context *bld_base, uint32_t stream_id); void (*vote)(struct lp_build_nir_context *bld_base, LLVMValueRef src, nir_intrinsic_instr *instr, LLVMValueRef dst[4]); + void (*elect)(struct lp_build_nir_context *bld_base, LLVMValueRef dst[4]); void (*helper_invocation)(struct lp_build_nir_context *bld_base, LLVMValueRef *dst); void (*interp_at)(struct lp_build_nir_context *bld_base, diff --git a/src/gallium/auxiliary/gallivm/lp_bld_nir_soa.c b/src/gallium/auxiliary/gallivm/lp_bld_nir_soa.c index 4847f5c49b0..6c122fc18ba 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_nir_soa.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_nir_soa.c @@ -1884,6 +1884,42 @@ static void emit_vote(struct lp_build_nir_context *bld_base, LLVMValueRef src, result[0] = lp_build_broadcast_scalar(&bld_base->uint_bld, LLVMBuildLoad(builder, res_store, "")); } +static void emit_elect(struct lp_build_nir_context *bld_base, LLVMValueRef result[4]) +{ + struct gallivm_state *gallivm = bld_base->base.gallivm; + LLVMBuilderRef builder = gallivm->builder; + LLVMValueRef exec_mask = mask_vec(bld_base); + struct lp_build_loop_state loop_state; + + LLVMValueRef idx_store = lp_build_alloca(gallivm, bld_base->int_bld.elem_type, ""); + LLVMValueRef found_store = lp_build_alloca(gallivm, bld_base->int_bld.elem_type, ""); + lp_build_loop_begin(&loop_state, gallivm, lp_build_const_int32(gallivm, 0)); + LLVMValueRef value_ptr = LLVMBuildExtractElement(gallivm->builder, exec_mask, + loop_state.counter, ""); + LLVMValueRef cond = LLVMBuildICmp(gallivm->builder, + LLVMIntEQ, + value_ptr, + lp_build_const_int32(gallivm, -1), ""); + LLVMValueRef cond2 = LLVMBuildICmp(gallivm->builder, + LLVMIntEQ, + LLVMBuildLoad(builder, found_store, ""), + lp_build_const_int32(gallivm, 0), ""); + + cond = LLVMBuildAnd(builder, cond, cond2, ""); + struct lp_build_if_state ifthen; + lp_build_if(&ifthen, gallivm, cond); + LLVMBuildStore(builder, lp_build_const_int32(gallivm, 1), found_store); + LLVMBuildStore(builder, loop_state.counter, idx_store); + lp_build_endif(&ifthen); + lp_build_loop_end_cond(&loop_state, lp_build_const_int32(gallivm, bld_base->uint_bld.type.length), + NULL, LLVMIntUGE); + + result[0] = LLVMBuildInsertElement(builder, bld_base->uint_bld.zero, + lp_build_const_int32(gallivm, -1), + LLVMBuildLoad(builder, idx_store, ""), + ""); +} + static void emit_interp_at(struct lp_build_nir_context *bld_base, unsigned num_components, @@ -2129,6 +2165,7 @@ void lp_build_nir_soa(struct gallivm_state *gallivm, bld.bld_base.image_op = emit_image_op; bld.bld_base.image_size = emit_image_size; bld.bld_base.vote = emit_vote; + bld.bld_base.elect = emit_elect; bld.bld_base.helper_invocation = emit_helper_invocation; bld.bld_base.interp_at = emit_interp_at; bld.bld_base.load_scratch = emit_load_scratch;