@@ -82,7 +82,8 @@ enum w_type
SW_FENCE_SIGNAL,
CTX_PRIORITY,
PREEMPTION,
- ENGINE_MAP
+ ENGINE_MAP,
+ LOAD_BALANCE,
};
struct deps
@@ -120,6 +121,7 @@ struct w_step
unsigned int engine_map_count;
enum intel_engine_id *engine_map;
};
+ bool load_balance;
};
/* Implementation details */
@@ -502,6 +504,25 @@ parse_workload(struct w_arg *arg, unsigned int flags, struct workload *app_w)
step.type = PREEMPTION;
goto add_step;
+ } else if (!strcmp(field, "B")) {
+ unsigned int nr = 0;
+ while ((field = strtok_r(fstart, ".", &fctx))) {
+ tmp = atoi(field);
+ check_arg(nr == 0 && tmp <= 0,
+ "Invalid context at step %u!\n",
+ nr_steps);
+ check_arg(nr > 0,
+ "Invalid load balance format at step %u!\n",
+ nr_steps);
+
+ step.context = tmp;
+ step.load_balance = true;
+
+ nr++;
+ }
+
+ step.type = LOAD_BALANCE;
+ goto add_step;
}
tmp = atoi(field);
@@ -828,7 +849,7 @@ find_engine_in_map(struct ctx *ctx, enum intel_engine_id engine)
return i + 1;
}
- igt_assert(0);
+ igt_assert(ctx->wants_balance);
return 0;
}
@@ -1039,12 +1060,19 @@ prepare_workload(unsigned int id, struct workload *wrk, unsigned int flags)
wrk->ctx_list[j].engine_map = w->engine_map;
wrk->ctx_list[j].engine_map_count =
w->engine_map_count;
+ } else if (w->type == LOAD_BALANCE) {
+ if (!wrk->ctx_list[j].engine_map) {
+ wsim_err("Load balancing needs an engine map!\n");
+ return 1;
+ }
+ wrk->ctx_list[j].wants_balance =
+ w->load_balance;
}
}
wrk->ctx_list[j].targets_instance = targets;
if (flags & I915)
- wrk->ctx_list[j].wants_balance = balance;
+ wrk->ctx_list[j].wants_balance |= balance;
}
/*
@@ -1058,10 +1086,19 @@ prepare_workload(unsigned int id, struct workload *wrk, unsigned int flags)
if (w->type != BATCH)
continue;
- if (wrk->ctx_list[j].engine_map && w->engine == VCS) {
+ if (wrk->ctx_list[j].engine_map &&
+ !wrk->ctx_list[j].wants_balance &&
+ (w->engine == VCS || w->engine == DEFAULT)) {
wsim_err("Batches targetting engine maps must use explicit engines!\n");
return -1;
}
+
+ if (wrk->ctx_list[j].engine_map &&
+ wrk->ctx_list[j].wants_balance &&
+ w->engine != DEFAULT) {
+ wsim_err("Batches targetting load balanced maps must not use explicit engines!\n");
+ return -1;
+ }
}
}
@@ -1090,7 +1127,8 @@ prepare_workload(unsigned int id, struct workload *wrk, unsigned int flags)
break;
}
- if ((!ctx->engine_map && !ctx->targets_instance))
+ if ((!ctx->engine_map && !ctx->targets_instance) ||
+ (ctx->engine_map && ctx->wants_balance))
args.flags |= I915_GEM_CONTEXT_SINGLE_TIMELINE;
drmIoctl(fd, DRM_IOCTL_I915_GEM_CONTEXT_CREATE, &args);
@@ -1154,8 +1192,17 @@ prepare_workload(unsigned int id, struct workload *wrk, unsigned int flags)
.size = sizeof(set_engines),
.value = to_user_pointer(&set_engines),
};
+ struct i915_context_engines_load_balance load_balance =
+ { .base.name = I915_CONTEXT_ENGINES_EXT_LOAD_BALANCE,
+ .engines_mask = -1,
+ };
- set_engines.extensions = 0;
+ if (ctx->wants_balance) {
+ set_engines.extensions =
+ to_user_pointer(&load_balance);
+ } else {
+ set_engines.extensions = 0;
+ }
for (j = 0; j < ctx->engine_map_count; j++) {
set_engines.engines[j].class =
@@ -2134,7 +2181,8 @@ static void *run_workload(void *data)
}
continue;
} else if (w->type == PREEMPTION ||
- w->type == ENGINE_MAP) {
+ w->type == ENGINE_MAP ||
+ w->type == LOAD_BALANCE) {
continue;
}
@@ -3,6 +3,7 @@ Workload descriptor format
ctx.engine.duration_us.dependency.wait,...
<uint>.<str>.<uint>[-<uint>].<int <= 0>[/<int <= 0>][...].<0|1>,...
+B.<uint>
M.<uint>.<str>[|<str>]...
P|X.<uint>.<int>
d|p|s|t|q|a.<int>,...
@@ -24,6 +25,7 @@ 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.
+ 'B' - Turn on context load balancing.
'M' - Set up engine map.
'P' - Context priority.
'X' - Context preemption control.
@@ -176,3 +178,19 @@ Example:
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.
+
+Context load balancing
+----------------------
+
+Context load balancing (aka Virtual Engine) is an i915 feature where the driver
+will pick the best engine (most idle) to submit to given previously configured
+engine map.
+
+Example:
+
+ 1.B
+
+This enables load balancing for context number one.
+
+Submissions to load balanced contexts are only allowed to use the DEFAULT engine
+specifier.