From: Józef Kucia jkucia@codeweavers.com
Signed-off-by: Józef Kucia jkucia@codeweavers.com ---
This should help us to not leak libvkd3d-shader symbols from libvkd3d in the next commit.
ld-version-script.m4 is imported from gnulib. It's used in a lot of projects.
--- Makefile.am | 9 +++++++ configure.ac | 2 ++ libs/vkd3d-shader/vkd3d_shader.map | 14 +++++++++++ libs/vkd3d-utils/vkd3d_utils.map | 13 +++++++++++ libs/vkd3d/vkd3d.map | 18 ++++++++++++++ m4/ld-version-script.m4 | 48 ++++++++++++++++++++++++++++++++++++++ 6 files changed, 104 insertions(+) create mode 100644 libs/vkd3d-shader/vkd3d_shader.map create mode 100644 libs/vkd3d-utils/vkd3d_utils.map create mode 100644 libs/vkd3d/vkd3d.map create mode 100644 m4/ld-version-script.m4
diff --git a/Makefile.am b/Makefile.am index 2876f6486df4..190a7ac8d134 100644 --- a/Makefile.am +++ b/Makefile.am @@ -68,6 +68,9 @@ libvkd3d_shader_la_SOURCES = \ libs/vkd3d-shader/vkd3d_shader_main.c \ libs/vkd3d-shader/vkd3d_shader_private.h libvkd3d_shader_la_LIBADD = libvkd3d-common.la @SPIRV_TOOLS_LIBS@ +if HAVE_LD_VERSION_SCRIPT +libvkd3d_shader_la_LDFLAGS = -Wl,--version-script=$(srcdir)/libs/vkd3d-shader/vkd3d_shader.map +endif
libvkd3d_la_SOURCES = \ include/d3d12.idl \ @@ -85,11 +88,17 @@ libvkd3d_la_SOURCES = \ libs/vkd3d/vkd3d_private.h \ libs/vkd3d/vulkan_procs.h libvkd3d_la_LIBADD = libvkd3d-common.la libvkd3d-shader.la @PTHREAD_LIBS@ @VULKAN_LIBS@ +if HAVE_LD_VERSION_SCRIPT +libvkd3d_la_LDFLAGS = -Wl,--version-script=$(srcdir)/libs/vkd3d/vkd3d.map +endif
libvkd3d_utils_la_SOURCES = \ libs/vkd3d-utils/vkd3d_utils_main.c \ libs/vkd3d-utils/vkd3d_utils_private.h libvkd3d_utils_la_LIBADD = libvkd3d-common.la libvkd3d.la +if HAVE_LD_VERSION_SCRIPT +libvkd3d_utils_la_LDFLAGS = -Wl,--version-script=$(srcdir)/libs/vkd3d-utils/vkd3d_utils.map +endif
EXTRA_DIST = LICENSE
diff --git a/configure.ac b/configure.ac index 5614f791fe64..b886058fef51 100644 --- a/configure.ac +++ b/configure.ac @@ -30,6 +30,8 @@ AM_SILENT_RULES([yes]) LT_PREREQ([2.4.2]) LT_INIT
+gl_LD_VERSION_SCRIPT + dnl Check compiler specific flags AC_SUBST([VKD3D_CFLAGS]) AS_IF([test "x${GCC}" = "xyes"], diff --git a/libs/vkd3d-shader/vkd3d_shader.map b/libs/vkd3d-shader/vkd3d_shader.map new file mode 100644 index 000000000000..31ee4a90c970 --- /dev/null +++ b/libs/vkd3d-shader/vkd3d_shader.map @@ -0,0 +1,14 @@ +{ +global: + vkd3d_shader_compile_dxbc; + vkd3d_shader_find_signature_element; + vkd3d_shader_free_root_signature; + vkd3d_shader_free_shader_code; + vkd3d_shader_free_shader_signature; + vkd3d_shader_parse_input_signature; + vkd3d_shader_parse_root_signature; + vkd3d_shader_scan_dxbc; + vkd3d_shader_serialize_root_signature; + +local: *; +}; diff --git a/libs/vkd3d-utils/vkd3d_utils.map b/libs/vkd3d-utils/vkd3d_utils.map new file mode 100644 index 000000000000..42df666bd6a7 --- /dev/null +++ b/libs/vkd3d-utils/vkd3d_utils.map @@ -0,0 +1,13 @@ +{ +global: + D3D12CreateDevice; + D3D12CreateRootSignatureDeserializer; + D3D12GetDebugInterface; + D3D12SerializeRootSignature; + vkd3d_create_event; + vkd3d_destroy_event; + vkd3d_signal_event; + vkd3d_wait_event; + +local: *; +}; diff --git a/libs/vkd3d/vkd3d.map b/libs/vkd3d/vkd3d.map new file mode 100644 index 000000000000..db638f6dd35c --- /dev/null +++ b/libs/vkd3d/vkd3d.map @@ -0,0 +1,18 @@ +{ +global: + vkd3d_create_device; + vkd3d_create_image_resource; + vkd3d_create_instance; + vkd3d_create_root_signature_deserializer; + vkd3d_get_vk_device; + vkd3d_get_vk_format; + vkd3d_get_vk_instance; + vkd3d_get_vk_physical_device; + vkd3d_get_vk_queue; + vkd3d_get_vk_queue_family_index; + vkd3d_instance_decref; + vkd3d_instance_incref; + vkd3d_serialize_root_signature; + +local: *; +}; diff --git a/m4/ld-version-script.m4 b/m4/ld-version-script.m4 new file mode 100644 index 000000000000..4364f9f7a81e --- /dev/null +++ b/m4/ld-version-script.m4 @@ -0,0 +1,48 @@ +# ld-version-script.m4 serial 4 +dnl Copyright (C) 2008-2018 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Simon Josefsson + +# FIXME: The test below returns a false positive for mingw +# cross-compiles, 'local:' statements does not reduce number of +# exported symbols in a DLL. Use --disable-ld-version-script to work +# around the problem. + +# gl_LD_VERSION_SCRIPT +# -------------------- +# Check if LD supports linker scripts, and define automake conditional +# HAVE_LD_VERSION_SCRIPT if so. +AC_DEFUN([gl_LD_VERSION_SCRIPT], +[ + AC_ARG_ENABLE([ld-version-script], + [AS_HELP_STRING([--enable-ld-version-script], + [enable linker version script (default is enabled when possible)])], + [have_ld_version_script=$enableval], + [AC_CACHE_CHECK([if LD -Wl,--version-script works], + [gl_cv_sys_ld_version_script], + [gl_cv_sys_ld_version_script=no + save_LDFLAGS=$LDFLAGS + LDFLAGS="$LDFLAGS -Wl,--version-script=conftest.map" + echo foo >conftest.map + AC_LINK_IFELSE([AC_LANG_PROGRAM([], [])], + [], + [cat > conftest.map <<EOF +VERS_1 { + global: sym; +}; + +VERS_2 { + global: sym; +} VERS_1; +EOF + AC_LINK_IFELSE([AC_LANG_PROGRAM([], [])], + [gl_cv_sys_ld_version_script=yes])]) + rm -f conftest.map + LDFLAGS=$save_LDFLAGS]) + have_ld_version_script=$gl_cv_sys_ld_version_script]) + AM_CONDITIONAL([HAVE_LD_VERSION_SCRIPT], + [test "$have_ld_version_script" = yes]) +])
From: Józef Kucia jkucia@codeweavers.com
libvkd3d-shader interface is expected to be extended significantly.
Signed-off-by: Józef Kucia jkucia@codeweavers.com ---
I think it's reasonable to exclude the library from the first release. It will give us more time to develop the library and stabilize the API. It should be quite easy to restore the library in the future release when we need it, e.g. wined3d could use it.
Let's limit the API which we have to get right in the first release ;-)
--- Makefile.am | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-)
diff --git a/Makefile.am b/Makefile.am index 190a7ac8d134..15a1783edc03 100644 --- a/Makefile.am +++ b/Makefile.am @@ -19,7 +19,6 @@ vkd3d_public_headers = \ include/vkd3d_d3d12.h \ include/vkd3d_dxgibase.h \ include/vkd3d_dxgiformat.h \ - include/vkd3d_shader.h \ include/vkd3d_utils.h \ include/vkd3d_windows.h
@@ -49,13 +48,13 @@ vkd3d_demos_headers = \
BUILT_SOURCES = $(widl_headers)
-noinst_LTLIBRARIES = libvkd3d-common.la +noinst_LTLIBRARIES = libvkd3d-common.la libvkd3d-shader.la libvkd3d_common_la_SOURCES = \ include/private/vkd3d_debug.h \ libs/vkd3d-common/debug.c \ libs/vkd3d-common/memory.c
-lib_LTLIBRARIES = libvkd3d-shader.la libvkd3d.la libvkd3d-utils.la +lib_LTLIBRARIES = libvkd3d.la libvkd3d-utils.la
libvkd3d_shader_la_SOURCES = \ include/private/list.h \ @@ -67,7 +66,7 @@ libvkd3d_shader_la_SOURCES = \ libs/vkd3d-shader/spirv.c \ libs/vkd3d-shader/vkd3d_shader_main.c \ libs/vkd3d-shader/vkd3d_shader_private.h -libvkd3d_shader_la_LIBADD = libvkd3d-common.la @SPIRV_TOOLS_LIBS@ +libvkd3d_shader_la_LIBADD = @SPIRV_TOOLS_LIBS@ if HAVE_LD_VERSION_SCRIPT libvkd3d_shader_la_LDFLAGS = -Wl,--version-script=$(srcdir)/libs/vkd3d-shader/vkd3d_shader.map endif @@ -110,7 +109,7 @@ EXTRA_DIST += libs/vkd3d/libvkd3d.pc.in libs/vkd3d-utils/libvkd3d-utils.pc.in
bin_PROGRAMS = vkd3d-compiler vkd3d_compiler_SOURCES = programs/vkd3d-compiler/main.c -vkd3d_compiler_LDADD = libvkd3d-shader.la +vkd3d_compiler_LDADD = libvkd3d-shader.la libvkd3d-common.la
LDADD = libvkd3d.la libvkd3d-utils.la check_PROGRAMS = $(vkd3d_tests) $(vkd3d_cross_tests)
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
From: Józef Kucia jkucia@codeweavers.com
At this stage, vkd3d-compiler is useful only as an internal tool for testing.
Signed-off-by: Józef Kucia jkucia@codeweavers.com --- Makefile.am | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/Makefile.am b/Makefile.am index 15a1783edc03..3ad9c2e78588 100644 --- a/Makefile.am +++ b/Makefile.am @@ -107,7 +107,7 @@ nodist_pkgconfig_DATA = libvkd3d.pc libvkd3d-utils.pc CLEANFILES = libvkd3d.pc libvkd3d-utils.pc EXTRA_DIST += libs/vkd3d/libvkd3d.pc.in libs/vkd3d-utils/libvkd3d-utils.pc.in
-bin_PROGRAMS = vkd3d-compiler +noinst_PROGRAMS = vkd3d-compiler vkd3d_compiler_SOURCES = programs/vkd3d-compiler/main.c vkd3d_compiler_LDADD = libvkd3d-shader.la libvkd3d-common.la
@@ -119,7 +119,7 @@ tests_d3d12_LDADD = $(LDADD) @PTHREAD_LIBS@
DEMOS_LDADD = $(LDADD) libvkd3d-shader.la @XCB_LIBS@ @VULKAN_LIBS@ DEMOS_CFLAGS = @XCB_CFLAGS@ -noinst_PROGRAMS = $(vkd3d_demos) +noinst_PROGRAMS += $(vkd3d_demos) EXTRA_DIST += $(vkd3d_demos_headers)
demos_gears_CFLAGS = $(DEMOS_CFLAGS)
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
From: Józef Kucia jkucia@codeweavers.com
Access to VkQueue must be externally synchronized.
Signed-off-by: Józef Kucia jkucia@codeweavers.com ---
Especially important on implementations which have a single queue.
--- libs/vkd3d/command.c | 155 +++++++++++++++++++++++++++++++-------------- libs/vkd3d/device.c | 73 +++++++++++++++++++-- libs/vkd3d/vkd3d_private.h | 27 +++++--- 3 files changed, 191 insertions(+), 64 deletions(-)
diff --git a/libs/vkd3d/command.c b/libs/vkd3d/command.c index f7d1699e3958..85dcf6fcabbf 100644 --- a/libs/vkd3d/command.c +++ b/libs/vkd3d/command.c @@ -19,6 +19,63 @@
#include "vkd3d_private.h"
+HRESULT vkd3d_queue_create(struct d3d12_device *device, + uint32_t family_index, uint32_t timestamp_bits, struct vkd3d_queue **queue) +{ + const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs; + struct vkd3d_queue *object; + int rc; + + if (!(object = vkd3d_malloc(sizeof(*object)))) + return E_OUTOFMEMORY; + + if ((rc = pthread_mutex_init(&object->mutex, NULL))) + { + ERR("Failed to initialize mutex, error %d.\n", rc); + vkd3d_free(object); + return E_FAIL; + } + + object->vk_family_index = family_index; + object->timestamp_bits = timestamp_bits; + + VK_CALL(vkGetDeviceQueue(device->vk_device, family_index, 0, &object->vk_queue)); + + TRACE("Created queue %p for queue family index %u.\n", object, family_index); + + *queue = object; + + return S_OK; +} + +void vkd3d_queue_destroy(struct vkd3d_queue *queue) +{ + pthread_mutex_destroy(&queue->mutex); + vkd3d_free(queue); +} + +static VkQueue vkd3d_queue_acquire(struct vkd3d_queue *queue) +{ + int rc; + + TRACE("queue %p.\n", queue); + + if ((rc = pthread_mutex_lock(&queue->mutex))) + { + ERR("Failed to lock mutex, error %d.\n", rc); + return VK_NULL_HANDLE; + } + + return queue->vk_queue; +} + +static void vkd3d_queue_release(struct vkd3d_queue *queue) +{ + TRACE("queue %p.\n", queue); + + pthread_mutex_unlock(&queue->mutex); +} + /* Fence worker thread */ static HRESULT vkd3d_queue_gpu_fence(struct vkd3d_fence_worker *worker, VkFence vk_fence, ID3D12Fence *fence, UINT64 value) @@ -955,13 +1012,34 @@ static struct d3d12_command_allocator *unsafe_impl_from_ID3D12CommandAllocator(I return impl_from_ID3D12CommandAllocator(iface); }
+static struct vkd3d_queue *d3d12_device_get_vkd3d_queue(struct d3d12_device *device, + D3D12_COMMAND_LIST_TYPE type) +{ + switch (type) + { + case D3D12_COMMAND_LIST_TYPE_DIRECT: + return device->direct_queue; + case D3D12_COMMAND_LIST_TYPE_COMPUTE: + return device->compute_queue; + case D3D12_COMMAND_LIST_TYPE_COPY: + return device->copy_queue; + default: + FIXME("Unhandled command list type %#x.\n", type); + return NULL; + } +} + static HRESULT d3d12_command_allocator_init(struct d3d12_command_allocator *allocator, struct d3d12_device *device, D3D12_COMMAND_LIST_TYPE type) { const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs; VkCommandPoolCreateInfo command_pool_info; + struct vkd3d_queue *queue; VkResult vr;
+ if (!(queue = d3d12_device_get_vkd3d_queue(device, type))) + queue = device->direct_queue; + allocator->ID3D12CommandAllocator_iface.lpVtbl = &d3d12_command_allocator_vtbl; allocator->refcount = 1;
@@ -970,22 +1048,7 @@ static HRESULT d3d12_command_allocator_init(struct d3d12_command_allocator *allo command_pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; command_pool_info.pNext = NULL; command_pool_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; - switch (type) - { - case D3D12_COMMAND_LIST_TYPE_DIRECT: - command_pool_info.queueFamilyIndex = device->direct_queue_family_index; - break; - case D3D12_COMMAND_LIST_TYPE_COMPUTE: - command_pool_info.queueFamilyIndex = device->compute_queue_family_index; - break; - case D3D12_COMMAND_LIST_TYPE_COPY: - command_pool_info.queueFamilyIndex = device->copy_queue_family_index; - break; - default: - FIXME("Unhandled command list type %#x.\n", type); - command_pool_info.queueFamilyIndex = device->direct_queue_family_index; - break; - } + command_pool_info.queueFamilyIndex = queue->vk_family_index;
if ((vr = VK_CALL(vkCreateCommandPool(device->vk_device, &command_pool_info, NULL, &allocator->vk_command_pool))) < 0) @@ -4077,6 +4140,7 @@ static void STDMETHODCALLTYPE d3d12_command_queue_ExecuteCommandLists(ID3D12Comm const struct vkd3d_vk_device_procs *vk_procs; struct VkSubmitInfo submit_desc; VkCommandBuffer *buffers; + VkQueue vk_queue; unsigned int i; VkResult vr;
@@ -4106,10 +4170,17 @@ static void STDMETHODCALLTYPE d3d12_command_queue_ExecuteCommandLists(ID3D12Comm submit_desc.signalSemaphoreCount = 0; submit_desc.pSignalSemaphores = NULL;
- if ((vr = VK_CALL(vkQueueSubmit(command_queue->vk_queue, - 1, &submit_desc, VK_NULL_HANDLE))) < 0) + if (!(vk_queue = vkd3d_queue_acquire(command_queue->vkd3d_queue))) + { + ERR("Failed to acquire queue %p.\n", command_queue->vkd3d_queue); + return; + } + + if ((vr = VK_CALL(vkQueueSubmit(vk_queue, 1, &submit_desc, VK_NULL_HANDLE))) < 0) ERR("Failed to submit queue(s), vr %d.\n", vr);
+ vkd3d_queue_release(command_queue->vkd3d_queue); + vkd3d_free(buffers); }
@@ -4140,6 +4211,7 @@ static HRESULT STDMETHODCALLTYPE d3d12_command_queue_Signal(ID3D12CommandQueue * VkFenceCreateInfo fence_info; struct d3d12_device *device; VkFence vk_fence; + VkQueue vk_queue; VkResult vr;
TRACE("iface %p, fence %p, value %#"PRIx64".\n", iface, fence, value); @@ -4158,7 +4230,14 @@ static HRESULT STDMETHODCALLTYPE d3d12_command_queue_Signal(ID3D12CommandQueue * return hresult_from_vk_result(vr); }
- if ((vr = VK_CALL(vkQueueSubmit(command_queue->vk_queue, 0, NULL, vk_fence))) < 0) + if (!(vk_queue = vkd3d_queue_acquire(command_queue->vkd3d_queue))) + { + ERR("Failed to acquire queue %p.\n", command_queue->vkd3d_queue); + return E_FAIL; + } + vr = VK_CALL(vkQueueSubmit(vk_queue, 0, NULL, vk_fence)); + vkd3d_queue_release(command_queue->vkd3d_queue); + if (vr < 0) { WARN("Failed to submit fence, vr %d.\n", vr); VK_CALL(vkDestroyFence(device->vk_device, vk_fence, NULL)); @@ -4197,8 +4276,11 @@ static HRESULT STDMETHODCALLTYPE d3d12_command_queue_GetTimestampFrequency(ID3D1
TRACE("iface %p, frequency %p.\n", iface, frequency);
- if (command_queue->vk_queue_timestamp_bits == 0) + if (!command_queue->vkd3d_queue->timestamp_bits) + { + WARN("Timestamp queries not supported.\n"); return E_FAIL; + }
*frequency = 1000000000 / device->vk_info.device_limits.timestampPeriod;
@@ -4255,10 +4337,6 @@ static const struct ID3D12CommandQueueVtbl d3d12_command_queue_vtbl = static HRESULT d3d12_command_queue_init(struct d3d12_command_queue *queue, struct d3d12_device *device, const D3D12_COMMAND_QUEUE_DESC *desc) { - const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs; - unsigned int queue_family_index; - uint32_t timestamp_bits; - queue->ID3D12CommandQueue_iface.lpVtbl = &d3d12_command_queue_vtbl; queue->refcount = 1;
@@ -4266,35 +4344,14 @@ static HRESULT d3d12_command_queue_init(struct d3d12_command_queue *queue, if (!queue->desc.NodeMask) queue->desc.NodeMask = 0x1;
- switch (desc->Type) - { - case D3D12_COMMAND_LIST_TYPE_DIRECT: - queue_family_index = device->direct_queue_family_index; - timestamp_bits = device->direct_queue_timestamp_bits; - break; - case D3D12_COMMAND_LIST_TYPE_COPY: - queue_family_index = device->copy_queue_family_index; - timestamp_bits = device->copy_queue_timestamp_bits; - break; - case D3D12_COMMAND_LIST_TYPE_COMPUTE: - queue_family_index = device->compute_queue_family_index; - timestamp_bits = device->compute_queue_timestamp_bits; - break; - default: - FIXME("Unhandled command list type %#x.\n", desc->Type); - return E_NOTIMPL; - } + if (!(queue->vkd3d_queue = d3d12_device_get_vkd3d_queue(device, desc->Type))) + return E_NOTIMPL;
if (desc->Priority) FIXME("Ignoring priority %#x.\n", desc->Priority); if (desc->Flags) FIXME("Ignoring flags %#x.\n", desc->Flags);
- /* FIXME: Access to VkQueue must be externally synchronized. */ - VK_CALL(vkGetDeviceQueue(device->vk_device, queue_family_index, 0, &queue->vk_queue)); - queue->vk_queue_family_index = queue_family_index; - queue->vk_queue_timestamp_bits = timestamp_bits; - queue->device = device; ID3D12Device_AddRef(&device->ID3D12Device_iface);
@@ -4327,14 +4384,14 @@ VkQueue vkd3d_get_vk_queue(ID3D12CommandQueue *queue) { struct d3d12_command_queue *d3d12_queue = impl_from_ID3D12CommandQueue(queue);
- return d3d12_queue->vk_queue; + return d3d12_queue->vkd3d_queue->vk_queue; }
uint32_t vkd3d_get_vk_queue_family_index(ID3D12CommandQueue *queue) { struct d3d12_command_queue *d3d12_queue = impl_from_ID3D12CommandQueue(queue);
- return d3d12_queue->vk_queue_family_index; + return d3d12_queue->vkd3d_queue->vk_family_index; }
/* ID3D12CommandSignature */ diff --git a/libs/vkd3d/device.c b/libs/vkd3d/device.c index 198971aca8b9..39ec9660255d 100644 --- a/libs/vkd3d/device.c +++ b/libs/vkd3d/device.c @@ -684,6 +684,62 @@ static HRESULT vkd3d_select_physical_device(struct vkd3d_instance *instance, return S_OK; }
+static void d3d12_device_destroy_vkd3d_queues(struct d3d12_device *device) +{ + if (device->direct_queue) + vkd3d_queue_destroy(device->direct_queue); + if (device->compute_queue && device->compute_queue != device->direct_queue) + vkd3d_queue_destroy(device->compute_queue); + if (device->copy_queue && device->copy_queue != device->direct_queue + && device->copy_queue != device->compute_queue) + vkd3d_queue_destroy(device->copy_queue); + + device->direct_queue = NULL; + device->compute_queue = NULL; + device->copy_queue = NULL; +} + +static HRESULT d3d12_device_create_vkd3d_queues(struct d3d12_device *device, + uint32_t direct_queue_family_index, uint32_t direct_queue_timestamp_bits, + uint32_t compute_queue_family_index, uint32_t compute_queue_timestamp_bits, + uint32_t copy_queue_family_index, uint32_t copy_queue_timestamp_bits) +{ + HRESULT hr; + + device->direct_queue = NULL; + device->compute_queue = NULL; + device->copy_queue = NULL; + + if (FAILED((hr = vkd3d_queue_create(device, direct_queue_family_index, + direct_queue_timestamp_bits, &device->direct_queue)))) + { + d3d12_device_destroy_vkd3d_queues(device); + return hr; + } + + if (compute_queue_family_index == direct_queue_family_index) + device->compute_queue = device->direct_queue; + else if (FAILED(hr = vkd3d_queue_create(device, compute_queue_family_index, + compute_queue_timestamp_bits, &device->compute_queue))) + { + d3d12_device_destroy_vkd3d_queues(device); + return hr; + } + + if (copy_queue_family_index == direct_queue_family_index) + device->copy_queue = device->direct_queue; + else if (copy_queue_family_index == compute_queue_family_index) + device->copy_queue = device->compute_queue; + else if (FAILED(hr = vkd3d_queue_create(device, copy_queue_family_index, + copy_queue_timestamp_bits, &device->copy_queue))) + { + d3d12_device_destroy_vkd3d_queues(device); + return hr; + } + + return S_OK; +} + static HRESULT vkd3d_create_vk_device(struct d3d12_device *device) { unsigned int direct_queue_family_index, copy_queue_family_index, compute_queue_family_index; @@ -776,12 +832,6 @@ static HRESULT vkd3d_create_vk_device(struct d3d12_device *device) compute_queue_timestamp_bits = direct_queue_timestamp_bits; }
- device->direct_queue_family_index = direct_queue_family_index; - device->copy_queue_family_index = copy_queue_family_index; - device->compute_queue_family_index = compute_queue_family_index; - device->direct_queue_timestamp_bits = direct_queue_timestamp_bits; - device->copy_queue_timestamp_bits = copy_queue_timestamp_bits; - device->compute_queue_timestamp_bits = compute_queue_timestamp_bits; TRACE("Using queue family %u for direct command queues.\n", direct_queue_family_index); TRACE("Using queue family %u for copy command queues.\n", copy_queue_family_index); TRACE("Using queue family %u for compute command queues.\n", compute_queue_family_index); @@ -824,6 +874,16 @@ static HRESULT vkd3d_create_vk_device(struct d3d12_device *device)
device->vk_device = vk_device;
+ if (FAILED(hr = d3d12_device_create_vkd3d_queues(device, + direct_queue_family_index, direct_queue_timestamp_bits, + compute_queue_family_index, compute_queue_timestamp_bits, + copy_queue_family_index, copy_queue_timestamp_bits))) + { + ERR("Failed to create queues, hr %#x.\n", hr); + vkDestroyDevice(vk_device, NULL); + return hr; + } + TRACE("Created Vulkan device %p.\n", vk_device);
return S_OK; @@ -982,6 +1042,7 @@ static ULONG STDMETHODCALLTYPE d3d12_device_Release(ID3D12Device *iface) VK_CALL(vkDestroySampler(device->vk_device, device->vk_default_sampler, NULL)); if (device->vk_pipeline_cache) VK_CALL(vkDestroyPipelineCache(device->vk_device, device->vk_pipeline_cache, NULL)); + d3d12_device_destroy_vkd3d_queues(device); VK_CALL(vkDestroyDevice(device->vk_device, NULL)); vkd3d_instance_decref(device->vkd3d_instance);
diff --git a/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/vkd3d_private.h index d09cb53eef8b..1b0924f3b312 100644 --- a/libs/vkd3d/vkd3d_private.h +++ b/libs/vkd3d/vkd3d_private.h @@ -578,6 +578,19 @@ HRESULT d3d12_command_list_create(struct d3d12_device *device, UINT node_mask, D3D12_COMMAND_LIST_TYPE type, ID3D12CommandAllocator *allocator_iface, ID3D12PipelineState *initial_pipeline_state, struct d3d12_command_list **list) DECLSPEC_HIDDEN;
+struct vkd3d_queue +{ + /* Access to VkQueue must be externally synchronized. */ + pthread_mutex_t mutex; + VkQueue vk_queue; + uint32_t vk_family_index; + uint32_t timestamp_bits; +}; + +HRESULT vkd3d_queue_create(struct d3d12_device *device, + uint32_t family_index, uint32_t timestamp_bits, struct vkd3d_queue **queue) DECLSPEC_HIDDEN; +void vkd3d_queue_destroy(struct vkd3d_queue *queue) DECLSPEC_HIDDEN; + /* ID3D12CommandQueue */ struct d3d12_command_queue { @@ -586,9 +599,7 @@ struct d3d12_command_queue
D3D12_COMMAND_QUEUE_DESC desc;
- VkQueue vk_queue; - uint32_t vk_queue_family_index; - uint32_t vk_queue_timestamp_bits; + struct vkd3d_queue *vkd3d_queue;
struct d3d12_device *device; }; @@ -631,18 +642,16 @@ struct d3d12_device /* A sampler used for SpvOpImageFetch. */ VkSampler vk_default_sampler;
- unsigned int direct_queue_family_index; - unsigned int copy_queue_family_index; - unsigned int compute_queue_family_index; VkPhysicalDeviceMemoryProperties memory_properties; - uint32_t direct_queue_timestamp_bits; - uint32_t copy_queue_timestamp_bits; - uint32_t compute_queue_timestamp_bits;
D3D12_FEATURE_DATA_D3D12_OPTIONS feature_options;
struct vkd3d_vulkan_info vk_info;
+ struct vkd3d_queue *direct_queue; + struct vkd3d_queue *compute_queue; + struct vkd3d_queue *copy_queue; + struct vkd3d_instance *vkd3d_instance;
vkd3d_create_thread_pfn create_thread;
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
From: Józef Kucia jkucia@codeweavers.com
Signed-off-by: Józef Kucia jkucia@codeweavers.com ---
Required by the test introduced in the next commit.
--- libs/vkd3d/device.c | 66 +++++++++++++++++++++++++++++++++++++++------- libs/vkd3d/vkd3d_private.h | 4 +-- 2 files changed, 59 insertions(+), 11 deletions(-)
diff --git a/libs/vkd3d/device.c b/libs/vkd3d/device.c index b7adb8ed797c..0750662890e5 100644 --- a/libs/vkd3d/device.c +++ b/libs/vkd3d/device.c @@ -920,19 +920,31 @@ static void d3d12_device_init_pipeline_cache(struct d3d12_device *device) } }
-/* FIXME: Allocator should be thread-safe. */ D3D12_GPU_VIRTUAL_ADDRESS vkd3d_gpu_va_allocator_allocate(struct vkd3d_gpu_va_allocator *allocator, size_t size, void *ptr) { D3D12_GPU_VIRTUAL_ADDRESS ceiling = ~(D3D12_GPU_VIRTUAL_ADDRESS)0; struct vkd3d_gpu_va_allocation *allocation; + int rc; + + if ((rc = pthread_mutex_lock(&allocator->mutex))) + { + ERR("Failed to lock mutex, error %d.\n", rc); + return 0; + }
if (!vkd3d_array_reserve((void **)&allocator->allocations, &allocator->allocations_size, allocator->allocation_count + 1, sizeof(*allocator->allocations))) + { + pthread_mutex_unlock(&allocator->mutex); return 0; + }
if (size > ceiling || ceiling - size < allocator->floor) + { + pthread_mutex_unlock(&allocator->mutex); return 0; + }
allocation = &allocator->allocations[allocator->allocation_count++]; allocation->base = allocator->floor; @@ -941,6 +953,8 @@ D3D12_GPU_VIRTUAL_ADDRESS vkd3d_gpu_va_allocator_allocate(struct vkd3d_gpu_va_al
allocator->floor += size;
+ pthread_mutex_unlock(&allocator->mutex); + return allocation->base; }
@@ -959,35 +973,69 @@ static int vkd3d_gpu_va_allocation_compare(const void *k, const void *e) void *vkd3d_gpu_va_allocator_dereference(struct vkd3d_gpu_va_allocator *allocator, D3D12_GPU_VIRTUAL_ADDRESS address) { struct vkd3d_gpu_va_allocation *allocation; + int rc;
- if (!(allocation = bsearch(&address, allocator->allocations, allocator->allocation_count, - sizeof(*allocation), vkd3d_gpu_va_allocation_compare))) + if ((rc = pthread_mutex_lock(&allocator->mutex))) + { + ERR("Failed to lock mutex, error %d.\n", rc); return NULL; + } + + allocation = bsearch(&address, allocator->allocations, allocator->allocation_count, + sizeof(*allocation), vkd3d_gpu_va_allocation_compare); + + pthread_mutex_unlock(&allocator->mutex);
- return allocation->ptr; + return allocation ? allocation->ptr : NULL; }
void vkd3d_gpu_va_allocator_free(struct vkd3d_gpu_va_allocator *allocator, D3D12_GPU_VIRTUAL_ADDRESS address) { struct vkd3d_gpu_va_allocation *allocation; + int rc;
- if (!(allocation = bsearch(&address, allocator->allocations, allocator->allocation_count, - sizeof(*allocation), vkd3d_gpu_va_allocation_compare))) + if ((rc = pthread_mutex_lock(&allocator->mutex))) + { + ERR("Failed to lock mutex, error %d.\n", rc); return; + }
- if (allocation->base == address) + allocation = bsearch(&address, allocator->allocations, allocator->allocation_count, + sizeof(*allocation), vkd3d_gpu_va_allocation_compare); + if (allocation && allocation->base == address) allocation->ptr = NULL; + + pthread_mutex_unlock(&allocator->mutex); }
-void vkd3d_gpu_va_allocator_init(struct vkd3d_gpu_va_allocator *allocator) +static bool vkd3d_gpu_va_allocator_init(struct vkd3d_gpu_va_allocator *allocator) { + int rc; + memset(allocator, 0, sizeof(*allocator)); allocator->floor = 0x1000; + + if ((rc = pthread_mutex_init(&allocator->mutex, NULL))) + { + ERR("Failed to initialize mutex, error %d.\n", rc); + return false; + } + + return true; }
-void vkd3d_gpu_va_allocator_cleanup(struct vkd3d_gpu_va_allocator *allocator) +static void vkd3d_gpu_va_allocator_cleanup(struct vkd3d_gpu_va_allocator *allocator) { + int rc; + + if ((rc = pthread_mutex_lock(&allocator->mutex))) + { + ERR("Failed to lock mutex, error %d.\n", rc); + return; + } vkd3d_free(allocator->allocations); + pthread_mutex_unlock(&allocator->mutex); + pthread_mutex_destroy(&allocator->mutex); }
/* ID3D12Device */ diff --git a/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/vkd3d_private.h index 1b0924f3b312..de5ed8e8576a 100644 --- a/libs/vkd3d/vkd3d_private.h +++ b/libs/vkd3d/vkd3d_private.h @@ -122,6 +122,8 @@ HRESULT vkd3d_fence_worker_stop(struct vkd3d_fence_worker *worker,
struct vkd3d_gpu_va_allocator { + pthread_mutex_t mutex; + D3D12_GPU_VIRTUAL_ADDRESS floor;
struct vkd3d_gpu_va_allocation @@ -136,12 +138,10 @@ struct vkd3d_gpu_va_allocator
D3D12_GPU_VIRTUAL_ADDRESS vkd3d_gpu_va_allocator_allocate(struct vkd3d_gpu_va_allocator *allocator, size_t size, void *ptr) DECLSPEC_HIDDEN; -void vkd3d_gpu_va_allocator_cleanup(struct vkd3d_gpu_va_allocator *allocator) DECLSPEC_HIDDEN; void *vkd3d_gpu_va_allocator_dereference(struct vkd3d_gpu_va_allocator *allocator, D3D12_GPU_VIRTUAL_ADDRESS address) DECLSPEC_HIDDEN; void vkd3d_gpu_va_allocator_free(struct vkd3d_gpu_va_allocator *allocator, D3D12_GPU_VIRTUAL_ADDRESS address) DECLSPEC_HIDDEN; -void vkd3d_gpu_va_allocator_init(struct vkd3d_gpu_va_allocator *allocator) DECLSPEC_HIDDEN;
/* ID3D12Fence */ struct d3d12_fence
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
From: Józef Kucia jkucia@codeweavers.com
Signed-off-by: Józef Kucia jkucia@codeweavers.com --- tests/d3d12.c | 98 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+)
diff --git a/tests/d3d12.c b/tests/d3d12.c index 55116204a209..b8b4d95d1df7 100644 --- a/tests/d3d12.c +++ b/tests/d3d12.c @@ -16983,6 +16983,103 @@ static void test_face_culling(void) destroy_test_context(&context); }
+static void draw_thread_main(void *thread_data) +{ + static const float white[] = {1.0f, 1.0f, 1.0f, 1.0f}; + struct test_context *context = thread_data; + ID3D12GraphicsCommandList *command_list; + ID3D12CommandAllocator *allocator; + D3D12_CPU_DESCRIPTOR_HANDLE rtv; + ID3D12Resource *render_target; + ID3D12DescriptorHeap *heap; + ID3D12CommandQueue *queue; + ID3D12Device *device; + unsigned int i; + HRESULT hr; + + queue = context->queue; + device = context->device; + heap = create_cpu_descriptor_heap(device, D3D12_DESCRIPTOR_HEAP_TYPE_RTV, 1); + rtv = get_cpu_descriptor_handle(context, heap, 0); + create_render_target(context, NULL, &render_target, &rtv); + + hr = ID3D12Device_CreateCommandAllocator(device, D3D12_COMMAND_LIST_TYPE_DIRECT, + &IID_ID3D12CommandAllocator, (void **)&allocator); + ok(SUCCEEDED(hr), "Failed to create command allocator, hr %#x.\n", hr); + hr = ID3D12Device_CreateCommandList(device, 0, D3D12_COMMAND_LIST_TYPE_DIRECT, + allocator, NULL, &IID_ID3D12GraphicsCommandList, (void **)&command_list); + ok(SUCCEEDED(hr), "Failed to create command list, hr %#x.\n", hr); + + for (i = 0; i < 100; ++i) + { + ID3D12GraphicsCommandList_ClearRenderTargetView(command_list, rtv, white, 0, NULL); + ID3D12GraphicsCommandList_OMSetRenderTargets(command_list, 1, &rtv, FALSE, NULL); + ID3D12GraphicsCommandList_SetGraphicsRootSignature(command_list, context->root_signature); + ID3D12GraphicsCommandList_SetPipelineState(command_list, context->pipeline_state); + ID3D12GraphicsCommandList_IASetPrimitiveTopology(command_list, D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ID3D12GraphicsCommandList_RSSetViewports(command_list, 1, &context->viewport); + ID3D12GraphicsCommandList_RSSetScissorRects(command_list, 1, &context->scissor_rect); + ID3D12GraphicsCommandList_DrawInstanced(command_list, 3, 1, 0, 0); + + transition_resource_state(command_list, render_target, + D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_COPY_SOURCE); + check_sub_resource_uint(render_target, 0, queue, command_list, 0xff00ff00, 0); + reset_command_list(command_list, allocator); + transition_resource_state(command_list, render_target, + D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_RENDER_TARGET); + } + + ID3D12DescriptorHeap_Release(heap); + ID3D12Resource_Release(render_target); + ID3D12CommandAllocator_Release(allocator); + ID3D12GraphicsCommandList_Release(command_list); +} + +static void test_multithread_command_queue_exec(void) +{ + static const float white[] = {1.0f, 1.0f, 1.0f, 1.0f}; + ID3D12GraphicsCommandList *command_list; + struct test_context context; + ID3D12CommandQueue *queue; + HANDLE threads[10]; + unsigned int i; + + if (!init_test_context(&context, NULL)) + return; + command_list = context.list; + queue = context.queue; + + for (i = 0; i < ARRAY_SIZE(threads); ++i) + { + threads[i] = create_thread(draw_thread_main, &context); + ok(threads[i], "Failed to create thread %u.\n", i); + } + + for (i = 0; i < 100; ++i) + { + ID3D12GraphicsCommandList_ClearRenderTargetView(command_list, context.rtv, white, 0, NULL); + ID3D12GraphicsCommandList_OMSetRenderTargets(command_list, 1, &context.rtv, FALSE, NULL); + ID3D12GraphicsCommandList_SetGraphicsRootSignature(command_list, context.root_signature); + ID3D12GraphicsCommandList_SetPipelineState(command_list, context.pipeline_state); + ID3D12GraphicsCommandList_IASetPrimitiveTopology(command_list, D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ID3D12GraphicsCommandList_RSSetViewports(command_list, 1, &context.viewport); + ID3D12GraphicsCommandList_RSSetScissorRects(command_list, 1, &context.scissor_rect); + ID3D12GraphicsCommandList_DrawInstanced(command_list, 3, 1, 0, 0); + + transition_resource_state(command_list, context.render_target, + D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_COPY_SOURCE); + check_sub_resource_uint(context.render_target, 0, queue, command_list, 0xff00ff00, 0); + reset_command_list(command_list, context.allocator); + transition_resource_state(command_list, context.render_target, + D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_RENDER_TARGET); + } + + for (i = 0; i < ARRAY_SIZE(threads); ++i) + ok(join_thread(threads[i]), "Failed to join thread %u.\n", i); + + destroy_test_context(&context); +} + START_TEST(d3d12) { bool enable_debug_layer = false; @@ -17085,4 +17182,5 @@ START_TEST(d3d12) run_test(test_copy_texture_region); run_test(test_separate_bindings); run_test(test_face_culling); + run_test(test_multithread_command_queue_exec); }
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
From: Józef Kucia jkucia@codeweavers.com
Signed-off-by: Józef Kucia jkucia@codeweavers.com ---
I'll remove vkd3d_get_vk_queue() after converting vkmodelviewer to the new API.
--- 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 3cc2c54d7ff4..a683dcae1951 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 8a04dbd97cfa..322675b9e992 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 85dcf6fcabbf..7aa138672315 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 db638f6dd35c..57b8606e3f6f 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 79d51ccd36aa..146467a4f8f6 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); }
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
On 15 January 2018 at 13:49, Józef Kucia joseph.kucia@gmail.com wrote:
+++ b/libs/vkd3d/vkd3d.map @@ -0,0 +1,18 @@ +{ +global:
- vkd3d_create_device;
- vkd3d_create_image_resource;
- vkd3d_create_instance;
- vkd3d_create_root_signature_deserializer;
- vkd3d_get_vk_device;
- vkd3d_get_vk_format;
- vkd3d_get_vk_instance;
- vkd3d_get_vk_physical_device;
- vkd3d_get_vk_queue;
- vkd3d_get_vk_queue_family_index;
- vkd3d_instance_decref;
- vkd3d_instance_incref;
- vkd3d_serialize_root_signature;
+local: *; +};
Should these maps use a named version, e.g. VKD3D_1.0?
On Mon, Jan 15, 2018 at 4:03 PM, Henri Verbeet hverbeet@gmail.com wrote:
On 15 January 2018 at 13:49, Józef Kucia joseph.kucia@gmail.com wrote:
+++ b/libs/vkd3d/vkd3d.map @@ -0,0 +1,18 @@ +{ +global:
- vkd3d_create_device;
- vkd3d_create_image_resource;
- vkd3d_create_instance;
- vkd3d_create_root_signature_deserializer;
- vkd3d_get_vk_device;
- vkd3d_get_vk_format;
- vkd3d_get_vk_instance;
- vkd3d_get_vk_physical_device;
- vkd3d_get_vk_queue;
- vkd3d_get_vk_queue_family_index;
- vkd3d_instance_decref;
- vkd3d_instance_incref;
- vkd3d_serialize_root_signature;
+local: *; +};
Should these maps use a named version, e.g. VKD3D_1.0?
They could, but I'm not sure if this is necessary. I think we do not plan to use symbol versioning for incompatible ABI changes. The intent is to not introduce any backward incompatible ABI changes after the the first release. If we ever want to revisit API and/or introduce backward incompatible ABI changes, we'll probably just bump the soname version.
On 15 January 2018 at 17:55, Józef Kucia joseph.kucia@gmail.com wrote:
On Mon, Jan 15, 2018 at 4:03 PM, Henri Verbeet hverbeet@gmail.com wrote:
On 15 January 2018 at 13:49, Józef Kucia joseph.kucia@gmail.com wrote:
+++ b/libs/vkd3d/vkd3d.map @@ -0,0 +1,18 @@ +{ +global:
- vkd3d_create_device;
- vkd3d_create_image_resource;
- vkd3d_create_instance;
- vkd3d_create_root_signature_deserializer;
- vkd3d_get_vk_device;
- vkd3d_get_vk_format;
- vkd3d_get_vk_instance;
- vkd3d_get_vk_physical_device;
- vkd3d_get_vk_queue;
- vkd3d_get_vk_queue_family_index;
- vkd3d_instance_decref;
- vkd3d_instance_incref;
- vkd3d_serialize_root_signature;
+local: *; +};
Should these maps use a named version, e.g. VKD3D_1.0?
They could, but I'm not sure if this is necessary. I think we do not plan to use symbol versioning for incompatible ABI changes. The intent is to not introduce any backward incompatible ABI changes after the the first release. If we ever want to revisit API and/or introduce backward incompatible ABI changes, we'll probably just bump the soname version.
Yeah, but I think a named version would make it easier to change our minds about that in the future.
On Mon, Jan 15, 2018 at 5:59 PM, Henri Verbeet hverbeet@gmail.com wrote:
On 15 January 2018 at 17:55, Józef Kucia joseph.kucia@gmail.com wrote:
On Mon, Jan 15, 2018 at 4:03 PM, Henri Verbeet hverbeet@gmail.com wrote:
On 15 January 2018 at 13:49, Józef Kucia joseph.kucia@gmail.com wrote:
+++ b/libs/vkd3d/vkd3d.map @@ -0,0 +1,18 @@ +{ +global:
- vkd3d_create_device;
- vkd3d_create_image_resource;
- vkd3d_create_instance;
- vkd3d_create_root_signature_deserializer;
- vkd3d_get_vk_device;
- vkd3d_get_vk_format;
- vkd3d_get_vk_instance;
- vkd3d_get_vk_physical_device;
- vkd3d_get_vk_queue;
- vkd3d_get_vk_queue_family_index;
- vkd3d_instance_decref;
- vkd3d_instance_incref;
- vkd3d_serialize_root_signature;
+local: *; +};
Should these maps use a named version, e.g. VKD3D_1.0?
They could, but I'm not sure if this is necessary. I think we do not plan to use symbol versioning for incompatible ABI changes. The intent is to not introduce any backward incompatible ABI changes after the the first release. If we ever want to revisit API and/or introduce backward incompatible ABI changes, we'll probably just bump the soname version.
Yeah, but I think a named version would make it easier to change our minds about that in the future.
Sure, I'll prepare a patch.