[Mesa-dev] [PATCH] draw: handle edge flags in llvm path

Brian Paul brianp at vmware.com
Tue Dec 15 09:40:58 PST 2015


Reviewed-by: Brian Paul <brianp at vmware.com>


On 12/15/2015 10:06 AM, sroland at vmware.com wrote:
> From: Roland Scheidegger <sroland at vmware.com>
>
> We just ignored them altogether. While this feature is rather old-fashioned
> supporting it is actually rather trivial.
> This fixes the associated piglit tests (2 gl-1.0-edgeflag, 2 gl-2.0-edgeflag
> and all (7) of point-vertex-id).
>
> v2: comment fixes, and make the use of the edgeflag in clipmask consistent
> with when it's actually there (should be impossible to hit a case where the
> difference would actually matter but still...)
> ---
>   src/gallium/auxiliary/draw/draw_llvm.c             | 86 +++++++++++++++-------
>   .../draw/draw_pt_fetch_shade_pipeline_llvm.c       |  1 +
>   2 files changed, 61 insertions(+), 26 deletions(-)
>
> diff --git a/src/gallium/auxiliary/draw/draw_llvm.c b/src/gallium/auxiliary/draw/draw_llvm.c
> index a966e45..89ed045 100644
> --- a/src/gallium/auxiliary/draw/draw_llvm.c
> +++ b/src/gallium/auxiliary/draw/draw_llvm.c
> @@ -880,7 +880,8 @@ store_aos_array(struct gallivm_state *gallivm,
>                   LLVMValueRef* aos,
>                   int attrib,
>                   int num_outputs,
> -                LLVMValueRef clipmask)
> +                LLVMValueRef clipmask,
> +                boolean need_edgeflag)
>   {
>      LLVMBuilderRef builder = gallivm->builder;
>      LLVMValueRef attr_index = lp_build_const_int32(gallivm, attrib);
> @@ -912,8 +913,14 @@ store_aos_array(struct gallivm_state *gallivm,
>          */
>         assert(DRAW_TOTAL_CLIP_PLANES==14);
>         /* initialize vertex id:16 = 0xffff, pad:1 = 0, edgeflag:1 = 1 */
> -      vertex_id_pad_edgeflag = (0xffff << 16) | (1 << DRAW_TOTAL_CLIP_PLANES);
> -      val = lp_build_const_int_vec(gallivm, lp_int_type(soa_type), vertex_id_pad_edgeflag);
> +      if (!need_edgeflag) {
> +         vertex_id_pad_edgeflag = (0xffff << 16) | (1 << DRAW_TOTAL_CLIP_PLANES);
> +      }
> +      else {
> +         vertex_id_pad_edgeflag = (0xffff << 16);
> +      }
> +      val = lp_build_const_int_vec(gallivm, lp_int_type(soa_type),
> +                                   vertex_id_pad_edgeflag);
>         /* OR with the clipmask */
>         cliptmp = LLVMBuildOr(builder, val, clipmask, "");
>         for (i = 0; i < vector_length; i++) {
> @@ -943,7 +950,7 @@ convert_to_aos(struct gallivm_state *gallivm,
>                  LLVMValueRef clipmask,
>                  int num_outputs,
>                  struct lp_type soa_type,
> -               boolean have_clipdist)
> +               boolean need_edgeflag)
>   {
>      LLVMBuilderRef builder = gallivm->builder;
>      unsigned chan, attrib, i;
> @@ -999,7 +1006,8 @@ convert_to_aos(struct gallivm_state *gallivm,
>                         aos,
>                         attrib,
>                         num_outputs,
> -                      clipmask);
> +                      clipmask,
> +                      need_edgeflag);
>      }
>   #if DEBUG_STORE
>      lp_build_printf(gallivm, "   # storing end\n");
> @@ -1135,11 +1143,7 @@ generate_clipmask(struct draw_llvm *llvm,
>                     struct gallivm_state *gallivm,
>                     struct lp_type vs_type,
>                     LLVMValueRef (*outputs)[TGSI_NUM_CHANNELS],
> -                  boolean clip_xy,
> -                  boolean clip_z,
> -                  boolean clip_user,
> -                  boolean clip_halfz,
> -                  unsigned ucp_enable,
> +                  struct draw_llvm_variant_key *key,
>                     LLVMValueRef context_ptr,
>                     boolean *have_clipdist)
>   {
> @@ -1155,7 +1159,9 @@ generate_clipmask(struct draw_llvm *llvm,
>      const unsigned pos = llvm->draw->vs.position_output;
>      const unsigned cv = llvm->draw->vs.clipvertex_output;
>      int num_written_clipdistance = llvm->draw->vs.vertex_shader->info.num_written_clipdistance;
> -   bool have_cd = false;
> +   boolean have_cd = false;
> +   boolean clip_user = key->clip_user;
> +   unsigned ucp_enable = key->ucp_enable;
>      unsigned cd[2];
>
>      cd[0] = llvm->draw->vs.clipdistance_output[0];
> @@ -1196,7 +1202,11 @@ generate_clipmask(struct draw_llvm *llvm,
>      }
>
>      /* Cliptest, for hardwired planes */
> -   if (clip_xy) {
> +   /*
> +    * XXX should take guardband into account (currently not in key).
> +    * Otherwise might run the draw pipeline stages for nothing.
> +    */
> +   if (key->clip_xy) {
>         /* plane 1 */
>         test = lp_build_compare(gallivm, f32_type, PIPE_FUNC_GREATER, pos_x , pos_w);
>         temp = shift;
> @@ -1224,9 +1234,9 @@ generate_clipmask(struct draw_llvm *llvm,
>         mask = LLVMBuildOr(builder, mask, test, "");
>      }
>
> -   if (clip_z) {
> +   if (key->clip_z) {
>         temp = lp_build_const_int_vec(gallivm, i32_type, 16);
> -      if (clip_halfz) {
> +      if (key->clip_halfz) {
>            /* plane 5 */
>            test = lp_build_compare(gallivm, f32_type, PIPE_FUNC_GREATER, zero, pos_z);
>            test = LLVMBuildAnd(builder, test, temp, "");
> @@ -1313,6 +1323,20 @@ generate_clipmask(struct draw_llvm *llvm,
>            }
>         }
>      }
> +   if (key->need_edgeflags) {
> +      /*
> +       * This isn't really part of clipmask but stored the same in vertex
> +       * header later, so do it here.
> +       */
> +      unsigned edge_attr = llvm->draw->vs.edgeflag_output;
> +      LLVMValueRef one = lp_build_const_vec(gallivm, f32_type, 1.0);
> +      LLVMValueRef edgeflag = LLVMBuildLoad(builder, outputs[edge_attr][0], "");
> +      test = lp_build_compare(gallivm, f32_type, PIPE_FUNC_EQUAL, one, edgeflag);
> +      temp = lp_build_const_int_vec(gallivm, i32_type,
> +                                    1LL << DRAW_TOTAL_CLIP_PLANES);
> +      test = LLVMBuildAnd(builder, test, temp, "");
> +      mask = LLVMBuildOr(builder, mask, test, "");
> +   }
>      return mask;
>   }
>
> @@ -1324,7 +1348,8 @@ generate_clipmask(struct draw_llvm *llvm,
>   static LLVMValueRef
>   clipmask_booli32(struct gallivm_state *gallivm,
>                    const struct lp_type vs_type,
> -                 LLVMValueRef clipmask_bool_ptr)
> +                 LLVMValueRef clipmask_bool_ptr,
> +                 boolean edgeflag_in_clipmask)
>   {
>      LLVMBuilderRef builder = gallivm->builder;
>      LLVMTypeRef int32_type = LLVMInt32TypeInContext(gallivm->context);
> @@ -1334,8 +1359,18 @@ clipmask_booli32(struct gallivm_state *gallivm,
>      int i;
>
>      /*
> -    * Can do this with log2(vector length) pack instructions and one extract
> -    * (as we don't actually need a or) with sse2 which would be way better.
> +    * We need to invert the edgeflag bit from the clipmask here
> +    * (because the result is really if we want to run the pipeline or not
> +    * and we (may) need it if edgeflag was 0).
> +    */
> +   if (edgeflag_in_clipmask) {
> +      struct lp_type i32_type = lp_int_type(vs_type);
> +      LLVMValueRef edge = lp_build_const_int_vec(gallivm, i32_type,
> +                                                 1LL << DRAW_TOTAL_CLIP_PLANES);
> +      clipmask_bool = LLVMBuildXor(builder, clipmask_bool, edge, "");
> +   }
> +   /*
> +    * Could do much better with just cmp/movmskps.
>       */
>      for (i=0; i < vs_type.length; i++) {
>         temp = LLVMBuildExtractElement(builder, clipmask_bool,
> @@ -1531,8 +1566,9 @@ draw_llvm_generate(struct draw_llvm *llvm, struct draw_llvm_variant *variant,
>      const boolean bypass_viewport = key->has_gs || key->bypass_viewport ||
>                                      llvm->draw->vs.vertex_shader->info.writes_viewport_index;
>      const boolean enable_cliptest = !key->has_gs && (key->clip_xy ||
> -                                                    key->clip_z  ||
> -                                                    key->clip_user);
> +                                                    key->clip_z ||
> +                                                    key->clip_user ||
> +                                                    key->need_edgeflags);
>      LLVMValueRef variant_func;
>      const unsigned pos = llvm->draw->vs.position_output;
>      const unsigned cv = llvm->draw->vs.clipvertex_output;
> @@ -1771,11 +1807,7 @@ draw_llvm_generate(struct draw_llvm *llvm, struct draw_llvm_variant *variant,
>                                            gallivm,
>                                            vs_type,
>                                            outputs,
> -                                         key->clip_xy,
> -                                         key->clip_z,
> -                                         key->clip_user,
> -                                         key->clip_halfz,
> -                                         key->ucp_enable,
> +                                         key,
>                                            context_ptr, &have_clipdist);
>               temp = LLVMBuildOr(builder, clipmask, temp, "");
>               /* store temporary clipping boolean value */
> @@ -1800,14 +1832,15 @@ draw_llvm_generate(struct draw_llvm *llvm, struct draw_llvm_variant *variant,
>          */
>         convert_to_aos(gallivm, io, NULL, outputs, clipmask,
>                        vs_info->num_outputs, vs_type,
> -                     have_clipdist);
> +                     enable_cliptest && key->need_edgeflags);
>      }
>      lp_build_loop_end_cond(&lp_loop, count, step, LLVMIntUGE);
>
>      sampler->destroy(sampler);
>
>      /* return clipping boolean value for function */
> -   ret = clipmask_booli32(gallivm, vs_type, clipmask_bool_ptr);
> +   ret = clipmask_booli32(gallivm, vs_type, clipmask_bool_ptr,
> +                          enable_cliptest && key->need_edgeflags);
>
>      LLVMBuildRet(builder, ret);
>
> @@ -1841,6 +1874,7 @@ draw_llvm_make_variant_key(struct draw_llvm *llvm, char *store)
>      key->clip_user = llvm->draw->clip_user;
>      key->bypass_viewport = llvm->draw->bypass_viewport;
>      key->clip_halfz = llvm->draw->rasterizer->clip_halfz;
> +   /* XXX assumes edgeflag output not at 0 */
>      key->need_edgeflags = (llvm->draw->vs.edgeflag_output ? TRUE : FALSE);
>      key->ucp_enable = llvm->draw->rasterizer->clip_plane_enable;
>      key->has_gs = llvm->draw->gs.geometry_shader != NULL;
> diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline_llvm.c b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline_llvm.c
> index 2d7569b..edd4541 100644
> --- a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline_llvm.c
> +++ b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline_llvm.c
> @@ -453,6 +453,7 @@ llvm_pipeline_generic(struct draw_pt_middle_end *middle,
>                                  draw->vs.vertex_shader->info.writes_viewport_index)) {
>            clipped = draw_pt_post_vs_run( fpme->post_vs, vert_info, prim_info );
>         }
> +      /* "clipped" also includes non-one edgeflag */
>         if (clipped) {
>            opt |= PT_PIPELINE;
>         }
>



More information about the mesa-dev mailing list