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:
@@ -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++;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -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 *
|
||||||
|
@@ -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";
|
||||||
|
@@ -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 {
|
||||||
|
@@ -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);
|
||||||
|
|
||||||
|
@@ -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;
|
||||||
}
|
}
|
||||||
|
@@ -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;
|
||||||
}
|
}
|
||||||
|
@@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@@ -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);
|
||||||
|
Reference in New Issue
Block a user