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 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
)
44 case VK_ERROR_OUT_OF_HOST_MEMORY
:
45 WARN("Out of host memory.\n");
47 case VK_ERROR_OUT_OF_DEVICE_MEMORY
:
48 WARN("Out of device memory.\n");
50 case VK_ERROR_DEVICE_LOST
:
51 WARN("Device lost.\n");
53 case VK_ERROR_EXTENSION_NOT_PRESENT
:
54 WARN("Extension not present.\n");
57 FIXME("Unhandled VkResult %d.\n", vr
);
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");
73 vk_ops
->vkGetInstanceProcAddr
= (void *)GetProcAddress(vk_info
->vulkan_lib
, "vkGetInstanceProcAddr");
74 if (!vk_ops
->vkGetInstanceProcAddr
)
76 FreeLibrary(vk_info
->vulkan_lib
);
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
;
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
;
99 vk_funcs
= __wine_get_vulkan_driver(dc
, WINE_VULKAN_DRIVER_VERSION
);
105 vk_ops
->vkGetInstanceProcAddr
= (void *)vk_funcs
->p_vkGetInstanceProcAddr
;
109 static void wined3d_unload_vulkan(struct wined3d_vk_info
*vk_info
) {}
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
;
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
);
147 heap_free(queue_properties
);
149 WARN("Failed to find graphics queue.\n");
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
;
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
)))
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
);
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"); \
246 #define VK_DEVICE_PFN LOAD_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
);
257 *device
= &device_vk
->d
;
262 VK_CALL(vkDestroyDevice(vk_device
, NULL
));
263 heap_free(device_vk
);
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
)
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
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
)
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
;
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");
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
);
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
);
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
);
447 wined3d_device_create_default_samplers(device
, &context_vk
->c
);
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
;
503 if (!(bo
= (struct wined3d_bo_vk
*)data
->buffer_object
))
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");
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
));
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
))
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
);
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
;
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
);
592 TRACE("Created swapchain %p.\n", swapchain_vk
);
593 *swapchain
= swapchain_vk
;
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
;
610 for (i
= 0; i
< memory_info
->memoryTypeCount
; ++i
)
612 if (!(memory_type_mask
& (1u << i
)))
614 if ((memory_info
->memoryTypes
[i
].propertyFlags
& flags
) == flags
)
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
;
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
);
641 TRACE("Created buffer %p.\n", buffer_vk
);
642 *buffer
= &buffer_vk
->b
;
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. */
660 wined3d_device_incref(device
);
661 wined3d_buffer_cleanup(&buffer_vk
->b
);
662 wined3d_cs_destroy_object(device
->cs
, heap_free
, buffer_vk
);
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
;
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
);
688 TRACE("Created texture %p.\n", texture_vk
);
689 *texture
= &texture_vk
->t
;
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. */
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
);
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
;
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
);
739 TRACE("Created render target view %p.\n", view_vk
);
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. */
758 wined3d_device_incref(device
);
759 wined3d_rendertarget_view_cleanup(&view_vk
->v
);
760 wined3d_cs_destroy_object(device
->cs
, heap_free
, view_vk
);
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
;
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
);
785 TRACE("Created shader resource view %p.\n", view_vk
);
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. */
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
);
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
;
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
);
831 TRACE("Created unordered access view %p.\n", view_vk
);
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. */
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
);
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
;
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
=
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
,
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
;
949 while (isdigit(*ptr
))
956 return VK_MAKE_VERSION(major
, minor
, 0);
962 unsigned int core_since_version
;
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
;
979 *extension_count
= 0;
981 if (!(pfn_vkEnumerateInstanceExtensionProperties
982 = (void *)VK_CALL(vkGetInstanceProcAddr(NULL
, "vkEnumerateInstanceExtensionProperties"))))
984 WARN("Failed to get 'vkEnumerateInstanceExtensionProperties'.\n");
988 if ((vr
= pfn_vkEnumerateInstanceExtensionProperties(NULL
, &count
, NULL
)) < 0)
990 WARN("Failed to count instance extensions, vr %s.\n", wined3d_debug_vkresult(vr
));
993 if (!(extensions
= heap_calloc(count
, sizeof(*extensions
))))
995 WARN("Out of memory.\n");
998 if ((vr
= pfn_vkEnumerateInstanceExtensionProperties(NULL
, &count
, extensions
)) < 0)
1000 WARN("Failed to enumerate extensions, vr %s.\n", wined3d_debug_vkresult(vr
));
1004 for (i
= 0; i
< ARRAY_SIZE(vulkan_instance_extensions
); ++i
)
1006 if (vulkan_instance_extensions
[i
].core_since_version
<= vk_info
->api_version
)
1009 for (j
= 0, found
= FALSE
; j
< count
; ++j
)
1011 if (!strcmp(extensions
[j
].extensionName
, vulkan_instance_extensions
[i
].name
))
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
);
1031 heap_free(extensions
);
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
];
1047 if (!wined3d_load_vulkan(vk_info
))
1050 if (!(vk_ops
->vkCreateInstance
= (void *)VK_CALL(vkGetInstanceProcAddr(NULL
, "vkCreateInstance"))))
1052 ERR("Failed to get 'vkCreateInstance'.\n");
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
))
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
));
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"); \
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
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
;
1117 if (vk_ops
->vkDestroyInstance
)
1118 VK_CALL(vkDestroyInstance(instance
, NULL
));
1119 wined3d_unload_vulkan(vk_info
);
1123 static VkPhysicalDevice
get_vulkan_physical_device(struct wined3d_vk_info
*vk_info
)
1125 VkPhysicalDevice physical_devices
[1];
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
;
1136 WARN("No physical device.\n");
1137 return VK_NULL_HANDLE
;
1141 /* TODO: Create wined3d_adapter for each device. */
1142 FIXME("Multiple physical devices available.\n");
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
)
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
;
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
;
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
))
1239 if (!wined3d_init_vulkan(vk_info
))
1241 WARN("Failed to initialize Vulkan.\n");
1245 if (!(adapter_vk
->physical_device
= get_vulkan_physical_device(vk_info
)))
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
));
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
))
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
);
1280 VK_CALL(vkDestroyInstance(vk_info
->instance
, NULL
));
1281 wined3d_unload_vulkan(vk_info
);
1283 wined3d_adapter_cleanup(adapter
);
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
))))
1295 if (!wined3d_adapter_vk_init(adapter_vk
, ordinal
, wined3d_creation_flags
))
1297 heap_free(adapter_vk
);
1301 TRACE("Created adapter %p.\n", adapter_vk
);
1303 return &adapter_vk
->a
;