[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