[PATCH vkd3d 04/12] libs/vkd3d: Add API for creating vkd3d instances.

Józef Kucia joseph.kucia at gmail.com
Thu Jan 11 10:03:47 CST 2018


From: Józef Kucia <jkucia at codeweavers.com>

Makes possible to share a Vulkan instance between multiple devices.

Signed-off-by: Józef Kucia <jkucia at codeweavers.com>
---
 include/vkd3d.h                     |  22 ++++++-
 libs/vkd3d-utils/vkd3d_utils_main.c |  18 +++---
 libs/vkd3d/device.c                 | 114 +++++++++++++++++++++++++-----------
 libs/vkd3d/vkd3d_main.c             |  28 ++++++++-
 libs/vkd3d/vkd3d_private.h          |  34 +++++++----
 5 files changed, 158 insertions(+), 58 deletions(-)

diff --git a/include/vkd3d.h b/include/vkd3d.h
index c4d1a2ade034..8a04dbd97cfa 100644
--- a/include/vkd3d.h
+++ b/include/vkd3d.h
@@ -38,27 +38,41 @@ typedef void * (*vkd3d_thread_pfn)(void *data);
 typedef void * (*vkd3d_create_thread_pfn)(vkd3d_thread_pfn thread_main, void *data);
 typedef bool (*vkd3d_join_thread_pfn)(void *thread);
 
-struct vkd3d_device_create_info
+struct vkd3d_instance;
+
+struct vkd3d_instance_create_info
 {
-    D3D_FEATURE_LEVEL minimum_feature_level;
     vkd3d_signal_event_pfn signal_event_pfn;
     vkd3d_create_thread_pfn create_thread_pfn;
     vkd3d_join_thread_pfn join_thread_pfn;
     size_t wchar_size;
 };
 
+struct vkd3d_device_create_info
+{
+    D3D_FEATURE_LEVEL minimum_feature_level;
+
+    struct vkd3d_instance *instance;
+    const struct vkd3d_instance_create_info *instance_create_info;
+};
+
 /* resource flags */
 #define VKD3D_RESOURCE_INITIAL_STATE_TRANSITION 0x00000001
 #define VKD3D_RESOURCE_SWAPCHAIN_IMAGE          0x00000002
 
+HRESULT vkd3d_create_instance(const struct vkd3d_instance_create_info *create_info,
+        struct vkd3d_instance **instance);
+ULONG vkd3d_instance_decref(struct vkd3d_instance *instance);
+ULONG vkd3d_instance_incref(struct vkd3d_instance *instance);
+
 HRESULT vkd3d_create_device(const struct vkd3d_device_create_info *create_info,
         REFIID riid, void **device);
 HRESULT vkd3d_create_image_resource(ID3D12Device *device, const D3D12_RESOURCE_DESC *desc,
         VkImage vk_image, unsigned int resource_flags, ID3D12Resource **resource);
 VkDevice vkd3d_get_vk_device(ID3D12Device *device);
-VkFormat vkd3d_get_vk_format(DXGI_FORMAT format);
 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);
 
@@ -68,6 +82,8 @@ HRESULT vkd3d_serialize_root_signature(const D3D12_ROOT_SIGNATURE_DESC *root_sig
 HRESULT vkd3d_create_root_signature_deserializer(const void *data, SIZE_T data_size,
         REFIID iid, void **deserializer);
 
+VkFormat vkd3d_get_vk_format(DXGI_FORMAT format);
+
 #ifdef __cplusplus
 }
 #endif  /* __cplusplus */
diff --git a/libs/vkd3d-utils/vkd3d_utils_main.c b/libs/vkd3d-utils/vkd3d_utils_main.c
index 1964df15efb1..38283bf23585 100644
--- a/libs/vkd3d-utils/vkd3d_utils_main.c
+++ b/libs/vkd3d-utils/vkd3d_utils_main.c
@@ -28,7 +28,8 @@ HRESULT WINAPI D3D12GetDebugInterface(REFIID riid, void **debug)
 HRESULT WINAPI D3D12CreateDevice(IUnknown *adapter,
         D3D_FEATURE_LEVEL minimum_feature_level, REFIID riid, void **device)
 {
-    struct vkd3d_device_create_info create_info;
+    struct vkd3d_instance_create_info instance_create_info;
+    struct vkd3d_device_create_info device_create_info;
 
     TRACE("adapter %p, minimum_feature_level %#x, riid %s, device %p.\n",
             adapter, minimum_feature_level, debugstr_guid(riid), device);
@@ -36,13 +37,16 @@ HRESULT WINAPI D3D12CreateDevice(IUnknown *adapter,
     if (adapter)
         FIXME("Ignoring adapter %p.\n", adapter);
 
-    create_info.minimum_feature_level = minimum_feature_level;
-    create_info.signal_event_pfn = vkd3d_signal_event;
-    create_info.create_thread_pfn = NULL;
-    create_info.join_thread_pfn = NULL;
-    create_info.wchar_size = sizeof(WCHAR);
+    instance_create_info.signal_event_pfn = vkd3d_signal_event;
+    instance_create_info.create_thread_pfn = NULL;
+    instance_create_info.join_thread_pfn = NULL;
+    instance_create_info.wchar_size = sizeof(WCHAR);
 
-    return vkd3d_create_device(&create_info, riid, device);
+    device_create_info.minimum_feature_level = minimum_feature_level;
+    device_create_info.instance = NULL;
+    device_create_info.instance_create_info = &instance_create_info;
+
+    return vkd3d_create_device(&device_create_info, riid, device);
 }
 
 HRESULT WINAPI D3D12CreateRootSignatureDeserializer(const void *data, SIZE_T data_size,
diff --git a/libs/vkd3d/device.c b/libs/vkd3d/device.c
index 51edd3660fb7..9819ea0df56b 100644
--- a/libs/vkd3d/device.c
+++ b/libs/vkd3d/device.c
@@ -170,7 +170,7 @@ static void vkd3d_init_instance_caps(struct vkd3d_vulkan_info *vulkan_info)
 }
 
 static HRESULT vkd3d_instance_init(struct vkd3d_instance *instance,
-        struct vkd3d_vulkan_info *vk_info)
+        const struct vkd3d_instance_create_info *create_info)
 {
     const char *extensions[MAX_INSTANCE_EXTENSION_COUNT];
     VkApplicationInfo application_info;
@@ -179,7 +179,19 @@ static HRESULT vkd3d_instance_init(struct vkd3d_instance *instance,
     VkResult vr;
     HRESULT hr;
 
-    TRACE("instance %p.\n", instance);
+    if (!create_info->create_thread_pfn != !create_info->join_thread_pfn)
+    {
+        ERR("Invalid create/join thread function pointers.\n");
+        return E_INVALIDARG;
+    }
+
+    instance->signal_event = create_info->signal_event_pfn;
+    instance->create_thread = create_info->create_thread_pfn;
+    instance->join_thread = create_info->join_thread_pfn;
+    instance->wchar_size = create_info->wchar_size;
+
+    memset(&instance->vk_info, 0, sizeof(instance->vk_info));
+    vkd3d_init_instance_caps(&instance->vk_info);
 
     application_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
     application_info.pNext = NULL;
@@ -198,7 +210,7 @@ static HRESULT vkd3d_instance_init(struct vkd3d_instance *instance,
     instance_info.enabledExtensionCount = vkd3d_enable_extensions(extensions,
             required_instance_extensions, ARRAY_SIZE(required_instance_extensions),
             optional_instance_extensions, ARRAY_SIZE(optional_instance_extensions),
-            vk_info);
+            &instance->vk_info);
     instance_info.ppEnabledExtensionNames = extensions;
 
     if ((vr = vkCreateInstance(&instance_info, NULL, &vk_instance)))
@@ -218,16 +230,58 @@ static HRESULT vkd3d_instance_init(struct vkd3d_instance *instance,
 
     TRACE("Created Vulkan instance %p.\n", vk_instance);
 
+    instance->refcount = 1;
+
     return S_OK;
 }
 
-static void vkd3d_instance_destroy(struct vkd3d_instance *instance)
+HRESULT vkd3d_create_instance(const struct vkd3d_instance_create_info *create_info,
+        struct vkd3d_instance **instance)
 {
-    const struct vkd3d_vk_instance_procs *vk_procs = &instance->vk_procs;
+    struct vkd3d_instance *object;
+    HRESULT hr;
 
-    TRACE("instance %p.\n", instance);
+    TRACE("create_info %p.\n", create_info);
 
-    VK_CALL(vkDestroyInstance(instance->vk_instance, NULL));
+    if (!(object = vkd3d_malloc(sizeof(*object))))
+        return E_OUTOFMEMORY;
+
+    if (FAILED(hr = vkd3d_instance_init(object, create_info)))
+    {
+        vkd3d_free(object);
+        return hr;
+    }
+
+    TRACE("Created instance %p.\n", object);
+
+    *instance = object;
+
+    return S_OK;
+}
+
+ULONG vkd3d_instance_incref(struct vkd3d_instance *instance)
+{
+    ULONG refcount = InterlockedIncrement(&instance->refcount);
+
+    TRACE("%p increasing refcount to %u.\n", instance, refcount);
+
+    return refcount;
+}
+
+ULONG vkd3d_instance_decref(struct vkd3d_instance *instance)
+{
+    ULONG refcount = InterlockedDecrement(&instance->refcount);
+
+    TRACE("%p decreasing refcount to %u.\n", instance, refcount);
+
+    if (!refcount)
+    {
+        const struct vkd3d_vk_instance_procs *vk_procs = &instance->vk_procs;
+        VK_CALL(vkDestroyInstance(instance->vk_instance, NULL));
+        vkd3d_free(instance);
+    }
+
+    return refcount;
 }
 
 static void vkd3d_trace_physical_device(VkPhysicalDevice device,
@@ -502,7 +556,7 @@ static void vkd3d_check_feature_level_11_requirements(const VkPhysicalDeviceLimi
 static void vkd3d_init_device_caps(struct d3d12_device *device,
         const VkPhysicalDeviceFeatures *features)
 {
-    const struct vkd3d_vk_instance_procs *vk_procs = &device->vkd3d_instance.vk_procs;
+    const struct vkd3d_vk_instance_procs *vk_procs = &device->vkd3d_instance->vk_procs;
     VkPhysicalDevice physical_device = device->vk_physical_device;
     struct vkd3d_vulkan_info *vulkan_info = &device->vk_info;
     VkPhysicalDeviceProperties device_properties;
@@ -629,7 +683,7 @@ static HRESULT vkd3d_create_vk_device(struct d3d12_device *device)
 {
     unsigned int direct_queue_family_index, copy_queue_family_index, compute_queue_family_index;
     uint32_t direct_queue_timestamp_bits, copy_queue_timestamp_bits, compute_queue_timestamp_bits;
-    const struct vkd3d_vk_instance_procs *vk_procs = &device->vkd3d_instance.vk_procs;
+    const struct vkd3d_vk_instance_procs *vk_procs = &device->vkd3d_instance->vk_procs;
     const char *extensions[MAX_DEVICE_EXTENSION_COUNT];
     VkQueueFamilyProperties *queue_properties;
     VkPhysicalDeviceFeatures device_features;
@@ -645,7 +699,7 @@ static HRESULT vkd3d_create_vk_device(struct d3d12_device *device)
     TRACE("device %p.\n", device);
 
     physical_device = VK_NULL_HANDLE;
-    if (FAILED(hr = vkd3d_select_physical_device(&device->vkd3d_instance, &physical_device)))
+    if (FAILED(hr = vkd3d_select_physical_device(device->vkd3d_instance, &physical_device)))
         return hr;
 
     /* Create command queues */
@@ -924,7 +978,7 @@ static ULONG STDMETHODCALLTYPE d3d12_device_Release(ID3D12Device *iface)
         if (device->vk_pipeline_cache)
             VK_CALL(vkDestroyPipelineCache(device->vk_device, device->vk_pipeline_cache, NULL));
         VK_CALL(vkDestroyDevice(device->vk_device, NULL));
-        vkd3d_instance_destroy(&device->vkd3d_instance);
+        vkd3d_instance_decref(device->vkd3d_instance);
 
         vkd3d_free(device);
     }
@@ -1808,42 +1862,32 @@ struct d3d12_device *unsafe_impl_from_ID3D12Device(ID3D12Device *iface)
     return impl_from_ID3D12Device(iface);
 }
 
-static HRESULT d3d12_device_init(struct d3d12_device *device,
-        const struct vkd3d_device_create_info *create_info)
+static HRESULT d3d12_device_init(struct d3d12_device *device, struct vkd3d_instance *instance)
 {
     HRESULT hr;
 
-    if (!create_info->create_thread_pfn != !create_info->join_thread_pfn)
-    {
-        ERR("Invalid create/join thread function pointers.\n");
-        return E_INVALIDARG;
-    }
-
     device->ID3D12Device_iface.lpVtbl = &d3d12_device_vtbl;
     device->refcount = 1;
 
-    memset(&device->vk_info, 0, sizeof(device->vk_info));
-    vkd3d_init_instance_caps(&device->vk_info);
-    if (FAILED(hr = vkd3d_instance_init(&device->vkd3d_instance, &device->vk_info)))
-        return hr;
+    vkd3d_instance_incref(device->vkd3d_instance = instance);
+    device->vk_info = instance->vk_info;
+    device->signal_event = instance->signal_event;
+    device->create_thread = instance->create_thread;
+    device->join_thread = instance->join_thread;
+    device->wchar_size = instance->wchar_size;
 
     if (FAILED(hr = vkd3d_create_vk_device(device)))
     {
-        vkd3d_instance_destroy(&device->vkd3d_instance);
+        vkd3d_instance_decref(device->vkd3d_instance);
         return hr;
     }
 
-    device->signal_event = create_info->signal_event_pfn;
-    device->create_thread = create_info->create_thread_pfn;
-    device->join_thread = create_info->join_thread_pfn;
-    device->wchar_size = create_info->wchar_size;
-
     if (FAILED(hr = d3d12_device_create_default_sampler(device)))
     {
         const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
         ERR("Failed to create default sampler, hr %#x.\n", hr);
         VK_CALL(vkDestroyDevice(device->vk_device, NULL));
-        vkd3d_instance_destroy(&device->vkd3d_instance);
+        vkd3d_instance_decref(device->vkd3d_instance);
         return hr;
     }
 
@@ -1852,7 +1896,7 @@ static HRESULT d3d12_device_init(struct d3d12_device *device,
         const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
         VK_CALL(vkDestroySampler(device->vk_device, device->vk_default_sampler, NULL));
         VK_CALL(vkDestroyDevice(device->vk_device, NULL));
-        vkd3d_instance_destroy(&device->vkd3d_instance);
+        vkd3d_instance_decref(device->vkd3d_instance);
         return hr;
     }
 
@@ -1863,8 +1907,7 @@ static HRESULT d3d12_device_init(struct d3d12_device *device,
     return S_OK;
 }
 
-HRESULT d3d12_device_create(const struct vkd3d_device_create_info *create_info,
-        struct d3d12_device **device)
+HRESULT d3d12_device_create(struct vkd3d_instance *instance, struct d3d12_device **device)
 {
     struct d3d12_device *object;
     HRESULT hr;
@@ -1872,7 +1915,7 @@ HRESULT d3d12_device_create(const struct vkd3d_device_create_info *create_info,
     if (!(object = vkd3d_malloc(sizeof(*object))))
         return E_OUTOFMEMORY;
 
-    if (FAILED(hr = d3d12_device_init(object, create_info)))
+    if (FAILED(hr = d3d12_device_init(object, instance)))
     {
         vkd3d_free(object);
         return hr;
@@ -1895,8 +1938,9 @@ VkDevice vkd3d_get_vk_device(ID3D12Device *device)
 VkInstance vkd3d_get_vk_instance(ID3D12Device *device)
 {
     struct d3d12_device *d3d12_device = impl_from_ID3D12Device(device);
+    struct vkd3d_instance *instance = d3d12_device->vkd3d_instance;
 
-    return d3d12_device->vkd3d_instance.vk_instance;
+    return instance->vk_instance;
 }
 
 VkPhysicalDevice vkd3d_get_vk_physical_device(ID3D12Device *device)
diff --git a/libs/vkd3d/vkd3d_main.c b/libs/vkd3d/vkd3d_main.c
index d1cb87bebd22..005e6bf240cc 100644
--- a/libs/vkd3d/vkd3d_main.c
+++ b/libs/vkd3d/vkd3d_main.c
@@ -22,11 +22,25 @@
 HRESULT vkd3d_create_device(const struct vkd3d_device_create_info *create_info,
         REFIID riid, void **device)
 {
+    struct vkd3d_instance *instance;
     struct d3d12_device *object;
     HRESULT hr;
 
     TRACE("create_info %p, riid %s, device %p.\n", create_info, debugstr_guid(riid), device);
 
+    if (!create_info || !device)
+        return E_INVALIDARG;
+    if (!create_info->instance && !create_info->instance_create_info)
+    {
+        ERR("Instance or instance create info is required.\n");
+        return E_INVALIDARG;
+    }
+    if (create_info->instance && create_info->instance_create_info)
+    {
+        ERR("Instance and instance create info are mutually exclusive parameters.\n");
+        return E_INVALIDARG;
+    }
+
     if (create_info->minimum_feature_level < D3D_FEATURE_LEVEL_11_0
             || !is_valid_feature_level(create_info->minimum_feature_level))
     {
@@ -40,7 +54,19 @@ HRESULT vkd3d_create_device(const struct vkd3d_device_create_info *create_info,
         return E_INVALIDARG;
     }
 
-    if (FAILED(hr = d3d12_device_create(create_info, &object)))
+    if ((instance = create_info->instance))
+    {
+        vkd3d_instance_incref(instance);
+    }
+    else if (FAILED(hr = vkd3d_create_instance(create_info->instance_create_info, &instance)))
+    {
+        WARN("Failed to create instance, hr %#x.\n", hr);
+        return E_FAIL;
+    }
+
+    hr = d3d12_device_create(instance, &object);
+    vkd3d_instance_decref(instance);
+    if (FAILED(hr))
         return hr;
 
     return return_interface((IUnknown *)&object->ID3D12Device_iface, &IID_ID3D12Device,
diff --git a/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/vkd3d_private.h
index ed636b562445..d09cb53eef8b 100644
--- a/libs/vkd3d/vkd3d_private.h
+++ b/libs/vkd3d/vkd3d_private.h
@@ -65,10 +65,30 @@ struct vkd3d_vk_device_procs
 };
 #undef DECLARE_VK_PFN
 
+struct vkd3d_vulkan_info
+{
+    /* instance extensions */
+    bool KHR_get_physical_device_properties2;
+    /* device extensions */
+    bool KHR_push_descriptor;
+
+    VkPhysicalDeviceLimits device_limits;
+    VkPhysicalDeviceSparseProperties sparse_properties;
+};
+
 struct vkd3d_instance
 {
     VkInstance vk_instance;
     struct vkd3d_vk_instance_procs vk_procs;
+
+    vkd3d_signal_event_pfn signal_event;
+    vkd3d_create_thread_pfn create_thread;
+    vkd3d_join_thread_pfn join_thread;
+    size_t wchar_size;
+
+    struct vkd3d_vulkan_info vk_info;
+
+    LONG refcount;
 };
 
 struct vkd3d_fence_worker
@@ -591,15 +611,6 @@ HRESULT d3d12_command_signature_create(struct d3d12_device *device, const D3D12_
         struct d3d12_command_signature **signature) DECLSPEC_HIDDEN;
 struct d3d12_command_signature *unsafe_impl_from_ID3D12CommandSignature(ID3D12CommandSignature *iface) DECLSPEC_HIDDEN;
 
-struct vkd3d_vulkan_info
-{
-    bool KHR_get_physical_device_properties2;
-    bool KHR_push_descriptor;
-
-    VkPhysicalDeviceLimits device_limits;
-    VkPhysicalDeviceSparseProperties sparse_properties;
-};
-
 /* ID3D12Device */
 struct d3d12_device
 {
@@ -632,14 +643,13 @@ struct d3d12_device
 
     struct vkd3d_vulkan_info vk_info;
 
-    struct vkd3d_instance vkd3d_instance;
+    struct vkd3d_instance *vkd3d_instance;
 
     vkd3d_create_thread_pfn create_thread;
     vkd3d_join_thread_pfn join_thread;
 };
 
-HRESULT d3d12_device_create(const struct vkd3d_device_create_info *create_info,
-        struct d3d12_device **device) DECLSPEC_HIDDEN;
+HRESULT d3d12_device_create(struct vkd3d_instance *instance, struct d3d12_device **device) DECLSPEC_HIDDEN;
 struct d3d12_device *unsafe_impl_from_ID3D12Device(ID3D12Device *iface) DECLSPEC_HIDDEN;
 
 HRESULT vkd3d_create_buffer(struct d3d12_device *device,
-- 
2.13.6




More information about the wine-devel mailing list