From: Józef Kucia jkucia@codeweavers.com
Makes possible to share a Vulkan instance between multiple devices.
Signed-off-by: Józef Kucia jkucia@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,