From: Brian Paul Date: Fri, 18 Jul 2008 20:44:01 +0000 (-0600) Subject: mesa: rework array/struct addressing code. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=7218626cf5ecc00fc7ef994253c20c9a2df35cc2;p=mesa.git mesa: rework array/struct addressing code. The slang_ir_storage type now has a pointer to parent storage to represent storage of an array element within an array, or a field within a struct. This fixes some problems related to addressing of fields/elements in non- trivial cases. More work to follow. --- diff --git a/src/mesa/shader/slang/slang_builtin.c b/src/mesa/shader/slang/slang_builtin.c index f0f59aa87a1..f99a59e3e1b 100644 --- a/src/mesa/shader/slang/slang_builtin.c +++ b/src/mesa/shader/slang/slang_builtin.c @@ -35,6 +35,7 @@ #include "shader/prog_parameter.h" #include "shader/prog_statevars.h" #include "shader/slang/slang_ir.h" +#include "shader/slang/slang_emit.h" #include "shader/slang/slang_builtin.h" @@ -438,8 +439,13 @@ _slang_alloc_statevar(slang_ir_node *n, pos = lookup_statevar(var, index1, index2, field, &swizzle, paramList); assert(pos >= 0); if (pos >= 0) { - n0->Store->Index = pos; - n0->Store->Swizzle = swizzle; + /* XXX should overwrite Store's fields instead of changing pointers + * since there may be a child storage_info pointing to this one. + */ + n0->Store = _slang_new_ir_storage_swz(PROGRAM_STATE_VAR, + pos, + n0->Store->Size, + swizzle); } return pos; } diff --git a/src/mesa/shader/slang/slang_codegen.c b/src/mesa/shader/slang/slang_codegen.c index 9d5721214f6..6261aab23c4 100644 --- a/src/mesa/shader/slang/slang_codegen.c +++ b/src/mesa/shader/slang/slang_codegen.c @@ -43,6 +43,7 @@ #include "shader/program.h" #include "shader/prog_instruction.h" #include "shader/prog_parameter.h" +#include "shader/prog_print.h" #include "shader/prog_statevars.h" #include "slang_typeinfo.h" #include "slang_codegen.h" @@ -243,7 +244,12 @@ _slang_attach_storage(slang_ir_node *n, slang_variable *var) } else { /* alloc new storage info */ - n->Store = _slang_new_ir_storage(PROGRAM_UNDEFINED, -1, -5); + n->Store = _slang_new_ir_storage(PROGRAM_UNDEFINED, -7, -5); +#if 0 + printf("%s var=%s Store=%p Size=%d\n", __FUNCTION__, + (char*) var->a_name, + (void*) n->Store, n->Store->Size); +#endif if (n->Var) n->Var->aux = n->Store; assert(n->Var->aux); @@ -658,6 +664,9 @@ new_var(slang_assemble_ctx *A, slang_operation *oper, slang_atom name) n = new_node0(IR_VAR); if (n) { _slang_attach_storage(n, var); + /* + printf("new_var %s store=%p\n", (char*)name, (void*) n->Store); + */ } return n; } @@ -935,6 +944,18 @@ slang_substitute(slang_assemble_ctx *A, slang_operation *oper, * __asm vec4_lrp __retVal, a, y, x; * } * + * + * A call to + * r = mix(p1, p2, p3); + * + * Becomes: + * + * mov + * / \ + * r vec4_lrp + * / | \ + * p3 p2 p1 + * * We basically translate a SLANG_OPER_CALL into a SLANG_OPER_ASM. */ static slang_operation * @@ -974,10 +995,10 @@ slang_inline_asm_function(slang_assemble_ctx *A, slang_operation_copy(inlined, &fun->body->children[0]); if (haveRetValue) { /* get rid of the __retVal child */ - for (i = 0; i < numArgs; i++) { + inlined->num_children--; + for (i = 0; i < inlined->num_children; i++) { inlined->children[i] = inlined->children[i + 1]; } - inlined->num_children--; } /* now do formal->actual substitutions */ @@ -1593,13 +1614,13 @@ _slang_gen_asm(slang_assemble_ctx *A, slang_operation *oper, if (info->NumParams == oper->num_children) { /* Storage for result is not specified. - * Children[0], [1] are the operands. + * Children[0], [1], [2] are the operands. */ firstOperand = 0; } else { /* Storage for result (child[0]) is specified. - * Children[1], [2] are the operands. + * Children[1], [2], [3] are the operands. */ firstOperand = 1; } @@ -1634,7 +1655,8 @@ _slang_gen_asm(slang_assemble_ctx *A, slang_operation *oper, n->Store = get_store(n0); n->Writemask = writemask; - assert(n->Store->File != PROGRAM_UNDEFINED); + assert(n->Store->File != PROGRAM_UNDEFINED || + n->Store->Parent); _slang_free(n0); } @@ -2071,7 +2093,7 @@ _slang_gen_temporary(GLint size) slang_ir_storage *store; slang_ir_node *n = NULL; - store = _slang_new_ir_storage(PROGRAM_TEMPORARY, -1, size); + store = _slang_new_ir_storage(PROGRAM_TEMPORARY, -2, size); if (store) { n = new_node0(IR_VAR_DECL); if (n) { @@ -2092,17 +2114,15 @@ static slang_ir_node * _slang_gen_var_decl(slang_assemble_ctx *A, slang_variable *var) { slang_ir_node *n; + /*assert(!var->declared);*/ var->declared = GL_TRUE; + assert(!is_sampler_type(&var->type)); + n = new_node0(IR_VAR_DECL); if (n) { _slang_attach_storage(n, var); -#if 0 - printf("%s var %p %s store=%p\n", - __FUNCTION__, (void *) var, (char *) var->a_name, - (void *) n->Store); -#endif assert(var->aux); assert(n->Store == var->aux); assert(n->Store); @@ -2110,6 +2130,13 @@ _slang_gen_var_decl(slang_assemble_ctx *A, slang_variable *var) n->Store->File = PROGRAM_TEMPORARY; n->Store->Size = _slang_sizeof_type_specifier(&n->Var->type.specifier); + +#if 0 + printf("%s var %p %s store=%p index=%d size=%d\n", + __FUNCTION__, (void *) var, (char *) var->a_name, + (void *) n->Store, n->Store->Index, n->Store->Size); +#endif + if (var->array_len > 0) { /* this is an array */ /* round up element size to mult of 4 */ @@ -2118,8 +2145,27 @@ _slang_gen_var_decl(slang_assemble_ctx *A, slang_variable *var) sz *= var->array_len; n->Store->Size = sz; } - A->program->NumTemporaries++; + assert(n->Store->Size > 0); + + /* setup default swizzle for storing the variable */ + switch (n->Store->Size) { + case 2: + n->Store->Swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, + SWIZZLE_NIL, SWIZZLE_NIL); + break; + case 3: + n->Store->Swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, + SWIZZLE_Z, SWIZZLE_NIL); + break; + default: + /* Note that float-sized vars may be allocated in any x/y/z/w + * slot, but that won't be determined until code emit time. + */ + n->Store->Swizzle = SWIZZLE_NOOP; + } + + A->program->NumTemporaries++; /* an approximation */ } return n; } @@ -2400,11 +2446,11 @@ _slang_gen_variable(slang_assemble_ctx * A, slang_operation *oper) static slang_ir_node * _slang_gen_swizzle(slang_ir_node *child, GLuint swizzle) { + /* XXX should rewrite this to use relative/Parent storage */ slang_ir_node *n = new_node1(IR_SWIZZLE, child); assert(child); if (n) { - n->Store = _slang_new_ir_storage(PROGRAM_UNDEFINED, -1, -1); - n->Store->Swizzle = swizzle; + n->Store = _slang_new_ir_storage_swz(PROGRAM_UNDEFINED, -1, -1, swizzle); } return n; } @@ -2495,7 +2541,7 @@ _slang_gen_assignment(slang_assemble_ctx * A, slang_operation *oper) * Generate IR tree for referencing a field in a struct (or basic vector type) */ static slang_ir_node * -_slang_gen_field(slang_assemble_ctx * A, slang_operation *oper) +_slang_gen_struct_field(slang_assemble_ctx * A, slang_operation *oper) { slang_typeinfo ti; @@ -2548,7 +2594,8 @@ _slang_gen_field(slang_assemble_ctx * A, slang_operation *oper) /* oper->a_id is the field name */ slang_ir_node *base, *n; slang_typeinfo field_ti; - GLint fieldSize, fieldOffset = -1; + GLint fieldSize, fieldOffset = -1, swz; + /* type of field */ slang_typeinfo_construct(&field_ti); _slang_typeof_operation(A, oper, &field_ti); @@ -2573,20 +2620,27 @@ _slang_gen_field(slang_assemble_ctx * A, slang_operation *oper) } n = new_node1(IR_FIELD, base); - if (n) { - n->Field = (char *) oper->a_id; - n->FieldOffset = fieldOffset; - assert(n->FieldOffset >= 0); - n->Store = _slang_new_ir_storage(base->Store->File, - base->Store->Index, - fieldSize); - } - return n; + if (!n) + return NULL; -#if 0 - _mesa_problem(NULL, "glsl structs/fields not supported yet"); - return NULL; -#endif + + /* setup the storage info for this node */ + swz = fieldOffset % 4; + + n->Field = (char *) oper->a_id; + n->Store = _slang_new_ir_storage_relative(fieldOffset / 4, + fieldSize, + base->Store); + if (fieldSize == 1) + n->Store->Swizzle = MAKE_SWIZZLE4(swz, swz, swz, swz); + else if (fieldSize == 2) + n->Store->Swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, + SWIZZLE_NIL, SWIZZLE_NIL); + else if (fieldSize == 3) + n->Store->Swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, + SWIZZLE_Z, SWIZZLE_NIL); + + return n; } } @@ -2595,7 +2649,7 @@ _slang_gen_field(slang_assemble_ctx * A, slang_operation *oper) * Gen code for array indexing. */ static slang_ir_node * -_slang_gen_subscript(slang_assemble_ctx * A, slang_operation *oper) +_slang_gen_array_element(slang_assemble_ctx * A, slang_operation *oper) { slang_typeinfo array_ti; @@ -2659,21 +2713,24 @@ _slang_gen_subscript(slang_assemble_ctx * A, slang_operation *oper) index = _slang_gen_operation(A, &oper->children[1]); if (array && index) { /* bounds check */ - if (index->Opcode == IR_FLOAT && - ((int) index->Value[0] < 0 || - (int) index->Value[0] >= arrayLen)) { - slang_info_log_error(A->log, + GLint constIndex = 0; + if (index->Opcode == IR_FLOAT) { + constIndex = (int) index->Value[0]; + if (constIndex < 0 || constIndex >= arrayLen) { + slang_info_log_error(A->log, "Array index out of bounds (index=%d size=%d)", - (int) index->Value[0], arrayLen); - _slang_free_ir_tree(array); - _slang_free_ir_tree(index); - return NULL; + constIndex, arrayLen); + _slang_free_ir_tree(array); + _slang_free_ir_tree(index); + return NULL; + } } elem = new_node2(IR_ELEMENT, array, index); - elem->Store = _slang_new_ir_storage(array->Store->File, - array->Store->Index, - elemSize); + elem->Store = _slang_new_ir_storage_relative(constIndex, + elemSize, + array->Store); + /* XXX try to do some array bounds checking here */ return elem; } @@ -2912,9 +2969,9 @@ _slang_gen_operation(slang_assemble_ctx * A, slang_operation *oper) case SLANG_OPER_IF: return _slang_gen_if(A, oper); case SLANG_OPER_FIELD: - return _slang_gen_field(A, oper); + return _slang_gen_struct_field(A, oper); case SLANG_OPER_SUBSCRIPT: - return _slang_gen_subscript(A, oper); + return _slang_gen_array_element(A, oper); case SLANG_OPER_LITERAL_FLOAT: /* fall-through */ case SLANG_OPER_LITERAL_INT: @@ -3076,8 +3133,7 @@ _slang_codegen_global_variable(slang_assemble_ctx *A, slang_variable *var, GLint index = _slang_input_index(varName, GL_FRAGMENT_PROGRAM_ARB, &swizzle); assert(index >= 0); - store = _slang_new_ir_storage(PROGRAM_INPUT, index, size); - store->Swizzle = swizzle; + store = _slang_new_ir_storage_swz(PROGRAM_INPUT, index, size, swizzle); assert(index < FRAG_ATTRIB_MAX); } else { @@ -3109,8 +3165,7 @@ _slang_codegen_global_variable(slang_assemble_ctx *A, slang_variable *var, &swizzle); GLint size = 4; /* XXX? */ assert(index >= 0); - store = _slang_new_ir_storage(PROGRAM_INPUT, index, size); - store->Swizzle = swizzle; + store = _slang_new_ir_storage_swz(PROGRAM_INPUT, index, size, swizzle); } if (dbg) printf("ATTRIB "); } @@ -3119,8 +3174,7 @@ _slang_codegen_global_variable(slang_assemble_ctx *A, slang_variable *var, GLint index = _slang_input_index(varName, GL_FRAGMENT_PROGRAM_ARB, &swizzle); GLint size = 4; /* XXX? */ - store = _slang_new_ir_storage(PROGRAM_INPUT, index, size); - store->Swizzle = swizzle; + store = _slang_new_ir_storage_swz(PROGRAM_INPUT, index, size, swizzle); if (dbg) printf("INPUT "); } else if (var->type.qualifier == SLANG_QUAL_FIXEDOUTPUT) { diff --git a/src/mesa/shader/slang/slang_emit.c b/src/mesa/shader/slang/slang_emit.c index c997c11a7de..ec8ed0b4e88 100644 --- a/src/mesa/shader/slang/slang_emit.c +++ b/src/mesa/shader/slang/slang_emit.c @@ -126,21 +126,6 @@ _slang_swizzle_swizzle(GLuint swz1, GLuint swz2) } -slang_ir_storage * -_slang_new_ir_storage(enum register_file file, GLint index, GLint size) -{ - slang_ir_storage *st; - st = (slang_ir_storage *) _slang_alloc(sizeof(slang_ir_storage)); - if (st) { - st->File = file; - st->Index = index; - st->Size = size; - st->Swizzle = SWIZZLE_NOOP; - } - return st; -} - - /** * Allocate temporary storage for an intermediate result (such as for * a multiply or add, etc. @@ -184,6 +169,27 @@ free_temp_storage(slang_var_table *vt, slang_ir_node *n) } + +/** + * Remove any SWIZZLE_NIL terms from given swizzle mask (smear prev term). + * Ex: fix_swizzle("zyNN") -> "zyyy" + * XXX should put in the default component for the position... + */ +static GLuint +fix_swizzle(GLuint swizzle) +{ + GLuint swz[4], i; + for (i = 0; i < 4; i++) { + swz[i] = GET_SWZ(swizzle, i); + if (swz[i] == SWIZZLE_NIL) { + swz[i] = swz[i - 1]; + } + } + return MAKE_SWIZZLE4(swz[0], swz[1], swz[2], swz[3]); +} + + + /** * Convert IR storage to an instruction dst register. */ @@ -191,14 +197,27 @@ static void storage_to_dst_reg(struct prog_dst_register *dst, const slang_ir_storage *st, GLuint writemask) { - assert(st->Index >= 0); - dst->File = st->File; - dst->Index = st->Index; + const GLint size = st->Size; + GLint index = st->Index; + GLuint swizzle = st->Swizzle; + + /* if this is storage relative to some parent storage, walk up the tree */ + while (st->Parent) { + st = st->Parent; + index += st->Index; + swizzle = _slang_swizzle_swizzle(st->Swizzle, swizzle); + } + assert(st->File != PROGRAM_UNDEFINED); - assert(st->Size >= 1); - assert(st->Size <= 4); - if (st->Size == 1) { - GLuint comp = GET_SWZ(st->Swizzle, 0); + dst->File = st->File; + + assert(index >= 0); + dst->Index = index; + + assert(size >= 1); + assert(size <= 4); + if (size == 1) { + GLuint comp = GET_SWZ(swizzle, 0); assert(comp < 4); dst->WriteMask = WRITEMASK_X << comp; } @@ -220,17 +239,35 @@ storage_to_src_reg(struct prog_src_register *src, const slang_ir_storage *st) MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_W), MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_W) }; + const GLint size = st->Size; + const GLboolean relAddr = st->RelAddr; + GLint index = st->Index; + GLuint swizzle = st->Swizzle; + + /* if this is storage relative to some parent storage, walk up the tree */ + while (st->Parent) { + st = st->Parent; + index += st->Index; + swizzle = _slang_swizzle_swizzle(st->Swizzle, swizzle); + } + swizzle = fix_swizzle(swizzle); + assert(st->File >= 0); assert(st->File < PROGRAM_UNDEFINED); - assert(st->Size >= 1); - assert(st->Size <= 4); src->File = st->File; - src->Index = st->Index; - src->RelAddr = st->RelAddr; - if (st->Swizzle != SWIZZLE_NOOP) - src->Swizzle = st->Swizzle; + + assert(index >= 0); + src->Index = index; + + assert(size >= 1); + assert(size <= 4); + + src->RelAddr = relAddr; + + if (swizzle != SWIZZLE_NOOP) + src->Swizzle = swizzle; else - src->Swizzle = defaultSwizzle[st->Size - 1]; /*XXX really need this?*/ + src->Swizzle = defaultSwizzle[size - 1]; /*XXX really need this?*/ assert(GET_SWZ(src->Swizzle, 0) <= 3); assert(GET_SWZ(src->Swizzle, 1) <= 3); @@ -549,6 +586,12 @@ emit_arith(slang_emit_info *emitInfo, slang_ir_node *n) ? n->Children[0]->Store->Size : info->ResultSize; if (!alloc_temp_storage(emitInfo, n, size)) return NULL; +#if 0000 /* this should work, but doesn't yet */ + if (size == 2) + n->Writemask = WRITEMASK_XY; + else if (size == 3) + n->Writemask = WRITEMASK_XYZ; +#endif } storage_to_dst_reg(&inst->DstReg, n->Store, n->Writemask); @@ -957,6 +1000,8 @@ emit_move(slang_emit_info *emitInfo, slang_ir_node *n) { struct prog_instruction *inst; + assert(n->Opcode == IR_MOVE); + /* lhs */ emit(emitInfo, n->Children[0]); if (!n->Children[0]->Store || n->Children[0]->Store->Index < 0) { @@ -995,8 +1040,15 @@ emit_move(slang_emit_info *emitInfo, slang_ir_node *n) if (n->Children[1]->Opcode != IR_SWIZZLE) _slang_free_temp(emitInfo->vt, n->Children[1]->Store); *n->Children[1]->Store = *n->Children[0]->Store; + /* fixup the previous instruction (which stored the RHS result) */ assert(n->Children[0]->Store->Index >= 0); + + /* use tighter writemask when possible */ +#if 0000 /* XXX enable this after more testing... */ + if (n->Writemask == WRITEMASK_XYZW) + n->Writemask = inst->DstReg.WriteMask; +#endif storage_to_dst_reg(&inst->DstReg, n->Children[0]->Store, n->Writemask); return inst; } @@ -1408,25 +1460,6 @@ emit_cont_break_if_true(slang_emit_info *emitInfo, slang_ir_node *n) } - -/** - * Remove any SWIZZLE_NIL terms from given swizzle mask (smear prev term). - * Ex: fix_swizzle("zyNN") -> "zyyy" - */ -static GLuint -fix_swizzle(GLuint swizzle) -{ - GLuint swz[4], i; - for (i = 0; i < 4; i++) { - swz[i] = GET_SWZ(swizzle, i); - if (swz[i] == SWIZZLE_NIL) { - swz[i] = swz[i - 1]; - } - } - return MAKE_SWIZZLE4(swz[0], swz[1], swz[2], swz[3]); -} - - /** * Return the number of components actually named by the swizzle. * Recall that swizzles may have undefined/don't-care values. @@ -1451,15 +1484,6 @@ emit_swizzle(slang_emit_info *emitInfo, slang_ir_node *n) inst = emit(emitInfo, n->Children[0]); -#ifdef DEBUG - { - GLuint s = n->Children[0]->Store->Swizzle; - assert(GET_SWZ(s, 0) != SWIZZLE_NIL); - assert(GET_SWZ(s, 1) != SWIZZLE_NIL); - assert(GET_SWZ(s, 2) != SWIZZLE_NIL); - assert(GET_SWZ(s, 3) != SWIZZLE_NIL); - } -#endif /* For debug: n->Var = n->Children[0]->Var; */ /* "pull-up" the child's storage info, applying our swizzle info */ @@ -1475,6 +1499,16 @@ emit_swizzle(slang_emit_info *emitInfo, slang_ir_node *n) /* apply this swizzle to child's swizzle to get composed swizzle */ swizzle = fix_swizzle(n->Store->Swizzle); /* remove the don't care terms */ + +#ifdef DEBUG + { + assert(GET_SWZ(swizzle, 0) != SWIZZLE_NIL); + assert(GET_SWZ(swizzle, 1) != SWIZZLE_NIL); + assert(GET_SWZ(swizzle, 2) != SWIZZLE_NIL); + assert(GET_SWZ(swizzle, 3) != SWIZZLE_NIL); + } +#endif + n->Store->Swizzle = _slang_swizzle_swizzle(n->Children[0]->Store->Swizzle, swizzle); @@ -1489,33 +1523,77 @@ emit_swizzle(slang_emit_info *emitInfo, slang_ir_node *n) static struct prog_instruction * emit_array_element(slang_emit_info *emitInfo, slang_ir_node *n) { + slang_ir_storage *root; + + assert(n->Opcode == IR_ELEMENT); assert(n->Store); - assert(n->Store->File != PROGRAM_UNDEFINED); + assert(n->Store->File == PROGRAM_UNDEFINED); + assert(n->Store->Parent); assert(n->Store->Size > 0); - if (n->Store->File == PROGRAM_STATE_VAR) { - n->Store->Index = _slang_alloc_statevar(n, emitInfo->prog->Parameters); + root = n->Store; + while (root->Parent) + root = root->Parent; + + if (root->File == PROGRAM_STATE_VAR) { + GLint index = _slang_alloc_statevar(n, emitInfo->prog->Parameters); + assert(n->Store->Index == index); return NULL; } if (n->Children[1]->Opcode == IR_FLOAT) { - /* Constant index */ + /* Constant array index */ +#if 0 /* just debug code */ const GLint arrayAddr = n->Children[0]->Store->Index; const GLint index = (GLint) n->Children[1]->Value[0]; - n->Store->Index = arrayAddr + index; + assert(index == n->Store->Index); + assert(arrayAddr == parent->Index); + assert(n->Children[0]->Store == parent); + assert(n->Children[0]->Store->Index == parent->Index); +#endif + + GLint index = n->Store->Index; + + slang_ir_storage *p = n->Store; + index = 0; + while (p->Parent) { + int sz = (p->Size + 3) / 4; + /*printf("element [%d] of size %d (%d)\n", p->Index, p->Size, sz);*/ + index += sz * p->Index; + p = p->Parent; + } + index += p->Index; + + assert(root->File != PROGRAM_UNDEFINED); + + /* resolve new absolute storage location */ + assert(n->Store); + n->Store->File = root->File; + n->Store->Index = index; + n->Store->Parent = NULL; } else { - /* Variable index*/ + /* Variable array index */ struct prog_instruction *inst; + + /* do codegen for array */ + emit(emitInfo, n->Children[0]); + + /* do codegen for array index expression */ + emit(emitInfo, n->Children[1]); + inst = new_instruction(emitInfo, OPCODE_ARL); + storage_to_dst_reg(&inst->DstReg, n->Store, n->Writemask); storage_to_src_reg(&inst->SrcReg[0], n->Children[1]->Store); + inst->DstReg.File = PROGRAM_ADDRESS; + inst->DstReg.Index = 0; /* always address register [0] */ inst->Comment = _mesa_strdup("ARL ADDR"); + n->Store->RelAddr = GL_TRUE; - n->Store->Index = inst->DstReg.Index;/*index of the array*/ - inst->DstReg.Index = 0; /*addr index is always 0*/ } + return NULL; /* no instruction */ } @@ -1526,25 +1604,27 @@ emit_array_element(slang_emit_info *emitInfo, slang_ir_node *n) static struct prog_instruction * emit_struct_field(slang_emit_info *emitInfo, slang_ir_node *n) { - if (n->Store->File == PROGRAM_STATE_VAR) { - n->Store->Index = _slang_alloc_statevar(n, emitInfo->prog->Parameters); - if (n->Store->Index < 0) { + slang_ir_storage *root = n->Store; + + assert(n->Opcode == IR_FIELD); + + while (root->Parent) + root = root->Parent; + + /* If this is the field of a state var, allocate constant/uniform + * storage for it now if we haven't already. + * Note that we allocate storage (uniform/constant slots) for state + * variables here rather than at declaration time so we only allocate + * space for the ones that we actually use! + */ + if (root->File == PROGRAM_STATE_VAR) { + root->Index = _slang_alloc_statevar(n, emitInfo->prog->Parameters); + if (root->Index < 0) { slang_info_log_error(emitInfo->log, "Error parsing state variable"); return NULL; } } - else { - GLint offset = n->FieldOffset / 4; - assert(n->Children[0]->Store->Index >= 0); - n->Store->Index = n->Children[0]->Store->Index + offset; - if (n->Store->Size == 1) { - GLint swz = n->FieldOffset % 4; - n->Store->Swizzle = MAKE_SWIZZLE4(swz, swz, swz, swz); - } - else { - n->Store->Swizzle = SWIZZLE_XYZW; - } - } + return NULL; /* no instruction */ } diff --git a/src/mesa/shader/slang/slang_emit.h b/src/mesa/shader/slang/slang_emit.h index 7d70b3311b8..153e872d740 100644 --- a/src/mesa/shader/slang/slang_emit.h +++ b/src/mesa/shader/slang/slang_emit.h @@ -40,10 +40,6 @@ extern GLuint _slang_swizzle_swizzle(GLuint swz1, GLuint swz2); -extern slang_ir_storage * -_slang_new_ir_storage(enum register_file file, GLint index, GLint size); - - extern GLboolean _slang_emit_code(slang_ir_node *n, slang_var_table *vartable, struct gl_program *prog, GLboolean withEnd, diff --git a/src/mesa/shader/slang/slang_ir.c b/src/mesa/shader/slang/slang_ir.c index 16c36aad0c1..ce4a198025e 100644 --- a/src/mesa/shader/slang/slang_ir.c +++ b/src/mesa/shader/slang/slang_ir.c @@ -51,6 +51,8 @@ static const slang_ir_info IrInfo[] = { { IR_SLT, "IR_SLT", OPCODE_SLT, 4, 2 }, { IR_POW, "IR_POW", OPCODE_POW, 1, 2 }, { IR_EQUAL, "IR_EQUAL", OPCODE_NOP, 1, 2 }, + { IR_NOTEQUAL, "IR_NOTEQUAL", OPCODE_NOP, 1, 2 }, + /* unary ops */ { IR_I_TO_F, "IR_I_TO_F", OPCODE_NOP, 1, 1 }, { IR_F_TO_I, "IR_F_TO_I", OPCODE_INT, 4, 1 }, /* 4 floats to 4 ints */ @@ -109,6 +111,66 @@ _slang_ir_info(slang_ir_opcode opcode) } +/** + * Return a new slang_ir_storage object. + */ +slang_ir_storage * +_slang_new_ir_storage(enum register_file file, GLint index, GLint size) +{ + slang_ir_storage *st; + st = (slang_ir_storage *) _slang_alloc(sizeof(slang_ir_storage)); + if (st) { + st->File = file; + st->Index = index; + st->Size = size; + st->Swizzle = SWIZZLE_NOOP; + st->Parent = NULL; + } + return st; +} + + +/** + * Return a new slang_ir_storage object. + */ +slang_ir_storage * +_slang_new_ir_storage_swz(enum register_file file, GLint index, GLint size, + GLuint swizzle) +{ + slang_ir_storage *st; + st = (slang_ir_storage *) _slang_alloc(sizeof(slang_ir_storage)); + if (st) { + st->File = file; + st->Index = index; + st->Size = size; + st->Swizzle = swizzle; + st->Parent = NULL; + } + return st; +} + + +/** + * Return a new slang_ir_storage object. + */ +slang_ir_storage * +_slang_new_ir_storage_relative(GLint index, GLint size, + slang_ir_storage *parent) +{ + slang_ir_storage *st; + st = (slang_ir_storage *) _slang_alloc(sizeof(slang_ir_storage)); + if (st) { + st->File = PROGRAM_UNDEFINED; + st->Index = index; + st->Size = size; + st->Swizzle = SWIZZLE_NOOP; + st->Parent = parent; + } + return st; +} + + + static const char * _slang_ir_name(slang_ir_opcode opcode) { @@ -116,6 +178,7 @@ _slang_ir_name(slang_ir_opcode opcode) } + #if 0 /* no longer needed with mempool */ /** * Since many IR nodes might point to the same IR storage info, we need diff --git a/src/mesa/shader/slang/slang_ir.h b/src/mesa/shader/slang/slang_ir.h index ba0735d64dd..61ff649e5cc 100644 --- a/src/mesa/shader/slang/slang_ir.h +++ b/src/mesa/shader/slang/slang_ir.h @@ -147,6 +147,11 @@ struct _slang_ir_storage GLuint Swizzle; GLint RefCount; /**< Used during IR tree delete */ GLboolean RelAddr; + + /** If Parent is non-null, Index is relative to parent. + * The other fields are ignored. + */ + struct _slang_ir_storage *Parent; }; typedef struct _slang_ir_storage slang_ir_storage; @@ -165,7 +170,6 @@ typedef struct slang_ir_node_ /** special fields depending on Opcode: */ const char *Field; /**< If Opcode == IR_FIELD */ - int FieldOffset; /**< If Opcode == IR_FIELD */ GLuint Writemask; /**< If Opcode == IR_MOVE */ GLfloat Value[4]; /**< If Opcode == IR_FLOAT */ slang_variable *Var; /**< If Opcode == IR_VAR or IR_VAR_DECL */ @@ -193,6 +197,20 @@ extern const slang_ir_info * _slang_ir_info(slang_ir_opcode opcode); +extern slang_ir_storage * +_slang_new_ir_storage(enum register_file file, GLint index, GLint size); + + +extern slang_ir_storage * +_slang_new_ir_storage_swz(enum register_file file, GLint index, GLint size, + GLuint swizzle); + +extern slang_ir_storage * +_slang_new_ir_storage_relative(GLint index, GLint size, + slang_ir_storage *parent); + + + extern void _slang_free_ir_tree(slang_ir_node *n); diff --git a/src/mesa/shader/slang/slang_vartable.c b/src/mesa/shader/slang/slang_vartable.c index 7bc92ea2975..68b4e00be03 100644 --- a/src/mesa/shader/slang/slang_vartable.c +++ b/src/mesa/shader/slang/slang_vartable.c @@ -1,6 +1,7 @@ #include "main/imports.h" -#include "shader/prog_instruction.h" +#include "shader/program.h" +#include "shader/prog_print.h" #include "slang_compile.h" #include "slang_compile_variable.h" #include "slang_mem.h" @@ -247,14 +248,25 @@ _slang_alloc_var(slang_var_table *vt, slang_ir_storage *store) if (store->Size == 1) { const GLuint comp = i % 4; store->Swizzle = MAKE_SWIZZLE4(comp, comp, comp, comp); - if (dbg) printf("Alloc var sz %d at %d.%c (level %d)\n", - store->Size, store->Index, "xyzw"[comp], t->Level); + } + else if (store->Size == 2) { + store->Swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, + SWIZZLE_NIL, SWIZZLE_NIL); + } + else if (store->Size == 3) { + store->Swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, + SWIZZLE_Z, SWIZZLE_NIL); } else { store->Swizzle = SWIZZLE_NOOP; - if (dbg) printf("Alloc var sz %d at %d.xyzw (level %d)\n", - store->Size, store->Index, t->Level); } + + if (dbg) + printf("Alloc var sz %d at %d.%s (level %d)\n", + store->Size, store->Index, + _mesa_swizzle_string(store->Swizzle, 0, 0), + t->Level); + return GL_TRUE; } @@ -279,6 +291,7 @@ _slang_alloc_temp(slang_var_table *vt, slang_ir_storage *store) store->Size, store->Index, "xyzw"[comp], t->Level); } else { + /* XXX improve swizzled for size=2/3, use for writemask... */ store->Swizzle = SWIZZLE_NOOP; if (dbg) printf("Alloc temp sz %d at %d.xyzw (level %d)\n", store->Size, store->Index, t->Level);