diff options
author | Marek Olšák <[email protected]> | 2011-05-14 19:25:55 +0200 |
---|---|---|
committer | Marek Olšák <[email protected]> | 2011-05-14 20:03:03 +0200 |
commit | 51095f74cf92d3cada7366ce898ade7693570b48 (patch) | |
tree | 6d6b118c2dbe000f69c941ecf97ef0c436e1888c | |
parent | ad2999d2113356d526b39774eb8114e974dac048 (diff) |
u_vbuf_mgr: fix max_index computation once again
See how I compute and use the 'unused' variable in the code.
It's crucial for getting max_index right.
Fixed with the help of apitrace.
(bisecting the problematic draw call manually was not fun though)
This should fix:
https://bugs.freedesktop.org/show_bug.cgi?id=36268
https://bugs.freedesktop.org/show_bug.cgi?id=36609
-rw-r--r-- | src/gallium/auxiliary/util/u_vbuf_mgr.c | 62 |
1 files changed, 47 insertions, 15 deletions
diff --git a/src/gallium/auxiliary/util/u_vbuf_mgr.c b/src/gallium/auxiliary/util/u_vbuf_mgr.c index dea2928f950..a034483ee5c 100644 --- a/src/gallium/auxiliary/util/u_vbuf_mgr.c +++ b/src/gallium/auxiliary/util/u_vbuf_mgr.c @@ -53,9 +53,11 @@ struct u_vbuf_mgr_elements { unsigned count; struct pipe_vertex_element ve[PIPE_MAX_ATTRIBS]; - /* If (velem[i].src_format != real_format[i]), the vertex buffer + unsigned src_format_size[PIPE_MAX_ATTRIBS]; + + /* If (velem[i].src_format != native_format[i]), the vertex buffer * referenced by the vertex element cannot be used for rendering and - * its vertex data must be translated to real_format[i]. */ + * its vertex data must be translated to native_format[i]. */ enum pipe_format native_format[PIPE_MAX_ATTRIBS]; unsigned native_format_size[PIPE_MAX_ATTRIBS]; @@ -353,6 +355,8 @@ u_vbuf_mgr_create_vertex_elements(struct u_vbuf_mgr *mgrb, for (i = 0; i < count; i++) { enum pipe_format format = ve->ve[i].src_format; + ve->src_format_size[i] = util_format_get_blocksize(format); + /* Choose a native format. * For now we don't care about the alignment, that's going to * be sorted out later. */ @@ -460,7 +464,6 @@ void u_vbuf_mgr_set_vertex_buffers(struct u_vbuf_mgr *mgrb, struct u_vbuf_mgr_priv *mgr = (struct u_vbuf_mgr_priv*)mgrb; unsigned i; - mgr->b.max_index = ~0; mgr->any_user_vbs = FALSE; mgr->incompatible_vb_layout = FALSE; @@ -483,23 +486,16 @@ void u_vbuf_mgr_set_vertex_buffers(struct u_vbuf_mgr *mgrb, pipe_resource_reference(&mgr->b.vertex_buffer[i].buffer, vb->buffer); pipe_resource_reference(&mgr->b.real_vertex_buffer[i], NULL); - if (u_vbuf_resource(vb->buffer)->user_ptr) { - mgr->any_user_vbs = TRUE; + if (!vb->buffer) { continue; } - pipe_resource_reference(&mgr->b.real_vertex_buffer[i], vb->buffer); - - /* The stride of zero means we will be fetching only the first - * vertex, so don't care about max_index. */ - if (!vb->stride) { + if (u_vbuf_resource(vb->buffer)->user_ptr) { + mgr->any_user_vbs = TRUE; continue; } - /* Update the maximum index. */ - mgr->b.max_index = - MIN2(mgr->b.max_index, - (vb->buffer->width0 - vb->buffer_offset) / vb->stride - 1); + pipe_resource_reference(&mgr->b.real_vertex_buffer[i], vb->buffer); } for (; i < mgr->b.nr_real_vertex_buffers; i++) { @@ -519,7 +515,7 @@ static void u_vbuf_upload_buffers(struct u_vbuf_mgr_priv *mgr, unsigned instance_count, boolean *upload_flushed) { - int i, nr = mgr->ve->count; + unsigned i, nr = mgr->ve->count; unsigned count = max_index + 1 - min_index; boolean uploaded[PIPE_MAX_ATTRIBS] = {0}; @@ -562,6 +558,40 @@ static void u_vbuf_upload_buffers(struct u_vbuf_mgr_priv *mgr, } } +static void u_vbuf_mgr_compute_max_index(struct u_vbuf_mgr_priv *mgr) +{ + unsigned i, nr = mgr->ve->count; + + mgr->b.max_index = ~0; + + for (i = 0; i < nr; i++) { + struct pipe_vertex_buffer *vb = + &mgr->b.vertex_buffer[mgr->ve->ve[i].vertex_buffer_index]; + int unused; + unsigned max_index; + + if (!vb->buffer || + !vb->stride || + u_vbuf_resource(vb->buffer)->user_ptr) { + continue; + } + + /* How many bytes is unused after the last vertex. + * width0 may be "count*stride - unused" and we have to compensate + * for that when dividing by stride. */ + unused = vb->stride - + (mgr->ve->ve[i].src_offset + mgr->ve->src_format_size[i]); + assert(unused >= 0); + + /* Compute the maximum index for this vertex element. */ + max_index = + (vb->buffer->width0 - vb->buffer_offset + (unsigned)unused) / + vb->stride - 1; + + mgr->b.max_index = MIN2(mgr->b.max_index, max_index); + } +} + void u_vbuf_mgr_draw_begin(struct u_vbuf_mgr *mgrb, const struct pipe_draw_info *info, boolean *buffers_updated, @@ -571,6 +601,8 @@ void u_vbuf_mgr_draw_begin(struct u_vbuf_mgr *mgrb, boolean bufs_updated = FALSE, upload_flushed = FALSE; int min_index, max_index; + u_vbuf_mgr_compute_max_index(mgr); + min_index = info->min_index - info->index_bias; if (info->max_index == ~0) { max_index = mgr->b.max_index; |