[igt-dev] [PATCH i-g-t 3/6] lib: Move aux pgtable state prepare/emit to intel_aux_pgtable.c

Imre Deak
2019-11-29T10:38:54Z

The AUX pagetables need to be set up for blits using the vebox engine
too, so move the related helper functions to intel_aux_pgtable.c.

Cc: Mika Kahola <mika.kahola@intel.com>
Cc: Brian Welty <brian.welty@intel.com>
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Imre Deak <imre.deak@intel.com>
---
lib/intel_aux_pgtable.c | 198 ++++++++++++++++++++++++++++++++++++++
lib/intel_aux_pgtable.h | 23 +++++
lib/rendercopy_gen9.c | 205 ----------------------------------------
3 files changed, 221 insertions(+), 205 deletions(-)

diff --git a/lib/intel_aux_pgtable.c b/lib/intel_aux_pgtable.c
index ea909ec0..319b2745 100644
--- a/lib/intel_aux_pgtable.c
+++ b/lib/intel_aux_pgtable.c
@@ -370,3 +370,201 @@ intel_aux_pgtable_create(drm_intel_bufmgr *bufmgr,

return pgt_bo;
}
+
+static void
+aux_pgtable_find_max_free_range(const struct igt_buf **bufs, int buf_count,
+ uint64_t *range_start, uint64_t *range_size)
+{
+ /*
+ * Keep the first page reserved, so we can differentiate pinned
+ * objects based on a non-NULL offset.
+ */
+ uint64_t start = 0x1000;
+ /* For now alloc only from the first 4GB address space. */
+ const uint64_t end = 1ULL << 32;
+ uint64_t max_range_start = 0;
+ uint64_t max_range_size = 0;
+ int i;
+
+ for (i = 0; i < buf_count; i++) {
+ if (bufs[i]->bo->offset64 >= end)
+ break;
+
+ if (bufs[i]->bo->offset64 - start > max_range_size) {
+ max_range_start = start;
+ max_range_size = bufs[i]->bo->offset64 - start;
+ }
+ start = bufs[i]->bo->offset64 + bufs[i]->bo->size;
+ }
+
+ if (start < end && end - start > max_range_size) {
+ max_range_start = start;
+ max_range_size = end - start;
+ }
+
+ *range_start = max_range_start;
+ *range_size = max_range_size;
+}
+
+static uint64_t
+aux_pgtable_find_free_range(const struct igt_buf **bufs, int buf_count,
+ uint32_t size)
+{
+ uint64_t range_start;
+ uint64_t range_size;
+ /* A compressed surface must be 64kB aligned. */
+ const uint32_t align = 0x10000;
+ int pad;
+
+ aux_pgtable_find_max_free_range(bufs, buf_count,
+ &range_start, &range_size);
+
+ pad = ALIGN(range_start, align) - range_start;
+ range_start += pad;
+ range_size -= pad;
+ igt_assert(range_size >= size);
+
+ return range_start +
+ ALIGN_DOWN(rand() % ((range_size - size) + 1), align);
+}
+
+static void
+aux_pgtable_reserve_range(const struct igt_buf **bufs, int buf_count,
+ const struct igt_buf *new_buf)
+{
+ int i;
+
+ if (new_buf->aux.stride) {
+ uint64_t pin_offset = new_buf->bo->offset64;
+
+ if (!pin_offset)
+ pin_offset = aux_pgtable_find_free_range(bufs,
+ buf_count,
+ new_buf->bo->size);
+ drm_intel_bo_set_softpin_offset(new_buf->bo, pin_offset);
+ igt_assert(new_buf->bo->offset64 == pin_offset);
+ }
+
+ for (i = 0; i < buf_count; i++)
+ if (bufs[i]->bo->offset64 > new_buf->bo->offset64)
+ break;
+
+ memmove(&bufs[i + 1], &bufs[i], sizeof(bufs[0]) * (buf_count - i));
+
+ bufs[i] = new_buf;
+}
+
+void
+gen12_aux_pgtable_init(struct aux_pgtable_info *info,
+ drm_intel_bufmgr *bufmgr,
+ const struct igt_buf *src_buf,
+ const struct igt_buf *dst_buf)
+{
+ const struct igt_buf *bufs[2];
+ const struct igt_buf *reserved_bufs[2];
+ int reserved_buf_count;
+ int i;
+
+ if (!src_buf->aux.stride && !dst_buf->aux.stride)
+ return;
+
+ bufs[0] = src_buf;
+ bufs[1] = dst_buf;
+
+ /*
+ * Ideally we'd need an IGT-wide GFX address space allocator, which
+ * would consider all allocations and thus avoid evictions. For now use
+ * a simpler scheme here, which only considers the buffers involved in
+ * the blit, which should at least minimize the chance for evictions
+ * in the case of subsequent blits:
+ * 1. If they were already bound (bo->offset64 != 0), use this
+ * address.
+ * 2. Pick a range randomly from the 4GB address space, that is not
+ * already occupied by a bound object, or an object we pinned.
+ */
+ reserved_buf_count = 0;
+ /* First reserve space for any bufs that are bound already. */
+ for (i = 0; i < ARRAY_SIZE(bufs); i++)
+ if (bufs[i]->bo->offset64)
+ aux_pgtable_reserve_range(reserved_bufs,
+ reserved_buf_count++,
+ bufs[i]);
+
+ /* Next, reserve space for unbound bufs with an AUX surface. */
+ for (i = 0; i < ARRAY_SIZE(bufs); i++)
+ if (!bufs[i]->bo->offset64 && bufs[i]->aux.stride)
+ aux_pgtable_reserve_range(reserved_bufs,
+ reserved_buf_count++,
+ bufs[i]);
+
+ /* Create AUX pgtable entries only for bufs with an AUX surface */
+ info->buf_count = 0;
+ for (i = 0; i < reserved_buf_count; i++) {
+ if (!reserved_bufs[i]->aux.stride)
+ continue;
+
+ info->bufs[info->buf_count] = reserved_bufs[i];
+ info->buf_pin_offsets[info->buf_count] =
+ reserved_bufs[i]->bo->offset64;
+ info->buf_count++;
+ }
+
+ info->pgtable_bo = intel_aux_pgtable_create(bufmgr,
+ info->bufs,
+ info->buf_count);
+ igt_assert(info->pgtable_bo);
+}
+
+void
+gen12_aux_pgtable_cleanup(struct aux_pgtable_info *info)
+{
+ int i;
+
+ /* Check that the pinned bufs kept their offset after the exec. */
+ for (i = 0; i < info->buf_count; i++)
+ igt_assert_eq_u64(info->bufs[i]->bo->offset64,
+ info->buf_pin_offsets[i]);
+
+ drm_intel_bo_unreference(info->pgtable_bo);
+}
+
+uint32_t
+gen12_create_aux_pgtable_state(struct intel_batchbuffer *batch,
+ drm_intel_bo *aux_pgtable_bo)
+{
+ uint64_t *pgtable_ptr;
+ uint32_t pgtable_ptr_offset;
+ int ret;
+
+ if (!aux_pgtable_bo)
+ return 0;
+
+ pgtable_ptr = intel_batchbuffer_subdata_alloc(batch,
+ sizeof(*pgtable_ptr),
+ sizeof(*pgtable_ptr));
+ pgtable_ptr_offset = intel_batchbuffer_subdata_offset(batch,
+ pgtable_ptr);
+
+ *pgtable_ptr = aux_pgtable_bo->offset64;
+ ret = drm_intel_bo_emit_reloc(batch->bo, pgtable_ptr_offset,
+ aux_pgtable_bo, 0,
+ 0, 0);
+ assert(ret == 0);
+
+ return pgtable_ptr_offset;
+}
+
+void
+gen12_emit_aux_pgtable_state(struct intel_batchbuffer *batch, uint32_t state)
+{
+ if (!state)
+ return;
+
+ OUT_BATCH(MI_LOAD_REGISTER_MEM_GEN8);
+ OUT_BATCH(GEN12_GFX_AUX_TABLE_BASE_ADDR);
+ OUT_RELOC(batch->bo, 0, 0, state);
+
+ OUT_BATCH(MI_LOAD_REGISTER_MEM_GEN8);
+ OUT_BATCH(GEN12_GFX_AUX_TABLE_BASE_ADDR + 4);
+ OUT_RELOC(batch->bo, 0, 0, state + 4);
+}
diff --git a/lib/intel_aux_pgtable.h b/lib/intel_aux_pgtable.h
index c0f001b4..20278db0 100644
--- a/lib/intel_aux_pgtable.h
+++ b/lib/intel_aux_pgtable.h
@@ -4,9 +4,32 @@
#include "intel_bufmgr.h"

struct igt_buf;
+struct intel_batchbuffer;
+
+struct aux_pgtable_info {
+ int buf_count;
+ const struct igt_buf *bufs[2];
+ uint64_t buf_pin_offsets[2];
+ drm_intel_bo *pgtable_bo;
+};

drm_intel_bo *
intel_aux_pgtable_create(drm_intel_bufmgr *bufmgr,
const struct igt_buf **bufs, int buf_count);

+void
+gen12_aux_pgtable_init(struct aux_pgtable_info *info,
+ drm_intel_bufmgr *bufmgr,
+ const struct igt_buf *src_buf,
+ const struct igt_buf *dst_buf);
+
+void
+gen12_aux_pgtable_cleanup(struct aux_pgtable_info *info);
+
+uint32_t
+gen12_create_aux_pgtable_state(struct intel_batchbuffer *batch,
+ drm_intel_bo *aux_pgtable_bo);
+void
+gen12_emit_aux_pgtable_state(struct intel_batchbuffer *batch, uint32_t state);
+
#endif
diff --git a/lib/rendercopy_gen9.c b/lib/rendercopy_gen9.c
index 3189594f..94e816b6 100644
--- a/lib/rendercopy_gen9.c
+++ b/lib/rendercopy_gen9.c
@@ -973,211 +973,6 @@ static void gen8_emit_primitive(struct intel_batchbuffer *batch, uint32_t offset

#define BATCH_STATE_SPLIT 2048

-static void
-aux_pgtable_find_max_free_range(const struct igt_buf **bufs, int buf_count,
- uint64_t *range_start, uint64_t *range_size)
-{
- /*
- * Keep the first page reserved, so we can differentiate pinned
- * objects based on a non-NULL offset.
- */
- uint64_t start = 0x1000;
- /* For now alloc only from the first 4GB address space. */
- const uint64_t end = 1ULL << 32;
- uint64_t max_range_start = 0;
- uint64_t max_range_size = 0;
- int i;
-
- for (i = 0; i < buf_count; i++) {
- if (bufs[i]->bo->offset64 >= end)
- break;
-
- if (bufs[i]->bo->offset64 - start > max_range_size) {
- max_range_start = start;
- max_range_size = bufs[i]->bo->offset64 - start;
- }
- start = bufs[i]->bo->offset64 + bufs[i]->bo->size;
- }
-
- if (start < end && end - start > max_range_size) {
- max_range_start = start;
- max_range_size = end - start;
- }
-
- *range_start = max_range_start;
- *range_size = max_range_size;
-}
-
-static uint64_t
-aux_pgtable_find_free_range(const struct igt_buf **bufs, int buf_count,
- uint32_t size)
-{
- uint64_t range_start;
- uint64_t range_size;
- /* A compressed surface must be 64kB aligned. */
- const uint32_t align = 0x10000;
- int pad;
-
- aux_pgtable_find_max_free_range(bufs, buf_count,
- &range_start, &range_size);
-
- pad = ALIGN(range_start, align) - range_start;
- range_start += pad;
- range_size -= pad;
- igt_assert(range_size >= size);
-
- return range_start +
- ALIGN_DOWN(rand() % ((range_size - size) + 1), align);
-}
-
-static void
-aux_pgtable_reserve_range(const struct igt_buf **bufs, int buf_count,
- const struct igt_buf *new_buf)
-{
- int i;
-
- if (new_buf->aux.stride) {
- uint64_t pin_offset = new_buf->bo->offset64;
-
- if (!pin_offset)
- pin_offset = aux_pgtable_find_free_range(bufs,
- buf_count,
- new_buf->bo->size);
- drm_intel_bo_set_softpin_offset(new_buf->bo, pin_offset);
- igt_assert(new_buf->bo->offset64 == pin_offset);
- }
-
- for (i = 0; i < buf_count; i++)
- if (bufs[i]->bo->offset64 > new_buf->bo->offset64)
- break;
-
- memmove(&bufs[i + 1], &bufs[i], sizeof(bufs[0]) * (buf_count - i));
-
- bufs[i] = new_buf;
-}
-
-struct aux_pgtable_info {
- int buf_count;
- const struct igt_buf *bufs[2];
- uint64_t buf_pin_offsets[2];
- drm_intel_bo *pgtable_bo;
-};
-
-static void
-gen12_aux_pgtable_init(struct aux_pgtable_info *info,
- drm_intel_bufmgr *bufmgr,
- const struct igt_buf *src_buf,
- const struct igt_buf *dst_buf)
-{
- const struct igt_buf *bufs[2];
- const struct igt_buf *reserved_bufs[2];
- int reserved_buf_count;
- int i;
-
- if (!src_buf->aux.stride && !dst_buf->aux.stride)
- return;
-
- bufs[0] = src_buf;
- bufs[1] = dst_buf;
-
- /*
- * Ideally we'd need an IGT-wide GFX address space allocator, which
- * would consider all allocations and thus avoid evictions. For now use
- * a simpler scheme here, which only considers the buffers involved in
- * the blit, which should at least minimize the chance for evictions
- * in the case of subsequent blits:
- * 1. If they were already bound (bo->offset64 != 0), use this
- * address.
- * 2. Pick a range randomly from the 4GB address space, that is not
- * already occupied by a bound object, or an object we pinned.
- */
- reserved_buf_count = 0;
- /* First reserve space for any bufs that are bound already. */
- for (i = 0; i < ARRAY_SIZE(bufs); i++)
- if (bufs[i]->bo->offset64)
- aux_pgtable_reserve_range(reserved_bufs,
- reserved_buf_count++,
- bufs[i]);
-
- /* Next, reserve space for unbound bufs with an AUX surface. */
- for (i = 0; i < ARRAY_SIZE(bufs); i++)
- if (!bufs[i]->bo->offset64 && bufs[i]->aux.stride)
- aux_pgtable_reserve_range(reserved_bufs,
- reserved_buf_count++,
- bufs[i]);
-
- /* Create AUX pgtable entries only for bufs with an AUX surface */
- info->buf_count = 0;
- for (i = 0; i < reserved_buf_count; i++) {
- if (!reserved_bufs[i]->aux.stride)
- continue;
-
- info->bufs[info->buf_count] = reserved_bufs[i];
- info->buf_pin_offsets[info->buf_count] =
- reserved_bufs[i]->bo->offset64;
- info->buf_count++;
- }
-
- info->pgtable_bo = intel_aux_pgtable_create(bufmgr,
- info->bufs,
- info->buf_count);
- igt_assert(info->pgtable_bo);
-}
-
-static void
-gen12_aux_pgtable_cleanup(struct aux_pgtable_info *info)
-{
- int i;
-
- /* Check that the pinned bufs kept their offset after the exec. */
- for (i = 0; i < info->buf_count; i++)
- igt_assert_eq_u64(info->bufs[i]->bo->offset64,
- info->buf_pin_offsets[i]);
-
- drm_intel_bo_unreference(info->pgtable_bo);
-}
-
-static uint32_t
-gen12_create_aux_pgtable_state(struct intel_batchbuffer *batch,
- drm_intel_bo *aux_pgtable_bo)
-{
- uint64_t *pgtable_ptr;
- uint32_t pgtable_ptr_offset;
- int ret;
-
- if (!aux_pgtable_bo)
- return 0;
-
- pgtable_ptr = intel_batchbuffer_subdata_alloc(batch,
- sizeof(*pgtable_ptr),
- sizeof(*pgtable_ptr));
- pgtable_ptr_offset = intel_batchbuffer_subdata_offset(batch,
- pgtable_ptr);
-
- *pgtable_ptr = aux_pgtable_bo->offset64;
- ret = drm_intel_bo_emit_reloc(batch->bo, pgtable_ptr_offset,
- aux_pgtable_bo, 0,
- 0, 0);
- assert(ret == 0);
-
- return pgtable_ptr_offset;
-}
-
-static void
-gen12_emit_aux_pgtable_state(struct intel_batchbuffer *batch, uint32_t state)
-{
- if (!state)
- return;
-
- OUT_BATCH(MI_LOAD_REGISTER_MEM_GEN8);
- OUT_BATCH(GEN12_GFX_AUX_TABLE_BASE_ADDR);
- OUT_RELOC(batch->bo, 0, 0, state);
-
- OUT_BATCH(MI_LOAD_REGISTER_MEM_GEN8);
- OUT_BATCH(GEN12_GFX_AUX_TABLE_BASE_ADDR + 4);
- OUT_RELOC(batch->bo, 0, 0, state + 4);
-}
-
static
void _gen9_render_copyfunc(struct intel_batchbuffer *batch,
drm_intel_context *context,
--
2.17.1