aboutsummaryrefslogtreecommitdiffstats
path: root/src/glsl
diff options
context:
space:
mode:
Diffstat (limited to 'src/glsl')
-rw-r--r--src/glsl/linker.cpp81
-rw-r--r--src/glsl/main.cpp22
2 files changed, 89 insertions, 14 deletions
diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp
index eb10f90a911..e70fa31a2b0 100644
--- a/src/glsl/linker.cpp
+++ b/src/glsl/linker.cpp
@@ -77,9 +77,8 @@ extern "C" {
#include "ir.h"
#include "ir_optimization.h"
#include "program.h"
-extern "C" {
#include "hash_table.h"
-}
+#include "shader_api.h"
/**
* Visitor that determines whether or not a variable is ever written.
@@ -399,6 +398,53 @@ cross_validate_outputs_to_inputs(struct gl_shader_program *prog,
}
+/**
+ * Populates a shaders symbol table with all global declarations
+ */
+static void
+populate_symbol_table(gl_shader *sh)
+{
+ sh->symbols = new(sh) glsl_symbol_table;
+
+ foreach_list(node, sh->ir) {
+ ir_instruction *const inst = (ir_instruction *) node;
+ ir_variable *var;
+ ir_function *func;
+
+ if ((func = inst->as_function()) != NULL) {
+ sh->symbols->add_function(func->name, func);
+ } else if ((var = inst->as_variable()) != NULL) {
+ sh->symbols->add_variable(var->name, var);
+ }
+ }
+}
+
+
+/**
+ * Combine a group of shaders for a single stage to generate a linked shader
+ *
+ * \note
+ * If this function is supplied a single shader, it is cloned, and the new
+ * shader is returned.
+ */
+static struct gl_shader *
+link_intrastage_shaders(struct gl_shader_program *prog,
+ struct gl_shader **shader_list,
+ unsigned num_shaders)
+{
+ (void) prog;
+ assert(num_shaders == 1);
+
+ gl_shader *const linked = _mesa_new_shader(NULL, 0, shader_list[0]->Type);
+ linked->ir = new(linked) exec_list;
+ clone_ir_list(linked->ir, shader_list[0]->ir);
+
+ populate_symbol_table(linked);
+
+ return linked;
+}
+
+
struct uniform_node {
exec_node link;
struct gl_uniform *u;
@@ -807,25 +853,32 @@ link_shaders(struct gl_shader_program *prog)
}
/* FINISHME: Implement intra-stage linking. */
- assert(num_vert_shaders <= 1);
- assert(num_frag_shaders <= 1);
-
- /* Verify that each of the per-target executables is valid.
- */
- if (!validate_vertex_shader_executable(prog, vert_shader_list[0])
- || !validate_fragment_shader_executable(prog, frag_shader_list[0]))
- goto done;
+ prog->_NumLinkedShaders = 0;
+ if (num_vert_shaders > 0) {
+ gl_shader *const sh =
+ link_intrastage_shaders(prog, vert_shader_list, num_vert_shaders);
+ if (sh == NULL)
+ goto done;
- prog->_NumLinkedShaders = 0;
+ if (!validate_vertex_shader_executable(prog, sh))
+ goto done;
- if (num_vert_shaders > 0) {
- prog->_LinkedShaders[prog->_NumLinkedShaders] = vert_shader_list[0];
+ prog->_LinkedShaders[prog->_NumLinkedShaders] = sh;
prog->_NumLinkedShaders++;
}
if (num_frag_shaders > 0) {
- prog->_LinkedShaders[prog->_NumLinkedShaders] = frag_shader_list[0];
+ gl_shader *const sh =
+ link_intrastage_shaders(prog, frag_shader_list, num_frag_shaders);
+
+ if (sh == NULL)
+ goto done;
+
+ if (!validate_fragment_shader_executable(prog, sh))
+ goto done;
+
+ prog->_LinkedShaders[prog->_NumLinkedShaders] = sh;
prog->_NumLinkedShaders++;
}
diff --git a/src/glsl/main.cpp b/src/glsl/main.cpp
index dd43d12474b..8b0bccdcb71 100644
--- a/src/glsl/main.cpp
+++ b/src/glsl/main.cpp
@@ -36,6 +36,25 @@
#include "ir_print_visitor.h"
#include "program.h"
+extern "C" struct gl_shader *
+_mesa_new_shader(GLcontext *ctx, GLuint name, GLenum type);
+
+/* Copied from shader_api.c for the stand-alone compiler.
+ */
+struct gl_shader *
+_mesa_new_shader(GLcontext *ctx, GLuint name, GLenum type)
+{
+ struct gl_shader *shader;
+ assert(type == GL_FRAGMENT_SHADER || type == GL_VERTEX_SHADER);
+ shader = talloc_zero(NULL, struct gl_shader);
+ if (shader) {
+ shader->Type = type;
+ shader->Name = name;
+ shader->RefCount = 1;
+ }
+ return shader;
+}
+
/* Returned string will have 'ctx' as its talloc owner. */
static char *
load_text_file(void *ctx, const char *file_name)
@@ -271,6 +290,9 @@ main(int argc, char **argv)
printf("Info log for linking:\n%s\n", whole_program->InfoLog);
}
+ for (unsigned i = 0; i < whole_program->_NumLinkedShaders; i++)
+ talloc_free(whole_program->_LinkedShaders[i]);
+
talloc_free(whole_program);
_mesa_glsl_release_types();