From: Marek Olšák <marek.ol...@amd.com> This is the best place to do it. Now drivers without u_vbuf don't have to do it. --- src/mesa/state_tracker/st_atom_array.c | 56 ++++++++++++++++++++++++---------- src/mesa/state_tracker/st_context.c | 2 ++ src/mesa/state_tracker/st_context.h | 1 + 3 files changed, 43 insertions(+), 16 deletions(-)
diff --git a/src/mesa/state_tracker/st_atom_array.c b/src/mesa/state_tracker/st_atom_array.c index cc9cac1..813468b 100644 --- a/src/mesa/state_tracker/st_atom_array.c +++ b/src/mesa/state_tracker/st_atom_array.c @@ -37,20 +37,21 @@ */ #include "st_context.h" #include "st_atom.h" #include "st_cb_bufferobjects.h" #include "st_draw.h" #include "st_program.h" #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" /* vertex_formats[gltype - GL_BYTE][integer*2 + normalized][size - 1] */ static const uint16_t vertex_formats[][4][4] = { { /* GL_BYTE */ { PIPE_FORMAT_R8_SSCALED, PIPE_FORMAT_R8G8_SSCALED, PIPE_FORMAT_R8G8B8_SSCALED, @@ -327,20 +328,25 @@ is_interleaved_arrays(const struct st_vertex_program *vp, for (attr = 0; attr < num_inputs; attr++) { const struct gl_vertex_array *array; const struct gl_buffer_object *bufObj; GLsizei stride; array = get_client_array(arrays, vp->index_to_input[attr]); if (!array) 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 */ firstStride = stride; firstPtr = array->Ptr; firstBufObj = bufObj; userSpaceBuffer = !bufObj || !bufObj->Name; } else { /* check if other arrays interleave with the first, in same buffer */ @@ -564,20 +570,21 @@ setup_interleaved_attribs(struct st_context *st, static void setup_non_interleaved_attribs(struct st_context *st, const struct st_vertex_program *vp, const struct gl_vertex_array **arrays, unsigned num_inputs) { struct gl_context *ctx = st->ctx; 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;) { const unsigned mesaAttr = vp->index_to_input[attr]; const struct gl_vertex_array *array; struct gl_buffer_object *bufobj; GLsizei stride; unsigned src_format; unsigned bufidx; @@ -601,54 +608,71 @@ setup_non_interleaved_attribs(struct st_context *st, if (!stobj || !stobj->buffer) { st->vertex_array_out_of_memory = true; return; /* out-of-memory error probably */ } vbuffer[bufidx].buffer.resource = stobj->buffer; vbuffer[bufidx].is_user_buffer = false; 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) { + 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, 32, 32, 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 */ vbuffer[bufidx].stride = stride; /* in bytes */ src_format = st_pipe_vertex_format(array->Type, array->Size, array->Format, array->Normalized, array->Integer); init_velement_lowered(vp, velements, 0, src_format, array->InstanceDivisor, bufidx, array->Size, array->Doubles, &attr); } 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) { struct gl_context *ctx = st->ctx; const struct gl_vertex_array **arrays = ctx->Array._DrawArrays; const struct st_vertex_program *vp; unsigned num_inputs; st->vertex_array_out_of_memory = FALSE; diff --git a/src/mesa/state_tracker/st_context.c b/src/mesa/state_tracker/st_context.c index d997911..c901764 100644 --- a/src/mesa/state_tracker/st_context.c +++ b/src/mesa/state_tracker/st_context.c @@ -331,20 +331,22 @@ st_create_context_priv( struct gl_context *ctx, struct pipe_context *pipe, st->ctx = ctx; st->pipe = pipe; /* state tracker needs the VBO module */ _vbo_CreateContext(ctx); st->dirty = ST_ALL_STATES_MASK; 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 * user vertex buffer uploads. */ unsigned vbuf_flags = ctx->API == API_OPENGL_CORE ? U_VBUF_FLAG_NO_USER_VBOS : 0; st->cso_context = cso_create_context(pipe, vbuf_flags); st_init_atoms( st ); diff --git a/src/mesa/state_tracker/st_context.h b/src/mesa/state_tracker/st_context.h index eb1a163..68fd9b9 100644 --- a/src/mesa/state_tracker/st_context.h +++ b/src/mesa/state_tracker/st_context.h @@ -97,20 +97,21 @@ struct st_context boolean has_time_elapsed; boolean has_shader_model3; boolean has_etc1; boolean has_etc2; boolean prefer_blit_based_texture_transfer; boolean force_persample_in_shader; boolean has_shareable_shaders; 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. * This means it has only 1 variant, not counting glBitmap and * glDrawPixels. */ boolean shader_has_one_variant[MESA_SHADER_STAGES]; boolean needs_texcoord_semantic; boolean apply_texture_swizzle_to_border_color; -- 2.7.4 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev