[Mesa-dev] [PATCH 04/12] vbo: Implement vbo_loopback_vertex_list in terms of the VAO.

Brian Paul brianp at vmware.com
Tue Feb 27 23:55:33 UTC 2018


Minor nit-picks below.

On 02/26/2018 11:12 PM, Mathias.Froehlich at gmx.net wrote:
> From: Mathias Fröhlich <mathias.froehlich at web.de>
> 
> Use the information already present in the VAO to replay a display list
> node using immediate mode draw commands. Use a hand full of helper methods
> that will be useful for the next patches also.
> 
> Signed-off-by: Mathias Fröhlich <Mathias.Froehlich at web.de>
> ---
>   src/mesa/vbo/vbo_save.h          |  53 ++++++++++++++---
>   src/mesa/vbo/vbo_save_api.c      |  42 ++++++--------
>   src/mesa/vbo/vbo_save_draw.c     |  28 +++------
>   src/mesa/vbo/vbo_save_loopback.c | 119 +++++++++++++++++++++++++--------------
>   4 files changed, 149 insertions(+), 93 deletions(-)
> 
> diff --git a/src/mesa/vbo/vbo_save.h b/src/mesa/vbo/vbo_save.h
> index 14ac831ffd..0672557c0e 100644
> --- a/src/mesa/vbo/vbo_save.h
> +++ b/src/mesa/vbo/vbo_save.h
> @@ -100,6 +100,50 @@ aligned_vertex_buffer_offset(const struct vbo_save_vertex_list *node)
>   }
>   
>   
> +/**
> + * Return the stride in bytes of the display list node.
> + */
> +static inline GLsizei
> +_vbo_save_get_stride(const struct vbo_save_vertex_list *node)
> +{
> +   return node->VAO[0]->BufferBinding[0].Stride;
> +}
> +
> +
> +/**
> + * Return the first referenced vertex index in the display list node.
> + */
> +static inline GLuint
> +_vbo_save_get_min_index(const struct vbo_save_vertex_list *node)
> +{
> +   const struct _mesa_prim *first_prim = &node->prims[0];
> +   return first_prim->start;

Maybe just  return node->prims[0].start;


> +}
> +
> +
> +/**
> + * Return the last referenced vertex index in the display list node.
> + */
> +static inline GLuint
> +_vbo_save_get_max_index(const struct vbo_save_vertex_list *node)
> +{

assert (node->prim_count > 0);

> +   const struct _mesa_prim *last_prim = &node->prims[node->prim_count - 1];
> +   return last_prim->start + last_prim->count - 1;
> +}
> +
> +
> +/**
> + * Return the vertex count in the display list node.
> + */
> +static inline GLuint
> +_vbo_save_get_vertex_count(const struct vbo_save_vertex_list *node)
> +{
> +   const struct _mesa_prim *first_prim = &node->prims[0];

assert (node->prim_count > 0);

> +   const struct _mesa_prim *last_prim = &node->prims[node->prim_count - 1];
> +   return last_prim->start - first_prim->start + last_prim->count;
> +}
> +
> +
>   /* These buffers should be a reasonable size to support upload to
>    * hardware.  Current vbo implementation will re-upload on any
>    * changes, so don't make too big or apps which dynamically create
> @@ -178,13 +222,8 @@ void vbo_save_fallback(struct gl_context *ctx, GLboolean fallback);
>   
>   /* save_loopback.c:
>    */
> -void vbo_loopback_vertex_list(struct gl_context *ctx,
> -                              const GLfloat *buffer,
> -                              const GLubyte *attrsz,
> -                              const struct _mesa_prim *prim,
> -                              GLuint prim_count,
> -                              GLuint wrap_count,
> -                              GLuint vertex_size);
> +void _vbo_loopback_vertex_list(struct gl_context *ctx,
> +                               const struct vbo_save_vertex_list* node);
>   
>   /* Callbacks:
>    */
> diff --git a/src/mesa/vbo/vbo_save_api.c b/src/mesa/vbo/vbo_save_api.c
> index b6fc7daa35..dc248934f7 100644
> --- a/src/mesa/vbo/vbo_save_api.c
> +++ b/src/mesa/vbo/vbo_save_api.c
> @@ -641,6 +641,22 @@ compile_vertex_list(struct gl_context *ctx)
>   
>      merge_prims(node->prims, &node->prim_count);
>   
> +   /* Correct the primitive starts, we can only do this here as copy_vertices
> +    * and convert_line_loop_to_strip above consume the uncorrected starts.
> +    * On the other hand the _vbo_loopback_vertex_list call below needs the
> +    * primitves to be corrected already.
> +    */
> +   if (aligned_vertex_buffer_offset(node)) {
> +      const unsigned start_offset =
> +         node->buffer_offset / (node->vertex_size * sizeof(GLfloat));
> +      for (unsigned i = 0; i < node->prim_count; i++) {
> +         node->prims[i].start += start_offset;
> +      }
> +      node->start_vertex = start_offset;
> +   } else {
> +      node->start_vertex = 0;
> +   }
> +
>      /* Deal with GL_COMPILE_AND_EXECUTE:
>       */
>      if (ctx->ExecuteFlag) {
> @@ -648,13 +664,8 @@ compile_vertex_list(struct gl_context *ctx)
>   
>         _glapi_set_dispatch(ctx->Exec);
>   
> -      const GLfloat *buffer = (const GLfloat *)
> -         ((const char *) save->vertex_store->buffer_map +
> -          node->buffer_offset);
> -
> -      vbo_loopback_vertex_list(ctx, buffer,
> -                               node->attrsz, node->prims, node->prim_count,
> -                               node->wrap_count, node->vertex_size);
> +      /* Note that the range of referenced vertices must be mapped already */
> +      _vbo_loopback_vertex_list(ctx, node);
>   
>         _glapi_set_dispatch(dispatch);
>      }
> @@ -693,23 +704,6 @@ compile_vertex_list(struct gl_context *ctx)
>         save->prim_store = alloc_prim_store();
>      }
>   
> -   /*
> -    * If the vertex buffer offset is a multiple of the vertex size,
> -    * we can use the _mesa_prim::start value to indicate where the
> -    * vertices starts, instead of the buffer offset.  Also see the
> -    * bind_vertex_list() function.
> -    */
> -   if (aligned_vertex_buffer_offset(node)) {
> -      const unsigned start_offset =
> -         node->buffer_offset / (node->vertex_size * sizeof(GLfloat));
> -      for (unsigned i = 0; i < save->prim_count; i++) {
> -         save->prims[i].start += start_offset;
> -      }
> -      node->start_vertex = start_offset;
> -   } else {
> -      node->start_vertex = 0;
> -   }
> -
>      /* Reset our structures for the next run of vertices:
>       */
>      reset_counters(ctx);
> diff --git a/src/mesa/vbo/vbo_save_draw.c b/src/mesa/vbo/vbo_save_draw.c
> index 7cb6799668..0358ecd2f9 100644
> --- a/src/mesa/vbo/vbo_save_draw.c
> +++ b/src/mesa/vbo/vbo_save_draw.c
> @@ -144,26 +144,14 @@ static void
>   loopback_vertex_list(struct gl_context *ctx,
>                        const struct vbo_save_vertex_list *list)
>   {
> -   const char *buffer =
> -      ctx->Driver.MapBufferRange(ctx, 0,
> -                                 list->vertex_store->bufferobj->Size,
> -                                 GL_MAP_READ_BIT, /* ? */
> -                                 list->vertex_store->bufferobj,
> -                                 MAP_INTERNAL);
> -
> -   unsigned buffer_offset =
> -      aligned_vertex_buffer_offset(list) ? 0 : list->buffer_offset;
> -
> -   vbo_loopback_vertex_list(ctx,
> -                            (const GLfloat *) (buffer + buffer_offset),
> -                            list->attrsz,
> -                            list->prims,
> -                            list->prim_count,
> -                            list->wrap_count,
> -                            list->vertex_size);
> -
> -   ctx->Driver.UnmapBuffer(ctx, list->vertex_store->bufferobj,
> -                           MAP_INTERNAL);
> +   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);
> +
> +   /* Note that the range of referenced vertices must be mapped already */
> +   _vbo_loopback_vertex_list(ctx, list);
> +
> +   ctx->Driver.UnmapBuffer(ctx, bo, MAP_INTERNAL);
>   }
>   
>   
> diff --git a/src/mesa/vbo/vbo_save_loopback.c b/src/mesa/vbo/vbo_save_loopback.c
> index 43d458a7c0..55a6fb8180 100644
> --- a/src/mesa/vbo/vbo_save_loopback.c
> +++ b/src/mesa/vbo/vbo_save_loopback.c
> @@ -81,8 +81,8 @@ static attr_func vert_attrfunc[4] = {
>   
>   
>   struct loopback_attr {
> -   GLint index;
> -   GLint sz;
> +   enum vbo_attrib index;
> +   GLuint offset;
>      attr_func func;
>   };
>   
> @@ -94,17 +94,15 @@ struct loopback_attr {
>    */
>   static void
>   loopback_prim(struct gl_context *ctx,
> -              const GLfloat *buffer,
> +              const GLubyte *buffer,
>                 const struct _mesa_prim *prim,
>                 GLuint wrap_count,
> -              GLuint vertex_size,
> +              GLuint stride,
>                 const struct loopback_attr *la, GLuint nr)
>   {
> -   GLint start = prim->start;
> -   GLint end = start + prim->count;
> -   const GLfloat *data;
> -   GLint j;
> -   GLuint k;
> +   GLuint start = prim->start;
> +   GLuint end = start + prim->count;

const on those two?

-Brian


> +   const GLubyte *data;
>   
>      if (0)
>         printf("loopback prim %s(%s,%s) verts %d..%d  vsize %d\n",
> @@ -112,7 +110,7 @@ loopback_prim(struct gl_context *ctx,
>                prim->begin ? "begin" : "..",
>                prim->end ? "end" : "..",
>                start, end,
> -             vertex_size);
> +             stride);
>   
>      if (prim->begin) {
>         CALL_Begin(GET_DISPATCH(), (prim->mode));
> @@ -121,20 +119,13 @@ loopback_prim(struct gl_context *ctx,
>         start += wrap_count;
>      }
>   
> -   data = buffer + start * vertex_size;
> +   data = buffer + start * stride;
>   
> -   for (j = start; j < end; j++) {
> -      const GLfloat *tmp = data + la[0].sz;
> +   for (GLuint j = start; j < end; j++) {
> +      for (GLuint k = 0; k < nr; k++)
> +         la[k].func(ctx, la[k].index, (const GLfloat *)(data + la[k].offset));
>   
> -      for (k = 1; k < nr; k++) {
> -         la[k].func(ctx, la[k].index, tmp);
> -         tmp += la[k].sz;
> -      }
> -
> -      /* Fire the vertex
> -       */
> -      la[0].func(ctx, VBO_ATTRIB_POS, data);
> -      data = tmp;
> +      data += stride;
>      }
>   
>      if (prim->end) {
> @@ -167,36 +158,80 @@ loopback_weak_prim(struct gl_context *ctx,
>   }
>   
>   
> +static inline void
> +append_attr(GLuint *nr, struct loopback_attr la[], int i, int shift,
> +            const struct gl_vertex_array_object *vao)
> +{
> +   la[*nr].index = shift + i;
> +   la[*nr].offset = vao->VertexAttrib[i].RelativeOffset;
> +   la[*nr].func = vert_attrfunc[vao->VertexAttrib[i].Size - 1];
> +   (*nr)++;
> +}
> +
> +
>   void
> -vbo_loopback_vertex_list(struct gl_context *ctx,
> -                         const GLfloat *buffer,
> -                         const GLubyte *attrsz,
> -                         const struct _mesa_prim *prim,
> -                         GLuint prim_count,
> -                         GLuint wrap_count,
> -                         GLuint vertex_size)
> +_vbo_loopback_vertex_list(struct gl_context *ctx,
> +                          const struct vbo_save_vertex_list* node)
>   {
>      struct loopback_attr la[VBO_ATTRIB_MAX];
> -   GLuint i, nr = 0;
> +   GLuint nr = 0;
>   
>      /* All Legacy, NV, ARB and Material attributes are routed through
>       * the NV attributes entrypoints:
>       */
> -   for (i = 0; i < VBO_ATTRIB_MAX; i++) {
> -      if (attrsz[i]) {
> -         la[nr].index = i;
> -         la[nr].sz = attrsz[i];
> -         la[nr].func = vert_attrfunc[attrsz[i]-1];
> -         nr++;
> -      }
> +   const struct gl_vertex_array_object *vao = node->VAO[VP_MODE_FF];
> +   GLbitfield mask = vao->_Enabled & VERT_BIT_MAT_ALL;
> +   while (mask) {
> +      const int i = u_bit_scan(&mask);
> +      append_attr(&nr, la, i, VBO_MATERIAL_SHIFT, vao);
> +   }
> +
> +   vao = node->VAO[VP_MODE_SHADER];
> +   mask = vao->_Enabled & ~(VERT_BIT_POS | VERT_BIT_GENERIC0);
> +   while (mask) {
> +      const int i = u_bit_scan(&mask);
> +      append_attr(&nr, la, i, 0, vao);
> +   }
> +
> +   /* The last in the list should be the vertex provoking attribute */
> +   if (vao->_Enabled & VERT_BIT_GENERIC0) {
> +      append_attr(&nr, la, VERT_ATTRIB_GENERIC0, 0, vao);
> +   } else if (vao->_Enabled & VERT_BIT_POS) {
> +      append_attr(&nr, la, VERT_ATTRIB_POS, 0, vao);
> +   }
> +
> +   const GLuint wrap_count = node->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);
>      }
>   
> -   for (i = 0; i < prim_count; i++) {
> -      if ((prim[i].mode & VBO_SAVE_PRIM_WEAK) &&
> -          _mesa_inside_begin_end(ctx)) {
> -         loopback_weak_prim(ctx, &prim[i]);
> +   /* Replay the primitives */
> +   const struct _mesa_prim *prims = node->prims;
> +   const GLuint prim_count = node->prim_count;
> +   for (GLuint i = 0; i < prim_count; i++) {
> +      if ((prims[i].mode & VBO_SAVE_PRIM_WEAK) && _mesa_inside_begin_end(ctx)) {
> +         loopback_weak_prim(ctx, &prims[i]);
>         } else {
> -         loopback_prim(ctx, buffer, &prim[i], wrap_count, vertex_size, la, nr);
> +         loopback_prim(ctx, buffer, &prims[i], wrap_count, stride, la, nr);
>         }
>      }
>   }
> 



More information about the mesa-dev mailing list