From 88e2dbfd10129eab2c7f4a935358a6ab2a18bf65 Mon Sep 17 00:00:00 2001 From: Brian Date: Wed, 10 Jan 2007 13:33:38 -0700 Subject: [PATCH] checkpoint: codegen for global vars w/ initializers --- src/mesa/shader/shader_api.c | 3 +- src/mesa/shader/slang/slang_codegen.c | 365 +++++++++++++++----------- src/mesa/shader/slang/slang_codegen.h | 7 +- src/mesa/shader/slang/slang_compile.c | 20 +- 4 files changed, 228 insertions(+), 167 deletions(-) diff --git a/src/mesa/shader/shader_api.c b/src/mesa/shader/shader_api.c index 69314b225a4..c18bbcec4be 100644 --- a/src/mesa/shader/shader_api.c +++ b/src/mesa/shader/shader_api.c @@ -307,9 +307,10 @@ _mesa_bind_attrib_location(GLcontext *ctx, GLuint program, GLuint index, _slang_remap_attribute(&shProg->VertexProgram->Base, oldIndex, index); } +#if 0 printf("===== post BindAttrib:\n"); _mesa_print_program(&shProg->VertexProgram->Base); - +#endif } diff --git a/src/mesa/shader/slang/slang_codegen.c b/src/mesa/shader/slang/slang_codegen.c index 07ca8107c0a..12e9588579e 100644 --- a/src/mesa/shader/slang/slang_codegen.c +++ b/src/mesa/shader/slang/slang_codegen.c @@ -291,10 +291,12 @@ slang_allocate_storage(slang_gen_context *gc, slang_ir_node *n, n->Store->Size = _slang_sizeof_type_specifier(&n->Var->type.specifier); assert(n->Store->Size > 0); n->Store->Index = _slang_alloc_temporary(gc, n->Store->Size); + /* printf("alloc var %s storage at %d (size %d)\n", (char *) n->Var->a_name, n->Store->Index, n->Store->Size); + */ assert(n->Store->Size > 0); n->Var->declared = GL_TRUE; return; @@ -459,155 +461,6 @@ _slang_output_index(const char *name, GLenum target) } -/** - * Called by compiler when a global variable has been parsed/compiled. - * Here we examine the variable's type to determine what kind of register - * storage will be used. - * - * A uniform such as "gl_Position" will become the register specification - * (PROGRAM_OUTPUT, VERT_RESULT_HPOS). Or, uniform "gl_FogFragCoord" - * will be (PROGRAM_INPUT, FRAG_ATTRIB_FOGC). - * - * Samplers are interesting. For "uniform sampler2D tex;" we'll specify - * (PROGRAM_SAMPLER, index) where index is resolved at link-time to an - * actual texture unit (as specified by the user calling glUniform1i()). - */ -void -_slang_codegen_global_variable(slang_variable *var, struct gl_program *prog, - slang_unit_type type) -{ - const char *varName = (char *) var->a_name; - GLint texIndex; - slang_ir_storage *store = NULL; - int dbg = 0; - - texIndex = sampler_to_texture_index(var->type.specifier.type); - - if (texIndex != -1) { - /* Texture sampler: - * store->File = PROGRAM_SAMPLER - * store->Index = sampler uniform location - * store->Size = texture type index (1D, 2D, 3D, cube, etc) - */ - GLint samplerUniform = _mesa_add_sampler(prog->Parameters, varName); - store = _slang_new_ir_storage(PROGRAM_SAMPLER, samplerUniform, texIndex); - if (dbg) printf("SAMPLER "); - } - else if (var->type.qualifier == slang_qual_uniform) { - /* Uniform variable */ - const GLint size = _slang_sizeof_type_specifier(&var->type.specifier); - if (prog) { - /* user-defined uniform */ - GLint uniformLoc = _mesa_add_uniform(prog->Parameters, varName, size); - store = _slang_new_ir_storage(PROGRAM_UNIFORM, uniformLoc, size); - } - else { - /* pre-defined uniform, like gl_ModelviewMatrix */ - /* We know it's a uniform, but don't allocate storage unless - * it's really used. - */ - - store = _slang_new_ir_storage(PROGRAM_STATE_VAR, -1, size); - - } - if (dbg) printf("UNIFORM "); - } - else if (var->type.qualifier == slang_qual_varying) { - const GLint size = 4; /* XXX fix */ - if (prog) { - /* user-defined varying */ - GLint varyingLoc = _mesa_add_varying(prog->Varying, varName, size); - store = _slang_new_ir_storage(PROGRAM_VARYING, varyingLoc, size); - } - else { - /* pre-defined varying, like gl_Color or gl_TexCoord */ - if (type == slang_unit_fragment_builtin) { - GLint index = _slang_input_index(varName, GL_FRAGMENT_PROGRAM_ARB); - assert(index >= 0); - store = _slang_new_ir_storage(PROGRAM_INPUT, index, size); - assert(index < FRAG_ATTRIB_MAX); - } - else { - GLint index = _slang_output_index(varName, GL_VERTEX_PROGRAM_ARB); - assert(index >= 0); - assert(type == slang_unit_vertex_builtin); - store = _slang_new_ir_storage(PROGRAM_OUTPUT, index, size); - assert(index < VERT_RESULT_MAX); - } - if (dbg) printf("V/F "); - } - if (dbg) printf("VARYING "); - } - else if (var->type.qualifier == slang_qual_const) { - if (prog) { - /* user-defined constant */ - const GLint size = _slang_sizeof_type_specifier(&var->type.specifier); - /* - const GLint index = _mesa_add_named_constant(prog->Parameters); - */ - printf("Global user constant\n"); - abort(); /* XXX fix */ - } - else { - /* pre-defined global constant, like gl_MaxLights */ - GLint size = -1; - store = _slang_new_ir_storage(PROGRAM_CONSTANT, -1, size); - } - if (dbg) printf("CONST "); - } - else if (var->type.qualifier == slang_qual_attribute) { - if (prog) { - /* user-defined vertex attribute */ - const GLint size = _slang_sizeof_type_specifier(&var->type.specifier); - const GLint attr = -1; /* unknown */ - GLint index = _mesa_add_attribute(prog->Attributes, varName, - size, attr); - assert(index >= 0); - store = _slang_new_ir_storage(PROGRAM_INPUT, - VERT_ATTRIB_GENERIC0 + index, size); - } - else { - /* pre-defined vertex attrib */ - GLint index = _slang_input_index(varName, GL_VERTEX_PROGRAM_ARB); - GLint size = 4; /* XXX? */ - assert(index >= 0); - store = _slang_new_ir_storage(PROGRAM_INPUT, index, size); - } - if (dbg) printf("ATTRIB "); - } - else if (var->type.qualifier == slang_qual_fixedinput) { - GLint index = _slang_input_index(varName, GL_FRAGMENT_PROGRAM_ARB); - GLint size = 4; /* XXX? */ - store = _slang_new_ir_storage(PROGRAM_INPUT, index, size); - if (dbg) printf("INPUT "); - } - else if (var->type.qualifier == slang_qual_fixedoutput) { - if (type == slang_unit_vertex_builtin) { - GLint index = _slang_output_index(varName, GL_VERTEX_PROGRAM_ARB); - GLint size = 4; /* XXX? */ - store = _slang_new_ir_storage(PROGRAM_OUTPUT, index, size); - } - else { - assert(type == slang_unit_fragment_builtin); - GLint index = _slang_output_index(varName, GL_FRAGMENT_PROGRAM_ARB); - GLint size = 4; /* XXX? */ - store = _slang_new_ir_storage(PROGRAM_OUTPUT, index, size); - } - if (dbg) printf("OUTPUT "); - } - else { - /* ordinary variable */ - assert(prog); /* shouldn't be any pre-defined, unqualified vars */ - if (dbg) printf("other "); - abort(); - } - if (dbg) printf("GLOBAL VAR %s idx %d\n", (char*) var->a_name, store?store->Index:-2); - - assert(!var->aux); - - var->aux = store; -} - /**********************************************************************/ @@ -1023,10 +876,9 @@ slang_inline_function_call(slang_assemble_ctx * A, slang_function *fun, /* allocate the return var */ resultVar = slang_variable_scope_grow(commaSeq->locals); /* - printf("ALLOC __retVal from scope %p\n", (void*) commaSeq->locals); - */ printf("Alloc __resultTemp in scope %p for retval of calling %s\n", (void*)commaSeq->locals, (char *) fun->header.a_name); + */ resultVar->a_name = slang_atom_pool_atom(A->atoms, "__resultTmp"); resultVar->type = fun->header.type; /* XXX copy? */ @@ -1071,9 +923,11 @@ slang_inline_function_call(slang_assemble_ctx * A, slang_function *fun, substCount = 0; for (i = 0; i < totalArgs; i++) { slang_variable *p = &fun->parameters->variables[i]; + /* printf("Param %d: %s %s \n", i, slang_type_qual_string(p->type.qualifier), (char *) p->a_name); + */ if (p->type.qualifier == slang_qual_inout || p->type.qualifier == slang_qual_out) { /* an output param */ @@ -2110,12 +1964,197 @@ _slang_gen_operation(slang_assemble_ctx * A, slang_operation *oper) } + +/** + * Called by compiler when a global variable has been parsed/compiled. + * Here we examine the variable's type to determine what kind of register + * storage will be used. + * + * A uniform such as "gl_Position" will become the register specification + * (PROGRAM_OUTPUT, VERT_RESULT_HPOS). Or, uniform "gl_FogFragCoord" + * will be (PROGRAM_INPUT, FRAG_ATTRIB_FOGC). + * + * Samplers are interesting. For "uniform sampler2D tex;" we'll specify + * (PROGRAM_SAMPLER, index) where index is resolved at link-time to an + * actual texture unit (as specified by the user calling glUniform1i()). + */ +GLboolean +_slang_codegen_global_variable(slang_assemble_ctx *A, slang_variable *var, + slang_unit_type type) +{ + struct gl_program *prog = A->program; + const char *varName = (char *) var->a_name; + GLint texIndex; + slang_ir_storage *store = NULL; + int dbg = 0; + GLboolean codegen = GL_FALSE; /* generate code for this global? */ + + texIndex = sampler_to_texture_index(var->type.specifier.type); + + if (texIndex != -1) { + /* Texture sampler: + * store->File = PROGRAM_SAMPLER + * store->Index = sampler uniform location + * store->Size = texture type index (1D, 2D, 3D, cube, etc) + */ + GLint samplerUniform = _mesa_add_sampler(prog->Parameters, varName); + store = _slang_new_ir_storage(PROGRAM_SAMPLER, samplerUniform, texIndex); + if (dbg) printf("SAMPLER "); + } + else if (var->type.qualifier == slang_qual_uniform) { + /* Uniform variable */ + const GLint size = _slang_sizeof_type_specifier(&var->type.specifier); + if (prog) { + /* user-defined uniform */ + GLint uniformLoc = _mesa_add_uniform(prog->Parameters, varName, size); + store = _slang_new_ir_storage(PROGRAM_UNIFORM, uniformLoc, size); + } + else { + /* pre-defined uniform, like gl_ModelviewMatrix */ + /* We know it's a uniform, but don't allocate storage unless + * it's really used. + */ + + store = _slang_new_ir_storage(PROGRAM_STATE_VAR, -1, size); + + } + if (dbg) printf("UNIFORM "); + } + else if (var->type.qualifier == slang_qual_varying) { + const GLint size = 4; /* XXX fix */ + if (prog) { + /* user-defined varying */ + GLint varyingLoc = _mesa_add_varying(prog->Varying, varName, size); + store = _slang_new_ir_storage(PROGRAM_VARYING, varyingLoc, size); + } + else { + /* pre-defined varying, like gl_Color or gl_TexCoord */ + if (type == slang_unit_fragment_builtin) { + GLint index = _slang_input_index(varName, GL_FRAGMENT_PROGRAM_ARB); + assert(index >= 0); + store = _slang_new_ir_storage(PROGRAM_INPUT, index, size); + assert(index < FRAG_ATTRIB_MAX); + } + else { + GLint index = _slang_output_index(varName, GL_VERTEX_PROGRAM_ARB); + assert(index >= 0); + assert(type == slang_unit_vertex_builtin); + store = _slang_new_ir_storage(PROGRAM_OUTPUT, index, size); + assert(index < VERT_RESULT_MAX); + } + if (dbg) printf("V/F "); + } + if (dbg) printf("VARYING "); + } + else if (var->type.qualifier == slang_qual_const) { + if (prog) { + /* user-defined constant */ + /* + const GLint size = _slang_sizeof_type_specifier(&var->type.specifier); + const GLint index = _mesa_add_named_constant(prog->Parameters); + */ + printf("Global user constant\n"); + abort(); /* XXX fix */ + } + else { + /* pre-defined global constant, like gl_MaxLights */ + GLint size = -1; + store = _slang_new_ir_storage(PROGRAM_CONSTANT, -1, size); + } + if (dbg) printf("CONST "); + } + else if (var->type.qualifier == slang_qual_attribute) { + if (prog) { + /* user-defined vertex attribute */ + const GLint size = _slang_sizeof_type_specifier(&var->type.specifier); + const GLint attr = -1; /* unknown */ + GLint index = _mesa_add_attribute(prog->Attributes, varName, + size, attr); + assert(index >= 0); + store = _slang_new_ir_storage(PROGRAM_INPUT, + VERT_ATTRIB_GENERIC0 + index, size); + } + else { + /* pre-defined vertex attrib */ + GLint index = _slang_input_index(varName, GL_VERTEX_PROGRAM_ARB); + GLint size = 4; /* XXX? */ + assert(index >= 0); + store = _slang_new_ir_storage(PROGRAM_INPUT, index, size); + } + if (dbg) printf("ATTRIB "); + } + else if (var->type.qualifier == slang_qual_fixedinput) { + GLint index = _slang_input_index(varName, GL_FRAGMENT_PROGRAM_ARB); + GLint size = 4; /* XXX? */ + store = _slang_new_ir_storage(PROGRAM_INPUT, index, size); + if (dbg) printf("INPUT "); + } + else if (var->type.qualifier == slang_qual_fixedoutput) { + if (type == slang_unit_vertex_builtin) { + GLint index = _slang_output_index(varName, GL_VERTEX_PROGRAM_ARB); + GLint size = 4; /* XXX? */ + store = _slang_new_ir_storage(PROGRAM_OUTPUT, index, size); + } + else { + assert(type == slang_unit_fragment_builtin); + GLint index = _slang_output_index(varName, GL_FRAGMENT_PROGRAM_ARB); + GLint size = 4; /* XXX? */ + store = _slang_new_ir_storage(PROGRAM_OUTPUT, index, size); + } + if (dbg) printf("OUTPUT "); + } + else { + /* ordinary variable */ + const GLint size = _slang_sizeof_type_specifier(&var->type.specifier); + const GLint index = -1; + store = _slang_new_ir_storage(PROGRAM_TEMPORARY, index, size); + codegen = GL_TRUE; + assert(prog); /* shouldn't be any pre-defined, unqualified vars */ + } + if (dbg) printf("GLOBAL VAR %s idx %d\n", (char*) var->a_name, + store ? store->Index : -2); + + assert(!var->aux); + var->aux = store; /* save var's storage info */ + + if (codegen) { + slang_ir_node *n; + + n = new_node(IR_VAR_DECL, NULL, NULL); + if (!n) + return GL_FALSE; + n->Var = var; + var->declared = GL_TRUE; + slang_allocate_storage(A->codegen, n, A->program); + + if (var->initializer) { + slang_ir_node *lhs, *rhs, *init; + + /* Generate IR_MOVE instruction to initialize the variable */ + lhs = new_node(IR_VAR, NULL, NULL); + lhs->Var = var; + lhs->Swizzle = SWIZZLE_NOOP; + lhs->Store = store; + + rhs = _slang_gen_operation(A, var->initializer); + init = new_node(IR_MOVE, lhs, rhs); + n = new_seq(n, init); + } + + /* emit code (n) */ + + } + + return GL_TRUE; +} + + /** - * Produce an IR tree from a function AST. + * Produce an IR tree from a function AST (fun->body). * Then call the code emitter to convert the IR tree into gl_program * instructions. */ -struct slang_ir_node_ * +GLboolean _slang_codegen_function(slang_assemble_ctx * A, slang_function * fun) { slang_ir_node *n, *endLabel; @@ -2125,11 +2164,13 @@ _slang_codegen_function(slang_assemble_ctx * A, slang_function * fun) /* we only really generate code for main, all other functions get * inlined. */ - return 0; + return GL_TRUE; /* not an error */ } #if 1 printf("\n*********** codegen_function %s\n", (char *) fun->header.a_name); +#endif +#if 0 slang_print_function(fun, 1); #endif @@ -2137,11 +2178,11 @@ _slang_codegen_function(slang_assemble_ctx * A, slang_function * fun) assert(A->program->Parameters ); assert(A->program->Varying); - A->codegen = _slang_new_codegen_context(); + assert(A->codegen); + /* A->codegen = _slang_new_codegen_context();*/ - /*printf("** Begin Simplify\n");*/ + /* fold constant expressions, etc. */ slang_simplify(fun->body, &A->space, A->atoms); - /*printf("** End Simplify\n");*/ CurFunction = fun; @@ -2159,19 +2200,23 @@ _slang_codegen_function(slang_assemble_ctx * A, slang_function * fun) CurFunction = NULL; -#if 1 +#if 0 printf("************* New AST for %s *****\n", (char*)fun->header.a_name); slang_print_function(fun, 1); +#endif +#if 1 printf("************* IR for %s *******\n", (char*)fun->header.a_name); slang_print_ir(n, 0); - printf("************* End assemble function2 ************\n\n"); + printf("************* End codegen function ************\n\n"); #endif success = _slang_emit_code(n, A->codegen, A->program); /* free codegen context */ + /* _mesa_free(A->codegen); + */ - return n; + return GL_TRUE; } diff --git a/src/mesa/shader/slang/slang_codegen.h b/src/mesa/shader/slang/slang_codegen.h index ad8e2a4fd88..76d364237a3 100644 --- a/src/mesa/shader/slang/slang_codegen.h +++ b/src/mesa/shader/slang/slang_codegen.h @@ -29,14 +29,13 @@ #include "imports.h" #include "slang_compile.h" -#include "slang_ir.h" -extern struct slang_ir_node_ * +extern GLboolean _slang_codegen_function(slang_assemble_ctx *A , struct slang_function_ *fun); -extern void -_slang_codegen_global_variable(slang_variable *var, struct gl_program *prog, +extern GLboolean +_slang_codegen_global_variable(slang_assemble_ctx *A, slang_variable *var, slang_unit_type type); diff --git a/src/mesa/shader/slang/slang_compile.c b/src/mesa/shader/slang/slang_compile.c index 314c32f7077..bb1da271524 100644 --- a/src/mesa/shader/slang/slang_compile.c +++ b/src/mesa/shader/slang/slang_compile.c @@ -38,6 +38,7 @@ #include "slang_preprocess.h" #include "slang_storage.h" #include "slang_error.h" +#include "slang_emit.h" #include "slang_print.h" @@ -247,6 +248,7 @@ typedef struct slang_output_ctx_ slang_var_pool *global_pool; slang_machine *machine; struct gl_program *program; + slang_gen_context *codegen; } slang_output_ctx; /* _slang_compile() */ @@ -1719,8 +1721,20 @@ parse_init_declarator(slang_parse_ctx * C, slang_output_ctx * O, } #if 1 - if (C->global_scope /*&& O->program*/) - _slang_codegen_global_variable(var, O->program, C->type); + if (C->global_scope) { + slang_assemble_ctx A; + + A.file = O->assembly; + A.mach = O->machine; + A.atoms = C->atoms; + A.space.funcs = O->funs; + A.space.structs = O->structs; + A.space.vars = O->vars; + A.codegen = O->codegen; + A.program = O->program; + + _slang_codegen_global_variable(&A, var, C->type); + } #endif /* allocate global address space for a variable with a known size */ @@ -1880,6 +1894,7 @@ parse_function(slang_parse_ctx * C, slang_output_ctx * O, int definition, A.space.structs = O->structs; A.space.vars = O->vars; A.program = O->program; + A.codegen = O->codegen; _slang_reset_error(); @@ -1953,6 +1968,7 @@ parse_code_unit(slang_parse_ctx * C, slang_code_unit * unit, o.global_pool = &unit->object->varpool; o.machine = &unit->object->machine; o.program = program; + o.codegen = _slang_new_codegen_context(); /* parse individual functions and declarations */ while (*C->I != EXTERNAL_NULL) { -- 2.30.2