<div dir="auto"><div>Yes, it's the right thread and the right commit for radeonsi. All geometry is broken. I might revert it.</div><div dir="auto"><br></div><div dir="auto">Marek<br><br><div class="gmail_quote" dir="auto"><div dir="ltr">On Mon, Nov 26, 2018, 3:56 PM Erik Faye-Lund <<a href="mailto:erik.faye-lund@collabora.com">erik.faye-lund@collabora.com</a> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Uhm, what? Are you sure you're responding to the right email and<br>
linking the right commit? Because, well, this problem has been present<br>
here since Mesa 18.1, and that commit went in *today*... Also, it seems<br>
very unlikely for a GetTexImage-related commit to change the renndered<br>
*geometry*...<br>
<br>
On Mon, 2018-11-26 at 15:42 -0500, Marek Olšák wrote:<br>
> I have this issue on radeonsi as well, but the bad commit is:<br>
> <br>
> commit f1998e15ffccf260552bf559abe1a733a8ce990e<br>
> Author: Erik Faye-Lund <<a href="mailto:erik.faye-lund@collabora.com" target="_blank" rel="noreferrer">erik.faye-lund@collabora.com</a>><br>
> Date:   Wed Nov 21 20:09:46 2018 +0100<br>
> <br>
>     mesa/main: remove ARB suffix from glGetnTexImage<br>
>     <br>
>     This function has been core since OpenGL 4.3, so naming the<br>
>     implementation and reporting erros using an ARB-suffix can be<br>
>     confusing.<br>
>     <br>
>     Signed-off-by: Erik Faye-Lund <<a href="mailto:erik.faye-lund@collabora.com" target="_blank" rel="noreferrer">erik.faye-lund@collabora.com</a>><br>
>     Reviewed-by: Juan A. Suarez <<a href="mailto:jasuarez@igalia.com" target="_blank" rel="noreferrer">jasuarez@igalia.com</a>><br>
> <br>
> Reverting the commit fixes supertuxkart.<br>
> <br>
> Marek<br>
> <br>
> On Mon, Nov 26, 2018 at 1:40 PM Erik Faye-Lund <<br>
> <a href="mailto:erik.faye-lund@collabora.com" target="_blank" rel="noreferrer">erik.faye-lund@collabora.com</a>> wrote:<br>
> > On Mon, 2018-05-07 at 08:14 +0200, <a href="mailto:Mathias.Froehlich@gmx.net" target="_blank" rel="noreferrer">Mathias.Froehlich@gmx.net</a> wrote:<br>
> > > From: Mathias Fröhlich <<a href="mailto:mathias.froehlich@web.de" target="_blank" rel="noreferrer">mathias.froehlich@web.de</a>><br>
> > > <br>
> > > Finally make use of the binding information in the VAO when<br>
> > > setting up arrays for draw.<br>
> > > <br>
> > > v2: Emit less relocations also for interleaved userspace arrays.<br>
> > > <br>
> > > Signed-off-by: Mathias Fröhlich <<a href="mailto:Mathias.Froehlich@web.de" target="_blank" rel="noreferrer">Mathias.Froehlich@web.de</a>><br>
> > <br>
> > I know this is *very* late notice, but this commit broke Super Tux<br>
> > Kart<br>
> > on VirGL. Both the player-models as as well as the level data<br>
> > renders<br>
> > with gibberish vertex positions since this commit.<br>
> > <br>
> > The fix that Rob Clark did on top does not fix the problem (and<br>
> > shouldn't have; VirGL doesn't use NIR).<br>
> > <br>
> > > ---<br>
> > >  src/mesa/state_tracker/st_atom_array.c | 432 ++++++++-----------<br>
> > ----<br>
> > > ----------<br>
> > >  1 file changed, 107 insertions(+), 325 deletions(-)<br>
> > > <br>
> > > diff --git a/src/mesa/state_tracker/st_atom_array.c<br>
> > > b/src/mesa/state_tracker/st_atom_array.c<br>
> > > index 2fd67e8d84..6b39b4186d 100644<br>
> > > --- a/src/mesa/state_tracker/st_atom_array.c<br>
> > > +++ b/src/mesa/state_tracker/st_atom_array.c<br>
> > > @@ -48,6 +48,7 @@<br>
> > >  #include "main/bufferobj.h"<br>
> > >  #include "main/glformats.h"<br>
> > >  #include "main/varray.h"<br>
> > > +#include "main/arrayobj.h"<br>
> > >  <br>
> > >  /* vertex_formats[gltype - GL_BYTE][integer*2 + normalized][size<br>
> > -<br>
> > > 1] */<br>
> > >  static const uint16_t vertex_formats[][4][4] = {<br>
> > > @@ -306,79 +307,6 @@ st_pipe_vertex_format(const struct<br>
> > > gl_array_attributes *attrib)<br>
> > >     return vertex_formats[type - GL_BYTE][index][size-1];<br>
> > >  }<br>
> > >  <br>
> > > -static const struct gl_vertex_array *<br>
> > > -get_client_array(const struct gl_vertex_array *arrays,<br>
> > > -                 unsigned mesaAttr)<br>
> > > -{<br>
> > > -   /* st_program uses 0xffffffff to denote a double placeholder<br>
> > > attribute */<br>
> > > -   if (mesaAttr == ST_DOUBLE_ATTRIB_PLACEHOLDER)<br>
> > > -      return NULL;<br>
> > > -   return &arrays[mesaAttr];<br>
> > > -}<br>
> > > -<br>
> > > -/**<br>
> > > - * Examine the active arrays to determine if we have interleaved<br>
> > > - * vertex arrays all living in one VBO, or all living in user<br>
> > space.<br>
> > > - */<br>
> > > -static GLboolean<br>
> > > -is_interleaved_arrays(const struct st_vertex_program *vp,<br>
> > > -                      const struct gl_vertex_array *arrays,<br>
> > > -                      unsigned num_inputs)<br>
> > > -{<br>
> > > -   GLuint attr;<br>
> > > -   const struct gl_buffer_object *firstBufObj = NULL;<br>
> > > -   GLint firstStride = -1;<br>
> > > -   const GLubyte *firstPtr = NULL;<br>
> > > -   GLboolean userSpaceBuffer = GL_FALSE;<br>
> > > -<br>
> > > -   for (attr = 0; attr < num_inputs; attr++) {<br>
> > > -      const struct gl_vertex_array *array;<br>
> > > -      const struct gl_vertex_buffer_binding *binding;<br>
> > > -      const struct gl_array_attributes *attrib;<br>
> > > -      const GLubyte *ptr;<br>
> > > -      const struct gl_buffer_object *bufObj;<br>
> > > -      GLsizei stride;<br>
> > > -<br>
> > > -      array = get_client_array(arrays, vp-<br>
> > >index_to_input[attr]);<br>
> > > -      if (!array)<br>
> > > -      continue;<br>
> > > -<br>
> > > -      binding = array->BufferBinding;<br>
> > > -      attrib = array->VertexAttrib;<br>
> > > -      stride = binding->Stride; /* in bytes */<br>
> > > -      ptr = _mesa_vertex_attrib_address(attrib, binding);<br>
> > > -<br>
> > > -      /* To keep things simple, don't allow interleaved zero-<br>
> > stride<br>
> > > attribs. */<br>
> > > -      if (stride == 0)<br>
> > > -         return false;<br>
> > > -<br>
> > > -      bufObj = binding->BufferObj;<br>
> > > -      if (attr == 0) {<br>
> > > -         /* save info about the first array */<br>
> > > -         firstStride = stride;<br>
> > > -         firstPtr = ptr;<br>
> > > -         firstBufObj = bufObj;<br>
> > > -         userSpaceBuffer = !_mesa_is_bufferobj(bufObj);<br>
> > > -      }<br>
> > > -      else {<br>
> > > -         /* check if other arrays interleave with the first, in<br>
> > same<br>
> > > buffer */<br>
> > > -         if (stride != firstStride)<br>
> > > -            return GL_FALSE; /* strides don't match */<br>
> > > -<br>
> > > -         if (bufObj != firstBufObj)<br>
> > > -            return GL_FALSE; /* arrays in different VBOs */<br>
> > > -<br>
> > > -         if (llabs(ptr - firstPtr) > firstStride)<br>
> > > -            return GL_FALSE; /* arrays start too far apart */<br>
> > > -<br>
> > > -         if ((!_mesa_is_bufferobj(bufObj)) != userSpaceBuffer)<br>
> > > -            return GL_FALSE; /* mix of VBO and user-space arrays<br>
> > */<br>
> > > -      }<br>
> > > -   }<br>
> > > -<br>
> > > -   return GL_TRUE;<br>
> > > -}<br>
> > > -<br>
> > >  static void init_velement(struct pipe_vertex_element *velement,<br>
> > >                            int src_offset, int format,<br>
> > >                            int instance_divisor, int vbo_index)<br>
> > > @@ -392,13 +320,14 @@ static void init_velement(struct<br>
> > > pipe_vertex_element *velement,<br>
> > >  <br>
> > >  static void init_velement_lowered(const struct st_vertex_program<br>
> > > *vp,<br>
> > >                                    struct pipe_vertex_element<br>
> > > *velements,<br>
> > > -                                  int src_offset, int format,<br>
> > > -                                  int instance_divisor, int<br>
> > > vbo_index,<br>
> > > -                                  int nr_components, GLboolean<br>
> > > doubles,<br>
> > > -                                  GLuint *attr_idx)<br>
> > > +                                  const struct<br>
> > gl_array_attributes<br>
> > > *attrib,<br>
> > > +                                  int src_offset, int<br>
> > > instance_divisor,<br>
> > > +                                  int vbo_index, int idx)<br>
> > >  {<br>
> > > -   int idx = *attr_idx;<br>
> > > -   if (doubles) {<br>
> > > +   const unsigned format = st_pipe_vertex_format(attrib);<br>
> > > +   const GLubyte nr_components = attrib->Size;<br>
> > > +<br>
> > > +   if (attrib->Doubles) {<br>
> > >        int lower_format;<br>
> > >  <br>
> > >        if (nr_components < 2)<br>
> > > @@ -427,15 +356,11 @@ static void init_velement_lowered(const<br>
> > struct<br>
> > > st_vertex_program *vp,<br>
> > >              init_velement(&velements[idx], src_offset,<br>
> > > PIPE_FORMAT_R32G32_UINT,<br>
> > >                            instance_divisor, vbo_index);<br>
> > >           }<br>
> > > -<br>
> > > -         idx++;<br>
> > >        }<br>
> > >     } else {<br>
> > >        init_velement(&velements[idx], src_offset,<br>
> > >                      format, instance_divisor, vbo_index);<br>
> > > -      idx++;<br>
> > >     }<br>
> > > -   *attr_idx = idx;<br>
> > >  }<br>
> > >  <br>
> > >  static void<br>
> > > @@ -457,274 +382,131 @@ set_vertex_attribs(struct st_context *st,<br>
> > >     cso_set_vertex_elements(cso, num_velements, velements);<br>
> > >  }<br>
> > >  <br>
> > > -/**<br>
> > > - * Set up for drawing interleaved arrays that all live in one<br>
> > VBO<br>
> > > - * or all live in user space.<br>
> > > - * \param vbuffer  returns vertex buffer info<br>
> > > - * \param velements  returns vertex element info<br>
> > > - */<br>
> > > -static void<br>
> > > -setup_interleaved_attribs(struct st_context *st,<br>
> > > -                          const struct st_vertex_program *vp,<br>
> > > -                          const struct gl_vertex_array *arrays,<br>
> > > -                          unsigned num_inputs)<br>
> > > -{<br>
> > > -   struct pipe_vertex_buffer vbuffer;<br>
> > > -   struct pipe_vertex_element velements[PIPE_MAX_ATTRIBS] =<br>
> > {{0}};<br>
> > > -   GLuint attr;<br>
> > > -   const GLubyte *low_addr = NULL;<br>
> > > -   GLboolean usingVBO;      /* all arrays in a VBO? */<br>
> > > -   struct gl_buffer_object *bufobj;<br>
> > > -   GLsizei stride;<br>
> > > -<br>
> > > -   /* Find the lowest address of the arrays we're drawing,<br>
> > > -    * Init bufobj and stride.<br>
> > > -    */<br>
> > > -   if (num_inputs) {<br>
> > > -      const struct gl_vertex_array *array;<br>
> > > -      const struct gl_vertex_buffer_binding *binding;<br>
> > > -      const struct gl_array_attributes *attrib;<br>
> > > -<br>
> > > -      array = get_client_array(arrays, vp->index_to_input[0]);<br>
> > > -      assert(array);<br>
> > > -<br>
> > > -      binding = array->BufferBinding;<br>
> > > -      attrib = array->VertexAttrib;<br>
> > > -<br>
> > > -      /* Since we're doing interleaved arrays, we know there'll<br>
> > be<br>
> > > at most<br>
> > > -       * one buffer object and the stride will be the same for<br>
> > all<br>
> > > arrays.<br>
> > > -       * Grab them now.<br>
> > > -       */<br>
> > > -      bufobj = binding->BufferObj;<br>
> > > -      stride = binding->Stride;<br>
> > > -<br>
> > > -      low_addr = _mesa_vertex_attrib_address(attrib, binding);<br>
> > > -<br>
> > > -      for (attr = 1; attr < num_inputs; attr++) {<br>
> > > -         const GLubyte *start;<br>
> > > -         array = get_client_array(arrays, vp-<br>
> > >index_to_input[attr]);<br>
> > > -         if (!array)<br>
> > > -            continue;<br>
> > > -         binding = array->BufferBinding;<br>
> > > -         attrib = array->VertexAttrib;<br>
> > > -         start = _mesa_vertex_attrib_address(attrib, binding);<br>
> > > -         low_addr = MIN2(low_addr, start);<br>
> > > -      }<br>
> > > -   }<br>
> > > -   else {<br>
> > > -      /* not sure we'll ever have zero inputs, but play it safe<br>
> > */<br>
> > > -      bufobj = NULL;<br>
> > > -      stride = 0;<br>
> > > -      low_addr = 0;<br>
> > > -   }<br>
> > > -<br>
> > > -   /* are the arrays in user space? */<br>
> > > -   usingVBO = _mesa_is_bufferobj(bufobj);<br>
> > > -<br>
> > > -   for (attr = 0; attr < num_inputs;) {<br>
> > > -      const struct gl_vertex_array *array;<br>
> > > -      const struct gl_vertex_buffer_binding *binding;<br>
> > > -      const struct gl_array_attributes *attrib;<br>
> > > -      const GLubyte *ptr;<br>
> > > -      unsigned src_offset;<br>
> > > -      unsigned src_format;<br>
> > > -<br>
> > > -      array = get_client_array(arrays, vp-<br>
> > >index_to_input[attr]);<br>
> > > -      assert(array);<br>
> > > -<br>
> > > -      binding = array->BufferBinding;<br>
> > > -      attrib = array->VertexAttrib;<br>
> > > -      ptr = _mesa_vertex_attrib_address(attrib, binding);<br>
> > > -<br>
> > > -      src_offset = (unsigned) (ptr - low_addr);<br>
> > > -<br>
> > > -      src_format = st_pipe_vertex_format(attrib);<br>
> > > -<br>
> > > -      init_velement_lowered(vp, velements, src_offset,<br>
> > src_format,<br>
> > > -                            binding->InstanceDivisor, 0,<br>
> > > -                            attrib->Size, attrib->Doubles,<br>
> > &attr);<br>
> > > -   }<br>
> > > -<br>
> > > -   /*<br>
> > > -    * Return the vbuffer info and setup user-space attrib info,<br>
> > if<br>
> > > needed.<br>
> > > -    */<br>
> > > -   if (num_inputs == 0) {<br>
> > > -      /* just defensive coding here */<br>
> > > -      vbuffer.buffer.resource = NULL;<br>
> > > -      vbuffer.is_user_buffer = false;<br>
> > > -      vbuffer.buffer_offset = 0;<br>
> > > -      vbuffer.stride = 0;<br>
> > > -   }<br>
> > > -   else if (usingVBO) {<br>
> > > -      /* all interleaved arrays in a VBO */<br>
> > > -      struct st_buffer_object *stobj = st_buffer_object(bufobj);<br>
> > > -<br>
> > > -      if (!stobj || !stobj->buffer) {<br>
> > > -         st->vertex_array_out_of_memory = true;<br>
> > > -         return; /* out-of-memory error probably */<br>
> > > -      }<br>
> > > -<br>
> > > -      vbuffer.buffer.resource = stobj->buffer;<br>
> > > -      vbuffer.is_user_buffer = false;<br>
> > > -      vbuffer.buffer_offset = pointer_to_offset(low_addr);<br>
> > > -      vbuffer.stride = stride;<br>
> > > -   }<br>
> > > -   else {<br>
> > > -      /* all interleaved arrays in user memory */<br>
> > > -      vbuffer.buffer.user = low_addr;<br>
> > > -      vbuffer.is_user_buffer = !!low_addr; /* if NULL, then<br>
> > unbind<br>
> > > */<br>
> > > -      vbuffer.buffer_offset = 0;<br>
> > > -      vbuffer.stride = stride;<br>
> > > -<br>
> > > -      if (low_addr)<br>
> > > -         st->draw_needs_minmax_index = true;<br>
> > > -   }<br>
> > > -<br>
> > > -   set_vertex_attribs(st, &vbuffer, num_inputs ? 1 : 0,<br>
> > > -                      velements, num_inputs);<br>
> > > -}<br>
> > > -<br>
> > > -/**<br>
> > > - * Set up a separate pipe_vertex_buffer and pipe_vertex_element<br>
> > for<br>
> > > each<br>
> > > - * vertex attribute.<br>
> > > - * \param vbuffer  returns vertex buffer info<br>
> > > - * \param velements  returns vertex element info<br>
> > > - */<br>
> > > -static void<br>
> > > -setup_non_interleaved_attribs(struct st_context *st,<br>
> > > -                              const struct st_vertex_program<br>
> > *vp,<br>
> > > -                              const struct gl_vertex_array<br>
> > *arrays,<br>
> > > -                              unsigned num_inputs)<br>
> > > +void st_update_array(struct st_context *st)<br>
> > >  {<br>
> > >     struct gl_context *ctx = st->ctx;<br>
> > > +   /* vertex program validation must be done before this */<br>
> > > +   const struct st_vertex_program *vp = st->vp;<br>
> > > +   /* _NEW_PROGRAM, ST_NEW_VS_STATE */<br>
> > > +   const GLbitfield inputs_read = st->vp_variant-<br>
> > >vert_attrib_mask;<br>
> > > +   const struct gl_vertex_array_object *vao = ctx-<br>
> > >Array._DrawVAO;<br>
> > > +   const ubyte *input_to_index = vp->input_to_index;<br>
> > > +<br>
> > >     struct pipe_vertex_buffer vbuffer[PIPE_MAX_ATTRIBS];<br>
> > > -   struct pipe_vertex_element velements[PIPE_MAX_ATTRIBS] =<br>
> > {{0}};<br>
> > > +   struct pipe_vertex_element velements[PIPE_MAX_ATTRIBS];<br>
> > >     unsigned num_vbuffers = 0;<br>
> > > -   unsigned unref_buffers = 0;<br>
> > > -   GLuint attr;<br>
> > > -<br>
> > > -   for (attr = 0; attr < num_inputs;) {<br>
> > > -      const unsigned mesaAttr = vp->index_to_input[attr];<br>
> > > -      const struct gl_vertex_array *array;<br>
> > > -      const struct gl_vertex_buffer_binding *binding;<br>
> > > -      const struct gl_array_attributes *attrib;<br>
> > > -      struct gl_buffer_object *bufobj;<br>
> > > -      GLsizei stride;<br>
> > > -      unsigned src_format;<br>
> > > -      unsigned bufidx;<br>
> > > -<br>
> > > -      array = get_client_array(arrays, mesaAttr);<br>
> > > -      assert(array);<br>
> > > -<br>
> > > -      bufidx = num_vbuffers++;<br>
> > > -<br>
> > > -      binding = array->BufferBinding;<br>
> > > -      attrib = array->VertexAttrib;<br>
> > > -      stride = binding->Stride;<br>
> > > -      bufobj = binding->BufferObj;<br>
> > > -<br>
> > > -      if (_mesa_is_bufferobj(bufobj)) {<br>
> > > -         /* Attribute data is in a VBO.<br>
> > > -          * Recall that for VBOs, the gl_vertex_array->Ptr field<br>
> > is<br>
> > > -          * really an offset from the start of the VBO, not a<br>
> > > pointer.<br>
> > > -          */<br>
> > > -         struct st_buffer_object *stobj =<br>
> > st_buffer_object(bufobj);<br>
> > >  <br>
> > > +   st->vertex_array_out_of_memory = FALSE;<br>
> > > +   st->draw_needs_minmax_index = false;<br>
> > > +<br>
> > > +   /* _NEW_PROGRAM */<br>
> > > +   /* ST_NEW_VERTEX_ARRAYS alias ctx->DriverFlags.NewArray */<br>
> > > +   /* Process attribute array data. */<br>
> > > +   GLbitfield mask = inputs_read & _mesa_draw_array_bits(ctx);<br>
> > > +   while (mask) {<br>
> > > +      /* The attribute index to start pulling a binding */<br>
> > > +      const gl_vert_attrib i = ffs(mask) - 1;<br>
> > > +      const struct gl_vertex_buffer_binding *const binding<br>
> > > +         = _mesa_draw_buffer_binding(vao, i);<br>
> > > +      const unsigned bufidx = num_vbuffers++;<br>
> > > +<br>
> > > +      if (_mesa_is_bufferobj(binding->BufferObj)) {<br>
> > > +         struct st_buffer_object *stobj =<br>
> > st_buffer_object(binding-<br>
> > > >BufferObj);<br>
> > >           if (!stobj || !stobj->buffer) {<br>
> > >              st->vertex_array_out_of_memory = true;<br>
> > >              return; /* out-of-memory error probably */<br>
> > >           }<br>
> > >  <br>
> > > +         /* Set the binding */<br>
> > >           vbuffer[bufidx].buffer.resource = stobj->buffer;<br>
> > >           vbuffer[bufidx].is_user_buffer = false;<br>
> > > -         vbuffer[bufidx].buffer_offset =<br>
> > > -            binding->Offset + attrib->RelativeOffset;<br>
> > > +         vbuffer[bufidx].buffer_offset =<br>
> > > _mesa_draw_binding_offset(binding);<br>
> > > +      } else {<br>
> > > +         /* Set the binding */<br>
> > > +         const void *ptr = (const void<br>
> > > *)_mesa_draw_binding_offset(binding);<br>
> > > +         vbuffer[bufidx].buffer.user = ptr;<br>
> > > +         vbuffer[bufidx].is_user_buffer = true;<br>
> > > +         vbuffer[bufidx].buffer_offset = 0;<br>
> > > +<br>
> > > +         if (!binding->InstanceDivisor)<br>
> > > +            st->draw_needs_minmax_index = true;<br>
> > >        }<br>
> > > -      else {<br>
> > > -         if (stride == 0) {<br>
> > > -            unsigned size = attrib->_ElementSize;<br>
> > > -            /* This is optimal for GPU cache line usage if the<br>
> > > upload size<br>
> > > -             * is <= cache line size.<br>
> > > -             */<br>
> > > -            unsigned alignment = util_next_power_of_two(size);<br>
> > > -<br>
> > > -            assert(attrib->Ptr);<br>
> > > -            vbuffer[bufidx].buffer.user = attrib->Ptr;<br>
> > > -            void *ptr = attrib->Ptr ? (void*)attrib->Ptr :<br>
> > > -                                      (void*)ctx-<br>
> > > >Current.Attrib[mesaAttr];<br>
> > > -<br>
> > > -            vbuffer[bufidx].is_user_buffer = false;<br>
> > > -            vbuffer[bufidx].buffer.resource = NULL;<br>
> > > -<br>
> > > -            /* Use const_uploader for zero-stride vertex<br>
> > attributes,<br>
> > > because<br>
> > > -             * it may use a better memory placement than<br>
> > > stream_uploader.<br>
> > > -             * The reason is that zero-stride attributes can be<br>
> > > fetched many<br>
> > > -             * times (thousands of times), so a better placement<br>
> > is<br>
> > > going to<br>
> > > -             * perform better.<br>
> > > -             *<br>
> > > -             * Upload the maximum possible size, which is 4x<br>
> > > GLdouble = 32.<br>
> > > -             */<br>
> > > -            u_upload_data(st->can_bind_const_buffer_as_vertex ?<br>
> > > -                             st->pipe->const_uploader :<br>
> > > -                             st->pipe->stream_uploader,<br>
> > > -                          0, size, alignment, ptr,<br>
> > > -                          &vbuffer[bufidx].buffer_offset,<br>
> > > -                          &vbuffer[bufidx].buffer.resource);<br>
> > > -            unref_buffers |= 1u << bufidx;<br>
> > > -         } else {<br>
> > > -            assert(attrib->Ptr);<br>
> > > -            vbuffer[bufidx].buffer.user = attrib->Ptr;<br>
> > > -            vbuffer[bufidx].is_user_buffer = true;<br>
> > > -            vbuffer[bufidx].buffer_offset = 0;<br>
> > > -<br>
> > > -            if (!binding->InstanceDivisor)<br>
> > > -               st->draw_needs_minmax_index = true;<br>
> > > -         }<br>
> > > +      vbuffer[bufidx].stride = binding->Stride; /* in bytes */<br>
> > > +<br>
> > > +      const GLbitfield boundmask =<br>
> > > _mesa_draw_bound_attrib_bits(binding);<br>
> > > +      GLbitfield attrmask = mask & boundmask;<br>
> > > +      /* Mark the those attributes as processed */<br>
> > > +      mask &= ~boundmask;<br>
> > > +      /* We can assume that we have array for the binding */<br>
> > > +      assert(attrmask);<br>
> > > +      /* Walk attributes belonging to the binding */<br>
> > > +      while (attrmask) {<br>
> > > +         const gl_vert_attrib attr = u_bit_scan(&attrmask);<br>
> > > +         const struct gl_array_attributes *const attrib<br>
> > > +            = _mesa_draw_array_attrib(vao, attr);<br>
> > > +         const GLuint off =<br>
> > > _mesa_draw_attributes_relative_offset(attrib);<br>
> > > +         init_velement_lowered(vp, velements, attrib, off,<br>
> > > +                               binding->InstanceDivisor, bufidx,<br>
> > > +                               input_to_index[attr]);<br>
> > >        }<br>
> > > +   }<br>
> > >  <br>
> > > -      /* common-case setup */<br>
> > > -      vbuffer[bufidx].stride = stride; /* in bytes */<br>
> > > +   const unsigned first_current_vbuffer = num_vbuffers;<br>
> > > +   /* _NEW_PROGRAM | _NEW_CURRENT_ATTRIB */<br>
> > > +   /* Process values that should have better been uniforms in<br>
> > the<br>
> > > application */<br>
> > > +   GLbitfield curmask = inputs_read &<br>
> > _mesa_draw_current_bits(ctx);<br>
> > > +   if (curmask) {<br>
> > > +      /* For each attribute, upload the maximum possible size.<br>
> > */<br>
> > > +      GLubyte data[VERT_ATTRIB_MAX*sizeof(GLdouble)*4];<br>
> > > +      GLubyte *cursor = data;<br>
> > > +      const unsigned bufidx = num_vbuffers++;<br>
> > > +      unsigned max_alignment = 1;<br>
> > > +<br>
> > > +      while (curmask) {<br>
> > > +         const gl_vert_attrib attr = u_bit_scan(&curmask);<br>
> > > +         const struct gl_array_attributes *const attrib<br>
> > > +            = _mesa_draw_current_attrib(ctx, attr);<br>
> > > +         const unsigned size = attrib->_ElementSize;<br>
> > > +         const unsigned alignment =<br>
> > util_next_power_of_two(size);<br>
> > > +         max_alignment = MAX2(max_alignment, alignment);<br>
> > > +         memcpy(cursor, attrib->Ptr, size);<br>
> > > +         if (alignment != size)<br>
> > > +            memset(cursor + size, 0, alignment - size);<br>
> > > +<br>
> > > +         init_velement_lowered(vp, velements, attrib, cursor -<br>
> > data,<br>
> > > 0,<br>
> > > +                               bufidx, input_to_index[attr]);<br>
> > > +<br>
> > > +         cursor += alignment;<br>
> > > +      }<br>
> > >  <br>
> > > -      src_format = st_pipe_vertex_format(attrib);<br>
> > > +      vbuffer[bufidx].is_user_buffer = false;<br>
> > > +      vbuffer[bufidx].buffer.resource = NULL;<br>
> > > +      /* vbuffer[bufidx].buffer_offset is set below */<br>
> > > +      vbuffer[bufidx].stride = 0;<br>
> > >  <br>
> > > -      init_velement_lowered(vp, velements, 0, src_format,<br>
> > > -                            binding->InstanceDivisor, bufidx,<br>
> > > -                            attrib->Size, attrib->Doubles,<br>
> > &attr);<br>
> > > +      /* Use const_uploader for zero-stride vertex attributes,<br>
> > > because<br>
> > > +       * it may use a better memory placement than<br>
> > stream_uploader.<br>
> > > +       * The reason is that zero-stride attributes can be<br>
> > fetched<br>
> > > many<br>
> > > +       * times (thousands of times), so a better placement is<br>
> > going<br>
> > > to<br>
> > > +       * perform better.<br>
> > > +       */<br>
> > > +      u_upload_data(st->can_bind_const_buffer_as_vertex ?<br>
> > > +                    st->pipe->const_uploader :<br>
> > > +                    st->pipe->stream_uploader,<br>
> > > +                    0, cursor - data, max_alignment, data,<br>
> > > +                    &vbuffer[bufidx].buffer_offset,<br>
> > > +                    &vbuffer[bufidx].buffer.resource);<br>
> > >     }<br>
> > >  <br>
> > >     if (!ctx->Const.AllowMappedBuffersDuringExecution) {<br>
> > >        u_upload_unmap(st->pipe->stream_uploader);<br>
> > >     }<br>
> > >  <br>
> > > +   const unsigned num_inputs = st->vp_variant->num_inputs;<br>
> > >     set_vertex_attribs(st, vbuffer, num_vbuffers, velements,<br>
> > > num_inputs);<br>
> > >  <br>
> > >     /* Unreference uploaded zero-stride vertex buffers. */<br>
> > > -   while (unref_buffers) {<br>
> > > -      unsigned i = u_bit_scan(&unref_buffers);<br>
> > > +   for (unsigned i = first_current_vbuffer; i < num_vbuffers;<br>
> > ++i) {<br>
> > >        pipe_resource_reference(&vbuffer[i].buffer.resource,<br>
> > NULL);<br>
> > >     }<br>
> > >  }<br>
> > > -<br>
> > > -void st_update_array(struct st_context *st)<br>
> > > -{<br>
> > > -   struct gl_context *ctx = st->ctx;<br>
> > > -   const struct gl_vertex_array *arrays = ctx-<br>
> > >Array._DrawArrays;<br>
> > > -   const struct st_vertex_program *vp;<br>
> > > -   unsigned num_inputs;<br>
> > > -<br>
> > > -   st->vertex_array_out_of_memory = FALSE;<br>
> > > -   st->draw_needs_minmax_index = false;<br>
> > > -<br>
> > > -   /* No drawing has been done yet, so do nothing. */<br>
> > > -   if (!arrays)<br>
> > > -      return;<br>
> > > -<br>
> > > -   /* vertex program validation must be done before this */<br>
> > > -   vp = st->vp;<br>
> > > -   num_inputs = st->vp_variant->num_inputs;<br>
> > > -<br>
> > > -   if (is_interleaved_arrays(vp, arrays, num_inputs))<br>
> > > -      setup_interleaved_attribs(st, vp, arrays, num_inputs);<br>
> > > -   else<br>
> > > -      setup_non_interleaved_attribs(st, vp, arrays, num_inputs);<br>
> > > -}<br>
> > <br>
> > _______________________________________________<br>
> > mesa-dev mailing list<br>
> > <a href="mailto:mesa-dev@lists.freedesktop.org" target="_blank" rel="noreferrer">mesa-dev@lists.freedesktop.org</a><br>
> > <a href="https://lists.freedesktop.org/mailman/listinfo/mesa-dev" rel="noreferrer noreferrer" target="_blank">https://lists.freedesktop.org/mailman/listinfo/mesa-dev</a><br>
<br>
</blockquote></div></div></div>