summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/gallium/auxiliary/util/u_vbuf_mgr.c94
1 files changed, 58 insertions, 36 deletions
diff --git a/src/gallium/auxiliary/util/u_vbuf_mgr.c b/src/gallium/auxiliary/util/u_vbuf_mgr.c
index 6ed1d0b2b7e..46b37aa7484 100644
--- a/src/gallium/auxiliary/util/u_vbuf_mgr.c
+++ b/src/gallium/auxiliary/util/u_vbuf_mgr.c
@@ -507,51 +507,73 @@ u_vbuf_upload_buffers(struct u_vbuf_priv *mgr,
int min_index, int max_index,
unsigned instance_count)
{
- unsigned i, nr = mgr->ve->count;
+ unsigned i;
unsigned count = max_index + 1 - min_index;
- boolean uploaded[PIPE_MAX_ATTRIBS] = {0};
-
- for (i = 0; i < nr; i++) {
- unsigned index = mgr->ve->ve[i].vertex_buffer_index;
+ unsigned nr_velems = mgr->ve->count;
+ unsigned nr_vbufs = mgr->b.nr_vertex_buffers;
+ unsigned start_offset[PIPE_MAX_ATTRIBS];
+ unsigned end_offset[PIPE_MAX_ATTRIBS] = {0};
+
+ /* Determine how much data needs to be uploaded. */
+ for (i = 0; i < nr_velems; i++) {
+ struct pipe_vertex_element *velem = &mgr->ve->ve[i];
+ unsigned index = velem->vertex_buffer_index;
+ unsigned instance_div = velem->instance_divisor;
struct pipe_vertex_buffer *vb = &mgr->b.vertex_buffer[index];
+ unsigned first, size;
- if (vb->buffer &&
- u_vbuf_resource(vb->buffer)->user_ptr &&
- !uploaded[index]) {
- unsigned first, size;
- boolean flushed;
- unsigned instance_div = mgr->ve->ve[i].instance_divisor;
-
- if (instance_div) {
- first = 0;
- size = vb->stride *
- ((instance_count + instance_div - 1) / instance_div);
- } else if (vb->stride) {
- first = vb->stride * min_index;
- size = vb->stride * count;
-
- /* Unusual case when stride is smaller than the format size.
- * XXX This won't work with interleaved arrays. */
- if (mgr->ve->native_format_size[i] > vb->stride)
- size += mgr->ve->native_format_size[i] - vb->stride;
- } else {
- first = 0;
- size = mgr->ve->native_format_size[i];
- }
+ assert(vb->buffer);
+
+ if (!u_vbuf_resource(vb->buffer)->user_ptr) {
+ continue;
+ }
- u_upload_data(mgr->b.uploader, first, size,
- u_vbuf_resource(vb->buffer)->user_ptr + first,
- &mgr->b.real_vertex_buffer[index].buffer_offset,
- &mgr->b.real_vertex_buffer[index].buffer,
- &flushed);
+ first = vb->buffer_offset + velem->src_offset;
- mgr->b.real_vertex_buffer[index].buffer_offset -= first;
+ if (!vb->stride) {
+ /* Constant attrib. */
+ size = mgr->ve->src_format_size[i];
+ } else if (instance_div) {
+ /* Per-instance attrib. */
+ unsigned count = (instance_count + instance_div - 1) / instance_div;
+ size = vb->stride * (count - 1) + mgr->ve->src_format_size[i];
+ } else {
+ /* Per-vertex attrib. */
+ first += vb->stride * min_index;
+ size = vb->stride * (count - 1) + mgr->ve->src_format_size[i];
+ }
- uploaded[index] = TRUE;
+ /* Update offsets. */
+ if (!end_offset[index]) {
+ start_offset[index] = first;
+ end_offset[index] = first + size;
} else {
- assert(mgr->b.real_vertex_buffer[index].buffer);
+ if (first < start_offset[index])
+ start_offset[index] = first;
+ if (first + size > end_offset[index])
+ end_offset[index] = first + size;
}
}
+
+ /* Upload buffers. */
+ for (i = 0; i < nr_vbufs; i++) {
+ unsigned start = start_offset[i];
+ unsigned end = end_offset[i];
+ boolean flushed;
+
+ if (!end) {
+ continue;
+ }
+ assert(start < end);
+
+ u_upload_data(mgr->b.uploader, start, end - start,
+ u_vbuf_resource(mgr->b.vertex_buffer[i].buffer)->user_ptr + start,
+ &mgr->b.real_vertex_buffer[i].buffer_offset,
+ &mgr->b.real_vertex_buffer[i].buffer,
+ &flushed);
+
+ mgr->b.real_vertex_buffer[i].buffer_offset -= start;
+ }
}
static void u_vbuf_compute_max_index(struct u_vbuf_priv *mgr)