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 <caio.oliveira@intel.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/14687>
This commit is contained in:
Kenneth Graunke 2020-08-28 15:08:29 -07:00 committed by Marge Bot
parent 31eeb72e45
commit a90a1f15a7
4 changed files with 46 additions and 35 deletions

View file

@ -234,6 +234,8 @@ iris_init_batch(struct iris_context *ice,
batch->decoder.dynamic_base = IRIS_MEMZONE_DYNAMIC_START; batch->decoder.dynamic_base = IRIS_MEMZONE_DYNAMIC_START;
batch->decoder.instruction_base = IRIS_MEMZONE_SHADER_START; batch->decoder.instruction_base = IRIS_MEMZONE_SHADER_START;
batch->decoder.max_vbo_decoded_lines = 32; 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); 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); 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);
} }
ice->batches[IRIS_BATCH_BLITTER].exec_flags = I915_EXEC_BLT;
} }
static int static int
iris_create_engines_context(struct iris_context *ice, int priority) iris_create_engines_context(struct iris_context *ice, int priority)
{ {
struct iris_screen *screen = (void *) ice->ctx.screen; struct iris_screen *screen = (void *) ice->ctx.screen;
const struct intel_device_info *devinfo = &screen->devinfo;
int fd = iris_bufmgr_get_fd(screen->bufmgr); int fd = iris_bufmgr_get_fd(screen->bufmgr);
struct drm_i915_query_engine_info *engines_info = struct drm_i915_query_engine_info *engines_info =
@ -275,14 +280,18 @@ iris_create_engines_context(struct iris_context *ice, int priority)
return -1; return -1;
} }
STATIC_ASSERT(IRIS_BATCH_COUNT == 2); STATIC_ASSERT(IRIS_BATCH_COUNT == 3);
uint16_t engine_classes[IRIS_BATCH_COUNT] = { uint16_t engine_classes[IRIS_BATCH_COUNT] = {
[IRIS_BATCH_RENDER] = I915_ENGINE_CLASS_RENDER, [IRIS_BATCH_RENDER] = I915_ENGINE_CLASS_RENDER,
[IRIS_BATCH_COMPUTE] = 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 = 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); engine_classes);
if (engines_ctx < 0) { 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]; struct iris_bo_screen_deps *deps = &bo->deps[screen->id];
int batch_idx = batch->name; int batch_idx = batch->name;
#if IRIS_BATCH_COUNT == 2 /* Someday if IRIS_BATCH_COUNT increases to 4, we could do:
/* 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:
* int other_batch_idxs[IRIS_BATCH_COUNT - 1] = { * int other_batch_idxs[IRIS_BATCH_COUNT - 1] = {
* (batch_idx + 1) & 3, * (batch_idx + 1) & 3,
* (batch_idx + 2) & 3, * (batch_idx + 2) & 3,
* (batch_idx + 3) & 3, * (batch_idx + 3) & 3,
* }; * };
*/ */
#error "Implement me." STATIC_ASSERT(IRIS_BATCH_COUNT == 3);
#endif 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. */ for (unsigned i = 0; i < ARRAY_SIZE(other_batch_idxs); i++) {
if (deps->write_syncobjs[other_batch_idx]) unsigned other_batch_idx = other_batch_idxs[i];
move_syncobj_to_batch(batch, &deps->write_syncobjs[other_batch_idx],
I915_EXEC_FENCE_WAIT);
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) { struct iris_syncobj *batch_syncobj =
/* If we're writing to it, set our batch's syncobj as write_syncobj so iris_batch_get_signal_syncobj(batch);
* 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);
move_syncobj_to_batch(batch, &deps->read_syncobjs[other_batch_idx], if (write) {
I915_EXEC_FENCE_WAIT); /* 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 { move_syncobj_to_batch(batch, &deps->read_syncobjs[other_batch_idx],
/* If we're reading, replace the other read from our batch index. */ I915_EXEC_FENCE_WAIT);
iris_syncobj_reference(bufmgr, &deps->read_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);
}
} }
} }
@ -995,6 +1002,7 @@ iris_batch_name_to_string(enum iris_batch_name name)
const char *names[IRIS_BATCH_COUNT] = { const char *names[IRIS_BATCH_COUNT] = {
[IRIS_BATCH_RENDER] = "render", [IRIS_BATCH_RENDER] = "render",
[IRIS_BATCH_COMPUTE] = "compute", [IRIS_BATCH_COMPUTE] = "compute",
[IRIS_BATCH_BLITTER] = "blitter",
}; };
return names[name]; return names[name];
} }

View file

@ -57,6 +57,7 @@ struct iris_context;
enum iris_batch_name { enum iris_batch_name {
IRIS_BATCH_RENDER, IRIS_BATCH_RENDER,
IRIS_BATCH_COMPUTE, IRIS_BATCH_COMPUTE,
IRIS_BATCH_BLITTER,
}; };
struct iris_batch { struct iris_batch {

View file

@ -146,7 +146,7 @@ enum iris_heap {
extern const char *iris_heap_to_string[]; extern const char *iris_heap_to_string[];
#define IRIS_BATCH_COUNT 2 #define IRIS_BATCH_COUNT 3
struct iris_bo_screen_deps { struct iris_bo_screen_deps {
struct iris_syncobj *write_syncobjs[IRIS_BATCH_COUNT]; struct iris_syncobj *write_syncobjs[IRIS_BATCH_COUNT];

View file

@ -71,6 +71,8 @@ iris_lost_context_state(struct iris_batch *batch)
batch->screen->vtbl.init_render_context(batch); batch->screen->vtbl.init_render_context(batch);
} else if (batch->name == IRIS_BATCH_COMPUTE) { } else if (batch->name == IRIS_BATCH_COMPUTE) {
batch->screen->vtbl.init_compute_context(batch); batch->screen->vtbl.init_compute_context(batch);
} else if (batch->name == IRIS_BATCH_BLITTER) {
/* No state to set up */
} else { } else {
unreachable("unhandled batch reset"); unreachable("unhandled batch reset");
} }