glsl2: Start integrating ir_to_mesa.cpp into shader_api.h
authorEric Anholt <eric@anholt.net>
Fri, 25 Jun 2010 19:37:21 +0000 (12:37 -0700)
committerEric Anholt <eric@anholt.net>
Fri, 25 Jun 2010 19:37:21 +0000 (12:37 -0700)
The compiler is now called by the driver, and generates program
instructions.  Parameter lists are still not set up, so the driver
chokes on it shortly thereafter.

src/glsl/program.h
src/mesa/Makefile
src/mesa/shader/ir_to_mesa.cpp
src/mesa/shader/shader_api.h

index 3c656e9e7c32444c055d2c46b29b07a335766451..fd8197a45a6525b1d7655a548d112cc51dbc28eb 100644 (file)
 
 #include <GL/gl.h>
 #include "main/mtypes.h"
+
+extern "C" {
 #include "shader/prog_parameter.h"
 #include "shader/prog_uniform.h"
+}
 
 /**
  * Based on gl_shader in Mesa's mtypes.h.
@@ -41,6 +44,7 @@ struct glsl_shader {
 
    struct exec_list ir;
    struct glsl_symbol_table *symbols;
+   struct gl_shader *mesa_shader;
 };
 
 /**
index 84ced279536ca4b87bb5c651a6973567cf22c6c9..e2eeb16c9a4f6589b42bb48b32da698170f7e0c1 100644 (file)
@@ -36,6 +36,8 @@ MESA_INCLUDES := $(INCLUDE_DIRS)
 ES1_INCLUDES := -I$(TOP)/src/mapi/es1api $(INCLUDE_DIRS)
 ES2_INCLUDES := -I$(TOP)/src/mapi/es2api $(INCLUDE_DIRS)
 MESA_INCLUDES := -I$(TOP)/src/glsl $(MESA_INCLUDES)
+# For symbol_table.h in glsl compiler headers.
+MESA_INCLUDES := -I$(TOP)/src/mesa/shader $(MESA_INCLUDES)
 
 define mesa-cc-c
        @mkdir -p $(dir $@)
index 9fc1268e5ab64e1296260944a2afba2ecf9185ee..02d3f7e2eeb8c5b9067f462e0adbb0e9199c6b47 100644 (file)
 #include "ir_print_visitor.h"
 #include "ir_expression_flattening.h"
 #include "glsl_types.h"
+#include "glsl_parser_extras.h"
+#include "../glsl/program.h"
+#include "ir_optimization.h"
+#include "ast.h"
 
 extern "C" {
 #include "main/mtypes.h"
 #include "shader/prog_instruction.h"
 #include "shader/prog_print.h"
+#include "shader/program.h"
+#include "shader/prog_uniform.h"
+#include "shader/prog_parameter.h"
+#include "shader/shader_api.h"
 }
 
 /**
@@ -87,6 +95,9 @@ class ir_to_mesa_visitor : public ir_visitor {
 public:
    ir_to_mesa_visitor();
 
+   GLcontext *ctx;
+   struct gl_program *prog;
+
    int next_temp;
    int next_constant;
    int next_uniform;
@@ -154,8 +165,7 @@ public:
                                   ir_to_mesa_dst_reg dst,
                                   ir_to_mesa_src_reg src0);
 
-   /* talloc context (the ) */
-   void *ctx;
+   void *mem_ctx;
 };
 
 ir_to_mesa_src_reg ir_to_mesa_undef = {
@@ -240,7 +250,7 @@ ir_to_mesa_visitor::ir_to_mesa_emit_op3(ir_instruction *ir,
                                        ir_to_mesa_src_reg src1,
                                        ir_to_mesa_src_reg src2)
 {
-   ir_to_mesa_instruction *inst = new(ctx) ir_to_mesa_instruction();
+   ir_to_mesa_instruction *inst = new(mem_ctx) ir_to_mesa_instruction();
 
    inst->op = op;
    inst->dst_reg = dst;
@@ -770,8 +780,8 @@ ir_to_mesa_visitor::visit(ir_dereference_variable *ir)
    if (!entry) {
       switch (ir->var->mode) {
       case ir_var_uniform:
-        entry = new(ctx)  temp_entry(ir->var, PROGRAM_UNIFORM,
-                                     this->next_uniform);
+        entry = new(mem_ctx) temp_entry(ir->var, PROGRAM_UNIFORM,
+                                        this->next_uniform);
         this->variable_storage.push_tail(entry);
 
         this->next_uniform += type_size(ir->var->type);
@@ -795,13 +805,13 @@ ir_to_mesa_visitor::visit(ir_dereference_variable *ir)
                   ir->var->name);
            abort();
         }
-        entry = new(ctx)  temp_entry(ir->var,
-                                     builtin_var_to_mesa_reg[i].file,
-                                     builtin_var_to_mesa_reg[i].index);
+        entry = new(mem_ctx) temp_entry(ir->var,
+                                        builtin_var_to_mesa_reg[i].file,
+                                        builtin_var_to_mesa_reg[i].index);
         break;
       case ir_var_auto:
-        entry = new(ctx) temp_entry(ir->var, PROGRAM_TEMPORARY,
-                                    this->next_temp);
+        entry = new(mem_ctx) temp_entry(ir->var, PROGRAM_TEMPORARY,
+                                        this->next_temp);
         this->variable_storage.push_tail(entry);
 
         next_temp += type_size(ir->var->type);
@@ -1162,17 +1172,37 @@ print_program(struct prog_instruction *mesa_instructions,
    }
 }
 
-void
-do_ir_to_mesa(exec_list *instructions)
+struct gl_program *
+get_mesa_program(GLcontext *ctx, void *mem_ctx, struct glsl_shader *shader)
 {
    ir_to_mesa_visitor v;
    struct prog_instruction *mesa_instructions, *mesa_inst;
    ir_instruction **mesa_instruction_annotation;
    int i;
+   exec_list *instructions = &shader->ir;
+   struct gl_program *prog;
+   GLenum target;
+
+   switch (shader->Type) {
+   case GL_VERTEX_SHADER:   target = GL_VERTEX_PROGRAM_ARB; break;
+   case GL_FRAGMENT_SHADER: target = GL_FRAGMENT_PROGRAM_ARB; break;
+   default: assert(!"should not be reached"); break;
+   }
 
-   v.ctx = talloc_new(NULL);
+   prog = ctx->Driver.NewProgram(ctx, target, 1);
+   if (!prog)
+      return NULL;
+   prog->Parameters = _mesa_new_parameter_list();
+   prog->Varying = _mesa_new_parameter_list();
+   prog->Attributes = _mesa_new_parameter_list();
+   v.ctx = ctx;
+   v.prog = prog;
+
+   v.mem_ctx = talloc_new(NULL);
    visit_exec_list(instructions, &v);
 
+   prog->NumTemporaries = v.next_temp;
+
    int num_instructions = 0;
    foreach_iter(exec_list_iterator, iter, v.instructions) {
       num_instructions++;
@@ -1181,9 +1211,8 @@ do_ir_to_mesa(exec_list *instructions)
    mesa_instructions =
       (struct prog_instruction *)calloc(num_instructions,
                                        sizeof(*mesa_instructions));
-   mesa_instruction_annotation =
-      (ir_instruction **)calloc(num_instructions,
-                               sizeof(*mesa_instruction_annotation));
+   mesa_instruction_annotation = talloc_array(mem_ctx, ir_instruction *,
+                                             num_instructions);
 
    mesa_inst = mesa_instructions;
    i = 0;
@@ -1205,8 +1234,159 @@ do_ir_to_mesa(exec_list *instructions)
    }
 
    set_branchtargets(mesa_instructions, num_instructions);
-   print_program(mesa_instructions, mesa_instruction_annotation, num_instructions);
+   if (0) {
+      print_program(mesa_instructions, mesa_instruction_annotation,
+                   num_instructions);
+   }
+
+   prog->Instructions = mesa_instructions;
+   prog->NumInstructions = num_instructions;
+
+   _mesa_reference_program(ctx, &shader->mesa_shader->Program, prog);
+
+   return prog;
+}
+
+/* Takes a Mesa gl shader structure and compiles it, returning our Mesa-like
+ * structure with the IR and such attached.
+ */
+static struct glsl_shader *
+_mesa_get_glsl_shader(GLcontext *ctx, void *mem_ctx, struct gl_shader *sh)
+{
+   struct glsl_shader *shader = talloc_zero(mem_ctx, struct glsl_shader);
+   struct _mesa_glsl_parse_state *state;
+
+   shader->Type = sh->Type;
+   shader->Name = sh->Name;
+   shader->RefCount = 1;
+   shader->Source = sh->Source;
+   shader->SourceLen = strlen(sh->Source);
+   shader->mesa_shader = sh;
+
+   state = talloc_zero(shader, struct _mesa_glsl_parse_state);
+   switch (shader->Type) {
+   case GL_VERTEX_SHADER:   state->target = vertex_shader; break;
+   case GL_FRAGMENT_SHADER: state->target = fragment_shader; break;
+   case GL_GEOMETRY_SHADER: state->target = geometry_shader; break;
+   }
+
+   state->scanner = NULL;
+   state->translation_unit.make_empty();
+   state->symbols = new(mem_ctx) glsl_symbol_table;
+   state->info_log = talloc_strdup(shader, "");
+   state->error = false;
+   state->temp_index = 0;
+   state->loop_or_switch_nesting = NULL;
+   state->ARB_texture_rectangle_enable = true;
+
+   _mesa_glsl_lexer_ctor(state, shader->Source);
+   _mesa_glsl_parse(state);
+   _mesa_glsl_lexer_dtor(state);
+
+   shader->ir.make_empty();
+   if (!state->error && !state->translation_unit.is_empty())
+      _mesa_ast_to_hir(&shader->ir, state);
+
+   /* Optimization passes */
+   if (!state->error && !shader->ir.is_empty()) {
+      bool progress;
+      do {
+        progress = false;
+
+        progress = do_function_inlining(&shader->ir) || progress;
+        progress = do_if_simplification(&shader->ir) || progress;
+        progress = do_copy_propagation(&shader->ir) || progress;
+        progress = do_dead_code_local(&shader->ir) || progress;
+        progress = do_dead_code_unlinked(&shader->ir) || progress;
+        progress = do_constant_variable_unlinked(&shader->ir) || progress;
+        progress = do_constant_folding(&shader->ir) || progress;
+        progress = do_vec_index_to_swizzle(&shader->ir) || progress;
+        progress = do_swizzle_swizzle(&shader->ir) || progress;
+      } while (progress);
+   }
+
+   shader->symbols = state->symbols;
+
+   shader->CompileStatus = !state->error;
+   shader->InfoLog = state->info_log;
 
-   free(mesa_instruction_annotation);
-   talloc_free(v.ctx);
+   talloc_free(state);
+
+   return shader;
 }
+
+extern "C" {
+
+void
+_mesa_glsl_compile_shader(GLcontext *ctx, struct gl_shader *sh)
+{
+   struct glsl_shader *shader;
+   TALLOC_CTX *mem_ctx = talloc_new(NULL);
+
+   shader = _mesa_get_glsl_shader(ctx, mem_ctx, sh);
+
+   sh->CompileStatus = shader->CompileStatus;
+   sh->InfoLog = strdup(shader->InfoLog);
+   talloc_free(mem_ctx);
+ }
+
+void
+_mesa_glsl_link_shader(GLcontext *ctx, struct gl_shader_program *prog)
+{
+   struct glsl_program *whole_program;
+   unsigned int i;
+
+   _mesa_clear_shader_program_data(ctx, prog);
+
+   whole_program = talloc_zero(NULL, struct glsl_program);
+   whole_program->LinkStatus = GL_TRUE;
+   whole_program->NumShaders = prog->NumShaders;
+   whole_program->Shaders = talloc_array(whole_program, struct glsl_shader *,
+                                        prog->NumShaders);
+
+   for (i = 0; i < prog->NumShaders; i++) {
+      whole_program->Shaders[i] = _mesa_get_glsl_shader(ctx, whole_program,
+                                                       prog->Shaders[i]);
+      if (!whole_program->Shaders[i]->CompileStatus) {
+        whole_program->InfoLog =
+           talloc_asprintf_append(whole_program->InfoLog,
+                                  "linking with uncompiled shader");
+        whole_program->LinkStatus = GL_FALSE;
+      }
+   }
+
+   prog->Uniforms = _mesa_new_uniform_list();
+   prog->Varying = _mesa_new_parameter_list();
+   _mesa_reference_vertprog(ctx, &prog->VertexProgram, NULL);
+   _mesa_reference_fragprog(ctx, &prog->FragmentProgram, NULL);
+
+   if (whole_program->LinkStatus)
+      link_shaders(whole_program);
+
+   prog->LinkStatus = whole_program->LinkStatus;
+
+   /* FINISHME: This should use the linker-generated code */
+   if (prog->LinkStatus) {
+      for (i = 0; i < prog->NumShaders; i++) {
+        struct gl_program *linked_prog;
+
+        linked_prog = get_mesa_program(ctx, whole_program,
+                                       whole_program->Shaders[i]);
+
+        switch (whole_program->Shaders[i]->Type) {
+        case GL_VERTEX_SHADER:
+           _mesa_reference_vertprog(ctx, &prog->VertexProgram,
+                                    (struct gl_vertex_program *)linked_prog);
+           break;
+        case GL_FRAGMENT_SHADER:
+           _mesa_reference_fragprog(ctx, &prog->FragmentProgram,
+                                    (struct gl_fragment_program *)linked_prog);
+           break;
+        }
+      }
+   }
+
+   talloc_free(whole_program);
+}
+
+} /* extern "C" */
index 9743a23ce63612a9615d9f35a258844dc0b26d20..557e910595acb5889b9bfc5e799f2388b6253d21 100644 (file)
@@ -30,7 +30,7 @@
 
 #include "main/glheader.h"
 #include "main/mtypes.h"
-
+#include "ir_to_mesa.h"
 
 /**
  * Internal functions