aboutsummaryrefslogtreecommitdiff
path: root/mesalib/src/glsl/linker.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'mesalib/src/glsl/linker.cpp')
-rw-r--r--mesalib/src/glsl/linker.cpp135
1 files changed, 78 insertions, 57 deletions
diff --git a/mesalib/src/glsl/linker.cpp b/mesalib/src/glsl/linker.cpp
index c168e47e0..ba97ade25 100644
--- a/mesalib/src/glsl/linker.cpp
+++ b/mesalib/src/glsl/linker.cpp
@@ -1514,31 +1514,31 @@ static bool
check_resources(struct gl_context *ctx, struct gl_shader_program *prog)
{
static const char *const shader_names[MESA_SHADER_TYPES] = {
- "vertex", "fragment", "geometry"
+ "vertex", "geometry", "fragment"
};
const unsigned max_samplers[MESA_SHADER_TYPES] = {
ctx->Const.VertexProgram.MaxTextureImageUnits,
- ctx->Const.FragmentProgram.MaxTextureImageUnits,
- ctx->Const.GeometryProgram.MaxTextureImageUnits
+ ctx->Const.GeometryProgram.MaxTextureImageUnits,
+ ctx->Const.FragmentProgram.MaxTextureImageUnits
};
const unsigned max_default_uniform_components[MESA_SHADER_TYPES] = {
ctx->Const.VertexProgram.MaxUniformComponents,
- ctx->Const.FragmentProgram.MaxUniformComponents,
- ctx->Const.GeometryProgram.MaxUniformComponents
+ ctx->Const.GeometryProgram.MaxUniformComponents,
+ ctx->Const.FragmentProgram.MaxUniformComponents
};
const unsigned max_combined_uniform_components[MESA_SHADER_TYPES] = {
ctx->Const.VertexProgram.MaxCombinedUniformComponents,
- ctx->Const.FragmentProgram.MaxCombinedUniformComponents,
- ctx->Const.GeometryProgram.MaxCombinedUniformComponents
+ ctx->Const.GeometryProgram.MaxCombinedUniformComponents,
+ ctx->Const.FragmentProgram.MaxCombinedUniformComponents
};
const unsigned max_uniform_blocks[MESA_SHADER_TYPES] = {
ctx->Const.VertexProgram.MaxUniformBlocks,
- ctx->Const.FragmentProgram.MaxUniformBlocks,
ctx->Const.GeometryProgram.MaxUniformBlocks,
+ ctx->Const.FragmentProgram.MaxUniformBlocks
};
for (unsigned i = 0; i < MESA_SHADER_TYPES; i++) {
@@ -1836,9 +1836,9 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
goto done;
}
- unsigned prev;
- for (prev = 0; prev < MESA_SHADER_TYPES; prev++) {
- if (prog->_LinkedShaders[prev] != NULL)
+ unsigned first;
+ for (first = 0; first < MESA_SHADER_TYPES; first++) {
+ if (prog->_LinkedShaders[first] != NULL)
break;
}
@@ -1850,7 +1850,7 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
* non-zero, but the program object has no vertex or geometry
* shader;
*/
- if (prev >= MESA_SHADER_FRAGMENT) {
+ if (first >= MESA_SHADER_FRAGMENT) {
linker_error(prog, "Transform feedback varyings specified, but "
"no vertex or geometry shader is present.");
goto done;
@@ -1864,69 +1864,90 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
goto done;
}
- for (unsigned i = prev + 1; i < MESA_SHADER_TYPES; i++) {
- if (prog->_LinkedShaders[i] == NULL)
- continue;
-
- if (!assign_varying_locations(
- ctx, mem_ctx, prog, prog->_LinkedShaders[prev], prog->_LinkedShaders[i],
- i == MESA_SHADER_FRAGMENT ? num_tfeedback_decls : 0,
- tfeedback_decls))
- goto done;
-
- prev = i;
+ /* Linking the stages in the opposite order (from fragment to vertex)
+ * ensures that inter-shader outputs written to in an earlier stage are
+ * eliminated if they are (transitively) not used in a later stage.
+ */
+ int last, next;
+ for (last = MESA_SHADER_TYPES-1; last >= 0; last--) {
+ if (prog->_LinkedShaders[last] != NULL)
+ break;
}
- if (prev != MESA_SHADER_FRAGMENT && num_tfeedback_decls != 0) {
- /* There was no fragment shader, but we still have to assign varying
- * locations for use by transform feedback.
- */
- if (!assign_varying_locations(
- ctx, mem_ctx, prog, prog->_LinkedShaders[prev], NULL, num_tfeedback_decls,
- tfeedback_decls))
- goto done;
- }
+ if (last >= 0 && last < MESA_SHADER_FRAGMENT) {
+ gl_shader *const sh = prog->_LinkedShaders[last];
- if (!store_tfeedback_info(ctx, prog, num_tfeedback_decls, tfeedback_decls))
- goto done;
+ if (num_tfeedback_decls != 0) {
+ /* There was no fragment shader, but we still have to assign varying
+ * locations for use by transform feedback.
+ */
+ if (!assign_varying_locations(ctx, mem_ctx, prog,
+ sh, NULL,
+ num_tfeedback_decls, tfeedback_decls))
+ goto done;
+ }
- if (prog->_LinkedShaders[MESA_SHADER_VERTEX] != NULL) {
- demote_shader_inputs_and_outputs(prog->_LinkedShaders[MESA_SHADER_VERTEX],
- ir_var_shader_out);
+ do_dead_builtin_varyings(ctx, sh->ir, NULL,
+ num_tfeedback_decls, tfeedback_decls);
- /* Eliminate code that is now dead due to unused vertex outputs being
- * demoted.
+ demote_shader_inputs_and_outputs(sh, ir_var_shader_out);
+
+ /* Eliminate code that is now dead due to unused outputs being demoted.
*/
- while (do_dead_code(prog->_LinkedShaders[MESA_SHADER_VERTEX]->ir, false))
- ;
+ while (do_dead_code(sh->ir, false))
+ ;
}
+ else if (first == MESA_SHADER_FRAGMENT) {
+ /* If the program only contains a fragment shader...
+ */
+ gl_shader *const sh = prog->_LinkedShaders[first];
- if (prog->_LinkedShaders[MESA_SHADER_GEOMETRY] != NULL) {
- gl_shader *const sh = prog->_LinkedShaders[MESA_SHADER_GEOMETRY];
+ do_dead_builtin_varyings(ctx, NULL, sh->ir,
+ num_tfeedback_decls, tfeedback_decls);
demote_shader_inputs_and_outputs(sh, ir_var_shader_in);
- demote_shader_inputs_and_outputs(sh, ir_var_shader_out);
- /* Eliminate code that is now dead due to unused geometry outputs being
- * demoted.
- */
- while (do_dead_code(prog->_LinkedShaders[MESA_SHADER_GEOMETRY]->ir, false))
- ;
+ while (do_dead_code(sh->ir, false))
+ ;
}
- if (prog->_LinkedShaders[MESA_SHADER_FRAGMENT] != NULL) {
- gl_shader *const sh = prog->_LinkedShaders[MESA_SHADER_FRAGMENT];
+ next = last;
+ for (int i = next - 1; i >= 0; i--) {
+ if (prog->_LinkedShaders[i] == NULL)
+ continue;
- demote_shader_inputs_and_outputs(sh, ir_var_shader_in);
+ gl_shader *const sh_i = prog->_LinkedShaders[i];
+ gl_shader *const sh_next = prog->_LinkedShaders[next];
+
+ if (!assign_varying_locations(ctx, mem_ctx, prog, sh_i, sh_next,
+ next == MESA_SHADER_FRAGMENT ? num_tfeedback_decls : 0,
+ tfeedback_decls))
+ goto done;
- /* Eliminate code that is now dead due to unused fragment inputs being
- * demoted. This shouldn't actually do anything other than remove
- * declarations of the (now unused) global variables.
+ do_dead_builtin_varyings(ctx, sh_i->ir, sh_next->ir,
+ next == MESA_SHADER_FRAGMENT ? num_tfeedback_decls : 0,
+ tfeedback_decls);
+
+ demote_shader_inputs_and_outputs(sh_i, ir_var_shader_out);
+ demote_shader_inputs_and_outputs(sh_next, ir_var_shader_in);
+
+ /* Eliminate code that is now dead due to unused outputs being demoted.
*/
- while (do_dead_code(prog->_LinkedShaders[MESA_SHADER_FRAGMENT]->ir, false))
- ;
+ while (do_dead_code(sh_i->ir, false))
+ ;
+ while (do_dead_code(sh_next->ir, false))
+ ;
+
+ /* This must be done after all dead varyings are eliminated. */
+ if (!check_against_varying_limit(ctx, prog, sh_next))
+ goto done;
+
+ next = i;
}
+ if (!store_tfeedback_info(ctx, prog, num_tfeedback_decls, tfeedback_decls))
+ goto done;
+
update_array_sizes(prog);
link_assign_uniform_locations(prog);
store_fragdepth_layout(prog);