Mesa (gallium-mesa-7.4): mesa: fix GLSL issue preventing use of all 16 generic vertex attributes

Alan Hourihane alanh at kemper.freedesktop.org
Fri Feb 20 01:30:24 UTC 2009


Module: Mesa
Branch: gallium-mesa-7.4
Commit: d3deab01e8d3f096974b1f9bee5b1c7280d67dc5
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=d3deab01e8d3f096974b1f9bee5b1c7280d67dc5

Author: Brian Paul <brianp at vmware.com>
Date:   Thu Feb 19 17:01:17 2009 -0700

mesa: fix GLSL issue preventing use of all 16 generic vertex attributes

Only 15 actually worked before since we always reserved generic[0] as an
alias for vertex position.

The case of vertex attribute 0 is tricky.  The spec says that there is no
aliasing between generic vertex attributes 0..MAX_VERTEX_ATTRIBS-1 and the
conventional attributes.  But it also says that calls to glVertexAttrib(0, v)
are equivalent to glVertex(v).  The distinction seems to be in glVertex-mode
versus vertex array mode.

So update the VBO code so that if the shader uses generic[0] but not gl_Vertex,
route the attribute data set with glVertex() to go to shader input generic[0].

No change needed for the glDrawArrays/Elements() path.

This is a potentially risky change so regressions are possible.  All the usual
tests seem OK though.

(cherry picked from mesa, commit dea0d4d56326f148a42c766bdbaf1b5bb247cc59)

Follow-up: This patch doesn't seem to be as risky as noted above.
There have been no known regressions on Mesa/master because of it.

---

 src/mesa/shader/slang/slang_link.c |   13 ++++++++-
 src/mesa/vbo/vbo_exec_api.c        |   49 +++++++++++++++--------------------
 src/mesa/vbo/vbo_exec_draw.c       |   13 +++++++++
 src/mesa/vbo/vbo_save_draw.c       |   19 ++++++++++++-
 4 files changed, 62 insertions(+), 32 deletions(-)

diff --git a/src/mesa/shader/slang/slang_link.c b/src/mesa/shader/slang/slang_link.c
index 28a0d0c..585ee84 100644
--- a/src/mesa/shader/slang/slang_link.c
+++ b/src/mesa/shader/slang/slang_link.c
@@ -318,7 +318,7 @@ _slang_resolve_attributes(struct gl_shader_program *shProg,
 {
    GLint attribMap[MAX_VERTEX_ATTRIBS];
    GLuint i, j;
-   GLbitfield usedAttributes;
+   GLbitfield usedAttributes; /* generics only, not legacy attributes */
 
    assert(origProg != linkedProg);
    assert(origProg->Target == GL_VERTEX_PROGRAM_ARB);
@@ -342,6 +342,15 @@ _slang_resolve_attributes(struct gl_shader_program *shProg,
       usedAttributes |= (1 << attr);
    }
 
+   /* If gl_Vertex is used, that actually counts against the limit
+    * on generic vertex attributes.  This avoids the ambiguity of
+    * whether glVertexAttrib4fv(0, v) sets legacy attribute 0 (vert pos)
+    * or generic attribute[0].  If gl_Vertex is used, we want the former.
+    */
+   if (origProg->InputsRead & VERT_BIT_POS) {
+      usedAttributes |= 0x1;
+   }
+
    /* initialize the generic attribute map entries to -1 */
    for (i = 0; i < MAX_VERTEX_ATTRIBS; i++) {
       attribMap[i] = -1;
@@ -384,7 +393,7 @@ _slang_resolve_attributes(struct gl_shader_program *shProg,
                    * Start at 1 since generic attribute 0 always aliases
                    * glVertex/position.
                    */
-                  for (attr = 1; attr < MAX_VERTEX_ATTRIBS; attr++) {
+                  for (attr = 0; attr < MAX_VERTEX_ATTRIBS; attr++) {
                      if (((1 << attr) & usedAttributes) == 0)
                         break;
                   }
diff --git a/src/mesa/vbo/vbo_exec_api.c b/src/mesa/vbo/vbo_exec_api.c
index a6ce26f..84e9b40 100644
--- a/src/mesa/vbo/vbo_exec_api.c
+++ b/src/mesa/vbo/vbo_exec_api.c
@@ -146,34 +146,27 @@ static void vbo_exec_copy_to_current( struct vbo_exec_context *exec )
          /* Note: the exec->vtx.current[i] pointers point into the
           * ctx->Current.Attrib and ctx->Light.Material.Attrib arrays.
           */
-	 GLfloat *current = (GLfloat *)vbo->currval[i].Ptr;
-         GLfloat tmp[4];
-
-         COPY_CLEAN_4V(tmp, 
-                       exec->vtx.attrsz[i], 
-                       exec->vtx.attrptr[i]);
-         
-         if (memcmp(current, tmp, sizeof(tmp)) != 0)
-         { 
-            memcpy(current, tmp, sizeof(tmp));
-
-	 
-            /* Given that we explicitly state size here, there is no need
-             * for the COPY_CLEAN above, could just copy 16 bytes and be
-             * done.  The only problem is when Mesa accesses ctx->Current
-             * directly.
-             */
-            vbo->currval[i].Size = exec->vtx.attrsz[i];
-
-            /* This triggers rather too much recalculation of Mesa state
-             * that doesn't get used (eg light positions).
-             */
-            if (i >= VBO_ATTRIB_MAT_FRONT_AMBIENT &&
-                i <= VBO_ATTRIB_MAT_BACK_INDEXES)
-               ctx->NewState |= _NEW_LIGHT;
-            
-            ctx->NewState |= _NEW_CURRENT_ATTRIB;
-         }
+         if (exec->vtx.attrptr[i]) {
+
+	 COPY_CLEAN_4V(current, 
+		       exec->vtx.attrsz[i], 
+		       exec->vtx.attrptr[i]);
+
+	 }
+
+	 /* Given that we explicitly state size here, there is no need
+	  * for the COPY_CLEAN above, could just copy 16 bytes and be
+	  * done.  The only problem is when Mesa accesses ctx->Current
+	  * directly.
+	  */
+	 vbo->currval[i].Size = exec->vtx.attrsz[i];
+
+	 /* This triggers rather too much recalculation of Mesa state
+	  * that doesn't get used (eg light positions).
+	  */
+	 if (i >= VBO_ATTRIB_MAT_FRONT_AMBIENT &&
+	     i <= VBO_ATTRIB_MAT_BACK_INDEXES)
+	    ctx->NewState |= _NEW_LIGHT;
       }
    }
 
diff --git a/src/mesa/vbo/vbo_exec_draw.c b/src/mesa/vbo/vbo_exec_draw.c
index 5bf3d83..2c8183d 100644
--- a/src/mesa/vbo/vbo_exec_draw.c
+++ b/src/mesa/vbo/vbo_exec_draw.c
@@ -176,7 +176,20 @@ static void vbo_exec_bind_arrays( GLcontext *ctx )
          exec->vtx.inputs[attr + 16] = &vbo->generic_currval[attr];
       }
       map = vbo->map_vp_arb;
+
+      /* 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.
+       */
+      if ((ctx->VertexProgram._Current->Base.InputsRead & VERT_BIT_POS) == 0 &&
+          (ctx->VertexProgram._Current->Base.InputsRead & VERT_BIT_GENERIC0)) {
+         exec->vtx.inputs[16] = exec->vtx.inputs[0];
+         exec->vtx.attrsz[16] = exec->vtx.attrsz[0];
+         exec->vtx.attrsz[0] = 0;
+      }
       break;
+   default:
+      assert(0);
    }
 
    /* Make all active attributes (including edgeflag) available as
diff --git a/src/mesa/vbo/vbo_save_draw.c b/src/mesa/vbo/vbo_save_draw.c
index 0488c5d..3c1b6d4 100644
--- a/src/mesa/vbo/vbo_save_draw.c
+++ b/src/mesa/vbo/vbo_save_draw.c
@@ -118,7 +118,9 @@ static void vbo_bind_vertex_list( GLcontext *ctx,
    GLuint data = node->buffer_offset;
    const GLuint *map;
    GLuint attr;
-   GLbitfield varying_inputs = 0x0;
+   GLubyte node_attrsz[VBO_ATTRIB_MAX];  /* copy of node->attrsz[] */
+
+   memcpy(node_attrsz, node->attrsz, sizeof(node->attrsz));
 
    /* Install the default (ie Current) attributes first, then overlay
     * all active ones.
@@ -144,13 +146,26 @@ static void vbo_bind_vertex_list( GLcontext *ctx,
          save->inputs[attr + 16] = &vbo->generic_currval[attr];
       }
       map = vbo->map_vp_arb;
+
+      /* 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.
+       */
+      if ((ctx->VertexProgram._Current->Base.InputsRead & VERT_BIT_POS) == 0 &&
+          (ctx->VertexProgram._Current->Base.InputsRead & VERT_BIT_GENERIC0)) {
+         save->inputs[16] = save->inputs[0];
+         node_attrsz[16] = node_attrsz[0];
+         node_attrsz[0] = 0;
+      }
       break;
+   default:
+      assert(0);
    }
 
    for (attr = 0; attr < VERT_ATTRIB_MAX; attr++) {
       GLuint src = map[attr];
 
-      if (node->attrsz[src]) {
+      if (node_attrsz[src]) {
          /* override the default array set above */
          save->inputs[attr] = &arrays[attr];
 




More information about the mesa-commit mailing list