iris/batch: Add support for engines contexts

As described in "intel: Add intel_gem_create_context_engines", this
should make it easier to support an I915_ENGINE_CLASS_FOO engine in
the future. For example, maybe something like:

98c3bbd5b5

Reworks:
 * Tweak engine counting logic (s-b Ken)
 * Tweak init of engine_classes in iris_init_engines_context (s-b Ken)
 * Add STATIC_ASSERT on engine_classes (Jordan)
 * Paulo: Call iris_hw_context_set_unrecoverable() for engines context
 * Rename to has_engines_context (s-b Paulo)
 * Jordan: Handle creating a new engines context when the context needs
   to be replaced.
 * Ken: Tweak context destroy code paths.
 * Call iris_lost_context_state on every batch. (s-b Ken)

Signed-off-by: Jordan Justen <jordan.l.justen@intel.com>
Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/12692>
This commit is contained in:
Jordan Justen 2021-08-31 13:37:12 -07:00
parent 9f0070e9e8
commit 5c4c8bdc4c
2 changed files with 105 additions and 12 deletions

View file

@ -180,6 +180,12 @@ iris_init_batch(struct iris_context *ice,
struct iris_batch *batch = &ice->batches[name]; struct iris_batch *batch = &ice->batches[name];
struct iris_screen *screen = (void *) ice->ctx.screen; struct iris_screen *screen = (void *) ice->ctx.screen;
/* Note: ctx_id, exec_flags and has_engines_context fields are initialized
* at an earlier phase when contexts are created.
*
* Ref: iris_init_engines_context(), iris_init_non_engine_contexts()
*/
batch->screen = screen; batch->screen = screen;
batch->dbg = &ice->dbg; batch->dbg = &ice->dbg;
batch->reset = &ice->reset; batch->reset = &ice->reset;
@ -243,14 +249,74 @@ iris_init_non_engine_contexts(struct iris_context *ice, int priority)
struct iris_batch *batch = &ice->batches[i]; struct iris_batch *batch = &ice->batches[i];
batch->ctx_id = iris_create_hw_context(screen->bufmgr); batch->ctx_id = iris_create_hw_context(screen->bufmgr);
batch->exec_flags = I915_EXEC_RENDER; batch->exec_flags = I915_EXEC_RENDER;
batch->has_engines_context = false;
assert(batch->ctx_id); assert(batch->ctx_id);
iris_hw_context_set_priority(screen->bufmgr, batch->ctx_id, priority); iris_hw_context_set_priority(screen->bufmgr, batch->ctx_id, priority);
} }
} }
static int
iris_create_engines_context(struct iris_context *ice, int priority)
{
struct iris_screen *screen = (void *) ice->ctx.screen;
int fd = iris_bufmgr_get_fd(screen->bufmgr);
struct drm_i915_query_engine_info *engines_info =
intel_i915_query_alloc(fd, DRM_I915_QUERY_ENGINE_INFO);
if (!engines_info)
return -1;
if (intel_gem_count_engines(engines_info, I915_ENGINE_CLASS_RENDER) < 1) {
free(engines_info);
return -1;
}
STATIC_ASSERT(IRIS_BATCH_COUNT == 2);
uint16_t engine_classes[IRIS_BATCH_COUNT] = {
[IRIS_BATCH_RENDER] = I915_ENGINE_CLASS_RENDER,
[IRIS_BATCH_COMPUTE] = I915_ENGINE_CLASS_RENDER,
};
int engines_ctx =
intel_gem_create_context_engines(fd, engines_info, IRIS_BATCH_COUNT,
engine_classes);
if (engines_ctx < 0) {
free(engines_info);
return -1;
}
iris_hw_context_set_unrecoverable(screen->bufmgr, engines_ctx);
free(engines_info);
return engines_ctx;
}
static bool
iris_init_engines_context(struct iris_context *ice, int priority)
{
int engines_ctx = iris_create_engines_context(ice, priority);
if (engines_ctx < 0)
return false;
struct iris_screen *screen = (void *) ice->ctx.screen;
iris_hw_context_set_priority(screen->bufmgr, engines_ctx, priority);
for (int i = 0; i < IRIS_BATCH_COUNT; i++) {
struct iris_batch *batch = &ice->batches[i];
batch->ctx_id = engines_ctx;
batch->exec_flags = i;
batch->has_engines_context = true;
}
return true;
}
void void
iris_init_batches(struct iris_context *ice, int priority) iris_init_batches(struct iris_context *ice, int priority)
{ {
if (!iris_init_engines_context(ice, priority))
iris_init_non_engine_contexts(ice, priority); iris_init_non_engine_contexts(ice, priority);
for (int i = 0; i < IRIS_BATCH_COUNT; i++) for (int i = 0; i < IRIS_BATCH_COUNT; i++)
iris_init_batch(ice, (enum iris_batch_name) i); iris_init_batch(ice, (enum iris_batch_name) i);
@ -488,6 +554,8 @@ iris_batch_free(struct iris_batch *batch)
batch->map = NULL; batch->map = NULL;
batch->map_next = NULL; batch->map_next = NULL;
/* iris_destroy_batches() will destroy engines contexts. */
if (!batch->has_engines_context)
iris_destroy_kernel_context(bufmgr, batch->ctx_id); iris_destroy_kernel_context(bufmgr, batch->ctx_id);
iris_destroy_batch_measure(batch->measure); iris_destroy_batch_measure(batch->measure);
@ -502,6 +570,15 @@ iris_batch_free(struct iris_batch *batch)
void void
iris_destroy_batches(struct iris_context *ice) iris_destroy_batches(struct iris_context *ice)
{ {
/* If we are using an engines context, then a single kernel context is
* created, with multiple hardware contexts. So, we only need to destroy
* the context on the first batch.
*/
if (ice->batches[0].has_engines_context) {
iris_destroy_kernel_context(ice->batches[0].screen->bufmgr,
ice->batches[0].ctx_id);
}
for (int i = 0; i < IRIS_BATCH_COUNT; i++) for (int i = 0; i < IRIS_BATCH_COUNT; i++)
iris_batch_free(&ice->batches[i]); iris_batch_free(&ice->batches[i]);
} }
@ -616,11 +693,25 @@ iris_finish_batch(struct iris_batch *batch)
* Replace our current GEM context with a new one (in case it got banned). * Replace our current GEM context with a new one (in case it got banned).
*/ */
static bool static bool
replace_hw_ctx(struct iris_batch *batch) replace_kernel_ctx(struct iris_batch *batch)
{ {
struct iris_screen *screen = batch->screen; struct iris_screen *screen = batch->screen;
struct iris_bufmgr *bufmgr = screen->bufmgr; struct iris_bufmgr *bufmgr = screen->bufmgr;
if (batch->has_engines_context) {
struct iris_context *ice = batch->ice;
int priority = iris_kernel_context_get_priority(bufmgr, batch->ctx_id);
uint32_t old_ctx = batch->ctx_id;
int new_ctx = iris_create_engines_context(ice, priority);
if (new_ctx < 0)
return false;
for (int i = 0; i < IRIS_BATCH_COUNT; i++) {
ice->batches[i].ctx_id = new_ctx;
/* Notify the context that state must be re-initialized. */
iris_lost_context_state(&ice->batches[i]);
}
iris_destroy_kernel_context(bufmgr, old_ctx);
} else {
uint32_t new_ctx = iris_clone_hw_context(bufmgr, batch->ctx_id); uint32_t new_ctx = iris_clone_hw_context(bufmgr, batch->ctx_id);
if (!new_ctx) if (!new_ctx)
return false; return false;
@ -630,6 +721,7 @@ replace_hw_ctx(struct iris_batch *batch)
/* Notify the context that state must be re-initialized. */ /* Notify the context that state must be re-initialized. */
iris_lost_context_state(batch); iris_lost_context_state(batch);
}
return true; return true;
} }
@ -662,7 +754,7 @@ iris_batch_check_for_reset(struct iris_batch *batch)
* Throw it away and start with a fresh context. Ideally this may * Throw it away and start with a fresh context. Ideally this may
* catch the problem before our next execbuf fails with -EIO. * catch the problem before our next execbuf fails with -EIO.
*/ */
replace_hw_ctx(batch); replace_kernel_ctx(batch);
} }
return status; return status;
@ -970,7 +1062,7 @@ _iris_batch_flush(struct iris_batch *batch, const char *file, int line)
* dubiously claim success... * dubiously claim success...
* Also handle ENOMEM here. * Also handle ENOMEM here.
*/ */
if ((ret == -EIO || ret == -ENOMEM) && replace_hw_ctx(batch)) { if ((ret == -EIO || ret == -ENOMEM) && replace_kernel_ctx(batch)) {
if (batch->reset->reset) { if (batch->reset->reset) {
/* Tell gallium frontends the device is lost and it was our fault. */ /* Tell gallium frontends the device is lost and it was our fault. */
batch->reset->reset(batch->reset->data, PIPE_GUILTY_CONTEXT_RESET); batch->reset->reset(batch->reset->data, PIPE_GUILTY_CONTEXT_RESET);

View file

@ -81,6 +81,7 @@ struct iris_batch {
uint32_t ctx_id; uint32_t ctx_id;
uint32_t exec_flags; uint32_t exec_flags;
bool has_engines_context;
/** A list of all BOs referenced by this batch */ /** A list of all BOs referenced by this batch */
struct iris_bo **exec_bos; struct iris_bo **exec_bos;