radeonsi: implement the workaround for Rocket League - postponed TGSI kill
authorMarek Olšák <marek.olsak@amd.com>
Tue, 20 Jun 2017 20:55:56 +0000 (22:55 +0200)
committerMarek Olšák <marek.olsak@amd.com>
Fri, 23 Jun 2017 17:50:20 +0000 (19:50 +0200)
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 <nicolai.haehnle@amd.com>
src/gallium/drivers/radeon/r600_pipe_common.c
src/gallium/drivers/radeon/r600_pipe_common.h
src/gallium/drivers/radeonsi/si_shader.c
src/gallium/drivers/radeonsi/si_shader_internal.h
src/gallium/drivers/radeonsi/si_shader_tgsi_alu.c

index 04f7fc19e9d8395f511917624d2730471ab4d988..fd67d9ae1b4424ef562399983610ab481bbb2ce2 100644 (file)
@@ -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);
index e67982a4094e91857c4e4bb021fe7bde43e6d0cb..b22a3a75cb3ac5f2b2e1a68a2d9de83689568949 100644 (file)
@@ -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. */
index e525a1807633ad46a5dc73ec0611b5270ec89dce..ecc51a3f4f5a338f83ebf55eb19d6884663959e5 100644 (file)
@@ -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;
index 5ccde713c77f5f47d5030fd20791ca48bad05ae6..3556e69cd0e080e28b686b73732fb35ad10b2a06 100644 (file)
@@ -217,6 +217,7 @@ struct si_shader_context {
 
        LLVMValueRef lds;
        LLVMValueRef gs_next_vertex[4];
+       LLVMValueRef postponed_kill;
        LLVMValueRef return_value;
 
        LLVMTypeRef voidt;
index 9fa56c75761d6524fbf7ccc194a1ef7bd914ff1c..12f8de405641ce97a1b5b2151297eec3e1abac3b 100644 (file)
@@ -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]);