intel: extend current vertex buffers
authorChris Wilson <chris@chris-wilson.co.uk>
Fri, 18 Feb 2011 10:37:43 +0000 (10:37 +0000)
committerChris Wilson <chris@chris-wilson.co.uk>
Mon, 21 Feb 2011 12:59:36 +0000 (12:59 +0000)
If the next vertex arrays are a (discontiguous) continuation of the
current arrays, such that the new vertices are simply offset from the
start of the current vertex buffer definitions we can reuse those
defintions and avoid the overhead of relocations and invalidations.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
src/mesa/drivers/dri/i965/brw_context.h
src/mesa/drivers/dri/i965/brw_draw.c
src/mesa/drivers/dri/i965/brw_draw_upload.c
src/mesa/drivers/dri/i965/brw_vtbl.c
src/mesa/drivers/dri/intel/intel_buffer_objects.c

index 03cce51..957acd2 100644 (file)
@@ -489,16 +489,26 @@ struct brw_context
    struct {
       struct brw_vertex_element inputs[VERT_ATTRIB_MAX];
       struct brw_vertex_buffer buffers[VERT_ATTRIB_MAX];
+      struct {
+             uint32_t handle;
+             uint32_t offset;
+             uint32_t stride;
+      } current_buffers[VERT_ATTRIB_MAX];
 
       struct brw_vertex_element *enabled[VERT_ATTRIB_MAX];
       GLuint nr_enabled;
-      GLuint nr_buffers;
+      GLuint nr_buffers, nr_current_buffers;
 
       /* Summary of size and varying of active arrays, so we can check
        * for changes to this state:
        */
       struct brw_vertex_info info;
       unsigned int min_index, max_index;
+
+      /* Offset from start of vertex buffer so we can avoid redefining
+       * the same VB packed over and over again.
+       */
+      unsigned int start_vertex_bias;
    } vb;
 
    struct {
@@ -512,6 +522,7 @@ struct brw_context
       /* Updates to these fields are signaled by BRW_NEW_INDEX_BUFFER. */
       drm_intel_bo *bo;
       unsigned int offset;
+
       /* Offset to index buffer index to use in CMD_3D_PRIM so that we can
        * avoid re-uploading the IB packet over and over if we're actually
        * referencing the same index buffer.
@@ -832,4 +843,3 @@ float convert_param(enum param_conversion conversion, float param)
 GLboolean brw_do_cubemap_normalize(struct exec_list *instructions);
 
 #endif
-
index 3431d29..f5abe02 100644 (file)
@@ -145,9 +145,14 @@ static void brw_emit_prim(struct brw_context *brw,
    prim_packet.start_vert_location = prim->start;
    if (prim->indexed)
       prim_packet.start_vert_location += brw->ib.start_vertex_offset;
+   else
+      prim_packet.start_vert_location += brw->vb.start_vertex_bias;
    prim_packet.instance_count = 1;
    prim_packet.start_instance_location = 0;
    prim_packet.base_vert_location = prim->basevertex;
+   if (prim->indexed)
+      prim_packet.base_vert_location += brw->vb.start_vertex_bias;
+
 
    /* If we're set to always flush, do it before and after the primitive emit.
     * We want to catch both missed flushes that hurt instruction/state cache
index d484122..09d7a5e 100644 (file)
@@ -271,11 +271,11 @@ static void brw_prepare_vertices(struct brw_context *brw)
    struct gl_context *ctx = &brw->intel.ctx;
    struct intel_context *intel = intel_context(ctx);
    GLbitfield vs_inputs = brw->vs.prog_data->inputs_read; 
-   GLuint i, j;
    const unsigned char *ptr = NULL;
    GLuint interleaved = 0, total_size = 0;
    unsigned int min_index = brw->vb.min_index;
    unsigned int max_index = brw->vb.max_index;
+   int i, j;
 
    struct brw_vertex_element *upload[VERT_ATTRIB_MAX];
    GLuint nr_uploads = 0;
@@ -455,6 +455,33 @@ static void brw_prepare_vertices(struct brw_context *brw)
                              upload[i]->element_size);
       upload[i]->buffer = j++;
    }
+
+   /* can we simply extend the current vb? */
+   brw->vb.start_vertex_bias = 0;
+   if (j == brw->vb.nr_current_buffers) {
+      int delta = 0;
+      for (i = 0; i < j; i++) {
+        int d;
+
+        if (brw->vb.current_buffers[i].handle != brw->vb.buffers[i].bo->handle ||
+            brw->vb.current_buffers[i].stride != brw->vb.buffers[i].stride)
+           break;
+
+        d = brw->vb.buffers[i].offset - brw->vb.current_buffers[i].offset;
+        if (delta == 0)
+           delta = d / brw->vb.current_buffers[i].stride;
+        else if (delta * brw->vb.current_buffers[i].stride != d)
+           break;
+      }
+
+      if (i == j) {
+        brw->vb.start_vertex_bias = delta;
+        while (--j >= 0)
+           drm_intel_bo_unreference(brw->vb.buffers[j].bo);
+        j = 0;
+      }
+   }
+
    brw->vb.nr_buffers = j;
 
 validate:
@@ -504,25 +531,33 @@ static void brw_emit_vertices(struct brw_context *brw)
    /* Now emit VB and VEP state packets.
     */
 
-   BEGIN_BATCH(1 + 4*brw->vb.nr_buffers);
-   OUT_BATCH((CMD_VERTEX_BUFFER << 16) | (4*brw->vb.nr_buffers - 1));
-   for (i = 0; i < brw->vb.nr_buffers; i++) {
-      struct brw_vertex_buffer *buffer = &brw->vb.buffers[i];
-      uint32_t dw0;
+   if (brw->vb.nr_buffers) {
+      BEGIN_BATCH(1 + 4*brw->vb.nr_buffers);
+      OUT_BATCH((CMD_VERTEX_BUFFER << 16) | (4*brw->vb.nr_buffers - 1));
+      for (i = 0; i < brw->vb.nr_buffers; i++) {
+        struct brw_vertex_buffer *buffer = &brw->vb.buffers[i];
+        uint32_t dw0;
+
+        if (intel->gen >= 6) {
+           dw0 = GEN6_VB0_ACCESS_VERTEXDATA | (i << GEN6_VB0_INDEX_SHIFT);
+        } else {
+           dw0 = BRW_VB0_ACCESS_VERTEXDATA | (i << BRW_VB0_INDEX_SHIFT);
+        }
 
-      if (intel->gen >= 6) {
-        dw0 = GEN6_VB0_ACCESS_VERTEXDATA | (i << GEN6_VB0_INDEX_SHIFT);
-      } else {
-        dw0 = BRW_VB0_ACCESS_VERTEXDATA | (i << BRW_VB0_INDEX_SHIFT);
+        OUT_BATCH(dw0 | (buffer->stride << BRW_VB0_PITCH_SHIFT));
+        OUT_RELOC(buffer->bo, I915_GEM_DOMAIN_VERTEX, 0, buffer->offset);
+        if (intel->gen >= 5) {
+           OUT_RELOC(buffer->bo, I915_GEM_DOMAIN_VERTEX, 0, buffer->bo->size - 1);
+        } else
+           OUT_BATCH(0);
+        OUT_BATCH(0); /* Instance data step rate */
+
+        brw->vb.current_buffers[i].handle = buffer->bo->handle;
+        brw->vb.current_buffers[i].offset = buffer->offset;
+        brw->vb.current_buffers[i].stride = buffer->stride;
       }
-
-      OUT_BATCH(dw0 | (buffer->stride << BRW_VB0_PITCH_SHIFT));
-      OUT_RELOC(buffer->bo, I915_GEM_DOMAIN_VERTEX, 0, buffer->offset);
-      if (intel->gen >= 5) {
-        OUT_RELOC(buffer->bo, I915_GEM_DOMAIN_VERTEX, 0, buffer->bo->size - 1);
-      } else
-          OUT_BATCH(0);
-      OUT_BATCH(0); /* Instance data step rate */
+      brw->vb.nr_current_buffers = i;
+      ADVANCE_BATCH();
    }
    ADVANCE_BATCH();
 
index 9a53516..152ee14 100644 (file)
@@ -158,6 +158,8 @@ static void brw_new_batch( struct intel_context *intel )
    brw->state.dirty.mesa |= ~0;
    brw->state.dirty.brw |= ~0;
    brw->state.dirty.cache |= ~0;
+
+   brw->vb.nr_current_buffers = 0;
 }
 
 static void brw_invalidate_state( struct intel_context *intel, GLuint new_state )
index 81afe17..bc57803 100644 (file)
@@ -120,10 +120,8 @@ intel_bufferobj_free(struct gl_context * ctx, struct gl_buffer_object *obj)
    if (intel_obj->region) {
       intel_bufferobj_release_region(intel, intel_obj);
    }
-   else if (intel_obj->buffer) {
-      drm_intel_bo_unreference(intel_obj->buffer);
-   }
 
+   drm_intel_bo_unreference(intel_obj->buffer);
    free(intel_obj);
 }