[Mesa-dev] [PATCH 3/3] draw: optimize for vertex element frequency (esp. draw_llvm)

Luca Barbieri luca at luca-barbieri.com
Mon Aug 16 04:30:07 PDT 2010


We can save a bunch of computations in the LLVM code for constant
elemens.
---
 src/gallium/auxiliary/draw/draw_llvm.c      |   54 +++++++++++++++------------
 src/gallium/auxiliary/draw/draw_pt.c        |   15 ++++---
 src/gallium/auxiliary/draw/draw_pt_vcache.c |    2 +-
 3 files changed, 40 insertions(+), 31 deletions(-)

diff --git a/src/gallium/auxiliary/draw/draw_llvm.c b/src/gallium/auxiliary/draw/draw_llvm.c
index 8d53601..2ed5b25 100644
--- a/src/gallium/auxiliary/draw/draw_llvm.c
+++ b/src/gallium/auxiliary/draw/draw_llvm.c
@@ -389,36 +389,42 @@ generate_fetch(LLVMBuilderRef builder,
    LLVMValueRef indices = LLVMConstInt(LLVMInt64Type(), velem->vertex_buffer_index, 0);
    LLVMValueRef vbuffer_ptr = LLVMBuildGEP(builder, vbuffers_ptr,
                                            &indices, 1, "");
-   LLVMValueRef vb_stride = draw_jit_vbuffer_stride(builder, vbuf);
-   LLVMValueRef vb_max_index = draw_jit_vbuffer_max_index(builder, vbuf);
    LLVMValueRef vb_buffer_offset = draw_jit_vbuffer_offset(builder, vbuf);
-   LLVMValueRef cond;
-   LLVMValueRef stride;
-
-   if (velem->instance_divisor) {
-      /* array index = instance_id / instance_divisor */
-      index = LLVMBuildUDiv(builder, instance_id,
-                            LLVMConstInt(LLVMInt32Type(), velem->instance_divisor, 0),
-                            "instance_divisor");
-   }
+   LLVMValueRef offset;
 
-   /* limit index to min(inex, vb_max_index) */
-   cond = LLVMBuildICmp(builder, LLVMIntULE, index, vb_max_index, "");
-   index = LLVMBuildSelect(builder, cond, index, vb_max_index, "");
+   vbuffer_ptr = LLVMBuildLoad(builder, vbuffer_ptr, "vbuffer");
 
-   stride = LLVMBuildMul(builder, vb_stride, index, "");
+   offset = LLVMConstInt(LLVMInt32Type(), velem->src_offset, 0);
 
-   vbuffer_ptr = LLVMBuildLoad(builder, vbuffer_ptr, "vbuffer");
+   offset = LLVMBuildAdd(builder, offset,
+                      vb_buffer_offset,
+                      "");
 
-   stride = LLVMBuildAdd(builder, stride,
-                         vb_buffer_offset,
-                         "");
-   stride = LLVMBuildAdd(builder, stride,
-                         LLVMConstInt(LLVMInt32Type(), velem->src_offset, 0),
-                         "");
+   if(velem->frequency != PIPE_ELEMENT_FREQUENCY_CONSTANT)
+   {
+      LLVMValueRef vb_stride = draw_jit_vbuffer_stride(builder, vbuf);
+      LLVMValueRef vb_max_index = draw_jit_vbuffer_max_index(builder, vbuf);
+      LLVMValueRef cond;
+      LLVMValueRef variable_offset;
+
+      if (velem->frequency == PIPE_ELEMENT_FREQUENCY_PER_INSTANCE) {
+         /* array index = instance_id / instance_divisor */
+         index = LLVMBuildUDiv(builder, instance_id,
+                               LLVMConstInt(LLVMInt32Type(), velem->instance_divisor, 0),
+                               "instance_divisor");
+      }
+
+      /* limit index to min(inex, vb_max_index) */
+      cond = LLVMBuildICmp(builder, LLVMIntULE, index, vb_max_index, "");
+      index = LLVMBuildSelect(builder, cond, index, vb_max_index, "");
+
+      variable_offset = LLVMBuildMul(builder, vb_stride, index, "");
+      offset = LLVMBuildAdd(builder, offset, variable_offset, "");
+
+      /*lp_build_printf(builder, "vbuf index = %d, stride is %d\n", indices, stride);*/
+   }
 
-   /*lp_build_printf(builder, "vbuf index = %d, stride is %d\n", indices, stride);*/
-   vbuffer_ptr = LLVMBuildGEP(builder, vbuffer_ptr, &stride, 1, "");
+   vbuffer_ptr = LLVMBuildGEP(builder, vbuffer_ptr, &offset, 1, "");
 
    *res = draw_llvm_translate_from(builder, vbuffer_ptr, velem->src_format);
 }
diff --git a/src/gallium/auxiliary/draw/draw_pt.c b/src/gallium/auxiliary/draw/draw_pt.c
index 2489275..4b58899 100644
--- a/src/gallium/auxiliary/draw/draw_pt.c
+++ b/src/gallium/auxiliary/draw/draw_pt.c
@@ -260,12 +260,13 @@ draw_print_arrays(struct draw_context *draw, uint prim, int start, uint count)
          uint buf = draw->pt.vertex_element[j].vertex_buffer_index;
          ubyte *ptr = (ubyte *) draw->pt.user.vbuffer[buf];
 
-         if (draw->pt.vertex_element[j].instance_divisor) {
-            ii = draw->instance_id / draw->pt.vertex_element[j].instance_divisor;
-         }
-
          ptr += draw->pt.vertex_buffer[buf].buffer_offset;
-         ptr += draw->pt.vertex_buffer[buf].stride * ii;
+
+         if (draw->pt.vertex_element[j].frequency == PIPE_ELEMENT_FREQUENCY_PER_INSTANCE)
+            ptr += draw->pt.vertex_buffer[buf].stride * (draw->instance_id / draw->pt.vertex_element[j].instance_divisor);
+         else if (draw->pt.vertex_element[j].frequency == PIPE_ELEMENT_FREQUENCY_PER_VERTEX)
+            ptr += draw->pt.vertex_buffer[buf].stride * ii;
+
          ptr += draw->pt.vertex_element[j].src_offset;
 
          debug_printf("  Attr %u: ", j);
@@ -363,11 +364,13 @@ draw_arrays_instanced(struct draw_context *draw,
 
    if (0) {
       unsigned int i;
+      const char* frequency_names[] = {"per-vertex", "per-instance", "constant"};
       debug_printf("Elements:\n");
       for (i = 0; i < draw->pt.nr_vertex_elements; i++) {
-         debug_printf("  %u: src_offset=%u  inst_div=%u   vbuf=%u  format=%s\n",
+         debug_printf("  %u: src_offset=%u  frequency=%s inst_div=%u   vbuf=%u  format=%s\n",
                       i,
                       draw->pt.vertex_element[i].src_offset,
+                      frequency_names[draw->pt.vertex_element[i].frequency],
                       draw->pt.vertex_element[i].instance_divisor,
                       draw->pt.vertex_element[i].vertex_buffer_index,
                       util_format_name(draw->pt.vertex_element[i].src_format));
diff --git a/src/gallium/auxiliary/draw/draw_pt_vcache.c b/src/gallium/auxiliary/draw/draw_pt_vcache.c
index a848b54..a41ed61 100644
--- a/src/gallium/auxiliary/draw/draw_pt_vcache.c
+++ b/src/gallium/auxiliary/draw/draw_pt_vcache.c
@@ -358,7 +358,7 @@ any_instance_divisors(const struct draw_context *draw)
    uint i;
 
    for (i = 0; i < draw->pt.nr_vertex_elements; i++) {
-      uint div = draw->pt.vertex_element[i].instance_divisor;
+      uint div = draw->pt.vertex_element[i].frequency == PIPE_ELEMENT_FREQUENCY_PER_INSTANCE;
       if (div)
          return TRUE;
    }
-- 
1.7.0.4



More information about the mesa-dev mailing list