diff options
author | Chia-I Wu <[email protected]> | 2019-05-10 11:56:46 -0700 |
---|---|---|
committer | Chia-I Wu <[email protected]> | 2019-06-11 10:03:54 -0700 |
commit | 9e4452cfd9cdad9cded9f75cca63036236b8b178 (patch) | |
tree | 2932be360fd1b947851bac943e6a5ed42bfd0884 /src/gallium/winsys | |
parent | ddc90be907a1386b071fa9cfffb4535a6fa0b19e (diff) |
virgl: make resource_wait/resource_is_busy cheaper
The round trip to the kernel is expensive. Add a local cache to
avoid it when possible.
There is a race condition when two contexts access the same resource
at the same time (e.g., ctx1 submits a cmdbuf that accesses a
resource while ctx2 maps the resource). But that is probably an app
bug in the first place.
Signed-off-by: Chia-I Wu <[email protected]>
Reviewed-by: Alexandros Frantzis <[email protected]>
Diffstat (limited to 'src/gallium/winsys')
-rw-r--r-- | src/gallium/winsys/virgl/drm/virgl_drm_winsys.c | 24 | ||||
-rw-r--r-- | src/gallium/winsys/virgl/drm/virgl_drm_winsys.h | 3 |
2 files changed, 27 insertions, 0 deletions
diff --git a/src/gallium/winsys/virgl/drm/virgl_drm_winsys.c b/src/gallium/winsys/virgl/drm/virgl_drm_winsys.c index 37ded2f1f22..4110901e283 100644 --- a/src/gallium/winsys/virgl/drm/virgl_drm_winsys.c +++ b/src/gallium/winsys/virgl/drm/virgl_drm_winsys.c @@ -87,6 +87,9 @@ static boolean virgl_drm_resource_is_busy(struct virgl_winsys *vws, struct drm_virtgpu_3d_wait waitcmd; int ret; + if (!p_atomic_read(&res->maybe_busy) && !p_atomic_read(&res->external)) + return false; + memset(&waitcmd, 0, sizeof(waitcmd)); waitcmd.handle = res->bo_handle; waitcmd.flags = VIRTGPU_WAIT_NOWAIT; @@ -94,6 +97,9 @@ static boolean virgl_drm_resource_is_busy(struct virgl_winsys *vws, ret = drmIoctl(vdws->fd, DRM_IOCTL_VIRTGPU_WAIT, &waitcmd); if (ret && errno == EBUSY) return TRUE; + + p_atomic_set(&res->maybe_busy, false); + return FALSE; } @@ -229,6 +235,12 @@ virgl_drm_winsys_resource_create(struct virgl_winsys *qws, pipe_reference_init(&res->reference, 1); p_atomic_set(&res->external, false); p_atomic_set(&res->num_cs_references, 0); + + /* A newly created resource is consdiered busy by the kernel until the + * command is retired. + */ + p_atomic_set(&res->maybe_busy, true); + return res; } @@ -263,6 +275,8 @@ virgl_bo_transfer_put(struct virgl_winsys *vws, struct virgl_drm_winsys *vdws = virgl_drm_winsys(vws); struct drm_virtgpu_3d_transfer_to_host tohostcmd; + p_atomic_set(&res->maybe_busy, true); + memset(&tohostcmd, 0, sizeof(tohostcmd)); tohostcmd.bo_handle = res->bo_handle; tohostcmd.box.x = box->x; @@ -288,6 +302,8 @@ virgl_bo_transfer_get(struct virgl_winsys *vws, struct virgl_drm_winsys *vdws = virgl_drm_winsys(vws); struct drm_virtgpu_3d_transfer_from_host fromhostcmd; + p_atomic_set(&res->maybe_busy, true); + memset(&fromhostcmd, 0, sizeof(fromhostcmd)); fromhostcmd.bo_handle = res->bo_handle; fromhostcmd.level = level; @@ -552,12 +568,17 @@ static void virgl_drm_resource_wait(struct virgl_winsys *qws, struct drm_virtgpu_3d_wait waitcmd; int ret; + if (!p_atomic_read(&res->maybe_busy) && !p_atomic_read(&res->external)) + return; + memset(&waitcmd, 0, sizeof(waitcmd)); waitcmd.handle = res->bo_handle; again: ret = drmIoctl(qdws->fd, DRM_IOCTL_VIRTGPU_WAIT, &waitcmd); if (ret == -EAGAIN) goto again; + + p_atomic_set(&res->maybe_busy, false); } static bool virgl_drm_alloc_res_list(struct virgl_drm_cmd_buf *cbuf, @@ -658,6 +679,9 @@ static void virgl_drm_clear_res_list(struct virgl_drm_cmd_buf *cbuf) int i; for (i = 0; i < cbuf->cres; i++) { + /* mark all BOs busy after submission */ + p_atomic_set(&cbuf->res_bo[i]->maybe_busy, true); + p_atomic_dec(&cbuf->res_bo[i]->num_cs_references); virgl_drm_resource_reference(qdws, &cbuf->res_bo[i], NULL); } diff --git a/src/gallium/winsys/virgl/drm/virgl_drm_winsys.h b/src/gallium/winsys/virgl/drm/virgl_drm_winsys.h index 8bc874cb351..2f27c811b67 100644 --- a/src/gallium/winsys/virgl/drm/virgl_drm_winsys.h +++ b/src/gallium/winsys/virgl/drm/virgl_drm_winsys.h @@ -50,6 +50,9 @@ struct virgl_hw_res { /* true when the resource is imported or exported */ int external; + + /* false when the resource is known to be idle */ + int maybe_busy; }; struct virgl_drm_winsys |