glsl: Use the utility function to copy symbols between symbol tables
[mesa.git] / src / compiler / glsl / glsl_parser_extras.cpp
index 68af6baafaef69f9c9e13e1d115bc99d85cf7531..822301a58420bddb99f5362dc83e2532c4960542 100644 (file)
@@ -54,9 +54,9 @@ glsl_compute_version_string(void *mem_ctx, bool is_es, unsigned version)
 
 
 static const unsigned known_desktop_glsl_versions[] =
-   { 110, 120, 130, 140, 150, 330, 400, 410, 420, 430, 440, 450 };
+   { 110, 120, 130, 140, 150, 330, 400, 410, 420, 430, 440, 450, 460 };
 static const unsigned known_desktop_gl_versions[] =
-   {  20,  21,  30,  31,  32,  33,  40,  41,  42,  43,  44,  45 };
+   {  20,  21,  30,  31,  32,  33,  40,  41,  42,  43,  44,  45, 46 };
 
 
 _mesa_glsl_parse_state::_mesa_glsl_parse_state(struct gl_context *_ctx,
@@ -1079,7 +1079,7 @@ _mesa_ast_process_interface_block(YYLTYPE *locp,
    }
 }
 
-void
+static void
 _mesa_ast_type_qualifier_print(const struct ast_type_qualifier *q)
 {
    if (q->is_subroutine_decl())
@@ -1672,23 +1672,12 @@ ast_struct_specifier::print(void) const
 }
 
 
-ast_struct_specifier::ast_struct_specifier(void *lin_ctx, const char *identifier,
+ast_struct_specifier::ast_struct_specifier(const char *identifier,
                                           ast_declarator_list *declarator_list)
+   : name(identifier), layout(NULL), declarations(), is_declaration(true),
+     type(NULL)
 {
-   if (identifier == NULL) {
-      /* All anonymous structs have the same name. This simplifies matching of
-       * globals whose type is an unnamed struct.
-       *
-       * It also avoids a memory leak when the same shader is compiled over and
-       * over again.
-       */
-      identifier = "#anon_struct";
-   }
-   name = identifier;
    this->declarations.push_degenerate_list_at_head(&declarator_list->link);
-   is_declaration = true;
-   layout = NULL;
-   type = NULL;
 }
 
 void ast_subroutine_list::print(void) const
@@ -1863,11 +1852,53 @@ set_shader_inout_layout(struct gl_shader *shader,
    shader->bound_image = state->bound_image_specified;
 }
 
+/* src can be NULL if only the symbols found in the exec_list should be
+ * copied
+ */
+void
+_mesa_glsl_copy_symbols_from_table(struct exec_list *shader_ir,
+                                   struct glsl_symbol_table *src,
+                                   struct glsl_symbol_table *dest)
+{
+   foreach_in_list (ir_instruction, ir, shader_ir) {
+      switch (ir->ir_type) {
+      case ir_type_function:
+         dest->add_function((ir_function *) ir);
+         break;
+      case ir_type_variable: {
+         ir_variable *const var = (ir_variable *) ir;
+
+         if (var->data.mode != ir_var_temporary)
+            dest->add_variable(var);
+         break;
+      }
+      default:
+         break;
+      }
+   }
+
+   if (src != NULL) {
+      /* Explicitly copy the gl_PerVertex interface definitions because these
+       * are needed to check they are the same during the interstage link.
+       * They can’t necessarily be found via the exec_list because the members
+       * might not be referenced. The GL spec still requires that they match
+       * in that case.
+       */
+      const glsl_type *iface =
+         src->get_interface("gl_PerVertex", ir_var_shader_in);
+      if (iface)
+         dest->add_interface(iface->name, iface, ir_var_shader_in);
+
+      iface = src->get_interface("gl_PerVertex", ir_var_shader_out);
+      if (iface)
+         dest->add_interface(iface->name, iface, ir_var_shader_out);
+   }
+}
+
 extern "C" {
 
 static void
-assign_subroutine_indexes(struct gl_shader *sh,
-                         struct _mesa_glsl_parse_state *state)
+assign_subroutine_indexes(struct _mesa_glsl_parse_state *state)
 {
    int j, k;
    int index = 0;
@@ -1937,6 +1968,7 @@ do_late_parsing_checks(struct _mesa_glsl_parse_state *state)
 
 static void
 opt_shader_and_create_symbol_table(struct gl_context *ctx,
+                                   struct glsl_symbol_table *source_symbols,
                                    struct gl_shader *shader)
 {
    assert(shader->CompileStatus != compile_failure &&
@@ -1994,24 +2026,8 @@ opt_shader_and_create_symbol_table(struct gl_context *ctx,
     * We don't have to worry about types or interface-types here because those
     * are fly-weights that are looked up by glsl_type.
     */
-   foreach_in_list (ir_instruction, ir, shader->ir) {
-      switch (ir->ir_type) {
-      case ir_type_function:
-         shader->symbols->add_function((ir_function *) ir);
-         break;
-      case ir_type_variable: {
-         ir_variable *const var = (ir_variable *) ir;
-
-         if (var->data.mode != ir_var_temporary)
-            shader->symbols->add_variable(var);
-         break;
-      }
-      default:
-         break;
-      }
-   }
-
-   _mesa_glsl_initialize_derived_variables(ctx, shader);
+   _mesa_glsl_copy_symbols_from_table(shader->ir, source_symbols,
+                                      shader->symbols);
 }
 
 void
@@ -2048,7 +2064,9 @@ _mesa_glsl_compile_shader(struct gl_context *ctx, struct gl_shader *shader,
          return;
 
       if (shader->CompileStatus == compiled_no_opts) {
-         opt_shader_and_create_symbol_table(ctx, shader);
+         opt_shader_and_create_symbol_table(ctx,
+                                            NULL, /* source_symbols */
+                                            shader);
          shader->CompileStatus = compile_success;
          return;
       }
@@ -2105,11 +2123,11 @@ _mesa_glsl_compile_shader(struct gl_context *ctx, struct gl_shader *shader,
    shader->IsES = state->es_shader;
 
    if (!state->error && !shader->ir->is_empty()) {
-      assign_subroutine_indexes(shader, state);
+      assign_subroutine_indexes(state);
       lower_subroutine(shader->ir, state);
 
       if (!ctx->Cache || force_recompile)
-         opt_shader_and_create_symbol_table(ctx, shader);
+         opt_shader_and_create_symbol_table(ctx, state->symbols, shader);
       else {
          reparent_ir(shader->ir, shader->ir);
          shader->CompileStatus = compiled_no_opts;
@@ -2217,8 +2235,13 @@ do_common_optimization(exec_list *ir, bool linked,
    if (options->MaxUnrollIterations) {
       loop_state *ls = analyze_loop_variables(ir);
       if (ls->loop_found) {
-         OPT(set_loop_controls, ir, ls);
-         OPT(unroll_loops, ir, ls, options);
+         bool loop_progress = unroll_loops(ir, ls, options);
+         while (loop_progress) {
+            loop_progress = false;
+            loop_progress |= do_constant_propagation(ir);
+            loop_progress |= do_if_simplification(ir);
+         }
+         progress |= loop_progress;
       }
       delete ls;
    }