diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/mesa/shader/prog_instruction.h | 1 | ||||
| -rw-r--r-- | src/mesa/shader/prog_print.c | 2 | ||||
| -rw-r--r-- | src/mesa/shader/slang/slang_assemble_constructor.c | 17 | ||||
| -rw-r--r-- | src/mesa/shader/slang/slang_codegen.c | 198 | ||||
| -rw-r--r-- | src/mesa/shader/slang/slang_emit.c | 69 | ||||
| -rw-r--r-- | src/mesa/shader/slang/slang_ir.h | 6 | 
6 files changed, 197 insertions, 96 deletions
diff --git a/src/mesa/shader/prog_instruction.h b/src/mesa/shader/prog_instruction.h index 3e88b4e627..f018de82b3 100644 --- a/src/mesa/shader/prog_instruction.h +++ b/src/mesa/shader/prog_instruction.h @@ -49,6 +49,7 @@  #define SWIZZLE_W    3  #define SWIZZLE_ZERO 4   /**< For SWZ instruction only */  #define SWIZZLE_ONE  5   /**< For SWZ instruction only */ +#define SWIZZLE_NIL  7   /**< used during shader code gen (undefined value) */  /*@}*/  #define MAKE_SWIZZLE4(a,b,c,d) (((a)<<0) | ((b)<<3) | ((c)<<6) | ((d)<<9)) diff --git a/src/mesa/shader/prog_print.c b/src/mesa/shader/prog_print.c index 78ce752f2a..63ff84e345 100644 --- a/src/mesa/shader/prog_print.c +++ b/src/mesa/shader/prog_print.c @@ -86,7 +86,7 @@ program_file_string(enum register_file f)  static const char *  swizzle_string(GLuint swizzle, GLuint negateBase, GLboolean extended)  { -   static const char swz[] = "xyzw01"; +   static const char swz[] = "xyzw01?!";     static char s[20];     GLuint i = 0; diff --git a/src/mesa/shader/slang/slang_assemble_constructor.c b/src/mesa/shader/slang/slang_assemble_constructor.c index a411597130..e045f2f6d2 100644 --- a/src/mesa/shader/slang/slang_assemble_constructor.c +++ b/src/mesa/shader/slang/slang_assemble_constructor.c @@ -31,7 +31,7 @@  #include "imports.h"  #include "slang_assemble.h"  #include "slang_storage.h" - +#include "prog_instruction.h"  /** @@ -46,9 +46,14 @@ _slang_is_swizzle(const char *field, GLuint rows, slang_swizzle * swz)     GLuint i;     GLboolean xyzw = GL_FALSE, rgba = GL_FALSE, stpq = GL_FALSE; -   /* init to default */ +   /* init to undefined. +    * We rely on undefined/nil values to distinguish between +    * regular swizzles and writemasks. +    * For example, the swizzle ".xNNN" is the writemask ".x". +    * That's different than the swizzle ".xxxx". +    */     for (i = 0; i < 4; i++) -      swz->swizzle[i] = i; +      swz->swizzle[i] = SWIZZLE_NIL;     /* the swizzle can be at most 4-component long */     swz->num_components = slang_string_length(field); @@ -113,12 +118,6 @@ _slang_is_swizzle(const char *field, GLuint rows, slang_swizzle * swz)     if ((xyzw && rgba) || (xyzw && stpq) || (rgba && stpq))        return GL_FALSE; -   if (swz->num_components == 1) { -      /* smear */ -      swz->swizzle[3] =  -      swz->swizzle[2] =  -      swz->swizzle[1] = swz->swizzle[0]; -   }     return GL_TRUE;  } diff --git a/src/mesa/shader/slang/slang_codegen.c b/src/mesa/shader/slang/slang_codegen.c index cc2a0b2738..d09883c664 100644 --- a/src/mesa/shader/slang/slang_codegen.c +++ b/src/mesa/shader/slang/slang_codegen.c @@ -609,42 +609,6 @@ new_var(slang_assemble_ctx *A, slang_operation *oper, slang_atom name)  } -static GLboolean -slang_is_writemask(const char *field, GLuint *mask) -{ -   const GLuint n = 4; -   GLuint i, bit, c = 0; - -   for (i = 0; i < n && field[i]; i++) { -      switch (field[i]) { -      case 'x': -      case 'r': -         bit = WRITEMASK_X; -         break; -      case 'y': -      case 'g': -         bit = WRITEMASK_Y; -         break; -      case 'z': -      case 'b': -         bit = WRITEMASK_Z; -         break; -      case 'w': -      case 'a': -         bit = WRITEMASK_W; -         break; -      default: -         return GL_FALSE; -      } -      if (c & bit) -         return GL_FALSE; -      c |= bit; -   } -   *mask = c; -   return GL_TRUE; -} - -  /**   * Check if the given function is really just a wrapper for a   * basic assembly instruction. @@ -1961,6 +1925,111 @@ _slang_gen_variable(slang_assemble_ctx * A, slang_operation *oper)  /** + * Some write-masked assignments are simple, but others are hard. + * Simple example: + *    vec3 v; + *    v.xy = vec2(a, b); + * Hard example: + *    vec3 v; + *    v.yz = vec2(a, b); + * this would have to be transformed/swizzled into: + *    v.yz = vec2(a, b).*xy*         (* = don't care) + * Instead, we'll effectively do this: + *    v.y = vec2(a, b).xxxx; + *    v.z = vec2(a, b).yyyy; + * + */ +static GLboolean +_slang_simple_writemask(GLuint writemask) +{ +   switch (writemask) { +   case WRITEMASK_X: +   case WRITEMASK_Y: +   case WRITEMASK_Z: +   case WRITEMASK_W: +   case WRITEMASK_XY: +   case WRITEMASK_XYZ: +   case WRITEMASK_XYZW: +      return GL_TRUE; +   default: +      return GL_FALSE; +   } +} + + +/** + * Convert the given swizzle into a writemask.  In some cases this + * is trivial, in other cases, we'll need to also swizzle the right + * hand side to put components in the right places. + * \param swizzle  the incoming swizzle + * \param writemaskOut  returns the writemask + * \param swizzleOut  swizzle to apply to the right-hand-side + * \return GL_FALSE for simple writemasks, GL_TRUE for non-simple + */ +static GLboolean +swizzle_to_writemask(GLuint swizzle, +                     GLuint *writemaskOut, GLuint *swizzleOut) +{ +   GLuint mask = 0x0, newSwizzle[4]; +   GLint i, size; + +   /* make new dst writemask, compute size */ +   for (i = 0; i < 4; i++) { +      const GLuint swz = GET_SWZ(swizzle, i); +      if (swz == SWIZZLE_NIL) { +         /* end */ +         break; +      } +      assert(swz >= 0 && swz <= 3); +      mask |= (1 << swz); +   } +   assert(mask <= 0xf); +   size = i;  /* number of components in mask/swizzle */ + +   *writemaskOut = mask; + +   /* make new src swizzle, by inversion */ +   for (i = 0; i < 4; i++) { +      newSwizzle[i] = i; /*identity*/ +   } +   for (i = 0; i < size; i++) { +      const GLuint swz = GET_SWZ(swizzle, i); +      newSwizzle[swz] = i; +   } +   *swizzleOut = MAKE_SWIZZLE4(newSwizzle[0], +                               newSwizzle[1], +                               newSwizzle[2], +                               newSwizzle[3]); + +   if (_slang_simple_writemask(mask)) { +      if (size >= 1) +         assert(GET_SWZ(*swizzleOut, 0) == SWIZZLE_X); +      if (size >= 2) +         assert(GET_SWZ(*swizzleOut, 1) == SWIZZLE_Y); +      if (size >= 3) +         assert(GET_SWZ(*swizzleOut, 2) == SWIZZLE_Z); +      if (size >= 4) +         assert(GET_SWZ(*swizzleOut, 3) == SWIZZLE_W); +      return GL_TRUE; +   } +   else +      return GL_FALSE; +} + + +static slang_ir_node * +_slang_gen_swizzle(slang_ir_node *child, GLuint swizzle) +{ +   slang_ir_node *n = new_node(IR_SWIZZLE, child, NULL); +   if (n) { +      n->Store = _slang_new_ir_storage(PROGRAM_UNDEFINED, -1, -1); +      n->Store->Swizzle = swizzle; +   } +   return n; +} + + +/**   * Generate IR tree for an assignment (=).   */  static slang_ir_node * @@ -1982,26 +2051,21 @@ _slang_gen_assignment(slang_assemble_ctx * A, slang_operation *oper)        return n;     }     else { -      slang_operation *lhs = &oper->children[0]; -      slang_ir_node *n, *c0, *c1; -      GLuint mask = WRITEMASK_XYZW; -      if (lhs->type == slang_oper_field) { -         /* XXXX this is a hack! */ -         /* writemask */ -         if (!slang_is_writemask((char *) lhs->a_id, &mask)) -            mask = WRITEMASK_XYZW; -         lhs = &lhs->children[0]; -      } -      c0 = _slang_gen_operation(A, lhs); -      c1 = _slang_gen_operation(A, &oper->children[1]); -      if (c0 && c1) { -         n = new_node(IR_MOVE, c0, c1); -         /*assert(c1->Opcode != IR_SEQ);*/ -         if (c0->Writemask != WRITEMASK_XYZW) -            /* XXX this is a hack! */ -            n->Writemask = c0->Writemask; -         else -            n->Writemask = mask; +      slang_ir_node *n, *lhs, *rhs; +      lhs = _slang_gen_operation(A, &oper->children[0]); +      rhs = _slang_gen_operation(A, &oper->children[1]); +      if (lhs && rhs) { +         /* convert lhs swizzle into writemask */ +         GLuint writemask, newSwizzle; +         if (!swizzle_to_writemask(lhs->Store->Swizzle, +                                   &writemask, &newSwizzle)) { +            /* Non-simple writemask, need to swizzle right hand side in +             * order to put components into the right place. +             */ +            rhs = _slang_gen_swizzle(rhs, newSwizzle); +         } +         n = new_node(IR_MOVE, lhs, rhs); +         n->Writemask = writemask;           return n;        }        else { @@ -2011,20 +2075,6 @@ _slang_gen_assignment(slang_assemble_ctx * A, slang_operation *oper)  } -static slang_ir_node * -_slang_gen_swizzle(slang_ir_node *child, GLuint swizzle) -{ -   slang_ir_node *n = new_node(IR_SWIZZLE, child, NULL); -   if (n) { -      n->Store = _slang_new_ir_storage(child->Store->File, -                                       child->Store->Index, -                                       child->Store->Size); -      n->Store->Swizzle = swizzle; -   } -   return n; -} - -  /**   * Generate IR tree for referencing a field in a struct (or basic vector type)   */ @@ -2101,13 +2151,17 @@ _slang_gen_subscript(slang_assemble_ctx * A, slang_operation *oper)        index = (GLint) oper->children[1].literal[0];        if (oper->children[1].type != slang_oper_literal_int ||            index >= max) { -         RETURN_ERROR("Invalid array index", 0); +         RETURN_ERROR("Invalid array index for vector type", 0);        }        n = _slang_gen_operation(A, &oper->children[0]);        if (n) {           /* use swizzle to access the element */ -         n = _slang_gen_swizzle(n, SWIZZLE_X + index); +         GLuint swizzle = MAKE_SWIZZLE4(SWIZZLE_X + index, +                                        SWIZZLE_NIL, +                                        SWIZZLE_NIL, +                                        SWIZZLE_NIL); +         n = _slang_gen_swizzle(n, swizzle);           /*n->Store = _slang_clone_ir_storage_swz(n->Store, */           n->Writemask = WRITEMASK_X << index;        } diff --git a/src/mesa/shader/slang/slang_emit.c b/src/mesa/shader/slang/slang_emit.c index 1c945fa0ba..0626f7a643 100644 --- a/src/mesa/shader/slang/slang_emit.c +++ b/src/mesa/shader/slang/slang_emit.c @@ -424,7 +424,12 @@ storage_to_src_reg(struct prog_src_register *src, const slang_ir_storage *st)     if (st->Swizzle != SWIZZLE_NOOP)        src->Swizzle = st->Swizzle;     else -      src->Swizzle = defaultSwizzle[st->Size - 1]; +      src->Swizzle = defaultSwizzle[st->Size - 1]; /*XXX really need this?*/ + +   assert(GET_SWZ(src->Swizzle, 0) != SWIZZLE_NIL); +   assert(GET_SWZ(src->Swizzle, 1) != SWIZZLE_NIL); +   assert(GET_SWZ(src->Swizzle, 2) != SWIZZLE_NIL); +   assert(GET_SWZ(src->Swizzle, 3) != SWIZZLE_NIL);  } @@ -975,6 +980,57 @@ emit_cond(slang_var_table *vt, slang_ir_node *n, struct gl_program *prog)  } +/** + * 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]); +} + + +static struct prog_instruction * +emit_swizzle(slang_var_table *vt, slang_ir_node *n, struct gl_program *prog) +{ +   GLuint swizzle; + +   /* swizzled storage access */ +   (void) emit(vt, n->Children[0], prog); + +   /* "pull-up" the child's storage info, applying our swizzle info */ +   n->Store->File  = n->Children[0]->Store->File; +   n->Store->Index = n->Children[0]->Store->Index; +   n->Store->Size  = n->Children[0]->Store->Size; +   /*n->Var = n->Children[0]->Var; XXX for debug */ +   assert(n->Store->Index >= 0); + +   swizzle = fix_swizzle(n->Store->Swizzle); +#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 + +   /* apply this swizzle to child's swizzle to get composed swizzle */ +   n->Store->Swizzle = swizzle_swizzle(n->Children[0]->Store->Swizzle, +                                       swizzle); +   return NULL; +} + +  static struct prog_instruction *  emit(slang_var_table *vt, slang_ir_node *n, struct gl_program *prog)  { @@ -1060,16 +1116,7 @@ emit(slang_var_table *vt, slang_ir_node *n, struct gl_program *prog)        return NULL; /* no instruction */     case IR_SWIZZLE: -      /* swizzled storage access */ -      (void) emit(vt, n->Children[0], prog); -      /* "pull-up" the child's storage info, applying our swizzle info */ -      n->Store->File  = n->Children[0]->Store->File; -      n->Store->Index = n->Children[0]->Store->Index; -      n->Store->Size  = n->Children[0]->Store->Size; -      assert(n->Store->Index >= 0); -      n->Store->Swizzle = swizzle_swizzle(n->Children[0]->Store->Swizzle, -                                          n->Store->Swizzle); -      return NULL; +      return emit_swizzle(vt, n, prog);     /* Simple arithmetic */     /* unary */ diff --git a/src/mesa/shader/slang/slang_ir.h b/src/mesa/shader/slang/slang_ir.h index 4b696c5c13..5fd72be36a 100644 --- a/src/mesa/shader/slang/slang_ir.h +++ b/src/mesa/shader/slang/slang_ir.h @@ -121,17 +121,17 @@ typedef struct _slang_ir_storage slang_ir_storage;  /**   * Intermediate Representation (IR) tree node - * Basically a binary tree, but IR_LRP has three children. + * Basically a binary tree, but IR_LRP and IR_CLAMP have three children.   */  typedef struct slang_ir_node_  {     slang_ir_opcode Opcode;     struct slang_ir_node_ *Children[3];     const char *Comment; -   const char *Target; +   const char *Target;  /**< Branch target string */     GLuint Writemask;  /**< If Opcode == IR_MOVE */     GLfloat Value[4];    /**< If Opcode == IR_FLOAT */ -   slang_variable *Var; +   slang_variable *Var;  /**< If Opcode == IR_VAR or IR_VAR_DECL */     slang_ir_storage *Store;  /**< location of result of this operation */  } slang_ir_node;  | 
