Mesa (master): intel/aubinator: Correctly read variable length structs.

Kenneth Graunke kwg at kemper.freedesktop.org
Mon Apr 24 22:14:38 UTC 2017


Module: Mesa
Branch: master
Commit: 1ea41163eb0657e7c6cd46c45bdbc3fd4e8e72f8
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=1ea41163eb0657e7c6cd46c45bdbc3fd4e8e72f8

Author: Rafael Antognolli <rafael.antognolli at intel.com>
Date:   Tue Apr 18 09:41:40 2017 -0700

intel/aubinator: Correctly read variable length structs.

Before this commit, when a group with count="0" is found, only one field
is added to the struct representing the instruction. This causes only
one entry to be printed by aubinator, for variable length groups.

With this commit we "detect" that there's a variable length group
(count="0") and store the offset of the last entry added to the struct
when reading the xml. When finally reading the aubdump file, we check
the size of the group and whether we have variable number of elements,
and in that case, reuse the last field to add the remaining elements.

Signed-off-by: Rafael Antognolli <rafael.antognolli at intel.com>
Tested-by: Jason Ekstrand <jason at jlekstrand.net>
Acked-by: Kenneth Graunke <kenneth at whitecape.org>

---

 src/intel/common/gen_decoder.c | 35 +++++++++++++++++++++++++++++------
 src/intel/common/gen_decoder.h |  6 ++++++
 src/intel/tools/aubinator.c    | 19 +++++++++++++++++++
 3 files changed, 54 insertions(+), 6 deletions(-)

diff --git a/src/intel/common/gen_decoder.c b/src/intel/common/gen_decoder.c
index e3327d3854..15bba3274e 100644
--- a/src/intel/common/gen_decoder.c
+++ b/src/intel/common/gen_decoder.c
@@ -190,6 +190,8 @@ create_group(struct parser_context *ctx, const char *name, const char **atts)
    group->spec = ctx->spec;
    group->group_offset = 0;
    group->group_count = 0;
+   group->variable_offset = 0;
+   group->variable = false;
 
    return group;
 }
@@ -210,16 +212,22 @@ create_enum(struct parser_context *ctx, const char *name, const char **atts)
 
 static void
 get_group_offset_count(struct parser_context *ctx, const char *name,
-                       const char **atts, uint32_t *offset, uint32_t *count)
+                       const char **atts, uint32_t *offset, uint32_t *count,
+                       uint32_t *elem_size, bool *variable)
 {
    char *p;
    int i;
 
    for (i = 0; atts[i]; i += 2) {
-      if (strcmp(atts[i], "count") == 0)
+      if (strcmp(atts[i], "count") == 0) {
          *count = strtoul(atts[i + 1], &p, 0);
-      else if (strcmp(atts[i], "start") == 0)
+         if (*count == 0)
+            *variable = true;
+      } else if (strcmp(atts[i], "start") == 0) {
          *offset = strtoul(atts[i + 1], &p, 0);
+      } else if (strcmp(atts[i], "size") == 0) {
+         *elem_size = strtoul(atts[i + 1], &p, 0);
+      }
    }
    return;
 }
@@ -331,8 +339,11 @@ create_field(struct parser_context *ctx, const char **atts)
          field->start = ctx->group->group_offset+strtoul(atts[i + 1], &p, 0);
       else if (strcmp(atts[i], "end") == 0) {
          field->end = ctx->group->group_offset+strtoul(atts[i + 1], &p, 0);
-         if (ctx->group->group_offset)
+         if (ctx->group->group_offset) {
             ctx->group->group_offset = field->end+1;
+            if (ctx->group->variable)
+               ctx->group->variable_offset = ctx->group->group_offset;
+         }
       } else if (strcmp(atts[i], "type") == 0)
          field->type = string_to_type(ctx, atts[i + 1]);
       else if (strcmp(atts[i], "default") == 0 &&
@@ -400,7 +411,8 @@ start_element(void *data, const char *element_name, const char **atts)
       get_register_offset(atts, &ctx->group->register_offset);
    } else if (strcmp(element_name, "group") == 0) {
       get_group_offset_count(ctx, name, atts, &ctx->group->group_offset,
-                             &ctx->group->group_count);
+                             &ctx->group->group_count, &ctx->group->elem_size,
+                             &ctx->group->variable);
    } else if (strcmp(element_name, "field") == 0) {
       do {
          ctx->fields[ctx->nfields++] = create_field(ctx, atts);
@@ -734,6 +746,8 @@ gen_field_iterator_init(struct gen_field_iterator *iter,
    iter->p = p;
    iter->i = 0;
    iter->print_colors = print_colors;
+   iter->repeat = false;
+   iter->addr_inc = 0;
 }
 
 static const char *
@@ -755,8 +769,17 @@ gen_field_iterator_next(struct gen_field_iterator *iter)
       float f;
    } v;
 
-   if (iter->i == iter->group->nfields)
+   if (iter->i == iter->group->nfields) {
+      if (iter->group->group_size > 0) {
+         int iter_length = iter->group->elem_size;
+
+         iter->group->group_size -= iter_length / 32;
+         iter->addr_inc += iter_length;
+         iter->dword = (iter->field->start + iter->addr_inc) / 32;
+         return true;
+      }
       return false;
+   }
 
    iter->field = iter->group->fields[iter->i++];
    iter->name = iter->field->name;
diff --git a/src/intel/common/gen_decoder.h b/src/intel/common/gen_decoder.h
index 870bd7f784..4f4295ff95 100644
--- a/src/intel/common/gen_decoder.h
+++ b/src/intel/common/gen_decoder.h
@@ -61,6 +61,8 @@ struct gen_field_iterator {
    int i;
    struct gen_field *field;
    bool print_colors;
+   bool repeat;
+   uint32_t addr_inc;
 };
 
 struct gen_group {
@@ -69,6 +71,10 @@ struct gen_group {
    int nfields;
    struct gen_field **fields;
    uint32_t group_offset, group_count;
+   uint32_t elem_size;
+   uint32_t variable_offset;
+   bool variable;
+   uint32_t group_size;
 
    uint32_t opcode_mask;
    uint32_t opcode;
diff --git a/src/intel/tools/aubinator.c b/src/intel/tools/aubinator.c
index f1bedd271e..53b2a27fa9 100644
--- a/src/intel/tools/aubinator.c
+++ b/src/intel/tools/aubinator.c
@@ -95,10 +95,28 @@ valid_offset(uint32_t offset)
    return offset < gtt_end;
 }
 
+/**
+ * Set group variable size for groups with count="0".
+ *
+ * By default the group size is fixed and not needed because the struct
+ * describing a group knows the number of elements. However, for groups with
+ * count="0" we have a variable number of elements, and the struct describing
+ * the group only includes one of them. So we calculate the remaining size of
+ * the group based on the size we get here, and the offset after the last
+ * element added to the group.
+ */
+static void
+group_set_size(struct gen_group *strct, uint32_t size)
+{
+   if (strct->variable && strct->elem_size)
+      strct->group_size = size - (strct->variable_offset / 32);
+}
+
 static void
 decode_group(struct gen_group *strct, const uint32_t *p, int starting_dword)
 {
    uint64_t offset = option_print_offsets ? (void *) p - gtt : 0;
+
    gen_print_group(outfile, strct, offset, p, option_color == COLOR_ALWAYS);
 }
 
@@ -722,6 +740,7 @@ parse_commands(struct gen_spec *spec, uint32_t *cmds, int size, int engine)
               gen_group_get_name(inst), reset_color);
 
       if (option_full_decode) {
+         group_set_size(inst, length);
          decode_group(inst, p, 0);
 
          for (i = 0; i < ARRAY_LENGTH(custom_handlers); i++) {




More information about the mesa-commit mailing list