Mesa (master): glsl: Lazily import built-in function prototypes.

Kenneth Graunke kwg at kemper.freedesktop.org
Tue Nov 30 13:50:38 PST 2010


Module: Mesa
Branch: master
Commit: f5692f452f7ae77d1e710041ffebb468cc5ba87b
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=f5692f452f7ae77d1e710041ffebb468cc5ba87b

Author: Kenneth Graunke <kenneth at whitecape.org>
Date:   Thu Nov 11 12:11:27 2010 -0800

glsl: Lazily import built-in function prototypes.

This makes a very simple 1.30 shader go from 196k of memory to 9k.

NOTE: This -may- be a candidate for the 7.9 branch, as the benefit is
substantial.  However, it's not a simple change, so it may be wiser to
wait for 7.10.

---

 src/glsl/ast_function.cpp                    |   69 +++++++++++++++-----------
 src/glsl/builtin_function.cpp                |    1 -
 src/glsl/builtins/tools/generate_builtins.py |    1 -
 3 files changed, 40 insertions(+), 31 deletions(-)

diff --git a/src/glsl/ast_function.cpp b/src/glsl/ast_function.cpp
index 1e66033..1dd210a 100644
--- a/src/glsl/ast_function.cpp
+++ b/src/glsl/ast_function.cpp
@@ -93,13 +93,34 @@ prototype_string(const glsl_type *return_type, const char *name,
 
 
 static ir_rvalue *
-process_call(exec_list *instructions, ir_function *f,
-	     YYLTYPE *loc, exec_list *actual_parameters,
-	     struct _mesa_glsl_parse_state *state)
+match_function_by_name(exec_list *instructions, const char *name,
+		       YYLTYPE *loc, exec_list *actual_parameters,
+		       struct _mesa_glsl_parse_state *state)
 {
    void *ctx = state;
+   ir_function *f = state->symbols->get_function(name);
+   ir_function_signature *sig = NULL;
 
-   ir_function_signature *sig = f->matching_signature(actual_parameters);
+   /* FINISHME: This doesn't handle the case where shader X contains a
+    * FINISHME: matching signature but shader X + N contains an _exact_
+    * FINISHME: matching signature.
+    */
+   if (f != NULL) {
+      sig = f->matching_signature(actual_parameters);
+   } else if (state->symbols->get_type(name) == NULL && (state->language_version == 110 || state->symbols->get_variable(name) == NULL)) {
+      /* The current shader doesn't contain a matching function or signature.
+       * Before giving up, look for the prototype in the built-in functions.
+       */
+      for (unsigned i = 0; i < state->num_builtins_to_link; i++) {
+	 f = state->builtins_to_link[i]->symbols->get_function(name);
+	 sig = f ? f->matching_signature(actual_parameters) : NULL;
+	 if (sig != NULL) {
+	    f = new(ctx) ir_function(name);
+	    f->add_signature(sig->clone_prototype(f, NULL));
+	    break;
+	 }
+      }
+   }
 
    if (sig != NULL) {
       /* Verify that 'out' and 'inout' actual parameters are lvalues.  This
@@ -164,45 +185,35 @@ process_call(exec_list *instructions, ir_function *f,
 	 return NULL;
       }
    } else {
-      char *str = prototype_string(NULL, f->name, actual_parameters);
+      char *str = prototype_string(NULL, name, actual_parameters);
 
       _mesa_glsl_error(loc, state, "no matching function for call to `%s'",
 		       str);
       talloc_free(str);
 
       const char *prefix = "candidates are: ";
-      foreach_list (node, &f->signatures) {
-	 ir_function_signature *sig = (ir_function_signature *) node;
 
-	 str = prototype_string(sig->return_type, f->name, &sig->parameters);
-	 _mesa_glsl_error(loc, state, "%s%s\n", prefix, str);
-	 talloc_free(str);
+      for (int i = -1; i < state->num_builtins_to_link; i++) {
+	 glsl_symbol_table *syms = i >= 0 ? state->builtins_to_link[i]->symbols
+					  : state->symbols;
+	 f = syms->get_function(name);
+	 if (f == NULL)
+	    continue;
 
-	 prefix = "                ";
-      }
+	 foreach_list (node, &f->signatures) {
+	    ir_function_signature *sig = (ir_function_signature *) node;
 
-      return ir_call::get_error_instruction(ctx);
-   }
-}
+	    str = prototype_string(sig->return_type, f->name, &sig->parameters);
+	    _mesa_glsl_error(loc, state, "%s%s\n", prefix, str);
+	    talloc_free(str);
 
+	    prefix = "                ";
+	 }
 
-static ir_rvalue *
-match_function_by_name(exec_list *instructions, const char *name,
-		       YYLTYPE *loc, exec_list *actual_parameters,
-		       struct _mesa_glsl_parse_state *state)
-{
-   void *ctx = state;
-   ir_function *f = state->symbols->get_function(name);
+      }
 
-   if (f == NULL) {
-      _mesa_glsl_error(loc, state, "function `%s' undeclared", name);
       return ir_call::get_error_instruction(ctx);
    }
-
-   /* Once we've determined that the function being called might exist, try
-    * to find an overload of the function that matches the parameters.
-    */
-   return process_call(instructions, f, loc, actual_parameters, state);
 }
 
 
diff --git a/src/glsl/builtin_function.cpp b/src/glsl/builtin_function.cpp
index bc36814..631aeac 100644
--- a/src/glsl/builtin_function.cpp
+++ b/src/glsl/builtin_function.cpp
@@ -13590,7 +13590,6 @@ _mesa_read_profile(struct _mesa_glsl_parse_state *state,
       builtin_profiles[profile_index] = sh;
    }
 
-   import_prototypes(sh->ir, instructions, state->symbols, state);
    state->builtins_to_link[state->num_builtins_to_link] = sh;
    state->num_builtins_to_link++;
 }
diff --git a/src/glsl/builtins/tools/generate_builtins.py b/src/glsl/builtins/tools/generate_builtins.py
index 1f1056e..5ea4b5c 100755
--- a/src/glsl/builtins/tools/generate_builtins.py
+++ b/src/glsl/builtins/tools/generate_builtins.py
@@ -214,7 +214,6 @@ _mesa_read_profile(struct _mesa_glsl_parse_state *state,
       builtin_profiles[profile_index] = sh;
    }
 
-   import_prototypes(sh->ir, instructions, state->symbols, state);
    state->builtins_to_link[state->num_builtins_to_link] = sh;
    state->num_builtins_to_link++;
 }



More information about the mesa-commit mailing list