mesa: glsl: various writemask/swizzle improvements and clean-ups
authorBrian Paul <brian.paul@tungstengraphics.com>
Sat, 19 Jul 2008 01:46:19 +0000 (19:46 -0600)
committerBrian Paul <brian.paul@tungstengraphics.com>
Sat, 19 Jul 2008 01:46:19 +0000 (19:46 -0600)
src/mesa/shader/prog_parameter.c
src/mesa/shader/prog_print.c
src/mesa/shader/slang/slang_codegen.c
src/mesa/shader/slang/slang_emit.c
src/mesa/shader/slang/slang_ir.c

index b302442227d0bf469f113186856c4f80db4080ba..be696385aaf452c561ab1927e521311196f76737 100644 (file)
@@ -348,7 +348,7 @@ _mesa_add_varying(struct gl_program_parameter_list *paramList,
       return i;
    }
    else {
-      assert(size == 4);
+      /*assert(size == 4);*/
       i = _mesa_add_parameter(paramList, PROGRAM_VARYING, name,
                               size, GL_NONE, NULL, NULL);
       return i;
index 014d08f062b035f073b9ebf3448b16bece5d541f..5368ab21877e113f21c4eb1df011b029cfdd40fc 100644 (file)
@@ -313,7 +313,7 @@ reg_string(enum register_file f, GLint index, gl_prog_print_mode mode,
 const char *
 _mesa_swizzle_string(GLuint swizzle, GLuint negateBase, GLboolean extended)
 {
-   static const char swz[] = "xyzw01?!";
+   static const char swz[] = "xyzw01!?";  /* See SWIZZLE_x definitions */
    static char s[20];
    GLuint i = 0;
 
index 6261aab23c42f0d51a8e9612226725b2bb85d4af..d4d2e34dee463f2f1c25896ccbbec459578d0a28 100644 (file)
@@ -1409,6 +1409,27 @@ slang_find_asm_info(const char *name)
 }
 
 
+/**
+ * Return the default swizzle mask for accessing a variable of the
+ * given size (in floats).  If size = 1, comp is used to identify
+ * which component [0..3] of the register holds the variable.
+ */
+static GLuint
+_slang_var_swizzle(GLint size, GLint comp)
+{
+   switch (size) {
+   case 1:
+      return MAKE_SWIZZLE4(comp, comp, comp, comp);
+   case 2:
+      return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_NIL, SWIZZLE_NIL);
+   case 3:
+      return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_NIL);
+   default:
+      return SWIZZLE_XYZW;
+   }
+}
+
+
 /**
  * Some write-masked assignments are simple, but others are hard.
  * Simple example:
@@ -3063,6 +3084,7 @@ _slang_codegen_global_variable(slang_assemble_ctx *A, slang_variable *var,
    int dbg = 0;
    const GLenum datatype = _slang_gltype_from_specifier(&var->type.specifier);
    const GLint texIndex = sampler_to_texture_index(var->type.specifier.type);
+   const GLint size = _slang_sizeof_type_specifier(&var->type.specifier);
 
    if (texIndex != -1) {
       /* This is a texture sampler variable...
@@ -3076,8 +3098,8 @@ _slang_codegen_global_variable(slang_assemble_ctx *A, slang_variable *var,
    }
    else if (var->type.qualifier == SLANG_QUAL_UNIFORM) {
       /* Uniform variable */
-      const GLint size = _slang_sizeof_type_specifier(&var->type.specifier)
-                         * MAX2(var->array_len, 1);
+      const GLint totalSize = size * MAX2(var->array_len, 1);
+      const GLuint swizzle = _slang_var_swizzle(totalSize, 0);
       if (prog) {
          /* user-defined uniform */
          if (datatype == GL_NONE) {
@@ -3106,8 +3128,10 @@ _slang_codegen_global_variable(slang_assemble_ctx *A, slang_variable *var,
          }
          else {
             GLint uniformLoc = _mesa_add_uniform(prog->Parameters, varName,
-                                                 size, datatype);
-            store = _slang_new_ir_storage(PROGRAM_UNIFORM, uniformLoc, size);
+                                                 totalSize, datatype);
+            store = _slang_new_ir_storage_swz(PROGRAM_UNIFORM, uniformLoc,
+                                              totalSize, swizzle);
+            printf("GLOBAL USER UNIFORM %s size %d\n", varName, totalSize);
          }
       }
       else {
@@ -3115,33 +3139,40 @@ _slang_codegen_global_variable(slang_assemble_ctx *A, slang_variable *var,
          /* 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);
+         store = _slang_new_ir_storage_swz(PROGRAM_STATE_VAR, -1,
+                                           totalSize, swizzle);
       }
-      if (dbg) printf("UNIFORM (sz %d) ", size);
+      if (dbg) printf("UNIFORM (sz %d) ", totalSize);
    }
    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);
+         GLuint swizzle = _slang_var_swizzle(size, 0);
+         store = _slang_new_ir_storage_swz(PROGRAM_VARYING, varyingLoc,
+                                           size, swizzle);
       }
       else {
          /* pre-defined varying, like gl_Color or gl_TexCoord */
          if (type == SLANG_UNIT_FRAGMENT_BUILTIN) {
+            /* fragment program input */
             GLuint swizzle;
             GLint index = _slang_input_index(varName, GL_FRAGMENT_PROGRAM_ARB,
                                              &swizzle);
             assert(index >= 0);
-            store = _slang_new_ir_storage_swz(PROGRAM_INPUT, index, size, swizzle);
             assert(index < FRAG_ATTRIB_MAX);
+            store = _slang_new_ir_storage_swz(PROGRAM_INPUT, index,
+                                              size, swizzle);
          }
          else {
+            /* vertex program output */
             GLint index = _slang_output_index(varName, GL_VERTEX_PROGRAM_ARB);
+            GLuint swizzle = _slang_var_swizzle(size, 0);
             assert(index >= 0);
-            assert(type == SLANG_UNIT_VERTEX_BUILTIN);
-            store = _slang_new_ir_storage(PROGRAM_OUTPUT, index, size);
             assert(index < VERT_RESULT_MAX);
+            assert(type == SLANG_UNIT_VERTEX_BUILTIN);
+            store = _slang_new_ir_storage_swz(PROGRAM_OUTPUT, index,
+                                              size, swizzle);
          }
          if (dbg) printf("V/F ");
       }
@@ -3150,7 +3181,6 @@ _slang_codegen_global_variable(slang_assemble_ctx *A, slang_variable *var,
    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);
@@ -3163,7 +3193,6 @@ _slang_codegen_global_variable(slang_assemble_ctx *A, slang_variable *var,
          GLuint swizzle;
          GLint index = _slang_input_index(varName, GL_VERTEX_PROGRAM_ARB,
                                           &swizzle);
-         GLint size = 4; /* XXX? */
          assert(index >= 0);
          store = _slang_new_ir_storage_swz(PROGRAM_INPUT, index, size, swizzle);
       }
@@ -3173,27 +3202,24 @@ _slang_codegen_global_variable(slang_assemble_ctx *A, slang_variable *var,
       GLuint swizzle = SWIZZLE_XYZW; /* silence compiler warning */
       GLint index = _slang_input_index(varName, GL_FRAGMENT_PROGRAM_ARB,
                                        &swizzle);
-      GLint size = 4; /* XXX? */
       store = _slang_new_ir_storage_swz(PROGRAM_INPUT, index, size, swizzle);
       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 {
          GLint index = _slang_output_index(varName, GL_FRAGMENT_PROGRAM_ARB);
-         GLint size = 4; /* XXX? */
+         GLint specialSize = 4; /* treat all fragment outputs as float[4] */
          assert(type == SLANG_UNIT_FRAGMENT_BUILTIN);
-         store = _slang_new_ir_storage(PROGRAM_OUTPUT, index, size);
+         store = _slang_new_ir_storage(PROGRAM_OUTPUT, index, specialSize);
       }
       if (dbg) printf("OUTPUT ");
    }
    else if (var->type.qualifier == SLANG_QUAL_CONST && !prog) {
       /* pre-defined global constant, like gl_MaxLights */
-      const GLint size = _slang_sizeof_type_specifier(&var->type.specifier);
       store = _slang_new_ir_storage(PROGRAM_CONSTANT, -1, size);
       if (dbg) printf("CONST ");
    }
index ec8ed0b4e8859f2eb09581432e89f1f2baa68f9b..291fd7c6ddf339e70b4ab3f2a5a6cd9ad86d3009 100644 (file)
@@ -171,21 +171,33 @@ 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...
+ * Remove any SWIZZLE_NIL terms from given swizzle mask.
+ * For a swizzle like .z??? generate .zzzz (replicate single component).
+ * Else, for .wx?? generate .wxzw (insert 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];
-      }
+   GLuint c0 = GET_SWZ(swizzle, 0),
+      c1 = GET_SWZ(swizzle, 1),
+      c2 = GET_SWZ(swizzle, 2),
+      c3 = GET_SWZ(swizzle, 3);
+   if (c1 == SWIZZLE_NIL && c2 == SWIZZLE_NIL && c3 == SWIZZLE_NIL) {
+      /* smear first component across all positions */
+      c1 = c2 = c3 = c0;
    }
-   return MAKE_SWIZZLE4(swz[0], swz[1], swz[2], swz[3]);
+   else {
+      /* insert default swizzle components */
+      if (c0 == SWIZZLE_NIL)
+         c0 = SWIZZLE_X;
+      if (c1 == SWIZZLE_NIL)
+         c1 = SWIZZLE_Y;
+      if (c2 == SWIZZLE_NIL)
+         c2 = SWIZZLE_Z;
+      if (c3 == SWIZZLE_NIL)
+         c3 = SWIZZLE_W;
+   }
+   return MAKE_SWIZZLE4(c0, c1, c2, c3);
 }
 
 
@@ -216,6 +228,7 @@ storage_to_dst_reg(struct prog_dst_register *dst, const slang_ir_storage *st,
 
    assert(size >= 1);
    assert(size <= 4);
+
    if (size == 1) {
       GLuint comp = GET_SWZ(swizzle, 0);
       assert(comp < 4);
@@ -233,13 +246,6 @@ storage_to_dst_reg(struct prog_dst_register *dst, const slang_ir_storage *st,
 static void
 storage_to_src_reg(struct prog_src_register *src, const slang_ir_storage *st)
 {
-   static const GLuint defaultSwizzle[4] = {
-      MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X),
-      MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_W),
-      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;
@@ -250,7 +256,6 @@ storage_to_src_reg(struct prog_src_register *src, const slang_ir_storage *st)
       index += st->Index;
       swizzle = _slang_swizzle_swizzle(st->Swizzle, swizzle);
    }
-   swizzle = fix_swizzle(swizzle);
 
    assert(st->File >= 0);
    assert(st->File < PROGRAM_UNDEFINED);
@@ -259,20 +264,14 @@ storage_to_src_reg(struct prog_src_register *src, const slang_ir_storage *st)
    assert(index >= 0);
    src->Index = index;
 
-   assert(size >= 1);
-   assert(size <= 4);
+   swizzle = fix_swizzle(swizzle);
+   assert(GET_SWZ(swizzle, 0) <= SWIZZLE_W);
+   assert(GET_SWZ(swizzle, 1) <= SWIZZLE_W);
+   assert(GET_SWZ(swizzle, 2) <= SWIZZLE_W);
+   assert(GET_SWZ(swizzle, 3) <= SWIZZLE_W);
+   src->Swizzle = swizzle;
 
    src->RelAddr = relAddr;
-
-   if (swizzle != SWIZZLE_NOOP)
-      src->Swizzle = swizzle;
-   else
-      src->Swizzle = defaultSwizzle[size - 1]; /*XXX really need this?*/
-
-   assert(GET_SWZ(src->Swizzle, 0) <= 3);
-   assert(GET_SWZ(src->Swizzle, 1) <= 3);
-   assert(GET_SWZ(src->Swizzle, 2) <= 3);
-   assert(GET_SWZ(src->Swizzle, 3) <= 3);
 }
 
 
@@ -582,8 +581,7 @@ emit_arith(slang_emit_info *emitInfo, slang_ir_node *n)
 
    /* result storage */
    if (!n->Store) {
-      GLint size = n->Children[0]->Store
-         ? n->Children[0]->Store->Size : info->ResultSize;
+      GLint size = info->ResultSize;
       if (!alloc_temp_storage(emitInfo, n, size))
          return NULL;
 #if 0000 /* this should work, but doesn't yet */
@@ -591,6 +589,8 @@ emit_arith(slang_emit_info *emitInfo, slang_ir_node *n)
          n->Writemask = WRITEMASK_XY;
       else if (size == 3)
          n->Writemask = WRITEMASK_XYZ;
+      else if (size == 1)
+         n->Writemask = WRITEMASK_X << GET_SWZ(n->Store->Swizzle,0);
 #endif
    }
 
@@ -1045,10 +1045,9 @@ emit_move(slang_emit_info *emitInfo, slang_ir_node *n)
       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;
    }
index ce4a198025e4d06ba6e08737bc38e0b259bf4b86..a414036a362fda600aad02d4a34cd22408216c26 100644 (file)
@@ -239,20 +239,6 @@ _slang_free_ir_tree(slang_ir_node *n)
 
 
 
-static const char *
-swizzle_string(GLuint swizzle)
-{
-   static char s[6];
-   GLuint i;
-   s[0] = '.';
-   for (i = 1; i < 5; i++) {
-      s[i] = "xyzw"[GET_SWZ(swizzle, i-1)];
-   }
-   s[i] = 0;
-   return s;
-}
-
-
 static const char *
 writemask_string(GLuint writemask)
 {
@@ -410,7 +396,7 @@ _slang_print_ir_tree(const slang_ir_node *n, int indent)
    case IR_VAR:
       printf("VAR %s%s at %s  store %p\n",
              (n->Var ? (char *) n->Var->a_name : "TEMP"),
-             swizzle_string(n->Store->Swizzle),
+             _mesa_swizzle_string(n->Store->Swizzle, 0, 0),
              storage_string(n->Store), (void*) n->Store);
       break;
    case IR_VAR_DECL:
@@ -437,7 +423,7 @@ _slang_print_ir_tree(const slang_ir_node *n, int indent)
       break;
    case IR_SWIZZLE:
       printf("SWIZZLE %s of  (store %p) \n",
-             swizzle_string(n->Store->Swizzle), (void*) n->Store);
+             _mesa_swizzle_string(n->Store->Swizzle, 0, 0), (void*) n->Store);
       _slang_print_ir_tree(n->Children[0], indent + 3);
       break;
    default: