gallivm: implement implicit primitive flushing
authorZack Rusin <zackr@vmware.com>
Wed, 27 Mar 2013 09:30:38 +0000 (02:30 -0700)
committerZack Rusin <zackr@vmware.com>
Wed, 27 Mar 2013 10:53:02 +0000 (03:53 -0700)
TGSI semantics currently require an implicit endprim at the end
of GS if an ending primitive hasn't been emitted.

Signed-off-by: Zack Rusin <zackr@vmware.com>
Reviewed-by: Brian Paul <brianp@vmware.com>
Reviewed-by: José Fonseca <jfonseca@vmware.com>
src/gallium/auxiliary/gallivm/lp_bld_tgsi.h
src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c

index 62d4707371fc5d16624f32e39933a4b1680b1714..fe4444edb1ad961f3cd09a7ec317c15aa29c0422 100644 (file)
@@ -392,6 +392,12 @@ struct lp_build_tgsi_soa_context
    LLVMValueRef emitted_prims_vec;
    LLVMValueRef total_emitted_vertices_vec;
    LLVMValueRef emitted_vertices_vec;
+   /* if a shader doesn't have ENDPRIM instruction but it has
+    * a number of EMIT instructions it means the END instruction
+    * implicitly invokes ENDPRIM. handle this via a flag here
+    * in the future maybe we can enforce TGSI to always have
+    * an explicit ENDPRIM */
+   boolean pending_end_primitive;
 
    LLVMValueRef consts_ptr;
    const LLVMValueRef *pos;
index 6f174a5b50eb20c1e8c07c3db2becbba1c3aa615..b9de31ca710beb873ffe871a5396906641b391f9 100644 (file)
@@ -2190,6 +2190,7 @@ emit_vertex(
          LLVMBuildAdd(builder, bld->emitted_vertices_vec, masked_ones, "");
       bld->total_emitted_vertices_vec =
          LLVMBuildAdd(builder, bld->total_emitted_vertices_vec, masked_ones, "");
+      bld->pending_end_primitive = TRUE;
    }
 }
 
@@ -2212,6 +2213,7 @@ end_primitive(
       bld->emitted_prims_vec =
          LLVMBuildAdd(builder, bld->emitted_prims_vec, masked_ones, "");
       bld->emitted_vertices_vec = bld_base->uint_bld.zero;
+      bld->pending_end_primitive = FALSE;
    }
 }
 
@@ -2504,6 +2506,12 @@ static void emit_epilogue(struct lp_build_tgsi_context * bld_base)
    /* If we have indirect addressing in outputs we need to copy our alloca array
     * to the outputs slots specified by the caller */
    if (bld->gs_iface) {
+      /* flush the accumulated vertices as a primitive */
+      if (bld->pending_end_primitive) {
+         end_primitive(NULL, bld_base, NULL);
+         bld->pending_end_primitive = FALSE;
+      }
+
       bld->gs_iface->gs_epilogue(&bld->bld_base,
                                 bld->total_emitted_vertices_vec,
                                 bld->emitted_prims_vec,
@@ -2607,6 +2615,7 @@ lp_build_tgsi_soa(struct gallivm_state *gallivm,
       /* inputs are always indirect with gs */
       bld.indirect_files |= (1 << TGSI_FILE_INPUT);
       bld.gs_iface = gs_iface;
+      bld.pending_end_primitive = FALSE;
       bld.bld_base.emit_fetch_funcs[TGSI_FILE_INPUT] = emit_fetch_gs_input;
       bld.bld_base.op_actions[TGSI_OPCODE_EMIT].emit = emit_vertex;
       bld.bld_base.op_actions[TGSI_OPCODE_ENDPRIM].emit = end_primitive;