diff options
-rw-r--r-- | src/glsl/program.h | 4 | ||||
-rw-r--r-- | src/mesa/Makefile | 2 | ||||
-rw-r--r-- | src/mesa/shader/ir_to_mesa.cpp | 218 | ||||
-rw-r--r-- | src/mesa/shader/shader_api.h | 2 |
4 files changed, 206 insertions, 20 deletions
diff --git a/src/glsl/program.h b/src/glsl/program.h index 3c656e9e7c3..fd8197a45a6 100644 --- a/src/glsl/program.h +++ b/src/glsl/program.h @@ -23,8 +23,11 @@ #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; }; /** diff --git a/src/mesa/Makefile b/src/mesa/Makefile index 84ced279536..e2eeb16c9a4 100644 --- a/src/mesa/Makefile +++ b/src/mesa/Makefile @@ -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 $@) diff --git a/src/mesa/shader/ir_to_mesa.cpp b/src/mesa/shader/ir_to_mesa.cpp index 9fc1268e5ab..02d3f7e2eeb 100644 --- a/src/mesa/shader/ir_to_mesa.cpp +++ b/src/mesa/shader/ir_to_mesa.cpp @@ -34,11 +34,19 @@ #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" */ diff --git a/src/mesa/shader/shader_api.h b/src/mesa/shader/shader_api.h index 9743a23ce63..557e910595a 100644 --- a/src/mesa/shader/shader_api.h +++ b/src/mesa/shader/shader_api.h @@ -30,7 +30,7 @@ #include "main/glheader.h" #include "main/mtypes.h" - +#include "ir_to_mesa.h" /** * Internal functions |