From a9e79dd88af230e3cb9fdf8fd81e070920d7c6a2 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Thu, 25 Aug 2022 13:14:24 -0700 Subject: [PATCH] freedreno/drm: Let backend hint about upload vs map For the virtgpu backend, immediately mmap'ing a buffer can be expensive (ie. require a sync with host), so for small transfers we'd prefer to go the upload path. Signed-off-by: Rob Clark Part-of: --- src/freedreno/drm/freedreno_bo.c | 9 +++++++++ src/freedreno/drm/freedreno_drmif.h | 1 + src/freedreno/drm/freedreno_priv.h | 5 +++++ src/freedreno/drm/virtio/virtio_bo.c | 24 ++++++++++++++++++++++++ src/freedreno/drm/virtio/virtio_priv.h | 1 + 5 files changed, 40 insertions(+) diff --git a/src/freedreno/drm/freedreno_bo.c b/src/freedreno/drm/freedreno_bo.c index 9b67ef3..4e98b7b 100644 --- a/src/freedreno/drm/freedreno_bo.c +++ b/src/freedreno/drm/freedreno_bo.c @@ -497,6 +497,15 @@ fd_bo_upload(struct fd_bo *bo, void *src, unsigned len) memcpy(bo_map(bo), src, len); } +bool +fd_bo_prefer_upload(struct fd_bo *bo, unsigned len) +{ + if (bo->funcs->prefer_upload) + return bo->funcs->prefer_upload(bo, len); + + return false; +} + /* a bit odd to take the pipe as an arg, but it's a, umm, quirk of kgsl.. */ int fd_bo_cpu_prep(struct fd_bo *bo, struct fd_pipe *pipe, uint32_t op) diff --git a/src/freedreno/drm/freedreno_drmif.h b/src/freedreno/drm/freedreno_drmif.h index 2583e67..39590c1 100644 --- a/src/freedreno/drm/freedreno_drmif.h +++ b/src/freedreno/drm/freedreno_drmif.h @@ -220,6 +220,7 @@ int fd_bo_dmabuf(struct fd_bo *bo); uint32_t fd_bo_size(struct fd_bo *bo); void *fd_bo_map(struct fd_bo *bo); void fd_bo_upload(struct fd_bo *bo, void *src, unsigned len); +bool fd_bo_prefer_upload(struct fd_bo *bo, unsigned len); int fd_bo_cpu_prep(struct fd_bo *bo, struct fd_pipe *pipe, uint32_t op); void fd_bo_cpu_fini(struct fd_bo *bo); bool fd_bo_is_cached(struct fd_bo *bo); diff --git a/src/freedreno/drm/freedreno_priv.h b/src/freedreno/drm/freedreno_priv.h index 44d81a3..d12c98e 100644 --- a/src/freedreno/drm/freedreno_priv.h +++ b/src/freedreno/drm/freedreno_priv.h @@ -313,6 +313,11 @@ struct fd_bo_funcs { * implemented, it must be possible to mmap all buffers */ void (*upload)(struct fd_bo *bo, void *src, unsigned len); + + /** + * Optional, if upload is supported, should upload be preferred? + */ + bool (*prefer_upload)(struct fd_bo *bo, unsigned len); }; struct fd_bo_fence { diff --git a/src/freedreno/drm/virtio/virtio_bo.c b/src/freedreno/drm/virtio/virtio_bo.c index c532b95..253f905 100644 --- a/src/freedreno/drm/virtio/virtio_bo.c +++ b/src/freedreno/drm/virtio/virtio_bo.c @@ -214,6 +214,27 @@ virtio_bo_upload(struct fd_bo *bo, void *src, unsigned len) } } +/** + * For recently allocated buffers, an immediate mmap would stall waiting + * for the host to handle the allocation and map to the guest, which + * could take a few ms. So for small transfers to recently allocated + * buffers, we'd prefer to use the upload path instead. + */ +static bool +virtio_bo_prefer_upload(struct fd_bo *bo, unsigned len) +{ + struct virtio_bo *virtio_bo = to_virtio_bo(bo); + + if (len > 0x4000) + return false; + + int64_t age_ns = os_time_get_nano() - virtio_bo->alloc_time_ns; + if (age_ns > 5000000) + return false; + + return true; +} + static void set_iova(struct fd_bo *bo, uint64_t iova) { @@ -255,6 +276,7 @@ static const struct fd_bo_funcs funcs = { .iova = virtio_bo_iova, .set_name = virtio_bo_set_name, .upload = virtio_bo_upload, + .prefer_upload = virtio_bo_prefer_upload, .destroy = virtio_bo_destroy, }; @@ -268,6 +290,8 @@ bo_from_handle(struct fd_device *dev, uint32_t size, uint32_t handle) if (!virtio_bo) return NULL; + virtio_bo->alloc_time_ns = os_time_get_nano(); + bo = &virtio_bo->base; /* Note we need to set these because allocation_wait_execute() could diff --git a/src/freedreno/drm/virtio/virtio_priv.h b/src/freedreno/drm/virtio/virtio_priv.h index 7191f46..83fb8c9 100644 --- a/src/freedreno/drm/virtio/virtio_priv.h +++ b/src/freedreno/drm/virtio/virtio_priv.h @@ -169,6 +169,7 @@ struct fd_submit *virtio_submit_new(struct fd_pipe *pipe); struct virtio_bo { struct fd_bo base; + uint64_t alloc_time_ns; uint64_t offset; uint32_t res_id; uint32_t blob_id; -- 2.7.4