[Mesa-dev] [PATCH] draw: fix vertex id computation

Roland Scheidegger sroland at vmware.com
Wed Jul 24 16:31:48 PDT 2013


Am 24.07.2013 23:22, schrieb Zack Rusin:
> vertex id has to be unaffected by the start index (i.e. when calling
> draw arrays with start_index = 5, the first vertex_id has to still
> be 0, not 5) and it has to be equal to the index when performing
> indexed rendering (in which case it has to be unaffected by the
> index bias). This fixes our behavior.
> 
> Signed-off-by: Zack Rusin <zackr at vmware.com>
> ---
>  src/gallium/auxiliary/draw/draw_llvm.c             |   36 +++++++++++++++-----
>  src/gallium/auxiliary/draw/draw_llvm.h             |    6 ++--
>  src/gallium/auxiliary/draw/draw_private.h          |    1 +
>  src/gallium/auxiliary/draw/draw_pt.c               |    1 +
>  .../draw/draw_pt_fetch_shade_pipeline_llvm.c       |    6 ++--
>  5 files changed, 37 insertions(+), 13 deletions(-)
> 
> diff --git a/src/gallium/auxiliary/draw/draw_llvm.c b/src/gallium/auxiliary/draw/draw_llvm.c
> index a3174b4..c195a2b 100644
> --- a/src/gallium/auxiliary/draw/draw_llvm.c
> +++ b/src/gallium/auxiliary/draw/draw_llvm.c
> @@ -1486,7 +1486,7 @@ draw_llvm_generate(struct draw_llvm *llvm, struct draw_llvm_variant *variant,
>     struct gallivm_state *gallivm = variant->gallivm;
>     LLVMContextRef context = gallivm->context;
>     LLVMTypeRef int32_type = LLVMInt32TypeInContext(context);
> -   LLVMTypeRef arg_types[9];
> +   LLVMTypeRef arg_types[10];
>     unsigned num_arg_types =
>        elts ? Elements(arg_types) : Elements(arg_types) - 1;
>     LLVMTypeRef func_type;
> @@ -1496,6 +1496,7 @@ draw_llvm_generate(struct draw_llvm *llvm, struct draw_llvm_variant *variant,
>     struct lp_type vs_type;
>     LLVMValueRef end, start;
>     LLVMValueRef count, fetch_elts, fetch_elt_max, fetch_count;
> +   LLVMValueRef vertex_id_offset;
>     LLVMValueRef stride, step, io_itr;
>     LLVMValueRef io_ptr, vbuffers_ptr, vb_ptr;
>     LLVMValueRef zero = lp_build_const_int32(gallivm, 0);
> @@ -1541,6 +1542,7 @@ draw_llvm_generate(struct draw_llvm *llvm, struct draw_llvm_variant *variant,
>     arg_types[i++] = int32_type;                     /* stride */
>     arg_types[i++] = get_vb_ptr_type(variant);       /* pipe_vertex_buffer's */
>     arg_types[i++] = int32_type;                     /* instance_id */
> +   arg_types[i++] = int32_type;                     /* vertex_id_offset */
>  
>     func_type = LLVMFunctionType(int32_type, arg_types, num_arg_types, 0);
>  
> @@ -1565,6 +1567,7 @@ draw_llvm_generate(struct draw_llvm *llvm, struct draw_llvm_variant *variant,
>     stride                    = LLVMGetParam(variant_func, 5 + (elts ? 1 : 0));
>     vb_ptr                    = LLVMGetParam(variant_func, 6 + (elts ? 1 : 0));
>     system_values.instance_id = LLVMGetParam(variant_func, 7 + (elts ? 1 : 0));
> +   vertex_id_offset          = LLVMGetParam(variant_func, 8 + (elts ? 1 : 0));
>  
>     lp_build_name(context_ptr, "context");
>     lp_build_name(io_ptr, "io");
> @@ -1572,6 +1575,7 @@ draw_llvm_generate(struct draw_llvm *llvm, struct draw_llvm_variant *variant,
>     lp_build_name(stride, "stride");
>     lp_build_name(vb_ptr, "vb");
>     lp_build_name(system_values.instance_id, "instance_id");
> +   lp_build_name(vertex_id_offset, "vertex_id_offset");
>  
>     if (elts) {
>        fetch_elts    = LLVMGetParam(variant_func, 3);
> @@ -1646,22 +1650,19 @@ draw_llvm_generate(struct draw_llvm *llvm, struct draw_llvm_variant *variant,
>  #endif
>        system_values.vertex_id = lp_build_zero(gallivm, lp_type_uint_vec(32, 32*vector_length));
>        for (i = 0; i < vector_length; ++i) {
> -         LLVMValueRef true_index =
> +         LLVMValueRef vert_index =
>              LLVMBuildAdd(builder,
>                           lp_loop.counter,
>                           lp_build_const_int32(gallivm, i), "");
> -         true_index = LLVMBuildAdd(builder, start, true_index, "");
> +         LLVMValueRef true_index =
> +            LLVMBuildAdd(builder, start, vert_index, "");
> +         LLVMValueRef vertex_id;
>  
>           /* make sure we're not out of bounds which can happen
>            * if fetch_count % 4 != 0, because on the last iteration
>            * a few of the 4 vertex fetches will be out of bounds */
>           true_index = lp_build_min(&bld, true_index, fetch_max);
>  
> -         system_values.vertex_id = LLVMBuildInsertElement(
> -            gallivm->builder,
> -            system_values.vertex_id, true_index,
> -            lp_build_const_int32(gallivm, i), "");
> -
>           if (elts) {
>              LLVMValueRef fetch_ptr;
>              LLVMValueRef index_overflowed;
> @@ -1673,7 +1674,7 @@ draw_llvm_generate(struct draw_llvm *llvm, struct draw_llvm_variant *variant,
>              index_overflowed = LLVMBuildICmp(builder, LLVMIntUGT,
>                                               true_index, fetch_elt_max,
>                                               "index_overflowed");
> -            
> +
>              lp_build_if(&if_ctx, gallivm, index_overflowed);
>              {
>                 /* Generate maximum possible index so that
> @@ -1698,6 +1699,23 @@ draw_llvm_generate(struct draw_llvm *llvm, struct draw_llvm_variant *variant,
>              lp_build_endif(&if_ctx);
>              true_index = LLVMBuildLoad(builder, index_ptr, "true_index");
>           }
> +         /* in the paths with elts vertex id has to be unaffected by the
> +          * index bias and because indices inside our elements array have
> +          * already had index bias applied we need to subtract it here to
> +          * get back to the original index.
> +          * in the linear paths vertex id has to be unaffected by the
> +          * original start index and because we abuse the 'start' variable
> +          * to either represent the actual start index or the index at which
> +          * the primitive was split (we split rendering into chunks of at
> +          * most 4095-vertices) we need to back out the original start
> +          * index out of our vertex id here.
> +          */
> +         vertex_id = LLVMBuildSub(builder, true_index, vertex_id_offset, "");
> +
> +         system_values.vertex_id = LLVMBuildInsertElement(
> +            gallivm->builder,
> +            system_values.vertex_id, vertex_id,
> +            lp_build_const_int32(gallivm, i), "");
>  
>           for (j = 0; j < draw->pt.nr_vertex_elements; ++j) {
>              struct pipe_vertex_element *velem = &draw->pt.vertex_element[j];
> diff --git a/src/gallium/auxiliary/draw/draw_llvm.h b/src/gallium/auxiliary/draw/draw_llvm.h
> index 347fde2..0675e3b 100644
> --- a/src/gallium/auxiliary/draw/draw_llvm.h
> +++ b/src/gallium/auxiliary/draw/draw_llvm.h
> @@ -263,7 +263,8 @@ typedef int
>                        unsigned count,
>                        unsigned stride,
>                        struct pipe_vertex_buffer *vertex_buffers,
> -                      unsigned instance_id);
> +                      unsigned instance_id,
> +                      unsigned vertex_id_offset);
>  
>  
>  typedef int
> @@ -275,7 +276,8 @@ typedef int
>                             unsigned fetch_count,
>                             unsigned stride,
>                             struct pipe_vertex_buffer *vertex_buffers,
> -                           unsigned instance_id);
> +                           unsigned instance_id,
> +                           unsigned vertex_id_offset);
>  
>  
>  typedef int
> diff --git a/src/gallium/auxiliary/draw/draw_private.h b/src/gallium/auxiliary/draw/draw_private.h
> index d8cd8eb..868b6c7 100644
> --- a/src/gallium/auxiliary/draw/draw_private.h
> +++ b/src/gallium/auxiliary/draw/draw_private.h
> @@ -311,6 +311,7 @@ struct draw_context
>  
>     unsigned instance_id;
>     unsigned start_instance;
> +   unsigned start_index;
>  
>  #ifdef HAVE_LLVM
>     struct draw_llvm *llvm;
> diff --git a/src/gallium/auxiliary/draw/draw_pt.c b/src/gallium/auxiliary/draw/draw_pt.c
> index fcc2405..5b16bc7 100644
> --- a/src/gallium/auxiliary/draw/draw_pt.c
> +++ b/src/gallium/auxiliary/draw/draw_pt.c
> @@ -535,6 +535,7 @@ draw_vbo(struct draw_context *draw,
>     }
>  
>     draw->pt.max_index = index_limit - 1;
> +   draw->start_index = info->start;
>  
>     /*
>      * TODO: We could use draw->pt.max_index to further narrow
> 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 2e47fad..17b948a 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
> @@ -353,7 +353,8 @@ llvm_pipeline_generic( struct draw_pt_middle_end *middle,
>                                         fetch_info->count,
>                                         fpme->vertex_size,
>                                         draw->pt.vertex_buffer,
> -                                       draw->instance_id);
> +                                       draw->instance_id,
> +                                       draw->start_index);
>     else
>        clipped = fpme->current_variant->jit_func_elts( &fpme->llvm->jit_context,
>                                              llvm_vert_info.verts,
> @@ -363,7 +364,8 @@ llvm_pipeline_generic( struct draw_pt_middle_end *middle,
>                                              fetch_info->count,
>                                              fpme->vertex_size,
>                                              draw->pt.vertex_buffer,
> -                                            draw->instance_id);
> +                                            draw->instance_id,
> +                                            draw->pt.user.eltBias);
>  
>     /* Finished with fetch and vs:
>      */
> 

LGTM. Is that handled correctly in the non-llvm path already?

Roland


More information about the mesa-dev mailing list