Commit 42305fb5 authored by Ian Romanick's avatar Ian Romanick

glsl: Count shader inputs and outputs separately

Starting with OpenGL 3.2 input limits and output limits for stages may
not match.  This means they need to be accounted separately.

No piglit regressions.
Signed-off-by: default avatarIan Romanick <ian.d.romanick@intel.com>
Reviewed-by: default avatarBrian Paul <brianp@vmware.com>
Reviewed-by: default avatarMarek Olšák <marek.olsak@amd.com>
Reviewed-by: default avatarPaul Berry <stereotype441@gmail.com>
parent d4b5bc62
......@@ -1220,39 +1220,98 @@ assign_varying_locations(struct gl_context *ctx,
}
bool
check_against_varying_limit(struct gl_context *ctx,
struct gl_shader_program *prog,
gl_shader *consumer)
check_against_output_limit(struct gl_context *ctx,
struct gl_shader_program *prog,
gl_shader *producer)
{
unsigned varying_vectors = 0;
unsigned output_vectors = 0;
foreach_list(node, producer->ir) {
ir_variable *const var = ((ir_instruction *) node)->as_variable();
if (var && var->mode == ir_var_shader_out &&
is_varying_var(producer->Type, var)) {
output_vectors += var->type->count_attribute_slots();
}
}
unsigned max_output_components;
switch (producer->Type) {
case GL_VERTEX_SHADER:
max_output_components = ctx->Const.VertexProgram.MaxOutputComponents;
break;
case GL_GEOMETRY_SHADER:
max_output_components = ctx->Const.GeometryProgram.MaxOutputComponents;
break;
case GL_FRAGMENT_SHADER:
default:
assert(!"Should not get here.");
return false;
}
const unsigned output_components = output_vectors * 4;
if (output_components > max_output_components) {
if (ctx->API == API_OPENGLES2 || prog->IsES)
linker_error(prog, "shader uses too many output vectors "
"(%u > %u)\n",
output_vectors,
max_output_components / 4);
else
linker_error(prog, "shader uses too many output components "
"(%u > %u)\n",
output_components,
max_output_components);
return false;
}
return true;
}
bool
check_against_input_limit(struct gl_context *ctx,
struct gl_shader_program *prog,
gl_shader *consumer)
{
unsigned input_vectors = 0;
foreach_list(node, consumer->ir) {
ir_variable *const var = ((ir_instruction *) node)->as_variable();
if (var && var->mode == ir_var_shader_in &&
is_varying_var(consumer->Type, var)) {
/* The packing rules used for vertex shader inputs are also
* used for fragment shader inputs.
*/
varying_vectors += var->type->count_attribute_slots();
input_vectors += var->type->count_attribute_slots();
}
}
if (ctx->API == API_OPENGLES2 || prog->IsES) {
if (varying_vectors > ctx->Const.MaxVarying) {
linker_error(prog, "shader uses too many varying vectors "
unsigned max_input_components;
switch (consumer->Type) {
case GL_GEOMETRY_SHADER:
max_input_components = ctx->Const.GeometryProgram.MaxInputComponents;
break;
case GL_FRAGMENT_SHADER:
max_input_components = ctx->Const.FragmentProgram.MaxInputComponents;
break;
case GL_VERTEX_SHADER:
default:
assert(!"Should not get here.");
return false;
}
const unsigned input_components = input_vectors * 4;
if (input_components > max_input_components) {
if (ctx->API == API_OPENGLES2 || prog->IsES)
linker_error(prog, "shader uses too many input vectors "
"(%u > %u)\n",
varying_vectors, ctx->Const.MaxVarying);
return false;
}
} else {
const unsigned float_components = varying_vectors * 4;
if (float_components > ctx->Const.MaxVarying * 4) {
linker_error(prog, "shader uses too many varying components "
input_vectors,
max_input_components / 4);
else
linker_error(prog, "shader uses too many input components "
"(%u > %u)\n",
float_components, ctx->Const.MaxVarying * 4);
return false;
}
input_components,
max_input_components);
return false;
}
return true;
......
......@@ -237,8 +237,13 @@ assign_varying_locations(struct gl_context *ctx,
unsigned gs_input_vertices);
bool
check_against_varying_limit(struct gl_context *ctx,
struct gl_shader_program *prog,
gl_shader *consumer);
check_against_output_limit(struct gl_context *ctx,
struct gl_shader_program *prog,
gl_shader *producer);
bool
check_against_input_limit(struct gl_context *ctx,
struct gl_shader_program *prog,
gl_shader *consumer);
#endif /* GLSL_LINK_VARYINGS_H */
......@@ -2203,7 +2203,9 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
;
/* This must be done after all dead varyings are eliminated. */
if (!check_against_varying_limit(ctx, prog, sh_next))
if (!check_against_output_limit(ctx, prog, sh_i))
goto done;
if (!check_against_input_limit(ctx, prog, sh_next))
goto done;
next = i;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment