diff options
author | Tvrtko Ursulin <tvrtko.ursulin@intel.com> | 2019-05-22 16:57:06 +0100 |
---|---|---|
committer | Tvrtko Ursulin <tvrtko.ursulin@intel.com> | 2019-05-23 15:12:13 +0100 |
commit | 9a89dda32c3f39128addd569aef49fc64d4201b3 (patch) | |
tree | 3365e24d7f866f8fccb88294fd5f3b8c90ef1c7f /benchmarks/gem_wsim.c | |
parent | 631f3ac2e78c8d6332afc693bf290ae23d8d5685 (diff) |
gem_wsim: Engine map support
Support new i915 uAPI for configuring contexts with engine maps.
Please refer to the README file for more detailed explanation.
v2:
* Allow defining engine maps by class.
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Diffstat (limited to 'benchmarks/gem_wsim.c')
-rw-r--r-- | benchmarks/gem_wsim.c | 211 |
1 files changed, 180 insertions, 31 deletions
diff --git a/benchmarks/gem_wsim.c b/benchmarks/gem_wsim.c index 60b7d32e..e5b12e37 100644 --- a/benchmarks/gem_wsim.c +++ b/benchmarks/gem_wsim.c @@ -57,6 +57,7 @@ #include "ewma.h" enum intel_engine_id { + DEFAULT, RCS, BCS, VCS, @@ -81,7 +82,8 @@ enum w_type SW_FENCE, SW_FENCE_SIGNAL, CTX_PRIORITY, - PREEMPTION + PREEMPTION, + ENGINE_MAP }; struct deps @@ -115,6 +117,10 @@ struct w_step int throttle; int fence_signal; int priority; + struct { + unsigned int engine_map_count; + enum intel_engine_id *engine_map; + }; }; /* Implementation details */ @@ -142,6 +148,8 @@ DECLARE_EWMA(uint64_t, rt, 4, 2) struct ctx { uint32_t id; int priority; + unsigned int engine_map_count; + enum intel_engine_id *engine_map; bool targets_instance; bool wants_balance; unsigned int static_vcs; @@ -200,10 +208,10 @@ struct workload int fd; bool first; unsigned int num_engines; - unsigned int engine_map[5]; + unsigned int engine_map[NUM_ENGINES]; uint64_t t_prev; - uint64_t prev[5]; - double busy[5]; + uint64_t prev[NUM_ENGINES]; + double busy[NUM_ENGINES]; } busy_balancer; }; @@ -234,6 +242,7 @@ static int fd; #define REG(x) (volatile uint32_t *)((volatile char *)igt_global_mmio + x) static const char *ring_str_map[NUM_ENGINES] = { + [DEFAULT] = "DEFAULT", [RCS] = "RCS", [BCS] = "BCS", [VCS] = "VCS", @@ -330,6 +339,43 @@ static int str_to_engine(const char *str) return -1; } +static int parse_engine_map(struct w_step *step, const char *_str) +{ + char *token, *tctx = NULL, *tstart = (char *)_str; + + while ((token = strtok_r(tstart, "|", &tctx))) { + enum intel_engine_id engine; + unsigned int add; + + tstart = NULL; + + if (!strcmp(token, "DEFAULT")) + return -1; + + engine = str_to_engine(token); + if ((int)engine < 0) + return -1; + + if (engine != VCS && engine != VCS1 && engine != VCS2) + return -1; /* TODO */ + + add = engine == VCS ? 2 : 1; + step->engine_map_count += add; + step->engine_map = realloc(step->engine_map, + step->engine_map_count * + sizeof(step->engine_map[0])); + + if (engine != VCS) { + step->engine_map[step->engine_map_count - 1] = engine; + } else { + step->engine_map[step->engine_map_count - 2] = VCS1; + step->engine_map[step->engine_map_count - 1] = VCS2; + } + } + + return 0; +} + static struct workload * parse_workload(struct w_arg *arg, unsigned int flags, struct workload *app_w) { @@ -448,6 +494,33 @@ parse_workload(struct w_arg *arg, unsigned int flags, struct workload *app_w) } else if (!strcmp(field, "f")) { step.type = SW_FENCE; goto add_step; + } else if (!strcmp(field, "M")) { + unsigned int nr = 0; + while ((field = strtok_r(fstart, ".", &fctx)) != + NULL) { + tmp = atoi(field); + check_arg(nr == 0 && tmp <= 0, + "Invalid context at step %u!\n", + nr_steps); + check_arg(nr > 1, + "Invalid engine map format at step %u!\n", + nr_steps); + + if (nr == 0) { + step.context = tmp; + } else { + tmp = parse_engine_map(&step, + field); + check_arg(tmp < 0, + "Invalid engine map list at step %u!\n", + nr_steps); + } + + nr++; + } + + step.type = ENGINE_MAP; + goto add_step; } else if (!strcmp(field, "X")) { unsigned int nr = 0; while ((field = strtok_r(fstart, ".", &fctx)) != @@ -774,6 +847,7 @@ terminate_bb(struct w_step *w, unsigned int flags) } static const unsigned int eb_engine_map[NUM_ENGINES] = { + [DEFAULT] = I915_EXEC_DEFAULT, [RCS] = I915_EXEC_RENDER, [BCS] = I915_EXEC_BLT, [VCS] = I915_EXEC_BSD, @@ -796,11 +870,36 @@ eb_set_engine(struct drm_i915_gem_execbuffer2 *eb, eb->flags = eb_engine_map[engine]; } +static unsigned int +find_engine_in_map(struct ctx *ctx, enum intel_engine_id engine) +{ + unsigned int i; + + for (i = 0; i < ctx->engine_map_count; i++) { + if (ctx->engine_map[i] == engine) + return i + 1; + } + + igt_assert(0); + return 0; +} + +static struct ctx * +__get_ctx(struct workload *wrk, struct w_step *w) +{ + return &wrk->ctx_list[w->context * 2]; +} + static void -eb_update_flags(struct w_step *w, enum intel_engine_id engine, - unsigned int flags) +eb_update_flags(struct workload *wrk, struct w_step *w, + enum intel_engine_id engine, unsigned int flags) { - eb_set_engine(&w->eb, engine, flags); + struct ctx *ctx = __get_ctx(wrk, w); + + if (ctx->engine_map) + w->eb.flags = find_engine_in_map(ctx, engine); + else + eb_set_engine(&w->eb, engine, flags); w->eb.flags |= I915_EXEC_HANDLE_LUT; w->eb.flags |= I915_EXEC_NO_RELOC; @@ -819,12 +918,6 @@ get_status_objects(struct workload *wrk) return wrk->status_object; } -static struct ctx * -__get_ctx(struct workload *wrk, struct w_step *w) -{ - return &wrk->ctx_list[w->context * 2]; -} - static uint32_t get_ctxid(struct workload *wrk, struct w_step *w) { @@ -894,7 +987,7 @@ alloc_step_batch(struct workload *wrk, struct w_step *w, unsigned int flags) engine = VCS2; else if (flags & SWAPVCS && engine == VCS2) engine = VCS1; - eb_update_flags(w, engine, flags); + eb_update_flags(wrk, w, engine, flags); #ifdef DEBUG printf("%u: %u:|", w->idx, w->eb.buffer_count); for (i = 0; i <= j; i++) @@ -936,7 +1029,7 @@ static void vm_destroy(int i915, uint32_t vm_id) igt_assert_eq(__vm_destroy(i915, vm_id), 0); } -static void +static int prepare_workload(unsigned int id, struct workload *wrk, unsigned int flags) { unsigned int ctx_vcs; @@ -999,30 +1092,53 @@ prepare_workload(unsigned int id, struct workload *wrk, unsigned int flags) /* * Identify if contexts target specific engine instances and if they * want to be balanced. + * + * Transfer over engine map configuration from the workload step. */ for (j = 0; j < wrk->nr_ctxs; j += 2) { bool targets = false; bool balance = false; for (i = 0, w = wrk->steps; i < wrk->nr_steps; i++, w++) { - if (w->type != BATCH) - continue; - if (w->context != (j / 2)) continue; - if (w->engine == VCS) - balance = true; - else - targets = true; + if (w->type == BATCH) { + if (w->engine == VCS) + balance = true; + else + targets = true; + } else if (w->type == ENGINE_MAP) { + wrk->ctx_list[j].engine_map = w->engine_map; + wrk->ctx_list[j].engine_map_count = + w->engine_map_count; + } } - if (flags & I915) { - wrk->ctx_list[j].targets_instance = targets; + wrk->ctx_list[j].targets_instance = targets; + if (flags & I915) wrk->ctx_list[j].wants_balance = balance; + } + + /* + * Ensure VCS is not allowed with engine map contexts. + */ + for (j = 0; j < wrk->nr_ctxs; j += 2) { + for (i = 0, w = wrk->steps; i < wrk->nr_steps; i++, w++) { + if (w->context != (j / 2)) + continue; + + if (w->type != BATCH) + continue; + + if (wrk->ctx_list[j].engine_map && w->engine == VCS) { + wsim_err("Batches targetting engine maps must use explicit engines!\n"); + return -1; + } } } + /* * Create and configure contexts. */ @@ -1033,7 +1149,7 @@ prepare_workload(unsigned int id, struct workload *wrk, unsigned int flags) if (ctx->id) continue; - if (flags & I915) { + if ((flags & I915) || ctx->engine_map) { struct drm_i915_gem_context_create_ext_setparam ext = { .base.name = I915_CONTEXT_CREATE_EXT_SETPARAM, .param.param = I915_CONTEXT_PARAM_VM, @@ -1063,7 +1179,7 @@ prepare_workload(unsigned int id, struct workload *wrk, unsigned int flags) break; } - if (!ctx->targets_instance) + if (!ctx->engine_map && !ctx->targets_instance) args.flags |= I915_CONTEXT_CREATE_FLAGS_SINGLE_TIMELINE; @@ -1096,7 +1212,7 @@ prepare_workload(unsigned int id, struct workload *wrk, unsigned int flags) * both want to target specific engines and be balanced by i915? */ if ((flags & I915) && ctx->wants_balance && - ctx->targets_instance) { + ctx->targets_instance && !ctx->engine_map) { struct drm_i915_gem_context_create_ext_setparam ext = { .base.name = I915_CONTEXT_CREATE_EXT_SETPARAM, .param.param = I915_CONTEXT_PARAM_VM, @@ -1121,7 +1237,33 @@ prepare_workload(unsigned int id, struct workload *wrk, unsigned int flags) __ctx_set_prio(ctx_id, wrk->prio); } - if (ctx->wants_balance) { + if (ctx->engine_map) { + I915_DEFINE_CONTEXT_PARAM_ENGINES(set_engines, + ctx->engine_map_count + 1); + struct drm_i915_gem_context_param param = { + .ctx_id = ctx_id, + .param = I915_CONTEXT_PARAM_ENGINES, + .size = sizeof(set_engines), + .value = to_user_pointer(&set_engines), + }; + + set_engines.extensions = 0; + + /* Reserve slot for virtual engine. */ + set_engines.engines[0].engine_class = + I915_ENGINE_CLASS_INVALID; + set_engines.engines[0].engine_instance = + I915_ENGINE_CLASS_INVALID_NONE; + + for (j = 1; j <= ctx->engine_map_count; j++) { + set_engines.engines[j].engine_class = + I915_ENGINE_CLASS_VIDEO; /* FIXME */ + set_engines.engines[j].engine_instance = + ctx->engine_map[j - 1] - VCS1; /* FIXME */ + } + + gem_context_set_param(fd, ¶m); + } else if (ctx->wants_balance) { I915_DEFINE_CONTEXT_ENGINES_LOAD_BALANCE(load_balance, 2) = { .base.name = I915_CONTEXT_ENGINES_EXT_LOAD_BALANCE, .num_siblings = 2, @@ -1204,6 +1346,8 @@ prepare_workload(unsigned int id, struct workload *wrk, unsigned int flags) alloc_step_batch(wrk, w, _flags); } + + return 0; } static double elapsed(const struct timespec *start, const struct timespec *end) @@ -1941,7 +2085,7 @@ do_eb(struct workload *wrk, struct w_step *w, enum intel_engine_id engine, uint32_t seqno = new_seqno(wrk, engine); unsigned int i; - eb_update_flags(w, engine, flags); + eb_update_flags(wrk, w, engine, flags); if (flags & SEQNO) update_bb_seqno(w, engine, seqno); @@ -2090,7 +2234,8 @@ static void *run_workload(void *data) w->priority; } continue; - } else if (w->type == PREEMPTION) { + } else if (w->type == PREEMPTION || + w->type == ENGINE_MAP) { continue; } @@ -2648,7 +2793,11 @@ int main(int argc, char **argv) w[i]->print_stats = verbose > 1 || (verbose > 0 && master_workload == i); - prepare_workload(i, w[i], flags_); + if (prepare_workload(i, w[i], flags_)) { + wsim_err("Failed to prepare workload %u!\n", i); + return 1; + } + if (balancer && balancer->init) { int ret = balancer->init(balancer, w[i]); |