From 0f29c9df315df8f8752cacc1d1ecab8cb9a2bb16 Mon Sep 17 00:00:00 2001 From: Rhys Perry Date: Mon, 29 Apr 2019 13:41:46 +0100 Subject: [PATCH] radv: keep GS threads with excessive emissions which could write to memory Signed-off-by: Rhys Perry Reviewed-by: Samuel Pitoiset --- src/amd/vulkan/radv_nir_to_llvm.c | 15 +++++++++++---- src/amd/vulkan/radv_shader.h | 1 + src/amd/vulkan/radv_shader_info.c | 4 ++++ 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/amd/vulkan/radv_nir_to_llvm.c b/src/amd/vulkan/radv_nir_to_llvm.c index ee4acf7b5a7..37c81d5b45f 100644 --- a/src/amd/vulkan/radv_nir_to_llvm.c +++ b/src/amd/vulkan/radv_nir_to_llvm.c @@ -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 diff --git a/src/amd/vulkan/radv_shader.h b/src/amd/vulkan/radv_shader.h index 874318e7dc4..57f9d160ed0 100644 --- a/src/amd/vulkan/radv_shader.h +++ b/src/amd/vulkan/radv_shader.h @@ -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; diff --git a/src/amd/vulkan/radv_shader_info.c b/src/amd/vulkan/radv_shader_info.c index e8efbf6778b..950b5bd599d 100644 --- a/src/amd/vulkan/radv_shader_info.c +++ b/src/amd/vulkan/radv_shader_info.c @@ -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); -- 2.30.2