glsl: Add uniform_locations_assigned parameter to do_dead_code opt pass
authorIan Romanick <ian.d.romanick@intel.com>
Fri, 21 Oct 2011 18:17:39 +0000 (11:17 -0700)
committerIan Romanick <ian.d.romanick@intel.com>
Wed, 26 Oct 2011 00:51:43 +0000 (17:51 -0700)
Setting this flag prevents declarations of uniforms from being removed
from the IR.  Since the IR is directly used by several API functions
that query uniforms in shaders, uniform declarations cannot be removed
after the locations have been set.  However, it should still be safe
to reorder the declarations (this is not tested).

Signed-off-by: Ian Romanick <ian.d.romanick@intel.com>
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=41980
Tested-by: Brian Paul <brianp@vmware.com>
Reviewed-by: Bryan Cain <bryancain3@gmail.com>
Cc: Vinson Lee <vlee@vmware.com>
Cc: José Fonseca <jfonseca@vmware.com>
Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
Reviewed-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
src/glsl/glsl_parser_extras.cpp
src/glsl/ir_optimization.h
src/glsl/linker.cpp
src/glsl/main.cpp
src/glsl/opt_dead_code.cpp
src/glsl/test_optpass.cpp
src/mesa/drivers/dri/i965/brw_shader.cpp
src/mesa/main/ff_fragment_shader.cpp
src/mesa/program/ir_to_mesa.cpp
src/mesa/state_tracker/st_glsl_to_tgsi.cpp

index a9075b2b1be02dc3a4c188b558a5988d3bb37acc..e2112fe6dd0cfef3a18b1ebb2c4888e036a6cb76 100644 (file)
@@ -883,8 +883,27 @@ ast_struct_specifier::ast_struct_specifier(char *identifier,
    this->declarations.push_degenerate_list_at_head(&declarator_list->link);
 }
 
+/**
+ * Do the set of common optimizations passes
+ *
+ * \param ir                          List of instructions to be optimized
+ * \param linked                      Is the shader linked?  This enables
+ *                                    optimizations passes that remove code at
+ *                                    global scope and could cause linking to
+ *                                    fail.
+ * \param uniform_locations_assigned  Have locations already been assigned for
+ *                                    uniforms?  This prevents the declarations
+ *                                    of unused uniforms from being removed.
+ *                                    The setting of this flag only matters if
+ *                                    \c linked is \c true.
+ * \param max_unroll_iterations       Maximum number of loop iterations to be
+ *                                    unrolled.  Setting to 0 forces all loops
+ *                                    to be unrolled.
+ */
 bool
-do_common_optimization(exec_list *ir, bool linked, unsigned max_unroll_iterations)
+do_common_optimization(exec_list *ir, bool linked,
+                      bool uniform_locations_assigned,
+                      unsigned max_unroll_iterations)
 {
    GLboolean progress = GL_FALSE;
 
@@ -900,7 +919,7 @@ do_common_optimization(exec_list *ir, bool linked, unsigned max_unroll_iteration
    progress = do_copy_propagation(ir) || progress;
    progress = do_copy_propagation_elements(ir) || progress;
    if (linked)
-      progress = do_dead_code(ir) || progress;
+      progress = do_dead_code(ir, uniform_locations_assigned) || progress;
    else
       progress = do_dead_code_unlinked(ir) || progress;
    progress = do_dead_code_local(ir) || progress;
index af80e26b9ff397a950caa659d5053ec4a160e730..7b32e84f0d8af8c32d5d42efa0b37e77dc87f18a 100644 (file)
@@ -37,7 +37,9 @@
 #define MOD_TO_FRACT       0x20
 #define INT_DIV_TO_MUL_RCP 0x40
 
-bool do_common_optimization(exec_list *ir, bool linked, unsigned max_unroll_iterations);
+bool do_common_optimization(exec_list *ir, bool linked,
+                           bool uniform_locations_assigned,
+                           unsigned max_unroll_iterations);
 
 bool do_algebraic(exec_list *instructions);
 bool do_constant_folding(exec_list *instructions);
@@ -46,7 +48,7 @@ bool do_constant_variable_unlinked(exec_list *instructions);
 bool do_copy_propagation(exec_list *instructions);
 bool do_copy_propagation_elements(exec_list *instructions);
 bool do_constant_propagation(exec_list *instructions);
-bool do_dead_code(exec_list *instructions);
+bool do_dead_code(exec_list *instructions, bool uniform_locations_assigned);
 bool do_dead_code_local(exec_list *instructions);
 bool do_dead_code_unlinked(exec_list *instructions);
 bool do_dead_functions(exec_list *instructions);
index a7c38a3426a5f914d638476d698112aa9cc113ad..d4d2496fedd88787f72457af91a8617a1dc5383a 100644 (file)
@@ -1742,7 +1742,7 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
       if (ctx->ShaderCompilerOptions[i].LowerClipDistance)
          lower_clip_distance(prog->_LinkedShaders[i]->ir);
 
-      while (do_common_optimization(prog->_LinkedShaders[i]->ir, true, 32))
+      while (do_common_optimization(prog->_LinkedShaders[i]->ir, true, false, 32))
         ;
    }
 
index 01921375070c34577cbec33df940f9f5f2ca9865..e174224712b651c18a7a2981c962546105c0686a 100644 (file)
@@ -166,7 +166,7 @@ compile_shader(struct gl_context *ctx, struct gl_shader *shader)
    if (!state->error && !shader->ir->is_empty()) {
       bool progress;
       do {
-        progress = do_common_optimization(shader->ir, false, 32);
+        progress = do_common_optimization(shader->ir, false, false, 32);
       } while (progress);
 
       validate_ir_tree(shader->ir);
index cb500d2d105b41f983c13cc59d6e2351daff81ff..5b9546ad40984708217f6eb7db907cfb22807659 100644 (file)
@@ -42,7 +42,7 @@ static bool debug = false;
  * for usage on an unlinked instruction stream.
  */
 bool
-do_dead_code(exec_list *instructions)
+do_dead_code(exec_list *instructions, bool uniform_locations_assigned)
 {
    ir_variable_refcount_visitor v;
    bool progress = false;
@@ -94,10 +94,11 @@ do_dead_code(exec_list *instructions)
          */
 
         /* uniform initializers are precious, and could get used by another
-         * stage.
+         * stage.  Also, once uniform locations have been assigned, the
+         * declaration cannot be deleted.
          */
         if (entry->var->mode == ir_var_uniform &&
-            entry->var->constant_value)
+            (uniform_locations_assigned || entry->var->constant_value))
            continue;
 
         entry->var->remove();
@@ -132,7 +133,12 @@ do_dead_code_unlinked(exec_list *instructions)
         foreach_iter(exec_list_iterator, sigiter, *f) {
            ir_function_signature *sig =
               (ir_function_signature *) sigiter.get();
-           if (do_dead_code(&sig->body))
+           /* The setting of the uniform_locations_assigned flag here is
+            * irrelevent.  If there is a uniform declaration encountered
+            * inside the body of the function, something has already gone
+            * terribly, terribly wrong.
+            */
+           if (do_dead_code(&sig->body, false))
               progress = true;
         }
       }
index 89b7f8338dccee0fadd3f7e4abe2211d8e515d93..6abafb5d3118d281490a029ffa2c08bff8c62f1b 100644 (file)
@@ -64,7 +64,7 @@ do_optimization(struct exec_list *ir, const char *optimization)
 
    if (sscanf(optimization, "do_common_optimization ( %d , %d ) ",
               &int_0, &int_1) == 2) {
-      return do_common_optimization(ir, int_0 != 0, int_1);
+      return do_common_optimization(ir, int_0 != 0, false, int_1);
    } else if (strcmp(optimization, "do_algebraic") == 0) {
       return do_algebraic(ir);
    } else if (strcmp(optimization, "do_constant_folding") == 0) {
@@ -80,7 +80,7 @@ do_optimization(struct exec_list *ir, const char *optimization)
    } else if (strcmp(optimization, "do_constant_propagation") == 0) {
       return do_constant_propagation(ir);
    } else if (strcmp(optimization, "do_dead_code") == 0) {
-      return do_dead_code(ir);
+      return do_dead_code(ir, false);
    } else if (strcmp(optimization, "do_dead_code_local") == 0) {
       return do_dead_code_local(ir);
    } else if (strcmp(optimization, "do_dead_code_unlinked") == 0) {
index 0858c4032bb5d5909ba8772e2f7cd47407f20292..d9d9414543d108f9daca7e36317202abe7aded6f 100644 (file)
@@ -138,7 +138,8 @@ brw_link_shader(struct gl_context *ctx, struct gl_shader_program *prog)
                                   false /* loops */
                                   ) || progress;
 
-        progress = do_common_optimization(shader->ir, true, 32) || progress;
+        progress = do_common_optimization(shader->ir, true, true, 32)
+          || progress;
       } while (progress);
 
       validate_ir_tree(shader->ir);
index 160a97c0caea1799d8300daa2129f89faf5944e4..3e449b03e9c3ad29a1d19e620b5ef50c9c139a6d 100644 (file)
@@ -1464,7 +1464,7 @@ create_new_program(struct gl_context *ctx, struct state_key *key)
 
    validate_ir_tree(p.shader->ir);
 
-   while (do_common_optimization(p.shader->ir, false, 32))
+   while (do_common_optimization(p.shader->ir, false, false, 32))
       ;
    reparent_ir(p.shader->ir, p.shader->ir);
 
index fecab50f753efb7df3cf38ca59c07d8cfe3ab361..635ebdd53f430c36c5fa1867a8292c127fdb4453 100644 (file)
@@ -3212,7 +3212,9 @@ _mesa_ir_link_shader(struct gl_context *ctx, struct gl_shader_program *prog)
 
         progress = do_lower_jumps(ir, true, true, options->EmitNoMainReturn, options->EmitNoCont, options->EmitNoLoops) || progress;
 
-        progress = do_common_optimization(ir, true, options->MaxUnrollIterations) || progress;
+        progress = do_common_optimization(ir, true, true,
+                                          options->MaxUnrollIterations)
+          || progress;
 
         progress = lower_quadop_vector(ir, true) || progress;
 
@@ -3321,7 +3323,7 @@ _mesa_glsl_compile_shader(struct gl_context *ctx, struct gl_shader *shader)
       /* Do some optimization at compile time to reduce shader IR size
        * and reduce later work if the same shader is linked multiple times
        */
-      while (do_common_optimization(shader->ir, false, 32))
+      while (do_common_optimization(shader->ir, false, false, 32))
         ;
 
       validate_ir_tree(shader->ir);
index 35fd1ffc13ae20d10ed6057b6ab0dcd21443a760..145bd7dcd0c8b96b7227987a3eb6d9d3433fcef5 100644 (file)
@@ -5058,7 +5058,9 @@ st_link_shader(struct gl_context *ctx, struct gl_shader_program *prog)
 
          progress = do_lower_jumps(ir, true, true, options->EmitNoMainReturn, options->EmitNoCont, options->EmitNoLoops) || progress;
 
-         progress = do_common_optimization(ir, true, options->MaxUnrollIterations) || progress;
+         progress = do_common_optimization(ir, true, true,
+                                          options->MaxUnrollIterations)
+          || progress;
 
          progress = lower_quadop_vector(ir, false) || progress;