[Mesa-dev] [PATCH 6/6] gallivm: implement breakc and implicit primitive flushing
Brian Paul
brianp at vmware.com
Wed Mar 27 07:44:00 PDT 2013
On 03/26/2013 10:38 AM, Zack Rusin wrote:
> we were missing implementation of the breakc instruction and our
> TGSI semantics currently require an implicit endprim at the end
> of GS if none is present - this implements both.
Maybe I'm dense, but off-hand I don't see the relationship between
endprim and breakc. Can you elaborate?
>
> 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_action.c | 1 +
> src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c | 38 ++++++++++++++++++++
> 3 files changed, 45 insertions(+)
>
> diff --git a/src/gallium/auxiliary/gallivm/lp_bld_tgsi.h b/src/gallium/auxiliary/gallivm/lp_bld_tgsi.h
> index 4c6456e..4acc592 100644
> --- a/src/gallium/auxiliary/gallivm/lp_bld_tgsi.h
> +++ b/src/gallium/auxiliary/gallivm/lp_bld_tgsi.h
> @@ -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;
> diff --git a/src/gallium/auxiliary/gallivm/lp_bld_tgsi_action.c b/src/gallium/auxiliary/gallivm/lp_bld_tgsi_action.c
> index 41ddd99..55bb8e3 100644
> --- a/src/gallium/auxiliary/gallivm/lp_bld_tgsi_action.c
> +++ b/src/gallium/auxiliary/gallivm/lp_bld_tgsi_action.c
> @@ -867,6 +867,7 @@ lp_set_default_actions(struct lp_build_tgsi_context * bld_base)
> bld_base->op_actions[TGSI_OPCODE_COS].fetch_args = scalar_unary_fetch_args;
> bld_base->op_actions[TGSI_OPCODE_EX2].fetch_args = scalar_unary_fetch_args;
> bld_base->op_actions[TGSI_OPCODE_IF].fetch_args = scalar_unary_fetch_args;
> + bld_base->op_actions[TGSI_OPCODE_BREAKC].fetch_args = scalar_unary_fetch_args;
> bld_base->op_actions[TGSI_OPCODE_KIL].fetch_args = kil_fetch_args;
> bld_base->op_actions[TGSI_OPCODE_KILP].fetch_args = kilp_fetch_args;
> bld_base->op_actions[TGSI_OPCODE_RCP].fetch_args = scalar_unary_fetch_args;
> diff --git a/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c b/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c
> index 95633ab..36e49ac 100644
> --- a/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c
> +++ b/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c
> @@ -213,6 +213,23 @@ static void lp_exec_break(struct lp_exec_mask *mask)
> lp_exec_mask_update(mask);
> }
>
> +
> +static void lp_exec_break_condition(struct lp_exec_mask *mask, LLVMValueRef cond)
> +{
> + LLVMBuilderRef builder = mask->bld->gallivm->builder;
> + LLVMValueRef exec_mask = LLVMBuildNot(builder,
> + mask->exec_mask,
> + "break");
> +
> + exec_mask = LLVMBuildAnd(builder, exec_mask, cond, "");
> +
> + mask->break_mask = LLVMBuildAnd(builder,
> + mask->break_mask,
> + exec_mask, "break_full");
> +
> + lp_exec_mask_update(mask);
> +}
> +
> static void lp_exec_continue(struct lp_exec_mask *mask)
> {
> LLVMBuilderRef builder = mask->bld->gallivm->builder;
> @@ -2190,6 +2207,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 +2230,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;
> }
> }
>
> @@ -2250,6 +2269,17 @@ brk_emit(
> }
>
> static void
> +breakc_emit(
> + 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);
> +
> + lp_exec_break_condition(&bld->exec_mask, emit_data->args[0]);
> +}
> +
> +static void
> if_emit(
> const struct lp_build_tgsi_action * action,
> struct lp_build_tgsi_context * bld_base,
> @@ -2504,6 +2534,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_args) {
> + /* 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_args->gs_epilogue(&bld->bld_base,
> bld->total_emitted_vertices_vec,
> bld->emitted_prims_vec,
> @@ -2572,6 +2608,7 @@ lp_build_tgsi_soa(struct gallivm_state *gallivm,
> bld.bld_base.op_actions[TGSI_OPCODE_BGNLOOP].emit = bgnloop_emit;
> bld.bld_base.op_actions[TGSI_OPCODE_BGNSUB].emit = bgnsub_emit;
> bld.bld_base.op_actions[TGSI_OPCODE_BRK].emit = brk_emit;
> + bld.bld_base.op_actions[TGSI_OPCODE_BREAKC].emit = breakc_emit;
> bld.bld_base.op_actions[TGSI_OPCODE_CAL].emit = cal_emit;
> bld.bld_base.op_actions[TGSI_OPCODE_CONT].emit = cont_emit;
> bld.bld_base.op_actions[TGSI_OPCODE_DDX].emit = ddx_emit;
> @@ -2607,6 +2644,7 @@ lp_build_tgsi_soa(struct gallivm_state *gallivm,
> /* inputs are always indirect with gs */
> bld.indirect_files |= (1<< TGSI_FILE_INPUT);
> bld.gs_args = gs_args;
> + 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;
More information about the mesa-dev
mailing list