From 62e8faf56c5e8ffb82519b28e84f1f51d825a7d7 Mon Sep 17 00:00:00 2001 From: Faith Ekstrand Date: Mon, 30 Jan 2023 20:12:01 -0600 Subject: [PATCH] nvk: Use poll for BO waits The nouveau ioctl doesn't support timeouts but poll() does. Part-of: --- src/nouveau/vulkan/nvk_bo_sync.c | 50 ++++++++++++++++++++++++++++++++++++---- src/nouveau/vulkan/nvk_bo_sync.h | 1 + 2 files changed, 47 insertions(+), 4 deletions(-) diff --git a/src/nouveau/vulkan/nvk_bo_sync.c b/src/nouveau/vulkan/nvk_bo_sync.c index d16da24..45cb7cb 100644 --- a/src/nouveau/vulkan/nvk_bo_sync.c +++ b/src/nouveau/vulkan/nvk_bo_sync.c @@ -32,6 +32,8 @@ #include "util/os_time.h" #include "util/timespec.h" +#include + static struct nvk_bo_sync * to_nvk_bo_sync(struct vk_sync *sync) { @@ -50,9 +52,17 @@ nvk_bo_sync_init(struct vk_device *vk_device, sync->state = initial_value ? NVK_BO_SYNC_STATE_SIGNALED : NVK_BO_SYNC_STATE_RESET; - sync->bo = nouveau_ws_bo_new(device->pdev->dev, 0x1000, 0, NOUVEAU_WS_BO_GART); + sync->bo = nouveau_ws_bo_new(device->pdev->dev, 0x1000, 0, + NOUVEAU_WS_BO_GART); if (!sync->bo) return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); + + int err = nouveau_ws_bo_dma_buf(sync->bo, &sync->dmabuf_fd); + if (err) { + nouveau_ws_bo_destroy(sync->bo); + return vk_errorf(device, VK_ERROR_UNKNOWN, "dma-buf export failed: %m"); + } + return VK_SUCCESS; } @@ -62,6 +72,7 @@ nvk_bo_sync_finish(struct vk_device *vk_device, { struct nvk_bo_sync *sync = to_nvk_bo_sync(vk_sync); + close(sync->dmabuf_fd); nouveau_ws_bo_destroy(sync->bo); } @@ -102,6 +113,35 @@ nvk_get_relative_timeout(uint64_t abs_timeout) } static VkResult +nvk_wait_dmabuf(struct nvk_device *device, int dmabuf_fd, + uint64_t abs_timeout_ns) +{ + uint64_t now = os_time_get_nano(); + uint64_t rel_timeout_ns = + now < abs_timeout_ns ? abs_timeout_ns - now : 0; + + struct timespec rel_timeout_ts = { + .tv_sec = rel_timeout_ns / 1000000000, + .tv_nsec = rel_timeout_ns % 1000000000, + }; + + struct pollfd fd = { + .fd = dmabuf_fd, + .events = POLLOUT + }; + + int ret = ppoll(&fd, 1, &rel_timeout_ts, NULL); + if (ret < 0) { + return vk_errorf(device, VK_ERROR_UNKNOWN, + "poll() failed: %m"); + } else if (ret == 0) { + return VK_TIMEOUT; + } else { + return VK_SUCCESS; + } +} + +static VkResult nvk_bo_sync_wait(struct vk_device *vk_device, uint32_t wait_count, const struct vk_sync_wait *waits, @@ -109,6 +149,7 @@ nvk_bo_sync_wait(struct vk_device *vk_device, uint64_t abs_timeout_ns) { struct nvk_device *device = container_of(vk_device, struct nvk_device, vk); + VkResult result; uint32_t pending = wait_count; while (pending) { @@ -140,9 +181,10 @@ nvk_bo_sync_wait(struct vk_device *vk_device, * on it until we hit a timeout. */ if (!(wait_flags & VK_SYNC_WAIT_PENDING)) { - if (!nouveau_ws_bo_wait(sync->bo, NOUVEAU_WS_BO_RDWR)) { - return vk_error(device, VK_TIMEOUT); - } + result = nvk_wait_dmabuf(device, sync->dmabuf_fd, abs_timeout_ns); + /* This also covers VK_TIMEOUT */ + if (result != VK_SUCCESS) + return result; sync->state = NVK_BO_SYNC_STATE_SIGNALED; signaled = true; diff --git a/src/nouveau/vulkan/nvk_bo_sync.h b/src/nouveau/vulkan/nvk_bo_sync.h index 60b3f7c..990e743 100644 --- a/src/nouveau/vulkan/nvk_bo_sync.h +++ b/src/nouveau/vulkan/nvk_bo_sync.h @@ -15,6 +15,7 @@ struct nvk_bo_sync { enum nvk_bo_sync_state state; struct nouveau_ws_bo *bo; + int dmabuf_fd; }; VKAPI_ATTR VkResult VKAPI_CALL -- 2.7.4