From d5be2acae379783c4aa31243e0a88a9e67e6ca7e Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Tue, 20 Jul 2010 11:29:46 -0700 Subject: [PATCH] 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. --- src/glsl/builtin_function.cpp | 218 ++++++++++++++----- src/glsl/builtins/110_vs/ftransform | 4 +- src/glsl/builtins/tools/generate_builtins.pl | 63 +++++- src/glsl/glsl_parser_extras.h | 4 + src/glsl/ir.h | 3 + src/glsl/linker.cpp | 23 +- src/glsl/main.cpp | 4 + src/mesa/main/mtypes.h | 4 + src/mesa/shader/ir_to_mesa.cpp | 3 + 9 files changed, 261 insertions(+), 65 deletions(-) diff --git a/src/glsl/builtin_function.cpp b/src/glsl/builtin_function.cpp index 967bcd0c40d..10e59e491e4 100644 --- a/src/glsl/builtin_function.cpp +++ b/src/glsl/builtin_function.cpp @@ -25,22 +25,41 @@ #include #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 3a5e8ccecfc..9ca63dc1e34 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 a0b5c1f421c..61d511da1d4 100755 --- a/src/glsl/builtins/tools/generate_builtins.pl +++ b/src/glsl/builtins/tools/generate_builtins.pl @@ -64,22 +64,41 @@ print << 'EOF'; #include #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 b50d9eea676..56f6e18e0bd 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 38b10f5b06d..3a643fc5807 100644 --- a/src/glsl/ir.h +++ b/src/glsl/ir.h @@ -1315,6 +1315,9 @@ extern void _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); diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp index 640e6eee8e0..7c30a40a6ce 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 cf9a5157857..2ecf57f8ce2 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; } diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h index 729c2eaf0fd..f8257d565bf 100644 --- a/src/mesa/main/mtypes.h +++ b/src/mesa/main/mtypes.h @@ -1971,6 +1971,10 @@ struct gl_shader struct exec_list *ir; struct glsl_symbol_table *symbols; + + /** Shaders containing built-in functions that are used for linking. */ + struct gl_shader *builtins_to_link[16]; + unsigned num_builtins_to_link; }; diff --git a/src/mesa/shader/ir_to_mesa.cpp b/src/mesa/shader/ir_to_mesa.cpp index a2b2eb95c82..bfb8e3201ac 100644 --- a/src/mesa/shader/ir_to_mesa.cpp +++ b/src/mesa/shader/ir_to_mesa.cpp @@ -2207,6 +2207,9 @@ _mesa_glsl_compile_shader(GLcontext *ctx, struct gl_shader *shader) shader->CompileStatus = !state->error; shader->InfoLog = state->info_log; 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; /* Retain any live IR, but trash the rest. */ reparent_ir(shader->ir, shader); -- 2.30.2