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
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
;
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
)
59 case VK_ERROR_OUT_OF_HOST_MEMORY
:
60 WARN("Out of host memory.\n");
62 case VK_ERROR_OUT_OF_DEVICE_MEMORY
:
63 WARN("Out of device memory.\n");
65 case VK_ERROR_DEVICE_LOST
:
66 WARN("Device lost.\n");
68 case VK_ERROR_EXTENSION_NOT_PRESENT
:
69 WARN("Extension not present.\n");
72 FIXME("Unhandled VkResult %d.\n", vr
);
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");
88 vk_ops
->vkGetInstanceProcAddr
= (void *)GetProcAddress(vk_info
->vulkan_lib
, "vkGetInstanceProcAddr");
89 if (!vk_ops
->vkGetInstanceProcAddr
)
91 FreeLibrary(vk_info
->vulkan_lib
);
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
;
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
;
114 vk_funcs
= __wine_get_vulkan_driver(dc
, WINE_VULKAN_DRIVER_VERSION
);
120 vk_ops
->vkGetInstanceProcAddr
= (void *)vk_funcs
->p_vkGetInstanceProcAddr
;
124 static void wined3d_unload_vulkan(struct wined3d_vk_info
*vk_info
) {}
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
;
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
);
162 heap_free(queue_properties
);
164 WARN("Failed to find graphics queue.\n");
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
;
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
)))
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
);
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"); \
260 #define VK_DEVICE_PFN LOAD_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
);
274 VK_CALL(vkDestroyDevice(vk_device
, NULL
));
275 heap_free(device_vk
);
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
)
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
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
)
400 static const struct wined3d_adapter_ops wined3d_adapter_vk_ops
=
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
;
417 while (isdigit(*ptr
) || *ptr
== '.')
422 return VK_MAKE_VERSION(major
, minor
, 0);
428 unsigned int core_since_version
;
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
;
445 *extension_count
= 0;
447 if (!(pfn_vkEnumerateInstanceExtensionProperties
448 = (void *)VK_CALL(vkGetInstanceProcAddr(NULL
, "vkEnumerateInstanceExtensionProperties"))))
450 WARN("Failed to get 'vkEnumerateInstanceExtensionProperties'.\n");
454 if ((vr
= pfn_vkEnumerateInstanceExtensionProperties(NULL
, &count
, NULL
)) < 0)
456 WARN("Failed to count instance extensions, vr %d.\n", vr
);
459 if (!(extensions
= heap_calloc(count
, sizeof(*extensions
))))
461 WARN("Out of memory.\n");
464 if ((vr
= pfn_vkEnumerateInstanceExtensionProperties(NULL
, &count
, extensions
)) < 0)
466 WARN("Failed to enumerate extensions, vr %d.\n", vr
);
470 for (i
= 0; i
< ARRAY_SIZE(vulkan_instance_extensions
); ++i
)
472 if (vulkan_instance_extensions
[i
].core_since_version
<= vk_info
->api_version
)
475 for (j
= 0, found
= FALSE
; j
< count
; ++j
)
477 if (!strcmp(extensions
[j
].extensionName
, vulkan_instance_extensions
[i
].name
))
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
);
497 heap_free(extensions
);
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
];
513 if (!wined3d_load_vulkan(vk_info
))
516 if (!(vk_ops
->vkCreateInstance
= (void *)VK_CALL(vkGetInstanceProcAddr(NULL
, "vkCreateInstance"))))
518 ERR("Failed to get 'vkCreateInstance'.\n");
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
))
547 if ((vr
= VK_CALL(vkCreateInstance(&instance_info
, NULL
, &instance
))) < 0)
549 WARN("Failed to create Vulkan instance, vr %d.\n", vr
);
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"); \
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
568 #undef VK_INSTANCE_PFN
569 #undef VK_INSTANCE_EXT_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
;
583 if (vk_ops
->vkDestroyInstance
)
584 VK_CALL(vkDestroyInstance(instance
, NULL
));
585 wined3d_unload_vulkan(vk_info
);
589 static VkPhysicalDevice
get_vulkan_physical_device(struct wined3d_vk_info
*vk_info
)
591 VkPhysicalDevice physical_devices
[1];
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
;
602 WARN("No physical device.\n");
603 return VK_NULL_HANDLE
;
607 /* TODO: Create wined3d_adapter for each device. */
608 FIXME("Multiple physical devices available.\n");
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
);
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
);
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
))
659 if (!wined3d_init_vulkan(vk_info
))
661 WARN("Failed to initialize Vulkan.\n");
665 if (!(adapter_vk
->physical_device
= get_vulkan_physical_device(vk_info
)))
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
));
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");
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
))
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
;
701 VK_CALL(vkDestroyInstance(vk_info
->instance
, NULL
));
702 wined3d_unload_vulkan(vk_info
);
704 wined3d_adapter_cleanup(adapter
);
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
))))
716 if (!wined3d_adapter_vk_init(adapter_vk
, ordinal
, wined3d_creation_flags
))
718 heap_free(adapter_vk
);
722 TRACE("Created adapter %p.\n", adapter_vk
);
724 return &adapter_vk
->a
;