From 12ca2bbcf62166f6ddda19419dc1cb8e9e094946 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B3zef=20Kucia?= Date: Mon, 15 Jan 2018 13:49:07 +0100 Subject: [PATCH] libs/vkd3d: Add thread-safe API for accessing Vulkan command queues. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Józef Kucia Signed-off-by: Henri Verbeet Signed-off-by: Alexandre Julliard --- demos/demo_xcb.h | 11 +++++-- include/vkd3d.h | 4 ++- libs/vkd3d/command.c | 14 ++++++++ libs/vkd3d/vkd3d.map | 2 ++ tests/vkd3d_api.c | 76 +++++++++++++++++++++++++++++++++++++++++--- 5 files changed, 99 insertions(+), 8 deletions(-) diff --git a/demos/demo_xcb.h b/demos/demo_xcb.h index 3cc2c54d..a683dcae 100644 --- a/demos/demo_xcb.h +++ b/demos/demo_xcb.h @@ -61,7 +61,7 @@ struct demo_swapchain VkInstance vk_instance; VkDevice vk_device; - VkQueue vk_queue; + ID3D12CommandQueue *command_queue; uint32_t current_buffer; unsigned int buffer_count; @@ -451,7 +451,6 @@ static inline struct demo_swapchain *demo_swapchain_create(ID3D12CommandQueue *c swapchain->vk_fence = vk_fence; swapchain->vk_instance = vk_instance; swapchain->vk_device = vk_device; - swapchain->vk_queue = vkd3d_get_vk_queue(command_queue); vkAcquireNextImageKHR(vk_device, vk_swapchain, UINT64_MAX, VK_NULL_HANDLE, vk_fence, &swapchain->current_buffer); @@ -488,6 +487,8 @@ static inline struct demo_swapchain *demo_swapchain_create(ID3D12CommandQueue *c free(vk_images); ID3D12Device_Release(d3d12_device); + ID3D12CommandQueue_AddRef(swapchain->command_queue = command_queue); + return swapchain; fail: @@ -518,6 +519,7 @@ static inline ID3D12Resource *demo_swapchain_get_back_buffer(struct demo_swapcha static inline void demo_swapchain_present(struct demo_swapchain *swapchain) { VkPresentInfoKHR present_desc; + VkQueue vk_queue; present_desc.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; present_desc.pNext = NULL; @@ -528,7 +530,9 @@ static inline void demo_swapchain_present(struct demo_swapchain *swapchain) present_desc.pImageIndices = &swapchain->current_buffer; present_desc.pResults = NULL; - vkQueuePresentKHR(swapchain->vk_queue, &present_desc); + vk_queue = vkd3d_acquire_vk_queue(swapchain->command_queue); + vkQueuePresentKHR(vk_queue, &present_desc); + vkd3d_release_vk_queue(swapchain->command_queue); vkAcquireNextImageKHR(swapchain->vk_device, swapchain->vk_swapchain, UINT64_MAX, VK_NULL_HANDLE, swapchain->vk_fence, &swapchain->current_buffer); @@ -540,6 +544,7 @@ static inline void demo_swapchain_destroy(struct demo_swapchain *swapchain) { unsigned int i; + ID3D12CommandQueue_Release(swapchain->command_queue); for (i = 0; i < swapchain->buffer_count; ++i) { ID3D12Resource_Release(swapchain->buffers[i]); diff --git a/include/vkd3d.h b/include/vkd3d.h index 8a04dbd9..322675b9 100644 --- a/include/vkd3d.h +++ b/include/vkd3d.h @@ -73,8 +73,10 @@ VkDevice vkd3d_get_vk_device(ID3D12Device *device); VkInstance vkd3d_get_vk_instance(ID3D12Device *device); VkPhysicalDevice vkd3d_get_vk_physical_device(ID3D12Device *device); -VkQueue vkd3d_get_vk_queue(ID3D12CommandQueue *queue); uint32_t vkd3d_get_vk_queue_family_index(ID3D12CommandQueue *queue); +VkQueue vkd3d_acquire_vk_queue(ID3D12CommandQueue *queue); +VkQueue vkd3d_get_vk_queue(ID3D12CommandQueue *queue); +void vkd3d_release_vk_queue(ID3D12CommandQueue *queue); HRESULT vkd3d_serialize_root_signature(const D3D12_ROOT_SIGNATURE_DESC *root_signature_desc, D3D_ROOT_SIGNATURE_VERSION version, ID3DBlob **blob, ID3DBlob **error_blob); diff --git a/libs/vkd3d/command.c b/libs/vkd3d/command.c index 85dcf6fc..7aa13867 100644 --- a/libs/vkd3d/command.c +++ b/libs/vkd3d/command.c @@ -4394,6 +4394,20 @@ uint32_t vkd3d_get_vk_queue_family_index(ID3D12CommandQueue *queue) return d3d12_queue->vkd3d_queue->vk_family_index; } +VkQueue vkd3d_acquire_vk_queue(ID3D12CommandQueue *queue) +{ + struct d3d12_command_queue *d3d12_queue = impl_from_ID3D12CommandQueue(queue); + + return vkd3d_queue_acquire(d3d12_queue->vkd3d_queue); +} + +void vkd3d_release_vk_queue(ID3D12CommandQueue *queue) +{ + struct d3d12_command_queue *d3d12_queue = impl_from_ID3D12CommandQueue(queue); + + return vkd3d_queue_release(d3d12_queue->vkd3d_queue); +} + /* ID3D12CommandSignature */ static inline struct d3d12_command_signature *impl_from_ID3D12CommandSignature(ID3D12CommandSignature *iface) { diff --git a/libs/vkd3d/vkd3d.map b/libs/vkd3d/vkd3d.map index db638f6d..57b8606e 100644 --- a/libs/vkd3d/vkd3d.map +++ b/libs/vkd3d/vkd3d.map @@ -1,5 +1,6 @@ { global: + vkd3d_acquire_vk_queue; vkd3d_create_device; vkd3d_create_image_resource; vkd3d_create_instance; @@ -12,6 +13,7 @@ global: vkd3d_get_vk_queue_family_index; vkd3d_instance_decref; vkd3d_instance_incref; + vkd3d_release_vk_queue; vkd3d_serialize_root_signature; local: *; diff --git a/tests/vkd3d_api.c b/tests/vkd3d_api.c index 79d51ccd..146467a4 100644 --- a/tests/vkd3d_api.c +++ b/tests/vkd3d_api.c @@ -40,6 +40,33 @@ static const struct vkd3d_device_create_info device_default_create_info = .instance_create_info = &instance_default_create_info, }; +static ID3D12Device *create_device(void) +{ + ID3D12Device *device; + HRESULT hr; + + hr = vkd3d_create_device(&device_default_create_info, + &IID_ID3D12Device, (void **)&device); + return SUCCEEDED(hr) ? device : NULL; +} + +static ID3D12CommandQueue *create_command_queue(ID3D12Device *device, + D3D12_COMMAND_LIST_TYPE type) +{ + D3D12_COMMAND_QUEUE_DESC desc; + ID3D12CommandQueue *queue; + HRESULT hr; + + desc.Type = type; + desc.Priority = D3D12_COMMAND_QUEUE_PRIORITY_NORMAL; + desc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; + desc.NodeMask = 0; + hr = ID3D12Device_CreateCommandQueue(device, &desc, + &IID_ID3D12CommandQueue, (void **)&queue); + ok(hr == S_OK, "Failed to create command queue, hr %#x.\n", hr); + return queue; +} + static void test_create_instance(void) { struct vkd3d_instance_create_info create_info; @@ -110,15 +137,55 @@ static void test_create_device(void) ok(!refcount, "Instance has %u references left.\n", refcount); } +static void test_vkd3d_queue(void) +{ + ID3D12CommandQueue *direct_queue, *compute_queue, *copy_queue; + uint32_t vk_queue_family; + ID3D12Device *device; + VkQueue vk_queue; + ULONG refcount; + + device = create_device(); + ok(device, "Failed to create device.\n"); + + direct_queue = create_command_queue(device, D3D12_COMMAND_LIST_TYPE_DIRECT); + ok(direct_queue, "Failed to create direct command queue.\n"); + compute_queue = create_command_queue(device, D3D12_COMMAND_LIST_TYPE_COMPUTE); + ok(compute_queue, "Failed to create direct command queue.\n"); + copy_queue = create_command_queue(device, D3D12_COMMAND_LIST_TYPE_COPY); + ok(copy_queue, "Failed to create direct command queue.\n"); + + vk_queue_family = vkd3d_get_vk_queue_family_index(direct_queue); + trace("Direct queue family index %u.\n", vk_queue_family); + vk_queue_family = vkd3d_get_vk_queue_family_index(compute_queue); + trace("Compute queue family index %u.\n", vk_queue_family); + vk_queue_family = vkd3d_get_vk_queue_family_index(copy_queue); + trace("Copy queue family index %u.\n", vk_queue_family); + + vk_queue = vkd3d_acquire_vk_queue(direct_queue); + ok(vk_queue != VK_NULL_HANDLE, "Failed to acquire Vulkan queue.\n"); + vkd3d_release_vk_queue(direct_queue); + vk_queue = vkd3d_acquire_vk_queue(compute_queue); + ok(vk_queue != VK_NULL_HANDLE, "Failed to acquire Vulkan queue.\n"); + vkd3d_release_vk_queue(compute_queue); + vk_queue = vkd3d_acquire_vk_queue(copy_queue); + ok(vk_queue != VK_NULL_HANDLE, "Failed to acquire Vulkan queue.\n"); + vkd3d_release_vk_queue(copy_queue); + + ID3D12CommandQueue_Release(direct_queue); + ID3D12CommandQueue_Release(compute_queue); + ID3D12CommandQueue_Release(copy_queue); + refcount = ID3D12Device_Release(device); + ok(!refcount, "Device has %u references left.\n", refcount); +} + static bool have_d3d12_device(void) { ID3D12Device *device; - HRESULT hr; - if (SUCCEEDED(hr = vkd3d_create_device(&device_default_create_info, - &IID_ID3D12Device, (void **)&device))) + if ((device = create_device())) ID3D12Device_Release(device); - return hr == S_OK; + return device; } START_TEST(vkd3d_api) @@ -131,4 +198,5 @@ START_TEST(vkd3d_api) run_test(test_create_instance); run_test(test_create_device); + run_test(test_vkd3d_queue); }