[Mesa-dev] [PATCH] gallivm: fix exec_mask interaction with geometry shader after end of main
Zack Rusin
zackr at vmware.com
Mon Aug 12 12:31:03 PDT 2013
Ah, that looks like a great catch.
Reviewed-by: Zack Rusin <zackr at vmware.com>
----- Original Message -----
> From: Roland Scheidegger <sroland at vmware.com>
>
> Because we must maintain an exec_mask even if there's currently nothing
> on the mask stack, we can still have an exec_mask at the end of the program.
> Effectively, this mask should be set back to default when returning from
> main.
> Without relying on END/RET opcode (I think it's valid to have neither) it is
> actually difficult to do this, as there doesn't seem any reasonable place to
> do it, so instead let's just say the exec_mask is invalid outside main (which
> it really is effectively).
> The problem is that geometry shader called end_primitive outside the shader
> (in the epilogue), and as a result used a bogus mask, leading to bugs if we
> had to set the (somewhat misnamed) ret_in_main bit anywhere. So just avoid
> the mask combining function when called from outside the shader.
> ---
> src/gallium/auxiliary/gallivm/lp_bld_tgsi.c | 2 +-
> src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c | 28
> +++++++++++------------
> 2 files changed, 14 insertions(+), 16 deletions(-)
>
> diff --git a/src/gallium/auxiliary/gallivm/lp_bld_tgsi.c
> b/src/gallium/auxiliary/gallivm/lp_bld_tgsi.c
> index 495940c..5a9e8d0 100644
> --- a/src/gallium/auxiliary/gallivm/lp_bld_tgsi.c
> +++ b/src/gallium/auxiliary/gallivm/lp_bld_tgsi.c
> @@ -466,7 +466,7 @@ lp_build_tgsi_llvm(
>
> while (bld_base->pc != -1) {
> struct tgsi_full_instruction *instr = bld_base->instructions +
> - bld_base->pc;
> + bld_base->pc;
> const struct tgsi_opcode_info *opcode_info =
> tgsi_get_opcode_info(instr->Instruction.Opcode);
> if (!lp_build_tgsi_inst_llvm(bld_base, instr)) {
> diff --git a/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c
> b/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c
> index 589ea4f..db8e997 100644
> --- a/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c
> +++ b/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c
> @@ -2691,11 +2691,21 @@ end_primitive_masked(struct lp_build_tgsi_context *
> bld_base,
> LLVMBuilderRef builder = bld->bld_base.base.gallivm->builder;
>
> if (bld->gs_iface->end_primitive) {
> + struct lp_build_context *uint_bld = &bld_base->uint_bld;
> LLVMValueRef emitted_vertices_vec =
> LLVMBuildLoad(builder, bld->emitted_vertices_vec_ptr, "");
> LLVMValueRef emitted_prims_vec =
> LLVMBuildLoad(builder, bld->emitted_prims_vec_ptr, "");
>
> + LLVMValueRef emitted_mask = lp_build_cmp(uint_bld, PIPE_FUNC_NOTEQUAL,
> + emitted_vertices_vec,
> + 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 */
> + mask = LLVMBuildAnd(builder, mask, emitted_mask, "");
> +
> bld->gs_iface->end_primitive(bld->gs_iface, &bld->bld_base,
> emitted_vertices_vec,
> emitted_prims_vec);
> @@ -2735,20 +2745,7 @@ end_primitive(
> 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 mask = mask_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 */
> - mask = LLVMBuildAnd(builder, mask, emitted_mask, "");
> -
> end_primitive_masked(bld_base, mask);
> }
> }
> @@ -3148,8 +3145,9 @@ static void emit_epilogue(struct lp_build_tgsi_context
> * bld_base)
> LLVMValueRef total_emitted_vertices_vec;
> LLVMValueRef emitted_prims_vec;
> /* implicit end_primitives, needed in case there are any unflushed
> - vertices in the cache */
> - end_primitive(NULL, bld_base, NULL);
> + vertices in the cache. Note must not call end_primitive here
> + since the exec_mask is not valid at this point. */
> + end_primitive_masked(bld_base, lp_build_mask_value(bld->mask));
>
> total_emitted_vertices_vec =
> LLVMBuildLoad(builder, bld->total_emitted_vertices_vec_ptr, "");
> --
> 1.7.9.5
>
More information about the mesa-dev
mailing list