mshtml/tests: Fix a typo in ok() message.
[wine.git] / dlls / wined3d / adapter_vk.c
blob4a5012928247d248c3637ff1a1a7d85d74ac96cf
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 static inline const struct wined3d_adapter_vk *wined3d_adapter_vk_const(const struct wined3d_adapter *adapter)
29 return CONTAINING_RECORD(adapter, struct wined3d_adapter_vk, a);
32 static const char *debug_vk_version(uint32_t version)
34 return wine_dbg_sprintf("%u.%u.%u",
35 VK_VERSION_MAJOR(version), VK_VERSION_MINOR(version), VK_VERSION_PATCH(version));
38 static HRESULT hresult_from_vk_result(VkResult vr)
40 switch (vr)
42 case VK_SUCCESS:
43 return S_OK;
44 case VK_ERROR_OUT_OF_HOST_MEMORY:
45 WARN("Out of host memory.\n");
46 return E_OUTOFMEMORY;
47 case VK_ERROR_OUT_OF_DEVICE_MEMORY:
48 WARN("Out of device memory.\n");
49 return E_OUTOFMEMORY;
50 case VK_ERROR_DEVICE_LOST:
51 WARN("Device lost.\n");
52 return E_FAIL;
53 case VK_ERROR_EXTENSION_NOT_PRESENT:
54 WARN("Extension not present.\n");
55 return E_FAIL;
56 default:
57 FIXME("Unhandled VkResult %d.\n", vr);
58 return E_FAIL;
62 #ifdef USE_WIN32_VULKAN
63 static BOOL wined3d_load_vulkan(struct wined3d_vk_info *vk_info)
65 struct vulkan_ops *vk_ops = &vk_info->vk_ops;
67 if (!(vk_info->vulkan_lib = LoadLibraryA("vulkan-1.dll")))
69 WARN("Failed to load vulkan-1.dll.\n");
70 return FALSE;
73 vk_ops->vkGetInstanceProcAddr = (void *)GetProcAddress(vk_info->vulkan_lib, "vkGetInstanceProcAddr");
74 if (!vk_ops->vkGetInstanceProcAddr)
76 FreeLibrary(vk_info->vulkan_lib);
77 return FALSE;
80 return TRUE;
83 static void wined3d_unload_vulkan(struct wined3d_vk_info *vk_info)
85 if (vk_info->vulkan_lib)
87 FreeLibrary(vk_info->vulkan_lib);
88 vk_info->vulkan_lib = NULL;
91 #else
92 static BOOL wined3d_load_vulkan(struct wined3d_vk_info *vk_info)
94 struct vulkan_ops *vk_ops = &vk_info->vk_ops;
95 const struct vulkan_funcs *vk_funcs;
96 HDC dc;
98 dc = GetDC(0);
99 vk_funcs = __wine_get_vulkan_driver(dc, WINE_VULKAN_DRIVER_VERSION);
100 ReleaseDC(0, dc);
102 if (!vk_funcs)
103 return FALSE;
105 vk_ops->vkGetInstanceProcAddr = (void *)vk_funcs->p_vkGetInstanceProcAddr;
106 return TRUE;
109 static void wined3d_unload_vulkan(struct wined3d_vk_info *vk_info) {}
110 #endif
112 static void adapter_vk_destroy(struct wined3d_adapter *adapter)
114 struct wined3d_adapter_vk *adapter_vk = wined3d_adapter_vk(adapter);
115 struct wined3d_vk_info *vk_info = &adapter_vk->vk_info;
117 VK_CALL(vkDestroyInstance(vk_info->instance, NULL));
118 wined3d_unload_vulkan(vk_info);
119 wined3d_adapter_cleanup(&adapter_vk->a);
120 heap_free(adapter_vk);
123 static HRESULT wined3d_select_vulkan_queue_family(const struct wined3d_adapter_vk *adapter_vk,
124 uint32_t *queue_family_index)
126 VkPhysicalDevice physical_device = adapter_vk->physical_device;
127 const struct wined3d_vk_info *vk_info = &adapter_vk->vk_info;
128 VkQueueFamilyProperties *queue_properties;
129 uint32_t count, i;
131 VK_CALL(vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &count, NULL));
133 if (!(queue_properties = heap_calloc(count, sizeof(*queue_properties))))
134 return E_OUTOFMEMORY;
136 VK_CALL(vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &count, queue_properties));
138 for (i = 0; i < count; ++i)
140 if (queue_properties[i].queueFlags & VK_QUEUE_GRAPHICS_BIT)
142 *queue_family_index = i;
143 heap_free(queue_properties);
144 return WINED3D_OK;
147 heap_free(queue_properties);
149 WARN("Failed to find graphics queue.\n");
150 return E_FAIL;
153 static void wined3d_disable_vulkan_features(VkPhysicalDeviceFeatures *features)
155 features->depthBounds = VK_FALSE;
156 features->alphaToOne = VK_FALSE;
157 features->textureCompressionETC2 = VK_FALSE;
158 features->textureCompressionASTC_LDR = VK_FALSE;
159 features->shaderStorageImageMultisample = VK_FALSE;
160 features->shaderUniformBufferArrayDynamicIndexing = VK_FALSE;
161 features->shaderSampledImageArrayDynamicIndexing = VK_FALSE;
162 features->shaderStorageBufferArrayDynamicIndexing = VK_FALSE;
163 features->shaderStorageImageArrayDynamicIndexing = VK_FALSE;
164 features->shaderInt16 = VK_FALSE;
165 features->shaderResourceResidency = VK_FALSE;
166 features->shaderResourceMinLod = VK_FALSE;
167 features->sparseBinding = VK_FALSE;
168 features->sparseResidencyBuffer = VK_FALSE;
169 features->sparseResidencyImage2D = VK_FALSE;
170 features->sparseResidencyImage3D = VK_FALSE;
171 features->sparseResidency2Samples = VK_FALSE;
172 features->sparseResidency4Samples = VK_FALSE;
173 features->sparseResidency8Samples = VK_FALSE;
174 features->sparseResidency16Samples = VK_FALSE;
175 features->sparseResidencyAliased = VK_FALSE;
176 features->inheritedQueries = VK_FALSE;
179 static HRESULT adapter_vk_create_device(struct wined3d *wined3d, const struct wined3d_adapter *adapter,
180 enum wined3d_device_type device_type, HWND focus_window, unsigned int flags, BYTE surface_alignment,
181 const enum wined3d_feature_level *levels, unsigned int level_count,
182 struct wined3d_device_parent *device_parent, struct wined3d_device **device)
184 const struct wined3d_adapter_vk *adapter_vk = wined3d_adapter_vk_const(adapter);
185 const struct wined3d_vk_info *vk_info = &adapter_vk->vk_info;
186 static const float priorities[] = {1.0f};
187 struct wined3d_device_vk *device_vk;
188 VkDevice vk_device = VK_NULL_HANDLE;
189 VkDeviceQueueCreateInfo queue_info;
190 VkPhysicalDeviceFeatures features;
191 VkPhysicalDevice physical_device;
192 VkDeviceCreateInfo device_info;
193 uint32_t queue_family_index;
194 VkResult vr;
195 HRESULT hr;
197 if (!(device_vk = heap_alloc_zero(sizeof(*device_vk))))
198 return E_OUTOFMEMORY;
200 if (FAILED(hr = wined3d_select_vulkan_queue_family(adapter_vk, &queue_family_index)))
201 goto fail;
203 physical_device = adapter_vk->physical_device;
205 VK_CALL(vkGetPhysicalDeviceFeatures(physical_device, &features));
206 wined3d_disable_vulkan_features(&features);
208 queue_info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
209 queue_info.pNext = NULL;
210 queue_info.flags = 0;
211 queue_info.queueFamilyIndex = queue_family_index;
212 queue_info.queueCount = ARRAY_SIZE(priorities);
213 queue_info.pQueuePriorities = priorities;
215 device_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
216 device_info.pNext = NULL;
217 device_info.flags = 0;
218 device_info.queueCreateInfoCount = 1;
219 device_info.pQueueCreateInfos = &queue_info;
220 device_info.enabledLayerCount = 0;
221 device_info.ppEnabledLayerNames = NULL;
222 device_info.enabledExtensionCount = 0;
223 device_info.ppEnabledExtensionNames = NULL;
224 device_info.pEnabledFeatures = &features;
226 if ((vr = VK_CALL(vkCreateDevice(physical_device, &device_info, NULL, &vk_device))) < 0)
228 WARN("Failed to create Vulkan device, vr %s.\n", wined3d_debug_vkresult(vr));
229 vk_device = VK_NULL_HANDLE;
230 hr = hresult_from_vk_result(vr);
231 goto fail;
234 device_vk->vk_device = vk_device;
235 VK_CALL(vkGetDeviceQueue(vk_device, queue_family_index, 0, &device_vk->vk_queue));
237 device_vk->vk_info = *vk_info;
238 #define LOAD_DEVICE_PFN(name) \
239 if (!(device_vk->vk_info.vk_ops.name = (void *)VK_CALL(vkGetDeviceProcAddr(vk_device, #name)))) \
241 WARN("Could not get device proc addr for '" #name "'.\n"); \
242 hr = E_FAIL; \
243 goto fail; \
245 #define VK_DEVICE_PFN LOAD_DEVICE_PFN
246 VK_DEVICE_FUNCS()
247 #undef VK_DEVICE_PFN
249 if (FAILED(hr = wined3d_device_init(&device_vk->d, wined3d, adapter->ordinal, device_type,
250 focus_window, flags, surface_alignment, levels, level_count, device_parent)))
252 WARN("Failed to initialize device, hr %#x.\n", hr);
253 goto fail;
256 *device = &device_vk->d;
258 return WINED3D_OK;
260 fail:
261 VK_CALL(vkDestroyDevice(vk_device, NULL));
262 heap_free(device_vk);
263 return hr;
266 static void adapter_vk_destroy_device(struct wined3d_device *device)
268 struct wined3d_device_vk *device_vk = wined3d_device_vk(device);
269 const struct wined3d_vk_info *vk_info = &device_vk->vk_info;
271 wined3d_device_cleanup(&device_vk->d);
272 VK_CALL(vkDestroyDevice(device_vk->vk_device, NULL));
273 heap_free(device_vk);
276 struct wined3d_context *adapter_vk_acquire_context(struct wined3d_device *device,
277 struct wined3d_texture *texture, unsigned int sub_resource_idx)
279 TRACE("device %p, texture %p, sub_resource_idx %u.\n", device, texture, sub_resource_idx);
281 wined3d_from_cs(device->cs);
283 if (!device->context_count)
284 return NULL;
286 return &wined3d_device_vk(device)->context_vk.c;
289 void adapter_vk_release_context(struct wined3d_context *context)
291 TRACE("context %p.\n", context);
294 static void adapter_vk_get_wined3d_caps(const struct wined3d_adapter *adapter, struct wined3d_caps *caps)
296 const struct wined3d_adapter_vk *adapter_vk = wined3d_adapter_vk_const(adapter);
297 const VkPhysicalDeviceLimits *limits = &adapter_vk->device_limits;
298 BOOL sampler_anisotropy = limits->maxSamplerAnisotropy > 1.0f;
300 caps->ddraw_caps.dds_caps |= WINEDDSCAPS_BACKBUFFER
301 | WINEDDSCAPS_COMPLEX
302 | WINEDDSCAPS_FRONTBUFFER
303 | WINEDDSCAPS_3DDEVICE
304 | WINEDDSCAPS_VIDEOMEMORY
305 | WINEDDSCAPS_OWNDC
306 | WINEDDSCAPS_LOCALVIDMEM
307 | WINEDDSCAPS_NONLOCALVIDMEM;
308 caps->ddraw_caps.caps |= WINEDDCAPS_3D;
310 caps->Caps2 |= WINED3DCAPS2_CANGENMIPMAP;
312 caps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_BLENDOP
313 | WINED3DPMISCCAPS_INDEPENDENTWRITEMASKS
314 | WINED3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS
315 | WINED3DPMISCCAPS_POSTBLENDSRGBCONVERT
316 | WINED3DPMISCCAPS_SEPARATEALPHABLEND;
318 caps->RasterCaps |= WINED3DPRASTERCAPS_MIPMAPLODBIAS;
320 if (sampler_anisotropy)
322 caps->RasterCaps |= WINED3DPRASTERCAPS_ANISOTROPY;
324 caps->TextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC
325 | WINED3DPTFILTERCAPS_MINFANISOTROPIC;
327 caps->MaxAnisotropy = limits->maxSamplerAnisotropy;
330 caps->SrcBlendCaps |= WINED3DPBLENDCAPS_BLENDFACTOR;
331 caps->DestBlendCaps |= WINED3DPBLENDCAPS_BLENDFACTOR
332 | WINED3DPBLENDCAPS_SRCALPHASAT;
334 caps->TextureCaps |= WINED3DPTEXTURECAPS_VOLUMEMAP
335 | WINED3DPTEXTURECAPS_MIPVOLUMEMAP
336 | WINED3DPTEXTURECAPS_VOLUMEMAP_POW2;
337 caps->VolumeTextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFLINEAR
338 | WINED3DPTFILTERCAPS_MAGFPOINT
339 | WINED3DPTFILTERCAPS_MINFLINEAR
340 | WINED3DPTFILTERCAPS_MINFPOINT
341 | WINED3DPTFILTERCAPS_MIPFLINEAR
342 | WINED3DPTFILTERCAPS_MIPFPOINT
343 | WINED3DPTFILTERCAPS_LINEAR
344 | WINED3DPTFILTERCAPS_LINEARMIPLINEAR
345 | WINED3DPTFILTERCAPS_LINEARMIPNEAREST
346 | WINED3DPTFILTERCAPS_MIPLINEAR
347 | WINED3DPTFILTERCAPS_MIPNEAREST
348 | WINED3DPTFILTERCAPS_NEAREST;
349 caps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_INDEPENDENTUV
350 | WINED3DPTADDRESSCAPS_CLAMP
351 | WINED3DPTADDRESSCAPS_WRAP;
352 caps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER
353 | WINED3DPTADDRESSCAPS_MIRROR
354 | WINED3DPTADDRESSCAPS_MIRRORONCE;
356 caps->MaxVolumeExtent = limits->maxImageDimension3D;
358 caps->TextureCaps |= WINED3DPTEXTURECAPS_CUBEMAP
359 | WINED3DPTEXTURECAPS_MIPCUBEMAP
360 | WINED3DPTEXTURECAPS_CUBEMAP_POW2;
361 caps->CubeTextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFLINEAR
362 | WINED3DPTFILTERCAPS_MAGFPOINT
363 | WINED3DPTFILTERCAPS_MINFLINEAR
364 | WINED3DPTFILTERCAPS_MINFPOINT
365 | WINED3DPTFILTERCAPS_MIPFLINEAR
366 | WINED3DPTFILTERCAPS_MIPFPOINT
367 | WINED3DPTFILTERCAPS_LINEAR
368 | WINED3DPTFILTERCAPS_LINEARMIPLINEAR
369 | WINED3DPTFILTERCAPS_LINEARMIPNEAREST
370 | WINED3DPTFILTERCAPS_MIPLINEAR
371 | WINED3DPTFILTERCAPS_MIPNEAREST
372 | WINED3DPTFILTERCAPS_NEAREST;
374 if (sampler_anisotropy)
376 caps->CubeTextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC
377 | WINED3DPTFILTERCAPS_MINFANISOTROPIC;
380 caps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER
381 | WINED3DPTADDRESSCAPS_MIRROR
382 | WINED3DPTADDRESSCAPS_MIRRORONCE;
384 caps->StencilCaps |= WINED3DSTENCILCAPS_DECR
385 | WINED3DSTENCILCAPS_INCR
386 | WINED3DSTENCILCAPS_TWOSIDED;
388 caps->DeclTypes |= WINED3DDTCAPS_FLOAT16_2 | WINED3DDTCAPS_FLOAT16_4;
390 caps->MaxPixelShader30InstructionSlots = WINED3DMAX30SHADERINSTRUCTIONS;
391 caps->MaxVertexShader30InstructionSlots = WINED3DMAX30SHADERINSTRUCTIONS;
392 caps->PS20Caps.temp_count = WINED3DPS20_MAX_NUMTEMPS;
393 caps->VS20Caps.temp_count = WINED3DVS20_MAX_NUMTEMPS;
396 static BOOL adapter_vk_check_format(const struct wined3d_adapter *adapter,
397 const struct wined3d_format *adapter_format, const struct wined3d_format *rt_format,
398 const struct wined3d_format *ds_format)
400 return TRUE;
403 static HRESULT adapter_vk_init_3d(struct wined3d_device *device)
405 struct wined3d_context_vk *context_vk;
406 struct wined3d_device_vk *device_vk;
407 HRESULT hr;
409 TRACE("device %p.\n", device);
411 device_vk = wined3d_device_vk(device);
412 context_vk = &device_vk->context_vk;
413 if (FAILED(hr = wined3d_context_vk_init(context_vk, device->swapchains[0])))
415 WARN("Failed to initialise context.\n");
416 return hr;
419 if (FAILED(hr = device->shader_backend->shader_alloc_private(device,
420 device->adapter->vertex_pipe, device->adapter->fragment_pipe)))
422 ERR("Failed to allocate shader private data, hr %#x.\n", hr);
423 wined3d_context_vk_cleanup(context_vk);
424 return hr;
427 if (!device_context_add(device, &context_vk->c))
429 ERR("Failed to add the newly created context to the context list.\n");
430 device->shader_backend->shader_free_private(device, NULL);
431 wined3d_context_vk_cleanup(context_vk);
432 return E_FAIL;
435 TRACE("Initialised context %p.\n", context_vk);
437 if (!(device_vk->d.blitter = wined3d_cpu_blitter_create()))
439 ERR("Failed to create CPU blitter.\n");
440 device_context_remove(device, &context_vk->c);
441 device->shader_backend->shader_free_private(device, NULL);
442 wined3d_context_vk_cleanup(context_vk);
443 return E_FAIL;
446 wined3d_device_create_default_samplers(device, &context_vk->c);
448 return WINED3D_OK;
451 static void adapter_vk_uninit_3d(struct wined3d_device *device)
453 struct wined3d_context_vk *context_vk;
454 struct wined3d_shader *shader;
456 TRACE("device %p.\n", device);
458 context_vk = &wined3d_device_vk(device)->context_vk;
460 LIST_FOR_EACH_ENTRY(shader, &device->shaders, struct wined3d_shader, shader_list_entry)
462 device->shader_backend->shader_destroy(shader);
465 wined3d_device_destroy_default_samplers(device, &context_vk->c);
467 device->blitter->ops->blitter_destroy(device->blitter, NULL);
469 wined3d_cs_finish(device->cs, WINED3D_CS_QUEUE_DEFAULT);
470 device_context_remove(device, &context_vk->c);
471 device->shader_backend->shader_free_private(device, NULL);
472 wined3d_context_vk_cleanup(context_vk);
475 static void *adapter_vk_map_bo_address(struct wined3d_context *context,
476 const struct wined3d_bo_address *data, size_t size, uint32_t bind_flags, uint32_t map_flags)
478 if (data->buffer_object)
480 ERR("Unsupported buffer object %#lx.\n", data->buffer_object);
481 return NULL;
484 return data->addr;
487 static void adapter_vk_unmap_bo_address(struct wined3d_context *context, const struct wined3d_bo_address *data,
488 uint32_t bind_flags, unsigned int range_count, const struct wined3d_map_range *ranges)
490 if (data->buffer_object)
491 ERR("Unsupported buffer object %#lx.\n", data->buffer_object);
494 static void adapter_vk_copy_bo_address(struct wined3d_context *context,
495 const struct wined3d_bo_address *dst, uint32_t dst_bind_flags,
496 const struct wined3d_bo_address *src, uint32_t src_bind_flags, size_t size)
498 struct wined3d_map_range range;
499 void *dst_ptr, *src_ptr;
501 src_ptr = adapter_vk_map_bo_address(context, src, size, src_bind_flags, WINED3D_MAP_READ);
502 dst_ptr = adapter_vk_map_bo_address(context, dst, size, dst_bind_flags, WINED3D_MAP_WRITE);
504 memcpy(dst_ptr, src_ptr, size);
506 range.offset = 0;
507 range.size = size;
508 adapter_vk_unmap_bo_address(context, dst, dst_bind_flags, 1, &range);
509 adapter_vk_unmap_bo_address(context, src, src_bind_flags, 0, NULL);
512 static HRESULT adapter_vk_create_swapchain(struct wined3d_device *device, struct wined3d_swapchain_desc *desc,
513 void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_swapchain **swapchain)
515 struct wined3d_swapchain *swapchain_vk;
516 HRESULT hr;
518 TRACE("device %p, desc %p, parent %p, parent_ops %p, swapchain %p.\n",
519 device, desc, parent, parent_ops, swapchain);
521 if (!(swapchain_vk = heap_alloc_zero(sizeof(*swapchain_vk))))
522 return E_OUTOFMEMORY;
524 if (FAILED(hr = wined3d_swapchain_vk_init(swapchain_vk, device, desc, parent, parent_ops)))
526 WARN("Failed to initialise swapchain, hr %#x.\n", hr);
527 heap_free(swapchain_vk);
528 return hr;
531 TRACE("Created swapchain %p.\n", swapchain_vk);
532 *swapchain = swapchain_vk;
534 return hr;
537 static void adapter_vk_destroy_swapchain(struct wined3d_swapchain *swapchain)
539 wined3d_swapchain_cleanup(swapchain);
540 heap_free(swapchain);
543 static HRESULT adapter_vk_create_buffer(struct wined3d_device *device,
544 const struct wined3d_buffer_desc *desc, const struct wined3d_sub_resource_data *data,
545 void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_buffer **buffer)
547 struct wined3d_buffer_vk *buffer_vk;
548 HRESULT hr;
550 TRACE("device %p, desc %p, data %p, parent %p, parent_ops %p, buffer %p.\n",
551 device, desc, data, parent, parent_ops, buffer);
553 if (!(buffer_vk = heap_alloc_zero(sizeof(*buffer_vk))))
554 return E_OUTOFMEMORY;
556 if (FAILED(hr = wined3d_buffer_vk_init(buffer_vk, device, desc, data, parent, parent_ops)))
558 WARN("Failed to initialise buffer, hr %#x.\n", hr);
559 heap_free(buffer_vk);
560 return hr;
563 TRACE("Created buffer %p.\n", buffer_vk);
564 *buffer = &buffer_vk->b;
566 return hr;
569 static void adapter_vk_destroy_buffer(struct wined3d_buffer *buffer)
571 struct wined3d_buffer_vk *buffer_vk = wined3d_buffer_vk(buffer);
572 struct wined3d_device *device = buffer_vk->b.resource.device;
573 unsigned int swapchain_count = device->swapchain_count;
575 TRACE("buffer_vk %p.\n", buffer_vk);
577 /* Take a reference to the device, in case releasing the buffer would
578 * cause the device to be destroyed. However, swapchain resources don't
579 * take a reference to the device, and we wouldn't want to increment the
580 * refcount on a device that's in the process of being destroyed. */
581 if (swapchain_count)
582 wined3d_device_incref(device);
583 wined3d_buffer_cleanup(&buffer_vk->b);
584 wined3d_cs_destroy_object(device->cs, heap_free, buffer_vk);
585 if (swapchain_count)
586 wined3d_device_decref(device);
589 static HRESULT adapter_vk_create_texture(struct wined3d_device *device,
590 const struct wined3d_resource_desc *desc, unsigned int layer_count, unsigned int level_count,
591 uint32_t flags, void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_texture **texture)
593 struct wined3d_texture_vk *texture_vk;
594 HRESULT hr;
596 TRACE("device %p, desc %p, layer_count %u, level_count %u, flags %#x, parent %p, parent_ops %p, texture %p.\n",
597 device, desc, layer_count, level_count, flags, parent, parent_ops, texture);
599 if (!(texture_vk = wined3d_texture_allocate_object_memory(sizeof(*texture_vk), level_count, layer_count)))
600 return E_OUTOFMEMORY;
602 if (FAILED(hr = wined3d_texture_vk_init(texture_vk, device, desc,
603 layer_count, level_count, flags, parent, parent_ops)))
605 WARN("Failed to initialise texture, hr %#x.\n", hr);
606 heap_free(texture_vk);
607 return hr;
610 TRACE("Created texture %p.\n", texture_vk);
611 *texture = &texture_vk->t;
613 return hr;
616 static void adapter_vk_destroy_texture(struct wined3d_texture *texture)
618 struct wined3d_texture_vk *texture_vk = wined3d_texture_vk(texture);
619 struct wined3d_device *device = texture_vk->t.resource.device;
620 unsigned int swapchain_count = device->swapchain_count;
622 TRACE("texture_vk %p.\n", texture_vk);
624 /* Take a reference to the device, in case releasing the texture would
625 * cause the device to be destroyed. However, swapchain resources don't
626 * take a reference to the device, and we wouldn't want to increment the
627 * refcount on a device that's in the process of being destroyed. */
628 if (swapchain_count)
629 wined3d_device_incref(device);
631 wined3d_texture_sub_resources_destroyed(texture);
632 texture->resource.parent_ops->wined3d_object_destroyed(texture->resource.parent);
634 wined3d_texture_cleanup(&texture_vk->t);
635 wined3d_cs_destroy_object(device->cs, heap_free, texture_vk);
637 if (swapchain_count)
638 wined3d_device_decref(device);
641 static HRESULT adapter_vk_create_rendertarget_view(const struct wined3d_view_desc *desc,
642 struct wined3d_resource *resource, void *parent, const struct wined3d_parent_ops *parent_ops,
643 struct wined3d_rendertarget_view **view)
645 struct wined3d_rendertarget_view_vk *view_vk;
646 HRESULT hr;
648 TRACE("desc %s, resource %p, parent %p, parent_ops %p, view %p.\n",
649 wined3d_debug_view_desc(desc, resource), resource, parent, parent_ops, view);
651 if (!(view_vk = heap_alloc_zero(sizeof(*view_vk))))
652 return E_OUTOFMEMORY;
654 if (FAILED(hr = wined3d_rendertarget_view_vk_init(view_vk, desc, resource, parent, parent_ops)))
656 WARN("Failed to initialise view, hr %#x.\n", hr);
657 heap_free(view_vk);
658 return hr;
661 TRACE("Created render target view %p.\n", view_vk);
662 *view = &view_vk->v;
664 return hr;
667 static void adapter_vk_destroy_rendertarget_view(struct wined3d_rendertarget_view *view)
669 struct wined3d_rendertarget_view_vk *view_vk = wined3d_rendertarget_view_vk(view);
670 struct wined3d_device *device = view_vk->v.resource->device;
671 unsigned int swapchain_count = device->swapchain_count;
673 TRACE("view_vk %p.\n", view_vk);
675 /* Take a reference to the device, in case releasing the view's resource
676 * would cause the device to be destroyed. However, swapchain resources
677 * don't take a reference to the device, and we wouldn't want to increment
678 * the refcount on a device that's in the process of being destroyed. */
679 if (swapchain_count)
680 wined3d_device_incref(device);
681 wined3d_rendertarget_view_cleanup(&view_vk->v);
682 wined3d_cs_destroy_object(device->cs, heap_free, view_vk);
683 if (swapchain_count)
684 wined3d_device_decref(device);
687 static HRESULT adapter_vk_create_shader_resource_view(const struct wined3d_view_desc *desc,
688 struct wined3d_resource *resource, void *parent, const struct wined3d_parent_ops *parent_ops,
689 struct wined3d_shader_resource_view **view)
691 struct wined3d_shader_resource_view_vk *view_vk;
692 HRESULT hr;
694 TRACE("desc %s, resource %p, parent %p, parent_ops %p, view %p.\n",
695 wined3d_debug_view_desc(desc, resource), resource, parent, parent_ops, view);
697 if (!(view_vk = heap_alloc_zero(sizeof(*view_vk))))
698 return E_OUTOFMEMORY;
700 if (FAILED(hr = wined3d_shader_resource_view_vk_init(view_vk, desc, resource, parent, parent_ops)))
702 WARN("Failed to initialise view, hr %#x.\n", hr);
703 heap_free(view_vk);
704 return hr;
707 TRACE("Created shader resource view %p.\n", view_vk);
708 *view = &view_vk->v;
710 return hr;
713 static void adapter_vk_destroy_shader_resource_view(struct wined3d_shader_resource_view *view)
715 struct wined3d_shader_resource_view_vk *view_vk = wined3d_shader_resource_view_vk(view);
716 struct wined3d_device *device = view_vk->v.resource->device;
717 unsigned int swapchain_count = device->swapchain_count;
719 TRACE("view_vk %p.\n", view_vk);
721 /* Take a reference to the device, in case releasing the view's resource
722 * would cause the device to be destroyed. However, swapchain resources
723 * don't take a reference to the device, and we wouldn't want to increment
724 * the refcount on a device that's in the process of being destroyed. */
725 if (swapchain_count)
726 wined3d_device_incref(device);
727 wined3d_shader_resource_view_cleanup(&view_vk->v);
728 wined3d_cs_destroy_object(device->cs, heap_free, view_vk);
729 if (swapchain_count)
730 wined3d_device_decref(device);
733 static HRESULT adapter_vk_create_unordered_access_view(const struct wined3d_view_desc *desc,
734 struct wined3d_resource *resource, void *parent, const struct wined3d_parent_ops *parent_ops,
735 struct wined3d_unordered_access_view **view)
737 struct wined3d_unordered_access_view_vk *view_vk;
738 HRESULT hr;
740 TRACE("desc %s, resource %p, parent %p, parent_ops %p, view %p.\n",
741 wined3d_debug_view_desc(desc, resource), resource, parent, parent_ops, view);
743 if (!(view_vk = heap_alloc_zero(sizeof(*view_vk))))
744 return E_OUTOFMEMORY;
746 if (FAILED(hr = wined3d_unordered_access_view_vk_init(view_vk, desc, resource, parent, parent_ops)))
748 WARN("Failed to initialise view, hr %#x.\n", hr);
749 heap_free(view_vk);
750 return hr;
753 TRACE("Created unordered access view %p.\n", view_vk);
754 *view = &view_vk->v;
756 return hr;
759 static void adapter_vk_destroy_unordered_access_view(struct wined3d_unordered_access_view *view)
761 struct wined3d_unordered_access_view_vk *view_vk = wined3d_unordered_access_view_vk(view);
762 struct wined3d_device *device = view_vk->v.resource->device;
763 unsigned int swapchain_count = device->swapchain_count;
765 TRACE("view_vk %p.\n", view_vk);
767 /* Take a reference to the device, in case releasing the view's resource
768 * would cause the device to be destroyed. However, swapchain resources
769 * don't take a reference to the device, and we wouldn't want to increment
770 * the refcount on a device that's in the process of being destroyed. */
771 if (swapchain_count)
772 wined3d_device_incref(device);
773 wined3d_unordered_access_view_cleanup(&view_vk->v);
774 wined3d_cs_destroy_object(device->cs, heap_free, view_vk);
775 if (swapchain_count)
776 wined3d_device_decref(device);
779 static HRESULT adapter_vk_create_sampler(struct wined3d_device *device, const struct wined3d_sampler_desc *desc,
780 void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_sampler **sampler)
782 struct wined3d_sampler *sampler_vk;
784 TRACE("device %p, desc %p, parent %p, parent_ops %p, sampler %p.\n",
785 device, desc, parent, parent_ops, sampler);
787 if (!(sampler_vk = heap_alloc_zero(sizeof(*sampler_vk))))
788 return E_OUTOFMEMORY;
790 wined3d_sampler_vk_init(sampler_vk, device, desc, parent, parent_ops);
792 TRACE("Created sampler %p.\n", sampler_vk);
793 *sampler = sampler_vk;
795 return WINED3D_OK;
798 static void adapter_vk_destroy_sampler(struct wined3d_sampler *sampler)
800 TRACE("sampler %p.\n", sampler);
802 wined3d_cs_destroy_object(sampler->device->cs, heap_free, sampler);
805 static HRESULT adapter_vk_create_query(struct wined3d_device *device, enum wined3d_query_type type,
806 void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_query **query)
808 TRACE("device %p, type %#x, parent %p, parent_ops %p, query %p.\n",
809 device, type, parent, parent_ops, query);
811 return WINED3DERR_NOTAVAILABLE;
814 static void adapter_vk_destroy_query(struct wined3d_query *query)
816 TRACE("query %p.\n", query);
819 static void adapter_vk_flush_context(struct wined3d_context *context)
821 TRACE("context %p.\n", context);
824 void adapter_vk_clear_uav(struct wined3d_context *context,
825 struct wined3d_unordered_access_view *view, const struct wined3d_uvec4 *clear_value)
827 FIXME("context %p, view %p, clear_value %s.\n", context, view, debug_uvec4(clear_value));
830 static const struct wined3d_adapter_ops wined3d_adapter_vk_ops =
832 adapter_vk_destroy,
833 adapter_vk_create_device,
834 adapter_vk_destroy_device,
835 adapter_vk_acquire_context,
836 adapter_vk_release_context,
837 adapter_vk_get_wined3d_caps,
838 adapter_vk_check_format,
839 adapter_vk_init_3d,
840 adapter_vk_uninit_3d,
841 adapter_vk_map_bo_address,
842 adapter_vk_unmap_bo_address,
843 adapter_vk_copy_bo_address,
844 adapter_vk_create_swapchain,
845 adapter_vk_destroy_swapchain,
846 adapter_vk_create_buffer,
847 adapter_vk_destroy_buffer,
848 adapter_vk_create_texture,
849 adapter_vk_destroy_texture,
850 adapter_vk_create_rendertarget_view,
851 adapter_vk_destroy_rendertarget_view,
852 adapter_vk_create_shader_resource_view,
853 adapter_vk_destroy_shader_resource_view,
854 adapter_vk_create_unordered_access_view,
855 adapter_vk_destroy_unordered_access_view,
856 adapter_vk_create_sampler,
857 adapter_vk_destroy_sampler,
858 adapter_vk_create_query,
859 adapter_vk_destroy_query,
860 adapter_vk_flush_context,
861 adapter_vk_clear_uav,
864 static unsigned int wined3d_get_wine_vk_version(void)
866 const char *ptr = PACKAGE_VERSION;
867 int major, minor;
869 major = atoi(ptr);
871 while (isdigit(*ptr))
872 ++ptr;
873 if (*ptr == '.')
874 ++ptr;
876 minor = atoi(ptr);
878 return VK_MAKE_VERSION(major, minor, 0);
881 static const struct
883 const char *name;
884 unsigned int core_since_version;
885 BOOL required;
887 vulkan_instance_extensions[] =
889 {VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, VK_API_VERSION_1_1, FALSE},
892 static BOOL enable_vulkan_instance_extensions(uint32_t *extension_count,
893 const char *enabled_extensions[], const struct wined3d_vk_info *vk_info)
895 PFN_vkEnumerateInstanceExtensionProperties pfn_vkEnumerateInstanceExtensionProperties;
896 VkExtensionProperties *extensions = NULL;
897 BOOL success = FALSE, found;
898 unsigned int i, j, count;
899 VkResult vr;
901 *extension_count = 0;
903 if (!(pfn_vkEnumerateInstanceExtensionProperties
904 = (void *)VK_CALL(vkGetInstanceProcAddr(NULL, "vkEnumerateInstanceExtensionProperties"))))
906 WARN("Failed to get 'vkEnumerateInstanceExtensionProperties'.\n");
907 goto done;
910 if ((vr = pfn_vkEnumerateInstanceExtensionProperties(NULL, &count, NULL)) < 0)
912 WARN("Failed to count instance extensions, vr %s.\n", wined3d_debug_vkresult(vr));
913 goto done;
915 if (!(extensions = heap_calloc(count, sizeof(*extensions))))
917 WARN("Out of memory.\n");
918 goto done;
920 if ((vr = pfn_vkEnumerateInstanceExtensionProperties(NULL, &count, extensions)) < 0)
922 WARN("Failed to enumerate extensions, vr %s.\n", wined3d_debug_vkresult(vr));
923 goto done;
926 for (i = 0; i < ARRAY_SIZE(vulkan_instance_extensions); ++i)
928 if (vulkan_instance_extensions[i].core_since_version <= vk_info->api_version)
929 continue;
931 for (j = 0, found = FALSE; j < count; ++j)
933 if (!strcmp(extensions[j].extensionName, vulkan_instance_extensions[i].name))
935 found = TRUE;
936 break;
939 if (found)
941 TRACE("Enabling instance extension '%s'.\n", vulkan_instance_extensions[i].name);
942 enabled_extensions[(*extension_count)++] = vulkan_instance_extensions[i].name;
944 else if (!found && vulkan_instance_extensions[i].required)
946 WARN("Required extension '%s' is not available.\n", vulkan_instance_extensions[i].name);
947 goto done;
950 success = TRUE;
952 done:
953 heap_free(extensions);
954 return success;
957 static BOOL wined3d_init_vulkan(struct wined3d_vk_info *vk_info)
959 const char *enabled_instance_extensions[ARRAY_SIZE(vulkan_instance_extensions)];
960 PFN_vkEnumerateInstanceVersion pfn_vkEnumerateInstanceVersion;
961 struct vulkan_ops *vk_ops = &vk_info->vk_ops;
962 VkInstance instance = VK_NULL_HANDLE;
963 VkInstanceCreateInfo instance_info;
964 VkApplicationInfo app_info;
965 uint32_t api_version = 0;
966 char app_name[MAX_PATH];
967 VkResult vr;
969 if (!wined3d_load_vulkan(vk_info))
970 return FALSE;
972 if (!(vk_ops->vkCreateInstance = (void *)VK_CALL(vkGetInstanceProcAddr(NULL, "vkCreateInstance"))))
974 ERR("Failed to get 'vkCreateInstance'.\n");
975 goto fail;
978 vk_info->api_version = VK_API_VERSION_1_0;
979 if ((pfn_vkEnumerateInstanceVersion = (void *)VK_CALL(vkGetInstanceProcAddr(NULL, "vkEnumerateInstanceVersion")))
980 && pfn_vkEnumerateInstanceVersion(&api_version) == VK_SUCCESS)
982 TRACE("Vulkan instance API version %s.\n", debug_vk_version(api_version));
984 if (api_version >= VK_API_VERSION_1_1)
985 vk_info->api_version = VK_API_VERSION_1_1;
988 memset(&app_info, 0, sizeof(app_info));
989 app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
990 if (wined3d_get_app_name(app_name, ARRAY_SIZE(app_name)))
991 app_info.pApplicationName = app_name;
992 app_info.pEngineName = "Damavand";
993 app_info.engineVersion = wined3d_get_wine_vk_version();
994 app_info.apiVersion = vk_info->api_version;
996 memset(&instance_info, 0, sizeof(instance_info));
997 instance_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
998 instance_info.pApplicationInfo = &app_info;
999 instance_info.ppEnabledExtensionNames = enabled_instance_extensions;
1000 if (!enable_vulkan_instance_extensions(&instance_info.enabledExtensionCount, enabled_instance_extensions, vk_info))
1001 goto fail;
1003 if ((vr = VK_CALL(vkCreateInstance(&instance_info, NULL, &instance))) < 0)
1005 WARN("Failed to create Vulkan instance, vr %s.\n", wined3d_debug_vkresult(vr));
1006 goto fail;
1009 TRACE("Created Vulkan instance %p.\n", instance);
1011 #define LOAD_INSTANCE_PFN(name) \
1012 if (!(vk_ops->name = (void *)VK_CALL(vkGetInstanceProcAddr(instance, #name)))) \
1014 WARN("Could not get instance proc addr for '" #name "'.\n"); \
1015 goto fail; \
1017 #define LOAD_INSTANCE_OPT_PFN(name) \
1018 vk_ops->name = (void *)VK_CALL(vkGetInstanceProcAddr(instance, #name));
1019 #define VK_INSTANCE_PFN LOAD_INSTANCE_PFN
1020 #define VK_INSTANCE_EXT_PFN LOAD_INSTANCE_OPT_PFN
1021 #define VK_DEVICE_PFN LOAD_INSTANCE_PFN
1022 VK_INSTANCE_FUNCS()
1023 VK_DEVICE_FUNCS()
1024 #undef VK_INSTANCE_PFN
1025 #undef VK_INSTANCE_EXT_PFN
1026 #undef VK_DEVICE_PFN
1028 #define MAP_INSTANCE_FUNCTION(core_pfn, ext_pfn) \
1029 if (!vk_ops->core_pfn) \
1030 vk_ops->core_pfn = (void *)VK_CALL(vkGetInstanceProcAddr(instance, #ext_pfn));
1031 MAP_INSTANCE_FUNCTION(vkGetPhysicalDeviceProperties2, vkGetPhysicalDeviceProperties2KHR)
1032 #undef MAP_INSTANCE_FUNCTION
1034 vk_info->instance = instance;
1036 return TRUE;
1038 fail:
1039 if (vk_ops->vkDestroyInstance)
1040 VK_CALL(vkDestroyInstance(instance, NULL));
1041 wined3d_unload_vulkan(vk_info);
1042 return FALSE;
1045 static VkPhysicalDevice get_vulkan_physical_device(struct wined3d_vk_info *vk_info)
1047 VkPhysicalDevice physical_devices[1];
1048 uint32_t count;
1049 VkResult vr;
1051 if ((vr = VK_CALL(vkEnumeratePhysicalDevices(vk_info->instance, &count, NULL))) < 0)
1053 WARN("Failed to enumerate physical devices, vr %s.\n", wined3d_debug_vkresult(vr));
1054 return VK_NULL_HANDLE;
1056 if (!count)
1058 WARN("No physical device.\n");
1059 return VK_NULL_HANDLE;
1061 if (count > 1)
1063 /* TODO: Create wined3d_adapter for each device. */
1064 FIXME("Multiple physical devices available.\n");
1065 count = 1;
1068 if ((vr = VK_CALL(vkEnumeratePhysicalDevices(vk_info->instance, &count, physical_devices))) < 0)
1070 WARN("Failed to get physical devices, vr %s.\n", wined3d_debug_vkresult(vr));
1071 return VK_NULL_HANDLE;
1074 return physical_devices[0];
1077 static enum wined3d_display_driver guess_display_driver(enum wined3d_pci_vendor vendor)
1079 switch (vendor)
1081 case HW_VENDOR_AMD: return DRIVER_AMD_RX;
1082 case HW_VENDOR_INTEL: return DRIVER_INTEL_HD4000;
1083 case HW_VENDOR_NVIDIA: return DRIVER_NVIDIA_GEFORCE8;
1084 default: return DRIVER_WINE;
1088 static void adapter_vk_init_driver_info(struct wined3d_adapter *adapter,
1089 const VkPhysicalDeviceProperties *properties, const VkPhysicalDeviceMemoryProperties *memory_properties)
1091 const struct wined3d_gpu_description *gpu_description;
1092 struct wined3d_gpu_description description;
1093 UINT64 vram_bytes, sysmem_bytes;
1094 const VkMemoryHeap *heap;
1095 unsigned int i;
1097 TRACE("Device name: %s.\n", debugstr_a(properties->deviceName));
1098 TRACE("Vendor ID: 0x%04x, Device ID: 0x%04x.\n", properties->vendorID, properties->deviceID);
1099 TRACE("Driver version: %#x.\n", properties->driverVersion);
1100 TRACE("API version: %s.\n", debug_vk_version(properties->apiVersion));
1102 for (i = 0, vram_bytes = 0, sysmem_bytes = 0; i < memory_properties->memoryHeapCount; ++i)
1104 heap = &memory_properties->memoryHeaps[i];
1105 TRACE("Memory heap [%u]: flags %#x, size 0x%s.\n",
1106 i, heap->flags, wine_dbgstr_longlong(heap->size));
1107 if (heap->flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT)
1108 vram_bytes += heap->size;
1109 else
1110 sysmem_bytes += heap->size;
1112 TRACE("Total device memory: 0x%s.\n", wine_dbgstr_longlong(vram_bytes));
1113 TRACE("Total shared system memory: 0x%s.\n", wine_dbgstr_longlong(sysmem_bytes));
1115 if (!(gpu_description = wined3d_get_user_override_gpu_description(properties->vendorID, properties->deviceID)))
1116 gpu_description = wined3d_get_gpu_description(properties->vendorID, properties->deviceID);
1118 if (!gpu_description)
1120 FIXME("Failed to retrieve GPU description for device %s %04x:%04x.\n",
1121 debugstr_a(properties->deviceName), properties->vendorID, properties->deviceID);
1123 description.vendor = properties->vendorID;
1124 description.device = properties->deviceID;
1125 description.description = properties->deviceName;
1126 description.driver = guess_display_driver(properties->vendorID);
1127 description.vidmem = vram_bytes;
1129 gpu_description = &description;
1132 wined3d_driver_info_init(&adapter->driver_info, gpu_description, vram_bytes, sysmem_bytes);
1135 static void wined3d_adapter_vk_init_d3d_info(struct wined3d_adapter *adapter, uint32_t wined3d_creation_flags)
1137 struct wined3d_d3d_info *d3d_info = &adapter->d3d_info;
1139 d3d_info->wined3d_creation_flags = wined3d_creation_flags;
1141 d3d_info->texture_swizzle = TRUE;
1143 d3d_info->multisample_draw_location = WINED3D_LOCATION_TEXTURE_RGB;
1146 static BOOL wined3d_adapter_vk_init(struct wined3d_adapter_vk *adapter_vk,
1147 unsigned int ordinal, unsigned int wined3d_creation_flags)
1149 struct wined3d_vk_info *vk_info = &adapter_vk->vk_info;
1150 VkPhysicalDeviceMemoryProperties memory_properties;
1151 struct wined3d_adapter *adapter = &adapter_vk->a;
1152 VkPhysicalDeviceIDProperties id_properties;
1153 VkPhysicalDeviceProperties2 properties2;
1155 TRACE("adapter_vk %p, ordinal %u, wined3d_creation_flags %#x.\n",
1156 adapter_vk, ordinal, wined3d_creation_flags);
1158 if (!wined3d_adapter_init(adapter, ordinal, &wined3d_adapter_vk_ops))
1159 return FALSE;
1161 if (!wined3d_init_vulkan(vk_info))
1163 WARN("Failed to initialize Vulkan.\n");
1164 goto fail;
1167 if (!(adapter_vk->physical_device = get_vulkan_physical_device(vk_info)))
1168 goto fail_vulkan;
1170 memset(&id_properties, 0, sizeof(id_properties));
1171 id_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES;
1172 properties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
1173 properties2.pNext = &id_properties;
1175 if (vk_info->vk_ops.vkGetPhysicalDeviceProperties2)
1176 VK_CALL(vkGetPhysicalDeviceProperties2(adapter_vk->physical_device, &properties2));
1177 else
1178 VK_CALL(vkGetPhysicalDeviceProperties(adapter_vk->physical_device, &properties2.properties));
1179 adapter_vk->device_limits = properties2.properties.limits;
1181 VK_CALL(vkGetPhysicalDeviceMemoryProperties(adapter_vk->physical_device, &memory_properties));
1183 adapter_vk_init_driver_info(adapter, &properties2.properties, &memory_properties);
1184 adapter->vram_bytes_used = 0;
1185 TRACE("Emulating 0x%s bytes of video ram.\n", wine_dbgstr_longlong(adapter->driver_info.vram_bytes));
1187 memcpy(&adapter->driver_uuid, id_properties.driverUUID, sizeof(adapter->driver_uuid));
1188 memcpy(&adapter->device_uuid, id_properties.deviceUUID, sizeof(adapter->device_uuid));
1190 if (!wined3d_adapter_vk_init_format_info(adapter_vk, vk_info))
1191 goto fail_vulkan;
1193 adapter->vertex_pipe = &none_vertex_pipe;
1194 adapter->fragment_pipe = &none_fragment_pipe;
1195 adapter->shader_backend = &none_shader_backend;
1197 wined3d_adapter_vk_init_d3d_info(adapter, wined3d_creation_flags);
1199 return TRUE;
1201 fail_vulkan:
1202 VK_CALL(vkDestroyInstance(vk_info->instance, NULL));
1203 wined3d_unload_vulkan(vk_info);
1204 fail:
1205 wined3d_adapter_cleanup(adapter);
1206 return FALSE;
1209 struct wined3d_adapter *wined3d_adapter_vk_create(unsigned int ordinal,
1210 unsigned int wined3d_creation_flags)
1212 struct wined3d_adapter_vk *adapter_vk;
1214 if (!(adapter_vk = heap_alloc_zero(sizeof(*adapter_vk))))
1215 return NULL;
1217 if (!wined3d_adapter_vk_init(adapter_vk, ordinal, wined3d_creation_flags))
1219 heap_free(adapter_vk);
1220 return NULL;
1223 TRACE("Created adapter %p.\n", adapter_vk);
1225 return &adapter_vk->a;