From ee16796d544975c85adadd7e74ea6f09dc426f34 Mon Sep 17 00:00:00 2001 From: Marek Olšák Date: Tue, 20 Jun 2017 22:55:56 +0200 Subject: radeonsi: implement the workaround for Rocket League - postponed TGSI kill MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Do KILL at the end of shaders so as not to break WQM. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=100070 Reviewed-by: Nicolai Hähnle --- src/gallium/drivers/radeon/r600_pipe_common.c | 5 +++++ src/gallium/drivers/radeon/r600_pipe_common.h | 1 + src/gallium/drivers/radeonsi/si_shader.c | 9 +++++++++ src/gallium/drivers/radeonsi/si_shader_internal.h | 1 + src/gallium/drivers/radeonsi/si_shader_tgsi_alu.c | 21 +++++++++++++++++++++ 5 files changed, 37 insertions(+) (limited to 'src/gallium') diff --git a/src/gallium/drivers/radeon/r600_pipe_common.c b/src/gallium/drivers/radeon/r600_pipe_common.c index 04f7fc19e9d..fd67d9ae1b4 100644 --- a/src/gallium/drivers/radeon/r600_pipe_common.c +++ b/src/gallium/drivers/radeon/r600_pipe_common.c @@ -1382,6 +1382,11 @@ bool r600_common_screen_init(struct r600_common_screen *rscreen, rscreen->has_rbplus = false; rscreen->rbplus_allowed = false; + /* Set the flag in debug_flags, so that the shader cache takes it + * into account. */ + if (flags & PIPE_SCREEN_ENABLE_CORRECT_TGSI_DERIVATIVES_AFTER_KILL) + rscreen->debug_flags |= DBG_FS_CORRECT_DERIVS_AFTER_KILL; + r600_disk_cache_create(rscreen); slab_create_parent(&rscreen->pool_transfers, sizeof(struct r600_transfer), 64); diff --git a/src/gallium/drivers/radeon/r600_pipe_common.h b/src/gallium/drivers/radeon/r600_pipe_common.h index e67982a4094..b22a3a75cb3 100644 --- a/src/gallium/drivers/radeon/r600_pipe_common.h +++ b/src/gallium/drivers/radeon/r600_pipe_common.h @@ -85,6 +85,7 @@ #define DBG_PREOPT_IR (1 << 15) #define DBG_CHECK_IR (1 << 16) #define DBG_NO_OPT_VARIANT (1 << 17) +#define DBG_FS_CORRECT_DERIVS_AFTER_KILL (1 << 18) /* gaps */ #define DBG_TEST_DMA (1 << 20) /* Bits 21-31 are reserved for the r600g driver. */ diff --git a/src/gallium/drivers/radeonsi/si_shader.c b/src/gallium/drivers/radeonsi/si_shader.c index e525a180763..ecc51a3f4f5 100644 --- a/src/gallium/drivers/radeonsi/si_shader.c +++ b/src/gallium/drivers/radeonsi/si_shader.c @@ -3251,6 +3251,9 @@ static void si_llvm_return_fs_outputs(struct lp_build_tgsi_context *bld_base) LLVMValueRef depth = NULL, stencil = NULL, samplemask = NULL; LLVMValueRef ret; + if (ctx->postponed_kill) + ac_build_kill(&ctx->ac, LLVMBuildLoad(builder, ctx->postponed_kill, "")); + /* Read the output values. */ for (i = 0; i < info->num_outputs; i++) { unsigned semantic_name = info->output_semantic_name[i]; @@ -5530,6 +5533,12 @@ static bool si_compile_tgsi_main(struct si_shader_context *ctx, } } + if (ctx->type == PIPE_SHADER_FRAGMENT && sel->info.uses_kill && + ctx->screen->b.debug_flags & DBG_FS_CORRECT_DERIVS_AFTER_KILL) { + /* This is initialized to 0.0 = not kill. */ + ctx->postponed_kill = lp_build_alloca(&ctx->gallivm, ctx->f32, ""); + } + if (!lp_build_tgsi_llvm(bld_base, sel->tokens)) { fprintf(stderr, "Failed to translate shader from TGSI to LLVM\n"); return false; diff --git a/src/gallium/drivers/radeonsi/si_shader_internal.h b/src/gallium/drivers/radeonsi/si_shader_internal.h index 5ccde713c77..3556e69cd0e 100644 --- a/src/gallium/drivers/radeonsi/si_shader_internal.h +++ b/src/gallium/drivers/radeonsi/si_shader_internal.h @@ -217,6 +217,7 @@ struct si_shader_context { LLVMValueRef lds; LLVMValueRef gs_next_vertex[4]; + LLVMValueRef postponed_kill; LLVMValueRef return_value; LLVMTypeRef voidt; diff --git a/src/gallium/drivers/radeonsi/si_shader_tgsi_alu.c b/src/gallium/drivers/radeonsi/si_shader_tgsi_alu.c index 9fa56c75761..12f8de40564 100644 --- a/src/gallium/drivers/radeonsi/si_shader_tgsi_alu.c +++ b/src/gallium/drivers/radeonsi/si_shader_tgsi_alu.c @@ -60,6 +60,27 @@ static void kil_emit(const struct lp_build_tgsi_action *action, struct lp_build_emit_data *emit_data) { struct si_shader_context *ctx = si_shader_context(bld_base); + LLVMBuilderRef builder = ctx->gallivm.builder; + + if (ctx->postponed_kill) { + if (emit_data->inst->Instruction.Opcode == TGSI_OPCODE_KILL_IF) { + LLVMValueRef val; + + /* Take the minimum kill value. This is the same as OR + * between 2 kill values. If the value is negative, + * the pixel will be killed. + */ + val = LLVMBuildLoad(builder, ctx->postponed_kill, ""); + val = lp_build_emit_llvm_binary(bld_base, TGSI_OPCODE_MIN, + val, emit_data->args[0]); + LLVMBuildStore(builder, val, ctx->postponed_kill); + } else { + LLVMBuildStore(builder, + LLVMConstReal(ctx->f32, -1), + ctx->postponed_kill); + } + return; + } if (emit_data->inst->Instruction.Opcode == TGSI_OPCODE_KILL_IF) ac_build_kill(&ctx->ac, emit_data->args[0]); -- cgit v1.2.3