radeonsi: Prevent geometry shader from emitting too many vertices
authorMichel Daenzer <michel.daenzer@amd.com>
Thu, 13 Feb 2014 06:37:11 +0000 (15:37 +0900)
committerMichel Dänzer <michel@daenzer.net>
Thu, 27 Feb 2014 01:27:55 +0000 (10:27 +0900)
src/gallium/drivers/radeonsi/si_shader.c

index 77768214f5aac42f94eeb352d2b4373b2bce41c0..3a441f94909729205c4b89f2ef1514b29e72c6bb 100644 (file)
@@ -1905,6 +1905,7 @@ static void si_llvm_emit_vertex(
        LLVMValueRef soffset = LLVMGetParam(si_shader_ctx->radeon_bld.main_fn,
                                            SI_PARAM_GS2VS_OFFSET);
        LLVMValueRef gs_next_vertex;
+       LLVMValueRef can_emit, kill;
        LLVMValueRef t_list_ptr;
        LLVMValueRef t_list;
        LLVMValueRef args[2];
@@ -1934,6 +1935,21 @@ static void si_llvm_emit_vertex(
 
        /* Write vertex attribute values to GSVS ring */
        gs_next_vertex = LLVMBuildLoad(gallivm->builder, si_shader_ctx->gs_next_vertex, "");
+
+       /* 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.
+        */
+       can_emit = LLVMBuildICmp(gallivm->builder, LLVMIntULE, gs_next_vertex,
+                                lp_build_const_int32(gallivm,
+                                                     shader->gs_max_out_vertices), "");
+       kill = lp_build_select(&bld_base->base, can_emit,
+                              lp_build_const_float(gallivm, 1.0f),
+                              lp_build_const_float(gallivm, -1.0f));
+       build_intrinsic(gallivm->builder, "llvm.AMDGPU.kill",
+                       LLVMVoidTypeInContext(gallivm->context), &kill, 1, 0);
+
        for (i = 0; i < shader->noutput; i++) {
                LLVMValueRef *out_ptr =
                        si_shader_ctx->radeon_bld.soa.outputs[shader->output[i].index];