From 42305fb50256c12b8e7a516115e72ae7089ccd1b Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Tue, 10 Sep 2013 12:00:34 -0500 Subject: [PATCH] glsl: Count shader inputs and outputs separately MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit 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 Reviewed-by: Brian Paul Reviewed-by: Marek Olšák Reviewed-by: Paul Berry --- src/glsl/link_varyings.cpp | 101 +++++++++++++++++++++++++++++-------- src/glsl/link_varyings.h | 11 ++-- src/glsl/linker.cpp | 4 +- 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; -- 2.30.2