From 17f776c27be266f253194db9dc11764254b1fc86 Mon Sep 17 00:00:00 2001 From: Marek Olšák Date: Sun, 30 Apr 2017 01:20:19 +0200 Subject: st/mesa: upload zero-stride vertex attributes here MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is the best place to do it. Now drivers without u_vbuf don't have to do it. v2: use correct upload size and optimal alignment Tested-by: Edmondo Tommasina Reviewed-by: Brian Paul Reviewed-by: Nicolai Hähnle --- src/mesa/state_tracker/st_atom_array.c | 61 +++++++++++++++++++++++++--------- src/mesa/state_tracker/st_context.c | 2 ++ src/mesa/state_tracker/st_context.h | 1 + 3 files changed, 48 insertions(+), 16 deletions(-) diff --git a/src/mesa/state_tracker/st_atom_array.c b/src/mesa/state_tracker/st_atom_array.c index cc9cac1b336..1327a196eff 100644 --- a/src/mesa/state_tracker/st_atom_array.c +++ b/src/mesa/state_tracker/st_atom_array.c @@ -44,6 +44,7 @@ #include "cso_cache/cso_context.h" #include "util/u_math.h" +#include "util/u_upload_mgr.h" #include "main/bufferobj.h" #include "main/glformats.h" @@ -334,6 +335,11 @@ is_interleaved_arrays(const struct st_vertex_program *vp, continue; stride = array->StrideB; /* in bytes */ + + /* To keep things simple, don't allow interleaved zero-stride attribs. */ + if (stride == 0) + return false; + bufObj = array->BufferObj; if (attr == 0) { /* save info about the first array */ @@ -571,6 +577,7 @@ setup_non_interleaved_attribs(struct st_context *st, struct pipe_vertex_buffer vbuffer[PIPE_MAX_ATTRIBS]; struct pipe_vertex_element velements[PIPE_MAX_ATTRIBS] = {{0}}; unsigned num_vbuffers = 0; + unsigned unref_buffers = 0; GLuint attr; for (attr = 0; attr < num_inputs;) { @@ -608,23 +615,39 @@ setup_non_interleaved_attribs(struct st_context *st, vbuffer[bufidx].buffer_offset = pointer_to_offset(array->Ptr); } else { - /* wrap user data */ - void *ptr; - - if (array->Ptr) { - ptr = (void *) array->Ptr; - } - else { - /* no array, use ctx->Current.Attrib[] value */ - ptr = (void *) ctx->Current.Attrib[mesaAttr]; - stride = 0; + if (stride == 0) { + unsigned size = array->_ElementSize; + /* This is optimal for GPU cache line usage if the upload size + * is <= cache line size. + */ + unsigned alignment = util_next_power_of_two(size); + void *ptr = array->Ptr ? (void*)array->Ptr : + (void*)ctx->Current.Attrib[mesaAttr]; + + vbuffer[bufidx].is_user_buffer = false; + vbuffer[bufidx].buffer.resource = NULL; + + /* Use const_uploader for zero-stride vertex attributes, because + * it may use a better memory placement than stream_uploader. + * The reason is that zero-stride attributes can be fetched many + * times (thousands of times), so a better placement is going to + * perform better. + * + * Upload the maximum possible size, which is 4x GLdouble = 32. + */ + u_upload_data(st->can_bind_const_buffer_as_vertex ? + st->pipe->const_uploader : + st->pipe->stream_uploader, + 0, size, alignment, ptr, + &vbuffer[bufidx].buffer_offset, + &vbuffer[bufidx].buffer.resource); + unref_buffers |= 1u << bufidx; + } else { + assert(array->Ptr); + vbuffer[bufidx].buffer.user = array->Ptr; + vbuffer[bufidx].is_user_buffer = true; + vbuffer[bufidx].buffer_offset = 0; } - - assert(ptr); - - vbuffer[bufidx].buffer.user = ptr; - vbuffer[bufidx].is_user_buffer = !!ptr; /* if NULL, then unbind */ - vbuffer[bufidx].buffer_offset = 0; } /* common-case setup */ @@ -642,6 +665,12 @@ setup_non_interleaved_attribs(struct st_context *st, } set_vertex_attribs(st, vbuffer, num_vbuffers, velements, num_inputs); + + /* Unreference uploaded zero-stride vertex buffers. */ + while (unref_buffers) { + unsigned i = u_bit_scan(&unref_buffers); + pipe_resource_reference(&vbuffer[i].buffer.resource, NULL); + } } void st_update_array(struct st_context *st) diff --git a/src/mesa/state_tracker/st_context.c b/src/mesa/state_tracker/st_context.c index d99791100a7..c9017646687 100644 --- a/src/mesa/state_tracker/st_context.c +++ b/src/mesa/state_tracker/st_context.c @@ -338,6 +338,8 @@ st_create_context_priv( struct gl_context *ctx, struct pipe_context *pipe, st->has_user_constbuf = screen->get_param(screen, PIPE_CAP_USER_CONSTANT_BUFFERS); + st->can_bind_const_buffer_as_vertex = + screen->get_param(screen, PIPE_CAP_CAN_BIND_CONST_BUFFER_AS_VERTEX); /* Drivers still have to upload zero-stride vertex attribs manually * with the GL core profile, but they don't have to deal with any complex diff --git a/src/mesa/state_tracker/st_context.h b/src/mesa/state_tracker/st_context.h index eb1a1630fd5..68fd9b9d3d2 100644 --- a/src/mesa/state_tracker/st_context.h +++ b/src/mesa/state_tracker/st_context.h @@ -104,6 +104,7 @@ struct st_context boolean has_half_float_packing; boolean has_multi_draw_indirect; boolean has_user_constbuf; + boolean can_bind_const_buffer_as_vertex; /** * If a shader can be created when we get its source. -- cgit v1.2.3