Mesa (master): st/mesa: fix vertex elements setup for doubles

Nicolai Hähnle nh at kemper.freedesktop.org
Thu Oct 13 13:42:49 UTC 2016


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

Author: Nicolai Hähnle <nicolai.haehnle at amd.com>
Date:   Mon Oct 10 20:20:22 2016 +0200

st/mesa: fix vertex elements setup for doubles

Whether one or two slots are taken up by one API array depends on the
vertex shader, not on how the array is configured. When an array is
set up with fewer components than the shader expects, the high components
are undefined.

Fixes GL45-CTS.vertex_attrib_binding.basic-inputL-case1.

Cc: mesa-stable at lists.freedesktop.org
Reviewed-by: Dave Airlie <airlied at redhat.com>

---

 src/mesa/state_tracker/st_atom_array.c | 98 +++++++++++++++++-----------------
 1 file changed, 50 insertions(+), 48 deletions(-)

diff --git a/src/mesa/state_tracker/st_atom_array.c b/src/mesa/state_tracker/st_atom_array.c
index 1c2cfa7..e5b949f 100644
--- a/src/mesa/state_tracker/st_atom_array.c
+++ b/src/mesa/state_tracker/st_atom_array.c
@@ -386,6 +386,7 @@ static void init_velement(struct pipe_vertex_element *velement,
 }
 
 static void init_velement_lowered(struct st_context *st,
+                                  const struct st_vertex_program *vp,
                                   struct pipe_vertex_element *velements,
                                   int src_offset, int format,
                                   int instance_divisor, int vbo_index,
@@ -396,23 +397,33 @@ static void init_velement_lowered(struct st_context *st,
    if (doubles) {
       int lower_format;
 
-      if (nr_components == 1)
+      if (nr_components < 2)
          lower_format = PIPE_FORMAT_R32G32_UINT;
-      else if (nr_components >= 2)
+      else
          lower_format = PIPE_FORMAT_R32G32B32A32_UINT;
 
       init_velement(&velements[idx], src_offset,
                     lower_format, instance_divisor, vbo_index);
       idx++;
 
-      if (nr_components > 2) {
-         if (nr_components == 3)
-            lower_format = PIPE_FORMAT_R32G32_UINT;
-         else if (nr_components >= 4)
-            lower_format = PIPE_FORMAT_R32G32B32A32_UINT;
+      if (idx < vp->num_inputs &&
+          vp->index_to_input[idx] == ST_DOUBLE_ATTRIB_PLACEHOLDER) {
+         if (nr_components >= 3) {
+            if (nr_components == 3)
+               lower_format = PIPE_FORMAT_R32G32_UINT;
+            else
+               lower_format = PIPE_FORMAT_R32G32B32A32_UINT;
+
+            init_velement(&velements[idx], src_offset + 4 * sizeof(float),
+                        lower_format, instance_divisor, vbo_index);
+         } else {
+            /* The values here are undefined. Fill in some conservative
+             * dummy values.
+             */
+            init_velement(&velements[idx], src_offset, PIPE_FORMAT_R32G32_UINT,
+                          instance_divisor, vbo_index);
+         }
 
-         init_velement(&velements[idx], src_offset + 4 * sizeof(float),
-                       lower_format, instance_divisor, vbo_index);
          idx++;
       }
    } else {
@@ -435,10 +446,9 @@ setup_interleaved_attribs(struct st_context *st,
                           const struct st_vp_variant *vpv,
                           const struct gl_client_array **arrays,
                           struct pipe_vertex_buffer *vbuffer,
-                          struct pipe_vertex_element velements[],
-                          unsigned *num_velements)
+                          struct pipe_vertex_element velements[])
 {
-   GLuint attr, attr_idx;
+   GLuint attr;
    const GLubyte *low_addr = NULL;
    GLboolean usingVBO;      /* all arrays in a VBO? */
    struct gl_buffer_object *bufobj;
@@ -481,15 +491,13 @@ setup_interleaved_attribs(struct st_context *st,
    /* are the arrays in user space? */
    usingVBO = _mesa_is_bufferobj(bufobj);
 
-   attr_idx = 0;
-   for (attr = 0; attr < vpv->num_inputs; attr++) {
+   for (attr = 0; attr < vpv->num_inputs;) {
       const struct gl_client_array *array;
       unsigned src_offset;
       unsigned src_format;
 
       array = get_client_array(vp, arrays, attr);
-      if (!array)
-         continue;
+      assert(array);
 
       src_offset = (unsigned) (array->Ptr - low_addr);
       assert(array->_ElementSize ==
@@ -501,13 +509,11 @@ setup_interleaved_attribs(struct st_context *st,
                                          array->Normalized,
                                          array->Integer);
 
-      init_velement_lowered(st, velements, src_offset, src_format,
+      init_velement_lowered(st, vp, velements, src_offset, src_format,
                             array->InstanceDivisor, 0,
-                            array->Size, array->Doubles, &attr_idx);
+                            array->Size, array->Doubles, &attr);
    }
 
-   *num_velements = attr_idx;
-
    /*
     * Return the vbuffer info and setup user-space attrib info, if needed.
     */
@@ -554,25 +560,25 @@ setup_non_interleaved_attribs(struct st_context *st,
                               const struct gl_client_array **arrays,
                               struct pipe_vertex_buffer vbuffer[],
                               struct pipe_vertex_element velements[],
-                              unsigned *num_velements)
+                              unsigned *num_vbuffers)
 {
    struct gl_context *ctx = st->ctx;
-   GLuint attr, attr_idx = 0;
+   GLuint attr;
 
-   for (attr = 0; attr < vpv->num_inputs; attr++) {
+   *num_vbuffers = 0;
+
+   for (attr = 0; attr < vpv->num_inputs;) {
       const GLuint mesaAttr = vp->index_to_input[attr];
       const struct gl_client_array *array;
       struct gl_buffer_object *bufobj;
       GLsizei stride;
       unsigned src_format;
+      unsigned bufidx;
 
       array = get_client_array(vp, arrays, attr);
-      if (!array) {
-         vbuffer[attr].buffer = NULL;
-         vbuffer[attr].user_buffer = NULL;
-         vbuffer[attr].buffer_offset = 0;
-         continue;
-      }
+      assert(array);
+
+      bufidx = (*num_vbuffers)++;
 
       stride = array->StrideB;
       bufobj = array->BufferObj;
@@ -590,9 +596,9 @@ setup_non_interleaved_attribs(struct st_context *st,
             return FALSE; /* out-of-memory error probably */
          }
 
-         vbuffer[attr].buffer = stobj->buffer;
-         vbuffer[attr].user_buffer = NULL;
-         vbuffer[attr].buffer_offset = pointer_to_offset(array->Ptr);
+         vbuffer[bufidx].buffer = stobj->buffer;
+         vbuffer[bufidx].user_buffer = NULL;
+         vbuffer[bufidx].buffer_offset = pointer_to_offset(array->Ptr);
       }
       else {
          /* wrap user data */
@@ -609,13 +615,13 @@ setup_non_interleaved_attribs(struct st_context *st,
 
          assert(ptr);
 
-         vbuffer[attr].buffer = NULL;
-         vbuffer[attr].user_buffer = ptr;
-         vbuffer[attr].buffer_offset = 0;
+         vbuffer[bufidx].buffer = NULL;
+         vbuffer[bufidx].user_buffer = ptr;
+         vbuffer[bufidx].buffer_offset = 0;
       }
 
       /* common-case setup */
-      vbuffer[attr].stride = stride; /* in bytes */
+      vbuffer[bufidx].stride = stride; /* in bytes */
 
       src_format = st_pipe_vertex_format(array->Type,
                                          array->Size,
@@ -623,13 +629,11 @@ setup_non_interleaved_attribs(struct st_context *st,
                                          array->Normalized,
                                          array->Integer);
 
-      init_velement_lowered(st, velements, 0, src_format,
-                            array->InstanceDivisor, attr,
-                            array->Size, array->Doubles, &attr_idx);
-
+      init_velement_lowered(st, vp, velements, 0, src_format,
+                            array->InstanceDivisor, bufidx,
+                            array->Size, array->Doubles, &attr);
    }
 
-   *num_velements = attr_idx;
    return TRUE;
 }
 
@@ -641,7 +645,7 @@ static void update_array(struct st_context *st)
    const struct st_vp_variant *vpv;
    struct pipe_vertex_buffer vbuffer[PIPE_MAX_SHADER_INPUTS];
    struct pipe_vertex_element velements[PIPE_MAX_ATTRIBS];
-   unsigned num_vbuffers, num_velements;
+   unsigned num_vbuffers;
 
    st->vertex_array_out_of_memory = FALSE;
 
@@ -659,23 +663,21 @@ static void update_array(struct st_context *st)
     * Setup the vbuffer[] and velements[] arrays.
     */
    if (is_interleaved_arrays(vp, vpv, arrays)) {
-      if (!setup_interleaved_attribs(st, vp, vpv, arrays, vbuffer, velements, &num_velements)) {
+      if (!setup_interleaved_attribs(st, vp, vpv, arrays, vbuffer, velements)) {
          st->vertex_array_out_of_memory = TRUE;
          return;
       }
 
       num_vbuffers = 1;
-      if (num_velements == 0)
+      if (vpv->num_inputs == 0)
          num_vbuffers = 0;
    }
    else {
       if (!setup_non_interleaved_attribs(st, vp, vpv, arrays, vbuffer,
-                                         velements, &num_velements)) {
+                                         velements, &num_vbuffers)) {
          st->vertex_array_out_of_memory = TRUE;
          return;
       }
-
-      num_vbuffers = vpv->num_inputs;
    }
 
    cso_set_vertex_buffers(st->cso_context, 0, num_vbuffers, vbuffer);
@@ -685,7 +687,7 @@ static void update_array(struct st_context *st)
                              st->last_num_vbuffers - num_vbuffers, NULL);
    }
    st->last_num_vbuffers = num_vbuffers;
-   cso_set_vertex_elements(st->cso_context, num_velements, velements);
+   cso_set_vertex_elements(st->cso_context, vpv->num_inputs, velements);
 }
 
 




More information about the mesa-commit mailing list