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 03cce5154c57ac993e4076a26ad466ea7ceb7767..957acd26a2a81fa4b7c4ed62f13679364ff63be6 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 3431d29b050b39f2141c680d4adb8a55c33d7f3f..f5abe021c433d73e3f78bb586db3a014bed65851 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 d4841226bfa3ef3aad4ae86ae8177bc5b1f3a9d1..09d7a5ee14df54aceae92e7efd133e98db62b9c6 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 9a53516046b77026ad0a2f6ea1ceb69e66a41e35..152ee141568d6ad7062c27ec0da7ba4a06fc4595 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 81afe170c1bfe87f54dd3dd23deab84266ba3732..bc57803c842b254ea61c30fc642829cce1696951 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);
 }