iris: Handle multiple BOs backed by the same GEM object in execbuf code

With suballocation, our batch BO list may have multiple BOs that are
suballocated from the same GEM object.  We still need to track each of
those buffers for cross-batch write tracking, cache tracking, and busy
tracking.  However, we only want to include underlying GEM objects in
the actual validation list building.  The validation list entry should
have EXEC_OBJECT_WRITE if any of the BOs are marked as writable.

We use a temporary array to map GEM handles to validation list entries
so we can quickly see if we've already emitted one and update the
EXEC_OBJECT_WRITE flag as needed.

Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/12623>
This commit is contained in:
Kenneth Graunke 2021-08-04 11:22:45 -07:00 committed by Marge Bot
parent 72a28706a4
commit 8a1fd43d61
2 changed files with 27 additions and 13 deletions

View file

@ -196,6 +196,7 @@ iris_init_batch(struct iris_context *ice,
util_dynarray_init(&batch->syncobjs, ralloc_context(NULL));
batch->exec_count = 0;
batch->max_gem_handle = 0;
batch->exec_array_size = 128;
batch->exec_bos =
malloc(batch->exec_array_size * sizeof(batch->exec_bos[0]));
@ -281,6 +282,8 @@ add_bo_to_batch(struct iris_batch *batch, struct iris_bo *bo, bool writable)
bo->index = batch->exec_count;
batch->exec_count++;
batch->aperture_space += bo->size;
batch->max_gem_handle = MAX2(batch->max_gem_handle, bo->gem_handle);
}
/**
@ -748,23 +751,32 @@ submit_batch(struct iris_batch *batch)
struct drm_i915_gem_exec_object2 *validation_list =
malloc(batch->exec_count * sizeof(*validation_list));
unsigned *index_for_handle =
calloc(batch->max_gem_handle + 1, sizeof(unsigned));
unsigned validation_count = 0;
for (int i = 0; i < batch->exec_count; i++) {
struct iris_bo *bo = batch->exec_bos[i];
bool written = BITSET_TEST(batch->bos_written, i);
unsigned extra_flags = 0;
if (written)
extra_flags |= EXEC_OBJECT_WRITE;
if (!iris_bo_is_external(bo))
extra_flags |= EXEC_OBJECT_ASYNC;
validation_list[i] = (struct drm_i915_gem_exec_object2) {
.handle = bo->gem_handle,
.offset = bo->address,
.flags = bo->real.kflags | extra_flags,
};
unsigned prev_index = index_for_handle[bo->gem_handle];
if (prev_index > 0) {
if (written)
validation_list[prev_index].flags |= EXEC_OBJECT_WRITE;
} else {
index_for_handle[bo->gem_handle] = validation_count;
validation_list[validation_count] =
(struct drm_i915_gem_exec_object2) {
.handle = bo->gem_handle,
.offset = bo->address,
.flags = bo->real.kflags | (written ? EXEC_OBJECT_WRITE : 0) |
(iris_bo_is_external(bo) ? 0 : EXEC_OBJECT_ASYNC),
};
++validation_count;
}
}
free(index_for_handle);
if (INTEL_DEBUG & (DEBUG_BATCH | DEBUG_SUBMIT)) {
dump_fence_list(batch);
dump_validation_list(batch, validation_list);
@ -788,7 +800,7 @@ submit_batch(struct iris_batch *batch)
*/
struct drm_i915_gem_execbuffer2 execbuf = {
.buffers_ptr = (uintptr_t) validation_list,
.buffer_count = batch->exec_count,
.buffer_count = validation_count,
.batch_start_offset = 0,
/* This must be QWord aligned. */
.batch_len = ALIGN(batch->primary_batch_size, 8),
@ -887,6 +899,7 @@ _iris_batch_flush(struct iris_batch *batch, const char *file, int line)
iris_syncobj_signal(screen->bufmgr, iris_batch_get_signal_syncobj(batch));
batch->exec_count = 0;
batch->max_gem_handle = 0;
batch->aperture_space = 0;
util_dynarray_foreach(&batch->syncobjs, struct iris_syncobj *, s)

View file

@ -87,6 +87,7 @@ struct iris_batch {
int exec_array_size;
/** Bitset of whether this batch writes to BO `i'. */
BITSET_WORD *bos_written;
uint32_t max_gem_handle;
/** Whether INTEL_BLACKHOLE_RENDER is enabled in the batch (aka first
* instruction is a MI_BATCH_BUFFER_END).