From: Tvrtko Ursulin <tursulin@ursulin.net>
To: igt-dev@lists.freedesktop.org
Cc: Intel-gfx@lists.freedesktop.org,
Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Subject: [igt-dev] [PATCH i-g-t 11/17] gem_wsim: Engine map support
Date: Thu, 18 Oct 2018 16:28:09 +0100 [thread overview]
Message-ID: <20181018152815.31816-12-tvrtko.ursulin@linux.intel.com> (raw)
In-Reply-To: <20181018152815.31816-1-tvrtko.ursulin@linux.intel.com>
From: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Support new i915 uAPI for configuring contexts with engine maps.
Please refer to the README file for more detailed explanation.
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
---
benchmarks/gem_wsim.c | 212 ++++++++++++++++++++++++++++++++++-------
benchmarks/wsim/README | 17 +++-
2 files changed, 192 insertions(+), 37 deletions(-)
diff --git a/benchmarks/gem_wsim.c b/benchmarks/gem_wsim.c
index 17325d2ceaf6..fbec23ad1753 100644
--- a/benchmarks/gem_wsim.c
+++ b/benchmarks/gem_wsim.c
@@ -56,6 +56,7 @@
#include "ewma.h"
enum intel_engine_id {
+ DEFAULT,
RCS,
BCS,
VCS,
@@ -80,7 +81,8 @@ enum w_type
SW_FENCE,
SW_FENCE_SIGNAL,
CTX_PRIORITY,
- PREEMPTION
+ PREEMPTION,
+ ENGINE_MAP
};
struct deps
@@ -114,6 +116,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 */
@@ -143,6 +149,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;
@@ -201,10 +209,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;
};
@@ -235,6 +243,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",
@@ -331,6 +340,37 @@ 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;
+
+ tstart = NULL;
+
+ if (!strcmp(token, "DEFAULT"))
+ return -1;
+ else if (!strcmp(token, "VCS"))
+ return -1;
+
+ engine = str_to_engine(token);
+ if ((int)engine < 0)
+ return -1;
+
+ if (engine != VCS1 && engine != VCS2)
+ return -1; /* TODO */
+
+ step->engine_map_count++;
+ step->engine_map = realloc(step->engine_map,
+ step->engine_map_count *
+ sizeof(step->engine_map[0]));
+ step->engine_map[step->engine_map_count - 1] = engine;
+ }
+
+ return 0;
+}
+
static struct workload *
parse_workload(struct w_arg *arg, unsigned int flags, struct workload *app_w)
{
@@ -449,6 +489,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)) !=
@@ -490,9 +557,7 @@ parse_workload(struct w_arg *arg, unsigned int flags, struct workload *app_w)
i = str_to_engine(field);
check_arg(i < 0,
"Invalid engine id at step %u!\n", nr_steps);
- if (i >= 0)
- valid++;
-
+ valid++;
step.engine = i;
if (step.engine == BCS)
@@ -769,6 +834,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,
@@ -785,18 +851,42 @@ eb_set_engine(struct drm_i915_gem_execbuffer2 *eb,
if (engine == VCS2 && (flags & VCS2REMAP))
engine = BCS;
- if ((flags & I915) && engine == VCS) {
+ if ((flags & I915) && engine == VCS)
eb->flags = 0;
- } else {
+ else
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;
@@ -815,12 +905,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)
{
@@ -890,7 +974,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++)
@@ -913,7 +997,7 @@ static void __ctx_set_prio(uint32_t ctx_id, unsigned int prio)
gem_context_set_param(fd, ¶m);
}
-static void
+static int
prepare_workload(unsigned int id, struct workload *wrk, unsigned int flags)
{
unsigned int ctx_vcs = 0;
@@ -974,30 +1058,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.
*/
@@ -1008,7 +1115,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_v2 args = { };
/* Find existing context to share ppgtt with. */
@@ -1022,7 +1129,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_GEM_CONTEXT_SINGLE_TIMELINE;
drmIoctl(fd, DRM_IOCTL_I915_GEM_CONTEXT_CREATE, &args);
@@ -1053,7 +1160,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_v2 args = {};
igt_assert(share_ctx);
@@ -1071,7 +1178,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) {
+ struct local_i915_context_param_engines {
+ __u64 extensions;
+
+ struct {
+ __u16 class; /* see enum drm_i915_gem_engine_class */
+ __u16 instance;
+ } engines[ctx->engine_map_count];
+ } __attribute__((packed)) set_engines;
+ 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;
+
+ for (j = 0; j < ctx->engine_map_count; j++) {
+ set_engines.engines[j].class =
+ I915_ENGINE_CLASS_VIDEO; /* FIXME */
+ set_engines.engines[j].instance =
+ ctx->engine_map[j] - VCS1; /* FIXME */
+ }
+
+ gem_context_set_param(fd, ¶m);
+ } else if (ctx->wants_balance) {
struct i915_context_engines_load_balance load_balance =
{ .base.name = I915_CONTEXT_ENGINES_EXT_LOAD_BALANCE,
.engines_mask = -1,
@@ -1151,6 +1284,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)
@@ -1888,7 +2023,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);
@@ -2037,7 +2172,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;
}
@@ -2595,7 +2731,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]);
diff --git a/benchmarks/wsim/README b/benchmarks/wsim/README
index 4786f116b4ac..20e3e358cd2e 100644
--- a/benchmarks/wsim/README
+++ b/benchmarks/wsim/README
@@ -3,6 +3,7 @@ Workload descriptor format
ctx.engine.duration_us.dependency.wait,...
<uint>.<str>.<uint>[-<uint>].<int <= 0>[/<int <= 0>][...].<0|1>,...
+M.<uint>.<str>[|<str>]...
P|X.<uint>.<int>
d|p|s|t|q|a.<int>,...
f
@@ -23,10 +24,11 @@ Additional workload steps are also supported:
'q' - Throttle to n max queue depth.
'f' - Create a sync fence.
'a' - Advance the previously created sync fence.
+ 'M' - Set up engine map.
'P' - Context priority.
'X' - Context preemption control.
-Engine ids: RCS, BCS, VCS, VCS1, VCS2, VECS
+Engine ids: DEFAULT, RCS, BCS, VCS, VCS1, VCS2, VECS
Example (leading spaces must not be present in the actual file):
----------------------------------------------------------------
@@ -161,3 +163,16 @@ The same context is then marked to have batches which can be preempted every
Same as with context priority, context preemption commands are valid until
optionally overriden by another preemption control change on the same context.
+
+Engine maps
+-----------
+
+Engine maps are a per context feature which changes the way engine selection is
+done in the driver.
+
+Example:
+
+ 1.M.VCS1|VCS2
+
+This sets up context 1 with an engine map containing VCS1 and VCS2 engine.
+Submission to this context can now only reference these two engines.
--
2.17.1
_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev
next prev parent reply other threads:[~2018-10-18 15:28 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-10-18 15:27 [igt-dev] [PATCH i-g-t 00/17] Media scalability tooling Tvrtko Ursulin
2018-10-18 15:27 ` [Intel-gfx] [PATCH i-g-t 01/17] lib: Update uapi headers Tvrtko Ursulin
2018-10-18 15:28 ` [igt-dev] [PATCH i-g-t 02/17] trace.pl: Virtual engine support Tvrtko Ursulin
2018-10-18 15:28 ` [igt-dev] [PATCH i-g-t 03/17] trace.pl: Virtual engine preemption support Tvrtko Ursulin
2018-10-18 15:28 ` [igt-dev] [PATCH i-g-t 04/17] wsim/media-bench: i915 balancing Tvrtko Ursulin
2018-10-18 15:28 ` [igt-dev] [PATCH i-g-t 05/17] gem_wsim: Use IGT uapi headers Tvrtko Ursulin
2018-10-18 15:28 ` [igt-dev] [PATCH i-g-t 06/17] gem_wsim: Fix shadowed local Tvrtko Ursulin
2018-10-18 15:28 ` [Intel-gfx] [PATCH i-g-t 07/17] gem_wsim: Factor out common error handling Tvrtko Ursulin
2018-10-18 15:28 ` [igt-dev] [PATCH i-g-t 08/17] gem_wsim: More wsim_err Tvrtko Ursulin
2018-10-18 15:28 ` [igt-dev] [PATCH i-g-t 09/17] gem_wsim: Submit fence support Tvrtko Ursulin
2018-10-18 15:28 ` [Intel-gfx] [PATCH i-g-t 10/17] gem_wsim: Extract str to engine lookup Tvrtko Ursulin
2018-10-18 15:28 ` Tvrtko Ursulin [this message]
2018-10-18 15:28 ` [igt-dev] [PATCH i-g-t 12/17] gem_wsim: Save some lines by changing to implicit NULL checking Tvrtko Ursulin
2018-10-18 15:28 ` [igt-dev] [PATCH i-g-t 13/17] gem_wsim: Compact int command parsing with a macro Tvrtko Ursulin
2018-10-18 15:28 ` [Intel-gfx] [PATCH i-g-t 14/17] gem_wsim: Engine map load balance command Tvrtko Ursulin
2018-10-18 15:28 ` [igt-dev] [PATCH i-g-t 15/17] gem_wsim: Engine bond command Tvrtko Ursulin
2018-10-18 21:48 ` Chris Wilson
2018-10-26 11:11 ` Tvrtko Ursulin
2018-10-18 15:28 ` [igt-dev] [PATCH i-g-t 16/17] gem_wsim: Some more example workloads Tvrtko Ursulin
2018-10-18 15:28 ` [igt-dev] [PATCH i-g-t 17/17] gem_wsim: Infinite batch support Tvrtko Ursulin
2018-10-18 15:37 ` [igt-dev] ✗ Fi.CI.BAT: failure for Media scalability tooling Patchwork
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20181018152815.31816-12-tvrtko.ursulin@linux.intel.com \
--to=tursulin@ursulin.net \
--cc=Intel-gfx@lists.freedesktop.org \
--cc=igt-dev@lists.freedesktop.org \
--cc=tvrtko.ursulin@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox