Mesa (main): dlist: upload vertices in compile_vertex_list

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Mon Aug 2 09:54:32 UTC 2021


Module: Mesa
Branch: main
Commit: e012b34e610f2ef64ebf97227e6c16339ef14136
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=e012b34e610f2ef64ebf97227e6c16339ef14136

Author: Pierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer at amd.com>
Date:   Fri Jul 16 13:59:17 2021 +0200

dlist: upload vertices in compile_vertex_list

Previously vertices were uploaded on-the-fly: each time
the position attribute was set, the newly added vertex
was copied to the mapped bo.

Replace this with a plain RAM buffer, and do the upload
at the end of compile_vertex_list.

This allows to remove the we-need-to-unmap-the-buffer-
before-drawing special case, but more importantly it
will allow to implement vertices deduplication in the
next commit.

Reviewed-by: Marek Olšák <marek.olsak at amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/11927>

---

 src/mesa/vbo/vbo_save.c          |  1 +
 src/mesa/vbo/vbo_save.h          | 14 ++----
 src/mesa/vbo/vbo_save_api.c      | 93 ++++++++--------------------------------
 src/mesa/vbo/vbo_save_draw.c     | 31 +++-----------
 src/mesa/vbo/vbo_save_loopback.c | 28 +++---------
 5 files changed, 34 insertions(+), 133 deletions(-)

diff --git a/src/mesa/vbo/vbo_save.c b/src/mesa/vbo/vbo_save.c
index b1419d2e590..a29b246c18b 100644
--- a/src/mesa/vbo/vbo_save.c
+++ b/src/mesa/vbo/vbo_save.c
@@ -68,6 +68,7 @@ void vbo_save_destroy( struct gl_context *ctx )
    }
    if (save->vertex_store) {
       _mesa_reference_buffer_object(ctx, &save->vertex_store->bufferobj, NULL);
+      free(save->vertex_store->buffer_in_ram);
       free(save->vertex_store);
       save->vertex_store = NULL;
    }
diff --git a/src/mesa/vbo/vbo_save.h b/src/mesa/vbo/vbo_save.h
index ec50d580649..89b2f496c51 100644
--- a/src/mesa/vbo/vbo_save.h
+++ b/src/mesa/vbo/vbo_save.h
@@ -150,7 +150,8 @@ _vbo_save_get_vertex_count(const struct vbo_save_vertex_list *node)
 
 struct vbo_save_vertex_store {
    struct gl_buffer_object *bufferobj;
-   fi_type *buffer_map;
+   fi_type *buffer_in_ram;
+   GLuint buffer_in_ram_size;
    GLuint used;           /**< Number of 4-byte words used in buffer */
 };
 
@@ -170,7 +171,8 @@ void vbo_save_destroy(struct gl_context *ctx);
 /* save_loopback.c:
  */
 void _vbo_loopback_vertex_list(struct gl_context *ctx,
-                               const struct vbo_save_vertex_list* node);
+                               const struct vbo_save_vertex_list* node,
+                               fi_type *buffer);
 
 /* Callbacks:
  */
@@ -183,12 +185,4 @@ vbo_save_playback_vertex_list_loopback(struct gl_context *ctx, void *data);
 void
 vbo_save_api_init(struct vbo_save_context *save);
 
-fi_type *
-vbo_save_map_vertex_store(struct gl_context *ctx,
-                          struct vbo_save_vertex_store *vertex_store);
-
-void
-vbo_save_unmap_vertex_store(struct gl_context *ctx,
-                            struct vbo_save_vertex_store *vertex_store);
-
 #endif /* VBO_SAVE_H */
diff --git a/src/mesa/vbo/vbo_save_api.c b/src/mesa/vbo/vbo_save_api.c
index 2ff6b5061d5..7a56b5ee73b 100644
--- a/src/mesa/vbo/vbo_save_api.c
+++ b/src/mesa/vbo/vbo_save_api.c
@@ -146,13 +146,15 @@ alloc_vertex_store(struct gl_context *ctx, int vertex_count)
     */
    vertex_store->bufferobj = ctx->Driver.NewBufferObject(ctx, VBO_BUF_ID);
    if (vertex_store->bufferobj) {
+      vertex_store->buffer_in_ram_size = size * sizeof(GLfloat);
+      vertex_store->buffer_in_ram = malloc(vertex_store->buffer_in_ram_size);
+      save->out_of_memory = vertex_store->buffer_in_ram == NULL;
       save->out_of_memory =
          !ctx->Driver.BufferData(ctx,
                                  GL_ARRAY_BUFFER_ARB,
                                  size * sizeof(GLfloat),
                                  NULL, GL_STATIC_DRAW_ARB,
-                                 GL_MAP_WRITE_BIT |
-                                 GL_DYNAMIC_STORAGE_BIT,
+                                 GL_MAP_WRITE_BIT,
                                  vertex_store->bufferobj);
    }
    else {
@@ -164,7 +166,6 @@ alloc_vertex_store(struct gl_context *ctx, int vertex_count)
       _mesa_install_save_vtxfmt(ctx, &save->vtxfmt_noop);
    }
 
-   vertex_store->buffer_map = NULL;
    vertex_store->used = 0;
 
    return vertex_store;
@@ -175,7 +176,7 @@ static void
 free_vertex_store(struct gl_context *ctx,
                   struct vbo_save_vertex_store *vertex_store)
 {
-   assert(!vertex_store->buffer_map);
+   free(vertex_store->buffer_in_ram);
 
    if (vertex_store->bufferobj) {
       _mesa_reference_buffer_object(ctx, &vertex_store->bufferobj, NULL);
@@ -185,65 +186,6 @@ free_vertex_store(struct gl_context *ctx,
 }
 
 
-fi_type *
-vbo_save_map_vertex_store(struct gl_context *ctx,
-                          struct vbo_save_vertex_store *vertex_store)
-{
-   const GLbitfield access = (GL_MAP_WRITE_BIT |
-                              GL_MAP_INVALIDATE_RANGE_BIT |
-                              GL_MAP_UNSYNCHRONIZED_BIT |
-                              GL_MAP_FLUSH_EXPLICIT_BIT |
-                              MESA_MAP_ONCE);
-
-   assert(vertex_store->bufferobj);
-   assert(!vertex_store->buffer_map);  /* the buffer should not be mapped */
-
-   if (vertex_store->bufferobj->Size > 0) {
-      /* Map the remaining free space in the VBO */
-      GLintptr offset = vertex_store->used * sizeof(GLfloat);
-      GLsizeiptr size = vertex_store->bufferobj->Size - offset;
-      fi_type *range = (fi_type *)
-         ctx->Driver.MapBufferRange(ctx, offset, size, access,
-                                    vertex_store->bufferobj,
-                                    MAP_INTERNAL);
-      if (range) {
-         /* compute address of start of whole buffer (needed elsewhere) */
-         vertex_store->buffer_map = range - vertex_store->used;
-         assert(vertex_store->buffer_map);
-         return range;
-      }
-      else {
-         vertex_store->buffer_map = NULL;
-         return NULL;
-      }
-   }
-   else {
-      /* probably ran out of memory for buffers */
-      return NULL;
-   }
-}
-
-
-void
-vbo_save_unmap_vertex_store(struct gl_context *ctx,
-                            struct vbo_save_vertex_store *vertex_store)
-{
-   if (vertex_store->bufferobj->Size > 0) {
-      GLintptr offset = 0;
-      GLsizeiptr length = vertex_store->used * sizeof(GLfloat)
-         - vertex_store->bufferobj->Mappings[MAP_INTERNAL].Offset;
-
-      /* Explicitly flush the region we wrote to */
-      ctx->Driver.FlushMappedBufferRange(ctx, offset, length,
-                                         vertex_store->bufferobj,
-                                         MAP_INTERNAL);
-
-      ctx->Driver.UnmapBuffer(ctx, vertex_store->bufferobj, MAP_INTERNAL);
-   }
-   vertex_store->buffer_map = NULL;
-}
-
-
 static struct vbo_save_primitive_store *
 alloc_prim_store(int prim_count)
 {
@@ -263,7 +205,7 @@ reset_counters(struct gl_context *ctx)
    struct vbo_save_context *save = &vbo_context(ctx)->save;
 
    save->prims = save->prim_store->prims + save->prim_store->used;
-   save->buffer_map = save->vertex_store->buffer_map + save->vertex_store->used;
+   save->buffer_map = save->vertex_store->buffer_in_ram + save->vertex_store->used;
 
    assert(save->buffer_map == save->buffer_ptr);
 
@@ -482,10 +424,6 @@ realloc_storage(struct gl_context *ctx, int prim_count, int vertex_count)
 {
    struct vbo_save_context *save = &vbo_context(ctx)->save;
    if (vertex_count >= 0) {
-      /* Unmap old store:
-       */
-      vbo_save_unmap_vertex_store(ctx, save->vertex_store);
-
       /* Release old reference:
        */
       free_vertex_store(ctx, save->vertex_store);
@@ -497,7 +435,7 @@ realloc_storage(struct gl_context *ctx, int prim_count, int vertex_count)
       /* Allocate and map new store:
        */
       save->vertex_store = alloc_vertex_store(ctx, vertex_count);
-      save->buffer_ptr = vbo_save_map_vertex_store(ctx, save->vertex_store);
+      save->buffer_ptr = save->vertex_store->buffer_in_ram + save->vertex_store->used;
       save->out_of_memory = save->buffer_ptr == NULL;
    }
 
@@ -545,7 +483,8 @@ compile_vertex_list(struct gl_context *ctx)
    }
    const GLsizei stride = save->vertex_size*sizeof(GLfloat);
    GLintptr buffer_offset =
-       (save->buffer_map - save->vertex_store->buffer_map) * sizeof(GLfloat);
+       (save->buffer_map - save->vertex_store->buffer_in_ram) * sizeof(GLfloat);
+   const GLintptr original_buffer_offset = buffer_offset;
    assert(old_offset <= buffer_offset);
    const GLintptr offset_diff = buffer_offset - old_offset;
    GLuint start_offset = 0;
@@ -798,6 +737,12 @@ compile_vertex_list(struct gl_context *ctx)
       node->cold->prim_count = 0;
    }
 
+   ctx->Driver.BufferSubData(ctx,
+                             original_buffer_offset,
+                             idx * save->vertex_size * sizeof(fi_type),
+                             &save->vertex_store->buffer_in_ram[original_buffer_offset / sizeof(float)],
+                             save->vertex_store->bufferobj);
+
    /* Prepare for DrawGallium */
    memset(&node->merged.info, 0, sizeof(struct pipe_draw_info));
    /* The other info fields will be updated in vbo_save_playback_vertex_list */
@@ -846,7 +791,7 @@ end:
       _glapi_set_dispatch(ctx->Exec);
 
       /* Note that the range of referenced vertices must be mapped already */
-      _vbo_loopback_vertex_list(ctx, node);
+      _vbo_loopback_vertex_list(ctx, node, save->vertex_store->buffer_in_ram);
 
       _glapi_set_dispatch(dispatch);
    }
@@ -860,7 +805,7 @@ end:
    }
    else {
       /* update buffer_ptr for next vertex */
-      save->buffer_ptr = save->vertex_store->buffer_map
+      save->buffer_ptr = save->vertex_store->buffer_in_ram
          + save->vertex_store->used;
    }
 
@@ -1882,7 +1827,7 @@ vbo_save_NewList(struct gl_context *ctx, GLuint list, GLenum mode)
    if (!save->vertex_store)
       save->vertex_store = alloc_vertex_store(ctx, 0);
 
-   save->buffer_ptr = vbo_save_map_vertex_store(ctx, save->vertex_store);
+   save->buffer_ptr = save->vertex_store->buffer_in_ram + save->vertex_store->used;
 
    reset_vertex(ctx);
    reset_counters(ctx);
@@ -1921,8 +1866,6 @@ vbo_save_EndList(struct gl_context *ctx)
       _mesa_install_save_vtxfmt(ctx, &ctx->ListState.ListVtxfmt);
    }
 
-   vbo_save_unmap_vertex_store(ctx, save->vertex_store);
-
    assert(save->vertex_size == 0);
 }
 
diff --git a/src/mesa/vbo/vbo_save_draw.c b/src/mesa/vbo/vbo_save_draw.c
index eae03daf48f..7170a3b7be6 100644
--- a/src/mesa/vbo/vbo_save_draw.c
+++ b/src/mesa/vbo/vbo_save_draw.c
@@ -147,11 +147,12 @@ loopback_vertex_list(struct gl_context *ctx,
                      const struct vbo_save_vertex_list *list)
 {
    struct gl_buffer_object *bo = list->VAO[0]->BufferBinding[0].BufferObj;
-   ctx->Driver.MapBufferRange(ctx, 0, bo->Size, GL_MAP_READ_BIT, /* ? */
-                              bo, MAP_INTERNAL);
+   void *buffer = ctx->Driver.MapBufferRange(ctx, 0, bo->Size, GL_MAP_READ_BIT, /* ? */
+                                             bo, MAP_INTERNAL);
 
-   /* Note that the range of referenced vertices must be mapped already */
-   _vbo_loopback_vertex_list(ctx, list);
+   /* TODO: in this case, we shouldn't create a bo at all and instead keep
+    * the in-RAM buffer. */
+   _vbo_loopback_vertex_list(ctx, list, buffer);
 
    ctx->Driver.UnmapBuffer(ctx, bo, MAP_INTERNAL);
 }
@@ -162,21 +163,6 @@ vbo_save_playback_vertex_list_loopback(struct gl_context *ctx, void *data)
 {
    const struct vbo_save_vertex_list *node =
       (const struct vbo_save_vertex_list *) data;
-   struct vbo_context *vbo = vbo_context(ctx);
-   struct vbo_save_context *save = &vbo->save;
-   GLboolean remap_vertex_store = GL_FALSE;
-
-   if (save->vertex_store && save->vertex_store->buffer_map) {
-      /* The vertex store is currently mapped but we're about to replay
-       * a display list.  This can happen when a nested display list is
-       * being build with GL_COMPILE_AND_EXECUTE.
-       * We never want to have mapped vertex buffers when we're drawing.
-       * Unmap the vertex store, execute the list, then remap the vertex
-       * store.
-       */
-      vbo_save_unmap_vertex_store(ctx, save->vertex_store);
-      remap_vertex_store = GL_TRUE;
-   }
 
    FLUSH_FOR_DRAW(ctx);
 
@@ -186,17 +172,12 @@ vbo_save_playback_vertex_list_loopback(struct gl_context *ctx, void *data)
        */
       _mesa_error(ctx, GL_INVALID_OPERATION,
                   "draw operation inside glBegin/End");
-      goto end;
+      return;
    }
    /* Various degenerate cases: translate into immediate mode
     * calls rather than trying to execute in place.
     */
    loopback_vertex_list(ctx, node);
-
-end:
-   if (remap_vertex_store) {
-      save->buffer_ptr = vbo_save_map_vertex_store(ctx, save->vertex_store);
-   }
 }
 
 /**
diff --git a/src/mesa/vbo/vbo_save_loopback.c b/src/mesa/vbo/vbo_save_loopback.c
index 014c5015f40..2bad1bd17a0 100644
--- a/src/mesa/vbo/vbo_save_loopback.c
+++ b/src/mesa/vbo/vbo_save_loopback.c
@@ -146,7 +146,8 @@ append_attr(GLuint *nr, struct loopback_attr la[], int i, int shift,
 
 void
 _vbo_loopback_vertex_list(struct gl_context *ctx,
-                          const struct vbo_save_vertex_list* node)
+                          const struct vbo_save_vertex_list* node,
+                          fi_type *buffer)
 {
    struct loopback_attr la[VBO_ATTRIB_MAX];
    GLuint nr = 0;
@@ -177,32 +178,13 @@ _vbo_loopback_vertex_list(struct gl_context *ctx,
 
    const GLuint wrap_count = node->cold->wrap_count;
    const GLuint stride = _vbo_save_get_stride(node);
-   const GLubyte *buffer = NULL;
-   if (0 < nr) {
-      /* Compute the minimal offset into the vertex buffer object */
-      GLuint offset = ~0u;
-      for (GLuint i = 0; i < nr; ++i)
-         offset = MIN2(offset, la[i].offset);
-      for (GLuint i = 0; i < nr; ++i)
-         la[i].offset -= offset;
-
-      /* Get the mapped base pointer, assert sufficient mapping */
-      struct gl_buffer_object *bufferobj = vao->BufferBinding[0].BufferObj;
-      assert(bufferobj && bufferobj->Mappings[MAP_INTERNAL].Pointer);
-      buffer = bufferobj->Mappings[MAP_INTERNAL].Pointer;
-      assert(bufferobj->Mappings[MAP_INTERNAL].Offset
-             <= vao->BufferBinding[0].Offset + offset
-             + stride*(_vbo_save_get_min_index(node) + wrap_count));
-      buffer += vao->BufferBinding[0].Offset + offset
-         - bufferobj->Mappings[MAP_INTERNAL].Offset;
-      assert(stride*(_vbo_save_get_vertex_count(node) - wrap_count)
-             <= bufferobj->Mappings[MAP_INTERNAL].Length);
-   }
 
    /* Replay the primitives */
    const struct _mesa_prim *prims = node->cold->prims;
    const GLuint prim_count = node->cold->prim_count;
+
    for (GLuint i = 0; i < prim_count; i++) {
-      loopback_prim(ctx, buffer, &prims[i], wrap_count, stride, la, nr);
+      loopback_prim(ctx, (GLubyte*)buffer + vao->BufferBinding[0].Offset,
+                    &prims[i], wrap_count, stride, la, nr);
    }
 }



More information about the mesa-commit mailing list