Hi Brian,

That one will not work as is.

Display lists are shared objects across contexts.
Means past that change the

   const struct gl_vertex_array *inputs[VBO_ATTRIB_MAX];

may be concurrently written to from different threads filling in current value 
pointers from the context where the list is executed from. That leaves current 
values form a differnet context and concurrency issues at least.

Beside that I am also not sure if the array update logic in bind_vertex_list 
works correctly when VBO_ATTRIB* arrays ending in an aliasing VERT_ATTRIB* 
slot are both enabled. You probably need to currectly mask out the VBO_ATTRIB 
arrays before you distribute them across the inputs[] array. But the the logic 
just to store subsequent node->arrays entries to save memory fails when 
skipping the masked out arrays.

best

Mathias

On Thursday, 25 January 2018 00:20:35 CET Brian Paul wrote:
> Do more of the vertex array setup at display list compilation time
> via the compile_vertex_list() function.
> 
> Then, at draw time, just do final vertex array setup dependent on
> whether we're using fixed function or a vertex shader.
> 
> This can help apps which use a lot of short display list drawing.
> ---
>  src/mesa/vbo/vbo_save.h      |  11 ++-
>  src/mesa/vbo/vbo_save_api.c  |  93 ++++++++++++++++++++++---
>  src/mesa/vbo/vbo_save_draw.c | 157 +++++++++++++
+-----------------------------
>  3 files changed, 147 insertions(+), 114 deletions(-)
> 
> diff --git a/src/mesa/vbo/vbo_save.h b/src/mesa/vbo/vbo_save.h
> index 51ea9cc..62a9d54 100644
> --- a/src/mesa/vbo/vbo_save.h
> +++ b/src/mesa/vbo/vbo_save.h
> @@ -85,6 +85,16 @@ struct vbo_save_vertex_list {
>  
>     struct vbo_save_vertex_store *vertex_store;
>     struct vbo_save_primitive_store *prim_store;
> +
> +   /* Array [bitcount(enabled)] of gl_vertex_array objects describing
> +    * the vertex data contained in this vbo_save_vertex_list.
> +    */
> +   struct gl_vertex_array *arrays;
> +
> +   /* The arrays to actually use at draw time.  Some will point at the
> +    * 'arrays' field above.  The rest will point at the vbo->currval arrays
> +    */
> +   const struct gl_vertex_array *inputs[VBO_ATTRIB_MAX];
>  };
>  
>  
> @@ -140,7 +150,6 @@ struct vbo_save_context {
>     GLvertexformat vtxfmt;
>     GLvertexformat vtxfmt_noop;  /**< Used if out_of_memory is true */
>     struct gl_vertex_array arrays[VBO_ATTRIB_MAX];
> -   const struct gl_vertex_array *inputs[VBO_ATTRIB_MAX];
>  
>     GLbitfield64 enabled; /**< mask of enabled vbo arrays. */
>     GLubyte attrsz[VBO_ATTRIB_MAX];  /**< 1, 2, 3 or 4 */
> diff --git a/src/mesa/vbo/vbo_save_api.c b/src/mesa/vbo/vbo_save_api.c
> index 11c40a2..e394d88 100644
> --- a/src/mesa/vbo/vbo_save_api.c
> +++ b/src/mesa/vbo/vbo_save_api.c
> @@ -412,8 +412,80 @@ convert_line_loop_to_strip(struct vbo_save_context 
*save,
>  
>  
>  /**
> - * Insert the active immediate struct onto the display list currently
> - * being built.
> + * Prepare the vertex arrays which will be used for drawing the primitives
> + * in the given vertex list.  By doing it here, we can avoid doing this
> + * work at display list execution/draw time.
> + */
> +static void
> +setup_vertex_arrays(struct gl_context *ctx,
> +                    struct vbo_save_vertex_list *node)
> +{
> +   struct vbo_context *vbo = vbo_context(ctx);
> +   unsigned buffer_offset = node->buffer_offset;
> +   unsigned attr;
> +   const unsigned num_arrays = _mesa_bitcount_64(node->enabled);
> +   unsigned array_count;
> +
> +   if (aligned_vertex_buffer_offset(node)) {
> +      /* The vertex size is an exact multiple of the buffer offset.
> +       * This means that we can use zero-based vertex attribute pointers
> +       * and specify the start of the primitive with the _mesa_prim::start
> +       * field.  This results in issuing several draw calls with identical
> +       * vertex attribute information.  This can result in fewer state
> +       * changes in drivers.  In particular, the Gallium CSO module will
> +       * filter out redundant vertex buffer changes.
> +       */
> +      buffer_offset = 0;
> +   }
> +
> +   assert(!node->arrays);
> +   node->arrays = calloc(num_arrays, sizeof(struct gl_vertex_array));
> +   if (!node->arrays) {
> +      _mesa_error(ctx, GL_OUT_OF_MEMORY,
> +                  "compiling vertex data into display list");
> +      /* just turn off all arrays */
> +      node->enabled = 0;
> +      return;
> +   }
> +
> +   array_count = 0;
> +   for (attr = 0; attr < VBO_ATTRIB_MAX; attr++) {
> +      if (node->attrsz[attr]) {
> +         /* this vertex array points at actual per-vertex data in a VB */
> +         struct gl_vertex_array *array = &node->arrays[array_count];
> +
> +         array->Ptr = (const GLubyte *) NULL + buffer_offset;
> +         array->Size = node->attrsz[attr];
> +         array->StrideB = node->vertex_size * sizeof(GLfloat);
> +         array->Type = node->attrtype[attr];
> +         array->Integer = vbo_attrtype_to_integer_flag(node-
>attrtype[attr]);
> +         array->Format = GL_RGBA;
> +         array->_ElementSize = array->Size * sizeof(GLfloat);
> +         _mesa_reference_buffer_object(ctx,
> +                                       &array->BufferObj,
> +                                       node->vertex_store->bufferobj);
> +
> +         node->inputs[attr] = array;
> +
> +         buffer_offset += node->attrsz[attr] * sizeof(GLfloat);
> +
> +         array_count++;
> +      }
> +      else {
> +         /* this vertex array points at currval/default values */
> +         node->inputs[attr] = &vbo->currval[attr];
> +      }
> +   }
> +
> +   assert(array_count == num_arrays);
> +}
> +
> +
> +/**
> + * Create a new vbo_save_vertex_list object and fill it with the vertices
> + * and primitives accumulated in the vbo_save_context.
> + * The new vbo_save_vertex_list is allocated from display list memory
> + * and will automatically be inserted into the current display list.
>   */
>  static void
>  compile_vertex_list(struct gl_context *ctx)
> @@ -430,6 +502,8 @@ compile_vertex_list(struct gl_context *ctx)
>     if (!node)
>        return;
>  
> +   memset(node, 0, sizeof(*node));
> +
>     /* Make sure the pointer is aligned to the size of a pointer */
>     assert((GLintptr) node % sizeof(void *) == 0);
>  
> @@ -568,6 +642,8 @@ compile_vertex_list(struct gl_context *ctx)
>        node->start_vertex = 0;
>     }
>  
> +   setup_vertex_arrays(ctx, node);
> +
>     /* Reset our structures for the next run of vertices:
>      */
>     reset_counters(ctx);
> @@ -1679,7 +1755,6 @@ static void
>  vbo_destroy_vertex_list(struct gl_context *ctx, void *data)
>  {
>     struct vbo_save_vertex_list *node = (struct vbo_save_vertex_list *) 
data;
> -   (void) ctx;
>  
>     if (--node->vertex_store->refcount == 0)
>        free_vertex_store(ctx, node->vertex_store);
> @@ -1688,6 +1763,13 @@ vbo_destroy_vertex_list(struct gl_context *ctx, void 
*data)
>        free(node->prim_store);
>  
>     free(node->current_data);
> +
> +   const unsigned num_arrays = _mesa_bitcount_64(node->enabled);
> +   for (unsigned i = 0; i < num_arrays; i++) {
> +      _mesa_reference_buffer_object(ctx, &(node->arrays[i].BufferObj), 
NULL);
> +   }
> +   free(node->arrays);
> +
>     node->current_data = NULL;
>  }
>  
> @@ -1752,7 +1834,6 @@ void
>  vbo_save_api_init(struct vbo_save_context *save)
>  {
>     struct gl_context *ctx = save->ctx;
> -   GLuint i;
>  
>     save->opcode_vertex_list =
>        _mesa_dlist_alloc_opcode(ctx,
> @@ -1764,8 +1845,4 @@ vbo_save_api_init(struct vbo_save_context *save)
>     vtxfmt_init(ctx);
>     current_init(ctx);
>     _mesa_noop_vtxfmt_init(&save->vtxfmt_noop);
> -
> -   /* These will actually get set again when binding/drawing */
> -   for (i = 0; i < VBO_ATTRIB_MAX; i++)
> -      save->inputs[i] = &save->arrays[i];
>  }
> diff --git a/src/mesa/vbo/vbo_save_draw.c b/src/mesa/vbo/vbo_save_draw.c
> index 5f5dcbe..1ef74d7 100644
> --- a/src/mesa/vbo/vbo_save_draw.c
> +++ b/src/mesa/vbo/vbo_save_draw.c
> @@ -125,69 +125,63 @@ playback_copy_to_current(struct gl_context *ctx,
>  }
>  
>  
> -
>  /**
> - * Treat the vertex storage as a VBO, define vertex arrays pointing
> - * into it:
> + * Setup the vertex arrays for drawing the primitives described by 'node'.
> + * This populates the node->inputs[] vertex arrays and calls
> + * _mesa_set_drawing_arrays().  Most of the work was previously done in
> + * the setup_vertex_arrays() function when the display list was compiled.
>   */
>  static void
>  bind_vertex_list(struct gl_context *ctx,
> -                 const struct vbo_save_vertex_list *node)
> +                 struct vbo_save_vertex_list *node)
>  {
>     struct vbo_context *vbo = vbo_context(ctx);
> -   struct vbo_save_context *save = &vbo->save;
> -   struct gl_vertex_array *arrays = save->arrays;
> -   GLuint buffer_offset = node->buffer_offset;
> -   const GLubyte *map;  /** map from VERT_ATTRIB_x to VBO_ATTRIB_x */
> -   GLuint attr;
> -   GLubyte node_attrsz[VBO_ATTRIB_MAX];  /* copy of node->attrsz[] */
> -   GLenum node_attrtype[VBO_ATTRIB_MAX];  /* copy of node->attrtype[] */
> +   const enum vp_mode vp_mode = get_vp_mode(ctx);
> +   unsigned array_count = 0;
>     GLbitfield64 enabled = node->enabled;
>  
> -   memcpy(node_attrsz, node->attrsz, sizeof(node->attrsz));
> -   memcpy(node_attrtype, node->attrtype, sizeof(node->attrtype));
> -
> -   if (aligned_vertex_buffer_offset(node)) {
> -      /* The vertex size is an exact multiple of the buffer offset.
> -       * This means that we can use zero-based vertex attribute pointers
> -       * and specify the start of the primitive with the _mesa_prim::start
> -       * field.  This results in issuing several draw calls with identical
> -       * vertex attribute information.  This can result in fewer state
> -       * changes in drivers.  In particular, the Gallium CSO module will
> -       * filter out redundant vertex buffer changes.
> -       */
> -      buffer_offset = 0;
> +   if (vp_mode == VP_SHADER) {
> +      /* per-vertex materials are to be ignored when using a VS */
> +      enabled &= ~VBO_ATTRIBS_MATERIALS;
>     }
>  
> -   /* Install the default (ie Current) attributes first */
> -   for (attr = 0; attr < VERT_ATTRIB_FF_MAX; attr++) {
> -      save->inputs[attr] = &vbo->currval[VBO_ATTRIB_POS + attr];
> -   }
> +   /* Loop over the attributes which are present in the vertex buffer
> +    * and set the node->input vertex arrays to point to those attributes.
> +    */
> +   GLbitfield64 enabled_scan = enabled;
> +   while (enabled_scan) {
> +      const int attr = u_bit_scan64(&enabled_scan);
> +      unsigned dst;
>  
> -   /* Overlay other active attributes */
> -   switch (get_vp_mode(ctx)) {
> -   case VP_FF:
> -      /* Point the generic attributes at the legacy material values */
> -      for (attr = 0; attr < MAT_ATTRIB_MAX; attr++) {
> -         save->inputs[VERT_ATTRIB_GENERIC(attr)] =
> -            &vbo->currval[VBO_ATTRIB_MAT_FRONT_AMBIENT+attr];
> +      /* Here is where we resolve whether array[16...] points to legacy
> +       * material coefficients or generic vertex attributes.
> +       */
> +      if (vp_mode == VP_FF) {
> +         if (attr >= VBO_ATTRIB_FIRST_MATERIAL) {
> +            dst = VBO_ATTRIB_GENERIC0 + attr - VBO_ATTRIB_FIRST_MATERIAL;
> +         } else {
> +            dst = attr;
> +         }
> +      } else {
> +         assert(vp_mode == VP_SHADER);
> +         dst = attr;
>        }
> -      map = vbo->map_vp_none;
>  
> -      /* shift material attrib flags into generic attribute positions */
> +      assert(dst < VERT_ATTRIB_MAX);
> +      assert(node->arrays);
> +      node->inputs[dst] = &node->arrays[array_count++];
> +   }
> +
> +   /* Final vertex array setup depending on whether we're using fixed
> +    * function or a vertex shader.
> +    */
> +   if (vp_mode == VP_FF) {
> +      /* Update the enabled attribute bitfield so the material attrib bits
> +       * replace the generic attrib bits.
> +       */
>        enabled = (enabled & VBO_ATTRIBS_LEGACY)
>           | ((enabled & VBO_ATTRIBS_MATERIALS) >> VBO_MATERIAL_SHIFT);
> -      break;
> -   case VP_SHADER:
> -      for (attr = 0; attr < VERT_ATTRIB_GENERIC_MAX; attr++) {
> -         save->inputs[VERT_ATTRIB_GENERIC(attr)] =
> -            &vbo->currval[VBO_ATTRIB_GENERIC0+attr];
> -      }
> -      map = vbo->map_vp_arb;
> -
> -      /* per-vertex materials are to be ignored when using a VS */
> -      enabled &= ~VBO_ATTRIBS_MATERIALS;
> -
> +   } else {
>        /* check if VERT_ATTRIB_POS is not read but VERT_BIT_GENERIC0 is 
read.
>         * In that case we effectively need to route the data from
>         * glVertexAttrib(0, val) calls to feed into the GENERIC0 input.
> @@ -196,64 +190,19 @@ bind_vertex_list(struct gl_context *ctx,
>           ctx->VertexProgram._Current->info.inputs_read;
>        if ((inputs_read & VERT_BIT_POS) == 0 &&
>            (inputs_read & VERT_BIT_GENERIC0)) {
> -         save->inputs[VERT_ATTRIB_GENERIC0] = save->inputs[0];
> -         node_attrsz[VERT_ATTRIB_GENERIC0] = node_attrsz[0];
> -         node_attrtype[VERT_ATTRIB_GENERIC0] = node_attrtype[0];
> -         node_attrsz[0] = 0;
> -         enabled = (enabled & ~VERT_BIT_POS) | VERT_BIT_GENERIC0;
> -      }
> -      break;
> -   default:
> -      unreachable("Bad vertex program mode");
> -   }
> -
> -#ifdef DEBUG
> -   /* verify the enabled bitmask is consistent with attribute size info */
> -   {
> -      GLbitfield64 used = 0x0;
> -      for (attr = 0; attr < VERT_ATTRIB_MAX; attr++) {
> -         const GLuint src = map[attr];
> -         if (node_attrsz[src]) {
> -            assert(enabled & VERT_BIT(attr));
> -            used |= VERT_BIT(attr);
> -         } else {
> -            assert((enabled & VERT_BIT(attr)) == 0);
> -         }
> +         node->inputs[VERT_ATTRIB_GENERIC0] = &node-
>arrays[VBO_ATTRIB_POS];
> +         node->inputs[VERT_ATTRIB_POS] = &vbo->currval[VBO_ATTRIB_POS];
> +         enabled &= ~BITFIELD64_BIT(VBO_ATTRIB_POS);
> +         enabled |= BITFIELD64_BIT(VBO_ATTRIB_GENERIC0);
>        }
> -      assert(used == enabled);
>     }
> -#endif
>  
> -   GLbitfield64 enabled_scan = enabled;
> -   while (enabled_scan) {
> -      const int attr = u_bit_scan64(&enabled_scan);
> -      const GLuint src = map[attr];
> -
> -      if (node_attrsz[src]) {
> -         struct gl_vertex_array *array = &arrays[attr];
> -
> -         /* override the default array set above */
> -         save->inputs[attr] = array;
> -
> -         array->Ptr = (const GLubyte *) NULL + buffer_offset;
> -         array->Size = node_attrsz[src];
> -         array->StrideB = node->vertex_size * sizeof(GLfloat);
> -         array->Type = node_attrtype[src];
> -         array->Integer = vbo_attrtype_to_integer_flag(node_attrtype[src]);
> -         array->Format = GL_RGBA;
> -         array->_ElementSize = array->Size * sizeof(GLfloat);
> -         _mesa_reference_buffer_object(ctx,
> -                                       &array->BufferObj,
> -                                       node->vertex_store->bufferobj);
> -
> -         assert(array->BufferObj->Name);
> -
> -         buffer_offset += node_attrsz[src] * sizeof(GLfloat);
> -      }
> -   }
> +   /* make sure none of the extra VBO_ATTRIB bits are set */
> +   assert((enabled & (GLbitfield64) VERT_BIT_ALL) == enabled);
>  
>     _mesa_set_varying_vp_inputs(ctx, enabled);
> -   ctx->NewDriverState |= ctx->DriverFlags.NewArray;
> +
> +   _mesa_set_drawing_arrays(ctx, node->inputs);
>  }
>  
>  
> @@ -292,8 +241,8 @@ loopback_vertex_list(struct gl_context *ctx,
>  void
>  vbo_save_playback_vertex_list(struct gl_context *ctx, void *data)
>  {
> -   const struct vbo_save_vertex_list *node =
> -      (const struct vbo_save_vertex_list *) data;
> +   struct vbo_save_vertex_list *node =
> +      (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;
> @@ -346,8 +295,6 @@ vbo_save_playback_vertex_list(struct gl_context *ctx, 
void *data)
>  
>        bind_vertex_list(ctx, node);
>  
> -      _mesa_set_drawing_arrays(ctx, vbo->save.inputs);
> -
>        /* Again...
>         */
>        if (ctx->NewState)
> 




_______________________________________________
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to