i965: upload normal arrays as interleaved
authorChris Wilson <chris@chris-wilson.co.uk>
Fri, 11 Feb 2011 14:14:18 +0000 (14:14 +0000)
committerChris Wilson <chris@chris-wilson.co.uk>
Mon, 21 Feb 2011 12:59:35 +0000 (12:59 +0000)
Upload the non-vbo arrays into a single interleaved buffer object, and
so need to just emit a single vertex buffer relocation.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
src/mesa/drivers/dri/i965/brw_draw_upload.c

index 587e74426f74462f7252adbfbfa119e67400f4ef..8952e97674cabe1760462c95ee9796b3bb624449 100644 (file)
@@ -272,7 +272,7 @@ static void brw_prepare_vertices(struct brw_context *brw)
    GLbitfield vs_inputs = brw->vs.prog_data->inputs_read; 
    GLuint i, j;
    const unsigned char *ptr = NULL;
-   GLuint interleave = 0;
+   GLuint interleaved = 0, total_size = 0;
    unsigned int min_index = brw->vb.min_index;
    unsigned int max_index = brw->vb.max_index;
 
@@ -313,8 +313,9 @@ static void brw_prepare_vertices(struct brw_context *brw)
 
    for (i = j = 0; i < brw->vb.nr_enabled; i++) {
       struct brw_vertex_element *input = brw->vb.enabled[i];
+      int type_size = get_size(input->glarray->Type);
 
-      input->element_size = get_size(input->glarray->Type) * input->glarray->Size;
+      input->element_size = type_size * input->glarray->Size;
 
       if (_mesa_is_bufferobj(input->glarray->BufferObj)) {
         struct intel_buffer_object *intel_buffer =
@@ -366,53 +367,94 @@ static void brw_prepare_vertices(struct brw_context *brw)
         /* Queue the buffer object up to be uploaded in the next pass,
          * when we've decided if we're doing interleaved or not.
          */
-        if (input->attrib == VERT_ATTRIB_POS) {
+        if (nr_uploads == 0) {
            /* Position array not properly enabled:
             */
-            if (input->glarray->StrideB == 0) {
+           if (input->attrib == VERT_ATTRIB_POS &&
+               input->glarray->StrideB == 0) {
                intel->Fallback = GL_TRUE; /* boolean, not bitfield */
                return;
             }
 
-           interleave = input->glarray->StrideB;
+           interleaved = input->glarray->StrideB;
            ptr = input->glarray->Ptr;
         }
-        else if (interleave != input->glarray->StrideB ||
-                 (uintptr_t)(input->glarray->Ptr - ptr) > interleave)
+        else if (interleaved != input->glarray->StrideB ||
+                 (uintptr_t)(input->glarray->Ptr - ptr) > interleaved)
         {
-           interleave = 0;
+           interleaved = 0;
+        }
+        else if (total_size & (type_size -1))
+        {
+           /* enforce natural alignment (for doubles) */
+           interleaved = 0;
         }
 
         upload[nr_uploads++] = input;
+        total_size += input->element_size;
       }
    }
 
    /* Handle any arrays to be uploaded. */
-   if (nr_uploads > 1 && interleave && interleave <= 256) {
-      /* 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], &brw->vb.buffers[j],
-                             interleave);
-
-      for (i = 0; i < nr_uploads; i++) {
-        /* Then, just point upload[i] at upload[0]'s buffer. */
-        upload[i]->offset =
-           ((const unsigned char *)upload[i]->glarray->Ptr - upload[0]->glarray->Ptr);
-        upload[i]->buffer = j;
+   if (nr_uploads > 1) {
+      if (interleaved && interleaved <= 2*total_size) {
+        /* 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], &brw->vb.buffers[j],
+                                interleaved);
+
+        for (i = 0; i < nr_uploads; i++) {
+           /* Then, just point upload[i] at upload[0]'s buffer. */
+           upload[i]->offset =
+              ((const unsigned char *)upload[i]->glarray->Ptr - ptr);
+           upload[i]->buffer = j;
+        }
+        j++;
+
+        nr_uploads = 0;
       }
-      j++;
-   }
-   else {
-      /* Upload non-interleaved arrays */
-      for (i = 0; i < nr_uploads; i++) {
-          copy_array_to_vbo_array(brw,
-                                 upload[i], &brw->vb.buffers[j],
-                                 upload[i]->element_size);
-         upload[i]->buffer = j++;
+      else if (total_size < 2048) {
+        /* Upload non-interleaved arrays into a single interleaved array */
+        struct brw_vertex_buffer *buffer = &brw->vb.buffers[j];
+        int count = upload[0]->count, offset;
+        char *map;
+
+        map = intel_upload_map(&brw->intel, total_size * count,
+                               &buffer->bo, &buffer->offset);
+
+        for (i = offset = 0; i < nr_uploads; i++) {
+           const unsigned char *src = upload[i]->glarray->Ptr;
+           int size = upload[i]->element_size;
+           int stride = upload[i]->glarray->StrideB;
+           char *dst = map + offset;
+           int n;
+
+           for (n = 0; n < count; n++) {
+              memcpy(dst, src, size);
+              src += stride;
+              dst += total_size;
+           }
+
+           upload[i]->offset = offset;
+           upload[i]->buffer = j;
+
+           offset += size;
+        }
+        buffer->stride = offset;
+        j++;
+
+        nr_uploads = 0;
       }
    }
+   /* Upload non-interleaved arrays */
+   for (i = 0; i < nr_uploads; i++) {
+      copy_array_to_vbo_array(brw,
+                             upload[i], &brw->vb.buffers[j],
+                             upload[i]->element_size);
+      upload[i]->buffer = j++;
+   }
    brw->vb.nr_buffers = j;
 
 validate: