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.
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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];
|
||||
|
||||
|
||||
Reference in New Issue
Block a user