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 <robdclark@chromium.org> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/18258>
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user