From: Thomas Hellstrom Date: Thu, 30 Jun 2011 06:52:19 +0000 (+0200) Subject: svga: Fix multiple uploads of the same user-buffer. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=542194251c36e88601cb20b96a4094da5d0ae675;p=mesa.git svga: Fix multiple uploads of the same user-buffer. If a user-buffer was referenced twice by a draw command, the affected ranges were uploaded separately, with only the last one being referenced by the hardware. Make sure we upload only a single range. Signed-off-by: Thomas Hellstrom --- diff --git a/src/gallium/drivers/svga/svga_pipe_draw.c b/src/gallium/drivers/svga/svga_pipe_draw.c index 358ef82db31..0b4d41bb807 100644 --- a/src/gallium/drivers/svga/svga_pipe_draw.c +++ b/src/gallium/drivers/svga/svga_pipe_draw.c @@ -42,22 +42,42 @@ #include "util/u_upload_mgr.h" /** - * svga_upload_user_buffers - upload parts of user buffers + * Determine the ranges to upload for the user-buffers referenced + * by the next draw command. * - * This function streams a part of a user buffer to hw and sets - * svga_buffer::source_offset to the first byte uploaded. After upload - * also svga_buffer::uploaded::buffer is set to !NULL + * TODO: It might be beneficial to support multiple ranges. In that case, + * the struct svga_buffer::uploaded member should be made an array or a + * list, since we need to account for the possibility that different ranges + * may be uploaded to different hardware buffers chosen by the utility + * upload manager. */ -static int -svga_upload_user_buffers(struct svga_context *svga, - unsigned start, - unsigned count, - unsigned instance_count) +static void +svga_user_buffer_range(struct svga_context *svga, + unsigned start, + unsigned count, + unsigned instance_count) { const struct pipe_vertex_element *ve = svga->curr.velems->velem; - unsigned i; - int ret; + int i; + + /* + * Release old uploaded range (if not done already) and + * initialize new ranges. + */ + + for (i=0; i < svga->curr.velems->count; i++) { + struct pipe_vertex_buffer *vb = + &svga->curr.vb[ve[i].vertex_buffer_index]; + + if (vb->buffer && svga_buffer_is_user_buffer(vb->buffer)) { + struct svga_buffer *buffer = svga_buffer(vb->buffer); + + pipe_resource_reference(&buffer->uploaded.buffer, NULL); + buffer->uploaded.start = ~0; + buffer->uploaded.end = 0; + } + } for (i=0; i < svga->curr.velems->count; i++) { struct pipe_vertex_buffer *vb = @@ -66,30 +86,71 @@ svga_upload_user_buffers(struct svga_context *svga, if (vb->buffer && svga_buffer_is_user_buffer(vb->buffer)) { struct svga_buffer *buffer = svga_buffer(vb->buffer); unsigned first, size; - boolean flushed; unsigned instance_div = ve[i].instance_divisor; unsigned elemSize = util_format_get_blocksize(ve->src_format); svga->dirty |= SVGA_NEW_VBUFFER; if (instance_div) { - first = 0; + first = ve[i].src_offset; count = (instance_count + instance_div - 1) / instance_div; size = vb->stride * (count - 1) + elemSize; } else if (vb->stride) { - first = vb->stride * start; + first = vb->stride * start + ve[i].src_offset; size = vb->stride * (count - 1) + elemSize; } else { /* Only a single vertex! * Upload with the largest vertex size the hw supports, * if possible. */ - first = 0; + first = ve[i].src_offset; size = MIN2(16, vb->buffer->width0); } + buffer->uploaded.start = MIN2(buffer->uploaded.start, first); + buffer->uploaded.end = MAX2(buffer->uploaded.end, first + size); + } + } +} + +/** + * svga_upload_user_buffers - upload parts of user buffers + * + * This function streams a part of a user buffer to hw and fills + * svga_buffer::uploaded with information on the upload. + */ + +static int +svga_upload_user_buffers(struct svga_context *svga, + unsigned start, + unsigned count, + unsigned instance_count) +{ + const struct pipe_vertex_element *ve = svga->curr.velems->velem; + unsigned i; + int ret; + + svga_user_buffer_range(svga, start, count, instance_count); + + for (i=0; i < svga->curr.velems->count; i++) { + struct pipe_vertex_buffer *vb = + &svga->curr.vb[ve[i].vertex_buffer_index]; + + if (vb->buffer && svga_buffer_is_user_buffer(vb->buffer)) { + struct svga_buffer *buffer = svga_buffer(vb->buffer); + boolean flushed; + + /* + * Check if already uploaded. Otherwise go ahead and upload. + */ + + if (buffer->uploaded.buffer) + continue; + ret = u_upload_buffer( svga->upload_vb, - 0, first, size, + 0, + buffer->uploaded.start, + buffer->uploaded.end - buffer->uploaded.start, &buffer->b.b, &buffer->uploaded.offset, &buffer->uploaded.buffer, @@ -106,11 +167,10 @@ svga_upload_user_buffers(struct svga_context *svga, buffer, buffer->uploaded.buffer, buffer->uploaded.offset, - first, - size); + buffer->uploaded.start, + buffer->uploaded.end - buffer->uploaded.start); vb->buffer_offset = buffer->uploaded.offset; - buffer->source_offset = first; } } @@ -143,7 +203,8 @@ svga_release_user_upl_buffers(struct svga_context *svga) if (vb->buffer && svga_buffer_is_user_buffer(vb->buffer)) { struct svga_buffer *buffer = svga_buffer(vb->buffer); - buffer->source_offset = 0; + buffer->uploaded.start = ~0; + buffer->uploaded.end = 0; if (buffer->uploaded.buffer) pipe_resource_reference(&buffer->uploaded.buffer, NULL); } diff --git a/src/gallium/drivers/svga/svga_resource_buffer.h b/src/gallium/drivers/svga/svga_resource_buffer.h index 69d6f72a11c..ca8c8d1f5ea 100644 --- a/src/gallium/drivers/svga/svga_resource_buffer.h +++ b/src/gallium/drivers/svga/svga_resource_buffer.h @@ -129,14 +129,13 @@ struct svga_buffer * is the relative offset within that buffer. */ unsigned offset; - } uploaded; - /** - * For user buffers, this is the offset to the data about to be - * referenced by the next draw command, and hence the data that needs - * to be uploaded. - */ - unsigned source_offset; + /** + * Range of user buffer that is uploaded in @buffer at @offset. + */ + unsigned start; + unsigned end; + } uploaded; /** * DMA'ble memory. diff --git a/src/gallium/drivers/svga/svga_state_vdecl.c b/src/gallium/drivers/svga/svga_state_vdecl.c index 2375a022f97..47eab1a9739 100644 --- a/src/gallium/drivers/svga/svga_state_vdecl.c +++ b/src/gallium/drivers/svga/svga_state_vdecl.c @@ -82,8 +82,8 @@ static int emit_hw_vs_vdecl( struct svga_context *svga, continue; buffer = svga_buffer(vb->buffer); - if (buffer->source_offset > offset) { - tmp_neg_bias = buffer->source_offset - offset; + if (buffer->uploaded.start > offset) { + tmp_neg_bias = buffer->uploaded.start - offset; if (vb->stride) tmp_neg_bias = (tmp_neg_bias + vb->stride - 1) / vb->stride; neg_bias = MAX2(neg_bias, tmp_neg_bias); @@ -116,7 +116,7 @@ static int emit_hw_vs_vdecl( struct svga_context *svga, decl.array.offset = (vb->buffer_offset + ve[i].src_offset + neg_bias * vb->stride - - buffer->source_offset); + - buffer->uploaded.start); assert(decl.array.offset >= 0);