[Mesa-dev] [PATCH 04/11] gallium: Use Array._DrawVAO in st_atom_array.c.

Brian Paul brianp at vmware.com
Wed Apr 11 14:23:52 UTC 2018


Hmm, in my experience, interleaved arrays are fairly common.

I still haven't had much time to look at Mathias's latest patches.

And I haven't looked this code in the state tracker recently, but I seem 
to recall there was some difference between interleaved arrays (in one 
VBO) vs. separate arrays in separate VBOs that needed special handling.

As for determining whether arrays are interleaved, if that's something 
we still need to do, I think it could be lifted into core Mesa.  We 
could add a new gl_vertex_array_object::_IsInterleaved field which is 
only updated when the VAO state is modified.

-Brian


On 04/10/2018 12:09 PM, Marek Olšák wrote:
> Generally, if you have to loop over all arrays to find common vertex 
> buffers, it's better not to do it. The default separate path is going to 
> perform best, because it's straightforward and interleaved arrays are 
> super rare.
> 
> Marek
> 
> On Mon, Apr 9, 2018 at 7:15 PM, Mathias Fröhlich 
> <Mathias.Froehlich at gmx.net <mailto:Mathias.Froehlich at gmx.net>> wrote:
> 
>     Hi Marek,
> 
>     On Saturday, 7 April 2018 01:53:58 CEST Marek Olšák wrote:
>     > So interleaved attribs are unsupported, right?
>     >
>     > is_interleaved_arrays was probably slowing things down, so I'm OK with that.
> 
>     I am currently away from all the source code and be back at about
>     the 22.4.
> 
>     But out of my head: The main purpose of the is_interleaved_arrays
>     that I could
>     spot is to minimize the vbo's that are send down the pipeline. In
>     the non vbo
>     case the is_interleaved_arrays check did nothing I could finally spot?
>     The buffer itself is marked as user buffer and we need a new vbuffer
>     because
>     of the pointer value anyway? Correct?
> 
>     So, the VAO now contains all the redundancy information. And thanks
>     to this
>     bitmask sieves we can easily collect the arrays belonging to a specific
>     precollapsed binding point.
>     So, the is_interleaved is fully there in the vbo case. Even better
>     as before.
>     It sees even 4 attributes distributed across two pairwise
>     interleaved vbo
>     arrays.
> 
>     So even if you are fine, if you tell me that the user buffer code
>     can make use
>     of the same sharing finally, I can take a look at that and establish
>     the same
>     sort of sharing here.
> 
>     best
> 
>     Mathias
> 
> 
>      >
>      > Marek
>      >
>      > On Sun, Apr 1, 2018 at 2:13 PM, <Mathias.Froehlich at gmx.net
>     <mailto:Mathias.Froehlich at gmx.net>> wrote:
>      > > From: Mathias Fröhlich <mathias.froehlich at web.de
>     <mailto:mathias.froehlich at web.de>>
>      > >
>      > > Finally make use of the binding information in the VAO when
>      > > setting up arrays for draw.
>      > >
>      > > Signed-off-by: Mathias Fröhlich <Mathias.Froehlich at web.de
>     <mailto:Mathias.Froehlich at web.de>>
>      > > ---
>      > >
>      > >  src/mesa/state_tracker/st_atom_array.c | 448
>      > >
>      > > +++++++++------------------------
>      > >
>      > >  1 file changed, 124 insertions(+), 324 deletions(-)
>      > >
>      > > diff --git a/src/mesa/state_tracker/st_atom_array.c
>      > > b/src/mesa/state_tracker/st_atom_array.c
>      > > index 2fd67e8d84..46934a718a 100644
>      > > --- a/src/mesa/state_tracker/st_atom_array.c
>      > > +++ b/src/mesa/state_tracker/st_atom_array.c
>      > > @@ -48,6 +48,7 @@
>      > >
>      > >  #include "main/bufferobj.h"
>      > >  #include "main/glformats.h"
>      > >  #include "main/varray.h"
>      > >
>      > > +#include "main/arrayobj.h"
>      > >
>      > >  /* vertex_formats[gltype - GL_BYTE][integer*2 +
>     normalized][size - 1] */
>      > >  static const uint16_t vertex_formats[][4][4] = {
>      > >
>      > > @@ -306,79 +307,6 @@ st_pipe_vertex_format(const struct
>      > > gl_array_attributes *attrib)
>      > >
>      > >     return vertex_formats[type - GL_BYTE][index][size-1];
>      > >
>      > >  }
>      > >
>      > > -static const struct gl_vertex_array *
>      > > -get_client_array(const struct gl_vertex_array *arrays,
>      > > -                 unsigned mesaAttr)
>      > > -{
>      > > -   /* st_program uses 0xffffffff to denote a double
>     placeholder attribute
>      > > */
>      > > -   if (mesaAttr == ST_DOUBLE_ATTRIB_PLACEHOLDER)
>      > > -      return NULL;
>      > > -   return &arrays[mesaAttr];
>      > > -}
>      > > -
>      > > -/**
>      > > - * Examine the active arrays to determine if we have interleaved
>      > > - * vertex arrays all living in one VBO, or all living in user
>     space.
>      > > - */
>      > > -static GLboolean
>      > > -is_interleaved_arrays(const struct st_vertex_program *vp,
>      > > -                      const struct gl_vertex_array *arrays,
>      > > -                      unsigned num_inputs)
>      > > -{
>      > > -   GLuint attr;
>      > > -   const struct gl_buffer_object *firstBufObj = NULL;
>      > > -   GLint firstStride = -1;
>      > > -   const GLubyte *firstPtr = NULL;
>      > > -   GLboolean userSpaceBuffer = GL_FALSE;
>      > > -
>      > > -   for (attr = 0; attr < num_inputs; attr++) {
>      > > -      const struct gl_vertex_array *array;
>      > > -      const struct gl_vertex_buffer_binding *binding;
>      > > -      const struct gl_array_attributes *attrib;
>      > > -      const GLubyte *ptr;
>      > > -      const struct gl_buffer_object *bufObj;
>      > > -      GLsizei stride;
>      > > -
>      > > -      array = get_client_array(arrays, vp->index_to_input[attr]);
>      > > -      if (!array)
>      > > -        continue;
>      > > -
>      > > -      binding = array->BufferBinding;
>      > > -      attrib = array->VertexAttrib;
>      > > -      stride = binding->Stride; /* in bytes */
>      > > -      ptr = _mesa_vertex_attrib_address(attrib, binding);
>      > > -
>      > > -      /* To keep things simple, don't allow interleaved
>     zero-stride
>      > > attribs. */
>      > > -      if (stride == 0)
>      > > -         return false;
>      > > -
>      > > -      bufObj = binding->BufferObj;
>      > > -      if (attr == 0) {
>      > > -         /* save info about the first array */
>      > > -         firstStride = stride;
>      > > -         firstPtr = ptr;
>      > > -         firstBufObj = bufObj;
>      > > -         userSpaceBuffer = !_mesa_is_bufferobj(bufObj);
>      > > -      }
>      > > -      else {
>      > > -         /* check if other arrays interleave with the first,
>     in same
>      > > buffer */
>      > > -         if (stride != firstStride)
>      > > -            return GL_FALSE; /* strides don't match */
>      > > -
>      > > -         if (bufObj != firstBufObj)
>      > > -            return GL_FALSE; /* arrays in different VBOs */
>      > > -
>      > > -         if (llabs(ptr - firstPtr) > firstStride)
>      > > -            return GL_FALSE; /* arrays start too far apart */
>      > > -
>      > > -         if ((!_mesa_is_bufferobj(bufObj)) != userSpaceBuffer)
>      > > -            return GL_FALSE; /* mix of VBO and user-space
>     arrays */
>      > > -      }
>      > > -   }
>      > > -
>      > > -   return GL_TRUE;
>      > > -}
>      > > -
>      > >
>      > >  static void init_velement(struct pipe_vertex_element *velement,
>      > >
>      > >                            int src_offset, int format,
>      > >                            int instance_divisor, int vbo_index)
>      > >
>      > > @@ -392,13 +320,14 @@ static void init_velement(struct
>     pipe_vertex_element
>      > > *velement,
>      > >
>      > >  static void init_velement_lowered(const struct
>     st_vertex_program *vp,
>      > >
>      > >                                    struct pipe_vertex_element
>     *velements,
>      > >
>      > > -                                  int src_offset, int format,
>      > > -                                  int instance_divisor, int
>     vbo_index,
>      > > -                                  int nr_components, GLboolean
>     doubles,
>      > > -                                  GLuint *attr_idx)
>      > > +                                  const struct gl_array_attributes
>      > > *attrib,
>      > > +                                  int src_offset, int
>     instance_divisor,
>      > > +                                  int vbo_index, int idx)
>      > >
>      > >  {
>      > >
>      > > -   int idx = *attr_idx;
>      > > -   if (doubles) {
>      > > +   const unsigned format = st_pipe_vertex_format(attrib);
>      > > +   const GLubyte nr_components = attrib->Size;
>      > > +
>      > > +   if (attrib->Doubles) {
>      > >
>      > >        int lower_format;
>      > >
>      > >        if (nr_components < 2)
>      > >
>      > > @@ -427,15 +356,11 @@ static void init_velement_lowered(const
>     struct
>      > > st_vertex_program *vp,
>      > >
>      > >              init_velement(&velements[idx], src_offset,
>      > >
>      > > PIPE_FORMAT_R32G32_UINT,
>      > >
>      > >                            instance_divisor, vbo_index);
>      > >
>      > >           }
>      > >
>      > > -
>      > > -         idx++;
>      > >
>      > >        }
>      > >
>      > >     } else {
>      > >
>      > >        init_velement(&velements[idx], src_offset,
>      > >
>      > >                      format, instance_divisor, vbo_index);
>      > >
>      > > -      idx++;
>      > >
>      > >     }
>      > >
>      > > -   *attr_idx = idx;
>      > >
>      > >  }
>      > >
>      > >  static void
>      > >
>      > > @@ -457,274 +382,149 @@ set_vertex_attribs(struct st_context *st,
>      > >
>      > >     cso_set_vertex_elements(cso, num_velements, velements);
>      > >
>      > >  }
>      > >
>      > > -/**
>      > > - * Set up for drawing interleaved arrays that all live in one VBO
>      > > - * or all live in user space.
>      > > - * \param vbuffer  returns vertex buffer info
>      > > - * \param velements  returns vertex element info
>      > > - */
>      > > -static void
>      > > -setup_interleaved_attribs(struct st_context *st,
>      > > -                          const struct st_vertex_program *vp,
>      > > -                          const struct gl_vertex_array *arrays,
>      > > -                          unsigned num_inputs)
>      > > +void st_update_array(struct st_context *st)
>      > >
>      > >  {
>      > >
>      > > -   struct pipe_vertex_buffer vbuffer;
>      > > -   struct pipe_vertex_element velements[PIPE_MAX_ATTRIBS] = {{0}};
>      > > -   GLuint attr;
>      > > -   const GLubyte *low_addr = NULL;
>      > > -   GLboolean usingVBO;      /* all arrays in a VBO? */
>      > > -   struct gl_buffer_object *bufobj;
>      > > -   GLsizei stride;
>      > > -
>      > > -   /* Find the lowest address of the arrays we're drawing,
>      > > -    * Init bufobj and stride.
>      > > -    */
>      > > -   if (num_inputs) {
>      > > -      const struct gl_vertex_array *array;
>      > > -      const struct gl_vertex_buffer_binding *binding;
>      > > -      const struct gl_array_attributes *attrib;
>      > > -
>      > > -      array = get_client_array(arrays, vp->index_to_input[0]);
>      > > -      assert(array);
>      > > -
>      > > -      binding = array->BufferBinding;
>      > > -      attrib = array->VertexAttrib;
>      > > -
>      > > -      /* Since we're doing interleaved arrays, we know
>     there'll be at
>      > > most
>      > > -       * one buffer object and the stride will be the same for all
>      > > arrays.
>      > > -       * Grab them now.
>      > > -       */
>      > > -      bufobj = binding->BufferObj;
>      > > -      stride = binding->Stride;
>      > > -
>      > > -      low_addr = _mesa_vertex_attrib_address(attrib, binding);
>      > > -
>      > > -      for (attr = 1; attr < num_inputs; attr++) {
>      > > -         const GLubyte *start;
>      > > -         array = get_client_array(arrays,
>     vp->index_to_input[attr]);
>      > > -         if (!array)
>      > > -            continue;
>      > > -         binding = array->BufferBinding;
>      > > -         attrib = array->VertexAttrib;
>      > > -         start = _mesa_vertex_attrib_address(attrib, binding);
>      > > -         low_addr = MIN2(low_addr, start);
>      > > -      }
>      > > -   }
>      > > -   else {
>      > > -      /* not sure we'll ever have zero inputs, but play it safe */
>      > > -      bufobj = NULL;
>      > > -      stride = 0;
>      > > -      low_addr = 0;
>      > > -   }
>      > > -
>      > > -   /* are the arrays in user space? */
>      > > -   usingVBO = _mesa_is_bufferobj(bufobj);
>      > > -
>      > > -   for (attr = 0; attr < num_inputs;) {
>      > > -      const struct gl_vertex_array *array;
>      > > -      const struct gl_vertex_buffer_binding *binding;
>      > > -      const struct gl_array_attributes *attrib;
>      > > -      const GLubyte *ptr;
>      > > -      unsigned src_offset;
>      > > -      unsigned src_format;
>      > > -
>      > > -      array = get_client_array(arrays, vp->index_to_input[attr]);
>      > > -      assert(array);
>      > > -
>      > > -      binding = array->BufferBinding;
>      > > -      attrib = array->VertexAttrib;
>      > > -      ptr = _mesa_vertex_attrib_address(attrib, binding);
>      > > +   struct gl_context *ctx = st->ctx;
>      > > +   /* vertex program validation must be done before this */
>      > > +   const struct st_vertex_program *vp = st->vp;
>      > > +   /* _NEW_PROGRAM, ST_NEW_VS_STATE */
>      > > +   const GLbitfield inputs_read =
>     st->vp_variant->vert_attrib_mask;
>      > > +   const struct gl_vertex_array_object *vao = ctx->Array._DrawVAO;
>      > > +   const ubyte *input_to_index = vp->input_to_index;
>      > >
>      > > -      src_offset = (unsigned) (ptr - low_addr);
>      > > +   struct pipe_vertex_buffer vbuffer[PIPE_MAX_ATTRIBS];
>      > > +   struct pipe_vertex_element velements[PIPE_MAX_ATTRIBS];
>      > > +   unsigned num_vbuffers = 0;
>      > >
>      > > -      src_format = st_pipe_vertex_format(attrib);
>      > > +   st->vertex_array_out_of_memory = FALSE;
>      > > +   st->draw_needs_minmax_index = false;
>      > >
>      > > -      init_velement_lowered(vp, velements, src_offset, src_format,
>      > > -                            binding->InstanceDivisor, 0,
>      > > -                            attrib->Size, attrib->Doubles, &attr);
>      > > -   }
>      > > +   /* _NEW_PROGRAM */
>      > > +   /* ST_NEW_VERTEX_ARRAYS alias ctx->DriverFlags.NewArray */
>      > > +   /* Attribute data is in a VBO. */
>      > > +   GLbitfield vbomask = inputs_read &
>     _mesa_draw_vbo_array_bits(ctx);
>      > > +   while (vbomask) {
>      > > +      /* The attribute index to start pulling a binding */
>      > > +      const gl_vert_attrib i = ffs(vbomask) - 1;
>      > > +      const struct gl_vertex_buffer_binding *const binding
>      > > +         = _mesa_draw_buffer_binding(vao, i);
>      > > +      const unsigned bufidx = num_vbuffers++;
>      > >
>      > > -   /*
>      > > -    * Return the vbuffer info and setup user-space attrib info, if
>      > > needed.
>      > > -    */
>      > > -   if (num_inputs == 0) {
>      > > -      /* just defensive coding here */
>      > > -      vbuffer.buffer.resource = NULL;
>      > > -      vbuffer.is_user_buffer = false;
>      > > -      vbuffer.buffer_offset = 0;
>      > > -      vbuffer.stride = 0;
>      > > -   }
>      > > -   else if (usingVBO) {
>      > > -      /* all interleaved arrays in a VBO */
>      > > -      struct st_buffer_object *stobj = st_buffer_object(bufobj);
>      > > +      assert(_mesa_is_bufferobj(binding->BufferObj));
>      > >
>      > > +      struct st_buffer_object *stobj =
>     st_buffer_object(binding->Buff
>      > > erObj);
>      > >
>      > >        if (!stobj || !stobj->buffer) {
>      > >
>      > >           st->vertex_array_out_of_memory = true;
>      > >           return; /* out-of-memory error probably */
>      > >
>      > >        }
>      > >
>      > > -      vbuffer.buffer.resource = stobj->buffer;
>      > > -      vbuffer.is_user_buffer = false;
>      > > -      vbuffer.buffer_offset = pointer_to_offset(low_addr);
>      > > -      vbuffer.stride = stride;
>      > > -   }
>      > > -   else {
>      > > -      /* all interleaved arrays in user memory */
>      > > -      vbuffer.buffer.user = low_addr;
>      > > -      vbuffer.is_user_buffer = !!low_addr; /* if NULL, then
>     unbind */
>      > > -      vbuffer.buffer_offset = 0;
>      > > -      vbuffer.stride = stride;
>      > > -
>      > > -      if (low_addr)
>      > > -         st->draw_needs_minmax_index = true;
>      > > +      /* Set the binding */
>      > > +      vbuffer[bufidx].buffer.resource = stobj->buffer;
>      > > +      vbuffer[bufidx].is_user_buffer = false;
>      > > +      vbuffer[bufidx].buffer_offset =
>     _mesa_draw_binding_offset(binding);
>      > > +      vbuffer[bufidx].stride = binding->Stride; /* in bytes */
>      > > +
>      > > +      const GLbitfield boundmask =
>     _mesa_draw_bound_attrib_bits(binding);
>      > > +      GLbitfield attrmask = vbomask & boundmask;
>      > > +      /* Mark the those attributes as processed */
>      > > +      vbomask &= ~boundmask;
>      > > +      /* We can assume that we have array for the binding */
>      > > +      assert(attrmask);
>      > > +      /* Walk attributes belonging to the binding */
>      > > +      while (attrmask) {
>      > > +         const gl_vert_attrib attr = u_bit_scan(&attrmask);
>      > > +         const struct gl_array_attributes *const attrib
>      > > +            = _mesa_draw_array_attrib(vao, attr);
>      > > +         const GLuint off = _mesa_draw_attributes_relative
>      > > _offset(attrib);
>      > > +         init_velement_lowered(vp, velements, attrib, off,
>      > > +                               binding->InstanceDivisor, bufidx,
>      > > +                               input_to_index[attr]);
>      > > +      }
>      > >
>      > >     }
>      > >
>      > > -   set_vertex_attribs(st, &vbuffer, num_inputs ? 1 : 0,
>      > > -                      velements, num_inputs);
>      > > -}
>      > > -
>      > > -/**
>      > > - * Set up a separate pipe_vertex_buffer and
>     pipe_vertex_element for each
>      > > - * vertex attribute.
>      > > - * \param vbuffer  returns vertex buffer info
>      > > - * \param velements  returns vertex element info
>      > > - */
>      > > -static void
>      > > -setup_non_interleaved_attribs(struct st_context *st,
>      > > -                              const struct st_vertex_program *vp,
>      > > -                              const struct gl_vertex_array
>     *arrays,
>      > > -                              unsigned num_inputs)
>      > > -{
>      > > -   struct gl_context *ctx = st->ctx;
>      > > -   struct pipe_vertex_buffer vbuffer[PIPE_MAX_ATTRIBS];
>      > > -   struct pipe_vertex_element velements[PIPE_MAX_ATTRIBS] = {{0}};
>      > > -   unsigned num_vbuffers = 0;
>      > > -   unsigned unref_buffers = 0;
>      > > -   GLuint attr;
>      > > -
>      > > -   for (attr = 0; attr < num_inputs;) {
>      > > -      const unsigned mesaAttr = vp->index_to_input[attr];
>      > > -      const struct gl_vertex_array *array;
>      > > -      const struct gl_vertex_buffer_binding *binding;
>      > > -      const struct gl_array_attributes *attrib;
>      > > -      struct gl_buffer_object *bufobj;
>      > > -      GLsizei stride;
>      > > -      unsigned src_format;
>      > > -      unsigned bufidx;
>      > > -
>      > > -      array = get_client_array(arrays, mesaAttr);
>      > > -      assert(array);
>      > > -
>      > > -      bufidx = num_vbuffers++;
>      > > -
>      > > -      binding = array->BufferBinding;
>      > > -      attrib = array->VertexAttrib;
>      > > -      stride = binding->Stride;
>      > > -      bufobj = binding->BufferObj;
>      > > -
>      > > -      if (_mesa_is_bufferobj(bufobj)) {
>      > > -         /* Attribute data is in a VBO.
>      > > -          * Recall that for VBOs, the gl_vertex_array->Ptr
>     field is
>      > > -          * really an offset from the start of the VBO, not a
>     pointer.
>      > > -          */
>      > > -         struct st_buffer_object *stobj =
>     st_buffer_object(bufobj);
>      > > -
>      > > -         if (!stobj || !stobj->buffer) {
>      > > -            st->vertex_array_out_of_memory = true;
>      > > -            return; /* out-of-memory error probably */
>      > > -         }
>      > > +   /* _NEW_PROGRAM */
>      > > +   /* ST_NEW_VERTEX_ARRAYS alias ctx->DriverFlags.NewArray */
>      > > +   /* Process user space buffers */
>      > > +   GLbitfield usermask = inputs_read &
>     _mesa_draw_user_array_bits(ctx);
>      > > +   while (usermask) {
>      > > +      const gl_vert_attrib attr = u_bit_scan(&usermask);
>      > > +      const struct gl_array_attributes *const attrib
>      > > +         = _mesa_draw_array_attrib(vao, attr);
>      > > +      const struct gl_vertex_buffer_binding *const binding
>      > > +         = _mesa_draw_buffer_binding_from_attrib(vao, attrib);
>      > > +      const unsigned bufidx = num_vbuffers++;
>      > > +
>      > > +      assert(!_mesa_is_bufferobj(binding->BufferObj));
>      > > +
>      > > +      vbuffer[bufidx].buffer.user = attrib->Ptr;
>      > > +      vbuffer[bufidx].is_user_buffer = true;
>      > > +      vbuffer[bufidx].buffer_offset = 0;
>      > > +      vbuffer[bufidx].stride = binding->Stride; /* in bytes */
>      > > +
>      > > +      init_velement_lowered(vp, velements, attrib, 0,
>      > > +                            binding->InstanceDivisor, bufidx,
>      > > +                            input_to_index[attr]);
>      > >
>      > > -         vbuffer[bufidx].buffer.resource = stobj->buffer;
>      > > -         vbuffer[bufidx].is_user_buffer = false;
>      > > -         vbuffer[bufidx].buffer_offset =
>      > > -            binding->Offset + attrib->RelativeOffset;
>      > > -      }
>      > > -      else {
>      > > -         if (stride == 0) {
>      > > -            unsigned size = attrib->_ElementSize;
>      > > -            /* This is optimal for GPU cache line usage if the
>     upload
>      > > size
>      > > -             * is <= cache line size.
>      > > -             */
>      > > -            unsigned alignment = util_next_power_of_two(size);
>      > > -
>      > > -            assert(attrib->Ptr);
>      > > -            vbuffer[bufidx].buffer.user = attrib->Ptr;
>      > > -            void *ptr = attrib->Ptr ? (void*)attrib->Ptr :
>      > > -                                     
>     (void*)ctx->Current.Attrib[mes
>      > > aAttr];
>      > > -
>      > > -            vbuffer[bufidx].is_user_buffer = false;
>      > > -            vbuffer[bufidx].buffer.resource = NULL;
>      > > -
>      > > -            /* Use const_uploader for zero-stride vertex
>     attributes,
>      > > because
>      > > -             * it may use a better memory placement than
>     stream_uploader.
>      > > -             * The reason is that zero-stride attributes can
>     be fetched
>      > > many
>      > > -             * times (thousands of times), so a better
>     placement is going
>      > > to
>      > > -             * perform better.
>      > > -             *
>      > > -             * Upload the maximum possible size, which is 4x
>     GLdouble =
>      > > 32.
>      > > -             */
>      > > -            u_upload_data(st->can_bind_const_buffer_as_vertex ?
>      > > -                             st->pipe->const_uploader :
>      > > -                             st->pipe->stream_uploader,
>      > > -                          0, size, alignment, ptr,
>      > > -                          &vbuffer[bufidx].buffer_offset,
>      > > -                          &vbuffer[bufidx].buffer.resource);
>      > > -            unref_buffers |= 1u << bufidx;
>      > > -         } else {
>      > > -            assert(attrib->Ptr);
>      > > -            vbuffer[bufidx].buffer.user = attrib->Ptr;
>      > > -            vbuffer[bufidx].is_user_buffer = true;
>      > > -            vbuffer[bufidx].buffer_offset = 0;
>      > > +      if (!binding->InstanceDivisor)
>      > > +         st->draw_needs_minmax_index = true;
>      > > +   }
>      > >
>      > > -            if (!binding->InstanceDivisor)
>      > > -               st->draw_needs_minmax_index = true;
>      > > -         }
>      > > +   const unsigned first_current_vbuffer = num_vbuffers;
>      > > +   /* _NEW_PROGRAM | _NEW_CURRENT_ATTRIB */
>      > > +   /* Process values that should have better been uniforms in the
>      > > application */
>      > > +   GLbitfield curmask = inputs_read &
>     _mesa_draw_current_bits(ctx);
>      > > +   if (curmask) {
>      > > +      /* For each attribute, upload the maximum possible size. */
>      > > +      GLubyte data[VERT_ATTRIB_MAX*sizeof(GLdouble)*4];
>      > > +      GLubyte *cursor = data;
>      > > +      const unsigned bufidx = num_vbuffers++;
>      > > +      unsigned max_alignment = 1;
>      > > +
>      > > +      while (curmask) {
>      > > +         const gl_vert_attrib attr = u_bit_scan(&curmask);
>      > > +         const struct gl_array_attributes *const attrib
>      > > +            = _mesa_draw_current_attrib(ctx, attr);
>      > > +         const unsigned size = attrib->_ElementSize;
>      > > +         const unsigned alignment = util_next_power_of_two(size);
>      > > +         max_alignment = MAX2(max_alignment, alignment);
>      > > +         memcpy(cursor, attrib->Ptr, size);
>      > > +         if (alignment != size)
>      > > +            memset(cursor + size, 0, alignment - size);
>      > > +
>      > > +         init_velement_lowered(vp, velements, attrib, cursor -
>     data, 0,
>      > > +                               bufidx, input_to_index[attr]);
>      > > +
>      > > +         cursor += alignment;
>      > >
>      > >        }
>      > >
>      > > -      /* common-case setup */
>      > > -      vbuffer[bufidx].stride = stride; /* in bytes */
>      > > +      vbuffer[bufidx].is_user_buffer = false;
>      > > +      vbuffer[bufidx].buffer.resource = NULL;
>      > > +      /* vbuffer[bufidx].buffer_offset is set below */
>      > > +      vbuffer[bufidx].stride = 0;
>      > >
>      > > -      src_format = st_pipe_vertex_format(attrib);
>      > > -
>      > > -      init_velement_lowered(vp, velements, 0, src_format,
>      > > -                            binding->InstanceDivisor, bufidx,
>      > > -                            attrib->Size, attrib->Doubles, &attr);
>      > > +      /* Use const_uploader for zero-stride vertex attributes,
>     because
>      > > +       * it may use a better memory placement than
>     stream_uploader.
>      > > +       * The reason is that zero-stride attributes can be
>     fetched many
>      > > +       * times (thousands of times), so a better placement is
>     going to
>      > > +       * perform better.
>      > > +       */
>      > > +      u_upload_data(st->can_bind_const_buffer_as_vertex ?
>      > > +                    st->pipe->const_uploader :
>      > > +                    st->pipe->stream_uploader,
>      > > +                    0, cursor - data, max_alignment, data,
>      > > +                    &vbuffer[bufidx].buffer_offset,
>      > > +                    &vbuffer[bufidx].buffer.resource);
>      > >
>      > >     }
>      > >
>      > >     if (!ctx->Const.AllowMappedBuffersDuringExecution) {
>      > >
>      > >        u_upload_unmap(st->pipe->stream_uploader);
>      > >
>      > >     }
>      > >
>      > > +   const unsigned num_inputs = st->vp_variant->num_inputs;
>      > >
>      > >     set_vertex_attribs(st, vbuffer, num_vbuffers, velements,
>     num_inputs);
>      > >
>      > >     /* Unreference uploaded zero-stride vertex buffers. */
>      > >
>      > > -   while (unref_buffers) {
>      > > -      unsigned i = u_bit_scan(&unref_buffers);
>      > > +   for (unsigned i = first_current_vbuffer; i < num_vbuffers;
>     ++i) {
>      > >
>      > >        pipe_resource_reference(&vbuffer[i].buffer.resource, NULL);
>      > >
>      > >     }
>      > >
>      > >  }
>      > >
>      > > -
>      > > -void st_update_array(struct st_context *st)
>      > > -{
>      > > -   struct gl_context *ctx = st->ctx;
>      > > -   const struct gl_vertex_array *arrays = ctx->Array._DrawArrays;
>      > > -   const struct st_vertex_program *vp;
>      > > -   unsigned num_inputs;
>      > > -
>      > > -   st->vertex_array_out_of_memory = FALSE;
>      > > -   st->draw_needs_minmax_index = false;
>      > > -
>      > > -   /* No drawing has been done yet, so do nothing. */
>      > > -   if (!arrays)
>      > > -      return;
>      > > -
>      > > -   /* vertex program validation must be done before this */
>      > > -   vp = st->vp;
>      > > -   num_inputs = st->vp_variant->num_inputs;
>      > > -
>      > > -   if (is_interleaved_arrays(vp, arrays, num_inputs))
>      > > -      setup_interleaved_attribs(st, vp, arrays, num_inputs);
>      > > -   else
>      > > -      setup_non_interleaved_attribs(st, vp, arrays, num_inputs);
>      > > -}
>      > > --
>      > > 2.14.3
>      > >
>      > > _______________________________________________
>      > > mesa-dev mailing list
>      > > mesa-dev at lists.freedesktop.org
>     <mailto:mesa-dev at lists.freedesktop.org>
>      > > https://lists.freedesktop.org/mailman/listinfo/mesa-dev
>     <https://urldefense.proofpoint.com/v2/url?u=https-3A__lists.freedesktop.org_mailman_listinfo_mesa-2Ddev&d=DwMFaQ&c=uilaK90D4TOVoH58JNXRgQ&r=Ie7_encNUsqxbSRbqbNgofw0ITcfE8JKfaUjIQhncGA&m=BvRi46sEMPR__KUw0U1URM0Eq0Lea_ZE0YYz9O71hWY&s=EKmb5XTawHwj4RTy4ZbncuYKs3jBTzYKO1SWbawHtbA&e=>
> 
> 
> 
> 
> 
> 
> 
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> https://urldefense.proofpoint.com/v2/url?u=https-3A__lists.freedesktop.org_mailman_listinfo_mesa-2Ddev&d=DwIGaQ&c=uilaK90D4TOVoH58JNXRgQ&r=Ie7_encNUsqxbSRbqbNgofw0ITcfE8JKfaUjIQhncGA&m=BvRi46sEMPR__KUw0U1URM0Eq0Lea_ZE0YYz9O71hWY&s=EKmb5XTawHwj4RTy4ZbncuYKs3jBTzYKO1SWbawHtbA&e=
> 



More information about the mesa-dev mailing list