From dfc6c96e5c470f6136cad26b753c024538fd09a0 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 11 Feb 2011 14:14:18 +0000 Subject: i965: upload normal arrays as interleaved 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 --- src/mesa/drivers/dri/i965/brw_draw_upload.c | 102 ++++++++++++++++++++-------- 1 file changed, 72 insertions(+), 30 deletions(-) (limited to 'src/mesa') diff --git a/src/mesa/drivers/dri/i965/brw_draw_upload.c b/src/mesa/drivers/dri/i965/brw_draw_upload.c index 587e74426f..8952e97674 100644 --- a/src/mesa/drivers/dri/i965/brw_draw_upload.c +++ b/src/mesa/drivers/dri/i965/brw_draw_upload.c @@ -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: -- cgit v1.2.3