[Mesa-dev] [PATCH 3/3] gallium/u_vbuf: use signed vertex buffers offsets for optimal uploads

Marek Olšák maraeo at gmail.com
Thu Oct 26 15:31:02 UTC 2017


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. 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;
 }
 
-- 
2.7.4



More information about the mesa-dev mailing list