[Mesa-dev] [PATCH 3/3] gallium/u_vbuf: use signed vertex buffers offsets for optimal uploads
Roland Scheidegger
sroland at vmware.com
Thu Oct 26 23:44:54 UTC 2017
Am 26.10.2017 um 17:31 schrieb Marek Olšák:
> From: Marek Olšák <marek.olsak at amd.com>
>
> Uploaded data must start at (stride * start), because we can't modify
> start in all cases.
I'm probably missing something here, but why not actually?
Roland
If it's the first allocation, it's also the amount
> of memory wasted. If the starting offset is larger than the size of
> the upload buffer, the buffer is re-created, used for 1 upload, and then
> thrown away. If the upload is small, most of the buffer space is unused
> and wasted. Keep doing that and the OOM killer comes. It's actually
> pretty quick.
>
> With signed VB offsets, we can set min_out_offset = 0
> in u_upload_alloc/u_upload_data.
>
> This fixes OOM situations with SPECviewperf.
> ---
> src/gallium/auxiliary/util/u_vbuf.c | 12 ++++++++++--
> 1 file changed, 10 insertions(+), 2 deletions(-)
>
> diff --git a/src/gallium/auxiliary/util/u_vbuf.c b/src/gallium/auxiliary/util/u_vbuf.c
> index 80c30ac..d30a702 100644
> --- a/src/gallium/auxiliary/util/u_vbuf.c
> +++ b/src/gallium/auxiliary/util/u_vbuf.c
> @@ -135,20 +135,21 @@ struct u_vbuf_elements {
>
> enum {
> VB_VERTEX = 0,
> VB_INSTANCE = 1,
> VB_CONST = 2,
> VB_NUM = 3
> };
>
> struct u_vbuf {
> struct u_vbuf_caps caps;
> + bool has_signed_vb_offset;
>
> struct pipe_context *pipe;
> struct translate_cache *translate_cache;
> struct cso_cache *cso_cache;
>
> /* This is what was set in set_vertex_buffers.
> * May contain user buffers. */
> struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS];
> uint32_t enabled_vb_mask;
>
> @@ -304,20 +305,24 @@ u_vbuf_create(struct pipe_context *pipe,
> {
> struct u_vbuf *mgr = CALLOC_STRUCT(u_vbuf);
>
> mgr->caps = *caps;
> mgr->aux_vertex_buffer_slot = aux_vertex_buffer_index;
> mgr->pipe = pipe;
> mgr->cso_cache = cso_cache_create();
> mgr->translate_cache = translate_cache_create();
> memset(mgr->fallback_vbs, ~0, sizeof(mgr->fallback_vbs));
>
> + mgr->has_signed_vb_offset =
> + pipe->screen->get_param(pipe->screen,
> + PIPE_CAP_SIGNED_VERTEX_BUFFER_OFFSET);
> +
> return mgr;
> }
>
> /* u_vbuf uses its own caching for vertex elements, because it needs to keep
> * its own preprocessed state per vertex element CSO. */
> static struct u_vbuf_elements *
> u_vbuf_set_vertex_elements_internal(struct u_vbuf *mgr, unsigned count,
> const struct pipe_vertex_element *states)
> {
> struct pipe_context *pipe = mgr->pipe;
> @@ -479,21 +484,22 @@ u_vbuf_translate_buffers(struct u_vbuf *mgr, struct translate_key *key,
> tr->run_elts8(tr, map, info->count, 0, 0, out_map);
> break;
> }
>
> if (transfer) {
> pipe_buffer_unmap(mgr->pipe, transfer);
> }
> } else {
> /* Create and map the output buffer. */
> u_upload_alloc(mgr->pipe->stream_uploader,
> - key->output_stride * start_vertex,
> + mgr->has_signed_vb_offset ?
> + 0 : key->output_stride * start_vertex,
> key->output_stride * num_vertices, 4,
> &out_offset, &out_buffer,
> (void**)&out_map);
> if (!out_buffer)
> return PIPE_ERROR_OUT_OF_MEMORY;
>
> out_offset -= key->output_stride * start_vertex;
>
> tr->run(tr, 0, num_vertices, 0, 0, out_map);
> }
> @@ -963,21 +969,23 @@ u_vbuf_upload_buffers(struct u_vbuf *mgr,
>
> i = u_bit_scan(&buffer_mask);
>
> start = start_offset[i];
> end = end_offset[i];
> assert(start < end);
>
> real_vb = &mgr->real_vertex_buffer[i];
> ptr = mgr->vertex_buffer[i].buffer.user;
>
> - u_upload_data(mgr->pipe->stream_uploader, start, end - start, 4,
> + u_upload_data(mgr->pipe->stream_uploader,
> + mgr->has_signed_vb_offset ? 0 : start,
> + end - start, 4,
> ptr + start, &real_vb->buffer_offset, &real_vb->buffer.resource);
> if (!real_vb->buffer.resource)
> return PIPE_ERROR_OUT_OF_MEMORY;
>
> real_vb->buffer_offset -= start;
> }
>
> return PIPE_OK;
> }
>
>
More information about the mesa-dev
mailing list