wined3d: Pass map flags to wined3d_context_copy_bo_address().
[wine.git] / dlls / wined3d / adapter_vk.c
bloba03ec37161e1e7776776784ee295d5f1cf37f984
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 "wined3d_private.h"
20 #include "wined3d_vk.h"
22 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
24 static const struct wined3d_state_entry_template misc_state_template_vk[] =
26 {STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_VERTEX), {STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_VERTEX), state_nop}},
27 {STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_HULL), {STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_HULL), state_nop}},
28 {STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_DOMAIN), {STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_DOMAIN), state_nop}},
29 {STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_GEOMETRY), {STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_GEOMETRY), state_nop}},
30 {STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_PIXEL), {STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_PIXEL), state_nop}},
31 {STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_COMPUTE), {STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_COMPUTE), state_nop}},
32 {STATE_GRAPHICS_SHADER_RESOURCE_BINDING, {STATE_GRAPHICS_SHADER_RESOURCE_BINDING, state_nop}},
33 {STATE_GRAPHICS_UNORDERED_ACCESS_VIEW_BINDING, {STATE_GRAPHICS_UNORDERED_ACCESS_VIEW_BINDING, state_nop}},
34 {STATE_COMPUTE_SHADER_RESOURCE_BINDING, {STATE_COMPUTE_SHADER_RESOURCE_BINDING, state_nop}},
35 {STATE_COMPUTE_UNORDERED_ACCESS_VIEW_BINDING, {STATE_COMPUTE_UNORDERED_ACCESS_VIEW_BINDING, state_nop}},
36 {STATE_STREAM_OUTPUT, {STATE_STREAM_OUTPUT, state_nop}},
37 {STATE_BLEND, {STATE_BLEND, state_nop}},
38 {STATE_BLEND_FACTOR, {STATE_BLEND_FACTOR, state_nop}},
39 {STATE_SAMPLE_MASK, {STATE_SAMPLE_MASK, state_nop}},
40 {STATE_STREAMSRC, {STATE_STREAMSRC, state_nop}},
41 {STATE_VDECL, {STATE_VDECL, state_nop}},
42 {STATE_DEPTH_STENCIL, {STATE_DEPTH_STENCIL, state_nop}},
43 {STATE_STENCIL_REF, {STATE_STENCIL_REF, state_nop}},
44 {STATE_DEPTH_BOUNDS, {STATE_DEPTH_BOUNDS, state_nop}},
45 {STATE_RASTERIZER, {STATE_RASTERIZER, state_nop}},
46 {STATE_SCISSORRECT, {STATE_SCISSORRECT, state_nop}},
47 {STATE_POINTSPRITECOORDORIGIN, {STATE_POINTSPRITECOORDORIGIN, state_nop}},
49 {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT00), {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT00), state_nop}},
50 {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT01), {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT00)}},
51 {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT10), {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT00)}},
52 {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT11), {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT00)}},
53 {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT00), {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT00), state_nop}},
54 {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT01), {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT00)}},
55 {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT10), {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT00)}},
56 {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT11), {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT00)}},
57 {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT00), {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT00), state_nop}},
58 {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT01), {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT00)}},
59 {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT10), {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT00)}},
60 {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT11), {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT00)}},
61 {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT00), {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT00), state_nop}},
62 {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT01), {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT00)}},
63 {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT10), {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT00)}},
64 {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT11), {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT00)}},
65 {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT00), {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT00), state_nop}},
66 {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT01), {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT00)}},
67 {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT10), {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT00)}},
68 {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT11), {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT00)}},
69 {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT00), {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT00), state_nop}},
70 {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT01), {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT00)}},
71 {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT10), {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT00)}},
72 {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT11), {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT00)}},
73 {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT00), {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT00), state_nop}},
74 {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT01), {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT00)}},
75 {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT10), {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT00)}},
76 {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT11), {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT00)}},
77 {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT00), {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT00), state_nop}},
78 {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT01), {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT00)}},
79 {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT10), {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT00)}},
80 {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT11), {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT00)}},
81 {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_LSCALE), {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_LSCALE), state_nop}},
82 {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_LOFFSET), {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_LSCALE)}},
83 {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_LSCALE), {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_LSCALE), state_nop}},
84 {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_LOFFSET), {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_LSCALE)}},
85 {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_LSCALE), {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_LSCALE), state_nop}},
86 {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_LOFFSET), {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_LSCALE)}},
87 {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_LSCALE), {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_LSCALE), state_nop}},
88 {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_LOFFSET), {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_LSCALE)}},
89 {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_LSCALE), {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_LSCALE), state_nop}},
90 {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_LOFFSET), {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_LSCALE)}},
91 {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_LSCALE), {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_LSCALE), state_nop}},
92 {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_LOFFSET), {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_LSCALE)}},
93 {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_LSCALE), {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_LSCALE), state_nop}},
94 {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_LOFFSET), {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_LSCALE)}},
95 {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_LSCALE), {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_LSCALE), state_nop}},
96 {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_LOFFSET), {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_LSCALE)}},
98 {STATE_VIEWPORT, {STATE_VIEWPORT, state_nop}},
99 {STATE_INDEXBUFFER, {STATE_INDEXBUFFER, state_nop}},
100 {STATE_RENDER(WINED3D_RS_LINEPATTERN), {STATE_RENDER(WINED3D_RS_LINEPATTERN), state_nop}},
101 {STATE_RENDER(WINED3D_RS_DITHERENABLE), {STATE_RENDER(WINED3D_RS_DITHERENABLE), state_nop}},
102 {STATE_RENDER(WINED3D_RS_MULTISAMPLEANTIALIAS), {STATE_RENDER(WINED3D_RS_MULTISAMPLEANTIALIAS), state_nop}},
103 /* Samplers */
104 {STATE_SAMPLER(0), {STATE_SAMPLER(0), state_nop}},
105 {STATE_SAMPLER(1), {STATE_SAMPLER(1), state_nop}},
106 {STATE_SAMPLER(2), {STATE_SAMPLER(2), state_nop}},
107 {STATE_SAMPLER(3), {STATE_SAMPLER(3), state_nop}},
108 {STATE_SAMPLER(4), {STATE_SAMPLER(4), state_nop}},
109 {STATE_SAMPLER(5), {STATE_SAMPLER(5), state_nop}},
110 {STATE_SAMPLER(6), {STATE_SAMPLER(6), state_nop}},
111 {STATE_SAMPLER(7), {STATE_SAMPLER(7), state_nop}},
112 {STATE_SAMPLER(8), {STATE_SAMPLER(8), state_nop}},
113 {STATE_SAMPLER(9), {STATE_SAMPLER(9), state_nop}},
114 {STATE_SAMPLER(10), {STATE_SAMPLER(10), state_nop}},
115 {STATE_SAMPLER(11), {STATE_SAMPLER(11), state_nop}},
116 {STATE_SAMPLER(12), {STATE_SAMPLER(12), state_nop}},
117 {STATE_SAMPLER(13), {STATE_SAMPLER(13), state_nop}},
118 {STATE_SAMPLER(14), {STATE_SAMPLER(14), state_nop}},
119 {STATE_SAMPLER(15), {STATE_SAMPLER(15), state_nop}},
120 {STATE_SAMPLER(16), /* Vertex sampler 0 */ {STATE_SAMPLER(16), state_nop}},
121 {STATE_SAMPLER(17), /* Vertex sampler 1 */ {STATE_SAMPLER(17), state_nop}},
122 {STATE_SAMPLER(18), /* Vertex sampler 2 */ {STATE_SAMPLER(18), state_nop}},
123 {STATE_SAMPLER(19), /* Vertex sampler 3 */ {STATE_SAMPLER(19), state_nop}},
124 {STATE_BASEVERTEXINDEX, {STATE_STREAMSRC}},
125 {STATE_FRAMEBUFFER, {STATE_FRAMEBUFFER, state_nop}},
126 {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), state_nop}},
127 {STATE_SHADER(WINED3D_SHADER_TYPE_HULL), {STATE_SHADER(WINED3D_SHADER_TYPE_HULL), state_nop}},
128 {STATE_SHADER(WINED3D_SHADER_TYPE_DOMAIN), {STATE_SHADER(WINED3D_SHADER_TYPE_DOMAIN), state_nop}},
129 {STATE_SHADER(WINED3D_SHADER_TYPE_GEOMETRY), {STATE_SHADER(WINED3D_SHADER_TYPE_GEOMETRY), state_nop}},
130 {STATE_SHADER(WINED3D_SHADER_TYPE_COMPUTE), {STATE_SHADER(WINED3D_SHADER_TYPE_COMPUTE), state_nop}},
131 {0}, /* Terminate */
134 static inline const struct wined3d_adapter_vk *wined3d_adapter_vk_const(const struct wined3d_adapter *adapter)
136 return CONTAINING_RECORD(adapter, struct wined3d_adapter_vk, a);
139 static const char *debug_vk_version(uint32_t version)
141 return wine_dbg_sprintf("%u.%u.%u",
142 VK_VERSION_MAJOR(version), VK_VERSION_MINOR(version), VK_VERSION_PATCH(version));
145 static HRESULT hresult_from_vk_result(VkResult vr)
147 switch (vr)
149 case VK_SUCCESS:
150 return S_OK;
151 case VK_ERROR_OUT_OF_HOST_MEMORY:
152 WARN("Out of host memory.\n");
153 return E_OUTOFMEMORY;
154 case VK_ERROR_OUT_OF_DEVICE_MEMORY:
155 WARN("Out of device memory.\n");
156 return E_OUTOFMEMORY;
157 case VK_ERROR_DEVICE_LOST:
158 WARN("Device lost.\n");
159 return E_FAIL;
160 case VK_ERROR_EXTENSION_NOT_PRESENT:
161 WARN("Extension not present.\n");
162 return E_FAIL;
163 default:
164 FIXME("Unhandled VkResult %d.\n", vr);
165 return E_FAIL;
169 static BOOL wined3d_load_vulkan(struct wined3d_vk_info *vk_info)
171 struct vulkan_ops *vk_ops = &vk_info->vk_ops;
173 if (!(vk_info->vulkan_lib = LoadLibraryA("winevulkan.dll"))
174 && !(vk_info->vulkan_lib = LoadLibraryA("vulkan-1.dll")))
176 WARN("Failed to load vulkan-1.dll.\n");
177 return FALSE;
180 vk_ops->vkGetInstanceProcAddr = (void *)GetProcAddress(vk_info->vulkan_lib, "vkGetInstanceProcAddr");
181 if (!vk_ops->vkGetInstanceProcAddr)
183 FreeLibrary(vk_info->vulkan_lib);
184 return FALSE;
187 return TRUE;
190 static void wined3d_unload_vulkan(struct wined3d_vk_info *vk_info)
192 if (vk_info->vulkan_lib)
194 FreeLibrary(vk_info->vulkan_lib);
195 vk_info->vulkan_lib = NULL;
199 static void adapter_vk_destroy(struct wined3d_adapter *adapter)
201 struct wined3d_adapter_vk *adapter_vk = wined3d_adapter_vk(adapter);
202 struct wined3d_vk_info *vk_info = &adapter_vk->vk_info;
204 VK_CALL(vkDestroyInstance(vk_info->instance, NULL));
205 wined3d_unload_vulkan(vk_info);
206 wined3d_adapter_cleanup(&adapter_vk->a);
207 heap_free(adapter_vk->device_extensions);
208 heap_free(adapter_vk);
211 static HRESULT wined3d_select_vulkan_queue_family(const struct wined3d_adapter_vk *adapter_vk,
212 uint32_t *queue_family_index, uint32_t *timestamp_bits)
214 VkPhysicalDevice physical_device = adapter_vk->physical_device;
215 const struct wined3d_vk_info *vk_info = &adapter_vk->vk_info;
216 VkQueueFamilyProperties *queue_properties;
217 uint32_t count, i;
219 VK_CALL(vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &count, NULL));
221 if (!(queue_properties = heap_calloc(count, sizeof(*queue_properties))))
222 return E_OUTOFMEMORY;
224 VK_CALL(vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &count, queue_properties));
226 for (i = 0; i < count; ++i)
228 if (queue_properties[i].queueFlags & VK_QUEUE_GRAPHICS_BIT)
230 *queue_family_index = i;
231 *timestamp_bits = queue_properties[i].timestampValidBits;
232 heap_free(queue_properties);
233 return WINED3D_OK;
236 heap_free(queue_properties);
238 WARN("Failed to find graphics queue.\n");
239 return E_FAIL;
242 struct wined3d_physical_device_info
244 VkPhysicalDeviceTransformFeedbackFeaturesEXT xfb_features;
245 VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT vertex_divisor_features;
246 VkPhysicalDeviceHostQueryResetFeatures host_query_reset_features;
248 VkPhysicalDeviceFeatures2 features2;
251 static void wined3d_disable_vulkan_features(struct wined3d_physical_device_info *info)
253 VkPhysicalDeviceFeatures *features = &info->features2.features;
255 features->depthBounds = VK_FALSE;
256 features->wideLines = VK_FALSE;
257 features->alphaToOne = VK_FALSE;
258 features->textureCompressionETC2 = VK_FALSE;
259 features->textureCompressionASTC_LDR = VK_FALSE;
260 features->shaderStorageImageMultisample = VK_FALSE;
261 features->shaderUniformBufferArrayDynamicIndexing = VK_FALSE;
262 features->shaderSampledImageArrayDynamicIndexing = VK_FALSE;
263 features->shaderStorageBufferArrayDynamicIndexing = VK_FALSE;
264 features->shaderStorageImageArrayDynamicIndexing = VK_FALSE;
265 features->shaderInt64 = VK_FALSE;
266 features->shaderInt16 = VK_FALSE;
267 features->shaderResourceResidency = VK_FALSE;
268 features->shaderResourceMinLod = VK_FALSE;
269 features->shaderTessellationAndGeometryPointSize = VK_FALSE;
270 features->sparseBinding = VK_FALSE;
271 features->sparseResidencyBuffer = VK_FALSE;
272 features->sparseResidencyImage2D = VK_FALSE;
273 features->sparseResidencyImage3D = VK_FALSE;
274 features->sparseResidency2Samples = VK_FALSE;
275 features->sparseResidency4Samples = VK_FALSE;
276 features->sparseResidency8Samples = VK_FALSE;
277 features->sparseResidency16Samples = VK_FALSE;
278 features->sparseResidencyAliased = VK_FALSE;
279 features->inheritedQueries = VK_FALSE;
282 static struct wined3d_allocator_chunk *wined3d_allocator_vk_create_chunk(struct wined3d_allocator *allocator,
283 struct wined3d_context *context, unsigned int memory_type, size_t chunk_size)
285 struct wined3d_context_vk *context_vk = wined3d_context_vk(context);
286 struct wined3d_allocator_chunk_vk *chunk_vk;
288 if (!(chunk_vk = heap_alloc(sizeof(*chunk_vk))))
289 return NULL;
291 if (!wined3d_allocator_chunk_init(&chunk_vk->c, allocator))
293 heap_free(chunk_vk);
294 return NULL;
297 if (!(chunk_vk->vk_memory = wined3d_context_vk_allocate_vram_chunk_memory(context_vk, memory_type, chunk_size)))
299 wined3d_allocator_chunk_cleanup(&chunk_vk->c);
300 heap_free(chunk_vk);
301 return NULL;
303 list_add_head(&allocator->pools[memory_type].chunks, &chunk_vk->c.entry);
305 return &chunk_vk->c;
308 static void wined3d_allocator_vk_destroy_chunk(struct wined3d_allocator_chunk *chunk)
310 struct wined3d_allocator_chunk_vk *chunk_vk = wined3d_allocator_chunk_vk(chunk);
311 const struct wined3d_vk_info *vk_info;
312 struct wined3d_device_vk *device_vk;
314 TRACE("chunk %p.\n", chunk);
316 device_vk = wined3d_device_vk_from_allocator(chunk_vk->c.allocator);
317 vk_info = &device_vk->vk_info;
319 if (chunk_vk->c.map_ptr)
321 VK_CALL(vkUnmapMemory(device_vk->vk_device, chunk_vk->vk_memory));
322 adapter_adjust_mapped_memory(device_vk->d.adapter, -WINED3D_ALLOCATOR_CHUNK_SIZE);
324 VK_CALL(vkFreeMemory(device_vk->vk_device, chunk_vk->vk_memory, NULL));
325 TRACE("Freed memory 0x%s.\n", wine_dbgstr_longlong(chunk_vk->vk_memory));
326 wined3d_allocator_chunk_cleanup(&chunk_vk->c);
327 heap_free(chunk_vk);
330 static const struct wined3d_allocator_ops wined3d_allocator_vk_ops =
332 .allocator_create_chunk = wined3d_allocator_vk_create_chunk,
333 .allocator_destroy_chunk = wined3d_allocator_vk_destroy_chunk,
336 static void get_physical_device_info(const struct wined3d_adapter_vk *adapter_vk, struct wined3d_physical_device_info *info)
338 VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT *vertex_divisor_features = &info->vertex_divisor_features;
339 VkPhysicalDeviceHostQueryResetFeatures *host_query_reset_features = &info->host_query_reset_features;
340 VkPhysicalDeviceTransformFeedbackFeaturesEXT *xfb_features = &info->xfb_features;
341 VkPhysicalDevice physical_device = adapter_vk->physical_device;
342 const struct wined3d_vk_info *vk_info = &adapter_vk->vk_info;
343 VkPhysicalDeviceFeatures2 *features2 = &info->features2;
345 memset(info, 0, sizeof(*info));
347 xfb_features->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_FEATURES_EXT;
349 vertex_divisor_features->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT;
350 vertex_divisor_features->pNext = xfb_features;
352 host_query_reset_features->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES;
353 host_query_reset_features->pNext = vertex_divisor_features;
355 features2->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
356 features2->pNext = host_query_reset_features;
358 if (vk_info->vk_ops.vkGetPhysicalDeviceFeatures2)
359 VK_CALL(vkGetPhysicalDeviceFeatures2(physical_device, features2));
360 else
361 VK_CALL(vkGetPhysicalDeviceFeatures(physical_device, &features2->features));
364 static HRESULT adapter_vk_create_device(struct wined3d *wined3d, const struct wined3d_adapter *adapter,
365 enum wined3d_device_type device_type, HWND focus_window, unsigned int flags, BYTE surface_alignment,
366 const enum wined3d_feature_level *levels, unsigned int level_count,
367 struct wined3d_device_parent *device_parent, struct wined3d_device **device)
369 const struct wined3d_adapter_vk *adapter_vk = wined3d_adapter_vk_const(adapter);
370 const struct wined3d_vk_info *vk_info = &adapter_vk->vk_info;
371 struct wined3d_physical_device_info physical_device_info;
372 static const float priorities[] = {1.0f};
373 struct wined3d_device_vk *device_vk;
374 VkDevice vk_device = VK_NULL_HANDLE;
375 VkDeviceQueueCreateInfo queue_info;
376 VkPhysicalDevice physical_device;
377 VkDeviceCreateInfo device_info;
378 uint32_t queue_family_index;
379 uint32_t timestamp_bits;
380 VkResult vr;
381 HRESULT hr;
383 if (!(device_vk = heap_alloc_zero(sizeof(*device_vk))))
384 return E_OUTOFMEMORY;
386 if (FAILED(hr = wined3d_select_vulkan_queue_family(adapter_vk, &queue_family_index, &timestamp_bits)))
387 goto fail;
389 physical_device = adapter_vk->physical_device;
391 get_physical_device_info(adapter_vk, &physical_device_info);
392 wined3d_disable_vulkan_features(&physical_device_info);
394 queue_info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
395 queue_info.pNext = NULL;
396 queue_info.flags = 0;
397 queue_info.queueFamilyIndex = queue_family_index;
398 queue_info.queueCount = ARRAY_SIZE(priorities);
399 queue_info.pQueuePriorities = priorities;
401 device_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
402 device_info.pNext = physical_device_info.features2.pNext;
403 device_info.flags = 0;
404 device_info.queueCreateInfoCount = 1;
405 device_info.pQueueCreateInfos = &queue_info;
406 device_info.enabledLayerCount = 0;
407 device_info.ppEnabledLayerNames = NULL;
408 device_info.enabledExtensionCount = adapter_vk->device_extension_count;
409 device_info.ppEnabledExtensionNames = adapter_vk->device_extensions;
410 device_info.pEnabledFeatures = &physical_device_info.features2.features;
412 if ((vr = VK_CALL(vkCreateDevice(physical_device, &device_info, NULL, &vk_device))) < 0)
414 WARN("Failed to create Vulkan device, vr %s.\n", wined3d_debug_vkresult(vr));
415 vk_device = VK_NULL_HANDLE;
416 hr = hresult_from_vk_result(vr);
417 goto fail;
420 device_vk->vk_device = vk_device;
421 VK_CALL(vkGetDeviceQueue(vk_device, queue_family_index, 0, &device_vk->vk_queue));
422 device_vk->vk_queue_family_index = queue_family_index;
423 device_vk->timestamp_bits = timestamp_bits;
425 device_vk->vk_info = *vk_info;
426 #define VK_DEVICE_PFN(name) \
427 if (!(device_vk->vk_info.vk_ops.name = (void *)VK_CALL(vkGetDeviceProcAddr(vk_device, #name)))) \
429 WARN("Could not get device proc addr for '" #name "'.\n"); \
430 hr = E_FAIL; \
431 goto fail; \
433 #define VK_DEVICE_EXT_PFN(name) \
434 device_vk->vk_info.vk_ops.name = (void *)VK_CALL(vkGetDeviceProcAddr(vk_device, #name));
435 VK_DEVICE_FUNCS()
436 #undef VK_DEVICE_EXT_PFN
437 #undef VK_DEVICE_PFN
439 if (!wined3d_allocator_init(&device_vk->allocator,
440 adapter_vk->memory_properties.memoryTypeCount, &wined3d_allocator_vk_ops))
442 WARN("Failed to initialise allocator.\n");
443 hr = E_FAIL;
444 goto fail;
447 if (FAILED(hr = wined3d_device_init(&device_vk->d, wined3d, adapter->ordinal, device_type, focus_window,
448 flags, surface_alignment, levels, level_count, vk_info->supported, device_parent)))
450 WARN("Failed to initialize device, hr %#lx.\n", hr);
451 wined3d_allocator_cleanup(&device_vk->allocator);
452 goto fail;
455 wined3d_lock_init(&device_vk->allocator_cs, "wined3d_device_vk.allocator_cs");
457 *device = &device_vk->d;
459 return WINED3D_OK;
461 fail:
462 VK_CALL(vkDestroyDevice(vk_device, NULL));
463 heap_free(device_vk);
464 return hr;
467 static void adapter_vk_destroy_device(struct wined3d_device *device)
469 struct wined3d_device_vk *device_vk = wined3d_device_vk(device);
470 const struct wined3d_vk_info *vk_info = &device_vk->vk_info;
472 wined3d_device_cleanup(&device_vk->d);
473 wined3d_allocator_cleanup(&device_vk->allocator);
475 wined3d_lock_cleanup(&device_vk->allocator_cs);
477 VK_CALL(vkDestroyDevice(device_vk->vk_device, NULL));
478 heap_free(device_vk);
481 static struct wined3d_context *adapter_vk_acquire_context(struct wined3d_device *device,
482 struct wined3d_texture *texture, unsigned int sub_resource_idx)
484 TRACE("device %p, texture %p, sub_resource_idx %u.\n", device, texture, sub_resource_idx);
486 wined3d_from_cs(device->cs);
488 if (!device->context_count)
489 return NULL;
491 return &wined3d_device_vk(device)->context_vk.c;
494 static void adapter_vk_release_context(struct wined3d_context *context)
496 TRACE("context %p.\n", context);
499 static void adapter_vk_get_wined3d_caps(const struct wined3d_adapter *adapter, struct wined3d_caps *caps)
501 const struct wined3d_adapter_vk *adapter_vk = wined3d_adapter_vk_const(adapter);
502 const VkPhysicalDeviceLimits *limits = &adapter_vk->device_limits;
503 bool sampler_anisotropy = limits->maxSamplerAnisotropy > 1.0f;
504 const struct wined3d_vk_info *vk_info = &adapter_vk->vk_info;
506 caps->ddraw_caps.dds_caps |= WINEDDSCAPS_BACKBUFFER
507 | WINEDDSCAPS_COMPLEX
508 | WINEDDSCAPS_FRONTBUFFER
509 | WINEDDSCAPS_3DDEVICE
510 | WINEDDSCAPS_VIDEOMEMORY
511 | WINEDDSCAPS_OWNDC
512 | WINEDDSCAPS_LOCALVIDMEM
513 | WINEDDSCAPS_NONLOCALVIDMEM;
514 caps->ddraw_caps.caps |= WINEDDCAPS_3D;
516 caps->Caps2 |= WINED3DCAPS2_CANGENMIPMAP;
518 caps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_BLENDOP
519 | WINED3DPMISCCAPS_INDEPENDENTWRITEMASKS
520 | WINED3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS
521 | WINED3DPMISCCAPS_POSTBLENDSRGBCONVERT
522 | WINED3DPMISCCAPS_SEPARATEALPHABLEND;
524 caps->RasterCaps |= WINED3DPRASTERCAPS_MIPMAPLODBIAS;
526 if (sampler_anisotropy)
528 caps->RasterCaps |= WINED3DPRASTERCAPS_ANISOTROPY;
530 caps->TextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC
531 | WINED3DPTFILTERCAPS_MINFANISOTROPIC;
533 caps->MaxAnisotropy = limits->maxSamplerAnisotropy;
536 caps->SrcBlendCaps |= WINED3DPBLENDCAPS_BLENDFACTOR;
537 caps->DestBlendCaps |= WINED3DPBLENDCAPS_BLENDFACTOR
538 | WINED3DPBLENDCAPS_SRCALPHASAT;
540 caps->TextureCaps |= WINED3DPTEXTURECAPS_VOLUMEMAP
541 | WINED3DPTEXTURECAPS_MIPVOLUMEMAP
542 | WINED3DPTEXTURECAPS_VOLUMEMAP_POW2;
543 caps->VolumeTextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFLINEAR
544 | WINED3DPTFILTERCAPS_MAGFPOINT
545 | WINED3DPTFILTERCAPS_MINFLINEAR
546 | WINED3DPTFILTERCAPS_MINFPOINT
547 | WINED3DPTFILTERCAPS_MIPFLINEAR
548 | WINED3DPTFILTERCAPS_MIPFPOINT
549 | WINED3DPTFILTERCAPS_LINEAR
550 | WINED3DPTFILTERCAPS_LINEARMIPLINEAR
551 | WINED3DPTFILTERCAPS_LINEARMIPNEAREST
552 | WINED3DPTFILTERCAPS_MIPLINEAR
553 | WINED3DPTFILTERCAPS_MIPNEAREST
554 | WINED3DPTFILTERCAPS_NEAREST;
555 caps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_INDEPENDENTUV
556 | WINED3DPTADDRESSCAPS_CLAMP
557 | WINED3DPTADDRESSCAPS_WRAP;
558 caps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER
559 | WINED3DPTADDRESSCAPS_MIRROR;
560 if (vk_info->supported[WINED3D_VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE])
561 caps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
563 caps->MaxVolumeExtent = limits->maxImageDimension3D;
565 caps->TextureCaps |= WINED3DPTEXTURECAPS_CUBEMAP
566 | WINED3DPTEXTURECAPS_MIPCUBEMAP
567 | WINED3DPTEXTURECAPS_CUBEMAP_POW2;
568 caps->CubeTextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFLINEAR
569 | WINED3DPTFILTERCAPS_MAGFPOINT
570 | WINED3DPTFILTERCAPS_MINFLINEAR
571 | WINED3DPTFILTERCAPS_MINFPOINT
572 | WINED3DPTFILTERCAPS_MIPFLINEAR
573 | WINED3DPTFILTERCAPS_MIPFPOINT
574 | WINED3DPTFILTERCAPS_LINEAR
575 | WINED3DPTFILTERCAPS_LINEARMIPLINEAR
576 | WINED3DPTFILTERCAPS_LINEARMIPNEAREST
577 | WINED3DPTFILTERCAPS_MIPLINEAR
578 | WINED3DPTFILTERCAPS_MIPNEAREST
579 | WINED3DPTFILTERCAPS_NEAREST;
581 if (sampler_anisotropy)
583 caps->CubeTextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC
584 | WINED3DPTFILTERCAPS_MINFANISOTROPIC;
587 caps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER
588 | WINED3DPTADDRESSCAPS_MIRROR;
589 if (vk_info->supported[WINED3D_VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE])
590 caps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
592 caps->StencilCaps |= WINED3DSTENCILCAPS_DECR
593 | WINED3DSTENCILCAPS_INCR
594 | WINED3DSTENCILCAPS_TWOSIDED;
596 caps->DeclTypes |= WINED3DDTCAPS_FLOAT16_2 | WINED3DDTCAPS_FLOAT16_4;
598 caps->MaxPixelShader30InstructionSlots = WINED3DMAX30SHADERINSTRUCTIONS;
599 caps->MaxVertexShader30InstructionSlots = WINED3DMAX30SHADERINSTRUCTIONS;
600 caps->PS20Caps.temp_count = WINED3DPS20_MAX_NUMTEMPS;
601 caps->VS20Caps.temp_count = WINED3DVS20_MAX_NUMTEMPS;
604 static BOOL adapter_vk_check_format(const struct wined3d_adapter *adapter,
605 const struct wined3d_format *adapter_format, const struct wined3d_format *rt_format,
606 const struct wined3d_format *ds_format)
608 return TRUE;
611 static HRESULT adapter_vk_init_3d(struct wined3d_device *device)
613 struct wined3d_context_vk *context_vk;
614 struct wined3d_device_vk *device_vk;
615 HRESULT hr;
617 TRACE("device %p.\n", device);
619 device_vk = wined3d_device_vk(device);
620 context_vk = &device_vk->context_vk;
621 if (FAILED(hr = wined3d_context_vk_init(context_vk, device->swapchains[0])))
623 WARN("Failed to initialise context.\n");
624 return hr;
627 if (FAILED(hr = device->shader_backend->shader_alloc_private(device,
628 device->adapter->vertex_pipe, device->adapter->fragment_pipe)))
630 ERR("Failed to allocate shader private data, hr %#lx.\n", hr);
631 wined3d_context_vk_cleanup(context_vk);
632 return hr;
635 if (!device_context_add(device, &context_vk->c))
637 ERR("Failed to add the newly created context to the context list.\n");
638 device->shader_backend->shader_free_private(device, NULL);
639 wined3d_context_vk_cleanup(context_vk);
640 return E_FAIL;
643 TRACE("Initialised context %p.\n", context_vk);
645 if (!(device_vk->d.blitter = wined3d_cpu_blitter_create()))
647 ERR("Failed to create CPU blitter.\n");
648 device_context_remove(device, &context_vk->c);
649 device->shader_backend->shader_free_private(device, NULL);
650 wined3d_context_vk_cleanup(context_vk);
651 return E_FAIL;
653 wined3d_vk_blitter_create(&device_vk->d.blitter);
655 wined3d_device_create_default_samplers(device, &context_vk->c);
656 wined3d_device_vk_create_null_resources(device_vk, context_vk);
657 wined3d_device_vk_create_null_views(device_vk, context_vk);
658 if (device->adapter->d3d_info.feature_level >= WINED3D_FEATURE_LEVEL_11)
659 wined3d_device_vk_uav_clear_state_init(device_vk);
661 return WINED3D_OK;
664 static void adapter_vk_uninit_3d_cs(void *object)
666 struct wined3d_device_vk *device_vk = object;
667 struct wined3d_context_vk *context_vk;
668 struct wined3d_device *device;
669 struct wined3d_shader *shader;
671 TRACE("device_vk %p.\n", device_vk);
673 context_vk = &device_vk->context_vk;
674 device = &device_vk->d;
676 LIST_FOR_EACH_ENTRY(shader, &device->shaders, struct wined3d_shader, shader_list_entry)
678 device->shader_backend->shader_destroy(shader);
681 if (device->adapter->d3d_info.feature_level >= WINED3D_FEATURE_LEVEL_11)
682 wined3d_device_vk_uav_clear_state_cleanup(device_vk);
683 device->blitter->ops->blitter_destroy(device->blitter, NULL);
684 device->shader_backend->shader_free_private(device, &context_vk->c);
685 wined3d_device_vk_destroy_null_views(device_vk, context_vk);
686 wined3d_device_vk_destroy_null_resources(device_vk, context_vk);
689 static void adapter_vk_uninit_3d(struct wined3d_device *device)
691 struct wined3d_context_vk *context_vk;
692 struct wined3d_device_vk *device_vk;
694 TRACE("device %p.\n", device);
696 device_vk = wined3d_device_vk(device);
697 context_vk = &device_vk->context_vk;
699 wined3d_device_destroy_default_samplers(device);
700 wined3d_cs_destroy_object(device->cs, adapter_vk_uninit_3d_cs, device_vk);
701 wined3d_cs_finish(device->cs, WINED3D_CS_QUEUE_DEFAULT);
703 device_context_remove(device, &context_vk->c);
704 wined3d_context_vk_cleanup(context_vk);
707 static void *wined3d_bo_vk_map(struct wined3d_bo_vk *bo, struct wined3d_context_vk *context_vk)
709 const struct wined3d_vk_info *vk_info;
710 struct wined3d_device_vk *device_vk;
711 struct wined3d_bo_slab_vk *slab;
712 VkResult vr;
714 if (bo->b.map_ptr)
715 return bo->b.map_ptr;
717 vk_info = context_vk->vk_info;
718 device_vk = wined3d_device_vk(context_vk->c.device);
720 if ((slab = bo->slab))
722 if (!(bo->b.map_ptr = wined3d_bo_slab_vk_map(slab, context_vk)))
724 ERR("Failed to map slab.\n");
725 return NULL;
728 else if (bo->memory)
730 struct wined3d_allocator_chunk_vk *chunk_vk = wined3d_allocator_chunk_vk(bo->memory->chunk);
732 if (!(bo->b.map_ptr = wined3d_allocator_chunk_vk_map(chunk_vk, context_vk)))
734 ERR("Failed to map chunk.\n");
735 return NULL;
738 else
740 if ((vr = VK_CALL(vkMapMemory(device_vk->vk_device, bo->vk_memory, 0, VK_WHOLE_SIZE, 0, &bo->b.map_ptr))) < 0)
742 ERR("Failed to map memory, vr %s.\n", wined3d_debug_vkresult(vr));
743 return NULL;
746 adapter_adjust_mapped_memory(device_vk->d.adapter, bo->size);
749 return bo->b.map_ptr;
752 static void wined3d_bo_vk_unmap(struct wined3d_bo_vk *bo, struct wined3d_context_vk *context_vk)
754 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
755 const struct wined3d_vk_info *vk_info;
756 struct wined3d_bo_slab_vk *slab;
758 /* This may race with the client thread, but it's not a hard limit anyway. */
759 if (device_vk->d.adapter->mapped_size <= MAX_PERSISTENT_MAPPED_BYTES)
761 TRACE("Not unmapping BO %p.\n", bo);
762 return;
765 wined3d_device_bo_map_lock(context_vk->c.device);
766 /* The mapping is still in use by the client (viz. for an accelerated
767 * NOOVERWRITE map). The client will trigger another unmap request when the
768 * d3d application requests to unmap the BO. */
769 if (bo->b.client_map_count)
771 wined3d_device_bo_map_unlock(context_vk->c.device);
772 TRACE("BO %p is still in use by a client thread; not unmapping.\n", bo);
773 return;
775 bo->b.map_ptr = NULL;
776 wined3d_device_bo_map_unlock(context_vk->c.device);
778 if ((slab = bo->slab))
780 wined3d_bo_slab_vk_unmap(slab, context_vk);
781 return;
784 if (bo->memory)
786 wined3d_allocator_chunk_vk_unmap(wined3d_allocator_chunk_vk(bo->memory->chunk), context_vk);
787 return;
790 vk_info = context_vk->vk_info;
791 VK_CALL(vkUnmapMemory(device_vk->vk_device, bo->vk_memory));
792 adapter_adjust_mapped_memory(device_vk->d.adapter, -bo->size);
795 static void wined3d_bo_slab_vk_lock(struct wined3d_bo_slab_vk *slab_vk, struct wined3d_context_vk *context_vk)
797 wined3d_device_vk_allocator_lock(wined3d_device_vk(context_vk->c.device));
800 static void wined3d_bo_slab_vk_unlock(struct wined3d_bo_slab_vk *slab_vk, struct wined3d_context_vk *context_vk)
802 wined3d_device_vk_allocator_unlock(wined3d_device_vk(context_vk->c.device));
805 void *wined3d_bo_slab_vk_map(struct wined3d_bo_slab_vk *slab_vk, struct wined3d_context_vk *context_vk)
807 void *map_ptr;
809 TRACE("slab_vk %p, context_vk %p.\n", slab_vk, context_vk);
811 wined3d_bo_slab_vk_lock(slab_vk, context_vk);
813 if (!slab_vk->map_ptr && !(slab_vk->map_ptr = wined3d_bo_vk_map(&slab_vk->bo, context_vk)))
815 wined3d_bo_slab_vk_unlock(slab_vk, context_vk);
816 ERR("Failed to map slab.\n");
817 return NULL;
820 ++slab_vk->map_count;
821 map_ptr = slab_vk->map_ptr;
823 wined3d_bo_slab_vk_unlock(slab_vk, context_vk);
825 return map_ptr;
828 void wined3d_bo_slab_vk_unmap(struct wined3d_bo_slab_vk *slab_vk, struct wined3d_context_vk *context_vk)
830 wined3d_bo_slab_vk_lock(slab_vk, context_vk);
832 if (--slab_vk->map_count)
834 wined3d_bo_slab_vk_unlock(slab_vk, context_vk);
835 return;
838 wined3d_bo_vk_unmap(&slab_vk->bo, context_vk);
839 slab_vk->map_ptr = NULL;
841 wined3d_bo_slab_vk_unlock(slab_vk, context_vk);
844 VkAccessFlags vk_access_mask_from_buffer_usage(VkBufferUsageFlags usage)
846 VkAccessFlags flags = 0;
848 if (usage & VK_BUFFER_USAGE_VERTEX_BUFFER_BIT)
849 flags |= VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT;
850 if (usage & VK_BUFFER_USAGE_INDEX_BUFFER_BIT)
851 flags |= VK_ACCESS_INDEX_READ_BIT;
852 if (usage & VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT)
853 flags |= VK_ACCESS_UNIFORM_READ_BIT;
854 if (usage & VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT)
855 flags |= VK_ACCESS_SHADER_READ_BIT;
856 if (usage & VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT)
857 flags |= VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
858 if (usage & VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT)
859 flags |= VK_ACCESS_INDIRECT_COMMAND_READ_BIT;
860 if (usage & VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT)
861 flags |= VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT;
862 if (usage & VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT)
863 flags |= VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT
864 | VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT;
865 if (usage & VK_BUFFER_USAGE_TRANSFER_SRC_BIT)
866 flags |= VK_ACCESS_TRANSFER_READ_BIT;
867 if (usage & VK_BUFFER_USAGE_TRANSFER_DST_BIT)
868 flags |= VK_ACCESS_TRANSFER_WRITE_BIT;
870 return flags;
873 VkPipelineStageFlags vk_pipeline_stage_mask_from_buffer_usage(VkBufferUsageFlags usage)
875 VkPipelineStageFlags flags = 0;
877 if (usage & (VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT))
878 flags |= VK_PIPELINE_STAGE_VERTEX_INPUT_BIT;
879 if (usage & (VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT
880 | VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT))
881 flags |= VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT
882 | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT
883 | VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT
884 | VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT;
885 if (usage & VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT)
886 flags |= VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT;
887 if (usage & (VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT
888 | VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT))
889 flags |= VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT;
890 if (usage & (VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT))
891 flags |= VK_PIPELINE_STAGE_TRANSFER_BIT;
893 return flags;
896 static void *adapter_vk_map_bo_address(struct wined3d_context *context,
897 const struct wined3d_bo_address *data, size_t size, uint32_t map_flags)
899 struct wined3d_context_vk *context_vk = wined3d_context_vk(context);
900 const struct wined3d_vk_info *vk_info;
901 struct wined3d_device_vk *device_vk;
902 VkCommandBuffer vk_command_buffer;
903 VkBufferMemoryBarrier vk_barrier;
904 struct wined3d_bo_user *bo_user;
905 struct wined3d_bo_vk *bo, tmp;
906 VkMappedMemoryRange range;
907 void *map_ptr;
909 if (!data->buffer_object)
910 return data->addr;
911 bo = wined3d_bo_vk(data->buffer_object);
913 vk_info = context_vk->vk_info;
914 device_vk = wined3d_device_vk(context->device);
916 if (map_flags & WINED3D_MAP_NOOVERWRITE)
917 goto map;
919 if ((map_flags & WINED3D_MAP_DISCARD) && bo->command_buffer_id > context_vk->completed_command_buffer_id)
921 if (wined3d_context_vk_create_bo(context_vk, bo->size, bo->usage, bo->memory_type, &tmp))
923 bool host_synced = bo->host_synced;
924 list_move_head(&tmp.b.users, &bo->b.users);
925 wined3d_context_vk_destroy_bo(context_vk, bo);
926 *bo = tmp;
927 bo->host_synced = host_synced;
928 list_init(&bo->b.users);
929 list_move_head(&bo->b.users, &tmp.b.users);
930 LIST_FOR_EACH_ENTRY(bo_user, &bo->b.users, struct wined3d_bo_user, entry)
932 bo_user->valid = false;
935 goto map;
938 ERR("Failed to create new buffer object.\n");
941 if (map_flags & WINED3D_MAP_READ)
943 if (!bo->host_synced)
945 if (!(vk_command_buffer = wined3d_context_vk_get_command_buffer(context_vk)))
947 ERR("Failed to get command buffer.\n");
948 return NULL;
951 wined3d_context_vk_end_current_render_pass(context_vk);
953 vk_barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
954 vk_barrier.pNext = NULL;
955 vk_barrier.srcAccessMask = vk_access_mask_from_buffer_usage(bo->usage);
956 vk_barrier.dstAccessMask = VK_ACCESS_HOST_READ_BIT;
957 vk_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
958 vk_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
959 vk_barrier.buffer = bo->vk_buffer;
960 vk_barrier.offset = bo->b.buffer_offset + (uintptr_t)data->addr;
961 vk_barrier.size = size;
962 VK_CALL(vkCmdPipelineBarrier(vk_command_buffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
963 VK_PIPELINE_STAGE_HOST_BIT, 0, 0, NULL, 1, &vk_barrier, 0, NULL));
965 wined3d_context_vk_reference_bo(context_vk, bo);
968 if (!bo->b.coherent)
970 range.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE;
971 range.pNext = NULL;
972 range.memory = bo->vk_memory;
973 range.offset = bo->b.memory_offset + (uintptr_t)data->addr;
974 range.size = size;
975 VK_CALL(vkInvalidateMappedMemoryRanges(device_vk->vk_device, 1, &range));
979 if (bo->command_buffer_id == context_vk->current_command_buffer.id)
980 wined3d_context_vk_submit_command_buffer(context_vk, 0, NULL, NULL, 0, NULL);
981 wined3d_context_vk_wait_command_buffer(context_vk, bo->command_buffer_id);
983 map:
984 if (!(map_ptr = wined3d_bo_vk_map(bo, context_vk)))
986 ERR("Failed to map bo.\n");
987 return NULL;
990 return (uint8_t *)map_ptr + bo->b.memory_offset + (uintptr_t)data->addr;
993 static void flush_bo_range(struct wined3d_context_vk *context_vk,
994 struct wined3d_bo_vk *bo, unsigned int offset, unsigned int size)
996 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
997 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
998 VkMappedMemoryRange range;
1000 range.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE;
1001 range.pNext = NULL;
1002 range.memory = bo->vk_memory;
1003 range.offset = bo->b.memory_offset + offset;
1004 range.size = size;
1005 VK_CALL(vkFlushMappedMemoryRanges(device_vk->vk_device, 1, &range));
1008 static void adapter_vk_unmap_bo_address(struct wined3d_context *context,
1009 const struct wined3d_bo_address *data, unsigned int range_count, const struct wined3d_range *ranges)
1011 struct wined3d_context_vk *context_vk = wined3d_context_vk(context);
1012 struct wined3d_bo_vk *bo;
1013 unsigned int i;
1015 if (!data->buffer_object)
1016 return;
1017 bo = wined3d_bo_vk(data->buffer_object);
1019 assert(bo->b.map_ptr);
1021 if (!bo->b.coherent)
1023 for (i = 0; i < range_count; ++i)
1024 flush_bo_range(context_vk, bo, ranges[i].offset, ranges[i].size);
1027 wined3d_bo_vk_unmap(bo, context_vk);
1030 void adapter_vk_copy_bo_address(struct wined3d_context *context,
1031 const struct wined3d_bo_address *dst, const struct wined3d_bo_address *src,
1032 unsigned int range_count, const struct wined3d_range *ranges, uint32_t map_flags)
1034 struct wined3d_context_vk *context_vk = wined3d_context_vk(context);
1035 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
1036 struct wined3d_bo_vk staging_bo, *src_bo, *dst_bo;
1037 VkAccessFlags src_access_mask, dst_access_mask;
1038 VkBufferMemoryBarrier vk_barrier[2];
1039 const struct wined3d_range *range;
1040 struct wined3d_bo_address staging;
1041 VkCommandBuffer vk_command_buffer;
1042 uint8_t *dst_ptr, *src_ptr;
1043 VkBufferCopy region;
1044 size_t size = 0;
1045 unsigned int i;
1047 src_bo = src->buffer_object ? wined3d_bo_vk(src->buffer_object) : NULL;
1048 dst_bo = dst->buffer_object ? wined3d_bo_vk(dst->buffer_object) : NULL;
1050 if (src_bo && dst_bo)
1052 if (!(vk_command_buffer = wined3d_context_vk_get_command_buffer(context_vk)))
1054 ERR("Failed to get command buffer.\n");
1055 return;
1058 wined3d_context_vk_end_current_render_pass(context_vk);
1060 src_access_mask = vk_access_mask_from_buffer_usage(src_bo->usage);
1061 dst_access_mask = vk_access_mask_from_buffer_usage(dst_bo->usage);
1063 vk_barrier[0].sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
1064 vk_barrier[0].pNext = NULL;
1065 vk_barrier[0].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
1066 vk_barrier[0].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
1067 vk_barrier[0].buffer = src_bo->vk_buffer;
1069 vk_barrier[1].sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
1070 vk_barrier[1].pNext = NULL;
1071 vk_barrier[1].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
1072 vk_barrier[1].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
1073 vk_barrier[1].buffer = dst_bo->vk_buffer;
1075 for (i = 0; i < range_count; ++i)
1077 range = &ranges[i];
1079 region.srcOffset = src_bo->b.buffer_offset + (uintptr_t)src->addr + range->offset;
1080 region.dstOffset = dst_bo->b.buffer_offset + (uintptr_t)dst->addr + range->offset;
1081 region.size = range->size;
1083 vk_barrier[0].offset = region.srcOffset;
1084 vk_barrier[0].size = region.size;
1086 vk_barrier[1].offset = region.dstOffset;
1087 vk_barrier[1].size = region.size;
1089 vk_barrier[0].srcAccessMask = src_access_mask;
1090 vk_barrier[0].dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
1092 vk_barrier[1].srcAccessMask = dst_access_mask;
1093 vk_barrier[1].dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
1095 VK_CALL(vkCmdPipelineBarrier(vk_command_buffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
1096 VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, NULL, 2, vk_barrier, 0, NULL));
1098 VK_CALL(vkCmdCopyBuffer(vk_command_buffer, src_bo->vk_buffer, dst_bo->vk_buffer, 1, &region));
1100 vk_barrier[0].srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
1101 vk_barrier[0].dstAccessMask = src_access_mask;
1103 vk_barrier[1].srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
1104 vk_barrier[1].dstAccessMask = dst_access_mask;
1106 VK_CALL(vkCmdPipelineBarrier(vk_command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT,
1107 VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, NULL, 2, vk_barrier, 0, NULL));
1110 wined3d_context_vk_reference_bo(context_vk, src_bo);
1111 wined3d_context_vk_reference_bo(context_vk, dst_bo);
1113 return;
1116 for (i = 0; i < range_count; ++i)
1117 size = max(size, ranges[i].offset + ranges[i].size);
1119 if (src_bo && !(src_bo->memory_type & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT))
1121 if (!(wined3d_context_vk_create_bo(context_vk, size, VK_BUFFER_USAGE_TRANSFER_DST_BIT,
1122 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, &staging_bo)))
1124 ERR("Failed to create staging bo.\n");
1125 return;
1128 staging.buffer_object = &staging_bo.b;
1129 staging.addr = NULL;
1130 adapter_vk_copy_bo_address(context, &staging, src, range_count, ranges, WINED3D_MAP_WRITE);
1131 adapter_vk_copy_bo_address(context, dst, &staging, range_count, ranges, WINED3D_MAP_WRITE);
1133 wined3d_context_vk_destroy_bo(context_vk, &staging_bo);
1135 return;
1138 if (dst_bo && (!(dst_bo->memory_type & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) || (!(map_flags & WINED3D_MAP_DISCARD)
1139 && dst_bo->command_buffer_id > context_vk->completed_command_buffer_id)))
1141 if (!(wined3d_context_vk_create_bo(context_vk, size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
1142 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, &staging_bo)))
1144 ERR("Failed to create staging bo.\n");
1145 return;
1148 staging.buffer_object = &staging_bo.b;
1149 staging.addr = NULL;
1150 adapter_vk_copy_bo_address(context, &staging, src, range_count, ranges, WINED3D_MAP_WRITE);
1151 adapter_vk_copy_bo_address(context, dst, &staging, range_count, ranges, WINED3D_MAP_WRITE);
1153 wined3d_context_vk_destroy_bo(context_vk, &staging_bo);
1155 return;
1158 src_ptr = adapter_vk_map_bo_address(context, src, size, WINED3D_MAP_READ);
1159 dst_ptr = adapter_vk_map_bo_address(context, dst, size, map_flags);
1161 for (i = 0; i < range_count; ++i)
1162 memcpy(dst_ptr + ranges[i].offset, src_ptr + ranges[i].offset, ranges[i].size);
1164 adapter_vk_unmap_bo_address(context, dst, range_count, ranges);
1165 adapter_vk_unmap_bo_address(context, src, 0, NULL);
1168 static void adapter_vk_flush_bo_address(struct wined3d_context *context,
1169 const struct wined3d_const_bo_address *data, size_t size)
1171 struct wined3d_context_vk *context_vk = wined3d_context_vk(context);
1172 struct wined3d_bo *bo;
1174 if (!(bo = data->buffer_object))
1175 return;
1177 flush_bo_range(context_vk, wined3d_bo_vk(bo), (uintptr_t)data->addr, size);
1180 static bool adapter_vk_alloc_bo(struct wined3d_device *device, struct wined3d_resource *resource,
1181 unsigned int sub_resource_idx, struct wined3d_bo_address *addr)
1183 struct wined3d_device_vk *device_vk = wined3d_device_vk(device);
1184 struct wined3d_context_vk *context_vk = &device_vk->context_vk;
1185 VkMemoryPropertyFlags memory_type;
1186 VkBufferUsageFlags buffer_usage;
1187 struct wined3d_bo_vk *bo_vk;
1188 VkDeviceSize size;
1190 wined3d_not_from_cs(device->cs);
1191 assert(device->context_count);
1193 if (resource->type == WINED3D_RTYPE_BUFFER)
1195 buffer_usage = vk_buffer_usage_from_bind_flags(resource->bind_flags);
1196 memory_type = vk_memory_type_from_access_flags(resource->access, resource->usage);
1197 size = resource->size;
1199 else
1201 struct wined3d_texture *texture = texture_from_resource(resource);
1203 buffer_usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
1204 memory_type = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
1205 size = texture->sub_resources[sub_resource_idx].size;
1208 if (!(bo_vk = heap_alloc(sizeof(*bo_vk))))
1209 return false;
1211 if (!(wined3d_context_vk_create_bo(context_vk, size, buffer_usage, memory_type, bo_vk)))
1213 WARN("Failed to create Vulkan buffer.\n");
1214 heap_free(bo_vk);
1215 return false;
1218 if (!bo_vk->b.map_ptr)
1220 if (!wined3d_bo_vk_map(bo_vk, context_vk))
1221 ERR("Failed to map bo.\n");
1224 addr->buffer_object = &bo_vk->b;
1225 addr->addr = NULL;
1226 return true;
1229 static void adapter_vk_destroy_bo(struct wined3d_context *context, struct wined3d_bo *bo)
1231 wined3d_context_vk_destroy_bo(wined3d_context_vk(context), wined3d_bo_vk(bo));
1234 static HRESULT adapter_vk_create_swapchain(struct wined3d_device *device,
1235 struct wined3d_swapchain_desc *desc, struct wined3d_swapchain_state_parent *state_parent,
1236 void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_swapchain **swapchain)
1238 struct wined3d_swapchain_vk *swapchain_vk;
1239 HRESULT hr;
1241 TRACE("device %p, desc %p, state_parent %p, parent %p, parent_ops %p, swapchain %p.\n",
1242 device, desc, state_parent, parent, parent_ops, swapchain);
1244 if (!(swapchain_vk = heap_alloc_zero(sizeof(*swapchain_vk))))
1245 return E_OUTOFMEMORY;
1247 if (FAILED(hr = wined3d_swapchain_vk_init(swapchain_vk, device, desc, state_parent, parent,
1248 parent_ops)))
1250 WARN("Failed to initialise swapchain, hr %#lx.\n", hr);
1251 heap_free(swapchain_vk);
1252 return hr;
1255 TRACE("Created swapchain %p.\n", swapchain_vk);
1256 *swapchain = &swapchain_vk->s;
1258 return hr;
1261 static void adapter_vk_destroy_swapchain(struct wined3d_swapchain *swapchain)
1263 struct wined3d_swapchain_vk *swapchain_vk = wined3d_swapchain_vk(swapchain);
1265 wined3d_swapchain_vk_cleanup(swapchain_vk);
1266 heap_free(swapchain_vk);
1269 unsigned int wined3d_adapter_vk_get_memory_type_index(const struct wined3d_adapter_vk *adapter_vk,
1270 uint32_t memory_type_mask, VkMemoryPropertyFlags flags)
1272 const VkPhysicalDeviceMemoryProperties *memory_info = &adapter_vk->memory_properties;
1273 unsigned int i;
1275 for (i = 0; i < memory_info->memoryTypeCount; ++i)
1277 if (!(memory_type_mask & (1u << i)))
1278 continue;
1279 if ((memory_info->memoryTypes[i].propertyFlags & flags) == flags)
1280 return i;
1283 return ~0u;
1286 static HRESULT adapter_vk_create_buffer(struct wined3d_device *device,
1287 const struct wined3d_buffer_desc *desc, const struct wined3d_sub_resource_data *data,
1288 void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_buffer **buffer)
1290 struct wined3d_buffer_vk *buffer_vk;
1291 HRESULT hr;
1293 TRACE("device %p, desc %p, data %p, parent %p, parent_ops %p, buffer %p.\n",
1294 device, desc, data, parent, parent_ops, buffer);
1296 if (!(buffer_vk = heap_alloc_zero(sizeof(*buffer_vk))))
1297 return E_OUTOFMEMORY;
1299 if (FAILED(hr = wined3d_buffer_vk_init(buffer_vk, device, desc, data, parent, parent_ops)))
1301 WARN("Failed to initialise buffer, hr %#lx.\n", hr);
1302 heap_free(buffer_vk);
1303 return hr;
1306 TRACE("Created buffer %p.\n", buffer_vk);
1307 *buffer = &buffer_vk->b;
1309 return hr;
1312 static void adapter_vk_destroy_buffer(struct wined3d_buffer *buffer)
1314 struct wined3d_buffer_vk *buffer_vk = wined3d_buffer_vk(buffer);
1315 struct wined3d_device *device = buffer_vk->b.resource.device;
1316 unsigned int swapchain_count = device->swapchain_count;
1318 TRACE("buffer_vk %p.\n", buffer_vk);
1320 /* Take a reference to the device, in case releasing the buffer would
1321 * cause the device to be destroyed. However, swapchain resources don't
1322 * take a reference to the device, and we wouldn't want to increment the
1323 * refcount on a device that's in the process of being destroyed. */
1324 if (swapchain_count)
1325 wined3d_device_incref(device);
1326 wined3d_buffer_cleanup(&buffer_vk->b);
1327 wined3d_cs_destroy_object(device->cs, heap_free, buffer_vk);
1328 if (swapchain_count)
1329 wined3d_device_decref(device);
1332 static HRESULT adapter_vk_create_texture(struct wined3d_device *device,
1333 const struct wined3d_resource_desc *desc, unsigned int layer_count, unsigned int level_count,
1334 uint32_t flags, void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_texture **texture)
1336 struct wined3d_texture_vk *texture_vk;
1337 HRESULT hr;
1339 TRACE("device %p, desc %p, layer_count %u, level_count %u, flags %#x, parent %p, parent_ops %p, texture %p.\n",
1340 device, desc, layer_count, level_count, flags, parent, parent_ops, texture);
1342 if (!(texture_vk = wined3d_texture_allocate_object_memory(sizeof(*texture_vk), level_count, layer_count)))
1343 return E_OUTOFMEMORY;
1345 if (FAILED(hr = wined3d_texture_vk_init(texture_vk, device, desc,
1346 layer_count, level_count, flags, parent, parent_ops)))
1348 WARN("Failed to initialise texture, hr %#lx.\n", hr);
1349 heap_free(texture_vk);
1350 return hr;
1353 TRACE("Created texture %p.\n", texture_vk);
1354 *texture = &texture_vk->t;
1356 return hr;
1359 static void adapter_vk_destroy_texture(struct wined3d_texture *texture)
1361 struct wined3d_texture_vk *texture_vk = wined3d_texture_vk(texture);
1362 struct wined3d_device *device = texture_vk->t.resource.device;
1363 unsigned int swapchain_count = device->swapchain_count;
1365 TRACE("texture_vk %p.\n", texture_vk);
1367 /* Take a reference to the device, in case releasing the texture would
1368 * cause the device to be destroyed. However, swapchain resources don't
1369 * take a reference to the device, and we wouldn't want to increment the
1370 * refcount on a device that's in the process of being destroyed. */
1371 if (swapchain_count)
1372 wined3d_device_incref(device);
1374 wined3d_texture_sub_resources_destroyed(texture);
1375 texture->resource.parent_ops->wined3d_object_destroyed(texture->resource.parent);
1377 wined3d_texture_cleanup(&texture_vk->t);
1378 wined3d_cs_destroy_object(device->cs, heap_free, texture_vk);
1380 if (swapchain_count)
1381 wined3d_device_decref(device);
1384 static HRESULT adapter_vk_create_rendertarget_view(const struct wined3d_view_desc *desc,
1385 struct wined3d_resource *resource, void *parent, const struct wined3d_parent_ops *parent_ops,
1386 struct wined3d_rendertarget_view **view)
1388 struct wined3d_rendertarget_view_vk *view_vk;
1389 HRESULT hr;
1391 TRACE("desc %s, resource %p, parent %p, parent_ops %p, view %p.\n",
1392 wined3d_debug_view_desc(desc, resource), resource, parent, parent_ops, view);
1394 if (!(view_vk = heap_alloc_zero(sizeof(*view_vk))))
1395 return E_OUTOFMEMORY;
1397 if (FAILED(hr = wined3d_rendertarget_view_vk_init(view_vk, desc, resource, parent, parent_ops)))
1399 WARN("Failed to initialise view, hr %#lx.\n", hr);
1400 heap_free(view_vk);
1401 return hr;
1404 TRACE("Created render target view %p.\n", view_vk);
1405 *view = &view_vk->v;
1407 return hr;
1410 struct wined3d_view_vk_destroy_ctx
1412 struct wined3d_device_vk *device_vk;
1413 VkBufferView *vk_buffer_view;
1414 VkImageView *vk_image_view;
1415 struct wined3d_bo_user *bo_user;
1416 struct wined3d_bo_vk *vk_counter_bo;
1417 VkBufferView *vk_counter_view;
1418 uint64_t *command_buffer_id;
1419 void *object;
1420 struct wined3d_view_vk_destroy_ctx *free;
1423 static void wined3d_view_vk_destroy_object(void *object)
1425 struct wined3d_view_vk_destroy_ctx *ctx = object;
1426 const struct wined3d_vk_info *vk_info;
1427 struct wined3d_device_vk *device_vk;
1428 struct wined3d_context *context;
1430 TRACE("ctx %p.\n", ctx);
1432 device_vk = ctx->device_vk;
1433 vk_info = &wined3d_adapter_vk(device_vk->d.adapter)->vk_info;
1434 context = context_acquire(&device_vk->d, NULL, 0);
1436 if (ctx->vk_buffer_view)
1438 if (context)
1440 wined3d_context_vk_destroy_vk_buffer_view(wined3d_context_vk(context),
1441 *ctx->vk_buffer_view, *ctx->command_buffer_id);
1443 else
1445 VK_CALL(vkDestroyBufferView(device_vk->vk_device, *ctx->vk_buffer_view, NULL));
1446 TRACE("Destroyed buffer view 0x%s.\n", wine_dbgstr_longlong(*ctx->vk_buffer_view));
1449 if (ctx->vk_image_view)
1451 if (context)
1453 wined3d_context_vk_destroy_vk_image_view(wined3d_context_vk(context),
1454 *ctx->vk_image_view, *ctx->command_buffer_id);
1456 else
1458 VK_CALL(vkDestroyImageView(device_vk->vk_device, *ctx->vk_image_view, NULL));
1459 TRACE("Destroyed image view 0x%s.\n", wine_dbgstr_longlong(*ctx->vk_image_view));
1462 if (ctx->bo_user)
1463 list_remove(&ctx->bo_user->entry);
1464 if (ctx->vk_counter_bo && ctx->vk_counter_bo->vk_buffer)
1465 wined3d_context_vk_destroy_bo(wined3d_context_vk(context), ctx->vk_counter_bo);
1466 if (ctx->vk_counter_view)
1468 if (context)
1470 wined3d_context_vk_destroy_vk_buffer_view(wined3d_context_vk(context),
1471 *ctx->vk_counter_view, *ctx->command_buffer_id);
1473 else
1475 VK_CALL(vkDestroyBufferView(device_vk->vk_device, *ctx->vk_counter_view, NULL));
1476 TRACE("Destroyed counter buffer view 0x%s.\n", wine_dbgstr_longlong(*ctx->vk_counter_view));
1480 if (context)
1481 context_release(context);
1483 heap_free(ctx->object);
1484 heap_free(ctx->free);
1487 static void wined3d_view_vk_destroy(struct wined3d_device *device, VkBufferView *vk_buffer_view,
1488 VkImageView *vk_image_view, struct wined3d_bo_user *bo_user, struct wined3d_bo_vk *vk_counter_bo,
1489 VkBufferView *vk_counter_view, uint64_t *command_buffer_id, void *view_vk)
1491 struct wined3d_view_vk_destroy_ctx *ctx, c;
1493 if (!(ctx = heap_alloc(sizeof(*ctx))))
1494 ctx = &c;
1495 ctx->device_vk = wined3d_device_vk(device);
1496 ctx->vk_buffer_view = vk_buffer_view;
1497 ctx->vk_image_view = vk_image_view;
1498 ctx->bo_user = bo_user;
1499 ctx->vk_counter_bo = vk_counter_bo;
1500 ctx->vk_counter_view = vk_counter_view;
1501 ctx->command_buffer_id = command_buffer_id;
1502 ctx->object = view_vk;
1503 ctx->free = ctx != &c ? ctx : NULL;
1505 wined3d_cs_destroy_object(device->cs, wined3d_view_vk_destroy_object, ctx);
1506 if (ctx == &c)
1507 wined3d_cs_finish(device->cs, WINED3D_CS_QUEUE_DEFAULT);
1510 static void adapter_vk_destroy_rendertarget_view(struct wined3d_rendertarget_view *view)
1512 struct wined3d_rendertarget_view_vk *view_vk = wined3d_rendertarget_view_vk(view);
1513 struct wined3d_resource *resource = view_vk->v.resource;
1515 TRACE("view_vk %p.\n", view_vk);
1517 /* Take a reference to the resource, in case releasing the resource
1518 * would cause the device to be destroyed. */
1519 wined3d_resource_incref(resource);
1520 wined3d_rendertarget_view_cleanup(&view_vk->v);
1521 wined3d_view_vk_destroy(resource->device, NULL, &view_vk->vk_image_view,
1522 NULL, NULL, NULL, &view_vk->command_buffer_id, view_vk);
1523 wined3d_resource_decref(resource);
1526 static HRESULT adapter_vk_create_shader_resource_view(const struct wined3d_view_desc *desc,
1527 struct wined3d_resource *resource, void *parent, const struct wined3d_parent_ops *parent_ops,
1528 struct wined3d_shader_resource_view **view)
1530 struct wined3d_shader_resource_view_vk *view_vk;
1531 HRESULT hr;
1533 TRACE("desc %s, resource %p, parent %p, parent_ops %p, view %p.\n",
1534 wined3d_debug_view_desc(desc, resource), resource, parent, parent_ops, view);
1536 if (!(view_vk = heap_alloc_zero(sizeof(*view_vk))))
1537 return E_OUTOFMEMORY;
1539 if (FAILED(hr = wined3d_shader_resource_view_vk_init(view_vk, desc, resource, parent, parent_ops)))
1541 WARN("Failed to initialise view, hr %#lx.\n", hr);
1542 heap_free(view_vk);
1543 return hr;
1546 TRACE("Created shader resource view %p.\n", view_vk);
1547 *view = &view_vk->v;
1549 return hr;
1552 static void adapter_vk_destroy_shader_resource_view(struct wined3d_shader_resource_view *view)
1554 struct wined3d_shader_resource_view_vk *srv_vk = wined3d_shader_resource_view_vk(view);
1555 struct wined3d_resource *resource = srv_vk->v.resource;
1556 struct wined3d_view_vk *view_vk = &srv_vk->view_vk;
1557 VkBufferView *vk_buffer_view = NULL;
1558 VkImageView *vk_image_view = NULL;
1560 TRACE("srv_vk %p.\n", srv_vk);
1562 /* Take a reference to the resource. There are two reasons for this:
1563 * - Releasing the resource could in turn cause the device to be
1564 * destroyed, but we still need the device for
1565 * wined3d_view_vk_destroy().
1566 * - We shouldn't free buffer resources until after we've removed the
1567 * view from its bo_user list. */
1568 wined3d_resource_incref(resource);
1569 if (resource->type == WINED3D_RTYPE_BUFFER)
1570 vk_buffer_view = &view_vk->u.vk_buffer_view;
1571 else
1572 vk_image_view = &view_vk->u.vk_image_info.imageView;
1573 wined3d_shader_resource_view_cleanup(&srv_vk->v);
1574 wined3d_view_vk_destroy(resource->device, vk_buffer_view, vk_image_view,
1575 &view_vk->bo_user, NULL, NULL, &view_vk->command_buffer_id, srv_vk);
1576 wined3d_resource_decref(resource);
1579 static HRESULT adapter_vk_create_unordered_access_view(const struct wined3d_view_desc *desc,
1580 struct wined3d_resource *resource, void *parent, const struct wined3d_parent_ops *parent_ops,
1581 struct wined3d_unordered_access_view **view)
1583 struct wined3d_unordered_access_view_vk *view_vk;
1584 HRESULT hr;
1586 TRACE("desc %s, resource %p, parent %p, parent_ops %p, view %p.\n",
1587 wined3d_debug_view_desc(desc, resource), resource, parent, parent_ops, view);
1589 if (!(view_vk = heap_alloc_zero(sizeof(*view_vk))))
1590 return E_OUTOFMEMORY;
1592 if (FAILED(hr = wined3d_unordered_access_view_vk_init(view_vk, desc, resource, parent, parent_ops)))
1594 WARN("Failed to initialise view, hr %#lx.\n", hr);
1595 heap_free(view_vk);
1596 return hr;
1599 TRACE("Created unordered access view %p.\n", view_vk);
1600 *view = &view_vk->v;
1602 return hr;
1605 static void adapter_vk_destroy_unordered_access_view(struct wined3d_unordered_access_view *view)
1607 struct wined3d_unordered_access_view_vk *uav_vk = wined3d_unordered_access_view_vk(view);
1608 struct wined3d_resource *resource = uav_vk->v.resource;
1609 struct wined3d_view_vk *view_vk = &uav_vk->view_vk;
1610 VkBufferView *vk_buffer_view = NULL;
1611 VkImageView *vk_image_view = NULL;
1613 TRACE("uav_vk %p.\n", uav_vk);
1615 /* Take a reference to the resource. There are two reasons for this:
1616 * - Releasing the resource could in turn cause the device to be
1617 * destroyed, but we still need the device for
1618 * wined3d_view_vk_destroy().
1619 * - We shouldn't free buffer resources until after we've removed the
1620 * view from its bo_user list. */
1621 wined3d_resource_incref(resource);
1622 if (resource->type == WINED3D_RTYPE_BUFFER)
1623 vk_buffer_view = &view_vk->u.vk_buffer_view;
1624 else
1625 vk_image_view = &view_vk->u.vk_image_info.imageView;
1626 wined3d_unordered_access_view_cleanup(&uav_vk->v);
1627 wined3d_view_vk_destroy(resource->device, vk_buffer_view, vk_image_view, &view_vk->bo_user,
1628 &uav_vk->counter_bo, &uav_vk->vk_counter_view, &view_vk->command_buffer_id, uav_vk);
1629 wined3d_resource_decref(resource);
1632 static HRESULT adapter_vk_create_sampler(struct wined3d_device *device, const struct wined3d_sampler_desc *desc,
1633 void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_sampler **sampler)
1635 struct wined3d_sampler_vk *sampler_vk;
1637 TRACE("device %p, desc %p, parent %p, parent_ops %p, sampler %p.\n",
1638 device, desc, parent, parent_ops, sampler);
1640 if (!(sampler_vk = heap_alloc_zero(sizeof(*sampler_vk))))
1641 return E_OUTOFMEMORY;
1643 wined3d_sampler_vk_init(sampler_vk, device, desc, parent, parent_ops);
1645 TRACE("Created sampler %p.\n", sampler_vk);
1646 *sampler = &sampler_vk->s;
1648 return WINED3D_OK;
1651 static void wined3d_sampler_vk_destroy_object(void *object)
1653 struct wined3d_sampler_vk *sampler_vk = object;
1654 struct wined3d_context_vk *context_vk;
1656 TRACE("sampler_vk %p.\n", sampler_vk);
1658 context_vk = wined3d_context_vk(context_acquire(sampler_vk->s.device, NULL, 0));
1660 wined3d_context_vk_destroy_vk_sampler(context_vk, sampler_vk->vk_image_info.sampler, sampler_vk->command_buffer_id);
1661 heap_free(sampler_vk);
1663 context_release(&context_vk->c);
1666 static void adapter_vk_destroy_sampler(struct wined3d_sampler *sampler)
1668 struct wined3d_sampler_vk *sampler_vk = wined3d_sampler_vk(sampler);
1670 TRACE("sampler_vk %p.\n", sampler_vk);
1672 wined3d_cs_destroy_object(sampler->device->cs, wined3d_sampler_vk_destroy_object, sampler_vk);
1675 static HRESULT adapter_vk_create_query(struct wined3d_device *device, enum wined3d_query_type type,
1676 void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_query **query)
1678 TRACE("device %p, type %#x, parent %p, parent_ops %p, query %p.\n",
1679 device, type, parent, parent_ops, query);
1681 return wined3d_query_vk_create(device, type, parent, parent_ops, query);
1684 static void wined3d_query_vk_destroy_object(void *object)
1686 struct wined3d_query_vk *query_vk = object;
1688 TRACE("query_vk %p.\n", query_vk);
1690 query_vk->q.query_ops->query_destroy(&query_vk->q);
1693 static void adapter_vk_destroy_query(struct wined3d_query *query)
1695 struct wined3d_query_vk *query_vk = wined3d_query_vk(query);
1697 TRACE("query_vk %p.\n", query_vk);
1699 wined3d_cs_destroy_object(query->device->cs, wined3d_query_vk_destroy_object, query_vk);
1702 static void adapter_vk_flush_context(struct wined3d_context *context)
1704 struct wined3d_context_vk *context_vk = wined3d_context_vk(context);
1706 TRACE("context_vk %p.\n", context_vk);
1708 wined3d_context_vk_submit_command_buffer(context_vk, 0, NULL, NULL, 0, NULL);
1711 static void adapter_vk_draw_primitive(struct wined3d_device *device,
1712 const struct wined3d_state *state, const struct wined3d_draw_parameters *parameters)
1714 struct wined3d_buffer_vk *indirect_vk = NULL;
1715 const struct wined3d_vk_info *vk_info;
1716 struct wined3d_context_vk *context_vk;
1717 VkCommandBuffer vk_command_buffer;
1718 uint32_t instance_count;
1719 unsigned int i;
1721 TRACE("device %p, state %p, parameters %p.\n", device, state, parameters);
1723 context_vk = wined3d_context_vk(context_acquire(device, NULL, 0));
1724 vk_info = context_vk->vk_info;
1726 if (parameters->indirect)
1727 indirect_vk = wined3d_buffer_vk(parameters->u.indirect.buffer);
1729 if (!(vk_command_buffer = wined3d_context_vk_apply_draw_state(context_vk,
1730 state, indirect_vk, parameters->indexed)))
1732 ERR("Failed to apply draw state.\n");
1733 context_release(&context_vk->c);
1734 return;
1737 if (context_vk->c.transform_feedback_active)
1739 if (!context_vk->vk_so_counter_bo.vk_buffer)
1741 struct wined3d_bo_vk *bo = &context_vk->vk_so_counter_bo;
1743 if (!wined3d_context_vk_create_bo(context_vk, ARRAY_SIZE(context_vk->vk_so_counters) * sizeof(uint32_t) * 2,
1744 VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, bo))
1745 ERR("Failed to create counter BO.\n");
1746 for (i = 0; i < ARRAY_SIZE(context_vk->vk_so_counters); ++i)
1748 context_vk->vk_so_counters[i] = bo->vk_buffer;
1749 context_vk->vk_so_offsets[i] = bo->b.buffer_offset + i * sizeof(uint32_t) * 2;
1753 wined3d_context_vk_reference_bo(context_vk, &context_vk->vk_so_counter_bo);
1754 if (context_vk->c.transform_feedback_paused)
1755 VK_CALL(vkCmdBeginTransformFeedbackEXT(vk_command_buffer, 0, ARRAY_SIZE(context_vk->vk_so_counters),
1756 context_vk->vk_so_counters, context_vk->vk_so_offsets));
1757 else
1758 VK_CALL(vkCmdBeginTransformFeedbackEXT(vk_command_buffer, 0, 0, NULL, NULL));
1761 if (parameters->indirect)
1763 struct wined3d_bo_vk *bo = wined3d_bo_vk(indirect_vk->b.buffer_object);
1765 wined3d_context_vk_reference_bo(context_vk, bo);
1766 if (parameters->indexed)
1767 VK_CALL(vkCmdDrawIndexedIndirect(vk_command_buffer, bo->vk_buffer,
1768 bo->b.buffer_offset + parameters->u.indirect.offset, 1, sizeof(VkDrawIndexedIndirectCommand)));
1769 else
1770 VK_CALL(vkCmdDrawIndirect(vk_command_buffer, bo->vk_buffer,
1771 bo->b.buffer_offset + parameters->u.indirect.offset, 1, sizeof(VkDrawIndirectCommand)));
1773 else
1775 instance_count = parameters->u.direct.instance_count;
1776 if (!instance_count)
1777 instance_count = 1;
1779 if (parameters->indexed)
1780 VK_CALL(vkCmdDrawIndexed(vk_command_buffer, parameters->u.direct.index_count,
1781 instance_count, parameters->u.direct.start_idx, parameters->u.direct.base_vertex_idx,
1782 parameters->u.direct.start_instance));
1783 else
1784 VK_CALL(vkCmdDraw(vk_command_buffer, parameters->u.direct.index_count, instance_count,
1785 parameters->u.direct.start_idx, parameters->u.direct.start_instance));
1788 if (context_vk->c.transform_feedback_active)
1790 VK_CALL(vkCmdEndTransformFeedbackEXT(vk_command_buffer, 0, ARRAY_SIZE(context_vk->vk_so_counters),
1791 context_vk->vk_so_counters, context_vk->vk_so_offsets));
1792 context_vk->c.transform_feedback_paused = 1;
1793 context_vk->c.transform_feedback_active = 0;
1796 context_release(&context_vk->c);
1799 static void adapter_vk_dispatch_compute(struct wined3d_device *device,
1800 const struct wined3d_state *state, const struct wined3d_dispatch_parameters *parameters)
1802 struct wined3d_buffer_vk *indirect_vk = NULL;
1803 const struct wined3d_vk_info *vk_info;
1804 struct wined3d_context_vk *context_vk;
1805 VkCommandBuffer vk_command_buffer;
1807 TRACE("device %p, state %p, parameters %p.\n", device, state, parameters);
1809 context_vk = wined3d_context_vk(context_acquire(device, NULL, 0));
1810 vk_info = context_vk->vk_info;
1812 if (parameters->indirect)
1813 indirect_vk = wined3d_buffer_vk(parameters->u.indirect.buffer);
1815 if (!(vk_command_buffer = wined3d_context_vk_apply_compute_state(context_vk, state, indirect_vk)))
1817 ERR("Failed to apply compute state.\n");
1818 context_release(&context_vk->c);
1819 return;
1822 if (parameters->indirect)
1824 struct wined3d_bo_vk *bo = wined3d_bo_vk(indirect_vk->b.buffer_object);
1826 wined3d_context_vk_reference_bo(context_vk, bo);
1827 VK_CALL(vkCmdDispatchIndirect(vk_command_buffer, bo->vk_buffer,
1828 bo->b.buffer_offset + parameters->u.indirect.offset));
1830 else
1832 const struct wined3d_direct_dispatch_parameters *direct = &parameters->u.direct;
1834 VK_CALL(vkCmdDispatch(vk_command_buffer, direct->group_count_x, direct->group_count_y, direct->group_count_z));
1837 VK_CALL(vkCmdPipelineBarrier(vk_command_buffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
1838 VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, 0, 0, NULL, 0, NULL, 0, NULL));
1840 context_release(&context_vk->c);
1843 static void adapter_vk_clear_uav(struct wined3d_context *context,
1844 struct wined3d_unordered_access_view *view, const struct wined3d_uvec4 *clear_value, bool fp)
1846 TRACE("context %p, view %p, clear_value %s.\n", context, view, debug_uvec4(clear_value));
1848 wined3d_unordered_access_view_vk_clear(wined3d_unordered_access_view_vk(view),
1849 clear_value, wined3d_context_vk(context), fp);
1852 static void adapter_vk_generate_mipmap(struct wined3d_context *context, struct wined3d_shader_resource_view *view)
1854 TRACE("context %p, view %p.\n", context, view);
1856 wined3d_shader_resource_view_vk_generate_mipmap(wined3d_shader_resource_view_vk(view),
1857 wined3d_context_vk(context));
1860 static const struct wined3d_adapter_ops wined3d_adapter_vk_ops =
1862 .adapter_destroy = adapter_vk_destroy,
1863 .adapter_create_device = adapter_vk_create_device,
1864 .adapter_destroy_device = adapter_vk_destroy_device,
1865 .adapter_acquire_context = adapter_vk_acquire_context,
1866 .adapter_release_context = adapter_vk_release_context,
1867 .adapter_get_wined3d_caps = adapter_vk_get_wined3d_caps,
1868 .adapter_check_format = adapter_vk_check_format,
1869 .adapter_init_3d = adapter_vk_init_3d,
1870 .adapter_uninit_3d = adapter_vk_uninit_3d,
1871 .adapter_map_bo_address = adapter_vk_map_bo_address,
1872 .adapter_unmap_bo_address = adapter_vk_unmap_bo_address,
1873 .adapter_copy_bo_address = adapter_vk_copy_bo_address,
1874 .adapter_flush_bo_address = adapter_vk_flush_bo_address,
1875 .adapter_alloc_bo = adapter_vk_alloc_bo,
1876 .adapter_destroy_bo = adapter_vk_destroy_bo,
1877 .adapter_create_swapchain = adapter_vk_create_swapchain,
1878 .adapter_destroy_swapchain = adapter_vk_destroy_swapchain,
1879 .adapter_create_buffer = adapter_vk_create_buffer,
1880 .adapter_destroy_buffer = adapter_vk_destroy_buffer,
1881 .adapter_create_texture = adapter_vk_create_texture,
1882 .adapter_destroy_texture = adapter_vk_destroy_texture,
1883 .adapter_create_rendertarget_view = adapter_vk_create_rendertarget_view,
1884 .adapter_destroy_rendertarget_view = adapter_vk_destroy_rendertarget_view,
1885 .adapter_create_shader_resource_view = adapter_vk_create_shader_resource_view,
1886 .adapter_destroy_shader_resource_view = adapter_vk_destroy_shader_resource_view,
1887 .adapter_create_unordered_access_view = adapter_vk_create_unordered_access_view,
1888 .adapter_destroy_unordered_access_view = adapter_vk_destroy_unordered_access_view,
1889 .adapter_create_sampler = adapter_vk_create_sampler,
1890 .adapter_destroy_sampler = adapter_vk_destroy_sampler,
1891 .adapter_create_query = adapter_vk_create_query,
1892 .adapter_destroy_query = adapter_vk_destroy_query,
1893 .adapter_flush_context = adapter_vk_flush_context,
1894 .adapter_draw_primitive = adapter_vk_draw_primitive,
1895 .adapter_dispatch_compute = adapter_vk_dispatch_compute,
1896 .adapter_clear_uav = adapter_vk_clear_uav,
1897 .adapter_generate_mipmap = adapter_vk_generate_mipmap,
1900 static unsigned int wined3d_get_wine_vk_version(void)
1902 const char * (CDECL *wine_get_version)(void) = (void *)GetProcAddress( GetModuleHandleW(L"ntdll.dll"),
1903 "wine_get_version" );
1904 const char *ptr;
1905 int major, minor;
1907 if (!wine_get_version) return VK_MAKE_VERSION(1, 0, 0);
1909 ptr = wine_get_version();
1910 major = atoi(ptr);
1912 while (isdigit(*ptr))
1913 ++ptr;
1914 if (*ptr == '.')
1915 ++ptr;
1917 minor = atoi(ptr);
1919 return VK_MAKE_VERSION(major, minor, 0);
1922 static const struct
1924 const char *name;
1925 unsigned int core_since_version;
1926 BOOL required;
1928 vulkan_instance_extensions[] =
1930 {VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, VK_API_VERSION_1_1, FALSE},
1931 {VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME, VK_API_VERSION_1_1, FALSE},
1932 {VK_KHR_SURFACE_EXTENSION_NAME, ~0u, TRUE},
1933 {VK_KHR_WIN32_SURFACE_EXTENSION_NAME, ~0u, TRUE},
1936 static BOOL enable_vulkan_instance_extensions(uint32_t *extension_count,
1937 const char *enabled_extensions[], const struct wined3d_vk_info *vk_info)
1939 PFN_vkEnumerateInstanceExtensionProperties pfn_vkEnumerateInstanceExtensionProperties;
1940 VkExtensionProperties *extensions = NULL;
1941 BOOL success = FALSE, found;
1942 unsigned int i, j, count;
1943 VkResult vr;
1945 *extension_count = 0;
1947 if (!(pfn_vkEnumerateInstanceExtensionProperties
1948 = (void *)VK_CALL(vkGetInstanceProcAddr(NULL, "vkEnumerateInstanceExtensionProperties"))))
1950 WARN("Failed to get 'vkEnumerateInstanceExtensionProperties'.\n");
1951 goto done;
1954 if ((vr = pfn_vkEnumerateInstanceExtensionProperties(NULL, &count, NULL)) < 0)
1956 WARN("Failed to count instance extensions, vr %s.\n", wined3d_debug_vkresult(vr));
1957 goto done;
1959 if (!(extensions = heap_calloc(count, sizeof(*extensions))))
1961 WARN("Out of memory.\n");
1962 goto done;
1964 if ((vr = pfn_vkEnumerateInstanceExtensionProperties(NULL, &count, extensions)) < 0)
1966 WARN("Failed to enumerate extensions, vr %s.\n", wined3d_debug_vkresult(vr));
1967 goto done;
1970 TRACE("Vulkan instance extensions reported:\n");
1971 for (i = 0; i < count; ++i)
1973 TRACE(" - %s.\n", debugstr_a(extensions[i].extensionName));
1976 for (i = 0; i < ARRAY_SIZE(vulkan_instance_extensions); ++i)
1978 if (vulkan_instance_extensions[i].core_since_version <= vk_info->api_version)
1979 continue;
1981 for (j = 0, found = FALSE; j < count; ++j)
1983 if (!strcmp(extensions[j].extensionName, vulkan_instance_extensions[i].name))
1985 found = TRUE;
1986 break;
1989 if (found)
1991 TRACE("Enabling instance extension '%s'.\n", vulkan_instance_extensions[i].name);
1992 enabled_extensions[(*extension_count)++] = vulkan_instance_extensions[i].name;
1994 else if (!found && vulkan_instance_extensions[i].required)
1996 WARN("Required extension '%s' is not available.\n", vulkan_instance_extensions[i].name);
1997 goto done;
2000 success = TRUE;
2002 done:
2003 heap_free(extensions);
2004 return success;
2007 static BOOL wined3d_init_vulkan(struct wined3d_vk_info *vk_info)
2009 const char *enabled_instance_extensions[ARRAY_SIZE(vulkan_instance_extensions)];
2010 PFN_vkEnumerateInstanceVersion pfn_vkEnumerateInstanceVersion;
2011 struct vulkan_ops *vk_ops = &vk_info->vk_ops;
2012 VkInstance instance = VK_NULL_HANDLE;
2013 VkInstanceCreateInfo instance_info;
2014 VkApplicationInfo app_info;
2015 uint32_t api_version = 0;
2016 char app_name[MAX_PATH];
2017 VkResult vr;
2019 if (!wined3d_load_vulkan(vk_info))
2020 return FALSE;
2022 if (!(vk_ops->vkCreateInstance = (void *)VK_CALL(vkGetInstanceProcAddr(NULL, "vkCreateInstance"))))
2024 ERR("Failed to get 'vkCreateInstance'.\n");
2025 goto fail;
2028 vk_info->api_version = VK_API_VERSION_1_0;
2029 if ((pfn_vkEnumerateInstanceVersion = (void *)VK_CALL(vkGetInstanceProcAddr(NULL, "vkEnumerateInstanceVersion")))
2030 && pfn_vkEnumerateInstanceVersion(&api_version) == VK_SUCCESS)
2032 TRACE("Vulkan instance API version %s.\n", debug_vk_version(api_version));
2034 if (api_version >= VK_API_VERSION_1_1)
2035 vk_info->api_version = VK_API_VERSION_1_1;
2038 memset(&app_info, 0, sizeof(app_info));
2039 app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
2040 if (wined3d_get_app_name(app_name, ARRAY_SIZE(app_name)))
2041 app_info.pApplicationName = app_name;
2042 app_info.pEngineName = "Damavand";
2043 app_info.engineVersion = wined3d_get_wine_vk_version();
2044 app_info.apiVersion = vk_info->api_version;
2046 memset(&instance_info, 0, sizeof(instance_info));
2047 instance_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
2048 instance_info.pApplicationInfo = &app_info;
2049 instance_info.ppEnabledExtensionNames = enabled_instance_extensions;
2050 if (!enable_vulkan_instance_extensions(&instance_info.enabledExtensionCount, enabled_instance_extensions, vk_info))
2051 goto fail;
2053 memset(vk_info->supported, 0, sizeof(vk_info->supported));
2054 vk_info->supported[WINED3D_VK_EXT_NONE] = TRUE;
2056 if ((vr = VK_CALL(vkCreateInstance(&instance_info, NULL, &instance))) < 0)
2058 WARN("Failed to create Vulkan instance, vr %s.\n", wined3d_debug_vkresult(vr));
2059 goto fail;
2062 TRACE("Created Vulkan instance %p.\n", instance);
2064 #define LOAD_INSTANCE_PFN(name) \
2065 if (!(vk_ops->name = (void *)VK_CALL(vkGetInstanceProcAddr(instance, #name)))) \
2067 WARN("Could not get instance proc addr for '" #name "'.\n"); \
2068 goto fail; \
2070 #define LOAD_INSTANCE_OPT_PFN(name) \
2071 vk_ops->name = (void *)VK_CALL(vkGetInstanceProcAddr(instance, #name));
2072 #define VK_INSTANCE_PFN LOAD_INSTANCE_PFN
2073 #define VK_INSTANCE_EXT_PFN LOAD_INSTANCE_OPT_PFN
2074 #define VK_DEVICE_PFN LOAD_INSTANCE_PFN
2075 #define VK_DEVICE_EXT_PFN LOAD_INSTANCE_OPT_PFN
2076 VK_INSTANCE_FUNCS()
2077 VK_DEVICE_FUNCS()
2078 #undef VK_INSTANCE_PFN
2079 #undef VK_INSTANCE_EXT_PFN
2080 #undef VK_DEVICE_PFN
2081 #undef VK_DEVICE_EXT_PFN
2083 #define MAP_INSTANCE_FUNCTION(core_pfn, ext_pfn) \
2084 if (!vk_ops->core_pfn) \
2085 vk_ops->core_pfn = (void *)VK_CALL(vkGetInstanceProcAddr(instance, #ext_pfn));
2086 MAP_INSTANCE_FUNCTION(vkGetPhysicalDeviceProperties2, vkGetPhysicalDeviceProperties2KHR)
2087 MAP_INSTANCE_FUNCTION(vkGetPhysicalDeviceFeatures2, vkGetPhysicalDeviceFeatures2KHR)
2088 #undef MAP_INSTANCE_FUNCTION
2090 vk_info->instance = instance;
2092 return TRUE;
2094 fail:
2095 if (vk_ops->vkDestroyInstance)
2096 VK_CALL(vkDestroyInstance(instance, NULL));
2097 wined3d_unload_vulkan(vk_info);
2098 return FALSE;
2101 static VkPhysicalDevice get_vulkan_physical_device(struct wined3d_vk_info *vk_info)
2103 VkPhysicalDevice physical_devices[1];
2104 uint32_t count;
2105 VkResult vr;
2107 if ((vr = VK_CALL(vkEnumeratePhysicalDevices(vk_info->instance, &count, NULL))) < 0)
2109 WARN("Failed to enumerate physical devices, vr %s.\n", wined3d_debug_vkresult(vr));
2110 return VK_NULL_HANDLE;
2112 if (!count)
2114 WARN("No physical device.\n");
2115 return VK_NULL_HANDLE;
2117 if (count > 1)
2119 /* TODO: Create wined3d_adapter for each device. */
2120 FIXME("Multiple physical devices available.\n");
2121 count = 1;
2124 if ((vr = VK_CALL(vkEnumeratePhysicalDevices(vk_info->instance, &count, physical_devices))) < 0)
2126 WARN("Failed to get physical devices, vr %s.\n", wined3d_debug_vkresult(vr));
2127 return VK_NULL_HANDLE;
2130 return physical_devices[0];
2133 static enum wined3d_display_driver guess_display_driver(enum wined3d_pci_vendor vendor)
2135 switch (vendor)
2137 case HW_VENDOR_AMD: return DRIVER_AMD_RX;
2138 case HW_VENDOR_INTEL: return DRIVER_INTEL_HD4000;
2139 case HW_VENDOR_NVIDIA: return DRIVER_NVIDIA_GEFORCE8;
2140 default: return DRIVER_WINE;
2144 static bool adapter_vk_init_driver_info(struct wined3d_adapter_vk *adapter_vk,
2145 const VkPhysicalDeviceProperties *properties)
2147 const VkPhysicalDeviceMemoryProperties *memory_properties = &adapter_vk->memory_properties;
2148 const struct wined3d_gpu_description *gpu_description;
2149 struct wined3d_gpu_description description;
2150 UINT64 vram_bytes, sysmem_bytes;
2151 const VkMemoryType *type;
2152 const VkMemoryHeap *heap;
2153 unsigned int i;
2155 TRACE("Device name: %s.\n", debugstr_a(properties->deviceName));
2156 TRACE("Vendor ID: 0x%04x, Device ID: 0x%04x.\n", properties->vendorID, properties->deviceID);
2157 TRACE("Driver version: %#x.\n", properties->driverVersion);
2158 TRACE("API version: %s.\n", debug_vk_version(properties->apiVersion));
2160 for (i = 0, vram_bytes = 0, sysmem_bytes = 0; i < memory_properties->memoryHeapCount; ++i)
2162 heap = &memory_properties->memoryHeaps[i];
2163 TRACE("Memory heap [%u]: flags %#x, size 0x%s.\n",
2164 i, heap->flags, wine_dbgstr_longlong(heap->size));
2165 if (heap->flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT)
2166 vram_bytes += heap->size;
2167 else
2168 sysmem_bytes += heap->size;
2170 TRACE("Total device memory: 0x%s.\n", wine_dbgstr_longlong(vram_bytes));
2171 TRACE("Total shared system memory: 0x%s.\n", wine_dbgstr_longlong(sysmem_bytes));
2173 for (i = 0; i < memory_properties->memoryTypeCount; ++i)
2175 type = &memory_properties->memoryTypes[i];
2176 TRACE("Memory type [%u]: flags %#x, heap %u.\n", i, type->propertyFlags, type->heapIndex);
2179 if (!(gpu_description = wined3d_get_user_override_gpu_description(properties->vendorID, properties->deviceID)))
2180 gpu_description = wined3d_get_gpu_description(properties->vendorID, properties->deviceID);
2182 if (!gpu_description)
2184 FIXME("Failed to retrieve GPU description for device %s %04x:%04x.\n",
2185 debugstr_a(properties->deviceName), properties->vendorID, properties->deviceID);
2187 description.vendor = properties->vendorID;
2188 description.device = properties->deviceID;
2189 description.description = properties->deviceName;
2190 description.driver = guess_display_driver(properties->vendorID);
2191 description.vidmem = vram_bytes;
2193 gpu_description = &description;
2196 return wined3d_driver_info_init(&adapter_vk->a.driver_info, gpu_description,
2197 adapter_vk->a.d3d_info.feature_level, vram_bytes, sysmem_bytes);
2200 static bool feature_level_9_2_supported(const struct wined3d_physical_device_info *info)
2202 return info->features2.features.occlusionQueryPrecise;
2205 static bool feature_level_9_3_supported(const struct wined3d_physical_device_info *info, unsigned int shader_model)
2207 return shader_model >= 3
2208 && info->features2.features.independentBlend;
2211 static bool feature_level_10_supported(const struct wined3d_physical_device_info *info, unsigned int shader_model)
2213 return shader_model >= 4
2214 && info->features2.features.multiViewport
2215 && info->features2.features.geometryShader
2216 && info->features2.features.depthClamp
2217 && info->features2.features.depthBiasClamp
2218 && info->features2.features.pipelineStatisticsQuery
2219 && info->features2.features.shaderClipDistance
2220 && info->features2.features.shaderCullDistance
2221 && info->vertex_divisor_features.vertexAttributeInstanceRateDivisor
2222 && info->vertex_divisor_features.vertexAttributeInstanceRateZeroDivisor;
2225 static bool feature_level_10_1_supported(const struct wined3d_physical_device_info *info, unsigned int shader_model)
2227 return info->features2.features.imageCubeArray;
2230 static bool feature_level_11_supported(const struct wined3d_physical_device_info *info, unsigned int shader_model)
2232 return shader_model >= 5
2233 && info->features2.features.multiDrawIndirect
2234 && info->features2.features.drawIndirectFirstInstance
2235 && info->features2.features.fragmentStoresAndAtomics
2236 && info->features2.features.shaderImageGatherExtended
2237 && info->features2.features.tessellationShader;
2240 static bool feature_level_11_1_supported(const struct wined3d_physical_device_info *info)
2242 return info->features2.features.vertexPipelineStoresAndAtomics;
2245 static enum wined3d_feature_level feature_level_from_caps(const struct wined3d_physical_device_info *info,
2246 const struct shader_caps *shader_caps)
2248 unsigned int shader_model;
2250 shader_model = min(shader_caps->vs_version, shader_caps->ps_version);
2251 shader_model = min(shader_model, max(shader_caps->gs_version, 3));
2252 shader_model = min(shader_model, max(shader_caps->hs_version, 4));
2253 shader_model = min(shader_model, max(shader_caps->ds_version, 4));
2255 if (!shader_model)
2256 return WINED3D_FEATURE_LEVEL_7;
2258 if (shader_model <= 1)
2259 return WINED3D_FEATURE_LEVEL_8;
2261 if (!feature_level_9_2_supported(info))
2262 return WINED3D_FEATURE_LEVEL_9_1;
2264 if (!feature_level_9_3_supported(info, shader_model))
2265 return WINED3D_FEATURE_LEVEL_9_2;
2267 if (!feature_level_10_supported(info, shader_model))
2268 return WINED3D_FEATURE_LEVEL_9_3;
2270 if (!feature_level_10_1_supported(info, shader_model))
2271 return WINED3D_FEATURE_LEVEL_10;
2273 if (!feature_level_11_supported(info, shader_model))
2274 return WINED3D_FEATURE_LEVEL_10_1;
2276 if (!feature_level_11_1_supported(info))
2277 return WINED3D_FEATURE_LEVEL_11;
2279 return WINED3D_FEATURE_LEVEL_11_1;
2282 static void wined3d_adapter_vk_init_d3d_info(struct wined3d_adapter_vk *adapter_vk, uint32_t wined3d_creation_flags)
2284 struct wined3d_d3d_info *d3d_info = &adapter_vk->a.d3d_info;
2285 struct wined3d_vk_info *vk_info = &adapter_vk->vk_info;
2286 struct wined3d_physical_device_info device_info;
2287 struct wined3d_vertex_caps vertex_caps;
2288 struct fragment_caps fragment_caps;
2289 unsigned int sample_counts_mask;
2290 struct shader_caps shader_caps;
2292 get_physical_device_info(adapter_vk, &device_info);
2294 adapter_vk->a.shader_backend->shader_get_caps(&adapter_vk->a, &shader_caps);
2295 adapter_vk->a.vertex_pipe->vp_get_caps(&adapter_vk->a, &vertex_caps);
2296 adapter_vk->a.fragment_pipe->get_caps(&adapter_vk->a, &fragment_caps);
2298 d3d_info->limits.vs_version = shader_caps.vs_version;
2299 d3d_info->limits.hs_version = shader_caps.hs_version;
2300 d3d_info->limits.ds_version = shader_caps.ds_version;
2301 d3d_info->limits.gs_version = shader_caps.gs_version;
2302 d3d_info->limits.ps_version = shader_caps.ps_version;
2303 d3d_info->limits.cs_version = shader_caps.cs_version;
2304 d3d_info->limits.vs_uniform_count = shader_caps.vs_uniform_count;
2305 d3d_info->limits.ps_uniform_count = shader_caps.ps_uniform_count;
2306 d3d_info->limits.varying_count = shader_caps.varying_count;
2307 d3d_info->limits.ffp_textures = fragment_caps.MaxSimultaneousTextures;
2308 d3d_info->limits.ffp_blend_stages = fragment_caps.MaxTextureBlendStages;
2309 d3d_info->limits.ffp_vertex_blend_matrices = vertex_caps.max_vertex_blend_matrices;
2310 d3d_info->limits.active_light_count = vertex_caps.max_active_lights;
2312 d3d_info->limits.max_rt_count = WINED3D_MAX_RENDER_TARGETS;
2313 d3d_info->limits.max_clip_distances = WINED3D_MAX_CLIP_DISTANCES;
2314 d3d_info->limits.texture_size = adapter_vk->device_limits.maxImageDimension2D;
2315 d3d_info->limits.pointsize_max = adapter_vk->device_limits.pointSizeRange[1];
2316 sample_counts_mask = adapter_vk->device_limits.framebufferColorSampleCounts
2317 | adapter_vk->device_limits.framebufferDepthSampleCounts
2318 | adapter_vk->device_limits.framebufferStencilSampleCounts
2319 | adapter_vk->device_limits.framebufferNoAttachmentsSampleCounts;
2320 d3d_info->limits.sample_count = (1u << wined3d_log2i(sample_counts_mask));
2322 d3d_info->wined3d_creation_flags = wined3d_creation_flags;
2324 d3d_info->xyzrhw = vertex_caps.xyzrhw;
2325 d3d_info->emulated_flatshading = vertex_caps.emulated_flatshading;
2326 d3d_info->ffp_generic_attributes = vertex_caps.ffp_generic_attributes;
2327 d3d_info->ffp_alpha_test = false;
2328 d3d_info->vs_clipping = !!(shader_caps.wined3d_caps & WINED3D_SHADER_CAP_VS_CLIPPING);
2329 d3d_info->shader_color_key = !!(fragment_caps.wined3d_caps & WINED3D_FRAGMENT_CAP_COLOR_KEY);
2330 d3d_info->shader_double_precision = !!(shader_caps.wined3d_caps & WINED3D_SHADER_CAP_DOUBLE_PRECISION);
2331 d3d_info->shader_output_interpolation = !!(shader_caps.wined3d_caps & WINED3D_SHADER_CAP_OUTPUT_INTERPOLATION);
2332 d3d_info->viewport_array_index_any_shader = false; /* VK_EXT_shader_viewport_index_layer */
2333 d3d_info->texture_npot = true;
2334 d3d_info->texture_npot_conditional = true;
2335 d3d_info->normalized_texrect = false;
2336 d3d_info->draw_base_vertex_offset = true;
2337 d3d_info->vertex_bgra = true;
2338 d3d_info->texture_swizzle = true;
2339 d3d_info->srgb_read_control = false;
2340 d3d_info->srgb_write_control = false;
2341 d3d_info->clip_control = true;
2342 d3d_info->full_ffp_varyings = !!(shader_caps.wined3d_caps & WINED3D_SHADER_CAP_FULL_FFP_VARYINGS);
2343 d3d_info->scaled_resolve = false;
2344 d3d_info->pbo = true;
2345 d3d_info->feature_level = feature_level_from_caps(&device_info, &shader_caps);
2346 d3d_info->subpixel_viewport = true;
2347 d3d_info->fences = true;
2348 d3d_info->persistent_map = true;
2350 /* Like GL, Vulkan doesn't explicitly specify a filling convention and only mandates that a
2351 * shared edge of two adjacent triangles generate a fragment for exactly one of the triangles.
2353 * However, every Vulkan implementation we have seen so far uses a top-left rule. Hardware
2354 * that differs either predates Vulkan (d3d9 class HW, GeForce 9xxx) or behaves the way we
2355 * want in Vulkan (MacOS Radeon driver through MoltenVK). */
2356 d3d_info->filling_convention_offset = 0.0f;
2358 d3d_info->multisample_draw_location = WINED3D_LOCATION_TEXTURE_RGB;
2360 vk_info->multiple_viewports = device_info.features2.features.multiViewport;
2363 static bool wined3d_adapter_vk_init_device_extensions(struct wined3d_adapter_vk *adapter_vk)
2365 VkPhysicalDevice physical_device = adapter_vk->physical_device;
2366 struct wined3d_vk_info *vk_info = &adapter_vk->vk_info;
2367 unsigned int count, enable_count, i, j;
2368 const char **enabled_extensions = NULL;
2369 VkExtensionProperties *extensions;
2370 bool found, success = false;
2371 SIZE_T enable_size = 0;
2372 VkResult vr;
2374 static const struct
2376 const char *name;
2377 unsigned int core_since_version;
2378 bool required;
2380 info[] =
2382 {VK_EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME, ~0u},
2383 {VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME, ~0u, true},
2384 {VK_KHR_MAINTENANCE1_EXTENSION_NAME, VK_API_VERSION_1_1, true},
2385 {VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE_EXTENSION_NAME,VK_API_VERSION_1_2},
2386 {VK_KHR_SHADER_DRAW_PARAMETERS_EXTENSION_NAME, VK_API_VERSION_1_1, true},
2387 {VK_KHR_SWAPCHAIN_EXTENSION_NAME, ~0u, true},
2388 {VK_EXT_HOST_QUERY_RESET_EXTENSION_NAME, VK_API_VERSION_1_2},
2391 static const struct
2393 const char *name;
2394 enum wined3d_vk_extension extension;
2396 map[] =
2398 {VK_EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME, WINED3D_VK_EXT_TRANSFORM_FEEDBACK},
2399 {VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE_EXTENSION_NAME, WINED3D_VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE},
2400 {VK_EXT_HOST_QUERY_RESET_EXTENSION_NAME, WINED3D_VK_EXT_HOST_QUERY_RESET},
2403 if ((vr = VK_CALL(vkEnumerateDeviceExtensionProperties(physical_device, NULL, &count, NULL))) < 0)
2405 ERR("Failed to enumerate device extensions, vr %s.\n", wined3d_debug_vkresult(vr));
2406 return false;
2409 if (!(extensions = heap_calloc(count, sizeof(*extensions))))
2411 ERR("Failed to allocate extension properties array.\n");
2412 return false;
2415 if ((vr = VK_CALL(vkEnumerateDeviceExtensionProperties(physical_device, NULL, &count, extensions))) < 0)
2417 ERR("Failed to enumerate device extensions, vr %s.\n", wined3d_debug_vkresult(vr));
2418 goto done;
2421 TRACE("Vulkan device extensions reported:\n");
2422 for (i = 0; i < count; ++i)
2424 TRACE(" - %s.\n", debugstr_a(extensions[i].extensionName));
2427 for (i = 0, enable_count = 0; i < ARRAY_SIZE(info); ++i)
2429 if (info[i].core_since_version <= vk_info->api_version)
2430 continue;
2432 for (j = 0, found = false; j < count; ++j)
2434 if (!strcmp(extensions[j].extensionName, info[i].name))
2436 found = true;
2437 break;
2441 if (!found)
2443 if (!info[i].required)
2444 continue;
2445 WARN("Required extension '%s' is not available.\n", info[i].name);
2446 goto done;
2449 TRACE("Enabling device extension '%s'.\n", info[i].name);
2450 if (!wined3d_array_reserve((void **)&enabled_extensions, &enable_size,
2451 enable_count + 1, sizeof(*enabled_extensions)))
2453 ERR("Failed to allocate enabled extensions array.\n");
2454 goto done;
2456 enabled_extensions[enable_count++] = info[i].name;
2458 success = true;
2460 for (i = 0; i < ARRAY_SIZE(map); ++i)
2462 for (j = 0; j < enable_count; ++j)
2464 if (!strcmp(enabled_extensions[j], map[i].name))
2466 vk_info->supported[map[i].extension] = TRUE;
2467 break;
2472 done:
2473 if (success)
2475 adapter_vk->device_extension_count = enable_count;
2476 adapter_vk->device_extensions = enabled_extensions;
2478 else
2480 heap_free(enabled_extensions);
2482 heap_free(extensions);
2483 return success;
2486 static BOOL wined3d_adapter_vk_init(struct wined3d_adapter_vk *adapter_vk,
2487 unsigned int ordinal, unsigned int wined3d_creation_flags)
2489 struct wined3d_vk_info *vk_info = &adapter_vk->vk_info;
2490 struct wined3d_adapter *adapter = &adapter_vk->a;
2491 VkPhysicalDeviceIDProperties id_properties;
2492 VkPhysicalDeviceProperties2 properties2;
2493 LUID primary_luid, *luid = NULL;
2495 TRACE("adapter_vk %p, ordinal %u, wined3d_creation_flags %#x.\n",
2496 adapter_vk, ordinal, wined3d_creation_flags);
2498 if (!wined3d_init_vulkan(vk_info))
2500 WARN("Failed to initialize Vulkan.\n");
2501 return FALSE;
2504 if (!(adapter_vk->physical_device = get_vulkan_physical_device(vk_info)))
2505 goto fail_vulkan;
2507 if (!wined3d_adapter_vk_init_device_extensions(adapter_vk))
2508 goto fail_vulkan;
2510 memset(&id_properties, 0, sizeof(id_properties));
2511 id_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES;
2512 properties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
2513 properties2.pNext = &id_properties;
2515 if (vk_info->vk_ops.vkGetPhysicalDeviceProperties2)
2516 VK_CALL(vkGetPhysicalDeviceProperties2(adapter_vk->physical_device, &properties2));
2517 else
2518 VK_CALL(vkGetPhysicalDeviceProperties(adapter_vk->physical_device, &properties2.properties));
2519 adapter_vk->device_limits = properties2.properties.limits;
2521 VK_CALL(vkGetPhysicalDeviceMemoryProperties(adapter_vk->physical_device, &adapter_vk->memory_properties));
2523 if (id_properties.deviceLUIDValid)
2524 luid = (LUID *)id_properties.deviceLUID;
2525 else if (ordinal == 0 && wined3d_get_primary_adapter_luid(&primary_luid))
2526 luid = &primary_luid;
2528 if (!wined3d_adapter_init(adapter, ordinal, luid, &wined3d_adapter_vk_ops))
2530 heap_free(adapter_vk->device_extensions);
2531 goto fail_vulkan;
2534 adapter->vertex_pipe = wined3d_spirv_vertex_pipe_init_vk();
2535 adapter->fragment_pipe = wined3d_spirv_fragment_pipe_init_vk();
2536 adapter->misc_state_template = misc_state_template_vk;
2537 adapter->shader_backend = wined3d_spirv_shader_backend_init_vk();
2539 wined3d_adapter_vk_init_d3d_info(adapter_vk, wined3d_creation_flags);
2541 if (!adapter_vk_init_driver_info(adapter_vk, &properties2.properties))
2542 goto fail;
2543 TRACE("Reporting (fake) driver version 0x%08x-0x%08x.\n",
2544 adapter_vk->a.driver_info.version_high, adapter_vk->a.driver_info.version_low);
2545 adapter->vram_bytes_used = 0;
2546 TRACE("Emulating 0x%s bytes of video ram.\n", wine_dbgstr_longlong(adapter->driver_info.vram_bytes));
2548 memcpy(&adapter->driver_uuid, id_properties.driverUUID, sizeof(adapter->driver_uuid));
2549 memcpy(&adapter->device_uuid, id_properties.deviceUUID, sizeof(adapter->device_uuid));
2551 if (!wined3d_adapter_vk_init_format_info(adapter_vk, vk_info))
2552 goto fail;
2554 return TRUE;
2556 fail:
2557 wined3d_adapter_cleanup(adapter);
2558 heap_free(adapter_vk->device_extensions);
2559 fail_vulkan:
2560 VK_CALL(vkDestroyInstance(vk_info->instance, NULL));
2561 wined3d_unload_vulkan(vk_info);
2562 return FALSE;
2565 struct wined3d_adapter *wined3d_adapter_vk_create(unsigned int ordinal,
2566 unsigned int wined3d_creation_flags)
2568 struct wined3d_adapter_vk *adapter_vk;
2570 if (!(adapter_vk = heap_alloc_zero(sizeof(*adapter_vk))))
2571 return NULL;
2573 if (!wined3d_adapter_vk_init(adapter_vk, ordinal, wined3d_creation_flags))
2575 heap_free(adapter_vk);
2576 return NULL;
2579 TRACE("Created adapter %p.\n", adapter_vk);
2581 return &adapter_vk->a;