libdrm/iris: map PPGTT buffers lazy + lseek

* let iris handle buffer management, this implies that BOs are mapped to
  the PPGTT during buffer execution and unmapped by iris later, for this
  to work buffers need to be unmapped when allocating cached BOs
  (vma_free) which requires a patch

* support lseek (drm_lseek for now) for determining object size

issue #4380
This commit is contained in:
Sebastian Sumpf 2021-10-22 07:34:17 +02:00 committed by Christian Helmuth
parent 96ab58691a
commit ce409a2438
5 changed files with 85 additions and 14 deletions

View File

@ -1 +1 @@
c964a648360166b72246613a7be71bbfa6475d88
ad8293ad3be9e4d0158ae5fbabb9fde180cea1ac

View File

@ -17,8 +17,10 @@ PATCHES := src/lib/mesa/patches/bitset_redefined.patch \
src/lib/mesa/patches/etnaviv.patch \
src/lib/mesa/patches/iris.patch \
src/lib/mesa/patches/iris_bufmgr_tmp.patch \
src/lib/mesa/patches/iris_bufmgr_unmap.patch \
src/lib/mesa/patches/iris_binder.patch \
src/lib/mesa/patches/iris_disable_compute.patch \
src/lib/mesa/patches/lseek.patch \
src/lib/mesa/patches/mesa.patch \
src/lib/mesa/patches/os_mmap.patch \
src/lib/mesa/patches/softpipe_cache.patch

View File

@ -28,6 +28,7 @@ extern "C" {
#include <errno.h>
#include <drm.h>
#include <i915_drm.h>
#include <unistd.h>
#define DRM_NUMBER(req) ((req) & 0xff)
}
@ -251,7 +252,7 @@ class Drm_call
Genode::Env &_env;
Genode::Heap _heap { _env.ram(), _env.rm() };
Gpu::Connection _gpu_session { _env };
Gpu::Connection _gpu_session { _env, 3*1024*1024 };
Gpu::Info_intel const &_gpu_info {
*_gpu_session.attached_info<Gpu::Info_intel>() };
size_t _available_gtt_size { _gpu_info.aperture_size };
@ -1032,9 +1033,6 @@ class Drm_call
Genode::warning("handle: ", obj[i].handle, " reused but is busy");
if (b.gpu_vaddr_valid && b.gpu_vaddr.addr != obj[i].offset) {
Genode::error("unmap already mapped ", b.id().value, " ",
Genode::Hex(b.gpu_vaddr.addr), "->",
Genode::Hex(obj[i].offset));
_unmap_buffer_ppgtt(b);
}
@ -1320,12 +1318,15 @@ class Drm_call
Gpu::Buffer_id const id { .value = p->handle };
try {
_buffer_space.apply<Buffer>(id, [&](Buffer const &b) {
_buffer_space.apply<Buffer>(id, [&](Buffer const &) {
if (!prime_handle.value)
prime_handle = id;
if (prime_handle.value != id.value)
Genode::error("prime handle changed - ignored ", b.id().value);
if (prime_handle.value != id.value) {
Genode::warning("prime handle changed: ", id.value);
prime_handle = id;
}
});
} catch (Genode::Id_space<Buffer>::Unknown_id) {
return -1;
@ -1375,6 +1376,19 @@ class Drm_call
_gpu_session.completion_sigh(_completion_sigh);
}
int lseek(int fd, off_t offset, int whence)
{
if (fd != prime_fd || offset || whence != SEEK_END)
return -1;
int size = -1;
_buffer_space.apply<Buffer>(prime_handle, [&](Buffer const &b) {
size =(int)b.size;
});
return size;
}
bool map_buffer_ggtt(Offset offset, size_t length)
{
bool result = false;
@ -1451,6 +1465,19 @@ class Drm_call
}
}
void unmap_buffer_ppgtt(__u32 handle)
{
Gpu::Buffer_id const id = { .value = handle };
try {
_buffer_space.apply<Buffer>(id, [&](Buffer &b) {
if (b.busy)
return;
_unmap_buffer_ppgtt(b);
});
} catch (Genode::Id_space<Buffer>::Unknown_id) { }
}
int ioctl(unsigned long request, void *arg)
{
bool const device = device_ioctl(request);
@ -1473,12 +1500,6 @@ class Drm_call
if (!h.busy) return;
if (h.seqno.value > _gpu_info.last_completed.value) return;
h.busy = false;
/*
* Because bo object map/unmap is not supported correctly right now
* (reference counting), we unmap and map the buffers on for each frame
*/
_unmap_buffer_ppgtt(h);
});
}
@ -1518,6 +1539,20 @@ extern "C" int drm_munmap(void *addr, size_t length)
}
extern "C" void drm_unmap_ppgtt(__u32 handle)
{
_call->unmap_buffer_ppgtt(handle);
}
extern "C" int drm_lseek(int fd, off_t offset, int whence)
{
if (_call.constructed() == false) { errno = EIO; return -1; }
return _call->lseek(fd, offset, whence);
}
extern "C" int genode_ioctl(int /* fd */, unsigned long request, void *arg)
{
if (verbose_ioctl) { dump_ioctl(request); }

View File

@ -0,0 +1,21 @@
--- a/src/lib/mesa/src/gallium/drivers/iris/iris_bufmgr.c
+++ b/src/lib/mesa/src/gallium/drivers/iris/iris_bufmgr.c
@@ -101,6 +101,8 @@
#define FILE_DEBUG_FLAG DEBUG_BUFMGR
+void drm_unmap_ppgtt(__u32 handle);
+
static inline int
atomic_add_unless(int *v, int add, int unless)
{
@@ -439,6 +441,9 @@
*/
if (memzone != iris_memzone_for_address(bo->gtt_offset) ||
bo->gtt_offset % alignment != 0) {
+
+
+ drm_unmap_ppgtt(bo->gem_handle);
vma_free(bufmgr, bo->gtt_offset, bo->size);
bo->gtt_offset = 0ull;
}

View File

@ -0,0 +1,13 @@
diff --git a/src/lib/mesa/src/gallium/drivers/iris/iris_bufmgr.c b/src/lib/mesa/src/gallium/drivers/iris/iris_bufmgr.c
index 2549729..c0045eb 100644
--- a/src/lib/mesa/src/gallium/drivers/iris/iris_bufmgr.c
+++ b/src/lib/mesa/src/gallium/drivers/iris/iris_bufmgr.c
@@ -1417,7 +1417,7 @@ iris_bo_import_dmabuf(struct iris_bufmgr *bufmgr, int prime_fd,
* later, we can lseek on the prime fd to get the size. Older
* kernels will just fail, in which case we fall back to the
* provided (estimated or guess size). */
- ret = lseek(prime_fd, 0, SEEK_END);
+ ret = drm_lseek(prime_fd, 0, SEEK_END);
if (ret != -1)
bo->size = ret;