mesa: rework array/struct addressing code.
authorBrian Paul <brian.paul@tungstengraphics.com>
Fri, 18 Jul 2008 20:44:01 +0000 (14:44 -0600)
committerBrian Paul <brian.paul@tungstengraphics.com>
Fri, 18 Jul 2008 20:46:42 +0000 (14:46 -0600)
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.

src/mesa/shader/slang/slang_builtin.c
src/mesa/shader/slang/slang_codegen.c
src/mesa/shader/slang/slang_emit.c
src/mesa/shader/slang/slang_emit.h
src/mesa/shader/slang/slang_ir.c
src/mesa/shader/slang/slang_ir.h
src/mesa/shader/slang/slang_vartable.c

index f0f59aa87a156c2592225f019a2647732b07d491..f99a59e3e1b45a47d869cd49d5e5d38a00922582 100644 (file)
@@ -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;
 }
index 9d5721214f6df07e14790bf4e86a9a2180fc03f6..6261aab23c42f0d51a8e9612226725b2bb85d4af 100644 (file)
@@ -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) {
index c997c11a7debc6a5222da314990eab36ebfa5df4..ec8ed0b4e8859f2eb09581432e89f1f2baa68f9b 100644 (file)
@@ -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 */
 }
 
index 7d70b3311b866ea5595ffffef45496995d88a2c6..153e872d7401ce9f23a30537a4a15de9e1c1e940 100644 (file)
@@ -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,
index 16c36aad0c1eb878cf6f52060a1494caf117a380..ce4a198025e4d06ba6e08737bc38e0b259bf4b86 100644 (file)
@@ -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
index ba0735d64dd69907d87a9a8482eba0b92772966b..61ff649e5cce7bdb49ed84070bbfd24601cb7565 100644 (file)
@@ -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);
 
index 7bc92ea2975e407727b89a9ba69a04a775c29c1d..68b4e00be0354f70143a8d222e71d2eb15ddfe22 100644 (file)
@@ -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);