mirror of
https://gitlab.winehq.org/wine/vkd3d.git
synced 2024-11-21 16:46:41 -08:00
libs/vkd3d: Wait for GPU fences in worker thread.
This could be implemented without a worker thread, if event objects would be tightly coupled with ID3D12Fences.
This commit is contained in:
parent
2f76260857
commit
2a7b614278
@ -24,6 +24,51 @@
|
|||||||
#include "vkd3d_private.h"
|
#include "vkd3d_private.h"
|
||||||
|
|
||||||
/* Fence worker thread */
|
/* Fence worker thread */
|
||||||
|
static void vkd3d_wait_for_gpu_fences(struct vkd3d_fence_worker *worker)
|
||||||
|
{
|
||||||
|
struct d3d12_device *device = worker->device;
|
||||||
|
const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
|
||||||
|
unsigned int i, j;
|
||||||
|
HRESULT hr;
|
||||||
|
int vr;
|
||||||
|
|
||||||
|
if (!worker->fence_count)
|
||||||
|
return;
|
||||||
|
|
||||||
|
vr = VK_CALL(vkWaitForFences(device->vk_device,
|
||||||
|
worker->fence_count, worker->vk_fences, VK_FALSE, 0));
|
||||||
|
if (vr == VK_TIMEOUT)
|
||||||
|
return;
|
||||||
|
if (vr != VK_SUCCESS)
|
||||||
|
{
|
||||||
|
ERR("Failed to wait for Vulkan fences, vr %d.\n", vr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0, j = 0; i < worker->fence_count; ++i)
|
||||||
|
{
|
||||||
|
if (!(vr = VK_CALL(vkGetFenceStatus(device->vk_device, worker->vk_fences[i]))))
|
||||||
|
{
|
||||||
|
struct vkd3d_waiting_fence *current = &worker->fences[i];
|
||||||
|
if (FAILED(hr = ID3D12Fence_Signal(current->fence, current->value)))
|
||||||
|
ERR("Failed to signal D3D12 fence, hr %d.\n", hr);
|
||||||
|
VK_CALL(vkDestroyFence(device->vk_device, worker->vk_fences[i], NULL));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vr != VK_NOT_READY)
|
||||||
|
ERR("Failed to get Vulkan fence status, vr %d.\n", vr);
|
||||||
|
|
||||||
|
if (i != j)
|
||||||
|
{
|
||||||
|
worker->vk_fences[j] = worker->vk_fences[i];
|
||||||
|
worker->fences[j] = worker->fences[i];
|
||||||
|
}
|
||||||
|
++j;
|
||||||
|
}
|
||||||
|
worker->fence_count = j;
|
||||||
|
}
|
||||||
|
|
||||||
static void *vkd3d_fence_worker_main(void *arg)
|
static void *vkd3d_fence_worker_main(void *arg)
|
||||||
{
|
{
|
||||||
struct vkd3d_fence_worker *worker = arg;
|
struct vkd3d_fence_worker *worker = arg;
|
||||||
@ -37,18 +82,23 @@ static void *vkd3d_fence_worker_main(void *arg)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (worker->should_exit)
|
if (worker->should_exit && !worker->fence_count)
|
||||||
{
|
{
|
||||||
pthread_mutex_unlock(&worker->mutex);
|
pthread_mutex_unlock(&worker->mutex);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!worker->fence_count)
|
||||||
|
{
|
||||||
if ((rc = pthread_cond_wait(&worker->cond, &worker->mutex)))
|
if ((rc = pthread_cond_wait(&worker->cond, &worker->mutex)))
|
||||||
{
|
{
|
||||||
ERR("Failed to wait on condition variable, error %d.\n", rc);
|
ERR("Failed to wait on condition variable, error %d.\n", rc);
|
||||||
pthread_mutex_unlock(&worker->mutex);
|
pthread_mutex_unlock(&worker->mutex);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vkd3d_wait_for_gpu_fences(worker);
|
||||||
|
|
||||||
pthread_mutex_unlock(&worker->mutex);
|
pthread_mutex_unlock(&worker->mutex);
|
||||||
}
|
}
|
||||||
@ -56,13 +106,22 @@ static void *vkd3d_fence_worker_main(void *arg)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT vkd3d_start_fence_worker(struct vkd3d_fence_worker *worker)
|
HRESULT vkd3d_start_fence_worker(struct vkd3d_fence_worker *worker,
|
||||||
|
struct d3d12_device *device)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
TRACE("worker %p.\n", worker);
|
TRACE("worker %p.\n", worker);
|
||||||
|
|
||||||
worker->should_exit = false;
|
worker->should_exit = false;
|
||||||
|
worker->device = device;
|
||||||
|
|
||||||
|
worker->fence_count = 0;
|
||||||
|
|
||||||
|
worker->vk_fences = NULL;
|
||||||
|
worker->vk_fences_size = 0;
|
||||||
|
worker->fences = NULL;
|
||||||
|
worker->fences_size = 0;
|
||||||
|
|
||||||
if ((rc = pthread_mutex_init(&worker->mutex, NULL)))
|
if ((rc = pthread_mutex_init(&worker->mutex, NULL)))
|
||||||
{
|
{
|
||||||
@ -114,6 +173,9 @@ HRESULT vkd3d_stop_fence_worker(struct vkd3d_fence_worker *worker)
|
|||||||
pthread_mutex_destroy(&worker->mutex);
|
pthread_mutex_destroy(&worker->mutex);
|
||||||
pthread_cond_destroy(&worker->cond);
|
pthread_cond_destroy(&worker->cond);
|
||||||
|
|
||||||
|
vkd3d_free(worker->vk_fences);
|
||||||
|
vkd3d_free(worker->fences);
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1091,7 +1091,7 @@ static HRESULT d3d12_device_init(struct d3d12_device *device,
|
|||||||
|
|
||||||
device->signal_event = create_info->signal_event_pfn;
|
device->signal_event = create_info->signal_event_pfn;
|
||||||
|
|
||||||
if (FAILED(hr = vkd3d_start_fence_worker(&device->fence_worker)))
|
if (FAILED(hr = vkd3d_start_fence_worker(&device->fence_worker, device)))
|
||||||
{
|
{
|
||||||
const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
|
const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
|
||||||
VK_CALL(vkDestroyDevice(device->vk_device, NULL));
|
VK_CALL(vkDestroyDevice(device->vk_device, NULL));
|
||||||
|
@ -45,21 +45,28 @@ struct vkd3d_instance
|
|||||||
struct vkd3d_vk_instance_procs vk_procs;
|
struct vkd3d_vk_instance_procs vk_procs;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct vkd3d_waiting_event
|
|
||||||
{
|
|
||||||
UINT64 value;
|
|
||||||
HANDLE event;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct vkd3d_fence_worker
|
struct vkd3d_fence_worker
|
||||||
{
|
{
|
||||||
pthread_t thread;
|
pthread_t thread;
|
||||||
pthread_mutex_t mutex;
|
pthread_mutex_t mutex;
|
||||||
pthread_cond_t cond;
|
pthread_cond_t cond;
|
||||||
bool should_exit;
|
bool should_exit;
|
||||||
|
|
||||||
|
size_t fence_count;
|
||||||
|
VkFence *vk_fences;
|
||||||
|
size_t vk_fences_size;
|
||||||
|
struct vkd3d_waiting_fence
|
||||||
|
{
|
||||||
|
ID3D12Fence *fence;
|
||||||
|
UINT64 value;
|
||||||
|
} *fences;
|
||||||
|
size_t fences_size;
|
||||||
|
|
||||||
|
struct d3d12_device *device;
|
||||||
};
|
};
|
||||||
|
|
||||||
HRESULT vkd3d_start_fence_worker(struct vkd3d_fence_worker *worker) DECLSPEC_HIDDEN;
|
HRESULT vkd3d_start_fence_worker(struct vkd3d_fence_worker *worker,
|
||||||
|
struct d3d12_device *device) DECLSPEC_HIDDEN;
|
||||||
HRESULT vkd3d_stop_fence_worker(struct vkd3d_fence_worker *worker) DECLSPEC_HIDDEN;
|
HRESULT vkd3d_stop_fence_worker(struct vkd3d_fence_worker *worker) DECLSPEC_HIDDEN;
|
||||||
|
|
||||||
/* ID3D12Fence */
|
/* ID3D12Fence */
|
||||||
@ -71,7 +78,11 @@ struct d3d12_fence
|
|||||||
UINT64 value;
|
UINT64 value;
|
||||||
pthread_mutex_t mutex;
|
pthread_mutex_t mutex;
|
||||||
|
|
||||||
struct vkd3d_waiting_event *events;
|
struct vkd3d_waiting_event
|
||||||
|
{
|
||||||
|
UINT64 value;
|
||||||
|
HANDLE event;
|
||||||
|
} *events;
|
||||||
size_t events_size;
|
size_t events_size;
|
||||||
size_t event_count;
|
size_t event_count;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user