From dea0d4d56326f148a42c766bdbaf1b5bb247cc59 Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Mon, 2 Feb 2009 16:33:08 -0700 Subject: 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. --- src/mesa/shader/slang/slang_link.c | 13 +++++++++++-- src/mesa/vbo/vbo_exec_api.c | 5 ++++- src/mesa/vbo/vbo_exec_draw.c | 13 +++++++++++++ src/mesa/vbo/vbo_save_draw.c | 18 +++++++++++++++++- 4 files changed, 45 insertions(+), 4 deletions(-) (limited to 'src/mesa') diff --git a/src/mesa/shader/slang/slang_link.c b/src/mesa/shader/slang/slang_link.c index c6d5cc0566..77bcda0871 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 d48f5230cb..f6daa253fd 100644 --- a/src/mesa/vbo/vbo_exec_api.c +++ b/src/mesa/vbo/vbo_exec_api.c @@ -148,11 +148,14 @@ 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. */ + 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 diff --git a/src/mesa/vbo/vbo_exec_draw.c b/src/mesa/vbo/vbo_exec_draw.c index 5b2e3550ca..7204aec1dc 100644 --- a/src/mesa/vbo/vbo_exec_draw.c +++ b/src/mesa/vbo/vbo_exec_draw.c @@ -175,7 +175,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 6fa3f1a7e4..7ee0a9a33f 100644 --- a/src/mesa/vbo/vbo_save_draw.c +++ b/src/mesa/vbo/vbo_save_draw.c @@ -110,6 +110,9 @@ static void vbo_bind_vertex_list( GLcontext *ctx, GLuint data = node->buffer_offset; const GLuint *map; GLuint attr; + 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. @@ -135,13 +138,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]; -- cgit v1.2.3