[igt-dev] [PATCH i-g-t v2 2/4] lib/intel_batchbuffer: add bb reset

Zbigniew Kempczyński
2020-06-04T09:14:02Z

For some scenarios we want to keep previous objects and their offsets
and recreate only batchbuffer object. To allow user do that add
bb reset function which can or not purge collected objects from
previous run.

Signed-off-by: Zbigniew Kempczyński <zbigniew.kempczynski@intel.com>
Cc: Chris Wilson <chris@chris-wilson.co.uk>
---
lib/intel_batchbuffer.c | 84 +++++++++++++++++++++++++++++++++++------
lib/intel_batchbuffer.h | 12 ++++--
2 files changed, 81 insertions(+), 15 deletions(-)

diff --git a/lib/intel_batchbuffer.c b/lib/intel_batchbuffer.c
index 49f2d0fe..2a882627 100644
--- a/lib/intel_batchbuffer.c
+++ b/lib/intel_batchbuffer.c
@@ -1203,7 +1203,7 @@ static void __reallocate_objects(struct intel_bb *ibb)
}

/**
- * __intel_bb_create:
+ * intel_bb_create:
* @i915: drm fd
* @size: size of the batchbuffer
*
@@ -1250,6 +1250,26 @@ static void __do_nothing(void *node)
(void) node;
}

+static void __intel_bb_destroy_objects(struct intel_bb *ibb)
+{
+ uint32_t i;
+
+ /* Free relocations */
+ for (i = 0; i < ibb->num_objects; i++)
+ free(from_user_pointer(ibb->objects[i].relocs_ptr));
+
+ free(ibb->objects);
+ tdestroy(ibb->root, __do_nothing);
+
+ ibb->objects = NULL;
+ ibb->root = NULL;
+ ibb->num_objects = 0;
+ ibb->num_relocs = 0;
+ ibb->allocated_objects = 0;
+ ibb->allocated_relocs = 0;
+ ibb->ptr = ibb->batch;
+}
+
/**
* intel_bb_destroy:
* @ibb: pointer to intel_bb
@@ -1258,21 +1278,33 @@ static void __do_nothing(void *node)
*/
void intel_bb_destroy(struct intel_bb *ibb)
{
- uint32_t i;
-
igt_assert(ibb);

- /* Free relocations */
- for (i = 0; i < ibb->num_objects; i++)
- free(from_user_pointer(ibb->objects[i].relocs_ptr));
+ __intel_bb_destroy_objects(ibb);
+ gem_close(ibb->i915, ibb->handle);

- free(ibb->objects);
- tdestroy(ibb->root, __do_nothing);
+ free(ibb);
+}
+
+/*
+ * intel_bb_reset:
+ * @ibb: pointer to intel_bb
+ * @purge_objects_cache: if true destroy internal execobj and relocs + cache
+ *
+ * Recreate batch bo.
+*/
+void intel_bb_reset(struct intel_bb *ibb, bool purge_objects_cache)
+{
+ if (purge_objects_cache) {
+ __intel_bb_destroy_objects(ibb);
+ __reallocate_objects(ibb);
+ }

- munmap(ibb->batch, ibb->size);
gem_close(ibb->i915, ibb->handle);
+ ibb->handle = gem_create(ibb->i915, ibb->size);

- free(ibb);
+ intel_bb_add_object(ibb, ibb->handle, 0, false);
+ ibb->ptr = ibb->batch;
}

/**
@@ -1573,7 +1605,7 @@ int __intel_bb_exec(struct intel_bb *ibb, uint32_t end_offset,
execbuf.buffers_ptr = (uintptr_t) ibb->objects;
execbuf.buffer_count = ibb->num_objects;
execbuf.batch_len = end_offset;
- execbuf.rsvd1 = ctx;
+ execbuf.rsvd1 = ibb->ctx = ctx;
execbuf.flags = flags | I915_EXEC_BATCH_FIRST;

ret = __gem_execbuf(ibb->i915, &execbuf);
@@ -1649,3 +1681,33 @@ uint64_t intel_bb_get_object_offset(struct intel_bb *ibb, uint32_t handle)

return (*found)->offset;
}
+
+/**
+ * intel_bb_object_offset_to_buf:
+ * @ibb: pointer to intel_bb
+ * @buf: buffer we want to store last exec offset and context id
+ *
+ * Copy object offset used in the batch to intel_buf to allow caller prepare
+ * other batch likely without relocations.
+ */
+bool intel_bb_object_offset_to_buf(struct intel_bb *ibb, struct intel_buf *buf)
+{
+ struct drm_i915_gem_exec_object2 object = { .handle = buf->handle };
+ struct drm_i915_gem_exec_object2 **found;
+
+ igt_assert(ibb);
+ igt_assert(buf);
+
+ found = tfind((void *) &object, &ibb->root, __compare_objects);
+ if (!found) {
+ buf->addr.offset = 0;
+ buf->addr.ctx = 0;
+
+ return false;
+ }
+
+ buf->addr.offset = (*found)->offset;
+ buf->addr.ctx = ibb->ctx;
+
+ return true;
+}
diff --git a/lib/intel_batchbuffer.h b/lib/intel_batchbuffer.h
index ae052c17..0649fc22 100644
--- a/lib/intel_batchbuffer.h
+++ b/lib/intel_batchbuffer.h
@@ -405,8 +405,8 @@ igt_vme_func_t igt_get_media_vme_func(int devid);

/**
* igt_media_spinfunc_t:
- * @batch: batchbuffer object
- * @dst: destination i-g-t buffer object
+ * @i915: drm fd
+ * @buf: destination buffer object
* @spins: number of loops to execute
*
* This is the type of the per-platform media spin functions. The
@@ -420,8 +420,8 @@ igt_vme_func_t igt_get_media_vme_func(int devid);
* destination buffer on completion. This utility provides a simple way
* to keep the render engine busy for a set time for various tests.
*/
-typedef void (*igt_media_spinfunc_t)(struct intel_batchbuffer *batch,
- const struct igt_buf *dst, uint32_t spins);
+typedef void (*igt_media_spinfunc_t)(int i915,
+ struct intel_buf *buf, uint32_t spins);

igt_media_spinfunc_t igt_get_media_spinfunc(int devid);

@@ -443,6 +443,8 @@ struct intel_bb {
uint64_t gtt_size;
bool supports_48b_address;

+ uint32_t ctx;
+
void *root;
struct drm_i915_gem_exec_object2 *objects;
uint32_t num_objects;
@@ -457,6 +459,7 @@ struct intel_bb {
struct intel_bb *intel_bb_create(int i915, uint32_t size);

void intel_bb_destroy(struct intel_bb *ibb);
+void intel_bb_reset(struct intel_bb *ibb, bool purge_objects_cache);
void intel_bb_set_debug(struct intel_bb *ibb, bool debug);

static inline uint32_t intel_bb_offset(struct intel_bb *ibb)
@@ -524,5 +527,6 @@ void intel_bb_exec_with_context(struct intel_bb *ibb, uint32_t end_offset,
uint32_t ctx, uint64_t flags, bool sync);

uint64_t intel_bb_get_object_offset(struct intel_bb *ibb, uint32_t handle);
+bool intel_bb_object_offset_to_buf(struct intel_bb *ibb, struct intel_buf *buf);

#endif