diff options
author | Nicolai Hähnle <[email protected]> | 2017-03-29 20:29:37 +0200 |
---|---|---|
committer | Nicolai Hähnle <[email protected]> | 2017-03-31 07:56:27 +0200 |
commit | 02112c3ef7716955c889b6d10fb569b028a33f0e (patch) | |
tree | afcb92b4cbc7efe79c291db4dea5905347d3d8b1 /src | |
parent | cd3f38606962977821913792e841da6444244baa (diff) |
radeonsi: implement ARB_shader_group_vote
Reviewed-by: Marek Olšák <[email protected]>
Diffstat (limited to 'src')
-rw-r--r-- | src/gallium/drivers/radeonsi/si_pipe.c | 4 | ||||
-rw-r--r-- | src/gallium/drivers/radeonsi/si_shader.c | 82 |
2 files changed, 85 insertions, 1 deletions
diff --git a/src/gallium/drivers/radeonsi/si_pipe.c b/src/gallium/drivers/radeonsi/si_pipe.c index 2369471aa58..8aae11d3be4 100644 --- a/src/gallium/drivers/radeonsi/si_pipe.c +++ b/src/gallium/drivers/radeonsi/si_pipe.c @@ -424,6 +424,9 @@ static int si_get_param(struct pipe_screen* pscreen, enum pipe_cap param) case PIPE_CAP_TGSI_CLOCK: return HAVE_LLVM >= 0x0309; + case PIPE_CAP_TGSI_VOTE: + return HAVE_LLVM >= 0x0400; + case PIPE_CAP_RESOURCE_FROM_USER_MEMORY: return !SI_BIG_ENDIAN && sscreen->b.info.has_userptr; @@ -480,7 +483,6 @@ static int si_get_param(struct pipe_screen* pscreen, enum pipe_cap param) case PIPE_CAP_TEXTURE_GATHER_OFFSETS: case PIPE_CAP_VERTEXID_NOBASE: case PIPE_CAP_PRIMITIVE_RESTART_FOR_PATCHES: - case PIPE_CAP_TGSI_VOTE: case PIPE_CAP_MAX_WINDOW_RECTANGLES: case PIPE_CAP_NATIVE_FENCE_FD: case PIPE_CAP_TGSI_FS_FBFETCH: diff --git a/src/gallium/drivers/radeonsi/si_shader.c b/src/gallium/drivers/radeonsi/si_shader.c index ec063ad9028..874535a6b77 100644 --- a/src/gallium/drivers/radeonsi/si_shader.c +++ b/src/gallium/drivers/radeonsi/si_shader.c @@ -5125,6 +5125,84 @@ static void build_interp_intrinsic(const struct lp_build_tgsi_action *action, } } +static LLVMValueRef si_emit_ballot(struct si_shader_context *ctx, + LLVMValueRef value) +{ + struct gallivm_state *gallivm = &ctx->gallivm; + LLVMValueRef args[3] = { + value, + ctx->i32_0, + LLVMConstInt(ctx->i32, LLVMIntNE, 0) + }; + + if (LLVMTypeOf(value) != ctx->i32) + args[0] = LLVMBuildBitCast(gallivm->builder, value, ctx->i32, ""); + + return lp_build_intrinsic(gallivm->builder, + "llvm.amdgcn.icmp.i32", + ctx->i64, args, 3, + LP_FUNC_ATTR_NOUNWIND | + LP_FUNC_ATTR_READNONE | + LP_FUNC_ATTR_CONVERGENT); +} + +static void vote_all_emit( + const struct lp_build_tgsi_action *action, + struct lp_build_tgsi_context *bld_base, + struct lp_build_emit_data *emit_data) +{ + struct si_shader_context *ctx = si_shader_context(bld_base); + struct gallivm_state *gallivm = &ctx->gallivm; + LLVMValueRef active_set, vote_set; + LLVMValueRef tmp; + + active_set = si_emit_ballot(ctx, ctx->i32_1); + vote_set = si_emit_ballot(ctx, emit_data->args[0]); + + tmp = LLVMBuildICmp(gallivm->builder, LLVMIntEQ, vote_set, active_set, ""); + emit_data->output[emit_data->chan] = + LLVMBuildSExt(gallivm->builder, tmp, ctx->i32, ""); +} + +static void vote_any_emit( + const struct lp_build_tgsi_action *action, + struct lp_build_tgsi_context *bld_base, + struct lp_build_emit_data *emit_data) +{ + struct si_shader_context *ctx = si_shader_context(bld_base); + struct gallivm_state *gallivm = &ctx->gallivm; + LLVMValueRef vote_set; + LLVMValueRef tmp; + + vote_set = si_emit_ballot(ctx, emit_data->args[0]); + + tmp = LLVMBuildICmp(gallivm->builder, LLVMIntNE, + vote_set, LLVMConstInt(ctx->i64, 0, 0), ""); + emit_data->output[emit_data->chan] = + LLVMBuildSExt(gallivm->builder, tmp, ctx->i32, ""); +} + +static void vote_eq_emit( + const struct lp_build_tgsi_action *action, + struct lp_build_tgsi_context *bld_base, + struct lp_build_emit_data *emit_data) +{ + struct si_shader_context *ctx = si_shader_context(bld_base); + struct gallivm_state *gallivm = &ctx->gallivm; + LLVMValueRef active_set, vote_set; + LLVMValueRef all, none, tmp; + + active_set = si_emit_ballot(ctx, ctx->i32_1); + vote_set = si_emit_ballot(ctx, emit_data->args[0]); + + all = LLVMBuildICmp(gallivm->builder, LLVMIntEQ, vote_set, active_set, ""); + none = LLVMBuildICmp(gallivm->builder, LLVMIntEQ, + vote_set, LLVMConstInt(ctx->i64, 0, 0), ""); + tmp = LLVMBuildOr(gallivm->builder, all, none, ""); + emit_data->output[emit_data->chan] = + LLVMBuildSExt(gallivm->builder, tmp, ctx->i32, ""); +} + static unsigned si_llvm_get_stream(struct lp_build_tgsi_context *bld_base, struct lp_build_emit_data *emit_data) { @@ -6574,6 +6652,10 @@ static void si_init_shader_ctx(struct si_shader_context *ctx, bld_base->op_actions[TGSI_OPCODE_DDX_FINE].emit = si_llvm_emit_ddxy; bld_base->op_actions[TGSI_OPCODE_DDY_FINE].emit = si_llvm_emit_ddxy; + bld_base->op_actions[TGSI_OPCODE_VOTE_ALL].emit = vote_all_emit; + bld_base->op_actions[TGSI_OPCODE_VOTE_ANY].emit = vote_any_emit; + bld_base->op_actions[TGSI_OPCODE_VOTE_EQ].emit = vote_eq_emit; + bld_base->op_actions[TGSI_OPCODE_EMIT].emit = si_llvm_emit_vertex; bld_base->op_actions[TGSI_OPCODE_ENDPRIM].emit = si_llvm_emit_primitive; bld_base->op_actions[TGSI_OPCODE_BARRIER].emit = si_llvm_emit_barrier; |