glsl: do extra link checking for transform feedback

This commit is contained in:
Brian Paul 2010-04-01 22:15:17 -06:00
parent 50a75a0b4a
commit 107c72f355

View file

@ -90,8 +90,7 @@ bits_agree(GLbitfield flags1, GLbitfield flags2, GLbitfield bit)
* Examine the outputs/varyings written by the vertex shader and
* append the names of those outputs onto the Varyings list.
* This will only capture the pre-defined/built-in varyings like
* gl_Position, not user-defined varyings. The later should already
* be in the varying vars list.
* gl_Position, not user-defined varyings.
*/
static void
update_varying_var_list(GLcontext *ctx, struct gl_shader_program *shProg)
@ -111,6 +110,83 @@ update_varying_var_list(GLcontext *ctx, struct gl_shader_program *shProg)
}
/**
* Do link error checking related to transform feedback.
*/
static GLboolean
link_transform_feedback(GLcontext *ctx, struct gl_shader_program *shProg)
{
GLbitfield varyingMask;
GLuint totalComps, maxComps, i;
if (shProg->TransformFeedback.NumVarying == 0) {
/* nothing to do */
return GL_FALSE;
}
/* Check that there's a vertex shader */
if (shProg->TransformFeedback.NumVarying > 0 &&
!shProg->VertexProgram) {
link_error(shProg, "Transform feedback without vertex shader");
return GL_FALSE;
}
/* Check that all named variables exist, and that none are duplicated.
* Also, build a count of the number of varying components to feedback.
*/
totalComps = 0;
varyingMask = 0x0;
for (i = 0; i < shProg->TransformFeedback.NumVarying; i++) {
const GLchar *name = shProg->TransformFeedback.VaryingNames[i];
GLint v = _mesa_lookup_parameter_index(shProg->Varying, -1, name);
struct gl_program_parameter *p;
if (v < 0) {
char msg[100];
_mesa_snprintf(msg, sizeof(msg),
"vertex shader does not emit %s", name);
link_error(shProg, msg);
return GL_FALSE;
}
assert(v < MAX_VARYING);
/* already seen this varying name? */
if (varyingMask & (1 << v)) {
char msg[100];
_mesa_snprintf(msg, sizeof(msg),
"duplicated transform feedback varying name: %s",
name);
link_error(shProg, msg);
return GL_FALSE;
}
varyingMask |= (1 << v);
p = &shProg->Varying->Parameters[v];
totalComps += _mesa_sizeof_glsl_type(p->DataType);
}
if (shProg->TransformFeedback.BufferMode == GL_INTERLEAVED_ATTRIBS)
maxComps = ctx->Const.MaxTransformFeedbackInterleavedComponents;
else
maxComps = ctx->Const.MaxTransformFeedbackSeparateComponents;
/* check max varying components against the limit */
if (totalComps > maxComps) {
char msg[100];
_mesa_snprintf(msg, sizeof(msg),
"Too many feedback components: %u, max is %u",
totalComps, maxComps);
link_error(shProg, msg);
return GL_FALSE;
}
return GL_TRUE;
}
/**
* Linking varying vars involves rearranging varying vars so that the
* vertex program's output varyings matches the order of the fragment
@ -891,9 +967,13 @@ _slang_link(GLcontext *ctx,
}
}
/* Append built-in, used varyings to the varying var list */
update_varying_var_list(ctx, shProg);
/* checks related to transform feedback */
if (!link_transform_feedback(ctx, shProg)) {
return;
}
if (fragProg && shProg->FragmentProgram) {
/* Compute initial program's TexturesUsed info */
_mesa_update_shader_textures_used(&shProg->FragmentProgram->Base);