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 #include "wine/port.h"
24 #define VK_NO_PROTOTYPES
25 #define VKD3D_NO_VULKAN_H
26 #define VKD3D_NO_WIN32_TYPES
27 #ifndef USE_WIN32_VULKAN
31 #include "wine/debug.h"
32 #include "wine/heap.h"
33 #include "wine/vulkan.h"
34 #include "wine/vulkan_driver.h"
42 #include "wine/wined3d.h"
43 #include "wine/winedxgi.h"
45 WINE_DEFAULT_DEBUG_CHANNEL(d3d12
);
46 WINE_DECLARE_DEBUG_CHANNEL(winediag
);
48 #ifdef USE_WIN32_VULKAN
50 static HMODULE vulkan_module
;
52 /* FIXME: We should unload vulkan-1.dll. */
53 static BOOL WINAPI
load_vulkan_dll_once(INIT_ONCE
*once
, void *param
, void **context
)
55 vulkan_module
= LoadLibraryA("vulkan-1.dll");
59 static PFN_vkGetInstanceProcAddr
load_vulkan(void)
61 static INIT_ONCE init_once
= INIT_ONCE_STATIC_INIT
;
63 InitOnceExecuteOnce(&init_once
, load_vulkan_dll_once
, NULL
, NULL
);
66 return (void *)GetProcAddress(vulkan_module
, "vkGetInstanceProcAddr");
73 static PFN_vkGetInstanceProcAddr
load_vulkan(void)
75 const struct vulkan_funcs
*vk_funcs
;
79 vk_funcs
= __wine_get_vulkan_driver(hdc
, WINE_VULKAN_DRIVER_VERSION
);
83 return (PFN_vkGetInstanceProcAddr
)vk_funcs
->p_vkGetInstanceProcAddr
;
88 #endif /* USE_WIN32_VULKAN */
90 HRESULT WINAPI
D3D12GetDebugInterface(REFIID iid
, void **debug
)
92 TRACE("iid %s, debug %p.\n", debugstr_guid(iid
), debug
);
94 WARN("Returning DXGI_ERROR_SDK_COMPONENT_MISSING.\n");
95 return DXGI_ERROR_SDK_COMPONENT_MISSING
;
98 HRESULT WINAPI
D3D12EnableExperimentalFeatures(UINT feature_count
,
99 const IID
*iids
, void *configurations
, UINT
*configurations_sizes
)
101 FIXME("feature_count %u, iids %p, configurations %p, configurations_sizes %p stub!\n",
102 feature_count
, iids
, configurations
, configurations_sizes
);
104 return E_NOINTERFACE
;
107 static HRESULT
d3d12_signal_event(HANDLE event
)
109 return SetEvent(event
) ? S_OK
: E_FAIL
;
112 struct d3d12_thread_data
114 PFN_vkd3d_thread main_pfn
;
118 static DWORD WINAPI
d3d12_thread_main(void *data
)
120 struct d3d12_thread_data
*thread_data
= data
;
122 thread_data
->main_pfn(thread_data
->data
);
123 heap_free(thread_data
);
127 static void *d3d12_create_thread(PFN_vkd3d_thread main_pfn
, void *data
)
129 struct d3d12_thread_data
*thread_data
;
132 if (!(thread_data
= heap_alloc(sizeof(*thread_data
))))
134 ERR("Failed to allocate thread data.\n");
138 thread_data
->main_pfn
= main_pfn
;
139 thread_data
->data
= data
;
141 if (!(thread
= CreateThread(NULL
, 0, d3d12_thread_main
, thread_data
, 0, NULL
)))
142 heap_free(thread_data
);
147 static HRESULT
d3d12_join_thread(void *handle
)
149 HANDLE thread
= handle
;
152 if ((ret
= WaitForSingleObject(thread
, INFINITE
)) != WAIT_OBJECT_0
)
153 ERR("Failed to wait for thread, ret %#x.\n", ret
);
155 return ret
== WAIT_OBJECT_0
? S_OK
: E_FAIL
;
158 static HRESULT
d3d12_get_adapter(IWineDXGIAdapter
**wine_adapter
, IUnknown
*adapter
)
160 IDXGIAdapter
*dxgi_adapter
= NULL
;
161 IDXGIFactory4
*factory
= NULL
;
166 if (FAILED(hr
= CreateDXGIFactory2(0, &IID_IDXGIFactory4
, (void **)&factory
)))
168 WARN("Failed to create DXGI factory, hr %#x.\n", hr
);
172 if (FAILED(hr
= IDXGIFactory4_EnumAdapters(factory
, 0, &dxgi_adapter
)))
174 WARN("Failed to enumerate primary adapter, hr %#x.\n", hr
);
178 adapter
= (IUnknown
*)dxgi_adapter
;
181 if (FAILED(hr
= IUnknown_QueryInterface(adapter
, &IID_IWineDXGIAdapter
, (void **)wine_adapter
)))
182 WARN("Invalid adapter %p, hr %#x.\n", adapter
, hr
);
186 IDXGIAdapter_Release(dxgi_adapter
);
188 IDXGIFactory4_Release(factory
);
193 static BOOL
check_vk_instance_extension(VkInstance vk_instance
,
194 PFN_vkGetInstanceProcAddr pfn_vkGetInstanceProcAddr
, const char *name
)
196 PFN_vkEnumerateInstanceExtensionProperties pfn_vkEnumerateInstanceExtensionProperties
;
197 VkExtensionProperties
*properties
;
202 pfn_vkEnumerateInstanceExtensionProperties
203 = (void *)pfn_vkGetInstanceProcAddr(vk_instance
, "vkEnumerateInstanceExtensionProperties");
205 if (pfn_vkEnumerateInstanceExtensionProperties(NULL
, &count
, NULL
) < 0)
208 if (!(properties
= heap_calloc(count
, sizeof(*properties
))))
211 if (pfn_vkEnumerateInstanceExtensionProperties(NULL
, &count
, properties
) >= 0)
213 for (i
= 0; i
< count
; ++i
)
215 if (!strcmp(properties
[i
].extensionName
, name
))
223 heap_free(properties
);
227 static VkPhysicalDevice
d3d12_get_vk_physical_device(struct vkd3d_instance
*instance
,
228 PFN_vkGetInstanceProcAddr pfn_vkGetInstanceProcAddr
, const struct wine_dxgi_adapter_info
*adapter_info
)
230 PFN_vkGetPhysicalDeviceProperties2 pfn_vkGetPhysicalDeviceProperties2
= NULL
;
231 PFN_vkGetPhysicalDeviceProperties pfn_vkGetPhysicalDeviceProperties
;
232 PFN_vkEnumeratePhysicalDevices pfn_vkEnumeratePhysicalDevices
;
233 VkPhysicalDevice vk_physical_device
= VK_NULL_HANDLE
;
234 VkPhysicalDeviceIDProperties id_properties
;
235 VkPhysicalDeviceProperties2 properties2
;
236 VkPhysicalDeviceProperties properties
;
237 VkPhysicalDevice
*vk_physical_devices
;
238 VkInstance vk_instance
;
243 vk_instance
= vkd3d_instance_get_vk_instance(instance
);
245 pfn_vkEnumeratePhysicalDevices
= (void *)pfn_vkGetInstanceProcAddr(vk_instance
, "vkEnumeratePhysicalDevices");
247 pfn_vkGetPhysicalDeviceProperties
= (void *)pfn_vkGetInstanceProcAddr(vk_instance
, "vkGetPhysicalDeviceProperties");
248 if (check_vk_instance_extension(vk_instance
, pfn_vkGetInstanceProcAddr
, VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME
))
249 pfn_vkGetPhysicalDeviceProperties2
= (void *)pfn_vkGetInstanceProcAddr(vk_instance
, "vkGetPhysicalDeviceProperties2KHR");
251 if ((vr
= pfn_vkEnumeratePhysicalDevices(vk_instance
, &count
, NULL
)) < 0)
253 WARN("Failed to get device count, vr %d.\n", vr
);
254 return VK_NULL_HANDLE
;
258 WARN("No physical device available.\n");
259 return VK_NULL_HANDLE
;
262 if (!(vk_physical_devices
= heap_calloc(count
, sizeof(*vk_physical_devices
))))
263 return VK_NULL_HANDLE
;
265 if ((vr
= pfn_vkEnumeratePhysicalDevices(vk_instance
, &count
, vk_physical_devices
)) < 0)
268 if (!IsEqualGUID(&adapter_info
->driver_uuid
, &GUID_NULL
) && pfn_vkGetPhysicalDeviceProperties2
)
270 TRACE("Matching adapters by UUIDs.\n");
272 for (i
= 0; i
< count
; ++i
)
274 memset(&id_properties
, 0, sizeof(id_properties
));
275 id_properties
.sType
= VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES
;
277 properties2
.sType
= VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2
;
278 properties2
.pNext
= &id_properties
;
280 pfn_vkGetPhysicalDeviceProperties2(vk_physical_devices
[i
], &properties2
);
282 if (!memcmp(id_properties
.driverUUID
, &adapter_info
->driver_uuid
, VK_UUID_SIZE
)
283 && !memcmp(id_properties
.deviceUUID
, &adapter_info
->device_uuid
, VK_UUID_SIZE
))
285 vk_physical_device
= vk_physical_devices
[i
];
291 if (!vk_physical_device
)
293 WARN("Matching adapters by PCI IDs.\n");
295 for (i
= 0; i
< count
; ++i
)
297 pfn_vkGetPhysicalDeviceProperties(vk_physical_devices
[i
], &properties
);
299 if (properties
.vendorID
== adapter_info
->vendor_id
&& properties
.deviceID
== adapter_info
->device_id
)
301 vk_physical_device
= vk_physical_devices
[i
];
307 if (!vk_physical_device
)
308 FIXME("Could not find Vulkan physical device for DXGI adapter.\n");
311 heap_free(vk_physical_devices
);
312 return vk_physical_device
;
315 HRESULT WINAPI
D3D12CreateDevice(IUnknown
*adapter
, D3D_FEATURE_LEVEL minimum_feature_level
,
316 REFIID iid
, void **device
)
318 struct vkd3d_optional_instance_extensions_info optional_extensions_info
;
319 struct vkd3d_instance_create_info instance_create_info
;
320 PFN_vkGetInstanceProcAddr pfn_vkGetInstanceProcAddr
;
321 struct vkd3d_device_create_info device_create_info
;
322 struct wine_dxgi_adapter_info adapter_info
;
323 struct vkd3d_instance
*instance
;
324 IWineDXGIAdapter
*wine_adapter
;
327 static const char * const instance_extensions
[] =
329 VK_KHR_SURFACE_EXTENSION_NAME
,
330 VK_KHR_WIN32_SURFACE_EXTENSION_NAME
,
332 static const char * const optional_instance_extensions
[] =
334 VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME
,
336 static const char * const device_extensions
[] =
338 VK_KHR_SWAPCHAIN_EXTENSION_NAME
,
341 TRACE("adapter %p, minimum_feature_level %#x, iid %s, device %p.\n",
342 adapter
, minimum_feature_level
, debugstr_guid(iid
), device
);
344 if (!(pfn_vkGetInstanceProcAddr
= load_vulkan()))
346 ERR_(winediag
)("Failed to load Vulkan library.\n");
350 if (FAILED(hr
= d3d12_get_adapter(&wine_adapter
, adapter
)))
353 if (FAILED(hr
= IWineDXGIAdapter_get_adapter_info(wine_adapter
, &adapter_info
)))
355 WARN("Failed to get adapter info, hr %#x.\n", hr
);
359 optional_extensions_info
.type
= VKD3D_STRUCTURE_TYPE_OPTIONAL_INSTANCE_EXTENSIONS_INFO
;
360 optional_extensions_info
.next
= NULL
;
361 optional_extensions_info
.extensions
= optional_instance_extensions
;
362 optional_extensions_info
.extension_count
= ARRAY_SIZE(optional_instance_extensions
);
364 instance_create_info
.type
= VKD3D_STRUCTURE_TYPE_INSTANCE_CREATE_INFO
;
365 instance_create_info
.next
= &optional_extensions_info
;
366 instance_create_info
.pfn_signal_event
= d3d12_signal_event
;
367 instance_create_info
.pfn_create_thread
= d3d12_create_thread
;
368 instance_create_info
.pfn_join_thread
= d3d12_join_thread
;
369 instance_create_info
.wchar_size
= sizeof(WCHAR
);
370 instance_create_info
.pfn_vkGetInstanceProcAddr
= pfn_vkGetInstanceProcAddr
;
371 instance_create_info
.instance_extensions
= instance_extensions
;
372 instance_create_info
.instance_extension_count
= ARRAY_SIZE(instance_extensions
);
374 if (FAILED(hr
= vkd3d_create_instance(&instance_create_info
, &instance
)))
376 WARN("Failed to create vkd3d instance, hr %#x.\n", hr
);
380 device_create_info
.type
= VKD3D_STRUCTURE_TYPE_DEVICE_CREATE_INFO
;
381 device_create_info
.next
= NULL
;
382 device_create_info
.minimum_feature_level
= minimum_feature_level
;
383 device_create_info
.instance
= instance
;
384 device_create_info
.instance_create_info
= NULL
;
385 device_create_info
.vk_physical_device
= d3d12_get_vk_physical_device(instance
, pfn_vkGetInstanceProcAddr
, &adapter_info
);
386 device_create_info
.device_extensions
= device_extensions
;
387 device_create_info
.device_extension_count
= ARRAY_SIZE(device_extensions
);
388 device_create_info
.parent
= (IUnknown
*)wine_adapter
;
389 device_create_info
.adapter_luid
= adapter_info
.luid
;
391 hr
= vkd3d_create_device(&device_create_info
, iid
, device
);
393 vkd3d_instance_decref(instance
);
396 IWineDXGIAdapter_Release(wine_adapter
);
400 HRESULT WINAPI
D3D12CreateRootSignatureDeserializer(const void *data
, SIZE_T data_size
,
401 REFIID iid
, void **deserializer
)
403 TRACE("data %p, data_size %lu, iid %s, deserializer %p.\n",
404 data
, data_size
, debugstr_guid(iid
), deserializer
);
406 return vkd3d_create_root_signature_deserializer(data
, data_size
, iid
, deserializer
);
409 HRESULT WINAPI
D3D12SerializeRootSignature(const D3D12_ROOT_SIGNATURE_DESC
*root_signature_desc
,
410 D3D_ROOT_SIGNATURE_VERSION version
, ID3DBlob
**blob
, ID3DBlob
**error_blob
)
412 TRACE("root_signature_desc %p, version %#x, blob %p, error_blob %p.\n",
413 root_signature_desc
, version
, blob
, error_blob
);
415 return vkd3d_serialize_root_signature(root_signature_desc
, version
, blob
, error_blob
);
418 HRESULT WINAPI
D3D12SerializeVersionedRootSignature(const D3D12_VERSIONED_ROOT_SIGNATURE_DESC
*desc
,
419 ID3DBlob
**blob
, ID3DBlob
**error_blob
)
421 TRACE("desc %p, blob %p, error_blob %p.\n", desc
, blob
, error_blob
);
423 if (desc
->Version
== D3D_ROOT_SIGNATURE_VERSION_1_0
)
424 return vkd3d_serialize_root_signature(&desc
->Desc_1_0
, desc
->Version
, blob
, error_blob
);
426 FIXME("Unsupported version %#x.\n", desc
->Version
);