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.
This commit is contained in:
Ian Romanick
2010-07-20 11:29:46 -07:00
parent 4ccd3c548b
commit d5be2acae3
9 changed files with 253 additions and 57 deletions

View File

@@ -25,22 +25,41 @@
#include <stdio.h> #include <stdio.h>
#include "glsl_parser_extras.h" #include "glsl_parser_extras.h"
#include "ir_reader.h" #include "ir_reader.h"
#include "program.h"
void extern "C" struct gl_shader *
read_builtins(_mesa_glsl_parse_state *st, exec_list *instructions, _mesa_new_shader(GLcontext *ctx, GLuint name, GLenum type);
const char **functions, unsigned count)
gl_shader *
read_builtins(GLenum target, const char **functions, unsigned count)
{ {
if (st->error) gl_shader *sh = _mesa_new_shader(NULL, 0, target);
return; 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++) { 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) { if (st->error) {
printf("error reading builtin: %.35s ...\n", functions[i]); 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 */ /* 110 builtins */
@@ -2580,7 +2599,9 @@ static const char *functions_for_110_fs [] = {
/* 110_vs builtins */ /* 110_vs builtins */
static const char *builtins_110_vs_ftransform = { 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" " (signature vec4\n"
" (parameters)\n" " (parameters)\n"
" ((return (expression vec4 *\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))) #define Elements(x) (sizeof(x)/sizeof(*(x)))
#endif #endif
void *builtin_mem_ctx = NULL;
void
_mesa_glsl_release_functions(void)
{
talloc_free(builtin_mem_ctx);
}
void void
_mesa_glsl_initialize_functions(exec_list *instructions, _mesa_glsl_initialize_functions(exec_list *instructions,
struct _mesa_glsl_parse_state *state) struct _mesa_glsl_parse_state *state)
{ {
if (state->language_version >= 110) if (builtin_mem_ctx == NULL)
read_builtins(state, instructions, builtin_mem_ctx = talloc_init("GLSL built-in functions");
functions_for_110,
Elements(functions_for_110));
if (state->target == fragment_shader && state->language_version >= 110) state->num_builtins_to_link = 0;
read_builtins(state, instructions, if (state->language_version >= 110) {
functions_for_110_fs, static gl_shader *sh = NULL;
Elements(functions_for_110_fs));
if (state->target == vertex_shader && state->language_version >= 110) if (sh == NULL) {
read_builtins(state, instructions, sh = read_builtins(GL_VERTEX_SHADER, functions_for_110,
functions_for_110_vs, Elements(functions_for_110));
Elements(functions_for_110_vs)); talloc_steal(builtin_mem_ctx, sh);
}
if (state->language_version >= 120) import_prototypes(sh->ir, instructions, state->symbols, state);
read_builtins(state, instructions, state->builtins_to_link[state->num_builtins_to_link] = sh;
functions_for_120, state->num_builtins_to_link++;
Elements(functions_for_120)); }
if (state->language_version >= 130) if (state->target == fragment_shader && state->language_version >= 110) {
read_builtins(state, instructions, static gl_shader *sh = NULL;
functions_for_130,
Elements(functions_for_130));
if (state->target == fragment_shader && state->language_version >= 130) if (sh == NULL) {
read_builtins(state, instructions, sh = read_builtins(GL_VERTEX_SHADER, functions_for_110_fs,
functions_for_130_fs, Elements(functions_for_110_fs));
Elements(functions_for_130_fs)); talloc_steal(builtin_mem_ctx, sh);
}
if (state->ARB_texture_rectangle_enable) import_prototypes(sh->ir, instructions, state->symbols, state);
read_builtins(state, instructions, state->builtins_to_link[state->num_builtins_to_link] = sh;
functions_for_ARB_texture_rectangle, state->num_builtins_to_link++;
Elements(functions_for_ARB_texture_rectangle)); }
if (state->EXT_texture_array_enable) if (state->target == vertex_shader && state->language_version >= 110) {
read_builtins(state, instructions, static gl_shader *sh = NULL;
functions_for_EXT_texture_array,
Elements(functions_for_EXT_texture_array));
if (state->target == fragment_shader && state->EXT_texture_array_enable) if (sh == NULL) {
read_builtins(state, instructions, sh = read_builtins(GL_VERTEX_SHADER, functions_for_110_vs,
functions_for_EXT_texture_array_fs, Elements(functions_for_110_vs));
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++;
}
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++;
}
} }

View File

@@ -1,4 +1,6 @@
((function ftransform ((declare (uniform) mat4 gl_ModelViewProjectionMatrix)
(declare (in) vec4 gl_Vertex)
(function ftransform
(signature vec4 (signature vec4
(parameters) (parameters)
((return (expression vec4 * ((return (expression vec4 *

View File

@@ -64,22 +64,41 @@ print << 'EOF';
#include <stdio.h> #include <stdio.h>
#include "glsl_parser_extras.h" #include "glsl_parser_extras.h"
#include "ir_reader.h" #include "ir_reader.h"
#include "program.h"
void extern "C" struct gl_shader *
read_builtins(_mesa_glsl_parse_state *st, exec_list *instructions, _mesa_new_shader(GLcontext *ctx, GLuint name, GLenum type);
const char **functions, unsigned count)
gl_shader *
read_builtins(GLenum target, const char **functions, unsigned count)
{ {
if (st->error) gl_shader *sh = _mesa_new_shader(NULL, 0, target);
return; 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++) { 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) { if (st->error) {
printf("error reading builtin: %.35s ...\n", functions[i]); 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 EOF
@@ -95,10 +114,22 @@ print << 'EOF';
#define Elements(x) (sizeof(x)/sizeof(*(x))) #define Elements(x) (sizeof(x)/sizeof(*(x)))
#endif #endif
void *builtin_mem_ctx = NULL;
void
_mesa_glsl_release_functions(void)
{
talloc_free(builtin_mem_ctx);
}
void void
_mesa_glsl_initialize_functions(exec_list *instructions, _mesa_glsl_initialize_functions(exec_list *instructions,
struct _mesa_glsl_parse_state *state) 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 EOF
foreach $version_xs (@versions) { foreach $version_xs (@versions) {
@@ -117,10 +148,20 @@ foreach $version_xs (@versions) {
# Not a version...an extension name # Not a version...an extension name
$check = "${check}state->${version}_enable"; $check = "${check}state->${version}_enable";
} }
print " if ($check)\n"; print " if ($check) {\n";
print " read_builtins(state, instructions,\n"; print " static gl_shader *sh = NULL;\n";
print " functions_for_$version_xs,\n"; print "\n";
print " Elements(functions_for_$version_xs));\n\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"; print "}\n";

View File

@@ -125,6 +125,10 @@ struct _mesa_glsl_parse_state {
/** Extensions supported by the OpenGL implementation. */ /** Extensions supported by the OpenGL implementation. */
const struct gl_extensions *extensions; 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 { typedef struct YYLTYPE {

View File

@@ -1315,6 +1315,9 @@ extern void
_mesa_glsl_initialize_functions(exec_list *instructions, _mesa_glsl_initialize_functions(exec_list *instructions,
struct _mesa_glsl_parse_state *state); struct _mesa_glsl_parse_state *state);
extern void
_mesa_glsl_release_functions(void);
extern void extern void
reparent_ir(exec_list *list, void *mem_ctx); reparent_ir(exec_list *list, void *mem_ctx);

View File

@@ -739,7 +739,28 @@ link_intrastage_shaders(struct gl_shader_program *prog,
/* Resolve initializers for global variables in the linked shader. /* 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; return linked;
} }

View File

@@ -219,6 +219,9 @@ compile_shader(struct gl_shader *shader)
shader->symbols = state->symbols; shader->symbols = state->symbols;
shader->CompileStatus = !state->error; shader->CompileStatus = !state->error;
shader->Version = state->language_version; 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) if (shader->InfoLog)
talloc_free(shader->InfoLog); talloc_free(shader->InfoLog);
@@ -305,6 +308,7 @@ main(int argc, char **argv)
talloc_free(whole_program); talloc_free(whole_program);
_mesa_glsl_release_types(); _mesa_glsl_release_types();
_mesa_glsl_release_functions();
return status; return status;
} }

View File

@@ -1971,6 +1971,10 @@ struct gl_shader
struct exec_list *ir; struct exec_list *ir;
struct glsl_symbol_table *symbols; 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;
}; };

View File

@@ -2207,6 +2207,9 @@ _mesa_glsl_compile_shader(GLcontext *ctx, struct gl_shader *shader)
shader->CompileStatus = !state->error; shader->CompileStatus = !state->error;
shader->InfoLog = state->info_log; shader->InfoLog = state->info_log;
shader->Version = state->language_version; 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. */ /* Retain any live IR, but trash the rest. */
reparent_ir(shader->ir, shader); reparent_ir(shader->ir, shader);