[Intel-gfx] [PATCH i-g-t 02/10] gem_wsim: Buffer objects working sets and complex dependencies

Chris Wilson chris at chris-wilson.co.uk
Thu Jun 18 09:22:59 UTC 2020


Quoting Tvrtko Ursulin (2020-06-18 10:05:56)
> 
> On 17/06/2020 17:57, Chris Wilson wrote:
> > Quoting Tvrtko Ursulin (2020-06-17 17:01:12)
> >> From: Tvrtko Ursulin <tvrtko.ursulin at intel.com>
> >>
> >> Add support for defining buffer object working sets and targetting them as
> >> data dependencies. For more information please see the README file.
> >>
> >> Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin at intel.com>
> >> ---
> >>   benchmarks/gem_wsim.c                   | 453 +++++++++++++++++++++---
> >>   benchmarks/wsim/README                  |  59 +++
> >>   benchmarks/wsim/cloud-gaming-60fps.wsim |  11 +
> >>   benchmarks/wsim/composited-ui.wsim      |   7 +
> >>   4 files changed, 476 insertions(+), 54 deletions(-)
> >>   create mode 100644 benchmarks/wsim/cloud-gaming-60fps.wsim
> >>   create mode 100644 benchmarks/wsim/composited-ui.wsim
> >>
> >> diff --git a/benchmarks/gem_wsim.c b/benchmarks/gem_wsim.c
> >> index 02fe8f5a5e69..9e5bfe6a36d4 100644
> >> --- a/benchmarks/gem_wsim.c
> >> +++ b/benchmarks/gem_wsim.c
> >> @@ -88,14 +88,21 @@ enum w_type
> >>          LOAD_BALANCE,
> >>          BOND,
> >>          TERMINATE,
> >> -       SSEU
> >> +       SSEU,
> >> +       WORKINGSET,
> >> +};
> >> +
> >> +struct dep_entry {
> >> +       int target;
> >> +       bool write;
> >> +       int working_set; /* -1 = step dependecy, >= 0 working set id */
> >>   };
> >>   
> >>   struct deps
> >>   {
> >>          int nr;
> >>          bool submit_fence;
> >> -       int *list;
> >> +       struct dep_entry *list;
> >>   };
> >>   
> >>   struct w_arg {
> >> @@ -110,6 +117,14 @@ struct bond {
> >>          enum intel_engine_id master;
> >>   };
> >>   
> >> +struct working_set {
> >> +       int id;
> >> +       bool shared;
> >> +       unsigned int nr;
> >> +       uint32_t *handles;
> >> +       unsigned long *sizes;
> >> +};
> >> +
> >>   struct workload;
> >>   
> >>   struct w_step
> >> @@ -143,6 +158,7 @@ struct w_step
> >>                          enum intel_engine_id bond_master;
> >>                  };
> >>                  int sseu;
> >> +               struct working_set working_set;
> >>          };
> >>   
> >>          /* Implementation details */
> >> @@ -193,6 +209,9 @@ struct workload
> >>          unsigned int nr_ctxs;
> >>          struct ctx *ctx_list;
> >>   
> >> +       struct working_set **working_sets; /* array indexed by set id */
> >> +       int max_working_set_id;
> >> +
> >>          int sync_timeline;
> >>          uint32_t sync_seqno;
> >>   
> >> @@ -281,11 +300,120 @@ print_engine_calibrations(void)
> >>          printf("\n");
> >>   }
> >>   
> >> +static void add_dep(struct deps *deps, struct dep_entry entry)
> >> +{
> >> +       deps->list = realloc(deps->list, sizeof(*deps->list) * (deps->nr + 1));
> >> +       igt_assert(deps->list);
> >> +
> >> +       deps->list[deps->nr++] = entry;
> >> +}
> >> +
> >> +
> >> +static int
> >> +parse_dependency(unsigned int nr_steps, struct w_step *w, char *str)
> >> +{
> >> +       struct dep_entry entry = { .working_set = -1 };
> >> +       bool submit_fence = false;
> >> +       char *s;
> >> +
> >> +       switch (str[0]) {
> >> +       case '-':
> >> +               if (str[1] < '0' || str[1] > '9')
> >> +                       return -1;
> >> +
> >> +               entry.target = atoi(str);
> >> +               if (entry.target > 0 || ((int)nr_steps + entry.target) < 0)
> >> +                       return -1;
> > 
> > add_dep for N steps ago, using a handle.
> > 
> >> +
> >> +               add_dep(&w->data_deps, entry);
> >> +
> >> +               break;
> >> +       case 's':
> >> +               submit_fence = true;
> >> +               /* Fall-through. */
> >> +       case 'f':
> >> +               /* Multiple fences not yet supported. */
> >> +               igt_assert_eq(w->fence_deps.nr, 0);
> >> +
> >> +               entry.target = atoi(++str);
> >> +               if (entry.target > 0 || ((int)nr_steps + entry.target) < 0)
> >> +                       return -1;
> >> +
> >> +               add_dep(&w->fence_deps, entry);
> >> +
> >> +               w->fence_deps.submit_fence = submit_fence;
> > 
> > add_dep for N steps ago, using the out-fence from that step
> > [A post processing steps adds emit_fence to the earlier steps.]
> > 
> >> +               break;
> >> +       case 'w':
> >> +               entry.write = true;
> > 
> > Got confused for a moment as I was expecting the submit_fence
> > fallthrough pattern.
> >> +               /* Fall-through. */
> >> +       case 'r':
> >> +               /*
> >> +                * [rw]N-<str>
> >> +                * r1-<str> or w2-<str>, where N is working set id.
> >> +                */
> >> +               s = index(++str, '-');
> >> +               if (!s)
> >> +                       return -1;
> >> +
> >> +               entry.working_set = atoi(str);
> > 
> > if (entry.working_set < 0)
> >       return -1;
> 
> Yep.
> 
> > 
> >> +
> >> +               if (parse_working_set_deps(w->wrk, &w->data_deps, entry, ++s))
> >> +                       return -1;
> > 
> > The new one...
> > 
> >> +static int
> >> +parse_working_set_deps(struct workload *wrk,
> >> +                      struct deps *deps,
> >> +                      struct dep_entry _entry,
> >> +                      char *str)
> >> +{
> >> +       /*
> >> +        * 1 - target handle index in the specified working set.
> >> +        * 2-4 - range
> >> +        */
> >> +       struct dep_entry entry = _entry;
> >> +       char *s;
> >> +
> >> +       s = index(str, '-');
> >> +       if (s) {
> >> +               int from, to;
> >> +
> >> +               from = atoi(str);
> >> +               if (from < 0)
> >> +                       return -1;
> >> +
> >> +               to = atoi(++s);
> >> +               if (to <= 0)
> >> +                       return -1;
> > 
> > if to < from, we add nothing. Is that worth the error?
> 
> Yep.
> 
> > 
> >> +
> >> +               for (entry.target = from; entry.target <= to; entry.target++)
> >> +                       add_dep(deps, entry);
> >> +       } else {
> >> +               entry.target = atoi(str);
> >> +               if (entry.target < 0)
> >> +                       return -1;
> >> +
> >> +               add_dep(deps, entry);
> > 
> > 
> >> +       }
> >> +
> >> +       return 0;
> >> +}
> >> +
> >> +               break;
> >> +       default:
> >> +               return -1;
> >> +       };
> >> +
> >> +       return 0;
> >> +}
> >> +
> >>   static int
> >>   parse_dependencies(unsigned int nr_steps, struct w_step *w, char *_desc)
> >>   {
> >>          char *desc = strdup(_desc);
> >>          char *token, *tctx = NULL, *tstart = desc;
> >> +       int ret = 0;
> >> +
> >> +       if (!strcmp(_desc, "0"))
> >> +               goto out;
> > 
> > Hang on, what this special case?
> 
> For no dependencies.
> 
> If I move the check to parse_dependency then dependency of "0/0/0/0" 
> would be silently accepted. It wouldn't be a big deal, who cares, but I 
> thought it is better to be more strict.

It was just not clear at this point what is being matched, what the
meaning of 0 is.

/* 0 refers to self, a degenerate dependency */
?
-Chris


More information about the Intel-gfx mailing list