aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIan Romanick <[email protected]>2013-09-10 12:00:34 -0500
committerIan Romanick <[email protected]>2013-10-07 09:59:23 -0700
commit42305fb50256c12b8e7a516115e72ae7089ccd1b (patch)
tree5017a6d92aeba57f0351c88beecee51e4822a010
parentd4b5bc62af3e3e6652801bf1b6377fd46c11f59c (diff)
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: Ian Romanick <[email protected]> Reviewed-by: Brian Paul <[email protected]> Reviewed-by: Marek Olšák <[email protected]> Reviewed-by: Paul Berry <[email protected]>
-rw-r--r--src/glsl/link_varyings.cpp101
-rw-r--r--src/glsl/link_varyings.h11
-rw-r--r--src/glsl/linker.cpp4
3 files changed, 91 insertions, 25 deletions
diff --git a/src/glsl/link_varyings.cpp b/src/glsl/link_varyings.cpp
index 905621daf8e..9d633e82020 100644
--- a/src/glsl/link_varyings.cpp
+++ b/src/glsl/link_varyings.cpp
@@ -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;
diff --git a/src/glsl/link_varyings.h b/src/glsl/link_varyings.h
index 6264ef05b2a..6fa26817677 100644
--- a/src/glsl/link_varyings.h
+++ b/src/glsl/link_varyings.h
@@ -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 */
diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp
index c54b7049bbe..61904dc0ed5 100644
--- a/src/glsl/linker.cpp
+++ b/src/glsl/linker.cpp
@@ -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;