draw: fix vertex id computation
authorZack Rusin <zackr@vmware.com>
Tue, 23 Jul 2013 05:29:30 +0000 (01:29 -0400)
committerZack Rusin <zackr@vmware.com>
Thu, 25 Jul 2013 06:02:59 +0000 (02:02 -0400)
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@vmware.com>
Reviewed-by: Roland Scheidegger <sroland@vmware.com>
Reviewed-by: Brian Paul <brianp@vmware.com>
Reviewed-by: Jose Fonseca <jfonseca@vmware.com>
src/gallium/auxiliary/draw/draw_llvm.c
src/gallium/auxiliary/draw/draw_llvm.h
src/gallium/auxiliary/draw/draw_private.h
src/gallium/auxiliary/draw/draw_pt.c
src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline_llvm.c

index a3174b404c1d163ba255b4243282bd9cbb3c1e64..c195a2b4defe573830afdd810c47161992efcfca 100644 (file)
@@ -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];
index 347fde2b55f4e1a34523b4065270650187b74f0b..0675e3bf17b6386fc2e344e3dfce668378de5ecc 100644 (file)
@@ -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
index d8cd8ebdb64dcde9e6696dfb5cdd6699aa8c25ef..868b6c78954090f8c54044a0da8a0150420b9d11 100644 (file)
@@ -311,6 +311,7 @@ struct draw_context
 
    unsigned instance_id;
    unsigned start_instance;
+   unsigned start_index;
 
 #ifdef HAVE_LLVM
    struct draw_llvm *llvm;
index fcc24057db074a8a1b35e6e5f6d6ce0efe6be3d7..5b16bc72ef4a90a5dfe5172a8040ac6d1f0efc3f 100644 (file)
@@ -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
index 2e47fad551a3a667e7204ac1f30c853e9141bfef..17b948a7652ba433c3369bc9ecd661d4ef882526 100644 (file)
@@ -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:
     */