wined3d: Implement GPU description registry override for Vulkan adapter.
[wine.git] / dlls / wined3d / adapter_vk.c
blob3709c940c984409d7b5cb3425336a3713b387faa
1 /*
2 * Copyright 2018 Henri Verbeet 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
19 #include "config.h"
20 #include "wine/port.h"
21 #include "wined3d_private.h"
23 #include "wine/vulkan_driver.h"
25 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
27 struct wined3d_device_vk
29 struct wined3d_device d;
31 VkDevice vk_device;
32 VkQueue vk_queue;
34 struct wined3d_vk_info vk_info;
37 static inline struct wined3d_device_vk *wined3d_device_vk(struct wined3d_device *device)
39 return CONTAINING_RECORD(device, struct wined3d_device_vk, d);
42 static inline const struct wined3d_adapter_vk *wined3d_adapter_vk_const(const struct wined3d_adapter *adapter)
44 return CONTAINING_RECORD(adapter, struct wined3d_adapter_vk, a);
47 static const char *debug_vk_version(uint32_t version)
49 return wine_dbg_sprintf("%u.%u.%u",
50 VK_VERSION_MAJOR(version), VK_VERSION_MINOR(version), VK_VERSION_PATCH(version));
53 static HRESULT hresult_from_vk_result(VkResult vr)
55 switch (vr)
57 case VK_SUCCESS:
58 return S_OK;
59 case VK_ERROR_OUT_OF_HOST_MEMORY:
60 WARN("Out of host memory.\n");
61 return E_OUTOFMEMORY;
62 case VK_ERROR_OUT_OF_DEVICE_MEMORY:
63 WARN("Out of device memory.\n");
64 return E_OUTOFMEMORY;
65 case VK_ERROR_DEVICE_LOST:
66 WARN("Device lost.\n");
67 return E_FAIL;
68 case VK_ERROR_EXTENSION_NOT_PRESENT:
69 WARN("Extension not present.\n");
70 return E_FAIL;
71 default:
72 FIXME("Unhandled VkResult %d.\n", vr);
73 return E_FAIL;
77 #ifdef USE_WIN32_VULKAN
78 static BOOL wined3d_load_vulkan(struct wined3d_vk_info *vk_info)
80 struct vulkan_ops *vk_ops = &vk_info->vk_ops;
82 if (!(vk_info->vulkan_lib = LoadLibraryA("vulkan-1.dll")))
84 WARN("Failed to load vulkan-1.dll.\n");
85 return FALSE;
88 vk_ops->vkGetInstanceProcAddr = (void *)GetProcAddress(vk_info->vulkan_lib, "vkGetInstanceProcAddr");
89 if (!vk_ops->vkGetInstanceProcAddr)
91 FreeLibrary(vk_info->vulkan_lib);
92 return FALSE;
95 return TRUE;
98 static void wined3d_unload_vulkan(struct wined3d_vk_info *vk_info)
100 if (vk_info->vulkan_lib)
102 FreeLibrary(vk_info->vulkan_lib);
103 vk_info->vulkan_lib = NULL;
106 #else
107 static BOOL wined3d_load_vulkan(struct wined3d_vk_info *vk_info)
109 struct vulkan_ops *vk_ops = &vk_info->vk_ops;
110 const struct vulkan_funcs *vk_funcs;
111 HDC dc;
113 dc = GetDC(0);
114 vk_funcs = __wine_get_vulkan_driver(dc, WINE_VULKAN_DRIVER_VERSION);
115 ReleaseDC(0, dc);
117 if (!vk_funcs)
118 return FALSE;
120 vk_ops->vkGetInstanceProcAddr = (void *)vk_funcs->p_vkGetInstanceProcAddr;
121 return TRUE;
124 static void wined3d_unload_vulkan(struct wined3d_vk_info *vk_info) {}
125 #endif
127 static void adapter_vk_destroy(struct wined3d_adapter *adapter)
129 struct wined3d_adapter_vk *adapter_vk = wined3d_adapter_vk(adapter);
130 struct wined3d_vk_info *vk_info = &adapter_vk->vk_info;
132 VK_CALL(vkDestroyInstance(vk_info->instance, NULL));
133 wined3d_unload_vulkan(vk_info);
134 wined3d_adapter_cleanup(&adapter_vk->a);
135 heap_free(adapter_vk);
138 static HRESULT wined3d_select_vulkan_queue_family(const struct wined3d_adapter_vk *adapter_vk,
139 uint32_t *queue_family_index)
141 VkPhysicalDevice physical_device = adapter_vk->physical_device;
142 const struct wined3d_vk_info *vk_info = &adapter_vk->vk_info;
143 VkQueueFamilyProperties *queue_properties;
144 uint32_t count, i;
146 VK_CALL(vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &count, NULL));
148 if (!(queue_properties = heap_calloc(count, sizeof(*queue_properties))))
149 return E_OUTOFMEMORY;
151 VK_CALL(vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &count, queue_properties));
153 for (i = 0; i < count; ++i)
155 if (queue_properties[i].queueFlags & VK_QUEUE_GRAPHICS_BIT)
157 *queue_family_index = i;
158 heap_free(queue_properties);
159 return WINED3D_OK;
162 heap_free(queue_properties);
164 WARN("Failed to find graphics queue.\n");
165 return E_FAIL;
168 static void wined3d_disable_vulkan_features(VkPhysicalDeviceFeatures *features)
170 features->depthBounds = VK_FALSE;
171 features->alphaToOne = VK_FALSE;
172 features->textureCompressionETC2 = VK_FALSE;
173 features->textureCompressionASTC_LDR = VK_FALSE;
174 features->shaderStorageImageMultisample = VK_FALSE;
175 features->shaderUniformBufferArrayDynamicIndexing = VK_FALSE;
176 features->shaderSampledImageArrayDynamicIndexing = VK_FALSE;
177 features->shaderStorageBufferArrayDynamicIndexing = VK_FALSE;
178 features->shaderStorageImageArrayDynamicIndexing = VK_FALSE;
179 features->shaderInt16 = VK_FALSE;
180 features->shaderResourceResidency = VK_FALSE;
181 features->shaderResourceMinLod = VK_FALSE;
182 features->sparseBinding = VK_FALSE;
183 features->sparseResidencyBuffer = VK_FALSE;
184 features->sparseResidencyImage2D = VK_FALSE;
185 features->sparseResidencyImage3D = VK_FALSE;
186 features->sparseResidency2Samples = VK_FALSE;
187 features->sparseResidency4Samples = VK_FALSE;
188 features->sparseResidency8Samples = VK_FALSE;
189 features->sparseResidency16Samples = VK_FALSE;
190 features->sparseResidencyAliased = VK_FALSE;
191 features->inheritedQueries = VK_FALSE;
194 static HRESULT adapter_vk_create_device(struct wined3d *wined3d, const struct wined3d_adapter *adapter,
195 enum wined3d_device_type device_type, HWND focus_window, unsigned int flags, BYTE surface_alignment,
196 const enum wined3d_feature_level *levels, unsigned int level_count,
197 struct wined3d_device_parent *device_parent, struct wined3d_device **device)
199 const struct wined3d_adapter_vk *adapter_vk = wined3d_adapter_vk_const(adapter);
200 const struct wined3d_vk_info *vk_info = &adapter_vk->vk_info;
201 static const float priorities[] = {1.0f};
202 struct wined3d_device_vk *device_vk;
203 VkDevice vk_device = VK_NULL_HANDLE;
204 VkDeviceQueueCreateInfo queue_info;
205 VkPhysicalDeviceFeatures features;
206 VkPhysicalDevice physical_device;
207 VkDeviceCreateInfo device_info;
208 uint32_t queue_family_index;
209 VkResult vr;
210 HRESULT hr;
212 if (!(device_vk = heap_alloc_zero(sizeof(*device_vk))))
213 return E_OUTOFMEMORY;
215 if (FAILED(hr = wined3d_select_vulkan_queue_family(adapter_vk, &queue_family_index)))
216 goto fail;
218 physical_device = adapter_vk->physical_device;
220 VK_CALL(vkGetPhysicalDeviceFeatures(physical_device, &features));
221 wined3d_disable_vulkan_features(&features);
223 queue_info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
224 queue_info.pNext = NULL;
225 queue_info.flags = 0;
226 queue_info.queueFamilyIndex = queue_family_index;
227 queue_info.queueCount = ARRAY_SIZE(priorities);
228 queue_info.pQueuePriorities = priorities;
230 device_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
231 device_info.pNext = NULL;
232 device_info.flags = 0;
233 device_info.queueCreateInfoCount = 1;
234 device_info.pQueueCreateInfos = &queue_info;
235 device_info.enabledLayerCount = 0;
236 device_info.ppEnabledLayerNames = NULL;
237 device_info.enabledExtensionCount = 0;
238 device_info.ppEnabledExtensionNames = NULL;
239 device_info.pEnabledFeatures = &features;
241 if ((vr = VK_CALL(vkCreateDevice(physical_device, &device_info, NULL, &vk_device))) < 0)
243 WARN("Failed to create Vulkan device, vr %d.\n", vr);
244 vk_device = VK_NULL_HANDLE;
245 hr = hresult_from_vk_result(vr);
246 goto fail;
249 device_vk->vk_device = vk_device;
250 VK_CALL(vkGetDeviceQueue(vk_device, queue_family_index, 0, &device_vk->vk_queue));
252 device_vk->vk_info = *vk_info;
253 #define LOAD_DEVICE_PFN(name) \
254 if (!(device_vk->vk_info.vk_ops.name = (void *)VK_CALL(vkGetDeviceProcAddr(vk_device, #name)))) \
256 WARN("Could not get device proc addr for '" #name "'.\n"); \
257 hr = E_FAIL; \
258 goto fail; \
260 #define VK_DEVICE_PFN LOAD_DEVICE_PFN
261 VK_DEVICE_FUNCS()
262 #undef VK_DEVICE_PFN
264 if (FAILED(hr = wined3d_device_init(&device_vk->d, wined3d, adapter->ordinal, device_type,
265 focus_window, flags, surface_alignment, levels, level_count, device_parent)))
267 WARN("Failed to initialize device, hr %#x.\n", hr);
268 goto fail;
271 return WINED3D_OK;
273 fail:
274 VK_CALL(vkDestroyDevice(vk_device, NULL));
275 heap_free(device_vk);
276 return hr;
279 static void adapter_vk_destroy_device(struct wined3d_device *device)
281 struct wined3d_device_vk *device_vk = wined3d_device_vk(device);
282 const struct wined3d_vk_info *vk_info = &device_vk->vk_info;
284 wined3d_device_cleanup(&device_vk->d);
285 VK_CALL(vkDestroyDevice(device_vk->vk_device, NULL));
286 heap_free(device_vk);
289 static BOOL adapter_vk_create_context(struct wined3d_context *context,
290 struct wined3d_texture *target, const struct wined3d_format *ds_format)
292 return TRUE;
295 static void adapter_vk_get_wined3d_caps(const struct wined3d_adapter *adapter, struct wined3d_caps *caps)
297 const struct wined3d_adapter_vk *adapter_vk = wined3d_adapter_vk_const(adapter);
298 const VkPhysicalDeviceLimits *limits = &adapter_vk->device_limits;
299 BOOL sampler_anisotropy = limits->maxSamplerAnisotropy > 1.0f;
301 caps->ddraw_caps.dds_caps |= WINEDDSCAPS_3DDEVICE
302 | WINEDDSCAPS_MIPMAP
303 | WINEDDSCAPS_TEXTURE
304 | WINEDDSCAPS_VIDEOMEMORY
305 | WINEDDSCAPS_ZBUFFER;
306 caps->ddraw_caps.caps |= WINEDDCAPS_3D;
308 caps->Caps2 |= WINED3DCAPS2_CANGENMIPMAP;
310 caps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_BLENDOP
311 | WINED3DPMISCCAPS_SEPARATEALPHABLEND
312 | WINED3DPMISCCAPS_INDEPENDENTWRITEMASKS
313 | WINED3DPMISCCAPS_POSTBLENDSRGBCONVERT;
315 if (sampler_anisotropy)
317 caps->RasterCaps |= WINED3DPRASTERCAPS_ANISOTROPY
318 | WINED3DPRASTERCAPS_ZBIAS
319 | WINED3DPRASTERCAPS_MIPMAPLODBIAS;
321 caps->TextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC
322 | WINED3DPTFILTERCAPS_MINFANISOTROPIC;
324 caps->MaxAnisotropy = limits->maxSamplerAnisotropy;
327 caps->SrcBlendCaps |= WINED3DPBLENDCAPS_BLENDFACTOR;
328 caps->DestBlendCaps |= WINED3DPBLENDCAPS_BLENDFACTOR
329 | WINED3DPBLENDCAPS_SRCALPHASAT;
331 caps->TextureCaps |= WINED3DPTEXTURECAPS_VOLUMEMAP
332 | WINED3DPTEXTURECAPS_MIPVOLUMEMAP
333 | WINED3DPTEXTURECAPS_VOLUMEMAP_POW2;
334 caps->VolumeTextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFLINEAR
335 | WINED3DPTFILTERCAPS_MAGFPOINT
336 | WINED3DPTFILTERCAPS_MINFLINEAR
337 | WINED3DPTFILTERCAPS_MINFPOINT
338 | WINED3DPTFILTERCAPS_MIPFLINEAR
339 | WINED3DPTFILTERCAPS_MIPFPOINT
340 | WINED3DPTFILTERCAPS_LINEAR
341 | WINED3DPTFILTERCAPS_LINEARMIPLINEAR
342 | WINED3DPTFILTERCAPS_LINEARMIPNEAREST
343 | WINED3DPTFILTERCAPS_MIPLINEAR
344 | WINED3DPTFILTERCAPS_MIPNEAREST
345 | WINED3DPTFILTERCAPS_NEAREST;
346 caps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_INDEPENDENTUV
347 | WINED3DPTADDRESSCAPS_CLAMP
348 | WINED3DPTADDRESSCAPS_WRAP;
349 caps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER
350 | WINED3DPTADDRESSCAPS_MIRROR
351 | WINED3DPTADDRESSCAPS_MIRRORONCE;
353 caps->MaxVolumeExtent = limits->maxImageDimension3D;
355 caps->TextureCaps |= WINED3DPTEXTURECAPS_CUBEMAP
356 | WINED3DPTEXTURECAPS_MIPCUBEMAP
357 | WINED3DPTEXTURECAPS_CUBEMAP_POW2;
358 caps->CubeTextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFLINEAR
359 | WINED3DPTFILTERCAPS_MAGFPOINT
360 | WINED3DPTFILTERCAPS_MINFLINEAR
361 | WINED3DPTFILTERCAPS_MINFPOINT
362 | WINED3DPTFILTERCAPS_MIPFLINEAR
363 | WINED3DPTFILTERCAPS_MIPFPOINT
364 | WINED3DPTFILTERCAPS_LINEAR
365 | WINED3DPTFILTERCAPS_LINEARMIPLINEAR
366 | WINED3DPTFILTERCAPS_LINEARMIPNEAREST
367 | WINED3DPTFILTERCAPS_MIPLINEAR
368 | WINED3DPTFILTERCAPS_MIPNEAREST
369 | WINED3DPTFILTERCAPS_NEAREST;
371 if (sampler_anisotropy)
373 caps->CubeTextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC
374 | WINED3DPTFILTERCAPS_MINFANISOTROPIC;
377 caps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER
378 | WINED3DPTADDRESSCAPS_MIRROR
379 | WINED3DPTADDRESSCAPS_MIRRORONCE;
381 caps->StencilCaps |= WINED3DSTENCILCAPS_DECR
382 | WINED3DSTENCILCAPS_INCR
383 | WINED3DSTENCILCAPS_TWOSIDED;
385 caps->DeclTypes |= WINED3DDTCAPS_FLOAT16_2 | WINED3DDTCAPS_FLOAT16_4;
387 caps->MaxPixelShader30InstructionSlots = WINED3DMAX30SHADERINSTRUCTIONS;
388 caps->MaxVertexShader30InstructionSlots = WINED3DMAX30SHADERINSTRUCTIONS;
389 caps->PS20Caps.temp_count = WINED3DPS20_MAX_NUMTEMPS;
390 caps->VS20Caps.temp_count = WINED3DVS20_MAX_NUMTEMPS;
393 static BOOL adapter_vk_check_format(const struct wined3d_adapter *adapter,
394 const struct wined3d_format *adapter_format, const struct wined3d_format *rt_format,
395 const struct wined3d_format *ds_format)
397 return TRUE;
400 static const struct wined3d_adapter_ops wined3d_adapter_vk_ops =
402 adapter_vk_destroy,
403 adapter_vk_create_device,
404 adapter_vk_destroy_device,
405 adapter_vk_create_context,
406 adapter_vk_get_wined3d_caps,
407 adapter_vk_check_format,
410 static unsigned int wined3d_get_wine_vk_version(void)
412 const char *ptr = PACKAGE_VERSION;
413 int major, minor;
415 major = atoi(ptr);
417 while (isdigit(*ptr) || *ptr == '.')
418 ++ptr;
420 minor = atoi(ptr);
422 return VK_MAKE_VERSION(major, minor, 0);
425 static const struct
427 const char *name;
428 unsigned int core_since_version;
429 BOOL required;
431 vulkan_instance_extensions[] =
433 {VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, VK_API_VERSION_1_1, FALSE},
436 static BOOL enable_vulkan_instance_extensions(uint32_t *extension_count,
437 const char *enabled_extensions[], const struct wined3d_vk_info *vk_info)
439 PFN_vkEnumerateInstanceExtensionProperties pfn_vkEnumerateInstanceExtensionProperties;
440 VkExtensionProperties *extensions = NULL;
441 BOOL success = FALSE, found;
442 unsigned int i, j, count;
443 VkResult vr;
445 *extension_count = 0;
447 if (!(pfn_vkEnumerateInstanceExtensionProperties
448 = (void *)VK_CALL(vkGetInstanceProcAddr(NULL, "vkEnumerateInstanceExtensionProperties"))))
450 WARN("Failed to get 'vkEnumerateInstanceExtensionProperties'.\n");
451 goto done;
454 if ((vr = pfn_vkEnumerateInstanceExtensionProperties(NULL, &count, NULL)) < 0)
456 WARN("Failed to count instance extensions, vr %d.\n", vr);
457 goto done;
459 if (!(extensions = heap_calloc(count, sizeof(*extensions))))
461 WARN("Out of memory.\n");
462 goto done;
464 if ((vr = pfn_vkEnumerateInstanceExtensionProperties(NULL, &count, extensions)) < 0)
466 WARN("Failed to enumerate extensions, vr %d.\n", vr);
467 goto done;
470 for (i = 0; i < ARRAY_SIZE(vulkan_instance_extensions); ++i)
472 if (vulkan_instance_extensions[i].core_since_version <= vk_info->api_version)
473 continue;
475 for (j = 0, found = FALSE; j < count; ++j)
477 if (!strcmp(extensions[j].extensionName, vulkan_instance_extensions[i].name))
479 found = TRUE;
480 break;
483 if (found)
485 TRACE("Enabling instance extension '%s'.\n", vulkan_instance_extensions[i].name);
486 enabled_extensions[(*extension_count)++] = vulkan_instance_extensions[i].name;
488 else if (!found && vulkan_instance_extensions[i].required)
490 WARN("Required extension '%s' is not available.\n", vulkan_instance_extensions[i].name);
491 goto done;
494 success = TRUE;
496 done:
497 heap_free(extensions);
498 return success;
501 static BOOL wined3d_init_vulkan(struct wined3d_vk_info *vk_info)
503 const char *enabled_instance_extensions[ARRAY_SIZE(vulkan_instance_extensions)];
504 PFN_vkEnumerateInstanceVersion pfn_vkEnumerateInstanceVersion;
505 struct vulkan_ops *vk_ops = &vk_info->vk_ops;
506 VkInstance instance = VK_NULL_HANDLE;
507 VkInstanceCreateInfo instance_info;
508 VkApplicationInfo app_info;
509 uint32_t api_version = 0;
510 char app_name[MAX_PATH];
511 VkResult vr;
513 if (!wined3d_load_vulkan(vk_info))
514 return FALSE;
516 if (!(vk_ops->vkCreateInstance = (void *)VK_CALL(vkGetInstanceProcAddr(NULL, "vkCreateInstance"))))
518 ERR("Failed to get 'vkCreateInstance'.\n");
519 goto fail;
522 vk_info->api_version = VK_API_VERSION_1_0;
523 if ((pfn_vkEnumerateInstanceVersion = (void *)VK_CALL(vkGetInstanceProcAddr(NULL, "vkEnumerateInstanceVersion")))
524 && pfn_vkEnumerateInstanceVersion(&api_version) == VK_SUCCESS)
526 TRACE("Vulkan instance API version %s.\n", debug_vk_version(api_version));
528 if (api_version >= VK_API_VERSION_1_1)
529 vk_info->api_version = VK_API_VERSION_1_1;
532 memset(&app_info, 0, sizeof(app_info));
533 app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
534 if (wined3d_get_app_name(app_name, ARRAY_SIZE(app_name)))
535 app_info.pApplicationName = app_name;
536 app_info.pEngineName = "Damavand";
537 app_info.engineVersion = wined3d_get_wine_vk_version();
538 app_info.apiVersion = vk_info->api_version;
540 memset(&instance_info, 0, sizeof(instance_info));
541 instance_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
542 instance_info.pApplicationInfo = &app_info;
543 instance_info.ppEnabledExtensionNames = enabled_instance_extensions;
544 if (!enable_vulkan_instance_extensions(&instance_info.enabledExtensionCount, enabled_instance_extensions, vk_info))
545 goto fail;
547 if ((vr = VK_CALL(vkCreateInstance(&instance_info, NULL, &instance))) < 0)
549 WARN("Failed to create Vulkan instance, vr %d.\n", vr);
550 goto fail;
553 TRACE("Created Vulkan instance %p.\n", instance);
555 #define LOAD_INSTANCE_PFN(name) \
556 if (!(vk_ops->name = (void *)VK_CALL(vkGetInstanceProcAddr(instance, #name)))) \
558 WARN("Could not get instance proc addr for '" #name "'.\n"); \
559 goto fail; \
561 #define LOAD_INSTANCE_OPT_PFN(name) \
562 vk_ops->name = (void *)VK_CALL(vkGetInstanceProcAddr(instance, #name));
563 #define VK_INSTANCE_PFN LOAD_INSTANCE_PFN
564 #define VK_INSTANCE_EXT_PFN LOAD_INSTANCE_OPT_PFN
565 #define VK_DEVICE_PFN LOAD_INSTANCE_PFN
566 VK_INSTANCE_FUNCS()
567 VK_DEVICE_FUNCS()
568 #undef VK_INSTANCE_PFN
569 #undef VK_INSTANCE_EXT_PFN
570 #undef VK_DEVICE_PFN
572 #define MAP_INSTANCE_FUNCTION(core_pfn, ext_pfn) \
573 if (!vk_ops->core_pfn) \
574 vk_ops->core_pfn = (void *)VK_CALL(vkGetInstanceProcAddr(instance, #ext_pfn));
575 MAP_INSTANCE_FUNCTION(vkGetPhysicalDeviceProperties2, vkGetPhysicalDeviceProperties2KHR)
576 #undef MAP_INSTANCE_FUNCTION
578 vk_info->instance = instance;
580 return TRUE;
582 fail:
583 if (vk_ops->vkDestroyInstance)
584 VK_CALL(vkDestroyInstance(instance, NULL));
585 wined3d_unload_vulkan(vk_info);
586 return FALSE;
589 static VkPhysicalDevice get_vulkan_physical_device(struct wined3d_vk_info *vk_info)
591 VkPhysicalDevice physical_devices[1];
592 uint32_t count;
593 VkResult vr;
595 if ((vr = VK_CALL(vkEnumeratePhysicalDevices(vk_info->instance, &count, NULL))) < 0)
597 WARN("Failed to enumerate physical devices, vr %d.\n", vr);
598 return VK_NULL_HANDLE;
600 if (!count)
602 WARN("No physical device.\n");
603 return VK_NULL_HANDLE;
605 if (count > 1)
607 /* TODO: Create wined3d_adapter for each device. */
608 FIXME("Multiple physical devices available.\n");
609 count = 1;
612 if ((vr = VK_CALL(vkEnumeratePhysicalDevices(vk_info->instance, &count, physical_devices))) < 0)
614 WARN("Failed to get physical devices, vr %d.\n", vr);
615 return VK_NULL_HANDLE;
618 return physical_devices[0];
621 const struct wined3d_gpu_description *get_vulkan_gpu_description(const VkPhysicalDeviceProperties *properties)
623 const struct wined3d_gpu_description *description;
625 TRACE("Device name: %s.\n", debugstr_a(properties->deviceName));
626 TRACE("Vendor ID: 0x%04x, Device ID: 0x%04x.\n", properties->vendorID, properties->deviceID);
627 TRACE("Driver version: %#x.\n", properties->driverVersion);
628 TRACE("API version: %s.\n", debug_vk_version(properties->apiVersion));
630 if (!(description = wined3d_get_user_override_gpu_description(properties->vendorID, properties->deviceID)))
631 description = wined3d_get_gpu_description(properties->vendorID, properties->deviceID);
633 if (!description)
635 FIXME("Failed to retrieve GPU description for device %s %04x:%04x.\n",
636 debugstr_a(properties->deviceName), properties->vendorID, properties->deviceID);
638 description = wined3d_get_gpu_description(HW_VENDOR_AMD, CARD_AMD_RADEON_RX_VEGA);
641 return description;
644 static BOOL wined3d_adapter_vk_init(struct wined3d_adapter_vk *adapter_vk,
645 unsigned int ordinal, unsigned int wined3d_creation_flags)
647 struct wined3d_vk_info *vk_info = &adapter_vk->vk_info;
648 const struct wined3d_gpu_description *gpu_description;
649 struct wined3d_adapter *adapter = &adapter_vk->a;
650 VkPhysicalDeviceIDProperties id_properties;
651 VkPhysicalDeviceProperties2 properties2;
653 TRACE("adapter_vk %p, ordinal %u, wined3d_creation_flags %#x.\n",
654 adapter_vk, ordinal, wined3d_creation_flags);
656 if (!wined3d_adapter_init(adapter, ordinal, &wined3d_adapter_vk_ops))
657 return FALSE;
659 if (!wined3d_init_vulkan(vk_info))
661 WARN("Failed to initialize Vulkan.\n");
662 goto fail;
665 if (!(adapter_vk->physical_device = get_vulkan_physical_device(vk_info)))
666 goto fail_vulkan;
668 memset(&id_properties, 0, sizeof(id_properties));
669 id_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES;
670 properties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
671 properties2.pNext = &id_properties;
673 if (vk_info->vk_ops.vkGetPhysicalDeviceProperties2)
674 VK_CALL(vkGetPhysicalDeviceProperties2(adapter_vk->physical_device, &properties2));
675 else
676 VK_CALL(vkGetPhysicalDeviceProperties(adapter_vk->physical_device, &properties2.properties));
677 adapter_vk->device_limits = properties2.properties.limits;
679 if (!(gpu_description = get_vulkan_gpu_description(&properties2.properties)))
681 ERR("Failed to get GPU description.\n");
682 goto fail_vulkan;
684 wined3d_driver_info_init(&adapter->driver_info, gpu_description, wined3d_settings.emulated_textureram);
686 memcpy(&adapter->driver_uuid, id_properties.driverUUID, sizeof(adapter->driver_uuid));
687 memcpy(&adapter->device_uuid, id_properties.deviceUUID, sizeof(adapter->device_uuid));
689 if (!wined3d_adapter_vk_init_format_info(adapter_vk, vk_info))
690 goto fail_vulkan;
692 adapter->vertex_pipe = &none_vertex_pipe;
693 adapter->fragment_pipe = &none_fragment_pipe;
694 adapter->shader_backend = &none_shader_backend;
696 adapter->d3d_info.wined3d_creation_flags = wined3d_creation_flags;
698 return TRUE;
700 fail_vulkan:
701 VK_CALL(vkDestroyInstance(vk_info->instance, NULL));
702 wined3d_unload_vulkan(vk_info);
703 fail:
704 wined3d_adapter_cleanup(adapter);
705 return FALSE;
708 struct wined3d_adapter *wined3d_adapter_vk_create(unsigned int ordinal,
709 unsigned int wined3d_creation_flags)
711 struct wined3d_adapter_vk *adapter_vk;
713 if (!(adapter_vk = heap_alloc_zero(sizeof(*adapter_vk))))
714 return NULL;
716 if (!wined3d_adapter_vk_init(adapter_vk, ordinal, wined3d_creation_flags))
718 heap_free(adapter_vk);
719 return NULL;
722 TRACE("Created adapter %p.\n", adapter_vk);
724 return &adapter_vk->a;