[Mesa-dev] [PATCH 1/2] gallivm/gs: fix the end primitive calls
Jose Fonseca
jfonseca at vmware.com
Fri Apr 12 01:47:55 PDT 2013
----- Original Message -----
> The issue with SOA execution and end_primitive opcode is that it
> can be executed both when we haven't emitted any vertices, in
> which case we don't want to emit an empty primitive, and when
> the execution mask is zero and the execution should be skipped. We
> handled only the latter of those conditions. Now we're combining the
> execution mask with a mask created from emitted vertices to handle
> both cases. As a result we don't need the pending_end_primitive
> flag which was broken because it was static and could be affected
> by both above mentioned conditions at run-time.
>
> Signed-off-by: Zack Rusin <zackr at vmware.com>
> ---
> src/gallium/auxiliary/gallivm/lp_bld_tgsi.h | 6 --
> src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c | 71
> ++++++++++++++++-------
> 2 files changed, 50 insertions(+), 27 deletions(-)
>
> diff --git a/src/gallium/auxiliary/gallivm/lp_bld_tgsi.h
> b/src/gallium/auxiliary/gallivm/lp_bld_tgsi.h
> index 23ccacc..f1b1d79 100644
> --- a/src/gallium/auxiliary/gallivm/lp_bld_tgsi.h
> +++ b/src/gallium/auxiliary/gallivm/lp_bld_tgsi.h
> @@ -396,12 +396,6 @@ struct lp_build_tgsi_soa_context
> LLVMValueRef emitted_prims_vec_ptr;
> LLVMValueRef total_emitted_vertices_vec_ptr;
> LLVMValueRef emitted_vertices_vec_ptr;
> - /* 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;
> diff --git a/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c
> b/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c
> index 8a29635..b54fc13 100644
> --- a/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c
> +++ b/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c
> @@ -65,6 +65,7 @@
> #include "lp_bld_sample.h"
> #include "lp_bld_struct.h"
>
> +/*#define DUMP_GS_EMITS 1*/
#define DUMP_GS_EMITS 0
>
> static void lp_exec_mask_init(struct lp_exec_mask *mask, struct
> lp_build_context *bld)
> {
> @@ -2278,27 +2279,25 @@ emit_vertex(
> increment_vec_ptr_by_mask(bld_base,
> bld->total_emitted_vertices_vec_ptr,
> masked_ones);
> #if DUMP_GS_EMITS
> - lp_build_print_value(bld->bld_base.base.gallivm, " +++ emit vertex
> masked ones = ",
> + lp_build_print_value(bld->bld_base.base.gallivm,
> + " +++ emit vertex masked ones = ",
> masked_ones);
> - lp_build_print_value(bld->bld_base.base.gallivm, " +++ emit vertex
> emitted = ",
> + lp_build_print_value(bld->bld_base.base.gallivm,
> + " +++ emit vertex emitted = ",
> total_emitted_vertices_vec);
> #endif
> - bld->pending_end_primitive = TRUE;
> }
> }
>
>
> static void
> -end_primitive(
> - const struct lp_build_tgsi_action * action,
> - struct lp_build_tgsi_context * bld_base,
> - struct lp_build_emit_data * emit_data)
> +end_primitive_masked(struct lp_build_tgsi_context * bld_base,
> + LLVMValueRef masked_ones)
> {
> struct lp_build_tgsi_soa_context * bld = lp_soa_context(bld_base);
> LLVMBuilderRef builder = bld->bld_base.base.gallivm->builder;
>
> if (bld->gs_iface->end_primitive) {
> - LLVMValueRef masked_ones = mask_to_one_vec(bld_base);
> LLVMValueRef emitted_vertices_vec =
> LLVMBuildLoad(builder, bld->emitted_vertices_vec_ptr, "");
> LLVMValueRef emitted_prims_vec =
> @@ -2309,23 +2308,55 @@ end_primitive(
> emitted_prims_vec);
>
> #if DUMP_GS_EMITS
> - lp_build_print_value(bld->bld_base.base.gallivm, " +++ end prim masked
> ones = ",
> + lp_build_print_value(bld->bld_base.base.gallivm,
> + " +++ end prim masked ones = ",
> masked_ones);
> - lp_build_print_value(bld->bld_base.base.gallivm, " +++ end prim
> emitted verts1 = ",
> + lp_build_print_value(bld->bld_base.base.gallivm,
> + " +++ end prim emitted verts1 = ",
> emitted_vertices_vec);
> - lp_build_print_value(bld->bld_base.base.gallivm, " +++ end prim
> emitted prims1 = ",
> - LLVMBuildLoad(builder,
> bld->emitted_prims_vec_ptr, ""));
> + lp_build_print_value(bld->bld_base.base.gallivm,
> + " +++ end prim emitted prims1 = ",
> + LLVMBuildLoad(builder,
> + bld->emitted_prims_vec_ptr, ""));
> #endif
> increment_vec_ptr_by_mask(bld_base, bld->emitted_prims_vec_ptr,
> masked_ones);
> clear_uint_vec_ptr_from_mask(bld_base, bld->emitted_vertices_vec_ptr,
> masked_ones);
> #if DUMP_GS_EMITS
> - lp_build_print_value(bld->bld_base.base.gallivm, " +++ end prim
> emitted verts2 = ",
> - LLVMBuildLoad(builder,
> bld->emitted_vertices_vec_ptr, ""));
> + lp_build_print_value(bld->bld_base.base.gallivm,
> + " +++ end prim emitted verts2 = ",
> + LLVMBuildLoad(builder,
> + bld->emitted_vertices_vec_ptr,
> ""));
> #endif
> + }
>
> - bld->pending_end_primitive = FALSE;
> +}
> +
> +static void
> +end_primitive(
> + const struct lp_build_tgsi_action * action,
> + struct lp_build_tgsi_context * bld_base,
> + struct lp_build_emit_data * emit_data)
> +{
> + struct lp_build_tgsi_soa_context * bld = lp_soa_context(bld_base);
> +
> + if (bld->gs_iface->end_primitive) {
> + LLVMBuilderRef builder = bld_base->base.gallivm->builder;
> + LLVMValueRef masked_ones = mask_to_one_vec(bld_base);
> + struct lp_build_context *uint_bld = &bld_base->uint_bld;
> + LLVMValueRef emitted_verts = LLVMBuildLoad(
> + builder, bld->emitted_vertices_vec_ptr, "");
> + LLVMValueRef emitted_mask = lp_build_cmp(uint_bld, PIPE_FUNC_NOTEQUAL,
> + emitted_verts,
> + uint_bld->zero);
> + /* We need to combine the current execution mask with the mask
> + telling us which, if any, execution slots actually have
> + unemitted primitives, this way we make sure that end_primitives
> + executes only on the paths that have unflushed vertices */
> + masked_ones = LLVMBuildAnd(builder, masked_ones, emitted_mask, "");
> +
> + end_primitive_masked(bld_base, masked_ones);
> }
> }
>
> @@ -2653,11 +2684,10 @@ static void emit_epilogue(struct
> lp_build_tgsi_context * bld_base)
> if (bld->gs_iface) {
> LLVMValueRef total_emitted_vertices_vec;
> LLVMValueRef emitted_prims_vec;
> - /* flush the accumulated vertices as a primitive */
> - if (bld->pending_end_primitive) {
> - end_primitive(NULL, bld_base, NULL);
> - bld->pending_end_primitive = FALSE;
> - }
> + /* implicit end_primitives, needed in case there are any unflushed
> + vertices in the cache */
> + end_primitive(NULL, bld_base, NULL);
> +
> total_emitted_vertices_vec =
> LLVMBuildLoad(builder, bld->total_emitted_vertices_vec_ptr, "");
> emitted_prims_vec =
> @@ -2767,7 +2797,6 @@ 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;
> --
> 1.7.10.4
>
>
Looks good to me.
Reviewed-by: Jose Fonseca <jfonseca at vmware.com>
More information about the mesa-dev
mailing list