tgsi: show textual format representation
[mesa.git] / src / gallium / auxiliary / tgsi / tgsi_text.c
index 187e23ede2676a358387c5cf1503a78cf735c671..91baa01ad8bdebad44ec44ba43f9d7a5166080d2 100644 (file)
@@ -1,6 +1,6 @@
 /**************************************************************************
  * 
- * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * Copyright 2008 VMware, Inc.
  * All Rights Reserved.
  * 
  * Permission is hereby granted, free of charge, to any person obtaining a
@@ -18,7 +18,7 @@
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -195,8 +195,15 @@ static boolean parse_float( const char **pcur, float *val )
    boolean integral_part = FALSE;
    boolean fractional_part = FALSE;
 
-   *val = (float) atof( cur );
+   if (*cur == '0' && *(cur + 1) == 'x') {
+      union fi fi;
+      fi.ui = strtoul(cur, NULL, 16);
+      *val = fi.f;
+      cur += 10;
+      goto out;
+   }
 
+   *val = (float) atof( cur );
    if (*cur == '-' || *cur == '+')
       cur++;
    if (is_digit( cur )) {
@@ -228,10 +235,30 @@ static boolean parse_float( const char **pcur, float *val )
       else
          return FALSE;
    }
+
+out:
    *pcur = cur;
    return TRUE;
 }
 
+static boolean parse_double( const char **pcur, uint32_t *val0, uint32_t *val1)
+{
+   const char *cur = *pcur;
+   union {
+      double dval;
+      uint32_t uval[2];
+   } v;
+
+   v.dval = strtod(cur, (char**)pcur);
+   if (*pcur == cur)
+      return FALSE;
+
+   *val0 = v.uval[0];
+   *val1 = v.uval[1];
+
+   return TRUE;
+}
+
 struct translate_ctx
 {
    const char *text;
@@ -241,7 +268,7 @@ struct translate_ctx
    struct tgsi_token *tokens_end;
    struct tgsi_header *header;
    unsigned processor : 4;
-   int implied_array_size : 5;
+   unsigned implied_array_size : 6;
    unsigned num_immediates;
 };
 
@@ -279,6 +306,10 @@ static boolean parse_header( struct translate_ctx *ctx )
       processor = TGSI_PROCESSOR_VERTEX;
    else if (str_match_nocase_whole( &ctx->cur, "GEOM" ))
       processor = TGSI_PROCESSOR_GEOMETRY;
+   else if (str_match_nocase_whole( &ctx->cur, "TESS_CTRL" ))
+      processor = TGSI_PROCESSOR_TESS_CTRL;
+   else if (str_match_nocase_whole( &ctx->cur, "TESS_EVAL" ))
+      processor = TGSI_PROCESSOR_TESS_EVAL;
    else if (str_match_nocase_whole( &ctx->cur, "COMP" ))
       processor = TGSI_PROCESSOR_COMPUTE;
    else {
@@ -322,7 +353,7 @@ parse_file( const char **pcur, uint *file )
    for (i = 0; i < TGSI_FILE_COUNT; i++) {
       const char *cur = *pcur;
 
-      if (str_match_nocase_whole( &cur, tgsi_file_names[i] )) {
+      if (str_match_nocase_whole( &cur, tgsi_file_name(i) )) {
          *pcur = cur;
          *file = i;
          return TRUE;
@@ -653,6 +684,9 @@ parse_register_dcl(
    eat_opt_white( &cur );
 
    if (cur[0] == '[') {
+      bool is_in = *file == TGSI_FILE_INPUT;
+      bool is_out = *file == TGSI_FILE_OUTPUT;
+
       ++cur;
       ctx->cur = cur;
       if (!parse_register_dcl_bracket( ctx, &brackets[1] ))
@@ -662,7 +696,11 @@ parse_register_dcl(
        * input primitive. so we want to declare just
        * the index relevant to the semantics which is in
        * the second bracket */
-      if (ctx->processor == TGSI_PROCESSOR_GEOMETRY && *file == TGSI_FILE_INPUT) {
+
+      /* tessellation has similar constraints to geometry shader */
+      if ((ctx->processor == TGSI_PROCESSOR_GEOMETRY && is_in) ||
+          (ctx->processor == TGSI_PROCESSOR_TESS_EVAL && is_in) ||
+          (ctx->processor == TGSI_PROCESSOR_TESS_CTRL && (is_in || is_out))) {
          brackets[0] = brackets[1];
          *num_brackets = 1;
       } else {
@@ -718,6 +756,14 @@ parse_dst_operand(
       dst->Dimension.Indirect = 0;
       dst->Dimension.Dimension = 0;
       dst->Dimension.Index = bracket[0].index;
+
+      if (bracket[0].ind_file != TGSI_FILE_NULL) {
+         dst->Dimension.Indirect = 1;
+         dst->DimIndirect.File = bracket[0].ind_file;
+         dst->DimIndirect.Index = bracket[0].ind_index;
+         dst->DimIndirect.Swizzle = bracket[0].ind_comp;
+         dst->DimIndirect.ArrayID = bracket[0].ind_array;
+      }
       bracket[0] = bracket[1];
    }
    dst->Register.Index = bracket[0].index;
@@ -735,8 +781,9 @@ parse_dst_operand(
 static boolean
 parse_optional_swizzle(
    struct translate_ctx *ctx,
-   uint swizzle[4],
-   boolean *parsed_swizzle )
+   uint *swizzle,
+   boolean *parsed_swizzle,
+   int components)
 {
    const char *cur = ctx->cur;
 
@@ -748,7 +795,7 @@ parse_optional_swizzle(
 
       cur++;
       eat_opt_white( &cur );
-      for (i = 0; i < 4; i++) {
+      for (i = 0; i < components; i++) {
          if (uprcase( *cur ) == 'X')
             swizzle[i] = TGSI_SWIZZLE_X;
          else if (uprcase( *cur ) == 'Y')
@@ -803,6 +850,13 @@ parse_src_operand(
       src->Dimension.Indirect = 0;
       src->Dimension.Dimension = 0;
       src->Dimension.Index = bracket[0].index;
+      if (bracket[0].ind_file != TGSI_FILE_NULL) {
+         src->Dimension.Indirect = 1;
+         src->DimIndirect.File = bracket[0].ind_file;
+         src->DimIndirect.Index = bracket[0].ind_index;
+         src->DimIndirect.Swizzle = bracket[0].ind_comp;
+         src->DimIndirect.ArrayID = bracket[0].ind_array;
+      }
       bracket[0] = bracket[1];
    }
    src->Register.Index = bracket[0].index;
@@ -816,7 +870,7 @@ parse_src_operand(
 
    /* Parse optional swizzle.
     */
-   if (parse_optional_swizzle( ctx, swizzle, &parsed_swizzle )) {
+   if (parse_optional_swizzle( ctx, swizzle, &parsed_swizzle, 4 )) {
       if (parsed_swizzle) {
          src->Register.SwizzleX = swizzle[0];
          src->Register.SwizzleY = swizzle[1];
@@ -838,6 +892,35 @@ parse_src_operand(
    return TRUE;
 }
 
+static boolean
+parse_texoffset_operand(
+   struct translate_ctx *ctx,
+   struct tgsi_texture_offset *src )
+{
+   uint file;
+   uint swizzle[3];
+   boolean parsed_swizzle;
+   struct parsed_bracket bracket;
+
+   if (!parse_register_src(ctx, &file, &bracket))
+      return FALSE;
+
+   src->File = file;
+   src->Index = bracket.index;
+
+   /* Parse optional swizzle.
+    */
+   if (parse_optional_swizzle( ctx, swizzle, &parsed_swizzle, 3 )) {
+      if (parsed_swizzle) {
+         src->SwizzleX = swizzle[0];
+         src->SwizzleY = swizzle[1];
+         src->SwizzleZ = swizzle[2];
+      }
+   }
+
+   return TRUE;
+}
+
 static boolean
 match_inst(const char **pcur,
            unsigned *saturate,
@@ -848,7 +931,7 @@ match_inst(const char **pcur,
    /* simple case: the whole string matches the instruction name */
    if (str_match_nocase_whole(&cur, info->mnemonic)) {
       *pcur = cur;
-      *saturate = TGSI_SAT_NONE;
+      *saturate = 0;
       return TRUE;
    }
 
@@ -856,13 +939,7 @@ match_inst(const char **pcur,
       /* the instruction has a suffix, figure it out */
       if (str_match_nocase_whole(&cur, "_SAT")) {
          *pcur = cur;
-         *saturate = TGSI_SAT_ZERO_ONE;
-         return TRUE;
-      }
-
-      if (str_match_nocase_whole(&cur, "_SATNV")) {
-         *pcur = cur;
-         *saturate = TGSI_SAT_MINUS_PLUS_ONE;
+         *saturate = 1;
          return TRUE;
       }
    }
@@ -876,7 +953,7 @@ parse_instruction(
    boolean has_label )
 {
    uint i;
-   uint saturate = TGSI_SAT_NONE;
+   uint saturate = 0;
    const struct tgsi_opcode_info *info;
    struct tgsi_full_instruction inst;
    const char *cur;
@@ -904,7 +981,7 @@ parse_instruction(
       if (!parse_register_1d( ctx, &file, &index ))
          return FALSE;
 
-      if (parse_optional_swizzle( ctx, swizzle, &parsed_swizzle )) {
+      if (parse_optional_swizzle( ctx, swizzle, &parsed_swizzle, 4 )) {
          if (parsed_swizzle) {
             inst.Predicate.SwizzleX = swizzle[0];
             inst.Predicate.SwizzleY = swizzle[1];
@@ -956,13 +1033,18 @@ parse_instruction(
       /*
        * These are not considered tex opcodes here (no additional
        * target argument) however we're required to set the Texture
-       * bit so we can set the number of tex offsets (offsets aren't
-       * actually handled here yet in any case).
+       * bit so we can set the number of tex offsets.
        */
       inst.Instruction.Texture = 1;
       inst.Texture.Texture = TGSI_TEXTURE_UNKNOWN;
    }
 
+   if ((i >= TGSI_OPCODE_LOAD && i <= TGSI_OPCODE_ATOMIMAX) ||
+       i == TGSI_OPCODE_RESQ) {
+      inst.Instruction.Memory = 1;
+      inst.Memory.Qualifier = 0;
+   }
+
    /* Parse instruction operands.
     */
    for (i = 0; i < info->num_dst + info->num_src + info->is_tex; i++) {
@@ -1001,6 +1083,40 @@ parse_instruction(
       }
    }
 
+   cur = ctx->cur;
+   eat_opt_white( &cur );
+   for (i = 0; inst.Instruction.Texture && *cur == ','; i++) {
+         cur++;
+         eat_opt_white( &cur );
+         ctx->cur = cur;
+         if (!parse_texoffset_operand( ctx, &inst.TexOffsets[i] ))
+            return FALSE;
+         cur = ctx->cur;
+         eat_opt_white( &cur );
+   }
+   inst.Texture.NumOffsets = i;
+
+   cur = ctx->cur;
+   eat_opt_white(&cur);
+   for (i = 0; inst.Instruction.Memory && *cur == ','; i++) {
+      uint j;
+      cur++;
+      eat_opt_white(&cur);
+      ctx->cur = cur;
+      for (j = 0; j < 3; j++) {
+         if (str_match_nocase_whole(&ctx->cur, tgsi_memory_names[j])) {
+            inst.Memory.Qualifier |= 1U << j;
+            break;
+         }
+      }
+      if (j == 3) {
+         report_error(ctx, "Expected memory qualifier");
+         return FALSE;
+      }
+      cur = ctx->cur;
+      eat_opt_white(&cur);
+   }
+
    cur = ctx->cur;
    eat_opt_white( &cur );
    if (info->is_branch && *cur == ':') {
@@ -1055,6 +1171,10 @@ static boolean parse_immediate_data(struct translate_ctx *ctx, unsigned type,
       }
 
       switch (type) {
+      case TGSI_IMM_FLOAT64:
+         ret = parse_double(&ctx->cur, &values[i].Uint, &values[i+1].Uint);
+         i++;
+         break;
       case TGSI_IMM_FLOAT32:
          ret = parse_float(&ctx->cur, &values[i].Float);
          break;
@@ -1129,8 +1249,13 @@ static boolean parse_declaration( struct translate_ctx *ctx )
       cur2 = cur;
       cur2++;
       eat_opt_white( &cur2 );
-      if (str_match_nocase_whole( &cur2, "ARRAY(" )) {
+      if (str_match_nocase_whole( &cur2, "ARRAY" )) {
          int arrayid;
+         if (*cur2 != '(') {
+            report_error( ctx, "Expected `('" );
+            return FALSE;
+         }
+         cur2++;
          eat_opt_white( &cur2 );
          if (!parse_int( &cur2, &arrayid )) {
             report_error( ctx, "Expected `,'" );
@@ -1138,12 +1263,13 @@ static boolean parse_declaration( struct translate_ctx *ctx )
          }
          eat_opt_white( &cur2 );
          if (*cur2 != ')') {
-            report_error( ctx, "Expected `,'" );
+            report_error( ctx, "Expected `)'" );
             return FALSE;
          }
+         cur2++;
          decl.Declaration.Array = 1;
          decl.Array.ArrayID = arrayid;
-         cur = cur2;
+         ctx->cur = cur = cur2;
       }
    }
 
@@ -1152,10 +1278,10 @@ static boolean parse_declaration( struct translate_ctx *ctx )
 
       cur++;
       eat_opt_white( &cur );
-      if (file == TGSI_FILE_RESOURCE) {
+      if (file == TGSI_FILE_IMAGE) {
          for (i = 0; i < TGSI_TEXTURE_COUNT; i++) {
             if (str_match_nocase_whole(&cur, tgsi_texture_names[i])) {
-               decl.Resource.Resource = i;
+               decl.Image.Resource = i;
                break;
             }
          }
@@ -1170,13 +1296,22 @@ static boolean parse_declaration( struct translate_ctx *ctx )
             cur2++;
             eat_opt_white(&cur2);
             if (str_match_nocase_whole(&cur2, "RAW")) {
-               decl.Resource.Raw = 1;
+               decl.Image.Raw = 1;
 
             } else if (str_match_nocase_whole(&cur2, "WR")) {
-               decl.Resource.Writable = 1;
+               decl.Image.Writable = 1;
 
             } else {
-               break;
+               for (i = 0; i < PIPE_FORMAT_COUNT; i++) {
+                  const struct util_format_description *desc =
+                     util_format_description(i);
+                  if (desc && str_match_nocase_whole(&cur2, desc->name)) {
+                     decl.Image.Format = i;
+                     break;
+                  }
+               }
+               if (i == PIPE_FORMAT_COUNT)
+                  break;
             }
             cur = cur2;
             eat_opt_white(&cur2);
@@ -1203,8 +1338,8 @@ static boolean parse_declaration( struct translate_ctx *ctx )
          ++cur;
          eat_opt_white( &cur );
          for (j = 0; j < 4; ++j) {
-            for (i = 0; i < PIPE_TYPE_COUNT; ++i) {
-               if (str_match_nocase_whole(&cur, tgsi_type_names[i])) {
+            for (i = 0; i < TGSI_RETURN_TYPE_COUNT; ++i) {
+               if (str_match_nocase_whole(&cur, tgsi_return_type_names[i])) {
                   switch (j) {
                   case 0:
                      decl.SamplerView.ReturnTypeX = i;
@@ -1224,7 +1359,7 @@ static boolean parse_declaration( struct translate_ctx *ctx )
                   break;
                }
             }
-            if (i == PIPE_TYPE_COUNT) {
+            if (i == TGSI_RETURN_TYPE_COUNT) {
                if (j == 0 || j >  2) {
                   report_error(ctx, "Expected type name");
                   return FALSE;
@@ -1249,6 +1384,14 @@ static boolean parse_declaration( struct translate_ctx *ctx )
                decl.SamplerView.ReturnTypeX;
          }
          ctx->cur = cur;
+      } else if (file == TGSI_FILE_BUFFER) {
+         if (str_match_nocase_whole(&cur, "ATOMIC")) {
+            decl.Declaration.Atomic = 1;
+            ctx->cur = cur;
+         } else if (str_match_nocase_whole(&cur, "SHARED")) {
+            decl.Declaration.Shared = 1;
+            ctx->cur = cur;
+         }
       } else {
          if (str_match_nocase_whole(&cur, "LOCAL")) {
             decl.Declaration.Local = 1;
@@ -1319,6 +1462,23 @@ static boolean parse_declaration( struct translate_ctx *ctx )
       }
    }
 
+   cur = ctx->cur;
+   eat_opt_white( &cur );
+   if (*cur == ',' && !is_vs_input) {
+      uint i;
+
+      cur++;
+      eat_opt_white( &cur );
+      for (i = 0; i < TGSI_INTERPOLATE_LOC_COUNT; i++) {
+         if (str_match_nocase_whole( &cur, tgsi_interpolate_locations[i] )) {
+            decl.Interp.Location = i;
+
+            ctx->cur = cur;
+            break;
+         }
+      }
+   }
+
    advance = tgsi_build_full_declaration(
       &decl,
       ctx->tokens_cur,
@@ -1531,6 +1691,10 @@ static boolean translate( struct translate_ctx *ctx )
    if (!parse_header( ctx ))
       return FALSE;
 
+   if (ctx->processor == TGSI_PROCESSOR_TESS_CTRL ||
+       ctx->processor == TGSI_PROCESSOR_TESS_EVAL)
+       ctx->implied_array_size = 32;
+
    while (*ctx->cur != '\0') {
       uint label_val = 0;
       if (!eat_white( &ctx->cur )) {