i965: Use negative relocation deltas to minimse vertex uploads
authorChris Wilson <chris@chris-wilson.co.uk>
Tue, 1 Mar 2011 14:46:50 +0000 (14:46 +0000)
committerChris Wilson <chris@chris-wilson.co.uk>
Tue, 1 Mar 2011 16:34:50 +0000 (16:34 +0000)
With relaxed relocation checking in the kernel, we can specify a
negative delta (i.e. pointing outside of the target bo) in order to fake
a range in a large buffer. We only then need to upload the elements used
and adjust the buffer offset such that they correspond with the indices
used in the DrawArrays.

(Depends on libdrm 0209428b3918c4336018da9293cdcbf7f8fedfb6)

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_upload.c
src/mesa/drivers/dri/intel/intel_screen.c
src/mesa/drivers/dri/intel/intel_screen.h

index 2e8561d36a6a2d909c9e3a15dd5f66c4f9bf95ef..897220b6ea39b004fef640e0157bfe5d12261629 100644 (file)
@@ -460,7 +460,7 @@ struct brw_context
    GLboolean has_negative_rhw_bug;
    GLboolean has_aa_line_parameters;
    GLboolean has_pln;
-;
+
    struct {
       struct brw_state_flags dirty;
 
index 1e129f98e0c7085802fd649713ac65bb838a99c6..185f1ffa598b2d7c9105273a2e8645e4c5af1007 100644 (file)
@@ -278,7 +278,7 @@ static void brw_prepare_vertices(struct brw_context *brw)
    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;
+   int delta, i, j;
 
    struct brw_vertex_element *upload[VERT_ATTRIB_MAX];
    GLuint nr_uploads = 0;
@@ -401,21 +401,25 @@ static void brw_prepare_vertices(struct brw_context *brw)
     * only the used elements [min_index, max_index] so long as we adjust all
     * the values used in the 3DPRIMITIVE i.e. by setting the vertex bias.
     */
+   brw->vb.start_vertex_bias = 0;
+   delta = min_index;
    if (nr_uploads == brw->vb.nr_enabled) {
-      brw->vb.start_vertex_bias = min_index;
-   } else {
-      brw->vb.start_vertex_bias = 0;
-      min_index = 0;
+      brw->vb.start_vertex_bias = -delta;
+      delta = 0;
    }
+   if (delta && !brw->intel.intelScreen->relaxed_relocations)
+      min_index = delta = 0;
 
    /* Handle any arrays to be uploaded. */
    if (nr_uploads > 1) {
       if (interleaved && interleaved <= 2*total_size) {
+        struct brw_vertex_buffer *buffer = &brw->vb.buffers[j];
         /* All uploads are interleaved, so upload the arrays together as
          * interleaved.  First, upload the contents and set up upload[0].
          */
         copy_array_to_vbo_array(brw, upload[0], min_index, max_index,
-                                &brw->vb.buffers[j], interleaved);
+                                buffer, interleaved);
+        buffer->offset -= delta * interleaved;
 
         for (i = 0; i < nr_uploads; i++) {
            /* Then, just point upload[i] at upload[0]'s buffer. */
@@ -462,14 +466,17 @@ static void brw_prepare_vertices(struct brw_context *brw)
         intel_upload_unmap(&brw->intel, map, offset * count, offset,
                            &buffer->bo, &buffer->offset);
         buffer->stride = offset;
+        buffer->offset -= delta * offset;
 
         nr_uploads = 0;
       }
    }
    /* Upload non-interleaved arrays */
    for (i = 0; i < nr_uploads; i++) {
+      struct brw_vertex_buffer *buffer = &brw->vb.buffers[j];
       copy_array_to_vbo_array(brw, upload[i], min_index, max_index,
-                             &brw->vb.buffers[j], upload[i]->element_size);
+                             buffer, upload[i]->element_size);
+      buffer->offset -= delta * buffer->stride;
       upload[i]->buffer = j++;
       upload[i]->offset = 0;
    }
index 746da462ee2e6c8cd09b9e22fdf4ae19bab00215..5c95c72732ee95ae81e95ac6b3a566a17d378d5c 100644 (file)
@@ -309,6 +309,13 @@ intel_get_param(__DRIscreen *psp, int param, int *value)
    return GL_TRUE;
 }
 
+static GLboolean
+intel_get_boolean(__DRIscreen *psp, int param)
+{
+   int value = 0;
+   return intel_get_param(psp, param, &value) && value;
+}
+
 static void
 nop_callback(GLuint key, void *data, void *userData)
 {
@@ -482,6 +489,10 @@ intel_init_bufmgr(struct intel_screen *intelScreen)
 
    intelScreen->named_regions = _mesa_NewHashTable();
 
+   intelScreen->relaxed_relocations = 0;
+   intelScreen->relaxed_relocations |=
+      intel_get_boolean(spriv, I915_PARAM_HAS_RELAXED_DELTA) << 0;
+
    return GL_TRUE;
 }
 
index 5863093f001765bf1316e9ce029cf63736c8525e..0f0b5be56dc0e287a705859e40fda7cbbaaec63d 100644 (file)
@@ -43,6 +43,7 @@ struct intel_screen
    __DRIscreen *driScrnPriv;
 
    GLboolean no_hw;
+   GLuint relaxed_relocations;
 
    GLboolean no_vbo;
    dri_bufmgr *bufmgr;