2 * Copyright 2018 Józef Kucia for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #define VKD3D_NO_VULKAN_H
22 #define VKD3D_NO_WIN32_TYPES
27 #include "wine/vulkan.h"
32 #include "wine/wined3d.h"
33 #include "wine/winedxgi.h"
34 #include "wine/debug.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(d3d12
);
37 WINE_DECLARE_DEBUG_CHANNEL(winediag
);
39 static HMODULE vulkan_module
;
41 /* FIXME: We should unload vulkan-1.dll. */
42 static BOOL WINAPI
load_vulkan_dll_once(INIT_ONCE
*once
, void *param
, void **context
)
44 vulkan_module
= LoadLibraryA("vulkan-1.dll");
48 static PFN_vkGetInstanceProcAddr
load_vulkan(void)
50 static INIT_ONCE init_once
= INIT_ONCE_STATIC_INIT
;
52 InitOnceExecuteOnce(&init_once
, load_vulkan_dll_once
, NULL
, NULL
);
55 return (void *)GetProcAddress(vulkan_module
, "vkGetInstanceProcAddr");
60 HRESULT WINAPI
D3D12GetDebugInterface(REFIID iid
, void **debug
)
62 TRACE("iid %s, debug %p.\n", debugstr_guid(iid
), debug
);
64 WARN("Returning DXGI_ERROR_SDK_COMPONENT_MISSING.\n");
65 return DXGI_ERROR_SDK_COMPONENT_MISSING
;
68 HRESULT WINAPI
D3D12EnableExperimentalFeatures(UINT feature_count
,
69 const IID
*iids
, void *configurations
, UINT
*configurations_sizes
)
71 FIXME("feature_count %u, iids %p, configurations %p, configurations_sizes %p stub!\n",
72 feature_count
, iids
, configurations
, configurations_sizes
);
77 static HRESULT
d3d12_signal_event(HANDLE event
)
79 return SetEvent(event
) ? S_OK
: E_FAIL
;
82 static HRESULT
d3d12_get_adapter(IWineDXGIAdapter
**wine_adapter
, IUnknown
*adapter
)
84 IDXGIAdapter
*dxgi_adapter
= NULL
;
85 IDXGIFactory4
*factory
= NULL
;
90 if (FAILED(hr
= CreateDXGIFactory2(0, &IID_IDXGIFactory4
, (void **)&factory
)))
92 WARN("Failed to create DXGI factory, hr %#lx.\n", hr
);
96 if (FAILED(hr
= IDXGIFactory4_EnumAdapters(factory
, 0, &dxgi_adapter
)))
98 WARN("Failed to enumerate primary adapter, hr %#lx.\n", hr
);
102 adapter
= (IUnknown
*)dxgi_adapter
;
105 if (FAILED(hr
= IUnknown_QueryInterface(adapter
, &IID_IWineDXGIAdapter
, (void **)wine_adapter
)))
106 WARN("Invalid adapter %p, hr %#lx.\n", adapter
, hr
);
110 IDXGIAdapter_Release(dxgi_adapter
);
112 IDXGIFactory4_Release(factory
);
117 static BOOL
check_vk_instance_extension(VkInstance vk_instance
,
118 PFN_vkGetInstanceProcAddr pfn_vkGetInstanceProcAddr
, const char *name
)
120 PFN_vkEnumerateInstanceExtensionProperties pfn_vkEnumerateInstanceExtensionProperties
;
121 VkExtensionProperties
*properties
;
126 pfn_vkEnumerateInstanceExtensionProperties
127 = (void *)pfn_vkGetInstanceProcAddr(vk_instance
, "vkEnumerateInstanceExtensionProperties");
129 if (pfn_vkEnumerateInstanceExtensionProperties(NULL
, &count
, NULL
) < 0)
132 if (!(properties
= calloc(count
, sizeof(*properties
))))
135 if (pfn_vkEnumerateInstanceExtensionProperties(NULL
, &count
, properties
) >= 0)
137 for (i
= 0; i
< count
; ++i
)
139 if (!strcmp(properties
[i
].extensionName
, name
))
151 static VkPhysicalDevice
d3d12_get_vk_physical_device(struct vkd3d_instance
*instance
,
152 PFN_vkGetInstanceProcAddr pfn_vkGetInstanceProcAddr
, const struct wine_dxgi_adapter_info
*adapter_info
)
154 PFN_vkGetPhysicalDeviceProperties2 pfn_vkGetPhysicalDeviceProperties2
= NULL
;
155 PFN_vkGetPhysicalDeviceProperties pfn_vkGetPhysicalDeviceProperties
;
156 PFN_vkEnumeratePhysicalDevices pfn_vkEnumeratePhysicalDevices
;
157 VkPhysicalDevice vk_physical_device
= VK_NULL_HANDLE
;
158 VkPhysicalDeviceIDProperties id_properties
;
159 VkPhysicalDeviceProperties2 properties2
;
160 VkPhysicalDeviceProperties properties
;
161 VkPhysicalDevice
*vk_physical_devices
;
162 VkInstance vk_instance
;
167 vk_instance
= vkd3d_instance_get_vk_instance(instance
);
169 pfn_vkEnumeratePhysicalDevices
= (void *)pfn_vkGetInstanceProcAddr(vk_instance
, "vkEnumeratePhysicalDevices");
171 pfn_vkGetPhysicalDeviceProperties
= (void *)pfn_vkGetInstanceProcAddr(vk_instance
, "vkGetPhysicalDeviceProperties");
172 if (check_vk_instance_extension(vk_instance
, pfn_vkGetInstanceProcAddr
, VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME
))
173 pfn_vkGetPhysicalDeviceProperties2
= (void *)pfn_vkGetInstanceProcAddr(vk_instance
, "vkGetPhysicalDeviceProperties2KHR");
175 if ((vr
= pfn_vkEnumeratePhysicalDevices(vk_instance
, &count
, NULL
)) < 0)
177 WARN("Failed to get device count, vr %d.\n", vr
);
178 return VK_NULL_HANDLE
;
182 WARN("No physical device available.\n");
183 return VK_NULL_HANDLE
;
186 if (!(vk_physical_devices
= calloc(count
, sizeof(*vk_physical_devices
))))
187 return VK_NULL_HANDLE
;
189 if ((vr
= pfn_vkEnumeratePhysicalDevices(vk_instance
, &count
, vk_physical_devices
)) < 0)
192 if (!IsEqualGUID(&adapter_info
->driver_uuid
, &GUID_NULL
) && pfn_vkGetPhysicalDeviceProperties2
193 && check_vk_instance_extension(vk_instance
, pfn_vkGetInstanceProcAddr
,
194 VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME
))
196 TRACE("Matching adapters by UUIDs.\n");
198 for (i
= 0; i
< count
; ++i
)
200 memset(&id_properties
, 0, sizeof(id_properties
));
201 id_properties
.sType
= VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES
;
203 properties2
.sType
= VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2
;
204 properties2
.pNext
= &id_properties
;
206 pfn_vkGetPhysicalDeviceProperties2(vk_physical_devices
[i
], &properties2
);
208 if (!memcmp(id_properties
.driverUUID
, &adapter_info
->driver_uuid
, VK_UUID_SIZE
)
209 && !memcmp(id_properties
.deviceUUID
, &adapter_info
->device_uuid
, VK_UUID_SIZE
))
211 vk_physical_device
= vk_physical_devices
[i
];
217 if (!vk_physical_device
)
219 WARN("Matching adapters by PCI IDs.\n");
221 for (i
= 0; i
< count
; ++i
)
223 pfn_vkGetPhysicalDeviceProperties(vk_physical_devices
[i
], &properties
);
225 if (properties
.vendorID
== adapter_info
->vendor_id
&& properties
.deviceID
== adapter_info
->device_id
)
227 vk_physical_device
= vk_physical_devices
[i
];
233 if (!vk_physical_device
)
234 FIXME("Could not find Vulkan physical device for DXGI adapter.\n");
237 free(vk_physical_devices
);
238 return vk_physical_device
;
241 HRESULT WINAPI
D3D12CreateDevice(IUnknown
*adapter
, D3D_FEATURE_LEVEL minimum_feature_level
,
242 REFIID iid
, void **device
)
244 struct vkd3d_optional_instance_extensions_info optional_extensions_info
;
245 struct vkd3d_instance_create_info instance_create_info
;
246 PFN_vkGetInstanceProcAddr pfn_vkGetInstanceProcAddr
;
247 struct vkd3d_device_create_info device_create_info
;
248 struct wine_dxgi_adapter_info adapter_info
;
249 struct vkd3d_instance
*instance
;
250 IWineDXGIAdapter
*wine_adapter
;
253 static const char * const instance_extensions
[] =
255 VK_KHR_SURFACE_EXTENSION_NAME
,
256 VK_KHR_WIN32_SURFACE_EXTENSION_NAME
,
258 static const char * const optional_instance_extensions
[] =
260 VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME
,
261 VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME
,
263 static const char * const device_extensions
[] =
265 VK_KHR_SWAPCHAIN_EXTENSION_NAME
,
267 static const struct vkd3d_application_info application_info
=
269 .type
= VKD3D_STRUCTURE_TYPE_APPLICATION_INFO
,
270 .api_version
= VKD3D_API_VERSION_1_2
,
273 TRACE("adapter %p, minimum_feature_level %#x, iid %s, device %p.\n",
274 adapter
, minimum_feature_level
, debugstr_guid(iid
), device
);
276 if (!(pfn_vkGetInstanceProcAddr
= load_vulkan()))
278 ERR_(winediag
)("Failed to load Vulkan library.\n");
282 if (FAILED(hr
= d3d12_get_adapter(&wine_adapter
, adapter
)))
285 if (FAILED(hr
= IWineDXGIAdapter_get_adapter_info(wine_adapter
, &adapter_info
)))
287 WARN("Failed to get adapter info, hr %#lx.\n", hr
);
291 optional_extensions_info
.type
= VKD3D_STRUCTURE_TYPE_OPTIONAL_INSTANCE_EXTENSIONS_INFO
;
292 optional_extensions_info
.next
= &application_info
;
293 optional_extensions_info
.extensions
= optional_instance_extensions
;
294 optional_extensions_info
.extension_count
= ARRAY_SIZE(optional_instance_extensions
);
296 instance_create_info
.type
= VKD3D_STRUCTURE_TYPE_INSTANCE_CREATE_INFO
;
297 instance_create_info
.next
= &optional_extensions_info
;
298 instance_create_info
.pfn_signal_event
= d3d12_signal_event
;
299 instance_create_info
.pfn_create_thread
= NULL
;
300 instance_create_info
.pfn_join_thread
= NULL
;
301 instance_create_info
.wchar_size
= sizeof(WCHAR
);
302 instance_create_info
.pfn_vkGetInstanceProcAddr
= pfn_vkGetInstanceProcAddr
;
303 instance_create_info
.instance_extensions
= instance_extensions
;
304 instance_create_info
.instance_extension_count
= ARRAY_SIZE(instance_extensions
);
306 if (FAILED(hr
= vkd3d_create_instance(&instance_create_info
, &instance
)))
308 WARN("Failed to create vkd3d instance, hr %#lx.\n", hr
);
312 device_create_info
.type
= VKD3D_STRUCTURE_TYPE_DEVICE_CREATE_INFO
;
313 device_create_info
.next
= NULL
;
314 device_create_info
.minimum_feature_level
= minimum_feature_level
;
315 device_create_info
.instance
= instance
;
316 device_create_info
.instance_create_info
= NULL
;
317 device_create_info
.vk_physical_device
= d3d12_get_vk_physical_device(instance
, pfn_vkGetInstanceProcAddr
, &adapter_info
);
318 device_create_info
.device_extensions
= device_extensions
;
319 device_create_info
.device_extension_count
= ARRAY_SIZE(device_extensions
);
320 device_create_info
.parent
= (IUnknown
*)wine_adapter
;
321 device_create_info
.adapter_luid
= adapter_info
.luid
;
323 hr
= vkd3d_create_device(&device_create_info
, iid
, device
);
325 vkd3d_instance_decref(instance
);
328 IWineDXGIAdapter_Release(wine_adapter
);
332 HRESULT WINAPI
D3D12CreateRootSignatureDeserializer(const void *data
, SIZE_T data_size
,
333 REFIID iid
, void **deserializer
)
335 TRACE("data %p, data_size %Iu, iid %s, deserializer %p.\n",
336 data
, data_size
, debugstr_guid(iid
), deserializer
);
338 return vkd3d_create_root_signature_deserializer(data
, data_size
, iid
, deserializer
);
341 HRESULT WINAPI
D3D12CreateVersionedRootSignatureDeserializer(const void *data
, SIZE_T data_size
,
342 REFIID iid
, void **deserializer
)
344 TRACE("data %p, data_size %Iu, iid %s, deserializer %p.\n",
345 data
, data_size
, debugstr_guid(iid
), deserializer
);
347 return vkd3d_create_versioned_root_signature_deserializer(data
, data_size
, iid
, deserializer
);
350 HRESULT WINAPI
D3D12SerializeRootSignature(const D3D12_ROOT_SIGNATURE_DESC
*root_signature_desc
,
351 D3D_ROOT_SIGNATURE_VERSION version
, ID3DBlob
**blob
, ID3DBlob
**error_blob
)
353 TRACE("root_signature_desc %p, version %#x, blob %p, error_blob %p.\n",
354 root_signature_desc
, version
, blob
, error_blob
);
356 return vkd3d_serialize_root_signature(root_signature_desc
, version
, blob
, error_blob
);
359 HRESULT WINAPI
D3D12SerializeVersionedRootSignature(const D3D12_VERSIONED_ROOT_SIGNATURE_DESC
*desc
,
360 ID3DBlob
**blob
, ID3DBlob
**error_blob
)
362 TRACE("desc %p, blob %p, error_blob %p.\n", desc
, blob
, error_blob
);
364 return vkd3d_serialize_versioned_root_signature(desc
, blob
, error_blob
);