wined3d: Move the WINED3D_RS_PATCHEDGESTYLE stub to wined3d_device_apply_stateblock.
[wine.git] / dlls / wined3d / adapter_vk.c
blob1b61801e68d36fb79c1927b93479a85adc09a0e9
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"
21 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
23 static const struct wined3d_state_entry_template misc_state_template_vk[] =
25 {STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_VERTEX), {STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_VERTEX), state_nop}},
26 {STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_HULL), {STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_HULL), state_nop}},
27 {STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_DOMAIN), {STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_DOMAIN), state_nop}},
28 {STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_GEOMETRY), {STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_GEOMETRY), state_nop}},
29 {STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_PIXEL), {STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_PIXEL), state_nop}},
30 {STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_COMPUTE), {STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_COMPUTE), state_nop}},
31 {STATE_GRAPHICS_SHADER_RESOURCE_BINDING, {STATE_GRAPHICS_SHADER_RESOURCE_BINDING, state_nop}},
32 {STATE_GRAPHICS_UNORDERED_ACCESS_VIEW_BINDING, {STATE_GRAPHICS_UNORDERED_ACCESS_VIEW_BINDING, state_nop}},
33 {STATE_COMPUTE_SHADER_RESOURCE_BINDING, {STATE_COMPUTE_SHADER_RESOURCE_BINDING, state_nop}},
34 {STATE_COMPUTE_UNORDERED_ACCESS_VIEW_BINDING, {STATE_COMPUTE_UNORDERED_ACCESS_VIEW_BINDING, state_nop}},
35 {STATE_STREAM_OUTPUT, {STATE_STREAM_OUTPUT, state_nop}},
36 {STATE_BLEND, {STATE_BLEND, state_nop}},
37 {STATE_BLEND_FACTOR, {STATE_BLEND_FACTOR, state_nop}},
38 {STATE_SAMPLE_MASK, {STATE_SAMPLE_MASK, state_nop}},
39 {STATE_STREAMSRC, {STATE_STREAMSRC, state_nop}},
40 {STATE_VDECL, {STATE_VDECL, state_nop}},
41 {STATE_DEPTH_STENCIL, {STATE_DEPTH_STENCIL, state_nop}},
42 {STATE_STENCIL_REF, {STATE_STENCIL_REF, state_nop}},
43 {STATE_DEPTH_BOUNDS, {STATE_DEPTH_BOUNDS, state_nop}},
44 {STATE_RASTERIZER, {STATE_RASTERIZER, state_nop}},
45 {STATE_SCISSORRECT, {STATE_SCISSORRECT, state_nop}},
46 {STATE_POINTSPRITECOORDORIGIN, {STATE_POINTSPRITECOORDORIGIN, state_nop}},
48 {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT00), {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT00), state_nop}},
49 {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT01), {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT00)}},
50 {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT10), {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT00)}},
51 {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT11), {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT00)}},
52 {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT00), {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT00), state_nop}},
53 {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT01), {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT00)}},
54 {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT10), {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT00)}},
55 {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT11), {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT00)}},
56 {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT00), {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT00), state_nop}},
57 {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT01), {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT00)}},
58 {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT10), {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT00)}},
59 {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT11), {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT00)}},
60 {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT00), {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT00), state_nop}},
61 {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT01), {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT00)}},
62 {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT10), {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT00)}},
63 {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT11), {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT00)}},
64 {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT00), {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT00), state_nop}},
65 {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT01), {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT00)}},
66 {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT10), {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT00)}},
67 {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT11), {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT00)}},
68 {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT00), {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT00), state_nop}},
69 {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT01), {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT00)}},
70 {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT10), {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT00)}},
71 {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT11), {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT00)}},
72 {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT00), {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT00), state_nop}},
73 {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT01), {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT00)}},
74 {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT10), {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT00)}},
75 {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT11), {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT00)}},
76 {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT00), {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT00), state_nop}},
77 {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT01), {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT00)}},
78 {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT10), {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT00)}},
79 {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT11), {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT00)}},
80 {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_LSCALE), {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_LSCALE), state_nop}},
81 {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_LOFFSET), {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_LSCALE)}},
82 {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_LSCALE), {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_LSCALE), state_nop}},
83 {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_LOFFSET), {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_LSCALE)}},
84 {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_LSCALE), {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_LSCALE), state_nop}},
85 {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_LOFFSET), {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_LSCALE)}},
86 {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_LSCALE), {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_LSCALE), state_nop}},
87 {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_LOFFSET), {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_LSCALE)}},
88 {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_LSCALE), {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_LSCALE), state_nop}},
89 {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_LOFFSET), {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_LSCALE)}},
90 {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_LSCALE), {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_LSCALE), state_nop}},
91 {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_LOFFSET), {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_LSCALE)}},
92 {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_LSCALE), {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_LSCALE), state_nop}},
93 {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_LOFFSET), {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_LSCALE)}},
94 {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_LSCALE), {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_LSCALE), state_nop}},
95 {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_LOFFSET), {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_LSCALE)}},
97 {STATE_VIEWPORT, {STATE_VIEWPORT, state_nop}},
98 {STATE_INDEXBUFFER, {STATE_INDEXBUFFER, state_nop}},
99 {STATE_RENDER(WINED3D_RS_LINEPATTERN), {STATE_RENDER(WINED3D_RS_LINEPATTERN), state_nop}},
100 {STATE_RENDER(WINED3D_RS_DITHERENABLE), {STATE_RENDER(WINED3D_RS_DITHERENABLE), state_nop}},
101 {STATE_RENDER(WINED3D_RS_PATCHSEGMENTS), {STATE_RENDER(WINED3D_RS_PATCHSEGMENTS), state_nop}},
102 {STATE_RENDER(WINED3D_RS_POSITIONDEGREE), {STATE_RENDER(WINED3D_RS_POSITIONDEGREE), state_nop}},
103 {STATE_RENDER(WINED3D_RS_NORMALDEGREE), {STATE_RENDER(WINED3D_RS_NORMALDEGREE), state_nop}},
104 {STATE_RENDER(WINED3D_RS_MINTESSELLATIONLEVEL), {STATE_RENDER(WINED3D_RS_ENABLEADAPTIVETESSELLATION)}},
105 {STATE_RENDER(WINED3D_RS_MAXTESSELLATIONLEVEL), {STATE_RENDER(WINED3D_RS_ENABLEADAPTIVETESSELLATION)}},
106 {STATE_RENDER(WINED3D_RS_ADAPTIVETESS_X), {STATE_RENDER(WINED3D_RS_ENABLEADAPTIVETESSELLATION)}},
107 {STATE_RENDER(WINED3D_RS_ADAPTIVETESS_Y), {STATE_RENDER(WINED3D_RS_ENABLEADAPTIVETESSELLATION)}},
108 {STATE_RENDER(WINED3D_RS_ADAPTIVETESS_Z), {STATE_RENDER(WINED3D_RS_ENABLEADAPTIVETESSELLATION)}},
109 {STATE_RENDER(WINED3D_RS_ADAPTIVETESS_W), {STATE_RENDER(WINED3D_RS_ENABLEADAPTIVETESSELLATION)}},
110 {STATE_RENDER(WINED3D_RS_ENABLEADAPTIVETESSELLATION), {STATE_RENDER(WINED3D_RS_ENABLEADAPTIVETESSELLATION), state_nop}},
111 {STATE_RENDER(WINED3D_RS_MULTISAMPLEANTIALIAS), {STATE_RENDER(WINED3D_RS_MULTISAMPLEANTIALIAS), state_nop}},
112 {STATE_RENDER(WINED3D_RS_DEBUGMONITORTOKEN), {STATE_RENDER(WINED3D_RS_DEBUGMONITORTOKEN), state_nop}},
113 /* Samplers */
114 {STATE_SAMPLER(0), {STATE_SAMPLER(0), state_nop}},
115 {STATE_SAMPLER(1), {STATE_SAMPLER(1), state_nop}},
116 {STATE_SAMPLER(2), {STATE_SAMPLER(2), state_nop}},
117 {STATE_SAMPLER(3), {STATE_SAMPLER(3), state_nop}},
118 {STATE_SAMPLER(4), {STATE_SAMPLER(4), state_nop}},
119 {STATE_SAMPLER(5), {STATE_SAMPLER(5), state_nop}},
120 {STATE_SAMPLER(6), {STATE_SAMPLER(6), state_nop}},
121 {STATE_SAMPLER(7), {STATE_SAMPLER(7), state_nop}},
122 {STATE_SAMPLER(8), {STATE_SAMPLER(8), state_nop}},
123 {STATE_SAMPLER(9), {STATE_SAMPLER(9), state_nop}},
124 {STATE_SAMPLER(10), {STATE_SAMPLER(10), state_nop}},
125 {STATE_SAMPLER(11), {STATE_SAMPLER(11), state_nop}},
126 {STATE_SAMPLER(12), {STATE_SAMPLER(12), state_nop}},
127 {STATE_SAMPLER(13), {STATE_SAMPLER(13), state_nop}},
128 {STATE_SAMPLER(14), {STATE_SAMPLER(14), state_nop}},
129 {STATE_SAMPLER(15), {STATE_SAMPLER(15), state_nop}},
130 {STATE_SAMPLER(16), /* Vertex sampler 0 */ {STATE_SAMPLER(16), state_nop}},
131 {STATE_SAMPLER(17), /* Vertex sampler 1 */ {STATE_SAMPLER(17), state_nop}},
132 {STATE_SAMPLER(18), /* Vertex sampler 2 */ {STATE_SAMPLER(18), state_nop}},
133 {STATE_SAMPLER(19), /* Vertex sampler 3 */ {STATE_SAMPLER(19), state_nop}},
134 {STATE_BASEVERTEXINDEX, {STATE_STREAMSRC}},
135 {STATE_FRAMEBUFFER, {STATE_FRAMEBUFFER, state_nop}},
136 {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), state_nop}},
137 {STATE_SHADER(WINED3D_SHADER_TYPE_HULL), {STATE_SHADER(WINED3D_SHADER_TYPE_HULL), state_nop}},
138 {STATE_SHADER(WINED3D_SHADER_TYPE_DOMAIN), {STATE_SHADER(WINED3D_SHADER_TYPE_DOMAIN), state_nop}},
139 {STATE_SHADER(WINED3D_SHADER_TYPE_GEOMETRY), {STATE_SHADER(WINED3D_SHADER_TYPE_GEOMETRY), state_nop}},
140 {STATE_SHADER(WINED3D_SHADER_TYPE_COMPUTE), {STATE_SHADER(WINED3D_SHADER_TYPE_COMPUTE), state_nop}},
141 {0}, /* Terminate */
144 static inline const struct wined3d_adapter_vk *wined3d_adapter_vk_const(const struct wined3d_adapter *adapter)
146 return CONTAINING_RECORD(adapter, struct wined3d_adapter_vk, a);
149 static const char *debug_vk_version(uint32_t version)
151 return wine_dbg_sprintf("%u.%u.%u",
152 VK_VERSION_MAJOR(version), VK_VERSION_MINOR(version), VK_VERSION_PATCH(version));
155 static HRESULT hresult_from_vk_result(VkResult vr)
157 switch (vr)
159 case VK_SUCCESS:
160 return S_OK;
161 case VK_ERROR_OUT_OF_HOST_MEMORY:
162 WARN("Out of host memory.\n");
163 return E_OUTOFMEMORY;
164 case VK_ERROR_OUT_OF_DEVICE_MEMORY:
165 WARN("Out of device memory.\n");
166 return E_OUTOFMEMORY;
167 case VK_ERROR_DEVICE_LOST:
168 WARN("Device lost.\n");
169 return E_FAIL;
170 case VK_ERROR_EXTENSION_NOT_PRESENT:
171 WARN("Extension not present.\n");
172 return E_FAIL;
173 default:
174 FIXME("Unhandled VkResult %d.\n", vr);
175 return E_FAIL;
179 static BOOL wined3d_load_vulkan(struct wined3d_vk_info *vk_info)
181 struct vulkan_ops *vk_ops = &vk_info->vk_ops;
183 if (!(vk_info->vulkan_lib = LoadLibraryA("winevulkan.dll"))
184 && !(vk_info->vulkan_lib = LoadLibraryA("vulkan-1.dll")))
186 WARN("Failed to load vulkan-1.dll.\n");
187 return FALSE;
190 vk_ops->vkGetInstanceProcAddr = (void *)GetProcAddress(vk_info->vulkan_lib, "vkGetInstanceProcAddr");
191 if (!vk_ops->vkGetInstanceProcAddr)
193 FreeLibrary(vk_info->vulkan_lib);
194 return FALSE;
197 return TRUE;
200 static void wined3d_unload_vulkan(struct wined3d_vk_info *vk_info)
202 if (vk_info->vulkan_lib)
204 FreeLibrary(vk_info->vulkan_lib);
205 vk_info->vulkan_lib = NULL;
209 static void adapter_vk_destroy(struct wined3d_adapter *adapter)
211 struct wined3d_adapter_vk *adapter_vk = wined3d_adapter_vk(adapter);
212 struct wined3d_vk_info *vk_info = &adapter_vk->vk_info;
214 VK_CALL(vkDestroyInstance(vk_info->instance, NULL));
215 wined3d_unload_vulkan(vk_info);
216 wined3d_adapter_cleanup(&adapter_vk->a);
217 heap_free(adapter_vk->device_extensions);
218 heap_free(adapter_vk);
221 static HRESULT wined3d_select_vulkan_queue_family(const struct wined3d_adapter_vk *adapter_vk,
222 uint32_t *queue_family_index, uint32_t *timestamp_bits)
224 VkPhysicalDevice physical_device = adapter_vk->physical_device;
225 const struct wined3d_vk_info *vk_info = &adapter_vk->vk_info;
226 VkQueueFamilyProperties *queue_properties;
227 uint32_t count, i;
229 VK_CALL(vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &count, NULL));
231 if (!(queue_properties = heap_calloc(count, sizeof(*queue_properties))))
232 return E_OUTOFMEMORY;
234 VK_CALL(vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &count, queue_properties));
236 for (i = 0; i < count; ++i)
238 if (queue_properties[i].queueFlags & VK_QUEUE_GRAPHICS_BIT)
240 *queue_family_index = i;
241 *timestamp_bits = queue_properties[i].timestampValidBits;
242 heap_free(queue_properties);
243 return WINED3D_OK;
246 heap_free(queue_properties);
248 WARN("Failed to find graphics queue.\n");
249 return E_FAIL;
252 struct wined3d_physical_device_info
254 VkPhysicalDeviceTransformFeedbackFeaturesEXT xfb_features;
255 VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT vertex_divisor_features;
256 VkPhysicalDeviceHostQueryResetFeatures host_query_reset_features;
258 VkPhysicalDeviceFeatures2 features2;
261 static void wined3d_disable_vulkan_features(struct wined3d_physical_device_info *info)
263 VkPhysicalDeviceFeatures *features = &info->features2.features;
265 features->depthBounds = VK_FALSE;
266 features->wideLines = VK_FALSE;
267 features->alphaToOne = VK_FALSE;
268 features->textureCompressionETC2 = VK_FALSE;
269 features->textureCompressionASTC_LDR = VK_FALSE;
270 features->shaderStorageImageMultisample = VK_FALSE;
271 features->shaderUniformBufferArrayDynamicIndexing = VK_FALSE;
272 features->shaderSampledImageArrayDynamicIndexing = VK_FALSE;
273 features->shaderStorageBufferArrayDynamicIndexing = VK_FALSE;
274 features->shaderStorageImageArrayDynamicIndexing = VK_FALSE;
275 features->shaderInt64 = VK_FALSE;
276 features->shaderInt16 = VK_FALSE;
277 features->shaderResourceResidency = VK_FALSE;
278 features->shaderResourceMinLod = VK_FALSE;
279 features->sparseBinding = VK_FALSE;
280 features->sparseResidencyBuffer = VK_FALSE;
281 features->sparseResidencyImage2D = VK_FALSE;
282 features->sparseResidencyImage3D = VK_FALSE;
283 features->sparseResidency2Samples = VK_FALSE;
284 features->sparseResidency4Samples = VK_FALSE;
285 features->sparseResidency8Samples = VK_FALSE;
286 features->sparseResidency16Samples = VK_FALSE;
287 features->sparseResidencyAliased = VK_FALSE;
288 features->inheritedQueries = VK_FALSE;
291 static struct wined3d_allocator_chunk *wined3d_allocator_vk_create_chunk(struct wined3d_allocator *allocator,
292 struct wined3d_context *context, unsigned int memory_type, size_t chunk_size)
294 struct wined3d_context_vk *context_vk = wined3d_context_vk(context);
295 struct wined3d_allocator_chunk_vk *chunk_vk;
297 if (!(chunk_vk = heap_alloc(sizeof(*chunk_vk))))
298 return NULL;
300 if (!wined3d_allocator_chunk_init(&chunk_vk->c, allocator))
302 heap_free(chunk_vk);
303 return NULL;
306 if (!(chunk_vk->vk_memory = wined3d_context_vk_allocate_vram_chunk_memory(context_vk, memory_type, chunk_size)))
308 wined3d_allocator_chunk_cleanup(&chunk_vk->c);
309 heap_free(chunk_vk);
310 return NULL;
312 list_add_head(&allocator->pools[memory_type].chunks, &chunk_vk->c.entry);
314 return &chunk_vk->c;
317 static void wined3d_allocator_vk_destroy_chunk(struct wined3d_allocator_chunk *chunk)
319 struct wined3d_allocator_chunk_vk *chunk_vk = wined3d_allocator_chunk_vk(chunk);
320 const struct wined3d_vk_info *vk_info;
321 struct wined3d_device_vk *device_vk;
323 TRACE("chunk %p.\n", chunk);
325 device_vk = wined3d_device_vk_from_allocator(chunk_vk->c.allocator);
326 vk_info = &device_vk->vk_info;
328 if (chunk_vk->c.map_ptr)
330 VK_CALL(vkUnmapMemory(device_vk->vk_device, chunk_vk->vk_memory));
331 adapter_adjust_mapped_memory(device_vk->d.adapter, -WINED3D_ALLOCATOR_CHUNK_SIZE);
333 VK_CALL(vkFreeMemory(device_vk->vk_device, chunk_vk->vk_memory, NULL));
334 TRACE("Freed memory 0x%s.\n", wine_dbgstr_longlong(chunk_vk->vk_memory));
335 wined3d_allocator_chunk_cleanup(&chunk_vk->c);
336 heap_free(chunk_vk);
339 static const struct wined3d_allocator_ops wined3d_allocator_vk_ops =
341 .allocator_create_chunk = wined3d_allocator_vk_create_chunk,
342 .allocator_destroy_chunk = wined3d_allocator_vk_destroy_chunk,
345 static void get_physical_device_info(const struct wined3d_adapter_vk *adapter_vk, struct wined3d_physical_device_info *info)
347 VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT *vertex_divisor_features = &info->vertex_divisor_features;
348 VkPhysicalDeviceHostQueryResetFeatures *host_query_reset_features = &info->host_query_reset_features;
349 VkPhysicalDeviceTransformFeedbackFeaturesEXT *xfb_features = &info->xfb_features;
350 VkPhysicalDevice physical_device = adapter_vk->physical_device;
351 const struct wined3d_vk_info *vk_info = &adapter_vk->vk_info;
352 VkPhysicalDeviceFeatures2 *features2 = &info->features2;
354 memset(info, 0, sizeof(*info));
356 xfb_features->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_FEATURES_EXT;
358 vertex_divisor_features->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT;
359 vertex_divisor_features->pNext = xfb_features;
361 host_query_reset_features->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES;
362 host_query_reset_features->pNext = vertex_divisor_features;
364 features2->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
365 features2->pNext = host_query_reset_features;
367 if (vk_info->vk_ops.vkGetPhysicalDeviceFeatures2)
368 VK_CALL(vkGetPhysicalDeviceFeatures2(physical_device, features2));
369 else
370 VK_CALL(vkGetPhysicalDeviceFeatures(physical_device, &features2->features));
373 static HRESULT adapter_vk_create_device(struct wined3d *wined3d, const struct wined3d_adapter *adapter,
374 enum wined3d_device_type device_type, HWND focus_window, unsigned int flags, BYTE surface_alignment,
375 const enum wined3d_feature_level *levels, unsigned int level_count,
376 struct wined3d_device_parent *device_parent, struct wined3d_device **device)
378 const struct wined3d_adapter_vk *adapter_vk = wined3d_adapter_vk_const(adapter);
379 const struct wined3d_vk_info *vk_info = &adapter_vk->vk_info;
380 struct wined3d_physical_device_info physical_device_info;
381 static const float priorities[] = {1.0f};
382 struct wined3d_device_vk *device_vk;
383 VkDevice vk_device = VK_NULL_HANDLE;
384 VkDeviceQueueCreateInfo queue_info;
385 VkPhysicalDevice physical_device;
386 VkDeviceCreateInfo device_info;
387 uint32_t queue_family_index;
388 uint32_t timestamp_bits;
389 VkResult vr;
390 HRESULT hr;
392 if (!(device_vk = heap_alloc_zero(sizeof(*device_vk))))
393 return E_OUTOFMEMORY;
395 if (FAILED(hr = wined3d_select_vulkan_queue_family(adapter_vk, &queue_family_index, &timestamp_bits)))
396 goto fail;
398 physical_device = adapter_vk->physical_device;
400 get_physical_device_info(adapter_vk, &physical_device_info);
401 wined3d_disable_vulkan_features(&physical_device_info);
403 queue_info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
404 queue_info.pNext = NULL;
405 queue_info.flags = 0;
406 queue_info.queueFamilyIndex = queue_family_index;
407 queue_info.queueCount = ARRAY_SIZE(priorities);
408 queue_info.pQueuePriorities = priorities;
410 device_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
411 device_info.pNext = physical_device_info.features2.pNext;
412 device_info.flags = 0;
413 device_info.queueCreateInfoCount = 1;
414 device_info.pQueueCreateInfos = &queue_info;
415 device_info.enabledLayerCount = 0;
416 device_info.ppEnabledLayerNames = NULL;
417 device_info.enabledExtensionCount = adapter_vk->device_extension_count;
418 device_info.ppEnabledExtensionNames = adapter_vk->device_extensions;
419 device_info.pEnabledFeatures = &physical_device_info.features2.features;
421 if ((vr = VK_CALL(vkCreateDevice(physical_device, &device_info, NULL, &vk_device))) < 0)
423 WARN("Failed to create Vulkan device, vr %s.\n", wined3d_debug_vkresult(vr));
424 vk_device = VK_NULL_HANDLE;
425 hr = hresult_from_vk_result(vr);
426 goto fail;
429 device_vk->vk_device = vk_device;
430 VK_CALL(vkGetDeviceQueue(vk_device, queue_family_index, 0, &device_vk->vk_queue));
431 device_vk->vk_queue_family_index = queue_family_index;
432 device_vk->timestamp_bits = timestamp_bits;
434 device_vk->vk_info = *vk_info;
435 #define VK_DEVICE_PFN(name) \
436 if (!(device_vk->vk_info.vk_ops.name = (void *)VK_CALL(vkGetDeviceProcAddr(vk_device, #name)))) \
438 WARN("Could not get device proc addr for '" #name "'.\n"); \
439 hr = E_FAIL; \
440 goto fail; \
442 #define VK_DEVICE_EXT_PFN(name) \
443 device_vk->vk_info.vk_ops.name = (void *)VK_CALL(vkGetDeviceProcAddr(vk_device, #name));
444 VK_DEVICE_FUNCS()
445 #undef VK_DEVICE_EXT_PFN
446 #undef VK_DEVICE_PFN
448 if (!wined3d_allocator_init(&device_vk->allocator,
449 adapter_vk->memory_properties.memoryTypeCount, &wined3d_allocator_vk_ops))
451 WARN("Failed to initialise allocator.\n");
452 hr = E_FAIL;
453 goto fail;
456 if (FAILED(hr = wined3d_device_init(&device_vk->d, wined3d, adapter->ordinal, device_type, focus_window,
457 flags, surface_alignment, levels, level_count, vk_info->supported, device_parent)))
459 WARN("Failed to initialize device, hr %#lx.\n", hr);
460 wined3d_allocator_cleanup(&device_vk->allocator);
461 goto fail;
464 wined3d_lock_init(&device_vk->allocator_cs, "wined3d_device_vk.allocator_cs");
466 *device = &device_vk->d;
468 return WINED3D_OK;
470 fail:
471 VK_CALL(vkDestroyDevice(vk_device, NULL));
472 heap_free(device_vk);
473 return hr;
476 static void adapter_vk_destroy_device(struct wined3d_device *device)
478 struct wined3d_device_vk *device_vk = wined3d_device_vk(device);
479 const struct wined3d_vk_info *vk_info = &device_vk->vk_info;
481 wined3d_device_cleanup(&device_vk->d);
482 wined3d_allocator_cleanup(&device_vk->allocator);
484 wined3d_lock_cleanup(&device_vk->allocator_cs);
486 VK_CALL(vkDestroyDevice(device_vk->vk_device, NULL));
487 heap_free(device_vk);
490 static struct wined3d_context *adapter_vk_acquire_context(struct wined3d_device *device,
491 struct wined3d_texture *texture, unsigned int sub_resource_idx)
493 TRACE("device %p, texture %p, sub_resource_idx %u.\n", device, texture, sub_resource_idx);
495 wined3d_from_cs(device->cs);
497 if (!device->context_count)
498 return NULL;
500 return &wined3d_device_vk(device)->context_vk.c;
503 static void adapter_vk_release_context(struct wined3d_context *context)
505 TRACE("context %p.\n", context);
508 static void adapter_vk_get_wined3d_caps(const struct wined3d_adapter *adapter, struct wined3d_caps *caps)
510 const struct wined3d_adapter_vk *adapter_vk = wined3d_adapter_vk_const(adapter);
511 const VkPhysicalDeviceLimits *limits = &adapter_vk->device_limits;
512 bool sampler_anisotropy = limits->maxSamplerAnisotropy > 1.0f;
513 const struct wined3d_vk_info *vk_info = &adapter_vk->vk_info;
515 caps->ddraw_caps.dds_caps |= WINEDDSCAPS_BACKBUFFER
516 | WINEDDSCAPS_COMPLEX
517 | WINEDDSCAPS_FRONTBUFFER
518 | WINEDDSCAPS_3DDEVICE
519 | WINEDDSCAPS_VIDEOMEMORY
520 | WINEDDSCAPS_OWNDC
521 | WINEDDSCAPS_LOCALVIDMEM
522 | WINEDDSCAPS_NONLOCALVIDMEM;
523 caps->ddraw_caps.caps |= WINEDDCAPS_3D;
525 caps->Caps2 |= WINED3DCAPS2_CANGENMIPMAP;
527 caps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_BLENDOP
528 | WINED3DPMISCCAPS_INDEPENDENTWRITEMASKS
529 | WINED3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS
530 | WINED3DPMISCCAPS_POSTBLENDSRGBCONVERT
531 | WINED3DPMISCCAPS_SEPARATEALPHABLEND;
533 caps->RasterCaps |= WINED3DPRASTERCAPS_MIPMAPLODBIAS;
535 if (sampler_anisotropy)
537 caps->RasterCaps |= WINED3DPRASTERCAPS_ANISOTROPY;
539 caps->TextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC
540 | WINED3DPTFILTERCAPS_MINFANISOTROPIC;
542 caps->MaxAnisotropy = limits->maxSamplerAnisotropy;
545 caps->SrcBlendCaps |= WINED3DPBLENDCAPS_BLENDFACTOR;
546 caps->DestBlendCaps |= WINED3DPBLENDCAPS_BLENDFACTOR
547 | WINED3DPBLENDCAPS_SRCALPHASAT;
549 caps->TextureCaps |= WINED3DPTEXTURECAPS_VOLUMEMAP
550 | WINED3DPTEXTURECAPS_MIPVOLUMEMAP
551 | WINED3DPTEXTURECAPS_VOLUMEMAP_POW2;
552 caps->VolumeTextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFLINEAR
553 | WINED3DPTFILTERCAPS_MAGFPOINT
554 | WINED3DPTFILTERCAPS_MINFLINEAR
555 | WINED3DPTFILTERCAPS_MINFPOINT
556 | WINED3DPTFILTERCAPS_MIPFLINEAR
557 | WINED3DPTFILTERCAPS_MIPFPOINT
558 | WINED3DPTFILTERCAPS_LINEAR
559 | WINED3DPTFILTERCAPS_LINEARMIPLINEAR
560 | WINED3DPTFILTERCAPS_LINEARMIPNEAREST
561 | WINED3DPTFILTERCAPS_MIPLINEAR
562 | WINED3DPTFILTERCAPS_MIPNEAREST
563 | WINED3DPTFILTERCAPS_NEAREST;
564 caps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_INDEPENDENTUV
565 | WINED3DPTADDRESSCAPS_CLAMP
566 | WINED3DPTADDRESSCAPS_WRAP;
567 caps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER
568 | WINED3DPTADDRESSCAPS_MIRROR;
569 if (vk_info->supported[WINED3D_VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE])
570 caps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
572 caps->MaxVolumeExtent = limits->maxImageDimension3D;
574 caps->TextureCaps |= WINED3DPTEXTURECAPS_CUBEMAP
575 | WINED3DPTEXTURECAPS_MIPCUBEMAP
576 | WINED3DPTEXTURECAPS_CUBEMAP_POW2;
577 caps->CubeTextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFLINEAR
578 | WINED3DPTFILTERCAPS_MAGFPOINT
579 | WINED3DPTFILTERCAPS_MINFLINEAR
580 | WINED3DPTFILTERCAPS_MINFPOINT
581 | WINED3DPTFILTERCAPS_MIPFLINEAR
582 | WINED3DPTFILTERCAPS_MIPFPOINT
583 | WINED3DPTFILTERCAPS_LINEAR
584 | WINED3DPTFILTERCAPS_LINEARMIPLINEAR
585 | WINED3DPTFILTERCAPS_LINEARMIPNEAREST
586 | WINED3DPTFILTERCAPS_MIPLINEAR
587 | WINED3DPTFILTERCAPS_MIPNEAREST
588 | WINED3DPTFILTERCAPS_NEAREST;
590 if (sampler_anisotropy)
592 caps->CubeTextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC
593 | WINED3DPTFILTERCAPS_MINFANISOTROPIC;
596 caps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER
597 | WINED3DPTADDRESSCAPS_MIRROR;
598 if (vk_info->supported[WINED3D_VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE])
599 caps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
601 caps->StencilCaps |= WINED3DSTENCILCAPS_DECR
602 | WINED3DSTENCILCAPS_INCR
603 | WINED3DSTENCILCAPS_TWOSIDED;
605 caps->DeclTypes |= WINED3DDTCAPS_FLOAT16_2 | WINED3DDTCAPS_FLOAT16_4;
607 caps->MaxPixelShader30InstructionSlots = WINED3DMAX30SHADERINSTRUCTIONS;
608 caps->MaxVertexShader30InstructionSlots = WINED3DMAX30SHADERINSTRUCTIONS;
609 caps->PS20Caps.temp_count = WINED3DPS20_MAX_NUMTEMPS;
610 caps->VS20Caps.temp_count = WINED3DVS20_MAX_NUMTEMPS;
613 static BOOL adapter_vk_check_format(const struct wined3d_adapter *adapter,
614 const struct wined3d_format *adapter_format, const struct wined3d_format *rt_format,
615 const struct wined3d_format *ds_format)
617 return TRUE;
620 static HRESULT adapter_vk_init_3d(struct wined3d_device *device)
622 struct wined3d_context_vk *context_vk;
623 struct wined3d_device_vk *device_vk;
624 HRESULT hr;
626 TRACE("device %p.\n", device);
628 device_vk = wined3d_device_vk(device);
629 context_vk = &device_vk->context_vk;
630 if (FAILED(hr = wined3d_context_vk_init(context_vk, device->swapchains[0])))
632 WARN("Failed to initialise context.\n");
633 return hr;
636 if (FAILED(hr = device->shader_backend->shader_alloc_private(device,
637 device->adapter->vertex_pipe, device->adapter->fragment_pipe)))
639 ERR("Failed to allocate shader private data, hr %#lx.\n", hr);
640 wined3d_context_vk_cleanup(context_vk);
641 return hr;
644 if (!device_context_add(device, &context_vk->c))
646 ERR("Failed to add the newly created context to the context list.\n");
647 device->shader_backend->shader_free_private(device, NULL);
648 wined3d_context_vk_cleanup(context_vk);
649 return E_FAIL;
652 TRACE("Initialised context %p.\n", context_vk);
654 if (!(device_vk->d.blitter = wined3d_cpu_blitter_create()))
656 ERR("Failed to create CPU blitter.\n");
657 device_context_remove(device, &context_vk->c);
658 device->shader_backend->shader_free_private(device, NULL);
659 wined3d_context_vk_cleanup(context_vk);
660 return E_FAIL;
662 wined3d_vk_blitter_create(&device_vk->d.blitter);
664 wined3d_device_create_default_samplers(device, &context_vk->c);
665 wined3d_device_vk_create_null_resources(device_vk, context_vk);
666 wined3d_device_vk_create_null_views(device_vk, context_vk);
667 if (device->adapter->d3d_info.feature_level >= WINED3D_FEATURE_LEVEL_11)
668 wined3d_device_vk_uav_clear_state_init(device_vk);
670 return WINED3D_OK;
673 static void adapter_vk_uninit_3d_cs(void *object)
675 struct wined3d_device_vk *device_vk = object;
676 struct wined3d_context_vk *context_vk;
677 struct wined3d_device *device;
678 struct wined3d_shader *shader;
680 TRACE("device_vk %p.\n", device_vk);
682 context_vk = &device_vk->context_vk;
683 device = &device_vk->d;
685 LIST_FOR_EACH_ENTRY(shader, &device->shaders, struct wined3d_shader, shader_list_entry)
687 device->shader_backend->shader_destroy(shader);
690 if (device->adapter->d3d_info.feature_level >= WINED3D_FEATURE_LEVEL_11)
691 wined3d_device_vk_uav_clear_state_cleanup(device_vk);
692 device->blitter->ops->blitter_destroy(device->blitter, NULL);
693 device->shader_backend->shader_free_private(device, &context_vk->c);
694 wined3d_device_vk_destroy_null_views(device_vk, context_vk);
695 wined3d_device_vk_destroy_null_resources(device_vk, context_vk);
698 static void adapter_vk_uninit_3d(struct wined3d_device *device)
700 struct wined3d_context_vk *context_vk;
701 struct wined3d_device_vk *device_vk;
703 TRACE("device %p.\n", device);
705 device_vk = wined3d_device_vk(device);
706 context_vk = &device_vk->context_vk;
708 wined3d_device_destroy_default_samplers(device);
709 wined3d_cs_destroy_object(device->cs, adapter_vk_uninit_3d_cs, device_vk);
710 wined3d_cs_finish(device->cs, WINED3D_CS_QUEUE_DEFAULT);
712 device_context_remove(device, &context_vk->c);
713 wined3d_context_vk_cleanup(context_vk);
716 static void *wined3d_bo_vk_map(struct wined3d_bo_vk *bo, struct wined3d_context_vk *context_vk)
718 const struct wined3d_vk_info *vk_info;
719 struct wined3d_device_vk *device_vk;
720 struct wined3d_bo_slab_vk *slab;
721 VkResult vr;
723 if (bo->b.map_ptr)
724 return bo->b.map_ptr;
726 vk_info = context_vk->vk_info;
727 device_vk = wined3d_device_vk(context_vk->c.device);
729 if ((slab = bo->slab))
731 if (!(bo->b.map_ptr = wined3d_bo_slab_vk_map(slab, context_vk)))
733 ERR("Failed to map slab.\n");
734 return NULL;
737 else if (bo->memory)
739 struct wined3d_allocator_chunk_vk *chunk_vk = wined3d_allocator_chunk_vk(bo->memory->chunk);
741 if (!(bo->b.map_ptr = wined3d_allocator_chunk_vk_map(chunk_vk, context_vk)))
743 ERR("Failed to map chunk.\n");
744 return NULL;
747 else
749 if ((vr = VK_CALL(vkMapMemory(device_vk->vk_device, bo->vk_memory, 0, VK_WHOLE_SIZE, 0, &bo->b.map_ptr))) < 0)
751 ERR("Failed to map memory, vr %s.\n", wined3d_debug_vkresult(vr));
752 return NULL;
755 adapter_adjust_mapped_memory(device_vk->d.adapter, bo->size);
758 return bo->b.map_ptr;
761 static void wined3d_bo_vk_unmap(struct wined3d_bo_vk *bo, struct wined3d_context_vk *context_vk)
763 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
764 const struct wined3d_vk_info *vk_info;
765 struct wined3d_bo_slab_vk *slab;
767 /* This may race with the client thread, but it's not a hard limit anyway. */
768 if (device_vk->d.adapter->mapped_size <= MAX_PERSISTENT_MAPPED_BYTES)
770 TRACE("Not unmapping BO %p.\n", bo);
771 return;
774 wined3d_device_bo_map_lock(context_vk->c.device);
775 /* The mapping is still in use by the client (viz. for an accelerated
776 * NOOVERWRITE map). The client will trigger another unmap request when the
777 * d3d application requests to unmap the BO. */
778 if (bo->b.client_map_count)
780 wined3d_device_bo_map_unlock(context_vk->c.device);
781 TRACE("BO %p is still in use by a client thread; not unmapping.\n", bo);
782 return;
784 bo->b.map_ptr = NULL;
785 wined3d_device_bo_map_unlock(context_vk->c.device);
787 if ((slab = bo->slab))
789 wined3d_bo_slab_vk_unmap(slab, context_vk);
790 return;
793 if (bo->memory)
795 wined3d_allocator_chunk_vk_unmap(wined3d_allocator_chunk_vk(bo->memory->chunk), context_vk);
796 return;
799 vk_info = context_vk->vk_info;
800 VK_CALL(vkUnmapMemory(device_vk->vk_device, bo->vk_memory));
801 adapter_adjust_mapped_memory(device_vk->d.adapter, -bo->size);
804 static void wined3d_bo_slab_vk_lock(struct wined3d_bo_slab_vk *slab_vk, struct wined3d_context_vk *context_vk)
806 wined3d_device_vk_allocator_lock(wined3d_device_vk(context_vk->c.device));
809 static void wined3d_bo_slab_vk_unlock(struct wined3d_bo_slab_vk *slab_vk, struct wined3d_context_vk *context_vk)
811 wined3d_device_vk_allocator_unlock(wined3d_device_vk(context_vk->c.device));
814 void *wined3d_bo_slab_vk_map(struct wined3d_bo_slab_vk *slab_vk, struct wined3d_context_vk *context_vk)
816 void *map_ptr;
818 TRACE("slab_vk %p, context_vk %p.\n", slab_vk, context_vk);
820 wined3d_bo_slab_vk_lock(slab_vk, context_vk);
822 if (!slab_vk->map_ptr && !(slab_vk->map_ptr = wined3d_bo_vk_map(&slab_vk->bo, context_vk)))
824 wined3d_bo_slab_vk_unlock(slab_vk, context_vk);
825 ERR("Failed to map slab.\n");
826 return NULL;
829 ++slab_vk->map_count;
830 map_ptr = slab_vk->map_ptr;
832 wined3d_bo_slab_vk_unlock(slab_vk, context_vk);
834 return map_ptr;
837 void wined3d_bo_slab_vk_unmap(struct wined3d_bo_slab_vk *slab_vk, struct wined3d_context_vk *context_vk)
839 wined3d_bo_slab_vk_lock(slab_vk, context_vk);
841 if (--slab_vk->map_count)
843 wined3d_bo_slab_vk_unlock(slab_vk, context_vk);
844 return;
847 wined3d_bo_vk_unmap(&slab_vk->bo, context_vk);
848 slab_vk->map_ptr = NULL;
850 wined3d_bo_slab_vk_unlock(slab_vk, context_vk);
853 VkAccessFlags vk_access_mask_from_buffer_usage(VkBufferUsageFlags usage)
855 VkAccessFlags flags = 0;
857 if (usage & VK_BUFFER_USAGE_VERTEX_BUFFER_BIT)
858 flags |= VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT;
859 if (usage & VK_BUFFER_USAGE_INDEX_BUFFER_BIT)
860 flags |= VK_ACCESS_INDEX_READ_BIT;
861 if (usage & VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT)
862 flags |= VK_ACCESS_UNIFORM_READ_BIT;
863 if (usage & VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT)
864 flags |= VK_ACCESS_SHADER_READ_BIT;
865 if (usage & VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT)
866 flags |= VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
867 if (usage & VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT)
868 flags |= VK_ACCESS_INDIRECT_COMMAND_READ_BIT;
869 if (usage & VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT)
870 flags |= VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT;
871 if (usage & VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT)
872 flags |= VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT
873 | VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT;
874 if (usage & VK_BUFFER_USAGE_TRANSFER_SRC_BIT)
875 flags |= VK_ACCESS_TRANSFER_READ_BIT;
876 if (usage & VK_BUFFER_USAGE_TRANSFER_DST_BIT)
877 flags |= VK_ACCESS_TRANSFER_WRITE_BIT;
879 return flags;
882 VkPipelineStageFlags vk_pipeline_stage_mask_from_buffer_usage(VkBufferUsageFlags usage)
884 VkPipelineStageFlags flags = 0;
886 if (usage & (VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT))
887 flags |= VK_PIPELINE_STAGE_VERTEX_INPUT_BIT;
888 if (usage & (VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT
889 | VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT))
890 flags |= VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT
891 | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT
892 | VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT
893 | VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT;
894 if (usage & VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT)
895 flags |= VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT;
896 if (usage & (VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT
897 | VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT))
898 flags |= VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT;
899 if (usage & (VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT))
900 flags |= VK_PIPELINE_STAGE_TRANSFER_BIT;
902 return flags;
905 static void *adapter_vk_map_bo_address(struct wined3d_context *context,
906 const struct wined3d_bo_address *data, size_t size, uint32_t map_flags)
908 struct wined3d_context_vk *context_vk = wined3d_context_vk(context);
909 const struct wined3d_vk_info *vk_info;
910 struct wined3d_device_vk *device_vk;
911 VkCommandBuffer vk_command_buffer;
912 VkBufferMemoryBarrier vk_barrier;
913 struct wined3d_bo_user *bo_user;
914 struct wined3d_bo_vk *bo, tmp;
915 VkMappedMemoryRange range;
916 void *map_ptr;
918 if (!data->buffer_object)
919 return data->addr;
920 bo = wined3d_bo_vk(data->buffer_object);
922 vk_info = context_vk->vk_info;
923 device_vk = wined3d_device_vk(context->device);
925 if (map_flags & WINED3D_MAP_NOOVERWRITE)
926 goto map;
928 if ((map_flags & WINED3D_MAP_DISCARD) && bo->command_buffer_id > context_vk->completed_command_buffer_id)
930 if (wined3d_context_vk_create_bo(context_vk, bo->size, bo->usage, bo->memory_type, &tmp))
932 bool host_synced = bo->host_synced;
933 list_move_head(&tmp.b.users, &bo->b.users);
934 wined3d_context_vk_destroy_bo(context_vk, bo);
935 *bo = tmp;
936 bo->host_synced = host_synced;
937 list_init(&bo->b.users);
938 list_move_head(&bo->b.users, &tmp.b.users);
939 LIST_FOR_EACH_ENTRY(bo_user, &bo->b.users, struct wined3d_bo_user, entry)
941 bo_user->valid = false;
944 goto map;
947 ERR("Failed to create new buffer object.\n");
950 if (map_flags & WINED3D_MAP_READ)
952 if (!bo->host_synced)
954 if (!(vk_command_buffer = wined3d_context_vk_get_command_buffer(context_vk)))
956 ERR("Failed to get command buffer.\n");
957 return NULL;
960 wined3d_context_vk_end_current_render_pass(context_vk);
962 vk_barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
963 vk_barrier.pNext = NULL;
964 vk_barrier.srcAccessMask = vk_access_mask_from_buffer_usage(bo->usage);
965 vk_barrier.dstAccessMask = VK_ACCESS_HOST_READ_BIT;
966 vk_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
967 vk_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
968 vk_barrier.buffer = bo->vk_buffer;
969 vk_barrier.offset = bo->b.buffer_offset + (uintptr_t)data->addr;
970 vk_barrier.size = size;
971 VK_CALL(vkCmdPipelineBarrier(vk_command_buffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
972 VK_PIPELINE_STAGE_HOST_BIT, 0, 0, NULL, 1, &vk_barrier, 0, NULL));
974 wined3d_context_vk_reference_bo(context_vk, bo);
977 if (!bo->b.coherent)
979 range.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE;
980 range.pNext = NULL;
981 range.memory = bo->vk_memory;
982 range.offset = bo->b.memory_offset + (uintptr_t)data->addr;
983 range.size = size;
984 VK_CALL(vkInvalidateMappedMemoryRanges(device_vk->vk_device, 1, &range));
988 if (bo->command_buffer_id == context_vk->current_command_buffer.id)
989 wined3d_context_vk_submit_command_buffer(context_vk, 0, NULL, NULL, 0, NULL);
990 wined3d_context_vk_wait_command_buffer(context_vk, bo->command_buffer_id);
992 map:
993 if (!(map_ptr = wined3d_bo_vk_map(bo, context_vk)))
995 ERR("Failed to map bo.\n");
996 return NULL;
999 return (uint8_t *)map_ptr + bo->b.memory_offset + (uintptr_t)data->addr;
1002 static void flush_bo_range(struct wined3d_context_vk *context_vk,
1003 struct wined3d_bo_vk *bo, unsigned int offset, unsigned int size)
1005 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
1006 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
1007 VkMappedMemoryRange range;
1009 range.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE;
1010 range.pNext = NULL;
1011 range.memory = bo->vk_memory;
1012 range.offset = bo->b.memory_offset + offset;
1013 range.size = size;
1014 VK_CALL(vkFlushMappedMemoryRanges(device_vk->vk_device, 1, &range));
1017 static void adapter_vk_unmap_bo_address(struct wined3d_context *context,
1018 const struct wined3d_bo_address *data, unsigned int range_count, const struct wined3d_range *ranges)
1020 struct wined3d_context_vk *context_vk = wined3d_context_vk(context);
1021 struct wined3d_bo_vk *bo;
1022 unsigned int i;
1024 if (!data->buffer_object)
1025 return;
1026 bo = wined3d_bo_vk(data->buffer_object);
1028 assert(bo->b.map_ptr);
1030 if (!bo->b.coherent)
1032 for (i = 0; i < range_count; ++i)
1033 flush_bo_range(context_vk, bo, ranges[i].offset, ranges[i].size);
1036 wined3d_bo_vk_unmap(bo, context_vk);
1039 void adapter_vk_copy_bo_address(struct wined3d_context *context,
1040 const struct wined3d_bo_address *dst, const struct wined3d_bo_address *src,
1041 unsigned int range_count, const struct wined3d_range *ranges)
1043 struct wined3d_context_vk *context_vk = wined3d_context_vk(context);
1044 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
1045 struct wined3d_bo_vk staging_bo, *src_bo, *dst_bo;
1046 VkAccessFlags src_access_mask, dst_access_mask;
1047 VkBufferMemoryBarrier vk_barrier[2];
1048 DWORD map_flags = WINED3D_MAP_WRITE;
1049 const struct wined3d_range *range;
1050 struct wined3d_bo_address staging;
1051 VkCommandBuffer vk_command_buffer;
1052 uint8_t *dst_ptr, *src_ptr;
1053 VkBufferCopy region;
1054 size_t size = 0;
1055 unsigned int i;
1057 src_bo = src->buffer_object ? wined3d_bo_vk(src->buffer_object) : NULL;
1058 dst_bo = dst->buffer_object ? wined3d_bo_vk(dst->buffer_object) : NULL;
1060 if (dst_bo && !dst->addr && !ranges->offset && ranges->size == dst_bo->size)
1061 map_flags |= WINED3D_MAP_DISCARD;
1063 if (src_bo && dst_bo)
1065 if (!(vk_command_buffer = wined3d_context_vk_get_command_buffer(context_vk)))
1067 ERR("Failed to get command buffer.\n");
1068 return;
1071 wined3d_context_vk_end_current_render_pass(context_vk);
1073 src_access_mask = vk_access_mask_from_buffer_usage(src_bo->usage);
1074 dst_access_mask = vk_access_mask_from_buffer_usage(dst_bo->usage);
1076 vk_barrier[0].sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
1077 vk_barrier[0].pNext = NULL;
1078 vk_barrier[0].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
1079 vk_barrier[0].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
1080 vk_barrier[0].buffer = src_bo->vk_buffer;
1082 vk_barrier[1].sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
1083 vk_barrier[1].pNext = NULL;
1084 vk_barrier[1].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
1085 vk_barrier[1].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
1086 vk_barrier[1].buffer = dst_bo->vk_buffer;
1088 for (i = 0; i < range_count; ++i)
1090 range = &ranges[i];
1092 region.srcOffset = src_bo->b.buffer_offset + (uintptr_t)src->addr + range->offset;
1093 region.dstOffset = dst_bo->b.buffer_offset + (uintptr_t)dst->addr + range->offset;
1094 region.size = range->size;
1096 vk_barrier[0].offset = region.srcOffset;
1097 vk_barrier[0].size = region.size;
1099 vk_barrier[1].offset = region.dstOffset;
1100 vk_barrier[1].size = region.size;
1102 vk_barrier[0].srcAccessMask = src_access_mask;
1103 vk_barrier[0].dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
1105 vk_barrier[1].srcAccessMask = dst_access_mask;
1106 vk_barrier[1].dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
1108 VK_CALL(vkCmdPipelineBarrier(vk_command_buffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
1109 VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, NULL, 2, vk_barrier, 0, NULL));
1111 VK_CALL(vkCmdCopyBuffer(vk_command_buffer, src_bo->vk_buffer, dst_bo->vk_buffer, 1, &region));
1113 vk_barrier[0].srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
1114 vk_barrier[0].dstAccessMask = src_access_mask;
1116 vk_barrier[1].srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
1117 vk_barrier[1].dstAccessMask = dst_access_mask;
1119 VK_CALL(vkCmdPipelineBarrier(vk_command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT,
1120 VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, NULL, 2, vk_barrier, 0, NULL));
1123 wined3d_context_vk_reference_bo(context_vk, src_bo);
1124 wined3d_context_vk_reference_bo(context_vk, dst_bo);
1126 return;
1129 for (i = 0; i < range_count; ++i)
1130 size = max(size, ranges[i].offset + ranges[i].size);
1132 if (src_bo && !(src_bo->memory_type & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT))
1134 if (!(wined3d_context_vk_create_bo(context_vk, size, VK_BUFFER_USAGE_TRANSFER_DST_BIT,
1135 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, &staging_bo)))
1137 ERR("Failed to create staging bo.\n");
1138 return;
1141 staging.buffer_object = &staging_bo.b;
1142 staging.addr = NULL;
1143 adapter_vk_copy_bo_address(context, &staging, src, range_count, ranges);
1144 adapter_vk_copy_bo_address(context, dst, &staging, range_count, ranges);
1146 wined3d_context_vk_destroy_bo(context_vk, &staging_bo);
1148 return;
1151 if (dst_bo && (!(dst_bo->memory_type & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) || (!(map_flags & WINED3D_MAP_DISCARD)
1152 && dst_bo->command_buffer_id > context_vk->completed_command_buffer_id)))
1154 if (!(wined3d_context_vk_create_bo(context_vk, size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
1155 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, &staging_bo)))
1157 ERR("Failed to create staging bo.\n");
1158 return;
1161 staging.buffer_object = &staging_bo.b;
1162 staging.addr = NULL;
1163 adapter_vk_copy_bo_address(context, &staging, src, range_count, ranges);
1164 adapter_vk_copy_bo_address(context, dst, &staging, range_count, ranges);
1166 wined3d_context_vk_destroy_bo(context_vk, &staging_bo);
1168 return;
1171 src_ptr = adapter_vk_map_bo_address(context, src, size, WINED3D_MAP_READ);
1172 dst_ptr = adapter_vk_map_bo_address(context, dst, size, map_flags);
1174 for (i = 0; i < range_count; ++i)
1175 memcpy(dst_ptr + ranges[i].offset, src_ptr + ranges[i].offset, ranges[i].size);
1177 adapter_vk_unmap_bo_address(context, dst, range_count, ranges);
1178 adapter_vk_unmap_bo_address(context, src, 0, NULL);
1181 static void adapter_vk_flush_bo_address(struct wined3d_context *context,
1182 const struct wined3d_const_bo_address *data, size_t size)
1184 struct wined3d_context_vk *context_vk = wined3d_context_vk(context);
1185 struct wined3d_bo *bo;
1187 if (!(bo = data->buffer_object))
1188 return;
1190 flush_bo_range(context_vk, wined3d_bo_vk(bo), (uintptr_t)data->addr, size);
1193 static bool adapter_vk_alloc_bo(struct wined3d_device *device, struct wined3d_resource *resource,
1194 unsigned int sub_resource_idx, struct wined3d_bo_address *addr)
1196 struct wined3d_device_vk *device_vk = wined3d_device_vk(device);
1197 struct wined3d_context_vk *context_vk = &device_vk->context_vk;
1198 VkMemoryPropertyFlags memory_type;
1199 VkBufferUsageFlags buffer_usage;
1200 struct wined3d_bo_vk *bo_vk;
1201 VkDeviceSize size;
1203 wined3d_not_from_cs(device->cs);
1204 assert(device->context_count);
1206 if (resource->type == WINED3D_RTYPE_BUFFER)
1208 buffer_usage = vk_buffer_usage_from_bind_flags(resource->bind_flags);
1209 memory_type = vk_memory_type_from_access_flags(resource->access, resource->usage);
1210 size = resource->size;
1212 else
1214 struct wined3d_texture *texture = texture_from_resource(resource);
1216 buffer_usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
1217 memory_type = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
1218 size = texture->sub_resources[sub_resource_idx].size;
1221 if (!(bo_vk = heap_alloc(sizeof(*bo_vk))))
1222 return false;
1224 if (!(wined3d_context_vk_create_bo(context_vk, size, buffer_usage, memory_type, bo_vk)))
1226 WARN("Failed to create Vulkan buffer.\n");
1227 heap_free(bo_vk);
1228 return false;
1231 if (!bo_vk->b.map_ptr)
1233 if (!wined3d_bo_vk_map(bo_vk, context_vk))
1234 ERR("Failed to map bo.\n");
1237 addr->buffer_object = &bo_vk->b;
1238 addr->addr = NULL;
1239 return true;
1242 static void adapter_vk_destroy_bo(struct wined3d_context *context, struct wined3d_bo *bo)
1244 wined3d_context_vk_destroy_bo(wined3d_context_vk(context), wined3d_bo_vk(bo));
1247 static HRESULT adapter_vk_create_swapchain(struct wined3d_device *device,
1248 struct wined3d_swapchain_desc *desc, struct wined3d_swapchain_state_parent *state_parent,
1249 void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_swapchain **swapchain)
1251 struct wined3d_swapchain_vk *swapchain_vk;
1252 HRESULT hr;
1254 TRACE("device %p, desc %p, state_parent %p, parent %p, parent_ops %p, swapchain %p.\n",
1255 device, desc, state_parent, parent, parent_ops, swapchain);
1257 if (!(swapchain_vk = heap_alloc_zero(sizeof(*swapchain_vk))))
1258 return E_OUTOFMEMORY;
1260 if (FAILED(hr = wined3d_swapchain_vk_init(swapchain_vk, device, desc, state_parent, parent,
1261 parent_ops)))
1263 WARN("Failed to initialise swapchain, hr %#lx.\n", hr);
1264 heap_free(swapchain_vk);
1265 return hr;
1268 TRACE("Created swapchain %p.\n", swapchain_vk);
1269 *swapchain = &swapchain_vk->s;
1271 return hr;
1274 static void adapter_vk_destroy_swapchain(struct wined3d_swapchain *swapchain)
1276 struct wined3d_swapchain_vk *swapchain_vk = wined3d_swapchain_vk(swapchain);
1278 wined3d_swapchain_vk_cleanup(swapchain_vk);
1279 heap_free(swapchain_vk);
1282 unsigned int wined3d_adapter_vk_get_memory_type_index(const struct wined3d_adapter_vk *adapter_vk,
1283 uint32_t memory_type_mask, VkMemoryPropertyFlags flags)
1285 const VkPhysicalDeviceMemoryProperties *memory_info = &adapter_vk->memory_properties;
1286 unsigned int i;
1288 for (i = 0; i < memory_info->memoryTypeCount; ++i)
1290 if (!(memory_type_mask & (1u << i)))
1291 continue;
1292 if ((memory_info->memoryTypes[i].propertyFlags & flags) == flags)
1293 return i;
1296 return ~0u;
1299 static HRESULT adapter_vk_create_buffer(struct wined3d_device *device,
1300 const struct wined3d_buffer_desc *desc, const struct wined3d_sub_resource_data *data,
1301 void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_buffer **buffer)
1303 struct wined3d_buffer_vk *buffer_vk;
1304 HRESULT hr;
1306 TRACE("device %p, desc %p, data %p, parent %p, parent_ops %p, buffer %p.\n",
1307 device, desc, data, parent, parent_ops, buffer);
1309 if (!(buffer_vk = heap_alloc_zero(sizeof(*buffer_vk))))
1310 return E_OUTOFMEMORY;
1312 if (FAILED(hr = wined3d_buffer_vk_init(buffer_vk, device, desc, data, parent, parent_ops)))
1314 WARN("Failed to initialise buffer, hr %#lx.\n", hr);
1315 heap_free(buffer_vk);
1316 return hr;
1319 TRACE("Created buffer %p.\n", buffer_vk);
1320 *buffer = &buffer_vk->b;
1322 return hr;
1325 static void adapter_vk_destroy_buffer(struct wined3d_buffer *buffer)
1327 struct wined3d_buffer_vk *buffer_vk = wined3d_buffer_vk(buffer);
1328 struct wined3d_device *device = buffer_vk->b.resource.device;
1329 unsigned int swapchain_count = device->swapchain_count;
1331 TRACE("buffer_vk %p.\n", buffer_vk);
1333 /* Take a reference to the device, in case releasing the buffer would
1334 * cause the device to be destroyed. However, swapchain resources don't
1335 * take a reference to the device, and we wouldn't want to increment the
1336 * refcount on a device that's in the process of being destroyed. */
1337 if (swapchain_count)
1338 wined3d_device_incref(device);
1339 wined3d_buffer_cleanup(&buffer_vk->b);
1340 wined3d_cs_destroy_object(device->cs, heap_free, buffer_vk);
1341 if (swapchain_count)
1342 wined3d_device_decref(device);
1345 static HRESULT adapter_vk_create_texture(struct wined3d_device *device,
1346 const struct wined3d_resource_desc *desc, unsigned int layer_count, unsigned int level_count,
1347 uint32_t flags, void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_texture **texture)
1349 struct wined3d_texture_vk *texture_vk;
1350 HRESULT hr;
1352 TRACE("device %p, desc %p, layer_count %u, level_count %u, flags %#x, parent %p, parent_ops %p, texture %p.\n",
1353 device, desc, layer_count, level_count, flags, parent, parent_ops, texture);
1355 if (!(texture_vk = wined3d_texture_allocate_object_memory(sizeof(*texture_vk), level_count, layer_count)))
1356 return E_OUTOFMEMORY;
1358 if (FAILED(hr = wined3d_texture_vk_init(texture_vk, device, desc,
1359 layer_count, level_count, flags, parent, parent_ops)))
1361 WARN("Failed to initialise texture, hr %#lx.\n", hr);
1362 heap_free(texture_vk);
1363 return hr;
1366 TRACE("Created texture %p.\n", texture_vk);
1367 *texture = &texture_vk->t;
1369 return hr;
1372 static void adapter_vk_destroy_texture(struct wined3d_texture *texture)
1374 struct wined3d_texture_vk *texture_vk = wined3d_texture_vk(texture);
1375 struct wined3d_device *device = texture_vk->t.resource.device;
1376 unsigned int swapchain_count = device->swapchain_count;
1378 TRACE("texture_vk %p.\n", texture_vk);
1380 /* Take a reference to the device, in case releasing the texture would
1381 * cause the device to be destroyed. However, swapchain resources don't
1382 * take a reference to the device, and we wouldn't want to increment the
1383 * refcount on a device that's in the process of being destroyed. */
1384 if (swapchain_count)
1385 wined3d_device_incref(device);
1387 wined3d_texture_sub_resources_destroyed(texture);
1388 texture->resource.parent_ops->wined3d_object_destroyed(texture->resource.parent);
1390 wined3d_texture_cleanup(&texture_vk->t);
1391 wined3d_cs_destroy_object(device->cs, heap_free, texture_vk);
1393 if (swapchain_count)
1394 wined3d_device_decref(device);
1397 static HRESULT adapter_vk_create_rendertarget_view(const struct wined3d_view_desc *desc,
1398 struct wined3d_resource *resource, void *parent, const struct wined3d_parent_ops *parent_ops,
1399 struct wined3d_rendertarget_view **view)
1401 struct wined3d_rendertarget_view_vk *view_vk;
1402 HRESULT hr;
1404 TRACE("desc %s, resource %p, parent %p, parent_ops %p, view %p.\n",
1405 wined3d_debug_view_desc(desc, resource), resource, parent, parent_ops, view);
1407 if (!(view_vk = heap_alloc_zero(sizeof(*view_vk))))
1408 return E_OUTOFMEMORY;
1410 if (FAILED(hr = wined3d_rendertarget_view_vk_init(view_vk, desc, resource, parent, parent_ops)))
1412 WARN("Failed to initialise view, hr %#lx.\n", hr);
1413 heap_free(view_vk);
1414 return hr;
1417 TRACE("Created render target view %p.\n", view_vk);
1418 *view = &view_vk->v;
1420 return hr;
1423 struct wined3d_view_vk_destroy_ctx
1425 struct wined3d_device_vk *device_vk;
1426 VkBufferView *vk_buffer_view;
1427 VkImageView *vk_image_view;
1428 struct wined3d_bo_user *bo_user;
1429 struct wined3d_bo_vk *vk_counter_bo;
1430 VkBufferView *vk_counter_view;
1431 uint64_t *command_buffer_id;
1432 void *object;
1433 struct wined3d_view_vk_destroy_ctx *free;
1436 static void wined3d_view_vk_destroy_object(void *object)
1438 struct wined3d_view_vk_destroy_ctx *ctx = object;
1439 const struct wined3d_vk_info *vk_info;
1440 struct wined3d_device_vk *device_vk;
1441 struct wined3d_context *context;
1443 TRACE("ctx %p.\n", ctx);
1445 device_vk = ctx->device_vk;
1446 vk_info = &wined3d_adapter_vk(device_vk->d.adapter)->vk_info;
1447 context = context_acquire(&device_vk->d, NULL, 0);
1449 if (ctx->vk_buffer_view)
1451 if (context)
1453 wined3d_context_vk_destroy_vk_buffer_view(wined3d_context_vk(context),
1454 *ctx->vk_buffer_view, *ctx->command_buffer_id);
1456 else
1458 VK_CALL(vkDestroyBufferView(device_vk->vk_device, *ctx->vk_buffer_view, NULL));
1459 TRACE("Destroyed buffer view 0x%s.\n", wine_dbgstr_longlong(*ctx->vk_buffer_view));
1462 if (ctx->vk_image_view)
1464 if (context)
1466 wined3d_context_vk_destroy_vk_image_view(wined3d_context_vk(context),
1467 *ctx->vk_image_view, *ctx->command_buffer_id);
1469 else
1471 VK_CALL(vkDestroyImageView(device_vk->vk_device, *ctx->vk_image_view, NULL));
1472 TRACE("Destroyed image view 0x%s.\n", wine_dbgstr_longlong(*ctx->vk_image_view));
1475 if (ctx->bo_user)
1476 list_remove(&ctx->bo_user->entry);
1477 if (ctx->vk_counter_bo && ctx->vk_counter_bo->vk_buffer)
1478 wined3d_context_vk_destroy_bo(wined3d_context_vk(context), ctx->vk_counter_bo);
1479 if (ctx->vk_counter_view)
1481 if (context)
1483 wined3d_context_vk_destroy_vk_buffer_view(wined3d_context_vk(context),
1484 *ctx->vk_counter_view, *ctx->command_buffer_id);
1486 else
1488 VK_CALL(vkDestroyBufferView(device_vk->vk_device, *ctx->vk_counter_view, NULL));
1489 TRACE("Destroyed counter buffer view 0x%s.\n", wine_dbgstr_longlong(*ctx->vk_counter_view));
1493 if (context)
1494 context_release(context);
1496 heap_free(ctx->object);
1497 heap_free(ctx->free);
1500 static void wined3d_view_vk_destroy(struct wined3d_device *device, VkBufferView *vk_buffer_view,
1501 VkImageView *vk_image_view, struct wined3d_bo_user *bo_user, struct wined3d_bo_vk *vk_counter_bo,
1502 VkBufferView *vk_counter_view, uint64_t *command_buffer_id, void *view_vk)
1504 struct wined3d_view_vk_destroy_ctx *ctx, c;
1506 if (!(ctx = heap_alloc(sizeof(*ctx))))
1507 ctx = &c;
1508 ctx->device_vk = wined3d_device_vk(device);
1509 ctx->vk_buffer_view = vk_buffer_view;
1510 ctx->vk_image_view = vk_image_view;
1511 ctx->bo_user = bo_user;
1512 ctx->vk_counter_bo = vk_counter_bo;
1513 ctx->vk_counter_view = vk_counter_view;
1514 ctx->command_buffer_id = command_buffer_id;
1515 ctx->object = view_vk;
1516 ctx->free = ctx != &c ? ctx : NULL;
1518 wined3d_cs_destroy_object(device->cs, wined3d_view_vk_destroy_object, ctx);
1519 if (ctx == &c)
1520 wined3d_cs_finish(device->cs, WINED3D_CS_QUEUE_DEFAULT);
1523 static void adapter_vk_destroy_rendertarget_view(struct wined3d_rendertarget_view *view)
1525 struct wined3d_rendertarget_view_vk *view_vk = wined3d_rendertarget_view_vk(view);
1526 struct wined3d_resource *resource = view_vk->v.resource;
1528 TRACE("view_vk %p.\n", view_vk);
1530 /* Take a reference to the resource, in case releasing the resource
1531 * would cause the device to be destroyed. */
1532 wined3d_resource_incref(resource);
1533 wined3d_rendertarget_view_cleanup(&view_vk->v);
1534 wined3d_view_vk_destroy(resource->device, NULL, &view_vk->vk_image_view,
1535 NULL, NULL, NULL, &view_vk->command_buffer_id, view_vk);
1536 wined3d_resource_decref(resource);
1539 static HRESULT adapter_vk_create_shader_resource_view(const struct wined3d_view_desc *desc,
1540 struct wined3d_resource *resource, void *parent, const struct wined3d_parent_ops *parent_ops,
1541 struct wined3d_shader_resource_view **view)
1543 struct wined3d_shader_resource_view_vk *view_vk;
1544 HRESULT hr;
1546 TRACE("desc %s, resource %p, parent %p, parent_ops %p, view %p.\n",
1547 wined3d_debug_view_desc(desc, resource), resource, parent, parent_ops, view);
1549 if (!(view_vk = heap_alloc_zero(sizeof(*view_vk))))
1550 return E_OUTOFMEMORY;
1552 if (FAILED(hr = wined3d_shader_resource_view_vk_init(view_vk, desc, resource, parent, parent_ops)))
1554 WARN("Failed to initialise view, hr %#lx.\n", hr);
1555 heap_free(view_vk);
1556 return hr;
1559 TRACE("Created shader resource view %p.\n", view_vk);
1560 *view = &view_vk->v;
1562 return hr;
1565 static void adapter_vk_destroy_shader_resource_view(struct wined3d_shader_resource_view *view)
1567 struct wined3d_shader_resource_view_vk *srv_vk = wined3d_shader_resource_view_vk(view);
1568 struct wined3d_resource *resource = srv_vk->v.resource;
1569 struct wined3d_view_vk *view_vk = &srv_vk->view_vk;
1570 VkBufferView *vk_buffer_view = NULL;
1571 VkImageView *vk_image_view = NULL;
1573 TRACE("srv_vk %p.\n", srv_vk);
1575 /* Take a reference to the resource. There are two reasons for this:
1576 * - Releasing the resource could in turn cause the device to be
1577 * destroyed, but we still need the device for
1578 * wined3d_view_vk_destroy().
1579 * - We shouldn't free buffer resources until after we've removed the
1580 * view from its bo_user list. */
1581 wined3d_resource_incref(resource);
1582 if (resource->type == WINED3D_RTYPE_BUFFER)
1583 vk_buffer_view = &view_vk->u.vk_buffer_view;
1584 else
1585 vk_image_view = &view_vk->u.vk_image_info.imageView;
1586 wined3d_shader_resource_view_cleanup(&srv_vk->v);
1587 wined3d_view_vk_destroy(resource->device, vk_buffer_view, vk_image_view,
1588 &view_vk->bo_user, NULL, NULL, &view_vk->command_buffer_id, srv_vk);
1589 wined3d_resource_decref(resource);
1592 static HRESULT adapter_vk_create_unordered_access_view(const struct wined3d_view_desc *desc,
1593 struct wined3d_resource *resource, void *parent, const struct wined3d_parent_ops *parent_ops,
1594 struct wined3d_unordered_access_view **view)
1596 struct wined3d_unordered_access_view_vk *view_vk;
1597 HRESULT hr;
1599 TRACE("desc %s, resource %p, parent %p, parent_ops %p, view %p.\n",
1600 wined3d_debug_view_desc(desc, resource), resource, parent, parent_ops, view);
1602 if (!(view_vk = heap_alloc_zero(sizeof(*view_vk))))
1603 return E_OUTOFMEMORY;
1605 if (FAILED(hr = wined3d_unordered_access_view_vk_init(view_vk, desc, resource, parent, parent_ops)))
1607 WARN("Failed to initialise view, hr %#lx.\n", hr);
1608 heap_free(view_vk);
1609 return hr;
1612 TRACE("Created unordered access view %p.\n", view_vk);
1613 *view = &view_vk->v;
1615 return hr;
1618 static void adapter_vk_destroy_unordered_access_view(struct wined3d_unordered_access_view *view)
1620 struct wined3d_unordered_access_view_vk *uav_vk = wined3d_unordered_access_view_vk(view);
1621 struct wined3d_resource *resource = uav_vk->v.resource;
1622 struct wined3d_view_vk *view_vk = &uav_vk->view_vk;
1623 VkBufferView *vk_buffer_view = NULL;
1624 VkImageView *vk_image_view = NULL;
1626 TRACE("uav_vk %p.\n", uav_vk);
1628 /* Take a reference to the resource. There are two reasons for this:
1629 * - Releasing the resource could in turn cause the device to be
1630 * destroyed, but we still need the device for
1631 * wined3d_view_vk_destroy().
1632 * - We shouldn't free buffer resources until after we've removed the
1633 * view from its bo_user list. */
1634 wined3d_resource_incref(resource);
1635 if (resource->type == WINED3D_RTYPE_BUFFER)
1636 vk_buffer_view = &view_vk->u.vk_buffer_view;
1637 else
1638 vk_image_view = &view_vk->u.vk_image_info.imageView;
1639 wined3d_unordered_access_view_cleanup(&uav_vk->v);
1640 wined3d_view_vk_destroy(resource->device, vk_buffer_view, vk_image_view, &view_vk->bo_user,
1641 &uav_vk->counter_bo, &uav_vk->vk_counter_view, &view_vk->command_buffer_id, uav_vk);
1642 wined3d_resource_decref(resource);
1645 static HRESULT adapter_vk_create_sampler(struct wined3d_device *device, const struct wined3d_sampler_desc *desc,
1646 void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_sampler **sampler)
1648 struct wined3d_sampler_vk *sampler_vk;
1650 TRACE("device %p, desc %p, parent %p, parent_ops %p, sampler %p.\n",
1651 device, desc, parent, parent_ops, sampler);
1653 if (!(sampler_vk = heap_alloc_zero(sizeof(*sampler_vk))))
1654 return E_OUTOFMEMORY;
1656 wined3d_sampler_vk_init(sampler_vk, device, desc, parent, parent_ops);
1658 TRACE("Created sampler %p.\n", sampler_vk);
1659 *sampler = &sampler_vk->s;
1661 return WINED3D_OK;
1664 static void wined3d_sampler_vk_destroy_object(void *object)
1666 struct wined3d_sampler_vk *sampler_vk = object;
1667 struct wined3d_context_vk *context_vk;
1669 TRACE("sampler_vk %p.\n", sampler_vk);
1671 context_vk = wined3d_context_vk(context_acquire(sampler_vk->s.device, NULL, 0));
1673 wined3d_context_vk_destroy_vk_sampler(context_vk, sampler_vk->vk_image_info.sampler, sampler_vk->command_buffer_id);
1674 heap_free(sampler_vk);
1676 context_release(&context_vk->c);
1679 static void adapter_vk_destroy_sampler(struct wined3d_sampler *sampler)
1681 struct wined3d_sampler_vk *sampler_vk = wined3d_sampler_vk(sampler);
1683 TRACE("sampler_vk %p.\n", sampler_vk);
1685 wined3d_cs_destroy_object(sampler->device->cs, wined3d_sampler_vk_destroy_object, sampler_vk);
1688 static HRESULT adapter_vk_create_query(struct wined3d_device *device, enum wined3d_query_type type,
1689 void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_query **query)
1691 TRACE("device %p, type %#x, parent %p, parent_ops %p, query %p.\n",
1692 device, type, parent, parent_ops, query);
1694 return wined3d_query_vk_create(device, type, parent, parent_ops, query);
1697 static void wined3d_query_vk_destroy_object(void *object)
1699 struct wined3d_query_vk *query_vk = object;
1701 TRACE("query_vk %p.\n", query_vk);
1703 query_vk->q.query_ops->query_destroy(&query_vk->q);
1706 static void adapter_vk_destroy_query(struct wined3d_query *query)
1708 struct wined3d_query_vk *query_vk = wined3d_query_vk(query);
1710 TRACE("query_vk %p.\n", query_vk);
1712 wined3d_cs_destroy_object(query->device->cs, wined3d_query_vk_destroy_object, query_vk);
1715 static void adapter_vk_flush_context(struct wined3d_context *context)
1717 struct wined3d_context_vk *context_vk = wined3d_context_vk(context);
1719 TRACE("context_vk %p.\n", context_vk);
1721 wined3d_context_vk_submit_command_buffer(context_vk, 0, NULL, NULL, 0, NULL);
1724 static void adapter_vk_draw_primitive(struct wined3d_device *device,
1725 const struct wined3d_state *state, const struct wined3d_draw_parameters *parameters)
1727 struct wined3d_buffer_vk *indirect_vk = NULL;
1728 const struct wined3d_vk_info *vk_info;
1729 struct wined3d_context_vk *context_vk;
1730 VkCommandBuffer vk_command_buffer;
1731 uint32_t instance_count;
1732 unsigned int i;
1734 TRACE("device %p, state %p, parameters %p.\n", device, state, parameters);
1736 context_vk = wined3d_context_vk(context_acquire(device, NULL, 0));
1737 vk_info = context_vk->vk_info;
1739 if (parameters->indirect)
1740 indirect_vk = wined3d_buffer_vk(parameters->u.indirect.buffer);
1742 if (!(vk_command_buffer = wined3d_context_vk_apply_draw_state(context_vk,
1743 state, indirect_vk, parameters->indexed)))
1745 ERR("Failed to apply draw state.\n");
1746 context_release(&context_vk->c);
1747 return;
1750 if (context_vk->c.transform_feedback_active)
1752 if (!context_vk->vk_so_counter_bo.vk_buffer)
1754 struct wined3d_bo_vk *bo = &context_vk->vk_so_counter_bo;
1756 if (!wined3d_context_vk_create_bo(context_vk, ARRAY_SIZE(context_vk->vk_so_counters) * sizeof(uint32_t) * 2,
1757 VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, bo))
1758 ERR("Failed to create counter BO.\n");
1759 for (i = 0; i < ARRAY_SIZE(context_vk->vk_so_counters); ++i)
1761 context_vk->vk_so_counters[i] = bo->vk_buffer;
1762 context_vk->vk_so_offsets[i] = bo->b.buffer_offset + i * sizeof(uint32_t) * 2;
1766 wined3d_context_vk_reference_bo(context_vk, &context_vk->vk_so_counter_bo);
1767 if (context_vk->c.transform_feedback_paused)
1768 VK_CALL(vkCmdBeginTransformFeedbackEXT(vk_command_buffer, 0, ARRAY_SIZE(context_vk->vk_so_counters),
1769 context_vk->vk_so_counters, context_vk->vk_so_offsets));
1770 else
1771 VK_CALL(vkCmdBeginTransformFeedbackEXT(vk_command_buffer, 0, 0, NULL, NULL));
1774 if (parameters->indirect)
1776 struct wined3d_bo_vk *bo = wined3d_bo_vk(indirect_vk->b.buffer_object);
1778 wined3d_context_vk_reference_bo(context_vk, bo);
1779 if (parameters->indexed)
1780 VK_CALL(vkCmdDrawIndexedIndirect(vk_command_buffer, bo->vk_buffer,
1781 bo->b.buffer_offset + parameters->u.indirect.offset, 1, sizeof(VkDrawIndexedIndirectCommand)));
1782 else
1783 VK_CALL(vkCmdDrawIndirect(vk_command_buffer, bo->vk_buffer,
1784 bo->b.buffer_offset + parameters->u.indirect.offset, 1, sizeof(VkDrawIndirectCommand)));
1786 else
1788 instance_count = parameters->u.direct.instance_count;
1789 if (!instance_count)
1790 instance_count = 1;
1792 if (parameters->indexed)
1793 VK_CALL(vkCmdDrawIndexed(vk_command_buffer, parameters->u.direct.index_count,
1794 instance_count, parameters->u.direct.start_idx, parameters->u.direct.base_vertex_idx,
1795 parameters->u.direct.start_instance));
1796 else
1797 VK_CALL(vkCmdDraw(vk_command_buffer, parameters->u.direct.index_count, instance_count,
1798 parameters->u.direct.start_idx, parameters->u.direct.start_instance));
1801 if (context_vk->c.transform_feedback_active)
1803 VK_CALL(vkCmdEndTransformFeedbackEXT(vk_command_buffer, 0, ARRAY_SIZE(context_vk->vk_so_counters),
1804 context_vk->vk_so_counters, context_vk->vk_so_offsets));
1805 context_vk->c.transform_feedback_paused = 1;
1806 context_vk->c.transform_feedback_active = 0;
1809 context_release(&context_vk->c);
1812 static void adapter_vk_dispatch_compute(struct wined3d_device *device,
1813 const struct wined3d_state *state, const struct wined3d_dispatch_parameters *parameters)
1815 struct wined3d_buffer_vk *indirect_vk = NULL;
1816 const struct wined3d_vk_info *vk_info;
1817 struct wined3d_context_vk *context_vk;
1818 VkCommandBuffer vk_command_buffer;
1820 TRACE("device %p, state %p, parameters %p.\n", device, state, parameters);
1822 context_vk = wined3d_context_vk(context_acquire(device, NULL, 0));
1823 vk_info = context_vk->vk_info;
1825 if (parameters->indirect)
1826 indirect_vk = wined3d_buffer_vk(parameters->u.indirect.buffer);
1828 if (!(vk_command_buffer = wined3d_context_vk_apply_compute_state(context_vk, state, indirect_vk)))
1830 ERR("Failed to apply compute state.\n");
1831 context_release(&context_vk->c);
1832 return;
1835 if (parameters->indirect)
1837 struct wined3d_bo_vk *bo = wined3d_bo_vk(indirect_vk->b.buffer_object);
1839 wined3d_context_vk_reference_bo(context_vk, bo);
1840 VK_CALL(vkCmdDispatchIndirect(vk_command_buffer, bo->vk_buffer,
1841 bo->b.buffer_offset + parameters->u.indirect.offset));
1843 else
1845 const struct wined3d_direct_dispatch_parameters *direct = &parameters->u.direct;
1847 VK_CALL(vkCmdDispatch(vk_command_buffer, direct->group_count_x, direct->group_count_y, direct->group_count_z));
1850 VK_CALL(vkCmdPipelineBarrier(vk_command_buffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
1851 VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, 0, 0, NULL, 0, NULL, 0, NULL));
1853 context_release(&context_vk->c);
1856 static void adapter_vk_clear_uav(struct wined3d_context *context,
1857 struct wined3d_unordered_access_view *view, const struct wined3d_uvec4 *clear_value, bool fp)
1859 TRACE("context %p, view %p, clear_value %s.\n", context, view, debug_uvec4(clear_value));
1861 wined3d_unordered_access_view_vk_clear(wined3d_unordered_access_view_vk(view),
1862 clear_value, wined3d_context_vk(context), fp);
1865 static void adapter_vk_generate_mipmap(struct wined3d_context *context, struct wined3d_shader_resource_view *view)
1867 TRACE("context %p, view %p.\n", context, view);
1869 wined3d_shader_resource_view_vk_generate_mipmap(wined3d_shader_resource_view_vk(view),
1870 wined3d_context_vk(context));
1873 static const struct wined3d_adapter_ops wined3d_adapter_vk_ops =
1875 .adapter_destroy = adapter_vk_destroy,
1876 .adapter_create_device = adapter_vk_create_device,
1877 .adapter_destroy_device = adapter_vk_destroy_device,
1878 .adapter_acquire_context = adapter_vk_acquire_context,
1879 .adapter_release_context = adapter_vk_release_context,
1880 .adapter_get_wined3d_caps = adapter_vk_get_wined3d_caps,
1881 .adapter_check_format = adapter_vk_check_format,
1882 .adapter_init_3d = adapter_vk_init_3d,
1883 .adapter_uninit_3d = adapter_vk_uninit_3d,
1884 .adapter_map_bo_address = adapter_vk_map_bo_address,
1885 .adapter_unmap_bo_address = adapter_vk_unmap_bo_address,
1886 .adapter_copy_bo_address = adapter_vk_copy_bo_address,
1887 .adapter_flush_bo_address = adapter_vk_flush_bo_address,
1888 .adapter_alloc_bo = adapter_vk_alloc_bo,
1889 .adapter_destroy_bo = adapter_vk_destroy_bo,
1890 .adapter_create_swapchain = adapter_vk_create_swapchain,
1891 .adapter_destroy_swapchain = adapter_vk_destroy_swapchain,
1892 .adapter_create_buffer = adapter_vk_create_buffer,
1893 .adapter_destroy_buffer = adapter_vk_destroy_buffer,
1894 .adapter_create_texture = adapter_vk_create_texture,
1895 .adapter_destroy_texture = adapter_vk_destroy_texture,
1896 .adapter_create_rendertarget_view = adapter_vk_create_rendertarget_view,
1897 .adapter_destroy_rendertarget_view = adapter_vk_destroy_rendertarget_view,
1898 .adapter_create_shader_resource_view = adapter_vk_create_shader_resource_view,
1899 .adapter_destroy_shader_resource_view = adapter_vk_destroy_shader_resource_view,
1900 .adapter_create_unordered_access_view = adapter_vk_create_unordered_access_view,
1901 .adapter_destroy_unordered_access_view = adapter_vk_destroy_unordered_access_view,
1902 .adapter_create_sampler = adapter_vk_create_sampler,
1903 .adapter_destroy_sampler = adapter_vk_destroy_sampler,
1904 .adapter_create_query = adapter_vk_create_query,
1905 .adapter_destroy_query = adapter_vk_destroy_query,
1906 .adapter_flush_context = adapter_vk_flush_context,
1907 .adapter_draw_primitive = adapter_vk_draw_primitive,
1908 .adapter_dispatch_compute = adapter_vk_dispatch_compute,
1909 .adapter_clear_uav = adapter_vk_clear_uav,
1910 .adapter_generate_mipmap = adapter_vk_generate_mipmap,
1913 static unsigned int wined3d_get_wine_vk_version(void)
1915 const char * (CDECL *wine_get_version)(void) = (void *)GetProcAddress( GetModuleHandleW(L"ntdll.dll"),
1916 "wine_get_version" );
1917 const char *ptr;
1918 int major, minor;
1920 if (!wine_get_version) return VK_MAKE_VERSION(1, 0, 0);
1922 ptr = wine_get_version();
1923 major = atoi(ptr);
1925 while (isdigit(*ptr))
1926 ++ptr;
1927 if (*ptr == '.')
1928 ++ptr;
1930 minor = atoi(ptr);
1932 return VK_MAKE_VERSION(major, minor, 0);
1935 static const struct
1937 const char *name;
1938 unsigned int core_since_version;
1939 BOOL required;
1941 vulkan_instance_extensions[] =
1943 {VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, VK_API_VERSION_1_1, FALSE},
1944 {VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME, VK_API_VERSION_1_1, FALSE},
1945 {VK_KHR_SURFACE_EXTENSION_NAME, ~0u, TRUE},
1946 {VK_KHR_WIN32_SURFACE_EXTENSION_NAME, ~0u, TRUE},
1949 static BOOL enable_vulkan_instance_extensions(uint32_t *extension_count,
1950 const char *enabled_extensions[], const struct wined3d_vk_info *vk_info)
1952 PFN_vkEnumerateInstanceExtensionProperties pfn_vkEnumerateInstanceExtensionProperties;
1953 VkExtensionProperties *extensions = NULL;
1954 BOOL success = FALSE, found;
1955 unsigned int i, j, count;
1956 VkResult vr;
1958 *extension_count = 0;
1960 if (!(pfn_vkEnumerateInstanceExtensionProperties
1961 = (void *)VK_CALL(vkGetInstanceProcAddr(NULL, "vkEnumerateInstanceExtensionProperties"))))
1963 WARN("Failed to get 'vkEnumerateInstanceExtensionProperties'.\n");
1964 goto done;
1967 if ((vr = pfn_vkEnumerateInstanceExtensionProperties(NULL, &count, NULL)) < 0)
1969 WARN("Failed to count instance extensions, vr %s.\n", wined3d_debug_vkresult(vr));
1970 goto done;
1972 if (!(extensions = heap_calloc(count, sizeof(*extensions))))
1974 WARN("Out of memory.\n");
1975 goto done;
1977 if ((vr = pfn_vkEnumerateInstanceExtensionProperties(NULL, &count, extensions)) < 0)
1979 WARN("Failed to enumerate extensions, vr %s.\n", wined3d_debug_vkresult(vr));
1980 goto done;
1983 TRACE("Vulkan instance extensions reported:\n");
1984 for (i = 0; i < count; ++i)
1986 TRACE(" - %s.\n", debugstr_a(extensions[i].extensionName));
1989 for (i = 0; i < ARRAY_SIZE(vulkan_instance_extensions); ++i)
1991 if (vulkan_instance_extensions[i].core_since_version <= vk_info->api_version)
1992 continue;
1994 for (j = 0, found = FALSE; j < count; ++j)
1996 if (!strcmp(extensions[j].extensionName, vulkan_instance_extensions[i].name))
1998 found = TRUE;
1999 break;
2002 if (found)
2004 TRACE("Enabling instance extension '%s'.\n", vulkan_instance_extensions[i].name);
2005 enabled_extensions[(*extension_count)++] = vulkan_instance_extensions[i].name;
2007 else if (!found && vulkan_instance_extensions[i].required)
2009 WARN("Required extension '%s' is not available.\n", vulkan_instance_extensions[i].name);
2010 goto done;
2013 success = TRUE;
2015 done:
2016 heap_free(extensions);
2017 return success;
2020 static BOOL wined3d_init_vulkan(struct wined3d_vk_info *vk_info)
2022 const char *enabled_instance_extensions[ARRAY_SIZE(vulkan_instance_extensions)];
2023 PFN_vkEnumerateInstanceVersion pfn_vkEnumerateInstanceVersion;
2024 struct vulkan_ops *vk_ops = &vk_info->vk_ops;
2025 VkInstance instance = VK_NULL_HANDLE;
2026 VkInstanceCreateInfo instance_info;
2027 VkApplicationInfo app_info;
2028 uint32_t api_version = 0;
2029 char app_name[MAX_PATH];
2030 VkResult vr;
2032 if (!wined3d_load_vulkan(vk_info))
2033 return FALSE;
2035 if (!(vk_ops->vkCreateInstance = (void *)VK_CALL(vkGetInstanceProcAddr(NULL, "vkCreateInstance"))))
2037 ERR("Failed to get 'vkCreateInstance'.\n");
2038 goto fail;
2041 vk_info->api_version = VK_API_VERSION_1_0;
2042 if ((pfn_vkEnumerateInstanceVersion = (void *)VK_CALL(vkGetInstanceProcAddr(NULL, "vkEnumerateInstanceVersion")))
2043 && pfn_vkEnumerateInstanceVersion(&api_version) == VK_SUCCESS)
2045 TRACE("Vulkan instance API version %s.\n", debug_vk_version(api_version));
2047 if (api_version >= VK_API_VERSION_1_1)
2048 vk_info->api_version = VK_API_VERSION_1_1;
2051 memset(&app_info, 0, sizeof(app_info));
2052 app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
2053 if (wined3d_get_app_name(app_name, ARRAY_SIZE(app_name)))
2054 app_info.pApplicationName = app_name;
2055 app_info.pEngineName = "Damavand";
2056 app_info.engineVersion = wined3d_get_wine_vk_version();
2057 app_info.apiVersion = vk_info->api_version;
2059 memset(&instance_info, 0, sizeof(instance_info));
2060 instance_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
2061 instance_info.pApplicationInfo = &app_info;
2062 instance_info.ppEnabledExtensionNames = enabled_instance_extensions;
2063 if (!enable_vulkan_instance_extensions(&instance_info.enabledExtensionCount, enabled_instance_extensions, vk_info))
2064 goto fail;
2066 memset(vk_info->supported, 0, sizeof(vk_info->supported));
2067 vk_info->supported[WINED3D_VK_EXT_NONE] = TRUE;
2069 if ((vr = VK_CALL(vkCreateInstance(&instance_info, NULL, &instance))) < 0)
2071 WARN("Failed to create Vulkan instance, vr %s.\n", wined3d_debug_vkresult(vr));
2072 goto fail;
2075 TRACE("Created Vulkan instance %p.\n", instance);
2077 #define LOAD_INSTANCE_PFN(name) \
2078 if (!(vk_ops->name = (void *)VK_CALL(vkGetInstanceProcAddr(instance, #name)))) \
2080 WARN("Could not get instance proc addr for '" #name "'.\n"); \
2081 goto fail; \
2083 #define LOAD_INSTANCE_OPT_PFN(name) \
2084 vk_ops->name = (void *)VK_CALL(vkGetInstanceProcAddr(instance, #name));
2085 #define VK_INSTANCE_PFN LOAD_INSTANCE_PFN
2086 #define VK_INSTANCE_EXT_PFN LOAD_INSTANCE_OPT_PFN
2087 #define VK_DEVICE_PFN LOAD_INSTANCE_PFN
2088 #define VK_DEVICE_EXT_PFN LOAD_INSTANCE_OPT_PFN
2089 VK_INSTANCE_FUNCS()
2090 VK_DEVICE_FUNCS()
2091 #undef VK_INSTANCE_PFN
2092 #undef VK_INSTANCE_EXT_PFN
2093 #undef VK_DEVICE_PFN
2094 #undef VK_DEVICE_EXT_PFN
2096 #define MAP_INSTANCE_FUNCTION(core_pfn, ext_pfn) \
2097 if (!vk_ops->core_pfn) \
2098 vk_ops->core_pfn = (void *)VK_CALL(vkGetInstanceProcAddr(instance, #ext_pfn));
2099 MAP_INSTANCE_FUNCTION(vkGetPhysicalDeviceProperties2, vkGetPhysicalDeviceProperties2KHR)
2100 MAP_INSTANCE_FUNCTION(vkGetPhysicalDeviceFeatures2, vkGetPhysicalDeviceFeatures2KHR)
2101 #undef MAP_INSTANCE_FUNCTION
2103 vk_info->instance = instance;
2105 return TRUE;
2107 fail:
2108 if (vk_ops->vkDestroyInstance)
2109 VK_CALL(vkDestroyInstance(instance, NULL));
2110 wined3d_unload_vulkan(vk_info);
2111 return FALSE;
2114 static VkPhysicalDevice get_vulkan_physical_device(struct wined3d_vk_info *vk_info)
2116 VkPhysicalDevice physical_devices[1];
2117 uint32_t count;
2118 VkResult vr;
2120 if ((vr = VK_CALL(vkEnumeratePhysicalDevices(vk_info->instance, &count, NULL))) < 0)
2122 WARN("Failed to enumerate physical devices, vr %s.\n", wined3d_debug_vkresult(vr));
2123 return VK_NULL_HANDLE;
2125 if (!count)
2127 WARN("No physical device.\n");
2128 return VK_NULL_HANDLE;
2130 if (count > 1)
2132 /* TODO: Create wined3d_adapter for each device. */
2133 FIXME("Multiple physical devices available.\n");
2134 count = 1;
2137 if ((vr = VK_CALL(vkEnumeratePhysicalDevices(vk_info->instance, &count, physical_devices))) < 0)
2139 WARN("Failed to get physical devices, vr %s.\n", wined3d_debug_vkresult(vr));
2140 return VK_NULL_HANDLE;
2143 return physical_devices[0];
2146 static enum wined3d_display_driver guess_display_driver(enum wined3d_pci_vendor vendor)
2148 switch (vendor)
2150 case HW_VENDOR_AMD: return DRIVER_AMD_RX;
2151 case HW_VENDOR_INTEL: return DRIVER_INTEL_HD4000;
2152 case HW_VENDOR_NVIDIA: return DRIVER_NVIDIA_GEFORCE8;
2153 default: return DRIVER_WINE;
2157 static bool adapter_vk_init_driver_info(struct wined3d_adapter_vk *adapter_vk,
2158 const VkPhysicalDeviceProperties *properties)
2160 const VkPhysicalDeviceMemoryProperties *memory_properties = &adapter_vk->memory_properties;
2161 const struct wined3d_gpu_description *gpu_description;
2162 struct wined3d_gpu_description description;
2163 UINT64 vram_bytes, sysmem_bytes;
2164 const VkMemoryType *type;
2165 const VkMemoryHeap *heap;
2166 unsigned int i;
2168 TRACE("Device name: %s.\n", debugstr_a(properties->deviceName));
2169 TRACE("Vendor ID: 0x%04x, Device ID: 0x%04x.\n", properties->vendorID, properties->deviceID);
2170 TRACE("Driver version: %#x.\n", properties->driverVersion);
2171 TRACE("API version: %s.\n", debug_vk_version(properties->apiVersion));
2173 for (i = 0, vram_bytes = 0, sysmem_bytes = 0; i < memory_properties->memoryHeapCount; ++i)
2175 heap = &memory_properties->memoryHeaps[i];
2176 TRACE("Memory heap [%u]: flags %#x, size 0x%s.\n",
2177 i, heap->flags, wine_dbgstr_longlong(heap->size));
2178 if (heap->flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT)
2179 vram_bytes += heap->size;
2180 else
2181 sysmem_bytes += heap->size;
2183 TRACE("Total device memory: 0x%s.\n", wine_dbgstr_longlong(vram_bytes));
2184 TRACE("Total shared system memory: 0x%s.\n", wine_dbgstr_longlong(sysmem_bytes));
2186 for (i = 0; i < memory_properties->memoryTypeCount; ++i)
2188 type = &memory_properties->memoryTypes[i];
2189 TRACE("Memory type [%u]: flags %#x, heap %u.\n", i, type->propertyFlags, type->heapIndex);
2192 if (!(gpu_description = wined3d_get_user_override_gpu_description(properties->vendorID, properties->deviceID)))
2193 gpu_description = wined3d_get_gpu_description(properties->vendorID, properties->deviceID);
2195 if (!gpu_description)
2197 FIXME("Failed to retrieve GPU description for device %s %04x:%04x.\n",
2198 debugstr_a(properties->deviceName), properties->vendorID, properties->deviceID);
2200 description.vendor = properties->vendorID;
2201 description.device = properties->deviceID;
2202 description.description = properties->deviceName;
2203 description.driver = guess_display_driver(properties->vendorID);
2204 description.vidmem = vram_bytes;
2206 gpu_description = &description;
2209 return wined3d_driver_info_init(&adapter_vk->a.driver_info, gpu_description,
2210 adapter_vk->a.d3d_info.feature_level, vram_bytes, sysmem_bytes);
2213 static bool feature_level_9_2_supported(const struct wined3d_physical_device_info *info)
2215 return info->features2.features.occlusionQueryPrecise;
2218 static bool feature_level_9_3_supported(const struct wined3d_physical_device_info *info, unsigned int shader_model)
2220 return shader_model >= 3
2221 && info->features2.features.independentBlend;
2224 static bool feature_level_10_supported(const struct wined3d_physical_device_info *info, unsigned int shader_model)
2226 return shader_model >= 4
2227 && info->features2.features.multiViewport
2228 && info->features2.features.geometryShader
2229 && info->features2.features.depthClamp
2230 && info->features2.features.depthBiasClamp
2231 && info->features2.features.pipelineStatisticsQuery
2232 && info->features2.features.shaderClipDistance
2233 && info->features2.features.shaderCullDistance
2234 && info->vertex_divisor_features.vertexAttributeInstanceRateDivisor
2235 && info->vertex_divisor_features.vertexAttributeInstanceRateZeroDivisor;
2238 static bool feature_level_10_1_supported(const struct wined3d_physical_device_info *info, unsigned int shader_model)
2240 return info->features2.features.imageCubeArray;
2243 static bool feature_level_11_supported(const struct wined3d_physical_device_info *info, unsigned int shader_model)
2245 return shader_model >= 5
2246 && info->features2.features.multiDrawIndirect
2247 && info->features2.features.drawIndirectFirstInstance
2248 && info->features2.features.fragmentStoresAndAtomics
2249 && info->features2.features.shaderImageGatherExtended
2250 && info->features2.features.tessellationShader;
2253 static bool feature_level_11_1_supported(const struct wined3d_physical_device_info *info)
2255 return info->features2.features.vertexPipelineStoresAndAtomics;
2258 static enum wined3d_feature_level feature_level_from_caps(const struct wined3d_physical_device_info *info,
2259 const struct shader_caps *shader_caps)
2261 unsigned int shader_model;
2263 shader_model = min(shader_caps->vs_version, shader_caps->ps_version);
2264 shader_model = min(shader_model, max(shader_caps->gs_version, 3));
2265 shader_model = min(shader_model, max(shader_caps->hs_version, 4));
2266 shader_model = min(shader_model, max(shader_caps->ds_version, 4));
2268 if (!shader_model)
2269 return WINED3D_FEATURE_LEVEL_7;
2271 if (shader_model <= 1)
2272 return WINED3D_FEATURE_LEVEL_8;
2274 if (!feature_level_9_2_supported(info))
2275 return WINED3D_FEATURE_LEVEL_9_1;
2277 if (!feature_level_9_3_supported(info, shader_model))
2278 return WINED3D_FEATURE_LEVEL_9_2;
2280 if (!feature_level_10_supported(info, shader_model))
2281 return WINED3D_FEATURE_LEVEL_9_3;
2283 if (!feature_level_10_1_supported(info, shader_model))
2284 return WINED3D_FEATURE_LEVEL_10;
2286 if (!feature_level_11_supported(info, shader_model))
2287 return WINED3D_FEATURE_LEVEL_10_1;
2289 if (!feature_level_11_1_supported(info))
2290 return WINED3D_FEATURE_LEVEL_11;
2292 return WINED3D_FEATURE_LEVEL_11_1;
2295 static void wined3d_adapter_vk_init_d3d_info(struct wined3d_adapter_vk *adapter_vk, uint32_t wined3d_creation_flags)
2297 struct wined3d_d3d_info *d3d_info = &adapter_vk->a.d3d_info;
2298 struct wined3d_vk_info *vk_info = &adapter_vk->vk_info;
2299 struct wined3d_physical_device_info device_info;
2300 struct wined3d_vertex_caps vertex_caps;
2301 struct fragment_caps fragment_caps;
2302 struct shader_caps shader_caps;
2304 get_physical_device_info(adapter_vk, &device_info);
2306 adapter_vk->a.shader_backend->shader_get_caps(&adapter_vk->a, &shader_caps);
2307 adapter_vk->a.vertex_pipe->vp_get_caps(&adapter_vk->a, &vertex_caps);
2308 adapter_vk->a.fragment_pipe->get_caps(&adapter_vk->a, &fragment_caps);
2310 d3d_info->limits.vs_version = shader_caps.vs_version;
2311 d3d_info->limits.hs_version = shader_caps.hs_version;
2312 d3d_info->limits.ds_version = shader_caps.ds_version;
2313 d3d_info->limits.gs_version = shader_caps.gs_version;
2314 d3d_info->limits.ps_version = shader_caps.ps_version;
2315 d3d_info->limits.cs_version = shader_caps.cs_version;
2316 d3d_info->limits.vs_uniform_count = shader_caps.vs_uniform_count;
2317 d3d_info->limits.ps_uniform_count = shader_caps.ps_uniform_count;
2318 d3d_info->limits.varying_count = shader_caps.varying_count;
2319 d3d_info->limits.ffp_textures = fragment_caps.MaxSimultaneousTextures;
2320 d3d_info->limits.ffp_blend_stages = fragment_caps.MaxTextureBlendStages;
2321 d3d_info->limits.ffp_vertex_blend_matrices = vertex_caps.max_vertex_blend_matrices;
2322 d3d_info->limits.active_light_count = vertex_caps.max_active_lights;
2324 d3d_info->limits.max_rt_count = WINED3D_MAX_RENDER_TARGETS;
2325 d3d_info->limits.max_clip_distances = WINED3D_MAX_CLIP_DISTANCES;
2326 d3d_info->limits.texture_size = adapter_vk->device_limits.maxImageDimension2D;
2327 d3d_info->limits.pointsize_max = adapter_vk->device_limits.pointSizeRange[1];
2329 d3d_info->wined3d_creation_flags = wined3d_creation_flags;
2331 d3d_info->xyzrhw = vertex_caps.xyzrhw;
2332 d3d_info->emulated_flatshading = vertex_caps.emulated_flatshading;
2333 d3d_info->ffp_generic_attributes = vertex_caps.ffp_generic_attributes;
2334 d3d_info->ffp_alpha_test = false;
2335 d3d_info->vs_clipping = !!(shader_caps.wined3d_caps & WINED3D_SHADER_CAP_VS_CLIPPING);
2336 d3d_info->shader_color_key = !!(fragment_caps.wined3d_caps & WINED3D_FRAGMENT_CAP_COLOR_KEY);
2337 d3d_info->shader_double_precision = !!(shader_caps.wined3d_caps & WINED3D_SHADER_CAP_DOUBLE_PRECISION);
2338 d3d_info->shader_output_interpolation = !!(shader_caps.wined3d_caps & WINED3D_SHADER_CAP_OUTPUT_INTERPOLATION);
2339 d3d_info->viewport_array_index_any_shader = false; /* VK_EXT_shader_viewport_index_layer */
2340 d3d_info->texture_npot = true;
2341 d3d_info->texture_npot_conditional = true;
2342 d3d_info->draw_base_vertex_offset = true;
2343 d3d_info->vertex_bgra = true;
2344 d3d_info->texture_swizzle = true;
2345 d3d_info->srgb_read_control = false;
2346 d3d_info->srgb_write_control = false;
2347 d3d_info->clip_control = true;
2348 d3d_info->full_ffp_varyings = !!(shader_caps.wined3d_caps & WINED3D_SHADER_CAP_FULL_FFP_VARYINGS);
2349 d3d_info->scaled_resolve = false;
2350 d3d_info->pbo = true;
2351 d3d_info->feature_level = feature_level_from_caps(&device_info, &shader_caps);
2352 d3d_info->subpixel_viewport = true;
2353 d3d_info->fences = true;
2354 d3d_info->persistent_map = true;
2356 /* Like GL, Vulkan doesn't explicitly specify a filling convention and only mandates that a
2357 * shared edge of two adjacent triangles generate a fragment for exactly one of the triangles.
2359 * However, every Vulkan implementation we have seen so far uses a top-left rule. Hardware
2360 * that differs either predates Vulkan (d3d9 class HW, GeForce 9xxx) or behaves the way we
2361 * want in Vulkan (MacOS Radeon driver through MoltenVK). */
2362 d3d_info->filling_convention_offset = 0.0f;
2364 d3d_info->multisample_draw_location = WINED3D_LOCATION_TEXTURE_RGB;
2366 vk_info->multiple_viewports = device_info.features2.features.multiViewport;
2369 static bool wined3d_adapter_vk_init_device_extensions(struct wined3d_adapter_vk *adapter_vk)
2371 VkPhysicalDevice physical_device = adapter_vk->physical_device;
2372 struct wined3d_vk_info *vk_info = &adapter_vk->vk_info;
2373 unsigned int count, enable_count, i, j;
2374 const char **enabled_extensions = NULL;
2375 VkExtensionProperties *extensions;
2376 bool found, success = false;
2377 SIZE_T enable_size = 0;
2378 VkResult vr;
2380 static const struct
2382 const char *name;
2383 unsigned int core_since_version;
2384 bool required;
2386 info[] =
2388 {VK_EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME, ~0u},
2389 {VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME, ~0u, true},
2390 {VK_KHR_MAINTENANCE1_EXTENSION_NAME, VK_API_VERSION_1_1, true},
2391 {VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE_EXTENSION_NAME,VK_API_VERSION_1_2},
2392 {VK_KHR_SHADER_DRAW_PARAMETERS_EXTENSION_NAME, VK_API_VERSION_1_1, true},
2393 {VK_KHR_SWAPCHAIN_EXTENSION_NAME, ~0u, true},
2394 {VK_EXT_HOST_QUERY_RESET_EXTENSION_NAME, VK_API_VERSION_1_2},
2397 static const struct
2399 const char *name;
2400 enum wined3d_vk_extension extension;
2402 map[] =
2404 {VK_EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME, WINED3D_VK_EXT_TRANSFORM_FEEDBACK},
2405 {VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE_EXTENSION_NAME, WINED3D_VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE},
2406 {VK_EXT_HOST_QUERY_RESET_EXTENSION_NAME, WINED3D_VK_EXT_HOST_QUERY_RESET},
2409 if ((vr = VK_CALL(vkEnumerateDeviceExtensionProperties(physical_device, NULL, &count, NULL))) < 0)
2411 ERR("Failed to enumerate device extensions, vr %s.\n", wined3d_debug_vkresult(vr));
2412 return false;
2415 if (!(extensions = heap_calloc(count, sizeof(*extensions))))
2417 ERR("Failed to allocate extension properties array.\n");
2418 return false;
2421 if ((vr = VK_CALL(vkEnumerateDeviceExtensionProperties(physical_device, NULL, &count, extensions))) < 0)
2423 ERR("Failed to enumerate device extensions, vr %s.\n", wined3d_debug_vkresult(vr));
2424 goto done;
2427 TRACE("Vulkan device extensions reported:\n");
2428 for (i = 0; i < count; ++i)
2430 TRACE(" - %s.\n", debugstr_a(extensions[i].extensionName));
2433 for (i = 0, enable_count = 0; i < ARRAY_SIZE(info); ++i)
2435 if (info[i].core_since_version <= vk_info->api_version)
2436 continue;
2438 for (j = 0, found = false; j < count; ++j)
2440 if (!strcmp(extensions[j].extensionName, info[i].name))
2442 found = true;
2443 break;
2447 if (!found)
2449 if (!info[i].required)
2450 continue;
2451 WARN("Required extension '%s' is not available.\n", info[i].name);
2452 goto done;
2455 TRACE("Enabling device extension '%s'.\n", info[i].name);
2456 if (!wined3d_array_reserve((void **)&enabled_extensions, &enable_size,
2457 enable_count + 1, sizeof(*enabled_extensions)))
2459 ERR("Failed to allocate enabled extensions array.\n");
2460 goto done;
2462 enabled_extensions[enable_count++] = info[i].name;
2464 success = true;
2466 for (i = 0; i < ARRAY_SIZE(map); ++i)
2468 for (j = 0; j < enable_count; ++j)
2470 if (!strcmp(enabled_extensions[j], map[i].name))
2472 vk_info->supported[map[i].extension] = TRUE;
2473 break;
2478 done:
2479 if (success)
2481 adapter_vk->device_extension_count = enable_count;
2482 adapter_vk->device_extensions = enabled_extensions;
2484 else
2486 heap_free(enabled_extensions);
2488 heap_free(extensions);
2489 return success;
2492 static BOOL wined3d_adapter_vk_init(struct wined3d_adapter_vk *adapter_vk,
2493 unsigned int ordinal, unsigned int wined3d_creation_flags)
2495 struct wined3d_vk_info *vk_info = &adapter_vk->vk_info;
2496 struct wined3d_adapter *adapter = &adapter_vk->a;
2497 VkPhysicalDeviceIDProperties id_properties;
2498 VkPhysicalDeviceProperties2 properties2;
2499 LUID primary_luid, *luid = NULL;
2501 TRACE("adapter_vk %p, ordinal %u, wined3d_creation_flags %#x.\n",
2502 adapter_vk, ordinal, wined3d_creation_flags);
2504 if (!wined3d_init_vulkan(vk_info))
2506 WARN("Failed to initialize Vulkan.\n");
2507 return FALSE;
2510 if (!(adapter_vk->physical_device = get_vulkan_physical_device(vk_info)))
2511 goto fail_vulkan;
2513 if (!wined3d_adapter_vk_init_device_extensions(adapter_vk))
2514 goto fail_vulkan;
2516 memset(&id_properties, 0, sizeof(id_properties));
2517 id_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES;
2518 properties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
2519 properties2.pNext = &id_properties;
2521 if (vk_info->vk_ops.vkGetPhysicalDeviceProperties2)
2522 VK_CALL(vkGetPhysicalDeviceProperties2(adapter_vk->physical_device, &properties2));
2523 else
2524 VK_CALL(vkGetPhysicalDeviceProperties(adapter_vk->physical_device, &properties2.properties));
2525 adapter_vk->device_limits = properties2.properties.limits;
2527 VK_CALL(vkGetPhysicalDeviceMemoryProperties(adapter_vk->physical_device, &adapter_vk->memory_properties));
2529 if (id_properties.deviceLUIDValid)
2530 luid = (LUID *)id_properties.deviceLUID;
2531 else if (ordinal == 0 && wined3d_get_primary_adapter_luid(&primary_luid))
2532 luid = &primary_luid;
2534 if (!wined3d_adapter_init(adapter, ordinal, luid, &wined3d_adapter_vk_ops))
2536 heap_free(adapter_vk->device_extensions);
2537 goto fail_vulkan;
2540 adapter->vertex_pipe = wined3d_spirv_vertex_pipe_init_vk();
2541 adapter->fragment_pipe = wined3d_spirv_fragment_pipe_init_vk();
2542 adapter->misc_state_template = misc_state_template_vk;
2543 adapter->shader_backend = wined3d_spirv_shader_backend_init_vk();
2545 wined3d_adapter_vk_init_d3d_info(adapter_vk, wined3d_creation_flags);
2547 if (!adapter_vk_init_driver_info(adapter_vk, &properties2.properties))
2548 goto fail;
2549 TRACE("Reporting (fake) driver version 0x%08x-0x%08x.\n",
2550 adapter_vk->a.driver_info.version_high, adapter_vk->a.driver_info.version_low);
2551 adapter->vram_bytes_used = 0;
2552 TRACE("Emulating 0x%s bytes of video ram.\n", wine_dbgstr_longlong(adapter->driver_info.vram_bytes));
2554 memcpy(&adapter->driver_uuid, id_properties.driverUUID, sizeof(adapter->driver_uuid));
2555 memcpy(&adapter->device_uuid, id_properties.deviceUUID, sizeof(adapter->device_uuid));
2557 if (!wined3d_adapter_vk_init_format_info(adapter_vk, vk_info))
2558 goto fail;
2560 return TRUE;
2562 fail:
2563 wined3d_adapter_cleanup(adapter);
2564 heap_free(adapter_vk->device_extensions);
2565 fail_vulkan:
2566 VK_CALL(vkDestroyInstance(vk_info->instance, NULL));
2567 wined3d_unload_vulkan(vk_info);
2568 return FALSE;
2571 struct wined3d_adapter *wined3d_adapter_vk_create(unsigned int ordinal,
2572 unsigned int wined3d_creation_flags)
2574 struct wined3d_adapter_vk *adapter_vk;
2576 if (!(adapter_vk = heap_alloc_zero(sizeof(*adapter_vk))))
2577 return NULL;
2579 if (!wined3d_adapter_vk_init(adapter_vk, ordinal, wined3d_creation_flags))
2581 heap_free(adapter_vk);
2582 return NULL;
2585 TRACE("Created adapter %p.\n", adapter_vk);
2587 return &adapter_vk->a;