radv: keep GS threads with excessive emissions which could write to memory
authorRhys Perry <pendingchaos02@gmail.com>
Mon, 29 Apr 2019 12:41:46 +0000 (13:41 +0100)
committerRhys Perry <pendingchaos02+freedesktop@gmail.com>
Mon, 16 Sep 2019 19:42:30 +0000 (19:42 +0000)
Signed-off-by: Rhys Perry <pendingchaos02@gmail.com>
Reviewed-by: Samuel Pitoiset <samuel.pitoiset@gmail.com>
src/amd/vulkan/radv_nir_to_llvm.c
src/amd/vulkan/radv_shader.h
src/amd/vulkan/radv_shader_info.c

index ee4acf7b5a787d5cbe18b676d02ac8197dc0dded..37c81d5b45f0ba253c10c476b631b162b57fb92c 100644 (file)
@@ -1761,13 +1761,17 @@ visit_emit_vertex(struct ac_shader_abi *abi, unsigned stream, LLVMValueRef *addr
                                       "");
 
        /* If this thread has already emitted the declared maximum number of
-        * vertices, kill it: excessive vertex emissions are not supposed to
-        * have any effect, and GS threads have no externally observable
-        * effects other than emitting vertices.
+        * vertices, don't emit any more: excessive vertex emissions are not
+        * supposed to have any effect.
         */
        can_emit = LLVMBuildICmp(ctx->ac.builder, LLVMIntULT, gs_next_vertex,
                                 LLVMConstInt(ctx->ac.i32, ctx->shader->info.gs.vertices_out, false), "");
-       ac_build_kill_if_false(&ctx->ac, can_emit);
+
+       bool use_kill = !ctx->shader_info->gs.writes_memory;
+       if (use_kill)
+               ac_build_kill_if_false(&ctx->ac, can_emit);
+       else
+               ac_build_ifcc(&ctx->ac, can_emit, 6505);
 
        for (unsigned i = 0; i < AC_LLVM_MAX_OUTPUTS; ++i) {
                unsigned output_usage_mask =
@@ -1814,6 +1818,9 @@ visit_emit_vertex(struct ac_shader_abi *abi, unsigned stream, LLVMValueRef *addr
        ac_build_sendmsg(&ctx->ac,
                         AC_SENDMSG_GS_OP_EMIT | AC_SENDMSG_GS | (stream << 8),
                         ctx->gs_wave_id);
+
+       if (!use_kill)
+               ac_build_endif(&ctx->ac, 6505);
 }
 
 static void
index 874318e7dc497c2d6287d549a800d89114528fb5..57f9d160ed0032623412ea0800e51ef9ab5d27c8 100644 (file)
@@ -253,6 +253,7 @@ struct radv_shader_info {
                uint8_t num_stream_output_components[4];
                uint8_t output_streams[VARYING_SLOT_VAR31 + 1];
                uint8_t max_stream;
+               bool writes_memory;
                unsigned gsvs_vertex_size;
                unsigned max_gsvs_emit_size;
                unsigned vertices_in;
index e8efbf6778b77c0f5538ad2e8891ba63823c65b9..950b5bd599d1e4a299cd4d97277ecefb06ce27f5 100644 (file)
@@ -310,6 +310,8 @@ gather_intrinsic_info(const nir_shader *nir, const nir_intrinsic_instr *instr,
                    instr->intrinsic == nir_intrinsic_image_deref_atomic_comp_swap) {
                        if (nir->info.stage == MESA_SHADER_FRAGMENT)
                                info->ps.writes_memory = true;
+                       else if (nir->info.stage == MESA_SHADER_GEOMETRY)
+                               info->gs.writes_memory = true;
                }
                break;
        }
@@ -326,6 +328,8 @@ gather_intrinsic_info(const nir_shader *nir, const nir_intrinsic_instr *instr,
        case nir_intrinsic_ssbo_atomic_comp_swap:
                if (nir->info.stage == MESA_SHADER_FRAGMENT)
                        info->ps.writes_memory = true;
+               else if (nir->info.stage == MESA_SHADER_GEOMETRY)
+                       info->gs.writes_memory = true;
                break;
        case nir_intrinsic_load_deref:
                gather_intrinsic_load_deref_info(nir, instr, info);