summaryrefslogtreecommitdiff
path: root/src/glsl
diff options
context:
space:
mode:
authorIan Romanick <ian.d.romanick@intel.com>2010-07-20 11:29:46 -0700
committerIan Romanick <ian.d.romanick@intel.com>2010-07-21 15:52:58 -0700
commitd5be2acae379783c4aa31243e0a88a9e67e6ca7e (patch)
tree91ebf30796116f1b4d20b6f2fe420a085a59d59e /src/glsl
parent4ccd3c548b9b9a2fee79342445f68d73525bfcdb (diff)
linker: Link built-in functions instead of including them in every shader
This is an invasive set of changes. Each user shader tracks a set of other shaders that contain built-in functions. During compilation, function prototypes are imported from these shaders. During linking, the shaders are linked with these built-in-function shaders just like with any other shader.
Diffstat (limited to 'src/glsl')
-rw-r--r--src/glsl/builtin_function.cpp218
-rw-r--r--src/glsl/builtins/110_vs/ftransform4
-rwxr-xr-xsrc/glsl/builtins/tools/generate_builtins.pl63
-rw-r--r--src/glsl/glsl_parser_extras.h4
-rw-r--r--src/glsl/ir.h3
-rw-r--r--src/glsl/linker.cpp23
-rw-r--r--src/glsl/main.cpp4
7 files changed, 254 insertions, 65 deletions
diff --git a/src/glsl/builtin_function.cpp b/src/glsl/builtin_function.cpp
index 967bcd0c40..10e59e491e 100644
--- a/src/glsl/builtin_function.cpp
+++ b/src/glsl/builtin_function.cpp
@@ -25,22 +25,41 @@
#include <stdio.h>
#include "glsl_parser_extras.h"
#include "ir_reader.h"
+#include "program.h"
-void
-read_builtins(_mesa_glsl_parse_state *st, exec_list *instructions,
- const char **functions, unsigned count)
+extern "C" struct gl_shader *
+_mesa_new_shader(GLcontext *ctx, GLuint name, GLenum type);
+
+gl_shader *
+read_builtins(GLenum target, const char **functions, unsigned count)
{
- if (st->error)
- return;
+ gl_shader *sh = _mesa_new_shader(NULL, 0, target);
+ struct _mesa_glsl_parse_state *st =
+ new(sh) _mesa_glsl_parse_state(NULL, target, sh);
+
+ st->language_version = 130;
+ st->ARB_texture_rectangle_enable = true;
+ st->EXT_texture_array_enable = true;
+ _mesa_glsl_initialize_types(st);
+
+ sh->ir = new(sh) exec_list;
+ sh->symbols = st->symbols;
for (unsigned i = 0; i < count; i++) {
- _mesa_glsl_read_ir(st, instructions, functions[i]);
+ _mesa_glsl_read_ir(st, sh->ir, functions[i]);
if (st->error) {
printf("error reading builtin: %.35s ...\n", functions[i]);
- return;
+ delete st;
+ talloc_free(sh);
+ return NULL;
}
}
+
+ reparent_ir(sh->ir, sh);
+ delete st;
+
+ return sh;
}
/* 110 builtins */
@@ -2580,7 +2599,9 @@ static const char *functions_for_110_fs [] = {
/* 110_vs builtins */
static const char *builtins_110_vs_ftransform = {
- "((function ftransform\n"
+ "((declare (uniform) mat4 gl_ModelViewProjectionMatrix)\n"
+ " (declare (in) vec4 gl_Vertex)\n"
+ " (function ftransform\n"
" (signature vec4\n"
" (parameters)\n"
" ((return (expression vec4 *\n"
@@ -4760,53 +4781,146 @@ static const char *functions_for_EXT_texture_array_fs [] = {
#define Elements(x) (sizeof(x)/sizeof(*(x)))
#endif
+void *builtin_mem_ctx = NULL;
+
+void
+_mesa_glsl_release_functions(void)
+{
+ talloc_free(builtin_mem_ctx);
+}
+
void
_mesa_glsl_initialize_functions(exec_list *instructions,
struct _mesa_glsl_parse_state *state)
{
- if (state->language_version >= 110)
- read_builtins(state, instructions,
- functions_for_110,
- Elements(functions_for_110));
-
- if (state->target == fragment_shader && state->language_version >= 110)
- read_builtins(state, instructions,
- functions_for_110_fs,
- Elements(functions_for_110_fs));
-
- if (state->target == vertex_shader && state->language_version >= 110)
- read_builtins(state, instructions,
- functions_for_110_vs,
- Elements(functions_for_110_vs));
-
- if (state->language_version >= 120)
- read_builtins(state, instructions,
- functions_for_120,
- Elements(functions_for_120));
-
- if (state->language_version >= 130)
- read_builtins(state, instructions,
- functions_for_130,
- Elements(functions_for_130));
-
- if (state->target == fragment_shader && state->language_version >= 130)
- read_builtins(state, instructions,
- functions_for_130_fs,
- Elements(functions_for_130_fs));
-
- if (state->ARB_texture_rectangle_enable)
- read_builtins(state, instructions,
- functions_for_ARB_texture_rectangle,
- Elements(functions_for_ARB_texture_rectangle));
-
- if (state->EXT_texture_array_enable)
- read_builtins(state, instructions,
- functions_for_EXT_texture_array,
- Elements(functions_for_EXT_texture_array));
-
- if (state->target == fragment_shader && state->EXT_texture_array_enable)
- read_builtins(state, instructions,
- functions_for_EXT_texture_array_fs,
- Elements(functions_for_EXT_texture_array_fs));
+ if (builtin_mem_ctx == NULL)
+ builtin_mem_ctx = talloc_init("GLSL built-in functions");
+
+ state->num_builtins_to_link = 0;
+ if (state->language_version >= 110) {
+ static gl_shader *sh = NULL;
+
+ if (sh == NULL) {
+ sh = read_builtins(GL_VERTEX_SHADER, functions_for_110,
+ Elements(functions_for_110));
+ talloc_steal(builtin_mem_ctx, sh);
+ }
+
+ import_prototypes(sh->ir, instructions, state->symbols, state);
+ state->builtins_to_link[state->num_builtins_to_link] = sh;
+ state->num_builtins_to_link++;
+ }
+
+ if (state->target == fragment_shader && state->language_version >= 110) {
+ static gl_shader *sh = NULL;
+
+ if (sh == NULL) {
+ sh = read_builtins(GL_VERTEX_SHADER, functions_for_110_fs,
+ Elements(functions_for_110_fs));
+ talloc_steal(builtin_mem_ctx, sh);
+ }
+
+ import_prototypes(sh->ir, instructions, state->symbols, state);
+ state->builtins_to_link[state->num_builtins_to_link] = sh;
+ state->num_builtins_to_link++;
+ }
+
+ if (state->target == vertex_shader && state->language_version >= 110) {
+ static gl_shader *sh = NULL;
+
+ if (sh == NULL) {
+ sh = read_builtins(GL_VERTEX_SHADER, functions_for_110_vs,
+ Elements(functions_for_110_vs));
+ talloc_steal(builtin_mem_ctx, sh);
+ }
+
+ import_prototypes(sh->ir, instructions, state->symbols, state);
+ state->builtins_to_link[state->num_builtins_to_link] = sh;
+ state->num_builtins_to_link++;
+ }
+
+ if (state->language_version >= 120) {
+ static gl_shader *sh = NULL;
+
+ if (sh == NULL) {
+ sh = read_builtins(GL_VERTEX_SHADER, functions_for_120,
+ Elements(functions_for_120));
+ talloc_steal(builtin_mem_ctx, sh);
+ }
+
+ import_prototypes(sh->ir, instructions, state->symbols, state);
+ state->builtins_to_link[state->num_builtins_to_link] = sh;
+ state->num_builtins_to_link++;
+ }
+
+ if (state->language_version >= 130) {
+ static gl_shader *sh = NULL;
+
+ if (sh == NULL) {
+ sh = read_builtins(GL_VERTEX_SHADER, functions_for_130,
+ Elements(functions_for_130));
+ talloc_steal(builtin_mem_ctx, sh);
+ }
+
+ import_prototypes(sh->ir, instructions, state->symbols, state);
+ state->builtins_to_link[state->num_builtins_to_link] = sh;
+ state->num_builtins_to_link++;
+ }
+
+ if (state->target == fragment_shader && state->language_version >= 130) {
+ static gl_shader *sh = NULL;
+
+ if (sh == NULL) {
+ sh = read_builtins(GL_VERTEX_SHADER, functions_for_130_fs,
+ Elements(functions_for_130_fs));
+ talloc_steal(builtin_mem_ctx, sh);
+ }
+
+ import_prototypes(sh->ir, instructions, state->symbols, state);
+ state->builtins_to_link[state->num_builtins_to_link] = sh;
+ state->num_builtins_to_link++;
+ }
+
+ if (state->ARB_texture_rectangle_enable) {
+ static gl_shader *sh = NULL;
+
+ if (sh == NULL) {
+ sh = read_builtins(GL_VERTEX_SHADER, functions_for_ARB_texture_rectangle,
+ Elements(functions_for_ARB_texture_rectangle));
+ talloc_steal(builtin_mem_ctx, sh);
+ }
+
+ import_prototypes(sh->ir, instructions, state->symbols, state);
+ state->builtins_to_link[state->num_builtins_to_link] = sh;
+ state->num_builtins_to_link++;
+ }
+
+ if (state->EXT_texture_array_enable) {
+ static gl_shader *sh = NULL;
+
+ if (sh == NULL) {
+ sh = read_builtins(GL_VERTEX_SHADER, functions_for_EXT_texture_array,
+ Elements(functions_for_EXT_texture_array));
+ talloc_steal(builtin_mem_ctx, sh);
+ }
+
+ import_prototypes(sh->ir, instructions, state->symbols, state);
+ state->builtins_to_link[state->num_builtins_to_link] = sh;
+ state->num_builtins_to_link++;
+ }
+
+ if (state->target == fragment_shader && state->EXT_texture_array_enable) {
+ static gl_shader *sh = NULL;
+
+ if (sh == NULL) {
+ sh = read_builtins(GL_VERTEX_SHADER, functions_for_EXT_texture_array_fs,
+ Elements(functions_for_EXT_texture_array_fs));
+ talloc_steal(builtin_mem_ctx, 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/110_vs/ftransform b/src/glsl/builtins/110_vs/ftransform
index 3a5e8ccecf..9ca63dc1e3 100644
--- a/src/glsl/builtins/110_vs/ftransform
+++ b/src/glsl/builtins/110_vs/ftransform
@@ -1,4 +1,6 @@
-((function ftransform
+((declare (uniform) mat4 gl_ModelViewProjectionMatrix)
+ (declare (in) vec4 gl_Vertex)
+ (function ftransform
(signature vec4
(parameters)
((return (expression vec4 *
diff --git a/src/glsl/builtins/tools/generate_builtins.pl b/src/glsl/builtins/tools/generate_builtins.pl
index a0b5c1f421..61d511da1d 100755
--- a/src/glsl/builtins/tools/generate_builtins.pl
+++ b/src/glsl/builtins/tools/generate_builtins.pl
@@ -64,22 +64,41 @@ print << 'EOF';
#include <stdio.h>
#include "glsl_parser_extras.h"
#include "ir_reader.h"
+#include "program.h"
-void
-read_builtins(_mesa_glsl_parse_state *st, exec_list *instructions,
- const char **functions, unsigned count)
+extern "C" struct gl_shader *
+_mesa_new_shader(GLcontext *ctx, GLuint name, GLenum type);
+
+gl_shader *
+read_builtins(GLenum target, const char **functions, unsigned count)
{
- if (st->error)
- return;
+ gl_shader *sh = _mesa_new_shader(NULL, 0, target);
+ struct _mesa_glsl_parse_state *st =
+ new(sh) _mesa_glsl_parse_state(NULL, target, sh);
+
+ st->language_version = 130;
+ st->ARB_texture_rectangle_enable = true;
+ st->EXT_texture_array_enable = true;
+ _mesa_glsl_initialize_types(st);
+
+ sh->ir = new(sh) exec_list;
+ sh->symbols = st->symbols;
for (unsigned i = 0; i < count; i++) {
- _mesa_glsl_read_ir(st, instructions, functions[i]);
+ _mesa_glsl_read_ir(st, sh->ir, functions[i]);
if (st->error) {
printf("error reading builtin: %.35s ...\n", functions[i]);
- return;
+ delete st;
+ talloc_free(sh);
+ return NULL;
}
}
+
+ reparent_ir(sh->ir, sh);
+ delete st;
+
+ return sh;
}
EOF
@@ -95,10 +114,22 @@ print << 'EOF';
#define Elements(x) (sizeof(x)/sizeof(*(x)))
#endif
+void *builtin_mem_ctx = NULL;
+
+void
+_mesa_glsl_release_functions(void)
+{
+ talloc_free(builtin_mem_ctx);
+}
+
void
_mesa_glsl_initialize_functions(exec_list *instructions,
struct _mesa_glsl_parse_state *state)
{
+ if (builtin_mem_ctx == NULL)
+ builtin_mem_ctx = talloc_init("GLSL built-in functions");
+
+ state->num_builtins_to_link = 0;
EOF
foreach $version_xs (@versions) {
@@ -117,10 +148,20 @@ foreach $version_xs (@versions) {
# Not a version...an extension name
$check = "${check}state->${version}_enable";
}
- print " if ($check)\n";
- print " read_builtins(state, instructions,\n";
- print " functions_for_$version_xs,\n";
- print " Elements(functions_for_$version_xs));\n\n"
+ print " if ($check) {\n";
+ print " static gl_shader *sh = NULL;\n";
+ print "\n";
+ print " if (sh == NULL) {\n";
+ print " sh = read_builtins(GL_VERTEX_SHADER, functions_for_$version_xs,\n";
+ print " Elements(functions_for_$version_xs));\n";
+ print " talloc_steal(builtin_mem_ctx, sh);\n";
+ print " }\n";
+ print "\n";
+ print " import_prototypes(sh->ir, instructions, state->symbols, state);\n";
+ print " state->builtins_to_link[state->num_builtins_to_link] = sh;\n";
+ print " state->num_builtins_to_link++;\n";
+ print " }\n";
+ print "\n";
}
print "}\n";
diff --git a/src/glsl/glsl_parser_extras.h b/src/glsl/glsl_parser_extras.h
index b50d9eea67..56f6e18e0b 100644
--- a/src/glsl/glsl_parser_extras.h
+++ b/src/glsl/glsl_parser_extras.h
@@ -125,6 +125,10 @@ struct _mesa_glsl_parse_state {
/** Extensions supported by the OpenGL implementation. */
const struct gl_extensions *extensions;
+
+ /** Shaders containing built-in functions that are used for linking. */
+ struct gl_shader *builtins_to_link[16];
+ unsigned num_builtins_to_link;
};
typedef struct YYLTYPE {
diff --git a/src/glsl/ir.h b/src/glsl/ir.h
index 38b10f5b06..3a643fc580 100644
--- a/src/glsl/ir.h
+++ b/src/glsl/ir.h
@@ -1316,6 +1316,9 @@ _mesa_glsl_initialize_functions(exec_list *instructions,
struct _mesa_glsl_parse_state *state);
extern void
+_mesa_glsl_release_functions(void);
+
+extern void
reparent_ir(exec_list *list, void *mem_ctx);
class glsl_symbol_table;
diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp
index 640e6eee8e..7c30a40a6c 100644
--- a/src/glsl/linker.cpp
+++ b/src/glsl/linker.cpp
@@ -739,7 +739,28 @@ link_intrastage_shaders(struct gl_shader_program *prog,
/* Resolve initializers for global variables in the linked shader.
*/
- link_function_calls(prog, linked, shader_list, num_shaders);
+ unsigned num_linking_shaders = num_shaders;
+ for (unsigned i = 0; i < num_shaders; i++)
+ num_linking_shaders += shader_list[i]->num_builtins_to_link;
+
+ gl_shader **linking_shaders =
+ (gl_shader **) calloc(num_linking_shaders, sizeof(gl_shader *));
+
+ memcpy(linking_shaders, shader_list,
+ sizeof(linking_shaders[0]) * num_shaders);
+
+ unsigned idx = num_shaders;
+ for (unsigned i = 0; i < num_shaders; i++) {
+ memcpy(&linking_shaders[idx], shader_list[i]->builtins_to_link,
+ sizeof(linking_shaders[0]) * shader_list[i]->num_builtins_to_link);
+ idx += shader_list[i]->num_builtins_to_link;
+ }
+
+ assert(idx == num_linking_shaders);
+
+ link_function_calls(prog, linked, linking_shaders, num_linking_shaders);
+
+ free(linking_shaders);
return linked;
}
diff --git a/src/glsl/main.cpp b/src/glsl/main.cpp
index cf9a515785..2ecf57f8ce 100644
--- a/src/glsl/main.cpp
+++ b/src/glsl/main.cpp
@@ -219,6 +219,9 @@ compile_shader(struct gl_shader *shader)
shader->symbols = state->symbols;
shader->CompileStatus = !state->error;
shader->Version = state->language_version;
+ memcpy(shader->builtins_to_link, state->builtins_to_link,
+ sizeof(shader->builtins_to_link[0]) * state->num_builtins_to_link);
+ shader->num_builtins_to_link = state->num_builtins_to_link;
if (shader->InfoLog)
talloc_free(shader->InfoLog);
@@ -305,6 +308,7 @@ main(int argc, char **argv)
talloc_free(whole_program);
_mesa_glsl_release_types();
+ _mesa_glsl_release_functions();
return status;
}