freedreno/drm: Let backend hint about upload vs map
authorRob Clark <robdclark@chromium.org>
Thu, 25 Aug 2022 20:14:24 +0000 (13:14 -0700)
committerMarge Bot <emma+marge@anholt.net>
Fri, 26 Aug 2022 20:48:36 +0000 (20:48 +0000)
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 <robdclark@chromium.org>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/18258>

src/freedreno/drm/freedreno_bo.c
src/freedreno/drm/freedreno_drmif.h
src/freedreno/drm/freedreno_priv.h
src/freedreno/drm/virtio/virtio_bo.c
src/freedreno/drm/virtio/virtio_priv.h

index 9b67ef3..4e98b7b 100644 (file)
@@ -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)
index 2583e67..39590c1 100644 (file)
@@ -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);
index 44d81a3..d12c98e 100644 (file)
@@ -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 {
index c532b95..253f905 100644 (file)
@@ -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
index 7191f46..83fb8c9 100644 (file)
@@ -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;