From a90a1f15a7c8943893e76a202f65bdac8c3e6b49 Mon Sep 17 00:00:00 2001 From: Kenneth Graunke Date: Fri, 28 Aug 2020 15:08:29 -0700 Subject: [PATCH] iris: Create an IRIS_BATCH_BLITTER for using the BLT command streamer We removed all the hardware blitter support from i965 years ago because the blitter was not worth using (limited functionality, bad performance, extra synchronization, and worse). However, on Tigerlake there are new blitter commands that are actually fast and allow us to do proper asynchronous copies while 3D is busy doing other work. So, reintroduce the blitter. We'll want to use it. Reviewed-by: Caio Oliveira Part-of: --- src/gallium/drivers/iris/iris_batch.c | 76 ++++++++++++++----------- src/gallium/drivers/iris/iris_batch.h | 1 + src/gallium/drivers/iris/iris_bufmgr.h | 2 +- src/gallium/drivers/iris/iris_context.c | 2 + 4 files changed, 46 insertions(+), 35 deletions(-) diff --git a/src/gallium/drivers/iris/iris_batch.c b/src/gallium/drivers/iris/iris_batch.c index 432cc5a4c33..e1f7e53884c 100644 --- a/src/gallium/drivers/iris/iris_batch.c +++ b/src/gallium/drivers/iris/iris_batch.c @@ -234,6 +234,8 @@ iris_init_batch(struct iris_context *ice, batch->decoder.dynamic_base = IRIS_MEMZONE_DYNAMIC_START; batch->decoder.instruction_base = IRIS_MEMZONE_SHADER_START; batch->decoder.max_vbo_decoded_lines = 32; + if (batch->name == IRIS_BATCH_BLITTER) + batch->decoder.engine = I915_ENGINE_CLASS_COPY; } iris_init_batch_measure(ice, batch); @@ -256,12 +258,15 @@ iris_init_non_engine_contexts(struct iris_context *ice, int priority) assert(batch->ctx_id); iris_hw_context_set_priority(screen->bufmgr, batch->ctx_id, priority); } + + ice->batches[IRIS_BATCH_BLITTER].exec_flags = I915_EXEC_BLT; } static int iris_create_engines_context(struct iris_context *ice, int priority) { struct iris_screen *screen = (void *) ice->ctx.screen; + const struct intel_device_info *devinfo = &screen->devinfo; int fd = iris_bufmgr_get_fd(screen->bufmgr); struct drm_i915_query_engine_info *engines_info = @@ -275,14 +280,18 @@ iris_create_engines_context(struct iris_context *ice, int priority) return -1; } - STATIC_ASSERT(IRIS_BATCH_COUNT == 2); + STATIC_ASSERT(IRIS_BATCH_COUNT == 3); uint16_t engine_classes[IRIS_BATCH_COUNT] = { [IRIS_BATCH_RENDER] = I915_ENGINE_CLASS_RENDER, [IRIS_BATCH_COMPUTE] = I915_ENGINE_CLASS_RENDER, + [IRIS_BATCH_BLITTER] = I915_ENGINE_CLASS_COPY, }; + /* Blitter is only supported on Gfx12+ */ + unsigned num_batches = IRIS_BATCH_COUNT - (devinfo->ver >= 12 ? 0 : 1); + int engines_ctx = - intel_gem_create_context_engines(fd, engines_info, IRIS_BATCH_COUNT, + intel_gem_create_context_engines(fd, engines_info, num_batches, engine_classes); if (engines_ctx < 0) { @@ -822,49 +831,47 @@ update_bo_syncobjs(struct iris_batch *batch, struct iris_bo *bo, bool write) struct iris_bo_screen_deps *deps = &bo->deps[screen->id]; int batch_idx = batch->name; -#if IRIS_BATCH_COUNT == 2 - /* Due to the above, we exploit the fact that IRIS_NUM_BATCHES is actually - * 2, which means there's only one other batch we need to care about. - */ - int other_batch_idx = 1 - batch_idx; -#else - /* For IRIS_BATCH_COUNT == 3 we can do: - * int other_batch_idxs[IRIS_BATCH_COUNT - 1] = { - * (batch_idx ^ 1) & 1, - * (batch_idx ^ 2) & 2, - * }; - * For IRIS_BATCH_COUNT == 4 we can do: + /* Someday if IRIS_BATCH_COUNT increases to 4, we could do: + * * int other_batch_idxs[IRIS_BATCH_COUNT - 1] = { * (batch_idx + 1) & 3, * (batch_idx + 2) & 3, * (batch_idx + 3) & 3, * }; */ -#error "Implement me." -#endif + STATIC_ASSERT(IRIS_BATCH_COUNT == 3); + int other_batch_idxs[IRIS_BATCH_COUNT - 1] = { + (batch_idx ^ 1) & 1, + (batch_idx ^ 2) & 2, + }; - /* If it is being written to by others, wait on it. */ - if (deps->write_syncobjs[other_batch_idx]) - move_syncobj_to_batch(batch, &deps->write_syncobjs[other_batch_idx], - I915_EXEC_FENCE_WAIT); + for (unsigned i = 0; i < ARRAY_SIZE(other_batch_idxs); i++) { + unsigned other_batch_idx = other_batch_idxs[i]; - struct iris_syncobj *batch_syncobj = iris_batch_get_signal_syncobj(batch); + /* If it is being written to by others, wait on it. */ + if (deps->write_syncobjs[other_batch_idx]) + move_syncobj_to_batch(batch, &deps->write_syncobjs[other_batch_idx], + I915_EXEC_FENCE_WAIT); - if (write) { - /* If we're writing to it, set our batch's syncobj as write_syncobj so - * others can wait on us. Also wait every reader we care about before - * writing. - */ - iris_syncobj_reference(bufmgr, &deps->write_syncobjs[batch_idx], - batch_syncobj); + struct iris_syncobj *batch_syncobj = + iris_batch_get_signal_syncobj(batch); - move_syncobj_to_batch(batch, &deps->read_syncobjs[other_batch_idx], - I915_EXEC_FENCE_WAIT); + if (write) { + /* If we're writing to it, set our batch's syncobj as write_syncobj + * so others can wait on us. Also wait every reader we care about + * before writing. + */ + iris_syncobj_reference(bufmgr, &deps->write_syncobjs[batch_idx], + batch_syncobj); - } else { - /* If we're reading, replace the other read from our batch index. */ - iris_syncobj_reference(bufmgr, &deps->read_syncobjs[batch_idx], - batch_syncobj); + move_syncobj_to_batch(batch, &deps->read_syncobjs[other_batch_idx], + I915_EXEC_FENCE_WAIT); + + } else { + /* If we're reading, replace the other read from our batch index. */ + iris_syncobj_reference(bufmgr, &deps->read_syncobjs[batch_idx], + batch_syncobj); + } } } @@ -995,6 +1002,7 @@ iris_batch_name_to_string(enum iris_batch_name name) const char *names[IRIS_BATCH_COUNT] = { [IRIS_BATCH_RENDER] = "render", [IRIS_BATCH_COMPUTE] = "compute", + [IRIS_BATCH_BLITTER] = "blitter", }; return names[name]; } diff --git a/src/gallium/drivers/iris/iris_batch.h b/src/gallium/drivers/iris/iris_batch.h index 55db669643d..1b5b4638753 100644 --- a/src/gallium/drivers/iris/iris_batch.h +++ b/src/gallium/drivers/iris/iris_batch.h @@ -57,6 +57,7 @@ struct iris_context; enum iris_batch_name { IRIS_BATCH_RENDER, IRIS_BATCH_COMPUTE, + IRIS_BATCH_BLITTER, }; struct iris_batch { diff --git a/src/gallium/drivers/iris/iris_bufmgr.h b/src/gallium/drivers/iris/iris_bufmgr.h index 8ecea2e51e7..24cd418965d 100644 --- a/src/gallium/drivers/iris/iris_bufmgr.h +++ b/src/gallium/drivers/iris/iris_bufmgr.h @@ -146,7 +146,7 @@ enum iris_heap { extern const char *iris_heap_to_string[]; -#define IRIS_BATCH_COUNT 2 +#define IRIS_BATCH_COUNT 3 struct iris_bo_screen_deps { struct iris_syncobj *write_syncobjs[IRIS_BATCH_COUNT]; diff --git a/src/gallium/drivers/iris/iris_context.c b/src/gallium/drivers/iris/iris_context.c index 3d5c75489de..1a92df1a5e6 100644 --- a/src/gallium/drivers/iris/iris_context.c +++ b/src/gallium/drivers/iris/iris_context.c @@ -71,6 +71,8 @@ iris_lost_context_state(struct iris_batch *batch) batch->screen->vtbl.init_render_context(batch); } else if (batch->name == IRIS_BATCH_COMPUTE) { batch->screen->vtbl.init_compute_context(batch); + } else if (batch->name == IRIS_BATCH_BLITTER) { + /* No state to set up */ } else { unreachable("unhandled batch reset"); }