crypt32: Implement CryptBinaryToStringW(HEXRAW).
[wine.git] / dlls / wined3d / adapter_vk.c
blob87e21b0b41faec200ab1c89a4e417d34748c9467
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));
236 device_vk->vk_queue_family_index = queue_family_index;
238 device_vk->vk_info = *vk_info;
239 #define LOAD_DEVICE_PFN(name) \
240 if (!(device_vk->vk_info.vk_ops.name = (void *)VK_CALL(vkGetDeviceProcAddr(vk_device, #name)))) \
242 WARN("Could not get device proc addr for '" #name "'.\n"); \
243 hr = E_FAIL; \
244 goto fail; \
246 #define VK_DEVICE_PFN LOAD_DEVICE_PFN
247 VK_DEVICE_FUNCS()
248 #undef VK_DEVICE_PFN
250 if (FAILED(hr = wined3d_device_init(&device_vk->d, wined3d, adapter->ordinal, device_type,
251 focus_window, flags, surface_alignment, levels, level_count, device_parent)))
253 WARN("Failed to initialize device, hr %#x.\n", hr);
254 goto fail;
257 *device = &device_vk->d;
259 return WINED3D_OK;
261 fail:
262 VK_CALL(vkDestroyDevice(vk_device, NULL));
263 heap_free(device_vk);
264 return hr;
267 static void adapter_vk_destroy_device(struct wined3d_device *device)
269 struct wined3d_device_vk *device_vk = wined3d_device_vk(device);
270 const struct wined3d_vk_info *vk_info = &device_vk->vk_info;
272 wined3d_device_cleanup(&device_vk->d);
273 VK_CALL(vkDestroyDevice(device_vk->vk_device, NULL));
274 heap_free(device_vk);
277 struct wined3d_context *adapter_vk_acquire_context(struct wined3d_device *device,
278 struct wined3d_texture *texture, unsigned int sub_resource_idx)
280 TRACE("device %p, texture %p, sub_resource_idx %u.\n", device, texture, sub_resource_idx);
282 wined3d_from_cs(device->cs);
284 if (!device->context_count)
285 return NULL;
287 return &wined3d_device_vk(device)->context_vk.c;
290 void adapter_vk_release_context(struct wined3d_context *context)
292 TRACE("context %p.\n", context);
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_BACKBUFFER
302 | WINEDDSCAPS_COMPLEX
303 | WINEDDSCAPS_FRONTBUFFER
304 | WINEDDSCAPS_3DDEVICE
305 | WINEDDSCAPS_VIDEOMEMORY
306 | WINEDDSCAPS_OWNDC
307 | WINEDDSCAPS_LOCALVIDMEM
308 | WINEDDSCAPS_NONLOCALVIDMEM;
309 caps->ddraw_caps.caps |= WINEDDCAPS_3D;
311 caps->Caps2 |= WINED3DCAPS2_CANGENMIPMAP;
313 caps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_BLENDOP
314 | WINED3DPMISCCAPS_INDEPENDENTWRITEMASKS
315 | WINED3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS
316 | WINED3DPMISCCAPS_POSTBLENDSRGBCONVERT
317 | WINED3DPMISCCAPS_SEPARATEALPHABLEND;
319 caps->RasterCaps |= WINED3DPRASTERCAPS_MIPMAPLODBIAS;
321 if (sampler_anisotropy)
323 caps->RasterCaps |= WINED3DPRASTERCAPS_ANISOTROPY;
325 caps->TextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC
326 | WINED3DPTFILTERCAPS_MINFANISOTROPIC;
328 caps->MaxAnisotropy = limits->maxSamplerAnisotropy;
331 caps->SrcBlendCaps |= WINED3DPBLENDCAPS_BLENDFACTOR;
332 caps->DestBlendCaps |= WINED3DPBLENDCAPS_BLENDFACTOR
333 | WINED3DPBLENDCAPS_SRCALPHASAT;
335 caps->TextureCaps |= WINED3DPTEXTURECAPS_VOLUMEMAP
336 | WINED3DPTEXTURECAPS_MIPVOLUMEMAP
337 | WINED3DPTEXTURECAPS_VOLUMEMAP_POW2;
338 caps->VolumeTextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFLINEAR
339 | WINED3DPTFILTERCAPS_MAGFPOINT
340 | WINED3DPTFILTERCAPS_MINFLINEAR
341 | WINED3DPTFILTERCAPS_MINFPOINT
342 | WINED3DPTFILTERCAPS_MIPFLINEAR
343 | WINED3DPTFILTERCAPS_MIPFPOINT
344 | WINED3DPTFILTERCAPS_LINEAR
345 | WINED3DPTFILTERCAPS_LINEARMIPLINEAR
346 | WINED3DPTFILTERCAPS_LINEARMIPNEAREST
347 | WINED3DPTFILTERCAPS_MIPLINEAR
348 | WINED3DPTFILTERCAPS_MIPNEAREST
349 | WINED3DPTFILTERCAPS_NEAREST;
350 caps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_INDEPENDENTUV
351 | WINED3DPTADDRESSCAPS_CLAMP
352 | WINED3DPTADDRESSCAPS_WRAP;
353 caps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER
354 | WINED3DPTADDRESSCAPS_MIRROR
355 | WINED3DPTADDRESSCAPS_MIRRORONCE;
357 caps->MaxVolumeExtent = limits->maxImageDimension3D;
359 caps->TextureCaps |= WINED3DPTEXTURECAPS_CUBEMAP
360 | WINED3DPTEXTURECAPS_MIPCUBEMAP
361 | WINED3DPTEXTURECAPS_CUBEMAP_POW2;
362 caps->CubeTextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFLINEAR
363 | WINED3DPTFILTERCAPS_MAGFPOINT
364 | WINED3DPTFILTERCAPS_MINFLINEAR
365 | WINED3DPTFILTERCAPS_MINFPOINT
366 | WINED3DPTFILTERCAPS_MIPFLINEAR
367 | WINED3DPTFILTERCAPS_MIPFPOINT
368 | WINED3DPTFILTERCAPS_LINEAR
369 | WINED3DPTFILTERCAPS_LINEARMIPLINEAR
370 | WINED3DPTFILTERCAPS_LINEARMIPNEAREST
371 | WINED3DPTFILTERCAPS_MIPLINEAR
372 | WINED3DPTFILTERCAPS_MIPNEAREST
373 | WINED3DPTFILTERCAPS_NEAREST;
375 if (sampler_anisotropy)
377 caps->CubeTextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC
378 | WINED3DPTFILTERCAPS_MINFANISOTROPIC;
381 caps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER
382 | WINED3DPTADDRESSCAPS_MIRROR
383 | WINED3DPTADDRESSCAPS_MIRRORONCE;
385 caps->StencilCaps |= WINED3DSTENCILCAPS_DECR
386 | WINED3DSTENCILCAPS_INCR
387 | WINED3DSTENCILCAPS_TWOSIDED;
389 caps->DeclTypes |= WINED3DDTCAPS_FLOAT16_2 | WINED3DDTCAPS_FLOAT16_4;
391 caps->MaxPixelShader30InstructionSlots = WINED3DMAX30SHADERINSTRUCTIONS;
392 caps->MaxVertexShader30InstructionSlots = WINED3DMAX30SHADERINSTRUCTIONS;
393 caps->PS20Caps.temp_count = WINED3DPS20_MAX_NUMTEMPS;
394 caps->VS20Caps.temp_count = WINED3DVS20_MAX_NUMTEMPS;
397 static BOOL adapter_vk_check_format(const struct wined3d_adapter *adapter,
398 const struct wined3d_format *adapter_format, const struct wined3d_format *rt_format,
399 const struct wined3d_format *ds_format)
401 return TRUE;
404 static HRESULT adapter_vk_init_3d(struct wined3d_device *device)
406 struct wined3d_context_vk *context_vk;
407 struct wined3d_device_vk *device_vk;
408 HRESULT hr;
410 TRACE("device %p.\n", device);
412 device_vk = wined3d_device_vk(device);
413 context_vk = &device_vk->context_vk;
414 if (FAILED(hr = wined3d_context_vk_init(context_vk, device->swapchains[0])))
416 WARN("Failed to initialise context.\n");
417 return hr;
420 if (FAILED(hr = device->shader_backend->shader_alloc_private(device,
421 device->adapter->vertex_pipe, device->adapter->fragment_pipe)))
423 ERR("Failed to allocate shader private data, hr %#x.\n", hr);
424 wined3d_context_vk_cleanup(context_vk);
425 return hr;
428 if (!device_context_add(device, &context_vk->c))
430 ERR("Failed to add the newly created context to the context list.\n");
431 device->shader_backend->shader_free_private(device, NULL);
432 wined3d_context_vk_cleanup(context_vk);
433 return E_FAIL;
436 TRACE("Initialised context %p.\n", context_vk);
438 if (!(device_vk->d.blitter = wined3d_cpu_blitter_create()))
440 ERR("Failed to create CPU blitter.\n");
441 device_context_remove(device, &context_vk->c);
442 device->shader_backend->shader_free_private(device, NULL);
443 wined3d_context_vk_cleanup(context_vk);
444 return E_FAIL;
447 wined3d_device_create_default_samplers(device, &context_vk->c);
449 return WINED3D_OK;
452 static void adapter_vk_uninit_3d_cs(void *object)
454 struct wined3d_device_vk *device_vk = object;
455 struct wined3d_context_vk *context_vk;
456 struct wined3d_device *device;
457 struct wined3d_shader *shader;
459 TRACE("device_vk %p.\n", device_vk);
461 context_vk = &device_vk->context_vk;
462 device = &device_vk->d;
464 LIST_FOR_EACH_ENTRY(shader, &device->shaders, struct wined3d_shader, shader_list_entry)
466 device->shader_backend->shader_destroy(shader);
469 device->blitter->ops->blitter_destroy(device->blitter, NULL);
470 device->shader_backend->shader_free_private(device, &context_vk->c);
471 wined3d_device_destroy_default_samplers(device, &context_vk->c);
474 static void adapter_vk_uninit_3d(struct wined3d_device *device)
476 struct wined3d_context_vk *context_vk;
477 struct wined3d_device_vk *device_vk;
479 TRACE("device %p.\n", device);
481 device_vk = wined3d_device_vk(device);
482 context_vk = &device_vk->context_vk;
484 wined3d_cs_destroy_object(device->cs, adapter_vk_uninit_3d_cs, device_vk);
485 wined3d_cs_finish(device->cs, WINED3D_CS_QUEUE_DEFAULT);
487 device_context_remove(device, &context_vk->c);
488 wined3d_context_vk_cleanup(context_vk);
491 static void *adapter_vk_map_bo_address(struct wined3d_context *context,
492 const struct wined3d_bo_address *data, size_t size, uint32_t bind_flags, uint32_t map_flags)
494 struct wined3d_context_vk *context_vk = wined3d_context_vk(context);
495 const struct wined3d_vk_info *vk_info;
496 struct wined3d_device_vk *device_vk;
497 VkCommandBuffer vk_command_buffer;
498 VkBufferMemoryBarrier vk_barrier;
499 struct wined3d_bo_vk *bo;
500 void *map_ptr;
501 VkResult vr;
503 if (!(bo = (struct wined3d_bo_vk *)data->buffer_object))
504 return data->addr;
506 vk_info = context_vk->vk_info;
507 device_vk = wined3d_device_vk(context->device);
509 if (!(vk_command_buffer = wined3d_context_vk_get_command_buffer(context_vk)))
511 ERR("Failed to get command buffer.\n");
512 return NULL;
515 vk_barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
516 vk_barrier.pNext = NULL;
517 vk_barrier.srcAccessMask = vk_access_mask_from_bind_flags(bind_flags);
518 vk_barrier.dstAccessMask = VK_ACCESS_HOST_READ_BIT;
519 vk_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
520 vk_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
521 vk_barrier.buffer = bo->vk_buffer;
522 vk_barrier.offset = (uintptr_t)data->addr;
523 vk_barrier.size = size;
524 VK_CALL(vkCmdPipelineBarrier(vk_command_buffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
525 VK_PIPELINE_STAGE_HOST_BIT, 0, 0, NULL, 1, &vk_barrier, 0, NULL));
527 wined3d_context_vk_submit_command_buffer(context_vk);
528 wined3d_context_vk_wait_command_buffer(context_vk, context_vk->current_command_buffer.id - 1);
530 if ((vr = VK_CALL(vkMapMemory(device_vk->vk_device, bo->vk_memory,
531 (uintptr_t)data->addr, size, 0, &map_ptr))) < 0)
533 ERR("Failed to map buffer, vr %s.\n", wined3d_debug_vkresult(vr));
534 return NULL;
537 return map_ptr;
540 static void adapter_vk_unmap_bo_address(struct wined3d_context *context, const struct wined3d_bo_address *data,
541 uint32_t bind_flags, unsigned int range_count, const struct wined3d_map_range *ranges)
543 const struct wined3d_vk_info *vk_info;
544 struct wined3d_device_vk *device_vk;
545 struct wined3d_bo_vk *bo;
547 if (!(bo = (struct wined3d_bo_vk *)data->buffer_object))
548 return;
550 vk_info = wined3d_context_vk(context)->vk_info;
551 device_vk = wined3d_device_vk(context->device);
552 VK_CALL(vkUnmapMemory(device_vk->vk_device, bo->vk_memory));
555 static void adapter_vk_copy_bo_address(struct wined3d_context *context,
556 const struct wined3d_bo_address *dst, uint32_t dst_bind_flags,
557 const struct wined3d_bo_address *src, uint32_t src_bind_flags, size_t size)
559 struct wined3d_map_range range;
560 void *dst_ptr, *src_ptr;
562 src_ptr = adapter_vk_map_bo_address(context, src, size, src_bind_flags, WINED3D_MAP_READ);
563 dst_ptr = adapter_vk_map_bo_address(context, dst, size, dst_bind_flags, WINED3D_MAP_WRITE);
565 memcpy(dst_ptr, src_ptr, size);
567 range.offset = 0;
568 range.size = size;
569 adapter_vk_unmap_bo_address(context, dst, dst_bind_flags, 1, &range);
570 adapter_vk_unmap_bo_address(context, src, src_bind_flags, 0, NULL);
573 static HRESULT adapter_vk_create_swapchain(struct wined3d_device *device, struct wined3d_swapchain_desc *desc,
574 void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_swapchain **swapchain)
576 struct wined3d_swapchain *swapchain_vk;
577 HRESULT hr;
579 TRACE("device %p, desc %p, parent %p, parent_ops %p, swapchain %p.\n",
580 device, desc, parent, parent_ops, swapchain);
582 if (!(swapchain_vk = heap_alloc_zero(sizeof(*swapchain_vk))))
583 return E_OUTOFMEMORY;
585 if (FAILED(hr = wined3d_swapchain_vk_init(swapchain_vk, device, desc, parent, parent_ops)))
587 WARN("Failed to initialise swapchain, hr %#x.\n", hr);
588 heap_free(swapchain_vk);
589 return hr;
592 TRACE("Created swapchain %p.\n", swapchain_vk);
593 *swapchain = swapchain_vk;
595 return hr;
598 static void adapter_vk_destroy_swapchain(struct wined3d_swapchain *swapchain)
600 wined3d_swapchain_cleanup(swapchain);
601 heap_free(swapchain);
604 unsigned int wined3d_adapter_vk_get_memory_type_index(const struct wined3d_adapter_vk *adapter_vk,
605 uint32_t memory_type_mask, VkMemoryPropertyFlags flags)
607 const VkPhysicalDeviceMemoryProperties *memory_info = &adapter_vk->memory_properties;
608 unsigned int i;
610 for (i = 0; i < memory_info->memoryTypeCount; ++i)
612 if (!(memory_type_mask & (1u << i)))
613 continue;
614 if ((memory_info->memoryTypes[i].propertyFlags & flags) == flags)
615 return i;
618 return ~0u;
621 static HRESULT adapter_vk_create_buffer(struct wined3d_device *device,
622 const struct wined3d_buffer_desc *desc, const struct wined3d_sub_resource_data *data,
623 void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_buffer **buffer)
625 struct wined3d_buffer_vk *buffer_vk;
626 HRESULT hr;
628 TRACE("device %p, desc %p, data %p, parent %p, parent_ops %p, buffer %p.\n",
629 device, desc, data, parent, parent_ops, buffer);
631 if (!(buffer_vk = heap_alloc_zero(sizeof(*buffer_vk))))
632 return E_OUTOFMEMORY;
634 if (FAILED(hr = wined3d_buffer_vk_init(buffer_vk, device, desc, data, parent, parent_ops)))
636 WARN("Failed to initialise buffer, hr %#x.\n", hr);
637 heap_free(buffer_vk);
638 return hr;
641 TRACE("Created buffer %p.\n", buffer_vk);
642 *buffer = &buffer_vk->b;
644 return hr;
647 static void adapter_vk_destroy_buffer(struct wined3d_buffer *buffer)
649 struct wined3d_buffer_vk *buffer_vk = wined3d_buffer_vk(buffer);
650 struct wined3d_device *device = buffer_vk->b.resource.device;
651 unsigned int swapchain_count = device->swapchain_count;
653 TRACE("buffer_vk %p.\n", buffer_vk);
655 /* Take a reference to the device, in case releasing the buffer would
656 * cause the device to be destroyed. However, swapchain resources don't
657 * take a reference to the device, and we wouldn't want to increment the
658 * refcount on a device that's in the process of being destroyed. */
659 if (swapchain_count)
660 wined3d_device_incref(device);
661 wined3d_buffer_cleanup(&buffer_vk->b);
662 wined3d_cs_destroy_object(device->cs, heap_free, buffer_vk);
663 if (swapchain_count)
664 wined3d_device_decref(device);
667 static HRESULT adapter_vk_create_texture(struct wined3d_device *device,
668 const struct wined3d_resource_desc *desc, unsigned int layer_count, unsigned int level_count,
669 uint32_t flags, void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_texture **texture)
671 struct wined3d_texture_vk *texture_vk;
672 HRESULT hr;
674 TRACE("device %p, desc %p, layer_count %u, level_count %u, flags %#x, parent %p, parent_ops %p, texture %p.\n",
675 device, desc, layer_count, level_count, flags, parent, parent_ops, texture);
677 if (!(texture_vk = wined3d_texture_allocate_object_memory(sizeof(*texture_vk), level_count, layer_count)))
678 return E_OUTOFMEMORY;
680 if (FAILED(hr = wined3d_texture_vk_init(texture_vk, device, desc,
681 layer_count, level_count, flags, parent, parent_ops)))
683 WARN("Failed to initialise texture, hr %#x.\n", hr);
684 heap_free(texture_vk);
685 return hr;
688 TRACE("Created texture %p.\n", texture_vk);
689 *texture = &texture_vk->t;
691 return hr;
694 static void adapter_vk_destroy_texture(struct wined3d_texture *texture)
696 struct wined3d_texture_vk *texture_vk = wined3d_texture_vk(texture);
697 struct wined3d_device *device = texture_vk->t.resource.device;
698 unsigned int swapchain_count = device->swapchain_count;
700 TRACE("texture_vk %p.\n", texture_vk);
702 /* Take a reference to the device, in case releasing the texture would
703 * cause the device to be destroyed. However, swapchain resources don't
704 * take a reference to the device, and we wouldn't want to increment the
705 * refcount on a device that's in the process of being destroyed. */
706 if (swapchain_count)
707 wined3d_device_incref(device);
709 wined3d_texture_sub_resources_destroyed(texture);
710 texture->resource.parent_ops->wined3d_object_destroyed(texture->resource.parent);
712 wined3d_texture_cleanup(&texture_vk->t);
713 wined3d_cs_destroy_object(device->cs, heap_free, texture_vk);
715 if (swapchain_count)
716 wined3d_device_decref(device);
719 static HRESULT adapter_vk_create_rendertarget_view(const struct wined3d_view_desc *desc,
720 struct wined3d_resource *resource, void *parent, const struct wined3d_parent_ops *parent_ops,
721 struct wined3d_rendertarget_view **view)
723 struct wined3d_rendertarget_view_vk *view_vk;
724 HRESULT hr;
726 TRACE("desc %s, resource %p, parent %p, parent_ops %p, view %p.\n",
727 wined3d_debug_view_desc(desc, resource), resource, parent, parent_ops, view);
729 if (!(view_vk = heap_alloc_zero(sizeof(*view_vk))))
730 return E_OUTOFMEMORY;
732 if (FAILED(hr = wined3d_rendertarget_view_vk_init(view_vk, desc, resource, parent, parent_ops)))
734 WARN("Failed to initialise view, hr %#x.\n", hr);
735 heap_free(view_vk);
736 return hr;
739 TRACE("Created render target view %p.\n", view_vk);
740 *view = &view_vk->v;
742 return hr;
745 static void adapter_vk_destroy_rendertarget_view(struct wined3d_rendertarget_view *view)
747 struct wined3d_rendertarget_view_vk *view_vk = wined3d_rendertarget_view_vk(view);
748 struct wined3d_device *device = view_vk->v.resource->device;
749 unsigned int swapchain_count = device->swapchain_count;
751 TRACE("view_vk %p.\n", view_vk);
753 /* Take a reference to the device, in case releasing the view's resource
754 * would cause the device to be destroyed. However, swapchain resources
755 * don't take a reference to the device, and we wouldn't want to increment
756 * the refcount on a device that's in the process of being destroyed. */
757 if (swapchain_count)
758 wined3d_device_incref(device);
759 wined3d_rendertarget_view_cleanup(&view_vk->v);
760 wined3d_cs_destroy_object(device->cs, heap_free, view_vk);
761 if (swapchain_count)
762 wined3d_device_decref(device);
765 static HRESULT adapter_vk_create_shader_resource_view(const struct wined3d_view_desc *desc,
766 struct wined3d_resource *resource, void *parent, const struct wined3d_parent_ops *parent_ops,
767 struct wined3d_shader_resource_view **view)
769 struct wined3d_shader_resource_view_vk *view_vk;
770 HRESULT hr;
772 TRACE("desc %s, resource %p, parent %p, parent_ops %p, view %p.\n",
773 wined3d_debug_view_desc(desc, resource), resource, parent, parent_ops, view);
775 if (!(view_vk = heap_alloc_zero(sizeof(*view_vk))))
776 return E_OUTOFMEMORY;
778 if (FAILED(hr = wined3d_shader_resource_view_vk_init(view_vk, desc, resource, parent, parent_ops)))
780 WARN("Failed to initialise view, hr %#x.\n", hr);
781 heap_free(view_vk);
782 return hr;
785 TRACE("Created shader resource view %p.\n", view_vk);
786 *view = &view_vk->v;
788 return hr;
791 static void adapter_vk_destroy_shader_resource_view(struct wined3d_shader_resource_view *view)
793 struct wined3d_shader_resource_view_vk *view_vk = wined3d_shader_resource_view_vk(view);
794 struct wined3d_device *device = view_vk->v.resource->device;
795 unsigned int swapchain_count = device->swapchain_count;
797 TRACE("view_vk %p.\n", view_vk);
799 /* Take a reference to the device, in case releasing the view's resource
800 * would cause the device to be destroyed. However, swapchain resources
801 * don't take a reference to the device, and we wouldn't want to increment
802 * the refcount on a device that's in the process of being destroyed. */
803 if (swapchain_count)
804 wined3d_device_incref(device);
805 wined3d_shader_resource_view_cleanup(&view_vk->v);
806 wined3d_cs_destroy_object(device->cs, heap_free, view_vk);
807 if (swapchain_count)
808 wined3d_device_decref(device);
811 static HRESULT adapter_vk_create_unordered_access_view(const struct wined3d_view_desc *desc,
812 struct wined3d_resource *resource, void *parent, const struct wined3d_parent_ops *parent_ops,
813 struct wined3d_unordered_access_view **view)
815 struct wined3d_unordered_access_view_vk *view_vk;
816 HRESULT hr;
818 TRACE("desc %s, resource %p, parent %p, parent_ops %p, view %p.\n",
819 wined3d_debug_view_desc(desc, resource), resource, parent, parent_ops, view);
821 if (!(view_vk = heap_alloc_zero(sizeof(*view_vk))))
822 return E_OUTOFMEMORY;
824 if (FAILED(hr = wined3d_unordered_access_view_vk_init(view_vk, desc, resource, parent, parent_ops)))
826 WARN("Failed to initialise view, hr %#x.\n", hr);
827 heap_free(view_vk);
828 return hr;
831 TRACE("Created unordered access view %p.\n", view_vk);
832 *view = &view_vk->v;
834 return hr;
837 static void adapter_vk_destroy_unordered_access_view(struct wined3d_unordered_access_view *view)
839 struct wined3d_unordered_access_view_vk *view_vk = wined3d_unordered_access_view_vk(view);
840 struct wined3d_device *device = view_vk->v.resource->device;
841 unsigned int swapchain_count = device->swapchain_count;
843 TRACE("view_vk %p.\n", view_vk);
845 /* Take a reference to the device, in case releasing the view's resource
846 * would cause the device to be destroyed. However, swapchain resources
847 * don't take a reference to the device, and we wouldn't want to increment
848 * the refcount on a device that's in the process of being destroyed. */
849 if (swapchain_count)
850 wined3d_device_incref(device);
851 wined3d_unordered_access_view_cleanup(&view_vk->v);
852 wined3d_cs_destroy_object(device->cs, heap_free, view_vk);
853 if (swapchain_count)
854 wined3d_device_decref(device);
857 static HRESULT adapter_vk_create_sampler(struct wined3d_device *device, const struct wined3d_sampler_desc *desc,
858 void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_sampler **sampler)
860 struct wined3d_sampler *sampler_vk;
862 TRACE("device %p, desc %p, parent %p, parent_ops %p, sampler %p.\n",
863 device, desc, parent, parent_ops, sampler);
865 if (!(sampler_vk = heap_alloc_zero(sizeof(*sampler_vk))))
866 return E_OUTOFMEMORY;
868 wined3d_sampler_vk_init(sampler_vk, device, desc, parent, parent_ops);
870 TRACE("Created sampler %p.\n", sampler_vk);
871 *sampler = sampler_vk;
873 return WINED3D_OK;
876 static void adapter_vk_destroy_sampler(struct wined3d_sampler *sampler)
878 TRACE("sampler %p.\n", sampler);
880 wined3d_cs_destroy_object(sampler->device->cs, heap_free, sampler);
883 static HRESULT adapter_vk_create_query(struct wined3d_device *device, enum wined3d_query_type type,
884 void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_query **query)
886 TRACE("device %p, type %#x, parent %p, parent_ops %p, query %p.\n",
887 device, type, parent, parent_ops, query);
889 return WINED3DERR_NOTAVAILABLE;
892 static void adapter_vk_destroy_query(struct wined3d_query *query)
894 TRACE("query %p.\n", query);
897 static void adapter_vk_flush_context(struct wined3d_context *context)
899 TRACE("context %p.\n", context);
902 void adapter_vk_clear_uav(struct wined3d_context *context,
903 struct wined3d_unordered_access_view *view, const struct wined3d_uvec4 *clear_value)
905 FIXME("context %p, view %p, clear_value %s.\n", context, view, debug_uvec4(clear_value));
908 static const struct wined3d_adapter_ops wined3d_adapter_vk_ops =
910 adapter_vk_destroy,
911 adapter_vk_create_device,
912 adapter_vk_destroy_device,
913 adapter_vk_acquire_context,
914 adapter_vk_release_context,
915 adapter_vk_get_wined3d_caps,
916 adapter_vk_check_format,
917 adapter_vk_init_3d,
918 adapter_vk_uninit_3d,
919 adapter_vk_map_bo_address,
920 adapter_vk_unmap_bo_address,
921 adapter_vk_copy_bo_address,
922 adapter_vk_create_swapchain,
923 adapter_vk_destroy_swapchain,
924 adapter_vk_create_buffer,
925 adapter_vk_destroy_buffer,
926 adapter_vk_create_texture,
927 adapter_vk_destroy_texture,
928 adapter_vk_create_rendertarget_view,
929 adapter_vk_destroy_rendertarget_view,
930 adapter_vk_create_shader_resource_view,
931 adapter_vk_destroy_shader_resource_view,
932 adapter_vk_create_unordered_access_view,
933 adapter_vk_destroy_unordered_access_view,
934 adapter_vk_create_sampler,
935 adapter_vk_destroy_sampler,
936 adapter_vk_create_query,
937 adapter_vk_destroy_query,
938 adapter_vk_flush_context,
939 adapter_vk_clear_uav,
942 static unsigned int wined3d_get_wine_vk_version(void)
944 const char *ptr = PACKAGE_VERSION;
945 int major, minor;
947 major = atoi(ptr);
949 while (isdigit(*ptr))
950 ++ptr;
951 if (*ptr == '.')
952 ++ptr;
954 minor = atoi(ptr);
956 return VK_MAKE_VERSION(major, minor, 0);
959 static const struct
961 const char *name;
962 unsigned int core_since_version;
963 BOOL required;
965 vulkan_instance_extensions[] =
967 {VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, VK_API_VERSION_1_1, FALSE},
970 static BOOL enable_vulkan_instance_extensions(uint32_t *extension_count,
971 const char *enabled_extensions[], const struct wined3d_vk_info *vk_info)
973 PFN_vkEnumerateInstanceExtensionProperties pfn_vkEnumerateInstanceExtensionProperties;
974 VkExtensionProperties *extensions = NULL;
975 BOOL success = FALSE, found;
976 unsigned int i, j, count;
977 VkResult vr;
979 *extension_count = 0;
981 if (!(pfn_vkEnumerateInstanceExtensionProperties
982 = (void *)VK_CALL(vkGetInstanceProcAddr(NULL, "vkEnumerateInstanceExtensionProperties"))))
984 WARN("Failed to get 'vkEnumerateInstanceExtensionProperties'.\n");
985 goto done;
988 if ((vr = pfn_vkEnumerateInstanceExtensionProperties(NULL, &count, NULL)) < 0)
990 WARN("Failed to count instance extensions, vr %s.\n", wined3d_debug_vkresult(vr));
991 goto done;
993 if (!(extensions = heap_calloc(count, sizeof(*extensions))))
995 WARN("Out of memory.\n");
996 goto done;
998 if ((vr = pfn_vkEnumerateInstanceExtensionProperties(NULL, &count, extensions)) < 0)
1000 WARN("Failed to enumerate extensions, vr %s.\n", wined3d_debug_vkresult(vr));
1001 goto done;
1004 for (i = 0; i < ARRAY_SIZE(vulkan_instance_extensions); ++i)
1006 if (vulkan_instance_extensions[i].core_since_version <= vk_info->api_version)
1007 continue;
1009 for (j = 0, found = FALSE; j < count; ++j)
1011 if (!strcmp(extensions[j].extensionName, vulkan_instance_extensions[i].name))
1013 found = TRUE;
1014 break;
1017 if (found)
1019 TRACE("Enabling instance extension '%s'.\n", vulkan_instance_extensions[i].name);
1020 enabled_extensions[(*extension_count)++] = vulkan_instance_extensions[i].name;
1022 else if (!found && vulkan_instance_extensions[i].required)
1024 WARN("Required extension '%s' is not available.\n", vulkan_instance_extensions[i].name);
1025 goto done;
1028 success = TRUE;
1030 done:
1031 heap_free(extensions);
1032 return success;
1035 static BOOL wined3d_init_vulkan(struct wined3d_vk_info *vk_info)
1037 const char *enabled_instance_extensions[ARRAY_SIZE(vulkan_instance_extensions)];
1038 PFN_vkEnumerateInstanceVersion pfn_vkEnumerateInstanceVersion;
1039 struct vulkan_ops *vk_ops = &vk_info->vk_ops;
1040 VkInstance instance = VK_NULL_HANDLE;
1041 VkInstanceCreateInfo instance_info;
1042 VkApplicationInfo app_info;
1043 uint32_t api_version = 0;
1044 char app_name[MAX_PATH];
1045 VkResult vr;
1047 if (!wined3d_load_vulkan(vk_info))
1048 return FALSE;
1050 if (!(vk_ops->vkCreateInstance = (void *)VK_CALL(vkGetInstanceProcAddr(NULL, "vkCreateInstance"))))
1052 ERR("Failed to get 'vkCreateInstance'.\n");
1053 goto fail;
1056 vk_info->api_version = VK_API_VERSION_1_0;
1057 if ((pfn_vkEnumerateInstanceVersion = (void *)VK_CALL(vkGetInstanceProcAddr(NULL, "vkEnumerateInstanceVersion")))
1058 && pfn_vkEnumerateInstanceVersion(&api_version) == VK_SUCCESS)
1060 TRACE("Vulkan instance API version %s.\n", debug_vk_version(api_version));
1062 if (api_version >= VK_API_VERSION_1_1)
1063 vk_info->api_version = VK_API_VERSION_1_1;
1066 memset(&app_info, 0, sizeof(app_info));
1067 app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
1068 if (wined3d_get_app_name(app_name, ARRAY_SIZE(app_name)))
1069 app_info.pApplicationName = app_name;
1070 app_info.pEngineName = "Damavand";
1071 app_info.engineVersion = wined3d_get_wine_vk_version();
1072 app_info.apiVersion = vk_info->api_version;
1074 memset(&instance_info, 0, sizeof(instance_info));
1075 instance_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
1076 instance_info.pApplicationInfo = &app_info;
1077 instance_info.ppEnabledExtensionNames = enabled_instance_extensions;
1078 if (!enable_vulkan_instance_extensions(&instance_info.enabledExtensionCount, enabled_instance_extensions, vk_info))
1079 goto fail;
1081 if ((vr = VK_CALL(vkCreateInstance(&instance_info, NULL, &instance))) < 0)
1083 WARN("Failed to create Vulkan instance, vr %s.\n", wined3d_debug_vkresult(vr));
1084 goto fail;
1087 TRACE("Created Vulkan instance %p.\n", instance);
1089 #define LOAD_INSTANCE_PFN(name) \
1090 if (!(vk_ops->name = (void *)VK_CALL(vkGetInstanceProcAddr(instance, #name)))) \
1092 WARN("Could not get instance proc addr for '" #name "'.\n"); \
1093 goto fail; \
1095 #define LOAD_INSTANCE_OPT_PFN(name) \
1096 vk_ops->name = (void *)VK_CALL(vkGetInstanceProcAddr(instance, #name));
1097 #define VK_INSTANCE_PFN LOAD_INSTANCE_PFN
1098 #define VK_INSTANCE_EXT_PFN LOAD_INSTANCE_OPT_PFN
1099 #define VK_DEVICE_PFN LOAD_INSTANCE_PFN
1100 VK_INSTANCE_FUNCS()
1101 VK_DEVICE_FUNCS()
1102 #undef VK_INSTANCE_PFN
1103 #undef VK_INSTANCE_EXT_PFN
1104 #undef VK_DEVICE_PFN
1106 #define MAP_INSTANCE_FUNCTION(core_pfn, ext_pfn) \
1107 if (!vk_ops->core_pfn) \
1108 vk_ops->core_pfn = (void *)VK_CALL(vkGetInstanceProcAddr(instance, #ext_pfn));
1109 MAP_INSTANCE_FUNCTION(vkGetPhysicalDeviceProperties2, vkGetPhysicalDeviceProperties2KHR)
1110 #undef MAP_INSTANCE_FUNCTION
1112 vk_info->instance = instance;
1114 return TRUE;
1116 fail:
1117 if (vk_ops->vkDestroyInstance)
1118 VK_CALL(vkDestroyInstance(instance, NULL));
1119 wined3d_unload_vulkan(vk_info);
1120 return FALSE;
1123 static VkPhysicalDevice get_vulkan_physical_device(struct wined3d_vk_info *vk_info)
1125 VkPhysicalDevice physical_devices[1];
1126 uint32_t count;
1127 VkResult vr;
1129 if ((vr = VK_CALL(vkEnumeratePhysicalDevices(vk_info->instance, &count, NULL))) < 0)
1131 WARN("Failed to enumerate physical devices, vr %s.\n", wined3d_debug_vkresult(vr));
1132 return VK_NULL_HANDLE;
1134 if (!count)
1136 WARN("No physical device.\n");
1137 return VK_NULL_HANDLE;
1139 if (count > 1)
1141 /* TODO: Create wined3d_adapter for each device. */
1142 FIXME("Multiple physical devices available.\n");
1143 count = 1;
1146 if ((vr = VK_CALL(vkEnumeratePhysicalDevices(vk_info->instance, &count, physical_devices))) < 0)
1148 WARN("Failed to get physical devices, vr %s.\n", wined3d_debug_vkresult(vr));
1149 return VK_NULL_HANDLE;
1152 return physical_devices[0];
1155 static enum wined3d_display_driver guess_display_driver(enum wined3d_pci_vendor vendor)
1157 switch (vendor)
1159 case HW_VENDOR_AMD: return DRIVER_AMD_RX;
1160 case HW_VENDOR_INTEL: return DRIVER_INTEL_HD4000;
1161 case HW_VENDOR_NVIDIA: return DRIVER_NVIDIA_GEFORCE8;
1162 default: return DRIVER_WINE;
1166 static void adapter_vk_init_driver_info(struct wined3d_adapter_vk *adapter_vk,
1167 const VkPhysicalDeviceProperties *properties)
1169 const VkPhysicalDeviceMemoryProperties *memory_properties = &adapter_vk->memory_properties;
1170 const struct wined3d_gpu_description *gpu_description;
1171 struct wined3d_gpu_description description;
1172 UINT64 vram_bytes, sysmem_bytes;
1173 const VkMemoryHeap *heap;
1174 unsigned int i;
1176 TRACE("Device name: %s.\n", debugstr_a(properties->deviceName));
1177 TRACE("Vendor ID: 0x%04x, Device ID: 0x%04x.\n", properties->vendorID, properties->deviceID);
1178 TRACE("Driver version: %#x.\n", properties->driverVersion);
1179 TRACE("API version: %s.\n", debug_vk_version(properties->apiVersion));
1181 for (i = 0, vram_bytes = 0, sysmem_bytes = 0; i < memory_properties->memoryHeapCount; ++i)
1183 heap = &memory_properties->memoryHeaps[i];
1184 TRACE("Memory heap [%u]: flags %#x, size 0x%s.\n",
1185 i, heap->flags, wine_dbgstr_longlong(heap->size));
1186 if (heap->flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT)
1187 vram_bytes += heap->size;
1188 else
1189 sysmem_bytes += heap->size;
1191 TRACE("Total device memory: 0x%s.\n", wine_dbgstr_longlong(vram_bytes));
1192 TRACE("Total shared system memory: 0x%s.\n", wine_dbgstr_longlong(sysmem_bytes));
1194 if (!(gpu_description = wined3d_get_user_override_gpu_description(properties->vendorID, properties->deviceID)))
1195 gpu_description = wined3d_get_gpu_description(properties->vendorID, properties->deviceID);
1197 if (!gpu_description)
1199 FIXME("Failed to retrieve GPU description for device %s %04x:%04x.\n",
1200 debugstr_a(properties->deviceName), properties->vendorID, properties->deviceID);
1202 description.vendor = properties->vendorID;
1203 description.device = properties->deviceID;
1204 description.description = properties->deviceName;
1205 description.driver = guess_display_driver(properties->vendorID);
1206 description.vidmem = vram_bytes;
1208 gpu_description = &description;
1211 wined3d_driver_info_init(&adapter_vk->a.driver_info, gpu_description, vram_bytes, sysmem_bytes);
1214 static void wined3d_adapter_vk_init_d3d_info(struct wined3d_adapter *adapter, uint32_t wined3d_creation_flags)
1216 struct wined3d_d3d_info *d3d_info = &adapter->d3d_info;
1218 d3d_info->wined3d_creation_flags = wined3d_creation_flags;
1220 d3d_info->texture_swizzle = TRUE;
1222 d3d_info->multisample_draw_location = WINED3D_LOCATION_TEXTURE_RGB;
1225 static BOOL wined3d_adapter_vk_init(struct wined3d_adapter_vk *adapter_vk,
1226 unsigned int ordinal, unsigned int wined3d_creation_flags)
1228 struct wined3d_vk_info *vk_info = &adapter_vk->vk_info;
1229 struct wined3d_adapter *adapter = &adapter_vk->a;
1230 VkPhysicalDeviceIDProperties id_properties;
1231 VkPhysicalDeviceProperties2 properties2;
1233 TRACE("adapter_vk %p, ordinal %u, wined3d_creation_flags %#x.\n",
1234 adapter_vk, ordinal, wined3d_creation_flags);
1236 if (!wined3d_adapter_init(adapter, ordinal, &wined3d_adapter_vk_ops))
1237 return FALSE;
1239 if (!wined3d_init_vulkan(vk_info))
1241 WARN("Failed to initialize Vulkan.\n");
1242 goto fail;
1245 if (!(adapter_vk->physical_device = get_vulkan_physical_device(vk_info)))
1246 goto fail_vulkan;
1248 memset(&id_properties, 0, sizeof(id_properties));
1249 id_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES;
1250 properties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
1251 properties2.pNext = &id_properties;
1253 if (vk_info->vk_ops.vkGetPhysicalDeviceProperties2)
1254 VK_CALL(vkGetPhysicalDeviceProperties2(adapter_vk->physical_device, &properties2));
1255 else
1256 VK_CALL(vkGetPhysicalDeviceProperties(adapter_vk->physical_device, &properties2.properties));
1257 adapter_vk->device_limits = properties2.properties.limits;
1259 VK_CALL(vkGetPhysicalDeviceMemoryProperties(adapter_vk->physical_device, &adapter_vk->memory_properties));
1261 adapter_vk_init_driver_info(adapter_vk, &properties2.properties);
1262 adapter->vram_bytes_used = 0;
1263 TRACE("Emulating 0x%s bytes of video ram.\n", wine_dbgstr_longlong(adapter->driver_info.vram_bytes));
1265 memcpy(&adapter->driver_uuid, id_properties.driverUUID, sizeof(adapter->driver_uuid));
1266 memcpy(&adapter->device_uuid, id_properties.deviceUUID, sizeof(adapter->device_uuid));
1268 if (!wined3d_adapter_vk_init_format_info(adapter_vk, vk_info))
1269 goto fail_vulkan;
1271 adapter->vertex_pipe = &none_vertex_pipe;
1272 adapter->fragment_pipe = &none_fragment_pipe;
1273 adapter->shader_backend = &none_shader_backend;
1275 wined3d_adapter_vk_init_d3d_info(adapter, wined3d_creation_flags);
1277 return TRUE;
1279 fail_vulkan:
1280 VK_CALL(vkDestroyInstance(vk_info->instance, NULL));
1281 wined3d_unload_vulkan(vk_info);
1282 fail:
1283 wined3d_adapter_cleanup(adapter);
1284 return FALSE;
1287 struct wined3d_adapter *wined3d_adapter_vk_create(unsigned int ordinal,
1288 unsigned int wined3d_creation_flags)
1290 struct wined3d_adapter_vk *adapter_vk;
1292 if (!(adapter_vk = heap_alloc_zero(sizeof(*adapter_vk))))
1293 return NULL;
1295 if (!wined3d_adapter_vk_init(adapter_vk, ordinal, wined3d_creation_flags))
1297 heap_free(adapter_vk);
1298 return NULL;
1301 TRACE("Created adapter %p.\n", adapter_vk);
1303 return &adapter_vk->a;